@orcestr/ui 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -0
- package/README.ru.md +151 -0
- package/assets/orcestr-banner.webp +0 -0
- package/dist/components/Action/ActionConfirmModal.d.ts +8 -0
- package/dist/components/Action/ActionConfirmModal.d.ts.map +1 -0
- package/dist/components/Action/ActionConfirmModal.js +13 -0
- package/dist/components/Action/ActionTypes.d.ts +47 -0
- package/dist/components/Action/ActionTypes.d.ts.map +1 -0
- package/dist/components/Action/ActionTypes.js +49 -0
- package/dist/components/ActionMenu/ActionMenu.d.ts +3 -0
- package/dist/components/ActionMenu/ActionMenu.d.ts.map +1 -0
- package/dist/components/ActionMenu/ActionMenu.js +1 -0
- package/dist/components/Alert/Alert.d.ts +11 -0
- package/dist/components/Alert/Alert.d.ts.map +1 -0
- package/dist/components/Alert/Alert.js +7 -0
- package/dist/components/AppShell/AppShell.d.ts +102 -0
- package/dist/components/AppShell/AppShell.d.ts.map +1 -0
- package/dist/components/AppShell/AppShell.js +96 -0
- package/dist/components/Badge/Badge.d.ts +15 -0
- package/dist/components/Badge/Badge.d.ts.map +1 -0
- package/dist/components/Badge/Badge.js +8 -0
- package/dist/components/Box/Box.d.ts +11 -0
- package/dist/components/Box/Box.d.ts.map +1 -0
- package/dist/components/Box/Box.js +8 -0
- package/dist/components/Button/Button.d.ts +27 -0
- package/dist/components/Button/Button.d.ts.map +1 -0
- package/dist/components/Button/Button.js +13 -0
- package/dist/components/Checkbox/Checkbox.d.ts +10 -0
- package/dist/components/Checkbox/Checkbox.d.ts.map +1 -0
- package/dist/components/Checkbox/Checkbox.js +15 -0
- package/dist/components/Collapse/Collapse.d.ts +11 -0
- package/dist/components/Collapse/Collapse.d.ts.map +1 -0
- package/dist/components/Collapse/Collapse.js +33 -0
- package/dist/components/Combobox/Combobox.d.ts +17 -0
- package/dist/components/Combobox/Combobox.d.ts.map +1 -0
- package/dist/components/Combobox/Combobox.js +32 -0
- package/dist/components/CommandPalette/CommandPalette.d.ts +21 -0
- package/dist/components/CommandPalette/CommandPalette.d.ts.map +1 -0
- package/dist/components/CommandPalette/CommandPalette.js +168 -0
- package/dist/components/ConfirmDialog/ConfirmDialog.d.ts +25 -0
- package/dist/components/ConfirmDialog/ConfirmDialog.d.ts.map +1 -0
- package/dist/components/ConfirmDialog/ConfirmDialog.js +25 -0
- package/dist/components/ContextMenu/ContextMenu.d.ts +11 -0
- package/dist/components/ContextMenu/ContextMenu.d.ts.map +1 -0
- package/dist/components/ContextMenu/ContextMenu.js +68 -0
- package/dist/components/DataTable/DataTable.d.ts +88 -0
- package/dist/components/DataTable/DataTable.d.ts.map +1 -0
- package/dist/components/DataTable/DataTable.js +415 -0
- package/dist/components/DataTable/DataTableStateAdapters.d.ts +41 -0
- package/dist/components/DataTable/DataTableStateAdapters.d.ts.map +1 -0
- package/dist/components/DataTable/DataTableStateAdapters.js +192 -0
- package/dist/components/DatePicker/DatePicker.d.ts +21 -0
- package/dist/components/DatePicker/DatePicker.d.ts.map +1 -0
- package/dist/components/DatePicker/DatePicker.js +39 -0
- package/dist/components/DatePicker/DatePickerState.d.ts +30 -0
- package/dist/components/DatePicker/DatePickerState.d.ts.map +1 -0
- package/dist/components/DatePicker/DatePickerState.js +106 -0
- package/dist/components/DateRangePicker/DateRangePicker.d.ts +19 -0
- package/dist/components/DateRangePicker/DateRangePicker.d.ts.map +1 -0
- package/dist/components/DateRangePicker/DateRangePicker.js +6 -0
- package/dist/components/DateRangePresetPicker/DateRangePresetPicker.d.ts +10 -0
- package/dist/components/DateRangePresetPicker/DateRangePresetPicker.d.ts.map +1 -0
- package/dist/components/DateRangePresetPicker/DateRangePresetPicker.js +26 -0
- package/dist/components/DateRangePresetPicker/DateRangePresetPickerState.d.ts +4 -0
- package/dist/components/DateRangePresetPicker/DateRangePresetPickerState.d.ts.map +1 -0
- package/dist/components/DateRangePresetPicker/DateRangePresetPickerState.js +20 -0
- package/dist/components/Dialog/Dialog.d.ts +2 -0
- package/dist/components/Dialog/Dialog.d.ts.map +1 -0
- package/dist/components/Dialog/Dialog.js +1 -0
- package/dist/components/Drawer/Drawer.d.ts +30 -0
- package/dist/components/Drawer/Drawer.d.ts.map +1 -0
- package/dist/components/Drawer/Drawer.js +83 -0
- package/dist/components/EntityPicker/EntityPicker.d.ts +41 -0
- package/dist/components/EntityPicker/EntityPicker.d.ts.map +1 -0
- package/dist/components/EntityPicker/EntityPicker.js +17 -0
- package/dist/components/Field/Field.d.ts +12 -0
- package/dist/components/Field/Field.d.ts.map +1 -0
- package/dist/components/Field/Field.js +8 -0
- package/dist/components/Flex/Flex.d.ts +9 -0
- package/dist/components/Flex/Flex.d.ts.map +1 -0
- package/dist/components/Flex/Flex.js +8 -0
- package/dist/components/Grid/Grid.d.ts +11 -0
- package/dist/components/Grid/Grid.d.ts.map +1 -0
- package/dist/components/Grid/Grid.js +12 -0
- package/dist/components/Highlight/Highlight.d.ts +27 -0
- package/dist/components/Highlight/Highlight.d.ts.map +1 -0
- package/dist/components/Highlight/Highlight.js +26 -0
- package/dist/components/IconButton/IconButton.d.ts +25 -0
- package/dist/components/IconButton/IconButton.d.ts.map +1 -0
- package/dist/components/IconButton/IconButton.js +13 -0
- package/dist/components/IconText/IconText.d.ts +12 -0
- package/dist/components/IconText/IconText.d.ts.map +1 -0
- package/dist/components/IconText/IconText.js +7 -0
- package/dist/components/Listbox/Listbox.d.ts +13 -0
- package/dist/components/Listbox/Listbox.d.ts.map +1 -0
- package/dist/components/Listbox/Listbox.js +74 -0
- package/dist/components/Menu/Menu.d.ts +14 -0
- package/dist/components/Menu/Menu.d.ts.map +1 -0
- package/dist/components/Menu/Menu.js +168 -0
- package/dist/components/Modal/Modal.d.ts +29 -0
- package/dist/components/Modal/Modal.d.ts.map +1 -0
- package/dist/components/Modal/Modal.js +155 -0
- package/dist/components/MultiSelect/MultiSelect.d.ts +21 -0
- package/dist/components/MultiSelect/MultiSelect.d.ts.map +1 -0
- package/dist/components/MultiSelect/MultiSelect.js +139 -0
- package/dist/components/NumberField/NumberField.d.ts +4 -0
- package/dist/components/NumberField/NumberField.d.ts.map +1 -0
- package/dist/components/NumberField/NumberField.js +6 -0
- package/dist/components/Overlay/OverlayProvider.d.ts +19 -0
- package/dist/components/Overlay/OverlayProvider.d.ts.map +1 -0
- package/dist/components/Overlay/OverlayProvider.js +73 -0
- package/dist/components/PaginatedCombobox/PaginatedCombobox.d.ts +48 -0
- package/dist/components/PaginatedCombobox/PaginatedCombobox.d.ts.map +1 -0
- package/dist/components/PaginatedCombobox/PaginatedCombobox.js +223 -0
- package/dist/components/PaginatedCombobox/PaginatedComboboxReactQueryAdapter.d.ts +13 -0
- package/dist/components/PaginatedCombobox/PaginatedComboboxReactQueryAdapter.d.ts.map +1 -0
- package/dist/components/PaginatedCombobox/PaginatedComboboxReactQueryAdapter.js +10 -0
- package/dist/components/Pagination/Pagination.d.ts +7 -0
- package/dist/components/Pagination/Pagination.d.ts.map +1 -0
- package/dist/components/Pagination/Pagination.js +9 -0
- package/dist/components/Popover/Popover.d.ts +19 -0
- package/dist/components/Popover/Popover.d.ts.map +1 -0
- package/dist/components/Popover/Popover.js +83 -0
- package/dist/components/Portal/Portal.d.ts +6 -0
- package/dist/components/Portal/Portal.d.ts.map +1 -0
- package/dist/components/Portal/Portal.js +23 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts +14 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts.map +1 -0
- package/dist/components/RadioGroup/RadioGroup.js +6 -0
- package/dist/components/ScrollArea/ScrollArea.d.ts +36 -0
- package/dist/components/ScrollArea/ScrollArea.d.ts.map +1 -0
- package/dist/components/ScrollArea/ScrollArea.js +124 -0
- package/dist/components/Section/Section.d.ts +14 -0
- package/dist/components/Section/Section.d.ts.map +1 -0
- package/dist/components/Section/Section.js +20 -0
- package/dist/components/SegmentedControl/SegmentedControl.d.ts +13 -0
- package/dist/components/SegmentedControl/SegmentedControl.d.ts.map +1 -0
- package/dist/components/SegmentedControl/SegmentedControl.js +6 -0
- package/dist/components/Select/Select.d.ts +27 -0
- package/dist/components/Select/Select.d.ts.map +1 -0
- package/dist/components/Select/Select.js +142 -0
- package/dist/components/Separator/Separator.d.ts +6 -0
- package/dist/components/Separator/Separator.d.ts.map +1 -0
- package/dist/components/Separator/Separator.js +5 -0
- package/dist/components/Skeleton/Skeleton.d.ts +9 -0
- package/dist/components/Skeleton/Skeleton.d.ts.map +1 -0
- package/dist/components/Skeleton/Skeleton.js +8 -0
- package/dist/components/Spinner/Spinner.d.ts +7 -0
- package/dist/components/Spinner/Spinner.d.ts.map +1 -0
- package/dist/components/Spinner/Spinner.js +5 -0
- package/dist/components/Stack/Stack.d.ts +9 -0
- package/dist/components/Stack/Stack.d.ts.map +1 -0
- package/dist/components/Stack/Stack.js +7 -0
- package/dist/components/State/State.d.ts +23 -0
- package/dist/components/State/State.d.ts.map +1 -0
- package/dist/components/State/State.js +30 -0
- package/dist/components/State/stateIcon.d.ts +3 -0
- package/dist/components/State/stateIcon.d.ts.map +1 -0
- package/dist/components/State/stateIcon.js +11 -0
- package/dist/components/StepperInput/StepperInput.d.ts +13 -0
- package/dist/components/StepperInput/StepperInput.d.ts.map +1 -0
- package/dist/components/StepperInput/StepperInput.js +22 -0
- package/dist/components/Switch/Switch.d.ts +10 -0
- package/dist/components/Switch/Switch.d.ts.map +1 -0
- package/dist/components/Switch/Switch.js +14 -0
- package/dist/components/Tabs/Tabs.d.ts +18 -0
- package/dist/components/Tabs/Tabs.d.ts.map +1 -0
- package/dist/components/Tabs/Tabs.js +104 -0
- package/dist/components/Text/Text.d.ts +13 -0
- package/dist/components/Text/Text.d.ts.map +1 -0
- package/dist/components/Text/Text.js +8 -0
- package/dist/components/TextArea/TextArea.d.ts +15 -0
- package/dist/components/TextArea/TextArea.d.ts.map +1 -0
- package/dist/components/TextArea/TextArea.js +17 -0
- package/dist/components/TextField/TextField.d.ts +25 -0
- package/dist/components/TextField/TextField.d.ts.map +1 -0
- package/dist/components/TextField/TextField.js +31 -0
- package/dist/components/Toast/Toast.d.ts +43 -0
- package/dist/components/Toast/Toast.d.ts.map +1 -0
- package/dist/components/Toast/Toast.js +205 -0
- package/dist/components/Tooltip/Tooltip.d.ts +10 -0
- package/dist/components/Tooltip/Tooltip.d.ts.map +1 -0
- package/dist/components/Tooltip/Tooltip.js +24 -0
- package/dist/components/VisuallyHidden/VisuallyHidden.d.ts +8 -0
- package/dist/components/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
- package/dist/components/VisuallyHidden/VisuallyHidden.js +6 -0
- package/dist/components/Workflow/Workflow.d.ts +82 -0
- package/dist/components/Workflow/Workflow.d.ts.map +1 -0
- package/dist/components/Workflow/Workflow.js +73 -0
- package/dist/example/CodePreview.d.ts +25 -0
- package/dist/example/CodePreview.d.ts.map +1 -0
- package/dist/example/CodePreview.js +93 -0
- package/dist/example/ExampleActionsSection.d.ts +10 -0
- package/dist/example/ExampleActionsSection.d.ts.map +1 -0
- package/dist/example/ExampleActionsSection.js +10 -0
- package/dist/example/ExampleBasicsSections.d.ts +8 -0
- package/dist/example/ExampleBasicsSections.d.ts.map +1 -0
- package/dist/example/ExampleBasicsSections.js +43 -0
- package/dist/example/ExampleDataSection.d.ts +7 -0
- package/dist/example/ExampleDataSection.d.ts.map +1 -0
- package/dist/example/ExampleDataSection.js +124 -0
- package/dist/example/ExampleFieldsSection.d.ts +17 -0
- package/dist/example/ExampleFieldsSection.d.ts.map +1 -0
- package/dist/example/ExampleFieldsSection.js +10 -0
- package/dist/example/ExampleFoundationsSection.d.ts +5 -0
- package/dist/example/ExampleFoundationsSection.d.ts.map +1 -0
- package/dist/example/ExampleFoundationsSection.js +25 -0
- package/dist/example/ExampleOverlays.d.ts +30 -0
- package/dist/example/ExampleOverlays.d.ts.map +1 -0
- package/dist/example/ExampleOverlays.js +12 -0
- package/dist/example/ExampleOverlaysSection.d.ts +14 -0
- package/dist/example/ExampleOverlaysSection.d.ts.map +1 -0
- package/dist/example/ExampleOverlaysSection.js +126 -0
- package/dist/example/ExampleSelectionSection.d.ts +30 -0
- package/dist/example/ExampleSelectionSection.d.ts.map +1 -0
- package/dist/example/ExampleSelectionSection.js +66 -0
- package/dist/example/ExampleStateSection.d.ts +8 -0
- package/dist/example/ExampleStateSection.d.ts.map +1 -0
- package/dist/example/ExampleStateSection.js +76 -0
- package/dist/example/ExampleThemePlayground.d.ts +417 -0
- package/dist/example/ExampleThemePlayground.d.ts.map +1 -0
- package/dist/example/ExampleThemePlayground.js +596 -0
- package/dist/example/UiExamplePage.d.ts +2 -0
- package/dist/example/UiExamplePage.d.ts.map +1 -0
- package/dist/example/UiExamplePage.js +315 -0
- package/dist/example/UiExampleSection.d.ts +8 -0
- package/dist/example/UiExampleSection.d.ts.map +1 -0
- package/dist/example/UiExampleSection.js +5 -0
- package/dist/example/codeSamples.d.ts +30 -0
- package/dist/example/codeSamples.d.ts.map +1 -0
- package/dist/example/codeSamples.js +976 -0
- package/dist/example/exampleData.d.ts +33 -0
- package/dist/example/exampleData.d.ts.map +1 -0
- package/dist/example/exampleData.js +217 -0
- package/dist/example/styles.css +1106 -0
- package/dist/hooks/useControllableState.d.ts +6 -0
- package/dist/hooks/useControllableState.d.ts.map +1 -0
- package/dist/hooks/useControllableState.js +16 -0
- package/dist/hooks/useDisclosure.d.ts +12 -0
- package/dist/hooks/useDisclosure.d.ts.map +1 -0
- package/dist/hooks/useDisclosure.js +14 -0
- package/dist/hooks/useEscapeKey.d.ts +2 -0
- package/dist/hooks/useEscapeKey.d.ts.map +1 -0
- package/dist/hooks/useEscapeKey.js +15 -0
- package/dist/hooks/useFloatingLayer.d.ts +19 -0
- package/dist/hooks/useFloatingLayer.d.ts.map +1 -0
- package/dist/hooks/useFloatingLayer.js +26 -0
- package/dist/hooks/useFloatingPosition.d.ts +17 -0
- package/dist/hooks/useFloatingPosition.d.ts.map +1 -0
- package/dist/hooks/useFloatingPosition.js +132 -0
- package/dist/hooks/useFocusTrap.d.ts +3 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -0
- package/dist/hooks/useFocusTrap.js +54 -0
- package/dist/hooks/useListNavigation.d.ts +17 -0
- package/dist/hooks/useListNavigation.d.ts.map +1 -0
- package/dist/hooks/useListNavigation.js +44 -0
- package/dist/hooks/useOutsidePointerDown.d.ts +3 -0
- package/dist/hooks/useOutsidePointerDown.d.ts.map +1 -0
- package/dist/hooks/useOutsidePointerDown.js +20 -0
- package/dist/hooks/usePresence.d.ts +5 -0
- package/dist/hooks/usePresence.d.ts.map +1 -0
- package/dist/hooks/usePresence.js +35 -0
- package/dist/hooks/useTypeahead.d.ts +2 -0
- package/dist/hooks/useTypeahead.d.ts.map +1 -0
- package/dist/hooks/useTypeahead.js +23 -0
- package/dist/index.d.ts +64 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +64 -0
- package/dist/locale/LocaleProvider.d.ts +89 -0
- package/dist/locale/LocaleProvider.d.ts.map +1 -0
- package/dist/locale/LocaleProvider.js +174 -0
- package/dist/provider/OrcestrUiProvider.d.ts +28 -0
- package/dist/provider/OrcestrUiProvider.d.ts.map +1 -0
- package/dist/provider/OrcestrUiProvider.js +9 -0
- package/dist/react-query.d.ts +2 -0
- package/dist/react-query.d.ts.map +1 -0
- package/dist/react-query.js +1 -0
- package/dist/styles/orcestr-ui.css +4676 -0
- package/dist/theme/ThemeProvider.d.ts +3 -0
- package/dist/theme/ThemeProvider.d.ts.map +1 -0
- package/dist/theme/ThemeProvider.js +280 -0
- package/dist/theme/defaultTheme.d.ts +12 -0
- package/dist/theme/defaultTheme.d.ts.map +1 -0
- package/dist/theme/defaultTheme.js +516 -0
- package/dist/theme/systemProps.d.ts +53 -0
- package/dist/theme/systemProps.d.ts.map +1 -0
- package/dist/theme/systemProps.js +240 -0
- package/dist/theme/themeTypes.d.ts +197 -0
- package/dist/theme/themeTypes.d.ts.map +1 -0
- package/dist/theme/themeTypes.js +1 -0
- package/dist/theme/useTheme.d.ts +4 -0
- package/dist/theme/useTheme.d.ts.map +1 -0
- package/dist/theme/useTheme.js +10 -0
- package/dist/utils/cn.d.ts +2 -0
- package/dist/utils/cn.d.ts.map +1 -0
- package/dist/utils/cn.js +3 -0
- package/dist/utils/composeRefs.d.ts +3 -0
- package/dist/utils/composeRefs.d.ts.map +1 -0
- package/dist/utils/composeRefs.js +14 -0
- package/dist/utils/mergeProps.d.ts +4 -0
- package/dist/utils/mergeProps.d.ts.map +1 -0
- package/dist/utils/mergeProps.js +26 -0
- package/dist/utils/ownerDocument.d.ts +2 -0
- package/dist/utils/ownerDocument.d.ts.map +1 -0
- package/dist/utils/ownerDocument.js +3 -0
- package/dist/utils/polymorphic.d.ts +6 -0
- package/dist/utils/polymorphic.d.ts.map +1 -0
- package/dist/utils/polymorphic.js +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
export function dataTablePreferenceStorageKey(scope) {
|
|
2
|
+
const tenant = scope.tenantId ?? 'global';
|
|
3
|
+
const user = scope.userId ?? 'anonymous';
|
|
4
|
+
return `orcestr-ui:data-table:${tenant}:${user}:${scope.tableKey}`;
|
|
5
|
+
}
|
|
6
|
+
export function readDataTableState(scope, storage = browserStorage()) {
|
|
7
|
+
if (!storage)
|
|
8
|
+
return null;
|
|
9
|
+
const raw = storage.getItem(dataTablePreferenceStorageKey(scope));
|
|
10
|
+
if (!raw)
|
|
11
|
+
return null;
|
|
12
|
+
try {
|
|
13
|
+
return normalizeDataTableState(JSON.parse(raw));
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function writeDataTableState(scope, state, storage = browserStorage()) {
|
|
20
|
+
if (!storage)
|
|
21
|
+
return;
|
|
22
|
+
storage.setItem(dataTablePreferenceStorageKey(scope), JSON.stringify(state));
|
|
23
|
+
}
|
|
24
|
+
export function clearDataTableState(scope, storage = browserStorage()) {
|
|
25
|
+
storage?.removeItem(dataTablePreferenceStorageKey(scope));
|
|
26
|
+
}
|
|
27
|
+
export function dataTableStateToSearchParams(state) {
|
|
28
|
+
const params = new URLSearchParams();
|
|
29
|
+
if (state.visibleColumnKeys?.length)
|
|
30
|
+
params.set('columns', state.visibleColumnKeys.join(','));
|
|
31
|
+
if (state.columnOrder?.length)
|
|
32
|
+
params.set('column_order', state.columnOrder.join(','));
|
|
33
|
+
if (state.columnWidths && Object.keys(state.columnWidths).length > 0) {
|
|
34
|
+
params.set('column_widths', serializeColumnWidths(state.columnWidths));
|
|
35
|
+
}
|
|
36
|
+
if (state.sort?.length) {
|
|
37
|
+
params.set('sort', state.sort.map((item) => `${encodeURIComponent(item.key)}:${item.direction}`).join(','));
|
|
38
|
+
}
|
|
39
|
+
if (state.page)
|
|
40
|
+
params.set('page', String(state.page));
|
|
41
|
+
if (state.pageSize)
|
|
42
|
+
params.set('page_size', String(state.pageSize));
|
|
43
|
+
if (state.savedViewKey)
|
|
44
|
+
params.set('view', state.savedViewKey);
|
|
45
|
+
return params;
|
|
46
|
+
}
|
|
47
|
+
export function dataTableStateFromSearchParams(params) {
|
|
48
|
+
return normalizeDataTableState({
|
|
49
|
+
visibleColumnKeys: splitParam(params.get('columns')),
|
|
50
|
+
columnOrder: splitParam(params.get('column_order')),
|
|
51
|
+
columnWidths: parseColumnWidthsParam(params.get('column_widths')),
|
|
52
|
+
sort: parseSortParam(params.get('sort')),
|
|
53
|
+
page: parsePositiveInt(params.get('page')),
|
|
54
|
+
pageSize: parsePositiveInt(params.get('page_size')),
|
|
55
|
+
savedViewKey: params.get('view') || undefined,
|
|
56
|
+
}) ?? {};
|
|
57
|
+
}
|
|
58
|
+
export function dataTablePaginationToSearchParams({ page, pageSize, }) {
|
|
59
|
+
return dataTableStateToSearchParams({ page, pageSize });
|
|
60
|
+
}
|
|
61
|
+
export function dataTablePaginationFromSearchParams(params) {
|
|
62
|
+
const state = dataTableStateFromSearchParams(params);
|
|
63
|
+
return {
|
|
64
|
+
page: state.page,
|
|
65
|
+
pageSize: state.pageSize,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export function resolveDataTableState({ defaultState, persistedState, urlState, }) {
|
|
69
|
+
return {
|
|
70
|
+
...defaultState,
|
|
71
|
+
...persistedState,
|
|
72
|
+
...urlState,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export function defaultDataTableSavedView(views) {
|
|
76
|
+
return views.find((view) => view.default) ?? null;
|
|
77
|
+
}
|
|
78
|
+
export function applyDataTableSavedView(state, view) {
|
|
79
|
+
return compactDataTableState({
|
|
80
|
+
...state,
|
|
81
|
+
visibleColumnKeys: view.visibleColumnKeys,
|
|
82
|
+
columnOrder: view.columnOrder,
|
|
83
|
+
columnWidths: view.columnWidths,
|
|
84
|
+
sort: view.sort,
|
|
85
|
+
page: view.page,
|
|
86
|
+
pageSize: view.pageSize,
|
|
87
|
+
savedViewKey: view.key,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
export function resetDataTableStateToDefault(defaultState = {}) {
|
|
91
|
+
return { ...defaultState };
|
|
92
|
+
}
|
|
93
|
+
function browserStorage() {
|
|
94
|
+
if (typeof window === 'undefined')
|
|
95
|
+
return null;
|
|
96
|
+
return window.localStorage;
|
|
97
|
+
}
|
|
98
|
+
function normalizeDataTableState(value) {
|
|
99
|
+
if (!isRecord(value))
|
|
100
|
+
return null;
|
|
101
|
+
return compactDataTableState({
|
|
102
|
+
visibleColumnKeys: stringArray(value.visibleColumnKeys),
|
|
103
|
+
columnOrder: stringArray(value.columnOrder),
|
|
104
|
+
columnWidths: columnWidthsRecord(value.columnWidths),
|
|
105
|
+
sort: sortArray(value.sort),
|
|
106
|
+
page: typeof value.page === 'number' && value.page > 0 ? value.page : undefined,
|
|
107
|
+
pageSize: typeof value.pageSize === 'number' && value.pageSize > 0 ? value.pageSize : undefined,
|
|
108
|
+
savedViewKey: typeof value.savedViewKey === 'string' ? value.savedViewKey : undefined,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
function compactDataTableState(state) {
|
|
112
|
+
return Object.fromEntries(Object.entries(state).filter(([, value]) => value !== undefined));
|
|
113
|
+
}
|
|
114
|
+
function stringArray(value) {
|
|
115
|
+
if (!Array.isArray(value))
|
|
116
|
+
return undefined;
|
|
117
|
+
const result = value.filter((item) => typeof item === 'string' && item.length > 0);
|
|
118
|
+
return result.length ? result : undefined;
|
|
119
|
+
}
|
|
120
|
+
function sortArray(value) {
|
|
121
|
+
if (!Array.isArray(value))
|
|
122
|
+
return undefined;
|
|
123
|
+
const result = value.filter(isSort);
|
|
124
|
+
return result.length ? result : undefined;
|
|
125
|
+
}
|
|
126
|
+
function columnWidthsRecord(value) {
|
|
127
|
+
if (!isRecord(value))
|
|
128
|
+
return undefined;
|
|
129
|
+
const result = {};
|
|
130
|
+
for (const [key, width] of Object.entries(value)) {
|
|
131
|
+
if (!key || typeof width !== 'number' || !Number.isFinite(width) || width <= 0)
|
|
132
|
+
continue;
|
|
133
|
+
result[key] = Math.round(width);
|
|
134
|
+
}
|
|
135
|
+
return Object.keys(result).length ? result : undefined;
|
|
136
|
+
}
|
|
137
|
+
function serializeColumnWidths(widths) {
|
|
138
|
+
return Object.entries(widths)
|
|
139
|
+
.filter(([, width]) => Number.isFinite(width) && width > 0)
|
|
140
|
+
.map(([key, width]) => `${encodeURIComponent(key)}:${Math.round(width)}`)
|
|
141
|
+
.join(',');
|
|
142
|
+
}
|
|
143
|
+
function parseColumnWidthsParam(value) {
|
|
144
|
+
if (!value)
|
|
145
|
+
return undefined;
|
|
146
|
+
const result = {};
|
|
147
|
+
for (const item of value.split(',')) {
|
|
148
|
+
const [encodedKey, rawWidth] = item.split(':');
|
|
149
|
+
const key = decodeURIComponent(encodedKey ?? '');
|
|
150
|
+
const width = Number.parseInt(rawWidth ?? '', 10);
|
|
151
|
+
if (!key || !Number.isFinite(width) || width <= 0)
|
|
152
|
+
continue;
|
|
153
|
+
result[key] = width;
|
|
154
|
+
}
|
|
155
|
+
return Object.keys(result).length ? result : undefined;
|
|
156
|
+
}
|
|
157
|
+
function parseSortParam(value) {
|
|
158
|
+
if (!value)
|
|
159
|
+
return undefined;
|
|
160
|
+
const result = value
|
|
161
|
+
.split(',')
|
|
162
|
+
.map((item) => {
|
|
163
|
+
const [key, direction] = item.split(':');
|
|
164
|
+
return {
|
|
165
|
+
key: decodeURIComponent(key ?? ''),
|
|
166
|
+
direction,
|
|
167
|
+
};
|
|
168
|
+
})
|
|
169
|
+
.filter(isSort);
|
|
170
|
+
return result.length ? result : undefined;
|
|
171
|
+
}
|
|
172
|
+
function splitParam(value) {
|
|
173
|
+
if (!value)
|
|
174
|
+
return undefined;
|
|
175
|
+
const result = value.split(',').filter(Boolean);
|
|
176
|
+
return result.length ? result : undefined;
|
|
177
|
+
}
|
|
178
|
+
function parsePositiveInt(value) {
|
|
179
|
+
if (!value)
|
|
180
|
+
return undefined;
|
|
181
|
+
const parsed = Number.parseInt(value, 10);
|
|
182
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
|
|
183
|
+
}
|
|
184
|
+
function isSort(value) {
|
|
185
|
+
if (!isRecord(value))
|
|
186
|
+
return false;
|
|
187
|
+
return (typeof value.key === 'string' &&
|
|
188
|
+
(value.direction === 'asc' || value.direction === 'desc'));
|
|
189
|
+
}
|
|
190
|
+
function isRecord(value) {
|
|
191
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
192
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type DatePickerDisabledDate } from './DatePickerState';
|
|
3
|
+
export type DatePickerProps = {
|
|
4
|
+
value: string;
|
|
5
|
+
onValueChange: (value: string) => void;
|
|
6
|
+
min?: string;
|
|
7
|
+
max?: string;
|
|
8
|
+
disabledDate?: DatePickerDisabledDate;
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
clearable?: boolean;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
readOnly?: boolean;
|
|
13
|
+
openCalendarLabel?: string;
|
|
14
|
+
previousMonthLabel?: string;
|
|
15
|
+
nextMonthLabel?: string;
|
|
16
|
+
todayLabel?: ReactNode;
|
|
17
|
+
locale?: string;
|
|
18
|
+
testId?: string;
|
|
19
|
+
};
|
|
20
|
+
export declare function DatePicker({ value, onValueChange, min, max, disabledDate, placeholder, clearable, disabled, readOnly, openCalendarLabel, previousMonthLabel, nextMonthLabel, todayLabel, locale, testId, }: DatePickerProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
//# sourceMappingURL=DatePicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DatePicker.d.ts","sourceRoot":"","sources":["../../../src/components/DatePicker/DatePicker.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAoB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAQxD,OAAO,EAQH,KAAK,sBAAsB,EAC9B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,eAAe,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,sBAAsB,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,UAAU,CAAC,EACvB,KAAK,EACL,aAAa,EACb,GAAG,EACH,GAAG,EACH,YAAY,EACZ,WAAW,EACX,SAAgB,EAChB,QAAgB,EAChB,QAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,MAAM,EACN,MAAM,GACT,EAAE,eAAe,2CAiIjB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo, useState } from 'react';
|
|
4
|
+
import { LuCalendarDays, LuChevronLeft, LuChevronRight } from 'react-icons/lu';
|
|
5
|
+
import { useOrcestrUiLocale } from '../../locale/LocaleProvider';
|
|
6
|
+
import { Button } from '../Button/Button';
|
|
7
|
+
import { IconButton } from '../IconButton/IconButton';
|
|
8
|
+
import { Popover } from '../Popover/Popover';
|
|
9
|
+
import { TextField } from '../TextField/TextField';
|
|
10
|
+
import { calendarMonthState, clampDate, formatDateLabel, formatMonthLabel, monthCursorForDate, shiftMonth, weekdayLabels, } from './DatePickerState';
|
|
11
|
+
export function DatePicker({ value, onValueChange, min, max, disabledDate, placeholder, clearable = true, disabled = false, readOnly = false, openCalendarLabel, previousMonthLabel, nextMonthLabel, todayLabel, locale, testId, }) {
|
|
12
|
+
const { copy, locale: contextLocale } = useOrcestrUiLocale();
|
|
13
|
+
const actualLocale = locale ?? contextLocale;
|
|
14
|
+
const [open, setOpen] = useState(false);
|
|
15
|
+
const [cursorMonth, setCursorMonth] = useState(() => monthCursorForDate(value));
|
|
16
|
+
const monthState = useMemo(() => calendarMonthState({
|
|
17
|
+
cursorMonth,
|
|
18
|
+
selectedDate: value,
|
|
19
|
+
min,
|
|
20
|
+
max,
|
|
21
|
+
disabledDate,
|
|
22
|
+
}), [cursorMonth, disabledDate, max, min, value]);
|
|
23
|
+
const weekdays = useMemo(() => weekdayLabels(actualLocale), [actualLocale]);
|
|
24
|
+
const displayValue = value ? formatDateLabel(value, actualLocale) : '';
|
|
25
|
+
const selectDate = (nextValue) => {
|
|
26
|
+
onValueChange(clampDate(nextValue, min, max));
|
|
27
|
+
setOpen(false);
|
|
28
|
+
};
|
|
29
|
+
return (_jsx(Popover, { open: open, onOpenChange: (nextOpen) => {
|
|
30
|
+
if (readOnly && nextOpen)
|
|
31
|
+
return;
|
|
32
|
+
if (nextOpen)
|
|
33
|
+
setCursorMonth(monthCursorForDate(value));
|
|
34
|
+
setOpen(nextOpen);
|
|
35
|
+
}, disabled: disabled || readOnly, matchTriggerWidth: false, sideOffset: 6, testId: testId ? `${testId}-popover` : undefined, trigger: _jsx(TextField, { value: displayValue, placeholder: placeholder, readOnly: true, disabled: disabled, clearable: clearable && Boolean(value) && !readOnly, testId: testId, "aria-label": openCalendarLabel ?? copy.common.openCalendar, onClear: () => onValueChange(''), rightSlot: _jsx("span", { className: 'oui-date-picker-trigger', "aria-hidden": true, children: _jsx(LuCalendarDays, { size: 16 }) }) }), className: 'oui-date-picker-popover', children: _jsxs("div", { className: 'oui-date-picker-panel', children: [_jsxs("div", { className: 'oui-date-picker-head', children: [_jsx(IconButton, { size: 1, v: 'ghost', type: 'button', icon: _jsx(LuChevronLeft, { size: 16 }), "aria-label": previousMonthLabel ?? copy.common.previous, onClick: () => setCursorMonth((current) => shiftMonth(current, -1)) }), _jsx("strong", { children: formatMonthLabel(cursorMonth, actualLocale) }), _jsx(IconButton, { size: 1, v: 'ghost', type: 'button', icon: _jsx(LuChevronRight, { size: 16 }), "aria-label": nextMonthLabel ?? copy.common.next, onClick: () => setCursorMonth((current) => shiftMonth(current, 1)) })] }), _jsx("div", { className: 'oui-date-picker-weekdays', children: weekdays.map((weekday) => (_jsx("span", { children: weekday }, weekday))) }), _jsx("div", { className: 'oui-date-picker-grid', children: monthState.weeks.flatMap((week) => week.map((day) => (_jsx("button", { type: 'button', className: 'oui-date-picker-day', "data-outside": day.outsideMonth ? 'true' : undefined, "data-selected": day.selected ? 'true' : undefined, "data-today": day.today ? 'true' : undefined, disabled: day.disabled, "aria-pressed": day.selected, onClick: () => selectDate(day.date), children: day.day }, day.date)))) }), _jsxs("div", { className: 'oui-date-picker-foot', children: [_jsx(Button, { size: 1, v: 'ghost', type: 'button', onClick: () => selectDate(clampDate(new Date().toISOString().slice(0, 10), min, max)), children: todayLabel ?? copy.dates.today }), clearable ? (_jsx(Button, { size: 1, v: 'ghost', type: 'button', disabled: !value, onClick: () => {
|
|
36
|
+
onValueChange('');
|
|
37
|
+
setOpen(false);
|
|
38
|
+
}, children: copy.common.clear })) : null] })] }) }));
|
|
39
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type CalendarDayState = {
|
|
2
|
+
date: string;
|
|
3
|
+
day: number;
|
|
4
|
+
outsideMonth: boolean;
|
|
5
|
+
selected: boolean;
|
|
6
|
+
today: boolean;
|
|
7
|
+
disabled: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type CalendarMonthState = {
|
|
10
|
+
month: string;
|
|
11
|
+
year: number;
|
|
12
|
+
monthIndex: number;
|
|
13
|
+
weeks: CalendarDayState[][];
|
|
14
|
+
};
|
|
15
|
+
export type DatePickerDisabledDate = (date: string) => boolean;
|
|
16
|
+
export declare function calendarMonthState({ cursorMonth, selectedDate, today, min, max, disabledDate, }: {
|
|
17
|
+
cursorMonth: string;
|
|
18
|
+
selectedDate?: string | null;
|
|
19
|
+
today?: string;
|
|
20
|
+
min?: string;
|
|
21
|
+
max?: string;
|
|
22
|
+
disabledDate?: DatePickerDisabledDate;
|
|
23
|
+
}): CalendarMonthState;
|
|
24
|
+
export declare function monthCursorForDate(value?: string | null, fallback?: string): string;
|
|
25
|
+
export declare function shiftMonth(cursorMonth: string, offset: number): string;
|
|
26
|
+
export declare function clampDate(value: string, min?: string, max?: string): string;
|
|
27
|
+
export declare function formatDateLabel(value: string, locale: string): string;
|
|
28
|
+
export declare function formatMonthLabel(cursorMonth: string, locale: string): string;
|
|
29
|
+
export declare function weekdayLabels(locale: string): string[];
|
|
30
|
+
//# sourceMappingURL=DatePickerState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DatePickerState.d.ts","sourceRoot":"","sources":["../../../src/components/DatePicker/DatePickerState.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,gBAAgB,EAAE,EAAE,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;AAE/D,wBAAgB,kBAAkB,CAAC,EAC/B,WAAW,EACX,YAAY,EACZ,KAAK,EACL,GAAG,EACH,GAAG,EACH,YAAY,GACf,EAAE;IACC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,sBAAsB,CAAC;CACzC,GAAG,kBAAkB,CA+BrB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAGnF;AAED,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGtE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAI3E;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQrE;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAO5E;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAKtD"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export function calendarMonthState({ cursorMonth, selectedDate, today, min, max, disabledDate, }) {
|
|
2
|
+
const cursor = parseDateParts(cursorMonth) ?? requiredDateParts(todayIsoDate());
|
|
3
|
+
const monthStart = new Date(Date.UTC(cursor.year, cursor.monthIndex, 1));
|
|
4
|
+
const gridStart = new Date(monthStart);
|
|
5
|
+
const startOffset = (monthStart.getUTCDay() + 6) % 7;
|
|
6
|
+
gridStart.setUTCDate(monthStart.getUTCDate() - startOffset);
|
|
7
|
+
const normalizedToday = today ?? todayIsoDate();
|
|
8
|
+
const days = Array.from({ length: 42 }, (_, index) => {
|
|
9
|
+
const date = new Date(gridStart);
|
|
10
|
+
date.setUTCDate(gridStart.getUTCDate() + index);
|
|
11
|
+
const dateValue = formatDate(date);
|
|
12
|
+
return {
|
|
13
|
+
date: dateValue,
|
|
14
|
+
day: date.getUTCDate(),
|
|
15
|
+
outsideMonth: date.getUTCMonth() !== cursor.monthIndex,
|
|
16
|
+
selected: selectedDate === dateValue,
|
|
17
|
+
today: normalizedToday === dateValue,
|
|
18
|
+
disabled: (min !== undefined && dateValue < min) ||
|
|
19
|
+
(max !== undefined && dateValue > max) ||
|
|
20
|
+
Boolean(disabledDate?.(dateValue)),
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
month: formatMonth(cursor.year, cursor.monthIndex),
|
|
25
|
+
year: cursor.year,
|
|
26
|
+
monthIndex: cursor.monthIndex,
|
|
27
|
+
weeks: chunk(days, 7),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function monthCursorForDate(value, fallback) {
|
|
31
|
+
const parts = parseDateParts(value ?? '') ?? parseDateParts(fallback ?? '') ?? requiredDateParts(todayIsoDate());
|
|
32
|
+
return formatMonth(parts.year, parts.monthIndex);
|
|
33
|
+
}
|
|
34
|
+
export function shiftMonth(cursorMonth, offset) {
|
|
35
|
+
const parts = parseDateParts(cursorMonth) ?? requiredDateParts(todayIsoDate());
|
|
36
|
+
return formatMonth(parts.year, parts.monthIndex + offset);
|
|
37
|
+
}
|
|
38
|
+
export function clampDate(value, min, max) {
|
|
39
|
+
if (min !== undefined && value < min)
|
|
40
|
+
return min;
|
|
41
|
+
if (max !== undefined && value > max)
|
|
42
|
+
return max;
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
export function formatDateLabel(value, locale) {
|
|
46
|
+
const parts = parseDateParts(value);
|
|
47
|
+
if (!parts)
|
|
48
|
+
return value;
|
|
49
|
+
return new Intl.DateTimeFormat(locale, {
|
|
50
|
+
day: '2-digit',
|
|
51
|
+
month: 'short',
|
|
52
|
+
year: 'numeric',
|
|
53
|
+
}).format(new Date(Date.UTC(parts.year, parts.monthIndex, parts.day)));
|
|
54
|
+
}
|
|
55
|
+
export function formatMonthLabel(cursorMonth, locale) {
|
|
56
|
+
const parts = parseDateParts(cursorMonth);
|
|
57
|
+
if (!parts)
|
|
58
|
+
return cursorMonth;
|
|
59
|
+
return new Intl.DateTimeFormat(locale, {
|
|
60
|
+
month: 'long',
|
|
61
|
+
year: 'numeric',
|
|
62
|
+
}).format(new Date(Date.UTC(parts.year, parts.monthIndex, 1)));
|
|
63
|
+
}
|
|
64
|
+
export function weekdayLabels(locale) {
|
|
65
|
+
return Array.from({ length: 7 }, (_, index) => {
|
|
66
|
+
const day = new Date(Date.UTC(2026, 5, 29 + index));
|
|
67
|
+
return new Intl.DateTimeFormat(locale, { weekday: 'short' }).format(day);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function parseDateParts(value) {
|
|
71
|
+
const match = /^(\d{4})-(\d{2})(?:-(\d{2}))?$/.exec(value);
|
|
72
|
+
if (!match)
|
|
73
|
+
return null;
|
|
74
|
+
const year = Number(match[1]);
|
|
75
|
+
const month = Number(match[2]);
|
|
76
|
+
const day = Number(match[3] ?? '01');
|
|
77
|
+
if (!Number.isInteger(year) || month < 1 || month > 12 || day < 1 || day > 31)
|
|
78
|
+
return null;
|
|
79
|
+
return { year, monthIndex: month - 1, day };
|
|
80
|
+
}
|
|
81
|
+
function requiredDateParts(value) {
|
|
82
|
+
const parts = parseDateParts(value);
|
|
83
|
+
if (!parts)
|
|
84
|
+
return { year: 1970, monthIndex: 0, day: 1 };
|
|
85
|
+
return parts;
|
|
86
|
+
}
|
|
87
|
+
function formatMonth(year, monthIndex) {
|
|
88
|
+
const date = new Date(Date.UTC(year, monthIndex, 1));
|
|
89
|
+
return `${date.getUTCFullYear()}-${pad(date.getUTCMonth() + 1)}`;
|
|
90
|
+
}
|
|
91
|
+
function formatDate(date) {
|
|
92
|
+
return `${date.getUTCFullYear()}-${pad(date.getUTCMonth() + 1)}-${pad(date.getUTCDate())}`;
|
|
93
|
+
}
|
|
94
|
+
function todayIsoDate() {
|
|
95
|
+
return formatDate(new Date());
|
|
96
|
+
}
|
|
97
|
+
function pad(value) {
|
|
98
|
+
return String(value).padStart(2, '0');
|
|
99
|
+
}
|
|
100
|
+
function chunk(items, size) {
|
|
101
|
+
const result = [];
|
|
102
|
+
for (let index = 0; index < items.length; index += size) {
|
|
103
|
+
result.push(items.slice(index, index + size));
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type DatePickerProps } from '../DatePicker/DatePicker';
|
|
2
|
+
export type DateRangePickerValue = {
|
|
3
|
+
from: string;
|
|
4
|
+
to: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function DateRangePicker({ value, onValueChange, min, max, disabledDate, fromPlaceholder, toPlaceholder, clearable, disabled, readOnly, testId, }: {
|
|
7
|
+
value: DateRangePickerValue;
|
|
8
|
+
onValueChange: (value: DateRangePickerValue) => void;
|
|
9
|
+
min?: string;
|
|
10
|
+
max?: string;
|
|
11
|
+
disabledDate?: DatePickerProps['disabledDate'];
|
|
12
|
+
fromPlaceholder?: string;
|
|
13
|
+
toPlaceholder?: string;
|
|
14
|
+
clearable?: boolean;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
readOnly?: boolean;
|
|
17
|
+
testId?: string;
|
|
18
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
//# sourceMappingURL=DateRangePicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DateRangePicker.d.ts","sourceRoot":"","sources":["../../../src/components/DateRangePicker/DateRangePicker.tsx"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,eAAe,EAAC,MAAM,0BAA0B,CAAC;AAE1E,MAAM,MAAM,oBAAoB,GAAG;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAC,CAAC;AAE9D,wBAAgB,eAAe,CAAC,EAC5B,KAAK,EACL,aAAa,EACb,GAAG,EACH,GAAG,EACH,YAAY,EACZ,eAAe,EACf,aAAa,EACb,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,MAAM,GACT,EAAE;IACC,KAAK,EAAE,oBAAoB,CAAC;IAC5B,aAAa,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,eAAe,CAAC,cAAc,CAAC,CAAC;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,2CA6BA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Flex } from '../Flex/Flex';
|
|
3
|
+
import { DatePicker } from '../DatePicker/DatePicker';
|
|
4
|
+
export function DateRangePicker({ value, onValueChange, min, max, disabledDate, fromPlaceholder, toPlaceholder, clearable, disabled, readOnly, testId, }) {
|
|
5
|
+
return (_jsxs(Flex, { g: 2, testId: testId, children: [_jsx(DatePicker, { value: value.from, min: min, max: value.to || max, disabledDate: disabledDate, placeholder: fromPlaceholder, clearable: clearable, disabled: disabled, readOnly: readOnly, testId: testId ? `${testId}-from` : undefined, onValueChange: (from) => onValueChange({ ...value, from }) }), _jsx(DatePicker, { value: value.to, min: value.from || min, max: max, disabledDate: disabledDate, placeholder: toPlaceholder, clearable: clearable, disabled: disabled, readOnly: readOnly, testId: testId ? `${testId}-to` : undefined, onValueChange: (to) => onValueChange({ ...value, to }) })] }));
|
|
6
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DateRangePickerValue } from '../DateRangePicker/DateRangePicker';
|
|
2
|
+
export type DateRangePreset = 'today' | 'week' | 'month';
|
|
3
|
+
export declare function DateRangePresetPicker({ onSelect, onValueChange, presets, today, testId, }: {
|
|
4
|
+
onSelect?: (preset: DateRangePreset) => void;
|
|
5
|
+
onValueChange?: (value: DateRangePickerValue, preset: DateRangePreset) => void;
|
|
6
|
+
presets?: ReadonlyArray<DateRangePreset>;
|
|
7
|
+
today?: string;
|
|
8
|
+
testId?: string;
|
|
9
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=DateRangePresetPicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DateRangePresetPicker.d.ts","sourceRoot":"","sources":["../../../src/components/DateRangePresetPicker/DateRangePresetPicker.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,oCAAoC,CAAC;AAG7E,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAEzD,wBAAgB,qBAAqB,CAAC,EAClC,QAAQ,EACR,aAAa,EACb,OAAoC,EACpC,KAAK,EACL,MAAM,GACT,EAAE;IACC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC/E,OAAO,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,2CA6BA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { LuCalendarDays } from 'react-icons/lu';
|
|
4
|
+
import { useOrcestrUiLocale } from '../../locale/LocaleProvider';
|
|
5
|
+
import { IconButton } from '../IconButton/IconButton';
|
|
6
|
+
import { Menu } from '../Menu/Menu';
|
|
7
|
+
import { resolveDateRangePreset } from './DateRangePresetPickerState';
|
|
8
|
+
export function DateRangePresetPicker({ onSelect, onValueChange, presets = ['today', 'week', 'month'], today, testId, }) {
|
|
9
|
+
const { copy } = useOrcestrUiLocale();
|
|
10
|
+
const items = presets.map((preset) => ({
|
|
11
|
+
key: preset,
|
|
12
|
+
label: presetLabel(preset, copy.dates),
|
|
13
|
+
onSelect: () => {
|
|
14
|
+
onSelect?.(preset);
|
|
15
|
+
onValueChange?.(resolveDateRangePreset(preset, today), preset);
|
|
16
|
+
},
|
|
17
|
+
}));
|
|
18
|
+
return (_jsx(Menu, { side: 'top', align: 'start', items: items, testId: testId, trigger: _jsx(IconButton, { size: 2, v: 'ghost', icon: _jsx(LuCalendarDays, { size: 15 }), "aria-label": copy.dates.quickPeriods, type: 'button', testId: testId ? `${testId}-trigger` : undefined }) }));
|
|
19
|
+
}
|
|
20
|
+
function presetLabel(preset, copy) {
|
|
21
|
+
if (preset === 'today')
|
|
22
|
+
return copy.today;
|
|
23
|
+
if (preset === 'week')
|
|
24
|
+
return copy.week;
|
|
25
|
+
return copy.month;
|
|
26
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DateRangePickerValue } from '../DateRangePicker/DateRangePicker';
|
|
2
|
+
import type { DateRangePreset } from './DateRangePresetPicker';
|
|
3
|
+
export declare function resolveDateRangePreset(preset: DateRangePreset, today?: string): DateRangePickerValue;
|
|
4
|
+
//# sourceMappingURL=DateRangePresetPickerState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DateRangePresetPickerState.d.ts","sourceRoot":"","sources":["../../../src/components/DateRangePresetPicker/DateRangePresetPickerState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,oCAAoC,CAAC;AAE7E,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,yBAAyB,CAAC;AAE7D,wBAAgB,sBAAsB,CAClC,MAAM,EAAE,eAAe,EACvB,KAAK,SAAwC,GAC9C,oBAAoB,CActB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function resolveDateRangePreset(preset, today = new Date().toISOString().slice(0, 10)) {
|
|
2
|
+
if (preset === 'today')
|
|
3
|
+
return { from: today, to: today };
|
|
4
|
+
if (preset === 'week') {
|
|
5
|
+
return {
|
|
6
|
+
from: shiftDate(today, -6),
|
|
7
|
+
to: today,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
from: `${today.slice(0, 8)}01`,
|
|
12
|
+
to: today,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function shiftDate(value, days) {
|
|
16
|
+
const [year, month, day] = value.split('-').map(Number);
|
|
17
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
18
|
+
date.setUTCDate(date.getUTCDate() + days);
|
|
19
|
+
return date.toISOString().slice(0, 10);
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../../src/components/Dialog/Dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,IAAI,MAAM,EAAE,KAAK,UAAU,IAAI,WAAW,EAAC,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Modal as Dialog } from '../Modal/Modal';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from 'react';
|
|
2
|
+
export type DrawerSide = 'bottom' | 'left' | 'right' | 'top';
|
|
3
|
+
export type DrawerProps = {
|
|
4
|
+
open?: boolean;
|
|
5
|
+
defaultOpen?: boolean;
|
|
6
|
+
onOpenChange?: (open: boolean) => void;
|
|
7
|
+
side?: DrawerSide;
|
|
8
|
+
size?: number | string;
|
|
9
|
+
title?: ReactNode;
|
|
10
|
+
description?: ReactNode;
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
footer?: ReactNode;
|
|
13
|
+
modal?: boolean;
|
|
14
|
+
trapFocus?: boolean;
|
|
15
|
+
lockScroll?: boolean;
|
|
16
|
+
closeOnBackdropClick?: boolean;
|
|
17
|
+
closeOnEscape?: boolean;
|
|
18
|
+
showBackdrop?: boolean;
|
|
19
|
+
showCloseButton?: boolean;
|
|
20
|
+
className?: string;
|
|
21
|
+
panelClassName?: string;
|
|
22
|
+
bodyClassName?: string;
|
|
23
|
+
backdropClassName?: string;
|
|
24
|
+
style?: CSSProperties;
|
|
25
|
+
panelStyle?: CSSProperties;
|
|
26
|
+
backdropStyle?: CSSProperties;
|
|
27
|
+
testId?: string;
|
|
28
|
+
};
|
|
29
|
+
export declare function Drawer({ open, defaultOpen, onOpenChange, side, size, title, description, children, footer, modal, trapFocus, lockScroll, closeOnBackdropClick, closeOnEscape, showBackdrop, showCloseButton, className, panelClassName, bodyClassName, backdropClassName, style, panelStyle, backdropStyle, testId, }: DrawerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
30
|
+
//# sourceMappingURL=Drawer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Drawer.d.ts","sourceRoot":"","sources":["../../../src/components/Drawer/Drawer.tsx"],"names":[],"mappings":"AAEA,OAAO,EAMH,KAAK,aAAa,EAClB,KAAK,SAAS,EACjB,MAAM,OAAO,CAAC;AAiBf,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAE7D,MAAM,MAAM,WAAW,GAAG;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,MAAM,CAAC,EACnB,IAAI,EACJ,WAAW,EACX,YAAY,EACZ,IAAc,EACd,IAAI,EACJ,KAAK,EACL,WAAW,EACX,QAAQ,EACR,MAAM,EACN,KAAY,EACZ,SAAiB,EACjB,UAAkB,EAClB,oBAA2B,EAC3B,aAAoB,EACpB,YAAoB,EACpB,eAAsB,EACtB,SAAS,EACT,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,KAAK,EACL,UAAU,EACV,aAAa,EACb,MAAM,GACT,EAAE,WAAW,kDAqHb"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useContext, useEffect, useId, useMemo, useRef, } from 'react';
|
|
4
|
+
import { LuX } from 'react-icons/lu';
|
|
5
|
+
import { useDisclosure } from '../../hooks/useDisclosure';
|
|
6
|
+
import { useFocusTrap } from '../../hooks/useFocusTrap';
|
|
7
|
+
import { usePresence } from '../../hooks/usePresence';
|
|
8
|
+
import { useOrcestrUiLocale } from '../../locale/LocaleProvider';
|
|
9
|
+
import { OrcestrThemeContext } from '../../theme/useTheme';
|
|
10
|
+
import { cn } from '../../utils/cn';
|
|
11
|
+
import { IconButton } from '../IconButton/IconButton';
|
|
12
|
+
import { lockOverlayScroll, useOverlayContext, useOverlayLayerIndex, } from '../Overlay/OverlayProvider';
|
|
13
|
+
import { Portal } from '../Portal/Portal';
|
|
14
|
+
export function Drawer({ open, defaultOpen, onOpenChange, side = 'right', size, title, description, children, footer, modal = true, trapFocus = modal, lockScroll = modal, closeOnBackdropClick = true, closeOnEscape = true, showBackdrop = modal, showCloseButton = true, className, panelClassName, bodyClassName, backdropClassName, style, panelStyle, backdropStyle, testId, }) {
|
|
15
|
+
const { copy } = useOrcestrUiLocale();
|
|
16
|
+
const themeContext = useContext(OrcestrThemeContext);
|
|
17
|
+
const overlay = useOverlayContext();
|
|
18
|
+
const disclosure = useDisclosure({ open, defaultOpen, onOpenChange });
|
|
19
|
+
const { open: isOpen, setOpen } = disclosure;
|
|
20
|
+
const duration = themeContext?.theme.motion.modalDuration ?? '260ms';
|
|
21
|
+
const durationMs = durationToMs(duration, 260);
|
|
22
|
+
const ease = themeContext?.theme.motion.ease ?? 'cubic-bezier(0.22, 1, 0.36, 1)';
|
|
23
|
+
const { present, state } = usePresence(isOpen, durationMs);
|
|
24
|
+
const layerIndex = useOverlayLayerIndex(present);
|
|
25
|
+
const zIndex = overlay.zIndex.modal + layerIndex * 20;
|
|
26
|
+
const panelRef = useRef(null);
|
|
27
|
+
const titleId = useId();
|
|
28
|
+
const descriptionId = useId();
|
|
29
|
+
const resolvedSize = cssSize(size ?? defaultDrawerSize(side));
|
|
30
|
+
const drawerStyle = useMemo(() => ({
|
|
31
|
+
'--oui-drawer-size': resolvedSize,
|
|
32
|
+
'--oui-drawer-duration': cssDuration(duration),
|
|
33
|
+
'--oui-drawer-ease': ease,
|
|
34
|
+
zIndex,
|
|
35
|
+
...style,
|
|
36
|
+
}), [duration, ease, resolvedSize, style, zIndex]);
|
|
37
|
+
useFocusTrap(panelRef, present && trapFocus);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (!present || !closeOnEscape)
|
|
40
|
+
return;
|
|
41
|
+
const handleKeyDown = (event) => {
|
|
42
|
+
if (event.key !== 'Escape')
|
|
43
|
+
return;
|
|
44
|
+
event.preventDefault();
|
|
45
|
+
setOpen(false);
|
|
46
|
+
};
|
|
47
|
+
document.addEventListener('keydown', handleKeyDown, true);
|
|
48
|
+
return () => document.removeEventListener('keydown', handleKeyDown, true);
|
|
49
|
+
}, [closeOnEscape, present, setOpen]);
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (!present || !lockScroll)
|
|
52
|
+
return;
|
|
53
|
+
return lockOverlayScroll();
|
|
54
|
+
}, [lockScroll, present]);
|
|
55
|
+
if (!present)
|
|
56
|
+
return null;
|
|
57
|
+
return (_jsx(Portal, { children: _jsxs("div", { className: cn('oui-drawer-layer', className), "data-state": state, "data-side": side, "data-modal": modal ? 'true' : undefined, "data-testid": testId, style: drawerStyle, children: [showBackdrop ? (_jsx("button", { type: 'button', "aria-label": copy.common.close, className: cn('oui-drawer-backdrop', backdropClassName), "data-state": state, "data-testid": testId ? `${testId}-backdrop` : undefined, style: backdropStyle, onClick: () => {
|
|
58
|
+
if (closeOnBackdropClick)
|
|
59
|
+
setOpen(false);
|
|
60
|
+
} })) : null, _jsxs("div", { ref: panelRef, role: modal ? 'dialog' : 'complementary', "aria-modal": modal ? 'true' : undefined, "aria-labelledby": title ? titleId : undefined, "aria-describedby": description ? descriptionId : undefined, className: cn('oui-drawer-panel', panelClassName), "data-state": state, "data-side": side, "data-testid": testId ? `${testId}-panel` : undefined, style: panelStyle, children: [title || description || showCloseButton ? (_jsxs("div", { className: 'oui-drawer-header', children: [_jsxs("div", { className: 'oui-drawer-title-wrap', children: [title ? (_jsx("h2", { id: titleId, className: 'oui-drawer-title', children: title })) : null, description ? (_jsx("p", { id: descriptionId, className: 'oui-drawer-description', children: description })) : null] }), showCloseButton ? (_jsx(IconButton, { v: 'ghost', icon: _jsx(LuX, { size: 18 }), "aria-label": copy.common.close, onClick: () => setOpen(false) })) : null] })) : null, _jsx("div", { className: cn('oui-drawer-body', bodyClassName), children: children }), footer ? _jsx("div", { className: 'oui-drawer-footer', children: footer }) : null] })] }) }));
|
|
61
|
+
}
|
|
62
|
+
function defaultDrawerSize(side) {
|
|
63
|
+
return side === 'left' || side === 'right' ? 'min(86vw, 360px)' : 'min(80vh, 420px)';
|
|
64
|
+
}
|
|
65
|
+
function cssSize(value) {
|
|
66
|
+
return typeof value === 'number' ? `${value}px` : value;
|
|
67
|
+
}
|
|
68
|
+
function cssDuration(value) {
|
|
69
|
+
return typeof value === 'number' ? `${value}ms` : value;
|
|
70
|
+
}
|
|
71
|
+
function durationToMs(value, fallback) {
|
|
72
|
+
if (typeof value === 'number')
|
|
73
|
+
return Math.max(0, value);
|
|
74
|
+
const normalized = value.trim().toLowerCase();
|
|
75
|
+
const parsed = Number.parseFloat(normalized);
|
|
76
|
+
if (!Number.isFinite(parsed))
|
|
77
|
+
return fallback;
|
|
78
|
+
if (normalized.endsWith('ms'))
|
|
79
|
+
return Math.max(0, parsed);
|
|
80
|
+
if (normalized.endsWith('s'))
|
|
81
|
+
return Math.max(0, parsed * 1000);
|
|
82
|
+
return Math.max(0, parsed);
|
|
83
|
+
}
|