@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAppliedFilters.js","names":["_react","require","useAppliedFilters","form","options","appliedFilters","setAppliedFilters","useState","empty","emptyValueFor","apply","values","onApply","resetAll","onReset","removeCriteria","keys","forEach","key","setFieldValue","remaining","onRemove","setApplied"],"sources":["../../../src/lib/v2/hooks/useAppliedFilters.ts"],"sourcesContent":["import { useState } from \"react\";\r\n\r\n/**\r\n * useAppliedFilters — tracks the criteria ACTUALLY applied to a listing\r\n * (capability gap G-43).\r\n *\r\n * Companion to `buildFilterChips`: that one builds the chips, this one decides\r\n * what they are allowed to show.\r\n *\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n * THE DEFECT IT PREVENTS — AND IT WAS SHIPPED TWICE BEFORE BEING UNDERSTOOD\r\n *\r\n * Chips CANNOT be built from live form values. `DataGridToolbar`'s search input\r\n * writes into them ON EVERY KEYSTROKE, so a chip \"Référence : ABC\" appears\r\n * while the user is still typing — announcing an active criterion that filters\r\n * nothing. Active criteria are the ones filtering the DISPLAYED list.\r\n *\r\n * Two distinct states are therefore required, and the split is counter-intuitive\r\n * enough that it was got wrong twice: form values track TYPING, this snapshot\r\n * tracks APPLICATION.\r\n *\r\n * The mirror-image defect is just as real: a snapshot left full after a \"clear\r\n * criteria\" shows chips for criteria that no longer filter anything. Both\r\n * failures are one forgotten line away, in opposite directions — which is the\r\n * argument for one hook rather than three lines per screen.\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n *\r\n * IT BUILDS NO PAYLOAD. Every screen has its own — key names, scope flags, page\r\n * value — and `onRemove` hands the turn back with the REMAINING criteria. This\r\n * hook knows only the cycle typing → application → removal.\r\n *\r\n * `setApplied`: THE THREE PATHS THAT BYPASS `apply()`. The snapshot is not only\r\n * filled by a click on \"Search\". Three other gestures change what actually\r\n * filters the list, and each one used to leave the chips lying:\r\n *\r\n * 1. RESTORING A SAVED FILTER. `SavedFiltersMenu` re-injects values and\r\n * payload: the list is filtered, the snapshot stays empty, so NO chip\r\n * appears. Observed on a real screen before this existed.\r\n * 2. CLICKING A STATUS CHIP. Screens with `FilterTab` write the payload\r\n * directly — on purpose, to avoid the async `setFieldValue` followed by a\r\n * submit that reads the previous render's values. Without updating the\r\n * snapshot, a later chip removal rebuilds the payload from a stale\r\n * snapshot and LOSES the active status.\r\n * 3. Any other direct payload write by the screen.\r\n *\r\n * Hence a function that SETS the snapshot, distinct from the one that freezes it\r\n * from the form. The screen alone knows when what-filters has changed; the hook\r\n * cannot guess it.\r\n *\r\n * Promoted from `refonte-frontend` (Area 5), where three listings consumed it.\r\n *\r\n * WHAT WAS NOT PROMOTED WITH IT. The original exported a ready-made\r\n * `videAvecMiroirsNumeriques` helper — \"id mirrors clear to `0`, everything\r\n * else to `\"\"`\" — and a measurement of its call sites found NONE: the three\r\n * hosts each passed their own inline strategy, and they disagree (`0` / `null`\r\n * / `\"\"`, per field). Codifying one of the three as the library's convention\r\n * would have blessed a rule no host follows, and the disagreement is exactly\r\n * why `emptyValueFor` is a parameter rather than a constant.\r\n */\r\n\r\n/** What a search form must expose to this hook — Formik satisfies it. */\r\nexport interface AppliedFiltersForm {\r\n values: Record<string, unknown>;\r\n setFieldValue: (\r\n field: string,\r\n value: unknown,\r\n shouldValidate?: boolean\r\n ) => unknown;\r\n}\r\n\r\nexport interface UseAppliedFiltersOptions {\r\n /** Applies the current search (the screen's existing function). */\r\n onApply: () => void;\r\n /** Resets the search (the screen's existing function). */\r\n onReset: () => void;\r\n /**\r\n * Rebuilds and re-runs the payload after a removal, from the REMAINING\r\n * criteria. Only the screen knows the shape of its payload.\r\n */\r\n onRemove: (remaining: Record<string, unknown>) => void;\r\n /**\r\n * The value that means \"empty\" for a given field. Hosts disagree, and the\r\n * disagreement is legitimate: some clear to `null`, others to `\"\"`, and\r\n * reference-id mirrors to `0`. A convention imposed here would have broken\r\n * half the payloads. @default `null`\r\n */\r\n emptyValueFor?: ((key: string) => unknown) | undefined;\r\n}\r\n\r\n/**\r\n * Explicit return type: §Hooks requires it (\"Every hook must expose explicit\r\n * return types\"), and inference left this surface implicit while four screens\r\n * consumed it.\r\n */\r\nexport interface UseAppliedFiltersResult {\r\n /** Criteria ACTUALLY applied to the displayed list. */\r\n appliedFilters: Record<string, unknown>;\r\n /** Freezes the snapshot from the form, then runs the screen's search. */\r\n apply: () => void;\r\n /** Clears the snapshot, then resets the screen. */\r\n resetAll: () => void;\r\n /** Removes one or more criteria and hands the turn back to `onRemove`. */\r\n removeCriteria: (keys: string[]) => void;\r\n /**\r\n * Sets the snapshot from values SUPPLIED by the screen, for the three paths\r\n * that bypass `apply` — see the note above.\r\n */\r\n setApplied: (values: Record<string, unknown>) => void;\r\n}\r\n\r\nexport default function useAppliedFilters(\r\n form: AppliedFiltersForm,\r\n options: UseAppliedFiltersOptions\r\n): UseAppliedFiltersResult {\r\n const [appliedFilters, setAppliedFilters] = useState<Record<string, unknown>>(\r\n {}\r\n );\r\n\r\n const empty = options.emptyValueFor ?? (() => null);\r\n\r\n return {\r\n appliedFilters,\r\n\r\n apply: () => {\r\n setAppliedFilters({ ...form.values });\r\n options.onApply();\r\n },\r\n\r\n resetAll: () => {\r\n setAppliedFilters({});\r\n options.onReset();\r\n },\r\n\r\n /**\r\n * Clears the fields and the snapshot, then hands the turn back so the\r\n * screen can rebuild its payload.\r\n *\r\n * The payload is rebuilt from the AMPUTATED SNAPSHOT, never re-read from\r\n * the form afterwards: `setFieldValue` is asynchronous, so reading values\r\n * back would give the criteria as they were BEFORE the removal.\r\n */\r\n removeCriteria: (keys: string[]) => {\r\n keys.forEach((key) => {\r\n void form.setFieldValue(key, empty(key));\r\n });\r\n const remaining: Record<string, unknown> = { ...appliedFilters };\r\n keys.forEach((key) => {\r\n remaining[key] = empty(key);\r\n });\r\n setAppliedFilters(remaining);\r\n options.onRemove(remaining);\r\n },\r\n\r\n setApplied: (values: Record<string, unknown>) => {\r\n setAppliedFilters({ ...values });\r\n },\r\n };\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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AA6BA;AACA;AACA;AACA;AACA;;AAiBe,SAASC,iBAAiBA,CACvCC,IAAwB,EACxBC,OAAiC,EACR;EACzB,MAAM,CAACC,cAAc,EAAEC,iBAAiB,CAAC,GAAG,IAAAC,eAAQ,EAClD,CAAC,CACH,CAAC;EAED,MAAMC,KAAK,GAAGJ,OAAO,CAACK,aAAa,KAAK,MAAM,IAAI,CAAC;EAEnD,OAAO;IACLJ,cAAc;IAEdK,KAAK,EAAEA,CAAA,KAAM;MACXJ,iBAAiB,CAAC;QAAE,GAAGH,IAAI,CAACQ;MAAO,CAAC,CAAC;MACrCP,OAAO,CAACQ,OAAO,CAAC,CAAC;IACnB,CAAC;IAEDC,QAAQ,EAAEA,CAAA,KAAM;MACdP,iBAAiB,CAAC,CAAC,CAAC,CAAC;MACrBF,OAAO,CAACU,OAAO,CAAC,CAAC;IACnB,CAAC;IAED;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;IACIC,cAAc,EAAGC,IAAc,IAAK;MAClCA,IAAI,CAACC,OAAO,CAAEC,GAAG,IAAK;QACpB,KAAKf,IAAI,CAACgB,aAAa,CAACD,GAAG,EAAEV,KAAK,CAACU,GAAG,CAAC,CAAC;MAC1C,CAAC,CAAC;MACF,MAAME,SAAkC,GAAG;QAAE,GAAGf;MAAe,CAAC;MAChEW,IAAI,CAACC,OAAO,CAAEC,GAAG,IAAK;QACpBE,SAAS,CAACF,GAAG,CAAC,GAAGV,KAAK,CAACU,GAAG,CAAC;MAC7B,CAAC,CAAC;MACFZ,iBAAiB,CAACc,SAAS,CAAC;MAC5BhB,OAAO,CAACiB,QAAQ,CAACD,SAAS,CAAC;IAC7B,CAAC;IAEDE,UAAU,EAAGX,MAA+B,IAAK;MAC/CL,iBAAiB,CAAC;QAAE,GAAGK;MAAO,CAAC,CAAC;IAClC;EACF,CAAC;AACH","ignoreList":[]}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useDebouncedCallback — defer a call until the input settles
|
|
3
|
+
* (capability gap G-39).
|
|
4
|
+
*
|
|
5
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
6
|
+
* WHY THIS BELONGS IN THE LIBRARY
|
|
7
|
+
*
|
|
8
|
+
* §Search of the Platform Mandatory UX Patterns makes "instant filtering" a
|
|
9
|
+
* MUST on every listing, and R-Pp/§Performance forbid paying for it with a
|
|
10
|
+
* request per keystroke. Between those two rules sits a debounce — needed by
|
|
11
|
+
* every search field, every referential lookup, every quick-filter in the
|
|
12
|
+
* fleet — and the library shipped `useDelayedFlag` (a boolean that turns on
|
|
13
|
+
* after a delay) and `useTabLoading`, neither of which defers a CALL.
|
|
14
|
+
*
|
|
15
|
+
* So each host reached for `lodash.debounce`, and the three defects that
|
|
16
|
+
* followed were the same everywhere. Promoted from `refonte-frontend` (Area 5),
|
|
17
|
+
* where its own header recorded them:
|
|
18
|
+
*
|
|
19
|
+
* 1. NO TYPES on the package (TS7016), whose two usual workarounds are both
|
|
20
|
+
* forbidden here — an extra dependency for ten lines, or a
|
|
21
|
+
* `declare module` that makes the import `any`.
|
|
22
|
+
* 2. THE DEBOUNCE DID NOT DEBOUNCE. `debounce(...)` was called in the render
|
|
23
|
+
* body, so every keystroke built a NEW instance with its own timer; the
|
|
24
|
+
* previous one was orphaned but still fired. The result was not
|
|
25
|
+
* coalescing — it was a delay applied to every character, i.e. one
|
|
26
|
+
* request per keystroke, arriving late.
|
|
27
|
+
* 3. NOTHING CANCELLED THE TIMER ON UNMOUNT, so switching tab produced a
|
|
28
|
+
* `setState` on an unmounted component.
|
|
29
|
+
*
|
|
30
|
+
* >>> DEFECT 2 IS WHY THIS IS A LIBRARY CONCERN AND NOT A SNIPPET. It is
|
|
31
|
+
* >>> invisible in review — the call site reads exactly like a correct one —
|
|
32
|
+
* >>> and invisible in use, because the feature still works. Only the network
|
|
33
|
+
* >>> panel shows it. A hook cannot be misused that way: the identity below is
|
|
34
|
+
* >>> stable by construction, so there is no per-render instance to orphan. <<<
|
|
35
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
36
|
+
*
|
|
37
|
+
* WHY `action` GOES THROUGH A REF. Callers naturally pass an inline arrow
|
|
38
|
+
* (`(v) => { setPage(0); setSearch(v); }`), so its identity is new on every
|
|
39
|
+
* render. Holding it in a ref keeps the returned trigger STABLE — without
|
|
40
|
+
* which the trigger would change every render and defect 2 would be back, one
|
|
41
|
+
* level up — while still invoking the LATEST action rather than a stale
|
|
42
|
+
* closure.
|
|
43
|
+
*
|
|
44
|
+
* Only `delay` is a dependency of the returned callback. Changing it mid-flight
|
|
45
|
+
* does not reschedule a pending call; the next trigger uses the new delay.
|
|
46
|
+
*
|
|
47
|
+
* Usage:
|
|
48
|
+
*
|
|
49
|
+
* const onSearchChange = useDebouncedCallback<string>((value) => {
|
|
50
|
+
* setPage(0);
|
|
51
|
+
* dispatch(search(value));
|
|
52
|
+
* });
|
|
53
|
+
* <Input onChange={(e) => onSearchChange(e.target.value)} />
|
|
54
|
+
*
|
|
55
|
+
* @param action what to do once the input has settled
|
|
56
|
+
* @param delay milliseconds. Defaults to 500 — the value the promoted
|
|
57
|
+
* implementation already shipped, kept deliberately: every
|
|
58
|
+
* existing call site relies on the default, and lowering it here
|
|
59
|
+
* would silently increase the request rate of nine listings
|
|
60
|
+
* while looking like a tidy-up. R-1.1's 100 ms feedback promise
|
|
61
|
+
* is met by the field's own visual state, not by this call.
|
|
62
|
+
*/
|
|
63
|
+
export default function useDebouncedCallback<T>(action: (value: T) => void, delay?: number): (value: T) => void;
|
|
64
|
+
//# sourceMappingURL=useDebouncedCallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDebouncedCallback.d.ts","sourceRoot":"","sources":["../../../src/lib/v2/hooks/useDebouncedCallback.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,CAAC,EAC5C,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,EAC1B,KAAK,SAAM,GACV,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAyBpB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = useDebouncedCallback;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
/**
|
|
9
|
+
* useDebouncedCallback — defer a call until the input settles
|
|
10
|
+
* (capability gap G-39).
|
|
11
|
+
*
|
|
12
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
13
|
+
* WHY THIS BELONGS IN THE LIBRARY
|
|
14
|
+
*
|
|
15
|
+
* §Search of the Platform Mandatory UX Patterns makes "instant filtering" a
|
|
16
|
+
* MUST on every listing, and R-Pp/§Performance forbid paying for it with a
|
|
17
|
+
* request per keystroke. Between those two rules sits a debounce — needed by
|
|
18
|
+
* every search field, every referential lookup, every quick-filter in the
|
|
19
|
+
* fleet — and the library shipped `useDelayedFlag` (a boolean that turns on
|
|
20
|
+
* after a delay) and `useTabLoading`, neither of which defers a CALL.
|
|
21
|
+
*
|
|
22
|
+
* So each host reached for `lodash.debounce`, and the three defects that
|
|
23
|
+
* followed were the same everywhere. Promoted from `refonte-frontend` (Area 5),
|
|
24
|
+
* where its own header recorded them:
|
|
25
|
+
*
|
|
26
|
+
* 1. NO TYPES on the package (TS7016), whose two usual workarounds are both
|
|
27
|
+
* forbidden here — an extra dependency for ten lines, or a
|
|
28
|
+
* `declare module` that makes the import `any`.
|
|
29
|
+
* 2. THE DEBOUNCE DID NOT DEBOUNCE. `debounce(...)` was called in the render
|
|
30
|
+
* body, so every keystroke built a NEW instance with its own timer; the
|
|
31
|
+
* previous one was orphaned but still fired. The result was not
|
|
32
|
+
* coalescing — it was a delay applied to every character, i.e. one
|
|
33
|
+
* request per keystroke, arriving late.
|
|
34
|
+
* 3. NOTHING CANCELLED THE TIMER ON UNMOUNT, so switching tab produced a
|
|
35
|
+
* `setState` on an unmounted component.
|
|
36
|
+
*
|
|
37
|
+
* >>> DEFECT 2 IS WHY THIS IS A LIBRARY CONCERN AND NOT A SNIPPET. It is
|
|
38
|
+
* >>> invisible in review — the call site reads exactly like a correct one —
|
|
39
|
+
* >>> and invisible in use, because the feature still works. Only the network
|
|
40
|
+
* >>> panel shows it. A hook cannot be misused that way: the identity below is
|
|
41
|
+
* >>> stable by construction, so there is no per-render instance to orphan. <<<
|
|
42
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
43
|
+
*
|
|
44
|
+
* WHY `action` GOES THROUGH A REF. Callers naturally pass an inline arrow
|
|
45
|
+
* (`(v) => { setPage(0); setSearch(v); }`), so its identity is new on every
|
|
46
|
+
* render. Holding it in a ref keeps the returned trigger STABLE — without
|
|
47
|
+
* which the trigger would change every render and defect 2 would be back, one
|
|
48
|
+
* level up — while still invoking the LATEST action rather than a stale
|
|
49
|
+
* closure.
|
|
50
|
+
*
|
|
51
|
+
* Only `delay` is a dependency of the returned callback. Changing it mid-flight
|
|
52
|
+
* does not reschedule a pending call; the next trigger uses the new delay.
|
|
53
|
+
*
|
|
54
|
+
* Usage:
|
|
55
|
+
*
|
|
56
|
+
* const onSearchChange = useDebouncedCallback<string>((value) => {
|
|
57
|
+
* setPage(0);
|
|
58
|
+
* dispatch(search(value));
|
|
59
|
+
* });
|
|
60
|
+
* <Input onChange={(e) => onSearchChange(e.target.value)} />
|
|
61
|
+
*
|
|
62
|
+
* @param action what to do once the input has settled
|
|
63
|
+
* @param delay milliseconds. Defaults to 500 — the value the promoted
|
|
64
|
+
* implementation already shipped, kept deliberately: every
|
|
65
|
+
* existing call site relies on the default, and lowering it here
|
|
66
|
+
* would silently increase the request rate of nine listings
|
|
67
|
+
* while looking like a tidy-up. R-1.1's 100 ms feedback promise
|
|
68
|
+
* is met by the field's own visual state, not by this call.
|
|
69
|
+
*/
|
|
70
|
+
function useDebouncedCallback(action, delay = 500) {
|
|
71
|
+
const actionRef = (0, _react.useRef)(action);
|
|
72
|
+
const timer = (0, _react.useRef)(null);
|
|
73
|
+
(0, _react.useEffect)(() => {
|
|
74
|
+
actionRef.current = action;
|
|
75
|
+
}, [action]);
|
|
76
|
+
(0, _react.useEffect)(() => () => {
|
|
77
|
+
if (timer.current !== null) clearTimeout(timer.current);
|
|
78
|
+
}, []);
|
|
79
|
+
return (0, _react.useCallback)(value => {
|
|
80
|
+
if (timer.current !== null) clearTimeout(timer.current);
|
|
81
|
+
timer.current = setTimeout(() => {
|
|
82
|
+
timer.current = null;
|
|
83
|
+
actionRef.current(value);
|
|
84
|
+
}, delay);
|
|
85
|
+
}, [delay]);
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=useDebouncedCallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDebouncedCallback.js","names":["_react","require","useDebouncedCallback","action","delay","actionRef","useRef","timer","useEffect","current","clearTimeout","useCallback","value","setTimeout"],"sources":["../../../src/lib/v2/hooks/useDebouncedCallback.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from \"react\";\r\n\r\n/**\r\n * useDebouncedCallback — defer a call until the input settles\r\n * (capability gap G-39).\r\n *\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n * WHY THIS BELONGS IN THE LIBRARY\r\n *\r\n * §Search of the Platform Mandatory UX Patterns makes \"instant filtering\" a\r\n * MUST on every listing, and R-Pp/§Performance forbid paying for it with a\r\n * request per keystroke. Between those two rules sits a debounce — needed by\r\n * every search field, every referential lookup, every quick-filter in the\r\n * fleet — and the library shipped `useDelayedFlag` (a boolean that turns on\r\n * after a delay) and `useTabLoading`, neither of which defers a CALL.\r\n *\r\n * So each host reached for `lodash.debounce`, and the three defects that\r\n * followed were the same everywhere. Promoted from `refonte-frontend` (Area 5),\r\n * where its own header recorded them:\r\n *\r\n * 1. NO TYPES on the package (TS7016), whose two usual workarounds are both\r\n * forbidden here — an extra dependency for ten lines, or a\r\n * `declare module` that makes the import `any`.\r\n * 2. THE DEBOUNCE DID NOT DEBOUNCE. `debounce(...)` was called in the render\r\n * body, so every keystroke built a NEW instance with its own timer; the\r\n * previous one was orphaned but still fired. The result was not\r\n * coalescing — it was a delay applied to every character, i.e. one\r\n * request per keystroke, arriving late.\r\n * 3. NOTHING CANCELLED THE TIMER ON UNMOUNT, so switching tab produced a\r\n * `setState` on an unmounted component.\r\n *\r\n * >>> DEFECT 2 IS WHY THIS IS A LIBRARY CONCERN AND NOT A SNIPPET. It is\r\n * >>> invisible in review — the call site reads exactly like a correct one —\r\n * >>> and invisible in use, because the feature still works. Only the network\r\n * >>> panel shows it. A hook cannot be misused that way: the identity below is\r\n * >>> stable by construction, so there is no per-render instance to orphan. <<<\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n *\r\n * WHY `action` GOES THROUGH A REF. Callers naturally pass an inline arrow\r\n * (`(v) => { setPage(0); setSearch(v); }`), so its identity is new on every\r\n * render. Holding it in a ref keeps the returned trigger STABLE — without\r\n * which the trigger would change every render and defect 2 would be back, one\r\n * level up — while still invoking the LATEST action rather than a stale\r\n * closure.\r\n *\r\n * Only `delay` is a dependency of the returned callback. Changing it mid-flight\r\n * does not reschedule a pending call; the next trigger uses the new delay.\r\n *\r\n * Usage:\r\n *\r\n * const onSearchChange = useDebouncedCallback<string>((value) => {\r\n * setPage(0);\r\n * dispatch(search(value));\r\n * });\r\n * <Input onChange={(e) => onSearchChange(e.target.value)} />\r\n *\r\n * @param action what to do once the input has settled\r\n * @param delay milliseconds. Defaults to 500 — the value the promoted\r\n * implementation already shipped, kept deliberately: every\r\n * existing call site relies on the default, and lowering it here\r\n * would silently increase the request rate of nine listings\r\n * while looking like a tidy-up. R-1.1's 100 ms feedback promise\r\n * is met by the field's own visual state, not by this call.\r\n */\r\nexport default function useDebouncedCallback<T>(\r\n action: (value: T) => void,\r\n delay = 500\r\n): (value: T) => void {\r\n const actionRef = useRef(action);\r\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n\r\n useEffect(() => {\r\n actionRef.current = action;\r\n }, [action]);\r\n\r\n useEffect(\r\n () => () => {\r\n if (timer.current !== null) clearTimeout(timer.current);\r\n },\r\n []\r\n );\r\n\r\n return useCallback(\r\n (value: T) => {\r\n if (timer.current !== null) clearTimeout(timer.current);\r\n timer.current = setTimeout(() => {\r\n timer.current = null;\r\n actionRef.current(value);\r\n }, delay);\r\n },\r\n [delay]\r\n );\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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASC,oBAAoBA,CAC1CC,MAA0B,EAC1BC,KAAK,GAAG,GAAG,EACS;EACpB,MAAMC,SAAS,GAAG,IAAAC,aAAM,EAACH,MAAM,CAAC;EAChC,MAAMI,KAAK,GAAG,IAAAD,aAAM,EAAuC,IAAI,CAAC;EAEhE,IAAAE,gBAAS,EAAC,MAAM;IACdH,SAAS,CAACI,OAAO,GAAGN,MAAM;EAC5B,CAAC,EAAE,CAACA,MAAM,CAAC,CAAC;EAEZ,IAAAK,gBAAS,EACP,MAAM,MAAM;IACV,IAAID,KAAK,CAACE,OAAO,KAAK,IAAI,EAAEC,YAAY,CAACH,KAAK,CAACE,OAAO,CAAC;EACzD,CAAC,EACD,EACF,CAAC;EAED,OAAO,IAAAE,kBAAW,EACfC,KAAQ,IAAK;IACZ,IAAIL,KAAK,CAACE,OAAO,KAAK,IAAI,EAAEC,YAAY,CAACH,KAAK,CAACE,OAAO,CAAC;IACvDF,KAAK,CAACE,OAAO,GAAGI,UAAU,CAAC,MAAM;MAC/BN,KAAK,CAACE,OAAO,GAAG,IAAI;MACpBJ,SAAS,CAACI,OAAO,CAACG,KAAK,CAAC;IAC1B,CAAC,EAAER,KAAK,CAAC;EACX,CAAC,EACD,CAACA,KAAK,CACR,CAAC;AACH","ignoreList":[]}
|
|
@@ -3,15 +3,9 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports
|
|
6
|
+
exports.default = useDelayedFlag;
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
var _useTabLoading = require("./useTabLoading");
|
|
9
|
-
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
10
|
-
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
11
|
-
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); }
|
|
12
|
-
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; }
|
|
13
|
-
function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0) { ; } } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
|
|
14
|
-
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
15
9
|
/**
|
|
16
10
|
* useDelayedFlag — Portnet UI v2
|
|
17
11
|
*
|
|
@@ -32,13 +26,9 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
|
32
26
|
* (preserves across tab swap to avoid flicker between two
|
|
33
27
|
* consecutive skeletons), use `useTabLoading`.
|
|
34
28
|
*/
|
|
35
|
-
function useDelayedFlag(active) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
_useState2 = _slicedToArray(_useState, 2),
|
|
39
|
-
delayed = _useState2[0],
|
|
40
|
-
setDelayed = _useState2[1];
|
|
41
|
-
(0, _react.useEffect)(function () {
|
|
29
|
+
function useDelayedFlag(active, delayMs = _useTabLoading.PERCEPTION_THRESHOLD_MS) {
|
|
30
|
+
const [delayed, setDelayed] = (0, _react.useState)(false);
|
|
31
|
+
(0, _react.useEffect)(() => {
|
|
42
32
|
if (!active) {
|
|
43
33
|
// Inactive — drop any in-flight delayed flag immediately so
|
|
44
34
|
// the consumer can render the success path without waiting.
|
|
@@ -48,12 +38,8 @@ function useDelayedFlag(active) {
|
|
|
48
38
|
// Schedule the flag flip. If `active` resolves false before the
|
|
49
39
|
// timer fires, cleanup clears the timer and the flag never goes
|
|
50
40
|
// true (the perception-threshold contract).
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}, delayMs);
|
|
54
|
-
return function () {
|
|
55
|
-
return clearTimeout(t);
|
|
56
|
-
};
|
|
41
|
+
const t = setTimeout(() => setDelayed(true), delayMs);
|
|
42
|
+
return () => clearTimeout(t);
|
|
57
43
|
}, [active, delayMs]);
|
|
58
44
|
return delayed;
|
|
59
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDelayedFlag.js","names":["_react","require","_useTabLoading","
|
|
1
|
+
{"version":3,"file":"useDelayedFlag.js","names":["_react","require","_useTabLoading","useDelayedFlag","active","delayMs","PERCEPTION_THRESHOLD_MS","delayed","setDelayed","useState","useEffect","undefined","t","setTimeout","clearTimeout"],"sources":["../../../src/lib/v2/hooks/useDelayedFlag.ts"],"sourcesContent":["import { useState, useEffect } from \"react\";\r\nimport { PERCEPTION_THRESHOLD_MS } from \"./useTabLoading\";\r\n\r\n/**\r\n * useDelayedFlag — Portnet UI v2\r\n *\r\n * Returns `true` only when `active` has been continuously true for\r\n * at least `delayMs` ms. Resets to `false` the moment `active` flips\r\n * back to false. Charter R-Sk.1 — perception threshold.\r\n *\r\n * const showSkeleton = useDelayedFlag(loading);\r\n * if (showSkeleton) return <Skeleton />;\r\n * if (loading) return null; // sub-threshold, render nothing\r\n * return <Data rows={rows} />;\r\n *\r\n * Use when:\r\n * - You want to delay showing a loading affordance (skeleton,\r\n * spinner overlay, \"Loading…\" text) until the user actually\r\n * perceives the wait.\r\n * - The flag has no tab/key semantics. For tab-aware loading\r\n * (preserves across tab swap to avoid flicker between two\r\n * consecutive skeletons), use `useTabLoading`.\r\n */\r\nexport default function useDelayedFlag(\r\n active: boolean,\r\n delayMs: number = PERCEPTION_THRESHOLD_MS\r\n): boolean {\r\n const [delayed, setDelayed] = useState(false);\r\n\r\n useEffect(() => {\r\n if (!active) {\r\n // Inactive — drop any in-flight delayed flag immediately so\r\n // the consumer can render the success path without waiting.\r\n setDelayed(false);\r\n return undefined;\r\n }\r\n // Schedule the flag flip. If `active` resolves false before the\r\n // timer fires, cleanup clears the timer and the flag never goes\r\n // true (the perception-threshold contract).\r\n const t = setTimeout(() => setDelayed(true), delayMs);\r\n return () => clearTimeout(t);\r\n }, [active, delayMs]);\r\n\r\n return delayed;\r\n}\r\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,cAAA,GAAAD,OAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASE,cAAcA,CACpCC,MAAe,EACfC,OAAe,GAAGC,sCAAuB,EAChC;EACT,MAAM,CAACC,OAAO,EAAEC,UAAU,CAAC,GAAG,IAAAC,eAAQ,EAAC,KAAK,CAAC;EAE7C,IAAAC,gBAAS,EAAC,MAAM;IACd,IAAI,CAACN,MAAM,EAAE;MACX;MACA;MACAI,UAAU,CAAC,KAAK,CAAC;MACjB,OAAOG,SAAS;IAClB;IACA;IACA;IACA;IACA,MAAMC,CAAC,GAAGC,UAAU,CAAC,MAAML,UAAU,CAAC,IAAI,CAAC,EAAEH,OAAO,CAAC;IACrD,OAAO,MAAMS,YAAY,CAACF,CAAC,CAAC;EAC9B,CAAC,EAAE,CAACR,MAAM,EAAEC,OAAO,CAAC,CAAC;EAErB,OAAOE,OAAO;AAChB","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDensity.d.ts","sourceRoot":"","sources":["../../../src/lib/v2/hooks/useDensity.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"useDensity.d.ts","sourceRoot":"","sources":["../../../src/lib/v2/hooks/useDensity.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,KAAK,WAAW,GAAG,aAAa,GAAG,SAAS,CAAC;AAkG7C,MAAM,CAAC,OAAO,UAAU,UAAU,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC,CAGhF"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports
|
|
6
|
+
exports.default = useDensity;
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
/**
|
|
9
9
|
* useDensity — Portnet UI v2
|
|
@@ -25,10 +25,10 @@ var _react = require("react");
|
|
|
25
25
|
* storage interactions are guarded.
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
const STORAGE_KEY = "portnet-ui-density";
|
|
29
|
+
const DEFAULT = "comfortable";
|
|
30
|
+
const VALID = Object.freeze(["comfortable", "compact"]);
|
|
31
|
+
const VALID_SET = new Set(VALID);
|
|
32
32
|
function isDensityPref(v) {
|
|
33
33
|
return typeof v === "string" && VALID_SET.has(v);
|
|
34
34
|
}
|
|
@@ -36,16 +36,16 @@ function isDensityPref(v) {
|
|
|
36
36
|
/* ── Module-level store ───────────────────────────────── */
|
|
37
37
|
|
|
38
38
|
/** Source of truth. Lazy-read from storage at module load on the client. */
|
|
39
|
-
|
|
39
|
+
let memoryValue = readInitialValue();
|
|
40
40
|
|
|
41
41
|
/** Active hook subscribers — notified on every value change. */
|
|
42
|
-
|
|
42
|
+
const subscribers = new Set();
|
|
43
43
|
function readInitialValue() {
|
|
44
44
|
if (typeof window === "undefined") return DEFAULT;
|
|
45
45
|
try {
|
|
46
|
-
|
|
46
|
+
const raw = window.localStorage.getItem(STORAGE_KEY);
|
|
47
47
|
return isDensityPref(raw) ? raw : DEFAULT;
|
|
48
|
-
} catch
|
|
48
|
+
} catch {
|
|
49
49
|
return DEFAULT;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -60,7 +60,7 @@ applyToDom(memoryValue);
|
|
|
60
60
|
/* Cross-tab sync. The `storage` event fires in OTHER tabs only —
|
|
61
61
|
* the writing tab is informed via the in-memory subscribers path. */
|
|
62
62
|
if (typeof window !== "undefined") {
|
|
63
|
-
window.addEventListener("storage",
|
|
63
|
+
window.addEventListener("storage", e => {
|
|
64
64
|
if (e.key !== STORAGE_KEY) return;
|
|
65
65
|
if (!isDensityPref(e.newValue)) return;
|
|
66
66
|
if (e.newValue === memoryValue) return;
|
|
@@ -73,16 +73,11 @@ if (typeof window !== "undefined") {
|
|
|
73
73
|
function notify() {
|
|
74
74
|
// Iterate a snapshot — a subscriber that unmounts during notify
|
|
75
75
|
// would otherwise mutate the Set under iteration.
|
|
76
|
-
for (
|
|
77
|
-
var cb = _Array$from[_i];
|
|
78
|
-
cb();
|
|
79
|
-
}
|
|
76
|
+
for (const cb of Array.from(subscribers)) cb();
|
|
80
77
|
}
|
|
81
78
|
function subscribe(callback) {
|
|
82
79
|
subscribers.add(callback);
|
|
83
|
-
return
|
|
84
|
-
return subscribers["delete"](callback);
|
|
85
|
-
};
|
|
80
|
+
return () => subscribers.delete(callback);
|
|
86
81
|
}
|
|
87
82
|
function getSnapshot() {
|
|
88
83
|
return memoryValue;
|
|
@@ -109,6 +104,7 @@ function setDensityValue(value) {
|
|
|
109
104
|
} catch (err) {
|
|
110
105
|
// Quota, private mode, or sandboxed iframe — preference is
|
|
111
106
|
// applied for this session but won't persist. Surface in dev.
|
|
107
|
+
// eslint-disable-next-line no-console
|
|
112
108
|
if (typeof console !== "undefined" && console.warn) {
|
|
113
109
|
// eslint-disable-next-line no-console
|
|
114
110
|
console.warn("[@portnet/ui v2] useDensity: localStorage write failed", err);
|
|
@@ -118,7 +114,7 @@ function setDensityValue(value) {
|
|
|
118
114
|
notify();
|
|
119
115
|
}
|
|
120
116
|
function useDensity() {
|
|
121
|
-
|
|
117
|
+
const density = (0, _react.useSyncExternalStore)(subscribe, getSnapshot, getServerSnapshot);
|
|
122
118
|
return [density, setDensityValue];
|
|
123
119
|
}
|
|
124
120
|
//# sourceMappingURL=useDensity.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDensity.js","names":["_react","require","STORAGE_KEY","DEFAULT","VALID","Object","freeze","VALID_SET","Set","isDensityPref","v","has","memoryValue","readInitialValue","subscribers","window","raw","localStorage","getItem","
|
|
1
|
+
{"version":3,"file":"useDensity.js","names":["_react","require","STORAGE_KEY","DEFAULT","VALID","Object","freeze","VALID_SET","Set","isDensityPref","v","has","memoryValue","readInitialValue","subscribers","window","raw","localStorage","getItem","applyToDom","value","document","documentElement","dataset","addEventListener","e","key","newValue","notify","cb","Array","from","subscribe","callback","add","delete","getSnapshot","getServerSnapshot","setDensityValue","setItem","err","console","warn","useDensity","density","useSyncExternalStore"],"sources":["../../../src/lib/v2/hooks/useDensity.ts"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\r\n\r\n/**\r\n * useDensity — Portnet UI v2\r\n *\r\n * Reads / writes the user's density preference (charter R-DG.11).\r\n * Applies it as `data-density` on <html> so all density-aware\r\n * tokens cascade.\r\n *\r\n * const [density, setDensity] = useDensity();\r\n * <button onClick={() => setDensity(density === \"compact\" ? \"comfortable\" : \"compact\")} />\r\n *\r\n * Synchronisation guarantees\r\n * - Multi-instance same-tab: every useDensity() consumer sees\r\n * the same value at all times. Implemented via a module-level\r\n * subscriber set fed by useSyncExternalStore.\r\n * - Cross-tab: a `storage` event listener at module load\r\n * propagates updates from sibling tabs sharing the origin.\r\n * - SSR-safe: server snapshot returns the DEFAULT; all DOM and\r\n * storage interactions are guarded.\r\n */\r\n\r\ntype DensityPref = \"comfortable\" | \"compact\";\r\n\r\nconst STORAGE_KEY = \"portnet-ui-density\";\r\nconst DEFAULT: DensityPref = \"comfortable\";\r\nconst VALID = Object.freeze([\"comfortable\", \"compact\"]);\r\nconst VALID_SET = new Set<string>(VALID);\r\n\r\nfunction isDensityPref(v: unknown): v is DensityPref {\r\n return typeof v === \"string\" && VALID_SET.has(v);\r\n}\r\n\r\n/* ── Module-level store ───────────────────────────────── */\r\n\r\n/** Source of truth. Lazy-read from storage at module load on the client. */\r\nlet memoryValue: DensityPref = readInitialValue();\r\n\r\n/** Active hook subscribers — notified on every value change. */\r\nconst subscribers = new Set<() => void>();\r\n\r\nfunction readInitialValue(): DensityPref {\r\n if (typeof window === \"undefined\") return DEFAULT;\r\n try {\r\n const raw = window.localStorage.getItem(STORAGE_KEY);\r\n return isDensityPref(raw) ? raw : DEFAULT;\r\n } catch {\r\n return DEFAULT;\r\n }\r\n}\r\n\r\nfunction applyToDom(value: DensityPref): void {\r\n if (typeof document === \"undefined\") return;\r\n document.documentElement.dataset[\"density\"] = value;\r\n}\r\n\r\n/** Apply the initial value to the DOM at module load (client-side). */\r\napplyToDom(memoryValue);\r\n\r\n/* Cross-tab sync. The `storage` event fires in OTHER tabs only —\r\n * the writing tab is informed via the in-memory subscribers path. */\r\nif (typeof window !== \"undefined\") {\r\n window.addEventListener(\"storage\", (e) => {\r\n if (e.key !== STORAGE_KEY) return;\r\n if (!isDensityPref(e.newValue)) return;\r\n if (e.newValue === memoryValue) return;\r\n memoryValue = e.newValue;\r\n applyToDom(memoryValue);\r\n // No storage write here — the originating tab already wrote.\r\n notify();\r\n });\r\n}\r\n\r\nfunction notify(): void {\r\n // Iterate a snapshot — a subscriber that unmounts during notify\r\n // would otherwise mutate the Set under iteration.\r\n for (const cb of Array.from(subscribers)) cb();\r\n}\r\n\r\nfunction subscribe(callback: () => void): () => void {\r\n subscribers.add(callback);\r\n return () => subscribers.delete(callback);\r\n}\r\n\r\nfunction getSnapshot(): DensityPref {\r\n return memoryValue;\r\n}\r\n\r\nfunction getServerSnapshot(): DensityPref {\r\n return DEFAULT;\r\n}\r\n\r\n/* ── Setter (module-level so identity is stable across renders) ── */\r\n\r\n/**\r\n * Set the density preference. Ignores invalid values silently\r\n * (consumer-supplied data sanitation is not this hook's job) and\r\n * short-circuits when the value is unchanged.\r\n */\r\nfunction setDensityValue(value: DensityPref): void {\r\n if (!VALID_SET.has(value)) return;\r\n if (value === memoryValue) return;\r\n memoryValue = value;\r\n applyToDom(value);\r\n if (typeof window !== \"undefined\") {\r\n try {\r\n window.localStorage.setItem(STORAGE_KEY, value);\r\n } catch (err) {\r\n // Quota, private mode, or sandboxed iframe — preference is\r\n // applied for this session but won't persist. Surface in dev.\r\n // eslint-disable-next-line no-console\r\n if (typeof console !== \"undefined\" && console.warn) {\r\n // eslint-disable-next-line no-console\r\n console.warn(\"[@portnet/ui v2] useDensity: localStorage write failed\", err);\r\n }\r\n }\r\n }\r\n notify();\r\n}\r\n\r\nexport default function useDensity(): [DensityPref, (value: DensityPref) => void] {\r\n const density = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\r\n return [density, setDensityValue];\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;;AAIA,MAAMC,WAAW,GAAG,oBAAoB;AACxC,MAAMC,OAAoB,GAAG,aAAa;AAC1C,MAAMC,KAAK,GAAGC,MAAM,CAACC,MAAM,CAAC,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;AACvD,MAAMC,SAAS,GAAG,IAAIC,GAAG,CAASJ,KAAK,CAAC;AAExC,SAASK,aAAaA,CAACC,CAAU,EAAoB;EACnD,OAAO,OAAOA,CAAC,KAAK,QAAQ,IAAIH,SAAS,CAACI,GAAG,CAACD,CAAC,CAAC;AAClD;;AAEA;;AAEA;AACA,IAAIE,WAAwB,GAAGC,gBAAgB,CAAC,CAAC;;AAEjD;AACA,MAAMC,WAAW,GAAG,IAAIN,GAAG,CAAa,CAAC;AAEzC,SAASK,gBAAgBA,CAAA,EAAgB;EACvC,IAAI,OAAOE,MAAM,KAAK,WAAW,EAAE,OAAOZ,OAAO;EACjD,IAAI;IACF,MAAMa,GAAG,GAAGD,MAAM,CAACE,YAAY,CAACC,OAAO,CAAChB,WAAW,CAAC;IACpD,OAAOO,aAAa,CAACO,GAAG,CAAC,GAAGA,GAAG,GAAGb,OAAO;EAC3C,CAAC,CAAC,MAAM;IACN,OAAOA,OAAO;EAChB;AACF;AAEA,SAASgB,UAAUA,CAACC,KAAkB,EAAQ;EAC5C,IAAI,OAAOC,QAAQ,KAAK,WAAW,EAAE;EACrCA,QAAQ,CAACC,eAAe,CAACC,OAAO,CAAC,SAAS,CAAC,GAAGH,KAAK;AACrD;;AAEA;AACAD,UAAU,CAACP,WAAW,CAAC;;AAEvB;AACA;AACA,IAAI,OAAOG,MAAM,KAAK,WAAW,EAAE;EACjCA,MAAM,CAACS,gBAAgB,CAAC,SAAS,EAAGC,CAAC,IAAK;IACxC,IAAIA,CAAC,CAACC,GAAG,KAAKxB,WAAW,EAAE;IAC3B,IAAI,CAACO,aAAa,CAACgB,CAAC,CAACE,QAAQ,CAAC,EAAE;IAChC,IAAIF,CAAC,CAACE,QAAQ,KAAKf,WAAW,EAAE;IAChCA,WAAW,GAAGa,CAAC,CAACE,QAAQ;IACxBR,UAAU,CAACP,WAAW,CAAC;IACvB;IACAgB,MAAM,CAAC,CAAC;EACV,CAAC,CAAC;AACJ;AAEA,SAASA,MAAMA,CAAA,EAAS;EACtB;EACA;EACA,KAAK,MAAMC,EAAE,IAAIC,KAAK,CAACC,IAAI,CAACjB,WAAW,CAAC,EAAEe,EAAE,CAAC,CAAC;AAChD;AAEA,SAASG,SAASA,CAACC,QAAoB,EAAc;EACnDnB,WAAW,CAACoB,GAAG,CAACD,QAAQ,CAAC;EACzB,OAAO,MAAMnB,WAAW,CAACqB,MAAM,CAACF,QAAQ,CAAC;AAC3C;AAEA,SAASG,WAAWA,CAAA,EAAgB;EAClC,OAAOxB,WAAW;AACpB;AAEA,SAASyB,iBAAiBA,CAAA,EAAgB;EACxC,OAAOlC,OAAO;AAChB;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA,SAASmC,eAAeA,CAAClB,KAAkB,EAAQ;EACjD,IAAI,CAACb,SAAS,CAACI,GAAG,CAACS,KAAK,CAAC,EAAE;EAC3B,IAAIA,KAAK,KAAKR,WAAW,EAAE;EAC3BA,WAAW,GAAGQ,KAAK;EACnBD,UAAU,CAACC,KAAK,CAAC;EACjB,IAAI,OAAOL,MAAM,KAAK,WAAW,EAAE;IACjC,IAAI;MACFA,MAAM,CAACE,YAAY,CAACsB,OAAO,CAACrC,WAAW,EAAEkB,KAAK,CAAC;IACjD,CAAC,CAAC,OAAOoB,GAAG,EAAE;MACZ;MACA;MACA;MACA,IAAI,OAAOC,OAAO,KAAK,WAAW,IAAIA,OAAO,CAACC,IAAI,EAAE;QAClD;QACAD,OAAO,CAACC,IAAI,CAAC,wDAAwD,EAAEF,GAAG,CAAC;MAC7E;IACF;EACF;EACAZ,MAAM,CAAC,CAAC;AACV;AAEe,SAASe,UAAUA,CAAA,EAAgD;EAChF,MAAMC,OAAO,GAAG,IAAAC,2BAAoB,EAACb,SAAS,EAAEI,WAAW,EAAEC,iBAAiB,CAAC;EAC/E,OAAO,CAACO,OAAO,EAAEN,eAAe,CAAC;AACnC","ignoreList":[]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports
|
|
6
|
+
exports.default = useFocusFirstError;
|
|
7
7
|
exports.focusFieldByName = focusFieldByName;
|
|
8
8
|
var _react = require("react");
|
|
9
9
|
/**
|
|
@@ -69,7 +69,7 @@ var _react = require("react");
|
|
|
69
69
|
* programmatically focusable but deliberately out of the tab order — landing
|
|
70
70
|
* there would put the user somewhere Tab cannot return to.
|
|
71
71
|
*/
|
|
72
|
-
|
|
72
|
+
const FOCUSABLE_WITHIN = 'input,select,textarea,button,[href],[tabindex]:not([tabindex="-1"])';
|
|
73
73
|
|
|
74
74
|
/**
|
|
75
75
|
* Escape a value for use inside an attribute selector.
|
|
@@ -110,26 +110,24 @@ function isFocusableNow(el) {
|
|
|
110
110
|
* caller should keep its inline error and, ideally, render
|
|
111
111
|
* FormErrorSummary so the field is still reachable.
|
|
112
112
|
*/
|
|
113
|
-
function focusFieldByName(name) {
|
|
114
|
-
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
113
|
+
function focusFieldByName(name, options = {}) {
|
|
115
114
|
if (typeof document === "undefined") return false;
|
|
116
115
|
if (!name) return false;
|
|
117
|
-
|
|
116
|
+
const escaped = escapeAttributeValue(name);
|
|
118
117
|
|
|
119
118
|
/* Order matters — see the `[id=]` note in the module docstring. */
|
|
120
|
-
|
|
121
|
-
for (
|
|
122
|
-
|
|
123
|
-
var host = null;
|
|
119
|
+
const selectors = [`[id="${escaped}"]`, `[name="${escaped}"]`, `[data-field="${escaped}"]`];
|
|
120
|
+
for (const selector of selectors) {
|
|
121
|
+
let host = null;
|
|
124
122
|
try {
|
|
125
123
|
host = document.querySelector(selector);
|
|
126
|
-
} catch
|
|
124
|
+
} catch {
|
|
127
125
|
/* Malformed selector — try the next shape rather than throwing into
|
|
128
126
|
the caller's validation branch. */
|
|
129
127
|
host = null;
|
|
130
128
|
}
|
|
131
129
|
if (host === null) continue;
|
|
132
|
-
|
|
130
|
+
const target = isFocusableNow(host) ? host : host.querySelector(FOCUSABLE_WITHIN);
|
|
133
131
|
if (!isFocusableNow(target)) continue;
|
|
134
132
|
if (options.scroll !== false) {
|
|
135
133
|
try {
|
|
@@ -137,7 +135,7 @@ function focusFieldByName(name) {
|
|
|
137
135
|
block: "center",
|
|
138
136
|
behavior: "auto"
|
|
139
137
|
});
|
|
140
|
-
} catch
|
|
138
|
+
} catch {
|
|
141
139
|
/* jsdom and older Safari lack the options overload. Focus below
|
|
142
140
|
still scrolls the control into view natively. */
|
|
143
141
|
}
|
|
@@ -158,25 +156,21 @@ function focusFieldByName(name) {
|
|
|
158
156
|
* error is actually found lets the effect re-run when the errors land,
|
|
159
157
|
* without re-firing for the same attempt afterwards.
|
|
160
158
|
*/
|
|
161
|
-
function useFocusFirstError(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
_ref$scroll = _ref.scroll,
|
|
169
|
-
scroll = _ref$scroll === void 0 ? true : _ref$scroll;
|
|
159
|
+
function useFocusFirstError({
|
|
160
|
+
errors,
|
|
161
|
+
order,
|
|
162
|
+
submitCount = 0,
|
|
163
|
+
enabled = true,
|
|
164
|
+
scroll = true
|
|
165
|
+
}) {
|
|
170
166
|
/** Highest submitCount already acted on. */
|
|
171
|
-
|
|
172
|
-
(0, _react.useEffect)(
|
|
167
|
+
const handledRef = (0, _react.useRef)(0);
|
|
168
|
+
(0, _react.useEffect)(() => {
|
|
173
169
|
if (!enabled) return undefined;
|
|
174
170
|
if (submitCount <= handledRef.current) return undefined;
|
|
175
171
|
if (!errors) return undefined;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return Boolean(errors[name]);
|
|
179
|
-
});
|
|
172
|
+
const names = order !== undefined && order.length > 0 ? order : Object.keys(errors);
|
|
173
|
+
const first = names.find(name => Boolean(errors[name]));
|
|
180
174
|
|
|
181
175
|
/* No error yet: either validation is still in flight for this attempt,
|
|
182
176
|
or it passed. Leave handledRef alone so a later errors update for the
|
|
@@ -186,18 +180,16 @@ function useFocusFirstError(_ref) {
|
|
|
186
180
|
|
|
187
181
|
/* One frame, so the inline errors have rendered and the target exists
|
|
188
182
|
and is measurable before it is focused and scrolled to. */
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
scroll
|
|
183
|
+
const frame = requestAnimationFrame(() => {
|
|
184
|
+
const focused = focusFieldByName(first, {
|
|
185
|
+
scroll
|
|
192
186
|
});
|
|
193
187
|
if (!focused && process.env["NODE_ENV"] !== "production") {
|
|
194
188
|
// eslint-disable-next-line no-console
|
|
195
|
-
console.warn(
|
|
189
|
+
console.warn(`[v2.useFocusFirstError] Could not focus "${first}" — no visible, ` + "enabled control matched [id], [name] or [data-field]. Either the " + "field is in a collapsed section, or its control does not publish " + "the field name (a hand-rolled control that skips Field). R-F.3 is " + "NOT satisfied for this field; render FormErrorSummary (R-FV.2) so " + "it stays reachable.");
|
|
196
190
|
}
|
|
197
191
|
});
|
|
198
|
-
return
|
|
199
|
-
return cancelAnimationFrame(frame);
|
|
200
|
-
};
|
|
192
|
+
return () => cancelAnimationFrame(frame);
|
|
201
193
|
}, [errors, order, submitCount, enabled, scroll]);
|
|
202
194
|
}
|
|
203
195
|
//# sourceMappingURL=useFocusFirstError.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFocusFirstError.js","names":["_react","require","FOCUSABLE_WITHIN","escapeAttributeValue","value","window","CSS","escape","replace","isFocusableNow","el","HTMLElement","hasAttribute","getAttribute","getClientRects","length","focusFieldByName","name","options","arguments","undefined","document","escaped","selectors","concat","_i","_selectors","selector","host","querySelector","_unused","target","scroll","scrollIntoView","block","behavior","_unused2","focus","useFocusFirstError","_ref","errors","order","_ref$submitCount","submitCount","_ref$enabled","enabled","_ref$scroll","handledRef","useRef","useEffect","current","names","Object","keys","first","find","Boolean","frame","requestAnimationFrame","focused","process","env","console","warn","cancelAnimationFrame"],"sources":["../../../src/lib/v2/hooks/useFocusFirstError.ts"],"sourcesContent":["import { useEffect, useRef } from \"react\";\r\n\r\n/**\r\n * useFocusFirstError — Portnet UI v2\r\n *\r\n * Charter §05.3 R-F.3 MUST — \"Submit form échoué → focus sur premier champ\r\n * en erreur\". Charter §04.1 R-FV.3 MUST — \"Scroll auto vers premier champ\r\n * en erreur + focus\". Both are the same behaviour; this is it, once.\r\n *\r\n * Formik-FREE on purpose, exactly like useFormAutoSave: the caller passes\r\n * `errors`, `submitCount` and the rendered field order as plain values.\r\n * Formik coupling belongs in patterns/ — use <FormikErrorFocus /> when the\r\n * form is a Formik form and this hook directly when it is not (a manual\r\n * \"Ajouter\" guard, a non-Formik dropzone section, a reducer-driven form).\r\n *\r\n * // Formik form — prefer the pattern, which wires this for you:\r\n * <FormikErrorFocus order={[\"numeroFacture\", \"fournisseur\", \"dateFacture\"]} />\r\n *\r\n * // Manual guard — call the imperative helper directly:\r\n * const missing = requiredFields.filter((f) => !f.value);\r\n * if (missing.length > 0) {\r\n * missing.forEach((f) => setFieldError(f.name, REQUIRED));\r\n * focusFieldByName(missing[0].name);\r\n * return;\r\n * }\r\n *\r\n * ── WHY THE `[id=]` LOOKUP COMES FIRST ──────────────────────────────\r\n *\r\n * Hosts have consistently written `[name=\"<field>\"]`, which is wrong for\r\n * most v2 fields. The Formik bridges wrap their control in Field, which\r\n * does `htmlFor={htmlFor || name}` and then\r\n * `cloneElement(child, { id: inputId })` — so the field NAME is published\r\n * as the control's `id`, and whether it also appears as `name` depends\r\n * entirely on which primitive is underneath. It does for Input/Textarea.\r\n * It does not for Select, Combobox, DatePicker or ReferentielField.\r\n *\r\n * A `[name=]`-only selector therefore fails precisely on the compound\r\n * fields, silently — the call runs, matches nothing, and the form reads as\r\n * compliant. `[id=]` is guaranteed by the Field contract for every bridge,\r\n * so it is tried first; `[name=]` and `[data-field=]` remain as fallbacks\r\n * for hand-rolled controls that never went through Field.\r\n *\r\n * ── WHAT THIS DELIBERATELY DOES NOT DO ──────────────────────────────\r\n *\r\n * It does not focus a control it cannot see. A field inside a collapsed\r\n * <details> (Accordion.Item) or a display:none branch has no client rects,\r\n * and focusing it would scroll the page to an invisible target and strand\r\n * the user with no visible focus ring. `focusFieldByName` returns false in\r\n * that case and dev-warns rather than guessing — the inline error\r\n * (role=\"alert\" via Field) still carries the message, and R-FV.2's summary\r\n * banner (FormErrorSummary) is the right affordance for reaching a field\r\n * in a closed section.\r\n *\r\n * It also does not announce anything. Field already renders its error with\r\n * role=\"alert\"; a second live region would double-announce.\r\n */\r\n\r\n/** Options for the imperative helper. */\r\nexport type FocusFieldOptions = {\r\n /**\r\n * Scroll the resolved control into view before focusing.\r\n *\r\n * `behavior: \"auto\"` always — never \"smooth\". R-Tg.2 caps animation at\r\n * 0.01 ms under prefers-reduced-motion, and a smooth scroll triggered by\r\n * a failed submit is exactly the motion that rule exists to suppress.\r\n *\r\n * @default true\r\n */\r\n scroll?: boolean | undefined;\r\n};\r\n\r\nexport type UseFocusFirstErrorOptions = {\r\n /**\r\n * Field name -> error. Formik's `errors` satisfies this directly.\r\n *\r\n * Only truthiness is read, so any error shape works (string, node,\r\n * nested object).\r\n */\r\n errors?: Readonly<Record<string, unknown>> | undefined;\r\n /**\r\n * Field names in RENDERED order — top-to-bottom as the user sees them.\r\n *\r\n * SUPPLY THIS. Without it the order falls back to `Object.keys(errors)`,\r\n * which is the order the validator happened to write its keys in and has\r\n * no relationship to the layout; \"first field in error\" then means\r\n * \"whichever field Yup reached first\", which can be the last one on\r\n * screen.\r\n */\r\n order?: readonly string[] | undefined;\r\n /**\r\n * Submit attempt counter. Formik's `submitCount`.\r\n *\r\n * This is the TRIGGER: focus moves when it increases, never on an\r\n * ordinary re-render. Without it a persisting error would re-steal focus\r\n * every time the component re-rendered, which is worse than not moving\r\n * focus at all.\r\n */\r\n submitCount?: number | undefined;\r\n /** @default true */\r\n enabled?: boolean | undefined;\r\n /** @default true */\r\n scroll?: boolean | undefined;\r\n};\r\n\r\n/**\r\n * Focusable descendants, for the case where the resolved element is a\r\n * wrapper rather than the control itself. Excludes tabindex=\"-1\", which is\r\n * programmatically focusable but deliberately out of the tab order — landing\r\n * there would put the user somewhere Tab cannot return to.\r\n */\r\nconst FOCUSABLE_WITHIN =\r\n 'input,select,textarea,button,[href],[tabindex]:not([tabindex=\"-1\"])';\r\n\r\n/**\r\n * Escape a value for use inside an attribute selector.\r\n *\r\n * CSS.escape where available, with a manual quote/backslash escape as the\r\n * fallback — same guard shape DataGrid uses for its reorder-grip lookup.\r\n * Field names are developer-authored, so this is robustness rather than a\r\n * sanitisation boundary.\r\n */\r\nfunction escapeAttributeValue(value: string): string {\r\n if (\r\n typeof window !== \"undefined\" &&\r\n window.CSS &&\r\n typeof window.CSS.escape === \"function\"\r\n ) {\r\n return window.CSS.escape(value);\r\n }\r\n return value.replace(/[\"\\\\]/g, \"\\\\$&\");\r\n}\r\n\r\n/**\r\n * Is this element something a user can actually be sent to?\r\n *\r\n * `getClientRects().length === 0` is what excludes a field inside a\r\n * collapsed <details> or a display:none branch. offsetParent alone is not\r\n * enough — it is also null for position:fixed elements, which are visible.\r\n */\r\nfunction isFocusableNow(el: Element | null): el is HTMLElement {\r\n if (!(el instanceof HTMLElement)) return false;\r\n if (el.hasAttribute(\"disabled\")) return false;\r\n if (el.getAttribute(\"aria-hidden\") === \"true\") return false;\r\n if (el.getClientRects().length === 0) return false;\r\n return true;\r\n}\r\n\r\n/**\r\n * Focus the control registered under `name`, resolving it the way the v2\r\n * Field contract publishes it.\r\n *\r\n * @returns true when a visible, enabled control was focused. False means\r\n * nothing matched, or the match was hidden or disabled — the\r\n * caller should keep its inline error and, ideally, render\r\n * FormErrorSummary so the field is still reachable.\r\n */\r\nexport function focusFieldByName(\r\n name: string,\r\n options: FocusFieldOptions = {}\r\n): boolean {\r\n if (typeof document === \"undefined\") return false;\r\n if (!name) return false;\r\n\r\n const escaped = escapeAttributeValue(name);\r\n\r\n /* Order matters — see the `[id=]` note in the module docstring. */\r\n const selectors = [\r\n `[id=\"${escaped}\"]`,\r\n `[name=\"${escaped}\"]`,\r\n `[data-field=\"${escaped}\"]`,\r\n ];\r\n\r\n for (const selector of selectors) {\r\n let host: Element | null = null;\r\n try {\r\n host = document.querySelector(selector);\r\n } catch {\r\n /* Malformed selector — try the next shape rather than throwing into\r\n the caller's validation branch. */\r\n host = null;\r\n }\r\n if (host === null) continue;\r\n\r\n const target = isFocusableNow(host)\r\n ? host\r\n : host.querySelector(FOCUSABLE_WITHIN);\r\n\r\n if (!isFocusableNow(target)) continue;\r\n\r\n if (options.scroll !== false) {\r\n try {\r\n target.scrollIntoView({ block: \"center\", behavior: \"auto\" });\r\n } catch {\r\n /* jsdom and older Safari lack the options overload. Focus below\r\n still scrolls the control into view natively. */\r\n }\r\n }\r\n\r\n target.focus();\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Move focus to the first field in error after each failed submit.\r\n *\r\n * Fires when `submitCount` increases AND an error is present. The two\r\n * conditions are separate on purpose: Formik increments submitCount before\r\n * async validation resolves, so on the render where the counter changes\r\n * `errors` can still be empty. Marking the attempt handled only once an\r\n * error is actually found lets the effect re-run when the errors land,\r\n * without re-firing for the same attempt afterwards.\r\n */\r\nexport default function useFocusFirstError({\r\n errors,\r\n order,\r\n submitCount = 0,\r\n enabled = true,\r\n scroll = true,\r\n}: UseFocusFirstErrorOptions): void {\r\n /** Highest submitCount already acted on. */\r\n const handledRef = useRef(0);\r\n\r\n useEffect(() => {\r\n if (!enabled) return undefined;\r\n if (submitCount <= handledRef.current) return undefined;\r\n if (!errors) return undefined;\r\n\r\n const names =\r\n order !== undefined && order.length > 0 ? order : Object.keys(errors);\r\n\r\n const first = names.find((name) => Boolean(errors[name]));\r\n\r\n /* No error yet: either validation is still in flight for this attempt,\r\n or it passed. Leave handledRef alone so a later errors update for the\r\n SAME attempt is still honoured. */\r\n if (first === undefined) return undefined;\r\n\r\n handledRef.current = submitCount;\r\n\r\n /* One frame, so the inline errors have rendered and the target exists\r\n and is measurable before it is focused and scrolled to. */\r\n const frame = requestAnimationFrame(() => {\r\n const focused = focusFieldByName(first, { scroll });\r\n\r\n if (!focused && process.env[\"NODE_ENV\"] !== \"production\") {\r\n // eslint-disable-next-line no-console\r\n console.warn(\r\n `[v2.useFocusFirstError] Could not focus \"${first}\" — no visible, ` +\r\n \"enabled control matched [id], [name] or [data-field]. Either the \" +\r\n \"field is in a collapsed section, or its control does not publish \" +\r\n \"the field name (a hand-rolled control that skips Field). R-F.3 is \" +\r\n \"NOT satisfied for this field; render FormErrorSummary (R-FV.2) so \" +\r\n \"it stays reachable.\"\r\n );\r\n }\r\n });\r\n\r\n return () => cancelAnimationFrame(frame);\r\n }, [errors, order, submitCount, enabled, scroll]);\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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AA+CA;AACA;AACA;AACA;AACA;AACA;AACA,IAAMC,gBAAgB,GACpB,qEAAqE;;AAEvE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,oBAAoBA,CAACC,KAAa,EAAU;EACnD,IACE,OAAOC,MAAM,KAAK,WAAW,IAC7BA,MAAM,CAACC,GAAG,IACV,OAAOD,MAAM,CAACC,GAAG,CAACC,MAAM,KAAK,UAAU,EACvC;IACA,OAAOF,MAAM,CAACC,GAAG,CAACC,MAAM,CAACH,KAAK,CAAC;EACjC;EACA,OAAOA,KAAK,CAACI,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC;AACxC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,cAAcA,CAACC,EAAkB,EAAqB;EAC7D,IAAI,EAAEA,EAAE,YAAYC,WAAW,CAAC,EAAE,OAAO,KAAK;EAC9C,IAAID,EAAE,CAACE,YAAY,CAAC,UAAU,CAAC,EAAE,OAAO,KAAK;EAC7C,IAAIF,EAAE,CAACG,YAAY,CAAC,aAAa,CAAC,KAAK,MAAM,EAAE,OAAO,KAAK;EAC3D,IAAIH,EAAE,CAACI,cAAc,CAAC,CAAC,CAACC,MAAM,KAAK,CAAC,EAAE,OAAO,KAAK;EAClD,OAAO,IAAI;AACb;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASC,gBAAgBA,CAC9BC,IAAY,EAEH;EAAA,IADTC,OAA0B,GAAAC,SAAA,CAAAJ,MAAA,QAAAI,SAAA,QAAAC,SAAA,GAAAD,SAAA,MAAG,CAAC,CAAC;EAE/B,IAAI,OAAOE,QAAQ,KAAK,WAAW,EAAE,OAAO,KAAK;EACjD,IAAI,CAACJ,IAAI,EAAE,OAAO,KAAK;EAEvB,IAAMK,OAAO,GAAGnB,oBAAoB,CAACc,IAAI,CAAC;;EAE1C;EACA,IAAMM,SAAS,GAAG,UAAAC,MAAA,CACRF,OAAO,qBAAAE,MAAA,CACLF,OAAO,2BAAAE,MAAA,CACDF,OAAO,SACxB;EAED,SAAAG,EAAA,MAAAC,UAAA,GAAuBH,SAAS,EAAAE,EAAA,GAAAC,UAAA,CAAAX,MAAA,EAAAU,EAAA,IAAE;IAA7B,IAAME,QAAQ,GAAAD,UAAA,CAAAD,EAAA;IACjB,IAAIG,IAAoB,GAAG,IAAI;IAC/B,IAAI;MACFA,IAAI,GAAGP,QAAQ,CAACQ,aAAa,CAACF,QAAQ,CAAC;IACzC,CAAC,CAAC,OAAAG,OAAA,EAAM;MACN;AACN;MACMF,IAAI,GAAG,IAAI;IACb;IACA,IAAIA,IAAI,KAAK,IAAI,EAAE;IAEnB,IAAMG,MAAM,GAAGtB,cAAc,CAACmB,IAAI,CAAC,GAC/BA,IAAI,GACJA,IAAI,CAACC,aAAa,CAAC3B,gBAAgB,CAAC;IAExC,IAAI,CAACO,cAAc,CAACsB,MAAM,CAAC,EAAE;IAE7B,IAAIb,OAAO,CAACc,MAAM,KAAK,KAAK,EAAE;MAC5B,IAAI;QACFD,MAAM,CAACE,cAAc,CAAC;UAAEC,KAAK,EAAE,QAAQ;UAAEC,QAAQ,EAAE;QAAO,CAAC,CAAC;MAC9D,CAAC,CAAC,OAAAC,QAAA,EAAM;QACN;AACR;MADQ;IAGJ;IAEAL,MAAM,CAACM,KAAK,CAAC,CAAC;IACd,OAAO,IAAI;EACb;EAEA,OAAO,KAAK;AACd;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASC,kBAAkBA,CAAAC,IAAA,EAMN;EAAA,IALlCC,MAAM,GAAAD,IAAA,CAANC,MAAM;IACNC,KAAK,GAAAF,IAAA,CAALE,KAAK;IAAAC,gBAAA,GAAAH,IAAA,CACLI,WAAW;IAAXA,WAAW,GAAAD,gBAAA,cAAG,CAAC,GAAAA,gBAAA;IAAAE,YAAA,GAAAL,IAAA,CACfM,OAAO;IAAPA,OAAO,GAAAD,YAAA,cAAG,IAAI,GAAAA,YAAA;IAAAE,WAAA,GAAAP,IAAA,CACdP,MAAM;IAANA,MAAM,GAAAc,WAAA,cAAG,IAAI,GAAAA,WAAA;EAEb;EACA,IAAMC,UAAU,GAAG,IAAAC,aAAM,EAAC,CAAC,CAAC;EAE5B,IAAAC,gBAAS,EAAC,YAAM;IACd,IAAI,CAACJ,OAAO,EAAE,OAAOzB,SAAS;IAC9B,IAAIuB,WAAW,IAAII,UAAU,CAACG,OAAO,EAAE,OAAO9B,SAAS;IACvD,IAAI,CAACoB,MAAM,EAAE,OAAOpB,SAAS;IAE7B,IAAM+B,KAAK,GACTV,KAAK,KAAKrB,SAAS,IAAIqB,KAAK,CAAC1B,MAAM,GAAG,CAAC,GAAG0B,KAAK,GAAGW,MAAM,CAACC,IAAI,CAACb,MAAM,CAAC;IAEvE,IAAMc,KAAK,GAAGH,KAAK,CAACI,IAAI,CAAC,UAACtC,IAAI;MAAA,OAAKuC,OAAO,CAAChB,MAAM,CAACvB,IAAI,CAAC,CAAC;IAAA,EAAC;;IAEzD;AACJ;AACA;IACI,IAAIqC,KAAK,KAAKlC,SAAS,EAAE,OAAOA,SAAS;IAEzC2B,UAAU,CAACG,OAAO,GAAGP,WAAW;;IAEhC;AACJ;IACI,IAAMc,KAAK,GAAGC,qBAAqB,CAAC,YAAM;MACxC,IAAMC,OAAO,GAAG3C,gBAAgB,CAACsC,KAAK,EAAE;QAAEtB,MAAM,EAANA;MAAO,CAAC,CAAC;MAEnD,IAAI,CAAC2B,OAAO,IAAIC,OAAO,CAACC,GAAG,CAAC,UAAU,CAAC,KAAK,YAAY,EAAE;QACxD;QACAC,OAAO,CAACC,IAAI,CACV,6CAAAvC,MAAA,CAA4C8B,KAAK,8BAC/C,mEAAmE,GACnE,mEAAmE,GACnE,oEAAoE,GACpE,oEAAoE,GACpE,qBACJ,CAAC;MACH;IACF,CAAC,CAAC;IAEF,OAAO;MAAA,OAAMU,oBAAoB,CAACP,KAAK,CAAC;IAAA;EAC1C,CAAC,EAAE,CAACjB,MAAM,EAAEC,KAAK,EAAEE,WAAW,EAAEE,OAAO,EAAEb,MAAM,CAAC,CAAC;AACnD","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"useFocusFirstError.js","names":["_react","require","FOCUSABLE_WITHIN","escapeAttributeValue","value","window","CSS","escape","replace","isFocusableNow","el","HTMLElement","hasAttribute","getAttribute","getClientRects","length","focusFieldByName","name","options","document","escaped","selectors","selector","host","querySelector","target","scroll","scrollIntoView","block","behavior","focus","useFocusFirstError","errors","order","submitCount","enabled","handledRef","useRef","useEffect","undefined","current","names","Object","keys","first","find","Boolean","frame","requestAnimationFrame","focused","process","env","console","warn","cancelAnimationFrame"],"sources":["../../../src/lib/v2/hooks/useFocusFirstError.ts"],"sourcesContent":["import { useEffect, useRef } from \"react\";\r\n\r\n/**\r\n * useFocusFirstError — Portnet UI v2\r\n *\r\n * Charter §05.3 R-F.3 MUST — \"Submit form échoué → focus sur premier champ\r\n * en erreur\". Charter §04.1 R-FV.3 MUST — \"Scroll auto vers premier champ\r\n * en erreur + focus\". Both are the same behaviour; this is it, once.\r\n *\r\n * Formik-FREE on purpose, exactly like useFormAutoSave: the caller passes\r\n * `errors`, `submitCount` and the rendered field order as plain values.\r\n * Formik coupling belongs in patterns/ — use <FormikErrorFocus /> when the\r\n * form is a Formik form and this hook directly when it is not (a manual\r\n * \"Ajouter\" guard, a non-Formik dropzone section, a reducer-driven form).\r\n *\r\n * // Formik form — prefer the pattern, which wires this for you:\r\n * <FormikErrorFocus order={[\"numeroFacture\", \"fournisseur\", \"dateFacture\"]} />\r\n *\r\n * // Manual guard — call the imperative helper directly:\r\n * const missing = requiredFields.filter((f) => !f.value);\r\n * if (missing.length > 0) {\r\n * missing.forEach((f) => setFieldError(f.name, REQUIRED));\r\n * focusFieldByName(missing[0].name);\r\n * return;\r\n * }\r\n *\r\n * ── WHY THE `[id=]` LOOKUP COMES FIRST ──────────────────────────────\r\n *\r\n * Hosts have consistently written `[name=\"<field>\"]`, which is wrong for\r\n * most v2 fields. The Formik bridges wrap their control in Field, which\r\n * does `htmlFor={htmlFor || name}` and then\r\n * `cloneElement(child, { id: inputId })` — so the field NAME is published\r\n * as the control's `id`, and whether it also appears as `name` depends\r\n * entirely on which primitive is underneath. It does for Input/Textarea.\r\n * It does not for Select, Combobox, DatePicker or ReferentielField.\r\n *\r\n * A `[name=]`-only selector therefore fails precisely on the compound\r\n * fields, silently — the call runs, matches nothing, and the form reads as\r\n * compliant. `[id=]` is guaranteed by the Field contract for every bridge,\r\n * so it is tried first; `[name=]` and `[data-field=]` remain as fallbacks\r\n * for hand-rolled controls that never went through Field.\r\n *\r\n * ── WHAT THIS DELIBERATELY DOES NOT DO ──────────────────────────────\r\n *\r\n * It does not focus a control it cannot see. A field inside a collapsed\r\n * <details> (Accordion.Item) or a display:none branch has no client rects,\r\n * and focusing it would scroll the page to an invisible target and strand\r\n * the user with no visible focus ring. `focusFieldByName` returns false in\r\n * that case and dev-warns rather than guessing — the inline error\r\n * (role=\"alert\" via Field) still carries the message, and R-FV.2's summary\r\n * banner (FormErrorSummary) is the right affordance for reaching a field\r\n * in a closed section.\r\n *\r\n * It also does not announce anything. Field already renders its error with\r\n * role=\"alert\"; a second live region would double-announce.\r\n */\r\n\r\n/** Options for the imperative helper. */\r\nexport type FocusFieldOptions = {\r\n /**\r\n * Scroll the resolved control into view before focusing.\r\n *\r\n * `behavior: \"auto\"` always — never \"smooth\". R-Tg.2 caps animation at\r\n * 0.01 ms under prefers-reduced-motion, and a smooth scroll triggered by\r\n * a failed submit is exactly the motion that rule exists to suppress.\r\n *\r\n * @default true\r\n */\r\n scroll?: boolean | undefined;\r\n};\r\n\r\nexport type UseFocusFirstErrorOptions = {\r\n /**\r\n * Field name -> error. Formik's `errors` satisfies this directly.\r\n *\r\n * Only truthiness is read, so any error shape works (string, node,\r\n * nested object).\r\n */\r\n errors?: Readonly<Record<string, unknown>> | undefined;\r\n /**\r\n * Field names in RENDERED order — top-to-bottom as the user sees them.\r\n *\r\n * SUPPLY THIS. Without it the order falls back to `Object.keys(errors)`,\r\n * which is the order the validator happened to write its keys in and has\r\n * no relationship to the layout; \"first field in error\" then means\r\n * \"whichever field Yup reached first\", which can be the last one on\r\n * screen.\r\n */\r\n order?: readonly string[] | undefined;\r\n /**\r\n * Submit attempt counter. Formik's `submitCount`.\r\n *\r\n * This is the TRIGGER: focus moves when it increases, never on an\r\n * ordinary re-render. Without it a persisting error would re-steal focus\r\n * every time the component re-rendered, which is worse than not moving\r\n * focus at all.\r\n */\r\n submitCount?: number | undefined;\r\n /** @default true */\r\n enabled?: boolean | undefined;\r\n /** @default true */\r\n scroll?: boolean | undefined;\r\n};\r\n\r\n/**\r\n * Focusable descendants, for the case where the resolved element is a\r\n * wrapper rather than the control itself. Excludes tabindex=\"-1\", which is\r\n * programmatically focusable but deliberately out of the tab order — landing\r\n * there would put the user somewhere Tab cannot return to.\r\n */\r\nconst FOCUSABLE_WITHIN =\r\n 'input,select,textarea,button,[href],[tabindex]:not([tabindex=\"-1\"])';\r\n\r\n/**\r\n * Escape a value for use inside an attribute selector.\r\n *\r\n * CSS.escape where available, with a manual quote/backslash escape as the\r\n * fallback — same guard shape DataGrid uses for its reorder-grip lookup.\r\n * Field names are developer-authored, so this is robustness rather than a\r\n * sanitisation boundary.\r\n */\r\nfunction escapeAttributeValue(value: string): string {\r\n if (\r\n typeof window !== \"undefined\" &&\r\n window.CSS &&\r\n typeof window.CSS.escape === \"function\"\r\n ) {\r\n return window.CSS.escape(value);\r\n }\r\n return value.replace(/[\"\\\\]/g, \"\\\\$&\");\r\n}\r\n\r\n/**\r\n * Is this element something a user can actually be sent to?\r\n *\r\n * `getClientRects().length === 0` is what excludes a field inside a\r\n * collapsed <details> or a display:none branch. offsetParent alone is not\r\n * enough — it is also null for position:fixed elements, which are visible.\r\n */\r\nfunction isFocusableNow(el: Element | null): el is HTMLElement {\r\n if (!(el instanceof HTMLElement)) return false;\r\n if (el.hasAttribute(\"disabled\")) return false;\r\n if (el.getAttribute(\"aria-hidden\") === \"true\") return false;\r\n if (el.getClientRects().length === 0) return false;\r\n return true;\r\n}\r\n\r\n/**\r\n * Focus the control registered under `name`, resolving it the way the v2\r\n * Field contract publishes it.\r\n *\r\n * @returns true when a visible, enabled control was focused. False means\r\n * nothing matched, or the match was hidden or disabled — the\r\n * caller should keep its inline error and, ideally, render\r\n * FormErrorSummary so the field is still reachable.\r\n */\r\nexport function focusFieldByName(\r\n name: string,\r\n options: FocusFieldOptions = {}\r\n): boolean {\r\n if (typeof document === \"undefined\") return false;\r\n if (!name) return false;\r\n\r\n const escaped = escapeAttributeValue(name);\r\n\r\n /* Order matters — see the `[id=]` note in the module docstring. */\r\n const selectors = [\r\n `[id=\"${escaped}\"]`,\r\n `[name=\"${escaped}\"]`,\r\n `[data-field=\"${escaped}\"]`,\r\n ];\r\n\r\n for (const selector of selectors) {\r\n let host: Element | null = null;\r\n try {\r\n host = document.querySelector(selector);\r\n } catch {\r\n /* Malformed selector — try the next shape rather than throwing into\r\n the caller's validation branch. */\r\n host = null;\r\n }\r\n if (host === null) continue;\r\n\r\n const target = isFocusableNow(host)\r\n ? host\r\n : host.querySelector(FOCUSABLE_WITHIN);\r\n\r\n if (!isFocusableNow(target)) continue;\r\n\r\n if (options.scroll !== false) {\r\n try {\r\n target.scrollIntoView({ block: \"center\", behavior: \"auto\" });\r\n } catch {\r\n /* jsdom and older Safari lack the options overload. Focus below\r\n still scrolls the control into view natively. */\r\n }\r\n }\r\n\r\n target.focus();\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Move focus to the first field in error after each failed submit.\r\n *\r\n * Fires when `submitCount` increases AND an error is present. The two\r\n * conditions are separate on purpose: Formik increments submitCount before\r\n * async validation resolves, so on the render where the counter changes\r\n * `errors` can still be empty. Marking the attempt handled only once an\r\n * error is actually found lets the effect re-run when the errors land,\r\n * without re-firing for the same attempt afterwards.\r\n */\r\nexport default function useFocusFirstError({\r\n errors,\r\n order,\r\n submitCount = 0,\r\n enabled = true,\r\n scroll = true,\r\n}: UseFocusFirstErrorOptions): void {\r\n /** Highest submitCount already acted on. */\r\n const handledRef = useRef(0);\r\n\r\n useEffect(() => {\r\n if (!enabled) return undefined;\r\n if (submitCount <= handledRef.current) return undefined;\r\n if (!errors) return undefined;\r\n\r\n const names =\r\n order !== undefined && order.length > 0 ? order : Object.keys(errors);\r\n\r\n const first = names.find((name) => Boolean(errors[name]));\r\n\r\n /* No error yet: either validation is still in flight for this attempt,\r\n or it passed. Leave handledRef alone so a later errors update for the\r\n SAME attempt is still honoured. */\r\n if (first === undefined) return undefined;\r\n\r\n handledRef.current = submitCount;\r\n\r\n /* One frame, so the inline errors have rendered and the target exists\r\n and is measurable before it is focused and scrolled to. */\r\n const frame = requestAnimationFrame(() => {\r\n const focused = focusFieldByName(first, { scroll });\r\n\r\n if (!focused && process.env[\"NODE_ENV\"] !== \"production\") {\r\n // eslint-disable-next-line no-console\r\n console.warn(\r\n `[v2.useFocusFirstError] Could not focus \"${first}\" — no visible, ` +\r\n \"enabled control matched [id], [name] or [data-field]. Either the \" +\r\n \"field is in a collapsed section, or its control does not publish \" +\r\n \"the field name (a hand-rolled control that skips Field). R-F.3 is \" +\r\n \"NOT satisfied for this field; render FormErrorSummary (R-FV.2) so \" +\r\n \"it stays reachable.\"\r\n );\r\n }\r\n });\r\n\r\n return () => cancelAnimationFrame(frame);\r\n }, [errors, order, submitCount, enabled, scroll]);\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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AA+CA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,gBAAgB,GACpB,qEAAqE;;AAEvE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,oBAAoBA,CAACC,KAAa,EAAU;EACnD,IACE,OAAOC,MAAM,KAAK,WAAW,IAC7BA,MAAM,CAACC,GAAG,IACV,OAAOD,MAAM,CAACC,GAAG,CAACC,MAAM,KAAK,UAAU,EACvC;IACA,OAAOF,MAAM,CAACC,GAAG,CAACC,MAAM,CAACH,KAAK,CAAC;EACjC;EACA,OAAOA,KAAK,CAACI,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC;AACxC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,cAAcA,CAACC,EAAkB,EAAqB;EAC7D,IAAI,EAAEA,EAAE,YAAYC,WAAW,CAAC,EAAE,OAAO,KAAK;EAC9C,IAAID,EAAE,CAACE,YAAY,CAAC,UAAU,CAAC,EAAE,OAAO,KAAK;EAC7C,IAAIF,EAAE,CAACG,YAAY,CAAC,aAAa,CAAC,KAAK,MAAM,EAAE,OAAO,KAAK;EAC3D,IAAIH,EAAE,CAACI,cAAc,CAAC,CAAC,CAACC,MAAM,KAAK,CAAC,EAAE,OAAO,KAAK;EAClD,OAAO,IAAI;AACb;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASC,gBAAgBA,CAC9BC,IAAY,EACZC,OAA0B,GAAG,CAAC,CAAC,EACtB;EACT,IAAI,OAAOC,QAAQ,KAAK,WAAW,EAAE,OAAO,KAAK;EACjD,IAAI,CAACF,IAAI,EAAE,OAAO,KAAK;EAEvB,MAAMG,OAAO,GAAGjB,oBAAoB,CAACc,IAAI,CAAC;;EAE1C;EACA,MAAMI,SAAS,GAAG,CAChB,QAAQD,OAAO,IAAI,EACnB,UAAUA,OAAO,IAAI,EACrB,gBAAgBA,OAAO,IAAI,CAC5B;EAED,KAAK,MAAME,QAAQ,IAAID,SAAS,EAAE;IAChC,IAAIE,IAAoB,GAAG,IAAI;IAC/B,IAAI;MACFA,IAAI,GAAGJ,QAAQ,CAACK,aAAa,CAACF,QAAQ,CAAC;IACzC,CAAC,CAAC,MAAM;MACN;AACN;MACMC,IAAI,GAAG,IAAI;IACb;IACA,IAAIA,IAAI,KAAK,IAAI,EAAE;IAEnB,MAAME,MAAM,GAAGhB,cAAc,CAACc,IAAI,CAAC,GAC/BA,IAAI,GACJA,IAAI,CAACC,aAAa,CAACtB,gBAAgB,CAAC;IAExC,IAAI,CAACO,cAAc,CAACgB,MAAM,CAAC,EAAE;IAE7B,IAAIP,OAAO,CAACQ,MAAM,KAAK,KAAK,EAAE;MAC5B,IAAI;QACFD,MAAM,CAACE,cAAc,CAAC;UAAEC,KAAK,EAAE,QAAQ;UAAEC,QAAQ,EAAE;QAAO,CAAC,CAAC;MAC9D,CAAC,CAAC,MAAM;QACN;AACR;MADQ;IAGJ;IAEAJ,MAAM,CAACK,KAAK,CAAC,CAAC;IACd,OAAO,IAAI;EACb;EAEA,OAAO,KAAK;AACd;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASC,kBAAkBA,CAAC;EACzCC,MAAM;EACNC,KAAK;EACLC,WAAW,GAAG,CAAC;EACfC,OAAO,GAAG,IAAI;EACdT,MAAM,GAAG;AACgB,CAAC,EAAQ;EAClC;EACA,MAAMU,UAAU,GAAG,IAAAC,aAAM,EAAC,CAAC,CAAC;EAE5B,IAAAC,gBAAS,EAAC,MAAM;IACd,IAAI,CAACH,OAAO,EAAE,OAAOI,SAAS;IAC9B,IAAIL,WAAW,IAAIE,UAAU,CAACI,OAAO,EAAE,OAAOD,SAAS;IACvD,IAAI,CAACP,MAAM,EAAE,OAAOO,SAAS;IAE7B,MAAME,KAAK,GACTR,KAAK,KAAKM,SAAS,IAAIN,KAAK,CAAClB,MAAM,GAAG,CAAC,GAAGkB,KAAK,GAAGS,MAAM,CAACC,IAAI,CAACX,MAAM,CAAC;IAEvE,MAAMY,KAAK,GAAGH,KAAK,CAACI,IAAI,CAAE5B,IAAI,IAAK6B,OAAO,CAACd,MAAM,CAACf,IAAI,CAAC,CAAC,CAAC;;IAEzD;AACJ;AACA;IACI,IAAI2B,KAAK,KAAKL,SAAS,EAAE,OAAOA,SAAS;IAEzCH,UAAU,CAACI,OAAO,GAAGN,WAAW;;IAEhC;AACJ;IACI,MAAMa,KAAK,GAAGC,qBAAqB,CAAC,MAAM;MACxC,MAAMC,OAAO,GAAGjC,gBAAgB,CAAC4B,KAAK,EAAE;QAAElB;MAAO,CAAC,CAAC;MAEnD,IAAI,CAACuB,OAAO,IAAIC,OAAO,CAACC,GAAG,CAAC,UAAU,CAAC,KAAK,YAAY,EAAE;QACxD;QACAC,OAAO,CAACC,IAAI,CACV,4CAA4CT,KAAK,kBAAkB,GACjE,mEAAmE,GACnE,mEAAmE,GACnE,oEAAoE,GACpE,oEAAoE,GACpE,qBACJ,CAAC;MACH;IACF,CAAC,CAAC;IAEF,OAAO,MAAMU,oBAAoB,CAACP,KAAK,CAAC;EAC1C,CAAC,EAAE,CAACf,MAAM,EAAEC,KAAK,EAAEC,WAAW,EAAEC,OAAO,EAAET,MAAM,CAAC,CAAC;AACnD","ignoreList":[]}
|