@portnet/ui 6.0.1 → 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 +737 -0
- package/dist/esm/index.js +90 -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 -39
- 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 +146 -0
- package/dist/esm/v2/__tests__/FieldWidth.test.js.map +1 -0
- package/dist/esm/v2/__tests__/FileCard.test.js +18 -18
- package/dist/esm/v2/__tests__/FileCard.test.js.map +1 -1
- package/dist/esm/v2/__tests__/FormikCheckbox.test.js +173 -0
- package/dist/esm/v2/__tests__/FormikCheckbox.test.js.map +1 -0
- package/dist/esm/v2/__tests__/FormikDateTimePicker.test.js +236 -0
- package/dist/esm/v2/__tests__/FormikDateTimePicker.test.js.map +1 -0
- 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 +299 -0
- package/dist/esm/v2/__tests__/FormikRadioGroup.test.js.map +1 -0
- package/dist/esm/v2/__tests__/MobileRowCard.test.js +44 -43
- 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 -22
- 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 +118 -90
- 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 +210 -52
- 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 +64 -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 +14 -4
- 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 +26 -75
- 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 +130 -0
- package/dist/esm/v2/patterns/FormikCheckbox.js.map +1 -0
- 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 -66
- package/dist/esm/v2/patterns/FormikCombobox.js.map +1 -1
- package/dist/esm/v2/patterns/FormikDatePicker.js +51 -99
- package/dist/esm/v2/patterns/FormikDatePicker.js.map +1 -1
- package/dist/esm/v2/patterns/FormikDateTimePicker.js +136 -0
- package/dist/esm/v2/patterns/FormikDateTimePicker.js.map +1 -0
- 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 -50
- package/dist/esm/v2/patterns/FormikInput.js.map +1 -1
- package/dist/esm/v2/patterns/FormikRadioGroup.js +129 -0
- package/dist/esm/v2/patterns/FormikRadioGroup.js.map +1 -0
- 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 -84
- package/dist/esm/v2/patterns/FormikSelect.js.map +1 -1
- package/dist/esm/v2/patterns/FormikTextarea.js +30 -43
- package/dist/esm/v2/patterns/FormikTextarea.js.map +1 -1
- package/dist/esm/v2/patterns/KeyboardShortcutsHelp.js +64 -65
- 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 +127 -0
- package/dist/esm/v2/patterns/RowFavoriteToggle.js.map +1 -0
- 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 +72 -0
- package/dist/esm/v2/patterns/_pickerSerialisation.js.map +1 -0
- 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 +235 -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 +203 -0
- package/dist/esm/v2/personalization/capabilities/gridPreferences.js.map +1 -0
- package/dist/esm/v2/personalization/capabilities/index.js +5 -0
- package/dist/esm/v2/personalization/capabilities/index.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 +35 -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 +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +122 -47
- 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 +98 -69
- 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 +148 -0
- package/dist/v2/__tests__/FieldWidth.test.js.map +1 -0
- package/dist/v2/__tests__/FileCard.test.js +45 -48
- package/dist/v2/__tests__/FileCard.test.js.map +1 -1
- package/dist/v2/__tests__/FormikCheckbox.test.js +175 -0
- package/dist/v2/__tests__/FormikCheckbox.test.js.map +1 -0
- package/dist/v2/__tests__/FormikDateTimePicker.test.js +237 -0
- package/dist/v2/__tests__/FormikDateTimePicker.test.js.map +1 -0
- 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 +300 -0
- package/dist/v2/__tests__/FormikRadioGroup.test.js.map +1 -0
- package/dist/v2/__tests__/MobileRowCard.test.js +100 -102
- 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 +38 -46
- 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.d.ts.map +1 -1
- package/dist/v2/components/DateTimePicker.js +121 -95
- 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 +121 -5
- package/dist/v2/components/Field.d.ts.map +1 -1
- package/dist/v2/components/Field.js +221 -62
- 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 +67 -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.d.ts.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.d.ts +9 -9
- package/dist/v2/patterns/FavoriteColumn.d.ts.map +1 -1
- package/dist/v2/patterns/FavoriteColumn.js +32 -80
- 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.d.ts +77 -0
- package/dist/v2/patterns/FormikCheckbox.d.ts.map +1 -0
- package/dist/v2/patterns/FormikCheckbox.js +138 -0
- package/dist/v2/patterns/FormikCheckbox.js.map +1 -0
- 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.d.ts +7 -1
- package/dist/v2/patterns/FormikCombobox.d.ts.map +1 -1
- package/dist/v2/patterns/FormikCombobox.js +55 -69
- package/dist/v2/patterns/FormikCombobox.js.map +1 -1
- package/dist/v2/patterns/FormikDatePicker.d.ts +13 -1
- package/dist/v2/patterns/FormikDatePicker.d.ts.map +1 -1
- package/dist/v2/patterns/FormikDatePicker.js +59 -106
- package/dist/v2/patterns/FormikDatePicker.js.map +1 -1
- package/dist/v2/patterns/FormikDateTimePicker.d.ts +111 -0
- package/dist/v2/patterns/FormikDateTimePicker.d.ts.map +1 -0
- package/dist/v2/patterns/FormikDateTimePicker.js +144 -0
- package/dist/v2/patterns/FormikDateTimePicker.js.map +1 -0
- 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.d.ts +11 -1
- package/dist/v2/patterns/FormikInput.d.ts.map +1 -1
- package/dist/v2/patterns/FormikInput.js +45 -55
- package/dist/v2/patterns/FormikInput.js.map +1 -1
- package/dist/v2/patterns/FormikRadioGroup.d.ts +80 -0
- package/dist/v2/patterns/FormikRadioGroup.d.ts.map +1 -0
- package/dist/v2/patterns/FormikRadioGroup.js +137 -0
- package/dist/v2/patterns/FormikRadioGroup.js.map +1 -0
- 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.d.ts +9 -1
- package/dist/v2/patterns/FormikSelect.d.ts.map +1 -1
- package/dist/v2/patterns/FormikSelect.js +70 -89
- package/dist/v2/patterns/FormikSelect.js.map +1 -1
- package/dist/v2/patterns/FormikTextarea.d.ts +9 -1
- package/dist/v2/patterns/FormikTextarea.d.ts.map +1 -1
- package/dist/v2/patterns/FormikTextarea.js +35 -48
- package/dist/v2/patterns/FormikTextarea.js.map +1 -1
- package/dist/v2/patterns/KeyboardShortcutsHelp.d.ts +14 -1
- package/dist/v2/patterns/KeyboardShortcutsHelp.d.ts.map +1 -1
- package/dist/v2/patterns/KeyboardShortcutsHelp.js +71 -74
- 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 +98 -0
- package/dist/v2/patterns/RowFavoriteToggle.d.ts.map +1 -0
- package/dist/v2/patterns/RowFavoriteToggle.js +135 -0
- package/dist/v2/patterns/RowFavoriteToggle.js.map +1 -0
- 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.d.ts +44 -0
- package/dist/v2/patterns/_pickerSerialisation.d.ts.map +1 -0
- package/dist/v2/patterns/_pickerSerialisation.js +80 -0
- package/dist/v2/patterns/_pickerSerialisation.js.map +1 -0
- 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 +247 -0
- package/dist/v2/patterns/index.d.ts.map +1 -1
- package/dist/v2/patterns/index.js +182 -70
- 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.d.ts +100 -0
- package/dist/v2/personalization/capabilities/gridPreferences.d.ts.map +1 -0
- package/dist/v2/personalization/capabilities/gridPreferences.js +210 -0
- package/dist/v2/personalization/capabilities/gridPreferences.js.map +1 -0
- package/dist/v2/personalization/capabilities/index.d.ts +6 -0
- package/dist/v2/personalization/capabilities/index.d.ts.map +1 -1
- package/dist/v2/personalization/capabilities/index.js +23 -10
- package/dist/v2/personalization/capabilities/index.js.map +1 -1
- 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 +34 -0
- package/dist/v2/personalization/index.d.ts.map +1 -1
- package/dist/v2/personalization/index.js +41 -21
- 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":"fileValidation.js","names":["EXECUTABLE_EXTENSIONS","Set","MIME_BY_EXTENSION","Object","freeze","pdf","png","jpg","jpeg","gif","webp","tif","tiff","txt","csv","doc","docx","xls","xlsx","ppt","pptx","UNRELIABLE_MIME_EXTENSIONS","DEFAULT_EXECUTABLE_MESSAGE","extensionOf","fileName","parts","split","length","toLowerCase","describeAcceptedTypes","extensions","map","ext","toUpperCase","join","toAcceptAttribute","isForbiddenExecutable","file","name","has","isAcceptedFile","policy","getFileRejection","executableMessage","labels","executable","typeMessage","type","reason","message","accepted","some","allowed","mime","trim","expected","undefined","includes","fileValidationApi"],"sources":["../../../../src/lib/v2/utils/fileValidation.ts"],"sourcesContent":["/**\r\n * fileValidation — is this file allowed to be uploaded?\r\n *\r\n * const POLICY = { extensions: [\"pdf\", \"png\", \"jpg\", \"jpeg\", \"doc\", \"docx\"] };\r\n *\r\n * const rejection = getFileRejection(file, POLICY);\r\n * if (rejection) toast(rejection.message, \"error\");\r\n *\r\n * <Dropzone accept={toAcceptAttribute(POLICY.extensions)} … />\r\n *\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n * WHY THIS BELONGS IN THE LIBRARY (capability gap G-52)\r\n *\r\n * `Dropzone` takes an `accept` attribute and reports `DropzoneRejection`, but it\r\n * validates nothing: the browser's `accept` is a FILE-PICKER FILTER, not a\r\n * control. It is trivially bypassed — drag and drop ignores it, and so does\r\n * \"All files\" in the picker on most platforms. So the library asked every host\r\n * to decide, itself, whether a dropped file is acceptable, and every host wrote:\r\n *\r\n * - an extension allow-list (business policy — rightly theirs), AND\r\n * - a deny-list of executables and scripts, AND\r\n * - an extension↔MIME cross-check with its browser tolerances.\r\n *\r\n * The last two are NOT business policy. They are one security decision, and a\r\n * security decision copied into every module is a security decision that WILL\r\n * drift: the day a file type has to be added to the deny-list, nobody can say\r\n * which of the fifteen GU modules received it. Worse, divergence here is\r\n * SILENT — a module missing an entry looks exactly like a module that has it,\r\n * until something gets uploaded.\r\n *\r\n * So the split this file draws: the HOST owns which extensions its business\r\n * accepts; the LIBRARY owns the executable deny-list and the MIME cross-check.\r\n *\r\n * Raised from `autorisation-admis-pour-conforme-fe` (Area 5), which carried a\r\n * 21-entry executable deny-list and a six-extension MIME table locally.\r\n *\r\n * NOT A SUBSTITUTE FOR SERVER-SIDE VALIDATION, and this must stay written down:\r\n * everything here runs in a browser the user controls. Its purpose is to give a\r\n * CLEAR, IMMEDIATE reason (R-4.1, R-4.4) instead of a server rejection after a\r\n * full upload. The back-end remains the authority.\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n */\r\n\r\n/**\r\n * Executables, scripts and installers — refused whatever the host's policy says.\r\n *\r\n * Checked FIRST, and the order carries meaning: a `.exe` gets a message naming\r\n * it as a dangerous file, not a vague \"unsupported type\", because those are not\r\n * the same information for the person at the screen.\r\n *\r\n * Windows-centric because GU workstations are: PE binaries, the cmd/PowerShell\r\n * script families, installer packages, and the HTML-application and\r\n * control-panel shims that are executable despite innocuous extensions.\r\n */\r\nconst EXECUTABLE_EXTENSIONS: ReadonlySet<string> = new Set([\r\n \"exe\", \"dll\", \"bat\", \"cmd\", \"com\", \"pif\", \"scr\",\r\n \"msi\", \"msu\", \"msp\",\r\n \"vbs\", \"vbe\", \"jse\", \"wsf\", \"wsh\",\r\n \"ps1\", \"psm1\", \"psc1\",\r\n \"cpl\", \"msc\", \"hta\",\r\n]);\r\n\r\n/**\r\n * Accepted MIME types per extension.\r\n *\r\n * DELIBERATELY NOT `getMimeType` from ./fileDownload, though both map\r\n * extensions to MIME types. That one answers \"what type should I stamp on this\r\n * Blob\" — ONE canonical value. This one answers \"what types may a browser\r\n * plausibly report for this extension\" — a SET, including variants no canonical\r\n * table would contain (`image/jpg` is not a registered type, and browsers send\r\n * it anyway). Collapsing the two would reject valid files.\r\n */\r\nconst MIME_BY_EXTENSION: Readonly<Record<string, readonly string[]>> =\r\n Object.freeze({\r\n pdf: [\"application/pdf\"],\r\n png: [\"image/png\"],\r\n jpg: [\"image/jpeg\", \"image/jpg\"],\r\n jpeg: [\"image/jpeg\", \"image/jpg\"],\r\n gif: [\"image/gif\"],\r\n webp: [\"image/webp\"],\r\n tif: [\"image/tiff\"],\r\n tiff: [\"image/tiff\"],\r\n txt: [\"text/plain\"],\r\n csv: [\"text/csv\", \"application/csv\", \"text/plain\"],\r\n doc: [\"application/msword\"],\r\n docx: [\r\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\r\n ],\r\n xls: [\"application/vnd.ms-excel\"],\r\n xlsx: [\r\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\r\n ],\r\n ppt: [\"application/vnd.ms-powerpoint\"],\r\n pptx: [\r\n \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\r\n ],\r\n });\r\n\r\n/**\r\n * Extensions whose reported MIME type cannot be trusted, so\r\n * `application/octet-stream` is tolerated for them.\r\n *\r\n * WITHOUT THIS TOLERANCE A LEGITIMATE `.docx` IS REFUSED on some machines —\r\n * Office documents are frequently reported as `application/octet-stream`\r\n * depending on browser and OS, and the refusal would be INTERMITTENT, which is\r\n * the hardest kind to diagnose from a support ticket. The extension has already\r\n * been checked against the host's allow-list at that point, so the tolerance\r\n * does not widen what is accepted, only what is believed.\r\n */\r\nconst UNRELIABLE_MIME_EXTENSIONS: ReadonlySet<string> = new Set([\r\n \"doc\", \"docx\", \"xls\", \"xlsx\", \"ppt\", \"pptx\", \"csv\",\r\n]);\r\n\r\n/** Why a file was refused. `reason` is for branching and logs, not for display. */\r\nexport type FileRejectionReason = \"executable\" | \"extension\" | \"mime\";\r\n\r\nexport interface FileRejection {\r\n reason: FileRejectionReason;\r\n /** Ready to render (French, Charter §09.3 — what, and what is accepted). */\r\n message: string;\r\n}\r\n\r\nexport interface FileAcceptPolicy {\r\n /**\r\n * Extensions the HOST's business accepts, without a leading dot,\r\n * case-insensitive. This is the only part of the decision that belongs to the\r\n * host — an empty list accepts nothing, which is a programming error rather\r\n * than a policy, so it is treated as \"refuse everything\" and not as \"allow\".\r\n */\r\n extensions: readonly string[];\r\n /** Overrides for the default messages. Keep them in French, verb + object. */\r\n labels?:\r\n | {\r\n executable?: string | undefined;\r\n type?: string | undefined;\r\n }\r\n | undefined;\r\n}\r\n\r\nconst DEFAULT_EXECUTABLE_MESSAGE =\r\n \"Les fichiers exécutables, scripts et installeurs ne sont pas autorisés.\";\r\n\r\n/** Lowercased extension of a file name, or `\"\"` when there is none. */\r\nconst extensionOf = (fileName: string | undefined): string => {\r\n if (!fileName) return \"\";\r\n const parts = fileName.split(\".\");\r\n /* A name with no dot has no extension: \"rapport\" must not be read as having\r\n extension \"rapport\", which a bare `pop()` would do. */\r\n if (parts.length < 2) return \"\";\r\n return (parts[parts.length - 1] ?? \"\").toLowerCase();\r\n};\r\n\r\n/**\r\n * Human list of the accepted types — \"PDF, PNG, JPG, JPEG, DOC, DOCX.\"\r\n *\r\n * Order is the host's: the list is read by a person, and a host lists its most\r\n * common format first for a reason. Sorting it here would silently reorder\r\n * copy the host wrote deliberately.\r\n */\r\nexport function describeAcceptedTypes(\r\n extensions: readonly string[]\r\n): string {\r\n return `${extensions.map((ext) => ext.toUpperCase()).join(\", \")}.`;\r\n}\r\n\r\n/**\r\n * The `accept` attribute for an input or `Dropzone` — \".pdf,.png,.jpg\".\r\n *\r\n * A picker filter, never a control: see the note on server-side validation in\r\n * the file header.\r\n */\r\nexport function toAcceptAttribute(extensions: readonly string[]): string {\r\n return extensions.map((ext) => `.${ext.toLowerCase()}`).join(\",\");\r\n}\r\n\r\n/**\r\n * Is this an executable, a script or an installer?\r\n *\r\n * Exported on its own because a host may want to refuse those EARLIER than its\r\n * own policy check — on a bulk drop, for instance, where one dangerous file\r\n * should stop the whole batch rather than be listed among type mismatches.\r\n *\r\n * Permissive parameter type on purpose: callers routinely pass an item pulled\r\n * out of a `FileList` without having checked it.\r\n */\r\nexport function isForbiddenExecutable(file?: File | null | undefined): boolean {\r\n const ext = extensionOf(file?.name);\r\n return ext !== \"\" && EXECUTABLE_EXTENSIONS.has(ext);\r\n}\r\n\r\n/** Does the file satisfy `policy` (and the library's own deny-list)? */\r\nexport function isAcceptedFile(\r\n file: File | null | undefined,\r\n policy: FileAcceptPolicy\r\n): boolean {\r\n return getFileRejection(file, policy) === null;\r\n}\r\n\r\n/**\r\n * Why this file cannot be uploaded, or `null` when it can.\r\n *\r\n * Order of checks is load-bearing:\r\n * 1. executable / script / installer — named as such;\r\n * 2. extension against the host's allow-list;\r\n * 3. reported MIME type against the extension.\r\n *\r\n * MIME RULES, both deliberate: an EMPTY type is accepted (some browsers report\r\n * none, and the extension has just been checked), and `application/octet-stream`\r\n * is accepted for the extensions listed in `UNRELIABLE_MIME_EXTENSIONS`. An\r\n * extension with no entry in the MIME table is accepted on its extension alone\r\n * — the table is a cross-check, not a second allow-list, and a host adding a\r\n * format to its policy must not have it refused by a table it cannot see.\r\n */\r\nexport function getFileRejection(\r\n file: File | null | undefined,\r\n policy: FileAcceptPolicy\r\n): FileRejection | null {\r\n const executableMessage =\r\n policy.labels?.executable ?? DEFAULT_EXECUTABLE_MESSAGE;\r\n const typeMessage =\r\n policy.labels?.type ??\r\n `Types autorisés : ${describeAcceptedTypes(policy.extensions)}`;\r\n\r\n if (isForbiddenExecutable(file)) {\r\n return { reason: \"executable\", message: executableMessage };\r\n }\r\n\r\n const ext = extensionOf(file?.name);\r\n if (ext === \"\") return { reason: \"extension\", message: typeMessage };\r\n\r\n const accepted = policy.extensions.some(\r\n (allowed) => allowed.toLowerCase() === ext\r\n );\r\n if (!accepted) return { reason: \"extension\", message: typeMessage };\r\n\r\n const mime = (file?.type ?? \"\").trim().toLowerCase();\r\n if (mime === \"\") return null;\r\n if (mime === \"application/octet-stream\" && UNRELIABLE_MIME_EXTENSIONS.has(ext)) {\r\n return null;\r\n }\r\n\r\n const expected = MIME_BY_EXTENSION[ext];\r\n if (expected === undefined) return null;\r\n if (expected.includes(mime)) return null;\r\n\r\n return { reason: \"mime\", message: typeMessage };\r\n}\r\n\r\nconst fileValidationApi = {\r\n isForbiddenExecutable,\r\n isAcceptedFile,\r\n getFileRejection,\r\n describeAcceptedTypes,\r\n toAcceptAttribute,\r\n};\r\nexport default fileValidationApi;\r\n"],"mappings":"AAAA;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMA,qBAA0C,GAAG,IAAIC,GAAG,CAAC,CACzD,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAC/C,KAAK,EAAE,KAAK,EAAE,KAAK,EACnB,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EACjC,KAAK,EAAE,MAAM,EAAE,MAAM,EACrB,KAAK,EAAE,KAAK,EAAE,KAAK,CACpB,CAAC;;AAEF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,iBAA8D,GAClEC,MAAM,CAACC,MAAM,CAAC;EACZC,GAAG,EAAE,CAAC,iBAAiB,CAAC;EACxBC,GAAG,EAAE,CAAC,WAAW,CAAC;EAClBC,GAAG,EAAE,CAAC,YAAY,EAAE,WAAW,CAAC;EAChCC,IAAI,EAAE,CAAC,YAAY,EAAE,WAAW,CAAC;EACjCC,GAAG,EAAE,CAAC,WAAW,CAAC;EAClBC,IAAI,EAAE,CAAC,YAAY,CAAC;EACpBC,GAAG,EAAE,CAAC,YAAY,CAAC;EACnBC,IAAI,EAAE,CAAC,YAAY,CAAC;EACpBC,GAAG,EAAE,CAAC,YAAY,CAAC;EACnBC,GAAG,EAAE,CAAC,UAAU,EAAE,iBAAiB,EAAE,YAAY,CAAC;EAClDC,GAAG,EAAE,CAAC,oBAAoB,CAAC;EAC3BC,IAAI,EAAE,CACJ,yEAAyE,CAC1E;EACDC,GAAG,EAAE,CAAC,0BAA0B,CAAC;EACjCC,IAAI,EAAE,CACJ,mEAAmE,CACpE;EACDC,GAAG,EAAE,CAAC,+BAA+B,CAAC;EACtCC,IAAI,EAAE,CACJ,2EAA2E;AAE/E,CAAC,CAAC;;AAEJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,0BAA+C,GAAG,IAAIpB,GAAG,CAAC,CAC9D,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CACnD,CAAC;;AAEF;;AA0BA,MAAMqB,0BAA0B,GAC9B,yEAAyE;;AAE3E;AACA,MAAMC,WAAW,GAAIC,QAA4B,IAAa;EAC5D,IAAI,CAACA,QAAQ,EAAE,OAAO,EAAE;EACxB,MAAMC,KAAK,GAAGD,QAAQ,CAACE,KAAK,CAAC,GAAG,CAAC;EACjC;AACF;EACE,IAAID,KAAK,CAACE,MAAM,GAAG,CAAC,EAAE,OAAO,EAAE;EAC/B,OAAO,CAACF,KAAK,CAACA,KAAK,CAACE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,EAAEC,WAAW,CAAC,CAAC;AACtD,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,qBAAqBA,CACnCC,UAA6B,EACrB;EACR,OAAO,GAAGA,UAAU,CAACC,GAAG,CAAEC,GAAG,IAAKA,GAAG,CAACC,WAAW,CAAC,CAAC,CAAC,CAACC,IAAI,CAAC,IAAI,CAAC,GAAG;AACpE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,iBAAiBA,CAACL,UAA6B,EAAU;EACvE,OAAOA,UAAU,CAACC,GAAG,CAAEC,GAAG,IAAK,IAAIA,GAAG,CAACJ,WAAW,CAAC,CAAC,EAAE,CAAC,CAACM,IAAI,CAAC,GAAG,CAAC;AACnE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,qBAAqBA,CAACC,IAA8B,EAAW;EAC7E,MAAML,GAAG,GAAGT,WAAW,CAACc,IAAI,EAAEC,IAAI,CAAC;EACnC,OAAON,GAAG,KAAK,EAAE,IAAIhC,qBAAqB,CAACuC,GAAG,CAACP,GAAG,CAAC;AACrD;;AAEA;AACA,OAAO,SAASQ,cAAcA,CAC5BH,IAA6B,EAC7BI,MAAwB,EACf;EACT,OAAOC,gBAAgB,CAACL,IAAI,EAAEI,MAAM,CAAC,KAAK,IAAI;AAChD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,gBAAgBA,CAC9BL,IAA6B,EAC7BI,MAAwB,EACF;EACtB,MAAME,iBAAiB,GACrBF,MAAM,CAACG,MAAM,EAAEC,UAAU,IAAIvB,0BAA0B;EACzD,MAAMwB,WAAW,GACfL,MAAM,CAACG,MAAM,EAAEG,IAAI,IACnB,qBAAqBlB,qBAAqB,CAACY,MAAM,CAACX,UAAU,CAAC,EAAE;EAEjE,IAAIM,qBAAqB,CAACC,IAAI,CAAC,EAAE;IAC/B,OAAO;MAAEW,MAAM,EAAE,YAAY;MAAEC,OAAO,EAAEN;IAAkB,CAAC;EAC7D;EAEA,MAAMX,GAAG,GAAGT,WAAW,CAACc,IAAI,EAAEC,IAAI,CAAC;EACnC,IAAIN,GAAG,KAAK,EAAE,EAAE,OAAO;IAAEgB,MAAM,EAAE,WAAW;IAAEC,OAAO,EAAEH;EAAY,CAAC;EAEpE,MAAMI,QAAQ,GAAGT,MAAM,CAACX,UAAU,CAACqB,IAAI,CACpCC,OAAO,IAAKA,OAAO,CAACxB,WAAW,CAAC,CAAC,KAAKI,GACzC,CAAC;EACD,IAAI,CAACkB,QAAQ,EAAE,OAAO;IAAEF,MAAM,EAAE,WAAW;IAAEC,OAAO,EAAEH;EAAY,CAAC;EAEnE,MAAMO,IAAI,GAAG,CAAChB,IAAI,EAAEU,IAAI,IAAI,EAAE,EAAEO,IAAI,CAAC,CAAC,CAAC1B,WAAW,CAAC,CAAC;EACpD,IAAIyB,IAAI,KAAK,EAAE,EAAE,OAAO,IAAI;EAC5B,IAAIA,IAAI,KAAK,0BAA0B,IAAIhC,0BAA0B,CAACkB,GAAG,CAACP,GAAG,CAAC,EAAE;IAC9E,OAAO,IAAI;EACb;EAEA,MAAMuB,QAAQ,GAAGrD,iBAAiB,CAAC8B,GAAG,CAAC;EACvC,IAAIuB,QAAQ,KAAKC,SAAS,EAAE,OAAO,IAAI;EACvC,IAAID,QAAQ,CAACE,QAAQ,CAACJ,IAAI,CAAC,EAAE,OAAO,IAAI;EAExC,OAAO;IAAEL,MAAM,EAAE,MAAM;IAAEC,OAAO,EAAEH;EAAY,CAAC;AACjD;AAEA,MAAMY,iBAAiB,GAAG;EACxBtB,qBAAqB;EACrBI,cAAc;EACdE,gBAAgB;EAChBb,qBAAqB;EACrBM;AACF,CAAC;AACD,eAAeuB,iBAAiB","ignoreList":[]}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fmtDate / fmtDateTime — render a date for DISPLAY.
|
|
3
|
+
*
|
|
4
|
+
* fmtDate("2026-03-05T14:30:00Z") → "05/03/2026"
|
|
5
|
+
* fmtDateTime("2026-03-05T14:30:00Z") → "05/03/2026 15:30" (local time)
|
|
6
|
+
* fmtDate(undefined) → "—"
|
|
7
|
+
* fmtDate("pas une date") → "—"
|
|
8
|
+
* fmtDate(d, { absent: "" }) → "" when there is no date
|
|
9
|
+
*
|
|
10
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
11
|
+
* WHY THIS BELONGS IN THE LIBRARY (capability gap G-51)
|
|
12
|
+
*
|
|
13
|
+
* The library already owns the money side of the same job — `fmtMoney`, same
|
|
14
|
+
* folder, same "—" for an absent value, for the same reason: a table cell must
|
|
15
|
+
* never read "NaN". It owned nothing for dates, which every GU screen renders
|
|
16
|
+
* far more often than amounts. So every module wrote its own, and the copies
|
|
17
|
+
* shared one defect:
|
|
18
|
+
*
|
|
19
|
+
* const fullformatDate = (stringDate) => {
|
|
20
|
+
* const date = new Date(stringDate);
|
|
21
|
+
* const day = formatIntoTwoDigits(date.getDate());
|
|
22
|
+
* …
|
|
23
|
+
*
|
|
24
|
+
* `new Date(undefined)` is an INVALID DATE whose every accessor returns `NaN`,
|
|
25
|
+
* so the helper rendered, literally:
|
|
26
|
+
*
|
|
27
|
+
* NaN/NaN/NaN NaN:NaN
|
|
28
|
+
*
|
|
29
|
+
* on any optional field — an update date, a visit date, a closure date — which
|
|
30
|
+
* is most of them. In `autorisation-admis-pour-conforme-fe` the guard had been
|
|
31
|
+
* added at CALL SITES one lot after another (lots 4 to 7) before being pulled
|
|
32
|
+
* into the module's own helper: treating the symptom eight times, because the
|
|
33
|
+
* one place where it cannot be forgotten is the formatter itself. That is the
|
|
34
|
+
* argument for owning it here rather than in each module.
|
|
35
|
+
*
|
|
36
|
+
* Two smaller things the same copies carried, fixed here by construction: a
|
|
37
|
+
* two-digit helper that returned `"08"` (string) or `12` (number) depending on
|
|
38
|
+
* the value, and an absent date rendered as an EMPTY string — indistinguishable
|
|
39
|
+
* from a cell that failed to render, where "—" says "we looked, there is
|
|
40
|
+
* nothing".
|
|
41
|
+
*
|
|
42
|
+
* WHY NO `moment`, THOUGH THE PACKAGE ALREADY DEPENDS ON IT
|
|
43
|
+
*
|
|
44
|
+
* `moment` is here for the pickers, and specifically for STRICT parsing against
|
|
45
|
+
* an explicit format (`patterns/_pickerSerialisation`) — reading
|
|
46
|
+
* `"31-12-2026"` back without guessing. That is the right use of it.
|
|
47
|
+
*
|
|
48
|
+
* Rendering an already-parsed instant as two numbers and a year is not. This
|
|
49
|
+
* folder is dependency-free on purpose (see `fileDownload`), and
|
|
50
|
+
* `moment(someString)` with no format falls back to `new Date` WHILE EMITTING A
|
|
51
|
+
* CONSOLE DEPRECATION WARNING — noise a display helper called once per table
|
|
52
|
+
* cell must not produce. Native padding has neither cost.
|
|
53
|
+
*
|
|
54
|
+
* TIME ZONE, STATED RATHER THAN IMPLIED. The output is in the VIEWER'S local
|
|
55
|
+
* zone (`getDate`, `getHours`…), which is what the module helpers this replaces
|
|
56
|
+
* did, and what a user expects of "date de dépôt". An instant sent as
|
|
57
|
+
* `…T23:30:00Z` therefore reads as the next day in Casablanca. If a screen ever
|
|
58
|
+
* needs the server's calendar day regardless of the reader, that is a DIFFERENT
|
|
59
|
+
* function and must be argued for on its own — silently switching this one to
|
|
60
|
+
* UTC would move dates by a day across the whole platform.
|
|
61
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/** What a formatter accepts: an API string, an epoch, or a `Date`. */
|
|
65
|
+
|
|
66
|
+
/** The platform's absence mark — same value `fmtMoney` returns. */
|
|
67
|
+
const ABSENT = "—";
|
|
68
|
+
const pad2 = value => String(value).padStart(2, "0");
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Parse an input into a USABLE `Date`, or `null`.
|
|
72
|
+
*
|
|
73
|
+
* `null` for every unusable case — absent, empty string, unparseable, or an
|
|
74
|
+
* Invalid Date — so no caller can accidentally format `NaN`. The empty-string
|
|
75
|
+
* check is explicit because `new Date("")` is Invalid while `new Date(0)` is a
|
|
76
|
+
* legitimate instant (1970), and a falsy test would conflate them.
|
|
77
|
+
*/
|
|
78
|
+
const toUsableDate = value => {
|
|
79
|
+
if (value === null || value === undefined || value === "") return null;
|
|
80
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
81
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Day, month and year — `DD/MM/YYYY`.
|
|
86
|
+
*
|
|
87
|
+
* @param value - API string, epoch, or `Date`. Absent or unparseable → `absent`.
|
|
88
|
+
*/
|
|
89
|
+
export function fmtDate(value, opts = {}) {
|
|
90
|
+
const date = toUsableDate(value);
|
|
91
|
+
if (date === null) return opts.absent ?? ABSENT;
|
|
92
|
+
return `${pad2(date.getDate())}/${pad2(date.getMonth() + 1)}/${date.getFullYear()}`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Day, month, year, then hours and minutes — `DD/MM/YYYY HH:mm`.
|
|
97
|
+
*
|
|
98
|
+
* Seconds are deliberately absent: no GU screen displays them, and a second
|
|
99
|
+
* shown is a second a reader tries to interpret.
|
|
100
|
+
*/
|
|
101
|
+
export function fmtDateTime(value, opts = {}) {
|
|
102
|
+
const date = toUsableDate(value);
|
|
103
|
+
if (date === null) return opts.absent ?? ABSENT;
|
|
104
|
+
return `${fmtDate(date, opts)} ${pad2(date.getHours())}:${pad2(date.getMinutes())}`;
|
|
105
|
+
}
|
|
106
|
+
const fmtDateApi = {
|
|
107
|
+
fmtDate,
|
|
108
|
+
fmtDateTime
|
|
109
|
+
};
|
|
110
|
+
export default fmtDateApi;
|
|
111
|
+
//# sourceMappingURL=fmtDate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fmtDate.js","names":["ABSENT","pad2","value","String","padStart","toUsableDate","undefined","date","Date","Number","isNaN","getTime","fmtDate","opts","absent","getDate","getMonth","getFullYear","fmtDateTime","getHours","getMinutes","fmtDateApi"],"sources":["../../../../src/lib/v2/utils/fmtDate.ts"],"sourcesContent":["/**\r\n * fmtDate / fmtDateTime — render a date for DISPLAY.\r\n *\r\n * fmtDate(\"2026-03-05T14:30:00Z\") → \"05/03/2026\"\r\n * fmtDateTime(\"2026-03-05T14:30:00Z\") → \"05/03/2026 15:30\" (local time)\r\n * fmtDate(undefined) → \"—\"\r\n * fmtDate(\"pas une date\") → \"—\"\r\n * fmtDate(d, { absent: \"\" }) → \"\" when there is no date\r\n *\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n * WHY THIS BELONGS IN THE LIBRARY (capability gap G-51)\r\n *\r\n * The library already owns the money side of the same job — `fmtMoney`, same\r\n * folder, same \"—\" for an absent value, for the same reason: a table cell must\r\n * never read \"NaN\". It owned nothing for dates, which every GU screen renders\r\n * far more often than amounts. So every module wrote its own, and the copies\r\n * shared one defect:\r\n *\r\n * const fullformatDate = (stringDate) => {\r\n * const date = new Date(stringDate);\r\n * const day = formatIntoTwoDigits(date.getDate());\r\n * …\r\n *\r\n * `new Date(undefined)` is an INVALID DATE whose every accessor returns `NaN`,\r\n * so the helper rendered, literally:\r\n *\r\n * NaN/NaN/NaN NaN:NaN\r\n *\r\n * on any optional field — an update date, a visit date, a closure date — which\r\n * is most of them. In `autorisation-admis-pour-conforme-fe` the guard had been\r\n * added at CALL SITES one lot after another (lots 4 to 7) before being pulled\r\n * into the module's own helper: treating the symptom eight times, because the\r\n * one place where it cannot be forgotten is the formatter itself. That is the\r\n * argument for owning it here rather than in each module.\r\n *\r\n * Two smaller things the same copies carried, fixed here by construction: a\r\n * two-digit helper that returned `\"08\"` (string) or `12` (number) depending on\r\n * the value, and an absent date rendered as an EMPTY string — indistinguishable\r\n * from a cell that failed to render, where \"—\" says \"we looked, there is\r\n * nothing\".\r\n *\r\n * WHY NO `moment`, THOUGH THE PACKAGE ALREADY DEPENDS ON IT\r\n *\r\n * `moment` is here for the pickers, and specifically for STRICT parsing against\r\n * an explicit format (`patterns/_pickerSerialisation`) — reading\r\n * `\"31-12-2026\"` back without guessing. That is the right use of it.\r\n *\r\n * Rendering an already-parsed instant as two numbers and a year is not. This\r\n * folder is dependency-free on purpose (see `fileDownload`), and\r\n * `moment(someString)` with no format falls back to `new Date` WHILE EMITTING A\r\n * CONSOLE DEPRECATION WARNING — noise a display helper called once per table\r\n * cell must not produce. Native padding has neither cost.\r\n *\r\n * TIME ZONE, STATED RATHER THAN IMPLIED. The output is in the VIEWER'S local\r\n * zone (`getDate`, `getHours`…), which is what the module helpers this replaces\r\n * did, and what a user expects of \"date de dépôt\". An instant sent as\r\n * `…T23:30:00Z` therefore reads as the next day in Casablanca. If a screen ever\r\n * needs the server's calendar day regardless of the reader, that is a DIFFERENT\r\n * function and must be argued for on its own — silently switching this one to\r\n * UTC would move dates by a day across the whole platform.\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n */\r\n\r\n/** What a formatter accepts: an API string, an epoch, or a `Date`. */\r\nexport type FmtDateInput = string | number | Date | null | undefined;\r\n\r\nexport type FmtDateOptions = {\r\n /**\r\n * Rendered when there is no usable date. Defaults to the em dash used as the\r\n * platform's absence mark in tables and detail sheets.\r\n *\r\n * Pass `\"\"` where an empty cell is the deliberate choice — a DataGrid column\r\n * that must stay visually quiet, or a value on its way into a search payload,\r\n * since an em dash travelling to a back-end as a criterion is worse than\r\n * nothing. Both cases exist in the module this was raised from.\r\n *\r\n * NO `separator` OPTION, and that is a correction rather than an omission.\r\n * The first draft had one, justified by a module helper documented as feeding\r\n * search criteria \"d'où le séparateur paramétrable\". A grep of the module\r\n * showed that helper has ZERO importers: the justification was dead code, so\r\n * the knob was speculative surface on a certified API (§2.8 — minimum API\r\n * surface). The emitted format is the charter's `DD/MM/YYYY`; a host needing\r\n * another separator should say why here.\r\n */\r\n absent?: string | undefined;\r\n};\r\n\r\n/** The platform's absence mark — same value `fmtMoney` returns. */\r\nconst ABSENT = \"—\";\r\n\r\nconst pad2 = (value: number): string => String(value).padStart(2, \"0\");\r\n\r\n/**\r\n * Parse an input into a USABLE `Date`, or `null`.\r\n *\r\n * `null` for every unusable case — absent, empty string, unparseable, or an\r\n * Invalid Date — so no caller can accidentally format `NaN`. The empty-string\r\n * check is explicit because `new Date(\"\")` is Invalid while `new Date(0)` is a\r\n * legitimate instant (1970), and a falsy test would conflate them.\r\n */\r\nconst toUsableDate = (value: FmtDateInput): Date | null => {\r\n if (value === null || value === undefined || value === \"\") return null;\r\n const date = value instanceof Date ? value : new Date(value);\r\n return Number.isNaN(date.getTime()) ? null : date;\r\n};\r\n\r\n/**\r\n * Day, month and year — `DD/MM/YYYY`.\r\n *\r\n * @param value - API string, epoch, or `Date`. Absent or unparseable → `absent`.\r\n */\r\nexport function fmtDate(value: FmtDateInput, opts: FmtDateOptions = {}): string {\r\n const date = toUsableDate(value);\r\n if (date === null) return opts.absent ?? ABSENT;\r\n\r\n return `${pad2(date.getDate())}/${pad2(\r\n date.getMonth() + 1\r\n )}/${date.getFullYear()}`;\r\n}\r\n\r\n/**\r\n * Day, month, year, then hours and minutes — `DD/MM/YYYY HH:mm`.\r\n *\r\n * Seconds are deliberately absent: no GU screen displays them, and a second\r\n * shown is a second a reader tries to interpret.\r\n */\r\nexport function fmtDateTime(\r\n value: FmtDateInput,\r\n opts: FmtDateOptions = {}\r\n): string {\r\n const date = toUsableDate(value);\r\n if (date === null) return opts.absent ?? ABSENT;\r\n\r\n return `${fmtDate(date, opts)} ${pad2(date.getHours())}:${pad2(\r\n date.getMinutes()\r\n )}`;\r\n}\r\n\r\nconst fmtDateApi = { fmtDate, fmtDateTime };\r\nexport default fmtDateApi;\r\n"],"mappings":"AAAA;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;;AAEA;;AAwBA;AACA,MAAMA,MAAM,GAAG,GAAG;AAElB,MAAMC,IAAI,GAAIC,KAAa,IAAaC,MAAM,CAACD,KAAK,CAAC,CAACE,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC;;AAEtE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,YAAY,GAAIH,KAAmB,IAAkB;EACzD,IAAIA,KAAK,KAAK,IAAI,IAAIA,KAAK,KAAKI,SAAS,IAAIJ,KAAK,KAAK,EAAE,EAAE,OAAO,IAAI;EACtE,MAAMK,IAAI,GAAGL,KAAK,YAAYM,IAAI,GAAGN,KAAK,GAAG,IAAIM,IAAI,CAACN,KAAK,CAAC;EAC5D,OAAOO,MAAM,CAACC,KAAK,CAACH,IAAI,CAACI,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,GAAGJ,IAAI;AACnD,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA,OAAO,SAASK,OAAOA,CAACV,KAAmB,EAAEW,IAAoB,GAAG,CAAC,CAAC,EAAU;EAC9E,MAAMN,IAAI,GAAGF,YAAY,CAACH,KAAK,CAAC;EAChC,IAAIK,IAAI,KAAK,IAAI,EAAE,OAAOM,IAAI,CAACC,MAAM,IAAId,MAAM;EAE/C,OAAO,GAAGC,IAAI,CAACM,IAAI,CAACQ,OAAO,CAAC,CAAC,CAAC,IAAId,IAAI,CACpCM,IAAI,CAACS,QAAQ,CAAC,CAAC,GAAG,CACpB,CAAC,IAAIT,IAAI,CAACU,WAAW,CAAC,CAAC,EAAE;AAC3B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,WAAWA,CACzBhB,KAAmB,EACnBW,IAAoB,GAAG,CAAC,CAAC,EACjB;EACR,MAAMN,IAAI,GAAGF,YAAY,CAACH,KAAK,CAAC;EAChC,IAAIK,IAAI,KAAK,IAAI,EAAE,OAAOM,IAAI,CAACC,MAAM,IAAId,MAAM;EAE/C,OAAO,GAAGY,OAAO,CAACL,IAAI,EAAEM,IAAI,CAAC,IAAIZ,IAAI,CAACM,IAAI,CAACY,QAAQ,CAAC,CAAC,CAAC,IAAIlB,IAAI,CAC5DM,IAAI,CAACa,UAAU,CAAC,CAClB,CAAC,EAAE;AACL;AAEA,MAAMC,UAAU,GAAG;EAAET,OAAO;EAAEM;AAAY,CAAC;AAC3C,eAAeG,UAAU","ignoreList":[]}
|
|
@@ -46,33 +46,31 @@
|
|
|
46
46
|
* an unmatched-but-valid tag negotiates down to fr-FR instead of to the host.
|
|
47
47
|
* The `try/catch` is still required for genuinely malformed input.
|
|
48
48
|
*/
|
|
49
|
-
|
|
50
|
-
export default function fmtMoney(n) {
|
|
51
|
-
var currency = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";
|
|
52
|
-
var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
49
|
+
const FALLBACK_LOCALE = "fr-FR";
|
|
50
|
+
export default function fmtMoney(n, currency = "", opts = {}) {
|
|
53
51
|
if (n == null || n === "") return "—";
|
|
54
|
-
|
|
52
|
+
const num = typeof n === "number" ? n : Number(n);
|
|
55
53
|
if (!Number.isFinite(num)) return "—";
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
const locale = opts.locale || FALLBACK_LOCALE;
|
|
55
|
+
const formatOpts = {};
|
|
58
56
|
if (opts.minimumFractionDigits != null) {
|
|
59
57
|
formatOpts.minimumFractionDigits = opts.minimumFractionDigits;
|
|
60
58
|
}
|
|
61
59
|
if (opts.maximumFractionDigits != null) {
|
|
62
60
|
formatOpts.maximumFractionDigits = opts.maximumFractionDigits;
|
|
63
61
|
}
|
|
64
|
-
|
|
62
|
+
let formatted;
|
|
65
63
|
try {
|
|
66
64
|
/* Requested locale first, fr-FR as the declared next preference — see
|
|
67
65
|
* FALLBACK_LOCALE. A resolvable request ("en-US") still wins outright; an
|
|
68
66
|
* unmatched-but-well-formed tag lands on fr-FR rather than on the host's
|
|
69
67
|
* default locale. */
|
|
70
68
|
formatted = new Intl.NumberFormat([locale, FALLBACK_LOCALE], formatOpts).format(num);
|
|
71
|
-
} catch
|
|
69
|
+
} catch {
|
|
72
70
|
/* Reached only for a STRUCTURALLY invalid tag (RangeError) or a non-string
|
|
73
71
|
* value from an untyped host — negotiation cannot help there. */
|
|
74
72
|
formatted = new Intl.NumberFormat(FALLBACK_LOCALE, formatOpts).format(num);
|
|
75
73
|
}
|
|
76
|
-
return currency ?
|
|
74
|
+
return currency ? `${formatted} ${currency}` : formatted;
|
|
77
75
|
}
|
|
78
76
|
//# sourceMappingURL=fmtMoney.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fmtMoney.js","names":["FALLBACK_LOCALE","fmtMoney","n","currency","
|
|
1
|
+
{"version":3,"file":"fmtMoney.js","names":["FALLBACK_LOCALE","fmtMoney","n","currency","opts","num","Number","isFinite","locale","formatOpts","minimumFractionDigits","maximumFractionDigits","formatted","Intl","NumberFormat","format"],"sources":["../../../../src/lib/v2/utils/fmtMoney.ts"],"sourcesContent":["/**\r\n * fmtMoney — format a number with locale-aware grouping.\r\n *\r\n * Returns \"—\" for null / empty / non-finite inputs (graceful empty\r\n * cells in tables — never \"NaN\" or \"∞\").\r\n *\r\n * Defaults to \"fr-FR\" for back-compat with v1 callers; pass `locale`\r\n * (BCP-47 tag) to format under any locale supported by the runtime\r\n * Intl.NumberFormat. Currency placement is a trailing suffix in the\r\n * locale-formatted number; future evolution toward `style:\"currency\"`\r\n * (locale-correct symbol position, proper RTL handling) is deliberately\r\n * deferred to avoid breaking consumers that grep on the suffix.\r\n *\r\n * fmtMoney(1234567.5) → \"1 234 567,5\"\r\n * fmtMoney(1234567.5, \"EUR\") → \"1 234 567,5 EUR\"\r\n * fmtMoney(1234567.5, \"EUR\", { locale: \"en-US\" }) → \"1,234,567.5 EUR\"\r\n * fmtMoney(1234.5, \"\", { minimumFractionDigits: 2 })\r\n * → \"1 234,50\"\r\n * fmtMoney(null) / fmtMoney(\"abc\") / fmtMoney(Infinity) → \"—\"\r\n */\r\ntype FmtMoneyOptions = {\r\n locale?: string | undefined;\r\n minimumFractionDigits?: number | undefined;\r\n maximumFractionDigits?: number | undefined;\r\n};\r\n\r\n/**\r\n * The locale every unresolvable request falls back to.\r\n *\r\n * ── WHY THIS IS NEGOTIATED, NOT JUST CAUGHT ─────────────────────────────\r\n *\r\n * The previous implementation relied ONLY on `try/catch`, on the assumption that\r\n * an unusable locale throws `RangeError`. It does not — and the gap was a live\r\n * defect, not a theoretical one:\r\n *\r\n * `Intl.NumberFormat` throws only on a STRUCTURALLY INVALID tag. A tag that is\r\n * well-formed but has no data does NOT throw — it negotiates, and with a single\r\n * unmatched tag the negotiation lands on the RUNTIME DEFAULT LOCALE.\r\n *\r\n * `\"not-a-real-locale\"` is well-formed: `not` parses as a 3-letter language\r\n * subtag and `-a-real-locale` as a singleton `a` extension sequence. So it never\r\n * threw, the `catch` never ran, and the result was formatted in whatever locale\r\n * the host happened to default to. On a German or Spanish host that renders\r\n * `\"1.234,5\"` — dot grouping — inside a French application.\r\n *\r\n * That is a real consistency breach (Charter §09: a French UI formats numbers in\r\n * French), and it is invisible on a French dev machine, which is exactly why it\r\n * survived: the unit test caught it only because CI ran under a non-FR default.\r\n *\r\n * Listing the fallback as the SECOND preference makes the guarantee explicit:\r\n * an unmatched-but-valid tag negotiates down to fr-FR instead of to the host.\r\n * The `try/catch` is still required for genuinely malformed input.\r\n */\r\nconst FALLBACK_LOCALE = \"fr-FR\";\r\n\r\nexport default function fmtMoney(\r\n n: number | string | null | undefined,\r\n currency: string = \"\",\r\n opts: FmtMoneyOptions = {}\r\n): string {\r\n if (n == null || n === \"\") return \"—\";\r\n const num = typeof n === \"number\" ? n : Number(n);\r\n if (!Number.isFinite(num)) return \"—\";\r\n\r\n const locale = opts.locale || FALLBACK_LOCALE;\r\n\r\n const formatOpts: Intl.NumberFormatOptions = {};\r\n if (opts.minimumFractionDigits != null) {\r\n formatOpts.minimumFractionDigits = opts.minimumFractionDigits;\r\n }\r\n if (opts.maximumFractionDigits != null) {\r\n formatOpts.maximumFractionDigits = opts.maximumFractionDigits;\r\n }\r\n\r\n let formatted: string;\r\n try {\r\n /* Requested locale first, fr-FR as the declared next preference — see\r\n * FALLBACK_LOCALE. A resolvable request (\"en-US\") still wins outright; an\r\n * unmatched-but-well-formed tag lands on fr-FR rather than on the host's\r\n * default locale. */\r\n formatted = new Intl.NumberFormat(\r\n [locale, FALLBACK_LOCALE],\r\n formatOpts\r\n ).format(num);\r\n } catch {\r\n /* Reached only for a STRUCTURALLY invalid tag (RangeError) or a non-string\r\n * value from an untyped host — negotiation cannot help there. */\r\n formatted = new Intl.NumberFormat(FALLBACK_LOCALE, formatOpts).format(num);\r\n }\r\n\r\n return currency ? `${formatted} ${currency}` : formatted;\r\n}\r\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAOA;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,MAAMA,eAAe,GAAG,OAAO;AAE/B,eAAe,SAASC,QAAQA,CAC9BC,CAAqC,EACrCC,QAAgB,GAAG,EAAE,EACrBC,IAAqB,GAAG,CAAC,CAAC,EAClB;EACR,IAAIF,CAAC,IAAI,IAAI,IAAIA,CAAC,KAAK,EAAE,EAAE,OAAO,GAAG;EACrC,MAAMG,GAAG,GAAG,OAAOH,CAAC,KAAK,QAAQ,GAAGA,CAAC,GAAGI,MAAM,CAACJ,CAAC,CAAC;EACjD,IAAI,CAACI,MAAM,CAACC,QAAQ,CAACF,GAAG,CAAC,EAAE,OAAO,GAAG;EAErC,MAAMG,MAAM,GAAGJ,IAAI,CAACI,MAAM,IAAIR,eAAe;EAE7C,MAAMS,UAAoC,GAAG,CAAC,CAAC;EAC/C,IAAIL,IAAI,CAACM,qBAAqB,IAAI,IAAI,EAAE;IACtCD,UAAU,CAACC,qBAAqB,GAAGN,IAAI,CAACM,qBAAqB;EAC/D;EACA,IAAIN,IAAI,CAACO,qBAAqB,IAAI,IAAI,EAAE;IACtCF,UAAU,CAACE,qBAAqB,GAAGP,IAAI,CAACO,qBAAqB;EAC/D;EAEA,IAAIC,SAAiB;EACrB,IAAI;IACF;AACJ;AACA;AACA;IACIA,SAAS,GAAG,IAAIC,IAAI,CAACC,YAAY,CAC/B,CAACN,MAAM,EAAER,eAAe,CAAC,EACzBS,UACF,CAAC,CAACM,MAAM,CAACV,GAAG,CAAC;EACf,CAAC,CAAC,MAAM;IACN;AACJ;IACIO,SAAS,GAAG,IAAIC,IAAI,CAACC,YAAY,CAACd,eAAe,EAAES,UAAU,CAAC,CAACM,MAAM,CAACV,GAAG,CAAC;EAC5E;EAEA,OAAOF,QAAQ,GAAG,GAAGS,SAAS,IAAIT,QAAQ,EAAE,GAAGS,SAAS;AAC1D","ignoreList":[]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* flattenFormikErrors — Formik's nested `errors` → the flat list
|
|
3
|
+
* `FormErrorSummary` consumes (capability gap G-38).
|
|
4
|
+
*
|
|
5
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
6
|
+
* WHY THIS BELONGS IN THE LIBRARY
|
|
7
|
+
*
|
|
8
|
+
* The library already owns BOTH ends of the failed-submit recipe that R-FV.2
|
|
9
|
+
* and R-FV.3 make mandatory:
|
|
10
|
+
*
|
|
11
|
+
* · `FormErrorSummary` — the banner at the top of the form, whose items are
|
|
12
|
+
* `{ name, message }` and whose `onItemClick` hands
|
|
13
|
+
* back the field NAME;
|
|
14
|
+
* · `FormikErrorFocus` / `focusFieldByName` — the counterpart that moves
|
|
15
|
+
* focus, resolving that same name as `[name="…"]`.
|
|
16
|
+
*
|
|
17
|
+
* What it never shipped is the step between them. Formik's `errors` mirrors the
|
|
18
|
+
* shape of `values` — a nested object whose leaves are message strings — and
|
|
19
|
+
* nothing in the library turned that tree into the flat list both ends speak.
|
|
20
|
+
* So every Formik host wrote the recursion itself, which is a duplication the
|
|
21
|
+
* Platform TypeScript Guidelines forbid outright, and which the library invited
|
|
22
|
+
* by publishing the type (`FormErrorSummaryError`) without the one function
|
|
23
|
+
* that produces it.
|
|
24
|
+
*
|
|
25
|
+
* >>> THE FAILURE MODE IS THE PATH, AND IT IS INVISIBLE TO REVIEW. Every
|
|
26
|
+
* >>> re-implementation gets `{ name, message }` right and the ACCUMULATED PATH
|
|
27
|
+
* >>> subtly wrong — a missing separator, a skipped array index, a `[0]`
|
|
28
|
+
* >>> written where Formik writes `.0`. Nothing throws. The banner renders,
|
|
29
|
+
* >>> lists the right messages, and its jump button targets a field that does
|
|
30
|
+
* >>> not exist: `focusFieldByName` finds no node and the click does nothing.
|
|
31
|
+
* >>> A user staring at a rejected form clicks the one affordance offered to
|
|
32
|
+
* >>> find the offending field, and it silently fails.
|
|
33
|
+
* >>>
|
|
34
|
+
* >>> Promoted from `refonte-frontend` (Area 5), where it had already been
|
|
35
|
+
* >>> extracted once — out of a single page and into module-common — for
|
|
36
|
+
* >>> exactly this reason, when a second form needed it. The next module along
|
|
37
|
+
* >>> would have been the third copy. <<<
|
|
38
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
39
|
+
*
|
|
40
|
+
* ARRAY ERRORS ARE TRAVERSED AS OBJECTS, DELIBERATELY. `Yup.array()` produces
|
|
41
|
+
* errors keyed by index, so the path becomes `beneficiaires.0.nom` — dot,
|
|
42
|
+
* not bracket. That is the form Formik itself produces and therefore the form
|
|
43
|
+
* the corresponding field's `name` attribute carries, which is what makes the
|
|
44
|
+
* path usable by `focusFieldByName` and by `setFieldValue` alike. Rewriting it
|
|
45
|
+
* as `beneficiaires[0].nom` would read more naturally and match nothing.
|
|
46
|
+
*
|
|
47
|
+
* Non-string leaves that are not objects (a `false`, a `null` left by a custom
|
|
48
|
+
* validator) yield nothing rather than an item with an empty message: a summary
|
|
49
|
+
* line with no text is worse than one line fewer, since it is clickable, blank,
|
|
50
|
+
* and lists no reason.
|
|
51
|
+
*
|
|
52
|
+
* Usage:
|
|
53
|
+
*
|
|
54
|
+
* <FormErrorSummary
|
|
55
|
+
* errors={flattenFormikErrors(formik.errors)}
|
|
56
|
+
* onItemClick={focusFieldByName}
|
|
57
|
+
* />
|
|
58
|
+
*
|
|
59
|
+
* The `FormErrorSummaryError` import is TYPE-ONLY and therefore erased at
|
|
60
|
+
* build time: this util does not depend on ./patterns at runtime, and the
|
|
61
|
+
* item shape keeps a single declaration next to the component that renders it
|
|
62
|
+
* rather than being restated here.
|
|
63
|
+
*/
|
|
64
|
+
export function flattenFormikErrors(errors, prefix = "") {
|
|
65
|
+
if (!errors || typeof errors !== "object") return [];
|
|
66
|
+
return Object.entries(errors).flatMap(([key, value]) => {
|
|
67
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
68
|
+
if (typeof value === "string") {
|
|
69
|
+
return value.length > 0 ? [{
|
|
70
|
+
name: path,
|
|
71
|
+
message: value
|
|
72
|
+
}] : [];
|
|
73
|
+
}
|
|
74
|
+
return flattenFormikErrors(value, path);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
export default flattenFormikErrors;
|
|
78
|
+
//# sourceMappingURL=formikErrors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formikErrors.js","names":["flattenFormikErrors","errors","prefix","Object","entries","flatMap","key","value","path","length","name","message"],"sources":["../../../../src/lib/v2/utils/formikErrors.ts"],"sourcesContent":["import type { FormErrorSummaryError } from \"../patterns/FormErrorSummary\";\r\n\r\n/**\r\n * flattenFormikErrors — Formik's nested `errors` → the flat list\r\n * `FormErrorSummary` consumes (capability gap G-38).\r\n *\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n * WHY THIS BELONGS IN THE LIBRARY\r\n *\r\n * The library already owns BOTH ends of the failed-submit recipe that R-FV.2\r\n * and R-FV.3 make mandatory:\r\n *\r\n * · `FormErrorSummary` — the banner at the top of the form, whose items are\r\n * `{ name, message }` and whose `onItemClick` hands\r\n * back the field NAME;\r\n * · `FormikErrorFocus` / `focusFieldByName` — the counterpart that moves\r\n * focus, resolving that same name as `[name=\"…\"]`.\r\n *\r\n * What it never shipped is the step between them. Formik's `errors` mirrors the\r\n * shape of `values` — a nested object whose leaves are message strings — and\r\n * nothing in the library turned that tree into the flat list both ends speak.\r\n * So every Formik host wrote the recursion itself, which is a duplication the\r\n * Platform TypeScript Guidelines forbid outright, and which the library invited\r\n * by publishing the type (`FormErrorSummaryError`) without the one function\r\n * that produces it.\r\n *\r\n * >>> THE FAILURE MODE IS THE PATH, AND IT IS INVISIBLE TO REVIEW. Every\r\n * >>> re-implementation gets `{ name, message }` right and the ACCUMULATED PATH\r\n * >>> subtly wrong — a missing separator, a skipped array index, a `[0]`\r\n * >>> written where Formik writes `.0`. Nothing throws. The banner renders,\r\n * >>> lists the right messages, and its jump button targets a field that does\r\n * >>> not exist: `focusFieldByName` finds no node and the click does nothing.\r\n * >>> A user staring at a rejected form clicks the one affordance offered to\r\n * >>> find the offending field, and it silently fails.\r\n * >>>\r\n * >>> Promoted from `refonte-frontend` (Area 5), where it had already been\r\n * >>> extracted once — out of a single page and into module-common — for\r\n * >>> exactly this reason, when a second form needed it. The next module along\r\n * >>> would have been the third copy. <<<\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n *\r\n * ARRAY ERRORS ARE TRAVERSED AS OBJECTS, DELIBERATELY. `Yup.array()` produces\r\n * errors keyed by index, so the path becomes `beneficiaires.0.nom` — dot,\r\n * not bracket. That is the form Formik itself produces and therefore the form\r\n * the corresponding field's `name` attribute carries, which is what makes the\r\n * path usable by `focusFieldByName` and by `setFieldValue` alike. Rewriting it\r\n * as `beneficiaires[0].nom` would read more naturally and match nothing.\r\n *\r\n * Non-string leaves that are not objects (a `false`, a `null` left by a custom\r\n * validator) yield nothing rather than an item with an empty message: a summary\r\n * line with no text is worse than one line fewer, since it is clickable, blank,\r\n * and lists no reason.\r\n *\r\n * Usage:\r\n *\r\n * <FormErrorSummary\r\n * errors={flattenFormikErrors(formik.errors)}\r\n * onItemClick={focusFieldByName}\r\n * />\r\n *\r\n * The `FormErrorSummaryError` import is TYPE-ONLY and therefore erased at\r\n * build time: this util does not depend on ./patterns at runtime, and the\r\n * item shape keeps a single declaration next to the component that renders it\r\n * rather than being restated here.\r\n */\r\nexport function flattenFormikErrors(\r\n errors: unknown,\r\n prefix = \"\"\r\n): FormErrorSummaryError[] {\r\n if (!errors || typeof errors !== \"object\") return [];\r\n return Object.entries(errors as Record<string, unknown>).flatMap(\r\n ([key, value]) => {\r\n const path = prefix ? `${prefix}.${key}` : key;\r\n if (typeof value === \"string\") {\r\n return value.length > 0 ? [{ name: path, message: value }] : [];\r\n }\r\n return flattenFormikErrors(value, path);\r\n }\r\n );\r\n}\r\n\r\nexport default flattenFormikErrors;\r\n"],"mappings":"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;AACA;AACA,OAAO,SAASA,mBAAmBA,CACjCC,MAAe,EACfC,MAAM,GAAG,EAAE,EACc;EACzB,IAAI,CAACD,MAAM,IAAI,OAAOA,MAAM,KAAK,QAAQ,EAAE,OAAO,EAAE;EACpD,OAAOE,MAAM,CAACC,OAAO,CAACH,MAAiC,CAAC,CAACI,OAAO,CAC9D,CAAC,CAACC,GAAG,EAAEC,KAAK,CAAC,KAAK;IAChB,MAAMC,IAAI,GAAGN,MAAM,GAAG,GAAGA,MAAM,IAAII,GAAG,EAAE,GAAGA,GAAG;IAC9C,IAAI,OAAOC,KAAK,KAAK,QAAQ,EAAE;MAC7B,OAAOA,KAAK,CAACE,MAAM,GAAG,CAAC,GAAG,CAAC;QAAEC,IAAI,EAAEF,IAAI;QAAEG,OAAO,EAAEJ;MAAM,CAAC,CAAC,GAAG,EAAE;IACjE;IACA,OAAOP,mBAAmB,CAACO,KAAK,EAAEC,IAAI,CAAC;EACzC,CACF,CAAC;AACH;AAEA,eAAeR,mBAAmB","ignoreList":[]}
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
export { cx } from "./cx";
|
|
2
2
|
export { default as fmtMoney } from "./fmtMoney";
|
|
3
3
|
|
|
4
|
+
// Date rendering for DISPLAY (gap G-51) — the counterpart of fmtMoney, which
|
|
5
|
+
// this folder has owned all along for the same reason: a cell must never read
|
|
6
|
+
// "NaN". Nothing existed for dates, which GU screens render far more often than
|
|
7
|
+
// amounts, so every module wrote it — and every copy fed `new Date(undefined)`
|
|
8
|
+
// straight into `getDate()`, rendering the literal string "NaN/NaN/NaN NaN:NaN"
|
|
9
|
+
// on any optional date field. One module had added the guard at eight CALL
|
|
10
|
+
// SITES across four lots before moving it into its own helper; the formatter is
|
|
11
|
+
// the only place it cannot be forgotten.
|
|
12
|
+
//
|
|
13
|
+
// REMINDER (the G-34 invariant): this barrel is re-exported from lib/index.ts by
|
|
14
|
+
// EXPLICIT NAME LIST, so these two must be added there in the SAME commit or
|
|
15
|
+
// they never reach a consumer.
|
|
16
|
+
export { fmtDate, fmtDateTime } from "./fmtDate";
|
|
4
17
|
// Undefined-safe label merge. Every localisable component used to write
|
|
5
18
|
// `labels ? { ...DEFAULTS, ...labels } : DEFAULTS`, and a spread does NOT skip
|
|
6
19
|
// explicit `undefined` — so an override of `undefined` DELETED the default and
|
|
@@ -16,13 +29,25 @@ export { mergeLabels } from "./mergeLabels";
|
|
|
16
29
|
// is the common call site — qualifying it would only add noise.
|
|
17
30
|
export { downloadBase64File, getMimeType, openBase64FileInTab, downloadBlobFile } from "./fileDownload";
|
|
18
31
|
|
|
32
|
+
// Upload validation (gap G-52). `Dropzone` takes an `accept` attribute and
|
|
33
|
+
// reports rejections, but validates NOTHING — `accept` is a file-picker filter
|
|
34
|
+
// that drag-and-drop ignores. So every host decided for itself, and each wrote
|
|
35
|
+
// the same two non-business parts alongside its own extension allow-list: a
|
|
36
|
+
// deny-list of executables and scripts, and an extension/MIME cross-check with
|
|
37
|
+
// its browser tolerances. A security decision copied into fifteen modules
|
|
38
|
+
// drifts, and drifts SILENTLY. The host keeps its allow-list; the library owns
|
|
39
|
+
// the deny-list and the cross-check.
|
|
40
|
+
//
|
|
41
|
+
// REMINDER (the G-34 invariant): added to lib/index.ts in the same commit.
|
|
42
|
+
export { isForbiddenExecutable, isAcceptedFile, getFileRejection, describeAcceptedTypes, toAcceptAttribute } from "./fileValidation";
|
|
19
43
|
// WCAG 2.1 contrast utilities. Re-exported under a namespace at
|
|
20
44
|
// the public barrel (v2.contrast.*) so the named API is grouped
|
|
21
45
|
// and self-describing for callers — used to validate runtime
|
|
22
46
|
// brand overrides against WCAG 1.4.3 and to audit dark-mode
|
|
23
47
|
// token pairs (F29).
|
|
24
|
-
|
|
25
|
-
|
|
48
|
+
export * as contrast from "./contrast";
|
|
49
|
+
|
|
50
|
+
// `unknown`-rejection narrowing. Mandated by the platform's own
|
|
26
51
|
// `useUnknownInCatchVariables` flag, which makes `catch (e)` bind `unknown` in
|
|
27
52
|
// every consuming saga while `any` and unsafe assertions stay forbidden — the
|
|
28
53
|
// library previously left no sanctioned route between those two rules, and the
|
|
@@ -40,4 +65,12 @@ export { getApiErrorMessage, getApiErrorDetail, getApiErrorStatus, DEFAULT_API_E
|
|
|
40
65
|
// subscribe/report/clear channel. Raised as capability gap G-03
|
|
41
66
|
// (procuration-portnet-fe Area 5).
|
|
42
67
|
export { networkStatus, createNetworkStatus } from "./networkStatus";
|
|
68
|
+
// Formik's nested `errors` -> the flat `{ name, message }[]` that
|
|
69
|
+
// FormErrorSummary consumes and focusFieldByName resolves. The library owned
|
|
70
|
+
// both ends of the R-FV.2 / R-FV.3 recipe and not the step between them, so
|
|
71
|
+
// every Formik host wrote the recursion — and each copy got the accumulated
|
|
72
|
+
// PATH subtly wrong, which fails silently: the summary lists the right
|
|
73
|
+
// messages and its jump button targets a field that does not exist.
|
|
74
|
+
// Capability gap G-38 (refonte-frontend Area 5).
|
|
75
|
+
export { flattenFormikErrors } from "./formikErrors";
|
|
43
76
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["cx","default","fmtMoney","mergeLabels","downloadBase64File","getMimeType","openBase64FileInTab","downloadBlobFile","
|
|
1
|
+
{"version":3,"file":"index.js","names":["cx","default","fmtMoney","fmtDate","fmtDateTime","mergeLabels","downloadBase64File","getMimeType","openBase64FileInTab","downloadBlobFile","isForbiddenExecutable","isAcceptedFile","getFileRejection","describeAcceptedTypes","toAcceptAttribute","contrast","getApiErrorMessage","getApiErrorDetail","getApiErrorStatus","DEFAULT_API_ERROR_MESSAGE","networkStatus","createNetworkStatus","flattenFormikErrors"],"sources":["../../../../src/lib/v2/utils/index.ts"],"sourcesContent":["export { cx } from \"./cx\";\r\nexport { default as fmtMoney } from \"./fmtMoney\";\r\n\r\n// Date rendering for DISPLAY (gap G-51) — the counterpart of fmtMoney, which\r\n// this folder has owned all along for the same reason: a cell must never read\r\n// \"NaN\". Nothing existed for dates, which GU screens render far more often than\r\n// amounts, so every module wrote it — and every copy fed `new Date(undefined)`\r\n// straight into `getDate()`, rendering the literal string \"NaN/NaN/NaN NaN:NaN\"\r\n// on any optional date field. One module had added the guard at eight CALL\r\n// SITES across four lots before moving it into its own helper; the formatter is\r\n// the only place it cannot be forgotten.\r\n//\r\n// REMINDER (the G-34 invariant): this barrel is re-exported from lib/index.ts by\r\n// EXPLICIT NAME LIST, so these two must be added there in the SAME commit or\r\n// they never reach a consumer.\r\nexport { fmtDate, fmtDateTime } from \"./fmtDate\";\r\nexport type { FmtDateInput, FmtDateOptions } from \"./fmtDate\";\r\n\r\n// Undefined-safe label merge. Every localisable component used to write\r\n// `labels ? { ...DEFAULTS, ...labels } : DEFAULTS`, and a spread does NOT skip\r\n// explicit `undefined` — so an override of `undefined` DELETED the default and\r\n// the component threw `L.x is not a function` at render. Eleven components\r\n// shipped that hazard; the `?: T` declarations hid it from the compiler by\r\n// asserting the merged value could never be undefined, which was false at\r\n// runtime. Surfaced by the G-14 widening. Latent runtime defect, not cosmetics.\r\nexport { mergeLabels } from \"./mergeLabels\";\r\n\r\n// Base64 → browser download, plus the extension→MIME map it uses.\r\n// Flat named exports (not a namespace like contrast below): two\r\n// independent functions with no shared state, and downloadBase64File\r\n// is the common call site — qualifying it would only add noise.\r\nexport {\r\n downloadBase64File,\r\n getMimeType,\r\n openBase64FileInTab,\r\n downloadBlobFile,\r\n} from \"./fileDownload\";\r\n\r\n// Upload validation (gap G-52). `Dropzone` takes an `accept` attribute and\r\n// reports rejections, but validates NOTHING — `accept` is a file-picker filter\r\n// that drag-and-drop ignores. So every host decided for itself, and each wrote\r\n// the same two non-business parts alongside its own extension allow-list: a\r\n// deny-list of executables and scripts, and an extension/MIME cross-check with\r\n// its browser tolerances. A security decision copied into fifteen modules\r\n// drifts, and drifts SILENTLY. The host keeps its allow-list; the library owns\r\n// the deny-list and the cross-check.\r\n//\r\n// REMINDER (the G-34 invariant): added to lib/index.ts in the same commit.\r\nexport {\r\n isForbiddenExecutable,\r\n isAcceptedFile,\r\n getFileRejection,\r\n describeAcceptedTypes,\r\n toAcceptAttribute,\r\n} from \"./fileValidation\";\r\nexport type {\r\n FileAcceptPolicy,\r\n FileRejection,\r\n FileRejectionReason,\r\n} from \"./fileValidation\";\r\n\r\n// WCAG 2.1 contrast utilities. Re-exported under a namespace at\r\n// the public barrel (v2.contrast.*) so the named API is grouped\r\n// and self-describing for callers — used to validate runtime\r\n// brand overrides against WCAG 1.4.3 and to audit dark-mode\r\n// token pairs (F29).\r\nexport * as contrast from \"./contrast\";\r\n\r\n// `unknown`-rejection narrowing. Mandated by the platform's own\r\n// `useUnknownInCatchVariables` flag, which makes `catch (e)` bind `unknown` in\r\n// every consuming saga while `any` and unsafe assertions stay forbidden — the\r\n// library previously left no sanctioned route between those two rules, and the\r\n// modules that filled the gap filled it with the forbidden construct.\r\n// Raised as capability gap G-04 (procuration-portnet-fe Area 5).\r\n//\r\n// `getApiErrorDetail` is the LOGGING counterpart added with G-07: since\r\n// `getApiErrorMessage` now suppresses axios transport phrasings so they cannot\r\n// reach a user (Charter §09.3), operators still need the unfiltered string for a\r\n// console or an APM breadcrumb. Display one, log the other.\r\nexport {\r\n getApiErrorMessage,\r\n getApiErrorDetail,\r\n getApiErrorStatus,\r\n DEFAULT_API_ERROR_MESSAGE,\r\n} from \"./apiError\";\r\n\r\n// The feed behind NetworkErrorBanner. The banner was exported without the\r\n// plumbing that decides when it shows, so every module rebuilt the same\r\n// subscribe/report/clear channel. Raised as capability gap G-03\r\n// (procuration-portnet-fe Area 5).\r\nexport { networkStatus, createNetworkStatus } from \"./networkStatus\";\r\nexport type { NetworkStatus, NetworkStatusListener } from \"./networkStatus\";\r\n\r\n// Formik's nested `errors` -> the flat `{ name, message }[]` that\r\n// FormErrorSummary consumes and focusFieldByName resolves. The library owned\r\n// both ends of the R-FV.2 / R-FV.3 recipe and not the step between them, so\r\n// every Formik host wrote the recursion — and each copy got the accumulated\r\n// PATH subtly wrong, which fails silently: the summary lists the right\r\n// messages and its jump button targets a field that does not exist.\r\n// Capability gap G-38 (refonte-frontend Area 5).\r\nexport { flattenFormikErrors } from \"./formikErrors\";\r\n"],"mappings":"AAAA,SAASA,EAAE,QAAyB,MAAM;AAC1C,SAASC,OAAO,IAAIC,QAAQ,QAAQ,YAAY;;AAEhD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,OAAO,EAAEC,WAAW,QAAQ,WAAW;AAGhD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,WAAW,QAAQ,eAAe;;AAE3C;AACA;AACA;AACA;AACA,SACEC,kBAAkB,EAClBC,WAAW,EACXC,mBAAmB,EACnBC,gBAAgB,QACX,gBAAgB;;AAEvB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SACEC,qBAAqB,EACrBC,cAAc,EACdC,gBAAgB,EAChBC,qBAAqB,EACrBC,iBAAiB,QACZ,kBAAkB;AAOzB;AACA;AACA;AACA;AACA;AACA,OAAO,KAAKC,QAAQ,MAAM,YAAY;;AAEtC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SACEC,kBAAkB,EAClBC,iBAAiB,EACjBC,iBAAiB,EACjBC,yBAAyB,QACpB,YAAY;;AAEnB;AACA;AACA;AACA;AACA,SAASC,aAAa,EAAEC,mBAAmB,QAAQ,iBAAiB;AAGpE;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,mBAAmB,QAAQ,gBAAgB","ignoreList":[]}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
2
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
3
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
4
|
-
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
5
|
-
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
|
|
6
|
-
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
7
1
|
/**
|
|
8
2
|
* mergeLabels — Portnet UI v2
|
|
9
3
|
*
|
|
@@ -64,11 +58,10 @@ export function mergeLabels(defaults, overrides) {
|
|
|
64
58
|
// Single documented assertion, guarded by the `!overrides` check above: the
|
|
65
59
|
// mapped parameter type deliberately says nothing about value types, so the
|
|
66
60
|
// only way to read them is through an index signature.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
for (
|
|
70
|
-
|
|
71
|
-
var value = source[key];
|
|
61
|
+
const source = overrides;
|
|
62
|
+
let out;
|
|
63
|
+
for (const key of Object.keys(source)) {
|
|
64
|
+
const value = source[key];
|
|
72
65
|
// THE point of this helper. `undefined` means "not specified", never
|
|
73
66
|
// "unset the default".
|
|
74
67
|
if (value === undefined) continue;
|
|
@@ -77,7 +70,9 @@ export function mergeLabels(defaults, overrides) {
|
|
|
77
70
|
// LAZILY — only once a real override is found — so the common paths (no
|
|
78
71
|
// overrides at all, or an object whose every value is undefined) return the
|
|
79
72
|
// defaults object itself and stay referentially stable across renders.
|
|
80
|
-
if (!out) out =
|
|
73
|
+
if (!out) out = {
|
|
74
|
+
...defaults
|
|
75
|
+
};
|
|
81
76
|
out[key] = value;
|
|
82
77
|
}
|
|
83
78
|
return out === undefined ? defaults : out;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mergeLabels.js","names":["mergeLabels","defaults","overrides","source","out","
|
|
1
|
+
{"version":3,"file":"mergeLabels.js","names":["mergeLabels","defaults","overrides","source","out","key","Object","keys","value","undefined"],"sources":["../../../../src/lib/v2/utils/mergeLabels.ts"],"sourcesContent":["/**\r\n * mergeLabels — Portnet UI v2\r\n *\r\n * Merges a consumer's partial label overrides onto a component's frozen\r\n * defaults, IGNORING keys whose value is `undefined`.\r\n *\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n * WHY THIS EXISTS (capability gap G-14, latent runtime defect)\r\n *\r\n * Every localisable component in this library merged its labels like this:\r\n *\r\n * const L = labels ? { ...DEFAULT_LABELS, ...labels } : DEFAULT_LABELS;\r\n *\r\n * A spread does NOT skip explicit `undefined`. `{ ...{a: 1}, ...{a: undefined} }`\r\n * is `{ a: undefined }` — so a consumer writing\r\n *\r\n * <FilterTab labels={{ countLabel: maybeFn }} /> // maybeFn possibly undefined\r\n *\r\n * silently DELETED the default and the component then threw\r\n * `L.countLabel is not a function` at render time. Eleven components shipped\r\n * that hazard.\r\n *\r\n * It stayed invisible because the label interfaces declared `?: T` rather than\r\n * `?: T | undefined`: under that declaration TypeScript concluded the merged\r\n * value could never be `undefined`, which is false at runtime. Widening the\r\n * optional props (G-14) removed the blindfold and the compiler reported all\r\n * seventeen call sites at once. The types were wrong; the code was wrong; only\r\n * the combination of the two looked right.\r\n *\r\n * The fix restores what every call site already intended: an override REPLACES a\r\n * default, an absent or `undefined` override LEAVES it alone.\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n *\r\n * const L = mergeLabels(DEFAULT_LABELS, labels);\r\n * // ^ every key guaranteed present, typed from the defaults\r\n *\r\n * The return type is the DEFAULTS' type, deliberately: defaults are the\r\n * exhaustive, all-required shape, so the component can call `L.anything()`\r\n * without a null check. That is the whole point.\r\n *\r\n * `overrides` is a mapped type over `keyof TDefaults` with `unknown` values\r\n * rather than `Partial<TDefaults>`. Two reasons, both load-bearing:\r\n * - a mapped type accepts an INTERFACE argument, whereas `Record<string,\r\n * unknown>` would not (TypeScript grants implicit index signatures to type\r\n * aliases, not to interfaces), and most label contracts here are interfaces;\r\n * - some label interfaces legitimately widen a default's type (`React.ReactNode`\r\n * where the default is a `string`), which `Partial<TDefaults>` would reject.\r\n * Value types are already checked at the component's `labels` prop boundary,\r\n * so nothing is lost by not re-checking them here.\r\n *\r\n * Returns the defaults object ITSELF when there is nothing to override, so the\r\n * common path allocates nothing and stays referentially stable across renders —\r\n * which matters because these results are routinely wrapped in `useMemo`.\r\n */\r\nexport function mergeLabels<TDefaults extends object>(\r\n defaults: TDefaults,\r\n overrides?: { readonly [K in keyof TDefaults]?: unknown } | undefined\r\n): TDefaults {\r\n if (!overrides) return defaults;\r\n\r\n // Single documented assertion, guarded by the `!overrides` check above: the\r\n // mapped parameter type deliberately says nothing about value types, so the\r\n // only way to read them is through an index signature.\r\n const source = overrides as Record<string, unknown>;\r\n\r\n let out: Record<string, unknown> | undefined;\r\n\r\n for (const key of Object.keys(source)) {\r\n const value = source[key];\r\n // THE point of this helper. `undefined` means \"not specified\", never\r\n // \"unset the default\".\r\n if (value === undefined) continue;\r\n // Second assertion, same cause: `TDefaults extends object` carries no index\r\n // signature, so spreading it into a writable record needs one. Allocated\r\n // LAZILY — only once a real override is found — so the common paths (no\r\n // overrides at all, or an object whose every value is undefined) return the\r\n // defaults object itself and stay referentially stable across renders.\r\n if (!out) out = { ...(defaults as Record<string, unknown>) };\r\n out[key] = value;\r\n }\r\n\r\n return out === undefined ? defaults : (out as TDefaults);\r\n}\r\n\r\nexport default mergeLabels;\r\n"],"mappings":"AAAA;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,OAAO,SAASA,WAAWA,CACzBC,QAAmB,EACnBC,SAAqE,EAC1D;EACX,IAAI,CAACA,SAAS,EAAE,OAAOD,QAAQ;;EAE/B;EACA;EACA;EACA,MAAME,MAAM,GAAGD,SAAoC;EAEnD,IAAIE,GAAwC;EAE5C,KAAK,MAAMC,GAAG,IAAIC,MAAM,CAACC,IAAI,CAACJ,MAAM,CAAC,EAAE;IACrC,MAAMK,KAAK,GAAGL,MAAM,CAACE,GAAG,CAAC;IACzB;IACA;IACA,IAAIG,KAAK,KAAKC,SAAS,EAAE;IACzB;IACA;IACA;IACA;IACA;IACA,IAAI,CAACL,GAAG,EAAEA,GAAG,GAAG;MAAE,GAAIH;IAAqC,CAAC;IAC5DG,GAAG,CAACC,GAAG,CAAC,GAAGG,KAAK;EAClB;EAEA,OAAOJ,GAAG,KAAKK,SAAS,GAAGR,QAAQ,GAAIG,GAAiB;AAC1D;AAEA,eAAeJ,WAAW","ignoreList":[]}
|
|
@@ -66,24 +66,24 @@
|
|
|
66
66
|
* Application code should normally use the `networkStatus` export below.
|
|
67
67
|
*/
|
|
68
68
|
export function createNetworkStatus() {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
subscribe
|
|
69
|
+
const subscribers = new Set();
|
|
70
|
+
let lastError = null;
|
|
71
|
+
const channel = {
|
|
72
|
+
subscribe(listener) {
|
|
73
73
|
subscribers.add(listener);
|
|
74
74
|
if (lastError !== null) listener(lastError);
|
|
75
|
-
return
|
|
76
|
-
subscribers
|
|
75
|
+
return () => {
|
|
76
|
+
subscribers.delete(listener);
|
|
77
77
|
};
|
|
78
78
|
},
|
|
79
|
-
report
|
|
80
|
-
|
|
79
|
+
report(message) {
|
|
80
|
+
const next = message || null;
|
|
81
81
|
/* De-duplicated: a flaky link can fail many times per second, and
|
|
82
82
|
* re-notifying an unchanged message would re-render every subscriber for
|
|
83
83
|
* no visible difference. */
|
|
84
84
|
if (lastError === next) return;
|
|
85
85
|
lastError = next;
|
|
86
|
-
subscribers.forEach(
|
|
86
|
+
subscribers.forEach(listener => {
|
|
87
87
|
try {
|
|
88
88
|
listener(lastError);
|
|
89
89
|
} catch (e) {
|
|
@@ -95,10 +95,10 @@ export function createNetworkStatus() {
|
|
|
95
95
|
}
|
|
96
96
|
});
|
|
97
97
|
},
|
|
98
|
-
clear
|
|
98
|
+
clear() {
|
|
99
99
|
channel.report(null);
|
|
100
100
|
},
|
|
101
|
-
current
|
|
101
|
+
current() {
|
|
102
102
|
return lastError;
|
|
103
103
|
}
|
|
104
104
|
};
|
|
@@ -109,6 +109,6 @@ export function createNetworkStatus() {
|
|
|
109
109
|
* The shared channel. One per bundle, which is the right granularity: the
|
|
110
110
|
* transport layer and the banner must agree, and both live in the same app.
|
|
111
111
|
*/
|
|
112
|
-
export
|
|
112
|
+
export const networkStatus = createNetworkStatus();
|
|
113
113
|
export default networkStatus;
|
|
114
114
|
//# sourceMappingURL=networkStatus.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"networkStatus.js","names":["createNetworkStatus","subscribers","Set","lastError","channel","subscribe","listener","add","report","message","next","forEach","e","console","error","clear","current","networkStatus"],"sources":["../../../../src/lib/v2/utils/networkStatus.ts"],"sourcesContent":["/**\r\n * networkStatus — the feed behind `NetworkErrorBanner`.\r\n *\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n * WHY THIS BELONGS IN THE LIBRARY (capability gap G-03)\r\n *\r\n * The library shipped `NetworkErrorBanner` — a presentational component — but\r\n * not the plumbing that decides when it appears. Charter R-A.3 / R-4.3 make the\r\n * banner MANDATORY (\"erreur réseau → bandeau persistant top, bouton\r\n * « Réessayer »\"), so every consuming module had to invent the same\r\n * subscribe / report / clear singleton and the same transport-interceptor\r\n * bridge. Two audited modules (`procuration-portnet-fe`, `procuration-fe`) had\r\n * each written their own.\r\n *\r\n * A presentational component whose trigger contract is left to consumers\r\n * guarantees divergence in precisely the state users encounter least often and\r\n * trust least — the offline path.\r\n *\r\n * NOT a redux slice, deliberately\r\n * -------------------------------\r\n * This state is presentation-only and high-frequency on a flaky link. Crossing a\r\n * dispatch boundary on every retry would slow the alert path for no benefit, and\r\n * would force the library to take an opinion on the host's store.\r\n *\r\n * Late subscribers are hydrated on subscribe, so a banner that mounts after the\r\n * failure (lazy route, remount) still shows the current state instead of missing\r\n * the edge.\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n *\r\n * Wiring (once, at the app root):\r\n *\r\n * const [netError, setNetError] = useState<string | null>(null);\r\n * useEffect(() => networkStatus.subscribe(setNetError), []);\r\n *\r\n * <NetworkErrorBanner\r\n * visible={Boolean(netError)}\r\n * message={netError ?? \"\"}\r\n * onRetry={() => { networkStatus.clear(); window.location.reload(); }}\r\n * />\r\n *\r\n * And in the transport layer:\r\n *\r\n * instance.interceptors.response.use(\r\n * (response) => { networkStatus.clear(); return response; },\r\n * (error: unknown) => {\r\n * if (getApiErrorStatus(error) === undefined) {\r\n * networkStatus.report(\"Connexion perdue. Vérifiez votre réseau, puis réessayez.\");\r\n * }\r\n * return Promise.reject(error);\r\n * }\r\n * );\r\n *\r\n * A status-less failure is the network case (offline, DNS, ingress timeout); a\r\n * failure WITH a status is a server error and belongs in a toast (R-A.4).\r\n */\r\n\r\n/** Receives the latest banner message, or `null` when the banner should clear. */\r\nexport type NetworkStatusListener = (message: string | null) => void;\r\n\r\n/** Public shape of a network-status channel. */\r\nexport interface NetworkStatus {\r\n /**\r\n * Subscribe to changes. The listener is invoked immediately with the current\r\n * state when that state is non-null, so a late-mounting banner hydrates\r\n * instead of missing the transition. Returns an unsubscribe function suitable\r\n * for returning directly from `useEffect`.\r\n */\r\n subscribe(listener: NetworkStatusListener): () => void;\r\n /** Report a global network failure. `null` (or omitted) clears. */\r\n report(message?: string | null): void;\r\n /** Clear the banner. Equivalent to `report(null)`. */\r\n clear(): void;\r\n /** Current message, or `null`. Useful in tests and for SSR snapshots. */\r\n current(): string | null;\r\n}\r\n\r\n/**\r\n * Create an independent network-status channel.\r\n *\r\n * Exported alongside the shared singleton so tests can use an isolated instance\r\n * — a module-level singleton shared between test cases leaks state across them.\r\n * Application code should normally use the `networkStatus` export below.\r\n */\r\nexport function createNetworkStatus(): NetworkStatus {\r\n const subscribers = new Set<NetworkStatusListener>();\r\n let lastError: string | null = null;\r\n\r\n const channel: NetworkStatus = {\r\n subscribe(listener) {\r\n subscribers.add(listener);\r\n if (lastError !== null) listener(lastError);\r\n return () => {\r\n subscribers.delete(listener);\r\n };\r\n },\r\n\r\n report(message) {\r\n const next = message || null;\r\n /* De-duplicated: a flaky link can fail many times per second, and\r\n * re-notifying an unchanged message would re-render every subscriber for\r\n * no visible difference. */\r\n if (lastError === next) return;\r\n lastError = next;\r\n subscribers.forEach((listener) => {\r\n try {\r\n listener(lastError);\r\n } catch (e) {\r\n /* One bad subscriber must not stop the others from being notified,\r\n * and must not propagate into the transport layer that reported the\r\n * failure. */\r\n // eslint-disable-next-line no-console\r\n console.error(\"[@portnet/ui networkStatus] subscriber threw:\", e);\r\n }\r\n });\r\n },\r\n\r\n clear() {\r\n channel.report(null);\r\n },\r\n\r\n current() {\r\n return lastError;\r\n },\r\n };\r\n\r\n return channel;\r\n}\r\n\r\n/**\r\n * The shared channel. One per bundle, which is the right granularity: the\r\n * transport layer and the banner must agree, and both live in the same app.\r\n */\r\nexport const networkStatus: NetworkStatus = createNetworkStatus();\r\n\r\nexport default networkStatus;\r\n"],"mappings":"AAAA;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;;AAGA;;AAiBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,mBAAmBA,CAAA,EAAkB;EACnD,
|
|
1
|
+
{"version":3,"file":"networkStatus.js","names":["createNetworkStatus","subscribers","Set","lastError","channel","subscribe","listener","add","delete","report","message","next","forEach","e","console","error","clear","current","networkStatus"],"sources":["../../../../src/lib/v2/utils/networkStatus.ts"],"sourcesContent":["/**\r\n * networkStatus — the feed behind `NetworkErrorBanner`.\r\n *\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n * WHY THIS BELONGS IN THE LIBRARY (capability gap G-03)\r\n *\r\n * The library shipped `NetworkErrorBanner` — a presentational component — but\r\n * not the plumbing that decides when it appears. Charter R-A.3 / R-4.3 make the\r\n * banner MANDATORY (\"erreur réseau → bandeau persistant top, bouton\r\n * « Réessayer »\"), so every consuming module had to invent the same\r\n * subscribe / report / clear singleton and the same transport-interceptor\r\n * bridge. Two audited modules (`procuration-portnet-fe`, `procuration-fe`) had\r\n * each written their own.\r\n *\r\n * A presentational component whose trigger contract is left to consumers\r\n * guarantees divergence in precisely the state users encounter least often and\r\n * trust least — the offline path.\r\n *\r\n * NOT a redux slice, deliberately\r\n * -------------------------------\r\n * This state is presentation-only and high-frequency on a flaky link. Crossing a\r\n * dispatch boundary on every retry would slow the alert path for no benefit, and\r\n * would force the library to take an opinion on the host's store.\r\n *\r\n * Late subscribers are hydrated on subscribe, so a banner that mounts after the\r\n * failure (lazy route, remount) still shows the current state instead of missing\r\n * the edge.\r\n * ─────────────────────────────────────────────────────────────────────────────\r\n *\r\n * Wiring (once, at the app root):\r\n *\r\n * const [netError, setNetError] = useState<string | null>(null);\r\n * useEffect(() => networkStatus.subscribe(setNetError), []);\r\n *\r\n * <NetworkErrorBanner\r\n * visible={Boolean(netError)}\r\n * message={netError ?? \"\"}\r\n * onRetry={() => { networkStatus.clear(); window.location.reload(); }}\r\n * />\r\n *\r\n * And in the transport layer:\r\n *\r\n * instance.interceptors.response.use(\r\n * (response) => { networkStatus.clear(); return response; },\r\n * (error: unknown) => {\r\n * if (getApiErrorStatus(error) === undefined) {\r\n * networkStatus.report(\"Connexion perdue. Vérifiez votre réseau, puis réessayez.\");\r\n * }\r\n * return Promise.reject(error);\r\n * }\r\n * );\r\n *\r\n * A status-less failure is the network case (offline, DNS, ingress timeout); a\r\n * failure WITH a status is a server error and belongs in a toast (R-A.4).\r\n */\r\n\r\n/** Receives the latest banner message, or `null` when the banner should clear. */\r\nexport type NetworkStatusListener = (message: string | null) => void;\r\n\r\n/** Public shape of a network-status channel. */\r\nexport interface NetworkStatus {\r\n /**\r\n * Subscribe to changes. The listener is invoked immediately with the current\r\n * state when that state is non-null, so a late-mounting banner hydrates\r\n * instead of missing the transition. Returns an unsubscribe function suitable\r\n * for returning directly from `useEffect`.\r\n */\r\n subscribe(listener: NetworkStatusListener): () => void;\r\n /** Report a global network failure. `null` (or omitted) clears. */\r\n report(message?: string | null): void;\r\n /** Clear the banner. Equivalent to `report(null)`. */\r\n clear(): void;\r\n /** Current message, or `null`. Useful in tests and for SSR snapshots. */\r\n current(): string | null;\r\n}\r\n\r\n/**\r\n * Create an independent network-status channel.\r\n *\r\n * Exported alongside the shared singleton so tests can use an isolated instance\r\n * — a module-level singleton shared between test cases leaks state across them.\r\n * Application code should normally use the `networkStatus` export below.\r\n */\r\nexport function createNetworkStatus(): NetworkStatus {\r\n const subscribers = new Set<NetworkStatusListener>();\r\n let lastError: string | null = null;\r\n\r\n const channel: NetworkStatus = {\r\n subscribe(listener) {\r\n subscribers.add(listener);\r\n if (lastError !== null) listener(lastError);\r\n return () => {\r\n subscribers.delete(listener);\r\n };\r\n },\r\n\r\n report(message) {\r\n const next = message || null;\r\n /* De-duplicated: a flaky link can fail many times per second, and\r\n * re-notifying an unchanged message would re-render every subscriber for\r\n * no visible difference. */\r\n if (lastError === next) return;\r\n lastError = next;\r\n subscribers.forEach((listener) => {\r\n try {\r\n listener(lastError);\r\n } catch (e) {\r\n /* One bad subscriber must not stop the others from being notified,\r\n * and must not propagate into the transport layer that reported the\r\n * failure. */\r\n // eslint-disable-next-line no-console\r\n console.error(\"[@portnet/ui networkStatus] subscriber threw:\", e);\r\n }\r\n });\r\n },\r\n\r\n clear() {\r\n channel.report(null);\r\n },\r\n\r\n current() {\r\n return lastError;\r\n },\r\n };\r\n\r\n return channel;\r\n}\r\n\r\n/**\r\n * The shared channel. One per bundle, which is the right granularity: the\r\n * transport layer and the banner must agree, and both live in the same app.\r\n */\r\nexport const networkStatus: NetworkStatus = createNetworkStatus();\r\n\r\nexport default networkStatus;\r\n"],"mappings":"AAAA;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;;AAGA;;AAiBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,mBAAmBA,CAAA,EAAkB;EACnD,MAAMC,WAAW,GAAG,IAAIC,GAAG,CAAwB,CAAC;EACpD,IAAIC,SAAwB,GAAG,IAAI;EAEnC,MAAMC,OAAsB,GAAG;IAC7BC,SAASA,CAACC,QAAQ,EAAE;MAClBL,WAAW,CAACM,GAAG,CAACD,QAAQ,CAAC;MACzB,IAAIH,SAAS,KAAK,IAAI,EAAEG,QAAQ,CAACH,SAAS,CAAC;MAC3C,OAAO,MAAM;QACXF,WAAW,CAACO,MAAM,CAACF,QAAQ,CAAC;MAC9B,CAAC;IACH,CAAC;IAEDG,MAAMA,CAACC,OAAO,EAAE;MACd,MAAMC,IAAI,GAAGD,OAAO,IAAI,IAAI;MAC5B;AACN;AACA;MACM,IAAIP,SAAS,KAAKQ,IAAI,EAAE;MACxBR,SAAS,GAAGQ,IAAI;MAChBV,WAAW,CAACW,OAAO,CAAEN,QAAQ,IAAK;QAChC,IAAI;UACFA,QAAQ,CAACH,SAAS,CAAC;QACrB,CAAC,CAAC,OAAOU,CAAC,EAAE;UACV;AACV;AACA;UACU;UACAC,OAAO,CAACC,KAAK,CAAC,+CAA+C,EAAEF,CAAC,CAAC;QACnE;MACF,CAAC,CAAC;IACJ,CAAC;IAEDG,KAAKA,CAAA,EAAG;MACNZ,OAAO,CAACK,MAAM,CAAC,IAAI,CAAC;IACtB,CAAC;IAEDQ,OAAOA,CAAA,EAAG;MACR,OAAOd,SAAS;IAClB;EACF,CAAC;EAED,OAAOC,OAAO;AAChB;;AAEA;AACA;AACA;AACA;AACA,OAAO,MAAMc,aAA4B,GAAGlB,mBAAmB,CAAC,CAAC;AAEjE,eAAekB,aAAa","ignoreList":[]}
|