@aloudata/aloudata-design 3.1.0 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) 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 +91 -78
  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 +1 -0
  60. package/dist/MemberPicker/components/MemberSelection.js +83 -94
  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 +1 -0
  65. package/dist/MemberPicker/components/Panel.js +4 -1
  66. package/dist/MemberPicker/components/Panel.js.map +1 -1
  67. package/dist/MemberPicker/components/SelectedMemberTags.js +14 -6
  68. package/dist/MemberPicker/components/SelectedMemberTags.js.map +1 -1
  69. package/dist/MemberPicker/components/SingleOption.js +12 -0
  70. package/dist/MemberPicker/components/SingleOption.js.map +1 -1
  71. package/dist/MemberPicker/components/UserGroupSelection.d.ts +2 -1
  72. package/dist/MemberPicker/components/UserGroupSelection.js +61 -48
  73. package/dist/MemberPicker/components/UserGroupSelection.js.map +1 -1
  74. package/dist/MemberPicker/index.js +134 -108
  75. package/dist/MemberPicker/index.js.map +1 -1
  76. package/dist/Menu/index.d.ts +8 -0
  77. package/dist/Menu/index.js +33 -3
  78. package/dist/Menu/index.js.map +1 -1
  79. package/dist/Modal/index.d.ts +4 -0
  80. package/dist/Modal/index.js +55 -66
  81. package/dist/Modal/index.js.map +1 -1
  82. package/dist/OverflowCount/index.js +10 -0
  83. package/dist/OverflowCount/index.js.map +1 -1
  84. package/dist/Pagination/index.js +1 -0
  85. package/dist/Pagination/index.js.map +1 -1
  86. package/dist/Popconfirm/index.js +9 -1
  87. package/dist/Popconfirm/index.js.map +1 -1
  88. package/dist/Popover/index.js +52 -1
  89. package/dist/Popover/index.js.map +1 -1
  90. package/dist/Progress/index.js +4 -0
  91. package/dist/Progress/index.js.map +1 -1
  92. package/dist/Radio/components/Group/index.d.ts +5 -1
  93. package/dist/Radio/components/Group/index.js +7 -2
  94. package/dist/Radio/components/Group/index.js.map +1 -1
  95. package/dist/Radio/components/Radio/index.js +26 -0
  96. package/dist/Radio/components/Radio/index.js.map +1 -1
  97. package/dist/Radio/interface/radio.d.ts +7 -0
  98. package/dist/Radio/interface/radioGroup.d.ts +2 -0
  99. package/dist/RenameInput/index.js +11 -0
  100. package/dist/RenameInput/index.js.map +1 -1
  101. package/dist/Select/BaseSelect.d.ts +3 -0
  102. package/dist/Select/BaseSelect.js +229 -32
  103. package/dist/Select/BaseSelect.js.map +1 -1
  104. package/dist/Select/SelectTrigger.d.ts +2 -0
  105. package/dist/Select/SelectTrigger.js +13 -5
  106. package/dist/Select/SelectTrigger.js.map +1 -1
  107. package/dist/Select/components/OptionCollection.d.ts +41 -0
  108. package/dist/Select/components/OptionCollection.js +124 -0
  109. package/dist/Select/components/OptionCollection.js.map +1 -0
  110. package/dist/Select/index.js +45 -3
  111. package/dist/Select/index.js.map +1 -1
  112. package/dist/Select/interface.d.ts +1 -1
  113. package/dist/Skeleton/index.js +1 -1
  114. package/dist/Skeleton/index.js.map +1 -1
  115. package/dist/Spin/index.d.ts +1 -1
  116. package/dist/Spin/index.js +22 -7
  117. package/dist/Spin/index.js.map +1 -1
  118. package/dist/Switch/index.d.ts +5 -0
  119. package/dist/Switch/index.js +15 -5
  120. package/dist/Switch/index.js.map +1 -1
  121. package/dist/Table/components/Header.js +0 -1
  122. package/dist/Table/components/Header.js.map +1 -1
  123. package/dist/Table/index.js +42 -27
  124. package/dist/Table/index.js.map +1 -1
  125. package/dist/Tabs/index.js +1 -0
  126. package/dist/Tabs/index.js.map +1 -1
  127. package/dist/Tag/index.js +20 -1
  128. package/dist/Tag/index.js.map +1 -1
  129. package/dist/Tooltip/index.js +34 -5
  130. package/dist/Tooltip/index.js.map +1 -1
  131. package/dist/Tour/index.js +13 -1
  132. package/dist/Tour/index.js.map +1 -1
  133. package/dist/Tree/Tree2.js +2 -0
  134. package/dist/Tree/Tree2.js.map +1 -1
  135. package/dist/_utils/dialogAccessibility.d.ts +17 -0
  136. package/dist/_utils/dialogAccessibility.js +110 -0
  137. package/dist/_utils/dialogAccessibility.js.map +1 -0
  138. package/dist/_utils/formControlSemanticOwner.d.ts +3 -0
  139. package/dist/_utils/formControlSemanticOwner.js +17 -0
  140. package/dist/_utils/formControlSemanticOwner.js.map +1 -0
  141. package/dist/_utils/overlayCoordinator.js +1 -11
  142. package/dist/_utils/overlayCoordinator.js.map +1 -1
  143. package/dist/aloudata-design.css +1 -1
  144. package/dist/theme/contract/baselineResolvedTokenValueManifest.d.ts +1 -1
  145. package/dist/theme/contract/darkResolvedTokenValueManifest.d.ts +1 -1
  146. package/dist/theme/generator/acceptedColorValues.d.ts +2 -1
  147. package/dist/theme/generator/baselineTokenValueDelivery.d.ts +9 -1
  148. package/dist/theme/generator/minimalAcceptedColorValues.d.ts +2 -2
  149. package/dist/theme/generator/neutralSourceResolver.d.ts +28 -0
  150. package/dist/theme/generator/neutralSourceResolver.js +2 -0
  151. package/dist/theme/generator/neutralSourceValues.d.ts +27 -0
  152. package/dist/theme/generator/neutralSourceValues.js +2 -0
  153. package/dist/theme/index.d.ts +2 -0
  154. package/dist/theme/index.js +1 -0
  155. package/dist/theme/neutralSourceContract.d.ts +3 -0
  156. package/dist/theme/neutralSourceContract.js +11 -0
  157. package/dist/theme/neutralSourceContract.js.map +1 -0
  158. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.d.ts +1 -1
  159. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js +45 -45
  160. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js.map +1 -1
  161. package/dist/theme/runtime/colorValueMode/generated/slateDarkDeclarations.d.ts +3 -0
  162. package/dist/theme/runtime/colorValueMode/generated/slateDarkDeclarations.js +2 -0
  163. package/dist/theme/runtime/colorValueMode/generated/slateLightDeclarations.d.ts +3 -0
  164. package/dist/theme/runtime/colorValueMode/generated/slateLightDeclarations.js +2 -0
  165. package/dist/theme/runtime/colorValueMode/generated/stoneDarkDeclarations.d.ts +3 -0
  166. package/dist/theme/runtime/colorValueMode/generated/stoneDarkDeclarations.js +2 -0
  167. package/dist/theme/runtime/colorValueMode/generated/stoneLightDeclarations.d.ts +3 -0
  168. package/dist/theme/runtime/colorValueMode/generated/stoneLightDeclarations.js +2 -0
  169. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.d.ts +1 -1
  170. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js +41 -41
  171. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js.map +1 -1
  172. package/dist/theme/runtime/colorValueMode/index.js +2 -12
  173. package/dist/theme/runtime/colorValueMode/index.js.map +1 -1
  174. package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.d.ts +2 -0
  175. package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.js +48 -0
  176. package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.js.map +1 -0
  177. package/dist/theme/runtime/colorValueMode/registry.d.ts +1 -1
  178. package/dist/theme/runtime/colorValueMode/registry.js +2 -1
  179. package/dist/theme/runtime/colorValueMode/registry.js.map +1 -1
  180. package/dist/theme/runtime/initAldTheme.js +1 -3
  181. package/dist/theme/runtime/initAldTheme.js.map +1 -1
  182. package/dist/theme/runtime/neutralSource/index.d.ts +6 -0
  183. package/dist/theme/runtime/neutralSource/index.js +11 -0
  184. package/dist/theme/runtime/neutralSource/index.js.map +1 -0
  185. package/dist/theme/runtime/neutralSource.d.ts +2 -0
  186. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/Radio/components/Group/index.tsx"],"sourcesContent":["import { cn } from '../../../lib/utils';\nimport React, { createContext, useEffect, useState } from 'react';\nimport DisabledContext from '../../../ConfigProvider/DisabledContext';\nimport { IRadioGroupProps } from '../../interface/radioGroup';\n\nexport const RadioGroupContext = createContext<\n Omit<IRadioGroupProps, 'children' | 'className'>\n>({});\n\nexport default function RadioGroup(props: IRadioGroupProps) {\n const {\n children,\n radioGroupStyle = 'filled',\n size = 'middle',\n type = 'radio',\n className,\n disabled: customDisabled,\n 'data-testid': dataTestId,\n 'aria-label': ariaLabel,\n } = props;\n const isControlled = 'value' in props && props.value !== undefined;\n const [innerValue, setInnerValue] = useState(props.defaultValue);\n\n useEffect(() => {\n if (isControlled) {\n setInnerValue(props.value);\n }\n }, [props.value, isControlled]);\n\n const value = isControlled ? props.value : innerValue;\n const setValue = (v: any) => {\n if (!isControlled) {\n setInnerValue(v);\n }\n };\n // ===================== Disabled =====================\n const disabled = React.useContext(DisabledContext);\n const mergedDisabled = customDisabled ?? disabled;\n const onRadioChange = (selectedValue: any) => {\n const lastValue = value;\n\n setValue(selectedValue);\n const { onChange } = props;\n if (onChange && selectedValue !== lastValue) {\n onChange(selectedValue);\n }\n };\n\n const getWrapperClass = () => {\n const isButton = ['button', 'iconButton'].includes(type);\n const tempType = type === 'iconButton' ? 'icon-button' : type;\n return cn('ald-radio-group', className, `ald-radio-group-${tempType}`, {\n // 约束只能在type为button和iconbutton的时候才可以设置样式和大小\n [`ald-radio-group-${radioGroupStyle}`]: isButton,\n [`ald-radio-group-${size}`]: isButton,\n });\n };\n\n return (\n <RadioGroupContext.Provider\n value={{\n onChange: onRadioChange,\n value,\n radioGroupStyle,\n size,\n type,\n disabled: mergedDisabled,\n }}\n >\n <div\n className={getWrapperClass()}\n data-testid={dataTestId}\n aria-label={ariaLabel}\n >\n {children}\n </div>\n </RadioGroupContext.Provider>\n );\n}\n"],"mappings":";;;;;AAKA,IAAa,oBAAoB,cAE/B,EAAE,CAAC;AAEL,SAAwB,WAAW,OAAyB;CAC1D,MAAM,EACJ,UACA,kBAAkB,UAClB,OAAO,UACP,OAAO,SACP,WACA,UAAU,gBACV,eAAe,YACf,cAAc,cACZ;CACJ,MAAM,eAAe,WAAW,SAAS,MAAM,UAAU;CACzD,MAAM,CAAC,YAAY,iBAAiB,SAAS,MAAM,aAAa;AAEhE,iBAAgB;AACd,MAAI,aACF,eAAc,MAAM,MAAM;IAE3B,CAAC,MAAM,OAAO,aAAa,CAAC;CAE/B,MAAM,QAAQ,eAAe,MAAM,QAAQ;CAC3C,MAAM,YAAY,MAAW;AAC3B,MAAI,CAAC,aACH,eAAc,EAAE;;CAIpB,MAAM,WAAW,MAAM,WAAW,gBAAgB;CAClD,MAAM,iBAAiB,kBAAkB;CACzC,MAAM,iBAAiB,kBAAuB;EAC5C,MAAM,YAAY;AAElB,WAAS,cAAc;EACvB,MAAM,EAAE,aAAa;AACrB,MAAI,YAAY,kBAAkB,UAChC,UAAS,cAAc;;CAI3B,MAAM,wBAAwB;EAC5B,MAAM,WAAW,CAAC,UAAU,aAAa,CAAC,SAAS,KAAK;AAExD,SAAO,GAAG,mBAAmB,WAAW,mBADvB,SAAS,eAAe,gBAAgB,QACc;IAEpE,mBAAmB,oBAAoB;IACvC,mBAAmB,SAAS;GAC9B,CAAC;;AAGJ,QACE,oBAAC,kBAAkB,UAAnB;EACE,OAAO;GACL,UAAU;GACV;GACA;GACA;GACA;GACA,UAAU;GACX;YAED,oBAAC,OAAD;GACE,WAAW,iBAAiB;GAC5B,eAAa;GACb,cAAY;GAEX;GACG,CAAA;EACqB,CAAA"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/Radio/components/Group/index.tsx"],"sourcesContent":["import { cn } from '../../../lib/utils';\nimport React, { createContext, useEffect, useState } from 'react';\nimport DisabledContext from '../../../ConfigProvider/DisabledContext';\nimport { IRadioGroupProps } from '../../interface/radioGroup';\n\ntype RadioGroupContextValue = Omit<\n IRadioGroupProps,\n 'children' | 'className'\n> & {\n name?: string;\n};\n\nexport const RadioGroupContext = createContext<RadioGroupContextValue>({});\n\nexport default function RadioGroup(props: IRadioGroupProps) {\n const {\n children,\n radioGroupStyle = 'filled',\n size = 'middle',\n type = 'radio',\n className,\n disabled: customDisabled,\n 'data-testid': dataTestId,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n } = props;\n const groupName = React.useId();\n const isControlled = 'value' in props && props.value !== undefined;\n const [innerValue, setInnerValue] = useState(props.defaultValue);\n\n useEffect(() => {\n if (isControlled) {\n setInnerValue(props.value);\n }\n }, [props.value, isControlled]);\n\n const value = isControlled ? props.value : innerValue;\n const setValue = (v: any) => {\n if (!isControlled) {\n setInnerValue(v);\n }\n };\n // ===================== Disabled =====================\n const disabled = React.useContext(DisabledContext);\n const mergedDisabled = customDisabled ?? disabled;\n const onRadioChange = (selectedValue: any) => {\n const lastValue = value;\n\n setValue(selectedValue);\n const { onChange } = props;\n if (onChange && selectedValue !== lastValue) {\n onChange(selectedValue);\n }\n };\n\n const getWrapperClass = () => {\n const isButton = ['button', 'iconButton'].includes(type);\n const tempType = type === 'iconButton' ? 'icon-button' : type;\n return cn('ald-radio-group', className, `ald-radio-group-${tempType}`, {\n // 约束只能在type为button和iconbutton的时候才可以设置样式和大小\n [`ald-radio-group-${radioGroupStyle}`]: isButton,\n [`ald-radio-group-${size}`]: isButton,\n });\n };\n\n return (\n <RadioGroupContext.Provider\n value={{\n onChange: onRadioChange,\n value,\n radioGroupStyle,\n size,\n type,\n disabled: mergedDisabled,\n name: groupName,\n }}\n >\n <div\n className={getWrapperClass()}\n data-testid={dataTestId}\n role=\"radiogroup\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n >\n {children}\n </div>\n </RadioGroupContext.Provider>\n );\n}\n"],"mappings":";;;;;AAYA,IAAa,oBAAoB,cAAsC,EAAE,CAAC;AAE1E,SAAwB,WAAW,OAAyB;CAC1D,MAAM,EACJ,UACA,kBAAkB,UAClB,OAAO,UACP,OAAO,SACP,WACA,UAAU,gBACV,eAAe,YACf,cAAc,WACd,mBAAmB,gBACnB,oBAAoB,oBAClB;CACJ,MAAM,YAAY,MAAM,OAAO;CAC/B,MAAM,eAAe,WAAW,SAAS,MAAM,UAAU;CACzD,MAAM,CAAC,YAAY,iBAAiB,SAAS,MAAM,aAAa;AAEhE,iBAAgB;AACd,MAAI,aACF,eAAc,MAAM,MAAM;IAE3B,CAAC,MAAM,OAAO,aAAa,CAAC;CAE/B,MAAM,QAAQ,eAAe,MAAM,QAAQ;CAC3C,MAAM,YAAY,MAAW;AAC3B,MAAI,CAAC,aACH,eAAc,EAAE;;CAIpB,MAAM,WAAW,MAAM,WAAW,gBAAgB;CAClD,MAAM,iBAAiB,kBAAkB;CACzC,MAAM,iBAAiB,kBAAuB;EAC5C,MAAM,YAAY;AAElB,WAAS,cAAc;EACvB,MAAM,EAAE,aAAa;AACrB,MAAI,YAAY,kBAAkB,UAChC,UAAS,cAAc;;CAI3B,MAAM,wBAAwB;EAC5B,MAAM,WAAW,CAAC,UAAU,aAAa,CAAC,SAAS,KAAK;AAExD,SAAO,GAAG,mBAAmB,WAAW,mBADvB,SAAS,eAAe,gBAAgB,QACc;IAEpE,mBAAmB,oBAAoB;IACvC,mBAAmB,SAAS;GAC9B,CAAC;;AAGJ,QACE,oBAAC,kBAAkB,UAAnB;EACE,OAAO;GACL,UAAU;GACV;GACA;GACA;GACA;GACA,UAAU;GACV,MAAM;GACP;YAED,oBAAC,OAAD;GACE,WAAW,iBAAiB;GAC5B,eAAa;GACb,MAAK;GACL,cAAY;GACZ,mBAAiB;GACjB,oBAAkB;GAEjB;GACG,CAAA;EACqB,CAAA"}
@@ -1,4 +1,5 @@
1
1
  import { cn } from "../../../lib/utils.js";
2
+ import { getSemanticOwnerAriaProps } from "../../../_utils/formControlSemanticOwner.js";
2
3
  import { getUUID } from "../../../_utils/hooks/useId.js";
3
4
  import { RadioGroupContext } from "../Group/index.js";
4
5
  import { useContext, useRef, useState } from "react";
@@ -56,12 +57,37 @@ function Radio(props) {
56
57
  className: "ald-radio-input",
57
58
  checked: !!checked,
58
59
  disabled: radioProps.disabled,
60
+ name: groupContext.name,
61
+ required: props.required,
59
62
  value: props.value,
63
+ ...getSemanticOwnerAriaProps({
64
+ "aria-label": props["aria-label"],
65
+ "aria-labelledby": props["aria-labelledby"],
66
+ "aria-describedby": props["aria-describedby"],
67
+ "aria-invalid": props["aria-invalid"],
68
+ "aria-required": props["aria-required"],
69
+ "aria-disabled": props["aria-disabled"]
70
+ }),
60
71
  onChange: (e) => {
61
72
  if (radioProps.disabled) return;
62
73
  if (!inGroup && !isControlled) setInnerChecked(e.target.checked);
63
74
  props.onChange?.(e);
64
75
  },
76
+ onKeyDown: (e) => {
77
+ if (!inGroup || ![
78
+ "ArrowUp",
79
+ "ArrowDown",
80
+ "ArrowLeft",
81
+ "ArrowRight"
82
+ ].includes(e.key)) return;
83
+ const radios = Array.from(document.querySelectorAll("input[type=\"radio\"]")).filter((radio) => radio.name === groupContext.name && !radio.disabled);
84
+ const currentIndex = radios.indexOf(e.currentTarget);
85
+ if (currentIndex < 0 || radios.length < 2) return;
86
+ e.preventDefault();
87
+ const nextRadio = radios[(currentIndex + (e.key === "ArrowUp" || e.key === "ArrowLeft" ? -1 : 1) + radios.length) % radios.length];
88
+ nextRadio.focus();
89
+ nextRadio.click();
90
+ },
65
91
  onClick: (e) => {
66
92
  props.onClick?.(e);
67
93
  if (inGroup && groupContext?.onChange) groupContext.onChange(props.value);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/Radio/components/Radio/index.tsx"],"sourcesContent":["import { cn } from '../../../lib/utils';\nimport _ from 'lodash';\nimport React, { useContext, useRef, useState } from 'react';\n\nimport { getUUID } from '../../../_utils/hooks/useId';\nimport { IRadioProps } from '../../interface/radio';\nimport { RadioGroupContext } from '../Group';\n\nexport default function Radio(props: IRadioProps) {\n const groupContext = useContext(RadioGroupContext);\n const labelRef = useRef<HTMLLabelElement>(null);\n const [id] = useState(() => getUUID().toString());\n\n const radioProps = { ...props };\n const inGroup = !_.isEmpty(groupContext);\n const isControlled = 'checked' in props;\n const [innerChecked, setInnerChecked] = useState(\n props.defaultChecked ?? false,\n );\n\n if (inGroup) {\n radioProps.disabled = groupContext.disabled || props.disabled;\n }\n\n // checked 直接从 groupContext 或 props 派生,不使用 useState + useEffect,\n // 避免双重渲染导致切换时视觉抖动。\n const checked = inGroup\n ? groupContext.value === props.value\n : !isControlled\n ? innerChecked\n : radioProps.checked;\n\n // 设置input外层盒子的class\n const aldRadioClass = cn('ald-radio', {\n 'ald-radio-checked': checked,\n 'ald-radio-disabled': radioProps.disabled,\n });\n\n // 根据属性设置最外层的class\n const getWrapperClass = () => {\n let otherClass = '';\n if (groupContext.type === 'button') {\n if (groupContext.radioGroupStyle === 'filled') {\n otherClass = 'ald-radio-button-wrapper-filled';\n } else if (groupContext.radioGroupStyle === 'border') {\n otherClass = 'ald-radio-button-wrapper-border';\n } else if (groupContext.radioGroupStyle === 'filter') {\n otherClass = 'ald-radio-button-wrapper-filter';\n } else {\n otherClass = 'ald-radio-button-wrapper-border-primary';\n }\n } else if (groupContext.type === 'iconButton') {\n if (groupContext.radioGroupStyle === 'filled') {\n otherClass = 'ald-radio-icon-button-wrapper-filled';\n } else if (groupContext.radioGroupStyle === 'border') {\n otherClass = 'ald-radio-icon-button-wrapper-border';\n } else if (groupContext.radioGroupStyle === 'filter') {\n otherClass = 'ald-radio-icon-button-wrapper-filter';\n } else {\n otherClass = 'ald-radio-icon-button-wrapper-border-primary';\n }\n } else {\n // 当type未设置或者是radio时\n otherClass = 'ald-radio-wrapper';\n if (props.indeterminate) {\n otherClass = otherClass + ' ald-radio-wrapper-indeterminate';\n }\n }\n return cn('ald-radio-label', otherClass, props.className, {\n 'ald-radio-wrapper-checked': checked,\n 'ald-radio-wrapper-disabled': radioProps.disabled,\n });\n };\n\n // button / iconButton 模式下,radio 圆圈需要完全隐藏\n const isButtonMode =\n groupContext.type === 'button' || groupContext.type === 'iconButton';\n const radioHideStyle: React.CSSProperties | undefined = isButtonMode\n ? { width: 0, height: 0, overflow: 'hidden' }\n : undefined;\n\n return (\n <label className={getWrapperClass()} htmlFor={id} ref={labelRef}>\n <span className={aldRadioClass} style={radioHideStyle}>\n <input\n id={id}\n type=\"radio\"\n className=\"ald-radio-input\"\n // 同步派生的 checked 到原生 input,对齐 v2/antd 行为(仅有 class 不更新 input.checked)\n checked={!!checked}\n disabled={radioProps.disabled}\n value={props.value}\n onChange={(e) => {\n if (radioProps.disabled) return;\n if (!inGroup && !isControlled) {\n setInnerChecked(e.target.checked);\n }\n props.onChange?.(e);\n }}\n onClick={(e) => {\n props.onClick?.(e);\n\n if (inGroup && groupContext?.onChange) {\n // input事件的value会被toString,所以此处进行一个覆盖\n groupContext.onChange(props.value);\n }\n }}\n />\n <span className=\"ald-radio-inner\" />\n </span>\n {props.children && (\n <span className=\"ald-radio-desc tw-text-typography-label\">\n {props.children}\n </span>\n )}\n </label>\n );\n}\n"],"mappings":";;;;;;;AAQA,SAAwB,MAAM,OAAoB;CAChD,MAAM,eAAe,WAAW,kBAAkB;CAClD,MAAM,WAAW,OAAyB,KAAK;CAC/C,MAAM,CAAC,MAAM,eAAe,SAAS,CAAC,UAAU,CAAC;CAEjD,MAAM,aAAa,EAAE,GAAG,OAAO;CAC/B,MAAM,UAAU,CAAC,EAAE,QAAQ,aAAa;CACxC,MAAM,eAAe,aAAa;CAClC,MAAM,CAAC,cAAc,mBAAmB,SACtC,MAAM,kBAAkB,MACzB;AAED,KAAI,QACF,YAAW,WAAW,aAAa,YAAY,MAAM;CAKvD,MAAM,UAAU,UACZ,aAAa,UAAU,MAAM,QAC7B,CAAC,eACD,eACA,WAAW;CAGf,MAAM,gBAAgB,GAAG,aAAa;EACpC,qBAAqB;EACrB,sBAAsB,WAAW;EAClC,CAAC;CAGF,MAAM,wBAAwB;EAC5B,IAAI,aAAa;AACjB,MAAI,aAAa,SAAS,SACxB,KAAI,aAAa,oBAAoB,SACnC,cAAa;WACJ,aAAa,oBAAoB,SAC1C,cAAa;WACJ,aAAa,oBAAoB,SAC1C,cAAa;MAEb,cAAa;WAEN,aAAa,SAAS,aAC/B,KAAI,aAAa,oBAAoB,SACnC,cAAa;WACJ,aAAa,oBAAoB,SAC1C,cAAa;WACJ,aAAa,oBAAoB,SAC1C,cAAa;MAEb,cAAa;OAEV;AAEL,gBAAa;AACb,OAAI,MAAM,cACR,cAAa,aAAa;;AAG9B,SAAO,GAAG,mBAAmB,YAAY,MAAM,WAAW;GACxD,6BAA6B;GAC7B,8BAA8B,WAAW;GAC1C,CAAC;;CAMJ,MAAM,iBADJ,aAAa,SAAS,YAAY,aAAa,SAAS,eAEtD;EAAE,OAAO;EAAG,QAAQ;EAAG,UAAU;EAAU,GAC3C;AAEJ,QACE,qBAAC,SAAD;EAAO,WAAW,iBAAiB;EAAE,SAAS;EAAI,KAAK;YAAvD,CACE,qBAAC,QAAD;GAAM,WAAW;GAAe,OAAO;aAAvC,CACE,oBAAC,SAAD;IACM;IACJ,MAAK;IACL,WAAU;IAEV,SAAS,CAAC,CAAC;IACX,UAAU,WAAW;IACrB,OAAO,MAAM;IACb,WAAW,MAAM;AACf,SAAI,WAAW,SAAU;AACzB,SAAI,CAAC,WAAW,CAAC,aACf,iBAAgB,EAAE,OAAO,QAAQ;AAEnC,WAAM,WAAW,EAAE;;IAErB,UAAU,MAAM;AACd,WAAM,UAAU,EAAE;AAElB,SAAI,WAAW,cAAc,SAE3B,cAAa,SAAS,MAAM,MAAM;;IAGtC,CAAA,EACF,oBAAC,QAAD,EAAM,WAAU,mBAAoB,CAAA,CAC/B;MACN,MAAM,YACL,oBAAC,QAAD;GAAM,WAAU;aACb,MAAM;GACF,CAAA,CAEH"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/Radio/components/Radio/index.tsx"],"sourcesContent":["import { cn } from '../../../lib/utils';\nimport { getSemanticOwnerAriaProps } from '../../../_utils/formControlSemanticOwner';\nimport _ from 'lodash';\nimport React, { useContext, useRef, useState } from 'react';\n\nimport { getUUID } from '../../../_utils/hooks/useId';\nimport { IRadioProps } from '../../interface/radio';\nimport { RadioGroupContext } from '../Group';\n\nexport default function Radio(props: IRadioProps) {\n const groupContext = useContext(RadioGroupContext);\n const labelRef = useRef<HTMLLabelElement>(null);\n const [id] = useState(() => getUUID().toString());\n\n const radioProps = { ...props };\n const inGroup = !_.isEmpty(groupContext);\n const isControlled = 'checked' in props;\n const [innerChecked, setInnerChecked] = useState(\n props.defaultChecked ?? false,\n );\n\n if (inGroup) {\n radioProps.disabled = groupContext.disabled || props.disabled;\n }\n\n // checked 直接从 groupContext 或 props 派生,不使用 useState + useEffect,\n // 避免双重渲染导致切换时视觉抖动。\n const checked = inGroup\n ? groupContext.value === props.value\n : !isControlled\n ? innerChecked\n : radioProps.checked;\n\n // 设置input外层盒子的class\n const aldRadioClass = cn('ald-radio', {\n 'ald-radio-checked': checked,\n 'ald-radio-disabled': radioProps.disabled,\n });\n\n // 根据属性设置最外层的class\n const getWrapperClass = () => {\n let otherClass = '';\n if (groupContext.type === 'button') {\n if (groupContext.radioGroupStyle === 'filled') {\n otherClass = 'ald-radio-button-wrapper-filled';\n } else if (groupContext.radioGroupStyle === 'border') {\n otherClass = 'ald-radio-button-wrapper-border';\n } else if (groupContext.radioGroupStyle === 'filter') {\n otherClass = 'ald-radio-button-wrapper-filter';\n } else {\n otherClass = 'ald-radio-button-wrapper-border-primary';\n }\n } else if (groupContext.type === 'iconButton') {\n if (groupContext.radioGroupStyle === 'filled') {\n otherClass = 'ald-radio-icon-button-wrapper-filled';\n } else if (groupContext.radioGroupStyle === 'border') {\n otherClass = 'ald-radio-icon-button-wrapper-border';\n } else if (groupContext.radioGroupStyle === 'filter') {\n otherClass = 'ald-radio-icon-button-wrapper-filter';\n } else {\n otherClass = 'ald-radio-icon-button-wrapper-border-primary';\n }\n } else {\n // 当type未设置或者是radio时\n otherClass = 'ald-radio-wrapper';\n if (props.indeterminate) {\n otherClass = otherClass + ' ald-radio-wrapper-indeterminate';\n }\n }\n return cn('ald-radio-label', otherClass, props.className, {\n 'ald-radio-wrapper-checked': checked,\n 'ald-radio-wrapper-disabled': radioProps.disabled,\n });\n };\n\n // button / iconButton 模式下,radio 圆圈需要完全隐藏\n const isButtonMode =\n groupContext.type === 'button' || groupContext.type === 'iconButton';\n const radioHideStyle: React.CSSProperties | undefined = isButtonMode\n ? { width: 0, height: 0, overflow: 'hidden' }\n : undefined;\n\n return (\n <label className={getWrapperClass()} htmlFor={id} ref={labelRef}>\n <span className={aldRadioClass} style={radioHideStyle}>\n <input\n id={id}\n type=\"radio\"\n className=\"ald-radio-input\"\n // 同步派生的 checked 到原生 input,对齐 v2/antd 行为(仅有 class 不更新 input.checked)\n checked={!!checked}\n disabled={radioProps.disabled}\n name={groupContext.name}\n required={props.required}\n value={props.value}\n {...getSemanticOwnerAriaProps({\n 'aria-label': props['aria-label'],\n 'aria-labelledby': props['aria-labelledby'],\n 'aria-describedby': props['aria-describedby'],\n 'aria-invalid': props['aria-invalid'],\n 'aria-required': props['aria-required'],\n 'aria-disabled': props['aria-disabled'],\n })}\n onChange={(e) => {\n if (radioProps.disabled) return;\n if (!inGroup && !isControlled) {\n setInnerChecked(e.target.checked);\n }\n props.onChange?.(e);\n }}\n onKeyDown={(e) => {\n if (\n !inGroup ||\n !['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(\n e.key,\n )\n ) {\n return;\n }\n\n const radios = Array.from(\n document.querySelectorAll<HTMLInputElement>(\n 'input[type=\"radio\"]',\n ),\n ).filter(\n (radio) => radio.name === groupContext.name && !radio.disabled,\n );\n const currentIndex = radios.indexOf(e.currentTarget);\n if (currentIndex < 0 || radios.length < 2) return;\n\n e.preventDefault();\n const direction =\n e.key === 'ArrowUp' || e.key === 'ArrowLeft' ? -1 : 1;\n const nextIndex =\n (currentIndex + direction + radios.length) % radios.length;\n const nextRadio = radios[nextIndex];\n nextRadio.focus();\n nextRadio.click();\n }}\n onClick={(e) => {\n props.onClick?.(e);\n\n if (inGroup && groupContext?.onChange) {\n // input事件的value会被toString,所以此处进行一个覆盖\n groupContext.onChange(props.value);\n }\n }}\n />\n <span className=\"ald-radio-inner\" />\n </span>\n {props.children && (\n <span className=\"ald-radio-desc tw-text-typography-label\">\n {props.children}\n </span>\n )}\n </label>\n );\n}\n"],"mappings":";;;;;;;;AASA,SAAwB,MAAM,OAAoB;CAChD,MAAM,eAAe,WAAW,kBAAkB;CAClD,MAAM,WAAW,OAAyB,KAAK;CAC/C,MAAM,CAAC,MAAM,eAAe,SAAS,CAAC,UAAU,CAAC;CAEjD,MAAM,aAAa,EAAE,GAAG,OAAO;CAC/B,MAAM,UAAU,CAAC,EAAE,QAAQ,aAAa;CACxC,MAAM,eAAe,aAAa;CAClC,MAAM,CAAC,cAAc,mBAAmB,SACtC,MAAM,kBAAkB,MACzB;AAED,KAAI,QACF,YAAW,WAAW,aAAa,YAAY,MAAM;CAKvD,MAAM,UAAU,UACZ,aAAa,UAAU,MAAM,QAC7B,CAAC,eACD,eACA,WAAW;CAGf,MAAM,gBAAgB,GAAG,aAAa;EACpC,qBAAqB;EACrB,sBAAsB,WAAW;EAClC,CAAC;CAGF,MAAM,wBAAwB;EAC5B,IAAI,aAAa;AACjB,MAAI,aAAa,SAAS,SACxB,KAAI,aAAa,oBAAoB,SACnC,cAAa;WACJ,aAAa,oBAAoB,SAC1C,cAAa;WACJ,aAAa,oBAAoB,SAC1C,cAAa;MAEb,cAAa;WAEN,aAAa,SAAS,aAC/B,KAAI,aAAa,oBAAoB,SACnC,cAAa;WACJ,aAAa,oBAAoB,SAC1C,cAAa;WACJ,aAAa,oBAAoB,SAC1C,cAAa;MAEb,cAAa;OAEV;AAEL,gBAAa;AACb,OAAI,MAAM,cACR,cAAa,aAAa;;AAG9B,SAAO,GAAG,mBAAmB,YAAY,MAAM,WAAW;GACxD,6BAA6B;GAC7B,8BAA8B,WAAW;GAC1C,CAAC;;CAMJ,MAAM,iBADJ,aAAa,SAAS,YAAY,aAAa,SAAS,eAEtD;EAAE,OAAO;EAAG,QAAQ;EAAG,UAAU;EAAU,GAC3C;AAEJ,QACE,qBAAC,SAAD;EAAO,WAAW,iBAAiB;EAAE,SAAS;EAAI,KAAK;YAAvD,CACE,qBAAC,QAAD;GAAM,WAAW;GAAe,OAAO;aAAvC,CACE,oBAAC,SAAD;IACM;IACJ,MAAK;IACL,WAAU;IAEV,SAAS,CAAC,CAAC;IACX,UAAU,WAAW;IACrB,MAAM,aAAa;IACnB,UAAU,MAAM;IAChB,OAAO,MAAM;IACb,GAAI,0BAA0B;KAC5B,cAAc,MAAM;KACpB,mBAAmB,MAAM;KACzB,oBAAoB,MAAM;KAC1B,gBAAgB,MAAM;KACtB,iBAAiB,MAAM;KACvB,iBAAiB,MAAM;KACxB,CAAC;IACF,WAAW,MAAM;AACf,SAAI,WAAW,SAAU;AACzB,SAAI,CAAC,WAAW,CAAC,aACf,iBAAgB,EAAE,OAAO,QAAQ;AAEnC,WAAM,WAAW,EAAE;;IAErB,YAAY,MAAM;AAChB,SACE,CAAC,WACD,CAAC;MAAC;MAAW;MAAa;MAAa;MAAa,CAAC,SACnD,EAAE,IACH,CAED;KAGF,MAAM,SAAS,MAAM,KACnB,SAAS,iBACP,wBACD,CACF,CAAC,QACC,UAAU,MAAM,SAAS,aAAa,QAAQ,CAAC,MAAM,SACvD;KACD,MAAM,eAAe,OAAO,QAAQ,EAAE,cAAc;AACpD,SAAI,eAAe,KAAK,OAAO,SAAS,EAAG;AAE3C,OAAE,gBAAgB;KAKlB,MAAM,YAAY,QADf,gBAFD,EAAE,QAAQ,aAAa,EAAE,QAAQ,cAAc,KAAK,KAExB,OAAO,UAAU,OAAO;AAEtD,eAAU,OAAO;AACjB,eAAU,OAAO;;IAEnB,UAAU,MAAM;AACd,WAAM,UAAU,EAAE;AAElB,SAAI,WAAW,cAAc,SAE3B,cAAa,SAAS,MAAM,MAAM;;IAGtC,CAAA,EACF,oBAAC,QAAD,EAAM,WAAU,mBAAoB,CAAA,CAC/B;MACN,MAAM,YACL,oBAAC,QAAD;GAAM,WAAU;aACb,MAAM;GACF,CAAA,CAEH"}
@@ -20,6 +20,13 @@ export interface IRadioProps {
20
20
  * @default -
21
21
  */
22
22
  value?: any;
23
+ required?: boolean;
24
+ 'aria-label'?: string;
25
+ 'aria-labelledby'?: string;
26
+ 'aria-describedby'?: string;
27
+ 'aria-invalid'?: React.AriaAttributes['aria-invalid'];
28
+ 'aria-required'?: React.AriaAttributes['aria-required'];
29
+ 'aria-disabled'?: React.AriaAttributes['aria-disabled'];
23
30
  children?: ReactNode[] | ReactNode;
24
31
  onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
25
32
  onClick?: (e: React.MouseEvent<HTMLInputElement>) => void;
@@ -48,4 +48,6 @@ export interface IRadioGroupProps {
48
48
  'data-testid'?: string;
49
49
  /** 透传到 RadioGroup 根容器的 aria-label,用于可访问性与自动化测试定位 */
50
50
  'aria-label'?: string;
51
+ 'aria-labelledby'?: string;
52
+ 'aria-describedby'?: string;
51
53
  }
@@ -49,6 +49,7 @@ var RenameInput = ({ value: propsValue, onConfirm, className, width, fontStyle,
49
49
  width
50
50
  },
51
51
  value,
52
+ "aria-label": `Rename ${propsValue}`,
52
53
  ref: inputRef,
53
54
  onChange: (e) => setValue(e.target.value),
54
55
  onBlur: (e) => {
@@ -80,6 +81,9 @@ var RenameInput = ({ value: propsValue, onConfirm, className, width, fontStyle,
80
81
  return /* @__PURE__ */ jsx("div", {
81
82
  className: cn(className, "ald-rename-input-text tw-flex tw-h-[22px] tw-items-center tw-border tw-border-[var(--action-ghost-normal)] tw-p-[2px] tw-text-[13px]"),
82
83
  style: fontStyle,
84
+ role: !readonly ? "button" : void 0,
85
+ tabIndex: !readonly ? 0 : void 0,
86
+ "aria-label": !readonly ? `Edit ${propsValue}` : void 0,
83
87
  onMouseMove: () => {
84
88
  setIsEdit(true);
85
89
  setValue(propsValue);
@@ -87,6 +91,13 @@ var RenameInput = ({ value: propsValue, onConfirm, className, width, fontStyle,
87
91
  onClick: () => {
88
92
  inputRef.current?.select();
89
93
  },
94
+ onKeyDown: (e) => {
95
+ if (!readonly && (e.key === "Enter" || e.key === " ")) {
96
+ e.preventDefault();
97
+ setIsEdit(true);
98
+ setValue(propsValue);
99
+ }
100
+ },
90
101
  children: propsValue
91
102
  });
92
103
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/RenameInput/index.tsx"],"sourcesContent":["import React, {\n CSSProperties,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { cn } from '../lib/utils';\n\ninterface IProps {\n value: string;\n onConfirm?: (value: string) => void;\n onError?: (value: string) => void;\n className?: string;\n width?: number;\n fontStyle?: CSSProperties;\n /**\n * @deprecated 如果要控制编辑态请使用 isEdit\n */\n focus?: boolean;\n isEdit?: boolean;\n maxLength?: number;\n distance?: [left: number, right: number];\n validateValue?: (value: string) => boolean;\n readonly?: boolean;\n}\n\nconst defaultWidth = 20;\n\nconst PADDING_WIDTH = 4;\n\nconst RenameInput = ({\n value: propsValue,\n onConfirm,\n className,\n width,\n fontStyle,\n maxLength,\n validateValue,\n onError,\n readonly = false,\n isEdit: propsIsEdit = false,\n}: IProps) => {\n const [isEdit, setIsEdit] = useState<boolean>(propsIsEdit);\n const [value, setValue] = useState(propsValue);\n\n useEffect(() => {\n setValue(propsValue);\n }, [propsValue]);\n\n const divRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const handleBlur = useCallback(() => {\n onConfirm?.(value);\n inputRef.current?.blur();\n }, [onConfirm, value]);\n\n useEffect(() => {\n if (!width && divRef.current && inputRef.current) {\n const tempWidth = divRef.current?.offsetWidth || defaultWidth;\n inputRef.current.style.width = tempWidth + PADDING_WIDTH + 'px';\n }\n }, [width, value, isEdit]);\n\n useEffect(() => {\n if (isEdit) {\n setValue(propsValue);\n }\n }, [isEdit, propsValue]);\n\n useEffect(() => {\n if (propsIsEdit) {\n setIsEdit(true);\n setTimeout(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n inputRef.current.select();\n }\n }, 100);\n } else {\n setIsEdit(false);\n }\n }, [propsIsEdit]);\n\n if (isEdit && !readonly) {\n return (\n <div className=\"ald-rename-input tw-flex tw-h-[22px] tw-min-w-[10px] tw-max-w-full tw-items-center tw-border tw-border-[var(--action-ghost-normal)]\">\n <input\n className={cn(\n className,\n 'ald-rename-input-wrapper tw-box-border tw-h-[22px] tw-max-w-full tw-border-0 tw-p-[2px] tw-text-[13px]',\n 'hover:tw-border hover:tw-border-solid hover:tw-border-[var(--border-neutral-strong)]',\n 'focus:tw-border focus:tw-border-solid focus:tw-border-[var(--border-brand-strong)] focus:tw-shadow-[0_0_0_1px_var(--border-brand-strong)]',\n )}\n style={{\n ...fontStyle,\n width,\n }}\n value={value}\n ref={inputRef}\n onChange={(e) => setValue(e.target.value)}\n onBlur={(e) => {\n if (!validateValue || validateValue(e.target.value.trim())) {\n handleBlur();\n } else {\n onError?.(value);\n setValue(propsValue);\n }\n setIsEdit(false);\n }}\n onFocus={() => {\n inputRef.current?.select();\n }}\n maxLength={maxLength}\n onKeyUp={(e) => {\n if (e.key === 'Enter') {\n if (\n !validateValue ||\n validateValue(inputRef.current?.value.trim() || '')\n ) {\n inputRef.current?.blur();\n } else {\n onError?.(inputRef.current?.value.trim() || '');\n setValue(propsValue);\n }\n }\n }}\n />\n <div\n ref={divRef}\n className=\"ald-rename-input-div tw-pointer-events-none tw-invisible tw-fixed tw-bottom-0 tw--ml-px tw-min-w-px tw-max-w-full tw-overflow-hidden tw-whitespace-pre tw-border tw-border-[var(--action-ghost-normal)] tw-p-0 tw-text-[13px] tw-font-normal\"\n style={fontStyle}\n >\n {value}\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n className,\n 'ald-rename-input-text tw-flex tw-h-[22px] tw-items-center tw-border tw-border-[var(--action-ghost-normal)] tw-p-[2px] tw-text-[13px]',\n )}\n style={fontStyle}\n onMouseMove={() => {\n setIsEdit(true);\n setValue(propsValue);\n }}\n onClick={() => {\n inputRef.current?.select();\n }}\n >\n {propsValue}\n </div>\n );\n};\n\nexport default RenameInput;\n"],"mappings":";;;;AA2BA,IAAM,eAAe;AAErB,IAAM,gBAAgB;AAEtB,IAAM,eAAe,EACnB,OAAO,YACP,WACA,WACA,OACA,WACA,WACA,eACA,SACA,WAAW,OACX,QAAQ,cAAc,YACV;CACZ,MAAM,CAAC,QAAQ,aAAa,SAAkB,YAAY;CAC1D,MAAM,CAAC,OAAO,YAAY,SAAS,WAAW;AAE9C,iBAAgB;AACd,WAAS,WAAW;IACnB,CAAC,WAAW,CAAC;CAEhB,MAAM,SAAS,OAAuB,KAAK;CAC3C,MAAM,WAAW,OAAyB,KAAK;CAE/C,MAAM,aAAa,kBAAkB;AACnC,cAAY,MAAM;AAClB,WAAS,SAAS,MAAM;IACvB,CAAC,WAAW,MAAM,CAAC;AAEtB,iBAAgB;AACd,MAAI,CAAC,SAAS,OAAO,WAAW,SAAS,SAAS;GAChD,MAAM,YAAY,OAAO,SAAS,eAAe;AACjD,YAAS,QAAQ,MAAM,QAAQ,YAAY,gBAAgB;;IAE5D;EAAC;EAAO;EAAO;EAAO,CAAC;AAE1B,iBAAgB;AACd,MAAI,OACF,UAAS,WAAW;IAErB,CAAC,QAAQ,WAAW,CAAC;AAExB,iBAAgB;AACd,MAAI,aAAa;AACf,aAAU,KAAK;AACf,oBAAiB;AACf,QAAI,SAAS,SAAS;AACpB,cAAS,QAAQ,OAAO;AACxB,cAAS,QAAQ,QAAQ;;MAE1B,IAAI;QAEP,WAAU,MAAM;IAEjB,CAAC,YAAY,CAAC;AAEjB,KAAI,UAAU,CAAC,SACb,QACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,SAAD;GACE,WAAW,GACT,WACA,0GACA,wFACA,4IACD;GACD,OAAO;IACL,GAAG;IACH;IACD;GACM;GACP,KAAK;GACL,WAAW,MAAM,SAAS,EAAE,OAAO,MAAM;GACzC,SAAS,MAAM;AACb,QAAI,CAAC,iBAAiB,cAAc,EAAE,OAAO,MAAM,MAAM,CAAC,CACxD,aAAY;SACP;AACL,eAAU,MAAM;AAChB,cAAS,WAAW;;AAEtB,cAAU,MAAM;;GAElB,eAAe;AACb,aAAS,SAAS,QAAQ;;GAEjB;GACX,UAAU,MAAM;AACd,QAAI,EAAE,QAAQ,QACZ,KACE,CAAC,iBACD,cAAc,SAAS,SAAS,MAAM,MAAM,IAAI,GAAG,CAEnD,UAAS,SAAS,MAAM;SACnB;AACL,eAAU,SAAS,SAAS,MAAM,MAAM,IAAI,GAAG;AAC/C,cAAS,WAAW;;;GAI1B,CAAA,EACF,oBAAC,OAAD;GACE,KAAK;GACL,WAAU;GACV,OAAO;aAEN;GACG,CAAA,CACF;;AAIV,QACE,oBAAC,OAAD;EACE,WAAW,GACT,WACA,uIACD;EACD,OAAO;EACP,mBAAmB;AACjB,aAAU,KAAK;AACf,YAAS,WAAW;;EAEtB,eAAe;AACb,YAAS,SAAS,QAAQ;;YAG3B;EACG,CAAA"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/RenameInput/index.tsx"],"sourcesContent":["import React, {\n CSSProperties,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { cn } from '../lib/utils';\n\ninterface IProps {\n value: string;\n onConfirm?: (value: string) => void;\n onError?: (value: string) => void;\n className?: string;\n width?: number;\n fontStyle?: CSSProperties;\n /**\n * @deprecated 如果要控制编辑态请使用 isEdit\n */\n focus?: boolean;\n isEdit?: boolean;\n maxLength?: number;\n distance?: [left: number, right: number];\n validateValue?: (value: string) => boolean;\n readonly?: boolean;\n}\n\nconst defaultWidth = 20;\n\nconst PADDING_WIDTH = 4;\n\nconst RenameInput = ({\n value: propsValue,\n onConfirm,\n className,\n width,\n fontStyle,\n maxLength,\n validateValue,\n onError,\n readonly = false,\n isEdit: propsIsEdit = false,\n}: IProps) => {\n const [isEdit, setIsEdit] = useState<boolean>(propsIsEdit);\n const [value, setValue] = useState(propsValue);\n\n useEffect(() => {\n setValue(propsValue);\n }, [propsValue]);\n\n const divRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const handleBlur = useCallback(() => {\n onConfirm?.(value);\n inputRef.current?.blur();\n }, [onConfirm, value]);\n\n useEffect(() => {\n if (!width && divRef.current && inputRef.current) {\n const tempWidth = divRef.current?.offsetWidth || defaultWidth;\n inputRef.current.style.width = tempWidth + PADDING_WIDTH + 'px';\n }\n }, [width, value, isEdit]);\n\n useEffect(() => {\n if (isEdit) {\n setValue(propsValue);\n }\n }, [isEdit, propsValue]);\n\n useEffect(() => {\n if (propsIsEdit) {\n setIsEdit(true);\n setTimeout(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n inputRef.current.select();\n }\n }, 100);\n } else {\n setIsEdit(false);\n }\n }, [propsIsEdit]);\n\n if (isEdit && !readonly) {\n return (\n <div className=\"ald-rename-input tw-flex tw-h-[22px] tw-min-w-[10px] tw-max-w-full tw-items-center tw-border tw-border-[var(--action-ghost-normal)]\">\n <input\n className={cn(\n className,\n 'ald-rename-input-wrapper tw-box-border tw-h-[22px] tw-max-w-full tw-border-0 tw-p-[2px] tw-text-[13px]',\n 'hover:tw-border hover:tw-border-solid hover:tw-border-[var(--border-neutral-strong)]',\n 'focus:tw-border focus:tw-border-solid focus:tw-border-[var(--border-brand-strong)] focus:tw-shadow-[0_0_0_1px_var(--border-brand-strong)]',\n )}\n style={{\n ...fontStyle,\n width,\n }}\n value={value}\n aria-label={`Rename ${propsValue}`}\n ref={inputRef}\n onChange={(e) => setValue(e.target.value)}\n onBlur={(e) => {\n if (!validateValue || validateValue(e.target.value.trim())) {\n handleBlur();\n } else {\n onError?.(value);\n setValue(propsValue);\n }\n setIsEdit(false);\n }}\n onFocus={() => {\n inputRef.current?.select();\n }}\n maxLength={maxLength}\n onKeyUp={(e) => {\n if (e.key === 'Enter') {\n if (\n !validateValue ||\n validateValue(inputRef.current?.value.trim() || '')\n ) {\n inputRef.current?.blur();\n } else {\n onError?.(inputRef.current?.value.trim() || '');\n setValue(propsValue);\n }\n }\n }}\n />\n <div\n ref={divRef}\n className=\"ald-rename-input-div tw-pointer-events-none tw-invisible tw-fixed tw-bottom-0 tw--ml-px tw-min-w-px tw-max-w-full tw-overflow-hidden tw-whitespace-pre tw-border tw-border-[var(--action-ghost-normal)] tw-p-0 tw-text-[13px] tw-font-normal\"\n style={fontStyle}\n >\n {value}\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n className,\n 'ald-rename-input-text tw-flex tw-h-[22px] tw-items-center tw-border tw-border-[var(--action-ghost-normal)] tw-p-[2px] tw-text-[13px]',\n )}\n style={fontStyle}\n role={!readonly ? 'button' : undefined}\n tabIndex={!readonly ? 0 : undefined}\n aria-label={!readonly ? `Edit ${propsValue}` : undefined}\n onMouseMove={() => {\n setIsEdit(true);\n setValue(propsValue);\n }}\n onClick={() => {\n inputRef.current?.select();\n }}\n onKeyDown={(e) => {\n if (!readonly && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n setIsEdit(true);\n setValue(propsValue);\n }\n }}\n >\n {propsValue}\n </div>\n );\n};\n\nexport default RenameInput;\n"],"mappings":";;;;AA2BA,IAAM,eAAe;AAErB,IAAM,gBAAgB;AAEtB,IAAM,eAAe,EACnB,OAAO,YACP,WACA,WACA,OACA,WACA,WACA,eACA,SACA,WAAW,OACX,QAAQ,cAAc,YACV;CACZ,MAAM,CAAC,QAAQ,aAAa,SAAkB,YAAY;CAC1D,MAAM,CAAC,OAAO,YAAY,SAAS,WAAW;AAE9C,iBAAgB;AACd,WAAS,WAAW;IACnB,CAAC,WAAW,CAAC;CAEhB,MAAM,SAAS,OAAuB,KAAK;CAC3C,MAAM,WAAW,OAAyB,KAAK;CAE/C,MAAM,aAAa,kBAAkB;AACnC,cAAY,MAAM;AAClB,WAAS,SAAS,MAAM;IACvB,CAAC,WAAW,MAAM,CAAC;AAEtB,iBAAgB;AACd,MAAI,CAAC,SAAS,OAAO,WAAW,SAAS,SAAS;GAChD,MAAM,YAAY,OAAO,SAAS,eAAe;AACjD,YAAS,QAAQ,MAAM,QAAQ,YAAY,gBAAgB;;IAE5D;EAAC;EAAO;EAAO;EAAO,CAAC;AAE1B,iBAAgB;AACd,MAAI,OACF,UAAS,WAAW;IAErB,CAAC,QAAQ,WAAW,CAAC;AAExB,iBAAgB;AACd,MAAI,aAAa;AACf,aAAU,KAAK;AACf,oBAAiB;AACf,QAAI,SAAS,SAAS;AACpB,cAAS,QAAQ,OAAO;AACxB,cAAS,QAAQ,QAAQ;;MAE1B,IAAI;QAEP,WAAU,MAAM;IAEjB,CAAC,YAAY,CAAC;AAEjB,KAAI,UAAU,CAAC,SACb,QACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,SAAD;GACE,WAAW,GACT,WACA,0GACA,wFACA,4IACD;GACD,OAAO;IACL,GAAG;IACH;IACD;GACM;GACP,cAAY,UAAU;GACtB,KAAK;GACL,WAAW,MAAM,SAAS,EAAE,OAAO,MAAM;GACzC,SAAS,MAAM;AACb,QAAI,CAAC,iBAAiB,cAAc,EAAE,OAAO,MAAM,MAAM,CAAC,CACxD,aAAY;SACP;AACL,eAAU,MAAM;AAChB,cAAS,WAAW;;AAEtB,cAAU,MAAM;;GAElB,eAAe;AACb,aAAS,SAAS,QAAQ;;GAEjB;GACX,UAAU,MAAM;AACd,QAAI,EAAE,QAAQ,QACZ,KACE,CAAC,iBACD,cAAc,SAAS,SAAS,MAAM,MAAM,IAAI,GAAG,CAEnD,UAAS,SAAS,MAAM;SACnB;AACL,eAAU,SAAS,SAAS,MAAM,MAAM,IAAI,GAAG;AAC/C,cAAS,WAAW;;;GAI1B,CAAA,EACF,oBAAC,OAAD;GACE,KAAK;GACL,WAAU;GACV,OAAO;aAEN;GACG,CAAA,CACF;;AAIV,QACE,oBAAC,OAAD;EACE,WAAW,GACT,WACA,uIACD;EACD,OAAO;EACP,MAAM,CAAC,WAAW,WAAW;EAC7B,UAAU,CAAC,WAAW,IAAI;EAC1B,cAAY,CAAC,WAAW,QAAQ,eAAe;EAC/C,mBAAmB;AACjB,aAAU,KAAK;AACf,YAAS,WAAW;;EAEtB,eAAe;AACb,YAAS,SAAS,QAAQ;;EAE5B,YAAY,MAAM;AAChB,OAAI,CAAC,aAAa,EAAE,QAAQ,WAAW,EAAE,QAAQ,MAAM;AACrD,MAAE,gBAAgB;AAClB,cAAU,KAAK;AACf,aAAS,WAAW;;;YAIvB;EACG,CAAA"}
@@ -1,5 +1,6 @@
1
1
  import { PlacementType } from '../Dropdown';
2
2
  import { BaseSelectRef, ISelectProps, LabelInValueType, SelectMenuProps } from './interface.js';
3
+ import { SelectOptionCollection } from './components/OptionCollection.js';
3
4
  import * as React from 'react';
4
5
  /** Align config type (locally defined to avoid rc-trigger dependency) */
5
6
  export interface AlignType {
@@ -50,10 +51,12 @@ export interface BaseSelectProps extends BaseSelectPrivateProps, ISelectProps, R
50
51
  innerSearchValue?: string;
51
52
  setInnerSearchValue?: (value: string) => void;
52
53
  displayMenu?: SelectMenuProps;
54
+ optionCollection?: SelectOptionCollection;
53
55
  open?: boolean;
54
56
  defaultOpen?: boolean;
55
57
  onOpenChange?: (open: boolean) => void;
56
58
  onOptionSelect?: (val: RawValueType) => void;
59
+ onCollectionOptionSelect?: (val: RawValueType) => void;
57
60
  allowClear?: boolean;
58
61
  showArrow?: boolean;
59
62
  suffixIcon?: React.ReactNode;
@@ -10,12 +10,23 @@ import Selector from "./Selector/index.js";
10
10
  import { FormItemInputContext } from "../Form/FormItemContext.js";
11
11
  import getWidthStyle from "./utils/getWidthStyle.js";
12
12
  import { ConfigContext } from "../ConfigProvider/index.js";
13
+ import OptionCollection from "./components/OptionCollection.js";
13
14
  import * as React$1 from "react";
14
15
  import { useContext, useRef, useState } from "react";
15
- import { jsx, jsxs } from "react/jsx-runtime";
16
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
16
17
  import _ from "lodash";
17
18
  import useMergedState from "rc-util/es/hooks/useMergedState";
18
19
  //#region src/Select/BaseSelect.tsx
20
+ function splitAriaProps(props) {
21
+ return Object.keys(props).reduce((result, key) => {
22
+ if (key.startsWith("aria-")) result.ariaProps[key] = props[key];
23
+ else result.restProps[key] = props[key];
24
+ return result;
25
+ }, {
26
+ ariaProps: {},
27
+ restProps: {}
28
+ });
29
+ }
19
30
  function isMultiple(mode) {
20
31
  return !!mode;
21
32
  }
@@ -27,10 +38,16 @@ function isShowSelectedSection(mode) {
27
38
  return typeof mode === "object" && mode.showSelectedSection && mode.responsive;
28
39
  }
29
40
  var BaseSelect = React$1.forwardRef((props, ref) => {
30
- const { id, className, displayValues, onDisplayValuesChange, displayMenu, notFoundContent, onClear, width, mode, status: customStatus, onOptionSelect, onClick, size: customSize, borderLess = false, disabled, placeholder, loading = false, open, defaultOpen, onOpenChange, showSearch, innerSearchValue, setInnerSearchValue, allowClear, showArrow = true, prefix, suffixIcon, dropdownRender, overlayStyle, dropdownStyle, popupMatchSelectWidth = true, placement, popupClassName, allowOverlap, style, "data-testid": dataTestid, "aria-label": ariaLabel, ...restProps } = props;
41
+ const { id, className, displayValues, onDisplayValuesChange, displayMenu, optionCollection, notFoundContent, onClear, width, mode, status: customStatus, onOptionSelect, onCollectionOptionSelect, onClick, size: customSize, borderLess = false, disabled, placeholder, loading = false, open, defaultOpen, onOpenChange, showSearch, innerSearchValue, setInnerSearchValue, onInputKeyDown, allowClear, showArrow = true, prefix, suffixIcon, dropdownRender, overlayStyle, dropdownStyle, popupMatchSelectWidth = true, placement, popupClassName, allowOverlap, style, "data-testid": dataTestid, "aria-label": ariaLabel, ...restProps } = props;
42
+ const { ariaProps, restProps: passthroughProps } = React$1.useMemo(() => splitAriaProps(restProps), [restProps]);
43
+ const triggerAriaProps = React$1.useMemo(() => ({
44
+ ...ariaProps,
45
+ "aria-label": ariaLabel
46
+ }), [ariaLabel, ariaProps]);
31
47
  const setClassNames = prefixCls("select");
32
48
  const selectRef = useRef(null);
33
49
  const triggerRef = useRef(null);
50
+ const searchInputRef = useRef(null);
34
51
  const widthStyle = getWidthStyle(width);
35
52
  const dropdownRef = useRef(null);
36
53
  const [matchedPopupWidth, setMatchedPopupWidth] = useState();
@@ -44,8 +61,14 @@ var BaseSelect = React$1.forwardRef((props, ref) => {
44
61
  const { status: contextStatus } = useContext(FormItemInputContext);
45
62
  const mergedStatus = customStatus === null ? void 0 : customStatus || contextStatus;
46
63
  React$1.useImperativeHandle(ref, () => ({
47
- focus: () => triggerRef.current?.focus(),
48
- blur: () => triggerRef.current?.blur(),
64
+ focus: () => {
65
+ if (showSearch && optionCollection) searchInputRef.current?.focus();
66
+ else triggerRef.current?.focus();
67
+ },
68
+ blur: () => {
69
+ if (showSearch && optionCollection) searchInputRef.current?.blur();
70
+ else triggerRef.current?.blur();
71
+ },
49
72
  open: () => onToggleOpen(true),
50
73
  close: () => {
51
74
  console.log("ref close");
@@ -53,6 +76,19 @@ var BaseSelect = React$1.forwardRef((props, ref) => {
53
76
  }
54
77
  }));
55
78
  const [isHover, setIsHover] = useState(false);
79
+ const [activeOptionKey, setActiveOptionKey] = useState();
80
+ const [composingSearchValue, setComposingSearchValue] = useState();
81
+ const isComposingSearchRef = useRef(false);
82
+ const isSearchableCollection = !!optionCollection && !!showSearch;
83
+ const ownerAriaProps = React$1.useMemo(() => ({
84
+ ...triggerAriaProps,
85
+ "aria-busy": loading || triggerAriaProps["aria-busy"] || void 0,
86
+ "aria-invalid": triggerAriaProps["aria-invalid"] ?? (mergedStatus === "error" ? true : void 0)
87
+ }), [
88
+ loading,
89
+ mergedStatus,
90
+ triggerAriaProps
91
+ ]);
56
92
  const [innerOpen, setInnerOpen] = useMergedState(false, {
57
93
  defaultValue: defaultOpen,
58
94
  value: open
@@ -79,6 +115,22 @@ var BaseSelect = React$1.forwardRef((props, ref) => {
79
115
  onOpenChange,
80
116
  updateMatchedPopupWidth
81
117
  ]);
118
+ const getInitialActiveOptionKey = React$1.useCallback((position) => {
119
+ if (!optionCollection) return;
120
+ if (position === "last") return optionCollection.enabledOptions[optionCollection.enabledOptions.length - 1]?.key;
121
+ return optionCollection.options.find((option) => !option.disabled && displayValues.some((value) => toString(value.value) === toString(option.value)))?.key ?? optionCollection.enabledOptions[0]?.key;
122
+ }, [displayValues, optionCollection]);
123
+ React$1.useEffect(() => {
124
+ if (!optionCollection || !mergedOpen) {
125
+ setActiveOptionKey(void 0);
126
+ return;
127
+ }
128
+ setActiveOptionKey((current) => optionCollection.enabledOptions.some((option) => option.key === current) ? current : getInitialActiveOptionKey("first"));
129
+ }, [
130
+ getInitialActiveOptionKey,
131
+ mergedOpen,
132
+ optionCollection
133
+ ]);
82
134
  React$1.useLayoutEffect(() => {
83
135
  if (!mergedOpen || !shouldMatchPopupWidth) return;
84
136
  const element = selectRef.current;
@@ -164,6 +216,124 @@ var BaseSelect = React$1.forwardRef((props, ref) => {
164
216
  }
165
217
  }, []);
166
218
  const mergedPopupMatchSelectWidth = shouldMatchPopupWidth && matchedPopupWidth !== void 0 ? matchedPopupWidth : popupMatchSelectWidth;
219
+ const activeOptionId = optionCollection?.options.find((option) => option.key === activeOptionKey)?.id;
220
+ const moveActiveOption = React$1.useCallback((direction) => {
221
+ if (!optionCollection || optionCollection.enabledOptions.length === 0) return;
222
+ const currentIndex = optionCollection.enabledOptions.findIndex((option) => option.key === activeOptionKey);
223
+ const nextIndex = currentIndex === -1 ? direction === 1 ? 0 : optionCollection.enabledOptions.length - 1 : (currentIndex + direction + optionCollection.enabledOptions.length) % optionCollection.enabledOptions.length;
224
+ setActiveOptionKey(optionCollection.enabledOptions[nextIndex].key);
225
+ }, [activeOptionKey, optionCollection]);
226
+ const typeaheadRef = useRef({
227
+ value: "",
228
+ timestamp: 0
229
+ });
230
+ const onCollectionKeyDown = React$1.useCallback((event) => {
231
+ if (!optionCollection || disabled) return;
232
+ const openCollection = (position) => {
233
+ event.preventDefault();
234
+ setActiveOptionKey(getInitialActiveOptionKey(position));
235
+ onToggleOpen(true);
236
+ };
237
+ if (!mergedOpen) {
238
+ if (event.key === "ArrowDown") openCollection("first");
239
+ else if (event.key === "ArrowUp") openCollection("last");
240
+ else if (event.key === "Enter" || event.key === " ") openCollection("first");
241
+ return;
242
+ }
243
+ if (event.key === "ArrowDown") {
244
+ event.preventDefault();
245
+ moveActiveOption(1);
246
+ return;
247
+ }
248
+ if (event.key === "ArrowUp") {
249
+ event.preventDefault();
250
+ moveActiveOption(-1);
251
+ return;
252
+ }
253
+ if (event.key === "Home") {
254
+ event.preventDefault();
255
+ setActiveOptionKey(optionCollection.enabledOptions[0]?.key);
256
+ return;
257
+ }
258
+ if (event.key === "End") {
259
+ event.preventDefault();
260
+ setActiveOptionKey(optionCollection.enabledOptions[optionCollection.enabledOptions.length - 1]?.key);
261
+ return;
262
+ }
263
+ if (event.key === "Enter" || event.key === " ") {
264
+ event.preventDefault();
265
+ const activeOption = optionCollection.options.find((option) => option.key === activeOptionKey);
266
+ if (activeOption && !activeOption.disabled) {
267
+ if (!isMultipleMode) onToggleOpen(false);
268
+ onCollectionOptionSelect?.(activeOption.value);
269
+ }
270
+ return;
271
+ }
272
+ if (event.key === "Escape") {
273
+ event.preventDefault();
274
+ onToggleOpen(false);
275
+ if (isSearchableCollection) searchInputRef.current?.focus();
276
+ else triggerRef.current?.focus();
277
+ return;
278
+ }
279
+ if (event.key === "Tab") {
280
+ onToggleOpen(false);
281
+ return;
282
+ }
283
+ if (event.key.length === 1 && !event.altKey && !event.ctrlKey && !event.metaKey) {
284
+ const now = Date.now();
285
+ const query = now - typeaheadRef.current.timestamp > 500 ? event.key : `${typeaheadRef.current.value}${event.key}`;
286
+ typeaheadRef.current = {
287
+ value: query,
288
+ timestamp: now
289
+ };
290
+ const normalizedQuery = query.toLocaleLowerCase();
291
+ const activeIndex = optionCollection.enabledOptions.findIndex((option) => option.key === activeOptionKey);
292
+ const match = [...optionCollection.enabledOptions.slice(activeIndex + 1), ...optionCollection.enabledOptions.slice(0, activeIndex + 1)].find((option) => String(option.label ?? option.value).toLocaleLowerCase().startsWith(normalizedQuery));
293
+ if (match) {
294
+ event.preventDefault();
295
+ setActiveOptionKey(match.key);
296
+ }
297
+ }
298
+ }, [
299
+ activeOptionKey,
300
+ disabled,
301
+ getInitialActiveOptionKey,
302
+ mergedOpen,
303
+ moveActiveOption,
304
+ onCollectionOptionSelect,
305
+ onToggleOpen,
306
+ optionCollection,
307
+ isSearchableCollection
308
+ ]);
309
+ const onSearchInputKeyDown = React$1.useCallback((event) => {
310
+ onInputKeyDown?.(event);
311
+ if (event.defaultPrevented) return;
312
+ if (event.key === " " || event.key.length === 1 && !event.altKey && !event.ctrlKey && !event.metaKey) return;
313
+ onCollectionKeyDown(event);
314
+ }, [onCollectionKeyDown, onInputKeyDown]);
315
+ const onSearchInputChange = React$1.useCallback((event) => {
316
+ const nextValue = event.target.value;
317
+ if (isComposingSearchRef.current) {
318
+ setComposingSearchValue(nextValue);
319
+ return;
320
+ }
321
+ setInnerSearchValue?.(nextValue);
322
+ }, [setInnerSearchValue]);
323
+ const searchInputValue = composingSearchValue ?? innerSearchValue ?? "";
324
+ const collectionContent = optionCollection ? /* @__PURE__ */ jsx(OptionCollection, {
325
+ collection: optionCollection,
326
+ selectedValues: displayValues.map((item) => item.value),
327
+ activeOptionKey,
328
+ multiple: isMultipleMode,
329
+ loading,
330
+ listHeight: props.listHeight ?? 256,
331
+ notFoundContent,
332
+ onSelect: (value) => {
333
+ if (!isMultipleMode) onToggleOpen(false);
334
+ onCollectionOptionSelect?.(value);
335
+ }
336
+ }) : void 0;
167
337
  return /* @__PURE__ */ jsxs("div", {
168
338
  className: mergedClassName,
169
339
  style: {
@@ -177,10 +347,11 @@ var BaseSelect = React$1.forwardRef((props, ref) => {
177
347
  "data-testid": dataTestid,
178
348
  "aria-label": ariaLabel,
179
349
  children: [/* @__PURE__ */ jsx(RefSelectTrigger, {
180
- ...restProps,
350
+ ...passthroughProps,
181
351
  open: !!mergedOpen,
182
352
  notFoundContent,
183
353
  menu: showMenu,
354
+ collection: collectionContent,
184
355
  ref: dropdownRef,
185
356
  showSearch,
186
357
  searchValue: innerSearchValue,
@@ -197,35 +368,61 @@ var BaseSelect = React$1.forwardRef((props, ref) => {
197
368
  else onToggleOpen(open);
198
369
  },
199
370
  children: /* @__PURE__ */ jsxs("div", {
371
+ ...!isSearchableCollection ? ownerAriaProps : {},
200
372
  ref: triggerRef,
201
- tabIndex: disabled ? void 0 : 0,
202
- role: "combobox",
203
- "aria-disabled": disabled || void 0,
204
- "aria-expanded": mergedOpen,
373
+ tabIndex: isSearchableCollection || disabled ? void 0 : 0,
374
+ role: isSearchableCollection ? void 0 : "combobox",
375
+ "aria-disabled": isSearchableCollection ? void 0 : disabled || void 0,
376
+ "aria-expanded": isSearchableCollection ? void 0 : mergedOpen,
377
+ "aria-haspopup": isSearchableCollection ? void 0 : optionCollection ? "listbox" : void 0,
378
+ "aria-controls": isSearchableCollection ? void 0 : mergedOpen && optionCollection ? optionCollection.listboxId : void 0,
379
+ "aria-activedescendant": isSearchableCollection ? void 0 : mergedOpen && optionCollection ? activeOptionId : void 0,
380
+ onKeyDown: isSearchableCollection ? void 0 : optionCollection ? onCollectionKeyDown : void 0,
205
381
  className: cn(setClassNames("trigger"), "ant-select-selector"),
206
- children: [
207
- prefix && /* @__PURE__ */ jsx("div", {
208
- className: setClassNames("prefix"),
209
- children: prefix
210
- }),
211
- _.isEmpty(displayValues) && /* @__PURE__ */ jsx("div", {
212
- className: cn(setClassNames("placeholder"), "ant-select-selection-placeholder"),
213
- children: placeholder
214
- }),
215
- !_.isEmpty(displayValues) && /* @__PURE__ */ jsx(Selector, {
216
- ...restProps,
217
- suffixIcon,
218
- size,
219
- disabled,
220
- mode,
221
- dropdownRef,
222
- displayValues,
223
- onToggleOpen,
224
- onRemove: onSelectorRemove,
225
- showResponsiveSelectedSection,
226
- onOverflowCollapsedChange: setOverflowCollapsed
227
- })
228
- ]
382
+ children: [prefix && /* @__PURE__ */ jsx("div", {
383
+ className: setClassNames("prefix"),
384
+ children: prefix
385
+ }), isSearchableCollection ? /* @__PURE__ */ jsx("input", {
386
+ ...ownerAriaProps,
387
+ ref: searchInputRef,
388
+ type: "text",
389
+ role: "combobox",
390
+ className: setClassNames("search-input"),
391
+ value: searchInputValue,
392
+ disabled,
393
+ placeholder: typeof placeholder === "string" ? placeholder : void 0,
394
+ "aria-disabled": disabled || void 0,
395
+ "aria-expanded": mergedOpen,
396
+ "aria-haspopup": "listbox",
397
+ "aria-controls": mergedOpen ? optionCollection?.listboxId : void 0,
398
+ "aria-activedescendant": mergedOpen ? activeOptionId : void 0,
399
+ onFocus: () => onToggleOpen(true),
400
+ onChange: onSearchInputChange,
401
+ onCompositionStart: () => {
402
+ isComposingSearchRef.current = true;
403
+ },
404
+ onCompositionEnd: (event) => {
405
+ isComposingSearchRef.current = false;
406
+ setComposingSearchValue(void 0);
407
+ setInnerSearchValue?.(event.currentTarget.value);
408
+ },
409
+ onKeyDown: onSearchInputKeyDown
410
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [_.isEmpty(displayValues) && /* @__PURE__ */ jsx("div", {
411
+ className: cn(setClassNames("placeholder"), "ant-select-selection-placeholder"),
412
+ children: placeholder
413
+ }), !_.isEmpty(displayValues) && /* @__PURE__ */ jsx(Selector, {
414
+ ...passthroughProps,
415
+ suffixIcon,
416
+ size,
417
+ disabled,
418
+ mode,
419
+ dropdownRef,
420
+ displayValues,
421
+ onToggleOpen,
422
+ onRemove: onSelectorRemove,
423
+ showResponsiveSelectedSection,
424
+ onOverflowCollapsedChange: setOverflowCollapsed
425
+ })] })]
229
426
  })
230
427
  }), /* @__PURE__ */ jsx(Suffix, {
231
428
  showArrow,