@12-apps/ui 1.0.0 → 1.3.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 (448) hide show
  1. package/components-catalog.md +14 -0
  2. package/package.json +42 -27
  3. package/src/__tests__/data-grid.test.tsx +125 -0
  4. package/src/__tests__/package-wiring.test.ts +12 -8
  5. package/src/__tests__/social-login-button.test.tsx +5 -5
  6. package/src/__tests__/viewport.test.ts +50 -0
  7. package/src/charts/index.ts +8 -0
  8. package/src/components/data-display/Alert/Alert.md +1 -1
  9. package/src/components/data-display/Alert/Alert.stories.tsx +5 -7
  10. package/src/components/data-display/Alert/Alert.styles.tsx +255 -0
  11. package/src/components/data-display/Alert/Alert.test.stories.tsx +11 -13
  12. package/src/components/data-display/Alert/Alert.tsx +135 -328
  13. package/src/components/data-display/AlertDialog/AlertDialog.stories.tsx +3 -1
  14. package/src/components/data-display/AlertDialog/AlertDialog.tsx +191 -78
  15. package/src/components/data-display/AlertDialog/AlertDialog.types.ts +8 -1
  16. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.test.stories.tsx +5 -5
  17. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.tsx +44 -35
  18. package/src/components/data-display/Avatar/Avatar.stories.tsx +4 -1
  19. package/src/components/data-display/Avatar/Avatar.test.stories.tsx +5 -3
  20. package/src/components/data-display/Avatar/Avatar.tsx +154 -450
  21. package/src/components/data-display/Avatar/Avatar.view.tsx +396 -0
  22. package/src/components/data-display/Badge/Badge.animations.ts +67 -0
  23. package/src/components/data-display/Badge/Badge.helpers.ts +74 -0
  24. package/src/components/data-display/Badge/Badge.stories.tsx +14 -16
  25. package/src/components/data-display/Badge/Badge.styles.ts +261 -0
  26. package/src/components/data-display/Badge/Badge.test.stories.tsx +32 -31
  27. package/src/components/data-display/Badge/Badge.tsx +151 -557
  28. package/src/components/data-display/Badge/Badge.variants.ts +106 -0
  29. package/src/components/data-display/Badge/BadgeContent.tsx +107 -0
  30. package/src/components/data-display/Banner/Banner.stories.tsx +5 -1
  31. package/src/components/data-display/Banner/Banner.styles.ts +120 -0
  32. package/src/components/data-display/Banner/Banner.tsx +179 -224
  33. package/src/components/data-display/Chart/Chart.md +48 -1
  34. package/src/components/data-display/Chart/Chart.tsx +82 -500
  35. package/src/components/data-display/Chart/Chart.types.ts +2 -0
  36. package/src/components/data-display/Chart/ChartComposables.tsx +121 -0
  37. package/src/components/data-display/Chart/ChartSpec.types.ts +70 -0
  38. package/src/components/data-display/Chart/SpecChart.stories.tsx +150 -0
  39. package/src/components/data-display/Chart/SpecChart.test.stories.tsx +56 -0
  40. package/src/components/data-display/Chart/SpecChart.tsx +53 -0
  41. package/src/components/data-display/Chart/__tests__/SpecChart.test.tsx +60 -0
  42. package/src/components/data-display/Chart/__tests__/chart-format.test.ts +43 -0
  43. package/src/components/data-display/Chart/__tests__/chart-spec.test.ts +119 -0
  44. package/src/components/data-display/Chart/chart-format.ts +26 -0
  45. package/src/components/data-display/Chart/chart-internals.ts +148 -0
  46. package/src/components/data-display/Chart/chart-renderers.tsx +338 -0
  47. package/src/components/data-display/Chart/chart-spec-registry.ts +74 -0
  48. package/src/components/data-display/Chart/chart-spec.ts +171 -0
  49. package/src/components/data-display/Chart/index.ts +30 -0
  50. package/src/components/data-display/Chip/Chip.helpers.tsx +131 -0
  51. package/src/components/data-display/Chip/Chip.stories.tsx +2 -1
  52. package/src/components/data-display/Chip/Chip.test.stories.tsx +11 -8
  53. package/src/components/data-display/Chip/Chip.tsx +31 -94
  54. package/src/components/data-display/DataGrid/DataGrid.body.tsx +141 -0
  55. package/src/components/data-display/DataGrid/DataGrid.cells.tsx +238 -0
  56. package/src/components/data-display/DataGrid/DataGrid.model.ts +315 -0
  57. package/src/components/data-display/DataGrid/DataGrid.rows.ts +112 -0
  58. package/src/components/data-display/DataGrid/DataGrid.states.tsx +102 -0
  59. package/src/components/data-display/DataGrid/DataGrid.test.stories.tsx +6 -12
  60. package/src/components/data-display/DataGrid/DataGrid.tsx +129 -725
  61. package/src/components/data-display/DataViews/DataViewsGrid.tsx +187 -0
  62. package/src/components/data-display/DataViews/DataViewsTableBase.tsx +400 -0
  63. package/src/components/data-display/DataViews/ManageViewsDialog.tsx +140 -0
  64. package/src/components/data-display/DataViews/SaveViewModal.tsx +289 -0
  65. package/src/components/data-display/DataViews/__tests__/DataViewsGrid.test.tsx +271 -0
  66. package/src/components/data-display/DataViews/__tests__/DataViewsTableBase.test.tsx +134 -0
  67. package/src/components/data-display/DataViews/__tests__/SaveViewModal.test.tsx +83 -0
  68. package/src/components/data-display/DataViews/__tests__/data-views-filter.test.ts +115 -0
  69. package/src/components/data-display/DataViews/__tests__/data-views-preview.test.ts +53 -0
  70. package/src/components/data-display/DataViews/__tests__/range-pill.test.tsx +114 -0
  71. package/src/components/data-display/DataViews/base-card.stories.tsx +136 -0
  72. package/src/components/data-display/DataViews/base-card.tsx +278 -0
  73. package/src/components/data-display/DataViews/data-views-filter-panel.tsx +184 -0
  74. package/src/components/data-display/DataViews/data-views-filter.ts +138 -0
  75. package/src/components/data-display/DataViews/data-views-grid-helpers.tsx +248 -0
  76. package/src/components/data-display/DataViews/data-views-grid-parts.tsx +400 -0
  77. package/src/components/data-display/DataViews/data-views-inline-bar.tsx +257 -0
  78. package/src/components/data-display/DataViews/data-views-layout-context.tsx +176 -0
  79. package/src/components/data-display/DataViews/data-views-pagination.tsx +31 -0
  80. package/src/components/data-display/DataViews/data-views-preview.ts +53 -0
  81. package/src/components/data-display/DataViews/data-views-range-pill.tsx +277 -0
  82. package/src/components/data-display/DataViews/data-views-table-parts.tsx +150 -0
  83. package/src/components/data-display/DataViews/data-views-toolbar.tsx +149 -0
  84. package/src/components/data-display/DataViews/data-views-types.ts +312 -0
  85. package/src/components/data-display/DataViews/data-views-view-mutations.ts +68 -0
  86. package/src/components/data-display/DataViews/index.ts +33 -0
  87. package/src/components/data-display/DataViews/use-data-views-state.ts +349 -0
  88. package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.hooks.ts +104 -0
  89. package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.tsx +68 -118
  90. package/src/components/data-display/DescriptionItem/DescriptionItem.stories.tsx +1 -1
  91. package/src/components/data-display/DescriptionItem/DescriptionItem.tsx +52 -34
  92. package/src/components/data-display/EmptyState/EmptyState.test.stories.tsx +6 -6
  93. package/src/components/data-display/EmptyState/EmptyState.tsx +218 -135
  94. package/src/components/data-display/ErrorState/ErrorState.test.stories.tsx +2 -2
  95. package/src/components/data-display/ErrorState/ErrorState.tsx +83 -55
  96. package/src/components/data-display/HoverCard/HoverCard.stories.tsx +3 -1
  97. package/src/components/data-display/HoverCard/HoverCard.test.stories.tsx +5 -5
  98. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.hooks.ts +99 -0
  99. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.styles.ts +87 -0
  100. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.tsx +28 -155
  101. package/src/components/data-display/LazyImage/LazyImage.hooks.ts +203 -0
  102. package/src/components/data-display/LazyImage/LazyImage.md +1 -1
  103. package/src/components/data-display/LazyImage/LazyImage.stories.tsx +3 -3
  104. package/src/components/data-display/LazyImage/LazyImage.tsx +144 -243
  105. package/src/components/data-display/Lightbox/Lightbox.constants.ts +53 -0
  106. package/src/components/data-display/Lightbox/Lightbox.helpers.ts +39 -0
  107. package/src/components/data-display/Lightbox/Lightbox.hooks.ts +259 -0
  108. package/src/components/data-display/Lightbox/Lightbox.test.stories.tsx +28 -35
  109. package/src/components/data-display/Lightbox/Lightbox.tsx +98 -658
  110. package/src/components/data-display/Lightbox/LightboxControls.tsx +152 -0
  111. package/src/components/data-display/Lightbox/LightboxCurrentMedia.tsx +50 -0
  112. package/src/components/data-display/Lightbox/LightboxMedia.tsx +76 -0
  113. package/src/components/data-display/Lightbox/LightboxOverlay.tsx +83 -0
  114. package/src/components/data-display/Lightbox/LightboxStage.tsx +97 -0
  115. package/src/components/data-display/Lightbox/LightboxThumbnails.tsx +83 -0
  116. package/src/components/data-display/Lightbox/useLightbox.ts +80 -0
  117. package/src/components/data-display/LoadingState/LoadingState.helpers.ts +52 -0
  118. package/src/components/data-display/LoadingState/LoadingState.tsx +117 -87
  119. package/src/components/data-display/MapPreview/MapControlBar.tsx +116 -0
  120. package/src/components/data-display/MapPreview/MapDecorations.tsx +155 -0
  121. package/src/components/data-display/MapPreview/MapLayers.tsx +70 -0
  122. package/src/components/data-display/MapPreview/MapMarkers.tsx +84 -0
  123. package/src/components/data-display/MapPreview/MapOverlays.tsx +68 -0
  124. package/src/components/data-display/MapPreview/MapPreview.constants.ts +19 -0
  125. package/src/components/data-display/MapPreview/MapPreview.helpers.ts +63 -0
  126. package/src/components/data-display/MapPreview/MapPreview.hooks.ts +265 -0
  127. package/src/components/data-display/MapPreview/MapPreview.test.stories.tsx +14 -10
  128. package/src/components/data-display/MapPreview/MapPreview.tsx +52 -882
  129. package/src/components/data-display/MapPreview/MapPreview.types.ts +8 -1
  130. package/src/components/data-display/MapPreview/MapSearchBar.tsx +64 -0
  131. package/src/components/data-display/MapPreview/MapTiles.tsx +70 -0
  132. package/src/components/data-display/MapPreview/StaticMapView.tsx +63 -0
  133. package/src/components/data-display/MapPreview/mapProjection.ts +52 -0
  134. package/src/components/data-display/MapPreview/mapSurface.ts +37 -0
  135. package/src/components/data-display/MapPreview/useMapPreview.ts +62 -0
  136. package/src/components/data-display/Popover/Popover.test.stories.tsx +13 -19
  137. package/src/components/data-display/Progress/Progress.helpers.ts +37 -0
  138. package/src/components/data-display/Progress/Progress.styles.ts +101 -0
  139. package/src/components/data-display/Progress/Progress.tsx +185 -213
  140. package/src/components/data-display/SectionOnboarding/SectionOnboarding.stories.tsx +1 -1
  141. package/src/components/data-display/SectionOnboarding/SectionOnboarding.tsx +1 -1
  142. package/src/components/data-display/StatCard/StatCard.md +117 -0
  143. package/src/components/data-display/StatCard/StatCard.stories.tsx +167 -0
  144. package/src/components/data-display/StatCard/StatCard.test.stories.tsx +240 -0
  145. package/src/components/data-display/StatCard/StatCard.tsx +236 -0
  146. package/src/components/data-display/StatCard/StatCard.types.ts +62 -0
  147. package/src/components/data-display/StatCard/index.ts +7 -0
  148. package/src/components/data-display/Stepper/Stepper.test.stories.tsx +12 -19
  149. package/src/components/data-display/Stepper/Stepper.tsx +1 -1
  150. package/src/components/data-display/Table/Table.helpers.ts +31 -0
  151. package/src/components/data-display/Table/Table.hooks.ts +161 -0
  152. package/src/components/data-display/Table/Table.stories.tsx +3 -1
  153. package/src/components/data-display/Table/Table.styles.ts +223 -0
  154. package/src/components/data-display/Table/Table.test.stories.tsx +4 -4
  155. package/src/components/data-display/Table/Table.tsx +291 -748
  156. package/src/components/data-display/Table/TableParts.hooks.tsx +112 -0
  157. package/src/components/data-display/Table/TableParts.tsx +298 -0
  158. package/src/components/data-display/Table/TableStates.tsx +21 -0
  159. package/src/components/data-display/Timeline/Timeline.stories.tsx +10 -12
  160. package/src/components/data-display/Timeline/Timeline.test.stories.tsx +30 -44
  161. package/src/components/data-display/Timeline/Timeline.tsx +23 -284
  162. package/src/components/data-display/Timeline/TimelineRow.tsx +346 -0
  163. package/src/components/data-display/TimingDiagram/TimingDiagram.tsx +38 -311
  164. package/src/components/data-display/TimingDiagram/TimingDiagram.views.tsx +346 -0
  165. package/src/components/data-display/Tooltip/Tooltip.stories.tsx +4 -1
  166. package/src/components/data-display/Tooltip/Tooltip.test.stories.tsx +44 -58
  167. package/src/components/data-display/Tooltip/Tooltip.tsx +67 -62
  168. package/src/components/data-display/index.ts +1 -0
  169. package/src/components/feedback/ConfirmAction/ConfirmAction.hooks.ts +96 -0
  170. package/src/components/feedback/ConfirmAction/ConfirmAction.md +140 -0
  171. package/src/components/feedback/ConfirmAction/ConfirmAction.parts.tsx +154 -0
  172. package/src/components/feedback/ConfirmAction/ConfirmAction.stories.tsx +146 -0
  173. package/src/components/feedback/ConfirmAction/ConfirmAction.test.stories.tsx +114 -0
  174. package/src/components/feedback/ConfirmAction/ConfirmAction.tsx +46 -0
  175. package/src/components/feedback/ConfirmAction/ConfirmAction.types.ts +111 -0
  176. package/src/components/feedback/ConfirmAction/ConfirmButton.tsx +18 -0
  177. package/src/components/feedback/ConfirmAction/__tests__/confirm-action.test.tsx +288 -0
  178. package/src/components/feedback/ConfirmAction/index.ts +16 -0
  179. package/src/components/feedback/ConfirmAction/with-confirmation.tsx +112 -0
  180. package/src/components/feedback/Dialog/Dialog.styles.ts +4 -2
  181. package/src/components/feedback/Dialog/Dialog.tsx +26 -1
  182. package/src/components/feedback/Dialog/__tests__/dialog-content-spacing.test.tsx +66 -0
  183. package/src/components/feedback/Modal/Modal.md +1 -1
  184. package/src/components/feedback/Modal/Modal.stories.tsx +2 -2
  185. package/src/components/feedback/Sonner/Sonner.tsx +104 -288
  186. package/src/components/feedback/Sonner/Sonner.types.ts +7 -0
  187. package/src/components/feedback/Sonner/SonnerToast.tsx +216 -0
  188. package/src/components/feedback/StackedModal/StackedModal.hooks.ts +226 -0
  189. package/src/components/feedback/StackedModal/StackedModal.parts.tsx +311 -0
  190. package/src/components/feedback/StackedModal/StackedModal.stories.tsx +13 -15
  191. package/src/components/feedback/StackedModal/StackedModal.styles.ts +193 -0
  192. package/src/components/feedback/StackedModal/StackedModal.tsx +100 -619
  193. package/src/components/feedback/StackedModal/StackedModal.types.ts +17 -3
  194. package/src/components/feedback/StackedModal/__tests__/stacked-modal-viewport.test.tsx +104 -0
  195. package/src/components/feedback/StackedModal/modal-stack.tsx +119 -0
  196. package/src/components/feedback/Toast/Toast.tsx +92 -81
  197. package/src/components/feedback/TutorialOverlay/TutorialOverlay.geometry.ts +65 -0
  198. package/src/components/feedback/TutorialOverlay/TutorialOverlay.hooks.ts +185 -0
  199. package/src/components/feedback/TutorialOverlay/TutorialOverlay.test.stories.tsx +2 -2
  200. package/src/components/feedback/TutorialOverlay/TutorialOverlay.tsx +156 -414
  201. package/src/components/feedback/TutorialOverlay/TutorialStepBody.tsx +255 -0
  202. package/src/components/feedback/index.ts +1 -0
  203. package/src/components/form/AddressAutocomplete/AddressAutocomplete.helpers.ts +58 -0
  204. package/src/components/form/AddressAutocomplete/AddressAutocomplete.hooks.ts +93 -0
  205. package/src/components/form/AddressAutocomplete/AddressAutocomplete.mapper.ts +57 -0
  206. package/src/components/form/AddressAutocomplete/AddressAutocomplete.stories.tsx +4 -2
  207. package/src/components/form/AddressAutocomplete/AddressAutocomplete.test.stories.tsx +20 -16
  208. package/src/components/form/AddressAutocomplete/AddressAutocomplete.tsx +26 -829
  209. package/src/components/form/AddressAutocomplete/AddressAutocomplete.types.ts +11 -0
  210. package/src/components/form/AddressAutocomplete/AddressAutocompleteField.tsx +86 -0
  211. package/src/components/form/AddressAutocomplete/AddressFallbackField.tsx +64 -0
  212. package/src/components/form/AddressAutocomplete/AddressInputField.tsx +80 -0
  213. package/src/components/form/AddressAutocomplete/AddressOption.tsx +83 -0
  214. package/src/components/form/AddressAutocomplete/AddressSuggestionsPaper.tsx +24 -0
  215. package/src/components/form/AddressAutocomplete/AddressTextField.tsx +43 -0
  216. package/src/components/form/AddressAutocomplete/mockPlaces.ts +208 -0
  217. package/src/components/form/AddressAutocomplete/useAddressPredictions.ts +136 -0
  218. package/src/components/form/AddressAutocomplete/useAddressSelection.ts +113 -0
  219. package/src/components/form/AddressAutocomplete/useCurrentLocation.ts +116 -0
  220. package/src/components/form/AddressAutocomplete/useGoogleMapsAPI.ts +75 -0
  221. package/src/components/form/Button/Button.helpers.ts +36 -0
  222. package/src/components/form/Button/Button.stories.tsx +4 -1
  223. package/src/components/form/Button/Button.styles.ts +225 -0
  224. package/src/components/form/Button/Button.test.stories.tsx +25 -21
  225. package/src/components/form/Button/Button.tsx +45 -252
  226. package/src/components/form/Calendar/Calendar.dates.ts +100 -0
  227. package/src/components/form/Calendar/Calendar.helpers.ts +32 -0
  228. package/src/components/form/Calendar/Calendar.hooks.ts +278 -0
  229. package/src/components/form/Calendar/Calendar.keyboard.ts +32 -0
  230. package/src/components/form/Calendar/Calendar.selection.ts +156 -0
  231. package/src/components/form/Calendar/Calendar.test.stories.tsx +33 -34
  232. package/src/components/form/Calendar/Calendar.tsx +63 -551
  233. package/src/components/form/Calendar/Calendar.types.ts +16 -0
  234. package/src/components/form/Calendar/CalendarDay.tsx +127 -0
  235. package/src/components/form/Calendar/CalendarDayCell.tsx +52 -0
  236. package/src/components/form/Calendar/CalendarMonth.tsx +128 -0
  237. package/src/components/form/CepField/CepField.md +138 -0
  238. package/src/components/form/CepField/CepField.stories.tsx +138 -0
  239. package/src/components/form/CepField/CepField.test.stories.tsx +281 -0
  240. package/src/components/form/CepField/CepField.tsx +211 -0
  241. package/src/components/form/CepField/CepField.types.ts +73 -0
  242. package/src/components/form/CepField/index.ts +2 -0
  243. package/src/components/form/Checkbox/Checkbox.helpers.ts +28 -0
  244. package/src/components/form/Checkbox/Checkbox.tsx +19 -16
  245. package/src/components/form/CodeEditor/CodeEditor.helpers.ts +45 -0
  246. package/src/components/form/CodeEditor/CodeEditor.hooks.ts +104 -0
  247. package/src/components/form/CodeEditor/CodeEditor.monaco.ts +109 -0
  248. package/src/components/form/CodeEditor/CodeEditor.test.stories.tsx +17 -18
  249. package/src/components/form/CodeEditor/CodeEditor.tsx +81 -330
  250. package/src/components/form/CodeEditor/CodeEditorToolbar.tsx +168 -0
  251. package/src/components/form/Command/Command.hooks.ts +207 -0
  252. package/src/components/form/Command/Command.parts.tsx +58 -0
  253. package/src/components/form/Command/Command.styles.ts +83 -0
  254. package/src/components/form/Command/Command.tsx +61 -270
  255. package/src/components/form/CreatableSelect/CreatableSelect.md +1 -1
  256. package/src/components/form/CreatableSelect/CreatableSelect.test.stories.tsx +1 -1
  257. package/src/components/form/CreatableSelect/CreatableSelect.tsx +152 -71
  258. package/src/components/form/CreatableSelect/CreatableSelect.types.ts +13 -0
  259. package/src/components/form/HeaderButton/HeaderButton.tsx +80 -0
  260. package/src/components/form/HeaderButton/index.ts +2 -0
  261. package/src/components/form/Input/Input.stories.tsx +5 -1
  262. package/src/components/form/Input/Input.styles.ts +176 -0
  263. package/src/components/form/Input/Input.test.stories.tsx +30 -23
  264. package/src/components/form/Input/Input.tsx +71 -211
  265. package/src/components/form/Input/Input.types.ts +11 -0
  266. package/src/components/form/InputOTP/InputOTP.test.stories.tsx +9 -17
  267. package/src/components/form/Menubar/Menubar.test.stories.tsx +4 -8
  268. package/src/components/form/PasswordStrength/PasswordStrength.helpers.tsx +117 -0
  269. package/src/components/form/PasswordStrength/PasswordStrength.test.stories.tsx +3 -3
  270. package/src/components/form/PasswordStrength/PasswordStrength.tsx +202 -255
  271. package/src/components/form/PhoneInput/PhoneInput.hooks.ts +134 -0
  272. package/src/components/form/PhoneInput/PhoneInput.test.stories.tsx +4 -4
  273. package/src/components/form/PhoneInput/PhoneInput.tsx +279 -292
  274. package/src/components/form/PhoneInput/countries.ts +54 -0
  275. package/src/components/form/PhoneInput/phone.ts +47 -0
  276. package/src/components/form/RadioGroup/RadioGroup.test.stories.tsx +9 -9
  277. package/src/components/form/RichTextEditor/RichTextEditor.dom.ts +124 -0
  278. package/src/components/form/RichTextEditor/RichTextEditor.format.ts +61 -0
  279. package/src/components/form/RichTextEditor/RichTextEditor.hooks.ts +142 -0
  280. package/src/components/form/RichTextEditor/RichTextEditor.test.stories.tsx +5 -12
  281. package/src/components/form/RichTextEditor/RichTextEditor.tsx +98 -410
  282. package/src/components/form/RichTextEditor/RichTextEditorToolbar.tsx +187 -0
  283. package/src/components/form/SearchPalette/SearchPalette.parts.tsx +22 -0
  284. package/src/components/form/SearchPalette/SearchPalette.tsx +13 -9
  285. package/src/components/form/Select/Select.test.stories.tsx +35 -27
  286. package/src/components/form/Slider/Slider.test.stories.tsx +9 -11
  287. package/src/components/form/Switch/Switch.md +2 -1
  288. package/src/components/form/Switch/Switch.test.stories.tsx +6 -6
  289. package/src/components/form/Textarea/Textarea.styles.ts +143 -0
  290. package/src/components/form/Textarea/Textarea.test.stories.tsx +20 -26
  291. package/src/components/form/Textarea/Textarea.tsx +114 -535
  292. package/src/components/form/Textarea/TextareaRichEditor.tsx +377 -0
  293. package/src/components/form/Toggle/Toggle.styles.ts +211 -0
  294. package/src/components/form/Toggle/Toggle.test.stories.tsx +19 -27
  295. package/src/components/form/Toggle/Toggle.tsx +10 -185
  296. package/src/components/form/UploadButton/UploadButton.hooks.ts +323 -0
  297. package/src/components/form/UploadButton/UploadButton.parts.tsx +210 -0
  298. package/src/components/form/UploadButton/UploadButton.stories.tsx +2 -1
  299. package/src/components/form/UploadButton/UploadButton.test.stories.tsx +123 -4
  300. package/src/components/form/UploadButton/UploadButton.tsx +76 -305
  301. package/src/components/form/UploadButton/UploadButton.types.ts +16 -0
  302. package/src/components/form/index.ts +1 -0
  303. package/src/components/form/total-form/Fields/CepField.tsx +143 -0
  304. package/src/components/form/total-form/Fields/ToggleField.tsx +61 -0
  305. package/src/components/form/total-form/Fields/index.ts +4 -0
  306. package/src/components/form/total-form/FormContainer.tsx +3 -3
  307. package/src/components/form/total-form/SubmitButton.tsx +25 -2
  308. package/src/components/form/total-form/total-form.test.tsx +118 -1
  309. package/src/components/layout/Accordion/Accordion.md +1 -1
  310. package/src/components/layout/Accordion/Accordion.stories.tsx +5 -1
  311. package/src/components/layout/Accordion/Accordion.styles.ts +80 -0
  312. package/src/components/layout/Accordion/Accordion.test.stories.tsx +32 -50
  313. package/src/components/layout/Accordion/Accordion.tsx +2 -75
  314. package/src/components/layout/Card/Card.helpers.ts +30 -0
  315. package/src/components/layout/Card/Card.stories.tsx +9 -11
  316. package/src/components/layout/Card/Card.styles.ts +182 -0
  317. package/src/components/layout/Card/Card.test.stories.tsx +46 -46
  318. package/src/components/layout/Card/Card.tsx +24 -241
  319. package/src/components/layout/CardGrid/CardGrid.md +96 -0
  320. package/src/components/layout/CardGrid/CardGrid.tsx +140 -0
  321. package/src/components/layout/CardGrid/__tests__/CardGrid.test.tsx +92 -0
  322. package/src/components/layout/CardGrid/index.ts +2 -0
  323. package/src/components/layout/Collapsible/Collapsible.helpers.ts +83 -0
  324. package/src/components/layout/Collapsible/Collapsible.test.stories.tsx +7 -3
  325. package/src/components/layout/Collapsible/Collapsible.tsx +111 -107
  326. package/src/components/layout/Container/Container.test.stories.tsx +11 -16
  327. package/src/components/layout/ContentToolbar/ColumnsMenu.tsx +1 -1
  328. package/src/components/layout/ContentToolbar/ContentToolbar.tsx +120 -44
  329. package/src/components/layout/ContentToolbar/ContentToolbar.types.ts +9 -0
  330. package/src/components/layout/ContentToolbar/FilterTrigger.tsx +1 -1
  331. package/src/components/layout/ContentToolbar/MultiSelectDropdown.tsx +58 -43
  332. package/src/components/layout/ContentToolbar/MultiSelectTriggers.tsx +139 -0
  333. package/src/components/layout/ContentToolbar/SavedViewsMenu.tsx +10 -3
  334. package/src/components/layout/ContentToolbar/SortByDropdown.tsx +35 -11
  335. package/src/components/layout/ContentToolbar/ViewSelector.tsx +5 -6
  336. package/src/components/layout/ContentToolbar/__tests__/MultiSelectDropdown.test.tsx +21 -0
  337. package/src/components/layout/Dashboard/Dashboard.test.stories.tsx +27 -1
  338. package/src/components/layout/Dashboard/Dashboard.tsx +27 -8
  339. package/src/components/layout/Dashboard/DashboardParts.tsx +12 -19
  340. package/src/components/layout/Dashboard/index.ts +2 -1
  341. package/src/components/layout/Drawer/Drawer.stories.tsx +8 -10
  342. package/src/components/layout/Drawer/Drawer.test.stories.tsx +18 -14
  343. package/src/components/layout/Drawer/Drawer.tsx +67 -53
  344. package/src/components/layout/Resizable/Resizable.helpers.ts +133 -0
  345. package/src/components/layout/Resizable/Resizable.hooks.ts +68 -0
  346. package/src/components/layout/Resizable/Resizable.tsx +38 -153
  347. package/src/components/layout/ScrollArea/ScrollArea.helpers.ts +51 -0
  348. package/src/components/layout/ScrollArea/ScrollArea.styles.ts +248 -0
  349. package/src/components/layout/ScrollArea/ScrollArea.tsx +183 -374
  350. package/src/components/layout/ScrollArea/ScrollAreaContent.tsx +70 -0
  351. package/src/components/layout/ScrollArea/ScrollViewport.tsx +90 -0
  352. package/src/components/layout/Separator/Separator.styles.ts +128 -0
  353. package/src/components/layout/Separator/Separator.test.stories.tsx +3 -12
  354. package/src/components/layout/Separator/Separator.tsx +6 -132
  355. package/src/components/layout/SettingsLayout/SettingsLayout.parts.tsx +2 -1
  356. package/src/components/layout/SettingsLayout/SettingsLayout.stories.tsx +6 -8
  357. package/src/components/layout/Sidebar/Sidebar.stories.tsx +10 -12
  358. package/src/components/layout/Sidebar/Sidebar.test.stories.tsx +35 -37
  359. package/src/components/layout/Skeleton/Skeleton.helpers.ts +33 -0
  360. package/src/components/layout/Skeleton/Skeleton.styles.ts +114 -0
  361. package/src/components/layout/Skeleton/Skeleton.test.stories.tsx +3 -3
  362. package/src/components/layout/Skeleton/Skeleton.tsx +67 -155
  363. package/src/components/layout/TableFilter/TableFilter.tsx +2 -1
  364. package/src/components/navigation/Breadcrumbs/BreadcrumbEntry.tsx +305 -0
  365. package/src/components/navigation/Breadcrumbs/Breadcrumbs.md +2 -1
  366. package/src/components/navigation/Breadcrumbs/Breadcrumbs.stories.tsx +12 -14
  367. package/src/components/navigation/Breadcrumbs/Breadcrumbs.styles.tsx +212 -0
  368. package/src/components/navigation/Breadcrumbs/Breadcrumbs.test.stories.tsx +62 -61
  369. package/src/components/navigation/Breadcrumbs/Breadcrumbs.tsx +116 -429
  370. package/src/components/navigation/CommandPalette/CommandPalette.helpers.ts +82 -0
  371. package/src/components/navigation/CommandPalette/CommandPalette.hooks.ts +202 -0
  372. package/src/components/navigation/CommandPalette/CommandPalette.stories.tsx +3 -1
  373. package/src/components/navigation/CommandPalette/CommandPalette.test.stories.tsx +3 -5
  374. package/src/components/navigation/CommandPalette/CommandPalette.tsx +108 -341
  375. package/src/components/navigation/CommandPalette/CommandPaletteResults.tsx +182 -0
  376. package/src/components/navigation/CommandPalette/ShortcutChip.tsx +18 -0
  377. package/src/components/navigation/ContextMenu/ContextMenu.md +3 -1
  378. package/src/components/navigation/ContextMenu/ContextMenu.stories.tsx +4 -1
  379. package/src/components/navigation/ContextMenu/ContextMenu.test.stories.tsx +19 -24
  380. package/src/components/navigation/ContextMenu/ContextMenu.tsx +70 -54
  381. package/src/components/navigation/DropdownMenu/DropdownMenu.md +3 -1
  382. package/src/components/navigation/DropdownMenu/DropdownMenu.stories.tsx +17 -19
  383. package/src/components/navigation/DropdownMenu/DropdownMenu.test.stories.tsx +26 -26
  384. package/src/components/navigation/DropdownMenu/DropdownMenu.tsx +189 -111
  385. package/src/components/navigation/NavigationMenu/NavigationMegaSection.tsx +66 -0
  386. package/src/components/navigation/NavigationMenu/NavigationMenu.md +7 -2
  387. package/src/components/navigation/NavigationMenu/NavigationMenu.shell.tsx +218 -0
  388. package/src/components/navigation/NavigationMenu/NavigationMenu.styles.ts +223 -0
  389. package/src/components/navigation/NavigationMenu/NavigationMenu.tsx +119 -808
  390. package/src/components/navigation/NavigationMenu/NavigationMenuItem.hooks.ts +126 -0
  391. package/src/components/navigation/NavigationMenu/NavigationMenuItem.tsx +352 -0
  392. package/src/components/navigation/NavigationMenu/NavigationStandardBody.tsx +148 -0
  393. package/src/components/navigation/NavigationMenu/stories/NavigationMenu.stories.tsx +15 -17
  394. package/src/components/navigation/NavigationMenu/stories/NavigationMenu.test.stories.tsx +27 -23
  395. package/src/components/navigation/NavigationMenu/stories/NavigationMenuHorizontal.stories.tsx +11 -13
  396. package/src/components/navigation/NavigationMenu/stories/NavigationMenuVertical.stories.tsx +9 -11
  397. package/src/components/navigation/Pagination/Pagination.helpers.tsx +85 -0
  398. package/src/components/navigation/Pagination/Pagination.md +2 -1
  399. package/src/components/navigation/Pagination/Pagination.stories.tsx +4 -6
  400. package/src/components/navigation/Pagination/Pagination.styles.ts +135 -0
  401. package/src/components/navigation/Pagination/Pagination.tsx +178 -313
  402. package/src/components/navigation/Pagination/PaginationParts.tsx +81 -0
  403. package/src/components/navigation/Tabs/Tabs.md +3 -1
  404. package/src/components/navigation/Tabs/Tabs.stories.tsx +21 -23
  405. package/src/components/navigation/Tabs/Tabs.styles.ts +163 -0
  406. package/src/components/navigation/Tabs/Tabs.test.stories.tsx +37 -37
  407. package/src/components/navigation/Tabs/Tabs.tsx +192 -361
  408. package/src/components/navigation/Tabs/TabsPanel.tsx +100 -0
  409. package/src/components/typography/Blockquote/Blockquote.tsx +1 -1
  410. package/src/components/typography/Code/Code.test.stories.tsx +5 -5
  411. package/src/components/typography/Code/Code.tsx +74 -49
  412. package/src/components/typography/Heading/Heading.test.stories.tsx +8 -8
  413. package/src/components/typography/Paragraph/Paragraph.test.stories.tsx +5 -12
  414. package/src/components/typography/Text/Text.tsx +84 -77
  415. package/src/components/utility/AnimatedIcon/AnimatedIcon.md +4 -4
  416. package/src/components/utility/AnimatedIcon/AnimatedIcon.stories.tsx +19 -21
  417. package/src/components/utility/AnimatedIcon/AnimatedIcon.test.stories.tsx +19 -12
  418. package/src/components/utility/AspectRatio/AspectRatio.test.stories.tsx +9 -9
  419. package/src/components/utility/InfiniteScroll/InfiniteScroll.hooks.ts +118 -0
  420. package/src/components/utility/InfiniteScroll/InfiniteScroll.parts.tsx +54 -0
  421. package/src/components/utility/InfiniteScroll/InfiniteScroll.test.stories.tsx +12 -9
  422. package/src/components/utility/InfiniteScroll/InfiniteScroll.tsx +29 -148
  423. package/src/components/utility/InstallPrompt/InstallPrompt.helpers.ts +124 -0
  424. package/src/components/utility/InstallPrompt/InstallPrompt.md +113 -0
  425. package/src/components/utility/InstallPrompt/InstallPrompt.stories.tsx +118 -0
  426. package/src/components/utility/InstallPrompt/InstallPrompt.styles.ts +50 -0
  427. package/src/components/utility/InstallPrompt/InstallPrompt.test.stories.tsx +83 -0
  428. package/src/components/utility/InstallPrompt/InstallPrompt.tsx +192 -0
  429. package/src/components/utility/InstallPrompt/InstallPrompt.types.ts +78 -0
  430. package/src/components/utility/InstallPrompt/__tests__/InstallPrompt.ios.test.tsx +65 -0
  431. package/src/components/utility/InstallPrompt/__tests__/usePwaInstall.test.tsx +271 -0
  432. package/src/components/utility/InstallPrompt/index.ts +10 -0
  433. package/src/components/utility/InstallPrompt/usePwaInstall.ts +171 -0
  434. package/src/components/utility/Transition/Transition.helpers.ts +40 -0
  435. package/src/components/utility/Transition/Transition.tsx +17 -68
  436. package/src/components/utility/VirtualList/VirtualList.hooks.ts +319 -0
  437. package/src/components/utility/VirtualList/VirtualList.test.stories.tsx +49 -38
  438. package/src/components/utility/VirtualList/VirtualList.tsx +110 -315
  439. package/src/components/utility/WorkflowStep/WorkflowStep.helpers.ts +151 -0
  440. package/src/components/utility/WorkflowStep/WorkflowStep.parts.tsx +371 -0
  441. package/src/components/utility/WorkflowStep/WorkflowStep.stories.tsx +9 -11
  442. package/src/components/utility/WorkflowStep/WorkflowStep.test.stories.tsx +7 -7
  443. package/src/components/utility/WorkflowStep/WorkflowStep.tsx +51 -449
  444. package/src/components/utility/WorkflowStep/WorkflowStepRow.tsx +96 -0
  445. package/src/components/utility/index.ts +1 -0
  446. package/src/mui/Link.ts +2 -0
  447. package/src/utils/index.ts +2 -1
  448. package/src/utils/viewport.ts +65 -0
@@ -1,13 +1,8 @@
1
- import {
2
- MoreVert as MoreVertIcon
3
- } from '@mui/icons-material';
1
+ import MoreVertIcon from '@mui/icons-material/MoreVert';
4
2
  import {
5
- alpha,
6
3
  Box,
7
- Checkbox,
8
4
  FormControlLabel,
9
5
  IconButton,
10
- keyframes,
11
6
  Menu,
12
7
  MenuItem,
13
8
  Skeleton,
@@ -16,93 +11,37 @@ import {
16
11
  TableBody,
17
12
  TableCell,
18
13
  TableContainer,
19
- TableHead,
20
- TableRow,
21
- TableSortLabel,
22
- useMediaQuery,
23
- useTheme} from '@mui/material';
14
+ TableRow
15
+ } from '@mui/material';
24
16
  import { styled } from '@mui/material/styles';
25
- import React, { useCallback,useEffect, useMemo, useState } from 'react';
17
+ import React from 'react';
26
18
 
27
19
  import type {
28
20
  ColumnConfig,
29
- TableBodyProps,
30
21
  TableDensity,
31
- TableHeaderProps,
32
22
  TableProps,
33
23
  TableStripeColor} from './Table.types';
24
+ import { TABLE_DEFAULTS, definedProps } from './Table.helpers';
25
+ import { useTableSelection } from './Table.hooks';
26
+ import { EnhancedTableBody, EnhancedTableHeader } from './TableParts';
27
+ import { EmptyRow, NoDataPlaceholder } from './TableStates';
28
+ import {
29
+ tableStyles } from './Table.styles';
34
30
 
35
31
  // Define pulse animation
36
- const pulseAnimation = keyframes`
37
- 0% {
38
- box-shadow: 0 0 0 0 currentColor;
39
- opacity: 1;
40
- }
41
- 70% {
42
- box-shadow: 0 0 0 10px currentColor;
43
- opacity: 0;
44
- }
45
- 100% {
46
- box-shadow: 0 0 0 0 currentColor;
47
- opacity: 0;
48
- }
49
- `;
50
-
51
- // Density configurations
52
- const getDensityConfig = (density: TableDensity = 'normal') => {
53
- const configs = {
54
- compact: {
55
- rowHeight: 36,
56
- cellPadding: '6px 12px',
57
- fontSize: '0.8125rem',
58
- headerPadding: '8px 12px',
59
- },
60
- normal: {
61
- rowHeight: 52,
62
- cellPadding: '12px 16px',
63
- fontSize: '0.875rem',
64
- headerPadding: '16px 16px',
65
- },
66
- comfortable: {
67
- rowHeight: 68,
68
- cellPadding: '18px 24px',
69
- fontSize: '0.875rem',
70
- headerPadding: '20px 24px',
71
- },
72
- };
73
- return configs[density];
74
- };
75
-
76
32
  const StyledTableContainer = styled(TableContainer, {
77
- shouldForwardProp: (prop) => !['virtualScrolling', 'containerHeight'].includes(prop as string),
78
- })<{
33
+ shouldForwardProp: (prop) => !['virtualScrolling', 'containerHeight'].includes(prop as string) })<{
79
34
  virtualScrolling?: boolean;
80
35
  containerHeight?: number | string;
81
36
  }>(({ virtualScrolling, containerHeight }) => ({
82
37
  ...(virtualScrolling && {
83
38
  height: containerHeight || 400,
84
- overflow: 'auto',
85
- }),
86
- }));
39
+ overflow: 'auto' }) }));
87
40
 
88
41
  // Helper function to get stripe color from theme
89
- const getStripeColorFromTheme = (theme: { palette: { primary: { main: string }; secondary: { main: string }; info: { main: string }; success: { main: string }; warning: { main: string }; error: { main: string }; action: { hover: string } } }, stripeColor: TableStripeColor = 'neutral') => {
90
- const colorMap: Record<TableStripeColor, string> = {
91
- primary: theme.palette.primary.main,
92
- secondary: theme.palette.secondary.main,
93
- info: theme.palette.info.main,
94
- success: theme.palette.success.main,
95
- warning: theme.palette.warning.main,
96
- error: theme.palette.error.main,
97
- neutral: theme.palette.action.hover,
98
- };
99
- return colorMap[stripeColor];
100
- };
101
-
102
42
  const StyledTable = styled(MuiTable, {
103
43
  shouldForwardProp: (prop) =>
104
- !['customVariant', 'glow', 'pulse', 'hoverable', 'density', 'stickyHeader', 'stripeColor'].includes(prop as string),
105
- })<{
44
+ !['customVariant', 'glow', 'pulse', 'hoverable', 'density', 'stickyHeader', 'stripeColor'].includes(prop as string) })<{
106
45
  customVariant?: string;
107
46
  glow?: boolean;
108
47
  pulse?: boolean;
@@ -111,721 +50,325 @@ const StyledTable = styled(MuiTable, {
111
50
  stickyHeader?: boolean;
112
51
  stripeColor?: TableStripeColor;
113
52
  }>(({ theme, customVariant, glow, pulse, hoverable, density, stickyHeader, stripeColor = 'neutral' }) => {
114
- const densityConfig = getDensityConfig(density);
115
-
116
- return {
117
- borderRadius: theme.spacing(1),
118
- overflow: 'hidden',
119
- transition: 'all 0.3s ease',
120
- position: 'relative',
121
-
122
- // Density styles
123
- '& .MuiTableCell-root': {
124
- padding: densityConfig.cellPadding,
125
- fontSize: densityConfig.fontSize,
126
- height: densityConfig.rowHeight,
127
- },
128
-
129
- // Sticky header
130
- ...(stickyHeader && {
131
- '& .MuiTableHead-root': {
132
- position: 'sticky',
133
- top: 0,
134
- zIndex: 100,
135
- backgroundColor: theme.palette.background.paper,
136
- '& .MuiTableCell-root': {
137
- borderBottom: `2px solid ${theme.palette.divider}`,
138
- fontWeight: 600,
139
- padding: densityConfig.headerPadding,
140
- },
141
- },
142
- }),
143
-
144
- // Variant styles
145
- ...(customVariant === 'default' && {
146
- backgroundColor: theme.palette.background.paper,
147
- '& .MuiTableHead-root': {
148
- backgroundColor: alpha(theme.palette.primary.main, 0.1),
149
- },
150
- }),
151
-
152
- ...(customVariant === 'striped' && {
153
- backgroundColor: theme.palette.background.paper,
154
- '& .MuiTableBody-root .MuiTableRow-root:nth-of-type(even)': {
155
- backgroundColor: alpha(getStripeColorFromTheme(theme, stripeColor), stripeColor === 'neutral' ? 0.5 : 0.15),
156
- },
157
- }),
158
-
159
- ...(customVariant === 'glass' && {
160
- backgroundColor: alpha(theme.palette.background.paper, 0.1),
161
- backdropFilter: 'blur(20px)',
162
- border: `1px solid ${alpha(theme.palette.divider, 0.2)}`,
163
- }),
164
-
165
- ...(customVariant === 'minimal' && {
166
- backgroundColor: 'transparent',
167
- '& .MuiTableCell-root': {
168
- borderBottom: `1px solid ${alpha(theme.palette.divider, 0.1)}`,
169
- },
170
- }),
171
-
172
- ...(customVariant === 'gradient' && {
173
- background: `linear-gradient(135deg, ${alpha(theme.palette.primary.main, 0.05)}, ${alpha(theme.palette.secondary.main, 0.05)})`,
174
- border: `1px solid ${alpha(theme.palette.divider, 0.2)}`,
175
- '& .MuiTableHead-root': {
176
- background: `linear-gradient(135deg, ${alpha(theme.palette.primary.main, 0.15)}, ${alpha(theme.palette.secondary.main, 0.15)})`,
177
- },
178
- '& .MuiTableCell-root': {
179
- borderBottom: `1px solid ${alpha(theme.palette.divider, 0.15)}`,
180
- },
181
- }),
182
-
183
- // Hoverable rows
184
- ...(hoverable && {
185
- '& .MuiTableBody-root .MuiTableRow-root:hover': {
186
- backgroundColor: alpha(theme.palette.primary.main, 0.08),
187
- cursor: 'pointer',
188
- transition: 'background-color 0.15s ease-in-out',
189
- },
190
- }),
191
-
192
- // Selection styles
193
- '& .MuiTableRow-root.selected': {
194
- backgroundColor: alpha(theme.palette.primary.main, 0.12),
195
- '&:hover': {
196
- backgroundColor: alpha(theme.palette.primary.main, 0.16),
197
- },
198
- },
199
-
200
- // Glow effect
201
- ...(glow && !pulse && {
202
- boxShadow: `0 0 20px 5px ${alpha(theme.palette.primary.main, 0.3)} !important`,
203
- filter: 'brightness(1.05)',
204
- }),
205
-
206
- // Pulse animation
207
- ...(pulse && !glow && {
208
- position: 'relative',
209
- '&::after': {
210
- content: '""',
211
- position: 'absolute',
212
- top: 0,
213
- left: 0,
214
- right: 0,
215
- bottom: 0,
216
- borderRadius: 'inherit',
217
- backgroundColor: theme.palette.primary.main,
218
- opacity: 0.1,
219
- animation: `${pulseAnimation} 2s infinite`,
220
- pointerEvents: 'none',
221
- zIndex: -1,
222
- },
223
- }),
224
-
225
- // Both glow and pulse
226
- ...(glow && pulse && {
227
- position: 'relative',
228
- boxShadow: `0 0 20px 5px ${alpha(theme.palette.primary.main, 0.3)} !important`,
229
- filter: 'brightness(1.05)',
230
- '&::after': {
231
- content: '""',
232
- position: 'absolute',
233
- top: 0,
234
- left: 0,
235
- right: 0,
236
- bottom: 0,
237
- borderRadius: 'inherit',
238
- backgroundColor: theme.palette.primary.main,
239
- opacity: 0.1,
240
- animation: `${pulseAnimation} 2s infinite`,
241
- pointerEvents: 'none',
242
- zIndex: -1,
243
- },
244
- }),
245
- };
53
+ return tableStyles({
54
+ theme,
55
+ customVariant,
56
+ glow,
57
+ pulse,
58
+ hoverable,
59
+ density,
60
+ stickyHeader,
61
+ stripeColor });
246
62
  });
247
63
 
248
64
  // Virtual Scrolling Hook
249
- const useVirtualScrolling = (
250
- data: Record<string, unknown>[],
251
- rowHeight: number,
252
- containerHeight: number,
253
- overscan: number = 5
254
- ) => {
255
- const [scrollTop, setScrollTop] = useState(0);
256
-
257
- const visibleItems = useMemo(() => {
258
- const visibleHeight = containerHeight;
259
- const startIndex = Math.floor(scrollTop / rowHeight);
260
- const endIndex = Math.min(
261
- data.length,
262
- Math.ceil((scrollTop + visibleHeight) / rowHeight)
263
- );
264
-
265
- const start = Math.max(0, startIndex - overscan);
266
- const end = Math.min(data.length, endIndex + overscan);
267
-
268
- return {
269
- startIndex: start,
270
- endIndex: end,
271
- items: data.slice(start, end),
272
- totalHeight: data.length * rowHeight,
273
- offsetY: start * rowHeight,
274
- };
275
- }, [data, rowHeight, containerHeight, scrollTop, overscan]);
276
-
277
- const handleScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {
278
- setScrollTop(e.currentTarget.scrollTop);
279
- }, []);
280
-
281
- return { visibleItems, handleScroll };
282
- };
283
-
284
- // Responsive Hook
285
- const useResponsive = (
286
- columns: ColumnConfig[],
287
- columnPriorities?: number[]
288
- ) => {
289
- const theme = useTheme();
290
- const isMobile = useMediaQuery(theme.breakpoints.down('md'));
291
- const isTablet = useMediaQuery(theme.breakpoints.down('lg'));
292
-
293
- const [hiddenColumns, setHiddenColumns] = useState<number[]>([]);
294
- const [columnMenuAnchor, setColumnMenuAnchor] = useState<null | HTMLElement>(null);
295
-
296
- useEffect(() => {
297
- if (!columnPriorities) return;
298
-
299
- let columnsToHide: number[] = [];
300
-
301
- if (isMobile) {
302
- // Hide lowest priority columns on mobile
303
- columnsToHide = columnPriorities
304
- .map((priority, index) => ({ priority, index }))
305
- .sort((a, b) => b.priority - a.priority)
306
- .slice(0, Math.floor(columns.length / 2))
307
- .map(item => item.index);
308
- } else if (isTablet) {
309
- // Hide some columns on tablet
310
- columnsToHide = columnPriorities
311
- .map((priority, index) => ({ priority, index }))
312
- .sort((a, b) => b.priority - a.priority)
313
- .slice(0, Math.floor(columns.length / 3))
314
- .map(item => item.index);
315
- }
316
-
317
- setHiddenColumns(columnsToHide);
318
- }, [isMobile, isTablet, columnPriorities, columns.length]);
319
-
320
- const visibleColumns = columns.filter((_, index) => !hiddenColumns.includes(index));
321
-
322
- return {
323
- visibleColumns,
324
- hiddenColumns,
325
- isMobile,
326
- columnMenuAnchor,
327
- setColumnMenuAnchor,
328
- setHiddenColumns,
329
- };
330
- };
331
-
332
- // Enhanced Table Header Component
333
- const EnhancedTableHeader: React.FC<TableHeaderProps> = React.memo(({
334
- columns,
335
- data,
336
- sortable,
337
- sortConfig,
338
- onSortChange,
339
- selectable,
340
- selectedRows = [],
341
- onSelectAll,
342
- }) => {
343
- const handleSort = useCallback(
344
- (columnKey: string) => {
345
- if (!sortable || !onSortChange) return;
346
-
347
- const direction =
348
- sortConfig?.key === columnKey && sortConfig.direction === 'asc' ? 'desc' : 'asc';
349
- onSortChange(columnKey, direction);
350
- },
351
- [sortable, onSortChange, sortConfig]
352
- );
65
+ const TableShell: React.FC<{
66
+ innerRef: React.Ref<globalThis.HTMLTableElement>;
67
+ variant?: string;
68
+ stripeColor?: TableStripeColor;
69
+ glow?: boolean;
70
+ pulse?: boolean;
71
+ hoverable?: boolean;
72
+ density?: TableDensity;
73
+ stickyHeader?: boolean;
74
+ header: React.ReactNode;
75
+ rest: Record<string, unknown>;
76
+ children: React.ReactNode;
77
+ }> = ({
78
+ innerRef,
79
+ variant,
80
+ stripeColor,
81
+ glow,
82
+ pulse,
83
+ hoverable,
84
+ density,
85
+ stickyHeader,
86
+ header,
87
+ rest,
88
+ children }) => (
89
+ <StyledTableContainer>
90
+ <StyledTable
91
+ ref={innerRef}
92
+ customVariant={variant}
93
+ stripeColor={stripeColor}
94
+ glow={glow}
95
+ pulse={pulse}
96
+ hoverable={hoverable}
97
+ density={density}
98
+ stickyHeader={stickyHeader}
99
+ {...rest}
100
+ >
101
+ {header}
102
+ {children}
103
+ </StyledTable>
104
+ </StyledTableContainer>
105
+ );
353
106
 
354
- const handleSelectAll = useCallback(
355
- (event: React.ChangeEvent<globalThis.HTMLInputElement>) => {
356
- if (!onSelectAll) return;
357
- onSelectAll(event.target.checked);
358
- },
359
- [onSelectAll]
360
- );
107
+ const SKELETON_ROW_COUNT = 5;
361
108
 
362
- return (
363
- <TableHead>
364
- <TableRow>
365
- {selectable && (
366
- <TableCell padding="checkbox">
367
- <Checkbox
368
- indeterminate={selectedRows.length > 0 && selectedRows.length < data.length}
369
- checked={selectedRows.length === data.length && data.length > 0}
370
- onChange={handleSelectAll}
371
- inputProps={{ 'aria-label': 'select all' }}
372
- />
373
- </TableCell>
374
- )}
375
- {columns.map((column) => (
376
- <TableCell
377
- key={column.key}
378
- align={column.align || 'left'}
379
- style={{
380
- minWidth: column.minWidth,
381
- width: column.width,
382
- }}
383
- aria-sort={
384
- sortable && column.sortable !== false && sortConfig?.key === column.key
385
- ? sortConfig.direction === 'asc' ? 'ascending' : 'descending'
386
- : undefined
387
- }
388
- >
389
- {sortable && column.sortable !== false ? (
390
- <TableSortLabel
391
- active={sortConfig?.key === column.key}
392
- direction={sortConfig?.key === column.key ? sortConfig.direction : 'asc'}
393
- onClick={() => handleSort(column.key)}
394
- data-testid="sort-indicator"
395
- aria-label={`Sort by ${column.label}`}
396
- >
397
- {column.label}
398
- </TableSortLabel>
399
- ) : (
400
- column.label
401
- )}
109
+ const LoadingSkeletonRows: React.FC<{ columns?: ColumnConfig[] }> = ({ columns }) => (
110
+ <>
111
+ {Array.from({ length: SKELETON_ROW_COUNT }, (_, index) => (
112
+ <TableRow key={index}>
113
+ {columns?.map((column) => (
114
+ <TableCell key={column.key}>
115
+ <Skeleton height={20} />
402
116
  </TableCell>
403
117
  ))}
404
118
  </TableRow>
405
- </TableHead>
406
- );
407
- });
408
-
409
- EnhancedTableHeader.displayName = 'EnhancedTableHeader';
410
-
411
- // Enhanced Table Body Component
412
- const EnhancedTableBody: React.FC<TableBodyProps> = React.memo(({
413
- data,
414
- columns,
415
- selectedRows = [],
416
- onRowClick,
417
- onRowFocus,
418
- onRowBlur,
419
- onSelectionChange,
420
- rowKeyExtractor,
421
- selectable,
422
- renderRow,
423
- renderCell,
424
- virtualScrolling,
425
- containerHeight,
426
- rowHeight,
427
- overscan = 5,
428
- }) => {
429
- const getRowKey = useCallback(
430
- (rowData: Record<string, unknown>, index: number): string | number => rowKeyExtractor ? rowKeyExtractor(rowData, index) : (rowData.id as string | number) || index,
431
- [rowKeyExtractor]
432
- );
433
-
434
- const isRowSelected = useCallback(
435
- (rowKey: string | number) => selectedRows.includes(rowKey),
436
- [selectedRows]
437
- );
438
-
439
- const handleRowSelection = useCallback(
440
- (event: React.MouseEvent | React.ChangeEvent, rowKey: string | number) => {
441
- // Stop propagation to prevent row click conflict
442
- event.stopPropagation();
443
- if (!onSelectionChange) return;
444
- const isSelected = selectedRows.includes(rowKey);
445
- onSelectionChange(rowKey, !isSelected);
446
- },
447
- [onSelectionChange, selectedRows]
448
- );
449
-
450
- const renderTableRow = useCallback((rowData: Record<string, unknown>, index: number, offsetY: number = 0) => {
451
- const rowKey = getRowKey(rowData, index);
452
- const selected = isRowSelected(rowKey);
453
-
454
- if (renderRow) {
455
- return renderRow(rowData, index, selected);
456
- }
119
+ ))}
120
+ </>
121
+ );
457
122
 
458
- return (
459
- <TableRow
460
- key={String(rowKey)}
461
- selected={selected}
462
- className={selected ? 'selected' : ''}
463
- onClick={(event: React.MouseEvent<globalThis.HTMLTableRowElement>) => onRowClick?.(event, rowData)}
464
- onFocus={(event: React.FocusEvent<globalThis.HTMLTableRowElement>) => onRowFocus?.(event, rowData)}
465
- onBlur={(event: React.FocusEvent<globalThis.HTMLTableRowElement>) => onRowBlur?.(event, rowData)}
466
- style={virtualScrolling ? {
467
- transform: `translateY(${offsetY}px)`,
468
- position: 'absolute',
469
- top: 0,
470
- left: 0,
471
- right: 0,
472
- height: rowHeight,
473
- } : undefined}
474
- >
475
- {selectable && (
476
- <TableCell padding="checkbox">
477
- <Checkbox
478
- checked={selected}
479
- onChange={(event) => handleRowSelection(event, rowKey)}
480
- onClick={(event) => event.stopPropagation()}
481
- inputProps={{ 'aria-label': `select row ${index + 1}` }}
482
- />
483
- </TableCell>
484
- )}
485
- {columns.map((column) => {
486
- const value = rowData[column.key];
487
- return (
488
- <TableCell key={column.key} align={column.align || 'left'}>
489
- {renderCell
490
- ? renderCell(value, column, rowData, index)
491
- : column.render
492
- ? column.render(value, rowData)
493
- : (value as React.ReactNode)
494
- }
495
- </TableCell>
496
- );
497
- })}
498
- </TableRow>
499
- );
500
- }, [getRowKey, isRowSelected, renderRow, renderCell, columns, selectable, handleRowSelection, onRowClick, onRowFocus, onRowBlur, virtualScrolling, rowHeight]);
123
+ export type TableShellProps = Omit<React.ComponentProps<typeof TableShell>, 'children'>;
124
+
125
+ type Selection = ReturnType<typeof useTableSelection>;
126
+
127
+ interface RendererProps {
128
+ resolved: TableProps;
129
+ selection: Selection;
130
+ innerRef: React.Ref<globalThis.HTMLTableElement>;
131
+ rest: Record<string, unknown>;
132
+ }
133
+
134
+ // The column-visibility control, shown only when responsive mode has actually
135
+ // hidden something on a narrow viewport.
136
+ const ColumnToggleMenu: React.FC<{
137
+ columns: ColumnConfig[];
138
+ hiddenColumns: number[];
139
+ anchor: HTMLElement | null;
140
+ setAnchor: (element: HTMLElement | null) => void;
141
+ setHiddenColumns: (next: number[]) => void;
142
+ }> = ({ columns, hiddenColumns, anchor, setAnchor, setHiddenColumns }) => (
143
+ <Box position="absolute" top={8} right={8}>
144
+ <IconButton onClick={(event) => setAnchor(event.currentTarget)} size="small">
145
+ <MoreVertIcon />
146
+ </IconButton>
147
+ <Menu anchorEl={anchor} open={Boolean(anchor)} onClose={() => setAnchor(null)}>
148
+ {columns.map((column, index) => (
149
+ <MenuItem key={column.key}>
150
+ <FormControlLabel
151
+ control={
152
+ <Switch
153
+ checked={!hiddenColumns.includes(index)}
154
+ onChange={(event) =>
155
+ setHiddenColumns(
156
+ event.target.checked
157
+ ? hiddenColumns.filter((i: number) => i !== index)
158
+ : [...hiddenColumns, index],
159
+ )
160
+ }
161
+ size="small"
162
+ />
163
+ }
164
+ label={column.label}
165
+ />
166
+ </MenuItem>
167
+ ))}
168
+ </Menu>
169
+ </Box>
170
+ );
501
171
 
502
- const { visibleItems, handleScroll } = useVirtualScrolling(
503
- data,
504
- rowHeight || 40,
505
- typeof containerHeight === 'number' ? containerHeight : 400,
506
- overscan
172
+ // The populated table. Local because StyledTableContainer and StyledTable
173
+ // cannot cross a module boundary (TS2742).
174
+ const columnsFor = (resolved: TableProps, selection: Selection): ColumnConfig[] =>
175
+ (resolved.responsive ? selection.visibleColumns : resolved.columns) ?? [];
176
+
177
+ // The toggle only earns its place when responsive mode has actually hidden
178
+ // something on a narrow viewport.
179
+ const showsColumnToggle = (resolved: TableProps, selection: Selection): boolean =>
180
+ Boolean(
181
+ resolved.responsive &&
182
+ selection.isMobile &&
183
+ resolved.showColumnToggle &&
184
+ selection.hiddenColumns.length > 0,
507
185
  );
508
186
 
509
- if (virtualScrolling && containerHeight && rowHeight) {
187
+ const AdvancedTable: React.FC<RendererProps> = ({ resolved: p, selection, innerRef, rest }) => {
188
+ const finalColumns = columnsFor(p, selection);
189
+ const showToggle = showsColumnToggle(p, selection);
510
190
 
511
- return (
512
- <Box
513
- onScroll={handleScroll}
514
- style={{
515
- height: containerHeight,
516
- overflow: 'auto',
517
- position: 'relative',
518
- }}
191
+ return (
192
+ <Box position="relative">
193
+ <StyledTableContainer
194
+ virtualScrolling={p.virtualScrolling}
195
+ containerHeight={p.containerHeight}
519
196
  >
520
- <TableBody
521
- style={{
522
- height: visibleItems.totalHeight,
523
- position: 'relative',
524
- }}
197
+ <StyledTable
198
+ ref={innerRef}
199
+ customVariant={p.variant}
200
+ stripeColor={p.stripeColor}
201
+ glow={p.glow}
202
+ pulse={p.pulse}
203
+ hoverable={p.hoverable}
204
+ density={p.density}
205
+ stickyHeader={p.stickyHeader}
206
+ {...rest}
525
207
  >
526
- {visibleItems.items.map((rowData, index) =>
527
- renderTableRow(rowData, visibleItems.startIndex + index, visibleItems.offsetY + index * rowHeight)
528
- )}
529
- </TableBody>
530
- </Box>
531
- );
532
- }
208
+ <EnhancedTableHeader
209
+ columns={finalColumns}
210
+ data={p.data ?? []}
211
+ sortable={p.sortable}
212
+ sortConfig={p.sortConfig}
213
+ onSortChange={p.onSortChange}
214
+ selectable={p.selectable}
215
+ selectedRows={p.selectedRows}
216
+ onSelectAll={selection.handleSelectAll}
217
+ density={p.density}
218
+ stickyHeader={p.stickyHeader}
219
+ />
220
+ <EnhancedTableBody
221
+ data={p.data ?? []}
222
+ columns={finalColumns}
223
+ selectedRows={p.selectedRows}
224
+ onRowClick={p.onRowClick}
225
+ onRowFocus={p.onRowFocus}
226
+ onRowBlur={p.onRowBlur}
227
+ onSelectionChange={selection.handleSelectionChange}
228
+ rowKeyExtractor={p.rowKeyExtractor}
229
+ density={p.density}
230
+ selectable={p.selectable}
231
+ hoverable={p.hoverable}
232
+ renderRow={p.renderRow}
233
+ renderCell={p.renderCell}
234
+ virtualScrolling={p.virtualScrolling}
235
+ containerHeight={typeof p.containerHeight === 'number' ? p.containerHeight : undefined}
236
+ rowHeight={p.rowHeight}
237
+ overscan={p.overscan}
238
+ />
239
+ </StyledTable>
240
+ </StyledTableContainer>
241
+
242
+ {showToggle && (
243
+ <ColumnToggleMenu
244
+ columns={p.columns ?? []}
245
+ hiddenColumns={selection.hiddenColumns}
246
+ anchor={selection.columnMenuAnchor}
247
+ setAnchor={selection.setColumnMenuAnchor}
248
+ setHiddenColumns={selection.setHiddenColumns}
249
+ />
250
+ )}
251
+ </Box>
252
+ );
253
+ };
533
254
 
534
- return (
535
- <TableBody>
536
- {data.map((rowData, index) => renderTableRow(rowData, index))}
255
+ // The loading and empty states render the same shell as the populated table, so
256
+ // they share TableShell rather than repeating it three times.
257
+ const buildShell = ({
258
+ resolved,
259
+ selection,
260
+ innerRef,
261
+ rest,
262
+ finalColumns }: RendererProps & { finalColumns?: ColumnConfig[] }) => ({
263
+ innerRef,
264
+ variant: resolved.variant,
265
+ stripeColor: resolved.stripeColor,
266
+ glow: resolved.glow,
267
+ pulse: resolved.pulse,
268
+ hoverable: resolved.hoverable,
269
+ density: resolved.density,
270
+ stickyHeader: resolved.stickyHeader,
271
+ header: resolved.columns ? (
272
+ <EnhancedTableHeader
273
+ columns={finalColumns ?? []}
274
+ data={[]}
275
+ sortable={resolved.sortable}
276
+ sortConfig={resolved.sortConfig}
277
+ onSortChange={resolved.onSortChange}
278
+ selectable={resolved.selectable}
279
+ selectedRows={resolved.selectedRows}
280
+ onSelectAll={selection.handleSelectAll}
281
+ density={resolved.density}
282
+ stickyHeader={resolved.stickyHeader}
283
+ />
284
+ ) : null,
285
+ rest: rest as Record<string, unknown> });
286
+
287
+ const TableLoadingState: React.FC<{
288
+ shell: TableShellProps;
289
+ loadingComponent?: React.ReactNode;
290
+ columns?: ColumnConfig[];
291
+ }> = ({ shell, loadingComponent, columns }) => (
292
+ <TableShell {...shell}>
293
+ <TableBody data-testid="table-loading">
294
+ {loadingComponent || <LoadingSkeletonRows columns={columns} />}
537
295
  </TableBody>
538
- );
539
- });
296
+ </TableShell>
297
+ );
540
298
 
541
- EnhancedTableBody.displayName = 'EnhancedTableBody';
299
+ const TableEmptyState: React.FC<{
300
+ shell: TableShellProps;
301
+ emptyStateComponent?: React.ReactNode;
302
+ colSpan: number;
303
+ }> = ({ shell, emptyStateComponent, colSpan }) => (
304
+ <TableShell {...shell}>
305
+ <EmptyRow colSpan={colSpan}>{emptyStateComponent || <NoDataPlaceholder />}</EmptyRow>
306
+ </TableShell>
307
+ );
542
308
 
543
- // Main Table Component
544
309
  export const Table = React.forwardRef<globalThis.HTMLTableElement, TableProps>(
545
- ({
546
- // Basic props
547
- variant = 'default',
548
- stripeColor = 'neutral',
549
- glow = false,
550
- pulse = false,
551
- hoverable = false,
552
- loading = false,
553
- children,
554
-
555
- // Advanced feature props
556
- density = 'normal',
557
- stickyHeader = false,
558
- selectable = false,
559
- selectedRows = [],
560
- onSelectionChange,
561
- rowKeyExtractor,
562
- sortable = false,
563
- sortConfig,
564
- onSortChange,
565
- columns,
566
- data,
567
- virtualScrolling = false,
568
- rowHeight = 52,
569
- overscan = 5,
570
- responsive = false,
571
- columnPriorities,
572
- showColumnToggle = true,
573
- containerHeight,
574
- loadingComponent,
575
- emptyStateComponent,
576
- renderRow,
577
- renderCell,
578
- onRowClick,
579
- onRowFocus,
580
- onRowBlur,
581
-
582
- ...props
583
- }, ref) => {
584
- useTheme(); // Required for responsive behavior
585
-
586
- // Use responsive hook if responsive mode is enabled
310
+ (tableProps, ref) => {
311
+ const resolved = { ...TABLE_DEFAULTS, ...definedProps(tableProps) } as TableProps;
587
312
  const {
588
- visibleColumns,
589
- hiddenColumns,
590
- isMobile,
591
- columnMenuAnchor,
592
- setColumnMenuAnchor,
593
- setHiddenColumns,
594
- } = useResponsive(
595
- columns || [],
596
- responsive ? columnPriorities : undefined
597
- );
598
-
599
- // Handle selection changes
600
- const handleSelectionChange = useCallback((rowKey: string | number, selected: boolean) => {
601
- if (!onSelectionChange) return;
602
-
603
- let newSelection: (string | number)[];
604
- if (selected) {
605
- newSelection = [...selectedRows, rowKey];
606
- } else {
607
- newSelection = selectedRows.filter(key => key !== rowKey);
608
- }
609
- onSelectionChange(newSelection);
610
- }, [selectedRows, onSelectionChange]);
313
+ columns,
314
+ data,
315
+ responsive,
316
+ loading,
317
+ loadingComponent,
318
+ emptyStateComponent,
319
+ children,
320
+ ...props
321
+ } = resolved;
322
+
323
+ const selection = useTableSelection({
324
+ columns,
325
+ data,
326
+ responsive,
327
+ columnPriorities: resolved.columnPriorities,
328
+ selectedRows: resolved.selectedRows ?? [],
329
+ rowKeyExtractor: resolved.rowKeyExtractor,
330
+ onSelectionChange: resolved.onSelectionChange });
331
+
332
+ const rest = props as unknown as Record<string, unknown>;
333
+ const renderer: RendererProps = { resolved, selection, innerRef: ref, rest };
334
+ const finalColumns = responsive ? selection.visibleColumns : columns;
335
+ const shell = buildShell({ ...renderer, finalColumns });
611
336
 
612
- const handleSelectAll = useCallback((selected: boolean) => {
613
- if (!onSelectionChange || !data) return;
614
-
615
- if (selected) {
616
- const allKeys = data.map((rowData, index) =>
617
- rowKeyExtractor ? rowKeyExtractor(rowData, index) : (rowData.id as string | number) || index
618
- );
619
- onSelectionChange(allKeys);
620
- } else {
621
- onSelectionChange([]);
622
- }
623
- }, [data, onSelectionChange, rowKeyExtractor]);
624
-
625
- // Loading state
626
337
  if (loading) {
627
- const loadingRows = Array.from({ length: 5 }, (_, index) => (
628
- <TableRow key={index}>
629
- {columns?.map((column) => (
630
- <TableCell key={column.key}>
631
- <Skeleton height={20} />
632
- </TableCell>
633
- ))}
634
- </TableRow>
635
- ));
636
-
637
338
  return (
638
- <StyledTableContainer>
639
- <StyledTable
640
- ref={ref}
641
- customVariant={variant}
642
- stripeColor={stripeColor}
643
- glow={glow}
644
- pulse={pulse}
645
- hoverable={hoverable}
646
- density={density}
647
- stickyHeader={stickyHeader}
648
- {...props}
649
- >
650
- {columns && (
651
- <EnhancedTableHeader
652
- columns={responsive ? visibleColumns : columns}
653
- data={[]}
654
- sortable={sortable}
655
- sortConfig={sortConfig}
656
- onSortChange={onSortChange}
657
- selectable={selectable}
658
- selectedRows={selectedRows}
659
- onSelectAll={handleSelectAll}
660
- density={density}
661
- stickyHeader={stickyHeader}
662
- />
663
- )}
664
- <TableBody data-testid="table-loading">
665
- {loadingComponent || loadingRows}
666
- </TableBody>
667
- </StyledTable>
668
- </StyledTableContainer>
339
+ <TableLoadingState shell={shell} loadingComponent={loadingComponent} columns={columns} />
669
340
  );
670
341
  }
671
342
 
672
- // Empty state
673
343
  if (data && data.length === 0) {
674
344
  return (
675
- <StyledTableContainer>
676
- <StyledTable
677
- ref={ref}
678
- customVariant={variant}
679
- stripeColor={stripeColor}
680
- glow={glow}
681
- pulse={pulse}
682
- hoverable={hoverable}
683
- density={density}
684
- stickyHeader={stickyHeader}
685
- {...props}
686
- >
687
- {columns && (
688
- <EnhancedTableHeader
689
- columns={responsive ? visibleColumns : columns}
690
- data={[]}
691
- sortable={sortable}
692
- sortConfig={sortConfig}
693
- onSortChange={onSortChange}
694
- selectable={selectable}
695
- selectedRows={selectedRows}
696
- onSelectAll={handleSelectAll}
697
- density={density}
698
- stickyHeader={stickyHeader}
699
- />
700
- )}
701
- <TableBody>
702
- <TableRow>
703
- <TableCell colSpan={(responsive ? visibleColumns : columns)?.length || 1} align="center">
704
- {emptyStateComponent || (
705
- <Box py={4} color="text.secondary">
706
- No data available
707
- </Box>
708
- )}
709
- </TableCell>
710
- </TableRow>
711
- </TableBody>
712
- </StyledTable>
713
- </StyledTableContainer>
345
+ <TableEmptyState
346
+ shell={shell}
347
+ emptyStateComponent={emptyStateComponent}
348
+ colSpan={finalColumns?.length || 1}
349
+ />
714
350
  );
715
351
  }
716
352
 
717
- // Advanced table with columns and data
718
- if (columns && data) {
719
- const finalColumns = responsive ? visibleColumns : columns;
720
-
721
- return (
722
- <Box position="relative">
723
- <StyledTableContainer
724
- virtualScrolling={virtualScrolling}
725
- containerHeight={containerHeight}
726
- >
727
- <StyledTable
728
- ref={ref}
729
- customVariant={variant}
730
- stripeColor={stripeColor}
731
- glow={glow}
732
- pulse={pulse}
733
- hoverable={hoverable}
734
- density={density}
735
- stickyHeader={stickyHeader}
736
- {...props}
737
- >
738
- <EnhancedTableHeader
739
- columns={finalColumns}
740
- data={data}
741
- sortable={sortable}
742
- sortConfig={sortConfig}
743
- onSortChange={onSortChange}
744
- selectable={selectable}
745
- selectedRows={selectedRows}
746
- onSelectAll={handleSelectAll}
747
- density={density}
748
- stickyHeader={stickyHeader}
749
- />
750
- <EnhancedTableBody
751
- data={data}
752
- columns={finalColumns}
753
- selectedRows={selectedRows}
754
- onRowClick={onRowClick}
755
- onRowFocus={onRowFocus}
756
- onRowBlur={onRowBlur}
757
- onSelectionChange={handleSelectionChange}
758
- rowKeyExtractor={rowKeyExtractor}
759
- density={density}
760
- selectable={selectable}
761
- hoverable={hoverable}
762
- renderRow={renderRow}
763
- renderCell={renderCell}
764
- virtualScrolling={virtualScrolling}
765
- containerHeight={typeof containerHeight === 'number' ? containerHeight : undefined}
766
- rowHeight={rowHeight}
767
- overscan={overscan}
768
- />
769
- </StyledTable>
770
- </StyledTableContainer>
771
-
772
- {/* Column Toggle Menu for Responsive */}
773
- {responsive && isMobile && showColumnToggle && hiddenColumns.length > 0 && (
774
- <Box position="absolute" top={8} right={8}>
775
- <IconButton
776
- onClick={(event) => setColumnMenuAnchor(event.currentTarget)}
777
- size="small"
778
- >
779
- <MoreVertIcon />
780
- </IconButton>
781
- <Menu
782
- anchorEl={columnMenuAnchor}
783
- open={Boolean(columnMenuAnchor)}
784
- onClose={() => setColumnMenuAnchor(null)}
785
- >
786
- {columns.map((column, index) => (
787
- <MenuItem key={column.key}>
788
- <FormControlLabel
789
- control={
790
- <Switch
791
- checked={!hiddenColumns.includes(index)}
792
- onChange={(e) => {
793
- const newHidden = e.target.checked
794
- ? hiddenColumns.filter(i => i !== index)
795
- : [...hiddenColumns, index];
796
- setHiddenColumns(newHidden);
797
- }}
798
- size="small"
799
- />
800
- }
801
- label={column.label}
802
- />
803
- </MenuItem>
804
- ))}
805
- </Menu>
806
- </Box>
807
- )}
808
- </Box>
809
- );
810
- }
353
+ if (columns && data) return <AdvancedTable {...renderer} />;
811
354
 
812
355
  // Basic table (backward compatibility)
813
356
  return (
814
357
  <StyledTable
815
358
  ref={ref}
816
- customVariant={variant}
817
- stripeColor={stripeColor}
818
- glow={glow}
819
- pulse={pulse}
820
- hoverable={hoverable}
821
- density={density}
822
- stickyHeader={stickyHeader}
823
- {...props}
359
+ customVariant={resolved.variant}
360
+ stripeColor={resolved.stripeColor}
361
+ glow={resolved.glow}
362
+ pulse={resolved.pulse}
363
+ hoverable={resolved.hoverable}
364
+ density={resolved.density}
365
+ stickyHeader={resolved.stickyHeader}
366
+ {...rest}
824
367
  >
825
368
  {children}
826
369
  </StyledTable>
827
370
  );
828
- }
371
+ },
829
372
  );
830
373
 
831
374
  Table.displayName = 'Table';