@12-apps/ui 1.0.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components-catalog.md +14 -0
- package/package.json +42 -27
- package/src/__tests__/data-grid.test.tsx +125 -0
- package/src/__tests__/package-wiring.test.ts +12 -8
- package/src/__tests__/social-login-button.test.tsx +5 -5
- package/src/__tests__/viewport.test.ts +50 -0
- package/src/charts/index.ts +8 -0
- package/src/components/data-display/Alert/Alert.md +1 -1
- package/src/components/data-display/Alert/Alert.stories.tsx +5 -7
- package/src/components/data-display/Alert/Alert.styles.tsx +255 -0
- package/src/components/data-display/Alert/Alert.test.stories.tsx +11 -13
- package/src/components/data-display/Alert/Alert.tsx +135 -328
- package/src/components/data-display/AlertDialog/AlertDialog.stories.tsx +3 -1
- package/src/components/data-display/AlertDialog/AlertDialog.tsx +191 -78
- package/src/components/data-display/AlertDialog/AlertDialog.types.ts +8 -1
- package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.test.stories.tsx +5 -5
- package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.tsx +44 -35
- package/src/components/data-display/Avatar/Avatar.stories.tsx +4 -1
- package/src/components/data-display/Avatar/Avatar.test.stories.tsx +5 -3
- package/src/components/data-display/Avatar/Avatar.tsx +154 -450
- package/src/components/data-display/Avatar/Avatar.view.tsx +396 -0
- package/src/components/data-display/Badge/Badge.animations.ts +67 -0
- package/src/components/data-display/Badge/Badge.helpers.ts +74 -0
- package/src/components/data-display/Badge/Badge.stories.tsx +14 -16
- package/src/components/data-display/Badge/Badge.styles.ts +261 -0
- package/src/components/data-display/Badge/Badge.test.stories.tsx +32 -31
- package/src/components/data-display/Badge/Badge.tsx +151 -557
- package/src/components/data-display/Badge/Badge.variants.ts +106 -0
- package/src/components/data-display/Badge/BadgeContent.tsx +107 -0
- package/src/components/data-display/Banner/Banner.stories.tsx +5 -1
- package/src/components/data-display/Banner/Banner.styles.ts +120 -0
- package/src/components/data-display/Banner/Banner.tsx +179 -224
- package/src/components/data-display/Chart/Chart.md +48 -1
- package/src/components/data-display/Chart/Chart.tsx +82 -500
- package/src/components/data-display/Chart/Chart.types.ts +2 -0
- package/src/components/data-display/Chart/ChartComposables.tsx +121 -0
- package/src/components/data-display/Chart/ChartSpec.types.ts +70 -0
- package/src/components/data-display/Chart/SpecChart.stories.tsx +150 -0
- package/src/components/data-display/Chart/SpecChart.test.stories.tsx +56 -0
- package/src/components/data-display/Chart/SpecChart.tsx +53 -0
- package/src/components/data-display/Chart/__tests__/SpecChart.test.tsx +60 -0
- package/src/components/data-display/Chart/__tests__/chart-format.test.ts +43 -0
- package/src/components/data-display/Chart/__tests__/chart-spec.test.ts +119 -0
- package/src/components/data-display/Chart/chart-format.ts +26 -0
- package/src/components/data-display/Chart/chart-internals.ts +148 -0
- package/src/components/data-display/Chart/chart-renderers.tsx +338 -0
- package/src/components/data-display/Chart/chart-spec-registry.ts +74 -0
- package/src/components/data-display/Chart/chart-spec.ts +171 -0
- package/src/components/data-display/Chart/index.ts +30 -0
- package/src/components/data-display/Chip/Chip.helpers.tsx +131 -0
- package/src/components/data-display/Chip/Chip.stories.tsx +2 -1
- package/src/components/data-display/Chip/Chip.test.stories.tsx +11 -8
- package/src/components/data-display/Chip/Chip.tsx +31 -94
- package/src/components/data-display/DataGrid/DataGrid.body.tsx +141 -0
- package/src/components/data-display/DataGrid/DataGrid.cells.tsx +238 -0
- package/src/components/data-display/DataGrid/DataGrid.model.ts +315 -0
- package/src/components/data-display/DataGrid/DataGrid.rows.ts +112 -0
- package/src/components/data-display/DataGrid/DataGrid.states.tsx +102 -0
- package/src/components/data-display/DataGrid/DataGrid.test.stories.tsx +6 -12
- package/src/components/data-display/DataGrid/DataGrid.tsx +129 -725
- package/src/components/data-display/DataViews/DataViewsGrid.tsx +187 -0
- package/src/components/data-display/DataViews/DataViewsTableBase.tsx +400 -0
- package/src/components/data-display/DataViews/ManageViewsDialog.tsx +140 -0
- package/src/components/data-display/DataViews/SaveViewModal.tsx +289 -0
- package/src/components/data-display/DataViews/__tests__/DataViewsGrid.test.tsx +271 -0
- package/src/components/data-display/DataViews/__tests__/DataViewsTableBase.test.tsx +134 -0
- package/src/components/data-display/DataViews/__tests__/SaveViewModal.test.tsx +83 -0
- package/src/components/data-display/DataViews/__tests__/data-views-filter.test.ts +115 -0
- package/src/components/data-display/DataViews/__tests__/data-views-preview.test.ts +53 -0
- package/src/components/data-display/DataViews/__tests__/range-pill.test.tsx +114 -0
- package/src/components/data-display/DataViews/base-card.stories.tsx +136 -0
- package/src/components/data-display/DataViews/base-card.tsx +278 -0
- package/src/components/data-display/DataViews/data-views-filter-panel.tsx +184 -0
- package/src/components/data-display/DataViews/data-views-filter.ts +138 -0
- package/src/components/data-display/DataViews/data-views-grid-helpers.tsx +248 -0
- package/src/components/data-display/DataViews/data-views-grid-parts.tsx +400 -0
- package/src/components/data-display/DataViews/data-views-inline-bar.tsx +257 -0
- package/src/components/data-display/DataViews/data-views-layout-context.tsx +176 -0
- package/src/components/data-display/DataViews/data-views-pagination.tsx +31 -0
- package/src/components/data-display/DataViews/data-views-preview.ts +53 -0
- package/src/components/data-display/DataViews/data-views-range-pill.tsx +277 -0
- package/src/components/data-display/DataViews/data-views-table-parts.tsx +150 -0
- package/src/components/data-display/DataViews/data-views-toolbar.tsx +149 -0
- package/src/components/data-display/DataViews/data-views-types.ts +312 -0
- package/src/components/data-display/DataViews/data-views-view-mutations.ts +68 -0
- package/src/components/data-display/DataViews/index.ts +33 -0
- package/src/components/data-display/DataViews/use-data-views-state.ts +349 -0
- package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.hooks.ts +104 -0
- package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.tsx +68 -118
- package/src/components/data-display/DescriptionItem/DescriptionItem.stories.tsx +1 -1
- package/src/components/data-display/DescriptionItem/DescriptionItem.tsx +52 -34
- package/src/components/data-display/EmptyState/EmptyState.test.stories.tsx +6 -6
- package/src/components/data-display/EmptyState/EmptyState.tsx +218 -135
- package/src/components/data-display/ErrorState/ErrorState.test.stories.tsx +2 -2
- package/src/components/data-display/ErrorState/ErrorState.tsx +83 -55
- package/src/components/data-display/HoverCard/HoverCard.stories.tsx +3 -1
- package/src/components/data-display/HoverCard/HoverCard.test.stories.tsx +5 -5
- package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.hooks.ts +99 -0
- package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.styles.ts +87 -0
- package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.tsx +28 -155
- package/src/components/data-display/LazyImage/LazyImage.hooks.ts +203 -0
- package/src/components/data-display/LazyImage/LazyImage.md +1 -1
- package/src/components/data-display/LazyImage/LazyImage.stories.tsx +3 -3
- package/src/components/data-display/LazyImage/LazyImage.tsx +144 -243
- package/src/components/data-display/Lightbox/Lightbox.constants.ts +53 -0
- package/src/components/data-display/Lightbox/Lightbox.helpers.ts +39 -0
- package/src/components/data-display/Lightbox/Lightbox.hooks.ts +259 -0
- package/src/components/data-display/Lightbox/Lightbox.test.stories.tsx +28 -35
- package/src/components/data-display/Lightbox/Lightbox.tsx +98 -658
- package/src/components/data-display/Lightbox/LightboxControls.tsx +152 -0
- package/src/components/data-display/Lightbox/LightboxCurrentMedia.tsx +50 -0
- package/src/components/data-display/Lightbox/LightboxMedia.tsx +76 -0
- package/src/components/data-display/Lightbox/LightboxOverlay.tsx +83 -0
- package/src/components/data-display/Lightbox/LightboxStage.tsx +97 -0
- package/src/components/data-display/Lightbox/LightboxThumbnails.tsx +83 -0
- package/src/components/data-display/Lightbox/useLightbox.ts +80 -0
- package/src/components/data-display/LoadingState/LoadingState.helpers.ts +52 -0
- package/src/components/data-display/LoadingState/LoadingState.tsx +117 -87
- package/src/components/data-display/MapPreview/MapControlBar.tsx +116 -0
- package/src/components/data-display/MapPreview/MapDecorations.tsx +155 -0
- package/src/components/data-display/MapPreview/MapLayers.tsx +70 -0
- package/src/components/data-display/MapPreview/MapMarkers.tsx +84 -0
- package/src/components/data-display/MapPreview/MapOverlays.tsx +68 -0
- package/src/components/data-display/MapPreview/MapPreview.constants.ts +19 -0
- package/src/components/data-display/MapPreview/MapPreview.helpers.ts +63 -0
- package/src/components/data-display/MapPreview/MapPreview.hooks.ts +265 -0
- package/src/components/data-display/MapPreview/MapPreview.test.stories.tsx +14 -10
- package/src/components/data-display/MapPreview/MapPreview.tsx +52 -882
- package/src/components/data-display/MapPreview/MapPreview.types.ts +8 -1
- package/src/components/data-display/MapPreview/MapSearchBar.tsx +64 -0
- package/src/components/data-display/MapPreview/MapTiles.tsx +70 -0
- package/src/components/data-display/MapPreview/StaticMapView.tsx +63 -0
- package/src/components/data-display/MapPreview/mapProjection.ts +52 -0
- package/src/components/data-display/MapPreview/mapSurface.ts +37 -0
- package/src/components/data-display/MapPreview/useMapPreview.ts +62 -0
- package/src/components/data-display/Popover/Popover.test.stories.tsx +13 -19
- package/src/components/data-display/Progress/Progress.helpers.ts +37 -0
- package/src/components/data-display/Progress/Progress.styles.ts +101 -0
- package/src/components/data-display/Progress/Progress.tsx +185 -213
- package/src/components/data-display/SectionOnboarding/SectionOnboarding.stories.tsx +1 -1
- package/src/components/data-display/SectionOnboarding/SectionOnboarding.tsx +1 -1
- package/src/components/data-display/StatCard/StatCard.md +117 -0
- package/src/components/data-display/StatCard/StatCard.stories.tsx +167 -0
- package/src/components/data-display/StatCard/StatCard.test.stories.tsx +240 -0
- package/src/components/data-display/StatCard/StatCard.tsx +236 -0
- package/src/components/data-display/StatCard/StatCard.types.ts +62 -0
- package/src/components/data-display/StatCard/index.ts +7 -0
- package/src/components/data-display/Stepper/Stepper.test.stories.tsx +12 -19
- package/src/components/data-display/Stepper/Stepper.tsx +1 -1
- package/src/components/data-display/Table/Table.helpers.ts +31 -0
- package/src/components/data-display/Table/Table.hooks.ts +161 -0
- package/src/components/data-display/Table/Table.stories.tsx +3 -1
- package/src/components/data-display/Table/Table.styles.ts +223 -0
- package/src/components/data-display/Table/Table.test.stories.tsx +4 -4
- package/src/components/data-display/Table/Table.tsx +291 -748
- package/src/components/data-display/Table/TableParts.hooks.tsx +112 -0
- package/src/components/data-display/Table/TableParts.tsx +298 -0
- package/src/components/data-display/Table/TableStates.tsx +21 -0
- package/src/components/data-display/Timeline/Timeline.stories.tsx +10 -12
- package/src/components/data-display/Timeline/Timeline.test.stories.tsx +30 -44
- package/src/components/data-display/Timeline/Timeline.tsx +23 -284
- package/src/components/data-display/Timeline/TimelineRow.tsx +346 -0
- package/src/components/data-display/TimingDiagram/TimingDiagram.tsx +38 -311
- package/src/components/data-display/TimingDiagram/TimingDiagram.views.tsx +346 -0
- package/src/components/data-display/Tooltip/Tooltip.stories.tsx +4 -1
- package/src/components/data-display/Tooltip/Tooltip.test.stories.tsx +44 -58
- package/src/components/data-display/Tooltip/Tooltip.tsx +67 -62
- package/src/components/data-display/index.ts +1 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.hooks.ts +96 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.md +140 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.parts.tsx +154 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.stories.tsx +146 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.test.stories.tsx +114 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.tsx +46 -0
- package/src/components/feedback/ConfirmAction/ConfirmAction.types.ts +111 -0
- package/src/components/feedback/ConfirmAction/ConfirmButton.tsx +18 -0
- package/src/components/feedback/ConfirmAction/__tests__/confirm-action.test.tsx +288 -0
- package/src/components/feedback/ConfirmAction/index.ts +16 -0
- package/src/components/feedback/ConfirmAction/with-confirmation.tsx +112 -0
- package/src/components/feedback/Dialog/Dialog.styles.ts +4 -2
- package/src/components/feedback/Dialog/Dialog.tsx +26 -1
- package/src/components/feedback/Dialog/__tests__/dialog-content-spacing.test.tsx +66 -0
- package/src/components/feedback/Modal/Modal.md +1 -1
- package/src/components/feedback/Modal/Modal.stories.tsx +2 -2
- package/src/components/feedback/Sonner/Sonner.tsx +104 -288
- package/src/components/feedback/Sonner/Sonner.types.ts +7 -0
- package/src/components/feedback/Sonner/SonnerToast.tsx +216 -0
- package/src/components/feedback/StackedModal/StackedModal.hooks.ts +226 -0
- package/src/components/feedback/StackedModal/StackedModal.parts.tsx +311 -0
- package/src/components/feedback/StackedModal/StackedModal.stories.tsx +13 -15
- package/src/components/feedback/StackedModal/StackedModal.styles.ts +193 -0
- package/src/components/feedback/StackedModal/StackedModal.tsx +100 -619
- package/src/components/feedback/StackedModal/StackedModal.types.ts +17 -3
- package/src/components/feedback/StackedModal/__tests__/stacked-modal-viewport.test.tsx +104 -0
- package/src/components/feedback/StackedModal/modal-stack.tsx +119 -0
- package/src/components/feedback/Toast/Toast.tsx +92 -81
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.geometry.ts +65 -0
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.hooks.ts +185 -0
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.test.stories.tsx +2 -2
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.tsx +156 -414
- package/src/components/feedback/TutorialOverlay/TutorialStepBody.tsx +255 -0
- package/src/components/feedback/index.ts +1 -0
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.helpers.ts +58 -0
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.hooks.ts +93 -0
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.mapper.ts +57 -0
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.stories.tsx +4 -2
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.test.stories.tsx +20 -16
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.tsx +26 -829
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.types.ts +11 -0
- package/src/components/form/AddressAutocomplete/AddressAutocompleteField.tsx +86 -0
- package/src/components/form/AddressAutocomplete/AddressFallbackField.tsx +64 -0
- package/src/components/form/AddressAutocomplete/AddressInputField.tsx +80 -0
- package/src/components/form/AddressAutocomplete/AddressOption.tsx +83 -0
- package/src/components/form/AddressAutocomplete/AddressSuggestionsPaper.tsx +24 -0
- package/src/components/form/AddressAutocomplete/AddressTextField.tsx +43 -0
- package/src/components/form/AddressAutocomplete/mockPlaces.ts +208 -0
- package/src/components/form/AddressAutocomplete/useAddressPredictions.ts +136 -0
- package/src/components/form/AddressAutocomplete/useAddressSelection.ts +113 -0
- package/src/components/form/AddressAutocomplete/useCurrentLocation.ts +116 -0
- package/src/components/form/AddressAutocomplete/useGoogleMapsAPI.ts +75 -0
- package/src/components/form/Button/Button.helpers.ts +36 -0
- package/src/components/form/Button/Button.stories.tsx +4 -1
- package/src/components/form/Button/Button.styles.ts +225 -0
- package/src/components/form/Button/Button.test.stories.tsx +25 -21
- package/src/components/form/Button/Button.tsx +45 -252
- package/src/components/form/Calendar/Calendar.dates.ts +100 -0
- package/src/components/form/Calendar/Calendar.helpers.ts +32 -0
- package/src/components/form/Calendar/Calendar.hooks.ts +278 -0
- package/src/components/form/Calendar/Calendar.keyboard.ts +32 -0
- package/src/components/form/Calendar/Calendar.selection.ts +156 -0
- package/src/components/form/Calendar/Calendar.test.stories.tsx +33 -34
- package/src/components/form/Calendar/Calendar.tsx +63 -551
- package/src/components/form/Calendar/Calendar.types.ts +16 -0
- package/src/components/form/Calendar/CalendarDay.tsx +127 -0
- package/src/components/form/Calendar/CalendarDayCell.tsx +52 -0
- package/src/components/form/Calendar/CalendarMonth.tsx +128 -0
- package/src/components/form/CepField/CepField.md +138 -0
- package/src/components/form/CepField/CepField.stories.tsx +138 -0
- package/src/components/form/CepField/CepField.test.stories.tsx +281 -0
- package/src/components/form/CepField/CepField.tsx +211 -0
- package/src/components/form/CepField/CepField.types.ts +73 -0
- package/src/components/form/CepField/index.ts +2 -0
- package/src/components/form/Checkbox/Checkbox.helpers.ts +28 -0
- package/src/components/form/Checkbox/Checkbox.tsx +19 -16
- package/src/components/form/CodeEditor/CodeEditor.helpers.ts +45 -0
- package/src/components/form/CodeEditor/CodeEditor.hooks.ts +104 -0
- package/src/components/form/CodeEditor/CodeEditor.monaco.ts +109 -0
- package/src/components/form/CodeEditor/CodeEditor.test.stories.tsx +17 -18
- package/src/components/form/CodeEditor/CodeEditor.tsx +81 -330
- package/src/components/form/CodeEditor/CodeEditorToolbar.tsx +168 -0
- package/src/components/form/Command/Command.hooks.ts +207 -0
- package/src/components/form/Command/Command.parts.tsx +58 -0
- package/src/components/form/Command/Command.styles.ts +83 -0
- package/src/components/form/Command/Command.tsx +61 -270
- package/src/components/form/CreatableSelect/CreatableSelect.md +1 -1
- package/src/components/form/CreatableSelect/CreatableSelect.test.stories.tsx +1 -1
- package/src/components/form/CreatableSelect/CreatableSelect.tsx +152 -71
- package/src/components/form/CreatableSelect/CreatableSelect.types.ts +13 -0
- package/src/components/form/HeaderButton/HeaderButton.tsx +80 -0
- package/src/components/form/HeaderButton/index.ts +2 -0
- package/src/components/form/Input/Input.stories.tsx +5 -1
- package/src/components/form/Input/Input.styles.ts +176 -0
- package/src/components/form/Input/Input.test.stories.tsx +30 -23
- package/src/components/form/Input/Input.tsx +71 -211
- package/src/components/form/Input/Input.types.ts +11 -0
- package/src/components/form/InputOTP/InputOTP.test.stories.tsx +9 -17
- package/src/components/form/Menubar/Menubar.test.stories.tsx +4 -8
- package/src/components/form/PasswordStrength/PasswordStrength.helpers.tsx +117 -0
- package/src/components/form/PasswordStrength/PasswordStrength.test.stories.tsx +3 -3
- package/src/components/form/PasswordStrength/PasswordStrength.tsx +202 -255
- package/src/components/form/PhoneInput/PhoneInput.hooks.ts +134 -0
- package/src/components/form/PhoneInput/PhoneInput.test.stories.tsx +4 -4
- package/src/components/form/PhoneInput/PhoneInput.tsx +279 -292
- package/src/components/form/PhoneInput/countries.ts +54 -0
- package/src/components/form/PhoneInput/phone.ts +47 -0
- package/src/components/form/RadioGroup/RadioGroup.test.stories.tsx +9 -9
- package/src/components/form/RichTextEditor/RichTextEditor.dom.ts +124 -0
- package/src/components/form/RichTextEditor/RichTextEditor.format.ts +61 -0
- package/src/components/form/RichTextEditor/RichTextEditor.hooks.ts +142 -0
- package/src/components/form/RichTextEditor/RichTextEditor.test.stories.tsx +5 -12
- package/src/components/form/RichTextEditor/RichTextEditor.tsx +98 -410
- package/src/components/form/RichTextEditor/RichTextEditorToolbar.tsx +187 -0
- package/src/components/form/SearchPalette/SearchPalette.parts.tsx +22 -0
- package/src/components/form/SearchPalette/SearchPalette.tsx +13 -9
- package/src/components/form/Select/Select.test.stories.tsx +35 -27
- package/src/components/form/Slider/Slider.test.stories.tsx +9 -11
- package/src/components/form/Switch/Switch.md +2 -1
- package/src/components/form/Switch/Switch.test.stories.tsx +6 -6
- package/src/components/form/Textarea/Textarea.styles.ts +143 -0
- package/src/components/form/Textarea/Textarea.test.stories.tsx +20 -26
- package/src/components/form/Textarea/Textarea.tsx +114 -535
- package/src/components/form/Textarea/TextareaRichEditor.tsx +377 -0
- package/src/components/form/Toggle/Toggle.styles.ts +211 -0
- package/src/components/form/Toggle/Toggle.test.stories.tsx +19 -27
- package/src/components/form/Toggle/Toggle.tsx +10 -185
- package/src/components/form/UploadButton/UploadButton.hooks.ts +323 -0
- package/src/components/form/UploadButton/UploadButton.parts.tsx +210 -0
- package/src/components/form/UploadButton/UploadButton.stories.tsx +2 -1
- package/src/components/form/UploadButton/UploadButton.test.stories.tsx +123 -4
- package/src/components/form/UploadButton/UploadButton.tsx +76 -305
- package/src/components/form/UploadButton/UploadButton.types.ts +16 -0
- package/src/components/form/index.ts +1 -0
- package/src/components/form/total-form/Fields/CepField.tsx +143 -0
- package/src/components/form/total-form/Fields/ToggleField.tsx +61 -0
- package/src/components/form/total-form/Fields/index.ts +4 -0
- package/src/components/form/total-form/FormContainer.tsx +3 -3
- package/src/components/form/total-form/SubmitButton.tsx +25 -2
- package/src/components/form/total-form/total-form.test.tsx +118 -1
- package/src/components/layout/Accordion/Accordion.md +1 -1
- package/src/components/layout/Accordion/Accordion.stories.tsx +5 -1
- package/src/components/layout/Accordion/Accordion.styles.ts +80 -0
- package/src/components/layout/Accordion/Accordion.test.stories.tsx +32 -50
- package/src/components/layout/Accordion/Accordion.tsx +2 -75
- package/src/components/layout/Card/Card.helpers.ts +30 -0
- package/src/components/layout/Card/Card.stories.tsx +9 -11
- package/src/components/layout/Card/Card.styles.ts +182 -0
- package/src/components/layout/Card/Card.test.stories.tsx +46 -46
- package/src/components/layout/Card/Card.tsx +24 -241
- package/src/components/layout/CardGrid/CardGrid.md +96 -0
- package/src/components/layout/CardGrid/CardGrid.tsx +140 -0
- package/src/components/layout/CardGrid/__tests__/CardGrid.test.tsx +92 -0
- package/src/components/layout/CardGrid/index.ts +2 -0
- package/src/components/layout/Collapsible/Collapsible.helpers.ts +83 -0
- package/src/components/layout/Collapsible/Collapsible.test.stories.tsx +7 -3
- package/src/components/layout/Collapsible/Collapsible.tsx +111 -107
- package/src/components/layout/Container/Container.test.stories.tsx +11 -16
- package/src/components/layout/ContentToolbar/ColumnsMenu.tsx +1 -1
- package/src/components/layout/ContentToolbar/ContentToolbar.tsx +120 -44
- package/src/components/layout/ContentToolbar/ContentToolbar.types.ts +9 -0
- package/src/components/layout/ContentToolbar/FilterTrigger.tsx +1 -1
- package/src/components/layout/ContentToolbar/MultiSelectDropdown.tsx +58 -43
- package/src/components/layout/ContentToolbar/MultiSelectTriggers.tsx +139 -0
- package/src/components/layout/ContentToolbar/SavedViewsMenu.tsx +10 -3
- package/src/components/layout/ContentToolbar/SortByDropdown.tsx +35 -11
- package/src/components/layout/ContentToolbar/ViewSelector.tsx +5 -6
- package/src/components/layout/ContentToolbar/__tests__/MultiSelectDropdown.test.tsx +21 -0
- package/src/components/layout/Dashboard/Dashboard.test.stories.tsx +27 -1
- package/src/components/layout/Dashboard/Dashboard.tsx +27 -8
- package/src/components/layout/Dashboard/DashboardParts.tsx +12 -19
- package/src/components/layout/Dashboard/index.ts +2 -1
- package/src/components/layout/Drawer/Drawer.stories.tsx +8 -10
- package/src/components/layout/Drawer/Drawer.test.stories.tsx +18 -14
- package/src/components/layout/Drawer/Drawer.tsx +67 -53
- package/src/components/layout/Resizable/Resizable.helpers.ts +133 -0
- package/src/components/layout/Resizable/Resizable.hooks.ts +68 -0
- package/src/components/layout/Resizable/Resizable.tsx +38 -153
- package/src/components/layout/ScrollArea/ScrollArea.helpers.ts +51 -0
- package/src/components/layout/ScrollArea/ScrollArea.styles.ts +248 -0
- package/src/components/layout/ScrollArea/ScrollArea.tsx +183 -374
- package/src/components/layout/ScrollArea/ScrollAreaContent.tsx +70 -0
- package/src/components/layout/ScrollArea/ScrollViewport.tsx +90 -0
- package/src/components/layout/Separator/Separator.styles.ts +128 -0
- package/src/components/layout/Separator/Separator.test.stories.tsx +3 -12
- package/src/components/layout/Separator/Separator.tsx +6 -132
- package/src/components/layout/SettingsLayout/SettingsLayout.parts.tsx +2 -1
- package/src/components/layout/SettingsLayout/SettingsLayout.stories.tsx +6 -8
- package/src/components/layout/Sidebar/Sidebar.stories.tsx +10 -12
- package/src/components/layout/Sidebar/Sidebar.test.stories.tsx +35 -37
- package/src/components/layout/Skeleton/Skeleton.helpers.ts +33 -0
- package/src/components/layout/Skeleton/Skeleton.styles.ts +114 -0
- package/src/components/layout/Skeleton/Skeleton.test.stories.tsx +3 -3
- package/src/components/layout/Skeleton/Skeleton.tsx +67 -155
- package/src/components/layout/TableFilter/TableFilter.tsx +2 -1
- package/src/components/navigation/Breadcrumbs/BreadcrumbEntry.tsx +305 -0
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.md +2 -1
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.stories.tsx +12 -14
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.styles.tsx +212 -0
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.test.stories.tsx +62 -61
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.tsx +116 -429
- package/src/components/navigation/CommandPalette/CommandPalette.helpers.ts +82 -0
- package/src/components/navigation/CommandPalette/CommandPalette.hooks.ts +202 -0
- package/src/components/navigation/CommandPalette/CommandPalette.stories.tsx +3 -1
- package/src/components/navigation/CommandPalette/CommandPalette.test.stories.tsx +3 -5
- package/src/components/navigation/CommandPalette/CommandPalette.tsx +108 -341
- package/src/components/navigation/CommandPalette/CommandPaletteResults.tsx +182 -0
- package/src/components/navigation/CommandPalette/ShortcutChip.tsx +18 -0
- package/src/components/navigation/ContextMenu/ContextMenu.md +3 -1
- package/src/components/navigation/ContextMenu/ContextMenu.stories.tsx +4 -1
- package/src/components/navigation/ContextMenu/ContextMenu.test.stories.tsx +19 -24
- package/src/components/navigation/ContextMenu/ContextMenu.tsx +70 -54
- package/src/components/navigation/DropdownMenu/DropdownMenu.md +3 -1
- package/src/components/navigation/DropdownMenu/DropdownMenu.stories.tsx +17 -19
- package/src/components/navigation/DropdownMenu/DropdownMenu.test.stories.tsx +26 -26
- package/src/components/navigation/DropdownMenu/DropdownMenu.tsx +189 -111
- package/src/components/navigation/NavigationMenu/NavigationMegaSection.tsx +66 -0
- package/src/components/navigation/NavigationMenu/NavigationMenu.md +7 -2
- package/src/components/navigation/NavigationMenu/NavigationMenu.shell.tsx +218 -0
- package/src/components/navigation/NavigationMenu/NavigationMenu.styles.ts +223 -0
- package/src/components/navigation/NavigationMenu/NavigationMenu.tsx +119 -808
- package/src/components/navigation/NavigationMenu/NavigationMenuItem.hooks.ts +126 -0
- package/src/components/navigation/NavigationMenu/NavigationMenuItem.tsx +352 -0
- package/src/components/navigation/NavigationMenu/NavigationStandardBody.tsx +148 -0
- package/src/components/navigation/NavigationMenu/stories/NavigationMenu.stories.tsx +15 -17
- package/src/components/navigation/NavigationMenu/stories/NavigationMenu.test.stories.tsx +27 -23
- package/src/components/navigation/NavigationMenu/stories/NavigationMenuHorizontal.stories.tsx +11 -13
- package/src/components/navigation/NavigationMenu/stories/NavigationMenuVertical.stories.tsx +9 -11
- package/src/components/navigation/Pagination/Pagination.helpers.tsx +85 -0
- package/src/components/navigation/Pagination/Pagination.md +2 -1
- package/src/components/navigation/Pagination/Pagination.stories.tsx +4 -6
- package/src/components/navigation/Pagination/Pagination.styles.ts +135 -0
- package/src/components/navigation/Pagination/Pagination.tsx +178 -313
- package/src/components/navigation/Pagination/PaginationParts.tsx +81 -0
- package/src/components/navigation/Tabs/Tabs.md +3 -1
- package/src/components/navigation/Tabs/Tabs.stories.tsx +21 -23
- package/src/components/navigation/Tabs/Tabs.styles.ts +163 -0
- package/src/components/navigation/Tabs/Tabs.test.stories.tsx +37 -37
- package/src/components/navigation/Tabs/Tabs.tsx +192 -361
- package/src/components/navigation/Tabs/TabsPanel.tsx +100 -0
- package/src/components/typography/Blockquote/Blockquote.tsx +1 -1
- package/src/components/typography/Code/Code.test.stories.tsx +5 -5
- package/src/components/typography/Code/Code.tsx +74 -49
- package/src/components/typography/Heading/Heading.test.stories.tsx +8 -8
- package/src/components/typography/Paragraph/Paragraph.test.stories.tsx +5 -12
- package/src/components/typography/Text/Text.tsx +84 -77
- package/src/components/utility/AnimatedIcon/AnimatedIcon.md +4 -4
- package/src/components/utility/AnimatedIcon/AnimatedIcon.stories.tsx +19 -21
- package/src/components/utility/AnimatedIcon/AnimatedIcon.test.stories.tsx +19 -12
- package/src/components/utility/AspectRatio/AspectRatio.test.stories.tsx +9 -9
- package/src/components/utility/InfiniteScroll/InfiniteScroll.hooks.ts +118 -0
- package/src/components/utility/InfiniteScroll/InfiniteScroll.parts.tsx +54 -0
- package/src/components/utility/InfiniteScroll/InfiniteScroll.test.stories.tsx +12 -9
- package/src/components/utility/InfiniteScroll/InfiniteScroll.tsx +29 -148
- package/src/components/utility/InstallPrompt/InstallPrompt.helpers.ts +124 -0
- package/src/components/utility/InstallPrompt/InstallPrompt.md +113 -0
- package/src/components/utility/InstallPrompt/InstallPrompt.stories.tsx +118 -0
- package/src/components/utility/InstallPrompt/InstallPrompt.styles.ts +50 -0
- package/src/components/utility/InstallPrompt/InstallPrompt.test.stories.tsx +83 -0
- package/src/components/utility/InstallPrompt/InstallPrompt.tsx +192 -0
- package/src/components/utility/InstallPrompt/InstallPrompt.types.ts +78 -0
- package/src/components/utility/InstallPrompt/__tests__/InstallPrompt.ios.test.tsx +65 -0
- package/src/components/utility/InstallPrompt/__tests__/usePwaInstall.test.tsx +271 -0
- package/src/components/utility/InstallPrompt/index.ts +10 -0
- package/src/components/utility/InstallPrompt/usePwaInstall.ts +171 -0
- package/src/components/utility/Transition/Transition.helpers.ts +40 -0
- package/src/components/utility/Transition/Transition.tsx +17 -68
- package/src/components/utility/VirtualList/VirtualList.hooks.ts +319 -0
- package/src/components/utility/VirtualList/VirtualList.test.stories.tsx +49 -38
- package/src/components/utility/VirtualList/VirtualList.tsx +110 -315
- package/src/components/utility/WorkflowStep/WorkflowStep.helpers.ts +151 -0
- package/src/components/utility/WorkflowStep/WorkflowStep.parts.tsx +371 -0
- package/src/components/utility/WorkflowStep/WorkflowStep.stories.tsx +9 -11
- package/src/components/utility/WorkflowStep/WorkflowStep.test.stories.tsx +7 -7
- package/src/components/utility/WorkflowStep/WorkflowStep.tsx +51 -449
- package/src/components/utility/WorkflowStep/WorkflowStepRow.tsx +96 -0
- package/src/components/utility/index.ts +1 -0
- package/src/mui/Link.ts +2 -0
- package/src/utils/index.ts +2 -1
- 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";
|