@portnet/ui 6.0.2 → 6.0.3
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/CHANGELOG.md +652 -0
- package/dist/esm/index.js +72 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/v2/__tests__/AppMain.test.js +130 -0
- package/dist/esm/v2/__tests__/AppMain.test.js.map +1 -0
- package/dist/esm/v2/__tests__/ChartFigure.test.js +180 -0
- package/dist/esm/v2/__tests__/ChartFigure.test.js.map +1 -0
- package/dist/esm/v2/__tests__/DataGridRowActionsPropagation.test.js +150 -0
- package/dist/esm/v2/__tests__/DataGridRowActionsPropagation.test.js.map +1 -0
- package/dist/esm/v2/__tests__/DrawerTactileTargets.test.js +93 -0
- package/dist/esm/v2/__tests__/DrawerTactileTargets.test.js.map +1 -0
- package/dist/esm/v2/__tests__/FieldError.test.js +71 -38
- package/dist/esm/v2/__tests__/FieldError.test.js.map +1 -1
- package/dist/esm/v2/__tests__/FieldNaming.test.js +160 -0
- package/dist/esm/v2/__tests__/FieldNaming.test.js.map +1 -0
- package/dist/esm/v2/__tests__/FieldWidth.test.js +11 -11
- package/dist/esm/v2/__tests__/FieldWidth.test.js.map +1 -1
- package/dist/esm/v2/__tests__/FileCard.test.js +18 -17
- package/dist/esm/v2/__tests__/FileCard.test.js.map +1 -1
- package/dist/esm/v2/__tests__/FormikCheckbox.test.js +87 -179
- package/dist/esm/v2/__tests__/FormikCheckbox.test.js.map +1 -1
- package/dist/esm/v2/__tests__/FormikDateTimePicker.test.js +32 -44
- package/dist/esm/v2/__tests__/FormikDateTimePicker.test.js.map +1 -1
- package/dist/esm/v2/__tests__/FormikDisplayWidth.test.js +101 -0
- package/dist/esm/v2/__tests__/FormikDisplayWidth.test.js.map +1 -0
- package/dist/esm/v2/__tests__/FormikRadioGroup.test.js +118 -199
- package/dist/esm/v2/__tests__/FormikRadioGroup.test.js.map +1 -1
- package/dist/esm/v2/__tests__/MobileRowCard.test.js +44 -42
- package/dist/esm/v2/__tests__/MobileRowCard.test.js.map +1 -1
- package/dist/esm/v2/__tests__/PreviewDrawer.test.js +165 -0
- package/dist/esm/v2/__tests__/PreviewDrawer.test.js.map +1 -0
- package/dist/esm/v2/__tests__/ReferentielFieldContainer.test.js +156 -0
- package/dist/esm/v2/__tests__/ReferentielFieldContainer.test.js.map +1 -0
- package/dist/esm/v2/__tests__/SectionErrorBoundary.test.js +37 -52
- package/dist/esm/v2/__tests__/SectionErrorBoundary.test.js.map +1 -1
- package/dist/esm/v2/__tests__/apiError.test.js +50 -69
- package/dist/esm/v2/__tests__/apiError.test.js.map +1 -1
- package/dist/esm/v2/__tests__/banned-patterns.test.js +41 -122
- package/dist/esm/v2/__tests__/banned-patterns.test.js.map +1 -1
- package/dist/esm/v2/__tests__/chart-palette.test.js +204 -0
- package/dist/esm/v2/__tests__/chart-palette.test.js.map +1 -0
- package/dist/esm/v2/__tests__/contrast-palette.test.js +42 -74
- package/dist/esm/v2/__tests__/contrast-palette.test.js.map +1 -1
- package/dist/esm/v2/__tests__/cssVariables.test.js +44 -51
- package/dist/esm/v2/__tests__/cssVariables.test.js.map +1 -1
- package/dist/esm/v2/__tests__/fileValidation.test.js +134 -0
- package/dist/esm/v2/__tests__/fileValidation.test.js.map +1 -0
- package/dist/esm/v2/__tests__/filterCriteria.test.js +321 -0
- package/dist/esm/v2/__tests__/filterCriteria.test.js.map +1 -0
- package/dist/esm/v2/__tests__/fmtDate.test.js +68 -0
- package/dist/esm/v2/__tests__/fmtDate.test.js.map +1 -0
- package/dist/esm/v2/__tests__/gap-leakage-refonte.test.js +218 -0
- package/dist/esm/v2/__tests__/gap-leakage-refonte.test.js.map +1 -0
- package/dist/esm/v2/__tests__/labels-merge.test.js +17 -21
- package/dist/esm/v2/__tests__/labels-merge.test.js.map +1 -1
- package/dist/esm/v2/__tests__/locale-fallback.test.js +35 -40
- package/dist/esm/v2/__tests__/locale-fallback.test.js.map +1 -1
- package/dist/esm/v2/__tests__/reviveSavedCriteria.test.js +143 -0
- package/dist/esm/v2/__tests__/reviveSavedCriteria.test.js.map +1 -0
- package/dist/esm/v2/__tests__/rowActions.test.js +182 -0
- package/dist/esm/v2/__tests__/rowActions.test.js.map +1 -0
- package/dist/esm/v2/__tests__/useFocusOnRouteChange.test.js +155 -0
- package/dist/esm/v2/__tests__/useFocusOnRouteChange.test.js.map +1 -0
- package/dist/esm/v2/__tests__/useFocusTrap.test.js +266 -402
- package/dist/esm/v2/__tests__/useFocusTrap.test.js.map +1 -1
- package/dist/esm/v2/__tests__/usePrefersReducedMotion.test.js +120 -0
- package/dist/esm/v2/__tests__/usePrefersReducedMotion.test.js.map +1 -0
- package/dist/esm/v2/components/Accordion.js +48 -70
- package/dist/esm/v2/components/Accordion.js.map +1 -1
- package/dist/esm/v2/components/ActionStrip.js +31 -43
- package/dist/esm/v2/components/ActionStrip.js.map +1 -1
- package/dist/esm/v2/components/Banner.js +25 -22
- package/dist/esm/v2/components/Banner.js.map +1 -1
- package/dist/esm/v2/components/Busy.js +14 -19
- package/dist/esm/v2/components/Busy.js.map +1 -1
- package/dist/esm/v2/components/Button.js +34 -45
- package/dist/esm/v2/components/Button.js.map +1 -1
- package/dist/esm/v2/components/CategoryTag.js +44 -27
- package/dist/esm/v2/components/CategoryTag.js.map +1 -1
- package/dist/esm/v2/components/Checkbox.js +32 -38
- package/dist/esm/v2/components/Checkbox.js.map +1 -1
- package/dist/esm/v2/components/Chip.js +23 -36
- package/dist/esm/v2/components/Chip.js.map +1 -1
- package/dist/esm/v2/components/Combobox.js +112 -136
- package/dist/esm/v2/components/Combobox.js.map +1 -1
- package/dist/esm/v2/components/CommandPalette.js +113 -198
- package/dist/esm/v2/components/CommandPalette.js.map +1 -1
- package/dist/esm/v2/components/ConfirmDialog.js +36 -45
- package/dist/esm/v2/components/ConfirmDialog.js.map +1 -1
- package/dist/esm/v2/components/DatePicker.js +78 -81
- package/dist/esm/v2/components/DatePicker.js.map +1 -1
- package/dist/esm/v2/components/DateRangePicker.js +63 -74
- package/dist/esm/v2/components/DateRangePicker.js.map +1 -1
- package/dist/esm/v2/components/DateTimePicker.js +81 -86
- package/dist/esm/v2/components/DateTimePicker.js.map +1 -1
- package/dist/esm/v2/components/Drawer.js +71 -65
- package/dist/esm/v2/components/Drawer.js.map +1 -1
- package/dist/esm/v2/components/Dropzone.js +130 -177
- package/dist/esm/v2/components/Dropzone.js.map +1 -1
- package/dist/esm/v2/components/EmptyState.js +9 -9
- package/dist/esm/v2/components/EmptyState.js.map +1 -1
- package/dist/esm/v2/components/FavoriteToggle.js +24 -33
- package/dist/esm/v2/components/FavoriteToggle.js.map +1 -1
- package/dist/esm/v2/components/Field.js +155 -59
- package/dist/esm/v2/components/Field.js.map +1 -1
- package/dist/esm/v2/components/FieldError.js +9 -13
- package/dist/esm/v2/components/FieldError.js.map +1 -1
- package/dist/esm/v2/components/FieldHelp.js +28 -49
- package/dist/esm/v2/components/FieldHelp.js.map +1 -1
- package/dist/esm/v2/components/FileCard.js +14 -19
- package/dist/esm/v2/components/FileCard.js.map +1 -1
- package/dist/esm/v2/components/FilterTab.js +22 -31
- package/dist/esm/v2/components/FilterTab.js.map +1 -1
- package/dist/esm/v2/components/ForbiddenPage.js +28 -8
- package/dist/esm/v2/components/ForbiddenPage.js.map +1 -1
- package/dist/esm/v2/components/FormGrid.js +48 -54
- package/dist/esm/v2/components/FormGrid.js.map +1 -1
- package/dist/esm/v2/components/FormikDisplay.js +98 -24
- package/dist/esm/v2/components/FormikDisplay.js.map +1 -1
- package/dist/esm/v2/components/Input.js +75 -34
- package/dist/esm/v2/components/Input.js.map +1 -1
- package/dist/esm/v2/components/KPICard.js +42 -51
- package/dist/esm/v2/components/KPICard.js.map +1 -1
- package/dist/esm/v2/components/KPIStrip.js +9 -15
- package/dist/esm/v2/components/KPIStrip.js.map +1 -1
- package/dist/esm/v2/components/KV.js +16 -23
- package/dist/esm/v2/components/KV.js.map +1 -1
- package/dist/esm/v2/components/KVGrid.js +15 -23
- package/dist/esm/v2/components/KVGrid.js.map +1 -1
- package/dist/esm/v2/components/Layout.js +81 -117
- package/dist/esm/v2/components/Layout.js.map +1 -1
- package/dist/esm/v2/components/MobileRowCard.js +64 -75
- package/dist/esm/v2/components/MobileRowCard.js.map +1 -1
- package/dist/esm/v2/components/Modal.js +44 -53
- package/dist/esm/v2/components/Modal.js.map +1 -1
- package/dist/esm/v2/components/NetworkErrorPage.js +28 -11
- package/dist/esm/v2/components/NetworkErrorPage.js.map +1 -1
- package/dist/esm/v2/components/NotFoundPage.js +28 -9
- package/dist/esm/v2/components/NotFoundPage.js.map +1 -1
- package/dist/esm/v2/components/NumberInput.js +77 -107
- package/dist/esm/v2/components/NumberInput.js.map +1 -1
- package/dist/esm/v2/components/OverflowMenu.js +24 -42
- package/dist/esm/v2/components/OverflowMenu.js.map +1 -1
- package/dist/esm/v2/components/PdfViewer.js +24 -33
- package/dist/esm/v2/components/PdfViewer.js.map +1 -1
- package/dist/esm/v2/components/ProgressBar.js +28 -36
- package/dist/esm/v2/components/ProgressBar.js.map +1 -1
- package/dist/esm/v2/components/Radio.js +49 -57
- package/dist/esm/v2/components/Radio.js.map +1 -1
- package/dist/esm/v2/components/SectionErrorBoundary.js +84 -130
- package/dist/esm/v2/components/SectionErrorBoundary.js.map +1 -1
- package/dist/esm/v2/components/SectionHeader.js +24 -31
- package/dist/esm/v2/components/SectionHeader.js.map +1 -1
- package/dist/esm/v2/components/Segmented.js +59 -84
- package/dist/esm/v2/components/Segmented.js.map +1 -1
- package/dist/esm/v2/components/Select.js +100 -138
- package/dist/esm/v2/components/Select.js.map +1 -1
- package/dist/esm/v2/components/ServerErrorPage.js +27 -10
- package/dist/esm/v2/components/ServerErrorPage.js.map +1 -1
- package/dist/esm/v2/components/Skeleton.js +81 -96
- package/dist/esm/v2/components/Skeleton.js.map +1 -1
- package/dist/esm/v2/components/SkipLink.js +6 -7
- package/dist/esm/v2/components/SkipLink.js.map +1 -1
- package/dist/esm/v2/components/Spinner.js +13 -22
- package/dist/esm/v2/components/Spinner.js.map +1 -1
- package/dist/esm/v2/components/Status.js +14 -25
- package/dist/esm/v2/components/Status.js.map +1 -1
- package/dist/esm/v2/components/Stepper.js +68 -71
- package/dist/esm/v2/components/Stepper.js.map +1 -1
- package/dist/esm/v2/components/Surface.js +25 -44
- package/dist/esm/v2/components/Surface.js.map +1 -1
- package/dist/esm/v2/components/Switch.js +21 -29
- package/dist/esm/v2/components/Switch.js.map +1 -1
- package/dist/esm/v2/components/TabPanel.js +84 -0
- package/dist/esm/v2/components/TabPanel.js.map +1 -0
- package/dist/esm/v2/components/Tabs.js +43 -19
- package/dist/esm/v2/components/Tabs.js.map +1 -1
- package/dist/esm/v2/components/TelInput.js +75 -108
- package/dist/esm/v2/components/TelInput.js.map +1 -1
- package/dist/esm/v2/components/Textarea.js +21 -30
- package/dist/esm/v2/components/Textarea.js.map +1 -1
- package/dist/esm/v2/components/TimePicker.js +59 -69
- package/dist/esm/v2/components/TimePicker.js.map +1 -1
- package/dist/esm/v2/components/Toast.js +109 -163
- package/dist/esm/v2/components/Toast.js.map +1 -1
- package/dist/esm/v2/components/Tooltip.js +18 -31
- package/dist/esm/v2/components/Tooltip.js.map +1 -1
- package/dist/esm/v2/components/_ErrorPageBody.js +6 -5
- package/dist/esm/v2/components/_ErrorPageBody.js.map +1 -1
- package/dist/esm/v2/components/_pickerShared.js +2 -2
- package/dist/esm/v2/components/_pickerShared.js.map +1 -1
- package/dist/esm/v2/components/index.js +37 -0
- package/dist/esm/v2/components/index.js.map +1 -1
- package/dist/esm/v2/hooks/index.js +62 -0
- package/dist/esm/v2/hooks/index.js.map +1 -1
- package/dist/esm/v2/hooks/useAppliedFilters.js +112 -0
- package/dist/esm/v2/hooks/useAppliedFilters.js.map +1 -0
- package/dist/esm/v2/hooks/useDebouncedCallback.js +82 -0
- package/dist/esm/v2/hooks/useDebouncedCallback.js.map +1 -0
- package/dist/esm/v2/hooks/useDelayedFlag.js +5 -19
- package/dist/esm/v2/hooks/useDelayedFlag.js.map +1 -1
- package/dist/esm/v2/hooks/useDensity.js +13 -17
- package/dist/esm/v2/hooks/useDensity.js.map +1 -1
- package/dist/esm/v2/hooks/useFocusFirstError.js +25 -33
- package/dist/esm/v2/hooks/useFocusFirstError.js.map +1 -1
- package/dist/esm/v2/hooks/useFocusOnRouteChange.js +81 -0
- package/dist/esm/v2/hooks/useFocusOnRouteChange.js.map +1 -0
- package/dist/esm/v2/hooks/useFocusTrap.js +19 -23
- package/dist/esm/v2/hooks/useFocusTrap.js.map +1 -1
- package/dist/esm/v2/hooks/useFormAutoSave.js +38 -53
- package/dist/esm/v2/hooks/useFormAutoSave.js.map +1 -1
- package/dist/esm/v2/hooks/useFormCompletionProgress.js +32 -51
- package/dist/esm/v2/hooks/useFormCompletionProgress.js.map +1 -1
- package/dist/esm/v2/hooks/useKeyboardShortcuts.js +125 -0
- package/dist/esm/v2/hooks/useKeyboardShortcuts.js.map +1 -0
- package/dist/esm/v2/hooks/usePrefersReducedMotion.js +99 -0
- package/dist/esm/v2/hooks/usePrefersReducedMotion.js.map +1 -0
- package/dist/esm/v2/hooks/useResolvedDensity.js +2 -10
- package/dist/esm/v2/hooks/useResolvedDensity.js.map +1 -1
- package/dist/esm/v2/hooks/useSortedRows.js +3 -5
- package/dist/esm/v2/hooks/useSortedRows.js.map +1 -1
- package/dist/esm/v2/hooks/useTabLoading.js +6 -21
- package/dist/esm/v2/hooks/useTabLoading.js.map +1 -1
- package/dist/esm/v2/index.js +2 -3
- package/dist/esm/v2/index.js.map +1 -1
- package/dist/esm/v2/modalContext.js +2 -2
- package/dist/esm/v2/modalContext.js.map +1 -1
- package/dist/esm/v2/models/favorite.js.map +1 -1
- package/dist/esm/v2/models/personalization.js.map +1 -1
- package/dist/esm/v2/models/referentiel.js.map +1 -1
- package/dist/esm/v2/models/savedFilter.js.map +1 -1
- package/dist/esm/v2/patterns/ActionBar.js +115 -159
- package/dist/esm/v2/patterns/ActionBar.js.map +1 -1
- package/dist/esm/v2/patterns/AppMain.js +108 -0
- package/dist/esm/v2/patterns/AppMain.js.map +1 -0
- package/dist/esm/v2/patterns/BulkActionBar.js +31 -34
- package/dist/esm/v2/patterns/BulkActionBar.js.map +1 -1
- package/dist/esm/v2/patterns/ChartFigure.js +151 -0
- package/dist/esm/v2/patterns/ChartFigure.js.map +1 -0
- package/dist/esm/v2/patterns/CollapsibleDataGrid.js +111 -152
- package/dist/esm/v2/patterns/CollapsibleDataGrid.js.map +1 -1
- package/dist/esm/v2/patterns/ColumnsToggle.js +43 -77
- package/dist/esm/v2/patterns/ColumnsToggle.js.map +1 -1
- package/dist/esm/v2/patterns/DataGrid.js +221 -255
- package/dist/esm/v2/patterns/DataGrid.js.map +1 -1
- package/dist/esm/v2/patterns/DataGridSettingsMenu.js +76 -94
- package/dist/esm/v2/patterns/DataGridSettingsMenu.js.map +1 -1
- package/dist/esm/v2/patterns/DataGridToolbar.js +85 -89
- package/dist/esm/v2/patterns/DataGridToolbar.js.map +1 -1
- package/dist/esm/v2/patterns/DataGridVirtualized.js +141 -182
- package/dist/esm/v2/patterns/DataGridVirtualized.js.map +1 -1
- package/dist/esm/v2/patterns/DeleteResourceConfirmDialog.js +26 -30
- package/dist/esm/v2/patterns/DeleteResourceConfirmDialog.js.map +1 -1
- package/dist/esm/v2/patterns/DetailSplit.js +108 -0
- package/dist/esm/v2/patterns/DetailSplit.js.map +1 -0
- package/dist/esm/v2/patterns/FavoriteColumn.js +15 -17
- package/dist/esm/v2/patterns/FavoriteColumn.js.map +1 -1
- package/dist/esm/v2/patterns/FavoritesFilter.js +30 -39
- package/dist/esm/v2/patterns/FavoritesFilter.js.map +1 -1
- package/dist/esm/v2/patterns/FilterTabBar.js +112 -0
- package/dist/esm/v2/patterns/FilterTabBar.js.map +1 -0
- package/dist/esm/v2/patterns/FormErrorSummary.js +12 -13
- package/dist/esm/v2/patterns/FormErrorSummary.js.map +1 -1
- package/dist/esm/v2/patterns/FormPageShell.js +43 -41
- package/dist/esm/v2/patterns/FormPageShell.js.map +1 -1
- package/dist/esm/v2/patterns/FormSection.js +30 -38
- package/dist/esm/v2/patterns/FormSection.js.map +1 -1
- package/dist/esm/v2/patterns/FormikCheckbox.js +29 -39
- package/dist/esm/v2/patterns/FormikCheckbox.js.map +1 -1
- package/dist/esm/v2/patterns/FormikCheckboxGroup.js +56 -60
- package/dist/esm/v2/patterns/FormikCheckboxGroup.js.map +1 -1
- package/dist/esm/v2/patterns/FormikCombobox.js +51 -69
- package/dist/esm/v2/patterns/FormikCombobox.js.map +1 -1
- package/dist/esm/v2/patterns/FormikDatePicker.js +44 -58
- package/dist/esm/v2/patterns/FormikDatePicker.js.map +1 -1
- package/dist/esm/v2/patterns/FormikDateTimePicker.js +44 -58
- package/dist/esm/v2/patterns/FormikDateTimePicker.js.map +1 -1
- package/dist/esm/v2/patterns/FormikErrorFocus.js +22 -23
- package/dist/esm/v2/patterns/FormikErrorFocus.js.map +1 -1
- package/dist/esm/v2/patterns/FormikErrorSummary.js +89 -0
- package/dist/esm/v2/patterns/FormikErrorSummary.js.map +1 -0
- package/dist/esm/v2/patterns/FormikFile.js +94 -78
- package/dist/esm/v2/patterns/FormikFile.js.map +1 -1
- package/dist/esm/v2/patterns/FormikInput.js +40 -53
- package/dist/esm/v2/patterns/FormikInput.js.map +1 -1
- package/dist/esm/v2/patterns/FormikRadioGroup.js +39 -51
- package/dist/esm/v2/patterns/FormikRadioGroup.js.map +1 -1
- package/dist/esm/v2/patterns/FormikReferentielField.js +49 -59
- package/dist/esm/v2/patterns/FormikReferentielField.js.map +1 -1
- package/dist/esm/v2/patterns/FormikSelect.js +64 -87
- package/dist/esm/v2/patterns/FormikSelect.js.map +1 -1
- package/dist/esm/v2/patterns/FormikTextarea.js +30 -46
- package/dist/esm/v2/patterns/FormikTextarea.js.map +1 -1
- package/dist/esm/v2/patterns/KeyboardShortcutsHelp.js +53 -71
- package/dist/esm/v2/patterns/KeyboardShortcutsHelp.js.map +1 -1
- package/dist/esm/v2/patterns/NetworkErrorBanner.js +6 -7
- package/dist/esm/v2/patterns/NetworkErrorBanner.js.map +1 -1
- package/dist/esm/v2/patterns/PageContent.js +10 -14
- package/dist/esm/v2/patterns/PageContent.js.map +1 -1
- package/dist/esm/v2/patterns/PreviewDrawer.js +153 -0
- package/dist/esm/v2/patterns/PreviewDrawer.js.map +1 -0
- package/dist/esm/v2/patterns/ReferentielField.js +327 -312
- package/dist/esm/v2/patterns/ReferentielField.js.map +1 -1
- package/dist/esm/v2/patterns/RowFavoriteToggle.js +27 -22
- package/dist/esm/v2/patterns/RowFavoriteToggle.js.map +1 -1
- package/dist/esm/v2/patterns/SaveFilterDialog.js +38 -66
- package/dist/esm/v2/patterns/SaveFilterDialog.js.map +1 -1
- package/dist/esm/v2/patterns/SavedFiltersMenu.js +62 -81
- package/dist/esm/v2/patterns/SavedFiltersMenu.js.map +1 -1
- package/dist/esm/v2/patterns/SkeletonPageShell.js +106 -129
- package/dist/esm/v2/patterns/SkeletonPageShell.js.map +1 -1
- package/dist/esm/v2/patterns/SortableHeader.js +22 -45
- package/dist/esm/v2/patterns/SortableHeader.js.map +1 -1
- package/dist/esm/v2/patterns/Tour.js +94 -120
- package/dist/esm/v2/patterns/Tour.js.map +1 -1
- package/dist/esm/v2/patterns/_dataGridShared.js +107 -128
- package/dist/esm/v2/patterns/_dataGridShared.js.map +1 -1
- package/dist/esm/v2/patterns/_pickerSerialisation.js +6 -8
- package/dist/esm/v2/patterns/_pickerSerialisation.js.map +1 -1
- package/dist/esm/v2/patterns/_sort.js +17 -33
- package/dist/esm/v2/patterns/_sort.js.map +1 -1
- package/dist/esm/v2/patterns/_useColumnReorder.js +122 -160
- package/dist/esm/v2/patterns/_useColumnReorder.js.map +1 -1
- package/dist/esm/v2/patterns/_useColumnResize.js +78 -96
- package/dist/esm/v2/patterns/_useColumnResize.js.map +1 -1
- package/dist/esm/v2/patterns/filterCriteria.js +102 -0
- package/dist/esm/v2/patterns/filterCriteria.js.map +1 -0
- package/dist/esm/v2/patterns/index.js +152 -0
- package/dist/esm/v2/patterns/index.js.map +1 -1
- package/dist/esm/v2/patterns/rowActions.js +223 -0
- package/dist/esm/v2/patterns/rowActions.js.map +1 -0
- package/dist/esm/v2/personalization/PersonalizationProvider.js +50 -47
- package/dist/esm/v2/personalization/PersonalizationProvider.js.map +1 -1
- package/dist/esm/v2/personalization/adapters/_storageKey.js +5 -5
- package/dist/esm/v2/personalization/adapters/_storageKey.js.map +1 -1
- package/dist/esm/v2/personalization/adapters/createLocalStorageAdapter.js +22 -23
- package/dist/esm/v2/personalization/adapters/createLocalStorageAdapter.js.map +1 -1
- package/dist/esm/v2/personalization/adapters/createMemoryAdapter.js +13 -13
- package/dist/esm/v2/personalization/adapters/createMemoryAdapter.js.map +1 -1
- package/dist/esm/v2/personalization/capabilities/favorites.js +36 -60
- package/dist/esm/v2/personalization/capabilities/favorites.js.map +1 -1
- package/dist/esm/v2/personalization/capabilities/favoritesView.js +22 -34
- package/dist/esm/v2/personalization/capabilities/favoritesView.js.map +1 -1
- package/dist/esm/v2/personalization/capabilities/gridPreferences.js +28 -34
- package/dist/esm/v2/personalization/capabilities/gridPreferences.js.map +1 -1
- package/dist/esm/v2/personalization/capabilities/reviveSavedCriteria.js +119 -0
- package/dist/esm/v2/personalization/capabilities/reviveSavedCriteria.js.map +1 -0
- package/dist/esm/v2/personalization/capabilities/savedFilters.js +90 -98
- package/dist/esm/v2/personalization/capabilities/savedFilters.js.map +1 -1
- package/dist/esm/v2/personalization/createPersonalizationStore.js +78 -181
- package/dist/esm/v2/personalization/createPersonalizationStore.js.map +1 -1
- package/dist/esm/v2/personalization/index.js +17 -0
- package/dist/esm/v2/personalization/index.js.map +1 -1
- package/dist/esm/v2/personalization/personalizationContext.js +9 -9
- package/dist/esm/v2/personalization/personalizationContext.js.map +1 -1
- package/dist/esm/v2/personalization/schema.js +8 -9
- package/dist/esm/v2/personalization/schema.js.map +1 -1
- package/dist/esm/v2/referentiel/ReferentielProvider.js +27 -42
- package/dist/esm/v2/referentiel/ReferentielProvider.js.map +1 -1
- package/dist/esm/v2/referentiel/types.js +2 -0
- package/dist/esm/v2/referentiel/types.js.map +1 -0
- package/dist/esm/v2/referentiel/useReferentielClient.js +10 -11
- package/dist/esm/v2/referentiel/useReferentielClient.js.map +1 -1
- package/dist/esm/v2/referentiel/useReferentielOptions.js +60 -117
- package/dist/esm/v2/referentiel/useReferentielOptions.js.map +1 -1
- package/dist/esm/v2/referentiel/useReferentielSearch.js +37 -91
- package/dist/esm/v2/referentiel/useReferentielSearch.js.map +1 -1
- package/dist/esm/v2/theme/_brand.js +8 -24
- package/dist/esm/v2/theme/_brand.js.map +1 -1
- package/dist/esm/v2/theme/_brandSecondary.js +8 -24
- package/dist/esm/v2/theme/_brandSecondary.js.map +1 -1
- package/dist/esm/v2/theme/createPortnetTheme.js +51 -61
- package/dist/esm/v2/theme/createPortnetTheme.js.map +1 -1
- package/dist/esm/v2/theme/cssVariables.js +62 -69
- package/dist/esm/v2/theme/cssVariables.js.map +1 -1
- package/dist/esm/v2/theme/index.js +5 -5
- package/dist/esm/v2/theme/index.js.map +1 -1
- package/dist/esm/v2/tokens/breakpoints.js +14 -14
- package/dist/esm/v2/tokens/breakpoints.js.map +1 -1
- package/dist/esm/v2/tokens/chart.js +261 -0
- package/dist/esm/v2/tokens/chart.js.map +1 -0
- package/dist/esm/v2/tokens/colors.js +22 -22
- package/dist/esm/v2/tokens/colors.js.map +1 -1
- package/dist/esm/v2/tokens/density.js +62 -7
- package/dist/esm/v2/tokens/density.js.map +1 -1
- package/dist/esm/v2/tokens/index.js +49 -34
- package/dist/esm/v2/tokens/index.js.map +1 -1
- package/dist/esm/v2/tokens/motion.js +12 -20
- package/dist/esm/v2/tokens/motion.js.map +1 -1
- package/dist/esm/v2/tokens/radius.js +1 -1
- package/dist/esm/v2/tokens/radius.js.map +1 -1
- package/dist/esm/v2/tokens/shadows.js +6 -6
- package/dist/esm/v2/tokens/shadows.js.map +1 -1
- package/dist/esm/v2/tokens/spacing.js +2 -2
- package/dist/esm/v2/tokens/spacing.js.map +1 -1
- package/dist/esm/v2/tokens/state.js +1 -1
- package/dist/esm/v2/tokens/state.js.map +1 -1
- package/dist/esm/v2/tokens/statusPalette.js +17 -21
- package/dist/esm/v2/tokens/statusPalette.js.map +1 -1
- package/dist/esm/v2/tokens/tokens.json +6 -1
- package/dist/esm/v2/tokens/typography.js +13 -13
- package/dist/esm/v2/tokens/typography.js.map +1 -1
- package/dist/esm/v2/tokens/zIndex.js +1 -1
- package/dist/esm/v2/tokens/zIndex.js.map +1 -1
- package/dist/esm/v2/types/datagrid.js.map +1 -1
- package/dist/esm/v2/utils/apiError.js +16 -37
- package/dist/esm/v2/utils/apiError.js.map +1 -1
- package/dist/esm/v2/utils/contrast.js +31 -32
- package/dist/esm/v2/utils/contrast.js.map +1 -1
- package/dist/esm/v2/utils/cx.js +5 -25
- package/dist/esm/v2/utils/cx.js.map +1 -1
- package/dist/esm/v2/utils/fileDownload.js +23 -26
- package/dist/esm/v2/utils/fileDownload.js.map +1 -1
- package/dist/esm/v2/utils/fileValidation.js +209 -0
- package/dist/esm/v2/utils/fileValidation.js.map +1 -0
- package/dist/esm/v2/utils/fmtDate.js +111 -0
- package/dist/esm/v2/utils/fmtDate.js.map +1 -0
- package/dist/esm/v2/utils/fmtMoney.js +8 -10
- package/dist/esm/v2/utils/fmtMoney.js.map +1 -1
- package/dist/esm/v2/utils/formikErrors.js +78 -0
- package/dist/esm/v2/utils/formikErrors.js.map +1 -0
- package/dist/esm/v2/utils/index.js +35 -2
- package/dist/esm/v2/utils/index.js.map +1 -1
- package/dist/esm/v2/utils/mergeLabels.js +7 -12
- package/dist/esm/v2/utils/mergeLabels.js.map +1 -1
- package/dist/esm/v2/utils/networkStatus.js +12 -12
- package/dist/esm/v2/utils/networkStatus.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +110 -49
- package/dist/index.js.map +1 -1
- package/dist/v2/__tests__/AppMain.test.js +133 -0
- package/dist/v2/__tests__/AppMain.test.js.map +1 -0
- package/dist/v2/__tests__/ChartFigure.test.js +183 -0
- package/dist/v2/__tests__/ChartFigure.test.js.map +1 -0
- package/dist/v2/__tests__/DataGridRowActionsPropagation.test.js +153 -0
- package/dist/v2/__tests__/DataGridRowActionsPropagation.test.js.map +1 -0
- package/dist/v2/__tests__/DrawerTactileTargets.test.js +94 -0
- package/dist/v2/__tests__/DrawerTactileTargets.test.js.map +1 -0
- package/dist/v2/__tests__/FieldError.test.js +82 -49
- package/dist/v2/__tests__/FieldError.test.js.map +1 -1
- package/dist/v2/__tests__/FieldNaming.test.js +161 -0
- package/dist/v2/__tests__/FieldNaming.test.js.map +1 -0
- package/dist/v2/__tests__/FieldWidth.test.js +23 -25
- package/dist/v2/__tests__/FieldWidth.test.js.map +1 -1
- package/dist/v2/__tests__/FileCard.test.js +29 -28
- package/dist/v2/__tests__/FileCard.test.js.map +1 -1
- package/dist/v2/__tests__/FormikCheckbox.test.js +90 -183
- package/dist/v2/__tests__/FormikCheckbox.test.js.map +1 -1
- package/dist/v2/__tests__/FormikDateTimePicker.test.js +38 -48
- package/dist/v2/__tests__/FormikDateTimePicker.test.js.map +1 -1
- package/dist/v2/__tests__/FormikDisplayWidth.test.js +102 -0
- package/dist/v2/__tests__/FormikDisplayWidth.test.js.map +1 -0
- package/dist/v2/__tests__/FormikRadioGroup.test.js +123 -204
- package/dist/v2/__tests__/FormikRadioGroup.test.js.map +1 -1
- package/dist/v2/__tests__/MobileRowCard.test.js +63 -61
- package/dist/v2/__tests__/MobileRowCard.test.js.map +1 -1
- package/dist/v2/__tests__/PreviewDrawer.test.js +169 -0
- package/dist/v2/__tests__/PreviewDrawer.test.js.map +1 -0
- package/dist/v2/__tests__/ReferentielFieldContainer.test.js +159 -0
- package/dist/v2/__tests__/ReferentielFieldContainer.test.js.map +1 -0
- package/dist/v2/__tests__/SectionErrorBoundary.test.js +53 -68
- package/dist/v2/__tests__/SectionErrorBoundary.test.js.map +1 -1
- package/dist/v2/__tests__/apiError.test.js +50 -69
- package/dist/v2/__tests__/apiError.test.js.map +1 -1
- package/dist/v2/__tests__/banned-patterns.test.js +42 -123
- package/dist/v2/__tests__/banned-patterns.test.js.map +1 -1
- package/dist/v2/__tests__/chart-palette.test.js +205 -0
- package/dist/v2/__tests__/chart-palette.test.js.map +1 -0
- package/dist/v2/__tests__/contrast-palette.test.js +42 -74
- package/dist/v2/__tests__/contrast-palette.test.js.map +1 -1
- package/dist/v2/__tests__/cssVariables.test.js +44 -51
- package/dist/v2/__tests__/cssVariables.test.js.map +1 -1
- package/dist/v2/__tests__/fileValidation.test.js +136 -0
- package/dist/v2/__tests__/fileValidation.test.js.map +1 -0
- package/dist/v2/__tests__/filterCriteria.test.js +324 -0
- package/dist/v2/__tests__/filterCriteria.test.js.map +1 -0
- package/dist/v2/__tests__/fmtDate.test.js +69 -0
- package/dist/v2/__tests__/fmtDate.test.js.map +1 -0
- package/dist/v2/__tests__/gap-leakage-refonte.test.js +221 -0
- package/dist/v2/__tests__/gap-leakage-refonte.test.js.map +1 -0
- package/dist/v2/__tests__/labels-merge.test.js +23 -27
- package/dist/v2/__tests__/labels-merge.test.js.map +1 -1
- package/dist/v2/__tests__/locale-fallback.test.js +47 -52
- package/dist/v2/__tests__/locale-fallback.test.js.map +1 -1
- package/dist/v2/__tests__/reviveSavedCriteria.test.js +144 -0
- package/dist/v2/__tests__/reviveSavedCriteria.test.js.map +1 -0
- package/dist/v2/__tests__/rowActions.test.js +186 -0
- package/dist/v2/__tests__/rowActions.test.js.map +1 -0
- package/dist/v2/__tests__/useFocusOnRouteChange.test.js +156 -0
- package/dist/v2/__tests__/useFocusOnRouteChange.test.js.map +1 -0
- package/dist/v2/__tests__/useFocusTrap.test.js +270 -407
- package/dist/v2/__tests__/useFocusTrap.test.js.map +1 -1
- package/dist/v2/__tests__/usePrefersReducedMotion.test.js +123 -0
- package/dist/v2/__tests__/usePrefersReducedMotion.test.js.map +1 -0
- package/dist/v2/components/Accordion.js +60 -82
- package/dist/v2/components/Accordion.js.map +1 -1
- package/dist/v2/components/ActionStrip.js +40 -52
- package/dist/v2/components/ActionStrip.js.map +1 -1
- package/dist/v2/components/Banner.js +42 -41
- package/dist/v2/components/Banner.js.map +1 -1
- package/dist/v2/components/Busy.js +22 -27
- package/dist/v2/components/Busy.js.map +1 -1
- package/dist/v2/components/Button.js +39 -50
- package/dist/v2/components/Button.js.map +1 -1
- package/dist/v2/components/CategoryTag.d.ts.map +1 -1
- package/dist/v2/components/CategoryTag.js +49 -32
- package/dist/v2/components/CategoryTag.js.map +1 -1
- package/dist/v2/components/Checkbox.js +39 -45
- package/dist/v2/components/Checkbox.js.map +1 -1
- package/dist/v2/components/Chip.js +29 -42
- package/dist/v2/components/Chip.js.map +1 -1
- package/dist/v2/components/Combobox.js +122 -144
- package/dist/v2/components/Combobox.js.map +1 -1
- package/dist/v2/components/CommandPalette.js +138 -225
- package/dist/v2/components/CommandPalette.js.map +1 -1
- package/dist/v2/components/ConfirmDialog.js +46 -56
- package/dist/v2/components/ConfirmDialog.js.map +1 -1
- package/dist/v2/components/DatePicker.js +81 -86
- package/dist/v2/components/DatePicker.js.map +1 -1
- package/dist/v2/components/DateRangePicker.js +77 -87
- package/dist/v2/components/DateRangePicker.js.map +1 -1
- package/dist/v2/components/DateTimePicker.js +84 -91
- package/dist/v2/components/DateTimePicker.js.map +1 -1
- package/dist/v2/components/Drawer.d.ts.map +1 -1
- package/dist/v2/components/Drawer.js +93 -88
- package/dist/v2/components/Drawer.js.map +1 -1
- package/dist/v2/components/Dropzone.js +150 -196
- package/dist/v2/components/Dropzone.js.map +1 -1
- package/dist/v2/components/EmptyState.js +18 -20
- package/dist/v2/components/EmptyState.js.map +1 -1
- package/dist/v2/components/FavoriteToggle.js +28 -39
- package/dist/v2/components/FavoriteToggle.js.map +1 -1
- package/dist/v2/components/Field.d.ts +62 -4
- package/dist/v2/components/Field.d.ts.map +1 -1
- package/dist/v2/components/Field.js +169 -70
- package/dist/v2/components/Field.js.map +1 -1
- package/dist/v2/components/FieldError.js +18 -21
- package/dist/v2/components/FieldError.js.map +1 -1
- package/dist/v2/components/FieldHelp.js +40 -60
- package/dist/v2/components/FieldHelp.js.map +1 -1
- package/dist/v2/components/FileCard.js +27 -31
- package/dist/v2/components/FileCard.js.map +1 -1
- package/dist/v2/components/FilterTab.js +30 -38
- package/dist/v2/components/FilterTab.js.map +1 -1
- package/dist/v2/components/ForbiddenPage.d.ts +25 -1
- package/dist/v2/components/ForbiddenPage.d.ts.map +1 -1
- package/dist/v2/components/ForbiddenPage.js +37 -17
- package/dist/v2/components/ForbiddenPage.js.map +1 -1
- package/dist/v2/components/FormGrid.js +53 -59
- package/dist/v2/components/FormGrid.js.map +1 -1
- package/dist/v2/components/FormikDisplay.d.ts +50 -1
- package/dist/v2/components/FormikDisplay.d.ts.map +1 -1
- package/dist/v2/components/FormikDisplay.js +108 -33
- package/dist/v2/components/FormikDisplay.js.map +1 -1
- package/dist/v2/components/Input.d.ts +40 -0
- package/dist/v2/components/Input.d.ts.map +1 -1
- package/dist/v2/components/Input.js +81 -41
- package/dist/v2/components/Input.js.map +1 -1
- package/dist/v2/components/KPICard.js +57 -67
- package/dist/v2/components/KPICard.js.map +1 -1
- package/dist/v2/components/KPIStrip.js +16 -22
- package/dist/v2/components/KPIStrip.js.map +1 -1
- package/dist/v2/components/KV.js +25 -31
- package/dist/v2/components/KV.js.map +1 -1
- package/dist/v2/components/KVGrid.js +19 -26
- package/dist/v2/components/KVGrid.js.map +1 -1
- package/dist/v2/components/Layout.js +91 -120
- package/dist/v2/components/Layout.js.map +1 -1
- package/dist/v2/components/MobileRowCard.js +79 -91
- package/dist/v2/components/MobileRowCard.js.map +1 -1
- package/dist/v2/components/Modal.js +61 -69
- package/dist/v2/components/Modal.js.map +1 -1
- package/dist/v2/components/NetworkErrorPage.d.ts +19 -1
- package/dist/v2/components/NetworkErrorPage.d.ts.map +1 -1
- package/dist/v2/components/NetworkErrorPage.js +38 -21
- package/dist/v2/components/NetworkErrorPage.js.map +1 -1
- package/dist/v2/components/NotFoundPage.d.ts +17 -1
- package/dist/v2/components/NotFoundPage.d.ts.map +1 -1
- package/dist/v2/components/NotFoundPage.js +37 -18
- package/dist/v2/components/NotFoundPage.js.map +1 -1
- package/dist/v2/components/NumberInput.js +88 -118
- package/dist/v2/components/NumberInput.js.map +1 -1
- package/dist/v2/components/OverflowMenu.js +38 -56
- package/dist/v2/components/OverflowMenu.js.map +1 -1
- package/dist/v2/components/PdfViewer.js +34 -45
- package/dist/v2/components/PdfViewer.js.map +1 -1
- package/dist/v2/components/ProgressBar.js +42 -49
- package/dist/v2/components/ProgressBar.js.map +1 -1
- package/dist/v2/components/Radio.js +59 -67
- package/dist/v2/components/Radio.js.map +1 -1
- package/dist/v2/components/SectionErrorBoundary.js +90 -135
- package/dist/v2/components/SectionErrorBoundary.js.map +1 -1
- package/dist/v2/components/SectionHeader.js +34 -41
- package/dist/v2/components/SectionHeader.js.map +1 -1
- package/dist/v2/components/Segmented.js +69 -93
- package/dist/v2/components/Segmented.js.map +1 -1
- package/dist/v2/components/Select.d.ts +26 -2
- package/dist/v2/components/Select.d.ts.map +1 -1
- package/dist/v2/components/Select.js +120 -155
- package/dist/v2/components/Select.js.map +1 -1
- package/dist/v2/components/ServerErrorPage.d.ts +27 -1
- package/dist/v2/components/ServerErrorPage.d.ts.map +1 -1
- package/dist/v2/components/ServerErrorPage.js +37 -20
- package/dist/v2/components/ServerErrorPage.js.map +1 -1
- package/dist/v2/components/Skeleton.js +86 -100
- package/dist/v2/components/Skeleton.js.map +1 -1
- package/dist/v2/components/SkipLink.js +9 -12
- package/dist/v2/components/SkipLink.js.map +1 -1
- package/dist/v2/components/Spinner.js +16 -25
- package/dist/v2/components/Spinner.js.map +1 -1
- package/dist/v2/components/Status.js +18 -29
- package/dist/v2/components/Status.js.map +1 -1
- package/dist/v2/components/Stepper.js +80 -82
- package/dist/v2/components/Stepper.js.map +1 -1
- package/dist/v2/components/Surface.js +34 -49
- package/dist/v2/components/Surface.js.map +1 -1
- package/dist/v2/components/Switch.js +29 -37
- package/dist/v2/components/Switch.js.map +1 -1
- package/dist/v2/components/TabPanel.d.ts +17 -0
- package/dist/v2/components/TabPanel.d.ts.map +1 -0
- package/dist/v2/components/TabPanel.js +90 -0
- package/dist/v2/components/TabPanel.js.map +1 -0
- package/dist/v2/components/Tabs.d.ts +25 -0
- package/dist/v2/components/Tabs.d.ts.map +1 -1
- package/dist/v2/components/Tabs.js +53 -29
- package/dist/v2/components/Tabs.js.map +1 -1
- package/dist/v2/components/TelInput.js +80 -115
- package/dist/v2/components/TelInput.js.map +1 -1
- package/dist/v2/components/Textarea.js +26 -35
- package/dist/v2/components/Textarea.js.map +1 -1
- package/dist/v2/components/TimePicker.js +62 -74
- package/dist/v2/components/TimePicker.js.map +1 -1
- package/dist/v2/components/Toast.js +119 -174
- package/dist/v2/components/Toast.js.map +1 -1
- package/dist/v2/components/Tooltip.js +23 -38
- package/dist/v2/components/Tooltip.js.map +1 -1
- package/dist/v2/components/_ErrorPageBody.js +15 -16
- package/dist/v2/components/_ErrorPageBody.js.map +1 -1
- package/dist/v2/components/_pickerShared.js +5 -5
- package/dist/v2/components/_pickerShared.js.map +1 -1
- package/dist/v2/components/index.d.ts +40 -1
- package/dist/v2/components/index.d.ts.map +1 -1
- package/dist/v2/components/index.js +153 -136
- package/dist/v2/components/index.js.map +1 -1
- package/dist/v2/hooks/index.d.ts +65 -0
- package/dist/v2/hooks/index.d.ts.map +1 -1
- package/dist/v2/hooks/index.js +63 -24
- package/dist/v2/hooks/index.js.map +1 -1
- package/dist/v2/hooks/useAppliedFilters.d.ts +102 -0
- package/dist/v2/hooks/useAppliedFilters.d.ts.map +1 -0
- package/dist/v2/hooks/useAppliedFilters.js +117 -0
- package/dist/v2/hooks/useAppliedFilters.js.map +1 -0
- package/dist/v2/hooks/useDebouncedCallback.d.ts +64 -0
- package/dist/v2/hooks/useDebouncedCallback.d.ts.map +1 -0
- package/dist/v2/hooks/useDebouncedCallback.js +87 -0
- package/dist/v2/hooks/useDebouncedCallback.js.map +1 -0
- package/dist/v2/hooks/useDelayedFlag.js +6 -20
- package/dist/v2/hooks/useDelayedFlag.js.map +1 -1
- package/dist/v2/hooks/useDensity.d.ts.map +1 -1
- package/dist/v2/hooks/useDensity.js +14 -18
- package/dist/v2/hooks/useDensity.js.map +1 -1
- package/dist/v2/hooks/useFocusFirstError.js +26 -34
- package/dist/v2/hooks/useFocusFirstError.js.map +1 -1
- package/dist/v2/hooks/useFocusOnRouteChange.d.ts +65 -0
- package/dist/v2/hooks/useFocusOnRouteChange.d.ts.map +1 -0
- package/dist/v2/hooks/useFocusOnRouteChange.js +88 -0
- package/dist/v2/hooks/useFocusOnRouteChange.js.map +1 -0
- package/dist/v2/hooks/useFocusTrap.js +20 -24
- package/dist/v2/hooks/useFocusTrap.js.map +1 -1
- package/dist/v2/hooks/useFormAutoSave.d.ts +4 -4
- package/dist/v2/hooks/useFormAutoSave.d.ts.map +1 -1
- package/dist/v2/hooks/useFormAutoSave.js +39 -54
- package/dist/v2/hooks/useFormAutoSave.js.map +1 -1
- package/dist/v2/hooks/useFormCompletionProgress.d.ts +1 -1
- package/dist/v2/hooks/useFormCompletionProgress.d.ts.map +1 -1
- package/dist/v2/hooks/useFormCompletionProgress.js +33 -52
- package/dist/v2/hooks/useFormCompletionProgress.js.map +1 -1
- package/dist/v2/hooks/useKeyboardShortcuts.d.ts +25 -0
- package/dist/v2/hooks/useKeyboardShortcuts.d.ts.map +1 -0
- package/dist/v2/hooks/useKeyboardShortcuts.js +132 -0
- package/dist/v2/hooks/useKeyboardShortcuts.js.map +1 -0
- package/dist/v2/hooks/usePrefersReducedMotion.d.ts +56 -0
- package/dist/v2/hooks/usePrefersReducedMotion.d.ts.map +1 -0
- package/dist/v2/hooks/usePrefersReducedMotion.js +105 -0
- package/dist/v2/hooks/usePrefersReducedMotion.js.map +1 -0
- package/dist/v2/hooks/useResolvedDensity.js +5 -13
- package/dist/v2/hooks/useResolvedDensity.js.map +1 -1
- package/dist/v2/hooks/useSortedRows.js +4 -6
- package/dist/v2/hooks/useSortedRows.js.map +1 -1
- package/dist/v2/hooks/useTabLoading.js +7 -22
- package/dist/v2/hooks/useTabLoading.js.map +1 -1
- package/dist/v2/index.js +143 -145
- package/dist/v2/index.js.map +1 -1
- package/dist/v2/modalContext.js +2 -2
- package/dist/v2/modalContext.js.map +1 -1
- package/dist/v2/models/favorite.d.ts +8 -9
- package/dist/v2/models/favorite.d.ts.map +1 -1
- package/dist/v2/models/favorite.js.map +1 -1
- package/dist/v2/models/index.js +4 -4
- package/dist/v2/models/index.js.map +1 -1
- package/dist/v2/models/personalization.d.ts +44 -48
- package/dist/v2/models/personalization.d.ts.map +1 -1
- package/dist/v2/models/personalization.js.map +1 -1
- package/dist/v2/models/referentiel.d.ts +32 -50
- package/dist/v2/models/referentiel.d.ts.map +1 -1
- package/dist/v2/models/referentiel.js.map +1 -1
- package/dist/v2/models/savedFilter.d.ts +8 -17
- package/dist/v2/models/savedFilter.d.ts.map +1 -1
- package/dist/v2/models/savedFilter.js.map +1 -1
- package/dist/v2/patterns/ActionBar.js +152 -187
- package/dist/v2/patterns/ActionBar.js.map +1 -1
- package/dist/v2/patterns/AppMain.d.ts +109 -0
- package/dist/v2/patterns/AppMain.d.ts.map +1 -0
- package/dist/v2/patterns/AppMain.js +115 -0
- package/dist/v2/patterns/AppMain.js.map +1 -0
- package/dist/v2/patterns/BulkActionBar.js +40 -42
- package/dist/v2/patterns/BulkActionBar.js.map +1 -1
- package/dist/v2/patterns/ChartFigure.d.ts +124 -0
- package/dist/v2/patterns/ChartFigure.d.ts.map +1 -0
- package/dist/v2/patterns/ChartFigure.js +159 -0
- package/dist/v2/patterns/ChartFigure.js.map +1 -0
- package/dist/v2/patterns/CollapsibleDataGrid.js +138 -174
- package/dist/v2/patterns/CollapsibleDataGrid.js.map +1 -1
- package/dist/v2/patterns/ColumnsToggle.js +60 -94
- package/dist/v2/patterns/ColumnsToggle.js.map +1 -1
- package/dist/v2/patterns/DataGrid.d.ts.map +1 -1
- package/dist/v2/patterns/DataGrid.js +262 -297
- package/dist/v2/patterns/DataGrid.js.map +1 -1
- package/dist/v2/patterns/DataGridSettingsMenu.d.ts +12 -0
- package/dist/v2/patterns/DataGridSettingsMenu.d.ts.map +1 -1
- package/dist/v2/patterns/DataGridSettingsMenu.js +104 -121
- package/dist/v2/patterns/DataGridSettingsMenu.js.map +1 -1
- package/dist/v2/patterns/DataGridToolbar.js +103 -106
- package/dist/v2/patterns/DataGridToolbar.js.map +1 -1
- package/dist/v2/patterns/DataGridVirtualized.js +179 -217
- package/dist/v2/patterns/DataGridVirtualized.js.map +1 -1
- package/dist/v2/patterns/DeleteResourceConfirmDialog.js +32 -35
- package/dist/v2/patterns/DeleteResourceConfirmDialog.js.map +1 -1
- package/dist/v2/patterns/DetailSplit.d.ts +87 -0
- package/dist/v2/patterns/DetailSplit.d.ts.map +1 -0
- package/dist/v2/patterns/DetailSplit.js +116 -0
- package/dist/v2/patterns/DetailSplit.js.map +1 -0
- package/dist/v2/patterns/FavoriteColumn.js +22 -23
- package/dist/v2/patterns/FavoriteColumn.js.map +1 -1
- package/dist/v2/patterns/FavoritesFilter.js +36 -44
- package/dist/v2/patterns/FavoritesFilter.js.map +1 -1
- package/dist/v2/patterns/FilterTabBar.d.ts +28 -0
- package/dist/v2/patterns/FilterTabBar.d.ts.map +1 -0
- package/dist/v2/patterns/FilterTabBar.js +120 -0
- package/dist/v2/patterns/FilterTabBar.js.map +1 -0
- package/dist/v2/patterns/FormErrorSummary.js +20 -23
- package/dist/v2/patterns/FormErrorSummary.js.map +1 -1
- package/dist/v2/patterns/FormPageShell.js +53 -50
- package/dist/v2/patterns/FormPageShell.js.map +1 -1
- package/dist/v2/patterns/FormSection.d.ts +8 -3
- package/dist/v2/patterns/FormSection.d.ts.map +1 -1
- package/dist/v2/patterns/FormSection.js +44 -51
- package/dist/v2/patterns/FormSection.js.map +1 -1
- package/dist/v2/patterns/FormikCheckbox.js +36 -45
- package/dist/v2/patterns/FormikCheckbox.js.map +1 -1
- package/dist/v2/patterns/FormikCheckboxGroup.d.ts +17 -1
- package/dist/v2/patterns/FormikCheckboxGroup.d.ts.map +1 -1
- package/dist/v2/patterns/FormikCheckboxGroup.js +62 -65
- package/dist/v2/patterns/FormikCheckboxGroup.js.map +1 -1
- package/dist/v2/patterns/FormikCombobox.js +55 -72
- package/dist/v2/patterns/FormikCombobox.js.map +1 -1
- package/dist/v2/patterns/FormikDatePicker.js +50 -64
- package/dist/v2/patterns/FormikDatePicker.js.map +1 -1
- package/dist/v2/patterns/FormikDateTimePicker.js +50 -64
- package/dist/v2/patterns/FormikDateTimePicker.js.map +1 -1
- package/dist/v2/patterns/FormikErrorFocus.js +25 -26
- package/dist/v2/patterns/FormikErrorFocus.js.map +1 -1
- package/dist/v2/patterns/FormikErrorSummary.d.ts +74 -0
- package/dist/v2/patterns/FormikErrorSummary.d.ts.map +1 -0
- package/dist/v2/patterns/FormikErrorSummary.js +97 -0
- package/dist/v2/patterns/FormikErrorSummary.js.map +1 -0
- package/dist/v2/patterns/FormikFile.d.ts +14 -1
- package/dist/v2/patterns/FormikFile.d.ts.map +1 -1
- package/dist/v2/patterns/FormikFile.js +99 -83
- package/dist/v2/patterns/FormikFile.js.map +1 -1
- package/dist/v2/patterns/FormikInput.js +45 -58
- package/dist/v2/patterns/FormikInput.js.map +1 -1
- package/dist/v2/patterns/FormikRadioGroup.js +45 -56
- package/dist/v2/patterns/FormikRadioGroup.js.map +1 -1
- package/dist/v2/patterns/FormikReferentielField.d.ts +12 -1
- package/dist/v2/patterns/FormikReferentielField.d.ts.map +1 -1
- package/dist/v2/patterns/FormikReferentielField.js +54 -64
- package/dist/v2/patterns/FormikReferentielField.js.map +1 -1
- package/dist/v2/patterns/FormikSelect.js +70 -92
- package/dist/v2/patterns/FormikSelect.js.map +1 -1
- package/dist/v2/patterns/FormikTextarea.js +35 -51
- package/dist/v2/patterns/FormikTextarea.js.map +1 -1
- package/dist/v2/patterns/KeyboardShortcutsHelp.js +60 -80
- package/dist/v2/patterns/KeyboardShortcutsHelp.js.map +1 -1
- package/dist/v2/patterns/NetworkErrorBanner.js +13 -16
- package/dist/v2/patterns/NetworkErrorBanner.js.map +1 -1
- package/dist/v2/patterns/PageContent.js +17 -20
- package/dist/v2/patterns/PageContent.js.map +1 -1
- package/dist/v2/patterns/PreviewDrawer.d.ts +49 -0
- package/dist/v2/patterns/PreviewDrawer.d.ts.map +1 -0
- package/dist/v2/patterns/PreviewDrawer.js +159 -0
- package/dist/v2/patterns/PreviewDrawer.js.map +1 -0
- package/dist/v2/patterns/ReferentielField.d.ts +86 -2
- package/dist/v2/patterns/ReferentielField.d.ts.map +1 -1
- package/dist/v2/patterns/ReferentielField.js +347 -327
- package/dist/v2/patterns/ReferentielField.js.map +1 -1
- package/dist/v2/patterns/RowFavoriteToggle.d.ts +6 -0
- package/dist/v2/patterns/RowFavoriteToggle.d.ts.map +1 -1
- package/dist/v2/patterns/RowFavoriteToggle.js +38 -30
- package/dist/v2/patterns/RowFavoriteToggle.js.map +1 -1
- package/dist/v2/patterns/SaveFilterDialog.js +50 -77
- package/dist/v2/patterns/SaveFilterDialog.js.map +1 -1
- package/dist/v2/patterns/SavedFiltersMenu.js +89 -107
- package/dist/v2/patterns/SavedFiltersMenu.js.map +1 -1
- package/dist/v2/patterns/SkeletonPageShell.js +122 -143
- package/dist/v2/patterns/SkeletonPageShell.js.map +1 -1
- package/dist/v2/patterns/SortableHeader.js +35 -57
- package/dist/v2/patterns/SortableHeader.js.map +1 -1
- package/dist/v2/patterns/Tour.js +121 -142
- package/dist/v2/patterns/Tour.js.map +1 -1
- package/dist/v2/patterns/_dataGridShared.d.ts.map +1 -1
- package/dist/v2/patterns/_dataGridShared.js +131 -147
- package/dist/v2/patterns/_dataGridShared.js.map +1 -1
- package/dist/v2/patterns/_pickerSerialisation.js +9 -10
- package/dist/v2/patterns/_pickerSerialisation.js.map +1 -1
- package/dist/v2/patterns/_sort.js +17 -33
- package/dist/v2/patterns/_sort.js.map +1 -1
- package/dist/v2/patterns/_useColumnReorder.js +124 -163
- package/dist/v2/patterns/_useColumnReorder.js.map +1 -1
- package/dist/v2/patterns/_useColumnResize.js +80 -99
- package/dist/v2/patterns/_useColumnResize.js.map +1 -1
- package/dist/v2/patterns/filterCriteria.d.ts +78 -0
- package/dist/v2/patterns/filterCriteria.d.ts.map +1 -0
- package/dist/v2/patterns/filterCriteria.js +110 -0
- package/dist/v2/patterns/filterCriteria.js.map +1 -0
- package/dist/v2/patterns/index.d.ts +160 -0
- package/dist/v2/patterns/index.d.ts.map +1 -1
- package/dist/v2/patterns/index.js +157 -79
- package/dist/v2/patterns/index.js.map +1 -1
- package/dist/v2/patterns/rowActions.d.ts +150 -0
- package/dist/v2/patterns/rowActions.d.ts.map +1 -0
- package/dist/v2/patterns/rowActions.js +232 -0
- package/dist/v2/patterns/rowActions.js.map +1 -0
- package/dist/v2/personalization/PersonalizationProvider.d.ts.map +1 -1
- package/dist/v2/personalization/PersonalizationProvider.js +57 -53
- package/dist/v2/personalization/PersonalizationProvider.js.map +1 -1
- package/dist/v2/personalization/adapters/_storageKey.js +5 -5
- package/dist/v2/personalization/adapters/_storageKey.js.map +1 -1
- package/dist/v2/personalization/adapters/createLocalStorageAdapter.js +25 -24
- package/dist/v2/personalization/adapters/createLocalStorageAdapter.js.map +1 -1
- package/dist/v2/personalization/adapters/createMemoryAdapter.js +14 -14
- package/dist/v2/personalization/adapters/createMemoryAdapter.js.map +1 -1
- package/dist/v2/personalization/adapters/index.js +5 -5
- package/dist/v2/personalization/adapters/index.js.map +1 -1
- package/dist/v2/personalization/capabilities/favorites.js +39 -62
- package/dist/v2/personalization/capabilities/favorites.js.map +1 -1
- package/dist/v2/personalization/capabilities/favoritesView.js +25 -37
- package/dist/v2/personalization/capabilities/favoritesView.js.map +1 -1
- package/dist/v2/personalization/capabilities/gridPreferences.js +31 -36
- package/dist/v2/personalization/capabilities/gridPreferences.js.map +1 -1
- package/dist/v2/personalization/capabilities/index.js +12 -12
- package/dist/v2/personalization/capabilities/reviveSavedCriteria.d.ts +88 -0
- package/dist/v2/personalization/capabilities/reviveSavedCriteria.d.ts.map +1 -0
- package/dist/v2/personalization/capabilities/reviveSavedCriteria.js +126 -0
- package/dist/v2/personalization/capabilities/reviveSavedCriteria.js.map +1 -0
- package/dist/v2/personalization/capabilities/savedFilters.js +93 -100
- package/dist/v2/personalization/capabilities/savedFilters.js.map +1 -1
- package/dist/v2/personalization/createPersonalizationStore.d.ts.map +1 -1
- package/dist/v2/personalization/createPersonalizationStore.js +81 -182
- package/dist/v2/personalization/createPersonalizationStore.js.map +1 -1
- package/dist/v2/personalization/index.d.ts +16 -0
- package/dist/v2/personalization/index.d.ts.map +1 -1
- package/dist/v2/personalization/index.js +30 -23
- package/dist/v2/personalization/index.js.map +1 -1
- package/dist/v2/personalization/personalizationContext.js +10 -12
- package/dist/v2/personalization/personalizationContext.js.map +1 -1
- package/dist/v2/personalization/schema.js +8 -9
- package/dist/v2/personalization/schema.js.map +1 -1
- package/dist/v2/referentiel/ReferentielProvider.js +31 -45
- package/dist/v2/referentiel/ReferentielProvider.js.map +1 -1
- package/dist/v2/referentiel/index.js +11 -13
- package/dist/v2/referentiel/index.js.map +1 -1
- package/dist/v2/referentiel/types.d.ts +105 -0
- package/dist/v2/referentiel/types.d.ts.map +1 -0
- package/dist/v2/referentiel/types.js +6 -0
- package/dist/v2/referentiel/types.js.map +1 -0
- package/dist/v2/referentiel/useReferentielClient.js +13 -16
- package/dist/v2/referentiel/useReferentielClient.js.map +1 -1
- package/dist/v2/referentiel/useReferentielOptions.d.ts +7 -17
- package/dist/v2/referentiel/useReferentielOptions.d.ts.map +1 -1
- package/dist/v2/referentiel/useReferentielOptions.js +63 -120
- package/dist/v2/referentiel/useReferentielOptions.js.map +1 -1
- package/dist/v2/referentiel/useReferentielSearch.d.ts +7 -48
- package/dist/v2/referentiel/useReferentielSearch.d.ts.map +1 -1
- package/dist/v2/referentiel/useReferentielSearch.js +40 -95
- package/dist/v2/referentiel/useReferentielSearch.js.map +1 -1
- package/dist/v2/theme/_brand.js +12 -26
- package/dist/v2/theme/_brand.js.map +1 -1
- package/dist/v2/theme/_brandSecondary.js +12 -26
- package/dist/v2/theme/_brandSecondary.js.map +1 -1
- package/dist/v2/theme/createPortnetTheme.js +41 -49
- package/dist/v2/theme/createPortnetTheme.js.map +1 -1
- package/dist/v2/theme/cssVariables.d.ts +3 -3
- package/dist/v2/theme/cssVariables.d.ts.map +1 -1
- package/dist/v2/theme/cssVariables.js +65 -70
- package/dist/v2/theme/cssVariables.js.map +1 -1
- package/dist/v2/theme/index.js +10 -10
- package/dist/v2/theme/index.js.map +1 -1
- package/dist/v2/tokens/breakpoints.js +16 -16
- package/dist/v2/tokens/breakpoints.js.map +1 -1
- package/dist/v2/tokens/chart.d.ts +103 -0
- package/dist/v2/tokens/chart.d.ts.map +1 -0
- package/dist/v2/tokens/chart.js +270 -0
- package/dist/v2/tokens/chart.js.map +1 -0
- package/dist/v2/tokens/colors.js +24 -24
- package/dist/v2/tokens/colors.js.map +1 -1
- package/dist/v2/tokens/density.d.ts +104 -0
- package/dist/v2/tokens/density.d.ts.map +1 -1
- package/dist/v2/tokens/density.js +67 -12
- package/dist/v2/tokens/density.js.map +1 -1
- package/dist/v2/tokens/index.d.ts +50 -1
- package/dist/v2/tokens/index.d.ts.map +1 -1
- package/dist/v2/tokens/index.js +116 -68
- package/dist/v2/tokens/index.js.map +1 -1
- package/dist/v2/tokens/motion.js +16 -22
- package/dist/v2/tokens/motion.js.map +1 -1
- package/dist/v2/tokens/radius.js +3 -3
- package/dist/v2/tokens/radius.js.map +1 -1
- package/dist/v2/tokens/shadows.js +8 -8
- package/dist/v2/tokens/shadows.js.map +1 -1
- package/dist/v2/tokens/spacing.js +4 -4
- package/dist/v2/tokens/spacing.js.map +1 -1
- package/dist/v2/tokens/state.js +3 -3
- package/dist/v2/tokens/state.js.map +1 -1
- package/dist/v2/tokens/statusPalette.js +21 -23
- package/dist/v2/tokens/statusPalette.js.map +1 -1
- package/dist/v2/tokens/tokens.json +6 -1
- package/dist/v2/tokens/typography.js +15 -15
- package/dist/v2/tokens/typography.js.map +1 -1
- package/dist/v2/tokens/zIndex.js +3 -3
- package/dist/v2/tokens/zIndex.js.map +1 -1
- package/dist/v2/types/datagrid.d.ts +9 -1
- package/dist/v2/types/datagrid.d.ts.map +1 -1
- package/dist/v2/types/datagrid.js.map +1 -1
- package/dist/v2/types/index.js +2 -2
- package/dist/v2/types/index.js.map +1 -1
- package/dist/v2/utils/apiError.js +16 -37
- package/dist/v2/utils/apiError.js.map +1 -1
- package/dist/v2/utils/contrast.js +31 -32
- package/dist/v2/utils/contrast.js.map +1 -1
- package/dist/v2/utils/cx.js +7 -27
- package/dist/v2/utils/cx.js.map +1 -1
- package/dist/v2/utils/fileDownload.js +25 -28
- package/dist/v2/utils/fileDownload.js.map +1 -1
- package/dist/v2/utils/fileValidation.d.ts +116 -0
- package/dist/v2/utils/fileValidation.d.ts.map +1 -0
- package/dist/v2/utils/fileValidation.js +220 -0
- package/dist/v2/utils/fileValidation.js.map +1 -0
- package/dist/v2/utils/fmtDate.d.ts +103 -0
- package/dist/v2/utils/fmtDate.d.ts.map +1 -0
- package/dist/v2/utils/fmtDate.js +119 -0
- package/dist/v2/utils/fmtDate.js.map +1 -0
- package/dist/v2/utils/fmtMoney.d.ts +3 -3
- package/dist/v2/utils/fmtMoney.d.ts.map +1 -1
- package/dist/v2/utils/fmtMoney.js +9 -11
- package/dist/v2/utils/fmtMoney.js.map +1 -1
- package/dist/v2/utils/formikErrors.d.ts +67 -0
- package/dist/v2/utils/formikErrors.d.ts.map +1 -0
- package/dist/v2/utils/formikErrors.js +85 -0
- package/dist/v2/utils/formikErrors.js.map +1 -0
- package/dist/v2/utils/index.d.ts +5 -0
- package/dist/v2/utils/index.d.ts.map +1 -1
- package/dist/v2/utils/index.js +67 -18
- package/dist/v2/utils/index.js.map +1 -1
- package/dist/v2/utils/mergeLabels.js +9 -14
- package/dist/v2/utils/mergeLabels.js.map +1 -1
- package/dist/v2/utils/networkStatus.js +14 -14
- package/dist/v2/utils/networkStatus.js.map +1 -1
- package/package.json +26 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormAutoSave.js","names":["_react","require","_typeof","obj","Symbol","iterator","constructor","prototype","_slicedToArray","arr","i","_arrayWithHoles","_iterableToArrayLimit","_unsupportedIterableToArray","_nonIterableRest","TypeError","o","minLen","_arrayLikeToArray","n","Object","toString","call","slice","name","Array","from","test","len","length","arr2","_i","_s","_e","_x","_r","_arr","_n","_d","next","done","push","value","err","isArray","useFormAutoSave","_ref","storageKey","values","setValues","_ref$enabled","enabled","_ref$debounceMs","debounceMs","_ref$initialEmptyChec","initialEmptyCheck","defaultEmptyCheck","_useState","useState","_useState2","hasDraft","setHasDraft","_useState3","_useState4","lastSavedAt","setLastSavedAt","debounceTimerRef","useRef","mountedRef","useEffect","current","raw","localStorage","getItem","parsed","JSON","parse","savedAt","d","Date","Number","isNaN","getTime","removeItem","_unused","_unused2","undefined","clearTimeout","setTimeout","now","setItem","stringify","toISOString","_unused3","restoreDraft","useCallback","process","env","console","warn","_unused4","clearDraft","_unused5","isEmptyValue","v","trim","keys","every"],"sources":["../../../src/lib/v2/hooks/useFormAutoSave.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\r\n\r\n/**\r\n * useFormAutoSave — persist Formik (or any form) values to\r\n * localStorage with debounced writes, and expose draft-restore\r\n * affordances to the host. Pure orchestration; no UI.\r\n *\r\n * Usage:\r\n * import { v2 } from \"@portnet/ui\";\r\n * const { useFormAutoSave, Banner } = v2;\r\n *\r\n * const { hasDraft, lastSavedAt, restoreDraft, clearDraft } =\r\n * useFormAutoSave({\r\n * storageKey: `addpe:autorisation:draft:${id || \"new\"}`,\r\n * values: formik.values,\r\n * setValues: formik.setValues,\r\n * enabled: !id, // CREATE only, not edit\r\n * });\r\n *\r\n * Safety:\r\n * - All localStorage access is try/catch-wrapped.\r\n * - Empty-state values are skipped so we don't produce noise entries.\r\n * - When a draft exists but hasn't been actioned (hasDraft=true),\r\n * the debounced write is PAUSED to prevent overwriting the draft\r\n * with empty initial values before the user decides to restore/ignore.\r\n */\r\n\r\ntype FormAutoSaveOptions<Values> = {\r\n storageKey: string;\r\n values: Values;\r\n /** Required if you call restoreDraft(). */\r\n setValues?: (values: Values) => void;\r\n enabled?: boolean;\r\n debounceMs?: number;\r\n initialEmptyCheck?: (values: Values) => boolean;\r\n};\r\n\r\ntype FormAutoSaveResult = {\r\n hasDraft: boolean;\r\n lastSavedAt: Date | null;\r\n restoreDraft: () => boolean;\r\n clearDraft: () => void;\r\n};\r\n\r\nexport default function useFormAutoSave<Values>({\r\n storageKey,\r\n values,\r\n setValues,\r\n enabled = true,\r\n debounceMs = 800,\r\n initialEmptyCheck = defaultEmptyCheck,\r\n}: FormAutoSaveOptions<Values>): FormAutoSaveResult {\r\n const [hasDraft, setHasDraft] = useState(false);\r\n const [lastSavedAt, setLastSavedAt] = useState<Date | null>(null);\r\n const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n const mountedRef = useRef(false);\r\n\r\n /* ── Mount-time draft detection ────────────────── */\r\n useEffect(() => {\r\n if (!enabled) return;\r\n if (mountedRef.current) return;\r\n mountedRef.current = true;\r\n\r\n try {\r\n const raw = localStorage.getItem(storageKey);\r\n if (!raw) return;\r\n const parsed: unknown = JSON.parse(raw);\r\n if (\r\n parsed &&\r\n typeof parsed === \"object\" &&\r\n \"values\" in parsed &&\r\n parsed.values &&\r\n typeof parsed.values === \"object\"\r\n ) {\r\n setHasDraft(true);\r\n if (\"savedAt\" in parsed && typeof parsed.savedAt === \"string\") {\r\n const d = new Date(parsed.savedAt);\r\n if (!Number.isNaN(d.getTime())) setLastSavedAt(d);\r\n }\r\n } else {\r\n localStorage.removeItem(storageKey);\r\n }\r\n } catch {\r\n try {\r\n localStorage.removeItem(storageKey);\r\n } catch {\r\n /* ignore */\r\n }\r\n }\r\n }, [enabled, storageKey]);\r\n\r\n /* ── Debounced write on values change ──────────────────\r\n *\r\n * CRITICAL: do NOT write while hasDraft=true (draft not yet actioned).\r\n *\r\n * If we write immediately on mount, the empty initial values would\r\n * overwrite the user's saved draft after `debounceMs` milliseconds.\r\n * The user would see the \"restore\" banner, wait/hesitate, then click\r\n * \"Restaurer\" only to find the form empty because restoreDraft() read\r\n * the overwritten (empty) localStorage entry.\r\n *\r\n * We pause writes until hasDraft becomes false, which happens when:\r\n * - restoreDraft() is called (user chose to restore)\r\n * - clearDraft() is called (user chose to ignore)\r\n * - No draft existed on mount (hasDraft was never set to true)\r\n */\r\n useEffect(() => {\r\n if (!enabled) return undefined;\r\n if (hasDraft) return undefined; // ← PAUSE: preserve existing draft\r\n if (initialEmptyCheck(values)) return undefined;\r\n\r\n if (debounceTimerRef.current) {\r\n clearTimeout(debounceTimerRef.current);\r\n }\r\n\r\n debounceTimerRef.current = setTimeout(() => {\r\n try {\r\n const now = new Date();\r\n localStorage.setItem(\r\n storageKey,\r\n JSON.stringify({ values, savedAt: now.toISOString() })\r\n );\r\n setLastSavedAt(now);\r\n } catch {\r\n // Quota full / private mode — no-op.\r\n }\r\n }, debounceMs);\r\n\r\n return () => {\r\n if (debounceTimerRef.current) {\r\n clearTimeout(debounceTimerRef.current);\r\n }\r\n };\r\n }, [values, enabled, hasDraft, storageKey, debounceMs, initialEmptyCheck]);\r\n\r\n /* ── Restore draft ─────────────────────── */\r\n const restoreDraft = useCallback((): boolean => {\r\n if (!setValues) {\r\n if (process.env[\"NODE_ENV\"] !== \"production\") {\r\n // eslint-disable-next-line no-console\r\n console.warn(\"[v2.useFormAutoSave] restoreDraft called but setValues was not provided.\");\r\n }\r\n return false;\r\n }\r\n try {\r\n const raw = localStorage.getItem(storageKey);\r\n if (!raw) return false;\r\n const parsed: unknown = JSON.parse(raw);\r\n if (\r\n !parsed ||\r\n typeof parsed !== \"object\" ||\r\n !(\"values\" in parsed) ||\r\n !parsed.values\r\n ) {\r\n return false;\r\n }\r\n // Persisted draft payload is the form's Values, round-tripped\r\n // through JSON; assert back to Values for the setter.\r\n setValues(parsed.values as Values);\r\n setHasDraft(false); // ← resumes auto-save with restored values\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }, [storageKey, setValues]);\r\n\r\n /* ── Clear draft ─────────────────────── */\r\n const clearDraft = useCallback((): void => {\r\n try {\r\n localStorage.removeItem(storageKey);\r\n } catch {\r\n /* ignore */\r\n }\r\n setHasDraft(false); // ← resumes auto-save for new input\r\n setLastSavedAt(null);\r\n }, [storageKey]);\r\n\r\n return { hasDraft, lastSavedAt, restoreDraft, clearDraft };\r\n}\r\n\r\n/* ── Helpers ───────────────────────────── */\r\n\r\nfunction isEmptyValue(v: unknown): boolean {\r\n if (v === null || v === undefined) return true;\r\n if (typeof v === \"string\") return v.trim().length === 0;\r\n if (Array.isArray(v)) return v.length === 0;\r\n if (typeof v === \"object\") return Object.keys(v).length === 0;\r\n return false;\r\n}\r\n\r\nfunction defaultEmptyCheck(values: unknown): boolean {\r\n if (!values || typeof values !== \"object\") return true;\r\n return Object.values(values).every(isEmptyValue);\r\n}\r\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"useFormAutoSave.js","names":["_react","require","useFormAutoSave","storageKey","values","setValues","enabled","debounceMs","initialEmptyCheck","defaultEmptyCheck","hasDraft","setHasDraft","useState","lastSavedAt","setLastSavedAt","debounceTimerRef","useRef","mountedRef","useEffect","current","raw","localStorage","getItem","parsed","JSON","parse","savedAt","d","Date","Number","isNaN","getTime","removeItem","undefined","clearTimeout","setTimeout","now","setItem","stringify","toISOString","restoreDraft","useCallback","process","env","console","warn","clearDraft","isEmptyValue","v","trim","length","Array","isArray","Object","keys","every"],"sources":["../../../src/lib/v2/hooks/useFormAutoSave.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\r\n\r\n/**\r\n * useFormAutoSave — persist Formik (or any form) values to\r\n * localStorage with debounced writes, and expose draft-restore\r\n * affordances to the host. Pure orchestration; no UI.\r\n *\r\n * Usage:\r\n * import { v2 } from \"@portnet/ui\";\r\n * const { useFormAutoSave, Banner } = v2;\r\n *\r\n * const { hasDraft, lastSavedAt, restoreDraft, clearDraft } =\r\n * useFormAutoSave({\r\n * storageKey: `addpe:autorisation:draft:${id || \"new\"}`,\r\n * values: formik.values,\r\n * setValues: formik.setValues,\r\n * enabled: !id, // CREATE only, not edit\r\n * });\r\n *\r\n * Safety:\r\n * - All localStorage access is try/catch-wrapped.\r\n * - Empty-state values are skipped so we don't produce noise entries.\r\n * - When a draft exists but hasn't been actioned (hasDraft=true),\r\n * the debounced write is PAUSED to prevent overwriting the draft\r\n * with empty initial values before the user decides to restore/ignore.\r\n */\r\n\r\ntype FormAutoSaveOptions<Values> = {\r\n storageKey: string;\r\n values: Values;\r\n /** Required if you call restoreDraft(). */\r\n setValues?: ((values: Values) => void) | undefined;\r\n enabled?: boolean | undefined;\r\n debounceMs?: number | undefined;\r\n initialEmptyCheck?: ((values: Values) => boolean) | undefined;\r\n};\r\n\r\ntype FormAutoSaveResult = {\r\n hasDraft: boolean;\r\n lastSavedAt: Date | null;\r\n restoreDraft: () => boolean;\r\n clearDraft: () => void;\r\n};\r\n\r\nexport default function useFormAutoSave<Values>({\r\n storageKey,\r\n values,\r\n setValues,\r\n enabled = true,\r\n debounceMs = 800,\r\n initialEmptyCheck = defaultEmptyCheck,\r\n}: FormAutoSaveOptions<Values>): FormAutoSaveResult {\r\n const [hasDraft, setHasDraft] = useState(false);\r\n const [lastSavedAt, setLastSavedAt] = useState<Date | null>(null);\r\n const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n const mountedRef = useRef(false);\r\n\r\n /* ── Mount-time draft detection ────────────────── */\r\n useEffect(() => {\r\n if (!enabled) return;\r\n if (mountedRef.current) return;\r\n mountedRef.current = true;\r\n\r\n try {\r\n const raw = localStorage.getItem(storageKey);\r\n if (!raw) return;\r\n const parsed: unknown = JSON.parse(raw);\r\n if (\r\n parsed &&\r\n typeof parsed === \"object\" &&\r\n \"values\" in parsed &&\r\n parsed.values &&\r\n typeof parsed.values === \"object\"\r\n ) {\r\n setHasDraft(true);\r\n if (\"savedAt\" in parsed && typeof parsed.savedAt === \"string\") {\r\n const d = new Date(parsed.savedAt);\r\n if (!Number.isNaN(d.getTime())) setLastSavedAt(d);\r\n }\r\n } else {\r\n localStorage.removeItem(storageKey);\r\n }\r\n } catch {\r\n try {\r\n localStorage.removeItem(storageKey);\r\n } catch {\r\n /* ignore */\r\n }\r\n }\r\n }, [enabled, storageKey]);\r\n\r\n /* ── Debounced write on values change ──────────────────\r\n *\r\n * CRITICAL: do NOT write while hasDraft=true (draft not yet actioned).\r\n *\r\n * If we write immediately on mount, the empty initial values would\r\n * overwrite the user's saved draft after `debounceMs` milliseconds.\r\n * The user would see the \"restore\" banner, wait/hesitate, then click\r\n * \"Restaurer\" only to find the form empty because restoreDraft() read\r\n * the overwritten (empty) localStorage entry.\r\n *\r\n * We pause writes until hasDraft becomes false, which happens when:\r\n * - restoreDraft() is called (user chose to restore)\r\n * - clearDraft() is called (user chose to ignore)\r\n * - No draft existed on mount (hasDraft was never set to true)\r\n */\r\n useEffect(() => {\r\n if (!enabled) return undefined;\r\n if (hasDraft) return undefined; // ← PAUSE: preserve existing draft\r\n if (initialEmptyCheck(values)) return undefined;\r\n\r\n if (debounceTimerRef.current) {\r\n clearTimeout(debounceTimerRef.current);\r\n }\r\n\r\n debounceTimerRef.current = setTimeout(() => {\r\n try {\r\n const now = new Date();\r\n localStorage.setItem(\r\n storageKey,\r\n JSON.stringify({ values, savedAt: now.toISOString() })\r\n );\r\n setLastSavedAt(now);\r\n } catch {\r\n // Quota full / private mode — no-op.\r\n }\r\n }, debounceMs);\r\n\r\n return () => {\r\n if (debounceTimerRef.current) {\r\n clearTimeout(debounceTimerRef.current);\r\n }\r\n };\r\n }, [values, enabled, hasDraft, storageKey, debounceMs, initialEmptyCheck]);\r\n\r\n /* ── Restore draft ─────────────────────── */\r\n const restoreDraft = useCallback((): boolean => {\r\n if (!setValues) {\r\n if (process.env[\"NODE_ENV\"] !== \"production\") {\r\n // eslint-disable-next-line no-console\r\n console.warn(\"[v2.useFormAutoSave] restoreDraft called but setValues was not provided.\");\r\n }\r\n return false;\r\n }\r\n try {\r\n const raw = localStorage.getItem(storageKey);\r\n if (!raw) return false;\r\n const parsed: unknown = JSON.parse(raw);\r\n if (\r\n !parsed ||\r\n typeof parsed !== \"object\" ||\r\n !(\"values\" in parsed) ||\r\n !parsed.values\r\n ) {\r\n return false;\r\n }\r\n // Persisted draft payload is the form's Values, round-tripped\r\n // through JSON; assert back to Values for the setter.\r\n setValues(parsed.values as Values);\r\n setHasDraft(false); // ← resumes auto-save with restored values\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }, [storageKey, setValues]);\r\n\r\n /* ── Clear draft ─────────────────────── */\r\n const clearDraft = useCallback((): void => {\r\n try {\r\n localStorage.removeItem(storageKey);\r\n } catch {\r\n /* ignore */\r\n }\r\n setHasDraft(false); // ← resumes auto-save for new input\r\n setLastSavedAt(null);\r\n }, [storageKey]);\r\n\r\n return { hasDraft, lastSavedAt, restoreDraft, clearDraft };\r\n}\r\n\r\n/* ── Helpers ───────────────────────────── */\r\n\r\nfunction isEmptyValue(v: unknown): boolean {\r\n if (v === null || v === undefined) return true;\r\n if (typeof v === \"string\") return v.trim().length === 0;\r\n if (Array.isArray(v)) return v.length === 0;\r\n if (typeof v === \"object\") return Object.keys(v).length === 0;\r\n return false;\r\n}\r\n\r\nfunction defaultEmptyCheck(values: unknown): boolean {\r\n if (!values || typeof values !== \"object\") return true;\r\n return Object.values(values).every(isEmptyValue);\r\n}\r\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAmBe,SAASC,eAAeA,CAAS;EAC9CC,UAAU;EACVC,MAAM;EACNC,SAAS;EACTC,OAAO,GAAG,IAAI;EACdC,UAAU,GAAG,GAAG;EAChBC,iBAAiB,GAAGC;AACO,CAAC,EAAsB;EAClD,MAAM,CAACC,QAAQ,EAAEC,WAAW,CAAC,GAAG,IAAAC,eAAQ,EAAC,KAAK,CAAC;EAC/C,MAAM,CAACC,WAAW,EAAEC,cAAc,CAAC,GAAG,IAAAF,eAAQ,EAAc,IAAI,CAAC;EACjE,MAAMG,gBAAgB,GAAG,IAAAC,aAAM,EAAuC,IAAI,CAAC;EAC3E,MAAMC,UAAU,GAAG,IAAAD,aAAM,EAAC,KAAK,CAAC;;EAEhC;EACA,IAAAE,gBAAS,EAAC,MAAM;IACd,IAAI,CAACZ,OAAO,EAAE;IACd,IAAIW,UAAU,CAACE,OAAO,EAAE;IACxBF,UAAU,CAACE,OAAO,GAAG,IAAI;IAEzB,IAAI;MACF,MAAMC,GAAG,GAAGC,YAAY,CAACC,OAAO,CAACnB,UAAU,CAAC;MAC5C,IAAI,CAACiB,GAAG,EAAE;MACV,MAAMG,MAAe,GAAGC,IAAI,CAACC,KAAK,CAACL,GAAG,CAAC;MACvC,IACEG,MAAM,IACN,OAAOA,MAAM,KAAK,QAAQ,IAC1B,QAAQ,IAAIA,MAAM,IAClBA,MAAM,CAACnB,MAAM,IACb,OAAOmB,MAAM,CAACnB,MAAM,KAAK,QAAQ,EACjC;QACAO,WAAW,CAAC,IAAI,CAAC;QACjB,IAAI,SAAS,IAAIY,MAAM,IAAI,OAAOA,MAAM,CAACG,OAAO,KAAK,QAAQ,EAAE;UAC7D,MAAMC,CAAC,GAAG,IAAIC,IAAI,CAACL,MAAM,CAACG,OAAO,CAAC;UAClC,IAAI,CAACG,MAAM,CAACC,KAAK,CAACH,CAAC,CAACI,OAAO,CAAC,CAAC,CAAC,EAAEjB,cAAc,CAACa,CAAC,CAAC;QACnD;MACF,CAAC,MAAM;QACLN,YAAY,CAACW,UAAU,CAAC7B,UAAU,CAAC;MACrC;IACF,CAAC,CAAC,MAAM;MACN,IAAI;QACFkB,YAAY,CAACW,UAAU,CAAC7B,UAAU,CAAC;MACrC,CAAC,CAAC,MAAM;QACN;MAAA;IAEJ;EACF,CAAC,EAAE,CAACG,OAAO,EAAEH,UAAU,CAAC,CAAC;;EAEzB;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACE,IAAAe,gBAAS,EAAC,MAAM;IACd,IAAI,CAACZ,OAAO,EAAE,OAAO2B,SAAS;IAC9B,IAAIvB,QAAQ,EAAE,OAAOuB,SAAS,CAAC,CAAW;IAC1C,IAAIzB,iBAAiB,CAACJ,MAAM,CAAC,EAAE,OAAO6B,SAAS;IAE/C,IAAIlB,gBAAgB,CAACI,OAAO,EAAE;MAC5Be,YAAY,CAACnB,gBAAgB,CAACI,OAAO,CAAC;IACxC;IAEAJ,gBAAgB,CAACI,OAAO,GAAGgB,UAAU,CAAC,MAAM;MAC1C,IAAI;QACF,MAAMC,GAAG,GAAG,IAAIR,IAAI,CAAC,CAAC;QACtBP,YAAY,CAACgB,OAAO,CAClBlC,UAAU,EACVqB,IAAI,CAACc,SAAS,CAAC;UAAElC,MAAM;UAAEsB,OAAO,EAAEU,GAAG,CAACG,WAAW,CAAC;QAAE,CAAC,CACvD,CAAC;QACDzB,cAAc,CAACsB,GAAG,CAAC;MACrB,CAAC,CAAC,MAAM;QACN;MAAA;IAEJ,CAAC,EAAE7B,UAAU,CAAC;IAEd,OAAO,MAAM;MACX,IAAIQ,gBAAgB,CAACI,OAAO,EAAE;QAC5Be,YAAY,CAACnB,gBAAgB,CAACI,OAAO,CAAC;MACxC;IACF,CAAC;EACH,CAAC,EAAE,CAACf,MAAM,EAAEE,OAAO,EAAEI,QAAQ,EAAEP,UAAU,EAAEI,UAAU,EAAEC,iBAAiB,CAAC,CAAC;;EAE1E;EACA,MAAMgC,YAAY,GAAG,IAAAC,kBAAW,EAAC,MAAe;IAC9C,IAAI,CAACpC,SAAS,EAAE;MACd,IAAIqC,OAAO,CAACC,GAAG,CAAC,UAAU,CAAC,KAAK,YAAY,EAAE;QAC5C;QACAC,OAAO,CAACC,IAAI,CAAC,0EAA0E,CAAC;MAC1F;MACA,OAAO,KAAK;IACd;IACA,IAAI;MACF,MAAMzB,GAAG,GAAGC,YAAY,CAACC,OAAO,CAACnB,UAAU,CAAC;MAC5C,IAAI,CAACiB,GAAG,EAAE,OAAO,KAAK;MACtB,MAAMG,MAAe,GAAGC,IAAI,CAACC,KAAK,CAACL,GAAG,CAAC;MACvC,IACE,CAACG,MAAM,IACP,OAAOA,MAAM,KAAK,QAAQ,IAC1B,EAAE,QAAQ,IAAIA,MAAM,CAAC,IACrB,CAACA,MAAM,CAACnB,MAAM,EACd;QACA,OAAO,KAAK;MACd;MACA;MACA;MACAC,SAAS,CAACkB,MAAM,CAACnB,MAAgB,CAAC;MAClCO,WAAW,CAAC,KAAK,CAAC,CAAC,CAAE;MACrB,OAAO,IAAI;IACb,CAAC,CAAC,MAAM;MACN,OAAO,KAAK;IACd;EACF,CAAC,EAAE,CAACR,UAAU,EAAEE,SAAS,CAAC,CAAC;;EAE3B;EACA,MAAMyC,UAAU,GAAG,IAAAL,kBAAW,EAAC,MAAY;IACzC,IAAI;MACFpB,YAAY,CAACW,UAAU,CAAC7B,UAAU,CAAC;IACrC,CAAC,CAAC,MAAM;MACN;IAAA;IAEFQ,WAAW,CAAC,KAAK,CAAC,CAAC,CAAI;IACvBG,cAAc,CAAC,IAAI,CAAC;EACtB,CAAC,EAAE,CAACX,UAAU,CAAC,CAAC;EAEhB,OAAO;IAAEO,QAAQ;IAAEG,WAAW;IAAE2B,YAAY;IAAEM;EAAW,CAAC;AAC5D;;AAEA;;AAEA,SAASC,YAAYA,CAACC,CAAU,EAAW;EACzC,IAAIA,CAAC,KAAK,IAAI,IAAIA,CAAC,KAAKf,SAAS,EAAE,OAAO,IAAI;EAC9C,IAAI,OAAOe,CAAC,KAAK,QAAQ,EAAE,OAAOA,CAAC,CAACC,IAAI,CAAC,CAAC,CAACC,MAAM,KAAK,CAAC;EACvD,IAAIC,KAAK,CAACC,OAAO,CAACJ,CAAC,CAAC,EAAE,OAAOA,CAAC,CAACE,MAAM,KAAK,CAAC;EAC3C,IAAI,OAAOF,CAAC,KAAK,QAAQ,EAAE,OAAOK,MAAM,CAACC,IAAI,CAACN,CAAC,CAAC,CAACE,MAAM,KAAK,CAAC;EAC7D,OAAO,KAAK;AACd;AAEA,SAASzC,iBAAiBA,CAACL,MAAe,EAAW;EACnD,IAAI,CAACA,MAAM,IAAI,OAAOA,MAAM,KAAK,QAAQ,EAAE,OAAO,IAAI;EACtD,OAAOiD,MAAM,CAACjD,MAAM,CAACA,MAAM,CAAC,CAACmD,KAAK,CAACR,YAAY,CAAC;AAClD","ignoreList":[]}
|
|
@@ -35,7 +35,7 @@ type FormCompletionProgressOptions<Values> = {
|
|
|
35
35
|
/** Field keys / dot-paths that are required. */
|
|
36
36
|
requiredFields: string[];
|
|
37
37
|
/** Field keys / dot-paths that are optional. */
|
|
38
|
-
optionalFields?: string[];
|
|
38
|
+
optionalFields?: string[] | undefined;
|
|
39
39
|
};
|
|
40
40
|
type FormCompletionProgress = {
|
|
41
41
|
requiredPct: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormCompletionProgress.d.ts","sourceRoot":"","sources":["../../../src/lib/v2/hooks/useFormCompletionProgress.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,KAAK,6BAA6B,CAAC,MAAM,IAAI;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"useFormCompletionProgress.d.ts","sourceRoot":"","sources":["../../../src/lib/v2/hooks/useFormCompletionProgress.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,KAAK,6BAA6B,CAAC,MAAM,IAAI;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CACvC,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,MAAM,EAAE,EACxD,MAAM,EACN,cAAc,EACd,cAAmB,GACpB,EAAE,6BAA6B,CAAC,MAAM,CAAC,GAAG,sBAAsB,CAwChE"}
|
|
@@ -3,12 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports
|
|
6
|
+
exports.default = useFormCompletionProgress;
|
|
7
7
|
var _react = require("react");
|
|
8
|
-
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
|
|
9
|
-
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
10
|
-
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
11
|
-
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
12
8
|
/**
|
|
13
9
|
* useFormCompletionProgress — derive required/overall completion
|
|
14
10
|
* percentages from current form values and a declared field list.
|
|
@@ -42,38 +38,32 @@ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" =
|
|
|
42
38
|
* "articles" → values.articles (array length checked)
|
|
43
39
|
*/
|
|
44
40
|
|
|
45
|
-
function useFormCompletionProgress(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return (0, _react.useMemo)(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
var totalRequired = required.length;
|
|
63
|
-
var totalOptional = optional.length;
|
|
64
|
-
var requiredPct = totalRequired ? Math.round(filledRequired / totalRequired * 100) : 100;
|
|
65
|
-
var overallFilled = filledRequired + filledOptional;
|
|
66
|
-
var overallTotal = totalRequired + totalOptional;
|
|
67
|
-
var overallPct = overallTotal ? Math.round(overallFilled / overallTotal * 100) : 0;
|
|
41
|
+
function useFormCompletionProgress({
|
|
42
|
+
values,
|
|
43
|
+
requiredFields,
|
|
44
|
+
optionalFields = []
|
|
45
|
+
}) {
|
|
46
|
+
return (0, _react.useMemo)(() => {
|
|
47
|
+
const required = Array.isArray(requiredFields) ? requiredFields : [];
|
|
48
|
+
const optional = Array.isArray(optionalFields) ? optionalFields : [];
|
|
49
|
+
const filledRequired = required.filter(path => isFilled(getFieldValue(values, path))).length;
|
|
50
|
+
const filledOptional = optional.filter(path => isFilled(getFieldValue(values, path))).length;
|
|
51
|
+
const missingRequired = required.filter(path => !isFilled(getFieldValue(values, path)));
|
|
52
|
+
const totalRequired = required.length;
|
|
53
|
+
const totalOptional = optional.length;
|
|
54
|
+
const requiredPct = totalRequired ? Math.round(filledRequired / totalRequired * 100) : 100;
|
|
55
|
+
const overallFilled = filledRequired + filledOptional;
|
|
56
|
+
const overallTotal = totalRequired + totalOptional;
|
|
57
|
+
const overallPct = overallTotal ? Math.round(overallFilled / overallTotal * 100) : 0;
|
|
68
58
|
return {
|
|
69
|
-
requiredPct
|
|
70
|
-
overallPct
|
|
71
|
-
filledRequired
|
|
72
|
-
totalRequired
|
|
73
|
-
filledOptional
|
|
74
|
-
totalOptional
|
|
59
|
+
requiredPct,
|
|
60
|
+
overallPct,
|
|
61
|
+
filledRequired,
|
|
62
|
+
totalRequired,
|
|
63
|
+
filledOptional,
|
|
64
|
+
totalOptional,
|
|
75
65
|
isCompleteRequired: totalRequired === 0 || filledRequired === totalRequired,
|
|
76
|
-
missingRequired
|
|
66
|
+
missingRequired
|
|
77
67
|
};
|
|
78
68
|
}, [values, requiredFields, optionalFields]);
|
|
79
69
|
}
|
|
@@ -89,23 +79,14 @@ function useFormCompletionProgress(_ref) {
|
|
|
89
79
|
* getFieldValue({}, "doesNotExist") → undefined
|
|
90
80
|
*/
|
|
91
81
|
function getFieldValue(obj, path) {
|
|
92
|
-
if (!obj ||
|
|
82
|
+
if (!obj || typeof obj !== "object") return undefined;
|
|
93
83
|
if (!path) return undefined;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
var p = _step.value;
|
|
101
|
-
if (cur === null || cur === undefined) return undefined;
|
|
102
|
-
if (_typeof(cur) !== "object") return undefined;
|
|
103
|
-
cur = cur[p];
|
|
104
|
-
}
|
|
105
|
-
} catch (err) {
|
|
106
|
-
_iterator.e(err);
|
|
107
|
-
} finally {
|
|
108
|
-
_iterator.f();
|
|
84
|
+
const parts = path.split(".");
|
|
85
|
+
let cur = obj;
|
|
86
|
+
for (const p of parts) {
|
|
87
|
+
if (cur === null || cur === undefined) return undefined;
|
|
88
|
+
if (typeof cur !== "object") return undefined;
|
|
89
|
+
cur = cur[p];
|
|
109
90
|
}
|
|
110
91
|
return cur;
|
|
111
92
|
}
|
|
@@ -129,7 +110,7 @@ function isFilled(v) {
|
|
|
129
110
|
if (typeof v === "string") return v.trim().length > 0;
|
|
130
111
|
if (Array.isArray(v)) return v.length > 0;
|
|
131
112
|
if (v instanceof Date) return !Number.isNaN(v.getTime());
|
|
132
|
-
if (
|
|
113
|
+
if (typeof v === "object") return Object.keys(v).length > 0;
|
|
133
114
|
// numbers, booleans
|
|
134
115
|
return true;
|
|
135
116
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormCompletionProgress.js","names":["_react","require","_createForOfIteratorHelper","o","allowArrayLike","it","Symbol","iterator","Array","isArray","_unsupportedIterableToArray","length","i","F","s","n","done","value","e","_e","f","TypeError","normalCompletion","didErr","err","call","step","next","_e2","minLen","_arrayLikeToArray","Object","prototype","toString","slice","constructor","name","from","test","arr","len","arr2","_typeof","obj","useFormCompletionProgress","_ref","values","requiredFields","_ref$optionalFields","optionalFields","useMemo","required","optional","filledRequired","filter","path","isFilled","getFieldValue","filledOptional","missingRequired","totalRequired","totalOptional","requiredPct","Math","round","overallFilled","overallTotal","overallPct","isCompleteRequired","undefined","parts","split","cur","_iterator","_step","p","v","trim","Date","Number","isNaN","getTime","keys"],"sources":["../../../src/lib/v2/hooks/useFormCompletionProgress.ts"],"sourcesContent":["import { useMemo } from \"react\";\r\n\r\n/**\r\n * useFormCompletionProgress — derive required/overall completion\r\n * percentages from current form values and a declared field list.\r\n * Pure useMemo computation, no side effects.\r\n *\r\n * Usage:\r\n * import { v2 } from \"@portnet/ui\";\r\n * const { useFormCompletionProgress, ProgressBar } = v2;\r\n *\r\n * const REQUIRED = [\"typeAutorisation\", \"importer.id\", \"dateFinValidite\"];\r\n * const OPTIONAL = [\"referenceLicence\", \"region\"];\r\n *\r\n * const {\r\n * requiredPct,\r\n * overallPct,\r\n * isCompleteRequired,\r\n * missingRequired,\r\n * filledRequired,\r\n * totalRequired,\r\n * } = useFormCompletionProgress({\r\n * values: formik.values,\r\n * requiredFields: REQUIRED,\r\n * optionalFields: OPTIONAL,\r\n * });\r\n *\r\n * <ProgressBar value={requiredPct} />\r\n * <span>{filledRequired}/{totalRequired} requis</span>\r\n *\r\n * Field paths support dot notation for nested values:\r\n * \"importer.id\" → values.importer.id\r\n * \"articles\" → values.articles (array length checked)\r\n */\r\n\r\ntype FormCompletionProgressOptions<Values> = {\r\n values: Values;\r\n /** Field keys / dot-paths that are required. */\r\n requiredFields: string[];\r\n /** Field keys / dot-paths that are optional. */\r\n optionalFields?: string[];\r\n};\r\n\r\ntype FormCompletionProgress = {\r\n requiredPct: number;\r\n overallPct: number;\r\n filledRequired: number;\r\n totalRequired: number;\r\n filledOptional: number;\r\n totalOptional: number;\r\n isCompleteRequired: boolean;\r\n missingRequired: string[];\r\n};\r\n\r\nexport default function useFormCompletionProgress<Values>({\r\n values,\r\n requiredFields,\r\n optionalFields = [],\r\n}: FormCompletionProgressOptions<Values>): FormCompletionProgress {\r\n return useMemo(() => {\r\n const required = Array.isArray(requiredFields) ? requiredFields : [];\r\n const optional = Array.isArray(optionalFields) ? optionalFields : [];\r\n\r\n const filledRequired = required.filter((path) =>\r\n isFilled(getFieldValue(values, path))\r\n ).length;\r\n const filledOptional = optional.filter((path) =>\r\n isFilled(getFieldValue(values, path))\r\n ).length;\r\n\r\n const missingRequired = required.filter(\r\n (path) => !isFilled(getFieldValue(values, path))\r\n );\r\n\r\n const totalRequired = required.length;\r\n const totalOptional = optional.length;\r\n\r\n const requiredPct = totalRequired\r\n ? Math.round((filledRequired / totalRequired) * 100)\r\n : 100;\r\n\r\n const overallFilled = filledRequired + filledOptional;\r\n const overallTotal = totalRequired + totalOptional;\r\n const overallPct = overallTotal\r\n ? Math.round((overallFilled / overallTotal) * 100)\r\n : 0;\r\n\r\n return {\r\n requiredPct,\r\n overallPct,\r\n filledRequired,\r\n totalRequired,\r\n filledOptional,\r\n totalOptional,\r\n isCompleteRequired: totalRequired === 0 || filledRequired === totalRequired,\r\n missingRequired,\r\n };\r\n }, [values, requiredFields, optionalFields]);\r\n}\r\n\r\n/* ── Helpers ───────────────────────────── */\r\n\r\n/**\r\n * Resolves a dot-separated field path against a values object.\r\n * Returns undefined on any missing intermediate.\r\n *\r\n * getFieldValue({ a: { b: { c: 42 } } }, \"a.b.c\") → 42\r\n * getFieldValue({ a: null }, \"a.b.c\") → undefined\r\n * getFieldValue({}, \"doesNotExist\") → undefined\r\n */\r\nfunction getFieldValue(obj: unknown, path: string): unknown {\r\n if (!obj || typeof obj !== \"object\") return undefined;\r\n if (!path) return undefined;\r\n const parts = path.split(\".\");\r\n let cur: unknown = obj;\r\n for (const p of parts) {\r\n if (cur === null || cur === undefined) return undefined;\r\n if (typeof cur !== \"object\") return undefined;\r\n cur = (cur as Record<string, unknown>)[p];\r\n }\r\n return cur;\r\n}\r\n\r\n/**\r\n * Centralised \"is this value considered filled?\" check.\r\n *\r\n * Considered EMPTY:\r\n * - null, undefined\r\n * - \"\" or whitespace-only string\r\n * - empty array []\r\n * - empty plain object {}\r\n *\r\n * Considered FILLED (intentional):\r\n * - 0, false (valid user input distinct from \"unset\")\r\n * - any non-empty array, object with keys, string, number\r\n * - Date instances with valid time\r\n */\r\nfunction isFilled(v: unknown): boolean {\r\n if (v === null || v === undefined) return false;\r\n if (typeof v === \"string\") return v.trim().length > 0;\r\n if (Array.isArray(v)) return v.length > 0;\r\n if (v instanceof Date) return !Number.isNaN(v.getTime());\r\n if (typeof v === \"object\") return Object.keys(v).length > 0;\r\n // numbers, booleans\r\n return true;\r\n}\r\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"useFormCompletionProgress.js","names":["_react","require","useFormCompletionProgress","values","requiredFields","optionalFields","useMemo","required","Array","isArray","optional","filledRequired","filter","path","isFilled","getFieldValue","length","filledOptional","missingRequired","totalRequired","totalOptional","requiredPct","Math","round","overallFilled","overallTotal","overallPct","isCompleteRequired","obj","undefined","parts","split","cur","p","v","trim","Date","Number","isNaN","getTime","Object","keys"],"sources":["../../../src/lib/v2/hooks/useFormCompletionProgress.ts"],"sourcesContent":["import { useMemo } from \"react\";\r\n\r\n/**\r\n * useFormCompletionProgress — derive required/overall completion\r\n * percentages from current form values and a declared field list.\r\n * Pure useMemo computation, no side effects.\r\n *\r\n * Usage:\r\n * import { v2 } from \"@portnet/ui\";\r\n * const { useFormCompletionProgress, ProgressBar } = v2;\r\n *\r\n * const REQUIRED = [\"typeAutorisation\", \"importer.id\", \"dateFinValidite\"];\r\n * const OPTIONAL = [\"referenceLicence\", \"region\"];\r\n *\r\n * const {\r\n * requiredPct,\r\n * overallPct,\r\n * isCompleteRequired,\r\n * missingRequired,\r\n * filledRequired,\r\n * totalRequired,\r\n * } = useFormCompletionProgress({\r\n * values: formik.values,\r\n * requiredFields: REQUIRED,\r\n * optionalFields: OPTIONAL,\r\n * });\r\n *\r\n * <ProgressBar value={requiredPct} />\r\n * <span>{filledRequired}/{totalRequired} requis</span>\r\n *\r\n * Field paths support dot notation for nested values:\r\n * \"importer.id\" → values.importer.id\r\n * \"articles\" → values.articles (array length checked)\r\n */\r\n\r\ntype FormCompletionProgressOptions<Values> = {\r\n values: Values;\r\n /** Field keys / dot-paths that are required. */\r\n requiredFields: string[];\r\n /** Field keys / dot-paths that are optional. */\r\n optionalFields?: string[] | undefined;\r\n};\r\n\r\ntype FormCompletionProgress = {\r\n requiredPct: number;\r\n overallPct: number;\r\n filledRequired: number;\r\n totalRequired: number;\r\n filledOptional: number;\r\n totalOptional: number;\r\n isCompleteRequired: boolean;\r\n missingRequired: string[];\r\n};\r\n\r\nexport default function useFormCompletionProgress<Values>({\r\n values,\r\n requiredFields,\r\n optionalFields = [],\r\n}: FormCompletionProgressOptions<Values>): FormCompletionProgress {\r\n return useMemo(() => {\r\n const required = Array.isArray(requiredFields) ? requiredFields : [];\r\n const optional = Array.isArray(optionalFields) ? optionalFields : [];\r\n\r\n const filledRequired = required.filter((path) =>\r\n isFilled(getFieldValue(values, path))\r\n ).length;\r\n const filledOptional = optional.filter((path) =>\r\n isFilled(getFieldValue(values, path))\r\n ).length;\r\n\r\n const missingRequired = required.filter(\r\n (path) => !isFilled(getFieldValue(values, path))\r\n );\r\n\r\n const totalRequired = required.length;\r\n const totalOptional = optional.length;\r\n\r\n const requiredPct = totalRequired\r\n ? Math.round((filledRequired / totalRequired) * 100)\r\n : 100;\r\n\r\n const overallFilled = filledRequired + filledOptional;\r\n const overallTotal = totalRequired + totalOptional;\r\n const overallPct = overallTotal\r\n ? Math.round((overallFilled / overallTotal) * 100)\r\n : 0;\r\n\r\n return {\r\n requiredPct,\r\n overallPct,\r\n filledRequired,\r\n totalRequired,\r\n filledOptional,\r\n totalOptional,\r\n isCompleteRequired: totalRequired === 0 || filledRequired === totalRequired,\r\n missingRequired,\r\n };\r\n }, [values, requiredFields, optionalFields]);\r\n}\r\n\r\n/* ── Helpers ───────────────────────────── */\r\n\r\n/**\r\n * Resolves a dot-separated field path against a values object.\r\n * Returns undefined on any missing intermediate.\r\n *\r\n * getFieldValue({ a: { b: { c: 42 } } }, \"a.b.c\") → 42\r\n * getFieldValue({ a: null }, \"a.b.c\") → undefined\r\n * getFieldValue({}, \"doesNotExist\") → undefined\r\n */\r\nfunction getFieldValue(obj: unknown, path: string): unknown {\r\n if (!obj || typeof obj !== \"object\") return undefined;\r\n if (!path) return undefined;\r\n const parts = path.split(\".\");\r\n let cur: unknown = obj;\r\n for (const p of parts) {\r\n if (cur === null || cur === undefined) return undefined;\r\n if (typeof cur !== \"object\") return undefined;\r\n cur = (cur as Record<string, unknown>)[p];\r\n }\r\n return cur;\r\n}\r\n\r\n/**\r\n * Centralised \"is this value considered filled?\" check.\r\n *\r\n * Considered EMPTY:\r\n * - null, undefined\r\n * - \"\" or whitespace-only string\r\n * - empty array []\r\n * - empty plain object {}\r\n *\r\n * Considered FILLED (intentional):\r\n * - 0, false (valid user input distinct from \"unset\")\r\n * - any non-empty array, object with keys, string, number\r\n * - Date instances with valid time\r\n */\r\nfunction isFilled(v: unknown): boolean {\r\n if (v === null || v === undefined) return false;\r\n if (typeof v === \"string\") return v.trim().length > 0;\r\n if (Array.isArray(v)) return v.length > 0;\r\n if (v instanceof Date) return !Number.isNaN(v.getTime());\r\n if (typeof v === \"object\") return Object.keys(v).length > 0;\r\n // numbers, booleans\r\n return true;\r\n}\r\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface KeyboardShortcut {
|
|
2
|
+
/**
|
|
3
|
+
* Keys that trigger it, as `KeyboardEvent.key` values — so `"/"`, `"?"`,
|
|
4
|
+
* `"1"`, `"n"`. Case matters: `"n"` does not match `Shift+N`.
|
|
5
|
+
*/
|
|
6
|
+
keys: readonly string[];
|
|
7
|
+
/**
|
|
8
|
+
* Receives the key that matched, so one descriptor can serve a range
|
|
9
|
+
* (`["1","2","3"]` → one handler that reads which was pressed).
|
|
10
|
+
*/
|
|
11
|
+
onTrigger: (key: string) => void;
|
|
12
|
+
/**
|
|
13
|
+
* @default true — a shortcut gated on a permission stays DECLARED and
|
|
14
|
+
* inactive rather than being spliced out of the array, so the descriptor
|
|
15
|
+
* list keeps the same shape as the help dialogue's.
|
|
16
|
+
*/
|
|
17
|
+
enabled?: boolean | undefined;
|
|
18
|
+
}
|
|
19
|
+
export interface UseKeyboardShortcutsOptions {
|
|
20
|
+
/** Suspends every shortcut at once. @default true */
|
|
21
|
+
enabled?: boolean | undefined;
|
|
22
|
+
}
|
|
23
|
+
export declare function useKeyboardShortcuts(shortcuts: readonly KeyboardShortcut[], { enabled }?: UseKeyboardShortcutsOptions): void;
|
|
24
|
+
export default useKeyboardShortcuts;
|
|
25
|
+
//# sourceMappingURL=useKeyboardShortcuts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useKeyboardShortcuts.d.ts","sourceRoot":"","sources":["../../../src/lib/v2/hooks/useKeyboardShortcuts.ts"],"names":[],"mappings":"AAoHA,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB;;;OAGG;IACH,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,2BAA2B;IAC1C,qDAAqD;IACrD,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/B;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,SAAS,gBAAgB,EAAE,EACtC,EAAE,OAAc,EAAE,GAAE,2BAAgC,GACnD,IAAI,CA+BN;AAED,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
exports.useKeyboardShortcuts = useKeyboardShortcuts;
|
|
8
|
+
var React = _interopRequireWildcard(require("react"));
|
|
9
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
10
|
+
/**
|
|
11
|
+
* useKeyboardShortcuts — Portnet UI v2 (hook)
|
|
12
|
+
*
|
|
13
|
+
* Raccourcis clavier de page. §Keyboard / R-K.1.
|
|
14
|
+
*
|
|
15
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
16
|
+
* WHY THIS BELONGS IN THE LIBRARY (capability gap G-48)
|
|
17
|
+
*
|
|
18
|
+
* The library already owned BOTH ENDS of page shortcuts and not the listener
|
|
19
|
+
* between them:
|
|
20
|
+
*
|
|
21
|
+
* · `KeyboardShortcutsHelp` — the « ? » dialogue that LISTS the shortcuts;
|
|
22
|
+
* · `data-v2-overlay-open` on `<body>` — the signal the library SETS when a
|
|
23
|
+
* modal or drawer is open, and which shortcuts must respect.
|
|
24
|
+
*
|
|
25
|
+
* So a host wiring shortcuts had to write the middle itself, and `ms-ti-fe`
|
|
26
|
+
* did: a `keydown` effect plus `isShortcutBlockingTarget` (a set of eleven
|
|
27
|
+
* interactive ARIA roles, the tag list, `isContentEditable`, `tabIndex >= 0`)
|
|
28
|
+
* plus `isOverlayOpen` reading the library's own attribute back off the body.
|
|
29
|
+
* Forty lines of platform behaviour in a listing page.
|
|
30
|
+
*
|
|
31
|
+
* >>> THE OVERLAY GUARD IS THE REASON THIS CANNOT STAY IN A HOST. The library
|
|
32
|
+
* >>> is what SETS `data-v2-overlay-open`; a host reading it is a module
|
|
33
|
+
* >>> depending on an implementation detail of the component it renders. If
|
|
34
|
+
* >>> that attribute is ever renamed, every host that copied the guard breaks
|
|
35
|
+
* >>> SILENTLY — the shortcuts simply start firing behind open modals, which
|
|
36
|
+
* >>> nothing tests and nobody notices until a « n » keystroke inside a drawer
|
|
37
|
+
* >>> navigates the page away. Owning the listener here means the guard and
|
|
38
|
+
* >>> the signal are maintained together. <<<
|
|
39
|
+
*
|
|
40
|
+
* Raised from `addm-fe` (Area 14), whose listings carry a `searchInputRef`
|
|
41
|
+
* declared and passed to `DataGridToolbar` FOR the « / » shortcut — a wire
|
|
42
|
+
* waiting for a listener that was never written.
|
|
43
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
44
|
+
*
|
|
45
|
+
* WHAT THE HOOK REFUSES TO FIRE ON, and why each case matters:
|
|
46
|
+
*
|
|
47
|
+
* · A MODIFIER is held (⌘/Ctrl/Alt). « n » is a shortcut; ⌘N is the
|
|
48
|
+
* browser's new window, and stealing it is worse than having no shortcut.
|
|
49
|
+
* · The target is an EDITABLE element — input, textarea, select,
|
|
50
|
+
* contenteditable. Typing « / » in a search box must insert a slash.
|
|
51
|
+
* · The target is otherwise INTERACTIVE — a button, a link, anything with an
|
|
52
|
+
* interactive ARIA role or a positive tabIndex. `Espace` on a focused
|
|
53
|
+
* button activates it; a page shortcut must not pre-empt that.
|
|
54
|
+
* · An OVERLAY is open. See the note above.
|
|
55
|
+
*
|
|
56
|
+
* `<main>` is excluded from the tabIndex test deliberately: a page shell gives
|
|
57
|
+
* `<main>` a `tabIndex` so a skip link can reach it, which would otherwise
|
|
58
|
+
* disable every shortcut for a user who just used the skip link.
|
|
59
|
+
*
|
|
60
|
+
* Usage:
|
|
61
|
+
*
|
|
62
|
+
* useKeyboardShortcuts([
|
|
63
|
+
* { keys: ["/"], onTrigger: () => searchRef.current?.focus() },
|
|
64
|
+
* { keys: ["n"], onTrigger: goToCreate, enabled: canCreate },
|
|
65
|
+
* { keys: ["1", "2", "3"], onTrigger: (key) => setBucket(BY_KEY[key]) },
|
|
66
|
+
* ]);
|
|
67
|
+
*
|
|
68
|
+
* The host keeps its own `KeyboardShortcutsHelp` list: this hook knows which
|
|
69
|
+
* keys DO something, not how to describe them to a user (§9.2 — the business
|
|
70
|
+
* wording belongs to the host).
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Roles whose focused element handles its own keys. Kept here rather than in
|
|
75
|
+
* a host so the list is maintained once for the fleet.
|
|
76
|
+
*/
|
|
77
|
+
const INTERACTIVE_ROLES = new Set(["button", "link", "tab", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "checkbox", "radio", "combobox", "searchbox", "textbox", "switch", "spinbutton", "slider"]);
|
|
78
|
+
const EDITABLE_TAGS = new Set(["INPUT", "TEXTAREA", "SELECT"]);
|
|
79
|
+
function isBlockingTarget(node) {
|
|
80
|
+
if (!node || node === document.body) return false;
|
|
81
|
+
if (!(node instanceof Element)) return false;
|
|
82
|
+
const tag = node.tagName;
|
|
83
|
+
if (EDITABLE_TAGS.has(tag)) return true;
|
|
84
|
+
if (tag === "BUTTON" || tag === "A") return true;
|
|
85
|
+
if (node instanceof HTMLElement && node.isContentEditable) return true;
|
|
86
|
+
const role = node.getAttribute("role");
|
|
87
|
+
if (role && INTERACTIVE_ROLES.has(role)) return true;
|
|
88
|
+
|
|
89
|
+
/* `MAIN` excluded — see the note in the file header on skip links. */
|
|
90
|
+
if (node instanceof HTMLElement && node.tabIndex >= 0 && tag !== "MAIN") {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Is a library overlay (modal / drawer) currently open? */
|
|
97
|
+
function isOverlayOpen() {
|
|
98
|
+
if (typeof document === "undefined") return false;
|
|
99
|
+
return document.body?.getAttribute("data-v2-overlay-open") === "true";
|
|
100
|
+
}
|
|
101
|
+
function useKeyboardShortcuts(shortcuts, {
|
|
102
|
+
enabled = true
|
|
103
|
+
} = {}) {
|
|
104
|
+
/* The descriptor array is rebuilt on every host render (inline literal, in
|
|
105
|
+
* practice), so it is read through a ref instead of being an effect
|
|
106
|
+
* dependency — otherwise the listener detaches and reattaches on each
|
|
107
|
+
* render, and a keystroke could land between the two. */
|
|
108
|
+
const ref = React.useRef(shortcuts);
|
|
109
|
+
React.useEffect(() => {
|
|
110
|
+
ref.current = shortcuts;
|
|
111
|
+
}, [shortcuts]);
|
|
112
|
+
React.useEffect(() => {
|
|
113
|
+
if (!enabled || typeof window === "undefined") return undefined;
|
|
114
|
+
const onKeyDown = e => {
|
|
115
|
+
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
|
116
|
+
if (isBlockingTarget(document.activeElement)) return;
|
|
117
|
+
if (isBlockingTarget(e.target)) return;
|
|
118
|
+
if (isOverlayOpen()) return;
|
|
119
|
+
for (const shortcut of ref.current) {
|
|
120
|
+
if (shortcut.enabled === false) continue;
|
|
121
|
+
if (!shortcut.keys.includes(e.key)) continue;
|
|
122
|
+
e.preventDefault();
|
|
123
|
+
shortcut.onTrigger(e.key);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
window.addEventListener("keydown", onKeyDown);
|
|
128
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
129
|
+
}, [enabled]);
|
|
130
|
+
}
|
|
131
|
+
var _default = exports.default = useKeyboardShortcuts;
|
|
132
|
+
//# sourceMappingURL=useKeyboardShortcuts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useKeyboardShortcuts.js","names":["React","_interopRequireWildcard","require","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","INTERACTIVE_ROLES","Set","EDITABLE_TAGS","isBlockingTarget","node","document","body","Element","tag","tagName","HTMLElement","isContentEditable","role","getAttribute","tabIndex","isOverlayOpen","useKeyboardShortcuts","shortcuts","enabled","ref","useRef","useEffect","current","window","undefined","onKeyDown","metaKey","ctrlKey","altKey","activeElement","target","shortcut","keys","includes","key","preventDefault","onTrigger","addEventListener","removeEventListener","_default","exports"],"sources":["../../../src/lib/v2/hooks/useKeyboardShortcuts.ts"],"sourcesContent":["import * as React from \"react\";\r\n\r\n/**\r\n * useKeyboardShortcuts — Portnet UI v2 (hook)\r\n *\r\n * Raccourcis clavier de page. §Keyboard / R-K.1.\r\n *\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n * WHY THIS BELONGS IN THE LIBRARY (capability gap G-48)\r\n *\r\n * The library already owned BOTH ENDS of page shortcuts and not the listener\r\n * between them:\r\n *\r\n * · `KeyboardShortcutsHelp` — the « ? » dialogue that LISTS the shortcuts;\r\n * · `data-v2-overlay-open` on `<body>` — the signal the library SETS when a\r\n * modal or drawer is open, and which shortcuts must respect.\r\n *\r\n * So a host wiring shortcuts had to write the middle itself, and `ms-ti-fe`\r\n * did: a `keydown` effect plus `isShortcutBlockingTarget` (a set of eleven\r\n * interactive ARIA roles, the tag list, `isContentEditable`, `tabIndex >= 0`)\r\n * plus `isOverlayOpen` reading the library's own attribute back off the body.\r\n * Forty lines of platform behaviour in a listing page.\r\n *\r\n * >>> THE OVERLAY GUARD IS THE REASON THIS CANNOT STAY IN A HOST. The library\r\n * >>> is what SETS `data-v2-overlay-open`; a host reading it is a module\r\n * >>> depending on an implementation detail of the component it renders. If\r\n * >>> that attribute is ever renamed, every host that copied the guard breaks\r\n * >>> SILENTLY — the shortcuts simply start firing behind open modals, which\r\n * >>> nothing tests and nobody notices until a « n » keystroke inside a drawer\r\n * >>> navigates the page away. Owning the listener here means the guard and\r\n * >>> the signal are maintained together. <<<\r\n *\r\n * Raised from `addm-fe` (Area 14), whose listings carry a `searchInputRef`\r\n * declared and passed to `DataGridToolbar` FOR the « / » shortcut — a wire\r\n * waiting for a listener that was never written.\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n *\r\n * WHAT THE HOOK REFUSES TO FIRE ON, and why each case matters:\r\n *\r\n * · A MODIFIER is held (⌘/Ctrl/Alt). « n » is a shortcut; ⌘N is the\r\n * browser's new window, and stealing it is worse than having no shortcut.\r\n * · The target is an EDITABLE element — input, textarea, select,\r\n * contenteditable. Typing « / » in a search box must insert a slash.\r\n * · The target is otherwise INTERACTIVE — a button, a link, anything with an\r\n * interactive ARIA role or a positive tabIndex. `Espace` on a focused\r\n * button activates it; a page shortcut must not pre-empt that.\r\n * · An OVERLAY is open. See the note above.\r\n *\r\n * `<main>` is excluded from the tabIndex test deliberately: a page shell gives\r\n * `<main>` a `tabIndex` so a skip link can reach it, which would otherwise\r\n * disable every shortcut for a user who just used the skip link.\r\n *\r\n * Usage:\r\n *\r\n * useKeyboardShortcuts([\r\n * { keys: [\"/\"], onTrigger: () => searchRef.current?.focus() },\r\n * { keys: [\"n\"], onTrigger: goToCreate, enabled: canCreate },\r\n * { keys: [\"1\", \"2\", \"3\"], onTrigger: (key) => setBucket(BY_KEY[key]) },\r\n * ]);\r\n *\r\n * The host keeps its own `KeyboardShortcutsHelp` list: this hook knows which\r\n * keys DO something, not how to describe them to a user (§9.2 — the business\r\n * wording belongs to the host).\r\n */\r\n\r\n/**\r\n * Roles whose focused element handles its own keys. Kept here rather than in\r\n * a host so the list is maintained once for the fleet.\r\n */\r\nconst INTERACTIVE_ROLES = new Set([\r\n \"button\",\r\n \"link\",\r\n \"tab\",\r\n \"menuitem\",\r\n \"menuitemcheckbox\",\r\n \"menuitemradio\",\r\n \"option\",\r\n \"checkbox\",\r\n \"radio\",\r\n \"combobox\",\r\n \"searchbox\",\r\n \"textbox\",\r\n \"switch\",\r\n \"spinbutton\",\r\n \"slider\",\r\n]);\r\n\r\nconst EDITABLE_TAGS = new Set([\"INPUT\", \"TEXTAREA\", \"SELECT\"]);\r\n\r\nfunction isBlockingTarget(node: EventTarget | null): boolean {\r\n if (!node || node === document.body) return false;\r\n if (!(node instanceof Element)) return false;\r\n\r\n const tag = node.tagName;\r\n if (EDITABLE_TAGS.has(tag)) return true;\r\n if (tag === \"BUTTON\" || tag === \"A\") return true;\r\n\r\n if (node instanceof HTMLElement && node.isContentEditable) return true;\r\n\r\n const role = node.getAttribute(\"role\");\r\n if (role && INTERACTIVE_ROLES.has(role)) return true;\r\n\r\n /* `MAIN` excluded — see the note in the file header on skip links. */\r\n if (node instanceof HTMLElement && node.tabIndex >= 0 && tag !== \"MAIN\") {\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/** Is a library overlay (modal / drawer) currently open? */\r\nfunction isOverlayOpen(): boolean {\r\n if (typeof document === \"undefined\") return false;\r\n return document.body?.getAttribute(\"data-v2-overlay-open\") === \"true\";\r\n}\r\n\r\nexport interface KeyboardShortcut {\r\n /**\r\n * Keys that trigger it, as `KeyboardEvent.key` values — so `\"/\"`, `\"?\"`,\r\n * `\"1\"`, `\"n\"`. Case matters: `\"n\"` does not match `Shift+N`.\r\n */\r\n keys: readonly string[];\r\n /**\r\n * Receives the key that matched, so one descriptor can serve a range\r\n * (`[\"1\",\"2\",\"3\"]` → one handler that reads which was pressed).\r\n */\r\n onTrigger: (key: string) => void;\r\n /**\r\n * @default true — a shortcut gated on a permission stays DECLARED and\r\n * inactive rather than being spliced out of the array, so the descriptor\r\n * list keeps the same shape as the help dialogue's.\r\n */\r\n enabled?: boolean | undefined;\r\n}\r\n\r\nexport interface UseKeyboardShortcutsOptions {\r\n /** Suspends every shortcut at once. @default true */\r\n enabled?: boolean | undefined;\r\n}\r\n\r\nexport function useKeyboardShortcuts(\r\n shortcuts: readonly KeyboardShortcut[],\r\n { enabled = true }: UseKeyboardShortcutsOptions = {}\r\n): void {\r\n /* The descriptor array is rebuilt on every host render (inline literal, in\r\n * practice), so it is read through a ref instead of being an effect\r\n * dependency — otherwise the listener detaches and reattaches on each\r\n * render, and a keystroke could land between the two. */\r\n const ref = React.useRef(shortcuts);\r\n React.useEffect(() => {\r\n ref.current = shortcuts;\r\n }, [shortcuts]);\r\n\r\n React.useEffect(() => {\r\n if (!enabled || typeof window === \"undefined\") return undefined;\r\n\r\n const onKeyDown = (e: KeyboardEvent): void => {\r\n if (e.metaKey || e.ctrlKey || e.altKey) return;\r\n if (isBlockingTarget(document.activeElement)) return;\r\n if (isBlockingTarget(e.target)) return;\r\n if (isOverlayOpen()) return;\r\n\r\n for (const shortcut of ref.current) {\r\n if (shortcut.enabled === false) continue;\r\n if (!shortcut.keys.includes(e.key)) continue;\r\n e.preventDefault();\r\n shortcut.onTrigger(e.key);\r\n return;\r\n }\r\n };\r\n\r\n window.addEventListener(\"keydown\", onKeyDown);\r\n return () => window.removeEventListener(\"keydown\", onKeyDown);\r\n }, [enabled]);\r\n}\r\n\r\nexport default useKeyboardShortcuts;\r\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* usePrefersReducedMotion — Portnet UI v2
|
|
3
|
+
*
|
|
4
|
+
* `true` when the user has asked the system to reduce motion.
|
|
5
|
+
*
|
|
6
|
+
* const reduced = usePrefersReducedMotion();
|
|
7
|
+
* const options = { chart: { animation: !reduced } };
|
|
8
|
+
*
|
|
9
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
10
|
+
* WHY THIS BELONGS IN THE LIBRARY (capability gap G-49)
|
|
11
|
+
*
|
|
12
|
+
* R-7.5 / R-Tg.2 MUST: `prefers-reduced-motion` is respected — animations
|
|
13
|
+
* ≤ 0.01 ms or none. The library already honours the rule everywhere IT owns
|
|
14
|
+
* the animation: `motion.ts` documents it, the base stylesheet carries the
|
|
15
|
+
* media query, `Skeleton` drops its shimmer (R-Sk.4).
|
|
16
|
+
*
|
|
17
|
+
* What was missing is the RUNTIME READ. A host that animates something the
|
|
18
|
+
* library does not own — a chart, a canvas, an imperative scroll, a
|
|
19
|
+
* third-party widget configured in JS — cannot reach the preference through
|
|
20
|
+
* CSS, because the decision is a JS value handed to another library. Every
|
|
21
|
+
* such host wrote the same helper, and every copy observed so far carried the
|
|
22
|
+
* SAME TWO DEFECTS:
|
|
23
|
+
*
|
|
24
|
+
* const prefersReducedMotion = (): boolean =>
|
|
25
|
+
* typeof window !== "undefined" &&
|
|
26
|
+
* typeof window.matchMedia === "function" &&
|
|
27
|
+
* window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
28
|
+
*
|
|
29
|
+
* 1. IT DOES NOT SUBSCRIBE. `matchMedia(...).matches` is read once, during a
|
|
30
|
+
* render that may never happen again. A user who turns the preference ON
|
|
31
|
+
* — which is exactly what someone does when motion starts to hurt — keeps
|
|
32
|
+
* the animations until something unrelated re-renders the screen. The
|
|
33
|
+
* rule is written in the present tense; a snapshot satisfies it by luck.
|
|
34
|
+
* 2. IT IS READ DURING RENDER, so the value is not part of React's state at
|
|
35
|
+
* all: two components on one page can disagree, and nothing reconciles
|
|
36
|
+
* them.
|
|
37
|
+
*
|
|
38
|
+
* `useSyncExternalStore` fixes both at once, and is the primitive React
|
|
39
|
+
* publishes for precisely this shape — an external, subscribable source of
|
|
40
|
+
* truth. It also supplies a correct server snapshot instead of a
|
|
41
|
+
* `typeof window` guard copied into every call site.
|
|
42
|
+
*
|
|
43
|
+
* Relevé depuis `autorisation-admis-pour-conforme-fe` (Area 4 — détection
|
|
44
|
+
* d'infrastructure UI locale), où le helper ci-dessus existait en TROIS copies
|
|
45
|
+
* identiques, une par écran de bilan, chacune appelée depuis un `useMemo` ou
|
|
46
|
+
* depuis une fabrique d'options au niveau module.
|
|
47
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
48
|
+
*
|
|
49
|
+
* REDUCED MOTION IS NOT AN ACCESSIBILITY CERTIFICATE. A chart that stops
|
|
50
|
+
* animating is still a chart that owes a text equivalent (WCAG 1.1.1), and a
|
|
51
|
+
* transition under 200 ms still owes R-Mi.1 its justification.
|
|
52
|
+
*/
|
|
53
|
+
/** The media query, exported so a consumer can assert on it in a test. */
|
|
54
|
+
export declare const PREFERS_REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
55
|
+
export default function usePrefersReducedMotion(): boolean;
|
|
56
|
+
//# sourceMappingURL=usePrefersReducedMotion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePrefersReducedMotion.d.ts","sourceRoot":"","sources":["../../../src/lib/v2/hooks/usePrefersReducedMotion.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,0EAA0E;AAC1E,eAAO,MAAM,4BAA4B,qCAAqC,CAAC;AA2C/E,MAAM,CAAC,OAAO,UAAU,uBAAuB,IAAI,OAAO,CAEzD"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.PREFERS_REDUCED_MOTION_QUERY = void 0;
|
|
7
|
+
exports.default = usePrefersReducedMotion;
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
/**
|
|
10
|
+
* usePrefersReducedMotion — Portnet UI v2
|
|
11
|
+
*
|
|
12
|
+
* `true` when the user has asked the system to reduce motion.
|
|
13
|
+
*
|
|
14
|
+
* const reduced = usePrefersReducedMotion();
|
|
15
|
+
* const options = { chart: { animation: !reduced } };
|
|
16
|
+
*
|
|
17
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
+
* WHY THIS BELONGS IN THE LIBRARY (capability gap G-49)
|
|
19
|
+
*
|
|
20
|
+
* R-7.5 / R-Tg.2 MUST: `prefers-reduced-motion` is respected — animations
|
|
21
|
+
* ≤ 0.01 ms or none. The library already honours the rule everywhere IT owns
|
|
22
|
+
* the animation: `motion.ts` documents it, the base stylesheet carries the
|
|
23
|
+
* media query, `Skeleton` drops its shimmer (R-Sk.4).
|
|
24
|
+
*
|
|
25
|
+
* What was missing is the RUNTIME READ. A host that animates something the
|
|
26
|
+
* library does not own — a chart, a canvas, an imperative scroll, a
|
|
27
|
+
* third-party widget configured in JS — cannot reach the preference through
|
|
28
|
+
* CSS, because the decision is a JS value handed to another library. Every
|
|
29
|
+
* such host wrote the same helper, and every copy observed so far carried the
|
|
30
|
+
* SAME TWO DEFECTS:
|
|
31
|
+
*
|
|
32
|
+
* const prefersReducedMotion = (): boolean =>
|
|
33
|
+
* typeof window !== "undefined" &&
|
|
34
|
+
* typeof window.matchMedia === "function" &&
|
|
35
|
+
* window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
36
|
+
*
|
|
37
|
+
* 1. IT DOES NOT SUBSCRIBE. `matchMedia(...).matches` is read once, during a
|
|
38
|
+
* render that may never happen again. A user who turns the preference ON
|
|
39
|
+
* — which is exactly what someone does when motion starts to hurt — keeps
|
|
40
|
+
* the animations until something unrelated re-renders the screen. The
|
|
41
|
+
* rule is written in the present tense; a snapshot satisfies it by luck.
|
|
42
|
+
* 2. IT IS READ DURING RENDER, so the value is not part of React's state at
|
|
43
|
+
* all: two components on one page can disagree, and nothing reconciles
|
|
44
|
+
* them.
|
|
45
|
+
*
|
|
46
|
+
* `useSyncExternalStore` fixes both at once, and is the primitive React
|
|
47
|
+
* publishes for precisely this shape — an external, subscribable source of
|
|
48
|
+
* truth. It also supplies a correct server snapshot instead of a
|
|
49
|
+
* `typeof window` guard copied into every call site.
|
|
50
|
+
*
|
|
51
|
+
* Relevé depuis `autorisation-admis-pour-conforme-fe` (Area 4 — détection
|
|
52
|
+
* d'infrastructure UI locale), où le helper ci-dessus existait en TROIS copies
|
|
53
|
+
* identiques, une par écran de bilan, chacune appelée depuis un `useMemo` ou
|
|
54
|
+
* depuis une fabrique d'options au niveau module.
|
|
55
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
56
|
+
*
|
|
57
|
+
* REDUCED MOTION IS NOT AN ACCESSIBILITY CERTIFICATE. A chart that stops
|
|
58
|
+
* animating is still a chart that owes a text equivalent (WCAG 1.1.1), and a
|
|
59
|
+
* transition under 200 ms still owes R-Mi.1 its justification.
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
/** The media query, exported so a consumer can assert on it in a test. */
|
|
63
|
+
const PREFERS_REDUCED_MOTION_QUERY = exports.PREFERS_REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* `null` in any environment without `matchMedia` — server rendering, and the
|
|
67
|
+
* older jsdom versions where the method is simply absent. Callers treat that
|
|
68
|
+
* as "no stated preference", the same default the CSS media query has.
|
|
69
|
+
*/
|
|
70
|
+
function getMediaQueryList() {
|
|
71
|
+
if (typeof window === "undefined") return null;
|
|
72
|
+
if (typeof window.matchMedia !== "function") return null;
|
|
73
|
+
return window.matchMedia(PREFERS_REDUCED_MOTION_QUERY);
|
|
74
|
+
}
|
|
75
|
+
function subscribe(onStoreChange) {
|
|
76
|
+
const mql = getMediaQueryList();
|
|
77
|
+
if (mql === null) return () => undefined;
|
|
78
|
+
|
|
79
|
+
/* Safari 13 / iOS 12 ship `addListener` but not `addEventListener` on
|
|
80
|
+
* MediaQueryList. Both paths are kept: the browserslist floor is Safari 17,
|
|
81
|
+
* but this hook is also what a host reaches for inside a webview it does not
|
|
82
|
+
* choose, and the fallback costs two lines. */
|
|
83
|
+
if (typeof mql.addEventListener === "function") {
|
|
84
|
+
mql.addEventListener("change", onStoreChange);
|
|
85
|
+
return () => mql.removeEventListener("change", onStoreChange);
|
|
86
|
+
}
|
|
87
|
+
mql.addListener(onStoreChange);
|
|
88
|
+
return () => mql.removeListener(onStoreChange);
|
|
89
|
+
}
|
|
90
|
+
function getSnapshot() {
|
|
91
|
+
return getMediaQueryList()?.matches ?? false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Server snapshot — `false`, and NOT the client default in disguise: a server
|
|
96
|
+
* has no user preference to read, and hydration corrects the value before
|
|
97
|
+
* paint, so nothing animates against the user's wish.
|
|
98
|
+
*/
|
|
99
|
+
function getServerSnapshot() {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
function usePrefersReducedMotion() {
|
|
103
|
+
return (0, _react.useSyncExternalStore)(subscribe, getSnapshot, getServerSnapshot);
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=usePrefersReducedMotion.js.map
|