@aloudata/aloudata-design 3.0.27 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/dist/AProgress/index.js +10 -0
  2. package/dist/AProgress/index.js.map +1 -1
  3. package/dist/Alert/index.js +3 -1
  4. package/dist/Alert/index.js.map +1 -1
  5. package/dist/Badge/index.js +37 -11
  6. package/dist/Badge/index.js.map +1 -1
  7. package/dist/Breadcrumb/index.js +12 -2
  8. package/dist/Breadcrumb/index.js.map +1 -1
  9. package/dist/Button/index.d.ts +1 -1
  10. package/dist/Button/index.js +29 -9
  11. package/dist/Button/index.js.map +1 -1
  12. package/dist/Card/index.js +1 -1
  13. package/dist/Card/index.js.map +1 -1
  14. package/dist/Carousel/index.js +9 -1
  15. package/dist/Carousel/index.js.map +1 -1
  16. package/dist/Checkbox/index.js +25 -4
  17. package/dist/Checkbox/index.js.map +1 -1
  18. package/dist/Checkbox/type.d.ts +10 -2
  19. package/dist/Collapse/index.js +68 -22
  20. package/dist/Collapse/index.js.map +1 -1
  21. package/dist/ColorPicker/index.js +112 -46
  22. package/dist/ColorPicker/index.js.map +1 -1
  23. package/dist/DataPreviewTable/components/Body/Cell.d.ts +2 -0
  24. package/dist/DataPreviewTable/components/Body/Cell.js +9 -1
  25. package/dist/DataPreviewTable/components/Body/Cell.js.map +1 -1
  26. package/dist/DataPreviewTable/components/Body/index.d.ts +1 -0
  27. package/dist/DataPreviewTable/components/Body/index.js +35 -23
  28. package/dist/DataPreviewTable/components/Body/index.js.map +1 -1
  29. package/dist/DataPreviewTable/components/Header/index.d.ts +1 -0
  30. package/dist/DataPreviewTable/components/Header/index.js +36 -28
  31. package/dist/DataPreviewTable/components/Header/index.js.map +1 -1
  32. package/dist/DataPreviewTable/index.js +19 -2
  33. package/dist/DataPreviewTable/index.js.map +1 -1
  34. package/dist/Drawer/index.d.ts +4 -0
  35. package/dist/Drawer/index.js +91 -78
  36. package/dist/Drawer/index.js.map +1 -1
  37. package/dist/Dropdown/index.d.ts +1 -1
  38. package/dist/Dropdown/index.js +116 -98
  39. package/dist/Dropdown/index.js.map +1 -1
  40. package/dist/Form/FormItemContext.d.ts +1 -1
  41. package/dist/Form/FormItemContext.js.map +1 -1
  42. package/dist/Form/index.js +50 -7
  43. package/dist/Form/index.js.map +1 -1
  44. package/dist/IconButton/index.d.ts +2 -2
  45. package/dist/IconButton/index.js +9 -3
  46. package/dist/IconButton/index.js.map +1 -1
  47. package/dist/Input/components/Input/index.js +23 -7
  48. package/dist/Input/components/Input/index.js.map +1 -1
  49. package/dist/Input/components/TextArea/index.js +20 -2
  50. package/dist/Input/components/TextArea/index.js.map +1 -1
  51. package/dist/Input/privateSemanticOwner.d.ts +2 -0
  52. package/dist/Input/privateSemanticOwner.js +1 -0
  53. package/dist/InputNumber/index.js +19 -5
  54. package/dist/InputNumber/index.js.map +1 -1
  55. package/dist/InputNumber/type.d.ts +2 -2
  56. package/dist/LogicTree/components/LogicItem/index.d.ts +2 -1
  57. package/dist/LogicTree/components/LogicItem/index.js +13 -2
  58. package/dist/LogicTree/components/LogicItem/index.js.map +1 -1
  59. package/dist/LogicTree/index.js +2 -0
  60. package/dist/LogicTree/index.js.map +1 -1
  61. package/dist/MemberPicker/components/MemberSelection.d.ts +1 -0
  62. package/dist/MemberPicker/components/MemberSelection.js +83 -94
  63. package/dist/MemberPicker/components/MemberSelection.js.map +1 -1
  64. package/dist/MemberPicker/components/MultipleOption.js +12 -0
  65. package/dist/MemberPicker/components/MultipleOption.js.map +1 -1
  66. package/dist/MemberPicker/components/Panel.d.ts +1 -0
  67. package/dist/MemberPicker/components/Panel.js +4 -1
  68. package/dist/MemberPicker/components/Panel.js.map +1 -1
  69. package/dist/MemberPicker/components/SelectedMemberTags.js +14 -6
  70. package/dist/MemberPicker/components/SelectedMemberTags.js.map +1 -1
  71. package/dist/MemberPicker/components/SingleOption.js +12 -0
  72. package/dist/MemberPicker/components/SingleOption.js.map +1 -1
  73. package/dist/MemberPicker/components/UserGroupSelection.d.ts +2 -1
  74. package/dist/MemberPicker/components/UserGroupSelection.js +61 -48
  75. package/dist/MemberPicker/components/UserGroupSelection.js.map +1 -1
  76. package/dist/MemberPicker/index.js +134 -108
  77. package/dist/MemberPicker/index.js.map +1 -1
  78. package/dist/Menu/index.d.ts +8 -0
  79. package/dist/Menu/index.js +33 -3
  80. package/dist/Menu/index.js.map +1 -1
  81. package/dist/Modal/index.d.ts +4 -0
  82. package/dist/Modal/index.js +55 -66
  83. package/dist/Modal/index.js.map +1 -1
  84. package/dist/OverflowCount/index.js +10 -0
  85. package/dist/OverflowCount/index.js.map +1 -1
  86. package/dist/Pagination/PageSizeChanger.d.ts +1 -0
  87. package/dist/Pagination/PageSizeChanger.js +3 -2
  88. package/dist/Pagination/PageSizeChanger.js.map +1 -1
  89. package/dist/Pagination/index.js +34 -19
  90. package/dist/Pagination/index.js.map +1 -1
  91. package/dist/Pagination/types.d.ts +3 -0
  92. package/dist/Popconfirm/index.js +9 -1
  93. package/dist/Popconfirm/index.js.map +1 -1
  94. package/dist/Popover/index.js +52 -1
  95. package/dist/Popover/index.js.map +1 -1
  96. package/dist/Progress/index.js +4 -0
  97. package/dist/Progress/index.js.map +1 -1
  98. package/dist/Radio/components/Group/index.d.ts +5 -1
  99. package/dist/Radio/components/Group/index.js +7 -2
  100. package/dist/Radio/components/Group/index.js.map +1 -1
  101. package/dist/Radio/components/Radio/index.js +27 -1
  102. package/dist/Radio/components/Radio/index.js.map +1 -1
  103. package/dist/Radio/interface/radio.d.ts +7 -0
  104. package/dist/Radio/interface/radioGroup.d.ts +2 -0
  105. package/dist/RenameInput/index.js +11 -0
  106. package/dist/RenameInput/index.js.map +1 -1
  107. package/dist/Select/BaseSelect.d.ts +3 -0
  108. package/dist/Select/BaseSelect.js +235 -38
  109. package/dist/Select/BaseSelect.js.map +1 -1
  110. package/dist/Select/SelectTrigger.d.ts +2 -0
  111. package/dist/Select/SelectTrigger.js +13 -5
  112. package/dist/Select/SelectTrigger.js.map +1 -1
  113. package/dist/Select/Selector/FixedOverflow.d.ts +1 -0
  114. package/dist/Select/Selector/FixedOverflow.js +3 -3
  115. package/dist/Select/Selector/FixedOverflow.js.map +1 -1
  116. package/dist/Select/Selector/MultipleSelector.js +1 -0
  117. package/dist/Select/Selector/MultipleSelector.js.map +1 -1
  118. package/dist/Select/components/OptionCollection.d.ts +41 -0
  119. package/dist/Select/components/OptionCollection.js +124 -0
  120. package/dist/Select/components/OptionCollection.js.map +1 -0
  121. package/dist/Select/index.js +45 -3
  122. package/dist/Select/index.js.map +1 -1
  123. package/dist/Select/interface.d.ts +1 -1
  124. package/dist/Skeleton/index.js +1 -1
  125. package/dist/Skeleton/index.js.map +1 -1
  126. package/dist/Spin/index.d.ts +1 -1
  127. package/dist/Spin/index.js +22 -7
  128. package/dist/Spin/index.js.map +1 -1
  129. package/dist/Steps/index.js +66 -14
  130. package/dist/Steps/index.js.map +1 -1
  131. package/dist/Switch/index.d.ts +5 -0
  132. package/dist/Switch/index.js +22 -5
  133. package/dist/Switch/index.js.map +1 -1
  134. package/dist/Table/components/Cell.js +8 -3
  135. package/dist/Table/components/Cell.js.map +1 -1
  136. package/dist/Table/components/ExpandCell.js +6 -2
  137. package/dist/Table/components/ExpandCell.js.map +1 -1
  138. package/dist/Table/components/Footer/index.js +2 -1
  139. package/dist/Table/components/Footer/index.js.map +1 -1
  140. package/dist/Table/components/Header.js +25 -18
  141. package/dist/Table/components/Header.js.map +1 -1
  142. package/dist/Table/hooks/useRowSelection.js +14 -7
  143. package/dist/Table/hooks/useRowSelection.js.map +1 -1
  144. package/dist/Table/index.js +50 -29
  145. package/dist/Table/index.js.map +1 -1
  146. package/dist/Tabs/index.d.ts +1 -1
  147. package/dist/Tabs/index.js +92 -11
  148. package/dist/Tabs/index.js.map +1 -1
  149. package/dist/Tag/index.js +20 -1
  150. package/dist/Tag/index.js.map +1 -1
  151. package/dist/Tooltip/index.js +34 -5
  152. package/dist/Tooltip/index.js.map +1 -1
  153. package/dist/Tour/index.js +13 -1
  154. package/dist/Tour/index.js.map +1 -1
  155. package/dist/Tree/Tree2.js +2 -0
  156. package/dist/Tree/Tree2.js.map +1 -1
  157. package/dist/_utils/dialogAccessibility.d.ts +17 -0
  158. package/dist/_utils/dialogAccessibility.js +110 -0
  159. package/dist/_utils/dialogAccessibility.js.map +1 -0
  160. package/dist/_utils/formControlSemanticOwner.d.ts +3 -0
  161. package/dist/_utils/formControlSemanticOwner.js +17 -0
  162. package/dist/_utils/formControlSemanticOwner.js.map +1 -0
  163. package/dist/_utils/overlayCoordinator.js +1 -11
  164. package/dist/_utils/overlayCoordinator.js.map +1 -1
  165. package/dist/aloudata-design.css +1 -1
  166. package/dist/locale/default.d.ts +6 -0
  167. package/dist/locale/en_US.d.ts +6 -0
  168. package/dist/locale/en_US.js +6 -0
  169. package/dist/locale/en_US.js.map +1 -1
  170. package/dist/locale/zh_CN.d.ts +6 -0
  171. package/dist/locale/zh_CN.js +6 -0
  172. package/dist/locale/zh_CN.js.map +1 -1
  173. package/dist/theme/contract/baselineResolvedTokenValueManifest.d.ts +1 -1
  174. package/dist/theme/contract/controlStateColorArtifact.d.ts +73 -0
  175. package/dist/theme/contract/controlStateColorArtifact.js +2 -0
  176. package/dist/theme/contract/darkResolvedTokenValueManifest.d.ts +1 -1
  177. package/dist/theme/contract/focusRingArtifact.d.ts +51 -0
  178. package/dist/theme/contract/focusRingArtifact.js +2 -0
  179. package/dist/theme/contract/tokenOutputContract.d.ts +1 -1
  180. package/dist/theme/contract/tokenOutputContract.js +4 -0
  181. package/dist/theme/contract/tokenOutputContract.js.map +1 -1
  182. package/dist/theme/generator/acceptedColorValues.d.ts +2 -1
  183. package/dist/theme/generator/baselineTokenValueDelivery.d.ts +9 -1
  184. package/dist/theme/generator/minimalAcceptedColorValues.d.ts +2 -2
  185. package/dist/theme/generator/neutralSourceResolver.d.ts +28 -0
  186. package/dist/theme/generator/neutralSourceResolver.js +2 -0
  187. package/dist/theme/generator/neutralSourceValues.d.ts +27 -0
  188. package/dist/theme/generator/neutralSourceValues.js +2 -0
  189. package/dist/theme/index.d.ts +2 -0
  190. package/dist/theme/index.js +1 -0
  191. package/dist/theme/neutralSourceContract.d.ts +3 -0
  192. package/dist/theme/neutralSourceContract.js +11 -0
  193. package/dist/theme/neutralSourceContract.js.map +1 -0
  194. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.d.ts +1 -1
  195. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js +47 -44
  196. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js.map +1 -1
  197. package/dist/theme/runtime/colorValueMode/generated/slateDarkDeclarations.d.ts +3 -0
  198. package/dist/theme/runtime/colorValueMode/generated/slateDarkDeclarations.js +2 -0
  199. package/dist/theme/runtime/colorValueMode/generated/slateLightDeclarations.d.ts +3 -0
  200. package/dist/theme/runtime/colorValueMode/generated/slateLightDeclarations.js +2 -0
  201. package/dist/theme/runtime/colorValueMode/generated/stoneDarkDeclarations.d.ts +3 -0
  202. package/dist/theme/runtime/colorValueMode/generated/stoneDarkDeclarations.js +2 -0
  203. package/dist/theme/runtime/colorValueMode/generated/stoneLightDeclarations.d.ts +3 -0
  204. package/dist/theme/runtime/colorValueMode/generated/stoneLightDeclarations.js +2 -0
  205. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.d.ts +1 -1
  206. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js +43 -40
  207. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js.map +1 -1
  208. package/dist/theme/runtime/colorValueMode/index.js +2 -12
  209. package/dist/theme/runtime/colorValueMode/index.js.map +1 -1
  210. package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.d.ts +2 -0
  211. package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.js +48 -0
  212. package/dist/theme/runtime/colorValueMode/legacyNeutralCompatibility.js.map +1 -0
  213. package/dist/theme/runtime/colorValueMode/registry.d.ts +1 -1
  214. package/dist/theme/runtime/colorValueMode/registry.js +2 -1
  215. package/dist/theme/runtime/colorValueMode/registry.js.map +1 -1
  216. package/dist/theme/runtime/initAldTheme.js +1 -3
  217. package/dist/theme/runtime/initAldTheme.js.map +1 -1
  218. package/dist/theme/runtime/neutralSource/index.d.ts +6 -0
  219. package/dist/theme/runtime/neutralSource/index.js +11 -0
  220. package/dist/theme/runtime/neutralSource/index.js.map +1 -0
  221. package/dist/theme/runtime/neutralSource.d.ts +2 -0
  222. package/dist/theme/runtime/themeToCssVars.js +3 -0
  223. package/dist/theme/runtime/themeToCssVars.js.map +1 -1
  224. package/package.json +1 -1
@@ -1 +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 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(--action-primary-normal)] hover:tw-bg-[var(--action-primary-hover)]'\n : 'tw-bg-[var(--semantic-neutral-500)]',\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,eAAa;GACb,cAAY;GACZ,UAAU;GACV,WAAW,GACT,uJACA,cACI,mFACA,uCACJ,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"}
@@ -10,13 +10,18 @@ function Cell(props) {
10
10
  const { render, dataIndex, align, ellipsis } = column.columnDef.meta;
11
11
  const colValue = _.get(row.original, dataIndex || "");
12
12
  const node = render ? render(colValue, row.original, row.index) : colValue;
13
+ const isDefaultTextValue = typeof render !== "function" && (typeof colValue === "string" || typeof colValue === "number");
14
+ const content = isDefaultTextValue ? /* @__PURE__ */ jsx("span", {
15
+ className: "tw-text-typography-body-dense",
16
+ children: node
17
+ }) : node;
13
18
  return /* @__PURE__ */ jsx("div", {
14
- className: cn(prefixCls("td-default"), prefixCls(`align-${align}`)),
19
+ className: cn(prefixCls("td-default"), prefixCls(`align-${align}`), { [prefixCls("td-legacy-content")]: !isDefaultTextValue }),
15
20
  children: ellipsis ? /* @__PURE__ */ jsx("div", {
16
21
  className: prefixCls("td-ellipsis-content"),
17
22
  title: typeof node === "string" ? node : void 0,
18
- children: node
19
- }) : node
23
+ children: content
24
+ }) : content
20
25
  });
21
26
  }
22
27
  function CellWithErrorBoundary(props) {
@@ -1 +1 @@
1
- {"version":3,"file":"Cell.js","names":[],"sources":["../../../src/Table/components/Cell.tsx"],"sourcesContent":["import { Column, Row } from '@tanstack/react-table';\nimport { cn } from '../../lib/utils';\nimport _ from 'lodash';\nimport React, { useCallback } from 'react';\nimport { prefixCls } from '../helper';\nimport { ITableColumn, ITableProps } from '../types';\nimport ErrorBoundary from './ErrorBoundary';\n\nfunction Cell<T>(props: IProps<T>) {\n const { column, row } = props;\n const meta = column.columnDef.meta as ITableColumn<unknown>;\n const { render, dataIndex, align, ellipsis } = meta;\n\n const colValue = _.get(row.original, dataIndex || '');\n const node = render ? render(colValue, row.original, row.index) : colValue;\n\n return (\n <div className={cn(prefixCls('td-default'), prefixCls(`align-${align}`))}>\n {ellipsis ? (\n <div\n className={prefixCls('td-ellipsis-content')}\n title={typeof node === 'string' ? node : undefined}\n >\n {node}\n </div>\n ) : (\n node\n )}\n </div>\n );\n}\n\nexport default function CellWithErrorBoundary<T>(props: IProps<T>) {\n const { column } = props;\n const meta = column.columnDef.meta as ITableColumn<unknown> & {\n onError: ITableProps<object>['onError'];\n };\n const { dataIndex, onError } = meta;\n const reportError = useCallback(\n (err: Error, stack: string) => {\n if (onError) {\n onError({\n error: err,\n stack,\n extra: {\n place: 'bodyCell',\n dataIndex,\n },\n });\n }\n },\n [onError, dataIndex],\n );\n\n return (\n <ErrorBoundary onError={reportError}>\n <Cell {...props} />\n </ErrorBoundary>\n );\n}\n\nexport interface IProps<T> {\n row: Row<T>;\n column: Column<T>;\n}\n"],"mappings":";;;;;;;AAQA,SAAS,KAAQ,OAAkB;CACjC,MAAM,EAAE,QAAQ,QAAQ;CAExB,MAAM,EAAE,QAAQ,WAAW,OAAO,aADrB,OAAO,UAAU;CAG9B,MAAM,WAAW,EAAE,IAAI,IAAI,UAAU,aAAa,GAAG;CACrD,MAAM,OAAO,SAAS,OAAO,UAAU,IAAI,UAAU,IAAI,MAAM,GAAG;AAElE,QACE,oBAAC,OAAD;EAAK,WAAW,GAAG,UAAU,aAAa,EAAE,UAAU,SAAS,QAAQ,CAAC;YACrE,WACC,oBAAC,OAAD;GACE,WAAW,UAAU,sBAAsB;GAC3C,OAAO,OAAO,SAAS,WAAW,OAAO;aAExC;GACG,CAAA,GAEN;EAEE,CAAA;;AAIV,SAAwB,sBAAyB,OAAkB;CACjE,MAAM,EAAE,WAAW;CAInB,MAAM,EAAE,WAAW,YAHN,OAAO,UAAU;AAoB9B,QACE,oBAAC,eAAD;EAAe,SAjBG,aACjB,KAAY,UAAkB;AAC7B,OAAI,QACF,SAAQ;IACN,OAAO;IACP;IACA,OAAO;KACL,OAAO;KACP;KACD;IACF,CAAC;KAGN,CAAC,SAAS,UAAU,CACrB;YAIG,oBAAC,MAAD,EAAM,GAAI,OAAS,CAAA;EACL,CAAA"}
1
+ {"version":3,"file":"Cell.js","names":[],"sources":["../../../src/Table/components/Cell.tsx"],"sourcesContent":["import { Column, Row } from '@tanstack/react-table';\nimport { cn } from '../../lib/utils';\nimport _ from 'lodash';\nimport React, { useCallback } from 'react';\nimport { prefixCls } from '../helper';\nimport { ITableColumn, ITableProps } from '../types';\nimport ErrorBoundary from './ErrorBoundary';\n\nfunction Cell<T>(props: IProps<T>) {\n const { column, row } = props;\n const meta = column.columnDef.meta as ITableColumn<unknown>;\n const { render, dataIndex, align, ellipsis } = meta;\n\n const colValue = _.get(row.original, dataIndex || '');\n const node = render ? render(colValue, row.original, row.index) : colValue;\n const isDefaultTextValue =\n typeof render !== 'function' &&\n (typeof colValue === 'string' || typeof colValue === 'number');\n const content = isDefaultTextValue ? (\n <span className=\"tw-text-typography-body-dense\">{node}</span>\n ) : (\n node\n );\n\n return (\n <div\n className={cn(prefixCls('td-default'), prefixCls(`align-${align}`), {\n [prefixCls('td-legacy-content')]: !isDefaultTextValue,\n })}\n >\n {ellipsis ? (\n <div\n className={prefixCls('td-ellipsis-content')}\n title={typeof node === 'string' ? node : undefined}\n >\n {content}\n </div>\n ) : (\n content\n )}\n </div>\n );\n}\n\nexport default function CellWithErrorBoundary<T>(props: IProps<T>) {\n const { column } = props;\n const meta = column.columnDef.meta as ITableColumn<unknown> & {\n onError: ITableProps<object>['onError'];\n };\n const { dataIndex, onError } = meta;\n const reportError = useCallback(\n (err: Error, stack: string) => {\n if (onError) {\n onError({\n error: err,\n stack,\n extra: {\n place: 'bodyCell',\n dataIndex,\n },\n });\n }\n },\n [onError, dataIndex],\n );\n\n return (\n <ErrorBoundary onError={reportError}>\n <Cell {...props} />\n </ErrorBoundary>\n );\n}\n\nexport interface IProps<T> {\n row: Row<T>;\n column: Column<T>;\n}\n"],"mappings":";;;;;;;AAQA,SAAS,KAAQ,OAAkB;CACjC,MAAM,EAAE,QAAQ,QAAQ;CAExB,MAAM,EAAE,QAAQ,WAAW,OAAO,aADrB,OAAO,UAAU;CAG9B,MAAM,WAAW,EAAE,IAAI,IAAI,UAAU,aAAa,GAAG;CACrD,MAAM,OAAO,SAAS,OAAO,UAAU,IAAI,UAAU,IAAI,MAAM,GAAG;CAClE,MAAM,qBACJ,OAAO,WAAW,eACjB,OAAO,aAAa,YAAY,OAAO,aAAa;CACvD,MAAM,UAAU,qBACd,oBAAC,QAAD;EAAM,WAAU;YAAiC;EAAY,CAAA,GAE7D;AAGF,QACE,oBAAC,OAAD;EACE,WAAW,GAAG,UAAU,aAAa,EAAE,UAAU,SAAS,QAAQ,EAAE,GACjE,UAAU,oBAAoB,GAAG,CAAC,oBACpC,CAAC;YAED,WACC,oBAAC,OAAD;GACE,WAAW,UAAU,sBAAsB;GAC3C,OAAO,OAAO,SAAS,WAAW,OAAO;aAExC;GACG,CAAA,GAEN;EAEE,CAAA;;AAIV,SAAwB,sBAAyB,OAAkB;CACjE,MAAM,EAAE,WAAW;CAInB,MAAM,EAAE,WAAW,YAHN,OAAO,UAAU;AAoB9B,QACE,oBAAC,eAAD;EAAe,SAjBG,aACjB,KAAY,UAAkB;AAC7B,OAAI,QACF,SAAQ;IACN,OAAO;IACP;IACA,OAAO;KACL,OAAO;KACP;KACD;IACF,CAAC;KAGN,CAAC,SAAS,UAAU,CACrB;YAIG,oBAAC,MAAD,EAAM,GAAI,OAAS,CAAA;EACL,CAAA"}
@@ -20,9 +20,13 @@ function ExpandCell(props) {
20
20
  const expandable = getExpandableConfig(propsExpandable);
21
21
  const defaultExpandIconRender = (params) => {
22
22
  const { record, onExpand, isExpanded: isExpandedIcon } = params;
23
- return /* @__PURE__ */ jsx("span", {
23
+ return /* @__PURE__ */ jsx("button", {
24
+ type: "button",
24
25
  className: prefixCls("expand-btn-inner"),
25
- onClick: () => {
26
+ "aria-label": `${isExpandedIcon ? "Collapse" : "Expand"} row ${key}`,
27
+ "aria-expanded": isExpandedIcon,
28
+ onClick: (event) => {
29
+ event.stopPropagation();
26
30
  if (isLeaf) return;
27
31
  onExpand(record, !isExpanded);
28
32
  },
@@ -1 +1 @@
1
- {"version":3,"file":"ExpandCell.js","names":[],"sources":["../../../src/Table/components/ExpandCell.tsx"],"sourcesContent":["import _ from 'lodash';\nimport React from 'react';\nimport { ArrowDownLightLine, ArrowRightLightLine } from '../../Icon';\nimport { getRowKey, prefixCls } from '../helper';\nimport { IExpandableInfo, getExpandableConfig } from '../hooks/useExpandable';\nimport { IExpandIconProps, ITableExpandable, TRowKey } from '../types';\n\nexport default function ExpandCell<TDataItem extends object>(\n props: IProps<TDataItem>,\n) {\n const {\n children,\n expandableInfo,\n data,\n rowKey,\n expandable: propsExpandable,\n } = props;\n if (!expandableInfo.isExpandable || !rowKey) {\n // 配置了折叠展开时,会在前面的流程中强制检查 rowKey 字段是否存在\n return <>{children}</>;\n }\n const { expandItemMap, onExpand } = expandableInfo;\n const key = getRowKey(data, rowKey);\n const expandItem = expandItemMap[key];\n\n if (!expandItem) {\n console.error('expandItem in not found', key, expandItemMap);\n return <>{children}</>;\n }\n const { level, isExpanded, isLeaf } = expandItem;\n\n const expandable = getExpandableConfig(propsExpandable);\n const defaultExpandIconRender = (params: IExpandIconProps<TDataItem>) => {\n const { record, onExpand, isExpanded: isExpandedIcon } = params;\n return (\n <span\n className={prefixCls('expand-btn-inner')}\n onClick={() => {\n if (isLeaf) {\n return;\n }\n onExpand(record, !isExpanded);\n }}\n >\n {isExpandedIcon ? <ArrowDownLightLine /> : <ArrowRightLightLine />}\n </span>\n );\n };\n const expandIcon = expandable.expandIcon || defaultExpandIconRender;\n\n const iconNode = isLeaf\n ? null\n : expandIcon({\n record: data,\n onExpand,\n isExpanded: !!isExpanded,\n });\n\n return (\n <div className={prefixCls('expandable-td')}>\n <div className={prefixCls('indent-list')}>\n {_.map(_.range(level), (i) => {\n return <div className={prefixCls('indent-item')} key={i} />;\n })}\n </div>\n <div className={prefixCls('expand-btn')}>{iconNode}</div>\n <div className={prefixCls('expand-content')}>{children}</div>\n </div>\n );\n}\n\ninterface IProps<TDataItem extends object> {\n expandableInfo: IExpandableInfo<TDataItem>;\n data: TDataItem;\n children: React.ReactNode;\n rowKey?: TRowKey<TDataItem>;\n expandable?: ITableExpandable<TDataItem> | boolean;\n}\n"],"mappings":";;;;;;;;AAOA,SAAwB,WACtB,OACA;CACA,MAAM,EACJ,UACA,gBACA,MACA,QACA,YAAY,oBACV;AACJ,KAAI,CAAC,eAAe,gBAAgB,CAAC,OAEnC,QAAO,oBAAA,UAAA,EAAG,UAAY,CAAA;CAExB,MAAM,EAAE,eAAe,aAAa;CACpC,MAAM,MAAM,UAAU,MAAM,OAAO;CACnC,MAAM,aAAa,cAAc;AAEjC,KAAI,CAAC,YAAY;AACf,UAAQ,MAAM,2BAA2B,KAAK,cAAc;AAC5D,SAAO,oBAAA,UAAA,EAAG,UAAY,CAAA;;CAExB,MAAM,EAAE,OAAO,YAAY,WAAW;CAEtC,MAAM,aAAa,oBAAoB,gBAAgB;CACvD,MAAM,2BAA2B,WAAwC;EACvE,MAAM,EAAE,QAAQ,UAAU,YAAY,mBAAmB;AACzD,SACE,oBAAC,QAAD;GACE,WAAW,UAAU,mBAAmB;GACxC,eAAe;AACb,QAAI,OACF;AAEF,aAAS,QAAQ,CAAC,WAAW;;aAG9B,iBAAiB,oBAAC,MAAD,EAAsB,CAAA,GAAG,oBAAC,QAAD,EAAuB,CAAA;GAC7D,CAAA;;CAGX,MAAM,aAAa,WAAW,cAAc;CAE5C,MAAM,WAAW,SACb,OACA,WAAW;EACT,QAAQ;EACR;EACA,YAAY,CAAC,CAAC;EACf,CAAC;AAEN,QACE,qBAAC,OAAD;EAAK,WAAW,UAAU,gBAAgB;YAA1C;GACE,oBAAC,OAAD;IAAK,WAAW,UAAU,cAAc;cACrC,EAAE,IAAI,EAAE,MAAM,MAAM,GAAG,MAAM;AAC5B,YAAO,oBAAC,OAAD,EAAK,WAAW,UAAU,cAAc,EAAY,EAAL,EAAK;MAC3D;IACE,CAAA;GACN,oBAAC,OAAD;IAAK,WAAW,UAAU,aAAa;cAAG;IAAe,CAAA;GACzD,oBAAC,OAAD;IAAK,WAAW,UAAU,iBAAiB;IAAG;IAAe,CAAA;GACzD"}
1
+ {"version":3,"file":"ExpandCell.js","names":[],"sources":["../../../src/Table/components/ExpandCell.tsx"],"sourcesContent":["import _ from 'lodash';\nimport React from 'react';\nimport { ArrowDownLightLine, ArrowRightLightLine } from '../../Icon';\nimport { getRowKey, prefixCls } from '../helper';\nimport { IExpandableInfo, getExpandableConfig } from '../hooks/useExpandable';\nimport { IExpandIconProps, ITableExpandable, TRowKey } from '../types';\n\nexport default function ExpandCell<TDataItem extends object>(\n props: IProps<TDataItem>,\n) {\n const {\n children,\n expandableInfo,\n data,\n rowKey,\n expandable: propsExpandable,\n } = props;\n if (!expandableInfo.isExpandable || !rowKey) {\n // 配置了折叠展开时,会在前面的流程中强制检查 rowKey 字段是否存在\n return <>{children}</>;\n }\n const { expandItemMap, onExpand } = expandableInfo;\n const key = getRowKey(data, rowKey);\n const expandItem = expandItemMap[key];\n\n if (!expandItem) {\n console.error('expandItem in not found', key, expandItemMap);\n return <>{children}</>;\n }\n const { level, isExpanded, isLeaf } = expandItem;\n\n const expandable = getExpandableConfig(propsExpandable);\n const defaultExpandIconRender = (params: IExpandIconProps<TDataItem>) => {\n const { record, onExpand, isExpanded: isExpandedIcon } = params;\n return (\n <button\n type=\"button\"\n className={prefixCls('expand-btn-inner')}\n aria-label={`${isExpandedIcon ? 'Collapse' : 'Expand'} row ${key}`}\n aria-expanded={isExpandedIcon}\n onClick={(event) => {\n event.stopPropagation();\n if (isLeaf) {\n return;\n }\n onExpand(record, !isExpanded);\n }}\n >\n {isExpandedIcon ? <ArrowDownLightLine /> : <ArrowRightLightLine />}\n </button>\n );\n };\n const expandIcon = expandable.expandIcon || defaultExpandIconRender;\n\n const iconNode = isLeaf\n ? null\n : expandIcon({\n record: data,\n onExpand,\n isExpanded: !!isExpanded,\n });\n\n return (\n <div className={prefixCls('expandable-td')}>\n <div className={prefixCls('indent-list')}>\n {_.map(_.range(level), (i) => {\n return <div className={prefixCls('indent-item')} key={i} />;\n })}\n </div>\n <div className={prefixCls('expand-btn')}>{iconNode}</div>\n <div className={prefixCls('expand-content')}>{children}</div>\n </div>\n );\n}\n\ninterface IProps<TDataItem extends object> {\n expandableInfo: IExpandableInfo<TDataItem>;\n data: TDataItem;\n children: React.ReactNode;\n rowKey?: TRowKey<TDataItem>;\n expandable?: ITableExpandable<TDataItem> | boolean;\n}\n"],"mappings":";;;;;;;;AAOA,SAAwB,WACtB,OACA;CACA,MAAM,EACJ,UACA,gBACA,MACA,QACA,YAAY,oBACV;AACJ,KAAI,CAAC,eAAe,gBAAgB,CAAC,OAEnC,QAAO,oBAAA,UAAA,EAAG,UAAY,CAAA;CAExB,MAAM,EAAE,eAAe,aAAa;CACpC,MAAM,MAAM,UAAU,MAAM,OAAO;CACnC,MAAM,aAAa,cAAc;AAEjC,KAAI,CAAC,YAAY;AACf,UAAQ,MAAM,2BAA2B,KAAK,cAAc;AAC5D,SAAO,oBAAA,UAAA,EAAG,UAAY,CAAA;;CAExB,MAAM,EAAE,OAAO,YAAY,WAAW;CAEtC,MAAM,aAAa,oBAAoB,gBAAgB;CACvD,MAAM,2BAA2B,WAAwC;EACvE,MAAM,EAAE,QAAQ,UAAU,YAAY,mBAAmB;AACzD,SACE,oBAAC,UAAD;GACE,MAAK;GACL,WAAW,UAAU,mBAAmB;GACxC,cAAY,GAAG,iBAAiB,aAAa,SAAS,OAAO;GAC7D,iBAAe;GACf,UAAU,UAAU;AAClB,UAAM,iBAAiB;AACvB,QAAI,OACF;AAEF,aAAS,QAAQ,CAAC,WAAW;;aAG9B,iBAAiB,oBAAC,MAAD,EAAsB,CAAA,GAAG,oBAAC,QAAD,EAAuB,CAAA;GAC3D,CAAA;;CAGb,MAAM,aAAa,WAAW,cAAc;CAE5C,MAAM,WAAW,SACb,OACA,WAAW;EACT,QAAQ;EACR;EACA,YAAY,CAAC,CAAC;EACf,CAAC;AAEN,QACE,qBAAC,OAAD;EAAK,WAAW,UAAU,gBAAgB;YAA1C;GACE,oBAAC,OAAD;IAAK,WAAW,UAAU,cAAc;cACrC,EAAE,IAAI,EAAE,MAAM,MAAM,GAAG,MAAM;AAC5B,YAAO,oBAAC,OAAD,EAAK,WAAW,UAAU,cAAc,EAAY,EAAL,EAAK;MAC3D;IACE,CAAA;GACN,oBAAC,OAAD;IAAK,WAAW,UAAU,aAAa;cAAG;IAAe,CAAA;GACzD,oBAAC,OAAD;IAAK,WAAW,UAAU,iBAAiB;IAAG;IAAe,CAAA;GACzD"}
@@ -1,3 +1,4 @@
1
+ import { cn } from "../../../lib/utils.js";
1
2
  import { LocaleContext, getTranslator } from "../../../locale/default.js";
2
3
  import TextLink from "../../../TextLink/index.js";
3
4
  import Pagination from "../../../Pagination/index.js";
@@ -23,7 +24,7 @@ function TableFooter(props) {
23
24
  children: getCheckboxAllNode?.(t.Table.selectAll)
24
25
  }),
25
26
  /* @__PURE__ */ jsxs("div", {
26
- className: prefixCls("footer-row-selection-selected"),
27
+ className: cn(prefixCls("footer-row-selection-selected"), "tw-text-typography-body-dense"),
27
28
  children: [
28
29
  t.Table.selected,
29
30
  /* @__PURE__ */ jsx(TextLink, {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/Table/components/Footer/index.tsx"],"sourcesContent":["import React, { useCallback, useContext } from 'react';\nimport { Pagination } from '../../..';\nimport { IPaginationProps } from '../../../Pagination/types';\nimport TextLink from '../../../TextLink';\nimport { LocaleContext, getTranslator } from '../../../locale/default';\nimport { prefixCls } from '../../helper';\nimport { IRowSelectionInfo } from '../../hooks/useRowSelection';\nimport { ITableProps } from '../../types';\n\nexport default function TableFooter<TDataItem extends object>(\n props: IProps<TDataItem>,\n) {\n const { locale } = useContext(LocaleContext);\n const t = getTranslator(locale);\n\n const {\n pagination,\n scroll = {},\n scrollToFirstRow,\n isShowPagination,\n rowSelectionInfo,\n } = props;\n\n // 选择行\n const {\n getCheckboxAllNode,\n selectedRowKeys,\n selectedRowKeysInCurrPage,\n items,\n isShowRowSelectionInFooter,\n onChange: changeSelectedRowKeys,\n } = rowSelectionInfo;\n\n const btnItems = [\n {\n key: '$UN_SELECT_ALL$',\n label: t.Table.cancelSelect,\n onClick: () => rowSelectionInfo.unSelectAll(),\n },\n ...items,\n ];\n\n const rowSelectionNode = isShowRowSelectionInFooter && (\n <div className={prefixCls('footer-row-selection')}>\n <div className={prefixCls('footer-row-selection-btn')}>\n {getCheckboxAllNode?.(t.Table.selectAll)}\n </div>\n <div className={prefixCls('footer-row-selection-selected')}>\n {t.Table.selected}\n <TextLink className={prefixCls('footer-row-selection-selected-num')}>\n {selectedRowKeys.length}\n </TextLink>\n {t.Table.item}\n </div>\n {btnItems.map((btnItem) => {\n return (\n <div\n key={btnItem.key}\n className={prefixCls('footer-row-selection-item')}\n onClick={(e) => {\n btnItem.onClick(e);\n }}\n >\n <TextLink>{btnItem.label}</TextLink>\n </div>\n );\n })}\n </div>\n );\n\n // 翻页器\n const onChangePage = useCallback(\n (page: number) => {\n const { onChange = () => {} } = pagination || {};\n const { scrollToFirstRowOnChange = true } = scroll;\n if (scrollToFirstRowOnChange) {\n scrollToFirstRow();\n }\n onChange(page);\n // 翻页后,清空已选行\n changeSelectedRowKeys([]);\n },\n [scrollToFirstRow, scroll, pagination, changeSelectedRowKeys],\n );\n\n const pager = isShowPagination && pagination && (\n <div className={prefixCls('pager')}>\n <Pagination hideOnSinglePage {...pagination} onChange={onChangePage} />\n </div>\n );\n\n const isShowRowSelection =\n rowSelectionInfo.isRowSelectionEnabled &&\n selectedRowKeysInCurrPage.length > 0;\n\n const isShowFooter = isShowPagination || isShowRowSelection;\n\n return isShowFooter ? (\n <div className={prefixCls('footer')}>\n {rowSelectionNode}\n {pager}\n </div>\n ) : null;\n}\n\ninterface IProps<TDataItem extends object> {\n isShowPagination: boolean;\n rowSelectionInfo: IRowSelectionInfo<TDataItem>;\n pagination?: IPaginationProps;\n scroll?: ITableProps<TDataItem>['scroll'];\n scrollToFirstRow: () => void;\n}\n"],"mappings":";;;;;;;AASA,SAAwB,YACtB,OACA;CACA,MAAM,EAAE,WAAW,WAAW,cAAc;CAC5C,MAAM,IAAI,cAAc,OAAO;CAE/B,MAAM,EACJ,YACA,SAAS,EAAE,EACX,kBACA,kBACA,qBACE;CAGJ,MAAM,EACJ,oBACA,iBACA,2BACA,OACA,4BACA,UAAU,0BACR;CAEJ,MAAM,WAAW,CACf;EACE,KAAK;EACL,OAAO,EAAE,MAAM;EACf,eAAe,iBAAiB,aAAa;EAC9C,EACD,GAAG,MACJ;CAED,MAAM,mBAAmB,8BACvB,qBAAC,OAAD;EAAK,WAAW,UAAU,uBAAuB;YAAjD;GACE,oBAAC,OAAD;IAAK,WAAW,UAAU,2BAA2B;cAClD,qBAAqB,EAAE,MAAM,UAAU;IACpC,CAAA;GACN,qBAAC,OAAD;IAAK,WAAW,UAAU,gCAAgC;cAA1D;KACG,EAAE,MAAM;KACT,oBAAC,UAAD;MAAU,WAAW,UAAU,oCAAoC;gBAChE,gBAAgB;MACR,CAAA;KACV,EAAE,MAAM;KACL;;GACL,SAAS,KAAK,YAAY;AACzB,WACE,oBAAC,OAAD;KAEE,WAAW,UAAU,4BAA4B;KACjD,UAAU,MAAM;AACd,cAAQ,QAAQ,EAAE;;eAGpB,oBAAC,UAAD,EAAA,UAAW,QAAQ,OAAiB,CAAA;KAChC,EAPC,QAAQ,IAOT;KAER;GACE;;CAIR,MAAM,eAAe,aAClB,SAAiB;EAChB,MAAM,EAAE,iBAAiB,OAAO,cAAc,EAAE;EAChD,MAAM,EAAE,2BAA2B,SAAS;AAC5C,MAAI,yBACF,mBAAkB;AAEpB,WAAS,KAAK;AAEd,wBAAsB,EAAE,CAAC;IAE3B;EAAC;EAAkB;EAAQ;EAAY;EAAsB,CAC9D;CAED,MAAM,QAAQ,oBAAoB,cAChC,oBAAC,OAAD;EAAK,WAAW,UAAU,QAAQ;YAChC,oBAAC,YAAD;GAAY,kBAAA;GAAiB,GAAI;GAAY,UAAU;GAAgB,CAAA;EACnE,CAAA;CAGR,MAAM,qBACJ,iBAAiB,yBACjB,0BAA0B,SAAS;AAIrC,QAFqB,oBAAoB,qBAGvC,qBAAC,OAAD;EAAK,WAAW,UAAU,SAAS;YAAnC,CACG,kBACA,MACG;MACJ"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/Table/components/Footer/index.tsx"],"sourcesContent":["import React, { useCallback, useContext } from 'react';\nimport { Pagination } from '../../..';\nimport { IPaginationProps } from '../../../Pagination/types';\nimport TextLink from '../../../TextLink';\nimport { cn } from '../../../lib/utils';\nimport { LocaleContext, getTranslator } from '../../../locale/default';\nimport { prefixCls } from '../../helper';\nimport { IRowSelectionInfo } from '../../hooks/useRowSelection';\nimport { ITableProps } from '../../types';\n\nexport default function TableFooter<TDataItem extends object>(\n props: IProps<TDataItem>,\n) {\n const { locale } = useContext(LocaleContext);\n const t = getTranslator(locale);\n\n const {\n pagination,\n scroll = {},\n scrollToFirstRow,\n isShowPagination,\n rowSelectionInfo,\n } = props;\n\n // 选择行\n const {\n getCheckboxAllNode,\n selectedRowKeys,\n selectedRowKeysInCurrPage,\n items,\n isShowRowSelectionInFooter,\n onChange: changeSelectedRowKeys,\n } = rowSelectionInfo;\n\n const btnItems = [\n {\n key: '$UN_SELECT_ALL$',\n label: t.Table.cancelSelect,\n onClick: () => rowSelectionInfo.unSelectAll(),\n },\n ...items,\n ];\n\n const rowSelectionNode = isShowRowSelectionInFooter && (\n <div className={prefixCls('footer-row-selection')}>\n <div className={prefixCls('footer-row-selection-btn')}>\n {getCheckboxAllNode?.(t.Table.selectAll)}\n </div>\n <div\n className={cn(\n prefixCls('footer-row-selection-selected'),\n 'tw-text-typography-body-dense',\n )}\n >\n {t.Table.selected}\n <TextLink className={prefixCls('footer-row-selection-selected-num')}>\n {selectedRowKeys.length}\n </TextLink>\n {t.Table.item}\n </div>\n {btnItems.map((btnItem) => {\n return (\n <div\n key={btnItem.key}\n className={prefixCls('footer-row-selection-item')}\n onClick={(e) => {\n btnItem.onClick(e);\n }}\n >\n <TextLink>{btnItem.label}</TextLink>\n </div>\n );\n })}\n </div>\n );\n\n // 翻页器\n const onChangePage = useCallback(\n (page: number) => {\n const { onChange = () => {} } = pagination || {};\n const { scrollToFirstRowOnChange = true } = scroll;\n if (scrollToFirstRowOnChange) {\n scrollToFirstRow();\n }\n onChange(page);\n // 翻页后,清空已选行\n changeSelectedRowKeys([]);\n },\n [scrollToFirstRow, scroll, pagination, changeSelectedRowKeys],\n );\n\n const pager = isShowPagination && pagination && (\n <div className={prefixCls('pager')}>\n <Pagination hideOnSinglePage {...pagination} onChange={onChangePage} />\n </div>\n );\n\n const isShowRowSelection =\n rowSelectionInfo.isRowSelectionEnabled &&\n selectedRowKeysInCurrPage.length > 0;\n\n const isShowFooter = isShowPagination || isShowRowSelection;\n\n return isShowFooter ? (\n <div className={prefixCls('footer')}>\n {rowSelectionNode}\n {pager}\n </div>\n ) : null;\n}\n\ninterface IProps<TDataItem extends object> {\n isShowPagination: boolean;\n rowSelectionInfo: IRowSelectionInfo<TDataItem>;\n pagination?: IPaginationProps;\n scroll?: ITableProps<TDataItem>['scroll'];\n scrollToFirstRow: () => void;\n}\n"],"mappings":";;;;;;;;AAUA,SAAwB,YACtB,OACA;CACA,MAAM,EAAE,WAAW,WAAW,cAAc;CAC5C,MAAM,IAAI,cAAc,OAAO;CAE/B,MAAM,EACJ,YACA,SAAS,EAAE,EACX,kBACA,kBACA,qBACE;CAGJ,MAAM,EACJ,oBACA,iBACA,2BACA,OACA,4BACA,UAAU,0BACR;CAEJ,MAAM,WAAW,CACf;EACE,KAAK;EACL,OAAO,EAAE,MAAM;EACf,eAAe,iBAAiB,aAAa;EAC9C,EACD,GAAG,MACJ;CAED,MAAM,mBAAmB,8BACvB,qBAAC,OAAD;EAAK,WAAW,UAAU,uBAAuB;YAAjD;GACE,oBAAC,OAAD;IAAK,WAAW,UAAU,2BAA2B;cAClD,qBAAqB,EAAE,MAAM,UAAU;IACpC,CAAA;GACN,qBAAC,OAAD;IACE,WAAW,GACT,UAAU,gCAAgC,EAC1C,gCACD;cAJH;KAMG,EAAE,MAAM;KACT,oBAAC,UAAD;MAAU,WAAW,UAAU,oCAAoC;gBAChE,gBAAgB;MACR,CAAA;KACV,EAAE,MAAM;KACL;;GACL,SAAS,KAAK,YAAY;AACzB,WACE,oBAAC,OAAD;KAEE,WAAW,UAAU,4BAA4B;KACjD,UAAU,MAAM;AACd,cAAQ,QAAQ,EAAE;;eAGpB,oBAAC,UAAD,EAAA,UAAW,QAAQ,OAAiB,CAAA;KAChC,EAPC,QAAQ,IAOT;KAER;GACE;;CAIR,MAAM,eAAe,aAClB,SAAiB;EAChB,MAAM,EAAE,iBAAiB,OAAO,cAAc,EAAE;EAChD,MAAM,EAAE,2BAA2B,SAAS;AAC5C,MAAI,yBACF,mBAAkB;AAEpB,WAAS,KAAK;AAEd,wBAAsB,EAAE,CAAC;IAE3B;EAAC;EAAkB;EAAQ;EAAY;EAAsB,CAC9D;CAED,MAAM,QAAQ,oBAAoB,cAChC,oBAAC,OAAD;EAAK,WAAW,UAAU,QAAQ;YAChC,oBAAC,YAAD;GAAY,kBAAA;GAAiB,GAAI;GAAY,UAAU;GAAgB,CAAA;EACnE,CAAA;CAGR,MAAM,qBACJ,iBAAiB,yBACjB,0BAA0B,SAAS;AAIrC,QAFqB,oBAAoB,qBAGvC,qBAAC,OAAD;EAAK,WAAW,UAAU,SAAS;YAAnC,CACG,kBACA,MACG;MACJ"}
@@ -9,6 +9,8 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
9
  function Header(props) {
10
10
  const { column } = props;
11
11
  const { title, dataIndex, align, ellipsis, sortOrder, onSort } = column.columnDef.meta;
12
+ const isSortable = sortOrder !== void 0 && !!dataIndex && typeof onSort === "function";
13
+ const ariaSort = sortOrder === "ascend" ? "ascending" : sortOrder === "descend" ? "descending" : "none";
12
14
  let sortIcon = /* @__PURE__ */ jsx(Memo$1, {
13
15
  size: 20,
14
16
  color: "var(--action-neutral-normal)"
@@ -22,7 +24,7 @@ function Header(props) {
22
24
  color: "var(--action-primary-normal)"
23
25
  });
24
26
  const onClickTh = useCallback((e) => {
25
- if (sortOrder === void 0 || !dataIndex || typeof onSort !== "function") return;
27
+ if (!isSortable || !dataIndex) return;
26
28
  e.stopPropagation();
27
29
  let newSortOrder;
28
30
  if (sortOrder === "ascend") newSortOrder = "descend";
@@ -31,29 +33,34 @@ function Header(props) {
31
33
  onSort(dataIndex, newSortOrder);
32
34
  }, [
33
35
  dataIndex,
36
+ isSortable,
34
37
  onSort,
35
38
  sortOrder
36
39
  ]);
37
- let content = title;
38
- if (typeof content === "string") {
39
- if (sortOrder !== void 0) content = /* @__PURE__ */ jsxs("span", {
40
- className: prefixCls("sort-th-inner"),
41
- children: [/* @__PURE__ */ jsx("span", {
42
- className: prefixCls("sort-title"),
43
- children: title
44
- }), /* @__PURE__ */ jsx("span", {
45
- className: prefixCls("sort-btn"),
46
- children: sortIcon
47
- })]
48
- });
49
- }
40
+ const content = isSortable ? /* @__PURE__ */ jsxs("span", {
41
+ className: prefixCls("sort-th-inner"),
42
+ children: [/* @__PURE__ */ jsx("span", {
43
+ className: prefixCls("sort-title"),
44
+ children: title
45
+ }), /* @__PURE__ */ jsx("span", {
46
+ className: prefixCls("sort-btn"),
47
+ "aria-hidden": "true",
48
+ children: sortIcon
49
+ })]
50
+ }) : title;
50
51
  return typeof title === "string" ? /* @__PURE__ */ jsx("div", {
51
- className: cn(prefixCls("th-default"), prefixCls(`align-${align}`), {
52
+ "aria-sort": isSortable ? ariaSort : void 0,
53
+ className: cn(prefixCls("th-default"), "tw-text-typography-label", prefixCls(`align-${align}`), {
52
54
  [prefixCls("td-ellipsis-content")]: ellipsis,
53
- [prefixCls("th-sortable")]: sortOrder !== void 0
55
+ [prefixCls("th-sortable")]: isSortable
54
56
  }),
55
- onClick: onClickTh,
56
- children: content
57
+ children: isSortable ? /* @__PURE__ */ jsx("button", {
58
+ type: "button",
59
+ className: prefixCls("sort-trigger"),
60
+ "aria-label": `Sort by ${title}`,
61
+ onClick: onClickTh,
62
+ children: content
63
+ }) : content
57
64
  }, dataIndex) : /* @__PURE__ */ jsx(Fragment, { children: title });
58
65
  }
59
66
  //#endregion
@@ -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\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 (\n sortOrder === undefined ||\n !dataIndex ||\n typeof onSort !== 'function'\n ) {\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, onSort, sortOrder],\n );\n\n let content = title;\n if (typeof content === 'string') {\n if (sortOrder !== undefined) {\n content = (\n <span className={prefixCls('sort-th-inner')}>\n <span className={prefixCls('sort-title')}>{title}</span>\n <span className={prefixCls('sort-btn')}>{sortIcon}</span>\n </span>\n );\n }\n }\n\n return typeof title === 'string' ? (\n <div\n key={dataIndex}\n className={cn(prefixCls('th-default'), prefixCls(`align-${align}`), {\n [prefixCls('td-ellipsis-content')]: ellipsis,\n [prefixCls('th-sortable')]: sortOrder !== undefined,\n })}\n onClick={onClickTh}\n >\n {content}\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;CAEb,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,MACE,cAAc,UACd,CAAC,aACD,OAAO,WAAW,WAElB;AAEF,IAAE,iBAAiB;EAEnB,IAAI;AACJ,MAAI,cAAc,SAChB,gBAAe;WACN,cAAc,UACvB,gBAAe;MAEf,gBAAe;AAEjB,SAAO,WAAW,aAAa;IAEjC;EAAC;EAAW;EAAQ;EAAU,CAC/B;CAED,IAAI,UAAU;AACd,KAAI,OAAO,YAAY,UACrB;MAAI,cAAc,OAChB,WACE,qBAAC,QAAD;GAAM,WAAW,UAAU,gBAAgB;aAA3C,CACE,oBAAC,QAAD;IAAM,WAAW,UAAU,aAAa;cAAG;IAAa,CAAA,EACxD,oBAAC,QAAD;IAAM,WAAW,UAAU,WAAW;cAAG;IAAgB,CAAA,CACpD;;;AAKb,QAAO,OAAO,UAAU,WACtB,oBAAC,OAAD;EAEE,WAAW,GAAG,UAAU,aAAa,EAAE,UAAU,SAAS,QAAQ,EAAE;IACjE,UAAU,sBAAsB,GAAG;IACnC,UAAU,cAAc,GAAG,cAAc;GAC3C,CAAC;EACF,SAAS;YAER;EACG,EARC,UAQD,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"}
@@ -1,7 +1,7 @@
1
1
  import Checkbox from "../../Checkbox/index.js";
2
2
  import { getRowKey, hasFixedLeftColumn, prefixCls } from "../helper.js";
3
3
  import { useCallback, useMemo, useState } from "react";
4
- import { jsx } from "react/jsx-runtime";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region src/Table/hooks/useRowSelection.tsx
6
6
  function useRowSelection(props) {
7
7
  const { columns, rowSelection, rowKey, data, isExpandable, flattenData } = props;
@@ -38,7 +38,7 @@ function useRowSelection(props) {
38
38
  const unSelectAll = useCallback(() => {
39
39
  changeSelectedRowKeys([]);
40
40
  }, [changeSelectedRowKeys]);
41
- const onClickAllCheckbox = useCallback(() => {
41
+ const onChangeAllCheckbox = useCallback(() => {
42
42
  if (checkboxAllStatus === "all") unSelectAll();
43
43
  else selectAll();
44
44
  }, [
@@ -68,7 +68,7 @@ function useRowSelection(props) {
68
68
  isExpandable,
69
69
  getDescendantKeys
70
70
  ]);
71
- const onClickCheckbox = useCallback((key, isChecked) => () => {
71
+ const onChangeCheckbox = useCallback((key, isChecked) => () => {
72
72
  changeSelectedRowKeys(calculateCascadeSelection(key, isChecked, selectedRowKeys, rowSelection?.checkStrictly, isExpandable, getDescendantKeys, getAncestorKeys));
73
73
  }, [
74
74
  selectedRowKeys,
@@ -81,10 +81,13 @@ function useRowSelection(props) {
81
81
  const getCheckboxAllNode = (children) => /* @__PURE__ */ jsx("div", {
82
82
  className: prefixCls("row-selection-all"),
83
83
  children: /* @__PURE__ */ jsx(Checkbox, {
84
- onClick: onClickAllCheckbox,
84
+ onChange: onChangeAllCheckbox,
85
85
  checked: checkboxAllStatus === "all",
86
86
  indeterminate: checkboxAllStatus === "indeterminate",
87
- children
87
+ children: children || /* @__PURE__ */ jsx("span", {
88
+ className: "tw-sr-only",
89
+ children: "Select all rows"
90
+ })
88
91
  })
89
92
  });
90
93
  if (!rowSelection) return {
@@ -114,10 +117,14 @@ function useRowSelection(props) {
114
117
  return /* @__PURE__ */ jsx("div", {
115
118
  className: prefixCls("row-selection-item"),
116
119
  children: /* @__PURE__ */ jsx(Checkbox, {
117
- onClick: onClickCheckbox(key, nodeStatus.checked || nodeStatus.indeterminate),
120
+ onChange: onChangeCheckbox(key, nodeStatus.checked || nodeStatus.indeterminate),
118
121
  checked: nodeStatus.checked,
119
122
  indeterminate: nodeStatus.indeterminate,
120
- ...checkboxProps
123
+ ...checkboxProps,
124
+ children: /* @__PURE__ */ jsxs("span", {
125
+ className: "tw-sr-only",
126
+ children: ["Select row ", key]
127
+ })
121
128
  })
122
129
  });
123
130
  },
@@ -1 +1 @@
1
- {"version":3,"file":"useRowSelection.js","names":[],"sources":["../../../src/Table/hooks/useRowSelection.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useState } from 'react';\nimport Checkbox from '../../Checkbox';\nimport { getRowKey, hasFixedLeftColumn, prefixCls } from '../helper';\nimport { IRowSelection, ITableColumn, ITableProps } from '../types';\n\nexport default function useRowSelection<TDataItem extends object>(\n props: ITableProps<TDataItem> & {\n isExpandable?: boolean;\n flattenData?: TDataItem[];\n },\n): IRowSelectionInfo<TDataItem> {\n const { columns, rowSelection, rowKey, data, isExpandable, flattenData } =\n props;\n\n const [selectedRowKeysState, setSelectedRowKeysState] = useState(\n rowSelection?.selectedRowKeys || rowSelection?.defaultSelectedRowKeys || [],\n );\n\n const selectedRowKeys = rowSelection?.selectedRowKeys || selectedRowKeysState;\n\n const getSelectedRows = useCallback(\n (rowKeys: string[]) => {\n return data.filter((record) =>\n rowKeys.includes(getRowKey(record, rowKey)),\n );\n },\n [data, rowKey],\n );\n\n // 获取用于全选状态计算和数据获取的完整数据\n const allDataForSelection = useMemo(() => {\n // 如果开启了 expandable,使用扁平化后的数据\n if (isExpandable && flattenData) {\n return flattenData;\n }\n // 否则使用原始数据\n return data;\n }, [isExpandable, flattenData, data]);\n\n // 从完整数据中获取选中的行\n const getAllSelectedRows = useCallback(\n (rowKeys: string[]) => {\n return allDataForSelection.filter((record) =>\n rowKeys.includes(getRowKey(record, rowKey)),\n );\n },\n [allDataForSelection, rowKey],\n );\n\n const changeSelectedRowKeys = useCallback(\n (newSelectedRowKeys: string[]) => {\n setSelectedRowKeysState(newSelectedRowKeys);\n\n // 获取所有选中的行数据(包括被折叠的子项)\n const allSelectedRows = getAllSelectedRows(newSelectedRowKeys);\n rowSelection?.onChange?.(newSelectedRowKeys, allSelectedRows);\n },\n [getAllSelectedRows, rowSelection],\n );\n\n const checkboxAllStatus = getCheckboxAllStatus(\n allDataForSelection,\n selectedRowKeys,\n rowKey,\n rowSelection?.getCheckboxProps,\n );\n\n const selectAll = useCallback(() => {\n const newKeys = getDataWithoutDisabled(\n allDataForSelection,\n rowSelection?.getCheckboxProps,\n ).map((record) => getRowKey(record, rowKey));\n\n changeSelectedRowKeys(newKeys);\n }, [\n allDataForSelection,\n rowKey,\n rowSelection?.getCheckboxProps,\n changeSelectedRowKeys,\n ]);\n\n const unSelectAll = useCallback(() => {\n changeSelectedRowKeys([]);\n }, [changeSelectedRowKeys]);\n\n const onClickAllCheckbox = useCallback<(e?: React.MouseEvent) => void>(() => {\n if (checkboxAllStatus === 'all') {\n unSelectAll();\n } else {\n selectAll();\n }\n }, [checkboxAllStatus, unSelectAll, selectAll]);\n\n // 获取节点的所有子孙节点keys\n const getDescendantKeys = useCallback(\n (parentKey: string): string[] => {\n return getNodeDescendants(parentKey, isExpandable, flattenData, rowKey);\n },\n [isExpandable, flattenData, rowKey],\n );\n\n // 获取节点的所有祖先节点keys\n const getAncestorKeys = useCallback(\n (targetKey: string): string[] => {\n return getNodeAncestors(targetKey, isExpandable, flattenData, rowKey);\n },\n [isExpandable, flattenData, rowKey],\n );\n\n // 获取节点的选择状态(考虑子节点状态)\n const getNodeCheckStatus = useCallback(\n (nodeKey: string): { checked: boolean; indeterminate: boolean } => {\n return calculateNodeCheckStatus(\n nodeKey,\n selectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n );\n },\n [\n selectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n ],\n );\n\n const onClickCheckbox = useCallback(\n (key: string, isChecked: boolean) => () => {\n const newKeys = calculateCascadeSelection(\n key,\n isChecked,\n selectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n getAncestorKeys,\n );\n\n changeSelectedRowKeys(newKeys);\n },\n [\n selectedRowKeys,\n changeSelectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n getAncestorKeys,\n ],\n );\n\n // 全选按钮\n const getCheckboxAllNode = (children?: React.ReactNode) => (\n <div className={prefixCls('row-selection-all')}>\n <Checkbox\n onClick={onClickAllCheckbox}\n checked={checkboxAllStatus === 'all'}\n indeterminate={checkboxAllStatus === 'indeterminate'}\n >\n {children}\n </Checkbox>\n </div>\n );\n\n if (!rowSelection) {\n return {\n columns,\n isRowSelectionEnabled: false,\n getCheckboxAllNode,\n selectedRowKeys: [],\n selectedRowKeysInCurrPage: [],\n unSelectAll,\n isShowRowSelectionInFooter: false,\n items: [],\n onChange: () => {},\n };\n }\n\n if (!rowKey) {\n throw new Error('rowKey is required when rowSelection is enabled');\n }\n\n const fixed = !!rowSelection.fixed || hasFixedLeftColumn(columns);\n\n const rowSelectionColumn: ITableColumn<TDataItem> = {\n dataIndex: '',\n title: (\n <div className={prefixCls('row-selection-all-header-wrap')}>\n {getCheckboxAllNode()}\n </div>\n ),\n width: 48,\n render: (text: unknown, record: TDataItem) => {\n const key = getRowKey(record, rowKey);\n const nodeStatus = getNodeCheckStatus(key);\n const checkboxProps = rowSelection.getCheckboxProps?.(record) || {};\n\n return (\n <div className={prefixCls('row-selection-item')}>\n <Checkbox\n onClick={onClickCheckbox(\n key,\n nodeStatus.checked || nodeStatus.indeterminate,\n )}\n checked={nodeStatus.checked}\n indeterminate={nodeStatus.indeterminate}\n {...checkboxProps}\n />\n </div>\n );\n },\n fixed: fixed ? 'left' : undefined,\n };\n\n const selectedRowKeysInCurrPage = getDataWithoutDisabled(\n data,\n rowSelection.getCheckboxProps,\n )\n .map((record) => getRowKey(record, rowKey))\n .filter((key) => selectedRowKeys.includes(key));\n\n const isShowRowSelectionInFooter = selectedRowKeysInCurrPage.length > 0;\n\n const items =\n rowSelection.items?.map((operationItem) => ({\n ...operationItem,\n onClick: (e: React.MouseEvent) => {\n operationItem.onClick(\n selectedRowKeysInCurrPage,\n getSelectedRows(selectedRowKeysInCurrPage),\n e,\n );\n },\n })) || [];\n\n return {\n columns: [rowSelectionColumn, ...columns],\n isRowSelectionEnabled: true,\n getCheckboxAllNode,\n selectedRowKeys: selectedRowKeys, // 返回完整的选中项列表\n selectedRowKeysInCurrPage, // 当前页面可见的选中项\n unSelectAll,\n isShowRowSelectionInFooter,\n items,\n onChange: changeSelectedRowKeys,\n };\n}\n\nfunction getCheckboxAllStatus<TDataItem extends object>(\n data: TDataItem[],\n selectedRowKeys: string[],\n rowKey: ITableProps<TDataItem>['rowKey'],\n getCheckboxProps?: IRowSelection<TDataItem>['getCheckboxProps'],\n): 'all' | 'none' | 'indeterminate' {\n const enabledData = getDataWithoutDisabled(data, getCheckboxProps);\n\n if (enabledData.length === 0) {\n return 'none';\n }\n\n const selectedEnabledCount = enabledData.filter((record) =>\n selectedRowKeys.includes(getRowKey(record, rowKey)),\n ).length;\n\n if (selectedEnabledCount === 0) {\n return 'none';\n }\n if (selectedEnabledCount === enabledData.length) {\n return 'all';\n }\n return 'indeterminate';\n}\n\nfunction getDataWithoutDisabled<TDataItem extends object>(\n data: TDataItem[],\n getCheckboxProps?: IRowSelection<TDataItem>['getCheckboxProps'],\n) {\n return data.filter((record) => {\n const checkboxProps = getCheckboxProps?.(record) || {};\n const { disabled } = checkboxProps;\n return !disabled;\n });\n}\n\nexport interface IRowSelectionInfo<TDataItem extends object> {\n columns: ITableProps<TDataItem>['columns'];\n isRowSelectionEnabled: boolean;\n getCheckboxAllNode: ((children?: React.ReactNode) => React.ReactNode) | null;\n selectedRowKeys: string[]; // 完整的选中项列表\n selectedRowKeysInCurrPage: string[]; // 当前页面可见的选中项\n unSelectAll: () => void;\n isShowRowSelectionInFooter: boolean;\n items: {\n key: string;\n label: React.ReactNode;\n onClick: (e: React.MouseEvent) => void;\n }[];\n onChange: (selectedRowKeys: string[]) => void;\n}\n\n/**\n * 获取节点的所有子孙节点keys\n * @param parentKey 父节点key\n * @param isExpandable 是否启用展开功能\n * @param flattenData 扁平化后的数据(包含所有节点,包括子节点)\n * @param rowKey 行key获取函数\n * @returns 子孙节点keys数组\n */\nexport function getNodeDescendants<TDataItem extends object>(\n parentKey: string,\n isExpandable?: boolean,\n flattenData?: TDataItem[],\n rowKey?: ITableProps<TDataItem>['rowKey'],\n): string[] {\n if (!isExpandable || !flattenData || !rowKey) return [];\n\n const descendants: string[] = [];\n\n // 找到父节点在flattenData中的记录\n const parentNode = flattenData.find(\n (item) => getRowKey(item, rowKey) === parentKey,\n );\n if (!parentNode) return [];\n\n // 从原始节点的children中收集所有子孙节点\n const collectDescendants = (node: any) => {\n const children = node.children || [];\n children.forEach((child: any) => {\n const childKey = getRowKey(child, rowKey);\n descendants.push(childKey);\n collectDescendants(child);\n });\n };\n\n collectDescendants(parentNode);\n return descendants;\n}\n\n/**\n * 获取节点的所有祖先节点keys\n * @param targetKey 目标节点key\n * @param isExpandable 是否启用展开功能\n * @param flattenData 扁平化后的数据\n * @param rowKey 行key获取函数\n * @returns 祖先节点keys数组(从直接父节点到根节点)\n */\nexport function getNodeAncestors<TDataItem extends object>(\n targetKey: string,\n isExpandable?: boolean,\n flattenData?: TDataItem[],\n rowKey?: ITableProps<TDataItem>['rowKey'],\n): string[] {\n if (!isExpandable || !flattenData || !rowKey) return [];\n\n const ancestors: string[] = [];\n\n // 找到目标节点的直接父节点\n const findDirectParent = (childKey: string): TDataItem | null => {\n for (const item of flattenData) {\n const children = (item as any).children || [];\n if (\n children.some((child: any) => getRowKey(child, rowKey) === childKey)\n ) {\n return item;\n }\n }\n return null;\n };\n\n let currentKey = targetKey;\n\n for (;;) {\n const parent = findDirectParent(currentKey);\n if (!parent) break;\n\n const parentKey = getRowKey(parent, rowKey);\n ancestors.push(parentKey);\n currentKey = parentKey;\n }\n\n return ancestors;\n}\n\n/**\n * 计算级联选择后的keys(包含向上级联)\n * @param targetKey 被操作的节点key\n * @param isChecked 当前是否选中\n * @param currentSelectedKeys 当前已选中的keys\n * @param checkStrictly 是否严格模式\n * @param isExpandable 是否启用展开功能\n * @param getDescendantKeys 获取子孙节点keys的函数\n * @param getAncestorKeys 获取祖先节点keys的函数\n * @returns 新的选中keys\n */\nexport function calculateCascadeSelection(\n targetKey: string,\n isChecked: boolean,\n currentSelectedKeys: string[],\n checkStrictly?: boolean,\n isExpandable?: boolean,\n getDescendantKeys?: (nodeKey: string) => string[],\n getAncestorKeys?: (nodeKey: string) => string[],\n): string[] {\n if (\n checkStrictly ||\n !isExpandable ||\n !getDescendantKeys ||\n !getAncestorKeys\n ) {\n // 严格模式,不进行级联\n return isChecked\n ? currentSelectedKeys.filter((key) => key !== targetKey)\n : [...currentSelectedKeys, targetKey];\n }\n\n let newKeys = [...currentSelectedKeys];\n\n if (isChecked) {\n // 取消选择:移除目标节点和所有子孙节点\n newKeys = newKeys.filter((key) => key !== targetKey);\n const descendants = getDescendantKeys(targetKey);\n newKeys = newKeys.filter((key) => !descendants.includes(key));\n\n // 向上级联:检查父节点是否需要取消选择\n const ancestors = getAncestorKeys(targetKey);\n ancestors.forEach((ancestorKey) => {\n const ancestorDescendants = getDescendantKeys(ancestorKey);\n const selectedDescendantsCount = ancestorDescendants.filter((key) =>\n newKeys.includes(key),\n ).length;\n\n // 如果子孙节点没有全部选中,则父节点也应该取消选择\n if (selectedDescendantsCount < ancestorDescendants.length) {\n newKeys = newKeys.filter((key) => key !== ancestorKey);\n }\n });\n } else {\n // 选择:添加目标节点和所有子孙节点\n if (!newKeys.includes(targetKey)) {\n newKeys.push(targetKey);\n }\n const descendants = getDescendantKeys(targetKey);\n descendants.forEach((descendantKey) => {\n if (!newKeys.includes(descendantKey)) {\n newKeys.push(descendantKey);\n }\n });\n\n // 向上级联:检查父节点是否需要选择\n const ancestors = getAncestorKeys(targetKey);\n ancestors.forEach((ancestorKey) => {\n const ancestorDescendants = getDescendantKeys(ancestorKey);\n const selectedDescendantsCount = ancestorDescendants.filter((key) =>\n newKeys.includes(key),\n ).length;\n\n // 如果所有子孙节点都被选中,则父节点也应该被选中\n if (\n selectedDescendantsCount === ancestorDescendants.length &&\n !newKeys.includes(ancestorKey)\n ) {\n newKeys.push(ancestorKey);\n }\n });\n }\n\n return newKeys;\n}\n\n/**\n * 计算节点的选择状态(考虑子节点状态)\n * @param nodeKey 节点key\n * @param selectedRowKeys 已选中的keys\n * @param checkStrictly 是否严格模式\n * @param isExpandable 是否启用展开功能\n * @param getDescendantKeys 获取子孙节点keys的函数\n * @returns 节点的选择状态\n */\nexport function calculateNodeCheckStatus(\n nodeKey: string,\n selectedRowKeys: string[],\n checkStrictly?: boolean,\n isExpandable?: boolean,\n getDescendantKeys?: (nodeKey: string) => string[],\n): { checked: boolean; indeterminate: boolean } {\n if (checkStrictly || !isExpandable || !getDescendantKeys) {\n // 严格模式下或非展开模式,直接返回节点本身的选择状态\n return {\n checked: selectedRowKeys.includes(nodeKey),\n indeterminate: false,\n };\n }\n\n const descendants = getDescendantKeys(nodeKey);\n\n // 如果没有子节点,直接返回本身状态\n if (descendants.length === 0) {\n return {\n checked: selectedRowKeys.includes(nodeKey),\n indeterminate: false,\n };\n }\n\n const selectedDescendants = descendants.filter((key) =>\n selectedRowKeys.includes(key),\n );\n const isNodeSelected = selectedRowKeys.includes(nodeKey);\n\n if (isNodeSelected && selectedDescendants.length === descendants.length) {\n // 节点本身选中且所有子节点都选中\n return { checked: true, indeterminate: false };\n } else if (!isNodeSelected && selectedDescendants.length === 0) {\n // 节点本身未选中且所有子节点都未选中\n return { checked: false, indeterminate: false };\n } else {\n // 部分选中的情况:节点选中但子节点未全选,或节点未选中但部分子节点选中\n return { checked: false, indeterminate: true };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useRowSelection.js","names":[],"sources":["../../../src/Table/hooks/useRowSelection.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useState } from 'react';\nimport Checkbox from '../../Checkbox';\nimport { getRowKey, hasFixedLeftColumn, prefixCls } from '../helper';\nimport { IRowSelection, ITableColumn, ITableProps } from '../types';\n\nexport default function useRowSelection<TDataItem extends object>(\n props: ITableProps<TDataItem> & {\n isExpandable?: boolean;\n flattenData?: TDataItem[];\n },\n): IRowSelectionInfo<TDataItem> {\n const { columns, rowSelection, rowKey, data, isExpandable, flattenData } =\n props;\n\n const [selectedRowKeysState, setSelectedRowKeysState] = useState(\n rowSelection?.selectedRowKeys || rowSelection?.defaultSelectedRowKeys || [],\n );\n\n const selectedRowKeys = rowSelection?.selectedRowKeys || selectedRowKeysState;\n\n const getSelectedRows = useCallback(\n (rowKeys: string[]) => {\n return data.filter((record) =>\n rowKeys.includes(getRowKey(record, rowKey)),\n );\n },\n [data, rowKey],\n );\n\n // 获取用于全选状态计算和数据获取的完整数据\n const allDataForSelection = useMemo(() => {\n // 如果开启了 expandable,使用扁平化后的数据\n if (isExpandable && flattenData) {\n return flattenData;\n }\n // 否则使用原始数据\n return data;\n }, [isExpandable, flattenData, data]);\n\n // 从完整数据中获取选中的行\n const getAllSelectedRows = useCallback(\n (rowKeys: string[]) => {\n return allDataForSelection.filter((record) =>\n rowKeys.includes(getRowKey(record, rowKey)),\n );\n },\n [allDataForSelection, rowKey],\n );\n\n const changeSelectedRowKeys = useCallback(\n (newSelectedRowKeys: string[]) => {\n setSelectedRowKeysState(newSelectedRowKeys);\n\n // 获取所有选中的行数据(包括被折叠的子项)\n const allSelectedRows = getAllSelectedRows(newSelectedRowKeys);\n rowSelection?.onChange?.(newSelectedRowKeys, allSelectedRows);\n },\n [getAllSelectedRows, rowSelection],\n );\n\n const checkboxAllStatus = getCheckboxAllStatus(\n allDataForSelection,\n selectedRowKeys,\n rowKey,\n rowSelection?.getCheckboxProps,\n );\n\n const selectAll = useCallback(() => {\n const newKeys = getDataWithoutDisabled(\n allDataForSelection,\n rowSelection?.getCheckboxProps,\n ).map((record) => getRowKey(record, rowKey));\n\n changeSelectedRowKeys(newKeys);\n }, [\n allDataForSelection,\n rowKey,\n rowSelection?.getCheckboxProps,\n changeSelectedRowKeys,\n ]);\n\n const unSelectAll = useCallback(() => {\n changeSelectedRowKeys([]);\n }, [changeSelectedRowKeys]);\n\n const onChangeAllCheckbox = useCallback(() => {\n if (checkboxAllStatus === 'all') {\n unSelectAll();\n } else {\n selectAll();\n }\n }, [checkboxAllStatus, unSelectAll, selectAll]);\n\n // 获取节点的所有子孙节点keys\n const getDescendantKeys = useCallback(\n (parentKey: string): string[] => {\n return getNodeDescendants(parentKey, isExpandable, flattenData, rowKey);\n },\n [isExpandable, flattenData, rowKey],\n );\n\n // 获取节点的所有祖先节点keys\n const getAncestorKeys = useCallback(\n (targetKey: string): string[] => {\n return getNodeAncestors(targetKey, isExpandable, flattenData, rowKey);\n },\n [isExpandable, flattenData, rowKey],\n );\n\n // 获取节点的选择状态(考虑子节点状态)\n const getNodeCheckStatus = useCallback(\n (nodeKey: string): { checked: boolean; indeterminate: boolean } => {\n return calculateNodeCheckStatus(\n nodeKey,\n selectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n );\n },\n [\n selectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n ],\n );\n\n const onChangeCheckbox = useCallback(\n (key: string, isChecked: boolean) => () => {\n const newKeys = calculateCascadeSelection(\n key,\n isChecked,\n selectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n getAncestorKeys,\n );\n\n changeSelectedRowKeys(newKeys);\n },\n [\n selectedRowKeys,\n changeSelectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n getAncestorKeys,\n ],\n );\n\n // 全选按钮\n const getCheckboxAllNode = (children?: React.ReactNode) => (\n <div className={prefixCls('row-selection-all')}>\n <Checkbox\n onChange={onChangeAllCheckbox}\n checked={checkboxAllStatus === 'all'}\n indeterminate={checkboxAllStatus === 'indeterminate'}\n >\n {children || <span className=\"tw-sr-only\">Select all rows</span>}\n </Checkbox>\n </div>\n );\n\n if (!rowSelection) {\n return {\n columns,\n isRowSelectionEnabled: false,\n getCheckboxAllNode,\n selectedRowKeys: [],\n selectedRowKeysInCurrPage: [],\n unSelectAll,\n isShowRowSelectionInFooter: false,\n items: [],\n onChange: () => {},\n };\n }\n\n if (!rowKey) {\n throw new Error('rowKey is required when rowSelection is enabled');\n }\n\n const fixed = !!rowSelection.fixed || hasFixedLeftColumn(columns);\n\n const rowSelectionColumn: ITableColumn<TDataItem> = {\n dataIndex: '',\n title: (\n <div className={prefixCls('row-selection-all-header-wrap')}>\n {getCheckboxAllNode()}\n </div>\n ),\n width: 48,\n render: (text: unknown, record: TDataItem) => {\n const key = getRowKey(record, rowKey);\n const nodeStatus = getNodeCheckStatus(key);\n const checkboxProps = rowSelection.getCheckboxProps?.(record) || {};\n\n return (\n <div className={prefixCls('row-selection-item')}>\n <Checkbox\n onChange={onChangeCheckbox(\n key,\n nodeStatus.checked || nodeStatus.indeterminate,\n )}\n checked={nodeStatus.checked}\n indeterminate={nodeStatus.indeterminate}\n {...checkboxProps}\n >\n <span className=\"tw-sr-only\">Select row {key}</span>\n </Checkbox>\n </div>\n );\n },\n fixed: fixed ? 'left' : undefined,\n };\n\n const selectedRowKeysInCurrPage = getDataWithoutDisabled(\n data,\n rowSelection.getCheckboxProps,\n )\n .map((record) => getRowKey(record, rowKey))\n .filter((key) => selectedRowKeys.includes(key));\n\n const isShowRowSelectionInFooter = selectedRowKeysInCurrPage.length > 0;\n\n const items =\n rowSelection.items?.map((operationItem) => ({\n ...operationItem,\n onClick: (e: React.MouseEvent) => {\n operationItem.onClick(\n selectedRowKeysInCurrPage,\n getSelectedRows(selectedRowKeysInCurrPage),\n e,\n );\n },\n })) || [];\n\n return {\n columns: [rowSelectionColumn, ...columns],\n isRowSelectionEnabled: true,\n getCheckboxAllNode,\n selectedRowKeys: selectedRowKeys, // 返回完整的选中项列表\n selectedRowKeysInCurrPage, // 当前页面可见的选中项\n unSelectAll,\n isShowRowSelectionInFooter,\n items,\n onChange: changeSelectedRowKeys,\n };\n}\n\nfunction getCheckboxAllStatus<TDataItem extends object>(\n data: TDataItem[],\n selectedRowKeys: string[],\n rowKey: ITableProps<TDataItem>['rowKey'],\n getCheckboxProps?: IRowSelection<TDataItem>['getCheckboxProps'],\n): 'all' | 'none' | 'indeterminate' {\n const enabledData = getDataWithoutDisabled(data, getCheckboxProps);\n\n if (enabledData.length === 0) {\n return 'none';\n }\n\n const selectedEnabledCount = enabledData.filter((record) =>\n selectedRowKeys.includes(getRowKey(record, rowKey)),\n ).length;\n\n if (selectedEnabledCount === 0) {\n return 'none';\n }\n if (selectedEnabledCount === enabledData.length) {\n return 'all';\n }\n return 'indeterminate';\n}\n\nfunction getDataWithoutDisabled<TDataItem extends object>(\n data: TDataItem[],\n getCheckboxProps?: IRowSelection<TDataItem>['getCheckboxProps'],\n) {\n return data.filter((record) => {\n const checkboxProps = getCheckboxProps?.(record) || {};\n const { disabled } = checkboxProps;\n return !disabled;\n });\n}\n\nexport interface IRowSelectionInfo<TDataItem extends object> {\n columns: ITableProps<TDataItem>['columns'];\n isRowSelectionEnabled: boolean;\n getCheckboxAllNode: ((children?: React.ReactNode) => React.ReactNode) | null;\n selectedRowKeys: string[]; // 完整的选中项列表\n selectedRowKeysInCurrPage: string[]; // 当前页面可见的选中项\n unSelectAll: () => void;\n isShowRowSelectionInFooter: boolean;\n items: {\n key: string;\n label: React.ReactNode;\n onClick: (e: React.MouseEvent) => void;\n }[];\n onChange: (selectedRowKeys: string[]) => void;\n}\n\n/**\n * 获取节点的所有子孙节点keys\n * @param parentKey 父节点key\n * @param isExpandable 是否启用展开功能\n * @param flattenData 扁平化后的数据(包含所有节点,包括子节点)\n * @param rowKey 行key获取函数\n * @returns 子孙节点keys数组\n */\nexport function getNodeDescendants<TDataItem extends object>(\n parentKey: string,\n isExpandable?: boolean,\n flattenData?: TDataItem[],\n rowKey?: ITableProps<TDataItem>['rowKey'],\n): string[] {\n if (!isExpandable || !flattenData || !rowKey) return [];\n\n const descendants: string[] = [];\n\n // 找到父节点在flattenData中的记录\n const parentNode = flattenData.find(\n (item) => getRowKey(item, rowKey) === parentKey,\n );\n if (!parentNode) return [];\n\n // 从原始节点的children中收集所有子孙节点\n const collectDescendants = (node: any) => {\n const children = node.children || [];\n children.forEach((child: any) => {\n const childKey = getRowKey(child, rowKey);\n descendants.push(childKey);\n collectDescendants(child);\n });\n };\n\n collectDescendants(parentNode);\n return descendants;\n}\n\n/**\n * 获取节点的所有祖先节点keys\n * @param targetKey 目标节点key\n * @param isExpandable 是否启用展开功能\n * @param flattenData 扁平化后的数据\n * @param rowKey 行key获取函数\n * @returns 祖先节点keys数组(从直接父节点到根节点)\n */\nexport function getNodeAncestors<TDataItem extends object>(\n targetKey: string,\n isExpandable?: boolean,\n flattenData?: TDataItem[],\n rowKey?: ITableProps<TDataItem>['rowKey'],\n): string[] {\n if (!isExpandable || !flattenData || !rowKey) return [];\n\n const ancestors: string[] = [];\n\n // 找到目标节点的直接父节点\n const findDirectParent = (childKey: string): TDataItem | null => {\n for (const item of flattenData) {\n const children = (item as any).children || [];\n if (\n children.some((child: any) => getRowKey(child, rowKey) === childKey)\n ) {\n return item;\n }\n }\n return null;\n };\n\n let currentKey = targetKey;\n\n for (;;) {\n const parent = findDirectParent(currentKey);\n if (!parent) break;\n\n const parentKey = getRowKey(parent, rowKey);\n ancestors.push(parentKey);\n currentKey = parentKey;\n }\n\n return ancestors;\n}\n\n/**\n * 计算级联选择后的keys(包含向上级联)\n * @param targetKey 被操作的节点key\n * @param isChecked 当前是否选中\n * @param currentSelectedKeys 当前已选中的keys\n * @param checkStrictly 是否严格模式\n * @param isExpandable 是否启用展开功能\n * @param getDescendantKeys 获取子孙节点keys的函数\n * @param getAncestorKeys 获取祖先节点keys的函数\n * @returns 新的选中keys\n */\nexport function calculateCascadeSelection(\n targetKey: string,\n isChecked: boolean,\n currentSelectedKeys: string[],\n checkStrictly?: boolean,\n isExpandable?: boolean,\n getDescendantKeys?: (nodeKey: string) => string[],\n getAncestorKeys?: (nodeKey: string) => string[],\n): string[] {\n if (\n checkStrictly ||\n !isExpandable ||\n !getDescendantKeys ||\n !getAncestorKeys\n ) {\n // 严格模式,不进行级联\n return isChecked\n ? currentSelectedKeys.filter((key) => key !== targetKey)\n : [...currentSelectedKeys, targetKey];\n }\n\n let newKeys = [...currentSelectedKeys];\n\n if (isChecked) {\n // 取消选择:移除目标节点和所有子孙节点\n newKeys = newKeys.filter((key) => key !== targetKey);\n const descendants = getDescendantKeys(targetKey);\n newKeys = newKeys.filter((key) => !descendants.includes(key));\n\n // 向上级联:检查父节点是否需要取消选择\n const ancestors = getAncestorKeys(targetKey);\n ancestors.forEach((ancestorKey) => {\n const ancestorDescendants = getDescendantKeys(ancestorKey);\n const selectedDescendantsCount = ancestorDescendants.filter((key) =>\n newKeys.includes(key),\n ).length;\n\n // 如果子孙节点没有全部选中,则父节点也应该取消选择\n if (selectedDescendantsCount < ancestorDescendants.length) {\n newKeys = newKeys.filter((key) => key !== ancestorKey);\n }\n });\n } else {\n // 选择:添加目标节点和所有子孙节点\n if (!newKeys.includes(targetKey)) {\n newKeys.push(targetKey);\n }\n const descendants = getDescendantKeys(targetKey);\n descendants.forEach((descendantKey) => {\n if (!newKeys.includes(descendantKey)) {\n newKeys.push(descendantKey);\n }\n });\n\n // 向上级联:检查父节点是否需要选择\n const ancestors = getAncestorKeys(targetKey);\n ancestors.forEach((ancestorKey) => {\n const ancestorDescendants = getDescendantKeys(ancestorKey);\n const selectedDescendantsCount = ancestorDescendants.filter((key) =>\n newKeys.includes(key),\n ).length;\n\n // 如果所有子孙节点都被选中,则父节点也应该被选中\n if (\n selectedDescendantsCount === ancestorDescendants.length &&\n !newKeys.includes(ancestorKey)\n ) {\n newKeys.push(ancestorKey);\n }\n });\n }\n\n return newKeys;\n}\n\n/**\n * 计算节点的选择状态(考虑子节点状态)\n * @param nodeKey 节点key\n * @param selectedRowKeys 已选中的keys\n * @param checkStrictly 是否严格模式\n * @param isExpandable 是否启用展开功能\n * @param getDescendantKeys 获取子孙节点keys的函数\n * @returns 节点的选择状态\n */\nexport function calculateNodeCheckStatus(\n nodeKey: string,\n selectedRowKeys: string[],\n checkStrictly?: boolean,\n isExpandable?: boolean,\n getDescendantKeys?: (nodeKey: string) => string[],\n): { checked: boolean; indeterminate: boolean } {\n if (checkStrictly || !isExpandable || !getDescendantKeys) {\n // 严格模式下或非展开模式,直接返回节点本身的选择状态\n return {\n checked: selectedRowKeys.includes(nodeKey),\n indeterminate: false,\n };\n }\n\n const descendants = getDescendantKeys(nodeKey);\n\n // 如果没有子节点,直接返回本身状态\n if (descendants.length === 0) {\n return {\n checked: selectedRowKeys.includes(nodeKey),\n indeterminate: false,\n };\n }\n\n const selectedDescendants = descendants.filter((key) =>\n selectedRowKeys.includes(key),\n );\n const isNodeSelected = selectedRowKeys.includes(nodeKey);\n\n if (isNodeSelected && selectedDescendants.length === descendants.length) {\n // 节点本身选中且所有子节点都选中\n return { checked: true, indeterminate: false };\n } else if (!isNodeSelected && selectedDescendants.length === 0) {\n // 节点本身未选中且所有子节点都未选中\n return { checked: false, indeterminate: false };\n } else {\n // 部分选中的情况:节点选中但子节点未全选,或节点未选中但部分子节点选中\n return { checked: false, indeterminate: true };\n }\n}\n"],"mappings":"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"}
@@ -46,7 +46,7 @@ function TableResizeWrapper({ children, onResize }) {
46
46
  });
47
47
  }
48
48
  function Table(props, ref) {
49
- const { data, bordered, rowKey, columnSizing, sticky, loading, pagination, scroll = {}, empty: emptyComponent, virtual = false, rowClassName = () => "", onRowClick, onError, onSort, expandable, rowDnd } = props;
49
+ const { data, bordered, rowKey, columnSizing, sticky, loading, pagination, scroll = {}, empty: emptyComponent, virtual = false, rowClassName = () => "", onRowClick, onError, onSort, expandable, rowDnd, rowSelection } = props;
50
50
  const [totalSize, setTotalSize] = useState(null);
51
51
  const [hoverRowId, setHoverRowId] = useState(null);
52
52
  const { y } = scroll;
@@ -118,6 +118,9 @@ function Table(props, ref) {
118
118
  const showResizer = columnSizing && !(!!rowSelectionInfo.isRowSelectionEnabled && index === 0);
119
119
  const { className: fixedClassName, style: fixedStyle } = getColumnFixedInfo(index, true);
120
120
  return /* @__PURE__ */ jsxs("div", {
121
+ role: "columnheader",
122
+ "aria-label": typeof header.column.columnDef.meta.title === "string" ? header.column.columnDef.meta.title : void 0,
123
+ "aria-sort": header.column.columnDef.meta.sortOrder === "ascend" ? "ascending" : header.column.columnDef.meta.sortOrder === "descend" ? "descending" : header.column.columnDef.meta.sortOrder !== void 0 ? "none" : void 0,
121
124
  className: cn(prefixCls("th"), fixedClassName),
122
125
  style: {
123
126
  width: header.getSize(),
@@ -150,6 +153,7 @@ function Table(props, ref) {
150
153
  virtualPaddingRight = columnVirtualizer.getTotalSize() - (virtualColumns[virtualColumns.length - 1]?.end ?? 0);
151
154
  }
152
155
  const headerContent = /* @__PURE__ */ jsx("div", {
156
+ role: "rowgroup",
153
157
  className: cn(prefixCls("header"), {
154
158
  [prefixCls("overflow-x")]: true,
155
159
  [prefixCls("sticky")]: isStickyWork,
@@ -204,6 +208,7 @@ function Table(props, ref) {
204
208
  } else content = _.map(allHeaderCells, (header, index) => renderHeaderCell(header, index));
205
209
  return /* @__PURE__ */ jsxs("div", {
206
210
  className: prefixCls("tr"),
211
+ role: "row",
207
212
  style: { width: totalColumnsWidth },
208
213
  children: [content, y !== void 0 && /* @__PURE__ */ jsx("div", {
209
214
  className: prefixCls("header-scroll-placeholder"),
@@ -234,6 +239,7 @@ function Table(props, ref) {
234
239
  const { className: fixedClassName, style: fixedStyle } = getColumnFixedInfo(colIndex);
235
240
  const tdContent = flexRender(cell.column.columnDef.cell, cell.getContext());
236
241
  return /* @__PURE__ */ jsx("div", {
242
+ role: "cell",
237
243
  className: cn(prefixCls("td"), fixedClassName),
238
244
  style: {
239
245
  width: cell.column.getSize(),
@@ -255,6 +261,7 @@ function Table(props, ref) {
255
261
  rowSelectionInfo.isRowSelectionEnabled
256
262
  ]);
257
263
  const bodyContent = /* @__PURE__ */ jsx("div", {
264
+ role: "rowgroup",
258
265
  className: prefixCls("body"),
259
266
  style: {
260
267
  width: totalColumnsWidth,
@@ -272,6 +279,8 @@ function Table(props, ref) {
272
279
  })
273
280
  })
274
281
  }), /* @__PURE__ */ jsx("div", {
282
+ role: "status",
283
+ "aria-live": "polite",
275
284
  "aria-invalid": "true",
276
285
  style: {
277
286
  position: "absolute",
@@ -336,11 +345,17 @@ function Table(props, ref) {
336
345
  ] });
337
346
  } else content = allRowCells.map((cell, index) => renderBodyCell(row, cell, index));
338
347
  const rowId = row.id;
348
+ const isRowSelected = rowSelectionInfo.isRowSelectionEnabled && rowSelectionInfo.selectedRowKeys.includes(rowId);
349
+ const isRowSelectionDisabled = rowSelectionInfo.isRowSelectionEnabled && !!rowSelection?.getCheckboxProps?.(row.original).disabled;
339
350
  const rowNode = /* @__PURE__ */ jsx("div", {
351
+ role: "row",
352
+ "aria-rowindex": rowIndex + 2,
340
353
  "data-index": virtual ? rowData.index : rowIndex,
341
354
  className: cn(prefixCls("tr"), {
342
355
  [prefixCls("row-hover")]: rowDndInfo.draggingRowId ? void 0 : hoverRowId === rowId,
343
356
  [prefixCls("row-dragging")]: rowDndInfo.draggingRowId === rowId,
357
+ [prefixCls("row-selected")]: isRowSelected,
358
+ [prefixCls("row-selection-disabled")]: isRowSelectionDisabled,
344
359
  [prefixCls("no-border-tr")]: isShowPagination && rowIndex === rows.length - 1
345
360
  }, rowClassName(row.original, rowIndex)),
346
361
  ref: (node) => {
@@ -351,7 +366,9 @@ function Table(props, ref) {
351
366
  }
352
367
  },
353
368
  onClick: onClickRow(row.original, rowIndex),
354
- onMouseEnter: () => setHoverRowId(rowId),
369
+ onMouseEnter: () => {
370
+ if (!isRowSelectionDisabled) setHoverRowId(rowId);
371
+ },
355
372
  onMouseLeave: () => setHoverRowId(null),
356
373
  style: virtual ? {
357
374
  position: "absolute",
@@ -371,6 +388,7 @@ function Table(props, ref) {
371
388
  if (expandItem?.isExpanded !== true) return rowList;
372
389
  const customRow = /* @__PURE__ */ jsx("div", {
373
390
  className: cn(prefixCls("tr")),
391
+ role: "row",
374
392
  onClick: onClickRow(row.original, rowIndex),
375
393
  children: expandedRowRender(row.original, expandItem.level + 1)
376
394
  }, customExpandRowKey);
@@ -386,35 +404,38 @@ function Table(props, ref) {
386
404
  totalSize,
387
405
  isShowFooter
388
406
  ]);
389
- const tableContent = /* @__PURE__ */ jsx(CustomSpin, {
390
- spinning: !!loading,
391
- children: /* @__PURE__ */ jsxs("div", {
392
- className: prefixCls("content"),
393
- children: [
394
- headerContent,
395
- /* @__PURE__ */ jsx("div", {
396
- style: {
397
- height: tableContentHeight,
398
- position: virtual ? "relative" : void 0
399
- },
400
- className: cn(prefixCls("body-scroll"), {
401
- [prefixCls("scroll-y")]: y !== void 0,
402
- [prefixCls("scroll-hidden")]: isEmpty
403
- }),
404
- ref: bodyRef,
405
- onScroll: onBodyScroll,
406
- children: bodyContent
407
+ const tableContentBody = /* @__PURE__ */ jsxs("div", {
408
+ className: prefixCls("content"),
409
+ role: "table",
410
+ "aria-label": "Data table",
411
+ children: [
412
+ headerContent,
413
+ /* @__PURE__ */ jsx("div", {
414
+ style: {
415
+ height: tableContentHeight,
416
+ position: virtual ? "relative" : void 0
417
+ },
418
+ className: cn(prefixCls("body-scroll"), {
419
+ [prefixCls("scroll-y")]: y !== void 0,
420
+ [prefixCls("scroll-hidden")]: isEmpty
407
421
  }),
408
- isShowFooter && /* @__PURE__ */ jsx(TableFooter, {
409
- rowSelectionInfo,
410
- isShowPagination,
411
- pagination,
412
- scroll,
413
- scrollToFirstRow
414
- })
415
- ]
416
- })
422
+ ref: bodyRef,
423
+ onScroll: onBodyScroll,
424
+ children: bodyContent
425
+ }),
426
+ isShowFooter && /* @__PURE__ */ jsx(TableFooter, {
427
+ rowSelectionInfo,
428
+ isShowPagination,
429
+ pagination,
430
+ scroll,
431
+ scrollToFirstRow
432
+ })
433
+ ]
417
434
  });
435
+ const tableContent = loading ? /* @__PURE__ */ jsx(CustomSpin, {
436
+ spinning: true,
437
+ children: tableContentBody
438
+ }) : tableContentBody;
418
439
  const tableStyle = {};
419
440
  if (y) tableStyle.height = y;
420
441
  return /* @__PURE__ */ jsx("div", {