@aloudata/aloudata-design 3.0.4 → 3.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -143,7 +143,7 @@ function Button(props, ref) {
143
143
  block: !!block,
144
144
  shape
145
145
  }), ghost && "!tw-border-transparent !tw-bg-[var(--action-ghost-normal)] !tw-shadow-none hover:!tw-border-transparent", ghost && type === "primary" && size === "middle" && "!tw-h-8 !tw-min-w-8 !tw-gap-[var(--component-gap-xs)] !tw-rounded-r-75 !tw-px-[var(--component-padding-md)] !tw-py-0", ghost && type === "dangerous" && size === "middle" && "!tw-h-8 !tw-min-w-8 !tw-gap-[var(--component-gap-xs)] !tw-rounded-r-75 !tw-px-[var(--component-padding-md)] !tw-py-0", ghost && type === "secondary" && size === "middle" && "!tw-h-8 !tw-min-w-8 !tw-gap-[var(--component-gap-xs)] !tw-rounded-r-75 !tw-px-[var(--component-padding-md)] !tw-py-0", ghost && type === "inverse" && size === "middle" && "!tw-h-8 !tw-min-w-8 !tw-gap-[var(--component-gap-xs)] !tw-rounded-r-75 !tw-bg-[var(--action-ghost-normal)] !tw-px-[var(--component-padding-md)] !tw-py-0", ghost && type === "primary" && "!tw-rounded-r-75 hover:!tw-bg-[var(--action-primary-subtle-hover)]", ghost && type === "dangerous" && "!tw-rounded-r-75 hover:!tw-bg-[var(--action-ghost-destructive-hover)]", ghost && type === "secondary" && "!tw-rounded-r-75 hover:!tw-bg-[var(--action-ghost-hover)]", ghost && type === "inverse" && "!tw-rounded-r-75 hover:!tw-bg-[var(--action-ghost-inverted-hover)]", ghost && type === "primary" && "!tw-text-[var(--action-primary-normal)]", ghost && type === "dangerous" && "!tw-text-[var(--action-destructive-normal)]", ghost && type === "secondary" && "!tw-text-[var(--action-neutral-normal)]", ghost && type === "inverse" && "!tw-text-[var(--action-inverted-normal)]", isIconOnly && "tw-aspect-square !tw-px-0", isIconOnly && size === "small" && "!tw-min-w-7", isIconOnly && size === "middle" && "!tw-min-w-8", isIconOnly && size === "large" && "!tw-min-w-10", compactClasses, className);
146
- const contentClasses = cn("tw-inline-flex tw-items-center tw-gap-1", ghost && type === "inverse" && size === "middle" && "tw-flex-[1_0_0] tw-text-sm tw-font-medium tw-leading-5 tw-text-[var(--action-inverted-normal)]");
146
+ const contentClasses = cn("tw-inline-flex tw-min-w-0 tw-items-center tw-gap-1 tw-truncate", ghost && type === "inverse" && size === "middle" && "tw-flex-[1_0_0] tw-text-sm tw-font-medium tw-leading-5 tw-text-[var(--action-inverted-normal)]");
147
147
  const buttonContent = /* @__PURE__ */ jsxs(Fragment, { children: [
148
148
  iconNode,
149
149
  children && /* @__PURE__ */ jsx("span", {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Button/index.tsx"],"sourcesContent":["import { cva } from 'class-variance-authority';\nimport React, { forwardRef, useContext, useEffect, useState } from 'react';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport SizeContext from '../ConfigProvider/sizeContext';\nimport { ChevronDownLine, LoadingLine } from '../Icon';\nimport { cn } from '../lib/utils';\nimport { useCompactItemContext } from '../Space/CompactContext';\n\nexport const btnPrefix = 'ald-btn';\n\nexport type ButtonType =\n | 'primary'\n | 'secondary'\n | 'dangerous'\n | 'text'\n | 'inverse'\n | 'link';\nexport type Size = 'small' | 'middle' | 'large';\nexport interface IButtonProps {\n type?: ButtonType;\n size?: Size;\n disabled?: boolean;\n icon?: React.ReactNode;\n shape?: 'circle' | 'default';\n href?: string;\n target?: string;\n onClick?: React.MouseEventHandler<HTMLElement>;\n loading?: boolean | { delay?: number };\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n block?: boolean;\n htmlType?: 'submit' | 'button' | 'reset';\n id?: string;\n tabIndex?: number;\n title?: string;\n 'aria-label'?: string;\n ghost?: boolean;\n danger?: boolean;\n color?: string;\n showArrow?: boolean;\n}\n\nexport function getButtonType(buttonType: ButtonType): string {\n return buttonType;\n}\nexport function getDangerStatus(buttonType: ButtonType): boolean {\n return buttonType === 'dangerous';\n}\nexport function getButtonSizeClass(s: Size): string {\n return ['small', 'large'].includes(s)\n ? `${btnPrefix}-${s}`\n : `${btnPrefix}-middle`;\n}\nexport function getShape(s: 'circle' | 'default'): 'circle' | 'default' {\n return s;\n}\nexport const setIcon = (\n iconNode: React.ReactElement,\n loading: boolean | { delay?: number },\n) => {\n if (loading) {\n return (\n <LoadingLine\n className=\"ald-loading-spin tw-shrink-0 tw-animate-spin\"\n size={'1em'}\n color=\"currentColor\"\n />\n );\n }\n\n if (iconNode) {\n const p: Record<string, string | number> = {\n className: '',\n fill: 'currentColor',\n ...iconNode.props,\n };\n p.size = '1em';\n return React.cloneElement(iconNode, p);\n }\n return <></>;\n};\n\nconst buttonVariants = cva(\n [\n btnPrefix,\n 'tw-inline-flex tw-cursor-pointer tw-appearance-none tw-items-center tw-justify-center tw-font-medium tw-no-underline tw-transition-colors [&_.i-icon]:tw-inline-flex [&_.i-icon]:tw-items-center',\n 'tw-border tw-border-solid',\n 'focus-visible:tw-outline-none',\n ],\n {\n variants: {\n type: {\n primary: [\n `${btnPrefix}-primary`,\n 'tw-border-transparent tw-bg-[var(--action-primary-normal)] tw-text-[var(--action-inverted-normal)] tw-shadow-[0_1px_2px_0_rgba(27,36,44,0.12)]',\n 'hover:tw-bg-[var(--action-primary-hover)]',\n 'active:tw-bg-[var(--action-primary-active)]',\n ],\n secondary: [\n `${btnPrefix}-secondary`,\n 'tw-border-[var(--action-outline-normal)] tw-bg-[var(--action-inverted-normal)] tw-text-[var(--action-neutral-normal)] tw-shadow-[0_1px_2px_0_rgba(27,36,44,0.12)]',\n 'hover:tw-border-[var(--action-outline-hover)] hover:tw-bg-[var(--action-inverted-normal)]',\n 'active:tw-border-[var(--action-outline-active)] active:tw-bg-[var(--action-inverted-active)] active:tw-text-[var(--action-neutral-active)]',\n ],\n dangerous: [\n `${btnPrefix}-dangerous`,\n 'tw-border-transparent tw-bg-[var(--action-destructive-normal)] tw-text-[var(--action-inverted-normal)] tw-shadow-[0_1px_2px_0_rgba(27,36,44,0.12)]',\n 'hover:tw-bg-[var(--action-destructive-hover)]',\n 'active:tw-bg-[var(--action-destructive-active)]',\n ],\n text: [\n `${btnPrefix}-text`,\n 'tw-border-transparent tw-bg-[var(--action-ghost-normal)] tw-text-[var(--action-neutral-normal)]',\n 'hover:tw-bg-[var(--action-ghost-hover)] hover:tw-text-[var(--action-neutral-hover)]',\n 'active:tw-bg-[var(--action-ghost-active)] active:tw-text-[var(--action-neutral-active)]',\n ],\n inverse: [\n `${btnPrefix}-inverse`,\n 'tw-border-[var(--action-neutral-normal)] tw-bg-[var(--action-ghost-normal)] tw-text-[var(--alias-colors-text-inverse-default)]',\n 'hover:tw-border-[var(--action-ghost-inverted-hover)] hover:tw-bg-[var(--action-ghost-normal)]',\n 'active:tw-bg-[var(--alias-colors-bg-skeleton-inverse-stronger)]',\n ],\n link: [\n `${btnPrefix}-link`,\n 'tw-border-transparent tw-bg-transparent tw-text-[var(--action-primary-normal)]',\n 'hover:tw-text-[var(--action-primary-hover)]',\n 'active:tw-text-[var(--action-primary-active)]',\n ],\n },\n size: {\n small: [\n `${btnPrefix}-small`,\n 'tw-h-7 tw-min-w-7 tw-gap-1 tw-rounded-r-75 tw-text-xs tw-leading-4',\n 'tw-px-[var(--alias-padding-150-minus-1)] tw-py-[var(--alias-padding-75-minus-1)]',\n ],\n middle: [\n `${btnPrefix}-middle`,\n 'tw-h-8 tw-min-w-8 tw-gap-1 tw-rounded-r-75 tw-text-sm tw-leading-5',\n 'tw-px-[var(--alias-padding-150-minus-1)] tw-py-[var(--alias-padding-75-minus-1)]',\n ],\n large: [\n `${btnPrefix}-large`,\n 'tw-h-10 tw-min-w-10 tw-gap-1 tw-rounded-r-75 tw-text-sm tw-leading-6',\n 'tw-px-[var(--alias-padding-150-minus-1)] tw-py-[var(--alias-padding-75-minus-1)]',\n ],\n },\n disabled: {\n true: 'tw-pointer-events-none tw-cursor-default tw-opacity-50',\n false: '',\n },\n block: {\n true: 'tw-w-full',\n false: '',\n },\n shape: {\n circle: 'tw-min-w-0 tw-rounded-full tw-p-0',\n default: '',\n },\n },\n defaultVariants: {\n type: 'secondary',\n size: 'middle',\n disabled: false,\n block: false,\n shape: 'default',\n },\n },\n);\n\nconst VALID_TYPES: ButtonType[] = [\n 'primary',\n 'secondary',\n 'dangerous',\n 'text',\n 'inverse',\n];\n\nfunction Button(props: IButtonProps, ref: React.Ref<HTMLElement>) {\n const {\n type: rawType = 'secondary',\n size: customSize,\n shape = 'default',\n loading = false,\n disabled,\n icon,\n className,\n children,\n href,\n target,\n onClick,\n block,\n htmlType = 'button',\n style,\n ghost,\n showArrow = false,\n ...rest\n } = props;\n\n // Radix Trigger asChild 会传入 type=\"button\"(HTML button type),与组件的 type 变体冲突\n // 当收到非法变体值时回退到 'secondary'\n const type: ButtonType = VALID_TYPES.includes(rawType as ButtonType)\n ? (rawType as ButtonType)\n : 'secondary';\n\n const contextDisabled = useContext(DisabledContext);\n const mergedDisabled = disabled ?? contextDisabled;\n\n const contentSize = useContext(SizeContext);\n const { compactSize, compactItemClassnames } =\n useCompactItemContext(btnPrefix);\n const size = customSize || compactSize || contentSize || 'middle';\n\n const [innerLoading, setInnerLoading] = useState(false);\n\n useEffect(() => {\n if (typeof loading === 'object' && loading.delay) {\n const timer = setTimeout(() => setInnerLoading(true), loading.delay);\n return () => clearTimeout(timer);\n }\n setInnerLoading(!!loading);\n }, [loading]);\n\n const isDisabled = innerLoading || mergedDisabled;\n const iconNode = setIcon(icon as React.ReactElement, innerLoading);\n\n // Build compact-mode border-radius and margin overrides\n const compactClasses = compactItemClassnames\n ? cn(\n // all compact items: remove border-radius on inner edges\n !compactItemClassnames[`${btnPrefix}-compact-first-item`] &&\n '!tw-rounded-l-none',\n !compactItemClassnames[`${btnPrefix}-compact-last-item`] &&\n '!tw-rounded-r-none',\n // merge borders via negative margin (except first item)\n !compactItemClassnames[`${btnPrefix}-compact-first-item`] &&\n '-tw-ml-px',\n )\n : undefined;\n\n const isIconOnly = !!icon && !children && !showArrow;\n\n const classes = cn(\n buttonVariants({\n type,\n size,\n disabled: !!isDisabled,\n block: !!block,\n shape,\n }),\n ghost &&\n '!tw-border-transparent !tw-bg-[var(--action-ghost-normal)] !tw-shadow-none hover:!tw-border-transparent',\n ghost &&\n type === 'primary' &&\n size === 'middle' &&\n '!tw-h-8 !tw-min-w-8 !tw-gap-[var(--component-gap-xs)] !tw-rounded-r-75 !tw-px-[var(--component-padding-md)] !tw-py-0',\n ghost &&\n type === 'dangerous' &&\n size === 'middle' &&\n '!tw-h-8 !tw-min-w-8 !tw-gap-[var(--component-gap-xs)] !tw-rounded-r-75 !tw-px-[var(--component-padding-md)] !tw-py-0',\n ghost &&\n type === 'secondary' &&\n size === 'middle' &&\n '!tw-h-8 !tw-min-w-8 !tw-gap-[var(--component-gap-xs)] !tw-rounded-r-75 !tw-px-[var(--component-padding-md)] !tw-py-0',\n ghost &&\n type === 'inverse' &&\n size === 'middle' &&\n '!tw-h-8 !tw-min-w-8 !tw-gap-[var(--component-gap-xs)] !tw-rounded-r-75 !tw-bg-[var(--action-ghost-normal)] !tw-px-[var(--component-padding-md)] !tw-py-0',\n ghost &&\n type === 'primary' &&\n '!tw-rounded-r-75 hover:!tw-bg-[var(--action-primary-subtle-hover)]',\n ghost &&\n type === 'dangerous' &&\n '!tw-rounded-r-75 hover:!tw-bg-[var(--action-ghost-destructive-hover)]',\n ghost &&\n type === 'secondary' &&\n '!tw-rounded-r-75 hover:!tw-bg-[var(--action-ghost-hover)]',\n ghost &&\n type === 'inverse' &&\n '!tw-rounded-r-75 hover:!tw-bg-[var(--action-ghost-inverted-hover)]',\n ghost && type === 'primary' && '!tw-text-[var(--action-primary-normal)]',\n ghost &&\n type === 'dangerous' &&\n '!tw-text-[var(--action-destructive-normal)]',\n ghost && type === 'secondary' && '!tw-text-[var(--action-neutral-normal)]',\n ghost && type === 'inverse' && '!tw-text-[var(--action-inverted-normal)]',\n // icon-only 方形按钮:宽度由 aspect-ratio 从 height 反推,但该反推值\n // 不构成 flex shrink 的下限——父行 max-content 被低估时(同行存在\n // width:auto Select / RangePicker 等子树时 Chromium 恒少算几 px),\n // 缺口会全压到本按钮上把它压扁。必须按 size 显式钳 min-width 兜底\n // (v2/antd 的 icon-only 即固定 width);带 ! 以盖过 shape=circle\n // 的 tw-min-w-0\n isIconOnly && 'tw-aspect-square !tw-px-0',\n isIconOnly && size === 'small' && '!tw-min-w-7',\n isIconOnly && size === 'middle' && '!tw-min-w-8',\n isIconOnly && size === 'large' && '!tw-min-w-10',\n compactClasses,\n className,\n );\n\n const contentClasses = cn(\n 'tw-inline-flex tw-items-center tw-gap-1',\n ghost &&\n type === 'inverse' &&\n size === 'middle' &&\n 'tw-flex-[1_0_0] tw-text-sm tw-font-medium tw-leading-5 tw-text-[var(--action-inverted-normal)]',\n );\n\n const arrowNode = showArrow ? (\n <span className=\"ald-btn-arrow tw-inline-flex tw-shrink-0 tw-items-center\">\n <ChevronDownLine size={16} />\n </span>\n ) : null;\n\n const buttonContent = (\n <>\n {iconNode}\n {children && <span className={contentClasses}>{children}</span>}\n {arrowNode}\n </>\n );\n\n if (href) {\n return (\n <a\n {...rest}\n className={classes}\n style={style}\n href={isDisabled ? undefined : href}\n target={target}\n ref={ref as React.Ref<HTMLAnchorElement>}\n onClick={isDisabled ? undefined : onClick}\n aria-disabled={isDisabled || undefined}\n >\n {buttonContent}\n </a>\n );\n }\n\n return (\n <button\n {...rest}\n type={\n htmlType === 'submit'\n ? 'submit'\n : htmlType === 'reset'\n ? 'reset'\n : 'button'\n }\n className={classes}\n style={style}\n disabled={isDisabled}\n aria-disabled={isDisabled || undefined}\n ref={ref as React.Ref<HTMLButtonElement>}\n onClick={onClick}\n >\n {buttonContent}\n </button>\n );\n}\n\nexport default forwardRef(Button);\n"],"mappings":";;;;;;;;;;AAQA,IAAa,YAAY;AAiDzB,IAAa,WACX,UACA,YACG;AACH,KAAI,QACF,QACE,oBAAC,QAAD;EACE,WAAU;EACV,MAAM;EACN,OAAM;EACN,CAAA;AAIN,KAAI,UAAU;EACZ,MAAM,IAAqC;GACzC,WAAW;GACX,MAAM;GACN,GAAG,SAAS;GACb;AACD,IAAE,OAAO;AACT,SAAO,MAAM,aAAa,UAAU,EAAE;;AAExC,QAAO,oBAAA,UAAA,EAAK,CAAA;;AAGd,IAAM,iBAAiB,IACrB;CACE;CACA;CACA;CACA;CACD,EACD;CACE,UAAU;EACR,MAAM;GACJ,SAAS;IACP,GAAG,UAAU;IACb;IACA;IACA;IACD;GACD,WAAW;IACT,GAAG,UAAU;IACb;IACA;IACA;IACD;GACD,WAAW;IACT,GAAG,UAAU;IACb;IACA;IACA;IACD;GACD,MAAM;IACJ,GAAG,UAAU;IACb;IACA;IACA;IACD;GACD,SAAS;IACP,GAAG,UAAU;IACb;IACA;IACA;IACD;GACD,MAAM;IACJ,GAAG,UAAU;IACb;IACA;IACA;IACD;GACF;EACD,MAAM;GACJ,OAAO;IACL,GAAG,UAAU;IACb;IACA;IACD;GACD,QAAQ;IACN,GAAG,UAAU;IACb;IACA;IACD;GACD,OAAO;IACL,GAAG,UAAU;IACb;IACA;IACD;GACF;EACD,UAAU;GACR,MAAM;GACN,OAAO;GACR;EACD,OAAO;GACL,MAAM;GACN,OAAO;GACR;EACD,OAAO;GACL,QAAQ;GACR,SAAS;GACV;EACF;CACD,iBAAiB;EACf,MAAM;EACN,MAAM;EACN,UAAU;EACV,OAAO;EACP,OAAO;EACR;CACF,CACF;AAED,IAAM,cAA4B;CAChC;CACA;CACA;CACA;CACA;CACD;AAED,SAAS,OAAO,OAAqB,KAA6B;CAChE,MAAM,EACJ,MAAM,UAAU,aAChB,MAAM,YACN,QAAQ,WACR,UAAU,OACV,UACA,MACA,WACA,UACA,MACA,QACA,SACA,OACA,WAAW,UACX,OACA,OACA,YAAY,OACZ,GAAG,SACD;CAIJ,MAAM,OAAmB,YAAY,SAAS,QAAsB,GAC/D,UACD;CAEJ,MAAM,kBAAkB,WAAW,gBAAgB;CACnD,MAAM,iBAAiB,YAAY;CAEnC,MAAM,cAAc,WAAW,YAAY;CAC3C,MAAM,EAAE,aAAa,0BACnB,sBAAsB,UAAU;CAClC,MAAM,OAAO,cAAc,eAAe,eAAe;CAEzD,MAAM,CAAC,cAAc,mBAAmB,SAAS,MAAM;AAEvD,iBAAgB;AACd,MAAI,OAAO,YAAY,YAAY,QAAQ,OAAO;GAChD,MAAM,QAAQ,iBAAiB,gBAAgB,KAAK,EAAE,QAAQ,MAAM;AACpE,gBAAa,aAAa,MAAM;;AAElC,kBAAgB,CAAC,CAAC,QAAQ;IACzB,CAAC,QAAQ,CAAC;CAEb,MAAM,aAAa,gBAAgB;CACnC,MAAM,WAAW,QAAQ,MAA4B,aAAa;CAGlE,MAAM,iBAAiB,wBACnB,GAEE,CAAC,sBAAsB,iCACrB,sBACF,CAAC,sBAAsB,gCACrB,sBAEF,CAAC,sBAAsB,iCACrB,YACH,GACD;CAEJ,MAAM,aAAa,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC;CAE3C,MAAM,UAAU,GACd,eAAe;EACb;EACA;EACA,UAAU,CAAC,CAAC;EACZ,OAAO,CAAC,CAAC;EACT;EACD,CAAC,EACF,SACE,2GACF,SACE,SAAS,aACT,SAAS,YACT,wHACF,SACE,SAAS,eACT,SAAS,YACT,wHACF,SACE,SAAS,eACT,SAAS,YACT,wHACF,SACE,SAAS,aACT,SAAS,YACT,4JACF,SACE,SAAS,aACT,sEACF,SACE,SAAS,eACT,yEACF,SACE,SAAS,eACT,6DACF,SACE,SAAS,aACT,sEACF,SAAS,SAAS,aAAa,2CAC/B,SACE,SAAS,eACT,+CACF,SAAS,SAAS,eAAe,2CACjC,SAAS,SAAS,aAAa,4CAO/B,cAAc,6BACd,cAAc,SAAS,WAAW,eAClC,cAAc,SAAS,YAAY,eACnC,cAAc,SAAS,WAAW,gBAClC,gBACA,UACD;CAED,MAAM,iBAAiB,GACrB,2CACA,SACE,SAAS,aACT,SAAS,YACT,iGACH;CAQD,MAAM,gBACJ,qBAAA,UAAA,EAAA,UAAA;EACG;EACA,YAAY,oBAAC,QAAD;GAAM,WAAW;GAAiB;GAAgB,CAAA;EATjD,YAChB,oBAAC,QAAD;GAAM,WAAU;aACd,oBAAC,MAAD,EAAiB,MAAM,IAAM,CAAA;GACxB,CAAA,GACL;EAOC,EAAA,CAAA;AAGL,KAAI,KACF,QACE,oBAAC,KAAD;EACE,GAAI;EACJ,WAAW;EACJ;EACP,MAAM,aAAa,SAAY;EACvB;EACH;EACL,SAAS,aAAa,SAAY;EAClC,iBAAe,cAAc;YAE5B;EACC,CAAA;AAIR,QACE,oBAAC,UAAD;EACE,GAAI;EACJ,MACE,aAAa,WACT,WACA,aAAa,UACb,UACA;EAEN,WAAW;EACJ;EACP,UAAU;EACV,iBAAe,cAAc;EACxB;EACI;YAER;EACM,CAAA;;AAIb,IAAA,iBAAe,WAAW,OAAO"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Button/index.tsx"],"sourcesContent":["import { cva } from 'class-variance-authority';\nimport React, { forwardRef, useContext, useEffect, useState } from 'react';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport SizeContext from '../ConfigProvider/sizeContext';\nimport { ChevronDownLine, LoadingLine } from '../Icon';\nimport { cn } from '../lib/utils';\nimport { useCompactItemContext } from '../Space/CompactContext';\n\nexport const btnPrefix = 'ald-btn';\n\nexport type ButtonType =\n | 'primary'\n | 'secondary'\n | 'dangerous'\n | 'text'\n | 'inverse'\n | 'link';\nexport type Size = 'small' | 'middle' | 'large';\nexport interface IButtonProps {\n type?: ButtonType;\n size?: Size;\n disabled?: boolean;\n icon?: React.ReactNode;\n shape?: 'circle' | 'default';\n href?: string;\n target?: string;\n onClick?: React.MouseEventHandler<HTMLElement>;\n loading?: boolean | { delay?: number };\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n block?: boolean;\n htmlType?: 'submit' | 'button' | 'reset';\n id?: string;\n tabIndex?: number;\n title?: string;\n 'aria-label'?: string;\n ghost?: boolean;\n danger?: boolean;\n color?: string;\n showArrow?: boolean;\n}\n\nexport function getButtonType(buttonType: ButtonType): string {\n return buttonType;\n}\nexport function getDangerStatus(buttonType: ButtonType): boolean {\n return buttonType === 'dangerous';\n}\nexport function getButtonSizeClass(s: Size): string {\n return ['small', 'large'].includes(s)\n ? `${btnPrefix}-${s}`\n : `${btnPrefix}-middle`;\n}\nexport function getShape(s: 'circle' | 'default'): 'circle' | 'default' {\n return s;\n}\nexport const setIcon = (\n iconNode: React.ReactElement,\n loading: boolean | { delay?: number },\n) => {\n if (loading) {\n return (\n <LoadingLine\n className=\"ald-loading-spin tw-shrink-0 tw-animate-spin\"\n size={'1em'}\n color=\"currentColor\"\n />\n );\n }\n\n if (iconNode) {\n const p: Record<string, string | number> = {\n className: '',\n fill: 'currentColor',\n ...iconNode.props,\n };\n p.size = '1em';\n return React.cloneElement(iconNode, p);\n }\n return <></>;\n};\n\nconst buttonVariants = cva(\n [\n btnPrefix,\n 'tw-inline-flex tw-cursor-pointer tw-appearance-none tw-items-center tw-justify-center tw-font-medium tw-no-underline tw-transition-colors [&_.i-icon]:tw-inline-flex [&_.i-icon]:tw-items-center',\n 'tw-border tw-border-solid',\n 'focus-visible:tw-outline-none',\n ],\n {\n variants: {\n type: {\n primary: [\n `${btnPrefix}-primary`,\n 'tw-border-transparent tw-bg-[var(--action-primary-normal)] tw-text-[var(--action-inverted-normal)] tw-shadow-[0_1px_2px_0_rgba(27,36,44,0.12)]',\n 'hover:tw-bg-[var(--action-primary-hover)]',\n 'active:tw-bg-[var(--action-primary-active)]',\n ],\n secondary: [\n `${btnPrefix}-secondary`,\n 'tw-border-[var(--action-outline-normal)] tw-bg-[var(--action-inverted-normal)] tw-text-[var(--action-neutral-normal)] tw-shadow-[0_1px_2px_0_rgba(27,36,44,0.12)]',\n 'hover:tw-border-[var(--action-outline-hover)] hover:tw-bg-[var(--action-inverted-normal)]',\n 'active:tw-border-[var(--action-outline-active)] active:tw-bg-[var(--action-inverted-active)] active:tw-text-[var(--action-neutral-active)]',\n ],\n dangerous: [\n `${btnPrefix}-dangerous`,\n 'tw-border-transparent tw-bg-[var(--action-destructive-normal)] tw-text-[var(--action-inverted-normal)] tw-shadow-[0_1px_2px_0_rgba(27,36,44,0.12)]',\n 'hover:tw-bg-[var(--action-destructive-hover)]',\n 'active:tw-bg-[var(--action-destructive-active)]',\n ],\n text: [\n `${btnPrefix}-text`,\n 'tw-border-transparent tw-bg-[var(--action-ghost-normal)] tw-text-[var(--action-neutral-normal)]',\n 'hover:tw-bg-[var(--action-ghost-hover)] hover:tw-text-[var(--action-neutral-hover)]',\n 'active:tw-bg-[var(--action-ghost-active)] active:tw-text-[var(--action-neutral-active)]',\n ],\n inverse: [\n `${btnPrefix}-inverse`,\n 'tw-border-[var(--action-neutral-normal)] tw-bg-[var(--action-ghost-normal)] tw-text-[var(--alias-colors-text-inverse-default)]',\n 'hover:tw-border-[var(--action-ghost-inverted-hover)] hover:tw-bg-[var(--action-ghost-normal)]',\n 'active:tw-bg-[var(--alias-colors-bg-skeleton-inverse-stronger)]',\n ],\n link: [\n `${btnPrefix}-link`,\n 'tw-border-transparent tw-bg-transparent tw-text-[var(--action-primary-normal)]',\n 'hover:tw-text-[var(--action-primary-hover)]',\n 'active:tw-text-[var(--action-primary-active)]',\n ],\n },\n size: {\n small: [\n `${btnPrefix}-small`,\n 'tw-h-7 tw-min-w-7 tw-gap-1 tw-rounded-r-75 tw-text-xs tw-leading-4',\n 'tw-px-[var(--alias-padding-150-minus-1)] tw-py-[var(--alias-padding-75-minus-1)]',\n ],\n middle: [\n `${btnPrefix}-middle`,\n 'tw-h-8 tw-min-w-8 tw-gap-1 tw-rounded-r-75 tw-text-sm tw-leading-5',\n 'tw-px-[var(--alias-padding-150-minus-1)] tw-py-[var(--alias-padding-75-minus-1)]',\n ],\n large: [\n `${btnPrefix}-large`,\n 'tw-h-10 tw-min-w-10 tw-gap-1 tw-rounded-r-75 tw-text-sm tw-leading-6',\n 'tw-px-[var(--alias-padding-150-minus-1)] tw-py-[var(--alias-padding-75-minus-1)]',\n ],\n },\n disabled: {\n true: 'tw-pointer-events-none tw-cursor-default tw-opacity-50',\n false: '',\n },\n block: {\n true: 'tw-w-full',\n false: '',\n },\n shape: {\n circle: 'tw-min-w-0 tw-rounded-full tw-p-0',\n default: '',\n },\n },\n defaultVariants: {\n type: 'secondary',\n size: 'middle',\n disabled: false,\n block: false,\n shape: 'default',\n },\n },\n);\n\nconst VALID_TYPES: ButtonType[] = [\n 'primary',\n 'secondary',\n 'dangerous',\n 'text',\n 'inverse',\n];\n\nfunction Button(props: IButtonProps, ref: React.Ref<HTMLElement>) {\n const {\n type: rawType = 'secondary',\n size: customSize,\n shape = 'default',\n loading = false,\n disabled,\n icon,\n className,\n children,\n href,\n target,\n onClick,\n block,\n htmlType = 'button',\n style,\n ghost,\n showArrow = false,\n ...rest\n } = props;\n\n // Radix Trigger asChild 会传入 type=\"button\"(HTML button type),与组件的 type 变体冲突\n // 当收到非法变体值时回退到 'secondary'\n const type: ButtonType = VALID_TYPES.includes(rawType as ButtonType)\n ? (rawType as ButtonType)\n : 'secondary';\n\n const contextDisabled = useContext(DisabledContext);\n const mergedDisabled = disabled ?? contextDisabled;\n\n const contentSize = useContext(SizeContext);\n const { compactSize, compactItemClassnames } =\n useCompactItemContext(btnPrefix);\n const size = customSize || compactSize || contentSize || 'middle';\n\n const [innerLoading, setInnerLoading] = useState(false);\n\n useEffect(() => {\n if (typeof loading === 'object' && loading.delay) {\n const timer = setTimeout(() => setInnerLoading(true), loading.delay);\n return () => clearTimeout(timer);\n }\n setInnerLoading(!!loading);\n }, [loading]);\n\n const isDisabled = innerLoading || mergedDisabled;\n const iconNode = setIcon(icon as React.ReactElement, innerLoading);\n\n // Build compact-mode border-radius and margin overrides\n const compactClasses = compactItemClassnames\n ? cn(\n // all compact items: remove border-radius on inner edges\n !compactItemClassnames[`${btnPrefix}-compact-first-item`] &&\n '!tw-rounded-l-none',\n !compactItemClassnames[`${btnPrefix}-compact-last-item`] &&\n '!tw-rounded-r-none',\n // merge borders via negative margin (except first item)\n !compactItemClassnames[`${btnPrefix}-compact-first-item`] &&\n '-tw-ml-px',\n )\n : undefined;\n\n const isIconOnly = !!icon && !children && !showArrow;\n\n const classes = cn(\n buttonVariants({\n type,\n size,\n disabled: !!isDisabled,\n block: !!block,\n shape,\n }),\n ghost &&\n '!tw-border-transparent !tw-bg-[var(--action-ghost-normal)] !tw-shadow-none hover:!tw-border-transparent',\n ghost &&\n type === 'primary' &&\n size === 'middle' &&\n '!tw-h-8 !tw-min-w-8 !tw-gap-[var(--component-gap-xs)] !tw-rounded-r-75 !tw-px-[var(--component-padding-md)] !tw-py-0',\n ghost &&\n type === 'dangerous' &&\n size === 'middle' &&\n '!tw-h-8 !tw-min-w-8 !tw-gap-[var(--component-gap-xs)] !tw-rounded-r-75 !tw-px-[var(--component-padding-md)] !tw-py-0',\n ghost &&\n type === 'secondary' &&\n size === 'middle' &&\n '!tw-h-8 !tw-min-w-8 !tw-gap-[var(--component-gap-xs)] !tw-rounded-r-75 !tw-px-[var(--component-padding-md)] !tw-py-0',\n ghost &&\n type === 'inverse' &&\n size === 'middle' &&\n '!tw-h-8 !tw-min-w-8 !tw-gap-[var(--component-gap-xs)] !tw-rounded-r-75 !tw-bg-[var(--action-ghost-normal)] !tw-px-[var(--component-padding-md)] !tw-py-0',\n ghost &&\n type === 'primary' &&\n '!tw-rounded-r-75 hover:!tw-bg-[var(--action-primary-subtle-hover)]',\n ghost &&\n type === 'dangerous' &&\n '!tw-rounded-r-75 hover:!tw-bg-[var(--action-ghost-destructive-hover)]',\n ghost &&\n type === 'secondary' &&\n '!tw-rounded-r-75 hover:!tw-bg-[var(--action-ghost-hover)]',\n ghost &&\n type === 'inverse' &&\n '!tw-rounded-r-75 hover:!tw-bg-[var(--action-ghost-inverted-hover)]',\n ghost && type === 'primary' && '!tw-text-[var(--action-primary-normal)]',\n ghost &&\n type === 'dangerous' &&\n '!tw-text-[var(--action-destructive-normal)]',\n ghost && type === 'secondary' && '!tw-text-[var(--action-neutral-normal)]',\n ghost && type === 'inverse' && '!tw-text-[var(--action-inverted-normal)]',\n // icon-only 方形按钮:宽度由 aspect-ratio 从 height 反推,但该反推值\n // 不构成 flex shrink 的下限——父行 max-content 被低估时(同行存在\n // width:auto Select / RangePicker 等子树时 Chromium 恒少算几 px),\n // 缺口会全压到本按钮上把它压扁。必须按 size 显式钳 min-width 兜底\n // (v2/antd 的 icon-only 即固定 width);带 ! 以盖过 shape=circle\n // 的 tw-min-w-0\n isIconOnly && 'tw-aspect-square !tw-px-0',\n isIconOnly && size === 'small' && '!tw-min-w-7',\n isIconOnly && size === 'middle' && '!tw-min-w-8',\n isIconOnly && size === 'large' && '!tw-min-w-10',\n compactClasses,\n className,\n );\n\n const contentClasses = cn(\n 'tw-inline-flex tw-min-w-0 tw-items-center tw-gap-1 tw-truncate',\n ghost &&\n type === 'inverse' &&\n size === 'middle' &&\n 'tw-flex-[1_0_0] tw-text-sm tw-font-medium tw-leading-5 tw-text-[var(--action-inverted-normal)]',\n );\n\n const arrowNode = showArrow ? (\n <span className=\"ald-btn-arrow tw-inline-flex tw-shrink-0 tw-items-center\">\n <ChevronDownLine size={16} />\n </span>\n ) : null;\n\n const buttonContent = (\n <>\n {iconNode}\n {children && <span className={contentClasses}>{children}</span>}\n {arrowNode}\n </>\n );\n\n if (href) {\n return (\n <a\n {...rest}\n className={classes}\n style={style}\n href={isDisabled ? undefined : href}\n target={target}\n ref={ref as React.Ref<HTMLAnchorElement>}\n onClick={isDisabled ? undefined : onClick}\n aria-disabled={isDisabled || undefined}\n >\n {buttonContent}\n </a>\n );\n }\n\n return (\n <button\n {...rest}\n type={\n htmlType === 'submit'\n ? 'submit'\n : htmlType === 'reset'\n ? 'reset'\n : 'button'\n }\n className={classes}\n style={style}\n disabled={isDisabled}\n aria-disabled={isDisabled || undefined}\n ref={ref as React.Ref<HTMLButtonElement>}\n onClick={onClick}\n >\n {buttonContent}\n </button>\n );\n}\n\nexport default forwardRef(Button);\n"],"mappings":";;;;;;;;;;AAQA,IAAa,YAAY;AAiDzB,IAAa,WACX,UACA,YACG;AACH,KAAI,QACF,QACE,oBAAC,QAAD;EACE,WAAU;EACV,MAAM;EACN,OAAM;EACN,CAAA;AAIN,KAAI,UAAU;EACZ,MAAM,IAAqC;GACzC,WAAW;GACX,MAAM;GACN,GAAG,SAAS;GACb;AACD,IAAE,OAAO;AACT,SAAO,MAAM,aAAa,UAAU,EAAE;;AAExC,QAAO,oBAAA,UAAA,EAAK,CAAA;;AAGd,IAAM,iBAAiB,IACrB;CACE;CACA;CACA;CACA;CACD,EACD;CACE,UAAU;EACR,MAAM;GACJ,SAAS;IACP,GAAG,UAAU;IACb;IACA;IACA;IACD;GACD,WAAW;IACT,GAAG,UAAU;IACb;IACA;IACA;IACD;GACD,WAAW;IACT,GAAG,UAAU;IACb;IACA;IACA;IACD;GACD,MAAM;IACJ,GAAG,UAAU;IACb;IACA;IACA;IACD;GACD,SAAS;IACP,GAAG,UAAU;IACb;IACA;IACA;IACD;GACD,MAAM;IACJ,GAAG,UAAU;IACb;IACA;IACA;IACD;GACF;EACD,MAAM;GACJ,OAAO;IACL,GAAG,UAAU;IACb;IACA;IACD;GACD,QAAQ;IACN,GAAG,UAAU;IACb;IACA;IACD;GACD,OAAO;IACL,GAAG,UAAU;IACb;IACA;IACD;GACF;EACD,UAAU;GACR,MAAM;GACN,OAAO;GACR;EACD,OAAO;GACL,MAAM;GACN,OAAO;GACR;EACD,OAAO;GACL,QAAQ;GACR,SAAS;GACV;EACF;CACD,iBAAiB;EACf,MAAM;EACN,MAAM;EACN,UAAU;EACV,OAAO;EACP,OAAO;EACR;CACF,CACF;AAED,IAAM,cAA4B;CAChC;CACA;CACA;CACA;CACA;CACD;AAED,SAAS,OAAO,OAAqB,KAA6B;CAChE,MAAM,EACJ,MAAM,UAAU,aAChB,MAAM,YACN,QAAQ,WACR,UAAU,OACV,UACA,MACA,WACA,UACA,MACA,QACA,SACA,OACA,WAAW,UACX,OACA,OACA,YAAY,OACZ,GAAG,SACD;CAIJ,MAAM,OAAmB,YAAY,SAAS,QAAsB,GAC/D,UACD;CAEJ,MAAM,kBAAkB,WAAW,gBAAgB;CACnD,MAAM,iBAAiB,YAAY;CAEnC,MAAM,cAAc,WAAW,YAAY;CAC3C,MAAM,EAAE,aAAa,0BACnB,sBAAsB,UAAU;CAClC,MAAM,OAAO,cAAc,eAAe,eAAe;CAEzD,MAAM,CAAC,cAAc,mBAAmB,SAAS,MAAM;AAEvD,iBAAgB;AACd,MAAI,OAAO,YAAY,YAAY,QAAQ,OAAO;GAChD,MAAM,QAAQ,iBAAiB,gBAAgB,KAAK,EAAE,QAAQ,MAAM;AACpE,gBAAa,aAAa,MAAM;;AAElC,kBAAgB,CAAC,CAAC,QAAQ;IACzB,CAAC,QAAQ,CAAC;CAEb,MAAM,aAAa,gBAAgB;CACnC,MAAM,WAAW,QAAQ,MAA4B,aAAa;CAGlE,MAAM,iBAAiB,wBACnB,GAEE,CAAC,sBAAsB,iCACrB,sBACF,CAAC,sBAAsB,gCACrB,sBAEF,CAAC,sBAAsB,iCACrB,YACH,GACD;CAEJ,MAAM,aAAa,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC;CAE3C,MAAM,UAAU,GACd,eAAe;EACb;EACA;EACA,UAAU,CAAC,CAAC;EACZ,OAAO,CAAC,CAAC;EACT;EACD,CAAC,EACF,SACE,2GACF,SACE,SAAS,aACT,SAAS,YACT,wHACF,SACE,SAAS,eACT,SAAS,YACT,wHACF,SACE,SAAS,eACT,SAAS,YACT,wHACF,SACE,SAAS,aACT,SAAS,YACT,4JACF,SACE,SAAS,aACT,sEACF,SACE,SAAS,eACT,yEACF,SACE,SAAS,eACT,6DACF,SACE,SAAS,aACT,sEACF,SAAS,SAAS,aAAa,2CAC/B,SACE,SAAS,eACT,+CACF,SAAS,SAAS,eAAe,2CACjC,SAAS,SAAS,aAAa,4CAO/B,cAAc,6BACd,cAAc,SAAS,WAAW,eAClC,cAAc,SAAS,YAAY,eACnC,cAAc,SAAS,WAAW,gBAClC,gBACA,UACD;CAED,MAAM,iBAAiB,GACrB,kEACA,SACE,SAAS,aACT,SAAS,YACT,iGACH;CAQD,MAAM,gBACJ,qBAAA,UAAA,EAAA,UAAA;EACG;EACA,YAAY,oBAAC,QAAD;GAAM,WAAW;GAAiB;GAAgB,CAAA;EATjD,YAChB,oBAAC,QAAD;GAAM,WAAU;aACd,oBAAC,MAAD,EAAiB,MAAM,IAAM,CAAA;GACxB,CAAA,GACL;EAOC,EAAA,CAAA;AAGL,KAAI,KACF,QACE,oBAAC,KAAD;EACE,GAAI;EACJ,WAAW;EACJ;EACP,MAAM,aAAa,SAAY;EACvB;EACH;EACL,SAAS,aAAa,SAAY;EAClC,iBAAe,cAAc;YAE5B;EACC,CAAA;AAIR,QACE,oBAAC,UAAD;EACE,GAAI;EACJ,MACE,aAAa,WACT,WACA,aAAa,UACb,UACA;EAEN,WAAW;EACJ;EACP,UAAU;EACV,iBAAe,cAAc;EACxB;EACI;YAER;EACM,CAAA;;AAIb,IAAA,iBAAe,WAAW,OAAO"}
@@ -1,6 +1,12 @@
1
1
  import { default as React } from 'react';
2
2
  export interface CollapsePanelProps {
3
- key: string;
3
+ /**
4
+ * 与父 Collapse 协调 activeKey / accordion 的 key。
5
+ * 不提供时 Panel 走内部 state(视觉一致但不参与父协调)。
6
+ * Radix Accordion 等同 prop 名是 `value`;这里沿用 `panelKey` 与已有
7
+ * `Collapse items[].key` 命名一致,迁移成本最低。
8
+ */
9
+ panelKey?: string;
4
10
  header?: React.ReactNode;
5
11
  className?: string;
6
12
  style?: React.CSSProperties;
@@ -10,7 +16,6 @@ export interface CollapsePanelProps {
10
16
  forceRender?: boolean;
11
17
  collapsible?: 'header' | 'icon' | 'disabled';
12
18
  showArrow?: boolean;
13
- ref?: React.Ref<HTMLDivElement>;
14
19
  }
15
20
  export interface CollapseProps {
16
21
  activeKey?: string | string[];
@@ -42,6 +47,6 @@ export interface CollapseProps {
42
47
  }
43
48
  declare const Collapse: {
44
49
  (props: CollapseProps): import("react/jsx-runtime").JSX.Element;
45
- Panel: React.FC<CollapsePanelProps>;
50
+ Panel: React.ForwardRefExoticComponent<CollapsePanelProps & React.RefAttributes<HTMLDivElement>>;
46
51
  };
47
52
  export default Collapse;
@@ -1,10 +1,107 @@
1
1
  import { cn } from "../lib/utils.js";
2
2
  import Memo from "../Icon/components/ArrowRightLightLine.js";
3
- import React, { useRef, useState } from "react";
4
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import React, { useContext, useRef, useState } from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region src/Collapse/index.tsx
6
- /** Internal rendering component for a single panel */
7
- function CollapsePanelInternal(props) {
6
+ var CollapseContext = React.createContext(null);
7
+ var normalizeKeys = (keys) => {
8
+ if (!keys) return [];
9
+ return Array.isArray(keys) ? keys : [keys];
10
+ };
11
+ var Collapse = (props) => {
12
+ const { defaultActiveKey = [], activeKey: controlledActiveKey, accordion, onChange, className, style, bordered = true, ghost, expandIconPosition, expandIcon, items: itemsProp, children } = props;
13
+ const resolvedPosition = expandIconPosition === "left" ? "start" : expandIconPosition === "right" ? "end" : expandIconPosition ?? "start";
14
+ const [internalActiveKey, setInternalActiveKey] = useState(normalizeKeys(defaultActiveKey));
15
+ const activeKeys = controlledActiveKey !== void 0 ? normalizeKeys(controlledActiveKey) : internalActiveKey;
16
+ const toggleKey = (key) => {
17
+ let newKeys;
18
+ if (accordion) newKeys = activeKeys.includes(key) ? [] : [key];
19
+ else newKeys = activeKeys.includes(key) ? activeKeys.filter((k) => k !== key) : [...activeKeys, key];
20
+ if (controlledActiveKey === void 0) setInternalActiveKey(newKeys);
21
+ onChange?.(accordion ? newKeys[0] || "" : newKeys);
22
+ };
23
+ const contextValue = {
24
+ expandIcon,
25
+ expandIconPosition: resolvedPosition,
26
+ bordered: bordered && !ghost,
27
+ activeKeys,
28
+ toggleKey
29
+ };
30
+ /**
31
+ * children 路径:向后兼容老用法 `<Collapse><Collapse.Panel key="1" ...>`
32
+ * ——React `key` 是保留字不会进 Panel props,所以把它读出来 cloneElement
33
+ * 注入到 `panelKey` 上(只对直接子元素生效;包装组件需要业务侧自己透传)。
34
+ */
35
+ const enhancedChildren = React.Children.map(children, (child) => {
36
+ if (!React.isValidElement(child)) return child;
37
+ if (child.type?.__COLLAPSE_PANEL !== true) return child;
38
+ if (child.props.panelKey !== void 0) return child;
39
+ if (child.key === null || child.key === void 0) return child;
40
+ return React.cloneElement(child, { panelKey: String(child.key) });
41
+ });
42
+ return /* @__PURE__ */ jsx(CollapseContext.Provider, {
43
+ value: contextValue,
44
+ children: /* @__PURE__ */ jsx("div", {
45
+ className: cn("ald-collapse ant-collapse tw-flex tw-flex-col tw-items-stretch tw-overflow-hidden tw-rounded-r-75 [&>.ald-collapse-item+.ald-collapse-item]:tw-border-0 [&>.ald-collapse-item+.ald-collapse-item]:tw-border-t [&>.ald-collapse-item+.ald-collapse-item]:tw-border-solid [&>.ald-collapse-item+.ald-collapse-item]:tw-border-[var(--border-default)]", !ghost && !bordered && "tw-bg-[var(--background-neutral-subtle)]", !ghost && bordered && "tw-border tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-neutral-subtle)]", className),
46
+ style,
47
+ children: itemsProp && itemsProp.length > 0 ? itemsProp.map((item) => /* @__PURE__ */ jsx(Panel, {
48
+ panelKey: item.key,
49
+ header: item.label,
50
+ disabled: item.disabled,
51
+ collapsible: item.collapsible,
52
+ extra: item.extra,
53
+ className: item.className,
54
+ style: item.style,
55
+ forceRender: item.forceRender,
56
+ children: item.children
57
+ }, item.key)) : enhancedChildren
58
+ })
59
+ });
60
+ };
61
+ /**
62
+ * Panel —— 始终自渲染。
63
+ *
64
+ * - 在 `<Collapse>` 内(ctx 存在)+ 提供 `panelKey`:受控渲染(参与父 activeKey
65
+ * / accordion 协调),点击调 `ctx.toggleKey`,`isActive` 来自 `ctx.activeKeys`。
66
+ * - 在 `<Collapse>` 内(ctx 存在)+ 未提供 `panelKey`:自渲染 + 独立 state,视觉
67
+ * 配置仍来自 ctx,但与父受控状态隔离(业务包装组件没透传 panelKey 时的退化)。
68
+ * - `<Collapse>` 外使用(ctx 不存在):完全自给自足,视觉配置走默认值。
69
+ *
70
+ * 用 forwardRef 转发 ref 到 `.ald-collapse-item` root div——业务侧包装组件常
71
+ * 需要拿到 panel 容器引用做滚动定位等,向后兼容旧版本 Panel 暴露的 ref API。
72
+ */
73
+ var Panel = React.forwardRef((props, ref) => {
74
+ const ctx = useContext(CollapseContext);
75
+ const { panelKey, header, children, className, style, extra, disabled, collapsible, forceRender } = props;
76
+ const isControlled = ctx !== null && panelKey !== void 0;
77
+ const [internalActive, setInternalActive] = useState(false);
78
+ const isActive = isControlled ? ctx.activeKeys.includes(panelKey) : internalActive;
79
+ const onToggle = () => {
80
+ if (isControlled) ctx.toggleKey(panelKey);
81
+ else setInternalActive((v) => !v);
82
+ };
83
+ const expandIcon = ctx?.expandIcon;
84
+ const expandIconPosition = ctx?.expandIconPosition ?? "start";
85
+ const bordered = ctx?.bordered ?? true;
86
+ return /* @__PURE__ */ jsx(CollapsePanelView, {
87
+ ref,
88
+ header,
89
+ isActive,
90
+ onToggle,
91
+ disabled: disabled || collapsible === "disabled",
92
+ extra,
93
+ className,
94
+ style,
95
+ forceRender,
96
+ expandIcon,
97
+ expandIconPosition,
98
+ bordered,
99
+ children
100
+ });
101
+ });
102
+ Panel.__COLLAPSE_PANEL = true;
103
+ /** 哑视图组件,承担 DOM 结构 + 折叠动画;不持有受控状态,ref 转发到 root div。 */
104
+ var CollapsePanelView = React.forwardRef((props, ref) => {
8
105
  const { header, isActive, onToggle, disabled, extra, className, style, children, forceRender, expandIcon, expandIconPosition = "start", bordered } = props;
9
106
  const contentRef = useRef(null);
10
107
  const [rendered, setRendered] = useState(isActive || !!forceRender);
@@ -25,6 +122,7 @@ function CollapsePanelInternal(props) {
25
122
  children: iconNode
26
123
  });
27
124
  return /* @__PURE__ */ jsxs("div", {
125
+ ref,
28
126
  className: cn("ald-collapse-item ant-collapse-item tw-w-full", isActive && "ald-collapse-item-active", disabled && "tw-pointer-events-none tw-opacity-50", className),
29
127
  style,
30
128
  children: [/* @__PURE__ */ jsxs("div", {
@@ -38,6 +136,7 @@ function CollapsePanelInternal(props) {
38
136
  }),
39
137
  extra && /* @__PURE__ */ jsx("span", {
40
138
  className: "ald-collapse-extra ant-collapse-extra",
139
+ onClick: (e) => e.stopPropagation(),
41
140
  children: extra
42
141
  }),
43
142
  expandIconPosition === "end" && iconElement
@@ -56,90 +155,7 @@ function CollapsePanelInternal(props) {
56
155
  })
57
156
  })]
58
157
  });
59
- }
60
- /**
61
- * Checks whether a React element is a Collapse.Panel.
62
- * We tag the Panel component with a `__COLLAPSE_PANEL` flag
63
- * so we can detect it regardless of module wrapper differences.
64
- */
65
- function isPanelElement(child) {
66
- if (!React.isValidElement(child)) return false;
67
- return child.type?.__COLLAPSE_PANEL === true;
68
- }
69
- /**
70
- * Convert Collapse.Panel children into the internal items format.
71
- */
72
- function panelChildrenToItems(children) {
73
- const items = [];
74
- React.Children.forEach(children, (child) => {
75
- if (!isPanelElement(child)) return;
76
- const { header, children: panelChildren, className, style, extra, disabled, collapsible, forceRender } = child.props;
77
- const panelKey = child.key !== null && child.key !== void 0 ? String(child.key) : "";
78
- items.push({
79
- key: panelKey,
80
- label: header,
81
- children: panelChildren,
82
- className,
83
- style,
84
- extra,
85
- disabled,
86
- collapsible,
87
- forceRender
88
- });
89
- });
90
- return items;
91
- }
92
- var Collapse = (props) => {
93
- const { defaultActiveKey = [], activeKey: controlledActiveKey, accordion, onChange, className, style, bordered = true, ghost, expandIconPosition, expandIcon, items: itemsProp, children } = props;
94
- const resolvedPosition = expandIconPosition === "left" ? "start" : expandIconPosition === "right" ? "end" : expandIconPosition ?? "start";
95
- const normalizeKeys = (keys) => {
96
- if (!keys) return [];
97
- return Array.isArray(keys) ? keys : [keys];
98
- };
99
- const [internalActiveKey, setInternalActiveKey] = useState(normalizeKeys(defaultActiveKey));
100
- const activeKeys = controlledActiveKey !== void 0 ? normalizeKeys(controlledActiveKey) : internalActiveKey;
101
- const toggleKey = (key) => {
102
- let newKeys;
103
- if (accordion) newKeys = activeKeys.includes(key) ? [] : [key];
104
- else newKeys = activeKeys.includes(key) ? activeKeys.filter((k) => k !== key) : [...activeKeys, key];
105
- if (controlledActiveKey === void 0) setInternalActiveKey(newKeys);
106
- onChange?.(accordion ? newKeys[0] || "" : newKeys);
107
- };
108
- const items = itemsProp || (children ? panelChildrenToItems(children) : void 0);
109
- const renderItems = () => {
110
- if (items && items.length > 0) return items.map((item, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [index > 0 && /* @__PURE__ */ jsx("div", { className: "ald-collapse-divider" }), /* @__PURE__ */ jsx(CollapsePanelInternal, {
111
- panelKey: item.key,
112
- header: item.label,
113
- isActive: activeKeys.includes(item.key),
114
- onToggle: () => toggleKey(item.key),
115
- disabled: item.disabled || item.collapsible === "disabled",
116
- extra: item.extra,
117
- className: item.className,
118
- style: item.style,
119
- forceRender: item.forceRender,
120
- expandIcon,
121
- expandIconPosition: resolvedPosition,
122
- bordered: bordered && !ghost,
123
- children: item.children
124
- })] }, item.key));
125
- return children;
126
- };
127
- return /* @__PURE__ */ jsx("div", {
128
- className: cn("ald-collapse ant-collapse tw-flex tw-flex-col tw-items-stretch tw-overflow-hidden tw-rounded-r-75 [&>.ald-collapse-divider]:tw-h-px [&>.ald-collapse-divider]:tw-w-full [&>.ald-collapse-divider]:tw-bg-[var(--border-default)]", !ghost && !bordered && "tw-bg-[var(--background-neutral-subtle)]", !ghost && bordered && "tw-border tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-neutral-subtle)]", className),
129
- style,
130
- children: renderItems()
131
- });
132
- };
133
- /**
134
- * Collapse.Panel — legacy sub-component for backwards compatibility.
135
- * When used as a child of <Collapse>, the parent extracts its props
136
- * and renders the panels via the internal CollapsePanelInternal component.
137
- * Panel itself never renders directly; the parent handles rendering.
138
- */
139
- var Panel = ({ children }) => {
140
- return /* @__PURE__ */ jsx(Fragment, { children });
141
- };
142
- Panel.__COLLAPSE_PANEL = true;
158
+ });
143
159
  Collapse.Panel = Panel;
144
160
  //#endregion
145
161
  export { Collapse as default };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Collapse/index.tsx"],"sourcesContent":["import React, { useRef, useState } from 'react';\nimport { ArrowRightLightLine } from '../Icon';\nimport { cn } from '../lib/utils';\n\nexport interface CollapsePanelProps {\n key: string;\n header?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n disabled?: boolean;\n extra?: React.ReactNode;\n forceRender?: boolean;\n collapsible?: 'header' | 'icon' | 'disabled';\n showArrow?: boolean;\n ref?: React.Ref<HTMLDivElement>;\n}\n\nexport interface CollapseProps {\n activeKey?: string | string[];\n defaultActiveKey?: string | string[];\n accordion?: boolean;\n onChange?: (key: string | string[]) => void;\n className?: string;\n style?: React.CSSProperties;\n bordered?: boolean;\n expandIconPosition?: 'start' | 'end' | 'left' | 'right';\n expandIcon?: (props: { isActive: boolean }) => React.ReactNode;\n ghost?: boolean;\n size?: 'large' | 'middle' | 'small';\n collapsible?: 'header' | 'icon' | 'disabled';\n children?: React.ReactNode;\n items?: Array<{\n key: string;\n label: React.ReactNode;\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n extra?: React.ReactNode;\n disabled?: boolean;\n collapsible?: 'header' | 'icon' | 'disabled';\n forceRender?: boolean;\n }>;\n}\n\n/** Internal rendering component for a single panel */\nfunction CollapsePanelInternal(props: {\n panelKey: string;\n header: React.ReactNode;\n isActive: boolean;\n onToggle: () => void;\n disabled?: boolean;\n extra?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n forceRender?: boolean;\n expandIcon?: (props: { isActive: boolean }) => React.ReactNode;\n expandIconPosition?: 'start' | 'end';\n bordered?: boolean;\n}) {\n const {\n header,\n isActive,\n onToggle,\n disabled,\n extra,\n className,\n style,\n children,\n forceRender,\n expandIcon,\n expandIconPosition = 'start',\n bordered,\n } = props;\n\n const contentRef = useRef<HTMLDivElement>(null);\n const [rendered, setRendered] = useState(isActive || !!forceRender);\n\n // Ensure content is in DOM before expanding so transition can play\n if (isActive && !rendered) {\n setRendered(true);\n }\n\n const handleTransitionEnd = () => {\n if (!isActive && !forceRender) {\n setRendered(false);\n }\n };\n\n const iconNode = expandIcon ? (\n expandIcon({ isActive })\n ) : (\n <ArrowRightLightLine size={20} color=\"var(--alias-colors-icon-subtle)\" />\n );\n\n // antd 兼容:保留 ant-collapse-expand-icon class,消费方 CSS 可能依赖该选择器\n const iconElement = (\n <span\n className=\"ald-collapse-expand-icon ant-collapse-expand-icon tw-flex tw-items-center\"\n style={{\n transform: isActive ? 'rotate(90deg)' : 'rotate(0deg)',\n transition: 'transform 200ms',\n }}\n >\n {iconNode}\n </span>\n );\n\n return (\n <div\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-collapse-item ant-collapse-item tw-w-full',\n isActive && 'ald-collapse-item-active',\n disabled && 'tw-pointer-events-none tw-opacity-50',\n className,\n )}\n style={style}\n >\n <div\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n className=\"ald-collapse-header ant-collapse-header tw-flex tw-cursor-pointer tw-items-center tw-gap-2 tw-p-3\"\n onClick={disabled ? undefined : onToggle}\n >\n {expandIconPosition === 'start' && iconElement}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <span className=\"ald-collapse-header-text ant-collapse-header-text tw-flex-1 tw-text-sm tw-font-medium tw-leading-5 tw-text-[var(--content-primary)]\">\n {header}\n </span>\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n {extra && (\n <span className=\"ald-collapse-extra ant-collapse-extra\">{extra}</span>\n )}\n {expandIconPosition === 'end' && iconElement}\n </div>\n <div\n className=\"tw-grid tw-transition-[grid-template-rows] tw-duration-200\"\n style={{ gridTemplateRows: isActive ? '1fr' : '0fr' }}\n onTransitionEnd={handleTransitionEnd}\n >\n <div className=\"tw-overflow-hidden\">\n {rendered && (\n <div\n ref={contentRef}\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n className={cn(\n // 默认列方向 + items-stretch,使 block 级子元素能撑满宽度(与 antd\n // Collapse 内容区行为一致)。row 布局由消费方自行包裹,避免在这里\n // 把\"label 靠左 / 控件靠右\"这种 space-between 行布局压缩掉。\n 'ald-collapse-content ant-collapse-content tw-flex tw-flex-col tw-items-stretch tw-gap-2.5 tw-self-stretch',\n bordered\n ? 'tw-bg-[var(--background-default)] tw-p-4'\n : 'tw-px-4 tw-pb-4 tw-pt-0',\n )}\n >\n {children}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n\n/**\n * Checks whether a React element is a Collapse.Panel.\n * We tag the Panel component with a `__COLLAPSE_PANEL` flag\n * so we can detect it regardless of module wrapper differences.\n */\nfunction isPanelElement(\n child: React.ReactNode,\n): child is React.ReactElement<CollapsePanelProps> {\n if (!React.isValidElement(child)) return false;\n return (child.type as any)?.__COLLAPSE_PANEL === true;\n}\n\n/**\n * Convert Collapse.Panel children into the internal items format.\n */\nfunction panelChildrenToItems(children: React.ReactNode) {\n const items: Array<{\n key: string;\n label: React.ReactNode;\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n extra?: React.ReactNode;\n disabled?: boolean;\n collapsible?: 'header' | 'icon' | 'disabled';\n forceRender?: boolean;\n }> = [];\n\n React.Children.forEach(children, (child) => {\n if (!isPanelElement(child)) return;\n const {\n header,\n children: panelChildren,\n className,\n style,\n extra,\n disabled,\n collapsible,\n forceRender,\n } = child.props;\n\n // The `key` prop is not part of child.props in React — access it from child.key\n const panelKey =\n child.key !== null && child.key !== undefined ? String(child.key) : '';\n\n items.push({\n key: panelKey,\n label: header,\n children: panelChildren,\n className,\n style,\n extra,\n disabled,\n collapsible,\n forceRender,\n });\n });\n\n return items;\n}\n\nconst Collapse = (props: CollapseProps) => {\n const {\n defaultActiveKey = [],\n activeKey: controlledActiveKey,\n accordion,\n onChange,\n className,\n style,\n bordered = true,\n ghost,\n expandIconPosition,\n expandIcon,\n items: itemsProp,\n children,\n } = props;\n\n const resolvedPosition =\n expandIconPosition === 'left'\n ? 'start'\n : expandIconPosition === 'right'\n ? 'end'\n : expandIconPosition ?? 'start';\n\n const normalizeKeys = (keys: string | string[] | undefined): string[] => {\n if (!keys) return [];\n return Array.isArray(keys) ? keys : [keys];\n };\n\n const [internalActiveKey, setInternalActiveKey] = useState<string[]>(\n normalizeKeys(defaultActiveKey),\n );\n\n const activeKeys =\n controlledActiveKey !== undefined\n ? normalizeKeys(controlledActiveKey)\n : internalActiveKey;\n\n const toggleKey = (key: string) => {\n let newKeys: string[];\n if (accordion) {\n newKeys = activeKeys.includes(key) ? [] : [key];\n } else {\n newKeys = activeKeys.includes(key)\n ? activeKeys.filter((k) => k !== key)\n : [...activeKeys, key];\n }\n if (controlledActiveKey === undefined) {\n setInternalActiveKey(newKeys);\n }\n onChange?.(accordion ? newKeys[0] || '' : newKeys);\n };\n\n // Resolve items: from `items` prop, or by converting Panel children\n const items =\n itemsProp || (children ? panelChildrenToItems(children) : undefined);\n\n const renderItems = () => {\n if (items && items.length > 0) {\n return items.map((item, index) => (\n <React.Fragment key={item.key}>\n {index > 0 && <div className=\"ald-collapse-divider\" />}\n <CollapsePanelInternal\n panelKey={item.key}\n header={item.label}\n isActive={activeKeys.includes(item.key)}\n onToggle={() => toggleKey(item.key)}\n disabled={item.disabled || item.collapsible === 'disabled'}\n extra={item.extra}\n className={item.className}\n style={item.style}\n forceRender={item.forceRender}\n expandIcon={expandIcon}\n expandIconPosition={resolvedPosition}\n bordered={bordered && !ghost}\n >\n {item.children}\n </CollapsePanelInternal>\n </React.Fragment>\n ));\n }\n // If children are not Panel elements (rare fallback), render them as-is\n return children;\n };\n\n return (\n <div\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-collapse ant-collapse tw-flex tw-flex-col tw-items-stretch tw-overflow-hidden tw-rounded-r-75 [&>.ald-collapse-divider]:tw-h-px [&>.ald-collapse-divider]:tw-w-full [&>.ald-collapse-divider]:tw-bg-[var(--border-default)]',\n !ghost && !bordered && 'tw-bg-[var(--background-neutral-subtle)]',\n !ghost &&\n bordered &&\n 'tw-border tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-neutral-subtle)]',\n className,\n )}\n style={style}\n >\n {renderItems()}\n </div>\n );\n};\n\n/**\n * Collapse.Panel — legacy sub-component for backwards compatibility.\n * When used as a child of <Collapse>, the parent extracts its props\n * and renders the panels via the internal CollapsePanelInternal component.\n * Panel itself never renders directly; the parent handles rendering.\n */\nconst Panel: React.FC<CollapsePanelProps> = ({ children }) => {\n // This component should never render on its own — Collapse extracts\n // its props. But if used outside of Collapse, render children as fallback.\n return <>{children}</>;\n};\n\n// Tag for detection by isPanelElement\n(Panel as any).__COLLAPSE_PANEL = true;\n\nCollapse.Panel = Panel;\n\nexport default Collapse;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Collapse/index.tsx"],"sourcesContent":["import React, { useContext, useRef, useState } from 'react';\nimport { ArrowRightLightLine } from '../Icon';\nimport { cn } from '../lib/utils';\n\n/**\n * Compound Components 模式:Collapse 通过 Context 注入受控状态 + 视觉配置,\n * Panel 始终自渲染(header + 折叠交互),靠 `panelKey` 与父协调 activeKey /\n * accordion。设计对齐 Radix / Mantine:Item 自渲染,靠声明式 value 与 Root 通信。\n *\n * 这里不再做\"扫描 children 提 Panel props 再替换渲染\"的 hack——后者无法穿透\n * forwardRef / 业务包装组件边界,是 ald v3 升级回归\"包装 Panel 丢 header\"的根因。\n */\ninterface CollapseContextValue {\n // 视觉配置\n expandIcon?: (props: { isActive: boolean }) => React.ReactNode;\n expandIconPosition: 'start' | 'end';\n bordered: boolean;\n // 受控状态协调\n activeKeys: string[];\n toggleKey: (key: string) => void;\n}\n\nconst CollapseContext = React.createContext<CollapseContextValue | null>(null);\n\nexport interface CollapsePanelProps {\n /**\n * 与父 Collapse 协调 activeKey / accordion 的 key。\n * 不提供时 Panel 走内部 state(视觉一致但不参与父协调)。\n * Radix Accordion 等同 prop 名是 `value`;这里沿用 `panelKey` 与已有\n * `Collapse items[].key` 命名一致,迁移成本最低。\n */\n panelKey?: string;\n header?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n disabled?: boolean;\n extra?: React.ReactNode;\n forceRender?: boolean;\n collapsible?: 'header' | 'icon' | 'disabled';\n showArrow?: boolean;\n}\n\nexport interface CollapseProps {\n activeKey?: string | string[];\n defaultActiveKey?: string | string[];\n accordion?: boolean;\n onChange?: (key: string | string[]) => void;\n className?: string;\n style?: React.CSSProperties;\n bordered?: boolean;\n expandIconPosition?: 'start' | 'end' | 'left' | 'right';\n expandIcon?: (props: { isActive: boolean }) => React.ReactNode;\n ghost?: boolean;\n size?: 'large' | 'middle' | 'small';\n collapsible?: 'header' | 'icon' | 'disabled';\n children?: React.ReactNode;\n items?: Array<{\n key: string;\n label: React.ReactNode;\n children?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n extra?: React.ReactNode;\n disabled?: boolean;\n collapsible?: 'header' | 'icon' | 'disabled';\n forceRender?: boolean;\n }>;\n}\n\nconst normalizeKeys = (keys: string | string[] | undefined): string[] => {\n if (!keys) return [];\n return Array.isArray(keys) ? keys : [keys];\n};\n\nconst Collapse = (props: CollapseProps) => {\n const {\n defaultActiveKey = [],\n activeKey: controlledActiveKey,\n accordion,\n onChange,\n className,\n style,\n bordered = true,\n ghost,\n expandIconPosition,\n expandIcon,\n items: itemsProp,\n children,\n } = props;\n\n const resolvedPosition =\n expandIconPosition === 'left'\n ? 'start'\n : expandIconPosition === 'right'\n ? 'end'\n : expandIconPosition ?? 'start';\n\n const [internalActiveKey, setInternalActiveKey] = useState<string[]>(\n normalizeKeys(defaultActiveKey),\n );\n\n const activeKeys =\n controlledActiveKey !== undefined\n ? normalizeKeys(controlledActiveKey)\n : internalActiveKey;\n\n const toggleKey = (key: string) => {\n let newKeys: string[];\n if (accordion) {\n newKeys = activeKeys.includes(key) ? [] : [key];\n } else {\n newKeys = activeKeys.includes(key)\n ? activeKeys.filter((k) => k !== key)\n : [...activeKeys, key];\n }\n if (controlledActiveKey === undefined) {\n setInternalActiveKey(newKeys);\n }\n onChange?.(accordion ? newKeys[0] || '' : newKeys);\n };\n\n const contextValue: CollapseContextValue = {\n expandIcon,\n expandIconPosition: resolvedPosition,\n bordered: bordered && !ghost,\n activeKeys,\n toggleKey,\n };\n\n /**\n * children 路径:向后兼容老用法 `<Collapse><Collapse.Panel key=\"1\" ...>`\n * ——React `key` 是保留字不会进 Panel props,所以把它读出来 cloneElement\n * 注入到 `panelKey` 上(只对直接子元素生效;包装组件需要业务侧自己透传)。\n */\n const enhancedChildren = React.Children.map(children, (child) => {\n if (!React.isValidElement<CollapsePanelProps>(child)) return child;\n if ((child.type as any)?.__COLLAPSE_PANEL !== true) return child;\n if (child.props.panelKey !== undefined) return child;\n if (child.key === null || child.key === undefined) return child;\n return React.cloneElement(child, { panelKey: String(child.key) });\n });\n\n return (\n <CollapseContext.Provider value={contextValue}>\n <div\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n // 相邻 .ald-collapse-item 用 CSS 兄弟选择器画分隔线,避免在 React 树里\n // 注入 <div .ald-collapse-divider /> 节点——后者在\"业务包装 Panel\"场景\n // 需要 Collapse 知道子元素拓扑,与 Compound Components 解耦原则冲突。\n 'ald-collapse ant-collapse tw-flex tw-flex-col tw-items-stretch tw-overflow-hidden tw-rounded-r-75 [&>.ald-collapse-item+.ald-collapse-item]:tw-border-0 [&>.ald-collapse-item+.ald-collapse-item]:tw-border-t [&>.ald-collapse-item+.ald-collapse-item]:tw-border-solid [&>.ald-collapse-item+.ald-collapse-item]:tw-border-[var(--border-default)]',\n !ghost && !bordered && 'tw-bg-[var(--background-neutral-subtle)]',\n !ghost &&\n bordered &&\n 'tw-border tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-neutral-subtle)]',\n className,\n )}\n style={style}\n >\n {itemsProp && itemsProp.length > 0\n ? itemsProp.map((item) => (\n <Panel\n key={item.key}\n panelKey={item.key}\n header={item.label}\n disabled={item.disabled}\n collapsible={item.collapsible}\n extra={item.extra}\n className={item.className}\n style={item.style}\n forceRender={item.forceRender}\n >\n {item.children}\n </Panel>\n ))\n : enhancedChildren}\n </div>\n </CollapseContext.Provider>\n );\n};\n\n/**\n * Panel —— 始终自渲染。\n *\n * - 在 `<Collapse>` 内(ctx 存在)+ 提供 `panelKey`:受控渲染(参与父 activeKey\n * / accordion 协调),点击调 `ctx.toggleKey`,`isActive` 来自 `ctx.activeKeys`。\n * - 在 `<Collapse>` 内(ctx 存在)+ 未提供 `panelKey`:自渲染 + 独立 state,视觉\n * 配置仍来自 ctx,但与父受控状态隔离(业务包装组件没透传 panelKey 时的退化)。\n * - `<Collapse>` 外使用(ctx 不存在):完全自给自足,视觉配置走默认值。\n *\n * 用 forwardRef 转发 ref 到 `.ald-collapse-item` root div——业务侧包装组件常\n * 需要拿到 panel 容器引用做滚动定位等,向后兼容旧版本 Panel 暴露的 ref API。\n */\nconst Panel = React.forwardRef<HTMLDivElement, CollapsePanelProps>(\n (props, ref) => {\n const ctx = useContext(CollapseContext);\n const {\n panelKey,\n header,\n children,\n className,\n style,\n extra,\n disabled,\n collapsible,\n forceRender,\n } = props;\n\n const isControlled = ctx !== null && panelKey !== undefined;\n\n const [internalActive, setInternalActive] = useState(false);\n\n const isActive = isControlled\n ? ctx!.activeKeys.includes(panelKey!)\n : internalActive;\n\n const onToggle = () => {\n if (isControlled) {\n ctx!.toggleKey(panelKey!);\n } else {\n setInternalActive((v) => !v);\n }\n };\n\n const expandIcon = ctx?.expandIcon;\n const expandIconPosition = ctx?.expandIconPosition ?? 'start';\n const bordered = ctx?.bordered ?? true;\n\n return (\n <CollapsePanelView\n ref={ref}\n header={header}\n isActive={isActive}\n onToggle={onToggle}\n disabled={disabled || collapsible === 'disabled'}\n extra={extra}\n className={className}\n style={style}\n forceRender={forceRender}\n expandIcon={expandIcon}\n expandIconPosition={expandIconPosition}\n bordered={bordered}\n >\n {children}\n </CollapsePanelView>\n );\n },\n);\n\n(Panel as any).__COLLAPSE_PANEL = true;\n\ninterface CollapsePanelViewProps {\n header: React.ReactNode;\n isActive: boolean;\n onToggle: () => void;\n disabled?: boolean;\n extra?: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n forceRender?: boolean;\n expandIcon?: (props: { isActive: boolean }) => React.ReactNode;\n expandIconPosition?: 'start' | 'end';\n bordered?: boolean;\n}\n\n/** 哑视图组件,承担 DOM 结构 + 折叠动画;不持有受控状态,ref 转发到 root div。 */\nconst CollapsePanelView = React.forwardRef<\n HTMLDivElement,\n CollapsePanelViewProps\n>((props, ref) => {\n const {\n header,\n isActive,\n onToggle,\n disabled,\n extra,\n className,\n style,\n children,\n forceRender,\n expandIcon,\n expandIconPosition = 'start',\n bordered,\n } = props;\n\n const contentRef = useRef<HTMLDivElement>(null);\n const [rendered, setRendered] = useState(isActive || !!forceRender);\n\n if (isActive && !rendered) {\n setRendered(true);\n }\n\n const handleTransitionEnd = () => {\n if (!isActive && !forceRender) {\n setRendered(false);\n }\n };\n\n const iconNode = expandIcon ? (\n expandIcon({ isActive })\n ) : (\n <ArrowRightLightLine size={20} color=\"var(--alias-colors-icon-subtle)\" />\n );\n\n const iconElement = (\n <span\n className=\"ald-collapse-expand-icon ant-collapse-expand-icon tw-flex tw-items-center\"\n style={{\n transform: isActive ? 'rotate(90deg)' : 'rotate(0deg)',\n transition: 'transform 200ms',\n }}\n >\n {iconNode}\n </span>\n );\n\n return (\n <div\n ref={ref}\n className={cn(\n 'ald-collapse-item ant-collapse-item tw-w-full',\n isActive && 'ald-collapse-item-active',\n disabled && 'tw-pointer-events-none tw-opacity-50',\n className,\n )}\n style={style}\n >\n <div\n className=\"ald-collapse-header ant-collapse-header tw-flex tw-cursor-pointer tw-items-center tw-gap-2 tw-p-3\"\n onClick={disabled ? undefined : onToggle}\n >\n {expandIconPosition === 'start' && iconElement}\n <span className=\"ald-collapse-header-text ant-collapse-header-text tw-flex-1 tw-text-sm tw-font-medium tw-leading-5 tw-text-[var(--content-primary)]\">\n {header}\n </span>\n {extra && (\n // extra 区域里常放 Switch / Button 等交互控件,点击不该冒泡触发 panel\n // 切展开/收起。antd Collapse 也是同样行为;不强制消费方在每个 extra\n // 控件上自己写 stopPropagation。\n <span\n className=\"ald-collapse-extra ant-collapse-extra\"\n onClick={(e) => e.stopPropagation()}\n >\n {extra}\n </span>\n )}\n {expandIconPosition === 'end' && iconElement}\n </div>\n <div\n className=\"tw-grid tw-transition-[grid-template-rows] tw-duration-200\"\n style={{ gridTemplateRows: isActive ? '1fr' : '0fr' }}\n onTransitionEnd={handleTransitionEnd}\n >\n <div className=\"tw-overflow-hidden\">\n {rendered && (\n <div\n ref={contentRef}\n className={cn(\n 'ald-collapse-content ant-collapse-content tw-flex tw-flex-col tw-items-stretch tw-gap-2.5 tw-self-stretch',\n bordered\n ? 'tw-bg-[var(--background-default)] tw-p-4'\n : 'tw-px-4 tw-pb-4 tw-pt-0',\n )}\n >\n {children}\n </div>\n )}\n </div>\n </div>\n </div>\n );\n});\n\nCollapse.Panel = Panel;\n\nexport default Collapse;\n"],"mappings":"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"}
@@ -141,7 +141,7 @@ function FormItemLayout({ label, children, meta, help, extra, required, rules, h
141
141
  })
142
142
  }) : null;
143
143
  const controlNode = /* @__PURE__ */ jsxs("div", {
144
- className: cn("ald-form-item-control ant-form-item-control", layout === "horizontal" && "tw-flex-1"),
144
+ className: cn("ald-form-item-control ant-form-item-control", layout === "horizontal" && "tw-min-w-0 tw-flex-1"),
145
145
  style: useGridLayout ? colStyle(resolvedWrapperCol) : void 0,
146
146
  children: [
147
147
  /* @__PURE__ */ jsx(FormItemInputContext.Provider, {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Form/index.tsx"],"sourcesContent":["import RcForm, {\n Field,\n FormInstance as RcFormInstance,\n FormProvider,\n List,\n useForm as rcUseForm,\n useWatch,\n} from 'rc-field-form';\nimport type { FormProps as RcFormProps } from 'rc-field-form';\nimport FieldContext from 'rc-field-form/es/FieldContext';\nimport type { Rule, RuleObject, RuleRender } from 'rc-field-form/es/interface';\nimport type { Meta, NamePath } from 'rc-field-form/es/interface';\nimport React, { forwardRef, useContext, useMemo } from 'react';\nimport SizeContext, {\n SizeContextProvider,\n} from '../ConfigProvider/sizeContext';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport { cn } from '../lib/utils';\nimport {\n FormContext,\n FormItemInputContext,\n type ValidateStatus,\n} from './FormItemContext';\n\n/**\n * Loose NamePath: accepts string, number, or array of them.\n * antd v4 uses loose paths; rc-field-form v2 uses strict DeepNamePath.\n * We override to keep backward compatibility.\n */\ntype LooseNamePath = string | number | (string | number)[];\n\n/**\n * FormInstance — extends rc-field-form FormInstance with loose-typed overloads\n * to maintain antd v4 backward compatibility. Uses intersection so that both\n * strict DeepNamePath and loose LooseNamePath signatures are accepted.\n */\nexport type FormInstance<Values = any> = RcFormInstance<Values> & {\n getFieldValue(name: LooseNamePath): any;\n setFieldValue(name: LooseNamePath, value: any): void;\n setFieldsValue(values: Record<string, any>): void;\n getFieldsValue(): Values;\n getFieldsValue(\n nameList: LooseNamePath[] | true,\n filterFunc?: (meta: Meta) => boolean,\n ): any;\n getFieldError(name: LooseNamePath): string[];\n getFieldsError(\n nameList?: LooseNamePath[],\n ): { name: (string | number)[]; errors: string[] }[];\n getFieldWarning(name: LooseNamePath): string[];\n isFieldTouched(name: LooseNamePath): boolean;\n isFieldsTouched(\n nameList?: LooseNamePath[],\n allFieldsTouched?: boolean,\n ): boolean;\n isFieldValidating(name: LooseNamePath): boolean;\n isFieldsValidating(nameList?: LooseNamePath[]): boolean;\n setFields(fields: FieldData[]): void;\n resetFields(fields?: LooseNamePath[]): void;\n validateFields(nameList?: LooseNamePath[]): Promise<Values>;\n /** Scroll to field position (antd-compatible extension) */\n scrollToField?(\n name: LooseNamePath,\n options?: { behavior?: 'smooth' | 'auto' },\n ): void;\n};\n\n// FormProps compatible with antd\nexport interface FormProps<Values = any> extends Omit<RcFormProps, 'form'> {\n form?: FormInstance<Values>;\n layout?: 'horizontal' | 'vertical' | 'inline';\n size?: 'small' | 'middle' | 'large';\n colon?: boolean;\n disabled?: boolean;\n labelCol?: { span?: number; offset?: number };\n wrapperCol?: { span?: number; offset?: number };\n className?: string;\n style?: React.CSSProperties;\n requiredMark?: boolean | 'optional';\n labelWidth?: number;\n labelAlign?: 'left' | 'right';\n}\n\n// FormItemProps\nexport interface FormItemProps {\n name?: NamePath;\n label?: React.ReactNode;\n rules?: Rule[];\n children?: React.ReactNode | ((form: RcFormInstance) => React.ReactNode);\n className?: string;\n style?: React.CSSProperties;\n required?: boolean;\n hidden?: boolean;\n initialValue?: any;\n dependencies?: NamePath[];\n shouldUpdate?: boolean | ((prevValues: any, curValues: any) => boolean);\n help?: React.ReactNode;\n extra?: React.ReactNode;\n validateTrigger?: string | string[];\n valuePropName?: string;\n getValueFromEvent?: (...args: any[]) => any;\n noStyle?: boolean;\n labelWidth?: number;\n tooltip?:\n | React.ReactNode\n | { title?: React.ReactNode; icon?: React.ReactNode };\n labelCol?: { span?: number; offset?: number; [key: string]: any };\n wrapperCol?: { span?: number; offset?: number; [key: string]: any };\n validateStatus?: ValidateStatus;\n colon?: boolean;\n trigger?: string;\n normalize?: (value: any, prevValue: any, allValues: any) => any;\n getValueProps?: (value: any) => Record<string, any>;\n}\n\n/** antd v4 compat: FormLabelAlign */\nexport type FormLabelAlign = 'left' | 'right';\n\n/** antd v4 compat: FieldData */\nexport type FieldData = {\n name: NamePath;\n value?: any;\n touched?: boolean;\n validating?: boolean;\n errors?: string[];\n};\n\nexport interface ErrorListProps {\n errors?: React.ReactNode[];\n help?: React.ReactNode;\n className?: string;\n}\n\nexport type FormListFieldData = {\n name: number;\n key: number;\n isListField: boolean;\n};\n\nexport type FormListOperation = {\n add: (defaultValue?: any, insertIndex?: number) => void;\n remove: (index: number | number[]) => void;\n move: (from: number, to: number) => void;\n};\n\nexport type FormListProps = {\n name: NamePath;\n rules?: Rule[];\n children: (\n fields: FormListFieldData[],\n operation: FormListOperation,\n meta: { errors: React.ReactNode[] },\n ) => React.ReactNode;\n initialValue?: any[];\n};\n\n// ============== Helpers ==============\n\n/** Convert a 24-column span/offset to Tailwind-compatible inline styles */\nfunction colStyle(col?: {\n span?: number;\n offset?: number;\n}): React.CSSProperties | undefined {\n if (!col) return undefined;\n const s: React.CSSProperties = {};\n if (col.span !== null && col.span !== undefined) {\n // 24-column grid: width = span / 24 * 100%\n s.width = `${(col.span / 24) * 100}%`;\n s.flex = `0 0 ${(col.span / 24) * 100}%`;\n }\n if (col.offset !== null && col.offset !== undefined && col.offset > 0) {\n s.marginLeft = `${(col.offset / 24) * 100}%`;\n }\n return s;\n}\n\nfunction mergeControlProps(\n childProps: Record<string, any>,\n control: Record<string, any>,\n) {\n const mergedControl = { ...control };\n\n Object.keys(control).forEach((key) => {\n const controlHandler = control[key];\n const childHandler = childProps[key];\n\n if (\n typeof controlHandler === 'function' &&\n typeof childHandler === 'function'\n ) {\n mergedControl[key] = (...args: any[]) => {\n controlHandler(...args);\n childHandler(...args);\n };\n }\n });\n\n return mergedControl;\n}\n\n// ============== Form ==============\n\nconst AldForm = forwardRef((props: any, ref: any) => {\n const contextSize = useContext(SizeContext);\n const {\n children,\n size = contextSize,\n labelWidth,\n style = {},\n className,\n layout = 'horizontal',\n disabled,\n labelCol,\n wrapperCol,\n colon = false,\n requiredMark,\n labelAlign,\n ...restProps\n } = props;\n const customStyle = {\n ...style,\n ...(labelWidth ? { '--label-width': `${labelWidth}px` } : {}),\n ...(labelAlign ? { '--label-align': labelAlign } : {}),\n };\n\n const formContextValue = useMemo(\n () => ({\n layout,\n labelCol,\n wrapperCol,\n colon,\n requiredMark,\n labelWidth,\n labelAlign,\n }),\n [layout, labelCol, wrapperCol, colon, requiredMark, labelWidth, labelAlign],\n );\n\n return (\n <FormContext.Provider value={formContextValue}>\n <DisabledContext.Provider value={disabled}>\n <SizeContextProvider size={size}>\n <RcForm\n style={customStyle}\n className={cn(\n 'ald-form ant-form',\n `ald-form-${layout}`,\n `ant-form-${layout}`,\n className,\n )}\n {...restProps}\n ref={ref}\n >\n {children}\n </RcForm>\n </SizeContextProvider>\n </DisabledContext.Provider>\n </FormContext.Provider>\n );\n}) as <Values = any>(\n props: React.PropsWithChildren<FormProps<Values>> & {\n ref?: React.Ref<FormInstance<Values>>;\n labelWidth?: number;\n },\n) => React.ReactElement;\n\n// ============== Form.Item ==============\n\ninterface IFormItemProps extends FormItemProps {\n labelWidth?: number;\n labelAlign?: 'left' | 'right';\n}\n\n/** Derive status from meta or manual validateStatus */\nfunction deriveStatus(\n meta?: Meta,\n validateStatus?: ValidateStatus,\n): ValidateStatus {\n if (validateStatus) return validateStatus;\n if (!meta) return '';\n if (meta.validating) return 'validating';\n if (meta.errors && meta.errors.length > 0) return 'error';\n if (meta.warnings && meta.warnings.length > 0) return 'warning';\n if (meta.touched) return 'success';\n return '';\n}\n\n/** Status-based border class for the control wrapper */\nfunction statusClassName(status: ValidateStatus): string {\n switch (status) {\n case 'error':\n return 'ald-form-item-has-error';\n case 'warning':\n return 'ald-form-item-has-warning';\n case 'success':\n return 'ald-form-item-has-success';\n case 'validating':\n return 'ald-form-item-is-validating';\n default:\n return '';\n }\n}\n\n/** Render the inner label + control layout, receiving meta from Field */\nfunction FormItemLayout({\n label,\n children,\n meta,\n help,\n extra,\n required,\n rules,\n hidden,\n className,\n customStyle,\n noStyle,\n labelCol: itemLabelCol,\n wrapperCol: itemWrapperCol,\n validateStatus: manualStatus,\n colon: itemColon,\n formContext,\n}: {\n label?: React.ReactNode;\n children: React.ReactNode;\n meta?: Meta;\n help?: React.ReactNode;\n extra?: React.ReactNode;\n required?: boolean;\n rules?: Rule[];\n hidden?: boolean;\n className?: string;\n customStyle?: React.CSSProperties;\n noStyle?: boolean;\n labelCol?: { span?: number; offset?: number };\n wrapperCol?: { span?: number; offset?: number };\n validateStatus?: ValidateStatus;\n colon?: boolean;\n formContext: {\n layout?: string;\n labelCol?: { span?: number; offset?: number };\n wrapperCol?: { span?: number; offset?: number };\n colon?: boolean;\n requiredMark?: boolean | 'optional';\n labelWidth?: number;\n };\n}) {\n const status = deriveStatus(meta, manualStatus);\n const errors = useMemo(() => meta?.errors ?? [], [meta?.errors]);\n const warnings = useMemo(() => meta?.warnings ?? [], [meta?.warnings]);\n\n // Provide status context to child controls\n const itemInputContextValue = useMemo(\n () => ({\n status,\n isFormItemInput: true,\n errors,\n warnings,\n }),\n [status, errors, warnings],\n );\n\n if (noStyle) {\n return <>{children}</>;\n }\n\n // Determine if we should show required mark\n const { requiredMark } = formContext;\n const rulesRequired =\n rules && rules.some((r: any) => typeof r === 'object' && r && r.required);\n const isRequired =\n required || rulesRequired || (meta && (meta as any).required);\n const showRequired = requiredMark !== false && isRequired;\n const showOptional = requiredMark === 'optional' && !isRequired;\n\n // Resolve cols: item-level overrides form-level\n const resolvedLabelCol = itemLabelCol ?? formContext.labelCol;\n const resolvedWrapperCol = itemWrapperCol ?? formContext.wrapperCol;\n const layout = formContext.layout || 'horizontal';\n const showColon =\n (itemColon ?? formContext.colon) !== false && layout === 'horizontal';\n\n // Decide whether to use grid-style layout\n const useGridLayout =\n layout === 'horizontal' && (resolvedLabelCol || resolvedWrapperCol);\n\n // Determine display errors: if help is provided, show help instead of validation errors\n const displayMessages = help !== null && help !== undefined ? [help] : errors;\n const hasError = status === 'error' || (errors.length > 0 && help === null);\n const hasWarning =\n status === 'warning' || (warnings.length > 0 && help === null);\n const hasLabel = label !== null && label !== undefined && label !== '';\n\n const labelNode = hasLabel ? (\n <div\n className={cn(\n 'ald-form-item-label ant-form-item-label',\n // tw-block 不能省:label 容器同时挂了 ant-form-item-label 兼容 class,\n // 消费方残留的 antd 样式会把它设为 inline-block,导致 vertical 布局下\n // label 缩成内容宽而非整行铺在控件上方\n layout === 'vertical' && 'tw-mb-1 tw-block',\n layout === 'horizontal' && 'tw-mr-3 tw-shrink-0',\n )}\n style={useGridLayout ? colStyle(resolvedLabelCol) : undefined}\n >\n <label\n className={cn(\n 'tw-text-sm tw-font-medium tw-text-[var(--alias-colors-text-subtle,var(--content-secondary))]',\n !showColon && 'ant-form-item-no-colon',\n )}\n >\n {showRequired && (\n <span className=\"tw-mr-1 tw-text-[var(--content-negative-primary)]\">\n *\n </span>\n )}\n {label}\n {showOptional && (\n <span className=\"tw-ml-1 tw-text-xs tw-font-normal tw-text-[var(--content-secondary)]\">\n (optional)\n </span>\n )}\n {showColon && label ? ':' : null}\n </label>\n </div>\n ) : null;\n\n const controlNode = (\n <div\n className={cn(\n 'ald-form-item-control ant-form-item-control',\n layout === 'horizontal' && 'tw-flex-1',\n )}\n style={useGridLayout ? colStyle(resolvedWrapperCol) : undefined}\n >\n <FormItemInputContext.Provider value={itemInputContextValue}>\n <div className=\"ald-form-item-control-input\">\n <div className=\"ald-form-item-control-input-content\">{children}</div>\n </div>\n </FormItemInputContext.Provider>\n {/* 始终渲染错误容器,避免 DOM 增删触发 Radix FocusScope MutationObserver 劫持焦点 */}\n <div\n className={cn(\n 'ald-form-item-explain ant-form-item-explain tw-text-xs tw-transition-all tw-duration-200',\n displayMessages.length > 0 && 'tw-mt-1',\n hasError && 'tw-text-[var(--content-negative-secondary)]',\n hasWarning &&\n !hasError &&\n 'tw-text-[color:var(--content-warning-primary,#faad14)]',\n !hasError &&\n !hasWarning &&\n help !== null &&\n help !== undefined &&\n 'tw-text-[var(--content-secondary)]',\n )}\n style={displayMessages.length === 0 ? { display: 'none' } : undefined}\n >\n {displayMessages.map((msg, i) => (\n <div key={i}>{msg}</div>\n ))}\n </div>\n {extra && (\n <div className=\"ald-form-item-extra tw-mt-1 tw-text-xs tw-text-[var(--content-secondary)]\">\n {extra}\n </div>\n )}\n </div>\n );\n\n return (\n <div\n className={cn(\n 'ald-form-item ant-form-item ant-row tw-mb-6',\n hidden && 'tw-hidden',\n showRequired && 'ald-form-item-required',\n statusClassName(status),\n layout === 'horizontal' && 'tw-flex tw-flex-row tw-items-start',\n layout === 'inline' &&\n 'tw-mr-4 tw-inline-flex tw-flex-row tw-items-start',\n className,\n )}\n style={customStyle as React.CSSProperties}\n >\n {labelNode}\n {controlNode}\n </div>\n );\n}\n\nconst AldFormItem = function (props: IFormItemProps) {\n const {\n labelWidth,\n style = {},\n label,\n name,\n rules,\n children,\n className,\n required,\n hidden,\n initialValue,\n dependencies,\n shouldUpdate,\n help,\n extra,\n validateTrigger,\n valuePropName,\n getValueFromEvent,\n normalize,\n getValueProps,\n noStyle,\n labelCol,\n wrapperCol,\n validateStatus,\n colon,\n trigger,\n } = props;\n\n const formContext = useContext(FormContext);\n\n const customStyle = {\n ...style,\n ...(labelWidth ? { '--label-width': `${labelWidth}px` } : {}),\n ...(props.labelAlign ? { '--label-align': props.labelAlign } : {}),\n };\n\n // If no name is provided (e.g. a submit button wrapper), we don't need Field\n // Also when shouldUpdate or dependencies are used without name, Field is still needed for re-render\n const needField =\n (name !== null && name !== undefined) ||\n (shouldUpdate !== null && shouldUpdate !== undefined) ||\n (dependencies !== null && dependencies !== undefined);\n\n if (!needField) {\n return (\n <FormItemLayout\n label={label}\n help={help}\n extra={extra}\n required={required}\n rules={rules}\n hidden={hidden}\n className={className}\n customStyle={customStyle as React.CSSProperties}\n noStyle={noStyle}\n labelCol={labelCol}\n wrapperCol={wrapperCol}\n validateStatus={validateStatus}\n colon={colon}\n formContext={formContext}\n >\n {children as React.ReactNode}\n </FormItemLayout>\n );\n }\n\n return (\n <Field\n name={name}\n rules={rules}\n initialValue={initialValue}\n dependencies={dependencies}\n shouldUpdate={shouldUpdate}\n validateTrigger={validateTrigger}\n trigger={trigger}\n valuePropName={valuePropName}\n getValueFromEvent={getValueFromEvent}\n normalize={normalize}\n getValueProps={getValueProps}\n >\n {(control, meta, form) => {\n // If children is a render function (shouldUpdate / dependencies pattern),\n // call it with the form instance and wrap in layout\n if (typeof children === 'function') {\n const childContent = (\n children as (form: RcFormInstance) => React.ReactNode\n )(form);\n if (noStyle) {\n return childContent;\n }\n return (\n <FormItemLayout\n label={label}\n meta={meta}\n help={help}\n extra={extra}\n required={required}\n rules={rules}\n hidden={hidden}\n className={className}\n customStyle={customStyle as React.CSSProperties}\n noStyle={noStyle}\n labelCol={labelCol}\n wrapperCol={wrapperCol}\n validateStatus={validateStatus}\n colon={colon}\n formContext={formContext}\n >\n {childContent}\n </FormItemLayout>\n );\n }\n\n // For noStyle, just clone with control props\n if (noStyle) {\n if (React.isValidElement(children)) {\n return React.cloneElement(\n children as React.ReactElement<any>,\n mergeControlProps(\n (children as React.ReactElement<any>).props,\n control,\n ),\n );\n }\n return children;\n }\n\n // Clone control props onto the single child element\n let childNode: React.ReactNode = children;\n if (React.isValidElement(children)) {\n childNode = React.cloneElement(\n children as React.ReactElement<any>,\n mergeControlProps(\n (children as React.ReactElement<any>).props,\n control,\n ),\n );\n }\n\n return (\n <FormItemLayout\n label={label}\n meta={meta}\n help={help}\n extra={extra}\n required={required}\n rules={rules}\n hidden={hidden}\n className={className}\n customStyle={customStyle as React.CSSProperties}\n labelCol={labelCol}\n wrapperCol={wrapperCol}\n validateStatus={validateStatus}\n colon={colon}\n formContext={formContext}\n >\n {childNode}\n </FormItemLayout>\n );\n }}\n </Field>\n );\n};\n\nfunction useFormItemStatus() {\n const ctx = useContext(FormItemInputContext);\n return {\n status: ctx.status,\n errors: ctx.errors ?? [],\n warnings: ctx.warnings ?? [],\n };\n}\n\nAldFormItem.useStatus = useFormItemStatus;\n\n// ============== ErrorList ==============\n\nfunction ErrorListComponent(props: ErrorListProps) {\n const { errors, className } = props;\n if (!errors || errors.length === 0) return null;\n return (\n <div className={cn('ald-form-error-list', className)}>\n {errors.map((err, i) => (\n <div\n key={i}\n className=\"tw-text-xs tw-text-[var(--content-negative-secondary)]\"\n >\n {err}\n </div>\n ))}\n </div>\n );\n}\n\n// ============== useFormInstance ==============\n\nfunction useFormInstance<T = any>(): FormInstance<T> {\n const form = useContext(FieldContext);\n return form as unknown as FormInstance<T>;\n}\n\n// ============== Compound component ==============\n\ntype InternalFormType = typeof AldForm;\ntype CompoundedComponent = InternalFormType & {\n useForm: <T = any>(...args: any[]) => [FormInstance<T>];\n useFormInstance: typeof useFormInstance;\n /** Loose-typed useWatch for antd v4 compat */\n useWatch: <T = any>(name: LooseNamePath, form?: FormInstance) => T;\n Item: typeof AldFormItem;\n List: typeof List;\n ErrorList: typeof ErrorListComponent;\n Provider: typeof FormProvider;\n create: () => void;\n};\n\nconst Form = AldForm as CompoundedComponent;\n\nForm.Item = AldFormItem;\nForm.List = List;\nForm.ErrorList = ErrorListComponent;\nForm.useForm = rcUseForm as CompoundedComponent['useForm'];\nForm.useFormInstance = useFormInstance;\nForm.useWatch = useWatch;\nForm.Provider = FormProvider;\nForm.create = () => {\n console.warn('Form.create is deprecated. Please use Form.useForm() instead.');\n};\n\nexport type { Rule, RuleObject, RuleRender };\nexport default Form;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Form/index.tsx"],"sourcesContent":["import RcForm, {\n Field,\n FormInstance as RcFormInstance,\n FormProvider,\n List,\n useForm as rcUseForm,\n useWatch,\n} from 'rc-field-form';\nimport type { FormProps as RcFormProps } from 'rc-field-form';\nimport FieldContext from 'rc-field-form/es/FieldContext';\nimport type { Rule, RuleObject, RuleRender } from 'rc-field-form/es/interface';\nimport type { Meta, NamePath } from 'rc-field-form/es/interface';\nimport React, { forwardRef, useContext, useMemo } from 'react';\nimport SizeContext, {\n SizeContextProvider,\n} from '../ConfigProvider/sizeContext';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport { cn } from '../lib/utils';\nimport {\n FormContext,\n FormItemInputContext,\n type ValidateStatus,\n} from './FormItemContext';\n\n/**\n * Loose NamePath: accepts string, number, or array of them.\n * antd v4 uses loose paths; rc-field-form v2 uses strict DeepNamePath.\n * We override to keep backward compatibility.\n */\ntype LooseNamePath = string | number | (string | number)[];\n\n/**\n * FormInstance — extends rc-field-form FormInstance with loose-typed overloads\n * to maintain antd v4 backward compatibility. Uses intersection so that both\n * strict DeepNamePath and loose LooseNamePath signatures are accepted.\n */\nexport type FormInstance<Values = any> = RcFormInstance<Values> & {\n getFieldValue(name: LooseNamePath): any;\n setFieldValue(name: LooseNamePath, value: any): void;\n setFieldsValue(values: Record<string, any>): void;\n getFieldsValue(): Values;\n getFieldsValue(\n nameList: LooseNamePath[] | true,\n filterFunc?: (meta: Meta) => boolean,\n ): any;\n getFieldError(name: LooseNamePath): string[];\n getFieldsError(\n nameList?: LooseNamePath[],\n ): { name: (string | number)[]; errors: string[] }[];\n getFieldWarning(name: LooseNamePath): string[];\n isFieldTouched(name: LooseNamePath): boolean;\n isFieldsTouched(\n nameList?: LooseNamePath[],\n allFieldsTouched?: boolean,\n ): boolean;\n isFieldValidating(name: LooseNamePath): boolean;\n isFieldsValidating(nameList?: LooseNamePath[]): boolean;\n setFields(fields: FieldData[]): void;\n resetFields(fields?: LooseNamePath[]): void;\n validateFields(nameList?: LooseNamePath[]): Promise<Values>;\n /** Scroll to field position (antd-compatible extension) */\n scrollToField?(\n name: LooseNamePath,\n options?: { behavior?: 'smooth' | 'auto' },\n ): void;\n};\n\n// FormProps compatible with antd\nexport interface FormProps<Values = any> extends Omit<RcFormProps, 'form'> {\n form?: FormInstance<Values>;\n layout?: 'horizontal' | 'vertical' | 'inline';\n size?: 'small' | 'middle' | 'large';\n colon?: boolean;\n disabled?: boolean;\n labelCol?: { span?: number; offset?: number };\n wrapperCol?: { span?: number; offset?: number };\n className?: string;\n style?: React.CSSProperties;\n requiredMark?: boolean | 'optional';\n labelWidth?: number;\n labelAlign?: 'left' | 'right';\n}\n\n// FormItemProps\nexport interface FormItemProps {\n name?: NamePath;\n label?: React.ReactNode;\n rules?: Rule[];\n children?: React.ReactNode | ((form: RcFormInstance) => React.ReactNode);\n className?: string;\n style?: React.CSSProperties;\n required?: boolean;\n hidden?: boolean;\n initialValue?: any;\n dependencies?: NamePath[];\n shouldUpdate?: boolean | ((prevValues: any, curValues: any) => boolean);\n help?: React.ReactNode;\n extra?: React.ReactNode;\n validateTrigger?: string | string[];\n valuePropName?: string;\n getValueFromEvent?: (...args: any[]) => any;\n noStyle?: boolean;\n labelWidth?: number;\n tooltip?:\n | React.ReactNode\n | { title?: React.ReactNode; icon?: React.ReactNode };\n labelCol?: { span?: number; offset?: number; [key: string]: any };\n wrapperCol?: { span?: number; offset?: number; [key: string]: any };\n validateStatus?: ValidateStatus;\n colon?: boolean;\n trigger?: string;\n normalize?: (value: any, prevValue: any, allValues: any) => any;\n getValueProps?: (value: any) => Record<string, any>;\n}\n\n/** antd v4 compat: FormLabelAlign */\nexport type FormLabelAlign = 'left' | 'right';\n\n/** antd v4 compat: FieldData */\nexport type FieldData = {\n name: NamePath;\n value?: any;\n touched?: boolean;\n validating?: boolean;\n errors?: string[];\n};\n\nexport interface ErrorListProps {\n errors?: React.ReactNode[];\n help?: React.ReactNode;\n className?: string;\n}\n\nexport type FormListFieldData = {\n name: number;\n key: number;\n isListField: boolean;\n};\n\nexport type FormListOperation = {\n add: (defaultValue?: any, insertIndex?: number) => void;\n remove: (index: number | number[]) => void;\n move: (from: number, to: number) => void;\n};\n\nexport type FormListProps = {\n name: NamePath;\n rules?: Rule[];\n children: (\n fields: FormListFieldData[],\n operation: FormListOperation,\n meta: { errors: React.ReactNode[] },\n ) => React.ReactNode;\n initialValue?: any[];\n};\n\n// ============== Helpers ==============\n\n/** Convert a 24-column span/offset to Tailwind-compatible inline styles */\nfunction colStyle(col?: {\n span?: number;\n offset?: number;\n}): React.CSSProperties | undefined {\n if (!col) return undefined;\n const s: React.CSSProperties = {};\n if (col.span !== null && col.span !== undefined) {\n // 24-column grid: width = span / 24 * 100%\n s.width = `${(col.span / 24) * 100}%`;\n s.flex = `0 0 ${(col.span / 24) * 100}%`;\n }\n if (col.offset !== null && col.offset !== undefined && col.offset > 0) {\n s.marginLeft = `${(col.offset / 24) * 100}%`;\n }\n return s;\n}\n\nfunction mergeControlProps(\n childProps: Record<string, any>,\n control: Record<string, any>,\n) {\n const mergedControl = { ...control };\n\n Object.keys(control).forEach((key) => {\n const controlHandler = control[key];\n const childHandler = childProps[key];\n\n if (\n typeof controlHandler === 'function' &&\n typeof childHandler === 'function'\n ) {\n mergedControl[key] = (...args: any[]) => {\n controlHandler(...args);\n childHandler(...args);\n };\n }\n });\n\n return mergedControl;\n}\n\n// ============== Form ==============\n\nconst AldForm = forwardRef((props: any, ref: any) => {\n const contextSize = useContext(SizeContext);\n const {\n children,\n size = contextSize,\n labelWidth,\n style = {},\n className,\n layout = 'horizontal',\n disabled,\n labelCol,\n wrapperCol,\n colon = false,\n requiredMark,\n labelAlign,\n ...restProps\n } = props;\n const customStyle = {\n ...style,\n ...(labelWidth ? { '--label-width': `${labelWidth}px` } : {}),\n ...(labelAlign ? { '--label-align': labelAlign } : {}),\n };\n\n const formContextValue = useMemo(\n () => ({\n layout,\n labelCol,\n wrapperCol,\n colon,\n requiredMark,\n labelWidth,\n labelAlign,\n }),\n [layout, labelCol, wrapperCol, colon, requiredMark, labelWidth, labelAlign],\n );\n\n return (\n <FormContext.Provider value={formContextValue}>\n <DisabledContext.Provider value={disabled}>\n <SizeContextProvider size={size}>\n <RcForm\n style={customStyle}\n className={cn(\n 'ald-form ant-form',\n `ald-form-${layout}`,\n `ant-form-${layout}`,\n className,\n )}\n {...restProps}\n ref={ref}\n >\n {children}\n </RcForm>\n </SizeContextProvider>\n </DisabledContext.Provider>\n </FormContext.Provider>\n );\n}) as <Values = any>(\n props: React.PropsWithChildren<FormProps<Values>> & {\n ref?: React.Ref<FormInstance<Values>>;\n labelWidth?: number;\n },\n) => React.ReactElement;\n\n// ============== Form.Item ==============\n\ninterface IFormItemProps extends FormItemProps {\n labelWidth?: number;\n labelAlign?: 'left' | 'right';\n}\n\n/** Derive status from meta or manual validateStatus */\nfunction deriveStatus(\n meta?: Meta,\n validateStatus?: ValidateStatus,\n): ValidateStatus {\n if (validateStatus) return validateStatus;\n if (!meta) return '';\n if (meta.validating) return 'validating';\n if (meta.errors && meta.errors.length > 0) return 'error';\n if (meta.warnings && meta.warnings.length > 0) return 'warning';\n if (meta.touched) return 'success';\n return '';\n}\n\n/** Status-based border class for the control wrapper */\nfunction statusClassName(status: ValidateStatus): string {\n switch (status) {\n case 'error':\n return 'ald-form-item-has-error';\n case 'warning':\n return 'ald-form-item-has-warning';\n case 'success':\n return 'ald-form-item-has-success';\n case 'validating':\n return 'ald-form-item-is-validating';\n default:\n return '';\n }\n}\n\n/** Render the inner label + control layout, receiving meta from Field */\nfunction FormItemLayout({\n label,\n children,\n meta,\n help,\n extra,\n required,\n rules,\n hidden,\n className,\n customStyle,\n noStyle,\n labelCol: itemLabelCol,\n wrapperCol: itemWrapperCol,\n validateStatus: manualStatus,\n colon: itemColon,\n formContext,\n}: {\n label?: React.ReactNode;\n children: React.ReactNode;\n meta?: Meta;\n help?: React.ReactNode;\n extra?: React.ReactNode;\n required?: boolean;\n rules?: Rule[];\n hidden?: boolean;\n className?: string;\n customStyle?: React.CSSProperties;\n noStyle?: boolean;\n labelCol?: { span?: number; offset?: number };\n wrapperCol?: { span?: number; offset?: number };\n validateStatus?: ValidateStatus;\n colon?: boolean;\n formContext: {\n layout?: string;\n labelCol?: { span?: number; offset?: number };\n wrapperCol?: { span?: number; offset?: number };\n colon?: boolean;\n requiredMark?: boolean | 'optional';\n labelWidth?: number;\n };\n}) {\n const status = deriveStatus(meta, manualStatus);\n const errors = useMemo(() => meta?.errors ?? [], [meta?.errors]);\n const warnings = useMemo(() => meta?.warnings ?? [], [meta?.warnings]);\n\n // Provide status context to child controls\n const itemInputContextValue = useMemo(\n () => ({\n status,\n isFormItemInput: true,\n errors,\n warnings,\n }),\n [status, errors, warnings],\n );\n\n if (noStyle) {\n return <>{children}</>;\n }\n\n // Determine if we should show required mark\n const { requiredMark } = formContext;\n const rulesRequired =\n rules && rules.some((r: any) => typeof r === 'object' && r && r.required);\n const isRequired =\n required || rulesRequired || (meta && (meta as any).required);\n const showRequired = requiredMark !== false && isRequired;\n const showOptional = requiredMark === 'optional' && !isRequired;\n\n // Resolve cols: item-level overrides form-level\n const resolvedLabelCol = itemLabelCol ?? formContext.labelCol;\n const resolvedWrapperCol = itemWrapperCol ?? formContext.wrapperCol;\n const layout = formContext.layout || 'horizontal';\n const showColon =\n (itemColon ?? formContext.colon) !== false && layout === 'horizontal';\n\n // Decide whether to use grid-style layout\n const useGridLayout =\n layout === 'horizontal' && (resolvedLabelCol || resolvedWrapperCol);\n\n // Determine display errors: if help is provided, show help instead of validation errors\n const displayMessages = help !== null && help !== undefined ? [help] : errors;\n const hasError = status === 'error' || (errors.length > 0 && help === null);\n const hasWarning =\n status === 'warning' || (warnings.length > 0 && help === null);\n const hasLabel = label !== null && label !== undefined && label !== '';\n\n const labelNode = hasLabel ? (\n <div\n className={cn(\n 'ald-form-item-label ant-form-item-label',\n // tw-block 不能省:label 容器同时挂了 ant-form-item-label 兼容 class,\n // 消费方残留的 antd 样式会把它设为 inline-block,导致 vertical 布局下\n // label 缩成内容宽而非整行铺在控件上方\n layout === 'vertical' && 'tw-mb-1 tw-block',\n layout === 'horizontal' && 'tw-mr-3 tw-shrink-0',\n )}\n style={useGridLayout ? colStyle(resolvedLabelCol) : undefined}\n >\n <label\n className={cn(\n 'tw-text-sm tw-font-medium tw-text-[var(--alias-colors-text-subtle,var(--content-secondary))]',\n !showColon && 'ant-form-item-no-colon',\n )}\n >\n {showRequired && (\n <span className=\"tw-mr-1 tw-text-[var(--content-negative-primary)]\">\n *\n </span>\n )}\n {label}\n {showOptional && (\n <span className=\"tw-ml-1 tw-text-xs tw-font-normal tw-text-[var(--content-secondary)]\">\n (optional)\n </span>\n )}\n {showColon && label ? ':' : null}\n </label>\n </div>\n ) : null;\n\n const controlNode = (\n <div\n className={cn(\n 'ald-form-item-control ant-form-item-control',\n // tw-min-w-0 必须同时加:flex item 默认 min-width:auto = min-content,\n // 子元素 intrinsic min-content(如多选 Select 的 tag 集合)会反向把 control 撑超出父\n // form-item 分配的宽度,再让 rc-overflow 误判\"全部能塞下\"导致不折叠 +N。\n // 实测:指标定义\"更多筛选\"浮窗里 8 个特性 tag 横向溢出浮窗边界即此因\n // (release-2.3_test 复现);这里钳住 min-width 后 Overflow 测量恢复正确。\n layout === 'horizontal' && 'tw-min-w-0 tw-flex-1',\n )}\n style={useGridLayout ? colStyle(resolvedWrapperCol) : undefined}\n >\n <FormItemInputContext.Provider value={itemInputContextValue}>\n <div className=\"ald-form-item-control-input\">\n <div className=\"ald-form-item-control-input-content\">{children}</div>\n </div>\n </FormItemInputContext.Provider>\n {/* 始终渲染错误容器,避免 DOM 增删触发 Radix FocusScope MutationObserver 劫持焦点 */}\n <div\n className={cn(\n 'ald-form-item-explain ant-form-item-explain tw-text-xs tw-transition-all tw-duration-200',\n displayMessages.length > 0 && 'tw-mt-1',\n hasError && 'tw-text-[var(--content-negative-secondary)]',\n hasWarning &&\n !hasError &&\n 'tw-text-[color:var(--content-warning-primary,#faad14)]',\n !hasError &&\n !hasWarning &&\n help !== null &&\n help !== undefined &&\n 'tw-text-[var(--content-secondary)]',\n )}\n style={displayMessages.length === 0 ? { display: 'none' } : undefined}\n >\n {displayMessages.map((msg, i) => (\n <div key={i}>{msg}</div>\n ))}\n </div>\n {extra && (\n <div className=\"ald-form-item-extra tw-mt-1 tw-text-xs tw-text-[var(--content-secondary)]\">\n {extra}\n </div>\n )}\n </div>\n );\n\n return (\n <div\n className={cn(\n 'ald-form-item ant-form-item ant-row tw-mb-6',\n hidden && 'tw-hidden',\n showRequired && 'ald-form-item-required',\n statusClassName(status),\n layout === 'horizontal' && 'tw-flex tw-flex-row tw-items-start',\n layout === 'inline' &&\n 'tw-mr-4 tw-inline-flex tw-flex-row tw-items-start',\n className,\n )}\n style={customStyle as React.CSSProperties}\n >\n {labelNode}\n {controlNode}\n </div>\n );\n}\n\nconst AldFormItem = function (props: IFormItemProps) {\n const {\n labelWidth,\n style = {},\n label,\n name,\n rules,\n children,\n className,\n required,\n hidden,\n initialValue,\n dependencies,\n shouldUpdate,\n help,\n extra,\n validateTrigger,\n valuePropName,\n getValueFromEvent,\n normalize,\n getValueProps,\n noStyle,\n labelCol,\n wrapperCol,\n validateStatus,\n colon,\n trigger,\n } = props;\n\n const formContext = useContext(FormContext);\n\n const customStyle = {\n ...style,\n ...(labelWidth ? { '--label-width': `${labelWidth}px` } : {}),\n ...(props.labelAlign ? { '--label-align': props.labelAlign } : {}),\n };\n\n // If no name is provided (e.g. a submit button wrapper), we don't need Field\n // Also when shouldUpdate or dependencies are used without name, Field is still needed for re-render\n const needField =\n (name !== null && name !== undefined) ||\n (shouldUpdate !== null && shouldUpdate !== undefined) ||\n (dependencies !== null && dependencies !== undefined);\n\n if (!needField) {\n return (\n <FormItemLayout\n label={label}\n help={help}\n extra={extra}\n required={required}\n rules={rules}\n hidden={hidden}\n className={className}\n customStyle={customStyle as React.CSSProperties}\n noStyle={noStyle}\n labelCol={labelCol}\n wrapperCol={wrapperCol}\n validateStatus={validateStatus}\n colon={colon}\n formContext={formContext}\n >\n {children as React.ReactNode}\n </FormItemLayout>\n );\n }\n\n return (\n <Field\n name={name}\n rules={rules}\n initialValue={initialValue}\n dependencies={dependencies}\n shouldUpdate={shouldUpdate}\n validateTrigger={validateTrigger}\n trigger={trigger}\n valuePropName={valuePropName}\n getValueFromEvent={getValueFromEvent}\n normalize={normalize}\n getValueProps={getValueProps}\n >\n {(control, meta, form) => {\n // If children is a render function (shouldUpdate / dependencies pattern),\n // call it with the form instance and wrap in layout\n if (typeof children === 'function') {\n const childContent = (\n children as (form: RcFormInstance) => React.ReactNode\n )(form);\n if (noStyle) {\n return childContent;\n }\n return (\n <FormItemLayout\n label={label}\n meta={meta}\n help={help}\n extra={extra}\n required={required}\n rules={rules}\n hidden={hidden}\n className={className}\n customStyle={customStyle as React.CSSProperties}\n noStyle={noStyle}\n labelCol={labelCol}\n wrapperCol={wrapperCol}\n validateStatus={validateStatus}\n colon={colon}\n formContext={formContext}\n >\n {childContent}\n </FormItemLayout>\n );\n }\n\n // For noStyle, just clone with control props\n if (noStyle) {\n if (React.isValidElement(children)) {\n return React.cloneElement(\n children as React.ReactElement<any>,\n mergeControlProps(\n (children as React.ReactElement<any>).props,\n control,\n ),\n );\n }\n return children;\n }\n\n // Clone control props onto the single child element\n let childNode: React.ReactNode = children;\n if (React.isValidElement(children)) {\n childNode = React.cloneElement(\n children as React.ReactElement<any>,\n mergeControlProps(\n (children as React.ReactElement<any>).props,\n control,\n ),\n );\n }\n\n return (\n <FormItemLayout\n label={label}\n meta={meta}\n help={help}\n extra={extra}\n required={required}\n rules={rules}\n hidden={hidden}\n className={className}\n customStyle={customStyle as React.CSSProperties}\n labelCol={labelCol}\n wrapperCol={wrapperCol}\n validateStatus={validateStatus}\n colon={colon}\n formContext={formContext}\n >\n {childNode}\n </FormItemLayout>\n );\n }}\n </Field>\n );\n};\n\nfunction useFormItemStatus() {\n const ctx = useContext(FormItemInputContext);\n return {\n status: ctx.status,\n errors: ctx.errors ?? [],\n warnings: ctx.warnings ?? [],\n };\n}\n\nAldFormItem.useStatus = useFormItemStatus;\n\n// ============== ErrorList ==============\n\nfunction ErrorListComponent(props: ErrorListProps) {\n const { errors, className } = props;\n if (!errors || errors.length === 0) return null;\n return (\n <div className={cn('ald-form-error-list', className)}>\n {errors.map((err, i) => (\n <div\n key={i}\n className=\"tw-text-xs tw-text-[var(--content-negative-secondary)]\"\n >\n {err}\n </div>\n ))}\n </div>\n );\n}\n\n// ============== useFormInstance ==============\n\nfunction useFormInstance<T = any>(): FormInstance<T> {\n const form = useContext(FieldContext);\n return form as unknown as FormInstance<T>;\n}\n\n// ============== Compound component ==============\n\ntype InternalFormType = typeof AldForm;\ntype CompoundedComponent = InternalFormType & {\n useForm: <T = any>(...args: any[]) => [FormInstance<T>];\n useFormInstance: typeof useFormInstance;\n /** Loose-typed useWatch for antd v4 compat */\n useWatch: <T = any>(name: LooseNamePath, form?: FormInstance) => T;\n Item: typeof AldFormItem;\n List: typeof List;\n ErrorList: typeof ErrorListComponent;\n Provider: typeof FormProvider;\n create: () => void;\n};\n\nconst Form = AldForm as CompoundedComponent;\n\nForm.Item = AldFormItem;\nForm.List = List;\nForm.ErrorList = ErrorListComponent;\nForm.useForm = rcUseForm as CompoundedComponent['useForm'];\nForm.useFormInstance = useFormInstance;\nForm.useWatch = useWatch;\nForm.Provider = FormProvider;\nForm.create = () => {\n console.warn('Form.create is deprecated. Please use Form.useForm() instead.');\n};\n\nexport type { Rule, RuleObject, RuleRender };\nexport default Form;\n"],"mappings":"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"}
@@ -40,7 +40,11 @@ function InputNumber(props) {
40
40
  const handleChange = (e) => {
41
41
  const raw = e.target.value;
42
42
  setInputStr(raw);
43
- if (raw === "" || raw === "-") return;
43
+ if (raw === "") {
44
+ updateValue(null);
45
+ return;
46
+ }
47
+ if (raw === "-") return;
44
48
  const parsed = parser ? parser(raw) : Number(raw);
45
49
  if (!isNaN(parsed)) updateValue(parsed);
46
50
  };
@@ -103,7 +107,7 @@ function InputNumber(props) {
103
107
  });
104
108
  if (!hasAddon) return inputBox;
105
109
  return /* @__PURE__ */ jsxs("div", {
106
- className: cn("ald-input-number-group tw-inline-flex tw-w-full tw-items-stretch", sizeClasses, radiusClasses, mergedDisabled && "ald-input-number-disabled", className),
110
+ className: cn("ald-input-number-group tw-inline-flex tw-min-w-0 tw-items-stretch", sizeClasses, radiusClasses, mergedDisabled && "ald-input-number-disabled", className),
107
111
  style,
108
112
  children: [
109
113
  addonBefore && /* @__PURE__ */ jsx("span", {