tekivex-ui 2.5.15 → 2.6.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 (395) hide show
  1. package/dist/charts.cjs +1 -1
  2. package/dist/charts.js +22 -553
  3. package/dist/chunk-B3ph66Zb.js +1 -0
  4. package/dist/chunk-Bc16rJT-.js +1 -0
  5. package/dist/chunk-Dike2DLU.js +3 -0
  6. package/dist/chunk-DjxOP8W4.js +1 -0
  7. package/dist/chunk-DkoFTL1O.js +1 -0
  8. package/dist/chunk-DmRB1Blb.js +1 -0
  9. package/dist/chunk-DnCXUUx5.js +1 -0
  10. package/dist/chunk-LWkKqC8d.js +1 -0
  11. package/dist/chunk-PJ50l0JC.js +1 -0
  12. package/dist/headless.cjs +1 -1
  13. package/dist/headless.js +1 -442
  14. package/dist/i18n.cjs +1 -1
  15. package/dist/i18n.js +1 -733
  16. package/dist/index.cjs +1 -152
  17. package/dist/index.d.ts +4 -2
  18. package/dist/index.js +429 -16786
  19. package/dist/quantum.cjs +1 -89
  20. package/dist/quantum.js +74 -2551
  21. package/dist/realtime.cjs +1 -23
  22. package/dist/realtime.js +1 -804
  23. package/dist/src/a11y/index.d.ts +0 -1
  24. package/dist/src/charts/TkxAreaChart.d.ts +0 -5
  25. package/dist/src/charts/TkxBarChart.d.ts +0 -3
  26. package/dist/src/charts/TkxDonutChart.d.ts +0 -5
  27. package/dist/src/charts/TkxLineChart.d.ts +0 -1
  28. package/dist/src/charts/TkxPieChart.d.ts +0 -3
  29. package/dist/src/charts/TkxRadarChart.d.ts +0 -3
  30. package/dist/src/charts/TkxScatterChart.d.ts +0 -2
  31. package/dist/src/charts/index.d.ts +0 -1
  32. package/dist/src/charts/shared.d.ts +0 -3
  33. package/dist/src/components/TkxAIChatBubble.d.ts +0 -9
  34. package/dist/src/components/TkxAIConfidenceBar.d.ts +0 -6
  35. package/dist/src/components/TkxAIThinking.d.ts +0 -6
  36. package/dist/src/components/TkxAccordion.d.ts +0 -1
  37. package/dist/src/components/TkxAffix.d.ts +0 -1
  38. package/dist/src/components/TkxAlert.d.ts +0 -1
  39. package/dist/src/components/TkxAnchor.d.ts +0 -1
  40. package/dist/src/components/TkxAppBar.d.ts +0 -1
  41. package/dist/src/components/TkxAutocomplete.d.ts +0 -1
  42. package/dist/src/components/TkxAvatar.d.ts +0 -1
  43. package/dist/src/components/TkxBadge.d.ts +0 -1
  44. package/dist/src/components/TkxBottomNav.d.ts +0 -1
  45. package/dist/src/components/TkxBreadcrumb.d.ts +0 -1
  46. package/dist/src/components/TkxButton.d.ts +0 -1
  47. package/dist/src/components/TkxCard.d.ts +0 -1
  48. package/dist/src/components/TkxCarousel.d.ts +0 -1
  49. package/dist/src/components/TkxCascader.d.ts +0 -1
  50. package/dist/src/components/TkxChat.d.ts +0 -1
  51. package/dist/src/components/TkxCheckbox.d.ts +0 -1
  52. package/dist/src/components/TkxClock.d.ts +0 -1
  53. package/dist/src/components/TkxColorPicker.d.ts +0 -1
  54. package/dist/src/components/TkxCommand.d.ts +0 -1
  55. package/dist/src/components/TkxConfigProvider.d.ts +0 -30
  56. package/dist/src/components/TkxDataGrid.d.ts +0 -15
  57. package/dist/src/components/TkxDatePicker.d.ts +0 -1
  58. package/dist/src/components/TkxDivider.d.ts +0 -1
  59. package/dist/src/components/TkxDrawer.d.ts +0 -1
  60. package/dist/src/components/TkxDropdown.d.ts +0 -1
  61. package/dist/src/components/TkxEmpty.d.ts +0 -1
  62. package/dist/src/components/TkxFileUpload.d.ts +0 -1
  63. package/dist/src/components/TkxForm.d.ts +0 -35
  64. package/dist/src/components/TkxIcon.d.ts +0 -1
  65. package/dist/src/components/TkxImage.d.ts +0 -1
  66. package/dist/src/components/TkxInput.d.ts +1 -1
  67. package/dist/src/components/TkxLayout.d.ts +0 -22
  68. package/dist/src/components/TkxList.d.ts +0 -1
  69. package/dist/src/components/TkxLiveFeed.d.ts +0 -1
  70. package/dist/src/components/TkxLiveLog.d.ts +0 -1
  71. package/dist/src/components/TkxLiveMetrics.d.ts +0 -1
  72. package/dist/src/components/TkxLogo.d.ts +0 -1
  73. package/dist/src/components/TkxMarkdown.d.ts +0 -10
  74. package/dist/src/components/TkxMasonry.d.ts +0 -1
  75. package/dist/src/components/TkxMentions.d.ts +0 -1
  76. package/dist/src/components/TkxMenu.d.ts +0 -1
  77. package/dist/src/components/TkxModal.d.ts +0 -1
  78. package/dist/src/components/TkxNumberInput.d.ts +0 -1
  79. package/dist/src/components/TkxOTP.d.ts +0 -1
  80. package/dist/src/components/TkxOrgChart.d.ts +32 -0
  81. package/dist/src/components/TkxPagination.d.ts +0 -1
  82. package/dist/src/components/TkxPlayground.d.ts +0 -13
  83. package/dist/src/components/TkxPopover.d.ts +0 -1
  84. package/dist/src/components/TkxProgress.d.ts +0 -1
  85. package/dist/src/components/TkxQRCode.d.ts +0 -1
  86. package/dist/src/components/TkxQuantumForm.d.ts +0 -1
  87. package/dist/src/components/TkxRadio.d.ts +0 -1
  88. package/dist/src/components/TkxRating.d.ts +0 -1
  89. package/dist/src/components/TkxRealTimeChart.d.ts +0 -1
  90. package/dist/src/components/TkxResult.d.ts +0 -1
  91. package/dist/src/components/TkxRichTextDisplay.d.ts +0 -1
  92. package/dist/src/components/TkxSegmented.d.ts +0 -1
  93. package/dist/src/components/TkxSelect.d.ts +0 -3
  94. package/dist/src/components/TkxSkeleton.d.ts +0 -1
  95. package/dist/src/components/TkxSlider.d.ts +0 -1
  96. package/dist/src/components/TkxSnackbar.d.ts +0 -1
  97. package/dist/src/components/TkxSpeedDial.d.ts +0 -1
  98. package/dist/src/components/TkxSpin.d.ts +0 -1
  99. package/dist/src/components/TkxStatistic.d.ts +0 -1
  100. package/dist/src/components/TkxStepper.d.ts +0 -1
  101. package/dist/src/components/TkxTable.d.ts +0 -1
  102. package/dist/src/components/TkxTabs.d.ts +0 -1
  103. package/dist/src/components/TkxTag.d.ts +0 -1
  104. package/dist/src/components/TkxThemeBuilder.d.ts +0 -1
  105. package/dist/src/components/TkxTimeline.d.ts +0 -1
  106. package/dist/src/components/TkxToast.d.ts +0 -1
  107. package/dist/src/components/TkxToggle.d.ts +0 -1
  108. package/dist/src/components/TkxToolbar.d.ts +0 -1
  109. package/dist/src/components/TkxTooltip.d.ts +0 -1
  110. package/dist/src/components/TkxTour.d.ts +0 -1
  111. package/dist/src/components/TkxTransferList.d.ts +0 -1
  112. package/dist/src/components/TkxTreeView.d.ts +0 -1
  113. package/dist/src/components/TkxTypography.d.ts +0 -1
  114. package/dist/src/components/TkxVideoPlayer.d.ts +0 -1
  115. package/dist/src/components/TkxWatermark.d.ts +0 -1
  116. package/dist/src/components/index.d.ts +1 -1
  117. package/dist/src/engine/css.d.ts +0 -1
  118. package/dist/src/engine/index.d.ts +0 -1
  119. package/dist/src/engine/quantum-ai.d.ts +0 -73
  120. package/dist/src/engine/quantum.d.ts +0 -1
  121. package/dist/src/engine/security.d.ts +45 -9
  122. package/dist/src/engine/tkx.d.ts +0 -53
  123. package/dist/src/engine/wcag.d.ts +0 -1
  124. package/dist/src/headless/index.d.ts +0 -1
  125. package/dist/src/headless/useControllable.d.ts +0 -15
  126. package/dist/src/headless/useDebounce.d.ts +0 -12
  127. package/dist/src/headless/useDisclosure.d.ts +0 -13
  128. package/dist/src/headless/useFormState.d.ts +0 -13
  129. package/dist/src/headless/useInfiniteQuery.d.ts +0 -11
  130. package/dist/src/headless/useIntersectionObserver.d.ts +0 -10
  131. package/dist/src/headless/useListSelection.d.ts +0 -9
  132. package/dist/src/headless/useLocalStorage.d.ts +0 -8
  133. package/dist/src/headless/useMediaQuery.d.ts +0 -10
  134. package/dist/src/headless/useRovingTabIndex.d.ts +0 -15
  135. package/dist/src/headless/useSSE.d.ts +0 -9
  136. package/dist/src/headless/useThrottle.d.ts +0 -7
  137. package/dist/src/headless/useWebSocket.d.ts +0 -9
  138. package/dist/src/hooks/index.d.ts +0 -1
  139. package/dist/src/i18n/I18nProvider.d.ts +0 -1
  140. package/dist/src/i18n/index.d.ts +0 -1
  141. package/dist/src/quantum/index.d.ts +0 -1
  142. package/dist/src/realtime/index.d.ts +0 -1
  143. package/dist/src/themes/index.d.ts +0 -1
  144. package/package.json +5 -3
  145. package/dist/TkxForm-BaO4wvXt.js +0 -320
  146. package/dist/TkxForm-M6ttomry.cjs +0 -12
  147. package/dist/chunk-Bmb41Sf3.cjs +0 -1
  148. package/dist/hooks-6pRsPOyG.js +0 -58
  149. package/dist/hooks-mivgRljH.cjs +0 -1
  150. package/dist/index.d.ts.map +0 -1
  151. package/dist/src/a11y/index.d.ts.map +0 -1
  152. package/dist/src/charts/TkxAreaChart.d.ts.map +0 -1
  153. package/dist/src/charts/TkxBarChart.d.ts.map +0 -1
  154. package/dist/src/charts/TkxDonutChart.d.ts.map +0 -1
  155. package/dist/src/charts/TkxLineChart.d.ts.map +0 -1
  156. package/dist/src/charts/TkxPieChart.d.ts.map +0 -1
  157. package/dist/src/charts/TkxRadarChart.d.ts.map +0 -1
  158. package/dist/src/charts/TkxScatterChart.d.ts.map +0 -1
  159. package/dist/src/charts/index.d.ts.map +0 -1
  160. package/dist/src/charts/shared.d.ts.map +0 -1
  161. package/dist/src/components/TkxAIChatBubble.d.ts.map +0 -1
  162. package/dist/src/components/TkxAIConfidenceBar.d.ts.map +0 -1
  163. package/dist/src/components/TkxAIThinking.d.ts.map +0 -1
  164. package/dist/src/components/TkxAccordion.d.ts.map +0 -1
  165. package/dist/src/components/TkxAffix.d.ts.map +0 -1
  166. package/dist/src/components/TkxAlert.d.ts.map +0 -1
  167. package/dist/src/components/TkxAnchor.d.ts.map +0 -1
  168. package/dist/src/components/TkxAppBar.d.ts.map +0 -1
  169. package/dist/src/components/TkxAutocomplete.d.ts.map +0 -1
  170. package/dist/src/components/TkxAvatar.d.ts.map +0 -1
  171. package/dist/src/components/TkxBadge.d.ts.map +0 -1
  172. package/dist/src/components/TkxBottomNav.d.ts.map +0 -1
  173. package/dist/src/components/TkxBreadcrumb.d.ts.map +0 -1
  174. package/dist/src/components/TkxButton.d.ts.map +0 -1
  175. package/dist/src/components/TkxCard.d.ts.map +0 -1
  176. package/dist/src/components/TkxCarousel.d.ts.map +0 -1
  177. package/dist/src/components/TkxCascader.d.ts.map +0 -1
  178. package/dist/src/components/TkxChat.d.ts.map +0 -1
  179. package/dist/src/components/TkxCheckbox.d.ts.map +0 -1
  180. package/dist/src/components/TkxClock.d.ts.map +0 -1
  181. package/dist/src/components/TkxColorPicker.d.ts.map +0 -1
  182. package/dist/src/components/TkxCommand.d.ts.map +0 -1
  183. package/dist/src/components/TkxConfigProvider.d.ts.map +0 -1
  184. package/dist/src/components/TkxDataGrid.d.ts.map +0 -1
  185. package/dist/src/components/TkxDatePicker.d.ts.map +0 -1
  186. package/dist/src/components/TkxDivider.d.ts.map +0 -1
  187. package/dist/src/components/TkxDrawer.d.ts.map +0 -1
  188. package/dist/src/components/TkxDropdown.d.ts.map +0 -1
  189. package/dist/src/components/TkxEmpty.d.ts.map +0 -1
  190. package/dist/src/components/TkxFileUpload.d.ts.map +0 -1
  191. package/dist/src/components/TkxForm.d.ts.map +0 -1
  192. package/dist/src/components/TkxIcon.d.ts.map +0 -1
  193. package/dist/src/components/TkxImage.d.ts.map +0 -1
  194. package/dist/src/components/TkxInput.d.ts.map +0 -1
  195. package/dist/src/components/TkxLayout.d.ts.map +0 -1
  196. package/dist/src/components/TkxList.d.ts.map +0 -1
  197. package/dist/src/components/TkxLiveFeed.d.ts.map +0 -1
  198. package/dist/src/components/TkxLiveLog.d.ts.map +0 -1
  199. package/dist/src/components/TkxLiveMetrics.d.ts.map +0 -1
  200. package/dist/src/components/TkxLogo.d.ts.map +0 -1
  201. package/dist/src/components/TkxMarkdown.d.ts.map +0 -1
  202. package/dist/src/components/TkxMasonry.d.ts.map +0 -1
  203. package/dist/src/components/TkxMentions.d.ts.map +0 -1
  204. package/dist/src/components/TkxMenu.d.ts.map +0 -1
  205. package/dist/src/components/TkxModal.d.ts.map +0 -1
  206. package/dist/src/components/TkxNumberInput.d.ts.map +0 -1
  207. package/dist/src/components/TkxOTP.d.ts.map +0 -1
  208. package/dist/src/components/TkxPagination.d.ts.map +0 -1
  209. package/dist/src/components/TkxPlayground.d.ts.map +0 -1
  210. package/dist/src/components/TkxPopover.d.ts.map +0 -1
  211. package/dist/src/components/TkxProgress.d.ts.map +0 -1
  212. package/dist/src/components/TkxQRCode.d.ts.map +0 -1
  213. package/dist/src/components/TkxQuantumForm.d.ts.map +0 -1
  214. package/dist/src/components/TkxRadio.d.ts.map +0 -1
  215. package/dist/src/components/TkxRating.d.ts.map +0 -1
  216. package/dist/src/components/TkxRealTimeChart.d.ts.map +0 -1
  217. package/dist/src/components/TkxResult.d.ts.map +0 -1
  218. package/dist/src/components/TkxRichTextDisplay.d.ts.map +0 -1
  219. package/dist/src/components/TkxSegmented.d.ts.map +0 -1
  220. package/dist/src/components/TkxSelect.d.ts.map +0 -1
  221. package/dist/src/components/TkxSkeleton.d.ts.map +0 -1
  222. package/dist/src/components/TkxSlider.d.ts.map +0 -1
  223. package/dist/src/components/TkxSnackbar.d.ts.map +0 -1
  224. package/dist/src/components/TkxSpeedDial.d.ts.map +0 -1
  225. package/dist/src/components/TkxSpin.d.ts.map +0 -1
  226. package/dist/src/components/TkxStatistic.d.ts.map +0 -1
  227. package/dist/src/components/TkxStepper.d.ts.map +0 -1
  228. package/dist/src/components/TkxTable.d.ts.map +0 -1
  229. package/dist/src/components/TkxTabs.d.ts.map +0 -1
  230. package/dist/src/components/TkxTag.d.ts.map +0 -1
  231. package/dist/src/components/TkxThemeBuilder.d.ts.map +0 -1
  232. package/dist/src/components/TkxTimeline.d.ts.map +0 -1
  233. package/dist/src/components/TkxToast.d.ts.map +0 -1
  234. package/dist/src/components/TkxToggle.d.ts.map +0 -1
  235. package/dist/src/components/TkxToolbar.d.ts.map +0 -1
  236. package/dist/src/components/TkxTooltip.d.ts.map +0 -1
  237. package/dist/src/components/TkxTour.d.ts.map +0 -1
  238. package/dist/src/components/TkxTransferList.d.ts.map +0 -1
  239. package/dist/src/components/TkxTreeView.d.ts.map +0 -1
  240. package/dist/src/components/TkxTypography.d.ts.map +0 -1
  241. package/dist/src/components/TkxVideoPlayer.d.ts.map +0 -1
  242. package/dist/src/components/TkxWatermark.d.ts.map +0 -1
  243. package/dist/src/components/index.d.ts.map +0 -1
  244. package/dist/src/engine/css.d.ts.map +0 -1
  245. package/dist/src/engine/index.d.ts.map +0 -1
  246. package/dist/src/engine/quantum-ai.d.ts.map +0 -1
  247. package/dist/src/engine/quantum.d.ts.map +0 -1
  248. package/dist/src/engine/security.d.ts.map +0 -1
  249. package/dist/src/engine/tkx.d.ts.map +0 -1
  250. package/dist/src/engine/wcag.d.ts.map +0 -1
  251. package/dist/src/headless/index.d.ts.map +0 -1
  252. package/dist/src/headless/useControllable.d.ts.map +0 -1
  253. package/dist/src/headless/useDebounce.d.ts.map +0 -1
  254. package/dist/src/headless/useDisclosure.d.ts.map +0 -1
  255. package/dist/src/headless/useFormState.d.ts.map +0 -1
  256. package/dist/src/headless/useInfiniteQuery.d.ts.map +0 -1
  257. package/dist/src/headless/useIntersectionObserver.d.ts.map +0 -1
  258. package/dist/src/headless/useListSelection.d.ts.map +0 -1
  259. package/dist/src/headless/useLocalStorage.d.ts.map +0 -1
  260. package/dist/src/headless/useMediaQuery.d.ts.map +0 -1
  261. package/dist/src/headless/useRovingTabIndex.d.ts.map +0 -1
  262. package/dist/src/headless/useSSE.d.ts.map +0 -1
  263. package/dist/src/headless/useThrottle.d.ts.map +0 -1
  264. package/dist/src/headless/useWebSocket.d.ts.map +0 -1
  265. package/dist/src/hooks/index.d.ts.map +0 -1
  266. package/dist/src/i18n/I18nProvider.d.ts.map +0 -1
  267. package/dist/src/i18n/index.d.ts.map +0 -1
  268. package/dist/src/quantum/index.d.ts.map +0 -1
  269. package/dist/src/realtime/index.d.ts.map +0 -1
  270. package/dist/src/themes/index.d.ts.map +0 -1
  271. package/dist/themes-BbJanqiC.js +0 -498
  272. package/dist/themes-CMq2vWXj.cjs +0 -2
  273. package/dist/tkx-BoP5V5zy.cjs +0 -4
  274. package/dist/tkx-mOKMzvUK.js +0 -1174
  275. package/src/a11y/index.tsx +0 -87
  276. package/src/charts/TkxAreaChart.tsx +0 -121
  277. package/src/charts/TkxBarChart.tsx +0 -117
  278. package/src/charts/TkxDonutChart.tsx +0 -164
  279. package/src/charts/TkxLineChart.tsx +0 -137
  280. package/src/charts/TkxPieChart.tsx +0 -103
  281. package/src/charts/TkxRadarChart.tsx +0 -92
  282. package/src/charts/TkxScatterChart.tsx +0 -104
  283. package/src/charts/index.ts +0 -22
  284. package/src/charts/shared.ts +0 -47
  285. package/src/components/TkxAIChatBubble.tsx +0 -256
  286. package/src/components/TkxAIConfidenceBar.tsx +0 -133
  287. package/src/components/TkxAIThinking.tsx +0 -193
  288. package/src/components/TkxAccordion.tsx +0 -590
  289. package/src/components/TkxAffix.tsx +0 -140
  290. package/src/components/TkxAlert.tsx +0 -94
  291. package/src/components/TkxAnchor.tsx +0 -195
  292. package/src/components/TkxAppBar.tsx +0 -262
  293. package/src/components/TkxAutocomplete.tsx +0 -455
  294. package/src/components/TkxAvatar.tsx +0 -103
  295. package/src/components/TkxBadge.tsx +0 -75
  296. package/src/components/TkxBottomNav.tsx +0 -241
  297. package/src/components/TkxBreadcrumb.tsx +0 -324
  298. package/src/components/TkxButton.tsx +0 -155
  299. package/src/components/TkxCard.tsx +0 -96
  300. package/src/components/TkxCarousel.tsx +0 -554
  301. package/src/components/TkxCascader.tsx +0 -278
  302. package/src/components/TkxChat.tsx +0 -356
  303. package/src/components/TkxCheckbox.tsx +0 -220
  304. package/src/components/TkxClock.tsx +0 -603
  305. package/src/components/TkxColorPicker.tsx +0 -635
  306. package/src/components/TkxCommand.tsx +0 -646
  307. package/src/components/TkxConfigProvider.tsx +0 -460
  308. package/src/components/TkxDataGrid.tsx +0 -941
  309. package/src/components/TkxDatePicker.tsx +0 -1625
  310. package/src/components/TkxDivider.tsx +0 -51
  311. package/src/components/TkxDrawer.tsx +0 -236
  312. package/src/components/TkxDropdown.tsx +0 -804
  313. package/src/components/TkxEmpty.tsx +0 -221
  314. package/src/components/TkxFileUpload.tsx +0 -373
  315. package/src/components/TkxForm.tsx +0 -683
  316. package/src/components/TkxIcon.tsx +0 -685
  317. package/src/components/TkxImage.tsx +0 -279
  318. package/src/components/TkxInput.tsx +0 -103
  319. package/src/components/TkxLayout.tsx +0 -649
  320. package/src/components/TkxList.tsx +0 -244
  321. package/src/components/TkxLiveFeed.tsx +0 -331
  322. package/src/components/TkxLiveLog.tsx +0 -472
  323. package/src/components/TkxLiveMetrics.tsx +0 -315
  324. package/src/components/TkxLogo.tsx +0 -299
  325. package/src/components/TkxMarkdown.tsx +0 -855
  326. package/src/components/TkxMasonry.tsx +0 -178
  327. package/src/components/TkxMentions.tsx +0 -212
  328. package/src/components/TkxMenu.tsx +0 -1044
  329. package/src/components/TkxModal.tsx +0 -122
  330. package/src/components/TkxNumberInput.tsx +0 -410
  331. package/src/components/TkxOTP.tsx +0 -297
  332. package/src/components/TkxPagination.tsx +0 -390
  333. package/src/components/TkxPlayground.tsx +0 -845
  334. package/src/components/TkxPopover.tsx +0 -297
  335. package/src/components/TkxProgress.tsx +0 -114
  336. package/src/components/TkxQRCode.tsx +0 -176
  337. package/src/components/TkxQuantumForm.tsx +0 -594
  338. package/src/components/TkxRadio.tsx +0 -286
  339. package/src/components/TkxRating.tsx +0 -288
  340. package/src/components/TkxRealTimeChart.tsx +0 -383
  341. package/src/components/TkxResult.tsx +0 -130
  342. package/src/components/TkxRichTextDisplay.tsx +0 -396
  343. package/src/components/TkxSegmented.tsx +0 -171
  344. package/src/components/TkxSelect.tsx +0 -1130
  345. package/src/components/TkxSkeleton.tsx +0 -107
  346. package/src/components/TkxSlider.tsx +0 -495
  347. package/src/components/TkxSnackbar.tsx +0 -316
  348. package/src/components/TkxSpeedDial.tsx +0 -397
  349. package/src/components/TkxSpin.tsx +0 -263
  350. package/src/components/TkxStatistic.tsx +0 -263
  351. package/src/components/TkxStepper.tsx +0 -487
  352. package/src/components/TkxTable.tsx +0 -424
  353. package/src/components/TkxTabs.tsx +0 -126
  354. package/src/components/TkxTag.tsx +0 -321
  355. package/src/components/TkxThemeBuilder.tsx +0 -687
  356. package/src/components/TkxTimeline.tsx +0 -305
  357. package/src/components/TkxToast.tsx +0 -287
  358. package/src/components/TkxToggle.tsx +0 -95
  359. package/src/components/TkxToolbar.tsx +0 -262
  360. package/src/components/TkxTooltip.tsx +0 -85
  361. package/src/components/TkxTour.tsx +0 -241
  362. package/src/components/TkxTransferList.tsx +0 -489
  363. package/src/components/TkxTreeView.tsx +0 -423
  364. package/src/components/TkxTypography.tsx +0 -267
  365. package/src/components/TkxVideoPlayer.tsx +0 -1015
  366. package/src/components/TkxWatermark.tsx +0 -145
  367. package/src/components/index.ts +0 -80
  368. package/src/engine/css.ts +0 -126
  369. package/src/engine/index.ts +0 -12
  370. package/src/engine/quantum-ai.ts +0 -1045
  371. package/src/engine/quantum.ts +0 -207
  372. package/src/engine/security.ts +0 -232
  373. package/src/engine/tkx.ts +0 -1084
  374. package/src/engine/wcag.ts +0 -276
  375. package/src/headless/index.ts +0 -52
  376. package/src/headless/useControllable.ts +0 -42
  377. package/src/headless/useDebounce.ts +0 -37
  378. package/src/headless/useDisclosure.ts +0 -30
  379. package/src/headless/useFormState.ts +0 -113
  380. package/src/headless/useInfiniteQuery.ts +0 -155
  381. package/src/headless/useIntersectionObserver.ts +0 -53
  382. package/src/headless/useListSelection.ts +0 -103
  383. package/src/headless/useLocalStorage.ts +0 -48
  384. package/src/headless/useMediaQuery.ts +0 -39
  385. package/src/headless/useRovingTabIndex.ts +0 -86
  386. package/src/headless/useSSE.ts +0 -167
  387. package/src/headless/useThrottle.ts +0 -48
  388. package/src/headless/useWebSocket.ts +0 -231
  389. package/src/hooks/index.ts +0 -122
  390. package/src/i18n/I18nProvider.tsx +0 -36
  391. package/src/i18n/index.ts +0 -877
  392. package/src/quantum/index.ts +0 -39
  393. package/src/realtime/index.ts +0 -21
  394. package/src/styles/global.css +0 -167
  395. package/src/themes/index.ts +0 -294
@@ -1,804 +0,0 @@
1
- 'use client';
2
-
3
- import {
4
- useState,
5
- useRef,
6
- useEffect,
7
- useCallback,
8
- useId,
9
- type ReactNode,
10
- type CSSProperties,
11
- type KeyboardEvent,
12
- } from 'react';
13
- import { createPortal } from 'react-dom';
14
- import { useTheme } from '../themes';
15
- import { sanitizeString } from '../engine/security';
16
-
17
- // ── Types ──────────────────────────────────────────────────────────────────────
18
-
19
- export interface DropdownItem {
20
- key: string;
21
- label: string;
22
- icon?: ReactNode;
23
- description?: string;
24
- disabled?: boolean;
25
- danger?: boolean;
26
- shortcut?: string;
27
- divider?: boolean;
28
- children?: DropdownItem[];
29
- badge?: string | number;
30
- }
31
-
32
- export interface DropdownGroup {
33
- label?: string;
34
- items: DropdownItem[];
35
- }
36
-
37
- export type DropdownPlacement = 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end' | 'right' | 'left';
38
-
39
- export interface TkxDropdownProps {
40
- trigger: ReactNode;
41
- items?: DropdownItem[];
42
- groups?: DropdownGroup[];
43
- placement?: DropdownPlacement;
44
- onSelect?: (key: string, item: DropdownItem) => void;
45
- selectedKeys?: string[];
46
- multiSelect?: boolean;
47
- searchable?: boolean;
48
- searchPlaceholder?: string;
49
- closeOnSelect?: boolean;
50
- disabled?: boolean;
51
- maxHeight?: number;
52
- minWidth?: number;
53
- open?: boolean;
54
- onOpenChange?: (open: boolean) => void;
55
- portal?: boolean;
56
- offset?: number;
57
- renderItem?: (item: DropdownItem, selected: boolean) => ReactNode;
58
- }
59
-
60
- // ── Positioning helpers ────────────────────────────────────────────────────────
61
-
62
- interface MenuPosition {
63
- top: number;
64
- left: number;
65
- minWidth: number;
66
- }
67
-
68
- function calcPosition(
69
- triggerEl: HTMLElement,
70
- menuEl: HTMLElement | null,
71
- placement: DropdownPlacement,
72
- offset: number,
73
- ): MenuPosition {
74
- const tr = triggerEl.getBoundingClientRect();
75
- const mh = menuEl ? menuEl.offsetHeight : 320;
76
- const mw = menuEl ? menuEl.offsetWidth : 200;
77
- const vw = window.innerWidth;
78
- const vh = window.innerHeight;
79
- const scrollX = window.scrollX;
80
- const scrollY = window.scrollY;
81
-
82
- let top = 0;
83
- let left = 0;
84
-
85
- switch (placement) {
86
- case 'bottom-start':
87
- top = tr.bottom + scrollY + offset;
88
- left = tr.left + scrollX;
89
- break;
90
- case 'bottom-end':
91
- top = tr.bottom + scrollY + offset;
92
- left = tr.right + scrollX - mw;
93
- break;
94
- case 'top-start':
95
- top = tr.top + scrollY - offset - mh;
96
- left = tr.left + scrollX;
97
- break;
98
- case 'top-end':
99
- top = tr.top + scrollY - offset - mh;
100
- left = tr.right + scrollX - mw;
101
- break;
102
- case 'right':
103
- top = tr.top + scrollY;
104
- left = tr.right + scrollX + offset;
105
- break;
106
- case 'left':
107
- top = tr.top + scrollY;
108
- left = tr.left + scrollX - offset - mw;
109
- break;
110
- default:
111
- top = tr.bottom + scrollY + offset;
112
- left = tr.left + scrollX;
113
- }
114
-
115
- // Flip if overflows viewport
116
- if (placement.startsWith('bottom') && tr.bottom + mh > vh) {
117
- top = tr.top + scrollY - offset - mh;
118
- }
119
- if (placement.startsWith('top') && tr.top - mh < 0) {
120
- top = tr.bottom + scrollY + offset;
121
- }
122
- if (left + mw > vw + scrollX) {
123
- left = vw + scrollX - mw - 8;
124
- }
125
- if (left < scrollX) {
126
- left = scrollX + 8;
127
- }
128
-
129
- return { top, left, minWidth: tr.width };
130
- }
131
-
132
- // ── Text highlight helper ──────────────────────────────────────────────────────
133
-
134
- function highlightText(text: string, query: string): ReactNode {
135
- if (!query) return text;
136
- const lower = text.toLowerCase();
137
- const idx = lower.indexOf(query.toLowerCase());
138
- if (idx === -1) return text;
139
- return (
140
- <>
141
- {text.slice(0, idx)}
142
- <mark style={{ background: 'rgba(0,245,212,0.3)', color: 'inherit', borderRadius: 2 }}>
143
- {text.slice(idx, idx + query.length)}
144
- </mark>
145
- {text.slice(idx + query.length)}
146
- </>
147
- );
148
- }
149
-
150
- // ── Flatten items for keyboard nav ────────────────────────────────────────────
151
-
152
- function flattenItems(groups: DropdownGroup[], query: string): DropdownItem[] {
153
- const flat: DropdownItem[] = [];
154
- for (const g of groups) {
155
- for (const item of g.items) {
156
- if (!item.disabled) {
157
- if (!query || item.label.toLowerCase().includes(query.toLowerCase())) {
158
- flat.push(item);
159
- }
160
- // Do not include submenu items in the top-level flat list for keyboard nav
161
- }
162
- }
163
- }
164
- return flat;
165
- }
166
-
167
- // ── DropdownMenu (the actual menu panel) ──────────────────────────────────────
168
-
169
- interface DropdownMenuProps {
170
- groups: DropdownGroup[];
171
- position: MenuPosition;
172
- maxHeight: number;
173
- minWidth: number;
174
- selectedKeys: string[];
175
- multiSelect: boolean;
176
- searchable: boolean;
177
- searchPlaceholder: string;
178
- onSelect: (key: string, item: DropdownItem) => void;
179
- onClose: () => void;
180
- renderItem?: (item: DropdownItem, selected: boolean) => ReactNode;
181
- menuRef: React.RefObject<HTMLDivElement | null>;
182
- isPortal: boolean;
183
- menuId: string;
184
- }
185
-
186
- function DropdownMenu({
187
- groups,
188
- position,
189
- maxHeight,
190
- minWidth: propMinWidth,
191
- selectedKeys,
192
- multiSelect,
193
- searchable,
194
- searchPlaceholder,
195
- onSelect,
196
- onClose,
197
- renderItem,
198
- menuRef,
199
- isPortal,
200
- menuId,
201
- }: DropdownMenuProps) {
202
- const theme = useTheme();
203
- const [query, setQuery] = useState('');
204
- const [focusedIndex, setFocusedIndex] = useState(0);
205
- const [openSubmenuKey, setOpenSubmenuKey] = useState<string | null>(null);
206
- const [submenuFocusedIndex, setSubmenuFocusedIndex] = useState(0);
207
- const searchRef = useRef<HTMLInputElement>(null);
208
- const itemRefs = useRef<(HTMLDivElement | null)[]>([]);
209
- const submenuItemRefs = useRef<(HTMLDivElement | null)[]>([]);
210
-
211
- const filteredGroups: DropdownGroup[] = query
212
- ? groups
213
- .map((g) => ({
214
- ...g,
215
- items: g.items.filter(
216
- (item) =>
217
- item.label.toLowerCase().includes(query.toLowerCase()) ||
218
- item.description?.toLowerCase().includes(query.toLowerCase()) ||
219
- item.children?.some((c) => c.label.toLowerCase().includes(query.toLowerCase())),
220
- ),
221
- }))
222
- .filter((g) => g.items.length > 0)
223
- : groups;
224
-
225
- const flatNavigable = flattenItems(filteredGroups, query);
226
-
227
- useEffect(() => {
228
- if (searchable && searchRef.current) {
229
- searchRef.current.focus();
230
- } else {
231
- itemRefs.current[0]?.focus();
232
- }
233
- setFocusedIndex(0);
234
- }, [searchable]);
235
-
236
- // Sync focus to DOM
237
- useEffect(() => {
238
- if (!searchable || query !== '') {
239
- itemRefs.current[focusedIndex]?.focus();
240
- }
241
- }, [focusedIndex, searchable, query]);
242
-
243
- const handleKeyDown = useCallback(
244
- (e: KeyboardEvent<HTMLDivElement>) => {
245
- switch (e.key) {
246
- case 'ArrowDown':
247
- e.preventDefault();
248
- if (openSubmenuKey) {
249
- const submenuItems = flatNavigable.find((i) => i.key === openSubmenuKey)?.children ?? [];
250
- const enabledSub = submenuItems.filter((i) => !i.disabled);
251
- setSubmenuFocusedIndex((idx) => Math.min(idx + 1, enabledSub.length - 1));
252
- } else {
253
- setFocusedIndex((idx) => Math.min(idx + 1, flatNavigable.length - 1));
254
- }
255
- break;
256
- case 'ArrowUp':
257
- e.preventDefault();
258
- if (openSubmenuKey) {
259
- setSubmenuFocusedIndex((idx) => Math.max(idx - 1, 0));
260
- } else {
261
- setFocusedIndex((idx) => Math.max(idx - 1, 0));
262
- }
263
- break;
264
- case 'ArrowRight': {
265
- e.preventDefault();
266
- const cur = flatNavigable[focusedIndex];
267
- if (cur?.children?.length) {
268
- setOpenSubmenuKey(cur.key);
269
- setSubmenuFocusedIndex(0);
270
- }
271
- break;
272
- }
273
- case 'ArrowLeft':
274
- e.preventDefault();
275
- setOpenSubmenuKey(null);
276
- break;
277
- case 'Enter':
278
- case ' ':
279
- e.preventDefault();
280
- if (openSubmenuKey) {
281
- const submenuItems = flatNavigable.find((i) => i.key === openSubmenuKey)?.children ?? [];
282
- const enabledSub = submenuItems.filter((i) => !i.disabled);
283
- const subItem = enabledSub[submenuFocusedIndex];
284
- if (subItem) onSelect(subItem.key, subItem);
285
- } else {
286
- const item = flatNavigable[focusedIndex];
287
- if (item) onSelect(item.key, item);
288
- }
289
- break;
290
- case 'Escape':
291
- e.preventDefault();
292
- if (openSubmenuKey) {
293
- setOpenSubmenuKey(null);
294
- } else {
295
- onClose();
296
- }
297
- break;
298
- case 'Tab':
299
- onClose();
300
- break;
301
- default:
302
- break;
303
- }
304
- },
305
- [flatNavigable, focusedIndex, onClose, onSelect, openSubmenuKey, submenuFocusedIndex],
306
- );
307
-
308
- // Sync submenu focus
309
- useEffect(() => {
310
- if (openSubmenuKey) {
311
- submenuItemRefs.current[submenuFocusedIndex]?.focus();
312
- }
313
- }, [submenuFocusedIndex, openSubmenuKey]);
314
-
315
- const menuStyle: CSSProperties = {
316
- position: isPortal ? 'fixed' : 'absolute',
317
- top: isPortal ? position.top : undefined,
318
- left: isPortal ? position.left : undefined,
319
- minWidth: Math.max(propMinWidth, position.minWidth),
320
- maxHeight,
321
- overflowY: 'auto',
322
- background: theme.surface,
323
- border: `1px solid ${theme.border}`,
324
- borderRadius: 8,
325
- boxShadow: `0 8px 32px rgba(0,0,0,0.4)`,
326
- zIndex: 9999,
327
- outline: 'none',
328
- transformOrigin: 'top left',
329
- animation: 'tkx-dropdown-in 150ms ease forwards',
330
- };
331
-
332
- let navIdx = 0;
333
-
334
- return (
335
- <div
336
- ref={menuRef as React.RefObject<HTMLDivElement>}
337
- id={menuId}
338
- role="menu"
339
- aria-label="Dropdown menu"
340
- tabIndex={-1}
341
- style={menuStyle}
342
- onKeyDown={handleKeyDown}
343
- >
344
- <style>{`
345
- @keyframes tkx-dropdown-in {
346
- from { opacity: 0; transform: scale(0.95); }
347
- to { opacity: 1; transform: scale(1); }
348
- }
349
- `}</style>
350
-
351
- {searchable && (
352
- <div style={{ padding: '8px 8px 4px' }}>
353
- <input
354
- ref={searchRef}
355
- type="text"
356
- value={query}
357
- onChange={(e) => {
358
- setQuery(e.target.value);
359
- setFocusedIndex(0);
360
- }}
361
- placeholder={searchPlaceholder}
362
- aria-label="Search items"
363
- style={{
364
- width: '100%',
365
- boxSizing: 'border-box',
366
- padding: '6px 10px',
367
- background: theme.surfaceAlt,
368
- border: `1px solid ${theme.border}`,
369
- borderRadius: 6,
370
- color: theme.text,
371
- fontSize: 13,
372
- outline: 'none',
373
- }}
374
- />
375
- </div>
376
- )}
377
-
378
- {filteredGroups.length === 0 && (
379
- <div
380
- style={{
381
- padding: '12px 16px',
382
- color: theme.textMuted,
383
- fontSize: 13,
384
- textAlign: 'center',
385
- }}
386
- >
387
- No results found
388
- </div>
389
- )}
390
-
391
- {filteredGroups.map((group, gi) => (
392
- <div key={gi} role="group" aria-label={group.label}>
393
- {group.label && (
394
- <div
395
- style={{
396
- padding: '8px 12px 4px',
397
- fontSize: 11,
398
- fontWeight: 600,
399
- letterSpacing: '0.06em',
400
- textTransform: 'uppercase',
401
- color: theme.textMuted,
402
- }}
403
- >
404
- {sanitizeString(group.label)}
405
- </div>
406
- )}
407
-
408
- {group.items.map((item) => {
409
- const currentNavIdx = navIdx;
410
- if (!item.disabled) navIdx++;
411
-
412
- const isSelected = selectedKeys.includes(item.key);
413
- const isFocused = currentNavIdx === focusedIndex && !item.disabled;
414
- const hasSubmenu = !!item.children?.length;
415
- const isSubmenuOpen = openSubmenuKey === item.key;
416
-
417
- const itemContent = renderItem ? (
418
- renderItem(item, isSelected)
419
- ) : (
420
- <DefaultItemContent
421
- item={item}
422
- isSelected={isSelected}
423
- isFocused={isFocused}
424
- multiSelect={multiSelect}
425
- query={query}
426
- theme={theme}
427
- hasSubmenu={hasSubmenu}
428
- />
429
- );
430
-
431
- return (
432
- <div key={item.key}>
433
- {item.divider && (
434
- <div
435
- role="separator"
436
- style={{
437
- height: 1,
438
- background: theme.border,
439
- margin: '4px 0',
440
- }}
441
- />
442
- )}
443
- <div
444
- ref={(el) => {
445
- itemRefs.current[currentNavIdx] = el;
446
- }}
447
- role="menuitem"
448
- aria-disabled={item.disabled}
449
- aria-checked={multiSelect ? isSelected : undefined}
450
- aria-selected={!multiSelect ? isSelected : undefined}
451
- aria-haspopup={hasSubmenu ? 'menu' : undefined}
452
- aria-expanded={hasSubmenu ? isSubmenuOpen : undefined}
453
- tabIndex={item.disabled ? -1 : 0}
454
- style={{
455
- position: 'relative',
456
- cursor: item.disabled ? 'not-allowed' : 'pointer',
457
- opacity: item.disabled ? 0.5 : 1,
458
- }}
459
- onClick={() => {
460
- if (item.disabled) return;
461
- if (hasSubmenu) {
462
- setOpenSubmenuKey(isSubmenuOpen ? null : item.key);
463
- setSubmenuFocusedIndex(0);
464
- } else {
465
- onSelect(item.key, item);
466
- }
467
- }}
468
- onMouseEnter={() => {
469
- if (!item.disabled) {
470
- setFocusedIndex(currentNavIdx);
471
- if (hasSubmenu) {
472
- setOpenSubmenuKey(item.key);
473
- setSubmenuFocusedIndex(0);
474
- } else {
475
- setOpenSubmenuKey(null);
476
- }
477
- }
478
- }}
479
- onFocus={() => {
480
- if (!item.disabled) setFocusedIndex(currentNavIdx);
481
- }}
482
- >
483
- {itemContent}
484
-
485
- {/* Submenu panel */}
486
- {hasSubmenu && isSubmenuOpen && (
487
- <div
488
- role="menu"
489
- style={{
490
- position: 'absolute',
491
- top: 0,
492
- left: '100%',
493
- minWidth: 180,
494
- background: theme.surface,
495
- border: `1px solid ${theme.border}`,
496
- borderRadius: 8,
497
- boxShadow: '0 8px 32px rgba(0,0,0,0.4)',
498
- zIndex: 10000,
499
- animation: 'tkx-dropdown-in 120ms ease forwards',
500
- }}
501
- >
502
- {item.children!.map((child, ci) => {
503
- const isChildSelected = selectedKeys.includes(child.key);
504
- const isChildFocused = ci === submenuFocusedIndex;
505
- return (
506
- <div
507
- key={child.key}
508
- ref={(el) => {
509
- submenuItemRefs.current[ci] = el;
510
- }}
511
- role="menuitem"
512
- aria-disabled={child.disabled}
513
- aria-selected={isChildSelected}
514
- tabIndex={child.disabled ? -1 : 0}
515
- style={{ cursor: child.disabled ? 'not-allowed' : 'pointer', opacity: child.disabled ? 0.5 : 1 }}
516
- onClick={(e) => {
517
- e.stopPropagation();
518
- if (!child.disabled) onSelect(child.key, child);
519
- }}
520
- onMouseEnter={() => setSubmenuFocusedIndex(ci)}
521
- >
522
- <DefaultItemContent
523
- item={child}
524
- isSelected={isChildSelected}
525
- isFocused={isChildFocused}
526
- multiSelect={multiSelect}
527
- query={query}
528
- theme={theme}
529
- hasSubmenu={false}
530
- />
531
- </div>
532
- );
533
- })}
534
- </div>
535
- )}
536
- </div>
537
- </div>
538
- );
539
- })}
540
- </div>
541
- ))}
542
- </div>
543
- );
544
- }
545
-
546
- // ── Default Item Content ───────────────────────────────────────────────────────
547
-
548
- interface DefaultItemContentProps {
549
- item: DropdownItem;
550
- isSelected: boolean;
551
- isFocused: boolean;
552
- multiSelect: boolean;
553
- query: string;
554
- theme: import('../themes').ThemeTokens;
555
- hasSubmenu: boolean;
556
- }
557
-
558
- function DefaultItemContent({ item, isSelected, isFocused, multiSelect, query, theme, hasSubmenu }: DefaultItemContentProps) {
559
- const bg = isFocused
560
- ? item.danger
561
- ? `${theme.danger}20`
562
- : `${theme.primary}18`
563
- : 'transparent';
564
-
565
- return (
566
- <div
567
- style={{
568
- display: 'flex',
569
- alignItems: 'center',
570
- gap: 8,
571
- padding: '8px 12px',
572
- background: bg,
573
- transition: 'background 80ms',
574
- color: item.danger ? theme.danger : theme.text,
575
- fontSize: 14,
576
- userSelect: 'none',
577
- }}
578
- >
579
- {/* Checkmark for multi-select */}
580
- {multiSelect && (
581
- <div
582
- style={{
583
- width: 16,
584
- height: 16,
585
- border: `2px solid ${isSelected ? theme.primary : theme.border}`,
586
- borderRadius: 4,
587
- background: isSelected ? theme.primary : 'transparent',
588
- display: 'flex',
589
- alignItems: 'center',
590
- justifyContent: 'center',
591
- flexShrink: 0,
592
- transition: 'all 120ms',
593
- }}
594
- >
595
- {isSelected && (
596
- <svg width="10" height="8" viewBox="0 0 10 8" fill="none">
597
- <path d="M1 4l3 3L9 1" stroke={theme.bg} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
598
- </svg>
599
- )}
600
- </div>
601
- )}
602
-
603
- {/* Icon */}
604
- {item.icon && (
605
- <span style={{ display: 'flex', alignItems: 'center', flexShrink: 0, color: item.danger ? theme.danger : theme.textMuted }}>
606
- {item.icon}
607
- </span>
608
- )}
609
-
610
- {/* Label + description */}
611
- <div style={{ flex: 1, minWidth: 0 }}>
612
- <div style={{ fontWeight: isSelected && !multiSelect ? 600 : 400 }}>
613
- {highlightText(item.label, query)}
614
- </div>
615
- {item.description && (
616
- <div style={{ fontSize: 12, color: theme.textMuted, marginTop: 1 }}>
617
- {highlightText(item.description, query)}
618
- </div>
619
- )}
620
- </div>
621
-
622
- {/* Badge */}
623
- {item.badge !== undefined && (
624
- <span
625
- style={{
626
- background: theme.primary,
627
- color: theme.bg,
628
- fontSize: 11,
629
- fontWeight: 700,
630
- borderRadius: 10,
631
- padding: '1px 7px',
632
- flexShrink: 0,
633
- }}
634
- >
635
- {item.badge}
636
- </span>
637
- )}
638
-
639
- {/* Shortcut */}
640
- {item.shortcut && !hasSubmenu && (
641
- <span style={{ fontSize: 12, color: theme.textMuted, flexShrink: 0 }}>
642
- {item.shortcut}
643
- </span>
644
- )}
645
-
646
- {/* Submenu chevron */}
647
- {hasSubmenu && (
648
- <svg width="12" height="12" viewBox="0 0 12 12" fill="none" style={{ flexShrink: 0 }}>
649
- <path d="M4 2l4 4-4 4" stroke={theme.textMuted} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
650
- </svg>
651
- )}
652
-
653
- {/* Selected indicator (single-select) */}
654
- {!multiSelect && isSelected && (
655
- <svg width="14" height="14" viewBox="0 0 14 14" fill="none" style={{ flexShrink: 0 }}>
656
- <path d="M2 7l4 4L12 3" stroke={theme.primary} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
657
- </svg>
658
- )}
659
- </div>
660
- );
661
- }
662
-
663
- // ── Main TkxDropdown ──────────────────────────────────────────────────────────
664
-
665
- export function TkxDropdown({
666
- trigger,
667
- items,
668
- groups,
669
- placement = 'bottom-start',
670
- onSelect,
671
- selectedKeys: controlledSelectedKeys,
672
- multiSelect = false,
673
- searchable = false,
674
- searchPlaceholder = 'Search…',
675
- closeOnSelect,
676
- disabled = false,
677
- maxHeight = 320,
678
- minWidth = 200,
679
- open: controlledOpen,
680
- onOpenChange,
681
- portal = true,
682
- offset = 6,
683
- renderItem,
684
- }: TkxDropdownProps) {
685
- const [internalOpen, setInternalOpen] = useState(false);
686
- const [internalSelectedKeys, setInternalSelectedKeys] = useState<string[]>([]);
687
- const [menuPosition, setMenuPosition] = useState<MenuPosition>({ top: 0, left: 0, minWidth });
688
-
689
- const triggerRef = useRef<HTMLDivElement>(null);
690
- const menuRef = useRef<HTMLDivElement>(null);
691
- const menuId = useId();
692
-
693
- const isOpen = controlledOpen !== undefined ? controlledOpen : internalOpen;
694
- const selectedKeys = controlledSelectedKeys !== undefined ? controlledSelectedKeys : internalSelectedKeys;
695
-
696
- const shouldCloseOnSelect = closeOnSelect !== undefined ? closeOnSelect : !multiSelect;
697
-
698
- // Normalize to groups
699
- const resolvedGroups: DropdownGroup[] = groups ?? (items ? [{ items }] : [{ items: [] }]);
700
-
701
- const setOpen = useCallback(
702
- (next: boolean) => {
703
- if (controlledOpen === undefined) setInternalOpen(next);
704
- onOpenChange?.(next);
705
- },
706
- [controlledOpen, onOpenChange],
707
- );
708
-
709
- const handleSelect = useCallback(
710
- (key: string, item: DropdownItem) => {
711
- if (multiSelect && controlledSelectedKeys === undefined) {
712
- setInternalSelectedKeys((prev) =>
713
- prev.includes(key) ? prev.filter((k) => k !== key) : [...prev, key],
714
- );
715
- }
716
- onSelect?.(key, item);
717
- if (shouldCloseOnSelect) {
718
- setOpen(false);
719
- }
720
- },
721
- [multiSelect, controlledSelectedKeys, onSelect, shouldCloseOnSelect, setOpen],
722
- );
723
-
724
- const handleClose = useCallback(() => setOpen(false), [setOpen]);
725
-
726
- // Calculate position when opening
727
- useEffect(() => {
728
- if (isOpen && triggerRef.current) {
729
- const pos = calcPosition(triggerRef.current, menuRef.current, placement, offset);
730
- setMenuPosition(pos);
731
- }
732
- }, [isOpen, placement, offset]);
733
-
734
- // Recalculate after menu mounts (to get actual dimensions)
735
- useEffect(() => {
736
- if (isOpen && triggerRef.current && menuRef.current) {
737
- const pos = calcPosition(triggerRef.current, menuRef.current, placement, offset);
738
- setMenuPosition(pos);
739
- }
740
- }, [isOpen, placement, offset]);
741
-
742
- // Outside click to close
743
- useEffect(() => {
744
- if (!isOpen) return;
745
- const handler = (e: MouseEvent) => {
746
- const target = e.target as Node;
747
- if (
748
- triggerRef.current &&
749
- !triggerRef.current.contains(target) &&
750
- menuRef.current &&
751
- !menuRef.current.contains(target)
752
- ) {
753
- setOpen(false);
754
- }
755
- };
756
- document.addEventListener('mousedown', handler);
757
- return () => document.removeEventListener('mousedown', handler);
758
- }, [isOpen, setOpen]);
759
-
760
- const toggleOpen = () => {
761
- if (!disabled) setOpen(!isOpen);
762
- };
763
-
764
- const menuContent = isOpen ? (
765
- <DropdownMenu
766
- groups={resolvedGroups}
767
- position={menuPosition}
768
- maxHeight={maxHeight}
769
- minWidth={minWidth}
770
- selectedKeys={selectedKeys}
771
- multiSelect={multiSelect}
772
- searchable={searchable}
773
- searchPlaceholder={searchPlaceholder}
774
- onSelect={handleSelect}
775
- onClose={handleClose}
776
- renderItem={renderItem}
777
- menuRef={menuRef as React.RefObject<HTMLDivElement | null>}
778
- isPortal={portal}
779
- menuId={menuId}
780
- />
781
- ) : null;
782
-
783
- return (
784
- <div style={{ display: 'inline-block', position: 'relative' }}>
785
- <div
786
- ref={triggerRef}
787
- onClick={toggleOpen}
788
- aria-haspopup="menu"
789
- aria-expanded={isOpen}
790
- aria-controls={isOpen ? menuId : undefined}
791
- aria-disabled={disabled}
792
- style={{ cursor: disabled ? 'not-allowed' : 'pointer', opacity: disabled ? 0.5 : 1, display: 'inline-block' }}
793
- >
794
- {trigger}
795
- </div>
796
-
797
- {portal && typeof document !== 'undefined'
798
- ? createPortal(menuContent, document.body)
799
- : menuContent}
800
- </div>
801
- );
802
- }
803
-
804
- export default TkxDropdown;