@12-apps/ui 1.0.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (448) hide show
  1. package/components-catalog.md +14 -0
  2. package/package.json +42 -27
  3. package/src/__tests__/data-grid.test.tsx +125 -0
  4. package/src/__tests__/package-wiring.test.ts +12 -8
  5. package/src/__tests__/social-login-button.test.tsx +5 -5
  6. package/src/__tests__/viewport.test.ts +50 -0
  7. package/src/charts/index.ts +8 -0
  8. package/src/components/data-display/Alert/Alert.md +1 -1
  9. package/src/components/data-display/Alert/Alert.stories.tsx +5 -7
  10. package/src/components/data-display/Alert/Alert.styles.tsx +255 -0
  11. package/src/components/data-display/Alert/Alert.test.stories.tsx +11 -13
  12. package/src/components/data-display/Alert/Alert.tsx +135 -328
  13. package/src/components/data-display/AlertDialog/AlertDialog.stories.tsx +3 -1
  14. package/src/components/data-display/AlertDialog/AlertDialog.tsx +191 -78
  15. package/src/components/data-display/AlertDialog/AlertDialog.types.ts +8 -1
  16. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.test.stories.tsx +5 -5
  17. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.tsx +44 -35
  18. package/src/components/data-display/Avatar/Avatar.stories.tsx +4 -1
  19. package/src/components/data-display/Avatar/Avatar.test.stories.tsx +5 -3
  20. package/src/components/data-display/Avatar/Avatar.tsx +154 -450
  21. package/src/components/data-display/Avatar/Avatar.view.tsx +396 -0
  22. package/src/components/data-display/Badge/Badge.animations.ts +67 -0
  23. package/src/components/data-display/Badge/Badge.helpers.ts +74 -0
  24. package/src/components/data-display/Badge/Badge.stories.tsx +14 -16
  25. package/src/components/data-display/Badge/Badge.styles.ts +261 -0
  26. package/src/components/data-display/Badge/Badge.test.stories.tsx +32 -31
  27. package/src/components/data-display/Badge/Badge.tsx +151 -557
  28. package/src/components/data-display/Badge/Badge.variants.ts +106 -0
  29. package/src/components/data-display/Badge/BadgeContent.tsx +107 -0
  30. package/src/components/data-display/Banner/Banner.stories.tsx +5 -1
  31. package/src/components/data-display/Banner/Banner.styles.ts +120 -0
  32. package/src/components/data-display/Banner/Banner.tsx +179 -224
  33. package/src/components/data-display/Chart/Chart.md +48 -1
  34. package/src/components/data-display/Chart/Chart.tsx +82 -500
  35. package/src/components/data-display/Chart/Chart.types.ts +2 -0
  36. package/src/components/data-display/Chart/ChartComposables.tsx +121 -0
  37. package/src/components/data-display/Chart/ChartSpec.types.ts +70 -0
  38. package/src/components/data-display/Chart/SpecChart.stories.tsx +150 -0
  39. package/src/components/data-display/Chart/SpecChart.test.stories.tsx +56 -0
  40. package/src/components/data-display/Chart/SpecChart.tsx +53 -0
  41. package/src/components/data-display/Chart/__tests__/SpecChart.test.tsx +60 -0
  42. package/src/components/data-display/Chart/__tests__/chart-format.test.ts +43 -0
  43. package/src/components/data-display/Chart/__tests__/chart-spec.test.ts +119 -0
  44. package/src/components/data-display/Chart/chart-format.ts +26 -0
  45. package/src/components/data-display/Chart/chart-internals.ts +148 -0
  46. package/src/components/data-display/Chart/chart-renderers.tsx +338 -0
  47. package/src/components/data-display/Chart/chart-spec-registry.ts +74 -0
  48. package/src/components/data-display/Chart/chart-spec.ts +171 -0
  49. package/src/components/data-display/Chart/index.ts +30 -0
  50. package/src/components/data-display/Chip/Chip.helpers.tsx +131 -0
  51. package/src/components/data-display/Chip/Chip.stories.tsx +2 -1
  52. package/src/components/data-display/Chip/Chip.test.stories.tsx +11 -8
  53. package/src/components/data-display/Chip/Chip.tsx +31 -94
  54. package/src/components/data-display/DataGrid/DataGrid.body.tsx +141 -0
  55. package/src/components/data-display/DataGrid/DataGrid.cells.tsx +238 -0
  56. package/src/components/data-display/DataGrid/DataGrid.model.ts +315 -0
  57. package/src/components/data-display/DataGrid/DataGrid.rows.ts +112 -0
  58. package/src/components/data-display/DataGrid/DataGrid.states.tsx +102 -0
  59. package/src/components/data-display/DataGrid/DataGrid.test.stories.tsx +6 -12
  60. package/src/components/data-display/DataGrid/DataGrid.tsx +129 -725
  61. package/src/components/data-display/DataViews/DataViewsGrid.tsx +187 -0
  62. package/src/components/data-display/DataViews/DataViewsTableBase.tsx +400 -0
  63. package/src/components/data-display/DataViews/ManageViewsDialog.tsx +140 -0
  64. package/src/components/data-display/DataViews/SaveViewModal.tsx +289 -0
  65. package/src/components/data-display/DataViews/__tests__/DataViewsGrid.test.tsx +271 -0
  66. package/src/components/data-display/DataViews/__tests__/DataViewsTableBase.test.tsx +134 -0
  67. package/src/components/data-display/DataViews/__tests__/SaveViewModal.test.tsx +83 -0
  68. package/src/components/data-display/DataViews/__tests__/data-views-filter.test.ts +115 -0
  69. package/src/components/data-display/DataViews/__tests__/data-views-preview.test.ts +53 -0
  70. package/src/components/data-display/DataViews/__tests__/range-pill.test.tsx +114 -0
  71. package/src/components/data-display/DataViews/base-card.stories.tsx +136 -0
  72. package/src/components/data-display/DataViews/base-card.tsx +278 -0
  73. package/src/components/data-display/DataViews/data-views-filter-panel.tsx +184 -0
  74. package/src/components/data-display/DataViews/data-views-filter.ts +138 -0
  75. package/src/components/data-display/DataViews/data-views-grid-helpers.tsx +248 -0
  76. package/src/components/data-display/DataViews/data-views-grid-parts.tsx +400 -0
  77. package/src/components/data-display/DataViews/data-views-inline-bar.tsx +257 -0
  78. package/src/components/data-display/DataViews/data-views-layout-context.tsx +176 -0
  79. package/src/components/data-display/DataViews/data-views-pagination.tsx +31 -0
  80. package/src/components/data-display/DataViews/data-views-preview.ts +53 -0
  81. package/src/components/data-display/DataViews/data-views-range-pill.tsx +277 -0
  82. package/src/components/data-display/DataViews/data-views-table-parts.tsx +150 -0
  83. package/src/components/data-display/DataViews/data-views-toolbar.tsx +149 -0
  84. package/src/components/data-display/DataViews/data-views-types.ts +312 -0
  85. package/src/components/data-display/DataViews/data-views-view-mutations.ts +68 -0
  86. package/src/components/data-display/DataViews/index.ts +33 -0
  87. package/src/components/data-display/DataViews/use-data-views-state.ts +349 -0
  88. package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.hooks.ts +104 -0
  89. package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.tsx +68 -118
  90. package/src/components/data-display/DescriptionItem/DescriptionItem.stories.tsx +1 -1
  91. package/src/components/data-display/DescriptionItem/DescriptionItem.tsx +52 -34
  92. package/src/components/data-display/EmptyState/EmptyState.test.stories.tsx +6 -6
  93. package/src/components/data-display/EmptyState/EmptyState.tsx +218 -135
  94. package/src/components/data-display/ErrorState/ErrorState.test.stories.tsx +2 -2
  95. package/src/components/data-display/ErrorState/ErrorState.tsx +83 -55
  96. package/src/components/data-display/HoverCard/HoverCard.stories.tsx +3 -1
  97. package/src/components/data-display/HoverCard/HoverCard.test.stories.tsx +5 -5
  98. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.hooks.ts +99 -0
  99. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.styles.ts +87 -0
  100. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.tsx +28 -155
  101. package/src/components/data-display/LazyImage/LazyImage.hooks.ts +203 -0
  102. package/src/components/data-display/LazyImage/LazyImage.md +1 -1
  103. package/src/components/data-display/LazyImage/LazyImage.stories.tsx +3 -3
  104. package/src/components/data-display/LazyImage/LazyImage.tsx +144 -243
  105. package/src/components/data-display/Lightbox/Lightbox.constants.ts +53 -0
  106. package/src/components/data-display/Lightbox/Lightbox.helpers.ts +39 -0
  107. package/src/components/data-display/Lightbox/Lightbox.hooks.ts +259 -0
  108. package/src/components/data-display/Lightbox/Lightbox.test.stories.tsx +28 -35
  109. package/src/components/data-display/Lightbox/Lightbox.tsx +98 -658
  110. package/src/components/data-display/Lightbox/LightboxControls.tsx +152 -0
  111. package/src/components/data-display/Lightbox/LightboxCurrentMedia.tsx +50 -0
  112. package/src/components/data-display/Lightbox/LightboxMedia.tsx +76 -0
  113. package/src/components/data-display/Lightbox/LightboxOverlay.tsx +83 -0
  114. package/src/components/data-display/Lightbox/LightboxStage.tsx +97 -0
  115. package/src/components/data-display/Lightbox/LightboxThumbnails.tsx +83 -0
  116. package/src/components/data-display/Lightbox/useLightbox.ts +80 -0
  117. package/src/components/data-display/LoadingState/LoadingState.helpers.ts +52 -0
  118. package/src/components/data-display/LoadingState/LoadingState.tsx +117 -87
  119. package/src/components/data-display/MapPreview/MapControlBar.tsx +116 -0
  120. package/src/components/data-display/MapPreview/MapDecorations.tsx +155 -0
  121. package/src/components/data-display/MapPreview/MapLayers.tsx +70 -0
  122. package/src/components/data-display/MapPreview/MapMarkers.tsx +84 -0
  123. package/src/components/data-display/MapPreview/MapOverlays.tsx +68 -0
  124. package/src/components/data-display/MapPreview/MapPreview.constants.ts +19 -0
  125. package/src/components/data-display/MapPreview/MapPreview.helpers.ts +63 -0
  126. package/src/components/data-display/MapPreview/MapPreview.hooks.ts +265 -0
  127. package/src/components/data-display/MapPreview/MapPreview.test.stories.tsx +14 -10
  128. package/src/components/data-display/MapPreview/MapPreview.tsx +52 -882
  129. package/src/components/data-display/MapPreview/MapPreview.types.ts +8 -1
  130. package/src/components/data-display/MapPreview/MapSearchBar.tsx +64 -0
  131. package/src/components/data-display/MapPreview/MapTiles.tsx +70 -0
  132. package/src/components/data-display/MapPreview/StaticMapView.tsx +63 -0
  133. package/src/components/data-display/MapPreview/mapProjection.ts +52 -0
  134. package/src/components/data-display/MapPreview/mapSurface.ts +37 -0
  135. package/src/components/data-display/MapPreview/useMapPreview.ts +62 -0
  136. package/src/components/data-display/Popover/Popover.test.stories.tsx +13 -19
  137. package/src/components/data-display/Progress/Progress.helpers.ts +37 -0
  138. package/src/components/data-display/Progress/Progress.styles.ts +101 -0
  139. package/src/components/data-display/Progress/Progress.tsx +185 -213
  140. package/src/components/data-display/SectionOnboarding/SectionOnboarding.stories.tsx +1 -1
  141. package/src/components/data-display/SectionOnboarding/SectionOnboarding.tsx +1 -1
  142. package/src/components/data-display/StatCard/StatCard.md +117 -0
  143. package/src/components/data-display/StatCard/StatCard.stories.tsx +167 -0
  144. package/src/components/data-display/StatCard/StatCard.test.stories.tsx +240 -0
  145. package/src/components/data-display/StatCard/StatCard.tsx +236 -0
  146. package/src/components/data-display/StatCard/StatCard.types.ts +62 -0
  147. package/src/components/data-display/StatCard/index.ts +7 -0
  148. package/src/components/data-display/Stepper/Stepper.test.stories.tsx +12 -19
  149. package/src/components/data-display/Stepper/Stepper.tsx +1 -1
  150. package/src/components/data-display/Table/Table.helpers.ts +31 -0
  151. package/src/components/data-display/Table/Table.hooks.ts +161 -0
  152. package/src/components/data-display/Table/Table.stories.tsx +3 -1
  153. package/src/components/data-display/Table/Table.styles.ts +223 -0
  154. package/src/components/data-display/Table/Table.test.stories.tsx +4 -4
  155. package/src/components/data-display/Table/Table.tsx +291 -748
  156. package/src/components/data-display/Table/TableParts.hooks.tsx +112 -0
  157. package/src/components/data-display/Table/TableParts.tsx +298 -0
  158. package/src/components/data-display/Table/TableStates.tsx +21 -0
  159. package/src/components/data-display/Timeline/Timeline.stories.tsx +10 -12
  160. package/src/components/data-display/Timeline/Timeline.test.stories.tsx +30 -44
  161. package/src/components/data-display/Timeline/Timeline.tsx +23 -284
  162. package/src/components/data-display/Timeline/TimelineRow.tsx +346 -0
  163. package/src/components/data-display/TimingDiagram/TimingDiagram.tsx +38 -311
  164. package/src/components/data-display/TimingDiagram/TimingDiagram.views.tsx +346 -0
  165. package/src/components/data-display/Tooltip/Tooltip.stories.tsx +4 -1
  166. package/src/components/data-display/Tooltip/Tooltip.test.stories.tsx +44 -58
  167. package/src/components/data-display/Tooltip/Tooltip.tsx +67 -62
  168. package/src/components/data-display/index.ts +1 -0
  169. package/src/components/feedback/ConfirmAction/ConfirmAction.hooks.ts +96 -0
  170. package/src/components/feedback/ConfirmAction/ConfirmAction.md +140 -0
  171. package/src/components/feedback/ConfirmAction/ConfirmAction.parts.tsx +154 -0
  172. package/src/components/feedback/ConfirmAction/ConfirmAction.stories.tsx +146 -0
  173. package/src/components/feedback/ConfirmAction/ConfirmAction.test.stories.tsx +114 -0
  174. package/src/components/feedback/ConfirmAction/ConfirmAction.tsx +46 -0
  175. package/src/components/feedback/ConfirmAction/ConfirmAction.types.ts +111 -0
  176. package/src/components/feedback/ConfirmAction/ConfirmButton.tsx +18 -0
  177. package/src/components/feedback/ConfirmAction/__tests__/confirm-action.test.tsx +288 -0
  178. package/src/components/feedback/ConfirmAction/index.ts +16 -0
  179. package/src/components/feedback/ConfirmAction/with-confirmation.tsx +112 -0
  180. package/src/components/feedback/Dialog/Dialog.styles.ts +4 -2
  181. package/src/components/feedback/Dialog/Dialog.tsx +26 -1
  182. package/src/components/feedback/Dialog/__tests__/dialog-content-spacing.test.tsx +66 -0
  183. package/src/components/feedback/Modal/Modal.md +1 -1
  184. package/src/components/feedback/Modal/Modal.stories.tsx +2 -2
  185. package/src/components/feedback/Sonner/Sonner.tsx +104 -288
  186. package/src/components/feedback/Sonner/Sonner.types.ts +7 -0
  187. package/src/components/feedback/Sonner/SonnerToast.tsx +216 -0
  188. package/src/components/feedback/StackedModal/StackedModal.hooks.ts +226 -0
  189. package/src/components/feedback/StackedModal/StackedModal.parts.tsx +311 -0
  190. package/src/components/feedback/StackedModal/StackedModal.stories.tsx +13 -15
  191. package/src/components/feedback/StackedModal/StackedModal.styles.ts +193 -0
  192. package/src/components/feedback/StackedModal/StackedModal.tsx +100 -619
  193. package/src/components/feedback/StackedModal/StackedModal.types.ts +17 -3
  194. package/src/components/feedback/StackedModal/__tests__/stacked-modal-viewport.test.tsx +104 -0
  195. package/src/components/feedback/StackedModal/modal-stack.tsx +119 -0
  196. package/src/components/feedback/Toast/Toast.tsx +92 -81
  197. package/src/components/feedback/TutorialOverlay/TutorialOverlay.geometry.ts +65 -0
  198. package/src/components/feedback/TutorialOverlay/TutorialOverlay.hooks.ts +185 -0
  199. package/src/components/feedback/TutorialOverlay/TutorialOverlay.test.stories.tsx +2 -2
  200. package/src/components/feedback/TutorialOverlay/TutorialOverlay.tsx +156 -414
  201. package/src/components/feedback/TutorialOverlay/TutorialStepBody.tsx +255 -0
  202. package/src/components/feedback/index.ts +1 -0
  203. package/src/components/form/AddressAutocomplete/AddressAutocomplete.helpers.ts +58 -0
  204. package/src/components/form/AddressAutocomplete/AddressAutocomplete.hooks.ts +93 -0
  205. package/src/components/form/AddressAutocomplete/AddressAutocomplete.mapper.ts +57 -0
  206. package/src/components/form/AddressAutocomplete/AddressAutocomplete.stories.tsx +4 -2
  207. package/src/components/form/AddressAutocomplete/AddressAutocomplete.test.stories.tsx +20 -16
  208. package/src/components/form/AddressAutocomplete/AddressAutocomplete.tsx +26 -829
  209. package/src/components/form/AddressAutocomplete/AddressAutocomplete.types.ts +11 -0
  210. package/src/components/form/AddressAutocomplete/AddressAutocompleteField.tsx +86 -0
  211. package/src/components/form/AddressAutocomplete/AddressFallbackField.tsx +64 -0
  212. package/src/components/form/AddressAutocomplete/AddressInputField.tsx +80 -0
  213. package/src/components/form/AddressAutocomplete/AddressOption.tsx +83 -0
  214. package/src/components/form/AddressAutocomplete/AddressSuggestionsPaper.tsx +24 -0
  215. package/src/components/form/AddressAutocomplete/AddressTextField.tsx +43 -0
  216. package/src/components/form/AddressAutocomplete/mockPlaces.ts +208 -0
  217. package/src/components/form/AddressAutocomplete/useAddressPredictions.ts +136 -0
  218. package/src/components/form/AddressAutocomplete/useAddressSelection.ts +113 -0
  219. package/src/components/form/AddressAutocomplete/useCurrentLocation.ts +116 -0
  220. package/src/components/form/AddressAutocomplete/useGoogleMapsAPI.ts +75 -0
  221. package/src/components/form/Button/Button.helpers.ts +36 -0
  222. package/src/components/form/Button/Button.stories.tsx +4 -1
  223. package/src/components/form/Button/Button.styles.ts +225 -0
  224. package/src/components/form/Button/Button.test.stories.tsx +25 -21
  225. package/src/components/form/Button/Button.tsx +45 -252
  226. package/src/components/form/Calendar/Calendar.dates.ts +100 -0
  227. package/src/components/form/Calendar/Calendar.helpers.ts +32 -0
  228. package/src/components/form/Calendar/Calendar.hooks.ts +278 -0
  229. package/src/components/form/Calendar/Calendar.keyboard.ts +32 -0
  230. package/src/components/form/Calendar/Calendar.selection.ts +156 -0
  231. package/src/components/form/Calendar/Calendar.test.stories.tsx +33 -34
  232. package/src/components/form/Calendar/Calendar.tsx +63 -551
  233. package/src/components/form/Calendar/Calendar.types.ts +16 -0
  234. package/src/components/form/Calendar/CalendarDay.tsx +127 -0
  235. package/src/components/form/Calendar/CalendarDayCell.tsx +52 -0
  236. package/src/components/form/Calendar/CalendarMonth.tsx +128 -0
  237. package/src/components/form/CepField/CepField.md +138 -0
  238. package/src/components/form/CepField/CepField.stories.tsx +138 -0
  239. package/src/components/form/CepField/CepField.test.stories.tsx +281 -0
  240. package/src/components/form/CepField/CepField.tsx +211 -0
  241. package/src/components/form/CepField/CepField.types.ts +73 -0
  242. package/src/components/form/CepField/index.ts +2 -0
  243. package/src/components/form/Checkbox/Checkbox.helpers.ts +28 -0
  244. package/src/components/form/Checkbox/Checkbox.tsx +19 -16
  245. package/src/components/form/CodeEditor/CodeEditor.helpers.ts +45 -0
  246. package/src/components/form/CodeEditor/CodeEditor.hooks.ts +104 -0
  247. package/src/components/form/CodeEditor/CodeEditor.monaco.ts +109 -0
  248. package/src/components/form/CodeEditor/CodeEditor.test.stories.tsx +17 -18
  249. package/src/components/form/CodeEditor/CodeEditor.tsx +81 -330
  250. package/src/components/form/CodeEditor/CodeEditorToolbar.tsx +168 -0
  251. package/src/components/form/Command/Command.hooks.ts +207 -0
  252. package/src/components/form/Command/Command.parts.tsx +58 -0
  253. package/src/components/form/Command/Command.styles.ts +83 -0
  254. package/src/components/form/Command/Command.tsx +61 -270
  255. package/src/components/form/CreatableSelect/CreatableSelect.md +1 -1
  256. package/src/components/form/CreatableSelect/CreatableSelect.test.stories.tsx +1 -1
  257. package/src/components/form/CreatableSelect/CreatableSelect.tsx +152 -71
  258. package/src/components/form/CreatableSelect/CreatableSelect.types.ts +13 -0
  259. package/src/components/form/HeaderButton/HeaderButton.tsx +80 -0
  260. package/src/components/form/HeaderButton/index.ts +2 -0
  261. package/src/components/form/Input/Input.stories.tsx +5 -1
  262. package/src/components/form/Input/Input.styles.ts +176 -0
  263. package/src/components/form/Input/Input.test.stories.tsx +30 -23
  264. package/src/components/form/Input/Input.tsx +71 -211
  265. package/src/components/form/Input/Input.types.ts +11 -0
  266. package/src/components/form/InputOTP/InputOTP.test.stories.tsx +9 -17
  267. package/src/components/form/Menubar/Menubar.test.stories.tsx +4 -8
  268. package/src/components/form/PasswordStrength/PasswordStrength.helpers.tsx +117 -0
  269. package/src/components/form/PasswordStrength/PasswordStrength.test.stories.tsx +3 -3
  270. package/src/components/form/PasswordStrength/PasswordStrength.tsx +202 -255
  271. package/src/components/form/PhoneInput/PhoneInput.hooks.ts +134 -0
  272. package/src/components/form/PhoneInput/PhoneInput.test.stories.tsx +4 -4
  273. package/src/components/form/PhoneInput/PhoneInput.tsx +279 -292
  274. package/src/components/form/PhoneInput/countries.ts +54 -0
  275. package/src/components/form/PhoneInput/phone.ts +47 -0
  276. package/src/components/form/RadioGroup/RadioGroup.test.stories.tsx +9 -9
  277. package/src/components/form/RichTextEditor/RichTextEditor.dom.ts +124 -0
  278. package/src/components/form/RichTextEditor/RichTextEditor.format.ts +61 -0
  279. package/src/components/form/RichTextEditor/RichTextEditor.hooks.ts +142 -0
  280. package/src/components/form/RichTextEditor/RichTextEditor.test.stories.tsx +5 -12
  281. package/src/components/form/RichTextEditor/RichTextEditor.tsx +98 -410
  282. package/src/components/form/RichTextEditor/RichTextEditorToolbar.tsx +187 -0
  283. package/src/components/form/SearchPalette/SearchPalette.parts.tsx +22 -0
  284. package/src/components/form/SearchPalette/SearchPalette.tsx +13 -9
  285. package/src/components/form/Select/Select.test.stories.tsx +35 -27
  286. package/src/components/form/Slider/Slider.test.stories.tsx +9 -11
  287. package/src/components/form/Switch/Switch.md +2 -1
  288. package/src/components/form/Switch/Switch.test.stories.tsx +6 -6
  289. package/src/components/form/Textarea/Textarea.styles.ts +143 -0
  290. package/src/components/form/Textarea/Textarea.test.stories.tsx +20 -26
  291. package/src/components/form/Textarea/Textarea.tsx +114 -535
  292. package/src/components/form/Textarea/TextareaRichEditor.tsx +377 -0
  293. package/src/components/form/Toggle/Toggle.styles.ts +211 -0
  294. package/src/components/form/Toggle/Toggle.test.stories.tsx +19 -27
  295. package/src/components/form/Toggle/Toggle.tsx +10 -185
  296. package/src/components/form/UploadButton/UploadButton.hooks.ts +323 -0
  297. package/src/components/form/UploadButton/UploadButton.parts.tsx +210 -0
  298. package/src/components/form/UploadButton/UploadButton.stories.tsx +2 -1
  299. package/src/components/form/UploadButton/UploadButton.test.stories.tsx +123 -4
  300. package/src/components/form/UploadButton/UploadButton.tsx +76 -305
  301. package/src/components/form/UploadButton/UploadButton.types.ts +16 -0
  302. package/src/components/form/index.ts +1 -0
  303. package/src/components/form/total-form/Fields/CepField.tsx +143 -0
  304. package/src/components/form/total-form/Fields/ToggleField.tsx +61 -0
  305. package/src/components/form/total-form/Fields/index.ts +4 -0
  306. package/src/components/form/total-form/FormContainer.tsx +3 -3
  307. package/src/components/form/total-form/SubmitButton.tsx +25 -2
  308. package/src/components/form/total-form/total-form.test.tsx +118 -1
  309. package/src/components/layout/Accordion/Accordion.md +1 -1
  310. package/src/components/layout/Accordion/Accordion.stories.tsx +5 -1
  311. package/src/components/layout/Accordion/Accordion.styles.ts +80 -0
  312. package/src/components/layout/Accordion/Accordion.test.stories.tsx +32 -50
  313. package/src/components/layout/Accordion/Accordion.tsx +2 -75
  314. package/src/components/layout/Card/Card.helpers.ts +30 -0
  315. package/src/components/layout/Card/Card.stories.tsx +9 -11
  316. package/src/components/layout/Card/Card.styles.ts +182 -0
  317. package/src/components/layout/Card/Card.test.stories.tsx +46 -46
  318. package/src/components/layout/Card/Card.tsx +24 -241
  319. package/src/components/layout/CardGrid/CardGrid.md +96 -0
  320. package/src/components/layout/CardGrid/CardGrid.tsx +140 -0
  321. package/src/components/layout/CardGrid/__tests__/CardGrid.test.tsx +92 -0
  322. package/src/components/layout/CardGrid/index.ts +2 -0
  323. package/src/components/layout/Collapsible/Collapsible.helpers.ts +83 -0
  324. package/src/components/layout/Collapsible/Collapsible.test.stories.tsx +7 -3
  325. package/src/components/layout/Collapsible/Collapsible.tsx +111 -107
  326. package/src/components/layout/Container/Container.test.stories.tsx +11 -16
  327. package/src/components/layout/ContentToolbar/ColumnsMenu.tsx +1 -1
  328. package/src/components/layout/ContentToolbar/ContentToolbar.tsx +120 -44
  329. package/src/components/layout/ContentToolbar/ContentToolbar.types.ts +9 -0
  330. package/src/components/layout/ContentToolbar/FilterTrigger.tsx +1 -1
  331. package/src/components/layout/ContentToolbar/MultiSelectDropdown.tsx +58 -43
  332. package/src/components/layout/ContentToolbar/MultiSelectTriggers.tsx +139 -0
  333. package/src/components/layout/ContentToolbar/SavedViewsMenu.tsx +10 -3
  334. package/src/components/layout/ContentToolbar/SortByDropdown.tsx +35 -11
  335. package/src/components/layout/ContentToolbar/ViewSelector.tsx +5 -6
  336. package/src/components/layout/ContentToolbar/__tests__/MultiSelectDropdown.test.tsx +21 -0
  337. package/src/components/layout/Dashboard/Dashboard.test.stories.tsx +27 -1
  338. package/src/components/layout/Dashboard/Dashboard.tsx +27 -8
  339. package/src/components/layout/Dashboard/DashboardParts.tsx +12 -19
  340. package/src/components/layout/Dashboard/index.ts +2 -1
  341. package/src/components/layout/Drawer/Drawer.stories.tsx +8 -10
  342. package/src/components/layout/Drawer/Drawer.test.stories.tsx +18 -14
  343. package/src/components/layout/Drawer/Drawer.tsx +67 -53
  344. package/src/components/layout/Resizable/Resizable.helpers.ts +133 -0
  345. package/src/components/layout/Resizable/Resizable.hooks.ts +68 -0
  346. package/src/components/layout/Resizable/Resizable.tsx +38 -153
  347. package/src/components/layout/ScrollArea/ScrollArea.helpers.ts +51 -0
  348. package/src/components/layout/ScrollArea/ScrollArea.styles.ts +248 -0
  349. package/src/components/layout/ScrollArea/ScrollArea.tsx +183 -374
  350. package/src/components/layout/ScrollArea/ScrollAreaContent.tsx +70 -0
  351. package/src/components/layout/ScrollArea/ScrollViewport.tsx +90 -0
  352. package/src/components/layout/Separator/Separator.styles.ts +128 -0
  353. package/src/components/layout/Separator/Separator.test.stories.tsx +3 -12
  354. package/src/components/layout/Separator/Separator.tsx +6 -132
  355. package/src/components/layout/SettingsLayout/SettingsLayout.parts.tsx +2 -1
  356. package/src/components/layout/SettingsLayout/SettingsLayout.stories.tsx +6 -8
  357. package/src/components/layout/Sidebar/Sidebar.stories.tsx +10 -12
  358. package/src/components/layout/Sidebar/Sidebar.test.stories.tsx +35 -37
  359. package/src/components/layout/Skeleton/Skeleton.helpers.ts +33 -0
  360. package/src/components/layout/Skeleton/Skeleton.styles.ts +114 -0
  361. package/src/components/layout/Skeleton/Skeleton.test.stories.tsx +3 -3
  362. package/src/components/layout/Skeleton/Skeleton.tsx +67 -155
  363. package/src/components/layout/TableFilter/TableFilter.tsx +2 -1
  364. package/src/components/navigation/Breadcrumbs/BreadcrumbEntry.tsx +305 -0
  365. package/src/components/navigation/Breadcrumbs/Breadcrumbs.md +2 -1
  366. package/src/components/navigation/Breadcrumbs/Breadcrumbs.stories.tsx +12 -14
  367. package/src/components/navigation/Breadcrumbs/Breadcrumbs.styles.tsx +212 -0
  368. package/src/components/navigation/Breadcrumbs/Breadcrumbs.test.stories.tsx +62 -61
  369. package/src/components/navigation/Breadcrumbs/Breadcrumbs.tsx +116 -429
  370. package/src/components/navigation/CommandPalette/CommandPalette.helpers.ts +82 -0
  371. package/src/components/navigation/CommandPalette/CommandPalette.hooks.ts +202 -0
  372. package/src/components/navigation/CommandPalette/CommandPalette.stories.tsx +3 -1
  373. package/src/components/navigation/CommandPalette/CommandPalette.test.stories.tsx +3 -5
  374. package/src/components/navigation/CommandPalette/CommandPalette.tsx +108 -341
  375. package/src/components/navigation/CommandPalette/CommandPaletteResults.tsx +182 -0
  376. package/src/components/navigation/CommandPalette/ShortcutChip.tsx +18 -0
  377. package/src/components/navigation/ContextMenu/ContextMenu.md +3 -1
  378. package/src/components/navigation/ContextMenu/ContextMenu.stories.tsx +4 -1
  379. package/src/components/navigation/ContextMenu/ContextMenu.test.stories.tsx +19 -24
  380. package/src/components/navigation/ContextMenu/ContextMenu.tsx +70 -54
  381. package/src/components/navigation/DropdownMenu/DropdownMenu.md +3 -1
  382. package/src/components/navigation/DropdownMenu/DropdownMenu.stories.tsx +17 -19
  383. package/src/components/navigation/DropdownMenu/DropdownMenu.test.stories.tsx +26 -26
  384. package/src/components/navigation/DropdownMenu/DropdownMenu.tsx +189 -111
  385. package/src/components/navigation/NavigationMenu/NavigationMegaSection.tsx +66 -0
  386. package/src/components/navigation/NavigationMenu/NavigationMenu.md +7 -2
  387. package/src/components/navigation/NavigationMenu/NavigationMenu.shell.tsx +218 -0
  388. package/src/components/navigation/NavigationMenu/NavigationMenu.styles.ts +223 -0
  389. package/src/components/navigation/NavigationMenu/NavigationMenu.tsx +119 -808
  390. package/src/components/navigation/NavigationMenu/NavigationMenuItem.hooks.ts +126 -0
  391. package/src/components/navigation/NavigationMenu/NavigationMenuItem.tsx +352 -0
  392. package/src/components/navigation/NavigationMenu/NavigationStandardBody.tsx +148 -0
  393. package/src/components/navigation/NavigationMenu/stories/NavigationMenu.stories.tsx +15 -17
  394. package/src/components/navigation/NavigationMenu/stories/NavigationMenu.test.stories.tsx +27 -23
  395. package/src/components/navigation/NavigationMenu/stories/NavigationMenuHorizontal.stories.tsx +11 -13
  396. package/src/components/navigation/NavigationMenu/stories/NavigationMenuVertical.stories.tsx +9 -11
  397. package/src/components/navigation/Pagination/Pagination.helpers.tsx +85 -0
  398. package/src/components/navigation/Pagination/Pagination.md +2 -1
  399. package/src/components/navigation/Pagination/Pagination.stories.tsx +4 -6
  400. package/src/components/navigation/Pagination/Pagination.styles.ts +135 -0
  401. package/src/components/navigation/Pagination/Pagination.tsx +178 -313
  402. package/src/components/navigation/Pagination/PaginationParts.tsx +81 -0
  403. package/src/components/navigation/Tabs/Tabs.md +3 -1
  404. package/src/components/navigation/Tabs/Tabs.stories.tsx +21 -23
  405. package/src/components/navigation/Tabs/Tabs.styles.ts +163 -0
  406. package/src/components/navigation/Tabs/Tabs.test.stories.tsx +37 -37
  407. package/src/components/navigation/Tabs/Tabs.tsx +192 -361
  408. package/src/components/navigation/Tabs/TabsPanel.tsx +100 -0
  409. package/src/components/typography/Blockquote/Blockquote.tsx +1 -1
  410. package/src/components/typography/Code/Code.test.stories.tsx +5 -5
  411. package/src/components/typography/Code/Code.tsx +74 -49
  412. package/src/components/typography/Heading/Heading.test.stories.tsx +8 -8
  413. package/src/components/typography/Paragraph/Paragraph.test.stories.tsx +5 -12
  414. package/src/components/typography/Text/Text.tsx +84 -77
  415. package/src/components/utility/AnimatedIcon/AnimatedIcon.md +4 -4
  416. package/src/components/utility/AnimatedIcon/AnimatedIcon.stories.tsx +19 -21
  417. package/src/components/utility/AnimatedIcon/AnimatedIcon.test.stories.tsx +19 -12
  418. package/src/components/utility/AspectRatio/AspectRatio.test.stories.tsx +9 -9
  419. package/src/components/utility/InfiniteScroll/InfiniteScroll.hooks.ts +118 -0
  420. package/src/components/utility/InfiniteScroll/InfiniteScroll.parts.tsx +54 -0
  421. package/src/components/utility/InfiniteScroll/InfiniteScroll.test.stories.tsx +12 -9
  422. package/src/components/utility/InfiniteScroll/InfiniteScroll.tsx +29 -148
  423. package/src/components/utility/InstallPrompt/InstallPrompt.helpers.ts +124 -0
  424. package/src/components/utility/InstallPrompt/InstallPrompt.md +113 -0
  425. package/src/components/utility/InstallPrompt/InstallPrompt.stories.tsx +118 -0
  426. package/src/components/utility/InstallPrompt/InstallPrompt.styles.ts +50 -0
  427. package/src/components/utility/InstallPrompt/InstallPrompt.test.stories.tsx +83 -0
  428. package/src/components/utility/InstallPrompt/InstallPrompt.tsx +192 -0
  429. package/src/components/utility/InstallPrompt/InstallPrompt.types.ts +78 -0
  430. package/src/components/utility/InstallPrompt/__tests__/InstallPrompt.ios.test.tsx +65 -0
  431. package/src/components/utility/InstallPrompt/__tests__/usePwaInstall.test.tsx +271 -0
  432. package/src/components/utility/InstallPrompt/index.ts +10 -0
  433. package/src/components/utility/InstallPrompt/usePwaInstall.ts +171 -0
  434. package/src/components/utility/Transition/Transition.helpers.ts +40 -0
  435. package/src/components/utility/Transition/Transition.tsx +17 -68
  436. package/src/components/utility/VirtualList/VirtualList.hooks.ts +319 -0
  437. package/src/components/utility/VirtualList/VirtualList.test.stories.tsx +49 -38
  438. package/src/components/utility/VirtualList/VirtualList.tsx +110 -315
  439. package/src/components/utility/WorkflowStep/WorkflowStep.helpers.ts +151 -0
  440. package/src/components/utility/WorkflowStep/WorkflowStep.parts.tsx +371 -0
  441. package/src/components/utility/WorkflowStep/WorkflowStep.stories.tsx +9 -11
  442. package/src/components/utility/WorkflowStep/WorkflowStep.test.stories.tsx +7 -7
  443. package/src/components/utility/WorkflowStep/WorkflowStep.tsx +51 -449
  444. package/src/components/utility/WorkflowStep/WorkflowStepRow.tsx +96 -0
  445. package/src/components/utility/index.ts +1 -0
  446. package/src/mui/Link.ts +2 -0
  447. package/src/utils/index.ts +2 -1
  448. package/src/utils/viewport.ts +65 -0
@@ -1,49 +1,26 @@
1
1
  import { Box, Collapse,useTheme } from '@mui/material';
2
2
  import React, { useCallback,useEffect, useRef, useState } from 'react';
3
3
 
4
+ import {
5
+ dimmedStyles,
6
+ regionAttrs,
7
+ transitionSettings,
8
+ triggerStyles,
9
+ } from './Collapsible.helpers';
4
10
  import type { CollapsibleContentProps,CollapsibleProps, CollapsibleTriggerProps } from './Collapsible.types';
5
11
 
6
- export const Collapsible: React.FC<CollapsibleProps> = ({
7
- children,
8
- open,
9
- variant = 'default',
10
- duration = 300,
11
- easing,
12
- onToggle,
13
- disabled = false,
14
- keepMounted = false,
15
- maxHeight,
16
- sx,
17
- className,
18
- dataTestId,
19
- ...otherProps
20
- }) => {
21
- const theme = useTheme();
12
+ /**
13
+ * The smooth and spring variants animate an explicit pixel height, so the content
14
+ * has to be measured after every render that could have changed it.
15
+ */
16
+ const useMeasuredHeight = (
17
+ open: boolean,
18
+ maxHeight: number | undefined,
19
+ children: React.ReactNode,
20
+ ) => {
22
21
  const contentRef = useRef<HTMLDivElement>(null);
23
22
  const [height, setHeight] = useState<number | 'auto'>('auto');
24
23
 
25
- const getTransitionSettings = () => {
26
- switch (variant) {
27
- case 'smooth':
28
- return {
29
- duration,
30
- easing: easing || theme.transitions.easing.easeInOut,
31
- };
32
- case 'spring':
33
- return {
34
- duration: duration * 1.2,
35
- easing: easing || 'cubic-bezier(0.34, 1.56, 0.64, 1)',
36
- };
37
- default:
38
- return {
39
- duration,
40
- easing: easing || theme.transitions.easing.easeInOut,
41
- };
42
- }
43
- };
44
-
45
- const transition = getTransitionSettings();
46
-
47
24
  const measureHeight = useCallback(() => {
48
25
  if (contentRef.current) {
49
26
  const scrollHeight = contentRef.current.scrollHeight;
@@ -60,41 +37,64 @@ export const Collapsible: React.FC<CollapsibleProps> = ({
60
37
  }
61
38
  }, [open, measureHeight, children]);
62
39
 
63
- // Trigger onToggle callback when open state changes
64
- useEffect(() => {
65
- if (onToggle && !disabled) {
66
- onToggle(open);
67
- }
68
- }, [open, onToggle, disabled]);
40
+ return { contentRef, height };
41
+ };
69
42
 
43
+ type VariantProps = Omit<CollapsibleProps, 'variant' | 'onToggle'> & {
44
+ duration: number;
45
+ disabled: boolean;
46
+ keepMounted: boolean;
47
+ transition: { duration: number; easing: string };
48
+ };
49
+
50
+ // Use MUI's built-in Collapse for the default variant.
51
+ const DefaultCollapsible: React.FC<VariantProps> = ({
52
+ children,
53
+ open,
54
+ duration,
55
+ disabled,
56
+ keepMounted,
57
+ maxHeight,
58
+ sx,
59
+ className,
60
+ dataTestId,
61
+ transition: _transition,
62
+ easing: _easing,
63
+ ...otherProps
64
+ }) => (
65
+ <Collapse
66
+ in={open && !disabled}
67
+ timeout={disabled ? 0 : duration}
68
+ sx={{
69
+ ...dimmedStyles(disabled),
70
+ ...(maxHeight && { maxHeight, overflow: 'hidden' }),
71
+ ...sx,
72
+ }}
73
+ className={className}
74
+ unmountOnExit={!keepMounted}
75
+ {...regionAttrs({ open, disabled, dataTestId })}
76
+ {...otherProps}
77
+ >
78
+ <Box>{children}</Box>
79
+ </Collapse>
80
+ );
81
+
82
+ const AnimatedCollapsible: React.FC<VariantProps> = ({
83
+ children,
84
+ open,
85
+ disabled,
86
+ keepMounted,
87
+ maxHeight,
88
+ transition,
89
+ sx,
90
+ className,
91
+ dataTestId,
92
+ duration: _duration,
93
+ easing: _easing,
94
+ ...otherProps
95
+ }) => {
96
+ const { contentRef, height } = useMeasuredHeight(open, maxHeight, children);
70
97
 
71
- if (variant === 'default') {
72
- // Use MUI's built-in Collapse for default variant
73
- return (
74
- <Collapse
75
- in={open && !disabled}
76
- timeout={disabled ? 0 : duration}
77
- sx={{
78
- opacity: disabled ? 0.6 : 1,
79
- pointerEvents: disabled ? 'none' : 'auto',
80
- ...(maxHeight && { maxHeight, overflow: 'hidden' }),
81
- ...sx,
82
- }}
83
- className={className}
84
- unmountOnExit={!keepMounted}
85
- data-disabled={disabled}
86
- data-testid={dataTestId}
87
- role="region"
88
- aria-expanded={open && !disabled}
89
- aria-hidden={disabled || !open}
90
- {...otherProps}
91
- >
92
- <Box>{children}</Box>
93
- </Collapse>
94
- );
95
- }
96
-
97
- // Custom implementation for smooth and spring variants
98
98
  return (
99
99
  <Box
100
100
  component="div"
@@ -103,25 +103,53 @@ export const Collapsible: React.FC<CollapsibleProps> = ({
103
103
  height: open && !disabled ? height : 0,
104
104
  transition: disabled ? 'none' : `height ${transition.duration}ms ${transition.easing}`,
105
105
  willChange: disabled ? 'auto' : 'height',
106
- opacity: disabled ? 0.6 : 1,
107
- pointerEvents: disabled ? 'none' : 'auto',
106
+ ...dimmedStyles(disabled),
108
107
  ...sx,
109
108
  }}
110
109
  className={className}
111
- data-disabled={disabled}
112
- data-testid={dataTestId}
113
- role="region"
114
- aria-expanded={open && !disabled}
115
- aria-hidden={disabled || !open}
110
+ {...regionAttrs({ open, disabled, dataTestId })}
116
111
  {...otherProps}
117
112
  >
118
- <Box ref={contentRef}>
119
- {(keepMounted || (open && !disabled)) && children}
120
- </Box>
113
+ <Box ref={contentRef}>{(keepMounted || (open && !disabled)) && children}</Box>
121
114
  </Box>
122
115
  );
123
116
  };
124
117
 
118
+ export const Collapsible: React.FC<CollapsibleProps> = ({
119
+ variant = 'default',
120
+ duration = 300,
121
+ easing,
122
+ onToggle,
123
+ disabled = false,
124
+ keepMounted = false,
125
+ ...rest
126
+ }) => {
127
+ const theme = useTheme();
128
+ const { open } = rest;
129
+
130
+ // Trigger onToggle callback when open state changes
131
+ useEffect(() => {
132
+ if (onToggle && !disabled) {
133
+ onToggle(open);
134
+ }
135
+ }, [open, onToggle, disabled]);
136
+
137
+ const variantProps: VariantProps = {
138
+ ...rest,
139
+ duration,
140
+ easing,
141
+ disabled,
142
+ keepMounted,
143
+ transition: transitionSettings(theme, variant, duration, easing),
144
+ };
145
+
146
+ return variant === 'default' ? (
147
+ <DefaultCollapsible {...variantProps} />
148
+ ) : (
149
+ <AnimatedCollapsible {...variantProps} />
150
+ );
151
+ };
152
+
125
153
  export const CollapsibleTrigger: React.FC<CollapsibleTriggerProps> = ({
126
154
  children,
127
155
  onClick,
@@ -145,31 +173,7 @@ export const CollapsibleTrigger: React.FC<CollapsibleTriggerProps> = ({
145
173
  role="button"
146
174
  tabIndex={disabled ? -1 : 0}
147
175
  data-state={expanded ? 'open' : 'closed'}
148
- sx={{
149
- width: '100%',
150
- padding: theme.spacing(1, 2),
151
- border: 'none',
152
- backgroundColor: expanded ? theme.palette.action.selected : 'transparent',
153
- cursor: disabled ? 'not-allowed' : 'pointer',
154
- display: 'flex',
155
- alignItems: 'center',
156
- justifyContent: 'space-between',
157
- transition: theme.transitions.create(['background-color', 'opacity'], {
158
- duration: theme.transitions.duration.short,
159
- }),
160
- opacity: disabled ? 0.6 : 1,
161
- '&:hover': {
162
- backgroundColor: disabled ? 'transparent' :
163
- expanded ? theme.palette.action.selected : theme.palette.action.hover,
164
- },
165
- '&:focus': {
166
- outline: `2px solid ${theme.palette.primary.main}`,
167
- outlineOffset: 2,
168
- },
169
- '&:active': {
170
- backgroundColor: disabled ? 'transparent' : theme.palette.action.focus,
171
- },
172
- }}
176
+ sx={triggerStyles(theme, { disabled, expanded })}
173
177
  {...otherProps}
174
178
  >
175
179
  {children}
@@ -195,4 +199,4 @@ export const CollapsibleContent: React.FC<CollapsibleContentProps> = ({
195
199
  {children}
196
200
  </Box>
197
201
  );
198
- };
202
+ };
@@ -1,6 +1,6 @@
1
1
  import { Box, Button, Card, CardContent,Paper, Typography } from '@mui/material';
2
2
  import type { Meta, StoryObj } from '@storybook/react-vite';
3
- import { expect, fn,userEvent, within } from 'storybook/test';
3
+ import { expect, fn,userEvent, within, waitFor } from 'storybook/test';
4
4
 
5
5
  import { Container } from './Container';
6
6
 
@@ -196,17 +196,17 @@ export const KeyboardNavigation: Story = {
196
196
 
197
197
  // Focus first element
198
198
  await userEvent.click(firstButton);
199
- await expect(firstButton).toHaveFocus();
199
+ await waitFor(() => expect(firstButton).toHaveFocus());
200
200
 
201
201
  // Tab to next element
202
202
  await userEvent.tab();
203
- await expect(secondButton).toHaveFocus();
203
+ await waitFor(() => expect(secondButton).toHaveFocus());
204
204
  });
205
205
 
206
206
  await step('Tab navigation backward', async () => {
207
207
  await userEvent.tab({ shift: true });
208
208
  const firstButton = canvas.getByTestId('first-focusable');
209
- await expect(firstButton).toHaveFocus();
209
+ await waitFor(() => expect(firstButton).toHaveFocus());
210
210
  });
211
211
 
212
212
  await step('Enter key activation', async () => {
@@ -214,14 +214,14 @@ export const KeyboardNavigation: Story = {
214
214
  await userEvent.click(button);
215
215
  await userEvent.keyboard('{Enter}');
216
216
  // Verify button is still focused after activation
217
- await expect(button).toHaveFocus();
217
+ await waitFor(() => expect(button).toHaveFocus());
218
218
  });
219
219
 
220
220
  await step('Space key activation', async () => {
221
221
  const nativeButton = canvas.getByTestId('native-button');
222
- nativeButton.focus();
222
+ await userEvent.click(nativeButton);
223
223
  await userEvent.keyboard(' ');
224
- await expect(nativeButton).toHaveFocus();
224
+ await waitFor(() => expect(nativeButton).toHaveFocus());
225
225
  });
226
226
  }
227
227
  };
@@ -296,23 +296,23 @@ export const FocusManagement: Story = {
296
296
  await step('Initial focus state', async () => {
297
297
  const triggerButton = canvas.getByTestId('trigger-button');
298
298
  await userEvent.click(triggerButton);
299
- await expect(triggerButton).toHaveFocus();
299
+ await waitFor(() => expect(triggerButton).toHaveFocus());
300
300
  });
301
301
 
302
302
  await step('Focus cycling through elements', async () => {
303
303
  await userEvent.tab();
304
304
  const firstElement = canvas.getByTestId('first-focus-element');
305
- await expect(firstElement).toHaveFocus();
305
+ await waitFor(() => expect(firstElement).toHaveFocus());
306
306
 
307
307
  await userEvent.tab();
308
308
  const secondElement = canvas.getByTestId('second-focus-element');
309
- await expect(secondElement).toHaveFocus();
309
+ await waitFor(() => expect(secondElement).toHaveFocus());
310
310
  });
311
311
 
312
312
  await step('Focus restoration', async () => {
313
313
  const triggerButton = canvas.getByTestId('trigger-button');
314
314
  await userEvent.click(triggerButton);
315
- await expect(triggerButton).toHaveFocus();
315
+ await waitFor(() => expect(triggerButton).toHaveFocus());
316
316
  });
317
317
  }
318
318
  };
@@ -551,13 +551,8 @@ export const PerformanceTest: Story = {
551
551
  const canvas = within(canvasElement);
552
552
 
553
553
  await step('Measure render time', async () => {
554
- const startTime = window.performance.now();
555
554
  const elements = canvas.getAllByTestId(/item-/);
556
- const endTime = window.performance.now();
557
555
 
558
- const renderTime = endTime - startTime;
559
- // eslint-disable-next-line no-console
560
- console.log(`Render time for ${elements.length} items: ${renderTime}ms`);
561
556
 
562
557
  // Verify reasonable number of elements rendered
563
558
  await expect(elements.length).toBeGreaterThan(50);
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { ViewColumnRounded as ColumnsIcon } from '@mui/icons-material';
3
+ import ColumnsIcon from '@mui/icons-material/ViewColumnRounded';
4
4
  import { Box, Checkbox, IconButton, ListSubheader, Menu, MenuItem } from '@mui/material';
5
5
  import React, { useState } from 'react';
6
6
 
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { Box, Button, Divider, Typography } from '@mui/material';
3
+ import { Box, Button, Checkbox, Divider, Typography } from '@mui/material';
4
4
  import React from 'react';
5
5
 
6
6
  import type { ContentToolbarProps } from './ContentToolbar.types';
@@ -17,6 +17,87 @@ const selectionButtonSx = {
17
17
  color: 'text.primary',
18
18
  } as const;
19
19
 
20
+ type SelectionClusterProps = Pick<
21
+ ContentToolbarProps,
22
+ 'hasSelection' | 'selectedCount' | 'selectAll' | 'clearSelection' | 'actions' | 'selectAllTestId' | 'clearAllTestId' | 'edgeAlign'
23
+ >;
24
+
25
+ /** The left cluster: Select All + (when selecting) Clear All / count / actions. */
26
+ function SelectionCluster({
27
+ hasSelection,
28
+ selectedCount,
29
+ selectAll,
30
+ clearSelection,
31
+ actions,
32
+ selectAllTestId,
33
+ clearAllTestId,
34
+ edgeAlign = false,
35
+ }: SelectionClusterProps): React.JSX.Element {
36
+ const actionsSlot = actions !== undefined && (
37
+ <Box sx={{ ml: 0.5, display: 'flex', flexShrink: 0, alignItems: 'center' }}>{actions}</Box>
38
+ );
39
+ return (
40
+ <Box
41
+ sx={{
42
+ display: 'flex',
43
+ minWidth: 0,
44
+ // Mobile: don't grow, so the controls sit on the SAME line as the checkbox
45
+ // (no orphaned selection row). Desktop: grow to push controls right.
46
+ flex: { xs: '0 0 auto', md: 1 },
47
+ alignItems: 'center',
48
+ gap: 1.5,
49
+ ml: edgeAlign ? -1.5 : 0,
50
+ }}
51
+ >
52
+ {/* Desktop: a "Select All" text button (md+). Mobile: a compact checkbox
53
+ that toggles select-all/clear — the text would eat the tight row. */}
54
+ <Button
55
+ variant="text"
56
+ size="small"
57
+ color="inherit"
58
+ onClick={selectAll}
59
+ data-testid={selectAllTestId}
60
+ sx={{ ...selectionButtonSx, display: { xs: 'none', md: 'inline-flex' } }}
61
+ >
62
+ Select All
63
+ </Button>
64
+ <Checkbox
65
+ size="small"
66
+ checked={hasSelection}
67
+ onChange={(event) => (event.target.checked ? selectAll() : clearSelection())}
68
+ data-testid={`${selectAllTestId}-checkbox`}
69
+ inputProps={{ 'aria-label': 'Selecionar todos' }}
70
+ sx={{ p: 0.5, display: { xs: 'inline-flex', md: 'none' } }}
71
+ />
72
+ {hasSelection ? (
73
+ <>
74
+ <Button
75
+ variant="text"
76
+ size="small"
77
+ color="inherit"
78
+ onClick={clearSelection}
79
+ data-testid={clearAllTestId}
80
+ sx={selectionButtonSx}
81
+ >
82
+ Clear All
83
+ </Button>
84
+ <Divider orientation="vertical" flexItem sx={{ height: 16, alignSelf: 'center' }} />
85
+ <Typography
86
+ component="span"
87
+ data-testid="selected-count-indicator"
88
+ sx={{ fontSize: '0.875rem', color: 'text.secondary', whiteSpace: 'nowrap', flexShrink: 0 }}
89
+ >
90
+ {selectedCount} {selectedCount === 1 ? 'item' : 'items'} selected
91
+ </Typography>
92
+ {actionsSlot}
93
+ </>
94
+ ) : (
95
+ actionsSlot
96
+ )}
97
+ </Box>
98
+ );
99
+ }
100
+
20
101
  /**
21
102
  * Shared toolbar for content pages (Favorites, Personal Space, Recents, …). The
22
103
  * left cluster owns selection chrome — **Select All**, and once items are
@@ -58,51 +139,46 @@ export function ContentToolbar({
58
139
  edgeAlign = false,
59
140
  }: ContentToolbarProps): React.JSX.Element {
60
141
  return (
61
- <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 2 }}>
62
- <Box sx={{ display: 'flex', minWidth: 0, flex: 1, alignItems: 'center', gap: 1.5, ml: edgeAlign ? -1.5 : 0 }}>
63
- <Button
64
- variant="text"
65
- size="small"
66
- color="inherit"
67
- onClick={selectAll}
68
- data-testid={selectAllTestId}
69
- sx={selectionButtonSx}
70
- >
71
- Select All
72
- </Button>
142
+ // Wrap the two clusters onto separate rows when they can't share one line
143
+ // (narrow screens / phones) instead of letting the controls collide.
144
+ <Box
145
+ sx={{
146
+ display: 'flex',
147
+ alignItems: 'center',
148
+ justifyContent: 'space-between',
149
+ gap: 2,
150
+ flexWrap: 'wrap',
151
+ rowGap: 1,
152
+ }}
153
+ >
154
+ <SelectionCluster
155
+ hasSelection={hasSelection}
156
+ selectedCount={selectedCount}
157
+ selectAll={selectAll}
158
+ clearSelection={clearSelection}
159
+ actions={actions}
160
+ selectAllTestId={selectAllTestId}
161
+ clearAllTestId={clearAllTestId}
162
+ edgeAlign={edgeAlign}
163
+ />
73
164
 
74
- {hasSelection ? (
75
- <>
76
- <Button
77
- variant="text"
78
- size="small"
79
- color="inherit"
80
- onClick={clearSelection}
81
- data-testid={clearAllTestId}
82
- sx={selectionButtonSx}
83
- >
84
- Clear All
85
- </Button>
86
- <Divider orientation="vertical" flexItem sx={{ height: 16, alignSelf: 'center' }} />
87
- <Typography
88
- component="span"
89
- data-testid="selected-count-indicator"
90
- sx={{ fontSize: '0.875rem', color: 'text.secondary', whiteSpace: 'nowrap', flexShrink: 0 }}
91
- >
92
- {selectedCount} {selectedCount === 1 ? 'item' : 'items'} selected
93
- </Typography>
94
- {actions !== undefined && (
95
- <Box sx={{ ml: 0.5, display: 'flex', flexShrink: 0, alignItems: 'center' }}>{actions}</Box>
96
- )}
97
- </>
98
- ) : (
99
- actions !== undefined && (
100
- <Box sx={{ ml: 0.5, display: 'flex', flexShrink: 0, alignItems: 'center' }}>{actions}</Box>
101
- )
102
- )}
165
+ {/* ml:auto keeps the controls right-aligned even when the cluster wraps to
166
+ * its own row (where justify-content:space-between would otherwise snap a
167
+ * lone item to the left); it's a no-op on a shared row. */}
168
+ <Box
169
+ sx={{
170
+ display: 'flex',
171
+ alignItems: 'center',
172
+ flexWrap: 'wrap',
173
+ // Tight (5px) when browsing so the controls fit one line beside the
174
+ // checkbox; roomier (14px) in selection mode where they get their own row.
175
+ gap: hasSelection ? '14px' : '5px',
176
+ ml: 'auto',
177
+ mr: edgeAlign ? -1.5 : 0,
178
+ }}
179
+ >
180
+ {rightControls}
103
181
  </Box>
104
-
105
- <Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5, mr: edgeAlign ? -1.5 : 0 }}>{rightControls}</Box>
106
182
  </Box>
107
183
  );
108
184
  }
@@ -124,6 +124,15 @@ export interface MultiSelectDropdownProps<TValue extends string = string> {
124
124
  searchPlaceholder?: string;
125
125
  /** Shown when the search matches no options. @default "No results" */
126
126
  noResultsLabel?: string;
127
+ /**
128
+ * Trigger layout. `inline` (default) renders a compact `Label:` text button for
129
+ * a horizontal toolbar. `stacked` renders the label on its own line above a
130
+ * full-width, outlined select-style control (a filter panel). `pill` renders a
131
+ * rounded outlined chip (`Label ▾`, with a count when a selection is active) —
132
+ * for a horizontal filter row.
133
+ * @default "inline"
134
+ */
135
+ layout?: 'inline' | 'stacked' | 'pill';
127
136
  'data-testid'?: string;
128
137
  }
129
138
 
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { FilterListRounded as FilterIcon } from '@mui/icons-material';
3
+ import FilterIcon from '@mui/icons-material/FilterListRounded';
4
4
  import { Box, Button } from '@mui/material';
5
5
  import React from 'react';
6
6