@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,312 @@
1
+ import type { GridColumn, GridSort } from "../DataGrid";
2
+ import type { DropdownMenuItem } from "../../navigation/DropdownMenu";
3
+
4
+ /**
5
+ * Shared types for the reusable admin "DataViews" table (FUT-88): a filter bar
6
+ * (search-across-all + typed multi-select pills + column visibility) whose full
7
+ * state — filters + sort + visible columns — a saved view (FUT-89) can capture
8
+ * and restore. Each table declares its own columns + filter fields.
9
+ */
10
+
11
+ /**
12
+ * A single, reusable row action. ONE definition drives BOTH the per-row "⋮"
13
+ * kebab menu and the bulk-actions menu (tabwoah model): `onSelect` receives the
14
+ * affected rows — `[row]` from a kebab, the whole selection from the bulk menu.
15
+ * Single-item-only actions (e.g. "Editar") set `bulk: false` so they never
16
+ * appear in the bulk menu.
17
+ */
18
+ export interface RowAction<T extends Record<string, unknown>> {
19
+ /** Stable id (also the `data-testid` suffix). */
20
+ id: string;
21
+ /** Menu label. In the kebab, `rowLabel` overrides it per row when provided. */
22
+ label: string;
23
+ /** Menu-item colour (e.g. `"error"` for destructive). */
24
+ color?: DropdownMenuItem["color"];
25
+ /**
26
+ * Runs on the affected rows: `[row]` from the kebab, all selected from bulk.
27
+ * May be async — the bulk menu awaits it and only clears the selection once it
28
+ * settles (keeping the selection on failure so the user can retry).
29
+ */
30
+ onSelect: (rows: T[]) => void | Promise<void>;
31
+ /** Include in the bulk menu (2+ selected). Defaults to `true`. */
32
+ bulk?: boolean;
33
+ /** Include in the per-row kebab. Defaults to `true`. */
34
+ row?: boolean;
35
+ /** Per-row kebab label (e.g. `row.active ? "Inativar" : "Ativar"`). */
36
+ rowLabel?: (row: T) => string;
37
+ /**
38
+ * Per-row applicability (e.g. state-machine guards). `false` hides the
39
+ * kebab item for that row; in bulk the action runs only on the passing
40
+ * rows and is dropped when none pass. Defaults to applicable.
41
+ */
42
+ isVisible?: (row: T) => boolean;
43
+ }
44
+
45
+ /** Selection state handed to a card renderer so it can drive its own checkbox. */
46
+ export interface DataViewCardSelection {
47
+ selected: boolean;
48
+ onToggleSelect: () => void;
49
+ /**
50
+ * Card SIZE multiplier from the toolbar zoom slider. The grid sizes the card's
51
+ * width to `base × scale`; a card passes this to {@link BaseCard} `scale` so its
52
+ * padding + typography grow by the same factor — the whole card scales together
53
+ * (scale 2 → ~2× size). The proportion (aspect ratio) stays constant.
54
+ */
55
+ scale: number;
56
+ }
57
+
58
+ /**
59
+ * The fixed proportions a {@link BaseCard} tile can take. The tile keeps this
60
+ * ratio and grows in BOTH width and height as the zoom slider widens its grid
61
+ * track, so a grid of cards stays visually uniform.
62
+ */
63
+ export type CardAspectRatio = "1:1" | "4:3" | "16:9" | "9:16" | "3:4";
64
+
65
+ /** Numeric width/height factor for each {@link CardAspectRatio} (CSS `aspect-ratio`). */
66
+ export const CARD_ASPECT_RATIOS: Record<CardAspectRatio, number> = {
67
+ "1:1": 1,
68
+ "4:3": 4 / 3,
69
+ "16:9": 16 / 9,
70
+ "9:16": 9 / 16,
71
+ "3:4": 3 / 4,
72
+ };
73
+
74
+ /** One selectable value inside a filter pill. */
75
+ export interface FilterOption {
76
+ value: string;
77
+ label: string;
78
+ }
79
+
80
+ /** A typed, multi-select filter pill's configuration for a table. */
81
+ export interface FilterFieldConfig<T extends Record<string, unknown>> {
82
+ /** Stable id; also the default row key when no `accessor` is given. */
83
+ id: string;
84
+ label: string;
85
+ options: FilterOption[];
86
+ /**
87
+ * How the field renders in the filter panel. `checkboxes` (default) is best for
88
+ * a few fixed options; `multiselect` is a compact dropdown for long option
89
+ * lists (e.g. many categories).
90
+ */
91
+ control?: "checkboxes" | "multiselect";
92
+ /**
93
+ * Forces this filter to render as a searchable multi-select dropdown with the
94
+ * search box always shown, regardless of how many options are currently
95
+ * loaded. Use it when the option set can grow unbounded (e.g. a filter backed
96
+ * by a relation such as Roles or Categories). Omit it for a closed value set
97
+ * (an enum), which keeps the plain checkbox / "search only when long"
98
+ * behavior.
99
+ */
100
+ searchEnabled?: boolean;
101
+ /**
102
+ * Reads the row's value(s) for this field. A row matches the pill when any of
103
+ * its values is selected. Defaults to `String(row[id])`.
104
+ */
105
+ accessor?: (row: T) => string | string[];
106
+ }
107
+
108
+ /**
109
+ * A selected range for a range filter (either bound optional). Numbers for a
110
+ * `number` field; `AAAA-MM-DD` day strings for a `day` one — which compare
111
+ * correctly with `<`/`>` precisely because ISO days sort lexicographically.
112
+ */
113
+ export interface RangeValue {
114
+ min?: number | string;
115
+ max?: number | string;
116
+ }
117
+
118
+ /** What a range field measures — the input it renders and the bound it stores. */
119
+ export type RangeFieldKind = "number" | "day";
120
+
121
+ interface RangeFieldBase {
122
+ /** Stable id; the key under `DataViewState.ranges`. */
123
+ id: string;
124
+ label: string;
125
+ }
126
+
127
+ /** "Filter by amount": price, stock, margin, order total. */
128
+ export interface NumberRangeFieldConfig<T extends Record<string, unknown>> extends RangeFieldBase {
129
+ kind?: "number";
130
+ /** Reads the row's numeric value for this range. */
131
+ accessor: (row: T) => number | null | undefined;
132
+ /** Optional unit suffix shown next to the inputs (e.g. "R$", "un"). */
133
+ unit?: string;
134
+ /** Numeric input step. Defaults to 1. */
135
+ step?: number;
136
+ }
137
+
138
+ /**
139
+ * "Filter by period": a pair of INCLUSIVE calendar days, rendered as two native
140
+ * date inputs. Inclusive is the reason a day range is its own kind rather than a
141
+ * number over timestamps — coercing an `até` of `2026-07-15` to a instant lands
142
+ * on that day's midnight and drops the whole final day (FUT-668).
143
+ */
144
+ export interface DayRangeFieldConfig<T extends Record<string, unknown>> extends RangeFieldBase {
145
+ kind: "day";
146
+ /** Reads the row's `AAAA-MM-DD` day for this range. */
147
+ accessor: (row: T) => string | null | undefined;
148
+ }
149
+
150
+ /**
151
+ * A min/max range filter's configuration. Complements the multi-select pills.
152
+ * A row with a null/undefined value never matches a bounded range.
153
+ */
154
+ export type RangeFieldConfig<T extends Record<string, unknown>> =
155
+ | NumberRangeFieldConfig<T>
156
+ | DayRangeFieldConfig<T>;
157
+
158
+ /** A grid column that can join the search scan and the column-visibility menu. */
159
+ export interface DataViewColumn<T extends Record<string, unknown>> extends GridColumn<T> {
160
+ /** Included in "search across all columns" (needs a resolvable value). */
161
+ searchable?: boolean;
162
+ /** Toggleable in the column-visibility menu. Defaults to true; set false for
163
+ * structural columns (image thumbnail, actions kebab) that must always show. */
164
+ hideable?: boolean;
165
+ }
166
+
167
+ /** The full, serializable state a view captures. */
168
+ export interface DataViewState {
169
+ /** Free text matched across every `searchable` column. */
170
+ search: string;
171
+ /** fieldId → selected option values (empty/absent = no constraint). */
172
+ pills: Record<string, string[]>;
173
+ /** fieldId → selected numeric range (min/max). Absent/empty = no constraint. */
174
+ ranges?: Record<string, RangeValue>;
175
+ sortBy: GridSort[];
176
+ /** Column ids kept visible; a hideable column not listed here is hidden. */
177
+ visibleColumns: string[];
178
+ }
179
+
180
+ /** A pristine view state showing every given column and no filters/sort. */
181
+ export function emptyViewState(visibleColumns: string[]): DataViewState {
182
+ return { search: "", pills: {}, ranges: {}, sortBy: [], visibleColumns };
183
+ }
184
+
185
+ /**
186
+ * The URL-driven slice of {@link DataViewState} — the controls a server-mode host
187
+ * mirrors from the address bar (search / pills / ranges / sort), WITHOUT
188
+ * `visibleColumns`. Supplying it re-applies those controls when its reference
189
+ * changes (e.g. browser back/forward or a deep-link on the same route), merging
190
+ * over the current state so a user's show/hide column choices are preserved —
191
+ * unlike `appliedState`, which fully replaces the state to apply a saved view.
192
+ */
193
+ export type DataViewSyncState = Pick<DataViewState, "search" | "pills" | "ranges" | "sortBy">;
194
+
195
+ /**
196
+ * The query a SERVER-mode table emits whenever its filter/sort/page changes
197
+ * (FUT-180). The host translates this into a backend request (see
198
+ * `@12-apps/shared-helpers/search`) — in server mode the grid never filters,
199
+ * sorts, or paginates in the browser; it renders exactly the page the server
200
+ * returned. `page` is 1-based to match the backend contract.
201
+ */
202
+ export interface DataViewQuery {
203
+ search: string;
204
+ pills: Record<string, string[]>;
205
+ ranges: Record<string, RangeValue>;
206
+ sortBy: GridSort[];
207
+ page: number;
208
+ pageSize: number;
209
+ }
210
+
211
+ /**
212
+ * Server-mode wiring for a DataViews table. Its PRESENCE flips the table from
213
+ * in-browser filtering/sorting/pagination to backend-driven: the rows handed in
214
+ * are already the current page, `totalCount` is the unpaginated total, and
215
+ * `onQueryChange` fires (search debounced by the host) whenever the user changes
216
+ * a filter, the sort, or the page. This is the ONLY way an admin list should run
217
+ * (see the app-side `DataViewsTable` wrapper, which requires it).
218
+ */
219
+ export interface DataViewServer {
220
+ /** Total matched rows across all pages (drives the counter + page count). */
221
+ totalCount: number;
222
+ /** Current 1-based page. */
223
+ page: number;
224
+ /** Rows per page. */
225
+ pageSize: number;
226
+ /** Fired when the effective query changes; the host re-fetches the page. */
227
+ onQueryChange: (query: DataViewQuery) => void;
228
+ }
229
+
230
+ /**
231
+ * Coerce an opaque persisted state (a saved view's JSON) into a valid
232
+ * DataViewState, filling any missing part with a sane default. Guards against
233
+ * legacy/older shapes so applying a saved view never renders an empty grid.
234
+ */
235
+ export function coerceViewState(raw: unknown, allColumnIds: string[]): DataViewState {
236
+ const value = (raw ?? {}) as Partial<DataViewState>;
237
+ return {
238
+ search: typeof value.search === "string" ? value.search : "",
239
+ pills:
240
+ value.pills && typeof value.pills === "object"
241
+ ? (value.pills as Record<string, string[]>)
242
+ : {},
243
+ ranges:
244
+ value.ranges && typeof value.ranges === "object"
245
+ ? (value.ranges as Record<string, RangeValue>)
246
+ : {},
247
+ sortBy: Array.isArray(value.sortBy) ? value.sortBy : [],
248
+ visibleColumns: Array.isArray(value.visibleColumns) ? value.visibleColumns : allColumnIds,
249
+ };
250
+ }
251
+
252
+ /** A saved view as consumed by the DataViews UI (FUT-89), with ownership flag. */
253
+ export interface SavedViewSummary {
254
+ id: string;
255
+ name: string;
256
+ description: string | null;
257
+ state: DataViewState;
258
+ shared: boolean;
259
+ pinned: boolean;
260
+ isDefault: boolean;
261
+ /** True when the current user owns the view (may edit/delete/pin/share it). */
262
+ isOwner: boolean;
263
+ }
264
+
265
+ /** A saved-view repository record (opaque `state`), as returned to server pages. */
266
+ interface SavedViewRecordLike {
267
+ id: string;
268
+ name: string;
269
+ description: string | null;
270
+ state: unknown;
271
+ shared: boolean;
272
+ pinned: boolean;
273
+ isDefault: boolean;
274
+ isOwner: boolean;
275
+ }
276
+
277
+ /** Map a repository record to the client summary (opaque state → DataViewState). */
278
+ export function toSavedViewSummary(record: SavedViewRecordLike): SavedViewSummary {
279
+ return { ...record, state: (record.state ?? {}) as DataViewState };
280
+ }
281
+
282
+ /**
283
+ * Dependency-injection contracts for the framework-agnostic DataViewsTableBase:
284
+ * the host app supplies saved-view persistence + router side-effects so the ui
285
+ * component imports neither a backend (server actions) nor a framework router.
286
+ */
287
+
288
+ /** A saved view's editable fields, as the host persists them. */
289
+ export interface DataViewSaveInput {
290
+ name: string;
291
+ description: string;
292
+ state: DataViewState;
293
+ shared: boolean;
294
+ pinned: boolean;
295
+ isDefault: boolean;
296
+ }
297
+
298
+ /** Result of a persistence call — mirrors the app's `Result` without importing it. */
299
+ export type DataViewMutationResult = { ok: true } | { ok: false; error: string };
300
+
301
+ /** Injected saved-view persistence (create/update/delete), wired by the host. */
302
+ export interface DataViewPersistence {
303
+ create: (input: DataViewSaveInput) => Promise<DataViewMutationResult>;
304
+ update: (id: string, input: DataViewSaveInput) => Promise<DataViewMutationResult>;
305
+ remove: (id: string) => Promise<DataViewMutationResult>;
306
+ }
307
+
308
+ /** Injected router side-effects: sync the `?view=` param and re-fetch on change. */
309
+ export interface DataViewRouter {
310
+ syncViewParam: (viewId: string | null) => void;
311
+ refresh: () => void;
312
+ }
@@ -0,0 +1,68 @@
1
+ "use client";
2
+
3
+ import type { MutableRefObject } from "react";
4
+
5
+ import type {
6
+ DataViewPersistence,
7
+ DataViewSaveInput,
8
+ DataViewState,
9
+ SavedViewSummary,
10
+ } from "./data-views-types";
11
+ import { type SaveViewPayload } from "./SaveViewModal";
12
+
13
+ export interface ViewMutations {
14
+ handleSave: (payload: SaveViewPayload) => Promise<void>;
15
+ patchView: (
16
+ view: SavedViewSummary,
17
+ changes: Partial<Pick<SavedViewSummary, "isDefault" | "pinned" | "shared">>,
18
+ ) => Promise<void>;
19
+ handleDelete: (view: SavedViewSummary) => Promise<void>;
20
+ }
21
+
22
+ /** The SavedView persistence handlers (create/update/delete), via injected `persistence`. */
23
+ export function useViewMutations(
24
+ persistence: DataViewPersistence,
25
+ editing: SavedViewSummary | null,
26
+ currentRef: MutableRefObject<DataViewState>,
27
+ onDone: (ok: boolean, error?: string) => void,
28
+ ): ViewMutations {
29
+ async function handleSave(payload: SaveViewPayload): Promise<void> {
30
+ const state = editing ? editing.state : currentRef.current;
31
+ const input: DataViewSaveInput = {
32
+ name: payload.name,
33
+ description: payload.description,
34
+ state,
35
+ shared: payload.shared,
36
+ pinned: payload.pinned,
37
+ isDefault: payload.isDefault,
38
+ };
39
+ const result = editing ? await persistence.update(editing.id, input) : await persistence.create(input);
40
+ // Fail loudly on a rejected save (e.g. duplicate name) so the modal stays
41
+ // open and shows the error instead of closing as if it succeeded.
42
+ if (!result.ok) throw new Error(result.error);
43
+ onDone(true);
44
+ }
45
+
46
+ async function patchView(
47
+ view: SavedViewSummary,
48
+ changes: Partial<Pick<SavedViewSummary, "isDefault" | "pinned" | "shared">>,
49
+ ): Promise<void> {
50
+ const next = { ...view, ...changes };
51
+ const result = await persistence.update(view.id, {
52
+ name: next.name,
53
+ description: next.description ?? "",
54
+ state: next.state,
55
+ shared: next.shared,
56
+ pinned: next.pinned,
57
+ isDefault: next.isDefault,
58
+ });
59
+ onDone(result.ok, result.ok ? undefined : result.error);
60
+ }
61
+
62
+ async function handleDelete(view: SavedViewSummary): Promise<void> {
63
+ const result = await persistence.remove(view.id);
64
+ onDone(result.ok, result.ok ? undefined : result.error);
65
+ }
66
+
67
+ return { handleSave, patchView, handleDelete };
68
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * DataViews — the reusable admin table/grid machinery (FUT-88/89): a filter bar,
3
+ * saved views, sort, column visibility, select-all + bulk actions, and an opt-in
4
+ * "Grade" (cards) layout. Framework-agnostic: {@link DataViewsTableBase} takes its
5
+ * saved-view persistence + router side-effects as injected props, so a host app
6
+ * wires them to its backend and framework router.
7
+ */
8
+ export { BaseCard } from "./base-card";
9
+ export { DataViewsGrid } from "./DataViewsGrid";
10
+ export { DataViewsTableBase, type DataViewsTableBaseProps } from "./DataViewsTableBase";
11
+ export { toSavedViewSummary, CARD_ASPECT_RATIOS } from "./data-views-types";
12
+ export { cardScaleForZoom, cardMinWidthForZoom } from "./data-views-layout-context";
13
+ export type {
14
+ RowAction,
15
+ DataViewCardSelection,
16
+ CardAspectRatio,
17
+ SavedViewSummary,
18
+ DataViewState,
19
+ DataViewSyncState,
20
+ DataViewColumn,
21
+ FilterFieldConfig,
22
+ RangeFieldConfig,
23
+ RangeFieldKind,
24
+ RangeValue,
25
+ NumberRangeFieldConfig,
26
+ DayRangeFieldConfig,
27
+ DataViewPersistence,
28
+ DataViewRouter,
29
+ DataViewSaveInput,
30
+ DataViewMutationResult,
31
+ DataViewQuery,
32
+ DataViewServer,
33
+ } from "./data-views-types";