@superad/ui 0.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 (343) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -0
  3. package/es/Button/Button.d.mts +7 -0
  4. package/es/Button/Button.mjs +29 -0
  5. package/es/Button/Button.mjs.map +1 -0
  6. package/es/Button/index.d.mts +3 -0
  7. package/es/Button/index.d.ts +1 -0
  8. package/es/Button/index.js +1 -0
  9. package/es/Button/index.mjs +2 -0
  10. package/es/Button/style.mjs +33 -0
  11. package/es/Button/style.mjs.map +1 -0
  12. package/es/Button/type.d.mts +21 -0
  13. package/es/ConfigProvider/index.d.mts +9 -0
  14. package/es/ConfigProvider/index.d.ts +1 -0
  15. package/es/ConfigProvider/index.js +1 -0
  16. package/es/ConfigProvider/index.mjs +82 -0
  17. package/es/ConfigProvider/index.mjs.map +1 -0
  18. package/es/ConfigProvider/type.d.mts +24 -0
  19. package/es/DraggablePanel/DraggablePanel.d.mts +6 -0
  20. package/es/DraggablePanel/DraggablePanel.mjs +104 -0
  21. package/es/DraggablePanel/DraggablePanel.mjs.map +1 -0
  22. package/es/DraggablePanel/index.d.mts +3 -0
  23. package/es/DraggablePanel/index.d.ts +1 -0
  24. package/es/DraggablePanel/index.js +1 -0
  25. package/es/DraggablePanel/index.mjs +3 -0
  26. package/es/DraggablePanel/style.mjs +86 -0
  27. package/es/DraggablePanel/style.mjs.map +1 -0
  28. package/es/DraggablePanel/type.d.mts +27 -0
  29. package/es/Flex/Center.d.mts +7 -0
  30. package/es/Flex/Center.mjs +14 -0
  31. package/es/Flex/Center.mjs.map +1 -0
  32. package/es/Flex/FlexBasic.d.mts +6 -0
  33. package/es/Flex/FlexBasic.mjs +46 -0
  34. package/es/Flex/FlexBasic.mjs.map +1 -0
  35. package/es/Flex/Flexbox.d.mts +2 -0
  36. package/es/Flex/index.d.mts +5 -0
  37. package/es/Flex/index.d.ts +1 -0
  38. package/es/Flex/index.js +1 -0
  39. package/es/Flex/index.mjs +3 -0
  40. package/es/Flex/type.d.mts +35 -0
  41. package/es/Flex/utils.mjs +24 -0
  42. package/es/Flex/utils.mjs.map +1 -0
  43. package/es/FontLoader/index.d.mts +9 -0
  44. package/es/FontLoader/index.d.ts +1 -0
  45. package/es/FontLoader/index.js +1 -0
  46. package/es/FontLoader/index.mjs +23 -0
  47. package/es/FontLoader/index.mjs.map +1 -0
  48. package/es/GlobalFocusRing/index.d.mts +6 -0
  49. package/es/GlobalFocusRing/index.d.ts +1 -0
  50. package/es/GlobalFocusRing/index.js +1 -0
  51. package/es/GlobalFocusRing/index.mjs +204 -0
  52. package/es/GlobalFocusRing/index.mjs.map +1 -0
  53. package/es/GlobalFocusRing/style.mjs +35 -0
  54. package/es/GlobalFocusRing/style.mjs.map +1 -0
  55. package/es/Provider.d.mts +5 -0
  56. package/es/Table/canvas/canvasPalette.mjs +11 -0
  57. package/es/Table/canvas/canvasPalette.mjs.map +1 -0
  58. package/es/Table/canvas/chipPainters.mjs +408 -0
  59. package/es/Table/canvas/chipPainters.mjs.map +1 -0
  60. package/es/Table/canvas/controlPainters.mjs +193 -0
  61. package/es/Table/canvas/controlPainters.mjs.map +1 -0
  62. package/es/Table/canvas/groupTitle.mjs +181 -0
  63. package/es/Table/canvas/groupTitle.mjs.map +1 -0
  64. package/es/Table/canvas/paintUtils.mjs +70 -0
  65. package/es/Table/canvas/paintUtils.mjs.map +1 -0
  66. package/es/Table/canvas/rowSeries.mjs +130 -0
  67. package/es/Table/canvas/rowSeries.mjs.map +1 -0
  68. package/es/Table/canvas/textPainters.mjs +97 -0
  69. package/es/Table/canvas/textPainters.mjs.map +1 -0
  70. package/es/Table/canvas/theme.d.mts +14 -0
  71. package/es/Table/canvas/theme.mjs +276 -0
  72. package/es/Table/canvas/theme.mjs.map +1 -0
  73. package/es/Table/core/cellValue.d.mts +1 -0
  74. package/es/Table/core/cellValue.mjs +240 -0
  75. package/es/Table/core/cellValue.mjs.map +1 -0
  76. package/es/Table/core/rowSelection.mjs +138 -0
  77. package/es/Table/core/rowSelection.mjs.map +1 -0
  78. package/es/Table/core/size.mjs +60 -0
  79. package/es/Table/core/size.mjs.map +1 -0
  80. package/es/Table/core/tableI18n.d.mts +11 -0
  81. package/es/Table/core/tableI18n.mjs +123 -0
  82. package/es/Table/core/tableI18n.mjs.map +1 -0
  83. package/es/Table/core/tagTone.mjs +245 -0
  84. package/es/Table/core/tagTone.mjs.map +1 -0
  85. package/es/Table/core/zIndex.mjs +7 -0
  86. package/es/Table/core/zIndex.mjs.map +1 -0
  87. package/es/Table/index.d.mts +6 -0
  88. package/es/Table/index.d.ts +1 -0
  89. package/es/Table/index.js +1 -0
  90. package/es/Table/index.mjs +6 -0
  91. package/es/Table/react/Table.d.mts +9 -0
  92. package/es/Table/react/Table.mjs +407 -0
  93. package/es/Table/react/Table.mjs.map +1 -0
  94. package/es/Table/react/TableColumnSettings.mjs +65 -0
  95. package/es/Table/react/TableColumnSettings.mjs.map +1 -0
  96. package/es/Table/react/a11y.mjs +72 -0
  97. package/es/Table/react/a11y.mjs.map +1 -0
  98. package/es/Table/react/editors/base.mjs +427 -0
  99. package/es/Table/react/editors/base.mjs.map +1 -0
  100. package/es/Table/react/editors/inline.mjs +225 -0
  101. package/es/Table/react/editors/inline.mjs.map +1 -0
  102. package/es/Table/react/editors/picker.mjs +368 -0
  103. package/es/Table/react/editors/picker.mjs.map +1 -0
  104. package/es/Table/react/overlayChips.mjs +50 -0
  105. package/es/Table/react/overlayChips.mjs.map +1 -0
  106. package/es/Table/react/sameRenderInputs.mjs +50 -0
  107. package/es/Table/react/sameRenderInputs.mjs.map +1 -0
  108. package/es/Table/react/style.mjs +650 -0
  109. package/es/Table/react/style.mjs.map +1 -0
  110. package/es/Table/react/useTableCellEvents.mjs +32 -0
  111. package/es/Table/react/useTableCellEvents.mjs.map +1 -0
  112. package/es/Table/react/useTableColumnSettings.mjs +107 -0
  113. package/es/Table/react/useTableColumnSettings.mjs.map +1 -0
  114. package/es/Table/react/useTableEditorSync.mjs +41 -0
  115. package/es/Table/react/useTableEditorSync.mjs.map +1 -0
  116. package/es/Table/react/useTableHoverHint.mjs +62 -0
  117. package/es/Table/react/useTableHoverHint.mjs.map +1 -0
  118. package/es/Table/react/useTableKeyboard.mjs +41 -0
  119. package/es/Table/react/useTableKeyboard.mjs.map +1 -0
  120. package/es/Table/react/useTableRenderState.mjs +194 -0
  121. package/es/Table/react/useTableRenderState.mjs.map +1 -0
  122. package/es/Table/react/useTableScroll.mjs +33 -0
  123. package/es/Table/react/useTableScroll.mjs.map +1 -0
  124. package/es/Table/react/useTableSelectionInfo.mjs +48 -0
  125. package/es/Table/react/useTableSelectionInfo.mjs.map +1 -0
  126. package/es/Table/react/useTableVTableEvents.mjs +132 -0
  127. package/es/Table/react/useTableVTableEvents.mjs.map +1 -0
  128. package/es/Table/type.d.mts +279 -0
  129. package/es/Table/type.mjs +34 -0
  130. package/es/Table/type.mjs.map +1 -0
  131. package/es/Table/vtable/columns.d.mts +17 -0
  132. package/es/Table/vtable/columns.mjs +381 -0
  133. package/es/Table/vtable/columns.mjs.map +1 -0
  134. package/es/Table/vtable/frozenShadow.mjs +27 -0
  135. package/es/Table/vtable/frozenShadow.mjs.map +1 -0
  136. package/es/Table/vtable/interaction.mjs +175 -0
  137. package/es/Table/vtable/interaction.mjs.map +1 -0
  138. package/es/Table/vtable/option.d.mts +39 -0
  139. package/es/Table/vtable/option.mjs +232 -0
  140. package/es/Table/vtable/option.mjs.map +1 -0
  141. package/es/Table/vtable/seriesSelection.mjs +374 -0
  142. package/es/Table/vtable/seriesSelection.mjs.map +1 -0
  143. package/es/Table/vtable/vtableAdapter.mjs +96 -0
  144. package/es/Table/vtable/vtableAdapter.mjs.map +1 -0
  145. package/es/ThemeProvider/AppElementContext.d.mts +5 -0
  146. package/es/ThemeProvider/AppElementContext.mjs +10 -0
  147. package/es/ThemeProvider/AppElementContext.mjs.map +1 -0
  148. package/es/ThemeProvider/ConfigProvider.mjs +29 -0
  149. package/es/ThemeProvider/ConfigProvider.mjs.map +1 -0
  150. package/es/ThemeProvider/GlobalStyle/antdOverride.mjs +73 -0
  151. package/es/ThemeProvider/GlobalStyle/antdOverride.mjs.map +1 -0
  152. package/es/ThemeProvider/GlobalStyle/essential.mjs +50 -0
  153. package/es/ThemeProvider/GlobalStyle/essential.mjs.map +1 -0
  154. package/es/ThemeProvider/GlobalStyle/global.mjs +90 -0
  155. package/es/ThemeProvider/GlobalStyle/global.mjs.map +1 -0
  156. package/es/ThemeProvider/GlobalStyle/index.mjs +14 -0
  157. package/es/ThemeProvider/GlobalStyle/index.mjs.map +1 -0
  158. package/es/ThemeProvider/Meta.d.mts +7 -0
  159. package/es/ThemeProvider/Meta.mjs +48 -0
  160. package/es/ThemeProvider/Meta.mjs.map +1 -0
  161. package/es/ThemeProvider/ThemeProvider.d.mts +6 -0
  162. package/es/ThemeProvider/ThemeProvider.mjs +89 -0
  163. package/es/ThemeProvider/ThemeProvider.mjs.map +1 -0
  164. package/es/ThemeProvider/constants.d.mts +5 -0
  165. package/es/ThemeProvider/constants.mjs +6 -0
  166. package/es/ThemeProvider/constants.mjs.map +1 -0
  167. package/es/ThemeProvider/index.d.mts +6 -0
  168. package/es/ThemeProvider/index.d.ts +1 -0
  169. package/es/ThemeProvider/index.js +1 -0
  170. package/es/ThemeProvider/index.mjs +5 -0
  171. package/es/ThemeProvider/type.d.mts +48 -0
  172. package/es/_virtual/_rolldown/runtime.mjs +13 -0
  173. package/es/color/colors/blue.d.mts +6 -0
  174. package/es/color/colors/blue.mjs +67 -0
  175. package/es/color/colors/blue.mjs.map +1 -0
  176. package/es/color/colors/cyan.d.mts +6 -0
  177. package/es/color/colors/cyan.mjs +67 -0
  178. package/es/color/colors/cyan.mjs.map +1 -0
  179. package/es/color/colors/geekblue.d.mts +6 -0
  180. package/es/color/colors/geekblue.mjs +67 -0
  181. package/es/color/colors/geekblue.mjs.map +1 -0
  182. package/es/color/colors/gold.d.mts +6 -0
  183. package/es/color/colors/gold.mjs +67 -0
  184. package/es/color/colors/gold.mjs.map +1 -0
  185. package/es/color/colors/gray.d.mts +6 -0
  186. package/es/color/colors/gray.mjs +67 -0
  187. package/es/color/colors/gray.mjs.map +1 -0
  188. package/es/color/colors/green.d.mts +6 -0
  189. package/es/color/colors/green.mjs +67 -0
  190. package/es/color/colors/green.mjs.map +1 -0
  191. package/es/color/colors/index.d.mts +22 -0
  192. package/es/color/colors/index.mjs +35 -0
  193. package/es/color/colors/index.mjs.map +1 -0
  194. package/es/color/colors/lime.d.mts +6 -0
  195. package/es/color/colors/lime.mjs +67 -0
  196. package/es/color/colors/lime.mjs.map +1 -0
  197. package/es/color/colors/magenta.d.mts +6 -0
  198. package/es/color/colors/magenta.mjs +67 -0
  199. package/es/color/colors/magenta.mjs.map +1 -0
  200. package/es/color/colors/orange.d.mts +6 -0
  201. package/es/color/colors/orange.mjs +67 -0
  202. package/es/color/colors/orange.mjs.map +1 -0
  203. package/es/color/colors/primary.d.mts +6 -0
  204. package/es/color/colors/primary.mjs +67 -0
  205. package/es/color/colors/primary.mjs.map +1 -0
  206. package/es/color/colors/purple.d.mts +6 -0
  207. package/es/color/colors/purple.mjs +67 -0
  208. package/es/color/colors/purple.mjs.map +1 -0
  209. package/es/color/colors/red.d.mts +6 -0
  210. package/es/color/colors/red.mjs +67 -0
  211. package/es/color/colors/red.mjs.map +1 -0
  212. package/es/color/colors/volcano.d.mts +6 -0
  213. package/es/color/colors/volcano.mjs +67 -0
  214. package/es/color/colors/volcano.mjs.map +1 -0
  215. package/es/color/colors/yellow.d.mts +6 -0
  216. package/es/color/colors/yellow.mjs +67 -0
  217. package/es/color/colors/yellow.mjs.map +1 -0
  218. package/es/color/index.d.mts +23 -0
  219. package/es/color/index.d.ts +1 -0
  220. package/es/color/index.js +1 -0
  221. package/es/color/index.mjs +22 -0
  222. package/es/color/neutrals/index.d.mts +13 -0
  223. package/es/color/neutrals/index.mjs +17 -0
  224. package/es/color/neutrals/index.mjs.map +1 -0
  225. package/es/color/neutrals/mauve.d.mts +6 -0
  226. package/es/color/neutrals/mauve.mjs +67 -0
  227. package/es/color/neutrals/mauve.mjs.map +1 -0
  228. package/es/color/neutrals/olive.d.mts +6 -0
  229. package/es/color/neutrals/olive.mjs +67 -0
  230. package/es/color/neutrals/olive.mjs.map +1 -0
  231. package/es/color/neutrals/sage.d.mts +6 -0
  232. package/es/color/neutrals/sage.mjs +67 -0
  233. package/es/color/neutrals/sage.mjs.map +1 -0
  234. package/es/color/neutrals/sand.d.mts +6 -0
  235. package/es/color/neutrals/sand.mjs +67 -0
  236. package/es/color/neutrals/sand.mjs.map +1 -0
  237. package/es/color/neutrals/slate.d.mts +6 -0
  238. package/es/color/neutrals/slate.mjs +67 -0
  239. package/es/color/neutrals/slate.mjs.map +1 -0
  240. package/es/color/types.d.mts +16 -0
  241. package/es/eslint/index.d.mts +26 -0
  242. package/es/eslint/index.d.ts +1 -0
  243. package/es/eslint/index.js +1 -0
  244. package/es/eslint/index.mjs +11 -0
  245. package/es/eslint/index.mjs.map +1 -0
  246. package/es/hooks/useIsClient.d.mts +8 -0
  247. package/es/hooks/useIsClient.mjs +13 -0
  248. package/es/hooks/useIsClient.mjs.map +1 -0
  249. package/es/i18n/context.d.mts +7 -0
  250. package/es/i18n/context.mjs +16 -0
  251. package/es/i18n/context.mjs.map +1 -0
  252. package/es/i18n/index.d.mts +6 -0
  253. package/es/i18n/index.d.ts +1 -0
  254. package/es/i18n/index.js +1 -0
  255. package/es/i18n/index.mjs +5 -0
  256. package/es/i18n/resources/en/common.d.mts +35 -0
  257. package/es/i18n/resources/en/common.mjs +36 -0
  258. package/es/i18n/resources/en/common.mjs.map +1 -0
  259. package/es/i18n/resources/en/index.d.mts +7 -0
  260. package/es/i18n/resources/en/index.mjs +8 -0
  261. package/es/i18n/resources/en/index.mjs.map +1 -0
  262. package/es/i18n/resources/zhCn/common.d.mts +35 -0
  263. package/es/i18n/resources/zhCn/common.mjs +36 -0
  264. package/es/i18n/resources/zhCn/common.mjs.map +1 -0
  265. package/es/i18n/resources/zhCn/index.d.mts +7 -0
  266. package/es/i18n/resources/zhCn/index.mjs +8 -0
  267. package/es/i18n/resources/zhCn/index.mjs.map +1 -0
  268. package/es/i18n/types.d.mts +22 -0
  269. package/es/i18n/useTranslation.d.mts +12 -0
  270. package/es/i18n/useTranslation.mjs +22 -0
  271. package/es/i18n/useTranslation.mjs.map +1 -0
  272. package/es/index.d.mts +43 -0
  273. package/es/index.mjs +26 -0
  274. package/es/storybook/StoryBook/StoryBook.d.mts +7 -0
  275. package/es/storybook/StoryBook/StoryBook.mjs +52 -0
  276. package/es/storybook/StoryBook/StoryBook.mjs.map +1 -0
  277. package/es/storybook/StoryBook/index.d.mts +3 -0
  278. package/es/storybook/StoryBook/style.mjs +97 -0
  279. package/es/storybook/StoryBook/style.mjs.map +1 -0
  280. package/es/storybook/StoryBook/type.d.mts +13 -0
  281. package/es/storybook/index.d.mts +4 -0
  282. package/es/storybook/index.d.ts +1 -0
  283. package/es/storybook/index.js +1 -0
  284. package/es/storybook/index.mjs +2 -0
  285. package/es/styles/classNames.d.mts +11 -0
  286. package/es/styles/classNames.mjs +12 -0
  287. package/es/styles/classNames.mjs.map +1 -0
  288. package/es/styles/customTheme.d.mts +36 -0
  289. package/es/styles/customTheme.mjs +71 -0
  290. package/es/styles/customTheme.mjs.map +1 -0
  291. package/es/styles/index.d.mts +6 -0
  292. package/es/styles/index.d.ts +1 -0
  293. package/es/styles/index.js +1 -0
  294. package/es/styles/index.mjs +6 -0
  295. package/es/styles/theme/algorithms/darkAlgorithm.mjs +18 -0
  296. package/es/styles/theme/algorithms/darkAlgorithm.mjs.map +1 -0
  297. package/es/styles/theme/algorithms/lightAlgorithm.mjs +18 -0
  298. package/es/styles/theme/algorithms/lightAlgorithm.mjs.map +1 -0
  299. package/es/styles/theme/algorithms/resolveScales.mjs +25 -0
  300. package/es/styles/theme/algorithms/resolveScales.mjs.map +1 -0
  301. package/es/styles/theme/antdTheme.mjs +31 -0
  302. package/es/styles/theme/antdTheme.mjs.map +1 -0
  303. package/es/styles/theme/customStylish.d.mts +7 -0
  304. package/es/styles/theme/customStylish.mjs +158 -0
  305. package/es/styles/theme/customStylish.mjs.map +1 -0
  306. package/es/styles/theme/customStylishStatic.d.mts +6 -0
  307. package/es/styles/theme/customStylishStatic.mjs +156 -0
  308. package/es/styles/theme/customStylishStatic.mjs.map +1 -0
  309. package/es/styles/theme/customToken.d.mts +7 -0
  310. package/es/styles/theme/customToken.mjs +127 -0
  311. package/es/styles/theme/customToken.mjs.map +1 -0
  312. package/es/styles/theme/generateColorPalette.d.mts +16 -0
  313. package/es/styles/theme/generateColorPalette.mjs +170 -0
  314. package/es/styles/theme/generateColorPalette.mjs.map +1 -0
  315. package/es/styles/theme/token/base.mjs +64 -0
  316. package/es/styles/theme/token/base.mjs.map +1 -0
  317. package/es/styles/theme/token/dark.mjs +37 -0
  318. package/es/styles/theme/token/dark.mjs.map +1 -0
  319. package/es/styles/theme/token/light.mjs +37 -0
  320. package/es/styles/theme/token/light.mjs.map +1 -0
  321. package/es/types/customStylish.d.mts +28 -0
  322. package/es/types/customToken.d.mts +34 -0
  323. package/es/types/customToken.mjs +32 -0
  324. package/es/types/customToken.mjs.map +1 -0
  325. package/es/types/index.d.mts +15 -0
  326. package/es/types/index.d.ts +1 -0
  327. package/es/types/index.js +1 -0
  328. package/es/types/index.mjs +2 -0
  329. package/es/utils/composeEventHandlers.d.mts +5 -0
  330. package/es/utils/composeEventHandlers.mjs +10 -0
  331. package/es/utils/composeEventHandlers.mjs.map +1 -0
  332. package/es/utils/copyToClipboard.d.mts +5 -0
  333. package/es/utils/copyToClipboard.mjs +28 -0
  334. package/es/utils/copyToClipboard.mjs.map +1 -0
  335. package/es/utils/dom.d.mts +15 -0
  336. package/es/utils/dom.mjs +16 -0
  337. package/es/utils/dom.mjs.map +1 -0
  338. package/es/utils/genCdnUrl.d.mts +12 -0
  339. package/es/utils/genCdnUrl.mjs +17 -0
  340. package/es/utils/genCdnUrl.mjs.map +1 -0
  341. package/es/utils/safeReadableColor.mjs +6 -0
  342. package/es/utils/safeReadableColor.mjs.map +1 -0
  343. package/package.json +96 -0
@@ -0,0 +1,138 @@
1
+ import { isGroupTitleRecord } from "./cellValue.mjs";
2
+ //#region src/Table/core/rowSelection.ts
3
+ const createFullRowRange = (startRow, endRow, endCol) => ({
4
+ end: {
5
+ col: endCol,
6
+ row: Math.max(startRow, endRow)
7
+ },
8
+ start: {
9
+ col: 0,
10
+ row: Math.min(startRow, endRow)
11
+ }
12
+ });
13
+ const isFullRowRange = (range, endCol) => range.start.col === 0 && range.end.col >= endCol;
14
+ const isFullRowSelected = (ranges, row, endCol) => ranges.some((range) => isFullRowRange(range, endCol) && range.start.row <= row && row <= range.end.row);
15
+ const removeRowsFromRanges = (ranges, startRow, endRow, endCol) => {
16
+ const from = Math.min(startRow, endRow);
17
+ const to = Math.max(startRow, endRow);
18
+ return ranges.flatMap((range) => {
19
+ if (false === isFullRowRange(range, endCol)) return [range];
20
+ const rangeStart = Math.min(range.start.row, range.end.row);
21
+ const rangeEnd = Math.max(range.start.row, range.end.row);
22
+ if (rangeEnd < from || rangeStart > to) return [range];
23
+ const next = [];
24
+ if (rangeStart < from) next.push(createFullRowRange(rangeStart, from - 1, endCol));
25
+ if (rangeEnd > to) next.push(createFullRowRange(to + 1, rangeEnd, endCol));
26
+ return next;
27
+ });
28
+ };
29
+ /**
30
+ * Select every body row. VTable keeps the previous selection anchor, so the
31
+ * old selection must be cleared first or `selectCells` can be a no-op after a
32
+ * partial selection.
33
+ */
34
+ const selectAllRows = (table, startRow, endRow, endCol) => {
35
+ table.clearSelected?.();
36
+ table.selectCells?.([createFullRowRange(startRow, endRow, endCol)]);
37
+ };
38
+ const toggleRowSelection = (table, row, shiftKey = false) => {
39
+ const endCol = (table.colCount ?? 1) - 1;
40
+ const ranges = table.stateManager?.select?.ranges ?? [];
41
+ const checked = isFullRowSelected(ranges, row, endCol);
42
+ const apply = (next) => {
43
+ if (next.length === 0) table.clearSelected?.();
44
+ else table.selectCells?.(next);
45
+ };
46
+ if (shiftKey === false) {
47
+ const cascade = getCascadeRowSelection(table, row, ranges, endCol);
48
+ if (cascade && cascade.total > 1) {
49
+ const next = removeRowsFromRanges(ranges, cascade.startRow, cascade.endRow, endCol);
50
+ if (cascade.selectedCount !== cascade.total) next.push(createFullRowRange(cascade.startRow, cascade.endRow, endCol));
51
+ apply(next);
52
+ return;
53
+ }
54
+ }
55
+ if (shiftKey) {
56
+ const anchorRow = table.stateManager?.select?.cellPos?.row ?? -1;
57
+ if (anchorRow >= 0 && anchorRow !== row) {
58
+ const startRow = Math.min(anchorRow, row);
59
+ const endRow = Math.max(anchorRow, row);
60
+ const shouldSelect = checked === false;
61
+ const next = removeRowsFromRanges(ranges, startRow, endRow, endCol);
62
+ if (shouldSelect) next.push(createFullRowRange(startRow, endRow, endCol));
63
+ apply(next);
64
+ return;
65
+ }
66
+ }
67
+ if (checked) {
68
+ apply(removeRowsFromRanges(ranges, row, row, endCol));
69
+ return;
70
+ }
71
+ apply([...ranges, createFullRowRange(row, row, endCol)]);
72
+ };
73
+ const normalizeIndexPath = (value) => Array.isArray(value) ? value : [value];
74
+ const cascadeIndexCache = /* @__PURE__ */ new WeakMap();
75
+ const pathKey = (path) => JSON.stringify(path);
76
+ /**
77
+ * 缓存的键要用**内容**而不是数组引用:VTable 会在拖拽分支里就地改 `state.select.ranges`
78
+ * (改 `end`、往同一个数组里 push),引用不变而内容已变 —— 按引用判等就会命中过期索引,
79
+ * 分组行的半选/全选态因此落后一次交互。
80
+ */
81
+ const rangesKey = (ranges) => ranges.map((range) => `${range.start.col},${range.start.row},${range.end.col},${range.end.row}`).join("|");
82
+ const buildCascadeIndex = (table, ranges, endCol) => {
83
+ const dataSource = table.dataSource;
84
+ const firstRow = table.columnHeaderLevelCount ?? 1;
85
+ const lastRow = (table.rowCount ?? 1) - 1;
86
+ const entries = /* @__PURE__ */ new Map();
87
+ for (let cursor = firstRow; cursor <= lastRow; cursor += 1) {
88
+ const showIndex = table.getRecordShowIndexByCell?.(0, cursor);
89
+ if (showIndex == null || showIndex < 0) continue;
90
+ const path = normalizeIndexPath(dataSource?.getRecordIndexPaths?.(showIndex));
91
+ if (path.length === 0) continue;
92
+ const selected = isFullRowSelected(ranges, cursor, endCol);
93
+ for (let length = 1; length <= path.length; length += 1) {
94
+ const key = pathKey(path.slice(0, length));
95
+ const entry = entries.get(key);
96
+ if (entry) {
97
+ entry.startRow = Math.min(entry.startRow, cursor);
98
+ entry.endRow = Math.max(entry.endRow, cursor);
99
+ entry.total += 1;
100
+ if (selected) entry.selectedCount += 1;
101
+ } else entries.set(key, {
102
+ endRow: cursor,
103
+ selectedCount: selected ? 1 : 0,
104
+ startRow: cursor,
105
+ total: 1
106
+ });
107
+ }
108
+ }
109
+ return entries;
110
+ };
111
+ const getCascadeRowSelection = (table, row, ranges, endCol) => {
112
+ const record = table.getCellOriginRecord?.(0, row);
113
+ const hasChildren = Array.isArray(record?.children);
114
+ const isGroupTitle = isGroupTitleRecord(record);
115
+ if (record == null || hasChildren === false && isGroupTitle === false) return;
116
+ const dataSource = table.dataSource;
117
+ if ((typeof dataSource?.getRecordIndexPaths === "function" && typeof table.getRecordShowIndexByCell === "function") === false) return void 0;
118
+ const parentShowIndex = table.getRecordShowIndexByCell?.(0, row);
119
+ if (parentShowIndex == null || parentShowIndex < 0) return void 0;
120
+ const parentPath = normalizeIndexPath(dataSource?.getRecordIndexPaths?.(parentShowIndex));
121
+ if (parentPath.length === 0) return void 0;
122
+ const cacheKey = table;
123
+ const key = rangesKey(ranges);
124
+ let cache = cascadeIndexCache.get(cacheKey);
125
+ if (cache == null || cache.key !== key || cache.endCol !== endCol) {
126
+ cache = {
127
+ endCol,
128
+ entries: buildCascadeIndex(table, ranges, endCol),
129
+ key
130
+ };
131
+ cascadeIndexCache.set(cacheKey, cache);
132
+ }
133
+ return cache.entries.get(pathKey(parentPath));
134
+ };
135
+ //#endregion
136
+ export { createFullRowRange, getCascadeRowSelection, isFullRowRange, isFullRowSelected, removeRowsFromRanges, selectAllRows, toggleRowSelection };
137
+
138
+ //# sourceMappingURL=rowSelection.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rowSelection.mjs","names":[],"sources":["../../../src/Table/core/rowSelection.ts"],"sourcesContent":["import { isGroupTitleRecord } from './cellValue';\n\nexport interface TableCellRange {\n end: { col: number; row: number };\n start: { col: number; row: number };\n}\n\nexport const createFullRowRange = (\n startRow: number,\n endRow: number,\n endCol: number,\n): TableCellRange => ({\n end: { col: endCol, row: Math.max(startRow, endRow) },\n start: { col: 0, row: Math.min(startRow, endRow) },\n});\n\nexport const isFullRowRange = (range: TableCellRange, endCol: number): boolean =>\n range.start.col === 0 && range.end.col >= endCol;\n\nexport const isFullRowSelected = (ranges: TableCellRange[], row: number, endCol: number): boolean =>\n ranges.some(\n (range) => isFullRowRange(range, endCol) && range.start.row <= row && row <= range.end.row,\n );\n\nexport const removeRowsFromRanges = (\n ranges: TableCellRange[],\n startRow: number,\n endRow: number,\n endCol: number,\n): TableCellRange[] => {\n const from = Math.min(startRow, endRow);\n const to = Math.max(startRow, endRow);\n\n return ranges.flatMap((range) => {\n if (false === isFullRowRange(range, endCol)) return [range];\n\n const rangeStart = Math.min(range.start.row, range.end.row);\n const rangeEnd = Math.max(range.start.row, range.end.row);\n\n if (rangeEnd < from || rangeStart > to) return [range];\n\n const next: TableCellRange[] = [];\n\n if (rangeStart < from) {\n next.push(createFullRowRange(rangeStart, from - 1, endCol));\n }\n\n if (rangeEnd > to) {\n next.push(createFullRowRange(to + 1, rangeEnd, endCol));\n }\n\n return next;\n });\n};\n\nexport interface RowSelectionTable {\n clearSelected?: () => void;\n colCount?: number;\n columnHeaderLevelCount?: number;\n dataSource?: {\n getRecordIndexPaths?: (index: number) => unknown;\n };\n getCellOriginRecord?: (col: number, row: number) => unknown;\n getRecordShowIndexByCell?: (col: number, row: number) => number;\n rowCount?: number;\n selectCells?: (ranges: TableCellRange[]) => void;\n stateManager?: {\n select?: {\n cellPos?: { row: number };\n ranges?: TableCellRange[];\n };\n };\n}\n\nexport interface CascadeRowSelection {\n endRow: number;\n selectedCount: number;\n startRow: number;\n total: number;\n}\n\n/**\n * Select every body row. VTable keeps the previous selection anchor, so the\n * old selection must be cleared first or `selectCells` can be a no-op after a\n * partial selection.\n */\nexport const selectAllRows = (\n table: RowSelectionTable,\n startRow: number,\n endRow: number,\n endCol: number,\n): void => {\n table.clearSelected?.();\n table.selectCells?.([createFullRowRange(startRow, endRow, endCol)]);\n};\n\nexport const toggleRowSelection = (\n table: RowSelectionTable,\n row: number,\n shiftKey = false,\n): void => {\n const endCol = (table.colCount ?? 1) - 1;\n const ranges = table.stateManager?.select?.ranges ?? [];\n const checked = isFullRowSelected(ranges, row, endCol);\n\n const apply = (next: TableCellRange[]): void => {\n if (next.length === 0) table.clearSelected?.();\n else table.selectCells?.(next);\n };\n\n if (shiftKey === false) {\n const cascade = getCascadeRowSelection(table, row, ranges, endCol);\n\n if (cascade && cascade.total > 1) {\n const next = removeRowsFromRanges(ranges, cascade.startRow, cascade.endRow, endCol);\n\n if (cascade.selectedCount !== cascade.total) {\n next.push(createFullRowRange(cascade.startRow, cascade.endRow, endCol));\n }\n\n apply(next);\n return;\n }\n }\n\n if (shiftKey) {\n const anchorRow = table.stateManager?.select?.cellPos?.row ?? -1;\n\n if (anchorRow >= 0 && anchorRow !== row) {\n const startRow = Math.min(anchorRow, row);\n const endRow = Math.max(anchorRow, row);\n const shouldSelect = checked === false;\n const next = removeRowsFromRanges(ranges, startRow, endRow, endCol);\n\n if (shouldSelect) next.push(createFullRowRange(startRow, endRow, endCol));\n apply(next);\n return;\n }\n }\n\n if (checked) {\n apply(removeRowsFromRanges(ranges, row, row, endCol));\n return;\n }\n\n apply([...ranges, createFullRowRange(row, row, endCol)]);\n};\n\nconst normalizeIndexPath = (value: unknown): unknown[] => (Array.isArray(value) ? value : [value]);\n\nconst cascadeIndexCache = new WeakMap<\n object,\n { endCol: number; entries: Map<string, CascadeRowSelection>; key: string }\n>();\n\nconst pathKey = (path: unknown[]): string => JSON.stringify(path);\n\n/**\n * 缓存的键要用**内容**而不是数组引用:VTable 会在拖拽分支里就地改 `state.select.ranges`\n * (改 `end`、往同一个数组里 push),引用不变而内容已变 —— 按引用判等就会命中过期索引,\n * 分组行的半选/全选态因此落后一次交互。\n */\nconst rangesKey = (ranges: TableCellRange[]): string =>\n ranges\n .map((range) => `${range.start.col},${range.start.row},${range.end.col},${range.end.row}`)\n .join('|');\n\nconst buildCascadeIndex = (\n table: RowSelectionTable,\n ranges: TableCellRange[],\n endCol: number,\n): Map<string, CascadeRowSelection> => {\n const dataSource = table.dataSource;\n const firstRow = table.columnHeaderLevelCount ?? 1;\n const lastRow = (table.rowCount ?? 1) - 1;\n const entries = new Map<string, CascadeRowSelection>();\n\n for (let cursor = firstRow; cursor <= lastRow; cursor += 1) {\n const showIndex = table.getRecordShowIndexByCell?.(0, cursor);\n if (showIndex == null || showIndex < 0) continue;\n\n const path = normalizeIndexPath(dataSource?.getRecordIndexPaths?.(showIndex));\n if (path.length === 0) continue;\n\n const selected = isFullRowSelected(ranges, cursor, endCol);\n\n for (let length = 1; length <= path.length; length += 1) {\n const key = pathKey(path.slice(0, length));\n const entry = entries.get(key);\n\n if (entry) {\n entry.startRow = Math.min(entry.startRow, cursor);\n entry.endRow = Math.max(entry.endRow, cursor);\n entry.total += 1;\n if (selected) entry.selectedCount += 1;\n } else {\n entries.set(key, {\n endRow: cursor,\n selectedCount: selected ? 1 : 0,\n startRow: cursor,\n total: 1,\n });\n }\n }\n }\n\n return entries;\n};\n\nexport const getCascadeRowSelection = (\n table: RowSelectionTable,\n row: number,\n ranges: TableCellRange[],\n endCol: number,\n): CascadeRowSelection | undefined => {\n const record = table.getCellOriginRecord?.(0, row) as\n { children?: unknown[]; vtableMerge?: boolean } | undefined;\n const hasChildren = Array.isArray(record?.children);\n const isGroupTitle = isGroupTitleRecord(record);\n\n if (record == null || (hasChildren === false && isGroupTitle === false)) {\n return undefined;\n }\n\n const dataSource = table.dataSource;\n const canReadIndex =\n typeof dataSource?.getRecordIndexPaths === 'function' &&\n typeof table.getRecordShowIndexByCell === 'function';\n\n if (canReadIndex === false) return undefined;\n\n const parentShowIndex = table.getRecordShowIndexByCell?.(0, row);\n if (parentShowIndex == null || parentShowIndex < 0) return undefined;\n\n const parentPath = normalizeIndexPath(dataSource?.getRecordIndexPaths?.(parentShowIndex));\n if (parentPath.length === 0) return undefined;\n\n const cacheKey = table as object;\n const key = rangesKey(ranges);\n let cache = cascadeIndexCache.get(cacheKey);\n\n if (cache == null || cache.key !== key || cache.endCol !== endCol) {\n cache = { endCol, entries: buildCascadeIndex(table, ranges, endCol), key };\n cascadeIndexCache.set(cacheKey, cache);\n }\n\n return cache.entries.get(pathKey(parentPath));\n};\n"],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { TABLE_ROW_HEIGHT } from "../type.mjs";
2
+ const toCssSize = (value) => typeof value === "number" ? `${value}px` : value;
3
+ const parsePxSize = (value) => {
4
+ if (value == null || value === "") return void 0;
5
+ const numeric = typeof value === "number" ? value : Number.parseFloat(value);
6
+ return Number.isFinite(numeric) ? numeric : void 0;
7
+ };
8
+ const countGroupRows = (records, groupBy) => {
9
+ const fields = (Array.isArray(groupBy) ? groupBy : [groupBy]).filter(Boolean);
10
+ const countLevel = (rows, level) => {
11
+ if (level >= fields.length) return 0;
12
+ const field = fields[level];
13
+ const buckets = /* @__PURE__ */ new Map();
14
+ rows.forEach((row) => {
15
+ const value = row[field];
16
+ if (value === void 0) return;
17
+ const bucket = buckets.get(value);
18
+ if (bucket) bucket.push(row);
19
+ else buckets.set(value, [row]);
20
+ });
21
+ let count = buckets.size;
22
+ buckets.forEach((bucket) => {
23
+ count += countLevel(bucket, level + 1);
24
+ });
25
+ return count;
26
+ };
27
+ return countLevel(records, 0);
28
+ };
29
+ const countTableRows = (records, tree, groupBy) => {
30
+ if (records == null || records.length === 0) return 0;
31
+ if (groupBy) {
32
+ const fields = (Array.isArray(groupBy) ? groupBy : [groupBy]).filter(Boolean);
33
+ const walk = (rows, level) => rows.reduce((sum, row) => {
34
+ const field = fields[level];
35
+ if (field != null && row[field] === void 0) return sum;
36
+ const children = row.children || [];
37
+ const collapsed = row.hierarchyState === "collapse";
38
+ return sum + 1 + (collapsed ? 0 : walk(children, level + 1));
39
+ }, 0);
40
+ return walk(records, 0) + countGroupRows(records, groupBy);
41
+ }
42
+ if (tree !== true) return records.length;
43
+ const walk = (rows) => rows.reduce((sum, row) => {
44
+ const children = row.children ?? [];
45
+ const collapsed = row.hierarchyState === "collapse";
46
+ return sum + 1 + (collapsed ? 0 : walk(children));
47
+ }, 0);
48
+ return walk(records);
49
+ };
50
+ const computeTableHeight = ({ groupBy, headerRowHeight, records, rowHeight, showHeader = true, size = "middle", tree }) => {
51
+ const density = rowHeight ?? TABLE_ROW_HEIGHT[size];
52
+ const header = showHeader === false ? 0 : headerRowHeight ?? 36;
53
+ const rows = countTableRows(records, tree, groupBy);
54
+ if (rows === 0) return header + 120;
55
+ return header + rows * density + 8;
56
+ };
57
+ //#endregion
58
+ export { computeTableHeight, countTableRows, parsePxSize, toCssSize };
59
+
60
+ //# sourceMappingURL=size.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"size.mjs","names":[],"sources":["../../../src/Table/core/size.ts"],"sourcesContent":["import { TABLE_HEADER_HEIGHT, TABLE_ROW_HEIGHT, type TableRecord, type TableSize } from '../type';\n\n/**\n * 内容高度之外多留的那一档 —— 横向滚动条的槽(`scrollStyle.width` 也是 8,见 canvas/theme.ts\n * 里关掉 `hoverOn` 的那段注释)。不留的话横条会压在底边框上。\n */\nexport const TABLE_HEIGHT_GUTTER = 8;\n\nexport const toCssSize = (value: number | string): string =>\n typeof value === 'number' ? `${value}px` : value;\n\nexport const parsePxSize = (value: number | string | undefined): number | undefined => {\n if (value == null || value === '') return undefined;\n const numeric = typeof value === 'number' ? value : Number.parseFloat(value);\n return Number.isFinite(numeric) ? numeric : undefined;\n};\n\nconst countGroupRows = (records: TableRecord[], groupBy: string | string[]): number => {\n const fields = (Array.isArray(groupBy) ? groupBy : [groupBy]).filter(Boolean);\n\n const countLevel = (rows: TableRecord[], level: number): number => {\n if (level >= fields.length) return 0;\n\n const field = fields[level];\n const buckets = new Map<unknown, TableRecord[]>();\n\n rows.forEach((row) => {\n const value = row[field];\n if (value === undefined) return;\n\n const bucket = buckets.get(value);\n if (bucket) bucket.push(row);\n else buckets.set(value, [row]);\n });\n\n let count = buckets.size;\n buckets.forEach((bucket) => {\n count += countLevel(bucket, level + 1);\n });\n return count;\n };\n\n return countLevel(records, 0);\n};\n\nexport const countTableRows = (\n records: TableRecord[] | undefined,\n tree?: boolean,\n groupBy?: string | string[],\n): number => {\n if (records == null || records.length === 0) return 0;\n\n if (groupBy) {\n const fields = (Array.isArray(groupBy) ? groupBy : [groupBy]).filter(Boolean);\n const walk = (rows: TableRecord[], level: number): number =>\n rows.reduce((sum, row) => {\n // 引擎的分组(`CachedDataSource.dealWithGroup`)对 `undefined` 分组值**没有 else 分支**\n // —— 这条记录连同它的子树被整个丢掉、根本不渲染。照单全收会让 `computeTableHeight`\n // 每个这样的记录多算一行(36px)。`null` 不同:引擎会给它建组,所以只有 `undefined`\n // 才跳过,这一点与 `countGroupRows` 的口径一致。\n const field = fields[level];\n if (field != null && row[field] === undefined) return sum;\n\n const children = row.children || [];\n const collapsed = row.hierarchyState === 'collapse';\n return sum + 1 + (collapsed ? 0 : walk(children, level + 1));\n }, 0);\n\n return walk(records, 0) + countGroupRows(records, groupBy);\n }\n\n if (tree !== true) return records.length;\n\n const walk = (rows: TableRecord[]): number =>\n rows.reduce((sum, row) => {\n const children = row.children ?? [];\n const collapsed = row.hierarchyState === 'collapse';\n return sum + 1 + (collapsed ? 0 : walk(children));\n }, 0);\n\n return walk(records);\n};\nexport const computeTableHeight = ({\n groupBy,\n headerRowHeight,\n records,\n rowHeight,\n showHeader = true,\n size = 'middle',\n tree,\n}: {\n groupBy?: string | string[];\n headerRowHeight?: number;\n records?: TableRecord[];\n rowHeight?: number;\n showHeader?: boolean;\n size?: TableSize;\n tree?: boolean;\n}): number => {\n const density = rowHeight ?? TABLE_ROW_HEIGHT[size];\n const header = showHeader === false ? 0 : (headerRowHeight ?? TABLE_HEADER_HEIGHT);\n const rows = countTableRows(records, tree, groupBy);\n if (rows === 0) return header + 120;\n return header + rows * density + TABLE_HEIGHT_GUTTER;\n};\n"],"mappings":";AAQA,MAAa,aAAa,UACxB,OAAO,UAAU,WAAW,GAAG,MAAM,MAAM;AAE7C,MAAa,eAAe,UAA2D;CACrF,IAAI,SAAS,QAAQ,UAAU,IAAI,OAAO,KAAA;CAC1C,MAAM,UAAU,OAAO,UAAU,WAAW,QAAQ,OAAO,WAAW,KAAK;CAC3E,OAAO,OAAO,SAAS,OAAO,IAAI,UAAU,KAAA;AAC9C;AAEA,MAAM,kBAAkB,SAAwB,YAAuC;CACrF,MAAM,UAAU,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO,EAAA,CAAG,OAAO,OAAO;CAE5E,MAAM,cAAc,MAAqB,UAA0B;EACjE,IAAI,SAAS,OAAO,QAAQ,OAAO;EAEnC,MAAM,QAAQ,OAAO;EACrB,MAAM,0BAAU,IAAI,IAA4B;EAEhD,KAAK,SAAS,QAAQ;GACpB,MAAM,QAAQ,IAAI;GAClB,IAAI,UAAU,KAAA,GAAW;GAEzB,MAAM,SAAS,QAAQ,IAAI,KAAK;GAChC,IAAI,QAAQ,OAAO,KAAK,GAAG;QACtB,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC;EAC/B,CAAC;EAED,IAAI,QAAQ,QAAQ;EACpB,QAAQ,SAAS,WAAW;GAC1B,SAAS,WAAW,QAAQ,QAAQ,CAAC;EACvC,CAAC;EACD,OAAO;CACT;CAEA,OAAO,WAAW,SAAS,CAAC;AAC9B;AAEA,MAAa,kBACX,SACA,MACA,YACW;CACX,IAAI,WAAW,QAAQ,QAAQ,WAAW,GAAG,OAAO;CAEpD,IAAI,SAAS;EACX,MAAM,UAAU,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO,EAAA,CAAG,OAAO,OAAO;EAC5E,MAAM,QAAQ,MAAqB,UACjC,KAAK,QAAQ,KAAK,QAAQ;GAKxB,MAAM,QAAQ,OAAO;GACrB,IAAI,SAAS,QAAQ,IAAI,WAAW,KAAA,GAAW,OAAO;GAEtD,MAAM,WAAW,IAAI,YAAY,CAAC;GAClC,MAAM,YAAY,IAAI,mBAAmB;GACzC,OAAO,MAAM,KAAK,YAAY,IAAI,KAAK,UAAU,QAAQ,CAAC;EAC5D,GAAG,CAAC;EAEN,OAAO,KAAK,SAAS,CAAC,IAAI,eAAe,SAAS,OAAO;CAC3D;CAEA,IAAI,SAAS,MAAM,OAAO,QAAQ;CAElC,MAAM,QAAQ,SACZ,KAAK,QAAQ,KAAK,QAAQ;EACxB,MAAM,WAAW,IAAI,YAAY,CAAC;EAClC,MAAM,YAAY,IAAI,mBAAmB;EACzC,OAAO,MAAM,KAAK,YAAY,IAAI,KAAK,QAAQ;CACjD,GAAG,CAAC;CAEN,OAAO,KAAK,OAAO;AACrB;AACA,MAAa,sBAAsB,EACjC,SACA,iBACA,SACA,WACA,aAAa,MACb,OAAO,UACP,WASY;CACZ,MAAM,UAAU,aAAa,iBAAiB;CAC9C,MAAM,SAAS,eAAe,QAAQ,IAAK,mBAAA;CAC3C,MAAM,OAAO,eAAe,SAAS,MAAM,OAAO;CAClD,IAAI,SAAS,GAAG,OAAO,SAAS;CAChC,OAAO,SAAS,OAAO,UAAA;AACzB"}
@@ -0,0 +1,11 @@
1
+ import "antd/es/locale/index.js";
2
+ //#region src/Table/core/tableI18n.d.ts
3
+ type TableI18nKey = 'addByEnter' | 'address.city' | 'address.country' | 'address.postcode' | 'address.state' | 'address.street' | 'address.street2' | 'clearSelection' | 'copy' | 'edit' | 'endDate' | 'fieldSettings' | 'hideColumn' | 'moveLeft' | 'moveRight' | 'noMatch' | 'pickDate' | 'remove' | 'search' | 'searchPeople' | 'selectedRows' | 'set' | 'setField' | 'showColumn' | 'startDate';
4
+ type TableI18nMessages = Record<TableI18nKey, string>;
5
+ interface TableI18n {
6
+ locale: string;
7
+ messages: TableI18nMessages;
8
+ }
9
+ //#endregion
10
+ export { TableI18n, TableI18nKey, TableI18nMessages };
11
+ //# sourceMappingURL=tableI18n.d.mts.map
@@ -0,0 +1,123 @@
1
+ import enUS from "antd/locale/en_US.js";
2
+ import zhCN from "antd/locale/zh_CN.js";
3
+ //#region src/Table/core/tableI18n.ts
4
+ const ZH = {
5
+ "addByEnter": "回车添加",
6
+ "address.city": "城市",
7
+ "address.country": "国家",
8
+ "address.postcode": "邮编",
9
+ "address.state": "州/省",
10
+ "address.street": "街道",
11
+ "address.street2": "地址2",
12
+ "clearSelection": "取消选择",
13
+ "copy": "复制",
14
+ "edit": "编辑",
15
+ "endDate": "结束日期",
16
+ "fieldSettings": "字段设置",
17
+ "hideColumn": "隐藏 {title}",
18
+ "moveLeft": "左移",
19
+ "moveRight": "右移",
20
+ "noMatch": "无匹配项",
21
+ "pickDate": "选择日期",
22
+ "remove": "移除 {label}",
23
+ "search": "搜索",
24
+ "searchPeople": "搜索人员或群组…",
25
+ "selectedRows": "已选 {count} 行",
26
+ "set": "设置",
27
+ "setField": "设置 {title}",
28
+ "showColumn": "显示 {title}",
29
+ "startDate": "开始日期"
30
+ };
31
+ const EN = {
32
+ "addByEnter": "Press Enter to add",
33
+ "address.city": "City",
34
+ "address.country": "Country",
35
+ "address.postcode": "Postal code",
36
+ "address.state": "State / Province",
37
+ "address.street": "Street",
38
+ "address.street2": "Address line 2",
39
+ "clearSelection": "Clear selection",
40
+ "copy": "Copy",
41
+ "edit": "Edit",
42
+ "endDate": "End date",
43
+ "fieldSettings": "Column settings",
44
+ "hideColumn": "Hide {title}",
45
+ "moveLeft": "Move left",
46
+ "moveRight": "Move right",
47
+ "noMatch": "No matching results",
48
+ "pickDate": "Select date",
49
+ "remove": "Remove {label}",
50
+ "search": "Search",
51
+ "searchPeople": "Search people or groups…",
52
+ "selectedRows": "{count} selected",
53
+ "set": "Set",
54
+ "setField": "Set {title}",
55
+ "showColumn": "Show {title}",
56
+ "startDate": "Start date"
57
+ };
58
+ const RESOURCE_KEY = {
59
+ "addByEnter": "table.addByEnter",
60
+ "address.city": "table.address.city",
61
+ "address.country": "table.address.country",
62
+ "address.postcode": "table.address.postcode",
63
+ "address.state": "table.address.state",
64
+ "address.street": "table.address.street",
65
+ "address.street2": "table.address.street2",
66
+ "clearSelection": "table.clearSelection",
67
+ "copy": "table.copy",
68
+ "edit": "common.edit",
69
+ "endDate": "table.endDate",
70
+ "fieldSettings": "table.fieldSettings",
71
+ "hideColumn": "table.hideColumn",
72
+ "moveLeft": "table.moveLeft",
73
+ "moveRight": "table.moveRight",
74
+ "noMatch": "table.noMatch",
75
+ "pickDate": "table.pickDate",
76
+ "remove": "table.remove",
77
+ "search": "table.search",
78
+ "searchPeople": "table.searchPeople",
79
+ "selectedRows": "table.selectedRows",
80
+ "set": "table.set",
81
+ "setField": "table.setField",
82
+ "showColumn": "table.showColumn",
83
+ "startDate": "table.startDate"
84
+ };
85
+ const isChineseLocale = (locale) => (locale ?? "").toLowerCase().startsWith("zh");
86
+ const builtinTableI18n = (locale) => ({
87
+ locale: locale ?? "en",
88
+ messages: isChineseLocale(locale) ? ZH : EN
89
+ });
90
+ /**
91
+ * 编辑器在独立 React root 里,读不到外层 i18n。没挂表实例时退回中文 —— 单测和旧 demo
92
+ * 都按中文写的;Table 挂载后会把真实 locale 写到实例上。
93
+ */
94
+ const fallbackTableI18n = () => builtinTableI18n("zh-CN");
95
+ const formatTableMessage = (template, vars = {}) => template.replaceAll(/\{(\w+)\}/g, (_, key) => String(vars[key] ?? ""));
96
+ const resolveTableI18n = (locale, translate) => {
97
+ const builtin = builtinTableI18n(locale).messages;
98
+ if (!translate) return {
99
+ locale,
100
+ messages: builtin
101
+ };
102
+ const messages = { ...builtin };
103
+ Object.keys(RESOURCE_KEY).forEach((key) => {
104
+ const resourceKey = RESOURCE_KEY[key];
105
+ const value = translate(resourceKey);
106
+ if (value && value !== resourceKey) messages[key] = value;
107
+ });
108
+ return {
109
+ locale,
110
+ messages
111
+ };
112
+ };
113
+ const readTableI18n = (table) => {
114
+ const host = table;
115
+ return host?.__superadI18n ?? host?.options?.customConfig?.__superadI18n ?? fallbackTableI18n();
116
+ };
117
+ const tableText = (table, key, vars) => formatTableMessage(readTableI18n(table).messages[key], vars);
118
+ const antdLocaleFor = (locale) => isChineseLocale(locale) ? zhCN : enUS;
119
+ const dayjsLocaleFor = (locale) => isChineseLocale(locale) ? "zh-cn" : "en";
120
+ //#endregion
121
+ export { antdLocaleFor, builtinTableI18n, dayjsLocaleFor, fallbackTableI18n, formatTableMessage, isChineseLocale, readTableI18n, resolveTableI18n, tableText };
122
+
123
+ //# sourceMappingURL=tableI18n.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tableI18n.mjs","names":[],"sources":["../../../src/Table/core/tableI18n.ts"],"sourcesContent":["import type { Locale } from 'antd/es/locale';\nimport enUS from 'antd/locale/en_US';\nimport zhCN from 'antd/locale/zh_CN';\n\nexport type TableI18nKey =\n | 'addByEnter'\n | 'address.city'\n | 'address.country'\n | 'address.postcode'\n | 'address.state'\n | 'address.street'\n | 'address.street2'\n | 'clearSelection'\n | 'copy'\n | 'edit'\n | 'endDate'\n | 'fieldSettings'\n | 'hideColumn'\n | 'moveLeft'\n | 'moveRight'\n | 'noMatch'\n | 'pickDate'\n | 'remove'\n | 'search'\n | 'searchPeople'\n | 'selectedRows'\n | 'set'\n | 'setField'\n | 'showColumn'\n | 'startDate';\n\nexport type TableI18nMessages = Record<TableI18nKey, string>;\n\nexport interface TableI18n {\n locale: string;\n messages: TableI18nMessages;\n}\n\nconst ZH: TableI18nMessages = {\n 'addByEnter': '回车添加',\n 'address.city': '城市',\n 'address.country': '国家',\n 'address.postcode': '邮编',\n 'address.state': '州/省',\n 'address.street': '街道',\n 'address.street2': '地址2',\n 'clearSelection': '取消选择',\n 'copy': '复制',\n 'edit': '编辑',\n 'endDate': '结束日期',\n 'fieldSettings': '字段设置',\n 'hideColumn': '隐藏 {title}',\n 'moveLeft': '左移',\n 'moveRight': '右移',\n 'noMatch': '无匹配项',\n 'pickDate': '选择日期',\n 'remove': '移除 {label}',\n 'search': '搜索',\n 'searchPeople': '搜索人员或群组…',\n 'selectedRows': '已选 {count} 行',\n 'set': '设置',\n 'setField': '设置 {title}',\n 'showColumn': '显示 {title}',\n 'startDate': '开始日期',\n};\n\nconst EN: TableI18nMessages = {\n 'addByEnter': 'Press Enter to add',\n 'address.city': 'City',\n 'address.country': 'Country',\n 'address.postcode': 'Postal code',\n 'address.state': 'State / Province',\n 'address.street': 'Street',\n 'address.street2': 'Address line 2',\n 'clearSelection': 'Clear selection',\n 'copy': 'Copy',\n 'edit': 'Edit',\n 'endDate': 'End date',\n 'fieldSettings': 'Column settings',\n 'hideColumn': 'Hide {title}',\n 'moveLeft': 'Move left',\n 'moveRight': 'Move right',\n 'noMatch': 'No matching results',\n 'pickDate': 'Select date',\n 'remove': 'Remove {label}',\n 'search': 'Search',\n 'searchPeople': 'Search people or groups…',\n 'selectedRows': '{count} selected',\n 'set': 'Set',\n 'setField': 'Set {title}',\n 'showColumn': 'Show {title}',\n 'startDate': 'Start date',\n};\n\nconst RESOURCE_KEY: Record<TableI18nKey, string> = {\n 'addByEnter': 'table.addByEnter',\n 'address.city': 'table.address.city',\n 'address.country': 'table.address.country',\n 'address.postcode': 'table.address.postcode',\n 'address.state': 'table.address.state',\n 'address.street': 'table.address.street',\n 'address.street2': 'table.address.street2',\n 'clearSelection': 'table.clearSelection',\n 'copy': 'table.copy',\n 'edit': 'common.edit',\n 'endDate': 'table.endDate',\n 'fieldSettings': 'table.fieldSettings',\n 'hideColumn': 'table.hideColumn',\n 'moveLeft': 'table.moveLeft',\n 'moveRight': 'table.moveRight',\n 'noMatch': 'table.noMatch',\n 'pickDate': 'table.pickDate',\n 'remove': 'table.remove',\n 'search': 'table.search',\n 'searchPeople': 'table.searchPeople',\n 'selectedRows': 'table.selectedRows',\n 'set': 'table.set',\n 'setField': 'table.setField',\n 'showColumn': 'table.showColumn',\n 'startDate': 'table.startDate',\n};\n\nexport const isChineseLocale = (locale?: string): boolean =>\n (locale ?? '').toLowerCase().startsWith('zh');\n\nexport const builtinTableI18n = (locale?: string): TableI18n => ({\n locale: locale ?? 'en',\n messages: isChineseLocale(locale) ? ZH : EN,\n});\n\n/**\n * 编辑器在独立 React root 里,读不到外层 i18n。没挂表实例时退回中文 —— 单测和旧 demo\n * 都按中文写的;Table 挂载后会把真实 locale 写到实例上。\n */\nexport const fallbackTableI18n = (): TableI18n => builtinTableI18n('zh-CN');\n\nexport const formatTableMessage = (\n template: string,\n vars: Record<string, string | number> = {},\n): string => template.replaceAll(/\\{(\\w+)\\}/g, (_, key: string) => String(vars[key] ?? ''));\n\nexport const resolveTableI18n = (\n locale: string,\n translate?: (key: string) => string,\n): TableI18n => {\n const builtin = builtinTableI18n(locale).messages;\n if (!translate) return { locale, messages: builtin };\n\n const messages = { ...builtin };\n (Object.keys(RESOURCE_KEY) as TableI18nKey[]).forEach((key) => {\n const resourceKey = RESOURCE_KEY[key];\n const value = translate(resourceKey);\n if (value && value !== resourceKey) messages[key] = value;\n });\n\n return { locale, messages };\n};\n\ntype TableI18nHost = {\n __superadI18n?: TableI18n;\n options?: { customConfig?: { __superadI18n?: TableI18n } };\n};\n\nexport const readTableI18n = (table?: unknown): TableI18n => {\n const host = table as TableI18nHost | undefined;\n return host?.__superadI18n ?? host?.options?.customConfig?.__superadI18n ?? fallbackTableI18n();\n};\n\nexport const tableText = (\n table: unknown,\n key: TableI18nKey,\n vars?: Record<string, string | number>,\n): string => formatTableMessage(readTableI18n(table).messages[key], vars);\n\nexport const antdLocaleFor = (locale?: string): Locale => (isChineseLocale(locale) ? zhCN : enUS);\n\nexport const dayjsLocaleFor = (locale?: string): string =>\n isChineseLocale(locale) ? 'zh-cn' : 'en';\n"],"mappings":";;;AAsCA,MAAM,KAAwB;CAC5B,cAAc;CACd,gBAAgB;CAChB,mBAAmB;CACnB,oBAAoB;CACpB,iBAAiB;CACjB,kBAAkB;CAClB,mBAAmB;CACnB,kBAAkB;CAClB,QAAQ;CACR,QAAQ;CACR,WAAW;CACX,iBAAiB;CACjB,cAAc;CACd,YAAY;CACZ,aAAa;CACb,WAAW;CACX,YAAY;CACZ,UAAU;CACV,UAAU;CACV,gBAAgB;CAChB,gBAAgB;CAChB,OAAO;CACP,YAAY;CACZ,cAAc;CACd,aAAa;AACf;AAEA,MAAM,KAAwB;CAC5B,cAAc;CACd,gBAAgB;CAChB,mBAAmB;CACnB,oBAAoB;CACpB,iBAAiB;CACjB,kBAAkB;CAClB,mBAAmB;CACnB,kBAAkB;CAClB,QAAQ;CACR,QAAQ;CACR,WAAW;CACX,iBAAiB;CACjB,cAAc;CACd,YAAY;CACZ,aAAa;CACb,WAAW;CACX,YAAY;CACZ,UAAU;CACV,UAAU;CACV,gBAAgB;CAChB,gBAAgB;CAChB,OAAO;CACP,YAAY;CACZ,cAAc;CACd,aAAa;AACf;AAEA,MAAM,eAA6C;CACjD,cAAc;CACd,gBAAgB;CAChB,mBAAmB;CACnB,oBAAoB;CACpB,iBAAiB;CACjB,kBAAkB;CAClB,mBAAmB;CACnB,kBAAkB;CAClB,QAAQ;CACR,QAAQ;CACR,WAAW;CACX,iBAAiB;CACjB,cAAc;CACd,YAAY;CACZ,aAAa;CACb,WAAW;CACX,YAAY;CACZ,UAAU;CACV,UAAU;CACV,gBAAgB;CAChB,gBAAgB;CAChB,OAAO;CACP,YAAY;CACZ,cAAc;CACd,aAAa;AACf;AAEA,MAAa,mBAAmB,YAC7B,UAAU,GAAA,CAAI,YAAY,CAAC,CAAC,WAAW,IAAI;AAE9C,MAAa,oBAAoB,YAAgC;CAC/D,QAAQ,UAAU;CAClB,UAAU,gBAAgB,MAAM,IAAI,KAAK;AAC3C;;;;;AAMA,MAAa,0BAAqC,iBAAiB,OAAO;AAE1E,MAAa,sBACX,UACA,OAAwC,CAAC,MAC9B,SAAS,WAAW,eAAe,GAAG,QAAgB,OAAO,KAAK,QAAQ,EAAE,CAAC;AAE1F,MAAa,oBACX,QACA,cACc;CACd,MAAM,UAAU,iBAAiB,MAAM,CAAC,CAAC;CACzC,IAAI,CAAC,WAAW,OAAO;EAAE;EAAQ,UAAU;CAAQ;CAEnD,MAAM,WAAW,EAAE,GAAG,QAAQ;CAC9B,OAAQ,KAAK,YAAY,CAAC,CAAoB,SAAS,QAAQ;EAC7D,MAAM,cAAc,aAAa;EACjC,MAAM,QAAQ,UAAU,WAAW;EACnC,IAAI,SAAS,UAAU,aAAa,SAAS,OAAO;CACtD,CAAC;CAED,OAAO;EAAE;EAAQ;CAAS;AAC5B;AAOA,MAAa,iBAAiB,UAA+B;CAC3D,MAAM,OAAO;CACb,OAAO,MAAM,iBAAiB,MAAM,SAAS,cAAc,iBAAiB,kBAAkB;AAChG;AAEA,MAAa,aACX,OACA,KACA,SACW,mBAAmB,cAAc,KAAK,CAAC,CAAC,SAAS,MAAM,IAAI;AAExE,MAAa,iBAAiB,WAA6B,gBAAgB,MAAM,IAAI,OAAO;AAE5F,MAAa,kBAAkB,WAC7B,gBAAgB,MAAM,IAAI,UAAU"}
@@ -0,0 +1,245 @@
1
+ //#region src/Table/core/tagTone.ts
2
+ /**
3
+ * SuperAd Table light-theme status and tag text/background pairs.
4
+ *
5
+ * Names are kept for API compatibility, but the rendered palette follows the
6
+ * Tailwind / SuperAd status colors used by the Figma table design.
7
+ */
8
+ const TABLE_TAG_TONES = {
9
+ amber: {
10
+ bg: "#FFF7ED",
11
+ color: "#EA580C"
12
+ },
13
+ blue: {
14
+ bg: "#EFF6FF",
15
+ color: "#1F5EFF"
16
+ },
17
+ bronze: {
18
+ bg: "#F5F5F4",
19
+ color: "#78716C"
20
+ },
21
+ brown: {
22
+ bg: "#F5F5F4",
23
+ color: "#78716C"
24
+ },
25
+ crimson: {
26
+ bg: "#FFF1F2",
27
+ color: "#E11D48"
28
+ },
29
+ cyan: {
30
+ bg: "#ECFEFF",
31
+ color: "#0891B2"
32
+ },
33
+ gold: {
34
+ bg: "#FEFCE8",
35
+ color: "#CA8A04"
36
+ },
37
+ grass: {
38
+ bg: "#F7FEE7",
39
+ color: "#65A30D"
40
+ },
41
+ gray: {
42
+ bg: "#FFFFFF",
43
+ border: "#E4E4E7",
44
+ color: "#52525B"
45
+ },
46
+ green: {
47
+ bg: "#F0FDF4",
48
+ color: "#16A34A"
49
+ },
50
+ iris: {
51
+ bg: "#EEF2FF",
52
+ color: "#4F46E5"
53
+ },
54
+ jade: {
55
+ bg: "#ECFDF5",
56
+ color: "#059669"
57
+ },
58
+ lime: {
59
+ bg: "#F7FEE7",
60
+ color: "#65A30D"
61
+ },
62
+ mint: {
63
+ bg: "#F0FDFA",
64
+ color: "#0D9488"
65
+ },
66
+ orange: {
67
+ bg: "#FFF7ED",
68
+ color: "#EA580C"
69
+ },
70
+ pink: {
71
+ bg: "#FDF2F8",
72
+ color: "#DB2777"
73
+ },
74
+ plum: {
75
+ bg: "#FAF5FF",
76
+ color: "#9333EA"
77
+ },
78
+ purple: {
79
+ bg: "#FAF5FF",
80
+ color: "#9333EA"
81
+ },
82
+ red: {
83
+ bg: "#FEF2F2",
84
+ color: "#DC2626"
85
+ },
86
+ ruby: {
87
+ bg: "#FFF1F2",
88
+ color: "#E11D48"
89
+ },
90
+ sky: {
91
+ bg: "#F0F9FF",
92
+ color: "#0284C7"
93
+ },
94
+ tomato: {
95
+ bg: "#FEF2F2",
96
+ color: "#DC2626"
97
+ },
98
+ turquoise: {
99
+ bg: "#F0FDFA",
100
+ color: "#0D9488"
101
+ },
102
+ violet: {
103
+ bg: "#F5F3FF",
104
+ color: "#7C3AED"
105
+ },
106
+ yellow: {
107
+ bg: "#FEFCE8",
108
+ color: "#CA8A04"
109
+ }
110
+ };
111
+ const TAG_TONE_LIST = Object.values(TABLE_TAG_TONES);
112
+ const parseHex = (value) => {
113
+ const hex = value.trim().replace(/^#/, "");
114
+ const full = hex.length === 3 ? hex.split("").map((part) => part + part).join("") : hex;
115
+ if (!/^[\da-fA-F]{6}$/.test(full)) return void 0;
116
+ return {
117
+ b: Number.parseInt(full.slice(4, 6), 16),
118
+ g: Number.parseInt(full.slice(2, 4), 16),
119
+ r: Number.parseInt(full.slice(0, 2), 16)
120
+ };
121
+ };
122
+ const withAlpha = (color, alpha) => {
123
+ const rgb = parseHex(color);
124
+ return rgb ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})` : color;
125
+ };
126
+ /** WCAG 2.x 相对亮度。 */
127
+ const relativeLuminance = ({ b, g, r }) => {
128
+ const channel = (value) => {
129
+ const ratio = value / 255;
130
+ return ratio <= .03928 ? ratio / 12.92 : ((ratio + .055) / 1.055) ** 2.4;
131
+ };
132
+ return .2126 * channel(r) + .7152 * channel(g) + .0722 * channel(b);
133
+ };
134
+ /** WCAG 2.x 对比度,1:1 – 21:1。 */
135
+ const contrastRatio = (a, b) => {
136
+ const first = relativeLuminance(a);
137
+ const second = relativeLuminance(b);
138
+ const lighter = Math.max(first, second);
139
+ const darker = Math.min(first, second);
140
+ return (lighter + .05) / (darker + .05);
141
+ };
142
+ /** 把半透明色叠在底色上,得到实际看到的颜色。 */
143
+ const compositeOver = (color, alpha, base) => ({
144
+ b: alpha * color.b + (1 - alpha) * base.b,
145
+ g: alpha * color.g + (1 - alpha) * base.g,
146
+ r: alpha * color.r + (1 - alpha) * base.r
147
+ });
148
+ const mixWithBlack = ({ b, g, r }, ratio) => ({
149
+ b: b * (1 - ratio),
150
+ g: g * (1 - ratio),
151
+ r: r * (1 - ratio)
152
+ });
153
+ /**
154
+ * 把前景色往**背景的反方向**调,直到对比度达到 AA 正文门槛:暗底提亮、亮底压暗。
155
+ *
156
+ * 逐档试探而不是一步到位:各 tone 的起点亮度差很多,固定比例会让本来就亮的过曝、暗的仍不达标。
157
+ * 这替代了原先「直接用调色板里的 600 级色值」的做法 —— 那套色值两边都不达标(暗底上 2.6–3.8:1,
158
+ * 浅底上 gold 2.84、lime 2.98…),13px 的标签文字读不清。色调不变,只动明度。
159
+ */
160
+ const readableOn = (backdrop, color) => {
161
+ const lighten = relativeLuminance(backdrop) < .5;
162
+ const mix = (ratio) => lighten ? mixWithWhite(color, ratio) : mixWithBlack(color, ratio);
163
+ for (let ratio = 0; ratio <= 1; ratio += .05) {
164
+ const candidate = mix(ratio);
165
+ if (contrastRatio(candidate, backdrop) >= 4.5) return candidate;
166
+ }
167
+ return mix(1);
168
+ };
169
+ const mixWithWhite = ({ b, g, r }, ratio) => ({
170
+ b: b + (255 - b) * ratio,
171
+ g: g + (255 - g) * ratio,
172
+ r: r + (255 - r) * ratio
173
+ });
174
+ const toHex = ({ b, g, r }) => `#${[
175
+ r,
176
+ g,
177
+ b
178
+ ].map((value) => Math.round(value).toString(16).padStart(2, "0")).join("")}`.toUpperCase();
179
+ /** 暗色下 chip 底色/描边的透明度。 */
180
+ const DARK_TONE_BG_ALPHA = .16;
181
+ const DARK_TONE_BORDER_ALPHA = .3;
182
+ /** 正文文字(13px,非大字号)的 WCAG AA 门槛。 */
183
+ const DARK_TEXT_CONTRAST = 4.5;
184
+ const nearestTagTone = (hex) => {
185
+ const rgb = parseHex(hex);
186
+ if (!rgb) return void 0;
187
+ let best = TABLE_TAG_TONES.gray;
188
+ let bestDist = Number.POSITIVE_INFINITY;
189
+ for (const tone of TAG_TONE_LIST) {
190
+ const target = parseHex(tone.color);
191
+ if (!target) continue;
192
+ const dist = (rgb.r - target.r) ** 2 + (rgb.g - target.g) ** 2 + (rgb.b - target.b) ** 2;
193
+ if (dist < bestDist) {
194
+ best = tone;
195
+ bestDist = dist;
196
+ }
197
+ }
198
+ return best;
199
+ };
200
+ /**
201
+ * 暗色模式下合成 chip 底色用的兜底单元格背景。调用方应传 `palette.checkboxBg`
202
+ * (即 antd 的 `colorBgContainer`);这里只在拿不到时用 antd 暗色的默认值。
203
+ */
204
+ const DARK_BASE_BG = "#141414";
205
+ const toneFor = (key, color, isDark = false, baseBg) => {
206
+ let tone;
207
+ if (color) {
208
+ const named = TABLE_TAG_TONES[color.trim().toLowerCase()];
209
+ if (named) tone = named;
210
+ else if (color.trim().toLowerCase() === "transparent") tone = {
211
+ bg: "transparent",
212
+ color: TABLE_TAG_TONES.gray.color
213
+ };
214
+ else tone = nearestTagTone(color) ?? TABLE_TAG_TONES.gray;
215
+ } else tone = TAG_TONE_LIST[Math.abs(hashTone(key)) % TAG_TONE_LIST.length] ?? TABLE_TAG_TONES.gray;
216
+ if (tone.bg === "transparent") return tone;
217
+ if (isDark === false) {
218
+ const background = parseHex(tone.bg);
219
+ const foreground = parseHex(tone.color);
220
+ if (!background || !foreground) return tone;
221
+ if (contrastRatio(foreground, background) >= 4.5) return tone;
222
+ return {
223
+ ...tone,
224
+ color: toHex(readableOn(background, foreground))
225
+ };
226
+ }
227
+ const rgb = parseHex(tone.color);
228
+ const base = parseHex(baseBg ?? DARK_BASE_BG);
229
+ if (!rgb || !base) return tone;
230
+ const backdrop = compositeOver(rgb, DARK_TONE_BG_ALPHA, base);
231
+ return {
232
+ bg: withAlpha(tone.color, DARK_TONE_BG_ALPHA),
233
+ border: withAlpha(tone.color, DARK_TONE_BORDER_ALPHA),
234
+ color: toHex(readableOn(backdrop, rgb))
235
+ };
236
+ };
237
+ const hashTone = (value) => {
238
+ let hash = 0;
239
+ for (let index = 0; index < value.length; index += 1) hash = hash * 31 + value.charCodeAt(index) | 0;
240
+ return hash;
241
+ };
242
+ //#endregion
243
+ export { DARK_TEXT_CONTRAST, DARK_TONE_BG_ALPHA, TABLE_TAG_TONES, compositeOver, contrastRatio, parseHex, relativeLuminance, toneFor };
244
+
245
+ //# sourceMappingURL=tagTone.mjs.map