@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,277 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * A range filter as a PILL in the inline filter bar — the same affordance the
5
+ * multi-select facets use, so "Data" and "Valor" sit in the filter row beside
6
+ * "Pagamento"/"Situação"/"Método" instead of floating above the grid.
7
+ *
8
+ * Before this the inline bar rendered pills only, and `rangeFields` had a
9
+ * surface on the slide-in panel alone — which `inlineFilters` REPLACES on a wide
10
+ * screen. So a range filter was invisible on exactly the screens that use it,
11
+ * and a page wanting one had to hang its own inputs outside the grid, outside
12
+ * `DataViewState`, and outside the grid's "Limpar filtros" (FUT-668).
13
+ */
14
+ import ChevronDownIcon from '@mui/icons-material/KeyboardArrowDown';
15
+ import { Box, Button, Popover, TextField, Typography } from '@mui/material';
16
+ import React, { useState } from 'react';
17
+
18
+ import { TableFilter } from '../../layout/TableFilter';
19
+ import type { RangeFieldConfig, RangeValue } from './data-views-types';
20
+
21
+ /** Is either bound set? Drives the pill's active styling and the chip. */
22
+ export function isRangeSet(range: RangeValue | undefined): boolean {
23
+ return Boolean(range && (range.min != null || range.max != null));
24
+ }
25
+
26
+ /** `AAAA-MM-DD` → `DD/MM` — the compact form a chip shows. */
27
+ function shortDay(day: string): string {
28
+ const [, month, date] = day.split('-');
29
+ return month && date ? `${date}/${month}` : day;
30
+ }
31
+
32
+ /** One bound, rendered for the chip: money in reais, a day as `DD/MM`. */
33
+ function boundLabel<T extends Record<string, unknown>>(
34
+ field: RangeFieldConfig<T>,
35
+ bound: number | string,
36
+ ): string {
37
+ if (field.kind === 'day') return shortDay(String(bound));
38
+ return field.unit ? `${field.unit} ${bound}` : String(bound);
39
+ }
40
+
41
+ /**
42
+ * The chip text for an applied range: "Data: 01/07–31/07" when both ends are
43
+ * set, and a one-sided window as the inequality it actually is ("Valor: ≥ R$ 20")
44
+ * rather than an en-dash with a blank side.
45
+ */
46
+ export function rangeChipLabel<T extends Record<string, unknown>>(
47
+ field: RangeFieldConfig<T>,
48
+ range: RangeValue,
49
+ ): string {
50
+ const { min, max } = range;
51
+ if (min != null && max != null) {
52
+ return `${field.label}: ${boundLabel(field, min)}–${boundLabel(field, max)}`;
53
+ }
54
+ if (min != null) return `${field.label}: ≥ ${boundLabel(field, min)}`;
55
+ return `${field.label}: ≤ ${boundLabel(field, max as number | string)}`;
56
+ }
57
+
58
+ /** A bound as the input's string value ('' when unset). */
59
+ function inputValue(bound: number | string | undefined): string {
60
+ return bound == null ? '' : String(bound);
61
+ }
62
+
63
+ /**
64
+ * One end of the range. A day keeps its `AAAA-MM-DD` string verbatim (the form
65
+ * both the native picker and the backend speak); a number parses, and an
66
+ * unparseable/blank entry CLEARS the bound rather than writing `NaN`.
67
+ */
68
+ function BoundField<T extends Record<string, unknown>>({
69
+ field,
70
+ label,
71
+ value,
72
+ onChange,
73
+ testId,
74
+ }: {
75
+ field: RangeFieldConfig<T>;
76
+ label: string;
77
+ value: number | string | undefined;
78
+ onChange: (bound: number | string | undefined) => void;
79
+ testId: string;
80
+ }): React.JSX.Element {
81
+ const isDay = field.kind === 'day';
82
+ return (
83
+ <TextField
84
+ size="small"
85
+ type={isDay ? 'date' : 'number'}
86
+ label={label}
87
+ value={inputValue(value)}
88
+ onChange={(event) => {
89
+ const raw = event.target.value;
90
+ if (raw === '') return onChange(undefined);
91
+ if (isDay) return onChange(raw);
92
+ const amount = Number(raw);
93
+ return onChange(Number.isNaN(amount) ? undefined : amount);
94
+ }}
95
+ // A native date input ALWAYS paints its `dd/mm/aaaa` placeholder, and a
96
+ // start adornment occupies the same space — so a label left to MUI's
97
+ // default (shrink only once filled) renders ON TOP of it.
98
+ InputLabelProps={{ shrink: true }}
99
+ inputProps={{
100
+ 'data-testid': testId,
101
+ ...(isDay ? {} : { step: field.step ?? 1, min: 0 }),
102
+ }}
103
+ InputProps={!isDay && field.unit ? { startAdornment: <Box component="span" sx={{ mr: 0.5, color: 'text.secondary' }}>{field.unit}</Box> } : undefined}
104
+ sx={{ width: isDay ? 165 : 140 }}
105
+ />
106
+ );
107
+ }
108
+
109
+ /**
110
+ * The `De`/`Até` pair for a range — shared by the pill's popover and the
111
+ * slide-in panel's day fields, so the two surfaces cannot drift on what a bound
112
+ * accepts or how it clears.
113
+ */
114
+ export function RangeBounds<T extends Record<string, unknown>>({
115
+ field,
116
+ value,
117
+ onChange,
118
+ testId,
119
+ }: {
120
+ field: RangeFieldConfig<T>;
121
+ value: RangeValue;
122
+ onChange: (range: RangeValue) => void;
123
+ testId: string;
124
+ }): React.JSX.Element {
125
+ return (
126
+ <Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }} data-testid={`${testId}-panel`}>
127
+ <BoundField
128
+ field={field}
129
+ label="De"
130
+ value={value.min}
131
+ onChange={(min) => onChange({ ...value, min })}
132
+ testId={`${testId}-min`}
133
+ />
134
+ <BoundField
135
+ field={field}
136
+ label="Até"
137
+ value={value.max}
138
+ onChange={(max) => onChange({ ...value, max })}
139
+ testId={`${testId}-max`}
140
+ />
141
+ </Box>
142
+ );
143
+ }
144
+
145
+ /**
146
+ * The pill + its popover. Bounds commit on change (the list is server-driven, so
147
+ * each edit is a query) and the popover stays open, which is what lets a
148
+ * merchant set "de" and then "até" without re-opening it.
149
+ */
150
+ export function RangePill<T extends Record<string, unknown>>({
151
+ field,
152
+ value,
153
+ onChange,
154
+ testIdPrefix,
155
+ }: {
156
+ field: RangeFieldConfig<T>;
157
+ value: RangeValue;
158
+ onChange: (range: RangeValue) => void;
159
+ testIdPrefix: string;
160
+ }): React.JSX.Element {
161
+ const [anchor, setAnchor] = useState<HTMLElement | null>(null);
162
+ const active = isRangeSet(value);
163
+ const testId = `${testIdPrefix}-range-${field.id}`;
164
+ return (
165
+ <>
166
+ <Button
167
+ variant="outlined"
168
+ color="inherit"
169
+ size="small"
170
+ data-testid={testId}
171
+ aria-haspopup="dialog"
172
+ aria-expanded={Boolean(anchor)}
173
+ onClick={(event) => setAnchor(event.currentTarget)}
174
+ endIcon={<ChevronDownIcon sx={{ fontSize: 16 }} />}
175
+ sx={{
176
+ borderRadius: 999,
177
+ height: 34,
178
+ px: 1.5,
179
+ color: 'text.primary',
180
+ fontWeight: 600,
181
+ fontSize: '0.8125rem',
182
+ textTransform: 'none',
183
+ borderColor: active ? 'primary.main' : 'divider',
184
+ bgcolor: active ? 'action.selected' : 'background.paper',
185
+ '&:hover': {
186
+ borderColor: active ? 'primary.main' : 'text.primary',
187
+ bgcolor: active ? 'action.selected' : 'action.hover',
188
+ },
189
+ }}
190
+ >
191
+ {field.label}
192
+ </Button>
193
+ <Popover
194
+ open={Boolean(anchor)}
195
+ anchorEl={anchor}
196
+ onClose={() => setAnchor(null)}
197
+ anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
198
+ slotProps={{ paper: { sx: { p: 2, mt: 0.5 } } }}
199
+ >
200
+ <RangeBounds field={field} value={value} onChange={onChange} testId={testId} />
201
+ {/* An inverted window is not an error the merchant must fix before the
202
+ list responds — it simply matches nothing, and saying so beats an
203
+ empty grid with no explanation (FUT-668). */}
204
+ {active && (
205
+ <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 2, mt: 1.5 }}>
206
+ <Typography component="span" sx={{ fontSize: '0.75rem', color: 'text.secondary' }}>
207
+ {rangeChipLabel(field, value)}
208
+ </Typography>
209
+ <Button
210
+ variant="text"
211
+ size="small"
212
+ onClick={() => onChange({})}
213
+ data-testid={`${testId}-clear`}
214
+ sx={{ textTransform: 'none' }}
215
+ >
216
+ Limpar
217
+ </Button>
218
+ </Box>
219
+ )}
220
+ </Popover>
221
+ </>
222
+ );
223
+ }
224
+
225
+ /**
226
+ * A stored range narrowed to NUMBERS, for the slide-in panel's numeric control.
227
+ * A bound that doesn't parse is dropped rather than passed on as `NaN`, which
228
+ * the control would render as an empty box that still filtered.
229
+ */
230
+ export function numericRange(range: RangeValue): { min?: number; max?: number } {
231
+ const parse = (bound: number | string | undefined): number | undefined => {
232
+ if (bound == null || bound === "") return undefined;
233
+ const value = Number(bound);
234
+ return Number.isNaN(value) ? undefined : value;
235
+ };
236
+ const min = parse(range.min);
237
+ const max = parse(range.max);
238
+ return { ...(min !== undefined ? { min } : {}), ...(max !== undefined ? { max } : {}) };
239
+ }
240
+
241
+ /**
242
+ * One range on the SLIDE-IN panel (and the narrow-screen modal): the numeric
243
+ * control the panel already had, or — for a day range, which that control cannot
244
+ * express — the same `De`/`Até` pair the pill's popover uses.
245
+ */
246
+ export function PanelRangeField<T extends Record<string, unknown>>({
247
+ field,
248
+ value,
249
+ onChange,
250
+ testId,
251
+ }: {
252
+ field: RangeFieldConfig<T>;
253
+ value: RangeValue;
254
+ onChange: (range: RangeValue) => void;
255
+ testId: string;
256
+ }): React.JSX.Element {
257
+ if (field.kind === "day") {
258
+ return (
259
+ <Box sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
260
+ <Typography component="span" sx={{ fontSize: "0.75rem", fontWeight: 500, color: "text.secondary" }}>
261
+ {field.label}
262
+ </Typography>
263
+ <RangeBounds field={field} value={value} onChange={onChange} testId={testId} />
264
+ </Box>
265
+ );
266
+ }
267
+ return (
268
+ <TableFilter.RangeField
269
+ label={field.label}
270
+ unit={field.unit}
271
+ step={field.step}
272
+ value={numericRange(value)}
273
+ onChange={(range) => onChange(range)}
274
+ testId={testId}
275
+ />
276
+ );
277
+ }
@@ -0,0 +1,150 @@
1
+ "use client";
2
+
3
+ import { Alert } from "../Alert";
4
+ import { SavedViewsMenu } from "../../layout/ContentToolbar";
5
+
6
+ import {
7
+ type DataViewColumn,
8
+ type DataViewState,
9
+ type FilterFieldConfig,
10
+ type SavedViewSummary,
11
+ } from "./data-views-types";
12
+ import { ManageViewsDialog } from "./ManageViewsDialog";
13
+ import { SaveViewModal, type SaveViewPayload } from "./SaveViewModal";
14
+
15
+ /**
16
+ * A rejected pin/share/default/delete surfaced inline (FUT-100) — the menus
17
+ * close on click, so this Alert is the only signal that survives the action.
18
+ */
19
+ export function ViewMutationErrorAlert({
20
+ error,
21
+ onClose,
22
+ testIdPrefix,
23
+ }: {
24
+ error: string | null;
25
+ onClose: () => void;
26
+ testIdPrefix: string;
27
+ }): React.JSX.Element | null {
28
+ if (!error) {
29
+ return null;
30
+ }
31
+ return (
32
+ <Alert
33
+ variant="danger"
34
+ title="Não foi possível atualizar a visão"
35
+ description={error}
36
+ closable
37
+ onClose={onClose}
38
+ data-testid={`${testIdPrefix}-views-mutation-error`}
39
+ />
40
+ );
41
+ }
42
+
43
+ interface ViewsMenuSlotProps {
44
+ views: SavedViewSummary[];
45
+ /** Name of the currently-applied view, shown in the trigger instead of "Visões". */
46
+ activeViewName?: string;
47
+ applyView: (view: SavedViewSummary) => void;
48
+ /** Reset to the built-in no-filter "Main vision" default. */
49
+ selectMain: () => void;
50
+ openCreate: () => void;
51
+ openEdit: (view: SavedViewSummary) => void;
52
+ handleDelete: (view: SavedViewSummary) => void;
53
+ patchView: (
54
+ view: SavedViewSummary,
55
+ changes: Partial<Pick<SavedViewSummary, "isDefault" | "pinned" | "shared">>,
56
+ ) => Promise<void>;
57
+ onManageAll: () => void;
58
+ testIdPrefix: string;
59
+ }
60
+
61
+ /**
62
+ * The saved-views Connector (FUT-89): binds the backend-backed SavedView state +
63
+ * mutations to the stateless `@12-apps/ui` SavedViewsMenu. All persistence lives here
64
+ * (via the passed handlers); the UI component itself stays data-free.
65
+ */
66
+ export function ViewsMenuSlot({
67
+ views,
68
+ activeViewName,
69
+ applyView,
70
+ selectMain,
71
+ openCreate,
72
+ openEdit,
73
+ handleDelete,
74
+ patchView,
75
+ onManageAll,
76
+ testIdPrefix,
77
+ }: ViewsMenuSlotProps): React.JSX.Element {
78
+ return (
79
+ <SavedViewsMenu<SavedViewSummary>
80
+ views={views}
81
+ activeViewName={activeViewName}
82
+ onApply={applyView}
83
+ onSelectMain={selectMain}
84
+ onSaveCurrent={openCreate}
85
+ onEdit={openEdit}
86
+ onDelete={(view) => void handleDelete(view)}
87
+ onSetDefault={(view) => void patchView(view, { isDefault: true })}
88
+ onTogglePin={(view) => void patchView(view, { pinned: !view.pinned })}
89
+ onToggleShare={(view) => void patchView(view, { shared: !view.shared })}
90
+ onManageAll={onManageAll}
91
+ testIdPrefix={`${testIdPrefix}-views`}
92
+ />
93
+ );
94
+ }
95
+
96
+ interface ViewDialogsProps<T extends Record<string, unknown>> {
97
+ saveOpen: boolean;
98
+ onCloseSave: () => void;
99
+ currentState: DataViewState;
100
+ fields: FilterFieldConfig<T>[];
101
+ columns: DataViewColumn<T>[];
102
+ editing: SavedViewSummary | null;
103
+ onSave: (payload: SaveViewPayload) => Promise<void>;
104
+ manageOpen: boolean;
105
+ onCloseManage: () => void;
106
+ views: SavedViewSummary[];
107
+ onEditFromManage: (view: SavedViewSummary) => void;
108
+ onDelete: (view: SavedViewSummary) => void;
109
+ testIdPrefix: string;
110
+ }
111
+
112
+ /** The save-view modal + the manage-views dialog (FUT-89). */
113
+ export function ViewDialogs<T extends Record<string, unknown>>({
114
+ saveOpen,
115
+ onCloseSave,
116
+ currentState,
117
+ fields,
118
+ columns,
119
+ editing,
120
+ onSave,
121
+ manageOpen,
122
+ onCloseManage,
123
+ views,
124
+ onEditFromManage,
125
+ onDelete,
126
+ testIdPrefix,
127
+ }: ViewDialogsProps<T>): React.JSX.Element {
128
+ return (
129
+ <>
130
+ <SaveViewModal<T>
131
+ open={saveOpen}
132
+ onClose={onCloseSave}
133
+ currentState={currentState}
134
+ fields={fields}
135
+ columns={columns}
136
+ editing={editing}
137
+ onSave={onSave}
138
+ testIdPrefix={`${testIdPrefix}-views`}
139
+ />
140
+ <ManageViewsDialog
141
+ open={manageOpen}
142
+ onClose={onCloseManage}
143
+ views={views}
144
+ onEdit={onEditFromManage}
145
+ onDelete={onDelete}
146
+ testIdPrefix={`${testIdPrefix}-views`}
147
+ />
148
+ </>
149
+ );
150
+ }
@@ -0,0 +1,149 @@
1
+ "use client";
2
+
3
+ import CollapseIcon from '@mui/icons-material/ExpandLess';
4
+ import ExpandIcon from '@mui/icons-material/ExpandMore';
5
+ import { IconButton, Tooltip } from "@mui/material";
6
+
7
+ import {
8
+ ColumnsMenu,
9
+ ContentToolbar,
10
+ FilterTrigger,
11
+ SortByDropdown,
12
+ type ColumnVisibilityOption,
13
+ type SortFieldDefinition,
14
+ } from "../../layout/ContentToolbar";
15
+ import { Box } from "../../../mui/Box";
16
+ import { Text } from "../../typography/Text";
17
+
18
+ import { DataViewsLayoutToggle, DataViewsZoomSlider } from "./data-views-layout-context";
19
+ import { renderBulkActions } from "./data-views-grid-helpers";
20
+ import type { RowAction } from "./data-views-types";
21
+
22
+ export interface GridToolbarProps<T extends Record<string, unknown>> {
23
+ testIdPrefix: string;
24
+ selectedRows: T[];
25
+ selectAll: () => void;
26
+ clearSelection: () => void;
27
+ rowActions?: RowAction<T>[];
28
+ bulkActions?: (selectedRows: T[], clearSelection: () => void) => React.ReactNode;
29
+ sortFields: SortFieldDefinition[];
30
+ activeSortField: string;
31
+ activeSortOrder: "asc" | "desc";
32
+ onChangeSort: (field: string, order: "asc" | "desc") => void;
33
+ matchedCount: number;
34
+ totalCount: number;
35
+ toolbarRightSlot?: React.ReactNode;
36
+ columnOptions: ColumnVisibilityOption[];
37
+ onToggleColumn: (id: string, visible: boolean) => void;
38
+ filterOpen: boolean;
39
+ setFilterOpen: (open: boolean) => void;
40
+ activeFilterCount: number;
41
+ /** Hide the "Filtros" slide-in trigger (compact layout shows filters inline). */
42
+ showFilterTrigger?: boolean;
43
+ /** Show the ∧/∨ toggle that collapses/expands the inline filter row. */
44
+ showFiltersToggle?: boolean;
45
+ /** Whether the inline filter row is currently hidden. */
46
+ filtersHidden?: boolean;
47
+ /** Toggle the inline filter row's visibility. */
48
+ onToggleFilters?: () => void;
49
+ }
50
+
51
+ /** The right-aligned toolbar controls: Sort By, the counter, zoom/layout/columns, filters. */
52
+ function ToolbarRightControls<T extends Record<string, unknown>>(props: GridToolbarProps<T>): React.JSX.Element {
53
+ const { testIdPrefix, sortFields, matchedCount, totalCount, filterOpen, setFilterOpen } = props;
54
+ return (
55
+ <>
56
+ {sortFields.length > 0 && (
57
+ <SortByDropdown
58
+ fields={sortFields}
59
+ activeField={props.activeSortField}
60
+ activeOrder={props.activeSortOrder}
61
+ onFieldChange={(field) => props.onChangeSort(field, "asc")}
62
+ onOrderChange={(order) => props.onChangeSort(props.activeSortField, order === "desc" ? "desc" : "asc")}
63
+ data-testid={`${testIdPrefix}-sort-trigger`}
64
+ />
65
+ )}
66
+ <Text variant="caption" as="span">
67
+ {/* The "N de N" counter is hidden on mobile to keep the toolbar one line. */}
68
+ <Box
69
+ component="span"
70
+ data-testid={`${testIdPrefix}-counter`}
71
+ sx={{ whiteSpace: "nowrap", display: { xs: "none", md: "inline" } }}
72
+ >
73
+ Exibindo {matchedCount} de {totalCount}
74
+ </Box>
75
+ </Text>
76
+ {props.toolbarRightSlot}
77
+ <DataViewsZoomSlider testIdPrefix={testIdPrefix} />
78
+ <DataViewsLayoutToggle testIdPrefix={testIdPrefix} />
79
+ {props.columnOptions.length > 0 && (
80
+ <ColumnsMenu
81
+ columns={props.columnOptions}
82
+ onToggle={props.onToggleColumn}
83
+ title="Colunas"
84
+ ariaLabel="Exibir colunas"
85
+ data-testid={`${testIdPrefix}-columns-toggle`}
86
+ />
87
+ )}
88
+ {props.showFilterTrigger !== false && (
89
+ <FilterTrigger
90
+ open={filterOpen}
91
+ onOpenChange={setFilterOpen}
92
+ activeCount={props.activeFilterCount}
93
+ data-testid={`${testIdPrefix}-filters-toggle`}
94
+ />
95
+ )}
96
+ {props.showFiltersToggle && (
97
+ <Tooltip title={props.filtersHidden ? "Mostrar filtros" : "Ocultar filtros"}>
98
+ <IconButton
99
+ size="small"
100
+ onClick={props.onToggleFilters}
101
+ aria-label={props.filtersHidden ? "Mostrar filtros" : "Ocultar filtros"}
102
+ aria-expanded={!props.filtersHidden}
103
+ data-testid={`${testIdPrefix}-filters-collapse`}
104
+ >
105
+ {props.filtersHidden ? <ExpandIcon fontSize="small" /> : <CollapseIcon fontSize="small" />}
106
+ </IconButton>
107
+ </Tooltip>
108
+ )}
109
+ </>
110
+ );
111
+ }
112
+
113
+ /**
114
+ * The bordered toolbar band: selection chrome + Sort By, the result counter, the
115
+ * saved-views slot, and the filter funnel. The negative margin lets the top/bottom
116
+ * separators reach the sidebar's vertical line and the window edge.
117
+ */
118
+ export function GridToolbar<T extends Record<string, unknown>>(props: GridToolbarProps<T>): React.JSX.Element {
119
+ const { testIdPrefix, selectedRows } = props;
120
+ return (
121
+ <Box
122
+ sx={{
123
+ borderTop: 1,
124
+ borderBottom: 1,
125
+ borderColor: "divider",
126
+ py: 1.25,
127
+ mx: { xs: -2, md: -3 },
128
+ px: { xs: 2, md: 3 },
129
+ }}
130
+ >
131
+ <ContentToolbar
132
+ hasSelection={selectedRows.length > 0}
133
+ selectedCount={selectedRows.length}
134
+ selectAll={props.selectAll}
135
+ clearSelection={props.clearSelection}
136
+ selectAllTestId={`${testIdPrefix}-select-all`}
137
+ clearAllTestId={`${testIdPrefix}-clear-all`}
138
+ actions={renderBulkActions({
139
+ rowActions: props.rowActions,
140
+ bulkActions: props.bulkActions,
141
+ selectedRows,
142
+ clearSelection: props.clearSelection,
143
+ testIdPrefix,
144
+ })}
145
+ rightControls={<ToolbarRightControls {...props} />}
146
+ />
147
+ </Box>
148
+ );
149
+ }