@gcsa/console-react 0.1.0

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 (394) hide show
  1. package/dist/ConsoleHeader.d.ts +9 -0
  2. package/dist/ConsoleHeader.js +21 -0
  3. package/dist/ConsoleHeader.js.map +1 -0
  4. package/dist/ConsolePage.d.ts +8 -0
  5. package/dist/ConsolePage.js +14 -0
  6. package/dist/ConsolePage.js.map +1 -0
  7. package/dist/ConsoleShell.d.ts +23 -0
  8. package/dist/ConsoleShell.js +133 -0
  9. package/dist/ConsoleShell.js.map +1 -0
  10. package/dist/ConsoleSidebar.d.ts +11 -0
  11. package/dist/ConsoleSidebar.js +52 -0
  12. package/dist/ConsoleSidebar.js.map +1 -0
  13. package/dist/GcsaAlert.d.ts +9 -0
  14. package/dist/GcsaAlert.js +24 -0
  15. package/dist/GcsaAlert.js.map +1 -0
  16. package/dist/GcsaAutoComplete.d.ts +15 -0
  17. package/dist/GcsaAutoComplete.js +106 -0
  18. package/dist/GcsaAutoComplete.js.map +1 -0
  19. package/dist/GcsaAvatar.d.ts +8 -0
  20. package/dist/GcsaAvatar.js +13 -0
  21. package/dist/GcsaAvatar.js.map +1 -0
  22. package/dist/GcsaBadge.d.ts +7 -0
  23. package/dist/GcsaBadge.js +8 -0
  24. package/dist/GcsaBadge.js.map +1 -0
  25. package/dist/GcsaBrandMark.d.ts +4 -0
  26. package/dist/GcsaBrandMark.js +21 -0
  27. package/dist/GcsaBrandMark.js.map +1 -0
  28. package/dist/GcsaBreadcrumb.d.ts +9 -0
  29. package/dist/GcsaBreadcrumb.js +20 -0
  30. package/dist/GcsaBreadcrumb.js.map +1 -0
  31. package/dist/GcsaButton.d.ts +8 -0
  32. package/dist/GcsaButton.js +38 -0
  33. package/dist/GcsaButton.js.map +1 -0
  34. package/dist/GcsaCalendar.d.ts +11 -0
  35. package/dist/GcsaCalendar.js +35 -0
  36. package/dist/GcsaCalendar.js.map +1 -0
  37. package/dist/GcsaCard.d.ts +8 -0
  38. package/dist/GcsaCard.js +11 -0
  39. package/dist/GcsaCard.js.map +1 -0
  40. package/dist/GcsaCascader.d.ts +14 -0
  41. package/dist/GcsaCascader.js +91 -0
  42. package/dist/GcsaCascader.js.map +1 -0
  43. package/dist/GcsaChatPanel.d.ts +43 -0
  44. package/dist/GcsaChatPanel.js +180 -0
  45. package/dist/GcsaChatPanel.js.map +1 -0
  46. package/dist/GcsaCheckbox.d.ts +11 -0
  47. package/dist/GcsaCheckbox.js +45 -0
  48. package/dist/GcsaCheckbox.js.map +1 -0
  49. package/dist/GcsaCollapse.d.ts +16 -0
  50. package/dist/GcsaCollapse.js +20 -0
  51. package/dist/GcsaCollapse.js.map +1 -0
  52. package/dist/GcsaConfigProvider.d.ts +13 -0
  53. package/dist/GcsaConfigProvider.js +68 -0
  54. package/dist/GcsaConfigProvider.js.map +1 -0
  55. package/dist/GcsaDataTable.d.ts +119 -0
  56. package/dist/GcsaDataTable.js +508 -0
  57. package/dist/GcsaDataTable.js.map +1 -0
  58. package/dist/GcsaDatePicker.d.ts +16 -0
  59. package/dist/GcsaDatePicker.js +211 -0
  60. package/dist/GcsaDatePicker.js.map +1 -0
  61. package/dist/GcsaDateRangePicker.d.ts +17 -0
  62. package/dist/GcsaDateRangePicker.js +222 -0
  63. package/dist/GcsaDateRangePicker.js.map +1 -0
  64. package/dist/GcsaDateTimePicker.d.ts +13 -0
  65. package/dist/GcsaDateTimePicker.js +300 -0
  66. package/dist/GcsaDateTimePicker.js.map +1 -0
  67. package/dist/GcsaDescriptions.d.ts +9 -0
  68. package/dist/GcsaDescriptions.js +11 -0
  69. package/dist/GcsaDescriptions.js.map +1 -0
  70. package/dist/GcsaDivider.d.ts +4 -0
  71. package/dist/GcsaDivider.js +8 -0
  72. package/dist/GcsaDivider.js.map +1 -0
  73. package/dist/GcsaDrawer.d.ts +15 -0
  74. package/dist/GcsaDrawer.js +68 -0
  75. package/dist/GcsaDrawer.js.map +1 -0
  76. package/dist/GcsaDropdown.d.ts +20 -0
  77. package/dist/GcsaDropdown.js +46 -0
  78. package/dist/GcsaDropdown.js.map +1 -0
  79. package/dist/GcsaEmpty.d.ts +9 -0
  80. package/dist/GcsaEmpty.js +16 -0
  81. package/dist/GcsaEmpty.js.map +1 -0
  82. package/dist/GcsaField.d.ts +11 -0
  83. package/dist/GcsaField.js +26 -0
  84. package/dist/GcsaField.js.map +1 -0
  85. package/dist/GcsaForm.d.ts +13 -0
  86. package/dist/GcsaForm.js +60 -0
  87. package/dist/GcsaForm.js.map +1 -0
  88. package/dist/GcsaFormField.d.ts +16 -0
  89. package/dist/GcsaFormField.js +39 -0
  90. package/dist/GcsaFormField.js.map +1 -0
  91. package/dist/GcsaIcon.d.ts +7 -0
  92. package/dist/GcsaIcon.js +17 -0
  93. package/dist/GcsaIcon.js.map +1 -0
  94. package/dist/GcsaImagePreview.d.ts +8 -0
  95. package/dist/GcsaImagePreview.js +18 -0
  96. package/dist/GcsaImagePreview.js.map +1 -0
  97. package/dist/GcsaInput.d.ts +13 -0
  98. package/dist/GcsaInput.js +76 -0
  99. package/dist/GcsaInput.js.map +1 -0
  100. package/dist/GcsaInputGroup.d.ts +11 -0
  101. package/dist/GcsaInputGroup.js +27 -0
  102. package/dist/GcsaInputGroup.js.map +1 -0
  103. package/dist/GcsaInputNumber.d.ts +18 -0
  104. package/dist/GcsaInputNumber.js +108 -0
  105. package/dist/GcsaInputNumber.js.map +1 -0
  106. package/dist/GcsaLoading.d.ts +24 -0
  107. package/dist/GcsaLoading.js +101 -0
  108. package/dist/GcsaLoading.js.map +1 -0
  109. package/dist/GcsaLoadingMask.d.ts +8 -0
  110. package/dist/GcsaLoadingMask.js +39 -0
  111. package/dist/GcsaLoadingMask.js.map +1 -0
  112. package/dist/GcsaMarkdownRenderer.d.ts +6 -0
  113. package/dist/GcsaMarkdownRenderer.js +32 -0
  114. package/dist/GcsaMarkdownRenderer.js.map +1 -0
  115. package/dist/GcsaMenu.d.ts +16 -0
  116. package/dist/GcsaMenu.js +241 -0
  117. package/dist/GcsaMenu.js.map +1 -0
  118. package/dist/GcsaModal.d.ts +10 -0
  119. package/dist/GcsaModal.js +45 -0
  120. package/dist/GcsaModal.js.map +1 -0
  121. package/dist/GcsaMultiSelect.d.ts +23 -0
  122. package/dist/GcsaMultiSelect.js +149 -0
  123. package/dist/GcsaMultiSelect.js.map +1 -0
  124. package/dist/GcsaPagination.d.ts +17 -0
  125. package/dist/GcsaPagination.js +108 -0
  126. package/dist/GcsaPagination.js.map +1 -0
  127. package/dist/GcsaPopconfirm.d.ts +18 -0
  128. package/dist/GcsaPopconfirm.js +68 -0
  129. package/dist/GcsaPopconfirm.js.map +1 -0
  130. package/dist/GcsaPopover.d.ts +30 -0
  131. package/dist/GcsaPopover.js +65 -0
  132. package/dist/GcsaPopover.js.map +1 -0
  133. package/dist/GcsaPopoverClose.d.ts +6 -0
  134. package/dist/GcsaPopoverClose.js +9 -0
  135. package/dist/GcsaPopoverClose.js.map +1 -0
  136. package/dist/GcsaProgress.d.ts +5 -0
  137. package/dist/GcsaProgress.js +18 -0
  138. package/dist/GcsaProgress.js.map +1 -0
  139. package/dist/GcsaRadioGroup.d.ts +9 -0
  140. package/dist/GcsaRadioGroup.js +37 -0
  141. package/dist/GcsaRadioGroup.js.map +1 -0
  142. package/dist/GcsaResult.d.ts +9 -0
  143. package/dist/GcsaResult.js +14 -0
  144. package/dist/GcsaResult.js.map +1 -0
  145. package/dist/GcsaRow.d.ts +7 -0
  146. package/dist/GcsaRow.js +8 -0
  147. package/dist/GcsaRow.js.map +1 -0
  148. package/dist/GcsaSelect.d.ts +20 -0
  149. package/dist/GcsaSelect.js +117 -0
  150. package/dist/GcsaSelect.js.map +1 -0
  151. package/dist/GcsaSkeleton.d.ts +6 -0
  152. package/dist/GcsaSkeleton.js +19 -0
  153. package/dist/GcsaSkeleton.js.map +1 -0
  154. package/dist/GcsaSpace.d.ts +7 -0
  155. package/dist/GcsaSpace.js +14 -0
  156. package/dist/GcsaSpace.js.map +1 -0
  157. package/dist/GcsaSpin.d.ts +7 -0
  158. package/dist/GcsaSpin.js +16 -0
  159. package/dist/GcsaSpin.js.map +1 -0
  160. package/dist/GcsaStatistic.d.ts +8 -0
  161. package/dist/GcsaStatistic.js +11 -0
  162. package/dist/GcsaStatistic.js.map +1 -0
  163. package/dist/GcsaSteps.d.ts +10 -0
  164. package/dist/GcsaSteps.js +54 -0
  165. package/dist/GcsaSteps.js.map +1 -0
  166. package/dist/GcsaSwitch.d.ts +11 -0
  167. package/dist/GcsaSwitch.js +36 -0
  168. package/dist/GcsaSwitch.js.map +1 -0
  169. package/dist/GcsaTabs.d.ts +15 -0
  170. package/dist/GcsaTabs.js +39 -0
  171. package/dist/GcsaTabs.js.map +1 -0
  172. package/dist/GcsaTag.d.ts +7 -0
  173. package/dist/GcsaTag.js +9 -0
  174. package/dist/GcsaTag.js.map +1 -0
  175. package/dist/GcsaTextarea.d.ts +13 -0
  176. package/dist/GcsaTextarea.js +76 -0
  177. package/dist/GcsaTextarea.js.map +1 -0
  178. package/dist/GcsaTimePicker.d.ts +12 -0
  179. package/dist/GcsaTimePicker.js +221 -0
  180. package/dist/GcsaTimePicker.js.map +1 -0
  181. package/dist/GcsaTimeline.d.ts +5 -0
  182. package/dist/GcsaTimeline.js +19 -0
  183. package/dist/GcsaTimeline.js.map +1 -0
  184. package/dist/GcsaToastStack.d.ts +11 -0
  185. package/dist/GcsaToastStack.js +45 -0
  186. package/dist/GcsaToastStack.js.map +1 -0
  187. package/dist/GcsaTooltip.d.ts +17 -0
  188. package/dist/GcsaTooltip.js +43 -0
  189. package/dist/GcsaTooltip.js.map +1 -0
  190. package/dist/GcsaTransfer.d.ts +11 -0
  191. package/dist/GcsaTransfer.js +95 -0
  192. package/dist/GcsaTransfer.js.map +1 -0
  193. package/dist/GcsaTree.d.ts +17 -0
  194. package/dist/GcsaTree.js +38 -0
  195. package/dist/GcsaTree.js.map +1 -0
  196. package/dist/GcsaTypography.d.ts +8 -0
  197. package/dist/GcsaTypography.js +14 -0
  198. package/dist/GcsaTypography.js.map +1 -0
  199. package/dist/GcsaUpload.d.ts +24 -0
  200. package/dist/GcsaUpload.js +146 -0
  201. package/dist/GcsaUpload.js.map +1 -0
  202. package/dist/hooks/gcsaFormTypes.d.ts +7 -0
  203. package/dist/hooks/useDocumentThemeSync.d.ts +3 -0
  204. package/dist/hooks/useDocumentThemeSync.js +7 -0
  205. package/dist/hooks/useDocumentThemeSync.js.map +1 -0
  206. package/dist/hooks/useGcsaComponentSize.d.ts +5 -0
  207. package/dist/hooks/useGcsaComponentSize.js +21 -0
  208. package/dist/hooks/useGcsaComponentSize.js.map +1 -0
  209. package/dist/hooks/useGcsaFormField.d.ts +26 -0
  210. package/dist/hooks/useGcsaFormField.js +47 -0
  211. package/dist/hooks/useGcsaFormField.js.map +1 -0
  212. package/dist/hooks/useGcsaFormSchema.d.ts +7 -0
  213. package/dist/hooks/useGcsaFormSchema.js +6 -0
  214. package/dist/hooks/useGcsaFormSchema.js.map +1 -0
  215. package/dist/hooks/useGcsaLocale.d.ts +4 -0
  216. package/dist/hooks/useGcsaLocale.js +15 -0
  217. package/dist/hooks/useGcsaLocale.js.map +1 -0
  218. package/dist/hooks/useGcsaPopupZIndex.d.ts +6 -0
  219. package/dist/hooks/useGcsaPopupZIndex.js +18 -0
  220. package/dist/hooks/useGcsaPopupZIndex.js.map +1 -0
  221. package/dist/hooks/useGcsaTextCount.d.ts +16 -0
  222. package/dist/hooks/useGcsaTextCount.js +16 -0
  223. package/dist/hooks/useGcsaTextCount.js.map +1 -0
  224. package/dist/hooks/useGcsaTheme.d.ts +7 -0
  225. package/dist/hooks/useGcsaTheme.js +19 -0
  226. package/dist/hooks/useGcsaTheme.js.map +1 -0
  227. package/dist/hooks/useGcsaZIndex.d.ts +13 -0
  228. package/dist/hooks/useGcsaZIndex.js +37 -0
  229. package/dist/hooks/useGcsaZIndex.js.map +1 -0
  230. package/dist/hooks/useMessage.d.ts +6 -0
  231. package/dist/hooks/useOverlayZIndex.d.ts +8 -0
  232. package/dist/hooks/useOverlayZIndex.js +14 -0
  233. package/dist/hooks/useOverlayZIndex.js.map +1 -0
  234. package/dist/hooks/usePreventHiddenInputScroll.d.ts +13 -0
  235. package/dist/hooks/usePreventHiddenInputScroll.js +124 -0
  236. package/dist/hooks/usePreventHiddenInputScroll.js.map +1 -0
  237. package/dist/icons/iconNames.d.ts +7 -0
  238. package/dist/icons/iconNames.js +24 -0
  239. package/dist/icons/iconNames.js.map +1 -0
  240. package/dist/icons/index.d.ts +2 -0
  241. package/dist/icons/registry.d.ts +3 -0
  242. package/dist/icons/registry.js +58 -0
  243. package/dist/icons/registry.js.map +1 -0
  244. package/dist/icons/svg/alert.svg.js +9 -0
  245. package/dist/icons/svg/alert.svg.js.map +1 -0
  246. package/dist/icons/svg/assets.svg.js +9 -0
  247. package/dist/icons/svg/assets.svg.js.map +1 -0
  248. package/dist/icons/svg/chat.svg.js +8 -0
  249. package/dist/icons/svg/chat.svg.js.map +1 -0
  250. package/dist/icons/svg/check.svg.js +8 -0
  251. package/dist/icons/svg/check.svg.js.map +1 -0
  252. package/dist/icons/svg/chevron-down.svg.js +8 -0
  253. package/dist/icons/svg/chevron-down.svg.js.map +1 -0
  254. package/dist/icons/svg/chevron-left.svg.js +8 -0
  255. package/dist/icons/svg/chevron-left.svg.js.map +1 -0
  256. package/dist/icons/svg/chevron-right.svg.js +8 -0
  257. package/dist/icons/svg/chevron-right.svg.js.map +1 -0
  258. package/dist/icons/svg/chevron-up.svg.js +8 -0
  259. package/dist/icons/svg/chevron-up.svg.js.map +1 -0
  260. package/dist/icons/svg/close.svg.js +6 -0
  261. package/dist/icons/svg/close.svg.js.map +1 -0
  262. package/dist/icons/svg/dashboard.svg.js +8 -0
  263. package/dist/icons/svg/dashboard.svg.js.map +1 -0
  264. package/dist/icons/svg/menu.svg.js +8 -0
  265. package/dist/icons/svg/menu.svg.js.map +1 -0
  266. package/dist/icons/svg/plus.svg.js +6 -0
  267. package/dist/icons/svg/plus.svg.js.map +1 -0
  268. package/dist/icons/svg/result-empty.svg.js +6 -0
  269. package/dist/icons/svg/result-empty.svg.js.map +1 -0
  270. package/dist/icons/svg/settings.svg.js +8 -0
  271. package/dist/icons/svg/settings.svg.js.map +1 -0
  272. package/dist/icons/svg/users.svg.js +11 -0
  273. package/dist/icons/svg/users.svg.js.map +1 -0
  274. package/dist/index.d.ts +151 -0
  275. package/dist/index.js +166 -0
  276. package/dist/index.js.map +1 -0
  277. package/dist/style.css +8028 -0
  278. package/dist/utils/gcsaDateValue.d.ts +25 -0
  279. package/dist/utils/gcsaDateValue.js +60 -0
  280. package/dist/utils/gcsaDateValue.js.map +1 -0
  281. package/dist/utils/gcsaTableColumns.d.ts +19 -0
  282. package/dist/utils/gcsaTableColumns.js +43 -0
  283. package/dist/utils/gcsaTableColumns.js.map +1 -0
  284. package/dist/utils/preserveDrawerScroll.d.ts +2 -0
  285. package/dist/utils/preserveDrawerScroll.js +13 -0
  286. package/dist/utils/preserveDrawerScroll.js.map +1 -0
  287. package/dist/utils/zodValidators.d.ts +21 -0
  288. package/dist/utils/zodValidators.js +35 -0
  289. package/dist/utils/zodValidators.js.map +1 -0
  290. package/package.json +58 -0
  291. package/src/ConsoleHeader.tsx +24 -0
  292. package/src/ConsolePage.tsx +22 -0
  293. package/src/ConsoleShell.tsx +248 -0
  294. package/src/ConsoleSidebar.tsx +61 -0
  295. package/src/GcsaAlert.tsx +29 -0
  296. package/src/GcsaAutoComplete.tsx +163 -0
  297. package/src/GcsaAvatar.tsx +21 -0
  298. package/src/GcsaBadge.tsx +15 -0
  299. package/src/GcsaBrandMark.tsx +18 -0
  300. package/src/GcsaBreadcrumb.tsx +35 -0
  301. package/src/GcsaButton.tsx +44 -0
  302. package/src/GcsaCalendar.tsx +14 -0
  303. package/src/GcsaCard.tsx +21 -0
  304. package/src/GcsaCascader.tsx +121 -0
  305. package/src/GcsaChatPanel.tsx +320 -0
  306. package/src/GcsaCheckbox.tsx +55 -0
  307. package/src/GcsaCollapse.tsx +23 -0
  308. package/src/GcsaConfigProvider.tsx +121 -0
  309. package/src/GcsaDataTable.tsx +779 -0
  310. package/src/GcsaDatePicker.tsx +284 -0
  311. package/src/GcsaDateRangePicker.tsx +310 -0
  312. package/src/GcsaDateTimePicker.tsx +407 -0
  313. package/src/GcsaDescriptions.tsx +22 -0
  314. package/src/GcsaDivider.tsx +7 -0
  315. package/src/GcsaDrawer.tsx +87 -0
  316. package/src/GcsaDropdown.tsx +84 -0
  317. package/src/GcsaEmpty.tsx +27 -0
  318. package/src/GcsaField.tsx +50 -0
  319. package/src/GcsaForm.tsx +82 -0
  320. package/src/GcsaFormField.tsx +67 -0
  321. package/src/GcsaIcon.tsx +21 -0
  322. package/src/GcsaImagePreview.tsx +30 -0
  323. package/src/GcsaInput.tsx +87 -0
  324. package/src/GcsaInputGroup.tsx +32 -0
  325. package/src/GcsaInputNumber.tsx +155 -0
  326. package/src/GcsaLoading.ts +206 -0
  327. package/src/GcsaLoadingMask.tsx +53 -0
  328. package/src/GcsaMarkdownRenderer.tsx +40 -0
  329. package/src/GcsaMenu.tsx +340 -0
  330. package/src/GcsaModal.tsx +68 -0
  331. package/src/GcsaMultiSelect.tsx +246 -0
  332. package/src/GcsaPagination.tsx +194 -0
  333. package/src/GcsaPopconfirm.tsx +104 -0
  334. package/src/GcsaPopover.tsx +131 -0
  335. package/src/GcsaPopoverClose.tsx +11 -0
  336. package/src/GcsaProgress.tsx +18 -0
  337. package/src/GcsaRadioGroup.tsx +42 -0
  338. package/src/GcsaResult.tsx +23 -0
  339. package/src/GcsaRow.tsx +13 -0
  340. package/src/GcsaSelect.tsx +186 -0
  341. package/src/GcsaSkeleton.tsx +19 -0
  342. package/src/GcsaSpace.tsx +17 -0
  343. package/src/GcsaSpin.tsx +25 -0
  344. package/src/GcsaStatistic.tsx +17 -0
  345. package/src/GcsaSteps.tsx +73 -0
  346. package/src/GcsaSwitch.tsx +45 -0
  347. package/src/GcsaTabs.tsx +53 -0
  348. package/src/GcsaTag.tsx +16 -0
  349. package/src/GcsaTextarea.tsx +87 -0
  350. package/src/GcsaTimePicker.tsx +298 -0
  351. package/src/GcsaTimeline.tsx +27 -0
  352. package/src/GcsaToastStack.tsx +67 -0
  353. package/src/GcsaTooltip.tsx +75 -0
  354. package/src/GcsaTransfer.tsx +129 -0
  355. package/src/GcsaTree.tsx +43 -0
  356. package/src/GcsaTypography.tsx +24 -0
  357. package/src/GcsaUpload.tsx +206 -0
  358. package/src/hooks/gcsaFormTypes.ts +23 -0
  359. package/src/hooks/useDocumentThemeSync.ts +6 -0
  360. package/src/hooks/useGcsaComponentSize.ts +24 -0
  361. package/src/hooks/useGcsaFormField.ts +49 -0
  362. package/src/hooks/useGcsaFormSchema.ts +6 -0
  363. package/src/hooks/useGcsaLocale.ts +16 -0
  364. package/src/hooks/useGcsaPopupZIndex.ts +23 -0
  365. package/src/hooks/useGcsaTextCount.ts +44 -0
  366. package/src/hooks/useGcsaTheme.ts +19 -0
  367. package/src/hooks/useGcsaZIndex.ts +60 -0
  368. package/src/hooks/useMessage.ts +7 -0
  369. package/src/hooks/useOverlayZIndex.ts +23 -0
  370. package/src/hooks/usePreventHiddenInputScroll.ts +233 -0
  371. package/src/icons/iconNames.ts +27 -0
  372. package/src/icons/index.ts +8 -0
  373. package/src/icons/registry.ts +38 -0
  374. package/src/icons/svg/alert.svg +4 -0
  375. package/src/icons/svg/assets.svg +4 -0
  376. package/src/icons/svg/chat.svg +3 -0
  377. package/src/icons/svg/check.svg +3 -0
  378. package/src/icons/svg/chevron-down.svg +3 -0
  379. package/src/icons/svg/chevron-left.svg +3 -0
  380. package/src/icons/svg/chevron-right.svg +3 -0
  381. package/src/icons/svg/chevron-up.svg +3 -0
  382. package/src/icons/svg/close.svg +1 -0
  383. package/src/icons/svg/dashboard.svg +3 -0
  384. package/src/icons/svg/menu.svg +3 -0
  385. package/src/icons/svg/plus.svg +1 -0
  386. package/src/icons/svg/result-empty.svg +1 -0
  387. package/src/icons/svg/settings.svg +3 -0
  388. package/src/icons/svg/users.svg +6 -0
  389. package/src/index.ts +166 -0
  390. package/src/utils/gcsaDateValue.ts +99 -0
  391. package/src/utils/gcsaTableColumns.ts +97 -0
  392. package/src/utils/preserveDrawerScroll.ts +20 -0
  393. package/src/utils/zodValidators.ts +45 -0
  394. package/src/vite-env.d.ts +6 -0
@@ -0,0 +1,298 @@
1
+ import {
2
+ gcsaBuildTimeOptions,
3
+ gcsaCurrentTimeOption,
4
+ gcsaResolveTimeDraft,
5
+ gcsaTimePickerHours,
6
+ gcsaTimePickerMinutes,
7
+ gcsaTimePickerScrollIndex,
8
+ gcsaTimePickerScrollTop
9
+ } from '@gcsa/console-core';
10
+ import { useEffect, useMemo, useRef, useState, type InputHTMLAttributes, type UIEvent } from 'react';
11
+ import { useGcsaLocaleMessages } from './hooks/useGcsaLocale';
12
+
13
+ export type GcsaTimePickerProps = Omit<
14
+ InputHTMLAttributes<HTMLInputElement>,
15
+ 'type' | 'onChange' | 'value' | 'placeholder' | 'readOnly'
16
+ > & {
17
+ value?: string;
18
+ step?: number;
19
+ min?: string;
20
+ max?: string;
21
+ allowClear?: boolean;
22
+ invalid?: boolean;
23
+ placeholder?: string;
24
+ onChange?: (value: string) => void;
25
+ };
26
+
27
+ function TimePickerIcon() {
28
+ return (
29
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
30
+ <circle cx="8" cy="8" r="5.75" stroke="currentColor" strokeWidth="1.2" />
31
+ <path d="M8 4.75V8l2.25 1.5" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" />
32
+ </svg>
33
+ );
34
+ }
35
+
36
+ export function GcsaTimePicker({
37
+ value = '',
38
+ onChange,
39
+ className,
40
+ step = 60,
41
+ min,
42
+ max,
43
+ allowClear = true,
44
+ invalid = false,
45
+ placeholder,
46
+ disabled,
47
+ ...props
48
+ }: GcsaTimePickerProps) {
49
+ const messages = useGcsaLocaleMessages();
50
+ const resolvedPlaceholder = placeholder ?? messages.timePickerPlaceholder;
51
+ const root = useRef<HTMLDivElement>(null);
52
+ const panelRef = useRef<HTMLDivElement>(null);
53
+ const hourColumn = useRef<HTMLDivElement>(null);
54
+ const minuteColumn = useRef<HTMLDivElement>(null);
55
+ const timers = useRef<{ hour?: ReturnType<typeof setTimeout>; minute?: ReturnType<typeof setTimeout> }>({});
56
+ const [open, setOpen] = useState(false);
57
+ const [alignPanelEnd, setAlignPanelEnd] = useState(false);
58
+ const [draft, setDraft] = useState('00:00');
59
+
60
+ const options = useMemo(
61
+ () => gcsaBuildTimeOptions({ min, max, step }),
62
+ [min, max, step]
63
+ );
64
+ const hours = useMemo(() => gcsaTimePickerHours(options), [options]);
65
+ const draftHour = draft.slice(0, 2);
66
+ const draftMinute = draft.slice(3);
67
+ const minutes = useMemo(
68
+ () => gcsaTimePickerMinutes(options, draftHour),
69
+ [options, draftHour]
70
+ );
71
+ const nowOption = useMemo(() => gcsaCurrentTimeOption(options), [options]);
72
+
73
+ const syncDraft = (next = value) => {
74
+ setDraft(gcsaResolveTimeDraft(next, options));
75
+ };
76
+
77
+ const scrollColumns = () => {
78
+ requestAnimationFrame(() => {
79
+ if (hourColumn.current) {
80
+ hourColumn.current.scrollTop = gcsaTimePickerScrollTop(hours.indexOf(draftHour));
81
+ }
82
+ if (minuteColumn.current) {
83
+ minuteColumn.current.scrollTop = gcsaTimePickerScrollTop(minutes.indexOf(draftMinute));
84
+ }
85
+ });
86
+ };
87
+
88
+ const syncPanelAlignment = () => {
89
+ requestAnimationFrame(() => {
90
+ if (!root.current) return;
91
+ const rect = root.current.getBoundingClientRect();
92
+ const panelWidth = panelRef.current?.offsetWidth ?? 220;
93
+ const padding = 8;
94
+ setAlignPanelEnd(rect.left + panelWidth > window.innerWidth - padding);
95
+ });
96
+ };
97
+
98
+ const openPicker = () => {
99
+ if (disabled || open) return;
100
+ syncDraft();
101
+ setOpen(true);
102
+ syncPanelAlignment();
103
+ scrollColumns();
104
+ };
105
+
106
+ const selectHour = (hour: string) => {
107
+ const nextMinute = minutes.includes(draftMinute) ? draftMinute : minutes[0] ?? '00';
108
+ setDraft(`${hour}:${nextMinute}`);
109
+ requestAnimationFrame(scrollColumns);
110
+ };
111
+
112
+ const handleScroll = (type: 'hour' | 'minute', event: UIEvent<HTMLDivElement>) => {
113
+ const element = event.currentTarget;
114
+ clearTimeout(timers.current[type]);
115
+ timers.current[type] = setTimeout(() => {
116
+ const values = type === 'hour' ? hours : minutes;
117
+ const nextValue = values[gcsaTimePickerScrollIndex(element.scrollTop, values.length)];
118
+ if (type === 'hour' && nextValue) selectHour(nextValue);
119
+ else if (type === 'minute' && nextValue) setDraft(`${draftHour}:${nextValue}`);
120
+ }, 80);
121
+ };
122
+
123
+ useEffect(() => {
124
+ if (!open) syncDraft(value);
125
+ }, [value, open, options]);
126
+
127
+ useEffect(() => {
128
+ const close = (event: PointerEvent) => {
129
+ if (!root.current?.contains(event.target as Node)) {
130
+ setOpen(false);
131
+ syncDraft();
132
+ }
133
+ };
134
+ document.addEventListener('pointerdown', close);
135
+ return () => {
136
+ document.removeEventListener('pointerdown', close);
137
+ clearTimeout(timers.current.hour);
138
+ clearTimeout(timers.current.minute);
139
+ };
140
+ }, [value, options]);
141
+
142
+ const commit = () => {
143
+ onChange?.(draft);
144
+ setOpen(false);
145
+ };
146
+
147
+ const cancel = () => {
148
+ setOpen(false);
149
+ syncDraft();
150
+ };
151
+
152
+ const onKeyDown: InputHTMLAttributes<HTMLInputElement>['onKeyDown'] = event => {
153
+ if (event.key === 'Escape') cancel();
154
+ else if (event.key === 'Enter') {
155
+ event.preventDefault();
156
+ if (open) commit();
157
+ else openPicker();
158
+ } else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
159
+ event.preventDefault();
160
+ openPicker();
161
+ const index = options.indexOf(draft);
162
+ const delta = event.key === 'ArrowDown' ? 1 : -1;
163
+ syncDraft(options[Math.max(0, Math.min(options.length - 1, index + delta))]);
164
+ scrollColumns();
165
+ }
166
+ };
167
+
168
+ return (
169
+ <div ref={root} className={`gcsa-time-picker__root${className ? ` ${className}` : ''}`}>
170
+ <div
171
+ className="gcsa-time-picker__control gcsa-focus-ring"
172
+ data-invalid={invalid || undefined}
173
+ onClick={openPicker}
174
+ >
175
+ <input
176
+ {...props}
177
+ type="text"
178
+ inputMode="numeric"
179
+ readOnly
180
+ value={value}
181
+ placeholder={resolvedPlaceholder}
182
+ disabled={disabled}
183
+ className="gcsa-time-picker__input"
184
+ aria-invalid={invalid || undefined}
185
+ aria-haspopup="dialog"
186
+ aria-expanded={open}
187
+ autoComplete="off"
188
+ onFocus={openPicker}
189
+ onKeyDown={onKeyDown}
190
+ />
191
+ <button
192
+ type="button"
193
+ className="gcsa-time-picker__trigger gcsa-focus-ring"
194
+ disabled={disabled}
195
+ aria-label={messages.timePickerOpen}
196
+ onMouseDown={event => event.preventDefault()}
197
+ onClick={event => {
198
+ event.stopPropagation();
199
+ openPicker();
200
+ }}
201
+ >
202
+ <TimePickerIcon />
203
+ </button>
204
+ </div>
205
+ {allowClear && value && !disabled ? (
206
+ <button
207
+ type="button"
208
+ className="gcsa-time-picker__clear"
209
+ aria-label={messages.timePickerClear}
210
+ onMouseDown={event => event.preventDefault()}
211
+ onClick={event => {
212
+ event.stopPropagation();
213
+ onChange?.('');
214
+ setOpen(false);
215
+ }}
216
+ >
217
+ ×
218
+ </button>
219
+ ) : null}
220
+ {open && !disabled ? (
221
+ <div
222
+ ref={panelRef}
223
+ className={`gcsa-time-picker__panel gcsa-ui-surface gcsa-time-picker__panel--open${alignPanelEnd ? ' gcsa-time-picker__panel--align-end' : ''}`}
224
+ role="dialog"
225
+ aria-label={messages.timePickerSelect}
226
+ >
227
+ <div className="gcsa-time-picker__spinner">
228
+ <div
229
+ ref={hourColumn}
230
+ className="gcsa-time-picker__column"
231
+ role="listbox"
232
+ aria-label={messages.timeHour}
233
+ onScroll={event => handleScroll('hour', event)}
234
+ >
235
+ {hours.map(hour => (
236
+ <button
237
+ key={hour}
238
+ type="button"
239
+ className={`gcsa-time-picker__cell${hour === draftHour ? ' gcsa-time-picker__cell--selected' : ''}`}
240
+ role="option"
241
+ aria-selected={hour === draftHour}
242
+ onMouseDown={event => event.preventDefault()}
243
+ onClick={() => selectHour(hour)}
244
+ >
245
+ {hour}
246
+ </button>
247
+ ))}
248
+ </div>
249
+ <div
250
+ ref={minuteColumn}
251
+ className="gcsa-time-picker__column"
252
+ role="listbox"
253
+ aria-label={messages.timeMinute}
254
+ onScroll={event => handleScroll('minute', event)}
255
+ >
256
+ {minutes.map(minute => (
257
+ <button
258
+ key={minute}
259
+ type="button"
260
+ className={`gcsa-time-picker__cell${minute === draftMinute ? ' gcsa-time-picker__cell--selected' : ''}`}
261
+ role="option"
262
+ aria-selected={minute === draftMinute}
263
+ onMouseDown={event => event.preventDefault()}
264
+ onClick={() => setDraft(`${draftHour}:${minute}`)}
265
+ >
266
+ {minute}
267
+ </button>
268
+ ))}
269
+ </div>
270
+ <div className="gcsa-time-picker__selection" aria-hidden="true" />
271
+ </div>
272
+ <div className="gcsa-time-picker__footer">
273
+ <button
274
+ type="button"
275
+ className="gcsa-time-picker__link"
276
+ disabled={!nowOption}
277
+ onMouseDown={event => event.preventDefault()}
278
+ onClick={() => {
279
+ syncDraft(nowOption);
280
+ scrollColumns();
281
+ }}
282
+ >
283
+ 此刻
284
+ </button>
285
+ <div className="gcsa-time-picker__actions">
286
+ <button type="button" className="gcsa-time-picker__link" onMouseDown={event => event.preventDefault()} onClick={cancel}>
287
+ 取消
288
+ </button>
289
+ <button type="button" className="gcsa-time-picker__confirm" onMouseDown={event => event.preventDefault()} onClick={commit}>
290
+ 确定
291
+ </button>
292
+ </div>
293
+ </div>
294
+ </div>
295
+ ) : null}
296
+ </div>
297
+ );
298
+ }
@@ -0,0 +1,27 @@
1
+ import type { GcsaTimelineItem } from '@gcsa/console-core';
2
+ import { useGcsaLocaleMessages } from './hooks/useGcsaLocale';
3
+
4
+ export type GcsaTimelineProps = { items: GcsaTimelineItem[] };
5
+
6
+ export function GcsaTimeline({ items }: GcsaTimelineProps) {
7
+ const messages = useGcsaLocaleMessages();
8
+
9
+ return (
10
+ <ol className="gcsa-timeline" aria-label={messages.timelineLabel}>
11
+ {items.map(item => (
12
+ <li key={item.key} className="gcsa-timeline__item">
13
+ <span className="gcsa-timeline__rail" aria-hidden="true">
14
+ <span className={`gcsa-timeline__dot gcsa-timeline__dot--${item.tone ?? 'primary'}`} />
15
+ </span>
16
+ <div className="gcsa-timeline__body">
17
+ <div className="gcsa-timeline__meta">
18
+ {item.label ? <strong>{item.label}</strong> : null}
19
+ {item.time ? <time>{item.time}</time> : null}
20
+ </div>
21
+ <p>{item.content}</p>
22
+ </div>
23
+ </li>
24
+ ))}
25
+ </ol>
26
+ );
27
+ }
@@ -0,0 +1,67 @@
1
+ import type { GcsaMessageType } from '@gcsa/console-core';
2
+
3
+ export type GcsaToastItem = {
4
+ id: number;
5
+ message: string;
6
+ type: GcsaMessageType;
7
+ };
8
+
9
+ function ToastIcon({ type }: { type: GcsaMessageType }) {
10
+ if (type === 'success') {
11
+ return (
12
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">
13
+ <path
14
+ d="M20 6 9 17l-5-5"
15
+ stroke="currentColor"
16
+ strokeWidth="2"
17
+ strokeLinecap="round"
18
+ strokeLinejoin="round"
19
+ />
20
+ </svg>
21
+ );
22
+ }
23
+
24
+ if (type === 'error') {
25
+ return (
26
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">
27
+ <path d="M15 9l-6 6M9 9l6 6" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
28
+ <circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="1.75" />
29
+ </svg>
30
+ );
31
+ }
32
+
33
+ return (
34
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">
35
+ <circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="1.75" />
36
+ <path d="M12 10v6M12 8h.01" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
37
+ </svg>
38
+ );
39
+ }
40
+
41
+ export type GcsaToastStackProps = {
42
+ toasts: GcsaToastItem[];
43
+ zIndex?: number;
44
+ };
45
+
46
+ export function GcsaToastStack({ toasts, zIndex }: GcsaToastStackProps) {
47
+ return (
48
+ <div
49
+ className="gcsa-toast-region"
50
+ aria-live="polite"
51
+ style={zIndex == null ? undefined : { zIndex }}
52
+ >
53
+ {toasts.map(toast => (
54
+ <div
55
+ key={toast.id}
56
+ className={`gcsa-toast gcsa-toast--${toast.type}`}
57
+ role="status"
58
+ >
59
+ <span className="gcsa-toast__icon" aria-hidden="true">
60
+ <ToastIcon type={toast.type} />
61
+ </span>
62
+ <span className="gcsa-toast__content">{toast.message}</span>
63
+ </div>
64
+ ))}
65
+ </div>
66
+ );
67
+ }
@@ -0,0 +1,75 @@
1
+ import type { CSSProperties, ReactNode } from 'react';
2
+ import { Tooltip } from '@ark-ui/react/tooltip';
3
+ import { Portal } from '@ark-ui/react/portal';
4
+ import { createGcsaPopupPositioning } from '@gcsa/console-core';
5
+ import { GcsaButton } from './GcsaButton';
6
+ import { useGcsaLocaleMessages } from './hooks/useGcsaLocale';
7
+ import { useGcsaPopupZIndex } from './hooks/useGcsaPopupZIndex';
8
+
9
+ export type GcsaTooltipPlacement = 'top' | 'right' | 'bottom' | 'left';
10
+
11
+ export type GcsaTooltipProps = {
12
+ content?: string;
13
+ tooltip?: ReactNode;
14
+ triggerLabel?: string;
15
+ placement?: GcsaTooltipPlacement;
16
+ disabled?: boolean;
17
+ openDelay?: number;
18
+ closeDelay?: number;
19
+ arrow?: boolean;
20
+ portalled?: boolean;
21
+ gutter?: number;
22
+ className?: string;
23
+ children?: ReactNode;
24
+ };
25
+
26
+ export function GcsaTooltip({
27
+ content = '',
28
+ tooltip,
29
+ triggerLabel,
30
+ placement = 'top',
31
+ disabled = false,
32
+ openDelay = 200,
33
+ closeDelay = 100,
34
+ arrow = true,
35
+ portalled = true,
36
+ gutter = 8,
37
+ children
38
+ }: GcsaTooltipProps) {
39
+ const messages = useGcsaLocaleMessages();
40
+ const { zIndex, onOpenChange } = useGcsaPopupZIndex();
41
+ const resolvedTriggerLabel = triggerLabel ?? messages.hoverToView;
42
+ const hasContent = Boolean(content || tooltip);
43
+ const trigger = children ?? (
44
+ <GcsaButton variant="secondary">
45
+ {resolvedTriggerLabel}
46
+ </GcsaButton>
47
+ );
48
+
49
+ const positionerStyle = (zIndex == null ? undefined : { zIndex }) as CSSProperties | undefined;
50
+ const contentStyle = (zIndex == null ? undefined : { zIndex }) as CSSProperties | undefined;
51
+
52
+ return (
53
+ <Tooltip.Root
54
+ disabled={disabled || !hasContent}
55
+ openDelay={openDelay}
56
+ closeDelay={closeDelay}
57
+ positioning={createGcsaPopupPositioning({ placement, gutter })}
58
+ onOpenChange={details => onOpenChange(details.open)}
59
+ >
60
+ <Tooltip.Trigger asChild>{trigger}</Tooltip.Trigger>
61
+ <Portal disabled={!portalled}>
62
+ <Tooltip.Positioner style={positionerStyle}>
63
+ <Tooltip.Content className="gcsa-tooltip gcsa-ui-surface" style={contentStyle}>
64
+ <span className="gcsa-tooltip__text">{tooltip ?? content}</span>
65
+ {arrow ? (
66
+ <Tooltip.Arrow className="gcsa-tooltip__arrow">
67
+ <Tooltip.ArrowTip className="gcsa-tooltip__arrow-tip" />
68
+ </Tooltip.Arrow>
69
+ ) : null}
70
+ </Tooltip.Content>
71
+ </Tooltip.Positioner>
72
+ </Portal>
73
+ </Tooltip.Root>
74
+ );
75
+ }
@@ -0,0 +1,129 @@
1
+ import { useMemo, useState } from 'react';
2
+ import type { GcsaTransferOption } from '@gcsa/console-core';
3
+ import { GcsaInput } from './GcsaInput';
4
+ import { useGcsaLocaleMessages } from './hooks/useGcsaLocale';
5
+
6
+ export type GcsaTransferProps = {
7
+ options: GcsaTransferOption[];
8
+ value?: string[];
9
+ sourceTitle?: string;
10
+ targetTitle?: string;
11
+ disabled?: boolean;
12
+ onValueChange?: (keys: string[]) => void;
13
+ onChange?: (keys: string[]) => void;
14
+ };
15
+
16
+ export function GcsaTransfer({
17
+ options,
18
+ value = [],
19
+ sourceTitle,
20
+ targetTitle,
21
+ disabled = false,
22
+ onValueChange,
23
+ onChange
24
+ }: GcsaTransferProps) {
25
+ const messages = useGcsaLocaleMessages();
26
+ const resolvedSourceTitle = sourceTitle ?? messages.transferSourceTitle;
27
+ const resolvedTargetTitle = targetTitle ?? messages.transferTargetTitle;
28
+ const [sourceSelected, setSourceSelected] = useState<string[]>([]);
29
+ const [targetSelected, setTargetSelected] = useState<string[]>([]);
30
+ const [sourceQuery, setSourceQuery] = useState('');
31
+ const [targetQuery, setTargetQuery] = useState('');
32
+ const availableItems = useMemo(
33
+ () =>
34
+ options.filter(
35
+ item =>
36
+ !value.includes(item.value) &&
37
+ item.label.toLowerCase().includes(sourceQuery.trim().toLowerCase())
38
+ ),
39
+ [options, sourceQuery, value]
40
+ );
41
+ const targetItems = useMemo(
42
+ () =>
43
+ options.filter(
44
+ item =>
45
+ value.includes(item.value) &&
46
+ item.label.toLowerCase().includes(targetQuery.trim().toLowerCase())
47
+ ),
48
+ [options, targetQuery, value]
49
+ );
50
+ const update = (next: string[]) => {
51
+ onValueChange?.(next);
52
+ onChange?.(next);
53
+ setSourceSelected([]);
54
+ setTargetSelected([]);
55
+ };
56
+ const toggle = (key: string, side: 'source' | 'target') => {
57
+ const current = side === 'source' ? sourceSelected : targetSelected;
58
+ const next = current.includes(key) ? current.filter(item => item !== key) : [...current, key];
59
+ if (side === 'source') setSourceSelected(next);
60
+ else setTargetSelected(next);
61
+ };
62
+ const panel = (items: GcsaTransferOption[], title: string, side: 'source' | 'target') => (
63
+ <section className="gcsa-transfer__panel" aria-label={title}>
64
+ <header className="gcsa-transfer__header">
65
+ <span>{title}</span>
66
+ <span>{items.length}</span>
67
+ </header>
68
+ <div className="gcsa-transfer__search">
69
+ <GcsaInput
70
+ value={side === 'source' ? sourceQuery : targetQuery}
71
+ placeholder={messages.searchPlaceholder}
72
+ disabled={disabled}
73
+ onValueChange={side === 'source' ? setSourceQuery : setTargetQuery}
74
+ />
75
+ </div>
76
+ <div className="gcsa-transfer__list" role="listbox" aria-multiselectable="true">
77
+ {items.length ? (
78
+ items.map(item => {
79
+ const selected = (side === 'source' ? sourceSelected : targetSelected).includes(item.value);
80
+ return (
81
+ <button
82
+ key={item.value}
83
+ type="button"
84
+ className={`gcsa-transfer__item gcsa-focus-ring${selected ? ' gcsa-transfer__item--selected' : ''}`}
85
+ disabled={disabled || item.disabled}
86
+ role="option"
87
+ aria-selected={selected}
88
+ onClick={() => toggle(item.value, side)}
89
+ >
90
+ <span className="gcsa-transfer__check" aria-hidden="true">
91
+ {selected ? '✓' : ''}
92
+ </span>
93
+ <span>{item.label}</span>
94
+ </button>
95
+ );
96
+ })
97
+ ) : (
98
+ <span className="gcsa-transfer__empty">{messages.noOptions}</span>
99
+ )}
100
+ </div>
101
+ </section>
102
+ );
103
+ return (
104
+ <div className={`gcsa-transfer${disabled ? ' gcsa-transfer--disabled' : ''}`}>
105
+ {panel(availableItems, resolvedSourceTitle, 'source')}
106
+ <div className="gcsa-transfer__actions">
107
+ <button
108
+ type="button"
109
+ className="gcsa-transfer__action gcsa-focus-ring"
110
+ disabled={disabled || !sourceSelected.length}
111
+ aria-label={messages.transferMoveRight}
112
+ onClick={() => update([...value, ...sourceSelected])}
113
+ >
114
+
115
+ </button>
116
+ <button
117
+ type="button"
118
+ className="gcsa-transfer__action gcsa-focus-ring"
119
+ disabled={disabled || !targetSelected.length}
120
+ aria-label={messages.transferMoveLeft}
121
+ onClick={() => update(value.filter(key => !targetSelected.includes(key)))}
122
+ >
123
+
124
+ </button>
125
+ </div>
126
+ {panel(targetItems, resolvedTargetTitle, 'target')}
127
+ </div>
128
+ );
129
+ }
@@ -0,0 +1,43 @@
1
+ import type { CSSProperties, ReactNode } from 'react';
2
+ import { useEffect, useState } from 'react';
3
+ import { GcsaIcon } from './GcsaIcon';
4
+ import { useGcsaLocaleMessages } from './hooks/useGcsaLocale';
5
+
6
+ export type GcsaTreeNode = { key: string; label: ReactNode; disabled?: boolean; children?: GcsaTreeNode[] };
7
+ export type GcsaTreeProps = { nodes?: GcsaTreeNode[]; expandedKeys?: string[]; selectedKeys?: string[]; multiple?: boolean; onExpandedKeysChange?: (keys: string[]) => void; onSelectedKeysChange?: (keys: string[]) => void; onSelect?: (node: GcsaTreeNode) => void };
8
+
9
+ export function GcsaTree({ nodes = [], expandedKeys, selectedKeys, multiple = false, onExpandedKeysChange, onSelectedKeysChange, onSelect }: GcsaTreeProps) {
10
+ const messages = useGcsaLocaleMessages();
11
+ const [internalExpandedKeys, setInternalExpandedKeys] = useState<string[]>(() => expandedKeys ?? []);
12
+ const [internalSelectedKeys, setInternalSelectedKeys] = useState<string[]>(() => selectedKeys ?? []);
13
+ const resolvedExpandedKeys = expandedKeys ?? internalExpandedKeys;
14
+ const resolvedSelectedKeys = selectedKeys ?? internalSelectedKeys;
15
+
16
+ useEffect(() => {
17
+ if (expandedKeys) setInternalExpandedKeys(expandedKeys);
18
+ }, [expandedKeys]);
19
+ useEffect(() => {
20
+ if (selectedKeys) setInternalSelectedKeys(selectedKeys);
21
+ }, [selectedKeys]);
22
+
23
+ function renderNode(node: GcsaTreeNode, depth: number, position: number, setSize: number): ReactNode {
24
+ const expanded = resolvedExpandedKeys.includes(node.key);
25
+ const selected = resolvedSelectedKeys.includes(node.key);
26
+ const hasChildren = Boolean(node.children?.length);
27
+ const updateExpanded = () => {
28
+ const next = expanded ? resolvedExpandedKeys.filter(key => key !== node.key) : [...resolvedExpandedKeys, node.key];
29
+ if (expandedKeys === undefined) setInternalExpandedKeys(next);
30
+ onExpandedKeysChange?.(next);
31
+ };
32
+ const childrenId = `gcsa-tree-children-${node.key}`;
33
+ return <div key={node.key} className="gcsa-tree__branch" role="treeitem" aria-level={depth + 1} aria-posinset={position} aria-setsize={setSize} aria-expanded={hasChildren ? expanded : undefined}>
34
+ <div className="gcsa-tree__node" style={{ paddingInlineStart: depth * 20 + 8 } as CSSProperties} data-selected={selected || undefined} data-expanded={hasChildren ? expanded : undefined} data-leaf={!hasChildren || undefined}>
35
+ {hasChildren ? <button type="button" className="gcsa-tree__toggle gcsa-focus-ring" aria-label={expanded ? 'Collapse' : 'Expand'} aria-expanded={expanded} aria-controls={childrenId} onClick={updateExpanded}><GcsaIcon name="chevronDown" size="sm" className={`gcsa-tree__caret${expanded ? ' gcsa-tree__caret--expanded' : ''}`} /></button> : <span className="gcsa-tree__spacer" />}
36
+ <button type="button" className="gcsa-tree__label gcsa-focus-ring" disabled={node.disabled} onClick={() => { const next = multiple ? selected ? resolvedSelectedKeys.filter(key => key !== node.key) : [...resolvedSelectedKeys, node.key] : [node.key]; if (selectedKeys === undefined) setInternalSelectedKeys(next); onSelectedKeysChange?.(next); onSelect?.(node); }}>{node.label}</button>
37
+ {hasChildren && !expanded ? <span className="gcsa-tree__summary" aria-label={`${node.children!.length} 项`}>{node.children!.length} 项</span> : null}
38
+ </div>
39
+ {hasChildren && expanded ? <div id={childrenId} className="gcsa-tree__children" role="group">{node.children!.map((child, index) => renderNode(child, depth + 1, index + 1, node.children!.length))}</div> : null}
40
+ </div>;
41
+ }
42
+ return <div className="gcsa-tree" role="tree" aria-multiselectable={multiple}>{nodes.length ? nodes.map((node, index) => renderNode(node, 0, index + 1, nodes.length)) : <div className="gcsa-tree__empty" role="status">{messages.emptyDefault}</div>}</div>;
43
+ }
@@ -0,0 +1,24 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export type GcsaTypographyProps = {
4
+ variant?: 'title' | 'text';
5
+ level?: 1 | 2 | 3 | 4 | 5;
6
+ className?: string;
7
+ children?: ReactNode;
8
+ };
9
+
10
+ export function GcsaTypography({
11
+ variant = 'text',
12
+ level = 3,
13
+ className,
14
+ children
15
+ }: GcsaTypographyProps) {
16
+ const classes =
17
+ variant === 'title'
18
+ ? `gcsa-typography gcsa-typography-title gcsa-typography-title--l${level}`
19
+ : 'gcsa-typography gcsa-typography-text';
20
+
21
+ return (
22
+ <div className={`gcsa-ui-surface ${classes}${className ? ` ${className}` : ''}`}>{children}</div>
23
+ );
24
+ }