@aloudata/aloudata-design 3.1.0 → 3.1.2

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 (196) 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 +20 -6
  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 +17 -2
  17. package/dist/Checkbox/index.js.map +1 -1
  18. package/dist/Checkbox/type.d.ts +10 -2
  19. package/dist/ColorPicker/index.js +112 -46
  20. package/dist/ColorPicker/index.js.map +1 -1
  21. package/dist/DataPreviewTable/components/Body/Cell.d.ts +2 -0
  22. package/dist/DataPreviewTable/components/Body/Cell.js +9 -1
  23. package/dist/DataPreviewTable/components/Body/Cell.js.map +1 -1
  24. package/dist/DataPreviewTable/components/Body/index.d.ts +1 -0
  25. package/dist/DataPreviewTable/components/Body/index.js +35 -23
  26. package/dist/DataPreviewTable/components/Body/index.js.map +1 -1
  27. package/dist/DataPreviewTable/components/Header/index.d.ts +1 -0
  28. package/dist/DataPreviewTable/components/Header/index.js +36 -28
  29. package/dist/DataPreviewTable/components/Header/index.js.map +1 -1
  30. package/dist/DataPreviewTable/index.js +19 -2
  31. package/dist/DataPreviewTable/index.js.map +1 -1
  32. package/dist/Drawer/index.d.ts +4 -0
  33. package/dist/Drawer/index.js +93 -79
  34. package/dist/Drawer/index.js.map +1 -1
  35. package/dist/Dropdown/index.d.ts +1 -1
  36. package/dist/Dropdown/index.js +64 -13
  37. package/dist/Dropdown/index.js.map +1 -1
  38. package/dist/Form/FormItemContext.d.ts +1 -1
  39. package/dist/Form/FormItemContext.js.map +1 -1
  40. package/dist/Form/index.js +50 -7
  41. package/dist/Form/index.js.map +1 -1
  42. package/dist/IconButton/index.d.ts +2 -2
  43. package/dist/IconButton/index.js +9 -3
  44. package/dist/IconButton/index.js.map +1 -1
  45. package/dist/Input/components/Input/index.js +18 -8
  46. package/dist/Input/components/Input/index.js.map +1 -1
  47. package/dist/Input/components/TextArea/index.js +18 -7
  48. package/dist/Input/components/TextArea/index.js.map +1 -1
  49. package/dist/Input/privateSemanticOwner.d.ts +2 -0
  50. package/dist/Input/privateSemanticOwner.js +1 -0
  51. package/dist/InputNumber/index.js +16 -9
  52. package/dist/InputNumber/index.js.map +1 -1
  53. package/dist/InputNumber/type.d.ts +2 -2
  54. package/dist/LogicTree/components/LogicItem/index.d.ts +2 -1
  55. package/dist/LogicTree/components/LogicItem/index.js +13 -2
  56. package/dist/LogicTree/components/LogicItem/index.js.map +1 -1
  57. package/dist/LogicTree/index.js +2 -0
  58. package/dist/LogicTree/index.js.map +1 -1
  59. package/dist/MemberPicker/components/MemberSelection.d.ts +2 -0
  60. package/dist/MemberPicker/components/MemberSelection.js +15 -13
  61. package/dist/MemberPicker/components/MemberSelection.js.map +1 -1
  62. package/dist/MemberPicker/components/MultipleOption.js +12 -0
  63. package/dist/MemberPicker/components/MultipleOption.js.map +1 -1
  64. package/dist/MemberPicker/components/Panel.d.ts +2 -0
  65. package/dist/MemberPicker/components/Panel.js +11 -1
  66. package/dist/MemberPicker/components/Panel.js.map +1 -1
  67. package/dist/MemberPicker/components/PanelWrapper.js +2 -0
  68. package/dist/MemberPicker/components/PanelWrapper.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 +3 -1
  74. package/dist/MemberPicker/components/UserGroupSelection.js +65 -42
  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/index.js +1 -0
  87. package/dist/Pagination/index.js.map +1 -1
  88. package/dist/Popconfirm/index.js +9 -1
  89. package/dist/Popconfirm/index.js.map +1 -1
  90. package/dist/Popover/index.js +52 -1
  91. package/dist/Popover/index.js.map +1 -1
  92. package/dist/Progress/index.js +4 -0
  93. package/dist/Progress/index.js.map +1 -1
  94. package/dist/Radio/components/Group/index.d.ts +5 -1
  95. package/dist/Radio/components/Group/index.js +7 -2
  96. package/dist/Radio/components/Group/index.js.map +1 -1
  97. package/dist/Radio/components/Radio/index.js +26 -0
  98. package/dist/Radio/components/Radio/index.js.map +1 -1
  99. package/dist/Radio/interface/radio.d.ts +7 -0
  100. package/dist/Radio/interface/radioGroup.d.ts +2 -0
  101. package/dist/RenameInput/index.js +11 -0
  102. package/dist/RenameInput/index.js.map +1 -1
  103. package/dist/Select/BaseSelect.d.ts +3 -0
  104. package/dist/Select/BaseSelect.js +229 -32
  105. package/dist/Select/BaseSelect.js.map +1 -1
  106. package/dist/Select/SelectTrigger.d.ts +2 -0
  107. package/dist/Select/SelectTrigger.js +13 -5
  108. package/dist/Select/SelectTrigger.js.map +1 -1
  109. package/dist/Select/components/OptionCollection.d.ts +41 -0
  110. package/dist/Select/components/OptionCollection.js +124 -0
  111. package/dist/Select/components/OptionCollection.js.map +1 -0
  112. package/dist/Select/index.js +45 -3
  113. package/dist/Select/index.js.map +1 -1
  114. package/dist/Select/interface.d.ts +1 -1
  115. package/dist/Skeleton/index.js +1 -1
  116. package/dist/Skeleton/index.js.map +1 -1
  117. package/dist/Spin/index.d.ts +1 -1
  118. package/dist/Spin/index.js +22 -7
  119. package/dist/Spin/index.js.map +1 -1
  120. package/dist/Switch/index.d.ts +5 -0
  121. package/dist/Switch/index.js +15 -5
  122. package/dist/Switch/index.js.map +1 -1
  123. package/dist/Table/components/Header.js +0 -1
  124. package/dist/Table/components/Header.js.map +1 -1
  125. package/dist/Table/index.js +42 -27
  126. package/dist/Table/index.js.map +1 -1
  127. package/dist/Tabs/index.js +1 -0
  128. package/dist/Tabs/index.js.map +1 -1
  129. package/dist/Tag/index.js +20 -1
  130. package/dist/Tag/index.js.map +1 -1
  131. package/dist/Tooltip/index.js +34 -5
  132. package/dist/Tooltip/index.js.map +1 -1
  133. package/dist/Tour/index.js +13 -1
  134. package/dist/Tour/index.js.map +1 -1
  135. package/dist/Tree/Tree2.js +2 -0
  136. package/dist/Tree/Tree2.js.map +1 -1
  137. package/dist/_utils/dialogAccessibility.d.ts +17 -0
  138. package/dist/_utils/dialogAccessibility.js +110 -0
  139. package/dist/_utils/dialogAccessibility.js.map +1 -0
  140. package/dist/_utils/formControlSemanticOwner.d.ts +3 -0
  141. package/dist/_utils/formControlSemanticOwner.js +17 -0
  142. package/dist/_utils/formControlSemanticOwner.js.map +1 -0
  143. package/dist/_utils/overlayCoordinator.js +1 -11
  144. package/dist/_utils/overlayCoordinator.js.map +1 -1
  145. package/dist/aloudata-design.css +1 -1
  146. package/dist/governance/semantic.d.ts +1 -0
  147. package/dist/governance/semantic.js +2 -0
  148. package/dist/governance/semantic.json +1737 -0
  149. package/dist/theme/contract/baselineResolvedTokenValueManifest.d.ts +1 -1
  150. package/dist/theme/contract/darkResolvedTokenValueManifest.d.ts +1 -1
  151. package/dist/theme/contract/tokenOutputContract.js +1 -0
  152. package/dist/theme/contract/tokenOutputContract.js.map +1 -1
  153. package/dist/theme/generator/acceptedColorValues.d.ts +2 -1
  154. package/dist/theme/generator/baselineTokenValueDelivery.d.ts +9 -1
  155. package/dist/theme/generator/minimalAcceptedColorValues.d.ts +2 -2
  156. package/dist/theme/generator/neutralSourceResolver.d.ts +28 -0
  157. package/dist/theme/generator/neutralSourceResolver.js +2 -0
  158. package/dist/theme/generator/neutralSourceValues.d.ts +28 -0
  159. package/dist/theme/generator/neutralSourceValues.js +2 -0
  160. package/dist/theme/governance/semanticGovernanceContract.d.ts +91 -0
  161. package/dist/theme/governance/semanticGovernanceContract.js +342 -0
  162. package/dist/theme/governance/semanticGovernanceContract.js.map +1 -0
  163. package/dist/theme/index.d.ts +2 -0
  164. package/dist/theme/index.js +1 -0
  165. package/dist/theme/neutralSourceContract.d.ts +3 -0
  166. package/dist/theme/neutralSourceContract.js +11 -0
  167. package/dist/theme/neutralSourceContract.js.map +1 -0
  168. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.d.ts +1 -1
  169. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js +46 -45
  170. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js.map +1 -1
  171. package/dist/theme/runtime/colorValueMode/generated/slateDarkDeclarations.d.ts +3 -0
  172. package/dist/theme/runtime/colorValueMode/generated/slateDarkDeclarations.js +2 -0
  173. package/dist/theme/runtime/colorValueMode/generated/slateLightDeclarations.d.ts +3 -0
  174. package/dist/theme/runtime/colorValueMode/generated/slateLightDeclarations.js +2 -0
  175. package/dist/theme/runtime/colorValueMode/generated/stoneDarkDeclarations.d.ts +3 -0
  176. package/dist/theme/runtime/colorValueMode/generated/stoneDarkDeclarations.js +2 -0
  177. package/dist/theme/runtime/colorValueMode/generated/stoneLightDeclarations.d.ts +3 -0
  178. package/dist/theme/runtime/colorValueMode/generated/stoneLightDeclarations.js +2 -0
  179. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.d.ts +1 -1
  180. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js +42 -41
  181. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js.map +1 -1
  182. package/dist/theme/runtime/colorValueMode/index.js +2 -12
  183. package/dist/theme/runtime/colorValueMode/index.js.map +1 -1
  184. package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.d.ts +2 -0
  185. package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.js +48 -0
  186. package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.js.map +1 -0
  187. package/dist/theme/runtime/colorValueMode/registry.d.ts +1 -1
  188. package/dist/theme/runtime/colorValueMode/registry.js +2 -1
  189. package/dist/theme/runtime/colorValueMode/registry.js.map +1 -1
  190. package/dist/theme/runtime/initAldTheme.js +1 -3
  191. package/dist/theme/runtime/initAldTheme.js.map +1 -1
  192. package/dist/theme/runtime/neutralSource/index.d.ts +6 -0
  193. package/dist/theme/runtime/neutralSource/index.js +11 -0
  194. package/dist/theme/runtime/neutralSource/index.js.map +1 -0
  195. package/dist/theme/runtime/neutralSource.d.ts +2 -0
  196. package/package.json +12 -2
@@ -0,0 +1,124 @@
1
+ import { cn } from "../../lib/utils.js";
2
+ import Memo from "../../Icon/components/CheckLightLine.js";
3
+ import { toString } from "../utils/commonUtil.js";
4
+ import "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ //#region src/Select/components/OptionCollection.tsx
7
+ /**
8
+ * Private Select collection seam for normalized, flat option data.
9
+ *
10
+ * It intentionally consumes the existing useOptions result instead of adding
11
+ * another public normalization path. Menu-shaped and hierarchical inputs stay
12
+ * on the legacy compatibility path until their Select contract is migrated.
13
+ */
14
+ function createSelectOptionCollection(listboxId, keyMenuItems) {
15
+ const options = Array.from(keyMenuItems.entries()).map(([key, option]) => ({
16
+ id: `${listboxId}-option-${key}`,
17
+ key,
18
+ value: option.value ?? key,
19
+ label: option.label,
20
+ disabled: !!option.disabled,
21
+ option
22
+ }));
23
+ return {
24
+ listboxId,
25
+ options,
26
+ enabledOptions: options.filter((option) => !option.disabled)
27
+ };
28
+ }
29
+ /**
30
+ * Visual collection renderer for the standard flat single-select popup.
31
+ *
32
+ * The legacy Menu class hooks are retained only to preserve existing Select
33
+ * geometry and option presentation while ownership moves to Select.
34
+ */
35
+ function OptionCollection({ collection, selectedValues, activeOptionKey, multiple = false, loading = false, listHeight, notFoundContent, onSelect }) {
36
+ if (collection.options.length === 0) return /* @__PURE__ */ jsx("div", {
37
+ className: "ald-menu",
38
+ "data-select-option-collection": collection.listboxId,
39
+ style: {
40
+ height: listHeight,
41
+ overflow: "auto"
42
+ },
43
+ children: /* @__PURE__ */ jsx("div", {
44
+ className: "szh-menu",
45
+ id: collection.listboxId,
46
+ role: "listbox",
47
+ "aria-multiselectable": multiple || void 0,
48
+ "aria-busy": loading || void 0,
49
+ style: {
50
+ height: listHeight,
51
+ overflow: "auto"
52
+ },
53
+ children: /* @__PURE__ */ jsx("div", {
54
+ role: "status",
55
+ "aria-live": "polite",
56
+ "aria-atomic": "true",
57
+ children: notFoundContent
58
+ })
59
+ })
60
+ });
61
+ return /* @__PURE__ */ jsx("div", {
62
+ className: "ald-menu",
63
+ "data-select-option-collection": collection.listboxId,
64
+ children: /* @__PURE__ */ jsx("div", {
65
+ className: "szh-menu",
66
+ id: collection.listboxId,
67
+ role: "listbox",
68
+ "aria-multiselectable": multiple || void 0,
69
+ "aria-busy": loading || void 0,
70
+ style: {
71
+ width: "100%",
72
+ minWidth: 0,
73
+ maxWidth: "none",
74
+ maxHeight: listHeight,
75
+ overflowY: "auto"
76
+ },
77
+ children: collection.options.map((item) => {
78
+ const selected = selectedValues.some((value) => toString(value) === toString(item.value));
79
+ return /* @__PURE__ */ jsx("div", {
80
+ id: item.id,
81
+ role: "option",
82
+ "aria-selected": selected,
83
+ "aria-disabled": item.disabled || void 0,
84
+ className: cn("szh-menu__item", "ald-menu-item", {
85
+ "szh-menu__item--disabled": item.disabled,
86
+ "ald-menu-item-selected": selected,
87
+ "szh-menu__item--hover": activeOptionKey === item.key
88
+ }),
89
+ "data-select-option-id": item.id,
90
+ onClick: () => {
91
+ if (!item.disabled) onSelect(item.value);
92
+ },
93
+ children: /* @__PURE__ */ jsxs("div", {
94
+ className: "ald-menu-item-label",
95
+ children: [
96
+ item.option.icon && /* @__PURE__ */ jsx("div", {
97
+ className: "ald-menu-item-label-icon",
98
+ children: item.option.icon
99
+ }),
100
+ /* @__PURE__ */ jsx("div", {
101
+ className: "ald-menu-item-label-text tw-text-typography-body-dense",
102
+ children: item.label
103
+ }),
104
+ (item.option.extra || selectedValues.length > 0) && /* @__PURE__ */ jsxs("div", {
105
+ className: "ald-menu-item-right",
106
+ children: [item.option.extra && /* @__PURE__ */ jsx("span", {
107
+ className: "ald-menu-item-extra",
108
+ children: item.option.extra
109
+ }), selectedValues.length > 0 && /* @__PURE__ */ jsx("div", {
110
+ className: cn("ald-menu-item-selection-slot", { "ald-menu-item-selection-slot-selected ald-menu-item-selected-icon": selected }),
111
+ children: selected ? /* @__PURE__ */ jsx(Memo, {}) : null
112
+ })]
113
+ })
114
+ ]
115
+ })
116
+ }, item.key);
117
+ })
118
+ })
119
+ });
120
+ }
121
+ //#endregion
122
+ export { createSelectOptionCollection, OptionCollection as default };
123
+
124
+ //# sourceMappingURL=OptionCollection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OptionCollection.js","names":[],"sources":["../../../src/Select/components/OptionCollection.tsx"],"sourcesContent":["import React from 'react';\nimport { CheckLightLine } from '../../Icon';\nimport { cn } from '../../lib/utils';\nimport { RawValueType, SelectItemType } from '../interface';\nimport { toString } from '../utils/commonUtil';\n\nexport interface SelectOptionCollectionItem {\n id: string;\n key: string;\n value: RawValueType;\n label: React.ReactNode;\n disabled: boolean;\n option: SelectItemType;\n}\n\nexport interface SelectOptionCollection {\n listboxId: string;\n options: SelectOptionCollectionItem[];\n enabledOptions: SelectOptionCollectionItem[];\n}\n\n/**\n * Private Select collection seam for normalized, flat option data.\n *\n * It intentionally consumes the existing useOptions result instead of adding\n * another public normalization path. Menu-shaped and hierarchical inputs stay\n * on the legacy compatibility path until their Select contract is migrated.\n */\nexport function createSelectOptionCollection(\n listboxId: string,\n keyMenuItems: Map<string, SelectItemType>,\n): SelectOptionCollection {\n const options = Array.from(keyMenuItems.entries()).map(([key, option]) => ({\n id: `${listboxId}-option-${key}`,\n key,\n value: (option.value ?? key) as RawValueType,\n label: option.label,\n disabled: !!option.disabled,\n option,\n }));\n\n return {\n listboxId,\n options,\n enabledOptions: options.filter((option) => !option.disabled),\n };\n}\n\ninterface OptionCollectionProps {\n collection: SelectOptionCollection;\n selectedValues: RawValueType[];\n activeOptionKey?: string;\n multiple?: boolean;\n loading?: boolean;\n listHeight: number;\n notFoundContent: React.ReactNode;\n onSelect: (value: RawValueType) => void;\n}\n\n/**\n * Visual collection renderer for the standard flat single-select popup.\n *\n * The legacy Menu class hooks are retained only to preserve existing Select\n * geometry and option presentation while ownership moves to Select.\n */\nexport default function OptionCollection({\n collection,\n selectedValues,\n activeOptionKey,\n multiple = false,\n loading = false,\n listHeight,\n notFoundContent,\n onSelect,\n}: OptionCollectionProps) {\n if (collection.options.length === 0) {\n return (\n <div\n className=\"ald-menu\"\n data-select-option-collection={collection.listboxId}\n style={{ height: listHeight, overflow: 'auto' }}\n >\n <div\n className=\"szh-menu\"\n id={collection.listboxId}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n aria-busy={loading || undefined}\n style={{ height: listHeight, overflow: 'auto' }}\n >\n <div role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {notFoundContent}\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div\n className=\"ald-menu\"\n data-select-option-collection={collection.listboxId}\n >\n <div\n className=\"szh-menu\"\n id={collection.listboxId}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n aria-busy={loading || undefined}\n style={{\n width: '100%',\n minWidth: 0,\n maxWidth: 'none',\n maxHeight: listHeight,\n overflowY: 'auto',\n }}\n >\n {collection.options.map((item) => {\n const selected = selectedValues.some(\n (value) => toString(value) === toString(item.value),\n );\n\n return (\n <div\n key={item.key}\n id={item.id}\n role=\"option\"\n aria-selected={selected}\n aria-disabled={item.disabled || undefined}\n className={cn('szh-menu__item', 'ald-menu-item', {\n 'szh-menu__item--disabled': item.disabled,\n 'ald-menu-item-selected': selected,\n 'szh-menu__item--hover': activeOptionKey === item.key,\n })}\n data-select-option-id={item.id}\n onClick={() => {\n if (!item.disabled) {\n onSelect(item.value);\n }\n }}\n >\n <div className=\"ald-menu-item-label\">\n {item.option.icon && (\n <div className=\"ald-menu-item-label-icon\">\n {item.option.icon}\n </div>\n )}\n <div className=\"ald-menu-item-label-text tw-text-typography-body-dense\">\n {item.label}\n </div>\n {(item.option.extra || selectedValues.length > 0) && (\n <div className=\"ald-menu-item-right\">\n {item.option.extra && (\n <span className=\"ald-menu-item-extra\">\n {item.option.extra}\n </span>\n )}\n {selectedValues.length > 0 && (\n <div\n className={cn('ald-menu-item-selection-slot', {\n 'ald-menu-item-selection-slot-selected ald-menu-item-selected-icon':\n selected,\n })}\n >\n {selected ? <CheckLightLine /> : null}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AA4BA,SAAgB,6BACd,WACA,cACwB;CACxB,MAAM,UAAU,MAAM,KAAK,aAAa,SAAS,CAAC,CAAC,KAAK,CAAC,KAAK,aAAa;EACzE,IAAI,GAAG,UAAU,UAAU;EAC3B;EACA,OAAQ,OAAO,SAAS;EACxB,OAAO,OAAO;EACd,UAAU,CAAC,CAAC,OAAO;EACnB;EACD,EAAE;AAEH,QAAO;EACL;EACA;EACA,gBAAgB,QAAQ,QAAQ,WAAW,CAAC,OAAO,SAAS;EAC7D;;;;;;;;AAoBH,SAAwB,iBAAiB,EACvC,YACA,gBACA,iBACA,WAAW,OACX,UAAU,OACV,YACA,iBACA,YACwB;AACxB,KAAI,WAAW,QAAQ,WAAW,EAChC,QACE,oBAAC,OAAD;EACE,WAAU;EACV,iCAA+B,WAAW;EAC1C,OAAO;GAAE,QAAQ;GAAY,UAAU;GAAQ;YAE/C,oBAAC,OAAD;GACE,WAAU;GACV,IAAI,WAAW;GACf,MAAK;GACL,wBAAsB,YAAY;GAClC,aAAW,WAAW;GACtB,OAAO;IAAE,QAAQ;IAAY,UAAU;IAAQ;aAE/C,oBAAC,OAAD;IAAK,MAAK;IAAS,aAAU;IAAS,eAAY;cAC/C;IACG,CAAA;GACF,CAAA;EACF,CAAA;AAIV,QACE,oBAAC,OAAD;EACE,WAAU;EACV,iCAA+B,WAAW;YAE1C,oBAAC,OAAD;GACE,WAAU;GACV,IAAI,WAAW;GACf,MAAK;GACL,wBAAsB,YAAY;GAClC,aAAW,WAAW;GACtB,OAAO;IACL,OAAO;IACP,UAAU;IACV,UAAU;IACV,WAAW;IACX,WAAW;IACZ;aAEA,WAAW,QAAQ,KAAK,SAAS;IAChC,MAAM,WAAW,eAAe,MAC7B,UAAU,SAAS,MAAM,KAAK,SAAS,KAAK,MAAM,CACpD;AAED,WACE,oBAAC,OAAD;KAEE,IAAI,KAAK;KACT,MAAK;KACL,iBAAe;KACf,iBAAe,KAAK,YAAY;KAChC,WAAW,GAAG,kBAAkB,iBAAiB;MAC/C,4BAA4B,KAAK;MACjC,0BAA0B;MAC1B,yBAAyB,oBAAoB,KAAK;MACnD,CAAC;KACF,yBAAuB,KAAK;KAC5B,eAAe;AACb,UAAI,CAAC,KAAK,SACR,UAAS,KAAK,MAAM;;eAIxB,qBAAC,OAAD;MAAK,WAAU;gBAAf;OACG,KAAK,OAAO,QACX,oBAAC,OAAD;QAAK,WAAU;kBACZ,KAAK,OAAO;QACT,CAAA;OAER,oBAAC,OAAD;QAAK,WAAU;kBACZ,KAAK;QACF,CAAA;QACJ,KAAK,OAAO,SAAS,eAAe,SAAS,MAC7C,qBAAC,OAAD;QAAK,WAAU;kBAAf,CACG,KAAK,OAAO,SACX,oBAAC,QAAD;SAAM,WAAU;mBACb,KAAK,OAAO;SACR,CAAA,EAER,eAAe,SAAS,KACvB,oBAAC,OAAD;SACE,WAAW,GAAG,gCAAgC,EAC5C,qEACE,UACH,CAAC;mBAED,WAAW,oBAAC,MAAD,EAAkB,CAAA,GAAG;SAC7B,CAAA,CAEJ;;OAEJ;;KACF,EA9CC,KAAK,IA8CN;KAER;GACE,CAAA;EACF,CAAA"}
@@ -2,6 +2,7 @@ import DisabledContext from "../ConfigProvider/DisabledContext.js";
2
2
  import { noOpFilter, toArray, toString } from "./utils/commonUtil.js";
3
3
  import useOptions, { isRawValue } from "./hooks/useOptions.js";
4
4
  import useCache_default from "./hooks/useCache.js";
5
+ import { createSelectOptionCollection } from "./components/OptionCollection.js";
5
6
  import BaseSelect, { isMultiple } from "./BaseSelect.js";
6
7
  import { injectPropsWithOption } from "./utils/valueUtil.js";
7
8
  import useDisplayMenu from "./hooks/useDisplayMenu.js";
@@ -10,7 +11,7 @@ import { jsx } from "react/jsx-runtime";
10
11
  import useMergedState from "rc-util/es/hooks/useMergedState";
11
12
  //#region src/Select/index.tsx
12
13
  var Select_default = forwardRef(function Select(props, ref) {
13
- const { value, defaultValue, mode, menu, options, onChange, onSelect, onSearch, onDeselect, labelInValue, filterOption, searchValue, optionLabelProp, listHeight = 256, disabled: customDisabled } = props;
14
+ const { value, defaultValue, mode, menu, options, onChange, onSelect, onSearch, onDeselect, labelInValue, filterOption, searchValue, optionLabelProp, listHeight = 256, disabled: customDisabled, showSearch, dropdownRender } = props;
14
15
  const [internalValue, setInternalValue] = useMergedState(defaultValue, { value });
15
16
  const disabled = useContext(DisabledContext);
16
17
  const mergedDisabled = customDisabled ?? disabled;
@@ -21,7 +22,7 @@ var Select_default = forwardRef(function Select(props, ref) {
21
22
  optionLabelProp,
22
23
  listHeight
23
24
  });
24
- const multiple = mode && isMultiple(mode);
25
+ const multiple = isMultiple(mode);
25
26
  const [innerSearchValue, setInnerSearchValue] = useMergedState(void 0, { value: searchValue });
26
27
  const convert2LabelValues = React.useCallback((draftValues) => {
27
28
  return toArray(draftValues).map((val) => {
@@ -132,6 +133,45 @@ var Select_default = forwardRef(function Select(props, ref) {
132
133
  keyMenuItems
133
134
  ]);
134
135
  const displayMenu = useDisplayMenu(selectMenu, onSearch ? filterOption || noOpFilter : filterOption, innerSearchValue);
136
+ const useStandardOptionCollection = !menu && !dropdownRender && !showSearch && !(options || []).some((option) => option.children?.length);
137
+ const collectionMenuItems = useMemo(() => {
138
+ if (!showSearch) return keyMenuItems;
139
+ const query = innerSearchValue || "";
140
+ return new Map(Array.from(keyMenuItems).filter(([, option]) => {
141
+ if (onSearch && !filterOption) return true;
142
+ if (filterOption) return filterOption(query, option);
143
+ return String(option.label ?? option.value).toLocaleLowerCase().includes(query.toLocaleLowerCase());
144
+ }));
145
+ }, [
146
+ filterOption,
147
+ innerSearchValue,
148
+ keyMenuItems,
149
+ onSearch,
150
+ showSearch
151
+ ]);
152
+ const collectionId = React.useId().replace(/:/g, "");
153
+ const optionCollection = useMemo(() => {
154
+ if (!useStandardOptionCollection) return;
155
+ return createSelectOptionCollection(`ald-select-listbox-${collectionId}`, collectionMenuItems);
156
+ }, [
157
+ collectionId,
158
+ collectionMenuItems,
159
+ useStandardOptionCollection
160
+ ]);
161
+ const onCollectionOptionSelect = useCallback((value) => {
162
+ const menuItem = keyMenuItems.get(toString(value));
163
+ const originalValue = menuItem?.value !== void 0 ? menuItem.value : value;
164
+ const selected = displayValues.some((item) => toString(item.value) === toString(originalValue));
165
+ if (multiple) triggerChange(selected ? displayValues.filter((item) => toString(item.value) !== toString(originalValue)).map((item) => item.value) : [...displayValues.map((item) => item.value), originalValue]);
166
+ else triggerChange(originalValue);
167
+ onOptionSelect(originalValue);
168
+ }, [
169
+ displayValues,
170
+ keyMenuItems,
171
+ multiple,
172
+ onOptionSelect,
173
+ triggerChange
174
+ ]);
135
175
  return /* @__PURE__ */ jsx(BaseSelect, {
136
176
  ...props,
137
177
  ref,
@@ -142,7 +182,9 @@ var Select_default = forwardRef(function Select(props, ref) {
142
182
  innerSearchValue: searchValue === void 0 ? innerSearchValue : searchValue,
143
183
  onOptionSelect,
144
184
  menu: selectMenu,
145
- displayMenu
185
+ displayMenu,
186
+ optionCollection,
187
+ onCollectionOptionSelect
146
188
  });
147
189
  });
148
190
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Select/index.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useContext, useMemo } from 'react';\nimport {\n BaseSelectRef,\n DefaultOptionType,\n DisplayInfoType,\n DraftValueType,\n ISelectProps,\n LabelInValueType,\n RawValueType,\n} from './interface';\n\nimport useOptions, { isRawValue } from './hooks/useOptions';\nimport useMergedState from 'rc-util/es/hooks/useMergedState';\nimport { noOpFilter, toArray } from './utils/commonUtil';\nimport useCache from './hooks/useCache';\nimport BaseSelect, { BaseSelectProps, isMultiple } from './BaseSelect';\nimport { MenuInfo } from '../Menu';\nimport { injectPropsWithOption } from './utils/valueUtil';\nimport useDisplayMenu from './hooks/useDisplayMenu';\nimport { toString } from './utils/commonUtil';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\n\nexport default forwardRef(function Select(\n props: ISelectProps,\n ref: React.Ref<BaseSelectRef>,\n) {\n const {\n value,\n defaultValue,\n mode,\n menu,\n options,\n onChange,\n onSelect,\n onSearch,\n onDeselect,\n labelInValue,\n filterOption,\n searchValue,\n optionLabelProp,\n listHeight = 256,\n disabled: customDisabled,\n } = props;\n\n // =========================== Values ===========================\n const [internalValue, setInternalValue] = useMergedState(defaultValue, {\n value,\n });\n const disabled = useContext(DisabledContext);\n const mergedDisabled = customDisabled ?? disabled;\n const parsedOptions = useOptions({\n menu,\n options,\n value: internalValue,\n optionLabelProp,\n listHeight,\n });\n const { menu: mergedMenu, keyMenuItems } = parsedOptions;\n const multiple = mode && isMultiple(mode);\n // ============================== SearchValue ==============================\n const [innerSearchValue, setInnerSearchValue] = useMergedState<\n string | undefined\n >(undefined, {\n value: searchValue,\n });\n // ========================= Wrap Value =========================\n const convert2LabelValues = React.useCallback(\n (draftValues: DraftValueType) => {\n // Convert to array\n const valueList = toArray(draftValues);\n\n // Convert to labelInValue type\n return valueList.map((val) => {\n let rawValue: RawValueType;\n let rawLabel: React.ReactNode;\n let rawDisabled: boolean | undefined;\n\n if (isRawValue(val)) {\n rawValue = val;\n } else {\n rawLabel = val.label;\n // @ts-ignore val.key是为了兼容存在key的情况\n rawValue = (val.value as RawValueType) ?? (val.key as RawValueType);\n }\n\n const menuItem = keyMenuItems.get(toString(rawValue));\n if (menuItem) {\n // Fill missing props\n if (rawLabel === undefined) {\n if (optionLabelProp) {\n rawLabel = menuItem[optionLabelProp] || menuItem.label;\n } else {\n rawLabel = menuItem.label;\n }\n }\n rawDisabled = menuItem.disabled;\n }\n\n return {\n label: rawLabel,\n value: rawValue,\n disabled: rawDisabled,\n };\n });\n },\n [keyMenuItems, optionLabelProp],\n );\n\n // Merged value with LabelValueType\n const rawLabeledValues = React.useMemo(() => {\n const values = convert2LabelValues(internalValue);\n\n return values;\n }, [internalValue, convert2LabelValues]);\n\n // Fill label with cache to avoid option remove\n const [mergedValues, getMixedOption] = useCache(\n rawLabeledValues,\n keyMenuItems,\n );\n\n const displayValues = React.useMemo(() => {\n // `null` need show as placeholder instead\n if (!mode && mergedValues.length === 1) {\n const firstValue = mergedValues[0];\n if (\n firstValue.value === null &&\n (firstValue.label === null || firstValue.label === undefined)\n ) {\n return [] as LabelInValueType[];\n }\n }\n\n return mergedValues.map((item) => ({\n ...item,\n label: item.label ?? item.value,\n }));\n }, [mode, mergedValues]);\n\n // =========================== Change ===========================\n const triggerChange = useCallback(\n (values: DraftValueType) => {\n const labeledValues = convert2LabelValues(values);\n setInternalValue(labeledValues);\n\n if (\n onChange &&\n // Trigger event only when value changed\n (labeledValues.length !== mergedValues.length ||\n labeledValues.some(\n (newVal, index) => mergedValues[index]?.value !== newVal?.value,\n ))\n ) {\n const returnValues = labelInValue\n ? labeledValues\n : labeledValues.map((v) => v.value);\n const returnOptions = labeledValues.map((v) =>\n injectPropsWithOption(getMixedOption(v.value)),\n );\n\n onChange(\n // Value\n multiple ? returnValues : returnValues[0],\n // Option\n multiple ? returnOptions : returnOptions[0],\n );\n }\n },\n [\n convert2LabelValues,\n setInternalValue,\n onChange,\n mergedValues,\n labelInValue,\n multiple,\n getMixedOption,\n ],\n );\n // ========================= OptionList =========================\n const triggerSelect = (\n val: RawValueType,\n selected: boolean,\n type?: DisplayInfoType,\n ) => {\n const getSelectEnt = (): [\n RawValueType | LabelInValueType,\n DefaultOptionType,\n ] => {\n const option = getMixedOption(val);\n\n return [\n labelInValue\n ? {\n label: option.label,\n value: val,\n }\n : val,\n injectPropsWithOption(option),\n ];\n };\n\n if (selected && onSelect) {\n const [wrappedValue, option] = getSelectEnt();\n onSelect(wrappedValue, option);\n } else if (!selected && onDeselect && type !== 'clear') {\n const [wrappedValue, option] = getSelectEnt();\n onDeselect(wrappedValue, option);\n }\n };\n // Used for OptionList selection\n const onOptionSelect = (val: RawValueType) => {\n // Get the original value from keyMenuItems to preserve the type (number/string)\n const menuItem = keyMenuItems.get(toString(val));\n const originalValue = menuItem?.value !== undefined ? menuItem.value : val;\n\n const selected = displayValues.find(\n (item) => toString(item.value) === toString(val),\n );\n if (isMultiple(mode)) {\n if (!selected) {\n triggerSelect(originalValue, true, 'add');\n } else {\n triggerSelect(originalValue, false, 'remove');\n }\n } else {\n triggerSelect(originalValue, true, 'add');\n }\n };\n // ======================= Display Change =======================\n // BaseSelect display values change\n const onDisplayValuesChange: BaseSelectProps['onDisplayValuesChange'] = (\n nextValues,\n info,\n ) => {\n triggerChange(nextValues);\n const { type, values } = info;\n\n if (type === 'remove' || type === 'clear') {\n values.forEach((item) => {\n triggerSelect(item.value, false, type);\n });\n }\n };\n const handleSearch = (value: string) => {\n setInnerSearchValue(value);\n if (onSearch) {\n onSearch(value);\n }\n };\n\n const selectMenu = useMemo(() => {\n return {\n ...mergedMenu,\n items: mergedMenu?.items || [],\n onClick: (menuInfo: MenuInfo) => {\n // Get the original value from keyMenuItems to preserve the type (number/string)\n const menuItem = keyMenuItems.get(menuInfo.key);\n const originalValue =\n menuItem?.value !== undefined ? menuItem.value : menuInfo.key;\n\n if (mode && isMultiple(mode)) {\n if (\n displayValues.find((item) => toString(item.value) === menuInfo.key)\n ) {\n triggerChange(\n displayValues\n .filter((item) => toString(item.value) !== menuInfo.key)\n .map((item) => item.value),\n );\n } else {\n triggerChange([...displayValues, originalValue]);\n }\n } else {\n triggerChange(originalValue);\n }\n mergedMenu?.onClick?.(menuInfo);\n },\n };\n }, [mergedMenu, mode, displayValues, triggerChange, keyMenuItems]);\n\n const displayMenu = useDisplayMenu(\n selectMenu,\n // 如果用户接管了搜索,则默认不做搜索过滤\n onSearch ? filterOption || noOpFilter : filterOption,\n innerSearchValue,\n );\n\n return (\n <BaseSelect\n {...props}\n ref={ref}\n disabled={mergedDisabled}\n displayValues={displayValues}\n onDisplayValuesChange={onDisplayValuesChange}\n setInnerSearchValue={handleSearch}\n innerSearchValue={\n searchValue === undefined ? innerSearchValue : searchValue\n }\n onOptionSelect={onOptionSelect}\n menu={selectMenu}\n displayMenu={displayMenu}\n ></BaseSelect>\n );\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Select/index.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useContext, useMemo } from 'react';\nimport {\n BaseSelectRef,\n DefaultOptionType,\n DisplayInfoType,\n DraftValueType,\n ISelectProps,\n LabelInValueType,\n RawValueType,\n} from './interface';\n\nimport useOptions, { isRawValue } from './hooks/useOptions';\nimport useMergedState from 'rc-util/es/hooks/useMergedState';\nimport { noOpFilter, toArray } from './utils/commonUtil';\nimport useCache from './hooks/useCache';\nimport BaseSelect, { BaseSelectProps, isMultiple } from './BaseSelect';\nimport { MenuInfo } from '../Menu';\nimport { injectPropsWithOption } from './utils/valueUtil';\nimport useDisplayMenu from './hooks/useDisplayMenu';\nimport { toString } from './utils/commonUtil';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport {\n createSelectOptionCollection,\n SelectOptionCollection,\n} from './components/OptionCollection';\n\nexport default forwardRef(function Select(\n props: ISelectProps,\n ref: React.Ref<BaseSelectRef>,\n) {\n const {\n value,\n defaultValue,\n mode,\n menu,\n options,\n onChange,\n onSelect,\n onSearch,\n onDeselect,\n labelInValue,\n filterOption,\n searchValue,\n optionLabelProp,\n listHeight = 256,\n disabled: customDisabled,\n showSearch,\n dropdownRender,\n } = props;\n\n // =========================== Values ===========================\n const [internalValue, setInternalValue] = useMergedState(defaultValue, {\n value,\n });\n const disabled = useContext(DisabledContext);\n const mergedDisabled = customDisabled ?? disabled;\n const parsedOptions = useOptions({\n menu,\n options,\n value: internalValue,\n optionLabelProp,\n listHeight,\n });\n const { menu: mergedMenu, keyMenuItems } = parsedOptions;\n const multiple = isMultiple(mode);\n // ============================== SearchValue ==============================\n const [innerSearchValue, setInnerSearchValue] = useMergedState<\n string | undefined\n >(undefined, {\n value: searchValue,\n });\n // ========================= Wrap Value =========================\n const convert2LabelValues = React.useCallback(\n (draftValues: DraftValueType) => {\n // Convert to array\n const valueList = toArray(draftValues);\n\n // Convert to labelInValue type\n return valueList.map((val) => {\n let rawValue: RawValueType;\n let rawLabel: React.ReactNode;\n let rawDisabled: boolean | undefined;\n\n if (isRawValue(val)) {\n rawValue = val;\n } else {\n rawLabel = val.label;\n // @ts-ignore val.key是为了兼容存在key的情况\n rawValue = (val.value as RawValueType) ?? (val.key as RawValueType);\n }\n\n const menuItem = keyMenuItems.get(toString(rawValue));\n if (menuItem) {\n // Fill missing props\n if (rawLabel === undefined) {\n if (optionLabelProp) {\n rawLabel = menuItem[optionLabelProp] || menuItem.label;\n } else {\n rawLabel = menuItem.label;\n }\n }\n rawDisabled = menuItem.disabled;\n }\n\n return {\n label: rawLabel,\n value: rawValue,\n disabled: rawDisabled,\n };\n });\n },\n [keyMenuItems, optionLabelProp],\n );\n\n // Merged value with LabelValueType\n const rawLabeledValues = React.useMemo(() => {\n const values = convert2LabelValues(internalValue);\n\n return values;\n }, [internalValue, convert2LabelValues]);\n\n // Fill label with cache to avoid option remove\n const [mergedValues, getMixedOption] = useCache(\n rawLabeledValues,\n keyMenuItems,\n );\n\n const displayValues = React.useMemo(() => {\n // `null` need show as placeholder instead\n if (!mode && mergedValues.length === 1) {\n const firstValue = mergedValues[0];\n if (\n firstValue.value === null &&\n (firstValue.label === null || firstValue.label === undefined)\n ) {\n return [] as LabelInValueType[];\n }\n }\n\n return mergedValues.map((item) => ({\n ...item,\n label: item.label ?? item.value,\n }));\n }, [mode, mergedValues]);\n\n // =========================== Change ===========================\n const triggerChange = useCallback(\n (values: DraftValueType) => {\n const labeledValues = convert2LabelValues(values);\n setInternalValue(labeledValues);\n\n if (\n onChange &&\n // Trigger event only when value changed\n (labeledValues.length !== mergedValues.length ||\n labeledValues.some(\n (newVal, index) => mergedValues[index]?.value !== newVal?.value,\n ))\n ) {\n const returnValues = labelInValue\n ? labeledValues\n : labeledValues.map((v) => v.value);\n const returnOptions = labeledValues.map((v) =>\n injectPropsWithOption(getMixedOption(v.value)),\n );\n\n onChange(\n // Value\n multiple ? returnValues : returnValues[0],\n // Option\n multiple ? returnOptions : returnOptions[0],\n );\n }\n },\n [\n convert2LabelValues,\n setInternalValue,\n onChange,\n mergedValues,\n labelInValue,\n multiple,\n getMixedOption,\n ],\n );\n // ========================= OptionList =========================\n const triggerSelect = (\n val: RawValueType,\n selected: boolean,\n type?: DisplayInfoType,\n ) => {\n const getSelectEnt = (): [\n RawValueType | LabelInValueType,\n DefaultOptionType,\n ] => {\n const option = getMixedOption(val);\n\n return [\n labelInValue\n ? {\n label: option.label,\n value: val,\n }\n : val,\n injectPropsWithOption(option),\n ];\n };\n\n if (selected && onSelect) {\n const [wrappedValue, option] = getSelectEnt();\n onSelect(wrappedValue, option);\n } else if (!selected && onDeselect && type !== 'clear') {\n const [wrappedValue, option] = getSelectEnt();\n onDeselect(wrappedValue, option);\n }\n };\n // Used for OptionList selection\n const onOptionSelect = (val: RawValueType) => {\n // Get the original value from keyMenuItems to preserve the type (number/string)\n const menuItem = keyMenuItems.get(toString(val));\n const originalValue = menuItem?.value !== undefined ? menuItem.value : val;\n\n const selected = displayValues.find(\n (item) => toString(item.value) === toString(val),\n );\n if (isMultiple(mode)) {\n if (!selected) {\n triggerSelect(originalValue, true, 'add');\n } else {\n triggerSelect(originalValue, false, 'remove');\n }\n } else {\n triggerSelect(originalValue, true, 'add');\n }\n };\n // ======================= Display Change =======================\n // BaseSelect display values change\n const onDisplayValuesChange: BaseSelectProps['onDisplayValuesChange'] = (\n nextValues,\n info,\n ) => {\n triggerChange(nextValues);\n const { type, values } = info;\n\n if (type === 'remove' || type === 'clear') {\n values.forEach((item) => {\n triggerSelect(item.value, false, type);\n });\n }\n };\n const handleSearch = (value: string) => {\n setInnerSearchValue(value);\n if (onSearch) {\n onSearch(value);\n }\n };\n\n const selectMenu = useMemo(() => {\n return {\n ...mergedMenu,\n items: mergedMenu?.items || [],\n onClick: (menuInfo: MenuInfo) => {\n // Get the original value from keyMenuItems to preserve the type (number/string)\n const menuItem = keyMenuItems.get(menuInfo.key);\n const originalValue =\n menuItem?.value !== undefined ? menuItem.value : menuInfo.key;\n\n if (mode && isMultiple(mode)) {\n if (\n displayValues.find((item) => toString(item.value) === menuInfo.key)\n ) {\n triggerChange(\n displayValues\n .filter((item) => toString(item.value) !== menuInfo.key)\n .map((item) => item.value),\n );\n } else {\n triggerChange([...displayValues, originalValue]);\n }\n } else {\n triggerChange(originalValue);\n }\n mergedMenu?.onClick?.(menuInfo);\n },\n };\n }, [mergedMenu, mode, displayValues, triggerChange, keyMenuItems]);\n\n const displayMenu = useDisplayMenu(\n selectMenu,\n // 如果用户接管了搜索,则默认不做搜索过滤\n onSearch ? filterOption || noOpFilter : filterOption,\n innerSearchValue,\n );\n\n // Flat standard options use the private collection. Menu-shaped,\n // searchable, custom popup, and nested inputs remain on the legacy path.\n const useStandardOptionCollection =\n !menu &&\n !dropdownRender &&\n !showSearch &&\n !(options || []).some((option) => option.children?.length);\n const collectionMenuItems = useMemo(() => {\n if (!showSearch) {\n return keyMenuItems;\n }\n\n const query = innerSearchValue || '';\n return new Map(\n Array.from(keyMenuItems).filter(([, option]) => {\n if (onSearch && !filterOption) {\n return true;\n }\n if (filterOption) {\n return filterOption(query, option);\n }\n return String(option.label ?? option.value)\n .toLocaleLowerCase()\n .includes(query.toLocaleLowerCase());\n }),\n );\n }, [filterOption, innerSearchValue, keyMenuItems, onSearch, showSearch]);\n const collectionId = React.useId().replace(/:/g, '');\n const optionCollection = useMemo<SelectOptionCollection | undefined>(() => {\n if (!useStandardOptionCollection) {\n return undefined;\n }\n\n return createSelectOptionCollection(\n `ald-select-listbox-${collectionId}`,\n collectionMenuItems,\n );\n }, [collectionId, collectionMenuItems, useStandardOptionCollection]);\n\n const onCollectionOptionSelect = useCallback(\n (value: RawValueType) => {\n const menuItem = keyMenuItems.get(toString(value));\n const originalValue =\n menuItem?.value !== undefined ? menuItem.value : value;\n\n const selected = displayValues.some(\n (item) => toString(item.value) === toString(originalValue),\n );\n if (multiple) {\n triggerChange(\n selected\n ? displayValues\n .filter(\n (item) => toString(item.value) !== toString(originalValue),\n )\n .map((item) => item.value)\n : [...displayValues.map((item) => item.value), originalValue],\n );\n } else {\n triggerChange(originalValue);\n }\n onOptionSelect(originalValue);\n },\n [displayValues, keyMenuItems, multiple, onOptionSelect, triggerChange],\n );\n\n return (\n <BaseSelect\n {...props}\n ref={ref}\n disabled={mergedDisabled}\n displayValues={displayValues}\n onDisplayValuesChange={onDisplayValuesChange}\n setInnerSearchValue={handleSearch}\n innerSearchValue={\n searchValue === undefined ? innerSearchValue : searchValue\n }\n onOptionSelect={onOptionSelect}\n menu={selectMenu}\n displayMenu={displayMenu}\n optionCollection={optionCollection}\n onCollectionOptionSelect={onCollectionOptionSelect}\n ></BaseSelect>\n );\n});\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { PlacementType } from '../Dropdown';
2
2
  import { ItemType, MenuDividerType, MenuHeaderType, MenuProps, SubMenuType } from '../Menu';
3
3
  import { CustomTagProps, Mode } from './BaseSelect.js';
4
4
  type ArrayElementType<T> = T extends (infer E)[] ? E : T;
5
- export interface ISelectProps<ValueType = any, OptionType extends BaseOptionType = DefaultOptionType> {
5
+ export interface ISelectProps<ValueType = any, OptionType extends BaseOptionType = DefaultOptionType> extends React.AriaAttributes {
6
6
  prefix?: React.ReactNode;
7
7
  size?: 'small' | 'middle' | 'large';
8
8
  mode?: Mode;
@@ -26,7 +26,7 @@ var INPUT_SIZE_MAP = {
26
26
  default: 32,
27
27
  large: 40
28
28
  };
29
- var SKELETON_BACKGROUND_COLOR = "var(--alias-colors-bg-skeleton-subtle, var(--background-neutral-subtle, #e5e7eb))";
29
+ var SKELETON_BACKGROUND_COLOR = "var(--background-neutral-surface)";
30
30
  var SkeletonButton = ({ active, size = "default", shape = "square", block, className, style }) => {
31
31
  const animClass = active ? "tw-animate-pulse" : "";
32
32
  const dims = BUTTON_SIZE_MAP[size];
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Skeleton/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface SkeletonProps {\n active?: boolean;\n loading?: boolean;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n avatar?:\n | boolean\n | {\n size?: number | 'small' | 'default' | 'large';\n shape?: 'circle' | 'square';\n };\n title?: boolean | { width?: number | string };\n paragraph?:\n | boolean\n | { rows?: number; width?: number | string | (number | string)[] };\n round?: boolean;\n}\n\n// --- Shared types for sub-components ---\n\ntype SkeletonElementSize = 'small' | 'default' | 'large';\n\ninterface SkeletonElementBaseProps {\n active?: boolean;\n size?: SkeletonElementSize;\n className?: string;\n style?: React.CSSProperties;\n}\n\ninterface SkeletonButtonProps extends SkeletonElementBaseProps {\n shape?: 'circle' | 'round' | 'square';\n block?: boolean;\n}\n\ninterface SkeletonAvatarProps extends SkeletonElementBaseProps {\n shape?: 'circle' | 'square';\n}\n\ninterface SkeletonInputProps extends SkeletonElementBaseProps {\n block?: boolean;\n}\n\ninterface SkeletonImageProps {\n active?: boolean;\n className?: string;\n style?: React.CSSProperties;\n}\n\n// --- Size maps ---\n\nconst BUTTON_SIZE_MAP: Record<\n SkeletonElementSize,\n { width: number; height: number }\n> = {\n small: { width: 64, height: 24 },\n default: { width: 80, height: 32 },\n large: { width: 96, height: 40 },\n};\n\nconst AVATAR_SIZE_MAP: Record<SkeletonElementSize, number> = {\n small: 24,\n default: 32,\n large: 40,\n};\n\nconst INPUT_SIZE_MAP: Record<SkeletonElementSize, number> = {\n small: 24,\n default: 32,\n large: 40,\n};\n\nconst SKELETON_BACKGROUND_COLOR =\n 'var(--alias-colors-bg-skeleton-subtle, var(--background-neutral-subtle, #e5e7eb))';\n\n// --- Sub-components ---\n\nconst SkeletonButton: React.FC<SkeletonButtonProps> = ({\n active,\n size = 'default',\n shape = 'square',\n block,\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n const dims = BUTTON_SIZE_MAP[size];\n\n const borderRadius =\n shape === 'circle'\n ? '50%'\n : shape === 'round'\n ? `${dims.height / 2}px`\n : '4px';\n\n return (\n <span\n className={cn(\n 'ald-skeleton-button tw-inline-block tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n block && 'tw-block tw-w-full',\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width:\n shape === 'circle' ? dims.height : block ? undefined : dims.width,\n height: dims.height,\n borderRadius,\n ...style,\n }}\n />\n );\n};\n\nconst SkeletonAvatar: React.FC<SkeletonAvatarProps> = ({\n active,\n size = 'default',\n shape = 'circle',\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n const dim = typeof size === 'number' ? size : AVATAR_SIZE_MAP[size];\n\n return (\n <span\n className={cn(\n 'ald-skeleton-avatar tw-inline-block tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: dim,\n height: dim,\n borderRadius: shape === 'circle' ? '50%' : '4px',\n ...style,\n }}\n />\n );\n};\n\nconst SkeletonInput: React.FC<SkeletonInputProps> = ({\n active,\n size = 'default',\n block,\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n const height = INPUT_SIZE_MAP[size];\n\n return (\n <span\n className={cn(\n 'ald-skeleton-input tw-inline-block tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n block && 'tw-block tw-w-full',\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: block ? undefined : 200,\n height,\n borderRadius: 4,\n ...style,\n }}\n />\n );\n};\n\nconst SkeletonImage: React.FC<SkeletonImageProps> = ({\n active,\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n\n return (\n <span\n className={cn(\n 'ald-skeleton-image tw-flex tw-items-center tw-justify-center tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: 96,\n height: 96,\n borderRadius: 4,\n ...style,\n }}\n >\n <svg\n viewBox=\"0 0 1098 1024\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"48\"\n height=\"48\"\n fill=\"currentColor\"\n style={{ opacity: 0.2 }}\n >\n <path d=\"M365.714 329.143q0 45.714-32.036 77.75t-77.75 32.036-77.75-32.036-32.036-77.75 32.036-77.75 77.75-32.036 77.75 32.036 32.036 77.75zM950.857 548.571v256H146.286V694.857l182.857-182.857 91.429 91.429 292.571-292.571zM1005.714 146.286H91.429q-7.46 0-12.873 5.413T73.143 164.571v694.857q0 7.46 5.413 12.873t12.873 5.413h914.286q7.46 0 12.873-5.413t5.413-12.873V164.571q0-7.46-5.413-12.873t-12.873-5.413zm91.429 18.286v694.857q0 37.714-26.857 64.571t-64.571 26.857H91.429q-37.714 0-64.571-26.857T0 859.429V164.571q0-37.714 26.857-64.571T91.429 73.143h914.286q37.714 0 64.571 26.857t26.857 64.571z\" />\n </svg>\n </span>\n );\n};\n\n// --- Main Skeleton component ---\n\nfunction Skeleton(props: SkeletonProps) {\n const {\n active = false,\n loading = true,\n className,\n style,\n children,\n avatar,\n title = true,\n paragraph = true,\n round,\n } = props;\n\n if (!loading) {\n return <>{children}</>;\n }\n\n const animClass = active ? 'tw-animate-pulse' : '';\n const rows =\n typeof paragraph === 'object' ? paragraph.rows || 3 : paragraph ? 3 : 0;\n\n return (\n <div\n className={cn('ald-skeleton tw-flex tw-gap-4', className)}\n style={style}\n >\n {avatar && (\n <div\n className={cn(\n 'ald-skeleton-avatar tw-shrink-0 tw-rounded-full tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n typeof avatar === 'object' && avatar.shape === 'square'\n ? 'tw-rounded-r-50'\n : 'tw-rounded-full',\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: 40,\n height: 40,\n }}\n />\n )}\n <div className=\"ald-skeleton-content tw-flex-1\">\n {title && (\n <div\n className={cn(\n 'ald-skeleton-title tw-mb-4 tw-h-4 tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n round ? 'tw-rounded-full' : 'tw-rounded-r-25',\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: typeof title === 'object' ? title.width : '38%',\n }}\n />\n )}\n {paragraph &&\n Array.from({ length: rows }).map((_, i) => (\n <div\n key={i}\n className={cn(\n 'ald-skeleton-paragraph tw-mb-3 tw-h-4 tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n round ? 'tw-rounded-full' : 'tw-rounded-r-25',\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: i === rows - 1 ? '61%' : '100%',\n }}\n />\n ))}\n </div>\n </div>\n );\n}\n\nfunction SkeletonNode({\n active,\n className,\n style,\n children,\n}: {\n active?: boolean;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n}) {\n return (\n <div\n className={cn(\n 'ald-skeleton-node tw-inline-flex tw-items-center tw-justify-center tw-rounded-r-25 tw-bg-[var(--background-neutral-subtle)]',\n active && 'tw-animate-pulse',\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n ...style,\n }}\n >\n {children}\n </div>\n );\n}\n\n// Attach sub-components\nSkeleton.Button = SkeletonButton;\nSkeleton.Avatar = SkeletonAvatar;\nSkeleton.Input = SkeletonInput;\nSkeleton.Image = SkeletonImage;\nSkeleton.Node = SkeletonNode;\n\nexport default Skeleton;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Skeleton/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface SkeletonProps {\n active?: boolean;\n loading?: boolean;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n avatar?:\n | boolean\n | {\n size?: number | 'small' | 'default' | 'large';\n shape?: 'circle' | 'square';\n };\n title?: boolean | { width?: number | string };\n paragraph?:\n | boolean\n | { rows?: number; width?: number | string | (number | string)[] };\n round?: boolean;\n}\n\n// --- Shared types for sub-components ---\n\ntype SkeletonElementSize = 'small' | 'default' | 'large';\n\ninterface SkeletonElementBaseProps {\n active?: boolean;\n size?: SkeletonElementSize;\n className?: string;\n style?: React.CSSProperties;\n}\n\ninterface SkeletonButtonProps extends SkeletonElementBaseProps {\n shape?: 'circle' | 'round' | 'square';\n block?: boolean;\n}\n\ninterface SkeletonAvatarProps extends SkeletonElementBaseProps {\n shape?: 'circle' | 'square';\n}\n\ninterface SkeletonInputProps extends SkeletonElementBaseProps {\n block?: boolean;\n}\n\ninterface SkeletonImageProps {\n active?: boolean;\n className?: string;\n style?: React.CSSProperties;\n}\n\n// --- Size maps ---\n\nconst BUTTON_SIZE_MAP: Record<\n SkeletonElementSize,\n { width: number; height: number }\n> = {\n small: { width: 64, height: 24 },\n default: { width: 80, height: 32 },\n large: { width: 96, height: 40 },\n};\n\nconst AVATAR_SIZE_MAP: Record<SkeletonElementSize, number> = {\n small: 24,\n default: 32,\n large: 40,\n};\n\nconst INPUT_SIZE_MAP: Record<SkeletonElementSize, number> = {\n small: 24,\n default: 32,\n large: 40,\n};\n\nconst SKELETON_BACKGROUND_COLOR = 'var(--background-neutral-surface)';\n\n// --- Sub-components ---\n\nconst SkeletonButton: React.FC<SkeletonButtonProps> = ({\n active,\n size = 'default',\n shape = 'square',\n block,\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n const dims = BUTTON_SIZE_MAP[size];\n\n const borderRadius =\n shape === 'circle'\n ? '50%'\n : shape === 'round'\n ? `${dims.height / 2}px`\n : '4px';\n\n return (\n <span\n className={cn(\n 'ald-skeleton-button tw-inline-block tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n block && 'tw-block tw-w-full',\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width:\n shape === 'circle' ? dims.height : block ? undefined : dims.width,\n height: dims.height,\n borderRadius,\n ...style,\n }}\n />\n );\n};\n\nconst SkeletonAvatar: React.FC<SkeletonAvatarProps> = ({\n active,\n size = 'default',\n shape = 'circle',\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n const dim = typeof size === 'number' ? size : AVATAR_SIZE_MAP[size];\n\n return (\n <span\n className={cn(\n 'ald-skeleton-avatar tw-inline-block tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: dim,\n height: dim,\n borderRadius: shape === 'circle' ? '50%' : '4px',\n ...style,\n }}\n />\n );\n};\n\nconst SkeletonInput: React.FC<SkeletonInputProps> = ({\n active,\n size = 'default',\n block,\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n const height = INPUT_SIZE_MAP[size];\n\n return (\n <span\n className={cn(\n 'ald-skeleton-input tw-inline-block tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n block && 'tw-block tw-w-full',\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: block ? undefined : 200,\n height,\n borderRadius: 4,\n ...style,\n }}\n />\n );\n};\n\nconst SkeletonImage: React.FC<SkeletonImageProps> = ({\n active,\n className,\n style,\n}) => {\n const animClass = active ? 'tw-animate-pulse' : '';\n\n return (\n <span\n className={cn(\n 'ald-skeleton-image tw-flex tw-items-center tw-justify-center tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: 96,\n height: 96,\n borderRadius: 4,\n ...style,\n }}\n >\n <svg\n viewBox=\"0 0 1098 1024\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"48\"\n height=\"48\"\n fill=\"currentColor\"\n style={{ opacity: 0.2 }}\n >\n <path d=\"M365.714 329.143q0 45.714-32.036 77.75t-77.75 32.036-77.75-32.036-32.036-77.75 32.036-77.75 77.75-32.036 77.75 32.036 32.036 77.75zM950.857 548.571v256H146.286V694.857l182.857-182.857 91.429 91.429 292.571-292.571zM1005.714 146.286H91.429q-7.46 0-12.873 5.413T73.143 164.571v694.857q0 7.46 5.413 12.873t12.873 5.413h914.286q7.46 0 12.873-5.413t5.413-12.873V164.571q0-7.46-5.413-12.873t-12.873-5.413zm91.429 18.286v694.857q0 37.714-26.857 64.571t-64.571 26.857H91.429q-37.714 0-64.571-26.857T0 859.429V164.571q0-37.714 26.857-64.571T91.429 73.143h914.286q37.714 0 64.571 26.857t26.857 64.571z\" />\n </svg>\n </span>\n );\n};\n\n// --- Main Skeleton component ---\n\nfunction Skeleton(props: SkeletonProps) {\n const {\n active = false,\n loading = true,\n className,\n style,\n children,\n avatar,\n title = true,\n paragraph = true,\n round,\n } = props;\n\n if (!loading) {\n return <>{children}</>;\n }\n\n const animClass = active ? 'tw-animate-pulse' : '';\n const rows =\n typeof paragraph === 'object' ? paragraph.rows || 3 : paragraph ? 3 : 0;\n\n return (\n <div\n className={cn('ald-skeleton tw-flex tw-gap-4', className)}\n style={style}\n >\n {avatar && (\n <div\n className={cn(\n 'ald-skeleton-avatar tw-shrink-0 tw-rounded-full tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n typeof avatar === 'object' && avatar.shape === 'square'\n ? 'tw-rounded-r-50'\n : 'tw-rounded-full',\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: 40,\n height: 40,\n }}\n />\n )}\n <div className=\"ald-skeleton-content tw-flex-1\">\n {title && (\n <div\n className={cn(\n 'ald-skeleton-title tw-mb-4 tw-h-4 tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n round ? 'tw-rounded-full' : 'tw-rounded-r-25',\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: typeof title === 'object' ? title.width : '38%',\n }}\n />\n )}\n {paragraph &&\n Array.from({ length: rows }).map((_, i) => (\n <div\n key={i}\n className={cn(\n 'ald-skeleton-paragraph tw-mb-3 tw-h-4 tw-bg-[var(--background-neutral-subtle)]',\n animClass,\n round ? 'tw-rounded-full' : 'tw-rounded-r-25',\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n width: i === rows - 1 ? '61%' : '100%',\n }}\n />\n ))}\n </div>\n </div>\n );\n}\n\nfunction SkeletonNode({\n active,\n className,\n style,\n children,\n}: {\n active?: boolean;\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n}) {\n return (\n <div\n className={cn(\n 'ald-skeleton-node tw-inline-flex tw-items-center tw-justify-center tw-rounded-r-25 tw-bg-[var(--background-neutral-subtle)]',\n active && 'tw-animate-pulse',\n className,\n )}\n style={{\n backgroundColor: SKELETON_BACKGROUND_COLOR,\n ...style,\n }}\n >\n {children}\n </div>\n );\n}\n\n// Attach sub-components\nSkeleton.Button = SkeletonButton;\nSkeleton.Avatar = SkeletonAvatar;\nSkeleton.Input = SkeletonInput;\nSkeleton.Image = SkeletonImage;\nSkeleton.Node = SkeletonNode;\n\nexport default Skeleton;\n"],"mappings":"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"}
@@ -10,5 +10,5 @@ export interface SpinProps {
10
10
  className?: string;
11
11
  style?: React.CSSProperties;
12
12
  }
13
- declare function CustomSpin(props: SpinProps): import("react/jsx-runtime").JSX.Element | null;
13
+ declare function CustomSpin(props: SpinProps): import("react/jsx-runtime").JSX.Element;
14
14
  export default CustomSpin;
@@ -2,15 +2,22 @@ import { cn } from "../lib/utils.js";
2
2
  import { cloneElement as cloneElement$1, isFragment, isReactComponent } from "../_utils/reactNode.js";
3
3
  import Icon from "./CustomIcon/index.js";
4
4
  import React, { isValidElement } from "react";
5
+ import { jsx } from "react/jsx-runtime";
5
6
  //#region src/Spin/index.tsx
6
7
  function CustomSpin(props) {
7
8
  const { size, tip, direction = "vertical", children, spinning, wrapperClassName, className, style } = props;
8
- if (!children) return Icon({
9
- size,
10
- tip,
11
- direction,
12
- spinning,
13
- className
9
+ if (!children) return /* @__PURE__ */ jsx("span", {
10
+ role: "status",
11
+ "aria-live": "polite",
12
+ "aria-busy": spinning,
13
+ "aria-label": typeof tip === "string" ? tip : "Loading",
14
+ children: Icon({
15
+ size,
16
+ tip,
17
+ direction,
18
+ spinning,
19
+ className
20
+ })
14
21
  });
15
22
  if (!isValidElement(children)) return children;
16
23
  if (isFragment(children) || isReactComponent(children)) return React.createElement("div", {
@@ -18,7 +25,11 @@ function CustomSpin(props) {
18
25
  ...style,
19
26
  position: "relative"
20
27
  },
21
- className: cn(wrapperClassName)
28
+ className: cn(wrapperClassName),
29
+ role: "status",
30
+ "aria-live": "polite",
31
+ "aria-busy": spinning,
32
+ "aria-label": typeof tip === "string" ? tip : "Loading"
22
33
  }, [children, Icon({
23
34
  size,
24
35
  tip,
@@ -33,6 +44,10 @@ function CustomSpin(props) {
33
44
  ...children.props.style
34
45
  },
35
46
  className: cn(wrapperClassName, children.props.className),
47
+ role: "status",
48
+ "aria-live": "polite",
49
+ "aria-busy": spinning,
50
+ "aria-label": typeof tip === "string" ? tip : "Loading",
36
51
  children: [children.props.children, Icon({
37
52
  size,
38
53
  tip,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Spin/index.tsx"],"sourcesContent":["import { cn } from '../lib/utils';\nimport React, { ReactElement, isValidElement } from 'react';\nimport {\n cloneElement,\n isFragment,\n isReactComponent,\n} from '../_utils/reactNode';\nimport CustomIcon from './CustomIcon';\n\nexport type TDirection = 'vertical' | 'horizontal';\n\nexport interface SpinProps {\n size?: 'small' | 'large' | 'middle';\n direction?: TDirection;\n children?: React.ReactElement;\n tip?: React.ReactNode;\n spinning?: boolean;\n wrapperClassName?: string;\n className?: string;\n style?: React.CSSProperties;\n}\nfunction CustomSpin(props: SpinProps) {\n const {\n size,\n tip,\n direction = 'vertical',\n children,\n spinning,\n wrapperClassName,\n className,\n style,\n } = props;\n if (!children) {\n return CustomIcon({ size, tip, direction, spinning, className });\n }\n if (!isValidElement(children)) {\n return children;\n }\n if (isFragment(children) || isReactComponent(children)) {\n return React.createElement(\n 'div',\n {\n style: { ...style, position: 'relative' },\n className: cn(wrapperClassName),\n },\n [\n children,\n CustomIcon({\n size,\n tip,\n direction,\n inContainer: true,\n spinning,\n className,\n }),\n ],\n );\n } else {\n return cloneElement(children, {\n style: {\n position: 'relative',\n ...(children as ReactElement).props.style,\n },\n className: cn(\n wrapperClassName,\n (children as ReactElement).props.className,\n ),\n children: [\n (children as ReactElement).props.children,\n CustomIcon({\n size,\n tip,\n direction,\n spinning,\n inContainer: true,\n className,\n }),\n ],\n });\n }\n}\nexport default CustomSpin;\n"],"mappings":";;;;;AAqBA,SAAS,WAAW,OAAkB;CACpC,MAAM,EACJ,MACA,KACA,YAAY,YACZ,UACA,UACA,kBACA,WACA,UACE;AACJ,KAAI,CAAC,SACH,QAAO,KAAW;EAAE;EAAM;EAAK;EAAW;EAAU;EAAW,CAAC;AAElE,KAAI,CAAC,eAAe,SAAS,CAC3B,QAAO;AAET,KAAI,WAAW,SAAS,IAAI,iBAAiB,SAAS,CACpD,QAAO,MAAM,cACX,OACA;EACE,OAAO;GAAE,GAAG;GAAO,UAAU;GAAY;EACzC,WAAW,GAAG,iBAAiB;EAChC,EACD,CACE,UACA,KAAW;EACT;EACA;EACA;EACA,aAAa;EACb;EACA;EACD,CAAC,CACH,CACF;KAED,QAAO,eAAa,UAAU;EAC5B,OAAO;GACL,UAAU;GACV,GAAI,SAA0B,MAAM;GACrC;EACD,WAAW,GACT,kBACC,SAA0B,MAAM,UAClC;EACD,UAAU,CACP,SAA0B,MAAM,UACjC,KAAW;GACT;GACA;GACA;GACA;GACA,aAAa;GACb;GACD,CAAC,CACH;EACF,CAAC"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Spin/index.tsx"],"sourcesContent":["import { cn } from '../lib/utils';\nimport React, { ReactElement, isValidElement } from 'react';\nimport {\n cloneElement,\n isFragment,\n isReactComponent,\n} from '../_utils/reactNode';\nimport CustomIcon from './CustomIcon';\n\nexport type TDirection = 'vertical' | 'horizontal';\n\nexport interface SpinProps {\n size?: 'small' | 'large' | 'middle';\n direction?: TDirection;\n children?: React.ReactElement;\n tip?: React.ReactNode;\n spinning?: boolean;\n wrapperClassName?: string;\n className?: string;\n style?: React.CSSProperties;\n}\nfunction CustomSpin(props: SpinProps) {\n const {\n size,\n tip,\n direction = 'vertical',\n children,\n spinning,\n wrapperClassName,\n className,\n style,\n } = props;\n if (!children) {\n return (\n <span\n role=\"status\"\n aria-live=\"polite\"\n aria-busy={spinning}\n aria-label={typeof tip === 'string' ? tip : 'Loading'}\n >\n {CustomIcon({ size, tip, direction, spinning, className })}\n </span>\n );\n }\n if (!isValidElement(children)) {\n return children;\n }\n if (isFragment(children) || isReactComponent(children)) {\n return React.createElement(\n 'div',\n {\n style: { ...style, position: 'relative' },\n className: cn(wrapperClassName),\n role: 'status',\n 'aria-live': 'polite',\n 'aria-busy': spinning,\n 'aria-label': typeof tip === 'string' ? tip : 'Loading',\n },\n [\n children,\n CustomIcon({\n size,\n tip,\n direction,\n inContainer: true,\n spinning,\n className,\n }),\n ],\n );\n } else {\n return cloneElement(children, {\n style: {\n position: 'relative',\n ...(children as ReactElement).props.style,\n },\n className: cn(\n wrapperClassName,\n (children as ReactElement).props.className,\n ),\n role: 'status',\n 'aria-live': 'polite',\n 'aria-busy': spinning,\n 'aria-label': typeof tip === 'string' ? tip : 'Loading',\n children: [\n (children as ReactElement).props.children,\n CustomIcon({\n size,\n tip,\n direction,\n spinning,\n inContainer: true,\n className,\n }),\n ],\n });\n }\n}\nexport default CustomSpin;\n"],"mappings":";;;;;;AAqBA,SAAS,WAAW,OAAkB;CACpC,MAAM,EACJ,MACA,KACA,YAAY,YACZ,UACA,UACA,kBACA,WACA,UACE;AACJ,KAAI,CAAC,SACH,QACE,oBAAC,QAAD;EACE,MAAK;EACL,aAAU;EACV,aAAW;EACX,cAAY,OAAO,QAAQ,WAAW,MAAM;YAE3C,KAAW;GAAE;GAAM;GAAK;GAAW;GAAU;GAAW,CAAC;EACrD,CAAA;AAGX,KAAI,CAAC,eAAe,SAAS,CAC3B,QAAO;AAET,KAAI,WAAW,SAAS,IAAI,iBAAiB,SAAS,CACpD,QAAO,MAAM,cACX,OACA;EACE,OAAO;GAAE,GAAG;GAAO,UAAU;GAAY;EACzC,WAAW,GAAG,iBAAiB;EAC/B,MAAM;EACN,aAAa;EACb,aAAa;EACb,cAAc,OAAO,QAAQ,WAAW,MAAM;EAC/C,EACD,CACE,UACA,KAAW;EACT;EACA;EACA;EACA,aAAa;EACb;EACA;EACD,CAAC,CACH,CACF;KAED,QAAO,eAAa,UAAU;EAC5B,OAAO;GACL,UAAU;GACV,GAAI,SAA0B,MAAM;GACrC;EACD,WAAW,GACT,kBACC,SAA0B,MAAM,UAClC;EACD,MAAM;EACN,aAAa;EACb,aAAa;EACb,cAAc,OAAO,QAAQ,WAAW,MAAM;EAC9C,UAAU,CACP,SAA0B,MAAM,UACjC,KAAW;GACT;GACA;GACA;GACA;GACA,aAAa;GACb;GACD,CAAC,CACH;EACF,CAAC"}
@@ -16,6 +16,11 @@ export interface ISwitchProps {
16
16
  'data-testid'?: string;
17
17
  /** 透传到内部 switch 按钮元素的 aria-label,用于可访问性与自动化测试定位 */
18
18
  'aria-label'?: string;
19
+ 'aria-labelledby'?: string;
20
+ 'aria-describedby'?: string;
21
+ 'aria-invalid'?: React.AriaAttributes['aria-invalid'];
22
+ 'aria-required'?: React.AriaAttributes['aria-required'];
23
+ 'aria-busy'?: React.AriaAttributes['aria-busy'];
19
24
  }
20
25
  declare const Switch: React.FC<ISwitchProps>;
21
26
  export default Switch;
@@ -1,7 +1,8 @@
1
1
  import { cn } from "../lib/utils.js";
2
2
  import DisabledContext from "../ConfigProvider/DisabledContext.js";
3
3
  import SizeContext from "../ConfigProvider/sizeContext.js";
4
- import { useContext, useEffect, useState } from "react";
4
+ import { getSemanticOwnerAriaProps } from "../_utils/formControlSemanticOwner.js";
5
+ import React, { useContext, useEffect, useState } from "react";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
7
  //#region src/Switch/index.tsx
7
8
  var switchSizeConfig = {
@@ -21,10 +22,11 @@ var switchSizeConfig = {
21
22
  thumbSize: 8
22
23
  }
23
24
  };
24
- var Switch = ({ className = "", disabled: customDisabled, loading = false, size: customSize, checked, defaultChecked, onChange, onClick, children, "data-testid": dataTestid, "aria-label": ariaLabel }) => {
25
+ var Switch = ({ className = "", disabled: customDisabled, loading = false, size: customSize, checked, defaultChecked, onChange, onClick, children, "data-testid": dataTestid, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid, "aria-required": ariaRequired, "aria-busy": ariaBusy }) => {
25
26
  const contentSize = useContext(SizeContext);
26
27
  const size = customSize || contentSize || "middle";
27
28
  const [userChecked, setUserChecked] = useState(typeof checked === "undefined" ? defaultChecked : checked);
29
+ const switchLabelId = React.useId();
28
30
  const disabled = useContext(DisabledContext);
29
31
  const currentDisabled = loading ? true : customDisabled ?? disabled;
30
32
  useEffect(() => {
@@ -40,6 +42,7 @@ var Switch = ({ className = "", disabled: customDisabled, loading = false, size:
40
42
  const { trackW, trackH, thumbSize } = switchSizeConfig[size];
41
43
  const thumbOffset = 2;
42
44
  const thumbTranslate = trackW - thumbSize - thumbOffset * 2;
45
+ const generatedLabelledBy = ariaLabelledBy || (!ariaLabel && children != null ? switchLabelId : void 0);
43
46
  return /* @__PURE__ */ jsxs("span", {
44
47
  className: cn(className, "ald-switch tw-inline-flex tw-items-center tw-gap-1.5 tw-text-[0]", `ald-switch-${size}`, currentDisabled && "tw-pointer-events-none tw-cursor-default", {
45
48
  "ald-switch-disabled": currentDisabled,
@@ -49,9 +52,15 @@ var Switch = ({ className = "", disabled: customDisabled, loading = false, size:
49
52
  type: "button",
50
53
  role: "switch",
51
54
  "aria-checked": !!userChecked,
52
- "aria-busy": loading || void 0,
53
55
  "data-testid": dataTestid,
54
- "aria-label": ariaLabel,
56
+ ...getSemanticOwnerAriaProps({
57
+ "aria-label": ariaLabel,
58
+ "aria-labelledby": generatedLabelledBy,
59
+ "aria-describedby": ariaDescribedBy,
60
+ "aria-invalid": ariaInvalid,
61
+ "aria-required": ariaRequired,
62
+ "aria-busy": loading || ariaBusy || void 0
63
+ }),
55
64
  disabled: currentDisabled,
56
65
  className: cn("ald-switch-btn tw-relative tw-inline-flex tw-cursor-pointer tw-items-center tw-rounded-full tw-border-0 tw-p-0 tw-transition-colors tw-duration-200", userChecked ? "tw-bg-[var(--control-state-selected)]" : "tw-bg-[var(--control-state-unselected)]", !currentDisabled && [
57
66
  "focus-visible:tw-shadow-[0_0_0_2px_var(--focus-ring)]",
@@ -66,7 +75,7 @@ var Switch = ({ className = "", disabled: customDisabled, loading = false, size:
66
75
  },
67
76
  onClick: handleClick,
68
77
  children: /* @__PURE__ */ jsx("span", {
69
- className: cn("tw-block tw-rounded-full tw-bg-[var(--background-default)] tw-shadow-sm tw-transition-transform tw-duration-200"),
78
+ className: cn("tw-block tw-rounded-full tw-bg-[var(--background-default)] tw-shadow-[var(--elevation-bottom-bottom-sm)] tw-transition-transform tw-duration-200"),
70
79
  style: {
71
80
  width: thumbSize,
72
81
  height: thumbSize,
@@ -75,6 +84,7 @@ var Switch = ({ className = "", disabled: customDisabled, loading = false, size:
75
84
  }
76
85
  })
77
86
  }), children && /* @__PURE__ */ jsx("span", {
87
+ id: generatedLabelledBy === switchLabelId ? switchLabelId : void 0,
78
88
  className: cn("ald-switch-text tw-inline-flex tw-items-center tw-align-middle tw-text-[var(--content-primary)]", size === "large" && "tw-h-5 tw-text-base tw-leading-5", size === "middle" && "tw-h-4 tw-text-sm tw-leading-4", size === "small" && "tw-h-3 tw-text-xs tw-leading-3", currentDisabled && "tw-opacity-50"),
79
89
  children
80
90
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Switch/index.tsx"],"sourcesContent":["import React, { useContext, useEffect, useState } from 'react';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport SizeContext from '../ConfigProvider/sizeContext';\nimport { cn } from '../lib/utils';\n\nexport type SwitchChangeEventHandler = (\n checked: boolean,\n event: React.MouseEvent<HTMLButtonElement>,\n) => void;\nexport type SwitchClickEventHandler = SwitchChangeEventHandler;\nexport type SwitchSize = 'large' | 'middle' | 'small';\n\nexport interface ISwitchProps {\n className?: string;\n checked?: boolean;\n defaultChecked?: boolean;\n disabled?: boolean;\n loading?: boolean;\n size?: SwitchSize;\n onClick?: SwitchChangeEventHandler;\n onChange?: SwitchChangeEventHandler;\n children?: React.ReactNode;\n /** 透传到内部 switch 按钮元素的 data-testid,用于自动化测试定位 */\n 'data-testid'?: string;\n /** 透传到内部 switch 按钮元素的 aria-label,用于可访问性与自动化测试定位 */\n 'aria-label'?: string;\n}\n\nconst switchSizeConfig: Record<\n SwitchSize,\n {\n trackW: number;\n trackH: number;\n thumbSize: number;\n }\n> = {\n large: {\n trackW: 36,\n trackH: 20,\n thumbSize: 16,\n },\n middle: {\n trackW: 28,\n trackH: 16,\n thumbSize: 12,\n },\n small: {\n trackW: 22,\n trackH: 12,\n thumbSize: 8,\n },\n};\n\nconst Switch: React.FC<ISwitchProps> = ({\n className = '',\n disabled: customDisabled,\n loading = false,\n size: customSize,\n checked,\n defaultChecked,\n onChange,\n onClick,\n children,\n 'data-testid': dataTestid,\n 'aria-label': ariaLabel,\n}) => {\n const contentSize = useContext(SizeContext);\n const size = customSize || contentSize || 'middle';\n\n const [userChecked, setUserChecked] = useState(\n typeof checked === 'undefined' ? defaultChecked : checked,\n );\n\n const disabled = useContext(DisabledContext);\n const mergedDisabled = customDisabled ?? disabled;\n\n const currentDisabled = loading ? true : mergedDisabled;\n\n useEffect(() => {\n if (typeof checked === 'boolean') {\n setUserChecked(checked);\n }\n }, [checked]);\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n if (currentDisabled) return;\n const newChecked = !userChecked;\n if (checked === undefined) {\n setUserChecked(newChecked);\n }\n onChange?.(newChecked, e);\n onClick?.(newChecked, e);\n };\n\n const { trackW, trackH, thumbSize } = switchSizeConfig[size];\n const thumbOffset = 2;\n const thumbTranslate = trackW - thumbSize - thumbOffset * 2;\n\n return (\n <span\n className={cn(\n className,\n 'ald-switch tw-inline-flex tw-items-center tw-gap-1.5 tw-text-[0]',\n `ald-switch-${size}`,\n currentDisabled && 'tw-pointer-events-none tw-cursor-default',\n {\n 'ald-switch-disabled': currentDisabled,\n 'ald-switch-checked': userChecked,\n },\n )}\n >\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={!!userChecked}\n aria-busy={loading || undefined}\n data-testid={dataTestid}\n aria-label={ariaLabel}\n disabled={currentDisabled}\n className={cn(\n 'ald-switch-btn tw-relative tw-inline-flex tw-cursor-pointer tw-items-center tw-rounded-full tw-border-0 tw-p-0 tw-transition-colors tw-duration-200',\n userChecked\n ? 'tw-bg-[var(--control-state-selected)]'\n : 'tw-bg-[var(--control-state-unselected)]',\n // Focus is an independent layer on the interactive button. The\n // selected/unselected Control State Color contract remains intact.\n !currentDisabled && [\n 'focus-visible:tw-shadow-[0_0_0_2px_var(--focus-ring)]',\n 'forced-colors:focus-visible:tw-outline',\n 'forced-colors:focus-visible:tw-outline-2',\n 'forced-colors:focus-visible:tw-outline-offset-2',\n 'forced-colors:focus-visible:tw-outline-[Highlight]',\n ],\n currentDisabled && 'tw-cursor-not-allowed tw-opacity-40',\n )}\n style={{ width: trackW, height: trackH }}\n onClick={handleClick}\n >\n <span\n className={cn(\n 'tw-block tw-rounded-full tw-bg-[var(--background-default)] tw-shadow-sm tw-transition-transform tw-duration-200',\n )}\n style={{\n width: thumbSize,\n height: thumbSize,\n marginLeft: thumbOffset,\n transform: userChecked\n ? `translateX(${thumbTranslate}px)`\n : 'translateX(0)',\n }}\n />\n </button>\n {children && (\n <span\n className={cn(\n 'ald-switch-text tw-inline-flex tw-items-center tw-align-middle tw-text-[var(--content-primary)]',\n size === 'large' && 'tw-h-5 tw-text-base tw-leading-5',\n size === 'middle' && 'tw-h-4 tw-text-sm tw-leading-4',\n size === 'small' && 'tw-h-3 tw-text-xs tw-leading-3',\n currentDisabled && 'tw-opacity-50',\n )}\n >\n {children}\n </span>\n )}\n </span>\n );\n};\n\nexport default Switch;\n"],"mappings":";;;;;;AA4BA,IAAM,mBAOF;CACF,OAAO;EACL,QAAQ;EACR,QAAQ;EACR,WAAW;EACZ;CACD,QAAQ;EACN,QAAQ;EACR,QAAQ;EACR,WAAW;EACZ;CACD,OAAO;EACL,QAAQ;EACR,QAAQ;EACR,WAAW;EACZ;CACF;AAED,IAAM,UAAkC,EACtC,YAAY,IACZ,UAAU,gBACV,UAAU,OACV,MAAM,YACN,SACA,gBACA,UACA,SACA,UACA,eAAe,YACf,cAAc,gBACV;CACJ,MAAM,cAAc,WAAW,YAAY;CAC3C,MAAM,OAAO,cAAc,eAAe;CAE1C,MAAM,CAAC,aAAa,kBAAkB,SACpC,OAAO,YAAY,cAAc,iBAAiB,QACnD;CAED,MAAM,WAAW,WAAW,gBAAgB;CAG5C,MAAM,kBAAkB,UAAU,OAFX,kBAAkB;AAIzC,iBAAgB;AACd,MAAI,OAAO,YAAY,UACrB,gBAAe,QAAQ;IAExB,CAAC,QAAQ,CAAC;CAEb,MAAM,eAAe,MAA2C;AAC9D,MAAI,gBAAiB;EACrB,MAAM,aAAa,CAAC;AACpB,MAAI,YAAY,OACd,gBAAe,WAAW;AAE5B,aAAW,YAAY,EAAE;AACzB,YAAU,YAAY,EAAE;;CAG1B,MAAM,EAAE,QAAQ,QAAQ,cAAc,iBAAiB;CACvD,MAAM,cAAc;CACpB,MAAM,iBAAiB,SAAS,YAAY,cAAc;AAE1D,QACE,qBAAC,QAAD;EACE,WAAW,GACT,WACA,oEACA,cAAc,QACd,mBAAmB,4CACnB;GACE,uBAAuB;GACvB,sBAAsB;GACvB,CACF;YAVH,CAYE,oBAAC,UAAD;GACE,MAAK;GACL,MAAK;GACL,gBAAc,CAAC,CAAC;GAChB,aAAW,WAAW;GACtB,eAAa;GACb,cAAY;GACZ,UAAU;GACV,WAAW,GACT,uJACA,cACI,0CACA,2CAGJ,CAAC,mBAAmB;IAClB;IACA;IACA;IACA;IACA;IACD,EACD,mBAAmB,sCACpB;GACD,OAAO;IAAE,OAAO;IAAQ,QAAQ;IAAQ;GACxC,SAAS;aAET,oBAAC,QAAD;IACE,WAAW,GACT,kHACD;IACD,OAAO;KACL,OAAO;KACP,QAAQ;KACR,YAAY;KACZ,WAAW,cACP,cAAc,eAAe,OAC7B;KACL;IACD,CAAA;GACK,CAAA,EACR,YACC,oBAAC,QAAD;GACE,WAAW,GACT,mGACA,SAAS,WAAW,oCACpB,SAAS,YAAY,kCACrB,SAAS,WAAW,kCACpB,mBAAmB,gBACpB;GAEA;GACI,CAAA,CAEJ"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Switch/index.tsx"],"sourcesContent":["import React, { useContext, useEffect, useState } from 'react';\nimport DisabledContext from '../ConfigProvider/DisabledContext';\nimport SizeContext from '../ConfigProvider/sizeContext';\nimport { getSemanticOwnerAriaProps } from '../_utils/formControlSemanticOwner';\nimport { cn } from '../lib/utils';\n\nexport type SwitchChangeEventHandler = (\n checked: boolean,\n event: React.MouseEvent<HTMLButtonElement>,\n) => void;\nexport type SwitchClickEventHandler = SwitchChangeEventHandler;\nexport type SwitchSize = 'large' | 'middle' | 'small';\n\nexport interface ISwitchProps {\n className?: string;\n checked?: boolean;\n defaultChecked?: boolean;\n disabled?: boolean;\n loading?: boolean;\n size?: SwitchSize;\n onClick?: SwitchChangeEventHandler;\n onChange?: SwitchChangeEventHandler;\n children?: React.ReactNode;\n /** 透传到内部 switch 按钮元素的 data-testid,用于自动化测试定位 */\n 'data-testid'?: string;\n /** 透传到内部 switch 按钮元素的 aria-label,用于可访问性与自动化测试定位 */\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-invalid'?: React.AriaAttributes['aria-invalid'];\n 'aria-required'?: React.AriaAttributes['aria-required'];\n 'aria-busy'?: React.AriaAttributes['aria-busy'];\n}\n\nconst switchSizeConfig: Record<\n SwitchSize,\n {\n trackW: number;\n trackH: number;\n thumbSize: number;\n }\n> = {\n large: {\n trackW: 36,\n trackH: 20,\n thumbSize: 16,\n },\n middle: {\n trackW: 28,\n trackH: 16,\n thumbSize: 12,\n },\n small: {\n trackW: 22,\n trackH: 12,\n thumbSize: 8,\n },\n};\n\nconst Switch: React.FC<ISwitchProps> = ({\n className = '',\n disabled: customDisabled,\n loading = false,\n size: customSize,\n checked,\n defaultChecked,\n onChange,\n onClick,\n children,\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-busy': ariaBusy,\n}) => {\n const contentSize = useContext(SizeContext);\n const size = customSize || contentSize || 'middle';\n\n const [userChecked, setUserChecked] = useState(\n typeof checked === 'undefined' ? defaultChecked : checked,\n );\n const switchLabelId = React.useId();\n\n const disabled = useContext(DisabledContext);\n const mergedDisabled = customDisabled ?? disabled;\n\n const currentDisabled = loading ? true : mergedDisabled;\n\n useEffect(() => {\n if (typeof checked === 'boolean') {\n setUserChecked(checked);\n }\n }, [checked]);\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n if (currentDisabled) return;\n const newChecked = !userChecked;\n if (checked === undefined) {\n setUserChecked(newChecked);\n }\n onChange?.(newChecked, e);\n onClick?.(newChecked, e);\n };\n\n const { trackW, trackH, thumbSize } = switchSizeConfig[size];\n const thumbOffset = 2;\n const thumbTranslate = trackW - thumbSize - thumbOffset * 2;\n const generatedLabelledBy =\n ariaLabelledBy ||\n (!ariaLabel && children != null ? switchLabelId : undefined);\n\n return (\n <span\n className={cn(\n className,\n 'ald-switch tw-inline-flex tw-items-center tw-gap-1.5 tw-text-[0]',\n `ald-switch-${size}`,\n currentDisabled && 'tw-pointer-events-none tw-cursor-default',\n {\n 'ald-switch-disabled': currentDisabled,\n 'ald-switch-checked': userChecked,\n },\n )}\n >\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={!!userChecked}\n data-testid={dataTestid}\n {...getSemanticOwnerAriaProps({\n 'aria-label': ariaLabel,\n 'aria-labelledby': generatedLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-invalid': ariaInvalid,\n 'aria-required': ariaRequired,\n 'aria-busy': loading || ariaBusy || undefined,\n })}\n disabled={currentDisabled}\n className={cn(\n 'ald-switch-btn tw-relative tw-inline-flex tw-cursor-pointer tw-items-center tw-rounded-full tw-border-0 tw-p-0 tw-transition-colors tw-duration-200',\n userChecked\n ? 'tw-bg-[var(--control-state-selected)]'\n : 'tw-bg-[var(--control-state-unselected)]',\n // Focus is an independent layer on the interactive button. The\n // selected/unselected Control State Color contract remains intact.\n !currentDisabled && [\n 'focus-visible:tw-shadow-[0_0_0_2px_var(--focus-ring)]',\n 'forced-colors:focus-visible:tw-outline',\n 'forced-colors:focus-visible:tw-outline-2',\n 'forced-colors:focus-visible:tw-outline-offset-2',\n 'forced-colors:focus-visible:tw-outline-[Highlight]',\n ],\n currentDisabled && 'tw-cursor-not-allowed tw-opacity-40',\n )}\n style={{ width: trackW, height: trackH }}\n onClick={handleClick}\n >\n <span\n className={cn(\n 'tw-block tw-rounded-full tw-bg-[var(--background-default)] tw-shadow-[var(--elevation-bottom-bottom-sm)] tw-transition-transform tw-duration-200',\n )}\n style={{\n width: thumbSize,\n height: thumbSize,\n marginLeft: thumbOffset,\n transform: userChecked\n ? `translateX(${thumbTranslate}px)`\n : 'translateX(0)',\n }}\n />\n </button>\n {children && (\n <span\n id={generatedLabelledBy === switchLabelId ? switchLabelId : undefined}\n className={cn(\n 'ald-switch-text tw-inline-flex tw-items-center tw-align-middle tw-text-[var(--content-primary)]',\n size === 'large' && 'tw-h-5 tw-text-base tw-leading-5',\n size === 'middle' && 'tw-h-4 tw-text-sm tw-leading-4',\n size === 'small' && 'tw-h-3 tw-text-xs tw-leading-3',\n currentDisabled && 'tw-opacity-50',\n )}\n >\n {children}\n </span>\n )}\n </span>\n );\n};\n\nexport default Switch;\n"],"mappings":";;;;;;;AAkCA,IAAM,mBAOF;CACF,OAAO;EACL,QAAQ;EACR,QAAQ;EACR,WAAW;EACZ;CACD,QAAQ;EACN,QAAQ;EACR,QAAQ;EACR,WAAW;EACZ;CACD,OAAO;EACL,QAAQ;EACR,QAAQ;EACR,WAAW;EACZ;CACF;AAED,IAAM,UAAkC,EACtC,YAAY,IACZ,UAAU,gBACV,UAAU,OACV,MAAM,YACN,SACA,gBACA,UACA,SACA,UACA,eAAe,YACf,cAAc,WACd,mBAAmB,gBACnB,oBAAoB,iBACpB,gBAAgB,aAChB,iBAAiB,cACjB,aAAa,eACT;CACJ,MAAM,cAAc,WAAW,YAAY;CAC3C,MAAM,OAAO,cAAc,eAAe;CAE1C,MAAM,CAAC,aAAa,kBAAkB,SACpC,OAAO,YAAY,cAAc,iBAAiB,QACnD;CACD,MAAM,gBAAgB,MAAM,OAAO;CAEnC,MAAM,WAAW,WAAW,gBAAgB;CAG5C,MAAM,kBAAkB,UAAU,OAFX,kBAAkB;AAIzC,iBAAgB;AACd,MAAI,OAAO,YAAY,UACrB,gBAAe,QAAQ;IAExB,CAAC,QAAQ,CAAC;CAEb,MAAM,eAAe,MAA2C;AAC9D,MAAI,gBAAiB;EACrB,MAAM,aAAa,CAAC;AACpB,MAAI,YAAY,OACd,gBAAe,WAAW;AAE5B,aAAW,YAAY,EAAE;AACzB,YAAU,YAAY,EAAE;;CAG1B,MAAM,EAAE,QAAQ,QAAQ,cAAc,iBAAiB;CACvD,MAAM,cAAc;CACpB,MAAM,iBAAiB,SAAS,YAAY,cAAc;CAC1D,MAAM,sBACJ,mBACC,CAAC,aAAa,YAAY,OAAO,gBAAgB;AAEpD,QACE,qBAAC,QAAD;EACE,WAAW,GACT,WACA,oEACA,cAAc,QACd,mBAAmB,4CACnB;GACE,uBAAuB;GACvB,sBAAsB;GACvB,CACF;YAVH,CAYE,oBAAC,UAAD;GACE,MAAK;GACL,MAAK;GACL,gBAAc,CAAC,CAAC;GAChB,eAAa;GACb,GAAI,0BAA0B;IAC5B,cAAc;IACd,mBAAmB;IACnB,oBAAoB;IACpB,gBAAgB;IAChB,iBAAiB;IACjB,aAAa,WAAW,YAAY;IACrC,CAAC;GACF,UAAU;GACV,WAAW,GACT,uJACA,cACI,0CACA,2CAGJ,CAAC,mBAAmB;IAClB;IACA;IACA;IACA;IACA;IACD,EACD,mBAAmB,sCACpB;GACD,OAAO;IAAE,OAAO;IAAQ,QAAQ;IAAQ;GACxC,SAAS;aAET,oBAAC,QAAD;IACE,WAAW,GACT,mJACD;IACD,OAAO;KACL,OAAO;KACP,QAAQ;KACR,YAAY;KACZ,WAAW,cACP,cAAc,eAAe,OAC7B;KACL;IACD,CAAA;GACK,CAAA,EACR,YACC,oBAAC,QAAD;GACE,IAAI,wBAAwB,gBAAgB,gBAAgB;GAC5D,WAAW,GACT,mGACA,SAAS,WAAW,oCACpB,SAAS,YAAY,kCACrB,SAAS,WAAW,kCACpB,mBAAmB,gBACpB;GAEA;GACI,CAAA,CAEJ"}
@@ -49,7 +49,6 @@ function Header(props) {
49
49
  })]
50
50
  }) : title;
51
51
  return typeof title === "string" ? /* @__PURE__ */ jsx("div", {
52
- role: isSortable ? "columnheader" : void 0,
53
52
  "aria-sort": isSortable ? ariaSort : void 0,
54
53
  className: cn(prefixCls("th-default"), "tw-text-typography-label", prefixCls(`align-${align}`), {
55
54
  [prefixCls("td-ellipsis-content")]: ellipsis,
@@ -1 +1 @@
1
- {"version":3,"file":"Header.js","names":[],"sources":["../../../src/Table/components/Header.tsx"],"sourcesContent":["import { Column } from '@tanstack/react-table';\nimport { cn } from '../../lib/utils';\nimport React, { MouseEventHandler, useCallback } from 'react';\nimport SortAscIcon from '../../Icon/components/SortAscendingOrderColor';\nimport SortIcon from '../../Icon/components/SortColor';\nimport SortDescIcon from '../../Icon/components/SortDescendingOrderColor';\nimport { prefixCls } from '../helper';\nimport { ITableColumn, ITableProps } from '../types';\n\nexport default function Header<T extends object>(props: IProps<T>) {\n const { column } = props;\n const { title, dataIndex, align, ellipsis, sortOrder, onSort } = column\n .columnDef.meta as ITableColumn & { onSort: ITableProps<T>['onSort'] };\n const isSortable =\n sortOrder !== undefined && !!dataIndex && typeof onSort === 'function';\n const ariaSort =\n sortOrder === 'ascend'\n ? 'ascending'\n : sortOrder === 'descend'\n ? 'descending'\n : 'none';\n\n let sortIcon = <SortIcon size={20} color={'var(--action-neutral-normal)'} />;\n if (sortOrder === 'ascend') {\n sortIcon = <SortAscIcon size={20} color={'var(--action-primary-normal)'} />;\n } else if (sortOrder === 'descend') {\n sortIcon = (\n <SortDescIcon size={20} color={'var(--action-primary-normal)'} />\n );\n }\n\n const onClickTh = useCallback<MouseEventHandler>(\n (e) => {\n if (!isSortable || !dataIndex) {\n return;\n }\n e.stopPropagation();\n\n let newSortOrder: typeof sortOrder;\n if (sortOrder === 'ascend') {\n newSortOrder = 'descend';\n } else if (sortOrder === 'descend') {\n newSortOrder = null;\n } else {\n newSortOrder = 'ascend';\n }\n onSort(dataIndex, newSortOrder);\n },\n [dataIndex, isSortable, onSort, sortOrder],\n );\n\n const content = isSortable ? (\n <span className={prefixCls('sort-th-inner')}>\n <span className={prefixCls('sort-title')}>{title}</span>\n <span className={prefixCls('sort-btn')} aria-hidden=\"true\">\n {sortIcon}\n </span>\n </span>\n ) : (\n title\n );\n\n return typeof title === 'string' ? (\n <div\n key={dataIndex}\n role={isSortable ? 'columnheader' : undefined}\n aria-sort={isSortable ? ariaSort : undefined}\n className={cn(\n prefixCls('th-default'),\n 'tw-text-typography-label',\n prefixCls(`align-${align}`),\n {\n [prefixCls('td-ellipsis-content')]: ellipsis,\n [prefixCls('th-sortable')]: isSortable,\n },\n )}\n >\n {isSortable ? (\n <button\n type=\"button\"\n className={prefixCls('sort-trigger')}\n aria-label={`Sort by ${title}`}\n onClick={onClickTh}\n >\n {content}\n </button>\n ) : (\n content\n )}\n </div>\n ) : (\n <>{title}</>\n );\n}\n\nexport interface IProps<T> {\n column: Column<T>;\n}\n"],"mappings":";;;;;;;;AASA,SAAwB,OAAyB,OAAkB;CACjE,MAAM,EAAE,WAAW;CACnB,MAAM,EAAE,OAAO,WAAW,OAAO,UAAU,WAAW,WAAW,OAC9D,UAAU;CACb,MAAM,aACJ,cAAc,UAAa,CAAC,CAAC,aAAa,OAAO,WAAW;CAC9D,MAAM,WACJ,cAAc,WACV,cACA,cAAc,YACd,eACA;CAEN,IAAI,WAAW,oBAAC,QAAD;EAAU,MAAM;EAAI,OAAO;EAAkC,CAAA;AAC5E,KAAI,cAAc,SAChB,YAAW,oBAAC,MAAD;EAAa,MAAM;EAAI,OAAO;EAAkC,CAAA;UAClE,cAAc,UACvB,YACE,oBAAC,QAAD;EAAc,MAAM;EAAI,OAAO;EAAkC,CAAA;CAIrE,MAAM,YAAY,aACf,MAAM;AACL,MAAI,CAAC,cAAc,CAAC,UAClB;AAEF,IAAE,iBAAiB;EAEnB,IAAI;AACJ,MAAI,cAAc,SAChB,gBAAe;WACN,cAAc,UACvB,gBAAe;MAEf,gBAAe;AAEjB,SAAO,WAAW,aAAa;IAEjC;EAAC;EAAW;EAAY;EAAQ;EAAU,CAC3C;CAED,MAAM,UAAU,aACd,qBAAC,QAAD;EAAM,WAAW,UAAU,gBAAgB;YAA3C,CACE,oBAAC,QAAD;GAAM,WAAW,UAAU,aAAa;aAAG;GAAa,CAAA,EACxD,oBAAC,QAAD;GAAM,WAAW,UAAU,WAAW;GAAE,eAAY;aACjD;GACI,CAAA,CACF;MAEP;AAGF,QAAO,OAAO,UAAU,WACtB,oBAAC,OAAD;EAEE,MAAM,aAAa,iBAAiB;EACpC,aAAW,aAAa,WAAW;EACnC,WAAW,GACT,UAAU,aAAa,EACvB,4BACA,UAAU,SAAS,QAAQ,EAC3B;IACG,UAAU,sBAAsB,GAAG;IACnC,UAAU,cAAc,GAAG;GAC7B,CACF;YAEA,aACC,oBAAC,UAAD;GACE,MAAK;GACL,WAAW,UAAU,eAAe;GACpC,cAAY,WAAW;GACvB,SAAS;aAER;GACM,CAAA,GAET;EAEE,EAzBC,UAyBD,GAEN,oBAAA,UAAA,EAAA,UAAG,OAAS,CAAA"}
1
+ {"version":3,"file":"Header.js","names":[],"sources":["../../../src/Table/components/Header.tsx"],"sourcesContent":["import { Column } from '@tanstack/react-table';\nimport { cn } from '../../lib/utils';\nimport React, { MouseEventHandler, useCallback } from 'react';\nimport SortAscIcon from '../../Icon/components/SortAscendingOrderColor';\nimport SortIcon from '../../Icon/components/SortColor';\nimport SortDescIcon from '../../Icon/components/SortDescendingOrderColor';\nimport { prefixCls } from '../helper';\nimport { ITableColumn, ITableProps } from '../types';\n\nexport default function Header<T extends object>(props: IProps<T>) {\n const { column } = props;\n const { title, dataIndex, align, ellipsis, sortOrder, onSort } = column\n .columnDef.meta as ITableColumn & { onSort: ITableProps<T>['onSort'] };\n const isSortable =\n sortOrder !== undefined && !!dataIndex && typeof onSort === 'function';\n const ariaSort =\n sortOrder === 'ascend'\n ? 'ascending'\n : sortOrder === 'descend'\n ? 'descending'\n : 'none';\n\n let sortIcon = <SortIcon size={20} color={'var(--action-neutral-normal)'} />;\n if (sortOrder === 'ascend') {\n sortIcon = <SortAscIcon size={20} color={'var(--action-primary-normal)'} />;\n } else if (sortOrder === 'descend') {\n sortIcon = (\n <SortDescIcon size={20} color={'var(--action-primary-normal)'} />\n );\n }\n\n const onClickTh = useCallback<MouseEventHandler>(\n (e) => {\n if (!isSortable || !dataIndex) {\n return;\n }\n e.stopPropagation();\n\n let newSortOrder: typeof sortOrder;\n if (sortOrder === 'ascend') {\n newSortOrder = 'descend';\n } else if (sortOrder === 'descend') {\n newSortOrder = null;\n } else {\n newSortOrder = 'ascend';\n }\n onSort(dataIndex, newSortOrder);\n },\n [dataIndex, isSortable, onSort, sortOrder],\n );\n\n const content = isSortable ? (\n <span className={prefixCls('sort-th-inner')}>\n <span className={prefixCls('sort-title')}>{title}</span>\n <span className={prefixCls('sort-btn')} aria-hidden=\"true\">\n {sortIcon}\n </span>\n </span>\n ) : (\n title\n );\n\n return typeof title === 'string' ? (\n <div\n key={dataIndex}\n aria-sort={isSortable ? ariaSort : undefined}\n className={cn(\n prefixCls('th-default'),\n 'tw-text-typography-label',\n prefixCls(`align-${align}`),\n {\n [prefixCls('td-ellipsis-content')]: ellipsis,\n [prefixCls('th-sortable')]: isSortable,\n },\n )}\n >\n {isSortable ? (\n <button\n type=\"button\"\n className={prefixCls('sort-trigger')}\n aria-label={`Sort by ${title}`}\n onClick={onClickTh}\n >\n {content}\n </button>\n ) : (\n content\n )}\n </div>\n ) : (\n <>{title}</>\n );\n}\n\nexport interface IProps<T> {\n column: Column<T>;\n}\n"],"mappings":";;;;;;;;AASA,SAAwB,OAAyB,OAAkB;CACjE,MAAM,EAAE,WAAW;CACnB,MAAM,EAAE,OAAO,WAAW,OAAO,UAAU,WAAW,WAAW,OAC9D,UAAU;CACb,MAAM,aACJ,cAAc,UAAa,CAAC,CAAC,aAAa,OAAO,WAAW;CAC9D,MAAM,WACJ,cAAc,WACV,cACA,cAAc,YACd,eACA;CAEN,IAAI,WAAW,oBAAC,QAAD;EAAU,MAAM;EAAI,OAAO;EAAkC,CAAA;AAC5E,KAAI,cAAc,SAChB,YAAW,oBAAC,MAAD;EAAa,MAAM;EAAI,OAAO;EAAkC,CAAA;UAClE,cAAc,UACvB,YACE,oBAAC,QAAD;EAAc,MAAM;EAAI,OAAO;EAAkC,CAAA;CAIrE,MAAM,YAAY,aACf,MAAM;AACL,MAAI,CAAC,cAAc,CAAC,UAClB;AAEF,IAAE,iBAAiB;EAEnB,IAAI;AACJ,MAAI,cAAc,SAChB,gBAAe;WACN,cAAc,UACvB,gBAAe;MAEf,gBAAe;AAEjB,SAAO,WAAW,aAAa;IAEjC;EAAC;EAAW;EAAY;EAAQ;EAAU,CAC3C;CAED,MAAM,UAAU,aACd,qBAAC,QAAD;EAAM,WAAW,UAAU,gBAAgB;YAA3C,CACE,oBAAC,QAAD;GAAM,WAAW,UAAU,aAAa;aAAG;GAAa,CAAA,EACxD,oBAAC,QAAD;GAAM,WAAW,UAAU,WAAW;GAAE,eAAY;aACjD;GACI,CAAA,CACF;MAEP;AAGF,QAAO,OAAO,UAAU,WACtB,oBAAC,OAAD;EAEE,aAAW,aAAa,WAAW;EACnC,WAAW,GACT,UAAU,aAAa,EACvB,4BACA,UAAU,SAAS,QAAQ,EAC3B;IACG,UAAU,sBAAsB,GAAG;IACnC,UAAU,cAAc,GAAG;GAC7B,CACF;YAEA,aACC,oBAAC,UAAD;GACE,MAAK;GACL,WAAW,UAAU,eAAe;GACpC,cAAY,WAAW;GACvB,SAAS;aAER;GACM,CAAA,GAET;EAEE,EAxBC,UAwBD,GAEN,oBAAA,UAAA,EAAA,UAAG,OAAS,CAAA"}