{"version":3,"file":"Field.mjs","names":["formMessages"],"sources":["../../../src/base-ui/FormKit/Field.tsx"],"sourcesContent":["'use client';\n\nimport { cx, useResponsive } from 'antd-style';\nimport {\n  cloneElement,\n  isValidElement,\n  memo,\n  type ReactElement,\n  type ReactNode,\n  useCallback,\n  useEffect,\n  useId,\n  useRef,\n} from 'react';\n\nimport formMessages from '@/i18n/resources/en/form';\nimport { useTranslation } from '@/i18n/useTranslation';\n\nimport FormDivider from '../Form/components/FormDivider';\nimport FormTitle from '../Form/components/FormTitle';\nimport { fieldStyles, fieldVariants } from '../Form/style';\nimport { resolveBinding } from './binding';\nimport { useFormKitContext } from './context';\nimport type { FieldValidator } from './engine/types';\nimport { getInternals } from './instance';\nimport { toFieldValidator } from './schema';\nimport { fieldKitStyles } from './style';\nimport type { FieldRenderProps, FormFieldProps, FormValues } from './type';\nimport { useStoreSelector } from './useStoreSelector';\n\nconst isEmpty = (value: unknown) =>\n  value === undefined ||\n  value === null ||\n  value === '' ||\n  (Array.isArray(value) && value.length === 0);\n\ntype ControlProps = Pick<\n  FormFieldProps,\n  | 'bare'\n  | 'children'\n  | 'deps'\n  | 'emptyValue'\n  | 'getValue'\n  | 'name'\n  | 'render'\n  | 'required'\n  | 'trigger'\n  | 'validate'\n  | 'validateDebounce'\n  | 'validateOn'\n  | 'valueProp'\n> & { id: string; name: string };\n\nconst FieldControl = memo<ControlProps>(\n  ({\n    bare,\n    children,\n    deps,\n    emptyValue,\n    getValue,\n    id,\n    name,\n    render,\n    required,\n    trigger,\n    validate,\n    validateDebounce,\n    validateOn,\n    valueProp,\n  }) => {\n    const { form } = useFormKitContext();\n    const { engine, validateOn: formValidateOn } = getInternals(form);\n    const { t } = useTranslation(formMessages);\n    const errorId = `${id}-error`;\n\n    const requiredMessage = typeof required === 'string' ? required : t('form.required');\n    const fieldValidator = validate ? toFieldValidator(validate) : undefined;\n    const validatorRef = useRef<FieldValidator | undefined>(undefined);\n    validatorRef.current = async (value, values) => {\n      if (required && isEmpty(value)) return requiredMessage;\n      return fieldValidator?.(value, values);\n    };\n    const hasValidator = Boolean(required || validate);\n    const depsKey = deps?.join('\\u0000');\n\n    useEffect(\n      () =>\n        engine.registerField(name, {\n          debounceMs: validateDebounce,\n          deps: depsKey ? depsKey.split('\\u0000') : undefined,\n          validate: hasValidator\n            ? (value, values) => validatorRef.current!(value, values)\n            : undefined,\n          validateOn: validateOn ?? formValidateOn,\n        }),\n      [engine, name, hasValidator, depsKey, validateDebounce, validateOn, formValidateOn],\n    );\n\n    const field = useStoreSelector(engine, (e) => e.getField(name));\n\n    const child = isValidElement(children) ? (children as ReactElement<any>) : undefined;\n    const binding = child\n      ? resolveBinding(child, { emptyValue, getValue, trigger, valueProp })\n      : undefined;\n    const handlerRef = useRef({ binding, childProps: child?.props as Record<string, any> });\n    handlerRef.current = { binding, childProps: child?.props as Record<string, any> };\n\n    const onChange = useCallback(\n      (...args: unknown[]) => {\n        const { binding: current, childProps } = handlerRef.current;\n        if (current) childProps?.[current.trigger]?.(...args);\n        const next = current ? current.getValue(...args) : args[0];\n        engine.setValue(name, next, 'user');\n      },\n      [engine, name],\n    );\n    const onBlur = useCallback(\n      (...args: unknown[]) => {\n        handlerRef.current.childProps?.onBlur?.(...args);\n        engine.blurField(name);\n      },\n      [engine, name],\n    );\n\n    const warnedRef = useRef(false);\n    useEffect(() => {\n      if (render || child || warnedRef.current || process.env.NODE_ENV === 'production') return;\n      warnedRef.current = true;\n      console.warn(\n        `[@lobehub/ui/base-ui/form] Form.Field \"${name}\" needs a single element child or a render prop; nothing was bound.`,\n      );\n    }, [render, child, name]);\n\n    const errorNode =\n      field.error && !bare ? (\n        <div className={fieldStyles.error} id={errorId}>\n          {field.error}\n        </div>\n      ) : null;\n\n    if (render) {\n      const renderProps: FieldRenderProps = {\n        error: field.error,\n        name,\n        onBlur,\n        onChange,\n        touched: field.touched,\n        validating: field.validating,\n        value: field.value,\n      };\n      return (\n        <>\n          {render(renderProps)}\n          {errorNode}\n        </>\n      );\n    }\n\n    if (!child || !binding) return <>{children}</>;\n\n    const control = cloneElement(child, {\n      'aria-describedby': field.error ? errorId : undefined,\n      'aria-invalid': field.error ? true : undefined,\n      'id': child.props.id ?? id,\n      [binding.trigger]: onChange,\n      [binding.valueProp]: field.value === undefined ? binding.emptyValue : field.value,\n      'onBlur': onBlur,\n    });\n\n    return (\n      <>\n        {control}\n        {errorNode}\n      </>\n    );\n  },\n);\n\nFieldControl.displayName = 'FormFieldControl';\n\nconst FormField = memo<FormFieldProps>(\n  ({\n    avatar,\n    bare,\n    children,\n    className,\n    deps,\n    desc,\n    divider,\n    emptyValue,\n    extra,\n    getValue,\n    hidden,\n    label,\n    layout,\n    minWidth,\n    name,\n    render,\n    required,\n    style,\n    tag,\n    trigger,\n    validate,\n    validateDebounce,\n    validateOn,\n    valueProp,\n    variant,\n  }) => {\n    const id = useId();\n    const { mobile } = useResponsive();\n    const config = useFormKitContext();\n\n    if (hidden) return null;\n\n    const control = !name ? (\n      children\n    ) : (\n      <FieldControl\n        bare={bare}\n        deps={deps}\n        emptyValue={emptyValue}\n        getValue={getValue}\n        id={id}\n        name={name}\n        render={render}\n        required={required}\n        trigger={trigger}\n        validate={validate}\n        validateDebounce={validateDebounce}\n        validateOn={validateOn}\n        valueProp={valueProp}\n      >\n        {children}\n      </FieldControl>\n    );\n\n    if (bare) return <>{control}</>;\n\n    const labelFor = render\n      ? undefined\n      : name\n        ? id\n        : isValidElement<{ id?: string }>(children)\n          ? children.props.id\n          : undefined;\n    const mergedLayout = layout || (mobile ? 'vertical' : config.layout);\n    const mergedVariant = variant || config.variant;\n    const controlWidth =\n      mergedLayout === 'vertical' || minWidth === undefined || minWidth === ''\n        ? undefined\n        : typeof minWidth === 'number'\n          ? `${minWidth}px`\n          : minWidth;\n\n    return (\n      <>\n        {divider && <FormDivider visible={mergedVariant !== 'borderless'} />}\n        <div className={cx(fieldVariants({ layout: mergedLayout }), className)} style={style}>\n          <label className={fieldStyles.label} htmlFor={labelFor}>\n            <FormTitle\n              avatar={avatar}\n              desc={desc}\n              tag={tag}\n              title={\n                required ? (\n                  <>\n                    {label}\n                    <span aria-hidden className={fieldKitStyles.required}>\n                      *\n                    </span>\n                  </>\n                ) : (\n                  label\n                )\n              }\n            />\n          </label>\n          <div\n            style={controlWidth ? { width: controlWidth } : undefined}\n            className={cx(\n              fieldStyles.control,\n              mergedLayout === 'vertical' && fieldStyles.controlVertical,\n              controlWidth && fieldKitStyles.controlFixed,\n            )}\n          >\n            {control}\n            {extra && <div className={fieldKitStyles.extra}>{extra}</div>}\n          </div>\n        </div>\n      </>\n    );\n  },\n);\n\nFormField.displayName = 'FormField';\n\nexport default FormField as unknown as (<T extends FormValues = FormValues>(\n  props: FormFieldProps<T>,\n) => ReactNode) & { displayName?: string };\n"],"mappings":"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"}