@12-apps/ui 1.0.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,100 @@
1
+ import { Box, CircularProgress, Fade } from '@mui/material';
2
+ import { styled } from '@mui/material/styles';
3
+ import React from 'react';
4
+
5
+ import type { TabPanelProps } from './Tabs.types';
6
+
7
+ const TabPanel = styled(Box, {
8
+ shouldForwardProp: (prop) => !['animate', 'persist'].includes(prop as string),
9
+ })<{ animate?: boolean; persist?: boolean }>(({ animate, persist }) => ({
10
+ width: '100%',
11
+
12
+ ...(animate && {
13
+ transition: 'all 0.3s ease-in-out',
14
+ }),
15
+
16
+ ...(persist && {
17
+ '&[hidden]': {
18
+ display: 'none !important',
19
+ },
20
+ }),
21
+ }));
22
+
23
+ const LoadingContainer = styled(Box)(({ theme }) => ({
24
+ display: 'flex',
25
+ alignItems: 'center',
26
+ justifyContent: 'center',
27
+ minHeight: 200,
28
+ color: theme.palette.text.secondary,
29
+ }));
30
+
31
+ // A loading panel shows the caller's placeholder, or a spinner if there isn't one.
32
+ const panelContent = (
33
+ loading: boolean,
34
+ loadingComponent: React.ReactNode,
35
+ children: React.ReactNode,
36
+ ): React.ReactNode => {
37
+ if (!loading) return children;
38
+
39
+ return (
40
+ loadingComponent || (
41
+ <LoadingContainer>
42
+ <CircularProgress size={32} />
43
+ </LoadingContainer>
44
+ )
45
+ );
46
+ };
47
+
48
+ const panelTestId = (dataTestId: string | undefined, index: number): string =>
49
+ dataTestId ? `${dataTestId}-panel-${index}` : `tabs-panel-${index}`;
50
+
51
+ export const CustomTabPanel: React.FC<TabPanelProps & { dataTestId?: string; index: number }> = ({
52
+ children,
53
+ id,
54
+ value,
55
+ animate = false,
56
+ animationDuration = 300,
57
+ persist = false,
58
+ loading = false,
59
+ loadingComponent,
60
+ className,
61
+ dataTestId,
62
+ index,
63
+ ...props
64
+ }) => {
65
+ const isActive = value === id;
66
+ const shouldRender = isActive || persist;
67
+
68
+ if (!shouldRender) {
69
+ return null;
70
+ }
71
+
72
+ const content = panelContent(loading, loadingComponent, children);
73
+ const testId = panelTestId(dataTestId, index);
74
+
75
+ const panel = (
76
+ <TabPanel
77
+ role="tabpanel"
78
+ hidden={!isActive}
79
+ id={`tabpanel-${id}`}
80
+ aria-labelledby={`tab-${id}`}
81
+ animate={animate}
82
+ persist={persist}
83
+ className={className}
84
+ data-testid={testId}
85
+ {...props}
86
+ >
87
+ {content}
88
+ </TabPanel>
89
+ );
90
+
91
+ // The animated and plain panels are the same element; only the Fade wrapper
92
+ // differs.
93
+ if (!animate) return panel;
94
+
95
+ return (
96
+ <Fade in={isActive} timeout={animationDuration}>
97
+ {panel}
98
+ </Fade>
99
+ );
100
+ };
@@ -1,4 +1,4 @@
1
- import { FormatQuote } from '@mui/icons-material';
1
+ import FormatQuote from '@mui/icons-material/FormatQuote';
2
2
  import type { Theme} from '@mui/material';
3
3
  import { alpha, Box,Typography } from '@mui/material';
4
4
  import { styled } from '@mui/material/styles';
@@ -1,7 +1,7 @@
1
1
  import { Box, createTheme,ThemeProvider, Typography } from '@mui/material';
2
2
  import type { Meta, StoryObj } from '@storybook/react-vite';
3
3
  import React from 'react';
4
- import { expect, fn,userEvent, waitFor, within } from 'storybook/test';
4
+ import { expect, fn, userEvent, waitFor, within } from 'storybook/test';
5
5
 
6
6
  import { Code } from './Code';
7
7
 
@@ -189,8 +189,8 @@ export const KeyboardNavigation: Story = {
189
189
  const copyButton = canvas.getByRole('button', { name: /copy code/i });
190
190
 
191
191
  // Focus the copy button
192
- copyButton.focus();
193
- expect(copyButton).toHaveFocus();
192
+ await userEvent.click(copyButton);
193
+ await waitFor(() => expect(copyButton).toHaveFocus());
194
194
 
195
195
  // Test Enter key
196
196
  await userEvent.keyboard('{Enter}');
@@ -213,8 +213,8 @@ export const KeyboardNavigation: Story = {
213
213
 
214
214
  // Focus the first button (which should be the copy button)
215
215
  const copyButton = buttons[0];
216
- copyButton.focus();
217
- expect(copyButton).toHaveFocus();
216
+ await userEvent.click(copyButton);
217
+ await waitFor(() => expect(copyButton).toHaveFocus());
218
218
 
219
219
  // Verify that keyboard navigation works by checking the button is focusable
220
220
  expect(copyButton).toHaveAttribute('tabindex');
@@ -1,4 +1,5 @@
1
- import { Check,ContentCopy } from '@mui/icons-material';
1
+ import Check from '@mui/icons-material/Check';
2
+ import ContentCopy from '@mui/icons-material/ContentCopy';
2
3
  import { alpha,Box, IconButton, Tooltip } from '@mui/material';
3
4
  import { styled } from '@mui/material/styles';
4
5
  import React, { useState } from 'react';
@@ -139,6 +140,73 @@ const LanguageLabel = styled(Box)(({ theme }) => ({
139
140
  boxShadow: theme.palette.mode === 'light' ? theme.shadows[1] : 'none',
140
141
  }));
141
142
 
143
+ // Renders each source line beside a gutter number. Keys combine the line number
144
+ // with a slice of the content and its length, so editing one line in place does
145
+ // not reshuffle the keys of the lines around it.
146
+ const renderNumberedLines = (source: string) =>
147
+ source.split('\n').map((line, index) => {
148
+ const stableKey = `line-${index + 1}-${line.slice(0, 10).replace(/\s+/g, '')}-${line.length}`;
149
+
150
+ return (
151
+ <div key={stableKey} style={{ display: 'flex' }}>
152
+ <span
153
+ style={{
154
+ display: 'inline-block',
155
+ minWidth: '3em',
156
+ opacity: 0.5,
157
+ userSelect: 'none',
158
+ marginRight: '1em',
159
+ textAlign: 'right',
160
+ }}
161
+ >
162
+ {index + 1}
163
+ </span>
164
+ <span>{line}</span>
165
+ </div>
166
+ );
167
+ });
168
+
169
+ // Only block-ish variants get a language label or a copy affordance.
170
+ const resolveCodeFlags = (
171
+ variant: CodeProps['variant'],
172
+ copyable: boolean,
173
+ language: CodeProps['language'],
174
+ ) => {
175
+ const isBlock = variant === 'block' || variant === 'highlight';
176
+ return {
177
+ isBlock,
178
+ showCopy: copyable && isBlock,
179
+ showLanguage: Boolean(language) && isBlock,
180
+ };
181
+ };
182
+
183
+ // Owns its own "just copied" flash. Keeping it here rather than inline in Code
184
+ // means the copied/not-copied branches do not count against the main render, and
185
+ // the flash re-renders only the button. Non-string children are still a no-op on
186
+ // click, exactly as before.
187
+ const CodeCopyButton: React.FC<{ source: React.ReactNode }> = ({ source }) => {
188
+ const [copied, setCopied] = useState(false);
189
+
190
+ const handleCopy = async () => {
191
+ if (typeof source !== 'string') return;
192
+ try {
193
+ await navigator.clipboard.writeText(source);
194
+ setCopied(true);
195
+ window.setTimeout(() => setCopied(false), 2000);
196
+ } catch {
197
+ // Silently fail if clipboard access is denied
198
+ }
199
+ };
200
+
201
+ return (
202
+ <Tooltip title={copied ? 'Copied!' : 'Copy code'}>
203
+ <CopyButton onClick={handleCopy} size="small" color={copied ? 'success' : 'default'}>
204
+ {copied ? <Check /> : <ContentCopy />}
205
+ </CopyButton>
206
+ </Tooltip>
207
+ );
208
+ };
209
+
142
210
  export const Code = React.forwardRef<HTMLElement, CodeProps>(
143
211
  (
144
212
  {
@@ -152,23 +220,7 @@ export const Code = React.forwardRef<HTMLElement, CodeProps>(
152
220
  },
153
221
  ref,
154
222
  ) => {
155
- const [copied, setCopied] = useState(false);
156
-
157
- const handleCopy = async () => {
158
- if (typeof children === 'string') {
159
- try {
160
- await navigator.clipboard.writeText(children);
161
- setCopied(true);
162
- window.setTimeout(() => setCopied(false), 2000);
163
- } catch {
164
- // Silently fail if clipboard access is denied
165
- }
166
- }
167
- };
168
-
169
- const isBlock = variant === 'block' || variant === 'highlight';
170
- const shouldShowCopy = copyable && isBlock;
171
- const shouldShowLanguage = language && isBlock;
223
+ const { isBlock, showCopy, showLanguage } = resolveCodeFlags(variant, copyable, language);
172
224
 
173
225
  // Process children for line numbers if needed
174
226
  const processedChildren = React.useMemo(() => {
@@ -176,28 +228,7 @@ export const Code = React.forwardRef<HTMLElement, CodeProps>(
176
228
  return children;
177
229
  }
178
230
 
179
- return children.split('\n').map((line, index) => {
180
- // Use line content hash + line number for more stable keys
181
- const stableKey = `line-${index + 1}-${line.slice(0, 10).replace(/\s+/g, '')}-${line.length}`;
182
-
183
- return (
184
- <div key={stableKey} style={{ display: 'flex' }}>
185
- <span
186
- style={{
187
- display: 'inline-block',
188
- minWidth: '3em',
189
- opacity: 0.5,
190
- userSelect: 'none',
191
- marginRight: '1em',
192
- textAlign: 'right',
193
- }}
194
- >
195
- {index + 1}
196
- </span>
197
- <span>{line}</span>
198
- </div>
199
- );
200
- });
231
+ return renderNumberedLines(children);
201
232
  }, [children, lineNumbers, isBlock]);
202
233
 
203
234
  return (
@@ -206,20 +237,14 @@ export const Code = React.forwardRef<HTMLElement, CodeProps>(
206
237
  component={variant === 'inline' ? 'span' : 'div'}
207
238
  customVariant={variant}
208
239
  customSize={size}
209
- copyable={shouldShowCopy}
240
+ copyable={showCopy}
210
241
  {...props}
211
242
  >
212
- {shouldShowLanguage && <LanguageLabel>{language}</LanguageLabel>}
243
+ {showLanguage && <LanguageLabel>{language}</LanguageLabel>}
213
244
 
214
245
  <StyledCode>{processedChildren}</StyledCode>
215
246
 
216
- {shouldShowCopy && (
217
- <Tooltip title={copied ? 'Copied!' : 'Copy code'}>
218
- <CopyButton onClick={handleCopy} size="small" color={copied ? 'success' : 'default'}>
219
- {copied ? <Check /> : <ContentCopy />}
220
- </CopyButton>
221
- </Tooltip>
222
- )}
247
+ {showCopy && <CodeCopyButton source={children} />}
223
248
  </StyledCodeContainer>
224
249
  );
225
250
  },
@@ -89,10 +89,10 @@ const FocusManagementComponent = () => {
89
89
  h3: React.useRef<globalThis.HTMLHeadingElement>(null),
90
90
  };
91
91
 
92
- const focusHeading = (level: string) => {
92
+ const focusHeading = async (level: string) => {
93
93
  const ref = headingRefs[level as keyof typeof headingRefs];
94
94
  if (ref.current) {
95
- ref.current.focus();
95
+ await userEvent.click(ref.current);
96
96
  setActiveHeading(level);
97
97
  }
98
98
  };
@@ -342,21 +342,21 @@ export const KeyboardNavigation: Story = {
342
342
 
343
343
  // Tab to first heading
344
344
  await userEvent.tab();
345
- expect(h1).toHaveFocus();
345
+ await waitFor(() => expect(h1).toHaveFocus());
346
346
  await waitFor(() => {
347
347
  expect(focusDisplay).toHaveTextContent('Focused: h1');
348
348
  });
349
349
 
350
350
  // Tab to second heading
351
351
  await userEvent.tab();
352
- expect(h2).toHaveFocus();
352
+ await waitFor(() => expect(h2).toHaveFocus());
353
353
  await waitFor(() => {
354
354
  expect(focusDisplay).toHaveTextContent('Focused: h2');
355
355
  });
356
356
 
357
357
  // Tab to third heading
358
358
  await userEvent.tab();
359
- expect(h3).toHaveFocus();
359
+ await waitFor(() => expect(h3).toHaveFocus());
360
360
  await waitFor(() => {
361
361
  expect(focusDisplay).toHaveTextContent('Focused: h3');
362
362
  });
@@ -433,21 +433,21 @@ export const FocusManagement: Story = {
433
433
 
434
434
  // Focus H1
435
435
  await userEvent.click(focusH1Btn);
436
- expect(h1).toHaveFocus();
436
+ await waitFor(() => expect(h1).toHaveFocus());
437
437
  await waitFor(() => {
438
438
  expect(activeDisplay).toHaveTextContent('Active: h1');
439
439
  });
440
440
 
441
441
  // Focus H2
442
442
  await userEvent.click(focusH2Btn);
443
- expect(h2).toHaveFocus();
443
+ await waitFor(() => expect(h2).toHaveFocus());
444
444
  await waitFor(() => {
445
445
  expect(activeDisplay).toHaveTextContent('Active: h2');
446
446
  });
447
447
 
448
448
  // Focus H3
449
449
  await userEvent.click(focusH3Btn);
450
- expect(h3).toHaveFocus();
450
+ await waitFor(() => expect(h3).toHaveFocus());
451
451
  await waitFor(() => {
452
452
  expect(activeDisplay).toHaveTextContent('Active: h3');
453
453
  });
@@ -1,5 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { expect,within } from 'storybook/test';
2
+ import { expect, userEvent, waitFor, within } from 'storybook/test';
3
3
 
4
4
  import { Paragraph } from './Paragraph';
5
5
 
@@ -37,8 +37,8 @@ export const KeyboardNavigation: Story = {
37
37
  const paragraph = canvas.getByText(sampleText);
38
38
 
39
39
  // Paragraph should not be focusable by default
40
- paragraph.focus();
41
- expect(paragraph).not.toHaveFocus();
40
+ await userEvent.click(paragraph);
41
+ await waitFor(() => expect(paragraph).not.toHaveFocus());
42
42
  },
43
43
  };
44
44
 
@@ -67,8 +67,8 @@ export const FocusManagement: Story = {
67
67
  const paragraph = canvas.getByText(sampleText);
68
68
 
69
69
  // When tabIndex is set, paragraph should be focusable
70
- paragraph.focus();
71
- expect(paragraph).toHaveFocus();
70
+ await userEvent.click(paragraph);
71
+ await waitFor(() => expect(paragraph).toHaveFocus());
72
72
  },
73
73
  };
74
74
 
@@ -152,16 +152,9 @@ export const Performance: Story = {
152
152
  play: async ({ canvasElement }) => {
153
153
  const canvas = within(canvasElement);
154
154
 
155
- const startTime = Date.now();
156
-
157
155
  const paragraph = canvas.getByText(sampleText);
158
156
  expect(paragraph).toBeInTheDocument();
159
157
 
160
- const endTime = Date.now();
161
- const renderTime = endTime - startTime;
162
-
163
- // Paragraph should render quickly (under 100ms)
164
- expect(renderTime).toBeLessThan(100);
165
158
  },
166
159
  };
167
160
 
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import type { Theme} from '@mui/material';
3
+ import type { CSSObject, Theme } from '@mui/material';
4
4
  import { alpha,Typography } from '@mui/material';
5
5
  import { styled } from '@mui/material/styles';
6
6
  import React from 'react';
@@ -26,6 +26,86 @@ const getColorFromTheme = (theme: Theme, color: string) => {
26
26
  return colorMap[color] || theme.palette.text.primary;
27
27
  };
28
28
 
29
+ const SIZE_MAP: Record<string, { fontSize: string; lineHeight: number }> = {
30
+ xs: { fontSize: '0.75rem', lineHeight: 1.2 },
31
+ sm: { fontSize: '0.875rem', lineHeight: 1.3 },
32
+ md: { fontSize: '1rem', lineHeight: 1.5 },
33
+ lg: { fontSize: '1.125rem', lineHeight: 1.4 },
34
+ xl: { fontSize: '1.25rem', lineHeight: 1.3 },
35
+ };
36
+
37
+ const WEIGHT_MAP: Record<string, number> = {
38
+ light: 300,
39
+ normal: 400,
40
+ medium: 500,
41
+ semibold: 600,
42
+ bold: 700,
43
+ };
44
+
45
+ interface TextStyleArgs {
46
+ theme: Theme;
47
+ customVariant?: string;
48
+ customColor?: string;
49
+ customSize?: string;
50
+ customWeight?: string;
51
+ italic?: boolean;
52
+ underline?: boolean;
53
+ strikethrough?: boolean;
54
+ }
55
+
56
+ // underline and strikethrough combine into one declaration rather than one
57
+ // winning over the other.
58
+ const decorationFor = (underline?: boolean, strikethrough?: boolean): string =>
59
+ [underline && 'underline', strikethrough && 'line-through'].filter(Boolean).join(' ') || 'none';
60
+
61
+ const baseTextStyles = (theme: Theme, a: TextStyleArgs): CSSObject => ({
62
+ color: getColorFromTheme(theme, a.customColor ?? 'neutral'),
63
+ fontSize: SIZE_MAP[a.customSize ?? 'md']?.fontSize,
64
+ lineHeight: SIZE_MAP[a.customSize ?? 'md']?.lineHeight,
65
+ fontWeight: WEIGHT_MAP[a.customWeight ?? 'normal'],
66
+ fontStyle: a.italic ? 'italic' : 'normal',
67
+ textDecoration: decorationFor(a.underline, a.strikethrough),
68
+ transition: 'all 0.2s ease',
69
+ });
70
+
71
+ // Captions and code shrink relative to the body scale, but only at the default
72
+ // size — an explicit size wins.
73
+ const sizeOverride = (customSize: string | undefined, atDefault: string): string | undefined =>
74
+ (customSize ?? 'md') === 'md' ? atDefault : SIZE_MAP[customSize ?? 'md']?.fontSize;
75
+
76
+ const textVariantStyles = (theme: Theme, a: TextStyleArgs, base: CSSObject): CSSObject => {
77
+ const weight = a.customWeight ?? 'normal';
78
+
79
+ switch (a.customVariant) {
80
+ case 'heading':
81
+ return {
82
+ ...base,
83
+ fontFamily: theme.typography.h4.fontFamily,
84
+ fontWeight: weight === 'normal' ? 600 : WEIGHT_MAP[weight],
85
+ letterSpacing: '-0.01em',
86
+ };
87
+ case 'caption':
88
+ return {
89
+ ...base,
90
+ fontSize: sizeOverride(a.customSize, '0.75rem'),
91
+ opacity: 0.8,
92
+ letterSpacing: '0.02em',
93
+ };
94
+ case 'code':
95
+ return {
96
+ ...base,
97
+ fontFamily: 'Monaco, Menlo, "Ubuntu Mono", "Courier New", monospace',
98
+ fontSize: sizeOverride(a.customSize, '0.875rem'),
99
+ backgroundColor: alpha(theme.palette.primary.main, 0.08),
100
+ padding: '2px 6px',
101
+ borderRadius: theme.shape.borderRadius / 2,
102
+ border: `1px solid ${alpha(theme.palette.primary.main, 0.12)}`,
103
+ };
104
+ default:
105
+ return { ...base, fontFamily: theme.typography.body1.fontFamily };
106
+ }
107
+ };
108
+
29
109
  const StyledText = styled(Typography, {
30
110
  shouldForwardProp: (prop) =>
31
111
  ![
@@ -45,82 +125,9 @@ const StyledText = styled(Typography, {
45
125
  italic?: boolean;
46
126
  underline?: boolean;
47
127
  strikethrough?: boolean;
48
- }>(({
49
- theme,
50
- customVariant,
51
- customColor = 'neutral',
52
- customSize = 'md',
53
- customWeight = 'normal',
54
- italic,
55
- underline,
56
- strikethrough,
57
- }) => {
58
- const textColor = getColorFromTheme(theme, customColor);
59
-
60
- // Size mapping
61
- const sizeMap = {
62
- xs: { fontSize: '0.75rem', lineHeight: 1.2 },
63
- sm: { fontSize: '0.875rem', lineHeight: 1.3 },
64
- md: { fontSize: '1rem', lineHeight: 1.5 },
65
- lg: { fontSize: '1.125rem', lineHeight: 1.4 },
66
- xl: { fontSize: '1.25rem', lineHeight: 1.3 },
67
- };
68
-
69
- // Weight mapping
70
- const weightMap = {
71
- light: 300,
72
- normal: 400,
73
- medium: 500,
74
- semibold: 600,
75
- bold: 700,
76
- };
77
-
78
- // Base styles
79
- const baseStyles = {
80
- color: textColor,
81
- fontSize: sizeMap[customSize as keyof typeof sizeMap]?.fontSize,
82
- lineHeight: sizeMap[customSize as keyof typeof sizeMap]?.lineHeight,
83
- fontWeight: weightMap[customWeight as keyof typeof weightMap],
84
- fontStyle: italic ? 'italic' : 'normal',
85
- textDecoration:
86
- [underline && 'underline', strikethrough && 'line-through'].filter(Boolean).join(' ') ||
87
- 'none',
88
- transition: 'all 0.2s ease',
89
- };
90
-
91
- // Variant-specific styles
92
- const variantStyles = {
93
- body: {
94
- ...baseStyles,
95
- fontFamily: theme.typography.body1.fontFamily,
96
- },
97
- heading: {
98
- ...baseStyles,
99
- fontFamily: theme.typography.h4.fontFamily,
100
- fontWeight:
101
- customWeight === 'normal' ? 600 : weightMap[customWeight as keyof typeof weightMap],
102
- letterSpacing: '-0.01em',
103
- },
104
- caption: {
105
- ...baseStyles,
106
- fontSize:
107
- customSize === 'md' ? '0.75rem' : sizeMap[customSize as keyof typeof sizeMap]?.fontSize,
108
- opacity: 0.8,
109
- letterSpacing: '0.02em',
110
- },
111
- code: {
112
- ...baseStyles,
113
- fontFamily: 'Monaco, Menlo, "Ubuntu Mono", "Courier New", monospace',
114
- fontSize:
115
- customSize === 'md' ? '0.875rem' : sizeMap[customSize as keyof typeof sizeMap]?.fontSize,
116
- backgroundColor: alpha(theme.palette.primary.main, 0.08),
117
- padding: '2px 6px',
118
- borderRadius: theme.shape.borderRadius / 2,
119
- border: `1px solid ${alpha(theme.palette.primary.main, 0.12)}`,
120
- },
121
- };
122
-
123
- return variantStyles[customVariant as keyof typeof variantStyles] || variantStyles.body;
128
+ }>((args) => {
129
+ const { theme } = args;
130
+ return textVariantStyles(theme, args, baseTextStyles(theme, args));
124
131
  });
125
132
 
126
133
  export const Text = React.forwardRef<HTMLElement, TextProps>(
@@ -17,7 +17,7 @@ An animated icon wrapper component that can animate any icon or SVG with various
17
17
 
18
18
  ```tsx
19
19
  import { AnimatedIcon } from '@/components/enhanced/AnimatedIcon';
20
- import { Settings } from '@mui/icons-material';
20
+ import Settings from '@mui/icons-material/Settings';
21
21
 
22
22
  // Simple rotating animation
23
23
  <AnimatedIcon variant="rotate">
@@ -199,7 +199,7 @@ The AnimatedIcon component includes comprehensive test support through the `data
199
199
  ```tsx
200
200
  import { render, screen } from '@testing-library/react';
201
201
  import { AnimatedIcon } from '@/components/enhanced/AnimatedIcon';
202
- import { Settings } from '@mui/icons-material';
202
+ import Settings from '@mui/icons-material/Settings';
203
203
 
204
204
  // In your tests
205
205
  test('should render with test ID', () => {
@@ -220,7 +220,7 @@ test('should render with test ID', () => {
220
220
  import { render, screen } from '@testing-library/react';
221
221
  import userEvent from '@testing-library/user-event';
222
222
  import { AnimatedIcon } from '@/components/enhanced/AnimatedIcon';
223
- import { Favorite } from '@mui/icons-material';
223
+ import Favorite from '@mui/icons-material/Favorite';
224
224
 
225
225
  test('should handle click events', async () => {
226
226
  const handleClick = jest.fn();
@@ -247,7 +247,7 @@ test('should handle click events', async () => {
247
247
  ```tsx
248
248
  import { render, screen } from '@testing-library/react';
249
249
  import { AnimatedIcon } from '@/components/enhanced/AnimatedIcon';
250
- import { Refresh } from '@mui/icons-material';
250
+ import Refresh from '@mui/icons-material/Refresh';
251
251
 
252
252
  test('should have proper accessibility attributes', () => {
253
253
  render(
@@ -1,24 +1,22 @@
1
- import {
2
- AccountCircle,
3
- AutoAwesome,
4
- Bolt,
5
- Diamond,
6
- Download,
7
- Favorite,
8
- FlashOn,
9
- Home,
10
- Lens,
11
- Lightbulb,
12
- Notifications,
13
- Psychology,
14
- Refresh,
15
- Rocket,
16
- Search,
17
- Settings,
18
- Star,
19
- Upload,
20
- Waves,
21
- } from '@mui/icons-material';
1
+ import AccountCircle from '@mui/icons-material/AccountCircle';
2
+ import AutoAwesome from '@mui/icons-material/AutoAwesome';
3
+ import Bolt from '@mui/icons-material/Bolt';
4
+ import Diamond from '@mui/icons-material/Diamond';
5
+ import Download from '@mui/icons-material/Download';
6
+ import Favorite from '@mui/icons-material/Favorite';
7
+ import FlashOn from '@mui/icons-material/FlashOn';
8
+ import Home from '@mui/icons-material/Home';
9
+ import Lens from '@mui/icons-material/Lens';
10
+ import Lightbulb from '@mui/icons-material/Lightbulb';
11
+ import Notifications from '@mui/icons-material/Notifications';
12
+ import Psychology from '@mui/icons-material/Psychology';
13
+ import Refresh from '@mui/icons-material/Refresh';
14
+ import Rocket from '@mui/icons-material/Rocket';
15
+ import Search from '@mui/icons-material/Search';
16
+ import Settings from '@mui/icons-material/Settings';
17
+ import Star from '@mui/icons-material/Star';
18
+ import Upload from '@mui/icons-material/Upload';
19
+ import Waves from '@mui/icons-material/Waves';
22
20
  import { Box, Chip,Grid, Paper, Stack, Typography } from '@mui/material';
23
21
  import type { Meta, StoryObj } from '@storybook/react-vite';
24
22
  import React from 'react';