{"version":3,"file":"Form.mjs","names":["Form","BaseForm"],"sources":["../../../src/base-ui/Form/Form.tsx"],"sourcesContent":["'use client';\n\nimport { Form as BaseForm } from '@base-ui/react/form';\nimport { cx, useResponsive } from 'antd-style';\nimport { isUndefined } from 'es-toolkit/compat';\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport FormField from './components/FormField';\nimport FormFlatGroup from './components/FormFlatGroup';\nimport FormGroup from './components/FormGroup';\nimport { FormContext } from './context';\nimport { rootVariants } from './style';\nimport type { FormFieldProps, FormGroupItemType, FormProps } from './type';\n\nconst serializeForm = (form: HTMLFormElement | null) => {\n  if (!form) return '';\n  const entries = [...new FormData(form).entries()].filter(\n    ([, value]) => typeof value === 'string',\n  ) as [string, string][];\n  return JSON.stringify(entries.sort((a, b) => a[0].localeCompare(b[0])));\n};\n\nconst Form = memo<FormProps>(\n  ({\n    className,\n    itemMinWidth,\n    footer,\n    items = [],\n    children,\n    itemsType = 'group',\n    variant = 'borderless',\n    classNames,\n    styles: customStyles,\n    gap,\n    style,\n    collapsible,\n    defaultActiveKey,\n    initialValues,\n    activeKey,\n    onCollapse,\n    onFinish,\n    onFormSubmit,\n    layout,\n    ref,\n    ...rest\n  }) => {\n    const { mobile } = useResponsive();\n    const formRef = useRef<HTMLFormElement>(null);\n    const [submitLoading, setSubmitLoading] = useState(false);\n    const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);\n    const snapshotRef = useRef('');\n\n    const syncUnsaved = useCallback(() => {\n      setHasUnsavedChanges(serializeForm(formRef.current) !== snapshotRef.current);\n    }, []);\n\n    useEffect(() => {\n      const form = formRef.current;\n      if (!form) return;\n      snapshotRef.current = serializeForm(form);\n      let resetTimer: ReturnType<typeof setTimeout>;\n      const handleMutation = () => syncUnsaved();\n      const handleReset = () => {\n        resetTimer = setTimeout(() => {\n          snapshotRef.current = serializeForm(formRef.current);\n          syncUnsaved();\n        }, 0);\n      };\n      form.addEventListener('input', handleMutation);\n      form.addEventListener('change', handleMutation);\n      form.addEventListener('reset', handleReset);\n      return () => {\n        clearTimeout(resetTimer);\n        form.removeEventListener('input', handleMutation);\n        form.removeEventListener('change', handleMutation);\n        form.removeEventListener('reset', handleReset);\n      };\n    }, [syncUnsaved]);\n\n    const requestReset = useCallback(() => {\n      formRef.current?.reset();\n    }, []);\n\n    const mergedRef = useCallback(\n      (node: HTMLFormElement | null) => {\n        formRef.current = node;\n        if (typeof ref === 'function') ref(node);\n        else if (ref) ref.current = node;\n      },\n      [ref],\n    );\n\n    const context = useMemo(\n      () => ({\n        hasUnsavedChanges,\n        initialValues,\n        itemMinWidth,\n        layout: layout || (mobile ? ('vertical' as const) : ('horizontal' as const)),\n        requestReset,\n        submitLoading,\n        variant,\n      }),\n      [\n        hasUnsavedChanges,\n        initialValues,\n        itemMinWidth,\n        layout,\n        mobile,\n        requestReset,\n        submitLoading,\n        variant,\n      ],\n    );\n\n    const mapFlat = useCallback(\n      (item: FormFieldProps, itemIndex: number) => (\n        <FormField\n          className={classNames?.item}\n          divider={itemIndex !== 0}\n          key={itemIndex}\n          style={customStyles?.item}\n          variant={variant}\n          {...item}\n        />\n      ),\n      [variant, classNames, customStyles],\n    );\n\n    const mapTree = useCallback(\n      (group: FormGroupItemType, groupIndex: number) => {\n        const key = group?.key || groupIndex;\n        return (\n          <FormGroup\n            active={activeKey && group?.key ? activeKey.includes(key) : undefined}\n            className={classNames?.group}\n            collapsible={isUndefined(group.collapsible) ? collapsible : group.collapsible}\n            desc={group?.desc}\n            extra={group?.extra}\n            icon={group?.icon}\n            key={key}\n            style={customStyles?.group}\n            title={group.title}\n            variant={group?.variant || variant}\n            defaultActive={\n              defaultActiveKey && group?.key ? defaultActiveKey.includes(key) : group?.defaultActive\n            }\n            onCollapse={(active) => {\n              let keys: (string | number)[] = activeKey || defaultActiveKey || [];\n              keys = keys.filter((k) => k !== key);\n              onCollapse?.(active ? [...keys, key] : keys);\n            }}\n          >\n            {Array.isArray(group.children)\n              ? group.children.filter((item) => !item.hidden).map((item, i) => mapFlat(item, i))\n              : group.children}\n          </FormGroup>\n        );\n      },\n      [\n        activeKey,\n        collapsible,\n        defaultActiveKey,\n        onCollapse,\n        variant,\n        classNames,\n        customStyles,\n        mapFlat,\n      ],\n    );\n\n    return (\n      <FormContext value={context}>\n        <BaseForm\n          className={cx(rootVariants({ variant }), className)}\n          ref={mergedRef}\n          style={{ gap, ...style }}\n          onFormSubmit={async (values, eventDetails) => {\n            onFormSubmit?.(values, eventDetails);\n            if (!onFinish) return;\n            setSubmitLoading(true);\n            try {\n              await onFinish(values, eventDetails);\n              snapshotRef.current = serializeForm(formRef.current);\n              syncUnsaved();\n            } finally {\n              setSubmitLoading(false);\n            }\n          }}\n          {...rest}\n        >\n          {items && items.length > 0 ? (\n            itemsType === 'group' ? (\n              (items as FormGroupItemType[]).map((item, i) => mapTree(item, i))\n            ) : (\n              <FormFlatGroup\n                className={classNames?.group}\n                style={customStyles?.group}\n                variant={variant}\n              >\n                {(items as FormFieldProps[])\n                  .filter((item) => !item.hidden)\n                  .map((item, i) => mapFlat(item, i))}\n              </FormFlatGroup>\n            )\n          ) : undefined}\n          {children}\n          {footer}\n        </BaseForm>\n      </FormContext>\n    );\n  },\n);\n\nForm.displayName = 'Form';\n\nexport default Form;\n"],"mappings":"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"}