@aloudata/aloudata-design 3.0.27 → 3.1.1

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.
Files changed (224) hide show
  1. package/dist/AProgress/index.js +10 -0
  2. package/dist/AProgress/index.js.map +1 -1
  3. package/dist/Alert/index.js +3 -1
  4. package/dist/Alert/index.js.map +1 -1
  5. package/dist/Badge/index.js +37 -11
  6. package/dist/Badge/index.js.map +1 -1
  7. package/dist/Breadcrumb/index.js +12 -2
  8. package/dist/Breadcrumb/index.js.map +1 -1
  9. package/dist/Button/index.d.ts +1 -1
  10. package/dist/Button/index.js +29 -9
  11. package/dist/Button/index.js.map +1 -1
  12. package/dist/Card/index.js +1 -1
  13. package/dist/Card/index.js.map +1 -1
  14. package/dist/Carousel/index.js +9 -1
  15. package/dist/Carousel/index.js.map +1 -1
  16. package/dist/Checkbox/index.js +25 -4
  17. package/dist/Checkbox/index.js.map +1 -1
  18. package/dist/Checkbox/type.d.ts +10 -2
  19. package/dist/Collapse/index.js +68 -22
  20. package/dist/Collapse/index.js.map +1 -1
  21. package/dist/ColorPicker/index.js +112 -46
  22. package/dist/ColorPicker/index.js.map +1 -1
  23. package/dist/DataPreviewTable/components/Body/Cell.d.ts +2 -0
  24. package/dist/DataPreviewTable/components/Body/Cell.js +9 -1
  25. package/dist/DataPreviewTable/components/Body/Cell.js.map +1 -1
  26. package/dist/DataPreviewTable/components/Body/index.d.ts +1 -0
  27. package/dist/DataPreviewTable/components/Body/index.js +35 -23
  28. package/dist/DataPreviewTable/components/Body/index.js.map +1 -1
  29. package/dist/DataPreviewTable/components/Header/index.d.ts +1 -0
  30. package/dist/DataPreviewTable/components/Header/index.js +36 -28
  31. package/dist/DataPreviewTable/components/Header/index.js.map +1 -1
  32. package/dist/DataPreviewTable/index.js +19 -2
  33. package/dist/DataPreviewTable/index.js.map +1 -1
  34. package/dist/Drawer/index.d.ts +4 -0
  35. package/dist/Drawer/index.js +91 -78
  36. package/dist/Drawer/index.js.map +1 -1
  37. package/dist/Dropdown/index.d.ts +1 -1
  38. package/dist/Dropdown/index.js +116 -98
  39. package/dist/Dropdown/index.js.map +1 -1
  40. package/dist/Form/FormItemContext.d.ts +1 -1
  41. package/dist/Form/FormItemContext.js.map +1 -1
  42. package/dist/Form/index.js +50 -7
  43. package/dist/Form/index.js.map +1 -1
  44. package/dist/IconButton/index.d.ts +2 -2
  45. package/dist/IconButton/index.js +9 -3
  46. package/dist/IconButton/index.js.map +1 -1
  47. package/dist/Input/components/Input/index.js +23 -7
  48. package/dist/Input/components/Input/index.js.map +1 -1
  49. package/dist/Input/components/TextArea/index.js +20 -2
  50. package/dist/Input/components/TextArea/index.js.map +1 -1
  51. package/dist/Input/privateSemanticOwner.d.ts +2 -0
  52. package/dist/Input/privateSemanticOwner.js +1 -0
  53. package/dist/InputNumber/index.js +19 -5
  54. package/dist/InputNumber/index.js.map +1 -1
  55. package/dist/InputNumber/type.d.ts +2 -2
  56. package/dist/LogicTree/components/LogicItem/index.d.ts +2 -1
  57. package/dist/LogicTree/components/LogicItem/index.js +13 -2
  58. package/dist/LogicTree/components/LogicItem/index.js.map +1 -1
  59. package/dist/LogicTree/index.js +2 -0
  60. package/dist/LogicTree/index.js.map +1 -1
  61. package/dist/MemberPicker/components/MemberSelection.d.ts +1 -0
  62. package/dist/MemberPicker/components/MemberSelection.js +83 -94
  63. package/dist/MemberPicker/components/MemberSelection.js.map +1 -1
  64. package/dist/MemberPicker/components/MultipleOption.js +12 -0
  65. package/dist/MemberPicker/components/MultipleOption.js.map +1 -1
  66. package/dist/MemberPicker/components/Panel.d.ts +1 -0
  67. package/dist/MemberPicker/components/Panel.js +4 -1
  68. package/dist/MemberPicker/components/Panel.js.map +1 -1
  69. package/dist/MemberPicker/components/SelectedMemberTags.js +14 -6
  70. package/dist/MemberPicker/components/SelectedMemberTags.js.map +1 -1
  71. package/dist/MemberPicker/components/SingleOption.js +12 -0
  72. package/dist/MemberPicker/components/SingleOption.js.map +1 -1
  73. package/dist/MemberPicker/components/UserGroupSelection.d.ts +2 -1
  74. package/dist/MemberPicker/components/UserGroupSelection.js +61 -48
  75. package/dist/MemberPicker/components/UserGroupSelection.js.map +1 -1
  76. package/dist/MemberPicker/index.js +134 -108
  77. package/dist/MemberPicker/index.js.map +1 -1
  78. package/dist/Menu/index.d.ts +8 -0
  79. package/dist/Menu/index.js +33 -3
  80. package/dist/Menu/index.js.map +1 -1
  81. package/dist/Modal/index.d.ts +4 -0
  82. package/dist/Modal/index.js +55 -66
  83. package/dist/Modal/index.js.map +1 -1
  84. package/dist/OverflowCount/index.js +10 -0
  85. package/dist/OverflowCount/index.js.map +1 -1
  86. package/dist/Pagination/PageSizeChanger.d.ts +1 -0
  87. package/dist/Pagination/PageSizeChanger.js +3 -2
  88. package/dist/Pagination/PageSizeChanger.js.map +1 -1
  89. package/dist/Pagination/index.js +34 -19
  90. package/dist/Pagination/index.js.map +1 -1
  91. package/dist/Pagination/types.d.ts +3 -0
  92. package/dist/Popconfirm/index.js +9 -1
  93. package/dist/Popconfirm/index.js.map +1 -1
  94. package/dist/Popover/index.js +52 -1
  95. package/dist/Popover/index.js.map +1 -1
  96. package/dist/Progress/index.js +4 -0
  97. package/dist/Progress/index.js.map +1 -1
  98. package/dist/Radio/components/Group/index.d.ts +5 -1
  99. package/dist/Radio/components/Group/index.js +7 -2
  100. package/dist/Radio/components/Group/index.js.map +1 -1
  101. package/dist/Radio/components/Radio/index.js +27 -1
  102. package/dist/Radio/components/Radio/index.js.map +1 -1
  103. package/dist/Radio/interface/radio.d.ts +7 -0
  104. package/dist/Radio/interface/radioGroup.d.ts +2 -0
  105. package/dist/RenameInput/index.js +11 -0
  106. package/dist/RenameInput/index.js.map +1 -1
  107. package/dist/Select/BaseSelect.d.ts +3 -0
  108. package/dist/Select/BaseSelect.js +235 -38
  109. package/dist/Select/BaseSelect.js.map +1 -1
  110. package/dist/Select/SelectTrigger.d.ts +2 -0
  111. package/dist/Select/SelectTrigger.js +13 -5
  112. package/dist/Select/SelectTrigger.js.map +1 -1
  113. package/dist/Select/Selector/FixedOverflow.d.ts +1 -0
  114. package/dist/Select/Selector/FixedOverflow.js +3 -3
  115. package/dist/Select/Selector/FixedOverflow.js.map +1 -1
  116. package/dist/Select/Selector/MultipleSelector.js +1 -0
  117. package/dist/Select/Selector/MultipleSelector.js.map +1 -1
  118. package/dist/Select/components/OptionCollection.d.ts +41 -0
  119. package/dist/Select/components/OptionCollection.js +124 -0
  120. package/dist/Select/components/OptionCollection.js.map +1 -0
  121. package/dist/Select/index.js +45 -3
  122. package/dist/Select/index.js.map +1 -1
  123. package/dist/Select/interface.d.ts +1 -1
  124. package/dist/Skeleton/index.js +1 -1
  125. package/dist/Skeleton/index.js.map +1 -1
  126. package/dist/Spin/index.d.ts +1 -1
  127. package/dist/Spin/index.js +22 -7
  128. package/dist/Spin/index.js.map +1 -1
  129. package/dist/Steps/index.js +66 -14
  130. package/dist/Steps/index.js.map +1 -1
  131. package/dist/Switch/index.d.ts +5 -0
  132. package/dist/Switch/index.js +22 -5
  133. package/dist/Switch/index.js.map +1 -1
  134. package/dist/Table/components/Cell.js +8 -3
  135. package/dist/Table/components/Cell.js.map +1 -1
  136. package/dist/Table/components/ExpandCell.js +6 -2
  137. package/dist/Table/components/ExpandCell.js.map +1 -1
  138. package/dist/Table/components/Footer/index.js +2 -1
  139. package/dist/Table/components/Footer/index.js.map +1 -1
  140. package/dist/Table/components/Header.js +25 -18
  141. package/dist/Table/components/Header.js.map +1 -1
  142. package/dist/Table/hooks/useRowSelection.js +14 -7
  143. package/dist/Table/hooks/useRowSelection.js.map +1 -1
  144. package/dist/Table/index.js +50 -29
  145. package/dist/Table/index.js.map +1 -1
  146. package/dist/Tabs/index.d.ts +1 -1
  147. package/dist/Tabs/index.js +92 -11
  148. package/dist/Tabs/index.js.map +1 -1
  149. package/dist/Tag/index.js +20 -1
  150. package/dist/Tag/index.js.map +1 -1
  151. package/dist/Tooltip/index.js +34 -5
  152. package/dist/Tooltip/index.js.map +1 -1
  153. package/dist/Tour/index.js +13 -1
  154. package/dist/Tour/index.js.map +1 -1
  155. package/dist/Tree/Tree2.js +2 -0
  156. package/dist/Tree/Tree2.js.map +1 -1
  157. package/dist/_utils/dialogAccessibility.d.ts +17 -0
  158. package/dist/_utils/dialogAccessibility.js +110 -0
  159. package/dist/_utils/dialogAccessibility.js.map +1 -0
  160. package/dist/_utils/formControlSemanticOwner.d.ts +3 -0
  161. package/dist/_utils/formControlSemanticOwner.js +17 -0
  162. package/dist/_utils/formControlSemanticOwner.js.map +1 -0
  163. package/dist/_utils/overlayCoordinator.js +1 -11
  164. package/dist/_utils/overlayCoordinator.js.map +1 -1
  165. package/dist/aloudata-design.css +1 -1
  166. package/dist/locale/default.d.ts +6 -0
  167. package/dist/locale/en_US.d.ts +6 -0
  168. package/dist/locale/en_US.js +6 -0
  169. package/dist/locale/en_US.js.map +1 -1
  170. package/dist/locale/zh_CN.d.ts +6 -0
  171. package/dist/locale/zh_CN.js +6 -0
  172. package/dist/locale/zh_CN.js.map +1 -1
  173. package/dist/theme/contract/baselineResolvedTokenValueManifest.d.ts +1 -1
  174. package/dist/theme/contract/controlStateColorArtifact.d.ts +73 -0
  175. package/dist/theme/contract/controlStateColorArtifact.js +2 -0
  176. package/dist/theme/contract/darkResolvedTokenValueManifest.d.ts +1 -1
  177. package/dist/theme/contract/focusRingArtifact.d.ts +51 -0
  178. package/dist/theme/contract/focusRingArtifact.js +2 -0
  179. package/dist/theme/contract/tokenOutputContract.d.ts +1 -1
  180. package/dist/theme/contract/tokenOutputContract.js +4 -0
  181. package/dist/theme/contract/tokenOutputContract.js.map +1 -1
  182. package/dist/theme/generator/acceptedColorValues.d.ts +2 -1
  183. package/dist/theme/generator/baselineTokenValueDelivery.d.ts +9 -1
  184. package/dist/theme/generator/minimalAcceptedColorValues.d.ts +2 -2
  185. package/dist/theme/generator/neutralSourceResolver.d.ts +28 -0
  186. package/dist/theme/generator/neutralSourceResolver.js +2 -0
  187. package/dist/theme/generator/neutralSourceValues.d.ts +27 -0
  188. package/dist/theme/generator/neutralSourceValues.js +2 -0
  189. package/dist/theme/index.d.ts +2 -0
  190. package/dist/theme/index.js +1 -0
  191. package/dist/theme/neutralSourceContract.d.ts +3 -0
  192. package/dist/theme/neutralSourceContract.js +11 -0
  193. package/dist/theme/neutralSourceContract.js.map +1 -0
  194. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.d.ts +1 -1
  195. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js +47 -44
  196. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js.map +1 -1
  197. package/dist/theme/runtime/colorValueMode/generated/slateDarkDeclarations.d.ts +3 -0
  198. package/dist/theme/runtime/colorValueMode/generated/slateDarkDeclarations.js +2 -0
  199. package/dist/theme/runtime/colorValueMode/generated/slateLightDeclarations.d.ts +3 -0
  200. package/dist/theme/runtime/colorValueMode/generated/slateLightDeclarations.js +2 -0
  201. package/dist/theme/runtime/colorValueMode/generated/stoneDarkDeclarations.d.ts +3 -0
  202. package/dist/theme/runtime/colorValueMode/generated/stoneDarkDeclarations.js +2 -0
  203. package/dist/theme/runtime/colorValueMode/generated/stoneLightDeclarations.d.ts +3 -0
  204. package/dist/theme/runtime/colorValueMode/generated/stoneLightDeclarations.js +2 -0
  205. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.d.ts +1 -1
  206. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js +43 -40
  207. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js.map +1 -1
  208. package/dist/theme/runtime/colorValueMode/index.js +2 -12
  209. package/dist/theme/runtime/colorValueMode/index.js.map +1 -1
  210. package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.d.ts +2 -0
  211. package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.js +48 -0
  212. package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.js.map +1 -0
  213. package/dist/theme/runtime/colorValueMode/registry.d.ts +1 -1
  214. package/dist/theme/runtime/colorValueMode/registry.js +2 -1
  215. package/dist/theme/runtime/colorValueMode/registry.js.map +1 -1
  216. package/dist/theme/runtime/initAldTheme.js +1 -3
  217. package/dist/theme/runtime/initAldTheme.js.map +1 -1
  218. package/dist/theme/runtime/neutralSource/index.d.ts +6 -0
  219. package/dist/theme/runtime/neutralSource/index.js +11 -0
  220. package/dist/theme/runtime/neutralSource/index.js.map +1 -0
  221. package/dist/theme/runtime/neutralSource.d.ts +2 -0
  222. package/dist/theme/runtime/themeToCssVars.js +3 -0
  223. package/dist/theme/runtime/themeToCssVars.js.map +1 -1
  224. package/package.json +1 -1
@@ -1,11 +1,12 @@
1
1
  import { cn } from "../lib/utils.js";
2
2
  import DisabledContext from "../ConfigProvider/DisabledContext.js";
3
+ import { getSemanticOwnerAriaProps } from "../_utils/formControlSemanticOwner.js";
3
4
  import { createContext, useContext, useEffect, useRef, useState } from "react";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
5
6
  //#region src/Checkbox/index.tsx
6
7
  var CheckboxGroupContext = createContext(null);
7
8
  function Checkbox(props) {
8
- const { className, disabled: customDisabled, alert, bold, size, checked: controlledChecked, defaultChecked, indeterminate, onChange, onClick, autoFocus, children, value, name, style, "data-testid": dataTestid, "aria-label": ariaLabel } = props;
9
+ const { className, disabled: customDisabled, alert, bold, size, checked: controlledChecked, defaultChecked, indeterminate, onChange, onClick, autoFocus, children, value, name, required, style, "data-testid": dataTestid, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, "aria-required": ariaRequired, "aria-disabled": ariaDisabled } = props;
9
10
  const disabled = useContext(DisabledContext);
10
11
  const group = useContext(CheckboxGroupContext);
11
12
  const isGroupCheckbox = group !== null && value !== void 0;
@@ -45,13 +46,29 @@ function Checkbox(props) {
45
46
  className: cn("ald-checkbox-wrapper ald-checkbox tw-inline-flex tw-cursor-pointer tw-items-center tw-gap-2 tw-leading-5", mergedDisabled && "tw-cursor-default", size === "small" && "ald-checkbox-small", !mergedDisabled && "[&:hover_.ald-checkbox-inner]:tw-border-2 [&:hover_.ald-checkbox-inner]:tw-border-[var(--border-brand-strong)]", !mergedDisabled && checked && "[&:hover_.ald-checkbox-inner]:tw-border-[var(--action-ghost-normal)] [&:hover_.ald-checkbox-inner]:tw-bg-[var(--action-primary-hover)]", className),
46
47
  style,
47
48
  children: [/* @__PURE__ */ jsxs("span", {
48
- className: cn("ald-checkbox-inner tw-relative tw-box-border tw-flex tw-size-4 tw-min-h-4 tw-min-w-4 tw-items-center tw-justify-center tw-rounded-r-50 tw-border-2 tw-border-solid tw-transition-all tw-duration-200", checked && "ald-checkbox-checked", checked && !mergedDisabled && "tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]", checked && mergedDisabled && "tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]", !checked && !indeterminate && mergedDisabled && "tw-border-[var(--content-disabled)] tw-bg-[var(--background-neutral-on-subtle)]", !checked && !indeterminate && !mergedDisabled && !alert && "tw-border-[var(--border-neutral-subtle)] tw-bg-[var(--background-default)]", !checked && !indeterminate && !mergedDisabled && alert && "tw-border-[var(--border-negative-strong)] tw-bg-[var(--background-default)]", indeterminate && !checked && "ald-checkbox-indeterminate", indeterminate && !checked && !mergedDisabled && "tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]", indeterminate && !checked && mergedDisabled && "tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]"),
49
+ className: cn("ald-checkbox-inner tw-relative tw-box-border tw-flex tw-size-4 tw-min-h-4 tw-min-w-4 tw-items-center tw-justify-center tw-rounded-r-50 tw-border-2 tw-border-solid tw-transition-colors tw-duration-200", !mergedDisabled && [
50
+ "has-[input:focus-visible]:tw-shadow-[0_0_0_2px_var(--focus-ring)]",
51
+ "forced-colors:has-[input:focus-visible]:tw-outline",
52
+ "forced-colors:has-[input:focus-visible]:tw-outline-2",
53
+ "forced-colors:has-[input:focus-visible]:tw-outline-offset-2",
54
+ "forced-colors:has-[input:focus-visible]:tw-outline-[Highlight]"
55
+ ], checked && "ald-checkbox-checked", checked && !mergedDisabled && "tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]", checked && mergedDisabled && "tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]", !checked && !indeterminate && mergedDisabled && "tw-border-[var(--content-disabled)] tw-bg-[var(--background-neutral-on-subtle)]", !checked && !indeterminate && !mergedDisabled && !alert && "tw-border-[var(--border-neutral-subtle)] tw-bg-[var(--background-default)]", !checked && !indeterminate && !mergedDisabled && alert && "tw-border-[var(--border-negative-strong)] tw-bg-[var(--background-default)]", indeterminate && !checked && "ald-checkbox-indeterminate", indeterminate && !checked && !mergedDisabled && "tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]", indeterminate && !checked && mergedDisabled && "tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]"),
49
56
  children: [/* @__PURE__ */ jsx("input", {
50
57
  ref: inputRef,
51
58
  type: "checkbox",
52
59
  className: "tw-absolute tw-inset-0 tw-m-0 tw-cursor-pointer tw-opacity-0 disabled:tw-cursor-default",
53
60
  checked: !!checked,
54
61
  disabled: mergedDisabled,
62
+ required,
63
+ "aria-checked": indeterminate ? "mixed" : void 0,
64
+ ...getSemanticOwnerAriaProps({
65
+ "aria-label": ariaLabel,
66
+ "aria-labelledby": ariaLabelledBy,
67
+ "aria-describedby": ariaDescribedBy,
68
+ "aria-invalid": ariaInvalid,
69
+ "aria-required": ariaRequired,
70
+ "aria-disabled": ariaDisabled
71
+ }),
55
72
  onChange: handleChange,
56
73
  autoFocus,
57
74
  name: group?.name ?? name,
@@ -64,13 +81,13 @@ function Checkbox(props) {
64
81
  }
65
82
  })]
66
83
  }), children && /* @__PURE__ */ jsx("span", {
67
- className: cn("ald-checkbox-label tw-inline-flex tw-select-none tw-items-center tw-gap-1 tw-text-[var(--content-primary)] [&_svg]:tw-inline-block [&_svg]:tw-shrink-0", size === "small" ? "tw-text-xs" : "tw-text-sm", bold && "tw-font-medium", mergedDisabled && "tw-cursor-default tw-text-[var(--content-disabled)]"),
84
+ className: cn("ald-checkbox-label tw-inline-flex tw-select-none tw-items-center tw-gap-1 tw-text-[var(--content-primary)] [&_svg]:tw-inline-block [&_svg]:tw-shrink-0", "tw-text-typography-label", bold && "tw-font-medium", mergedDisabled && "tw-cursor-default tw-text-[var(--content-disabled)]"),
68
85
  children
69
86
  })]
70
87
  });
71
88
  }
72
89
  function CheckboxGroup(props) {
73
- const { className, disabled: customDisabled, size, options, value: controlledValue, defaultValue, onChange, direction, name, children, style } = props;
90
+ const { className, disabled: customDisabled, size, options, value: controlledValue, defaultValue, onChange, direction, name, children, style, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy } = props;
74
91
  const disabled = useContext(DisabledContext);
75
92
  const mergedDisabled = customDisabled ?? disabled;
76
93
  const isControlled = "value" in props;
@@ -100,6 +117,10 @@ function CheckboxGroup(props) {
100
117
  return /* @__PURE__ */ jsx("div", {
101
118
  className: cn("ald-checkbox-group tw-flex tw-flex-wrap tw-gap-3", direction === "vertical" && "ald-checkbox-group-vertical tw-flex-col", size === "small" && "ald-checkbox-group-small", className),
102
119
  style,
120
+ role: "group",
121
+ "aria-label": ariaLabel,
122
+ "aria-labelledby": ariaLabelledBy,
123
+ "aria-describedby": ariaDescribedBy,
103
124
  children: /* @__PURE__ */ jsx(CheckboxGroupContext.Provider, {
104
125
  value: {
105
126
  value,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Checkbox/index.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport { cn } from '../lib/utils';\nimport {\n CheckboxChangeEvent,\n CheckboxValueType,\n ICheckboxGroupProps,\n ICheckboxProps,\n} from './type';\n\nexport type { CheckboxChangeEvent, CheckboxValueType };\nexport type { CheckboxOptionType } from './type';\nexport type { ICheckboxProps, ICheckboxGroupProps };\n\ninterface CheckboxGroupContextValue {\n value: CheckboxValueType[];\n disabled?: boolean;\n name?: string;\n toggleOption: (value: CheckboxValueType, checked: boolean) => void;\n}\n\nconst CheckboxGroupContext = createContext<CheckboxGroupContextValue | null>(\n null,\n);\n\nfunction Checkbox(props: ICheckboxProps) {\n const {\n className,\n disabled: customDisabled,\n alert,\n bold,\n size,\n checked: controlledChecked,\n defaultChecked,\n indeterminate,\n onChange,\n onClick,\n autoFocus,\n children,\n value,\n name,\n style,\n 'data-testid': dataTestid,\n 'aria-label': ariaLabel,\n } = props;\n\n const disabled = useContext(DisabledContext);\n const group = useContext(CheckboxGroupContext);\n const isGroupCheckbox = group !== null && value !== undefined;\n const mergedDisabled = group?.disabled || customDisabled || disabled;\n\n const isControlled = isGroupCheckbox || 'checked' in props;\n const [innerChecked, setInnerChecked] = useState(defaultChecked ?? false);\n const checked = isGroupCheckbox\n ? group.value.includes(value)\n : isControlled\n ? controlledChecked\n : innerChecked;\n\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.indeterminate = !!indeterminate;\n }\n }, [indeterminate]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (mergedDisabled) return;\n const newChecked = e.target.checked;\n if (isGroupCheckbox) {\n group.toggleOption(value, newChecked);\n } else if (!isControlled) {\n setInnerChecked(newChecked);\n }\n onChange?.({\n target: { checked: newChecked, value },\n nativeEvent: e.nativeEvent,\n });\n };\n\n const handleLabelClick = (e: React.MouseEvent) => {\n if (mergedDisabled) return;\n if (onClick) {\n // Table row selection uses onClick — prevent label from also toggling input\n e.preventDefault();\n e.stopPropagation();\n onClick(e);\n }\n };\n\n return (\n <label\n onClick={handleLabelClick}\n data-testid={dataTestid}\n aria-label={ariaLabel}\n className={cn(\n 'ald-checkbox-wrapper ald-checkbox tw-inline-flex tw-cursor-pointer tw-items-center tw-gap-2 tw-leading-5',\n mergedDisabled && 'tw-cursor-default',\n size === 'small' && 'ald-checkbox-small',\n !mergedDisabled &&\n '[&:hover_.ald-checkbox-inner]:tw-border-2 [&:hover_.ald-checkbox-inner]:tw-border-[var(--border-brand-strong)]',\n !mergedDisabled &&\n checked &&\n '[&:hover_.ald-checkbox-inner]:tw-border-[var(--action-ghost-normal)] [&:hover_.ald-checkbox-inner]:tw-bg-[var(--action-primary-hover)]',\n className,\n )}\n style={style}\n >\n <span\n className={cn(\n 'ald-checkbox-inner tw-relative tw-box-border tw-flex tw-size-4 tw-min-h-4 tw-min-w-4 tw-items-center tw-justify-center tw-rounded-r-50 tw-border-2 tw-border-solid tw-transition-all tw-duration-200',\n checked && 'ald-checkbox-checked',\n checked &&\n !mergedDisabled &&\n 'tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]',\n checked &&\n mergedDisabled &&\n 'tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]',\n !checked &&\n !indeterminate &&\n mergedDisabled &&\n 'tw-border-[var(--content-disabled)] tw-bg-[var(--background-neutral-on-subtle)]',\n !checked &&\n !indeterminate &&\n !mergedDisabled &&\n !alert &&\n 'tw-border-[var(--border-neutral-subtle)] tw-bg-[var(--background-default)]',\n !checked &&\n !indeterminate &&\n !mergedDisabled &&\n alert &&\n 'tw-border-[var(--border-negative-strong)] tw-bg-[var(--background-default)]',\n indeterminate && !checked && 'ald-checkbox-indeterminate',\n indeterminate &&\n !checked &&\n !mergedDisabled &&\n 'tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]',\n indeterminate &&\n !checked &&\n mergedDisabled &&\n 'tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]',\n )}\n >\n <input\n ref={inputRef}\n type=\"checkbox\"\n className=\"tw-absolute tw-inset-0 tw-m-0 tw-cursor-pointer tw-opacity-0 disabled:tw-cursor-default\"\n checked={!!checked}\n disabled={mergedDisabled}\n onChange={handleChange}\n autoFocus={autoFocus}\n name={group?.name ?? name}\n value={value as string}\n />\n {(checked || (indeterminate && !checked)) && (\n <span\n className=\"tw-absolute tw-inset-0 tw-bg-center tw-bg-no-repeat\"\n style={{\n backgroundImage:\n indeterminate && !checked\n ? 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMiIgdmlld0JveD0iMCAwIDEwIDIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGlkPSJWZWN0b3IgMSAoU3Ryb2tlKSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wLjc1IDFDMC43NSAwLjU4NTc4NiAxLjA4NTc5IDAuMjUgMS41IDAuMjVIOC41QzguOTE0MjEgMC4yNSA5LjI1IDAuNTg1Nzg2IDkuMjUgMUM5LjI1IDEuNDE0MjEgOC45MTQyMSAxLjc1IDguNSAxLjc1SDEuNUMxLjA4NTc5IDEuNzUgMC43NSAxLjQxNDIxIDAuNzUgMVoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=\")'\n : 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iOCIgdmlld0JveD0iMCAwIDEwIDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGlkPSJJY29uIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTkuNTMwMzMgMC45Njk2N0M5LjgyMzIyIDEuMjYyNTYgOS44MjMyMiAxLjczNzQ0IDkuNTMwMzMgMi4wMzAzM0w0LjUzMDMzIDcuMDMwMzNDNC4yMzc0NCA3LjMyMzIyIDMuNzYyNTYgNy4zMjMyMiAzLjQ2OTY3IDcuMDMwMzNMMC45Njk2NyA0LjUzMDMzQzAuNjc2Nzc3IDQuMjM3NDQgMC42NzY3NzcgMy43NjI1NiAwLjk2OTY3IDMuNDY5NjdDMS4yNjI1NiAzLjE3Njc4IDEuNzM3NDQgMy4xNzY3OCAyLjAzMDMzIDMuNDY5NjdMNCA1LjQzOTM0TDguNDY5NjcgMC45Njk2N0M4Ljc2MjU2IDAuNjc2Nzc3IDkuMjM3NDQgMC42NzY3NzcgOS41MzAzMyAwLjk2OTY3WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg==\")',\n backgroundSize:\n indeterminate && !checked ? '10px 2px' : '10px 8px',\n }}\n />\n )}\n </span>\n {children && (\n <span\n className={cn(\n 'ald-checkbox-label tw-inline-flex tw-select-none tw-items-center tw-gap-1 tw-text-[var(--content-primary)] [&_svg]:tw-inline-block [&_svg]:tw-shrink-0',\n size === 'small' ? 'tw-text-xs' : 'tw-text-sm',\n bold && 'tw-font-medium',\n mergedDisabled &&\n 'tw-cursor-default tw-text-[var(--content-disabled)]',\n )}\n >\n {children}\n </span>\n )}\n </label>\n );\n}\n\nfunction CheckboxGroup(props: ICheckboxGroupProps) {\n const {\n className,\n disabled: customDisabled,\n size,\n options,\n value: controlledValue,\n defaultValue,\n onChange,\n direction,\n name,\n children,\n style,\n } = props;\n\n const disabled = useContext(DisabledContext);\n const mergedDisabled = customDisabled ?? disabled;\n\n const isControlled = 'value' in props;\n const [innerValue, setInnerValue] = useState<CheckboxValueType[]>(\n defaultValue ?? [],\n );\n const value = isControlled ? controlledValue ?? [] : innerValue;\n\n const handleGroupChange = (\n itemValue: CheckboxValueType,\n itemChecked: boolean,\n ) => {\n const newValue = itemChecked\n ? [...value, itemValue]\n : value.filter((v) => v !== itemValue);\n if (!isControlled) {\n setInnerValue(newValue);\n }\n onChange?.(newValue);\n };\n\n const renderOptions = () => {\n if (!options) return children;\n return options.map((opt) => {\n const optObj =\n typeof opt === 'object' ? opt : { label: String(opt), value: opt };\n return (\n <Checkbox\n key={String(optObj.value)}\n value={optObj.value}\n disabled={optObj.disabled}\n size={size}\n onChange={optObj.onChange}\n >\n {optObj.label}\n </Checkbox>\n );\n });\n };\n\n return (\n <div\n className={cn(\n 'ald-checkbox-group tw-flex tw-flex-wrap tw-gap-3',\n direction === 'vertical' && 'ald-checkbox-group-vertical tw-flex-col',\n size === 'small' && 'ald-checkbox-group-small',\n className,\n )}\n style={style}\n >\n <CheckboxGroupContext.Provider\n value={{\n value,\n disabled: mergedDisabled,\n name,\n toggleOption: handleGroupChange,\n }}\n >\n {renderOptions()}\n </CheckboxGroupContext.Provider>\n </div>\n );\n}\n\nCheckbox.Group = CheckboxGroup;\n\nexport default Checkbox;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Checkbox/index.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport { getSemanticOwnerAriaProps } from '../_utils/formControlSemanticOwner';\nimport { cn } from '../lib/utils';\nimport {\n CheckboxChangeEvent,\n CheckboxValueType,\n ICheckboxGroupProps,\n ICheckboxProps,\n} from './type';\n\nexport type { CheckboxChangeEvent, CheckboxValueType };\nexport type { CheckboxOptionType } from './type';\nexport type { ICheckboxProps, ICheckboxGroupProps };\n\ninterface CheckboxGroupContextValue {\n value: CheckboxValueType[];\n disabled?: boolean;\n name?: string;\n toggleOption: (value: CheckboxValueType, checked: boolean) => void;\n}\n\nconst CheckboxGroupContext = createContext<CheckboxGroupContextValue | null>(\n null,\n);\n\nfunction Checkbox(props: ICheckboxProps) {\n const {\n className,\n disabled: customDisabled,\n alert,\n bold,\n size,\n checked: controlledChecked,\n defaultChecked,\n indeterminate,\n onChange,\n onClick,\n autoFocus,\n children,\n value,\n name,\n required,\n style,\n 'data-testid': dataTestid,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-disabled': ariaDisabled,\n } = props;\n\n const disabled = useContext(DisabledContext);\n const group = useContext(CheckboxGroupContext);\n const isGroupCheckbox = group !== null && value !== undefined;\n const mergedDisabled = group?.disabled || customDisabled || disabled;\n\n const isControlled = isGroupCheckbox || 'checked' in props;\n const [innerChecked, setInnerChecked] = useState(defaultChecked ?? false);\n const checked = isGroupCheckbox\n ? group.value.includes(value)\n : isControlled\n ? controlledChecked\n : innerChecked;\n\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.indeterminate = !!indeterminate;\n }\n }, [indeterminate]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (mergedDisabled) return;\n const newChecked = e.target.checked;\n if (isGroupCheckbox) {\n group.toggleOption(value, newChecked);\n } else if (!isControlled) {\n setInnerChecked(newChecked);\n }\n onChange?.({\n target: { checked: newChecked, value },\n nativeEvent: e.nativeEvent,\n });\n };\n\n const handleLabelClick = (e: React.MouseEvent) => {\n if (mergedDisabled) return;\n if (onClick) {\n // Table row selection uses onClick — prevent label from also toggling input\n e.preventDefault();\n e.stopPropagation();\n onClick(e);\n }\n };\n\n return (\n <label\n onClick={handleLabelClick}\n data-testid={dataTestid}\n aria-label={ariaLabel}\n className={cn(\n 'ald-checkbox-wrapper ald-checkbox tw-inline-flex tw-cursor-pointer tw-items-center tw-gap-2 tw-leading-5',\n mergedDisabled && 'tw-cursor-default',\n size === 'small' && 'ald-checkbox-small',\n !mergedDisabled &&\n '[&:hover_.ald-checkbox-inner]:tw-border-2 [&:hover_.ald-checkbox-inner]:tw-border-[var(--border-brand-strong)]',\n !mergedDisabled &&\n checked &&\n '[&:hover_.ald-checkbox-inner]:tw-border-[var(--action-ghost-normal)] [&:hover_.ald-checkbox-inner]:tw-bg-[var(--action-primary-hover)]',\n className,\n )}\n style={style}\n >\n <span\n className={cn(\n 'ald-checkbox-inner tw-relative tw-box-border tw-flex tw-size-4 tw-min-h-4 tw-min-w-4 tw-items-center tw-justify-center tw-rounded-r-50 tw-border-2 tw-border-solid tw-transition-colors tw-duration-200',\n // The native input owns focus and its visual control owns the\n // Focus State Layer. Checked, indeterminate, and alert styling\n // remain independent control states.\n !mergedDisabled && [\n 'has-[input:focus-visible]:tw-shadow-[0_0_0_2px_var(--focus-ring)]',\n 'forced-colors:has-[input:focus-visible]:tw-outline',\n 'forced-colors:has-[input:focus-visible]:tw-outline-2',\n 'forced-colors:has-[input:focus-visible]:tw-outline-offset-2',\n 'forced-colors:has-[input:focus-visible]:tw-outline-[Highlight]',\n ],\n checked && 'ald-checkbox-checked',\n checked &&\n !mergedDisabled &&\n 'tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]',\n checked &&\n mergedDisabled &&\n 'tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]',\n !checked &&\n !indeterminate &&\n mergedDisabled &&\n 'tw-border-[var(--content-disabled)] tw-bg-[var(--background-neutral-on-subtle)]',\n !checked &&\n !indeterminate &&\n !mergedDisabled &&\n !alert &&\n 'tw-border-[var(--border-neutral-subtle)] tw-bg-[var(--background-default)]',\n !checked &&\n !indeterminate &&\n !mergedDisabled &&\n alert &&\n 'tw-border-[var(--border-negative-strong)] tw-bg-[var(--background-default)]',\n indeterminate && !checked && 'ald-checkbox-indeterminate',\n indeterminate &&\n !checked &&\n !mergedDisabled &&\n 'tw-border-[var(--action-ghost-normal)] tw-bg-[var(--action-primary-normal)]',\n indeterminate &&\n !checked &&\n mergedDisabled &&\n 'tw-border-[var(--content-disabled)] tw-bg-[var(--content-disabled)]',\n )}\n >\n <input\n ref={inputRef}\n type=\"checkbox\"\n className=\"tw-absolute tw-inset-0 tw-m-0 tw-cursor-pointer tw-opacity-0 disabled:tw-cursor-default\"\n checked={!!checked}\n disabled={mergedDisabled}\n required={required}\n aria-checked={indeterminate ? 'mixed' : undefined}\n {...getSemanticOwnerAriaProps({\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-disabled': ariaDisabled,\n })}\n onChange={handleChange}\n autoFocus={autoFocus}\n name={group?.name ?? name}\n value={value as string}\n />\n {(checked || (indeterminate && !checked)) && (\n <span\n className=\"tw-absolute tw-inset-0 tw-bg-center tw-bg-no-repeat\"\n style={{\n backgroundImage:\n indeterminate && !checked\n ? 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMiIgdmlld0JveD0iMCAwIDEwIDIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGlkPSJWZWN0b3IgMSAoU3Ryb2tlKSIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wLjc1IDFDMC43NSAwLjU4NTc4NiAxLjA4NTc5IDAuMjUgMS41IDAuMjVIOC41QzguOTE0MjEgMC4yNSA5LjI1IDAuNTg1Nzg2IDkuMjUgMUM5LjI1IDEuNDE0MjEgOC45MTQyMSAxLjc1IDguNSAxLjc1SDEuNUMxLjA4NTc5IDEuNzUgMC43NSAxLjQxNDIxIDAuNzUgMVoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=\")'\n : 'url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iOCIgdmlld0JveD0iMCAwIDEwIDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGlkPSJJY29uIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTkuNTMwMzMgMC45Njk2N0M5LjgyMzIyIDEuMjYyNTYgOS44MjMyMiAxLjczNzQ0IDkuNTMwMzMgMi4wMzAzM0w0LjUzMDMzIDcuMDMwMzNDNC4yMzc0NCA3LjMyMzIyIDMuNzYyNTYgNy4zMjMyMiAzLjQ2OTY3IDcuMDMwMzNMMC45Njk2NyA0LjUzMDMzQzAuNjc2Nzc3IDQuMjM3NDQgMC42NzY3NzcgMy43NjI1NiAwLjk2OTY3IDMuNDY5NjdDMS4yNjI1NiAzLjE3Njc4IDEuNzM3NDQgMy4xNzY3OCAyLjAzMDMzIDMuNDY5NjdMNCA1LjQzOTM0TDguNDY5NjcgMC45Njk2N0M4Ljc2MjU2IDAuNjc2Nzc3IDkuMjM3NDQgMC42NzY3NzcgOS41MzAzMyAwLjk2OTY3WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+Cg==\")',\n backgroundSize:\n indeterminate && !checked ? '10px 2px' : '10px 8px',\n }}\n />\n )}\n </span>\n {children && (\n <span\n className={cn(\n 'ald-checkbox-label tw-inline-flex tw-select-none tw-items-center tw-gap-1 tw-text-[var(--content-primary)] [&_svg]:tw-inline-block [&_svg]:tw-shrink-0',\n 'tw-text-typography-label',\n bold && 'tw-font-medium',\n mergedDisabled &&\n 'tw-cursor-default tw-text-[var(--content-disabled)]',\n )}\n >\n {children}\n </span>\n )}\n </label>\n );\n}\n\nfunction CheckboxGroup(props: ICheckboxGroupProps) {\n const {\n className,\n disabled: customDisabled,\n size,\n options,\n value: controlledValue,\n defaultValue,\n onChange,\n direction,\n name,\n children,\n style,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n } = props;\n\n const disabled = useContext(DisabledContext);\n const mergedDisabled = customDisabled ?? disabled;\n\n const isControlled = 'value' in props;\n const [innerValue, setInnerValue] = useState<CheckboxValueType[]>(\n defaultValue ?? [],\n );\n const value = isControlled ? controlledValue ?? [] : innerValue;\n\n const handleGroupChange = (\n itemValue: CheckboxValueType,\n itemChecked: boolean,\n ) => {\n const newValue = itemChecked\n ? [...value, itemValue]\n : value.filter((v) => v !== itemValue);\n if (!isControlled) {\n setInnerValue(newValue);\n }\n onChange?.(newValue);\n };\n\n const renderOptions = () => {\n if (!options) return children;\n return options.map((opt) => {\n const optObj =\n typeof opt === 'object' ? opt : { label: String(opt), value: opt };\n return (\n <Checkbox\n key={String(optObj.value)}\n value={optObj.value}\n disabled={optObj.disabled}\n size={size}\n onChange={optObj.onChange}\n >\n {optObj.label}\n </Checkbox>\n );\n });\n };\n\n return (\n <div\n className={cn(\n 'ald-checkbox-group tw-flex tw-flex-wrap tw-gap-3',\n direction === 'vertical' && 'ald-checkbox-group-vertical tw-flex-col',\n size === 'small' && 'ald-checkbox-group-small',\n className,\n )}\n style={style}\n role=\"group\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n >\n <CheckboxGroupContext.Provider\n value={{\n value,\n disabled: mergedDisabled,\n name,\n toggleOption: handleGroupChange,\n }}\n >\n {renderOptions()}\n </CheckboxGroupContext.Provider>\n </div>\n );\n}\n\nCheckbox.Group = CheckboxGroup;\n\nexport default Checkbox;\n"],"mappings":"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"}
@@ -35,10 +35,15 @@ export interface ICheckboxProps {
35
35
  children?: React.ReactNode;
36
36
  value?: CheckboxValueType;
37
37
  name?: string;
38
+ required?: boolean;
39
+ 'aria-label'?: string;
40
+ 'aria-labelledby'?: string;
41
+ 'aria-describedby'?: string;
42
+ 'aria-invalid'?: React.AriaAttributes['aria-invalid'];
43
+ 'aria-required'?: React.AriaAttributes['aria-required'];
44
+ 'aria-disabled'?: React.AriaAttributes['aria-disabled'];
38
45
  /** 透传到根 label 元素的 data-testid,用于自动化测试定位 */
39
46
  'data-testid'?: string;
40
- /** 透传到根 label 元素的 aria-label,用于可访问性与自动化测试定位 */
41
- 'aria-label'?: string;
42
47
  }
43
48
  export interface ICheckboxGroupProps {
44
49
  defaultValue?: Array<CheckboxValueType>;
@@ -52,4 +57,7 @@ export interface ICheckboxGroupProps {
52
57
  style?: React.CSSProperties;
53
58
  size?: TSize;
54
59
  children?: React.ReactNode;
60
+ 'aria-label'?: string;
61
+ 'aria-labelledby'?: string;
62
+ 'aria-describedby'?: string;
55
63
  }
@@ -1,7 +1,7 @@
1
1
  import { cn } from "../lib/utils.js";
2
2
  import Memo from "../Icon/components/ArrowRightLightLine.js";
3
- import React, { useContext, useRef, useState } from "react";
4
- import { jsx, jsxs } from "react/jsx-runtime";
3
+ import React, { useContext, useEffect, useId, useRef, useState } from "react";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region src/Collapse/index.tsx
6
6
  var CollapseContext = React.createContext(null);
7
7
  var normalizeKeys = (keys) => {
@@ -110,8 +110,13 @@ Panel.__COLLAPSE_PANEL = true;
110
110
  var CollapsePanelView = React.forwardRef((props, ref) => {
111
111
  const { header, isActive, onToggle, disabled, extra, className, style, children, forceRender, expandIcon, expandIconPosition = "start", bordered, size = "middle", collapsible = "header" } = props;
112
112
  const contentRef = useRef(null);
113
+ const triggerId = useId();
114
+ const headerId = useId();
115
+ const contentId = useId();
113
116
  const [rendered, setRendered] = useState(isActive || !!forceRender);
114
- if (isActive && !rendered) setRendered(true);
117
+ useEffect(() => {
118
+ if (isActive || forceRender) setRendered(true);
119
+ }, [forceRender, isActive]);
115
120
  const handleTransitionEnd = () => {
116
121
  if (!isActive && !forceRender) setRendered(false);
117
122
  };
@@ -121,37 +126,78 @@ var CollapsePanelView = React.forwardRef((props, ref) => {
121
126
  });
122
127
  const iconElement = /* @__PURE__ */ jsx("span", {
123
128
  className: "ald-collapse-expand-icon ant-collapse-expand-icon tw-flex tw-items-center",
129
+ "aria-hidden": "true",
124
130
  style: {
125
131
  transform: isActive ? "rotate(90deg)" : "rotate(0deg)",
126
132
  transition: "transform 200ms"
127
133
  },
128
- onClick: disabled || collapsible !== "icon" ? void 0 : (e) => {
129
- e.stopPropagation();
130
- onToggle();
131
- },
132
134
  children: iconNode
133
135
  });
136
+ const triggerProps = {
137
+ type: "button",
138
+ id: triggerId,
139
+ "aria-expanded": isActive,
140
+ "aria-controls": contentId,
141
+ disabled,
142
+ onClick: onToggle
143
+ };
144
+ const headerText = /* @__PURE__ */ jsx("span", {
145
+ 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)]",
146
+ children: header
147
+ });
148
+ const headerTrigger = collapsible === "disabled" ? /* @__PURE__ */ jsxs("div", {
149
+ id: triggerId,
150
+ className: "tw-flex tw-flex-1 tw-items-center tw-gap-2",
151
+ "aria-disabled": "true",
152
+ children: [
153
+ expandIconPosition === "start" && iconElement,
154
+ headerText,
155
+ expandIconPosition === "end" && iconElement
156
+ ]
157
+ }) : collapsible === "icon" ? /* @__PURE__ */ jsxs(Fragment, { children: [
158
+ expandIconPosition === "start" && /* @__PURE__ */ jsx("button", {
159
+ ...triggerProps,
160
+ className: "tw-flex tw-cursor-pointer tw-items-center tw-border-0 tw-bg-transparent tw-p-0",
161
+ "aria-labelledby": headerId,
162
+ children: iconElement
163
+ }),
164
+ /* @__PURE__ */ jsx("span", {
165
+ id: headerId,
166
+ 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)]",
167
+ children: header
168
+ }),
169
+ expandIconPosition === "end" && /* @__PURE__ */ jsx("button", {
170
+ ...triggerProps,
171
+ className: "tw-flex tw-cursor-pointer tw-items-center tw-border-0 tw-bg-transparent tw-p-0",
172
+ "aria-labelledby": headerId,
173
+ children: iconElement
174
+ })
175
+ ] }) : /* @__PURE__ */ jsxs("button", {
176
+ ...triggerProps,
177
+ className: "tw-flex tw-flex-1 tw-items-center tw-gap-2 tw-border-0 tw-bg-transparent tw-p-0 tw-text-left",
178
+ children: [
179
+ expandIconPosition === "start" && iconElement,
180
+ headerText,
181
+ expandIconPosition === "end" && iconElement
182
+ ]
183
+ });
134
184
  return /* @__PURE__ */ jsxs("div", {
135
185
  ref,
136
186
  className: cn("ald-collapse-item ant-collapse-item tw-w-full", isActive && "ald-collapse-item-active", disabled && "tw-pointer-events-none tw-opacity-50", `ald-collapse-item-${size}`, className),
137
187
  style,
188
+ "aria-disabled": disabled || collapsible === "disabled" || void 0,
138
189
  children: [/* @__PURE__ */ jsxs("div", {
139
- className: cn("ald-collapse-header ant-collapse-header tw-flex tw-items-center tw-gap-2 tw-p-3", !disabled && collapsible !== "icon" && "tw-cursor-pointer"),
140
- onClick: disabled || collapsible === "icon" ? void 0 : onToggle,
141
- children: [
142
- expandIconPosition === "start" && iconElement,
143
- /* @__PURE__ */ jsx("span", {
144
- 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)]",
145
- children: header
146
- }),
147
- extra && /* @__PURE__ */ jsx("span", {
148
- className: "ald-collapse-extra ant-collapse-extra",
149
- onClick: (e) => e.stopPropagation(),
150
- children: extra
151
- }),
152
- expandIconPosition === "end" && iconElement
153
- ]
190
+ className: cn("ald-collapse-header ant-collapse-header tw-flex tw-items-center tw-gap-2 tw-p-3", !disabled && collapsible !== "icon" && collapsible !== "disabled" && "tw-cursor-pointer"),
191
+ children: [headerTrigger, extra && /* @__PURE__ */ jsx("span", {
192
+ className: "ald-collapse-extra ant-collapse-extra",
193
+ onClick: (e) => e.stopPropagation(),
194
+ children: extra
195
+ })]
154
196
  }), /* @__PURE__ */ jsx("div", {
197
+ id: contentId,
198
+ role: "region",
199
+ "aria-labelledby": triggerId,
200
+ "aria-hidden": !isActive,
155
201
  className: "tw-grid tw-transition-[grid-template-rows] tw-duration-200",
156
202
  style: { gridTemplateRows: isActive ? "1fr" : "0fr" },
157
203
  onTransitionEnd: handleTransitionEnd,
@@ -1 +1 @@
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 size: 'large' | 'middle' | 'small';\n collapsible?: 'header' | 'icon' | 'disabled';\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 size = 'middle',\n collapsible,\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 size,\n collapsible,\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 `ald-collapse-${size}`,\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 ?? 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 const size = ctx?.size ?? 'middle';\n const mergedCollapsible = collapsible ?? ctx?.collapsible;\n\n return (\n <CollapsePanelView\n ref={ref}\n header={header}\n isActive={isActive}\n onToggle={onToggle}\n disabled={disabled || mergedCollapsible === 'disabled'}\n extra={extra}\n className={className}\n style={style}\n forceRender={forceRender}\n expandIcon={expandIcon}\n expandIconPosition={expandIconPosition}\n bordered={bordered}\n size={size}\n collapsible={mergedCollapsible}\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 size?: 'large' | 'middle' | 'small';\n collapsible?: 'header' | 'icon' | 'disabled';\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 size = 'middle',\n collapsible = 'header',\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(--content-secondary)\" />\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 onClick={\n disabled || collapsible !== 'icon'\n ? undefined\n : (e) => {\n e.stopPropagation();\n onToggle();\n }\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 `ald-collapse-item-${size}`,\n className,\n )}\n style={style}\n >\n <div\n className={cn(\n 'ald-collapse-header ant-collapse-header tw-flex tw-items-center tw-gap-2 tw-p-3',\n !disabled && collapsible !== 'icon' && 'tw-cursor-pointer',\n )}\n onClick={disabled || collapsible === 'icon' ? 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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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Collapse/index.tsx"],"sourcesContent":["import React, { useContext, useEffect, useId, 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 size: 'large' | 'middle' | 'small';\n collapsible?: 'header' | 'icon' | 'disabled';\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 size = 'middle',\n collapsible,\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 size,\n collapsible,\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 `ald-collapse-${size}`,\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 ?? 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 const size = ctx?.size ?? 'middle';\n const mergedCollapsible = collapsible ?? ctx?.collapsible;\n\n return (\n <CollapsePanelView\n ref={ref}\n header={header}\n isActive={isActive}\n onToggle={onToggle}\n disabled={disabled || mergedCollapsible === 'disabled'}\n extra={extra}\n className={className}\n style={style}\n forceRender={forceRender}\n expandIcon={expandIcon}\n expandIconPosition={expandIconPosition}\n bordered={bordered}\n size={size}\n collapsible={mergedCollapsible}\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 size?: 'large' | 'middle' | 'small';\n collapsible?: 'header' | 'icon' | 'disabled';\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 size = 'middle',\n collapsible = 'header',\n } = props;\n\n const contentRef = useRef<HTMLDivElement>(null);\n const triggerId = useId();\n const headerId = useId();\n const contentId = useId();\n const [rendered, setRendered] = useState(isActive || !!forceRender);\n\n useEffect(() => {\n if (isActive || forceRender) {\n setRendered(true);\n }\n }, [forceRender, isActive]);\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(--content-secondary)\" />\n );\n\n const iconElement = (\n <span\n className=\"ald-collapse-expand-icon ant-collapse-expand-icon tw-flex tw-items-center\"\n aria-hidden=\"true\"\n style={{\n transform: isActive ? 'rotate(90deg)' : 'rotate(0deg)',\n transition: 'transform 200ms',\n }}\n >\n {iconNode}\n </span>\n );\n\n const triggerProps = {\n type: 'button' as const,\n id: triggerId,\n 'aria-expanded': isActive,\n 'aria-controls': contentId,\n disabled,\n onClick: onToggle,\n };\n\n const headerText = (\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 );\n\n const headerTrigger =\n collapsible === 'disabled' ? (\n <div\n id={triggerId}\n className=\"tw-flex tw-flex-1 tw-items-center tw-gap-2\"\n aria-disabled=\"true\"\n >\n {expandIconPosition === 'start' && iconElement}\n {headerText}\n {expandIconPosition === 'end' && iconElement}\n </div>\n ) : collapsible === 'icon' ? (\n <>\n {expandIconPosition === 'start' && (\n <button\n {...triggerProps}\n className=\"tw-flex tw-cursor-pointer tw-items-center tw-border-0 tw-bg-transparent tw-p-0\"\n aria-labelledby={headerId}\n >\n {iconElement}\n </button>\n )}\n <span\n id={headerId}\n 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 >\n {header}\n </span>\n {expandIconPosition === 'end' && (\n <button\n {...triggerProps}\n className=\"tw-flex tw-cursor-pointer tw-items-center tw-border-0 tw-bg-transparent tw-p-0\"\n aria-labelledby={headerId}\n >\n {iconElement}\n </button>\n )}\n </>\n ) : (\n <button\n {...triggerProps}\n className=\"tw-flex tw-flex-1 tw-items-center tw-gap-2 tw-border-0 tw-bg-transparent tw-p-0 tw-text-left\"\n >\n {expandIconPosition === 'start' && iconElement}\n {headerText}\n {expandIconPosition === 'end' && iconElement}\n </button>\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 `ald-collapse-item-${size}`,\n className,\n )}\n style={style}\n aria-disabled={disabled || collapsible === 'disabled' || undefined}\n >\n <div\n className={cn(\n 'ald-collapse-header ant-collapse-header tw-flex tw-items-center tw-gap-2 tw-p-3',\n !disabled &&\n collapsible !== 'icon' &&\n collapsible !== 'disabled' &&\n 'tw-cursor-pointer',\n )}\n >\n {headerTrigger}\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 </div>\n <div\n id={contentId}\n role=\"region\"\n aria-labelledby={triggerId}\n aria-hidden={!isActive}\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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"}
@@ -5,7 +5,7 @@ import { LocaleContext, getTranslator } from "../locale/default.js";
5
5
  import { colors, specialColors } from "./constant.js";
6
6
  /* empty css */
7
7
  import ColorPicker$1 from "./ComplexColorPicker/index.js";
8
- import { useContext, useEffect, useRef, useState } from "react";
8
+ import { useContext, useEffect, useId, useRef, useState } from "react";
9
9
  import { jsx, jsxs } from "react/jsx-runtime";
10
10
  //#region src/ColorPicker/index.tsx
11
11
  function getLocalRecentColors(localStorageKey) {
@@ -26,6 +26,15 @@ function ColorPicker({ className, value, icon, onChange, defaultColor = colors[0
26
26
  const [recentColors, setRecentColors] = useState([]);
27
27
  const overlayRef = useRef(null);
28
28
  const wrapRef = useRef(null);
29
+ const triggerRef = useRef(null);
30
+ const swatchRefs = useRef({});
31
+ const triggerId = `ald-color-picker-trigger-${useId().replace(/:/g, "")}`;
32
+ const popupId = `ald-color-picker-popup-${useId().replace(/:/g, "")}`;
33
+ const swatchOrder = Array.from(new Set([
34
+ defaultColor,
35
+ ...colors,
36
+ ...recentColors
37
+ ]));
29
38
  useEffect(() => {
30
39
  setRecentColors(getLocalRecentColors(localStorageKey));
31
40
  }, [localStorageKey]);
@@ -36,76 +45,115 @@ function ColorPicker({ className, value, icon, onChange, defaultColor = colors[0
36
45
  setLocalRecentColors(localStorageKey, newRecentColors);
37
46
  onChange?.(color);
38
47
  setOpen(false);
48
+ window.setTimeout(() => triggerRef.current?.focus(), 0);
39
49
  };
40
50
  useEffect(() => {
41
51
  const handleClick = (e) => {
42
- if (wrapRef.current?.contains(e.target)) return setOpen(!open);
43
- if (!overlayRef.current?.contains(e.target)) return setOpen(false);
52
+ if (!wrapRef.current?.contains(e.target) && !overlayRef.current?.contains(e.target)) return setOpen(false);
44
53
  };
45
54
  document.addEventListener("click", handleClick);
46
55
  return () => {
47
56
  document.removeEventListener("click", handleClick);
48
57
  };
49
- }, [open]);
58
+ }, []);
59
+ useEffect(() => {
60
+ if (!open) return;
61
+ const selectedIndex = Math.max(0, swatchOrder.indexOf(value ?? defaultColor));
62
+ window.setTimeout(() => {
63
+ swatchRefs.current[swatchOrder[selectedIndex]]?.focus();
64
+ }, 0);
65
+ }, [
66
+ defaultColor,
67
+ open,
68
+ swatchOrder,
69
+ value
70
+ ]);
71
+ useEffect(() => {
72
+ triggerRef.current?.setAttribute("aria-expanded", String(open));
73
+ triggerRef.current?.setAttribute("aria-controls", popupId);
74
+ }, [open, popupId]);
75
+ const renderSwatch = (color, label) => {
76
+ const selected = color === value;
77
+ const index = swatchOrder.indexOf(color);
78
+ const selectedIndex = Math.max(0, swatchOrder.indexOf(value ?? defaultColor));
79
+ return /* @__PURE__ */ jsx("button", {
80
+ type: "button",
81
+ id: `${popupId}-swatch-${encodeURIComponent(color)}`,
82
+ ref: (node) => {
83
+ swatchRefs.current[color] = node;
84
+ },
85
+ role: "radio",
86
+ "aria-label": label,
87
+ "aria-checked": selected,
88
+ tabIndex: index === selectedIndex ? 0 : -1,
89
+ disabled,
90
+ className: cn("tw-box-border tw-h-[21px] tw-w-[21px] tw-cursor-pointer tw-border tw-border-solid tw-border-[var(--background-default)] tw-bg-transparent tw-p-0", { "tw-border-[var(--border-neutral-strong)]": selected }),
91
+ onClick: () => {
92
+ if (!selected) onColorSelect(color);
93
+ },
94
+ onKeyDown: (event) => {
95
+ if (event.key === "Escape") {
96
+ event.preventDefault();
97
+ setOpen(false);
98
+ triggerRef.current?.focus();
99
+ return;
100
+ }
101
+ if (event.key === "ArrowRight" || event.key === "ArrowDown") {
102
+ event.preventDefault();
103
+ swatchRefs.current[swatchOrder[(index + 1) % swatchOrder.length]]?.focus();
104
+ return;
105
+ }
106
+ if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
107
+ event.preventDefault();
108
+ swatchRefs.current[swatchOrder[(index - 1 + swatchOrder.length) % swatchOrder.length]]?.focus();
109
+ return;
110
+ }
111
+ if (event.key === "Home" || event.key === "End") {
112
+ event.preventDefault();
113
+ swatchRefs.current[swatchOrder[event.key === "Home" ? 0 : swatchOrder.length - 1]]?.focus();
114
+ }
115
+ },
116
+ style: { borderColor: selected ? "var(--border-neutral-strong)" : specialColors.includes(color) ? "var(--border-neutral-subtle)" : color },
117
+ children: /* @__PURE__ */ jsx("span", {
118
+ "aria-hidden": "true",
119
+ className: cn("tw-block tw-h-full tw-w-full", { "tw-m-px tw-h-[17px] tw-w-[17px]": selected }),
120
+ style: { backgroundColor: color }
121
+ })
122
+ }, `${label}-${color}`);
123
+ };
50
124
  const overlay = /* @__PURE__ */ jsxs("div", {
125
+ id: popupId,
126
+ role: "radiogroup",
127
+ "aria-label": t.ColorPicker.standardColor,
51
128
  className: "tw-relative tw-box-border tw-w-[253px] tw-rounded-sm tw-bg-[var(--background-default)] tw-p-[8px_7px]",
52
129
  ref: overlayRef,
130
+ onKeyDown: (event) => {
131
+ if (event.key === "Escape") {
132
+ event.preventDefault();
133
+ setOpen(false);
134
+ triggerRef.current?.focus();
135
+ }
136
+ },
53
137
  children: [
54
138
  /* @__PURE__ */ jsxs("div", {
55
139
  className: "tw-flex tw-items-center tw-text-xs",
56
140
  children: [/* @__PURE__ */ jsx("div", {
57
- className: cn("tw-mr-2 tw-box-border tw-h-[21px] tw-w-[21px] tw-cursor-pointer tw-border tw-border-solid tw-border-[var(--background-default)]", { "tw-border-[var(--border-neutral-strong)]": defaultColor === value }),
58
- onClick: () => {
59
- if (disabled) return;
60
- if (defaultColor === value) return;
61
- onColorSelect(defaultColor);
62
- },
63
- children: /* @__PURE__ */ jsx("div", {
64
- className: "tw-size-full",
65
- style: { backgroundColor: defaultColor }
66
- })
141
+ className: "tw-mr-2",
142
+ children: renderSwatch(defaultColor, t.ColorPicker.default)
67
143
  }), t.ColorPicker.default]
68
144
  }),
69
145
  /* @__PURE__ */ jsxs("div", {
70
146
  className: "tw-mt-1.5 tw-text-xs",
71
147
  children: [/* @__PURE__ */ jsx("p", { children: t.ColorPicker.standardColor }), /* @__PURE__ */ jsx("div", {
72
148
  className: "tw-mt-0.5 tw-flex tw-flex-wrap tw-justify-evenly tw-gap-[4px_2px] tw-text-[0px]",
73
- children: colors.map((color) => {
74
- const isSelected = color === value;
75
- return /* @__PURE__ */ jsx("div", {
76
- className: cn("tw-box-border tw-h-[21px] tw-w-[21px] tw-cursor-pointer tw-border tw-border-solid tw-border-[var(--background-default)]", { "tw-border-[var(--border-neutral-strong)]": isSelected }),
77
- onClick: () => {
78
- if (color === value) return;
79
- onColorSelect(color);
80
- },
81
- style: { borderColor: isSelected ? "var(--border-neutral-strong)" : specialColors.includes(color) ? "var(--border-neutral-subtle)" : color },
82
- children: /* @__PURE__ */ jsx("div", {
83
- className: cn("tw-h-full tw-w-full", { "tw-m-px tw-h-[17px] tw-w-[17px]": isSelected }),
84
- style: { backgroundColor: color }
85
- })
86
- }, color);
87
- })
149
+ children: colors.map((color) => renderSwatch(color, color))
88
150
  })]
89
151
  }),
90
152
  /* @__PURE__ */ jsxs("div", {
91
153
  className: "tw-mt-1.5 tw-text-xs",
92
154
  children: [/* @__PURE__ */ jsx("p", { children: t.ColorPicker.recentlyUsed }), /* @__PURE__ */ jsx("div", {
93
155
  className: "tw-mt-0.5 tw-flex tw-flex-wrap tw-justify-start tw-gap-[4px_2px] tw-text-[0px]",
94
- children: recentColors.map((color) => {
95
- const isSelected = color === value;
96
- return /* @__PURE__ */ jsx("div", {
97
- className: cn("tw-box-border tw-h-[21px] tw-w-[21px] tw-cursor-pointer tw-border tw-border-solid tw-border-[var(--background-default)]", { "tw-border-[var(--border-neutral-strong)]": isSelected }),
98
- onClick: () => {
99
- if (color === value) return;
100
- onColorSelect(color);
101
- },
102
- style: { borderColor: isSelected ? "var(--border-neutral-strong)" : specialColors.includes(color) ? "var(--border-neutral-subtle)" : color },
103
- children: /* @__PURE__ */ jsx("div", {
104
- className: cn("tw-h-full tw-w-full", { "tw-m-px tw-h-[17px] tw-w-[17px]": isSelected }),
105
- style: { backgroundColor: color }
106
- })
107
- }, color);
108
- })
156
+ children: recentColors.map((color) => renderSwatch(color, color))
109
157
  })]
110
158
  })
111
159
  ]
@@ -116,13 +164,20 @@ function ColorPicker({ className, value, icon, onChange, defaultColor = colors[0
116
164
  children: /* @__PURE__ */ jsx(Dropdown, {
117
165
  trigger: "click",
118
166
  open,
167
+ onOpenChange: setOpen,
119
168
  disabled,
120
169
  placement: "bottom-start",
121
170
  overlayClassName: "ald-color-picker-overlay-wrapper",
122
171
  dropdownRender: () => {
123
172
  return overlay;
124
173
  },
125
- children: /* @__PURE__ */ jsxs("div", {
174
+ children: /* @__PURE__ */ jsxs("button", {
175
+ type: "button",
176
+ id: triggerId,
177
+ ref: triggerRef,
178
+ "aria-label": t.ColorPicker.default,
179
+ "aria-controls": popupId,
180
+ "aria-expanded": open,
126
181
  className: cn("ald-color-picker-wrapper", "tw-flex tw-flex-row tw-items-center tw-justify-between tw-gap-1 tw-h-7 tw-px-2.5 tw-py-1.5 tw-bg-[var(--background-default)] tw-border tw-border-solid tw-border-[var(--border-neutral-subtle)] tw-box-border tw-cursor-pointer tw-rounded tw-text-[var(--content-primary)] tw-transition-[border] tw-duration-500 tw-ease-in-out", {
127
182
  "tw-border-[var(--border-brand-subtle)]": open && bordered !== false,
128
183
  "tw-border-[var(--border-neutral-subtle)] tw-bg-[var(--background-neutral-on-subtle)]": disabled,
@@ -131,7 +186,18 @@ function ColorPicker({ className, value, icon, onChange, defaultColor = colors[0
131
186
  "hover:tw-border-[var(--action-ghost-normal)]": bordered === false
132
187
  }),
133
188
  onClick: (e) => {
134
- if (disabled) e.stopPropagation();
189
+ if (disabled) {
190
+ e.stopPropagation();
191
+ return;
192
+ }
193
+ setOpen((current) => !current);
194
+ },
195
+ onKeyDown: (event) => {
196
+ if (disabled) return;
197
+ if (event.key === "ArrowDown" || event.key === "ArrowUp" || event.key === "Enter" || event.key === " ") {
198
+ event.preventDefault();
199
+ setOpen(true);
200
+ }
135
201
  },
136
202
  children: [icon ? /* @__PURE__ */ jsxs("div", {
137
203
  className: "tw-relative -tw-top-px",