Skip to content

Zeal Components

Components designed to simplify list-related operations.

1. PopupModal

A popup modal component.

Props

Prop NameDescriptionTypeDefaultRequired
titleModal title; can also be a render functionReactNode | (() => ReactNode)-No
modalPropsPass-through / override props for Antd Modal (merged with internal defaults)ModalProps-No
toMount container (passed to Modal.getContainer)string | HTMLElement-No
showCloseWhether to show the close button in the top-right corner (closable)booleantrueNo
draggableWhether the modal is draggable (depends on react-draggable; install from peerDependencies)booleanfalseNo
closeOnMaskWhether clicking the mask closes the modal (maskClosable)booleantrueNo
widthModal width (applied via style.width)string'min(1080px,90%)'No
onCancelCallback when clicking the cancel button; if it returns false in a promise, the modal stays open, otherwise it closes() => boolean | void | Promise<boolean | void>() => undefinedNo
onSubmitCallback when clicking the submit button; if it returns false in a promise, the modal stays open, otherwise it closes() => boolean | void | Promise<boolean | void>() => undefinedNo
footerTxtFooter button text in the form of [Cancel, Submit]string[]['Cancel', 'Submit']No
modalRenderCustom modal renderer((node: ReactNode) => ReactNode) | undefined-No
childrenModal body content (content area)ReactNode-No

Ref (Function)

MethodDescriptionSignature
toggleToggle visibility; if omitted, it toggles automatically; pass true/false to force open/close(f?: boolean) => void

Example

Details
tsx
import {useRef} from "react";
import {AdPopupModal, adPopupModalRef} from "dynamicformdjx-react/antd";
import {Button} from "antd";

function PopupModal() {
    const modalRef = useRef<adPopupModalRef>(null);

    return (
        <div>
            <Button onClick={() => modalRef.current?.toggle(true)}>打开弹窗</Button>

            <AdPopupModal
                ref={modalRef}
                title="测试弹窗"
                draggable
                onCancel={() => {
                    return true;
                }}
                onSubmit={async () => {
                    return await new Promise(resolve => setTimeout(() => resolve(true), 2000));
                }}
            >
                <div>这里是弹窗内容</div>
            </AdPopupModal>
        </div>
    );
}

export default PopupModal

2. AntZealCard

A card layout container, commonly used to wrap pages with a “search area + action area + content area” structure. It calculates the available content height based on the container and window size, and passes it to the children render function.

Props

Prop NameDescriptionTypeDefaultRequired
titleCard titleReactNode-No
zealHeightOuter container height, ultimately used in calc(${zealHeight} - ${outPadding * 2}px)string'100vh'No
outPaddingOuter top and bottom padding reserved from the total height; 2 * outPadding will be subtractednumber0No
searchBtnTxtDefault search button text, in the order of [Reset, Search]string[]['Reset', 'Search']No
checkWindowSizeWindow size listener config, in the order of [mobile threshold, debounce delay]number[][756, 500]No
headerCustom header renderer; receives window-related args. If provided, it replaces the default header area(args: ZealCardSlotArgs) => ReactNode-No
footerCustom footer renderer; rendered as Card.actions content(args: ZealCardSlotArgs) => ReactNode-No
searchFormSearch form area renderer() => ReactNode-No
searchBtnCustom search button area; if omitted and searchForm exists, the default reset/search buttons will be rendered() => ReactNode-No
controlBtnRenderer for the right-side control area in the header() => ReactNode-No
toolBtnRenderer for the right-side tool area in the header() => ReactNode-No
restExtra content rendered below the card and included in the remaining height calculation() => ReactNode-No
childrenCard body content; can be a node directly, or a render function that receives dynamic height and window infoReactNode | ((args: ZealCardDefaultArgs) => ReactNode)-No

ZealCardSlotArgs

ParamDescriptionType
widthCurrent window widthnumber
heightCurrent window heightnumber
isMobileWhether the current width is considered mobileboolean

Arguments When children Is a Function

ZealCardDefaultArgs

In addition to ZealCardSlotArgs, it also exposes content area height information.

ParamDescriptionType
tableHeightAvailable height of the main content areanumber
ctxHeightContext height information calculated by observationCtxHeightState
widthCurrent window widthnumber
heightCurrent window heightnumber
isMobileWhether the current width is considered mobileboolean

Notes

  1. If header is provided, the default header layout using title / searchForm / searchBtn will no longer take effect.
  2. If searchBtn is not provided but searchForm is, the default Reset and Search buttons will be rendered automatically, and their labels are controlled by searchBtnTxt.
  3. The content rendered by rest is placed below the card container, making it suitable for extra notes, pagination bars, and similar elements. It also affects the content height calculation.
  4. When children is a function, it is suitable for tables, self-adaptive height regions, and other cases where tableHeight is needed dynamically.

Example

Details
tsx
import {AdZealCard} from "dynamicformdjx-react/antd";
import {Button} from "antd";

function ZealCard({pad}: { pad: number }) {
    return <AdZealCard
        outPadding={pad}
        title="Zeal Card"
        footer={({width}) => <div>windows width: {width}</div>}
        searchForm={() => <></>}
        controlBtn={() => <Button size='small' color={'green'} variant={'dashed'}>New</Button>}
    >
        {({tableHeight, isMobile}) => (<div>
            tableHeight:{tableHeight},isMobile:{`${isMobile}`}
        </div>)}
    </AdZealCard>
}

export default ZealCard

2. AdZealTableSearch

A table search area component that supports both desktop inline search mode and mobile drawer search mode.

Props

Prop NameDescriptionTypeDefaultRequired
titleTitle of the search areastring-No
drawerTitleDrawer title; uses title if not providedstring-No
searchItemsStateSearch form item state, used internally by useDyForm / AdDynamicFormItemsState<Row, RuleT>-Yes
searchFormMaxHeightMaximum height of the search form area on desktopstring'200px'No
drawerMaxHeightHeight of the drawer on mobilenumber420No
drawerOpenTxtButton text for opening the drawer on mobilestring'Search Drawer'No
searchBtnTxtSearch button text, in the order of [Reset, Search]string[]['Reset', 'Search']No
mobileDrawerWhether to use drawer mode on mobilebooleantrueNo
closeDrawerAutoWhether to automatically close the drawer when switching from mobile to non-mobile modebooleantrueNo
drawerConfigPass-through / override config for Antd DrawerDrawerProps-No
copyDefaultWhether to cache the initial default values; if enabled, reset restores the initial values instead of clearing thembooleanfalseNo
isMobileWhether the current mode is mobile, controlled externallybooleanfalseNo
onResetCallback when clicking the reset button() => void-No
onSearchCallback when clicking the search button; returns the current form values(data: Row) => void-No
slotsCustom slot renderersZealTableSearchSlots-No

Ref (Function)

MethodDescriptionSignature
onResetExecute the reset logic() => void
onSearchExecute the search logic() => void
toggleDrawerToggle drawer visibility; if omitted, it toggles automatically; pass true/false to force open/close(f?: boolean) => void
getParamsGet the current form parameters() => Row

ZealTableSearchSlots (slots)

Slot NameDescriptionSignature
titleCustom title area() => ReactNode
drawerBtnCustom button for opening the drawer on mobile(args: { openDrawer: () => void }) => ReactNode
searchBtnCustom search button area(args: { onSearch: () => void; onReset: () => void }) => ReactNode

Notes

  1. When mobileDrawer = true and isMobile = true, the component switches to drawer search mode.
  2. When copyDefault = true, clicking Reset restores the initial form values; otherwise, it clears the form.
  3. When closeDrawerAuto = true, if the component is currently in drawer mode, switching to non-mobile mode will automatically close the drawer.
  4. If slots.searchBtn is provided, it completely replaces the default Reset/Search button area.
  5. drawerConfig overrides internal Drawer props with the same names.

Example

Details
tsx
import {useWindowSize} from "dynamicformdjx-react";
import {useRef} from "react";
import {AdZealTableSearch, adZealTableSearchRef, useDecorateForm} from "dynamicformdjx-react/antd";
import {Button} from "antd";

function ZealTableSearch() {
    type RowProps = {
        name: string
        age: string
        address: string
    }
    const {isMobile} = useWindowSize(630)
    const searchRef = useRef<adZealTableSearchRef<RowProps>>(null)
    const searchFormItems = useDecorateForm<RowProps>([
        {
            key: "name",
            label: "Name",
        },
        {
            key: "age",
            label: "Age",
        },
        {
            key: "address",
            label: "Address",
        },
    ].map(it => ({
        value: null,
        allowClear: true,
        renderType: 'renderInput',
        span: 8,
        ...it,
    })) as any[])
    const onSearch = (params: any) => {
        console.log('search params:', params)
    }

    const onReset = () => {
        console.log('reset')
    }
    return <div>
        <AdZealTableSearch<RowProps>
            ref={searchRef}
            title={'Search Params'}
            isMobile={isMobile}
            searchItemsState={searchFormItems}
            onSearch={onSearch}
            onReset={onReset}
        />
        <Button size='small' onClick={() => {
            console.log(searchRef.current?.getParams())
        }}>Search (Ref Func)</Button>
    </div>
}

export default ZealTableSearch

3. AdZealTablePaginationControl

A table pagination control component that wraps Antd Pagination and adapts it to the ZealPagination pagination object.

Props

Prop NameDescriptionTypeDefaultRequired
paginationPagination state objectZealPagination-Yes
onChangeTriggered when the page number or page size changes(pageNo: number, pageSize: number) => void-Yes
pageConfigPass-through / override config for Antd PaginationPaginationProps-No
isMobileWhether the current mode is mobile; in mobile mode the pagination uses a more compact stylebooleanfalseNo
prefixRenderer for content placed before the pagination(pageModal: ZealPagination) => ReactNode-No

Notes

  1. The current page comes from pagination.pageNo.

  2. The page size comes from pagination.pageSize.

  3. The total count comes from pagination.total.

  4. The selectable page size options come from pagination.pageSizes.

  5. When changing the page number, the following are triggered in order:

    • pagination.onChange(page, size)
    • onChange(page, size)
  6. When changing the page size, the following are triggered:

    • pagination.onPageSizeChange?.(size)
    • onChange(1, size)
  7. In mobile mode:

    • Pagination.size = 'small'
    • showLessItems = true
  8. When prefix exists and the component is in mobile mode, showSizeChanger will be hidden.

Example

Details
tsx
import {message} from "antd";
import {usePagination, useWindowSize} from "dynamicformdjx-react";
import {useEffect} from "react";
import {AdZealTablePaginationControl} from "dynamicformdjx-react/antd";

function ZealTablePaginationControl() {
    const [messageApi, contextHolder] = message.useMessage();
    const {isMobile} = useWindowSize(630)
    const paginationModal = usePagination(fetchData)

    function fetchData() {
        const {pagination} = paginationModal
        console.log(pagination.pageNo, pagination.pageSize)
    }

    useEffect(() => {
        paginationModal.setTotal(52)
    }, [])
    return (<div>
        {contextHolder}
        <AdZealTablePaginationControl
            prefix={({total}) => isMobile ? null : <span>Total {total}</span>}
            isMobile={isMobile}
            pagination={paginationModal.pagination}
            onChange={(pn, ps) => {
                messageApi.info(JSON.stringify({
                    pageNo: pn,
                    pageSize: ps,
                }, null, 2))
            }}
        />
    </div>)
}

export default ZealTablePaginationControl