@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
@@ -0,0 +1,90 @@
1
+ import { Box, useTheme } from '@mui/material';
2
+ import type { FC, ReactNode, UIEvent } from 'react';
3
+ import React from 'react';
4
+
5
+ import { getOverflowStyle, getVariantStyles } from './ScrollArea.styles';
6
+ import type { ResolvedScrollAreaProps } from './ScrollArea.helpers';
7
+
8
+ export interface ScrollViewportProps
9
+ extends Pick<
10
+ ResolvedScrollAreaProps,
11
+ | 'height'
12
+ | 'maxHeight'
13
+ | 'orientation'
14
+ | 'scrollbarSize'
15
+ | 'scrollbarColor'
16
+ | 'scrollbarTrackColor'
17
+ | 'contentPadding'
18
+ | 'variant'
19
+ | 'disabled'
20
+ | 'loading'
21
+ | 'smoothScroll'
22
+ > {
23
+ children: ReactNode;
24
+ shouldShowScrollbar: boolean;
25
+ setScrollRef: (node: HTMLDivElement | null) => void;
26
+ onScroll: (event: UIEvent<HTMLDivElement>) => void;
27
+ }
28
+
29
+ // The element that actually scrolls: its own overflow and scrollbar styling,
30
+ // plus the disabled and loading treatments.
31
+ export const ScrollViewport: FC<ScrollViewportProps> = ({
32
+ children,
33
+ height,
34
+ maxHeight,
35
+ orientation,
36
+ scrollbarSize,
37
+ scrollbarColor,
38
+ scrollbarTrackColor,
39
+ contentPadding,
40
+ variant,
41
+ disabled,
42
+ loading,
43
+ smoothScroll,
44
+ shouldShowScrollbar,
45
+ setScrollRef,
46
+ onScroll,
47
+ }) => {
48
+ const theme = useTheme();
49
+
50
+ return (
51
+ <Box
52
+ ref={setScrollRef}
53
+ onScroll={onScroll}
54
+ role="region"
55
+ aria-label="Scrollable content"
56
+ aria-busy={loading}
57
+ tabIndex={disabled ? -1 : 0}
58
+ sx={{
59
+ width: '100%',
60
+ height: '100%',
61
+ // Use an explicit maxHeight when height is 'auto', else inherit.
62
+ maxHeight: height === 'auto' && maxHeight ? maxHeight : '100%',
63
+ padding: contentPadding,
64
+ opacity: loading ? 0.5 : 1,
65
+ pointerEvents: disabled || loading ? 'none' : 'auto',
66
+ transition: 'opacity 0.3s ease',
67
+ '&:focus': {
68
+ outline: 'none',
69
+ '&:focus-visible': {
70
+ outline: `2px solid ${theme.palette.primary.main}`,
71
+ outlineOffset: -2,
72
+ },
73
+ },
74
+ ...getOverflowStyle({ disabled, orientation }),
75
+ ...getVariantStyles({
76
+ theme,
77
+ variant,
78
+ orientation,
79
+ scrollbarSize,
80
+ scrollbarColor,
81
+ scrollbarTrackColor,
82
+ shouldShowScrollbar,
83
+ }),
84
+ }}
85
+ style={{ scrollBehavior: smoothScroll ? 'smooth' : 'auto' }}
86
+ >
87
+ {children}
88
+ </Box>
89
+ );
90
+ };
@@ -0,0 +1,128 @@
1
+ import type { CSSObject, Theme } from '@mui/material';
2
+
3
+ import type {
4
+ SeparatorOrientation,
5
+ SeparatorProps,
6
+ SeparatorSize,
7
+ SeparatorVariant,
8
+ } from './Separator.types';
9
+
10
+ const THICKNESS_PX: Record<SeparatorSize, number> = {
11
+ xs: 1,
12
+ sm: 2,
13
+ md: 3,
14
+ lg: 4,
15
+ xl: 6,
16
+ };
17
+
18
+ const MARGIN_PX: Record<SeparatorSize, number> = {
19
+ xs: 4,
20
+ sm: 8,
21
+ md: 16,
22
+ lg: 24,
23
+ xl: 32,
24
+ };
25
+
26
+ const separatorThickness = (size: SeparatorSize): number =>
27
+ THICKNESS_PX[size] ?? THICKNESS_PX.md;
28
+
29
+ /** An explicit `margin` wins; otherwise the size picks one. */
30
+ export const separatorMargin = (
31
+ size: SeparatorSize,
32
+ margin?: number | string,
33
+ ): number | string => margin ?? MARGIN_PX[size] ?? MARGIN_PX.md;
34
+
35
+ // `gradient` paints a background rather than a border, so it draws its line as a
36
+ // solid border of zero visual consequence.
37
+ const borderStyleFor = (variant: SeparatorVariant): 'dashed' | 'dotted' | 'solid' => {
38
+ switch (variant) {
39
+ case 'dashed':
40
+ return 'dashed';
41
+ case 'dotted':
42
+ return 'dotted';
43
+ default:
44
+ return 'solid';
45
+ }
46
+ };
47
+
48
+ const gradientBackground = (
49
+ variant: SeparatorVariant,
50
+ orientation: SeparatorOrientation,
51
+ color: string,
52
+ ): string | undefined => {
53
+ if (variant !== 'gradient') return undefined;
54
+ const angle = orientation === 'horizontal' ? '90deg' : '180deg';
55
+ return `linear-gradient(${angle}, transparent 0%, ${color} 50%, transparent 100%)`;
56
+ };
57
+
58
+ // Only the leading edge carries the rule; the other three are zeroed explicitly so
59
+ // a parent's border shorthand cannot leak through.
60
+ const borderEdges = (
61
+ isHorizontal: boolean,
62
+ thickness: number,
63
+ style: 'dashed' | 'dotted' | 'solid',
64
+ color: string,
65
+ ): CSSObject => {
66
+ const leading = isHorizontal ? 'Top' : 'Left';
67
+ const blank: CSSObject = {
68
+ borderTopWidth: 0,
69
+ borderBottomWidth: 0,
70
+ borderLeftWidth: 0,
71
+ borderRightWidth: 0,
72
+ borderTopStyle: 'none',
73
+ borderBottomStyle: 'none',
74
+ borderLeftStyle: 'none',
75
+ borderRightStyle: 'none',
76
+ borderTopColor: 'transparent',
77
+ borderBottomColor: 'transparent',
78
+ borderLeftColor: 'transparent',
79
+ borderRightColor: 'transparent',
80
+ };
81
+
82
+ return {
83
+ ...blank,
84
+ [`border${leading}Width`]: thickness,
85
+ [`border${leading}Style`]: style,
86
+ [`border${leading}Color`]: color,
87
+ };
88
+ };
89
+
90
+ type SeparatorStyleArgs = Required<
91
+ Pick<SeparatorProps, 'variant' | 'orientation' | 'size'>
92
+ > &
93
+ Pick<SeparatorProps, 'color' | 'margin' | 'length'>;
94
+
95
+ export const separatorStyles = (
96
+ theme: Theme,
97
+ { variant, orientation, size, color, margin, length }: SeparatorStyleArgs,
98
+ ): CSSObject => {
99
+ const isHorizontal = orientation === 'horizontal';
100
+ const thickness = separatorThickness(size);
101
+ const resolvedColor = color || theme.palette.divider;
102
+
103
+ // A margin given as a string carries its own units; a number is pixels.
104
+ const marginValue = separatorMargin(size, margin);
105
+ const marginStr = typeof marginValue === 'string' ? marginValue : `${marginValue}px`;
106
+
107
+ const baseStyles: CSSObject = {
108
+ display: 'flex',
109
+ alignItems: 'center',
110
+ margin: isHorizontal ? `${marginStr} 0` : `0 ${marginStr}`,
111
+ width: isHorizontal ? length || '100%' : `${thickness}px`,
112
+ height: isHorizontal ? `${thickness}px` : length || '100%',
113
+ boxSizing: 'border-box',
114
+ };
115
+
116
+ if (variant === 'gradient') {
117
+ return {
118
+ ...baseStyles,
119
+ background: gradientBackground(variant, orientation, resolvedColor),
120
+ };
121
+ }
122
+
123
+ return {
124
+ ...baseStyles,
125
+ backgroundColor: 'transparent',
126
+ ...borderEdges(isHorizontal, thickness, borderStyleFor(variant), resolvedColor),
127
+ };
128
+ };
@@ -486,22 +486,13 @@ export const Performance: Story = {
486
486
  play: async ({ canvasElement, step }) => {
487
487
  const canvas = within(canvasElement);
488
488
 
489
- await step('Measure render time for multiple separators', async () => {
490
-
491
- const startTime = performance.now();
489
+ // This bracketed the query below with performance.now() and asserted a
490
+ // wall-clock budget. That measured the machine, not the component.
491
+ await step('Render multiple separators', async () => {
492
492
  const separators = canvas.getAllByRole('separator');
493
493
 
494
- const endTime = performance.now();
495
-
496
- const renderTime = endTime - startTime;
497
- // eslint-disable-next-line no-console
498
- console.log(`Render time for ${separators.length} separators: ${renderTime}ms`);
499
-
500
494
  // Verify all separators are rendered
501
495
  await expect(separators.length).toBe(20);
502
-
503
- // Assert reasonable render time (adjust threshold as needed)
504
- await expect(renderTime).toBeLessThan(100);
505
496
  });
506
497
 
507
498
  await step('Test memory usage with many separators', async () => {
@@ -1,6 +1,7 @@
1
1
  import { Box, Typography,useTheme } from '@mui/material';
2
2
  import React from 'react';
3
3
 
4
+ import { separatorMargin, separatorStyles } from './Separator.styles';
4
5
  import type { SeparatorProps } from './Separator.types';
5
6
 
6
7
  export const Separator: React.FC<SeparatorProps> = ({
@@ -15,134 +16,7 @@ export const Separator: React.FC<SeparatorProps> = ({
15
16
  'data-testid': dataTestId,
16
17
  }) => {
17
18
  const theme = useTheme();
18
-
19
- const getThickness = () => {
20
- switch (size) {
21
- case 'xs':
22
- return 1;
23
- case 'sm':
24
- return 2;
25
- case 'md':
26
- return 3;
27
- case 'lg':
28
- return 4;
29
- case 'xl':
30
- return 6;
31
- default:
32
- return 3;
33
- }
34
- };
35
-
36
- const getMargin = () => {
37
- if (margin !== undefined) return margin;
38
- switch (size) {
39
- case 'xs':
40
- return 4; // 0.5 * 8 = 4px
41
- case 'sm':
42
- return 8; // 1 * 8 = 8px
43
- case 'md':
44
- return 16; // 2 * 8 = 16px
45
- case 'lg':
46
- return 24; // 3 * 8 = 24px
47
- case 'xl':
48
- return 32; // 4 * 8 = 32px
49
- default:
50
- return 16;
51
- }
52
- };
53
-
54
- const getBorderStyle = () => {
55
- switch (variant) {
56
- case 'dashed':
57
- return 'dashed';
58
- case 'dotted':
59
- return 'dotted';
60
- case 'gradient':
61
- return 'solid';
62
- default:
63
- return 'solid';
64
- }
65
- };
66
-
67
- const getColor = () => {
68
- if (color) return color;
69
- return theme.palette.divider;
70
- };
71
-
72
- const getGradientBackground = () => {
73
- if (variant !== 'gradient') return undefined;
74
-
75
- if (orientation === 'horizontal') {
76
- return `linear-gradient(90deg, transparent 0%, ${getColor()} 50%, transparent 100%)`;
77
- } else {
78
- return `linear-gradient(180deg, transparent 0%, ${getColor()} 50%, transparent 100%)`;
79
- }
80
- };
81
-
82
- const getSeparatorStyles = () => {
83
- const isHorizontal = orientation === 'horizontal';
84
- const thickness = getThickness();
85
- const marginValue = getMargin();
86
-
87
- // Handle margin - if it's a string with units, use as-is, otherwise add px
88
- const marginStr = typeof marginValue === 'string' ? marginValue : `${marginValue}px`;
89
-
90
- const baseStyles = {
91
- display: 'flex' as const,
92
- alignItems: 'center' as const,
93
- margin: isHorizontal ? `${marginStr} 0` : `0 ${marginStr}`,
94
- width: isHorizontal ? length || '100%' : `${thickness}px`,
95
- height: isHorizontal ? `${thickness}px` : length || '100%',
96
- boxSizing: 'border-box' as const,
97
- };
98
-
99
- if (variant === 'gradient') {
100
- return {
101
- ...baseStyles,
102
- background: getGradientBackground(),
103
- };
104
- }
105
-
106
- // Apply border styles separately for better compatibility with MUI's sx prop
107
- const borderStyle = getBorderStyle();
108
- const borderColor = getColor();
109
-
110
- const borderStyles = isHorizontal
111
- ? {
112
- borderTopWidth: thickness,
113
- borderTopStyle: borderStyle,
114
- borderTopColor: borderColor,
115
- borderBottomWidth: 0,
116
- borderLeftWidth: 0,
117
- borderRightWidth: 0,
118
- borderBottomStyle: 'none',
119
- borderLeftStyle: 'none',
120
- borderRightStyle: 'none',
121
- borderBottomColor: 'transparent',
122
- borderLeftColor: 'transparent',
123
- borderRightColor: 'transparent',
124
- }
125
- : {
126
- borderLeftWidth: thickness,
127
- borderLeftStyle: borderStyle,
128
- borderLeftColor: borderColor,
129
- borderTopWidth: 0,
130
- borderBottomWidth: 0,
131
- borderRightWidth: 0,
132
- borderTopStyle: 'none',
133
- borderBottomStyle: 'none',
134
- borderRightStyle: 'none',
135
- borderTopColor: 'transparent',
136
- borderBottomColor: 'transparent',
137
- borderRightColor: 'transparent',
138
- };
139
-
140
- return {
141
- ...baseStyles,
142
- backgroundColor: 'transparent' as const,
143
- ...borderStyles,
144
- };
145
- };
19
+ const styles = separatorStyles(theme, { variant, orientation, size, color, margin, length });
146
20
 
147
21
  if (children) {
148
22
  const isHorizontal = orientation === 'horizontal';
@@ -153,12 +27,12 @@ export const Separator: React.FC<SeparatorProps> = ({
153
27
  sx={{
154
28
  display: 'flex',
155
29
  alignItems: 'center',
156
- margin: getMargin(),
30
+ margin: separatorMargin(size, margin),
157
31
  flexDirection: isHorizontal ? 'row' : 'column',
158
32
  gap: theme.spacing(2),
159
33
  }}
160
34
  >
161
- <Box sx={getSeparatorStyles()} />
35
+ <Box sx={styles} />
162
36
  <Typography
163
37
  variant="body2"
164
38
  color="text.secondary"
@@ -170,7 +44,7 @@ export const Separator: React.FC<SeparatorProps> = ({
170
44
  >
171
45
  {children}
172
46
  </Typography>
173
- <Box sx={getSeparatorStyles()} />
47
+ <Box sx={styles} />
174
48
  </Box>
175
49
  );
176
50
  }
@@ -178,7 +52,7 @@ export const Separator: React.FC<SeparatorProps> = ({
178
52
  return (
179
53
  <Box
180
54
  className={className}
181
- sx={getSeparatorStyles()}
55
+ sx={styles}
182
56
  role="separator"
183
57
  aria-orientation={orientation}
184
58
  data-testid={dataTestId}
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
 
3
- import { ExpandMore as ExpandMoreIcon, Search as SearchIcon } from '@mui/icons-material';
3
+ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
4
+ import SearchIcon from '@mui/icons-material/Search';
4
5
  import {
5
6
  alpha,
6
7
  Box,
@@ -1,11 +1,9 @@
1
- import {
2
- LanguageOutlined,
3
- LockOutlined,
4
- NotificationsOutlined,
5
- PaletteOutlined,
6
- PaymentOutlined,
7
- PersonOutlined,
8
- } from '@mui/icons-material';
1
+ import LanguageOutlined from '@mui/icons-material/LanguageOutlined';
2
+ import LockOutlined from '@mui/icons-material/LockOutlined';
3
+ import NotificationsOutlined from '@mui/icons-material/NotificationsOutlined';
4
+ import PaletteOutlined from '@mui/icons-material/PaletteOutlined';
5
+ import PaymentOutlined from '@mui/icons-material/PaymentOutlined';
6
+ import PersonOutlined from '@mui/icons-material/PersonOutlined';
9
7
  import { Box, Stack, Typography } from '@mui/material';
10
8
  import type { Meta, StoryObj } from '@storybook/react-vite';
11
9
  import React, { useState } from 'react';
@@ -1,15 +1,13 @@
1
- import {
2
- ChevronLeft as ChevronLeftIcon,
3
- ChevronRight as ChevronRightIcon,
4
- Dashboard as DashboardIcon,
5
- Home as HomeIcon,
6
- Inbox as InboxIcon,
7
- Menu as MenuIcon,
8
- Person as PersonIcon,
9
- Send as SendIcon,
10
- Settings as SettingsIcon,
11
- Star as StarIcon,
12
- } from '@mui/icons-material';
1
+ import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
2
+ import ChevronRightIcon from '@mui/icons-material/ChevronRight';
3
+ import DashboardIcon from '@mui/icons-material/Dashboard';
4
+ import HomeIcon from '@mui/icons-material/Home';
5
+ import InboxIcon from '@mui/icons-material/Inbox';
6
+ import MenuIcon from '@mui/icons-material/Menu';
7
+ import PersonIcon from '@mui/icons-material/Person';
8
+ import SendIcon from '@mui/icons-material/Send';
9
+ import SettingsIcon from '@mui/icons-material/Settings';
10
+ import StarIcon from '@mui/icons-material/Star';
13
11
  import {
14
12
  Avatar,
15
13
  Box,
@@ -1,15 +1,13 @@
1
- import {
2
- ChevronLeft as ChevronLeftIcon,
3
- ChevronRight as ChevronRightIcon,
4
- Dashboard as DashboardIcon,
5
- Home as HomeIcon,
6
- Inbox as InboxIcon,
7
- Menu as MenuIcon,
8
- Person as PersonIcon,
9
- Send as SendIcon,
10
- Settings as SettingsIcon,
11
- Star as StarIcon,
12
- } from '@mui/icons-material';
1
+ import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
2
+ import ChevronRightIcon from '@mui/icons-material/ChevronRight';
3
+ import DashboardIcon from '@mui/icons-material/Dashboard';
4
+ import HomeIcon from '@mui/icons-material/Home';
5
+ import InboxIcon from '@mui/icons-material/Inbox';
6
+ import MenuIcon from '@mui/icons-material/Menu';
7
+ import PersonIcon from '@mui/icons-material/Person';
8
+ import SendIcon from '@mui/icons-material/Send';
9
+ import SettingsIcon from '@mui/icons-material/Settings';
10
+ import StarIcon from '@mui/icons-material/Star';
13
11
  import {
14
12
  Avatar,
15
13
  Box,
@@ -265,35 +263,35 @@ export const KeyboardNavigation: Story = {
265
263
  play: async ({ canvasElement }) => {
266
264
  const canvas = within(canvasElement);
267
265
 
268
- // Test Tab navigation through sidebar items
266
+ // Test Tab navigation through sidebar items. The first nav item is the
267
+ // first focusable node in the story, so tabbing in from the body reaches it
268
+ // — the old .focus() call asserted only that focus() works.
269
269
  const firstNavItem = canvas.getByTestId('keyboard-nav-home');
270
- firstNavItem.focus();
271
- await expect(firstNavItem).toHaveFocus();
270
+ await userEvent.tab();
271
+ await waitFor(() => expect(firstNavItem).toHaveFocus());
272
+
273
+ // Enter key activation, checked here while focus is already on the item
274
+ // rather than by re-focusing it at the end of the journey.
275
+ await userEvent.keyboard('{Enter}');
276
+ await expect(firstNavItem).toBeInTheDocument();
272
277
 
273
278
  // Tab to next item
274
279
  await userEvent.tab();
275
- await expect(canvas.getByTestId('keyboard-nav-dashboard')).toHaveFocus();
280
+ await waitFor(() => expect(canvas.getByTestId('keyboard-nav-dashboard')).toHaveFocus());
276
281
 
277
282
  // Tab to next item
278
283
  await userEvent.tab();
279
- await expect(canvas.getByTestId('keyboard-nav-inbox')).toHaveFocus();
284
+ await waitFor(() => expect(canvas.getByTestId('keyboard-nav-inbox')).toHaveFocus());
280
285
 
281
286
  // Tab to footer button
282
287
  await userEvent.tab();
283
288
  await userEvent.tab();
284
289
  await userEvent.tab();
285
- await expect(canvas.getByTestId('footer-button')).toHaveFocus();
290
+ await waitFor(() => expect(canvas.getByTestId('footer-button')).toHaveFocus());
286
291
 
287
292
  // Tab to main content
288
293
  await userEvent.tab();
289
- await expect(canvas.getByTestId('main-button')).toHaveFocus();
290
-
291
- // Test Enter key activation
292
- const homeItem = canvas.getByTestId('keyboard-nav-home');
293
- homeItem.focus();
294
- await userEvent.keyboard('{Enter}');
295
- // Verify item is still accessible after Enter
296
- await expect(homeItem).toBeInTheDocument();
294
+ await waitFor(() => expect(canvas.getByTestId('main-button')).toHaveFocus());
297
295
  },
298
296
  };
299
297
 
@@ -460,22 +458,22 @@ export const FocusManagement: Story = {
460
458
 
461
459
  // Test initial focus on first sidebar item
462
460
  const firstItem = canvas.getByTestId('focus-nav-home');
463
- firstItem.focus();
464
- await expect(firstItem).toHaveFocus();
461
+ await userEvent.tab();
462
+ await waitFor(() => expect(firstItem).toHaveFocus());
465
463
 
466
464
  // Test focus moves through sidebar elements
467
465
  await userEvent.tab();
468
- await expect(canvas.getByTestId('focus-nav-dashboard')).toHaveFocus();
466
+ await waitFor(() => expect(canvas.getByTestId('focus-nav-dashboard')).toHaveFocus());
469
467
 
470
468
  await userEvent.tab();
471
- await expect(canvas.getByTestId('focus-nav-inbox')).toHaveFocus();
469
+ await waitFor(() => expect(canvas.getByTestId('focus-nav-inbox')).toHaveFocus());
472
470
 
473
471
  await userEvent.tab();
474
- await expect(canvas.getByTestId('sidebar-action')).toHaveFocus();
472
+ await waitFor(() => expect(canvas.getByTestId('sidebar-action')).toHaveFocus());
475
473
 
476
474
  // Test focus moves to main content
477
475
  await userEvent.tab();
478
- await expect(canvas.getByTestId('main-focus-button')).toHaveFocus();
476
+ await waitFor(() => expect(canvas.getByTestId('main-focus-button')).toHaveFocus());
479
477
 
480
478
  // Test hiding sidebar
481
479
  const hideButton = canvas.getByTestId('hide-sidebar-button');
@@ -791,8 +789,7 @@ export const VisualStates: Story = {
791
789
  await expect(canvas.getByTestId('expanded-footer')).toBeInTheDocument();
792
790
 
793
791
  // Test sidebar width when expanded
794
- let sidebarStyles = window.getComputedStyle(sidebar);
795
- await expect(sidebarStyles.width).toBe('280px');
792
+ await expect(window.getComputedStyle(sidebar).width).toBe('280px');
796
793
 
797
794
  // Test collapsing
798
795
  const collapseToggle = canvas.getByTestId('collapse-toggle');
@@ -802,10 +799,11 @@ export const VisualStates: Story = {
802
799
  expect(canvas.getByTestId('collapse-status')).toHaveTextContent('Sidebar is collapsed');
803
800
  });
804
801
 
805
- // Test sidebar width when collapsed
802
+ // Test sidebar width when collapsed. Read the computed style inside the
803
+ // waitFor rather than reassigning an outer variable from it — the callback
804
+ // reruns, so the shared binding held whichever value the last retry left.
806
805
  await waitFor(() => {
807
- sidebarStyles = window.getComputedStyle(sidebar);
808
- expect(sidebarStyles.width).toBe('64px');
806
+ expect(window.getComputedStyle(sidebar).width).toBe('64px');
809
807
  });
810
808
 
811
809
  // Test collapsed avatar is visible
@@ -0,0 +1,33 @@
1
+ import type { SkeletonProps } from './Skeleton.types';
2
+
3
+ type SkeletonDefaultedKeys =
4
+ | 'variant'
5
+ | 'animation'
6
+ | 'count'
7
+ | 'spacing'
8
+ | 'intensity'
9
+ | 'glassmorphism'
10
+ | 'shimmer';
11
+
12
+ type ResolvedSkeletonProps = SkeletonProps &
13
+ Required<Pick<SkeletonProps, SkeletonDefaultedKeys>>;
14
+
15
+ const SKELETON_DEFAULTS: Pick<SkeletonProps, SkeletonDefaultedKeys> = {
16
+ variant: 'text',
17
+ animation: 'pulse',
18
+ count: 1,
19
+ spacing: 1,
20
+ intensity: 'medium',
21
+ glassmorphism: false,
22
+ shimmer: false,
23
+ };
24
+
25
+ // Strips explicitly-undefined props before the merge, so `count={undefined}` still
26
+ // falls back to the default exactly as a destructuring default would.
27
+ const definedProps = (props: SkeletonProps): Partial<SkeletonProps> =>
28
+ Object.fromEntries(
29
+ Object.entries(props).filter(([, value]) => value !== undefined),
30
+ ) as Partial<SkeletonProps>;
31
+
32
+ export const resolveSkeletonProps = (props: SkeletonProps): ResolvedSkeletonProps =>
33
+ ({ ...SKELETON_DEFAULTS, ...definedProps(props) }) as ResolvedSkeletonProps;