@dbcdk/react-components 0.0.95 → 0.0.97
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/dist/components/alert/Alert.d.ts +13 -0
- package/dist/components/forms/input/Input.d.ts +2 -1
- package/dist/components/forms/input-container/InputContainer.d.ts +3 -1
- package/dist/components/forms/text-area/Textarea.d.ts +1 -1
- package/dist/components/stack/Stack.d.ts +11 -3
- package/dist/components/table/Table.d.ts +1 -1
- package/dist/components/table/Table.types.d.ts +3 -0
- package/dist/components/table/components/TableHeader.d.ts +2 -1
- package/dist/index.cjs +12750 -0
- package/dist/index.css +7149 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +12641 -78
- package/dist/tanstack.cjs +2674 -0
- package/dist/tanstack.css +1267 -0
- package/dist/tanstack.js +2650 -3
- package/dist/themes/dbc.css +3 -0
- package/dist/themes/forfatterweb.css +2 -0
- package/package.json +11 -10
- package/dist/assets/logo.js +0 -2
- package/dist/components/__stories__/_data/table.d.ts +0 -15
- package/dist/components/__stories__/_data/table.js +0 -55
- package/dist/components/__stories__/_data/tabs.d.ts +0 -9
- package/dist/components/__stories__/_data/tabs.js +0 -31
- package/dist/components/__stories__/story-components/Colors.d.ts +0 -11
- package/dist/components/__stories__/story-components/Colors.js +0 -96
- package/dist/components/__stories__/story-components/Colors.module.css +0 -27
- package/dist/components/__stories__/story-components/ComponentSizes.d.ts +0 -2
- package/dist/components/__stories__/story-components/ComponentSizes.js +0 -26
- package/dist/components/__stories__/story-components/Elevation.d.ts +0 -2
- package/dist/components/__stories__/story-components/Elevation.js +0 -49
- package/dist/components/__stories__/story-components/Flex.d.ts +0 -2
- package/dist/components/__stories__/story-components/Flex.js +0 -177
- package/dist/components/__stories__/story-components/Flex.module.css +0 -317
- package/dist/components/__stories__/story-components/Spacing.d.ts +0 -6
- package/dist/components/__stories__/story-components/Spacing.js +0 -76
- package/dist/components/__stories__/story-components/Spacing.module.css +0 -154
- package/dist/components/accordion/Accordion.js +0 -70
- package/dist/components/accordion/Accordion.module.css +0 -28
- package/dist/components/accordion/components/AccordionRow.js +0 -53
- package/dist/components/accordion/components/AccordionRow.module.css +0 -90
- package/dist/components/app-header/AppHeader.js +0 -5
- package/dist/components/app-header/AppHeader.module.css +0 -74
- package/dist/components/attribute-chip/AttributeChip.js +0 -5
- package/dist/components/attribute-chip/AttributeChip.module.css +0 -65
- package/dist/components/avatar/Avatar.js +0 -48
- package/dist/components/avatar/Avatar.module.css +0 -91
- package/dist/components/breadcrumbs/Breadcrumbs.js +0 -6
- package/dist/components/breadcrumbs/Breadcrumbs.module.css +0 -80
- package/dist/components/button/Button.js +0 -81
- package/dist/components/button/Button.module.css +0 -249
- package/dist/components/button-select/ButtonSelect.js +0 -7
- package/dist/components/button-select/ButtonSelect.module.css +0 -40
- package/dist/components/card/Card.js +0 -71
- package/dist/components/card/Card.module.css +0 -160
- package/dist/components/card/components/CardMeta.js +0 -26
- package/dist/components/card/components/CardMeta.module.css +0 -55
- package/dist/components/card-container/CardContainer.js +0 -6
- package/dist/components/card-container/CardContainer.module.css +0 -61
- package/dist/components/chip/Chip.js +0 -31
- package/dist/components/chip/Chip.module.css +0 -236
- package/dist/components/circle/Circle.js +0 -5
- package/dist/components/circle/Circle.module.css +0 -128
- package/dist/components/clear-button/ClearButton.js +0 -13
- package/dist/components/clear-button/ClearButton.module.css +0 -26
- package/dist/components/code-block/CodeBlock.js +0 -58
- package/dist/components/code-block/CodeBlock.module.css +0 -124
- package/dist/components/copy-button/CopyButton.js +0 -78
- package/dist/components/copy-button/CopyButton.module.css +0 -22
- package/dist/components/datetime-picker/DateTimePicker.js +0 -403
- package/dist/components/datetime-picker/DateTimePicker.module.css +0 -155
- package/dist/components/datetime-picker/dateTimeHelpers.js +0 -248
- package/dist/components/divider/Divider.js +0 -12
- package/dist/components/filter-field/FilterField.js +0 -191
- package/dist/components/filter-field/FilterField.module.css +0 -379
- package/dist/components/filtering/chip-multi-toggle/ChipMultiToggle.js +0 -52
- package/dist/components/filtering/chip-multi-toggle/ChipMultiToggle.module.css +0 -59
- package/dist/components/forms/checkbox/Checkbox.js +0 -26
- package/dist/components/forms/checkbox/Checkbox.module.css +0 -99
- package/dist/components/forms/checkbox-group/CheckboxGroup.js +0 -75
- package/dist/components/forms/checkbox-group/CheckboxGroup.module.css +0 -115
- package/dist/components/forms/form-select/FormSelect.js +0 -86
- package/dist/components/forms/form-select/FormSelect.module.css +0 -236
- package/dist/components/forms/input/Input.js +0 -77
- package/dist/components/forms/input/Input.module.css +0 -468
- package/dist/components/forms/input-container/InputContainer.js +0 -15
- package/dist/components/forms/input-container/InputContainer.module.css +0 -56
- package/dist/components/forms/multi-select/MultiSelect.js +0 -122
- package/dist/components/forms/radio-buttons/RadioButton.js +0 -26
- package/dist/components/forms/radio-buttons/RadioButtonGroup.js +0 -19
- package/dist/components/forms/radio-buttons/RadioButtons.module.css +0 -118
- package/dist/components/forms/select/Select.js +0 -185
- package/dist/components/forms/select/Select.module.css +0 -32
- package/dist/components/forms/text-area/Textarea.js +0 -47
- package/dist/components/forms/text-area/Textarea.module.css +0 -70
- package/dist/components/forms/typeahead/Typeahead.js +0 -668
- package/dist/components/forms/typeahead/Typeahead.module.css +0 -38
- package/dist/components/grid/Grid.js +0 -23
- package/dist/components/grid/Grid.module.css +0 -35
- package/dist/components/headline/CollapsibleHeadline.js +0 -29
- package/dist/components/headline/Headline.js +0 -26
- package/dist/components/headline/Headline.module.css +0 -165
- package/dist/components/hyperlink/Hyperlink.js +0 -40
- package/dist/components/hyperlink/Hyperlink.module.css +0 -107
- package/dist/components/icon/Icon.js +0 -14
- package/dist/components/icon/Icon.module.css +0 -36
- package/dist/components/interval-select/IntervalSelect.js +0 -99
- package/dist/components/json-viewer/HighlightedText.js +0 -6
- package/dist/components/json-viewer/JsonNode.js +0 -30
- package/dist/components/json-viewer/JsonViewer.js +0 -68
- package/dist/components/json-viewer/JsonViewer.module.css +0 -346
- package/dist/components/json-viewer/types.js +0 -1
- package/dist/components/json-viewer/useClipboardStatus.js +0 -11
- package/dist/components/json-viewer/utils.js +0 -125
- package/dist/components/menu/Menu.js +0 -165
- package/dist/components/menu/Menu.module.css +0 -211
- package/dist/components/meta-bar/MetaBar.js +0 -9
- package/dist/components/meta-bar/MetaBar.module.css +0 -27
- package/dist/components/nav-bar/NavBar.js +0 -29
- package/dist/components/nav-bar/NavBar.module.css +0 -200
- package/dist/components/overlay/fade-overlay/FadeOverlay.js +0 -8
- package/dist/components/overlay/fade-overlay/FadeOverlay.module.css +0 -54
- package/dist/components/overlay/modal/Modal.js +0 -115
- package/dist/components/overlay/modal/Modal.module.css +0 -109
- package/dist/components/overlay/modal/provider/ModalProvider.js +0 -73
- package/dist/components/overlay/side-panel/SidePanel.js +0 -83
- package/dist/components/overlay/side-panel/SidePanel.module.css +0 -177
- package/dist/components/overlay/side-panel/useSidePanel.js +0 -11
- package/dist/components/overlay/tooltip/Tooltip.js +0 -17
- package/dist/components/overlay/tooltip/Tooltip.module.css +0 -104
- package/dist/components/overlay/tooltip/TooltipProvider.js +0 -255
- package/dist/components/overlay/tooltip/useTooltipTrigger.js +0 -118
- package/dist/components/page/Page.js +0 -11
- package/dist/components/page/Page.module.css +0 -76
- package/dist/components/page-layout/PageLayout.js +0 -76
- package/dist/components/page-layout/PageLayout.module.css +0 -236
- package/dist/components/page-layout/components/layout-footer/LayoutFooter.js +0 -27
- package/dist/components/page-layout/components/layout-footer/LayoutFooter.module.css +0 -89
- package/dist/components/page-layout/components/page-layout-hero/PageLayoutHero.js +0 -14
- package/dist/components/page-layout/components/page-layout-hero/PageLayoutHero.module.css +0 -84
- package/dist/components/pagination/Pagination.js +0 -56
- package/dist/components/pagination/Pagination.module.css +0 -25
- package/dist/components/panel/Panel.js +0 -7
- package/dist/components/panel/Panel.module.css +0 -29
- package/dist/components/popover/Popover.js +0 -257
- package/dist/components/popover/Popover.module.css +0 -54
- package/dist/components/search-box/SearchBox.js +0 -170
- package/dist/components/search-box/SearchBox.module.css +0 -21
- package/dist/components/segmented-progress-bar/SegmentedProgressBar.js +0 -48
- package/dist/components/segmented-progress-bar/SegmentedProgressBar.module.css +0 -167
- package/dist/components/sidebar/Sidebar.js +0 -6
- package/dist/components/sidebar/components/SidebarItem.js +0 -8
- package/dist/components/sidebar/components/SidebarItem.module.css +0 -0
- package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.js +0 -63
- package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.module.css +0 -29
- package/dist/components/sidebar/components/sidebar-container/SidebarContainer.js +0 -153
- package/dist/components/sidebar/components/sidebar-container/SidebarContainer.module.css +0 -260
- package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.js +0 -18
- package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.module.css +0 -106
- package/dist/components/sidebar/components/sidebar-items/SidebarItems.js +0 -26
- package/dist/components/sidebar/components/sidebar-items/SidebarItems.module.css +0 -20
- package/dist/components/sidebar/components/sidenav-filteirng/SidenavFiltering.js +0 -30
- package/dist/components/sidebar/providers/SidebarProvider.js +0 -229
- package/dist/components/skeleton-loader/SkeletonLoader.js +0 -73
- package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.js +0 -13
- package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.module.css +0 -51
- package/dist/components/split-button/SplitButton.js +0 -10
- package/dist/components/split-button/SplitButton.module.css +0 -32
- package/dist/components/split-pane/SplitPane.js +0 -107
- package/dist/components/split-pane/SplitPane.module.css +0 -111
- package/dist/components/split-pane/provider/SplitPaneContext.js +0 -124
- package/dist/components/stack/Stack.js +0 -19
- package/dist/components/state-page/StatePage.js +0 -20
- package/dist/components/state-page/StatePage.module.css +0 -9
- package/dist/components/state-page/empty.js +0 -2
- package/dist/components/state-page/error.js +0 -2
- package/dist/components/state-page/notFound.js +0 -2
- package/dist/components/sticky-footer-layout/StickyFooterLayout.js +0 -64
- package/dist/components/table/Table.js +0 -50
- package/dist/components/table/Table.module.css +0 -536
- package/dist/components/table/Table.types.js +0 -1
- package/dist/components/table/TanstackTable.js +0 -111
- package/dist/components/table/components/TableBody.js +0 -10
- package/dist/components/table/components/TableHeader.js +0 -7
- package/dist/components/table/components/TableHeaderCell.js +0 -24
- package/dist/components/table/components/TableLoadingBody.js +0 -26
- package/dist/components/table/components/TablePagination.js +0 -1
- package/dist/components/table/components/TableRow.js +0 -54
- package/dist/components/table/components/TableSelectionCell.js +0 -16
- package/dist/components/table/components/column-resizer/ColumnResizer.js +0 -5
- package/dist/components/table/components/column-resizer/ColumnResizer.module.css +0 -22
- package/dist/components/table/components/empty-state/EmptyState.js +0 -23
- package/dist/components/table/components/empty-state/EmptyState.module.css +0 -4
- package/dist/components/table/components/table-settings/TableSettings.js +0 -63
- package/dist/components/table/hooks/useTableRowInteractions.js +0 -30
- package/dist/components/table/table.classes.js +0 -23
- package/dist/components/table/table.utils.js +0 -47
- package/dist/components/table/tanstackTable.utils.js +0 -175
- package/dist/components/tabs/Tabs.js +0 -125
- package/dist/components/tabs/Tabs.module.css +0 -204
- package/dist/components/theme-button/ThemeButton.js +0 -23
- package/dist/components/toast/Toast.js +0 -20
- package/dist/components/toast/Toast.module.css +0 -161
- package/dist/components/toast/provider/ToastProvider.js +0 -70
- package/dist/components/user-display/UserDisplay.js +0 -6
- package/dist/components/user-display/UserDisplay.module.css +0 -25
- package/dist/constants/severity.js +0 -24
- package/dist/constants/severity.types.js +0 -1
- package/dist/constants/sizes.js +0 -7
- package/dist/hooks/useDeviceSize.js +0 -32
- package/dist/hooks/useListNavigation.js +0 -234
- package/dist/hooks/usePagination.js +0 -140
- package/dist/hooks/useSorting.js +0 -118
- package/dist/hooks/useTableData.js +0 -45
- package/dist/hooks/useTableSelection.js +0 -164
- package/dist/hooks/useTableSettings.js +0 -71
- package/dist/hooks/useTheme.js +0 -66
- package/dist/hooks/useTimeDuration.js +0 -68
- package/dist/hooks/useViewportFill.js +0 -77
- package/dist/styles/animation.js +0 -5
- package/dist/styles/themes/types.js +0 -1
- package/dist/types/a11y-props.types.js +0 -1
- package/dist/types/sizes.types.js +0 -1
- package/dist/utils/arrays/nested-filtering.js +0 -48
- package/dist/utils/date/formatDate.js +0 -51
- package/dist/utils/localStorage.utils.js +0 -78
- package/dist/utils/text/get-highlighted-segments.js +0 -46
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
/* ---------- Range separator helpers ---------- */
|
|
2
|
-
/**
|
|
3
|
-
* IMPORTANT:
|
|
4
|
-
* "-" is only treated as a range separator when surrounded by whitespace: " - "
|
|
5
|
-
* so we don't split inside "DD-MM-YYYY".
|
|
6
|
-
*
|
|
7
|
-
* Supported separators:
|
|
8
|
-
* - En dash: "–" (with optional surrounding spaces)
|
|
9
|
-
* - Hyphen as range sep: " - " (spaces required)
|
|
10
|
-
* - Words: "to", "til" (with optional surrounding spaces)
|
|
11
|
-
*
|
|
12
|
-
* COMPAT:
|
|
13
|
-
* - Also supports digit-only ranges like "01022026-02022026" (no spaces),
|
|
14
|
-
* because that cannot be confused with "DD-MM-YYYY".
|
|
15
|
-
*/
|
|
16
|
-
const RANGE_SEP_RE = /\s*(?:–|\bto\b|\btil\b|\s-\s)\s*/i;
|
|
17
|
-
function normalizeSpaces(s) {
|
|
18
|
-
return s.trim().replace(/\s+/g, ' ');
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Special-case for digit-only ranges: 8 digits + '-' + 8 digits (optional spaces).
|
|
22
|
-
* This keeps legacy UX working without reintroducing the DD-MM-YYYY split bug.
|
|
23
|
-
*/
|
|
24
|
-
function splitDigitOnlyRangeParts(input) {
|
|
25
|
-
const m = /^\s*(\d{8})\s*-\s*(\d{8})\s*$/.exec(input);
|
|
26
|
-
if (!m)
|
|
27
|
-
return null;
|
|
28
|
-
return [m[1], m[2]];
|
|
29
|
-
}
|
|
30
|
-
function splitRangeParts(input) {
|
|
31
|
-
var _a;
|
|
32
|
-
// 1) digit-only fast path: 01022026-02022026
|
|
33
|
-
const digitOnly = splitDigitOnlyRangeParts(input);
|
|
34
|
-
if (digitOnly)
|
|
35
|
-
return digitOnly;
|
|
36
|
-
// 2) normal path: use safe separators (–, to, til, " - ")
|
|
37
|
-
const txt = normalizeSpaces(input);
|
|
38
|
-
const parts = txt.split(RANGE_SEP_RE);
|
|
39
|
-
if (parts.length < 2)
|
|
40
|
-
return null;
|
|
41
|
-
const left = ((_a = parts[0]) !== null && _a !== void 0 ? _a : '').trim();
|
|
42
|
-
const right = parts.slice(1).join(' ').trim();
|
|
43
|
-
if (!left || !right)
|
|
44
|
-
return null;
|
|
45
|
-
return [left, right];
|
|
46
|
-
}
|
|
47
|
-
/* ---------- Mask helpers (no deps) ---------- */
|
|
48
|
-
// Pull only 0-9
|
|
49
|
-
export const digits = (s) => (s.match(/\d/g) || []).join('');
|
|
50
|
-
// DD-MM-YYYY
|
|
51
|
-
export function maskDateEU(text) {
|
|
52
|
-
const d = digits(text).slice(0, 8);
|
|
53
|
-
const dd = d.slice(0, 2);
|
|
54
|
-
const mm = d.slice(2, 4);
|
|
55
|
-
const yyyy = d.slice(4, 8);
|
|
56
|
-
let out = dd;
|
|
57
|
-
if (mm.length)
|
|
58
|
-
out += (out ? '-' : '') + mm;
|
|
59
|
-
if (yyyy.length)
|
|
60
|
-
out += (out ? '-' : '') + yyyy;
|
|
61
|
-
return out;
|
|
62
|
-
}
|
|
63
|
-
// HH:mm (24h)
|
|
64
|
-
export function maskTimeHM(text) {
|
|
65
|
-
const d = digits(text).slice(0, 4);
|
|
66
|
-
const hh = d.slice(0, 2);
|
|
67
|
-
const mm = d.slice(2, 4);
|
|
68
|
-
return mm.length ? `${hh}:${mm}` : hh;
|
|
69
|
-
}
|
|
70
|
-
// Single: "DD-MM-YYYY" or "DD-MM-YYYY HH:mm"
|
|
71
|
-
export function maskSingle(text, enableTime) {
|
|
72
|
-
const t = normalizeSpaces(text);
|
|
73
|
-
if (!enableTime)
|
|
74
|
-
return maskDateEU(t);
|
|
75
|
-
// split date + time by first space or 'T'
|
|
76
|
-
const m = /^(.*?)[ T](.*)$/.exec(t);
|
|
77
|
-
if (!m)
|
|
78
|
-
return maskDateEU(t);
|
|
79
|
-
const datePart = maskDateEU(m[1]);
|
|
80
|
-
const timePart = maskTimeHM(m[2]);
|
|
81
|
-
return timePart ? `${datePart} ${timePart}` : datePart;
|
|
82
|
-
}
|
|
83
|
-
// Range: mask both sides around common separators (–, " - ", to, til, or digit-only "01022026-02022026")
|
|
84
|
-
export function maskRange(text, _enableTime) {
|
|
85
|
-
// NOTE: range is date-only in the UI
|
|
86
|
-
const parts = splitRangeParts(text);
|
|
87
|
-
if (!parts)
|
|
88
|
-
return maskSingle(text, false);
|
|
89
|
-
const [left, right] = parts;
|
|
90
|
-
const a = maskSingle(left, false);
|
|
91
|
-
const b = maskSingle(right, false);
|
|
92
|
-
return `${a} – ${b}`.trim();
|
|
93
|
-
}
|
|
94
|
-
// Pad helper
|
|
95
|
-
export const pad2 = (n) => String(n).padStart(2, '0');
|
|
96
|
-
export function isUtcIsoString(v) {
|
|
97
|
-
return typeof v === 'string' && /Z$/.test(v) && !Number.isNaN(Date.parse(v));
|
|
98
|
-
}
|
|
99
|
-
export function isDateOnlyString(v) {
|
|
100
|
-
if (typeof v !== 'string')
|
|
101
|
-
return false;
|
|
102
|
-
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(v);
|
|
103
|
-
if (!m)
|
|
104
|
-
return false;
|
|
105
|
-
const y = +m[1];
|
|
106
|
-
const mo = +m[2];
|
|
107
|
-
const d = +m[3];
|
|
108
|
-
if (mo < 1 || mo > 12)
|
|
109
|
-
return false;
|
|
110
|
-
if (d < 1 || d > 31)
|
|
111
|
-
return false;
|
|
112
|
-
// Validate exact date (guard against 2026-02-31 etc.)
|
|
113
|
-
const local = new Date(y, mo - 1, d, 0, 0, 0, 0);
|
|
114
|
-
return local.getFullYear() === y && local.getMonth() === mo - 1 && local.getDate() === d;
|
|
115
|
-
}
|
|
116
|
-
export function utcMillisFromIso(iso) {
|
|
117
|
-
return Date.parse(iso);
|
|
118
|
-
}
|
|
119
|
-
/** Convert a local DateTime to a UTC ISO string (Z). */
|
|
120
|
-
export function isoFromLocalDate(dLocal) {
|
|
121
|
-
return dLocal.toISOString();
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Build a *local* Date from y/m/d/hh/mm and return UTC ISO string (Z).
|
|
125
|
-
* This keeps the UI meaning "local wall time", while emitting a stable UTC instant.
|
|
126
|
-
*
|
|
127
|
-
* DST NOTE:
|
|
128
|
-
* If the requested local wall time does not exist (spring-forward), JS will auto-correct.
|
|
129
|
-
* We detect that and return null so caller can handle it (e.g., show validation error).
|
|
130
|
-
*/
|
|
131
|
-
export function isoFromLocalParts(y, m0, // 0-based
|
|
132
|
-
d, hh = 0, mm = 0) {
|
|
133
|
-
const local = new Date(y, m0, d, hh, mm, 0, 0);
|
|
134
|
-
if (Number.isNaN(local.getTime()))
|
|
135
|
-
return null;
|
|
136
|
-
// Guard: JS autocorrects invalid dates/times; re-validate exact parts
|
|
137
|
-
if (local.getFullYear() !== y ||
|
|
138
|
-
local.getMonth() !== m0 ||
|
|
139
|
-
local.getDate() !== d ||
|
|
140
|
-
local.getHours() !== hh ||
|
|
141
|
-
local.getMinutes() !== mm) {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
return local.toISOString();
|
|
145
|
-
}
|
|
146
|
-
/** For anchoring the calendar safely from a UTC ISO string. */
|
|
147
|
-
export function localDateFromIso(iso) {
|
|
148
|
-
const ms = Date.parse(iso);
|
|
149
|
-
if (Number.isNaN(ms))
|
|
150
|
-
return null;
|
|
151
|
-
return new Date(ms); // local rendering
|
|
152
|
-
}
|
|
153
|
-
/** Date-only: build 'YYYY-MM-DD' from local parts */
|
|
154
|
-
export function dateOnlyFromLocalParts(y, m0, d) {
|
|
155
|
-
return `${String(y).padStart(4, '0')}-${pad2(m0 + 1)}-${pad2(d)}`;
|
|
156
|
-
}
|
|
157
|
-
/** Parse 'YYYY-MM-DD' into a local Date at midnight */
|
|
158
|
-
export function localDateFromDateOnly(s) {
|
|
159
|
-
if (!isDateOnlyString(s))
|
|
160
|
-
return null;
|
|
161
|
-
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(s);
|
|
162
|
-
if (!m)
|
|
163
|
-
return null;
|
|
164
|
-
const y = +m[1];
|
|
165
|
-
const mo0 = +m[2] - 1;
|
|
166
|
-
const d = +m[3];
|
|
167
|
-
const local = new Date(y, mo0, d, 0, 0, 0, 0);
|
|
168
|
-
if (Number.isNaN(local.getTime()))
|
|
169
|
-
return null;
|
|
170
|
-
if (local.getFullYear() !== y || local.getMonth() !== mo0 || local.getDate() !== d)
|
|
171
|
-
return null;
|
|
172
|
-
return local;
|
|
173
|
-
}
|
|
174
|
-
/** Compare date-only strings by UTC date-only time (stable ordering) */
|
|
175
|
-
export function compareDateOnly(a, b) {
|
|
176
|
-
const da = localDateFromDateOnly(a);
|
|
177
|
-
const db = localDateFromDateOnly(b);
|
|
178
|
-
if (!da || !db)
|
|
179
|
-
return 0;
|
|
180
|
-
const ta = Date.UTC(da.getFullYear(), da.getMonth(), da.getDate());
|
|
181
|
-
const tb = Date.UTC(db.getFullYear(), db.getMonth(), db.getDate());
|
|
182
|
-
return ta - tb;
|
|
183
|
-
}
|
|
184
|
-
/* ---------- Formatting (UI shows local) ---------- */
|
|
185
|
-
// From Date → "DD-MM-YYYY" or "DD-MM-YYYY HH:mm" (local time)
|
|
186
|
-
export function toMaskedFromDate(d, enableTime) {
|
|
187
|
-
const dd = pad2(d.getDate());
|
|
188
|
-
const mm = pad2(d.getMonth() + 1);
|
|
189
|
-
const yyyy = String(d.getFullYear());
|
|
190
|
-
let out = `${dd}-${mm}-${yyyy}`;
|
|
191
|
-
if (enableTime)
|
|
192
|
-
out += ` ${pad2(d.getHours())}:${pad2(d.getMinutes())}`;
|
|
193
|
-
return out;
|
|
194
|
-
}
|
|
195
|
-
/* ---------- Parsing helpers (no deps) ---------- */
|
|
196
|
-
// Accepts: YYYY-MM-DD, DD-MM-YYYY, DD/MM/YYYY, DD.MM.YYYY (+ optional HH:mm)
|
|
197
|
-
export function parseLooseDateOrDateTime(input) {
|
|
198
|
-
const txt = normalizeSpaces(input);
|
|
199
|
-
const dateTimeMatch = /^(?<date>[\d./-]{8,10})(?:[ T](?<hh>\d{1,2}):(?<mm>\d{2}))?$/i.exec(txt);
|
|
200
|
-
if (!(dateTimeMatch === null || dateTimeMatch === void 0 ? void 0 : dateTimeMatch.groups))
|
|
201
|
-
return null;
|
|
202
|
-
const raw = dateTimeMatch.groups.date;
|
|
203
|
-
const hh = dateTimeMatch.groups.hh ? parseInt(dateTimeMatch.groups.hh, 10) : 0;
|
|
204
|
-
const mm = dateTimeMatch.groups.mm ? parseInt(dateTimeMatch.groups.mm, 10) : 0;
|
|
205
|
-
if (hh < 0 || hh > 23 || mm < 0 || mm > 59)
|
|
206
|
-
return null;
|
|
207
|
-
// Try YYYY-MM-DD first (still accepts 1-2 digits for month/day in ISO form)
|
|
208
|
-
let y, m, d;
|
|
209
|
-
const mIso = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(raw);
|
|
210
|
-
if (mIso) {
|
|
211
|
-
y = +mIso[1];
|
|
212
|
-
m = +mIso[2] - 1;
|
|
213
|
-
d = +mIso[3];
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
// EU formats must be strict DD-MM-YYYY / DD/MM/YYYY / DD.MM.YYYY
|
|
217
|
-
const mEu = /^(\d{2})[./-](\d{2})[./-](\d{4})$/.exec(raw);
|
|
218
|
-
if (!mEu)
|
|
219
|
-
return null;
|
|
220
|
-
d = +mEu[1];
|
|
221
|
-
m = +mEu[2] - 1;
|
|
222
|
-
y = +mEu[3];
|
|
223
|
-
}
|
|
224
|
-
const local = new Date(y, m, d, hh, mm, 0, 0);
|
|
225
|
-
if (Number.isNaN(local.getTime()))
|
|
226
|
-
return null;
|
|
227
|
-
// Guard: JS autocorrects invalid dates; re-validate exact Y/M/D/H/M
|
|
228
|
-
if (local.getFullYear() !== y ||
|
|
229
|
-
local.getMonth() !== m ||
|
|
230
|
-
local.getDate() !== d ||
|
|
231
|
-
local.getHours() !== hh ||
|
|
232
|
-
local.getMinutes() !== mm) {
|
|
233
|
-
return null;
|
|
234
|
-
}
|
|
235
|
-
return local;
|
|
236
|
-
}
|
|
237
|
-
// Parse a range string with separators: "–", " - ", "to", "til", or digit-only "01022026-02022026"
|
|
238
|
-
export function parseLooseRange(input) {
|
|
239
|
-
const parts = splitRangeParts(input);
|
|
240
|
-
if (!parts)
|
|
241
|
-
return null;
|
|
242
|
-
const [a, b] = parts;
|
|
243
|
-
const s = parseLooseDateOrDateTime(a);
|
|
244
|
-
const e = parseLooseDateOrDateTime(b);
|
|
245
|
-
if (!s || !e)
|
|
246
|
-
return null;
|
|
247
|
-
return s <= e ? { start: s, end: e } : { start: e, end: s };
|
|
248
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
const spacingMap = {
|
|
3
|
-
sm: 'var(--spacing-sm)',
|
|
4
|
-
md: 'var(--spacing-md)',
|
|
5
|
-
lg: 'var(--spacing-lg)',
|
|
6
|
-
};
|
|
7
|
-
export const Divider = ({ spacing = 'md' }) => {
|
|
8
|
-
return (_jsx("div", { style: {
|
|
9
|
-
borderTop: '1px solid var(--color-border-subtle)',
|
|
10
|
-
marginBlock: spacingMap[spacing],
|
|
11
|
-
} }));
|
|
12
|
-
};
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Check } from 'lucide-react';
|
|
4
|
-
import { useMemo, useRef, useState, useEffect } from 'react';
|
|
5
|
-
import { Input } from '../../components/forms/input/Input';
|
|
6
|
-
import { Typeahead } from '../../components/forms/typeahead/Typeahead';
|
|
7
|
-
import styles from './FilterField.module.css';
|
|
8
|
-
import { Menu } from '../menu/Menu';
|
|
9
|
-
import { Popover } from '../popover/Popover';
|
|
10
|
-
const LABELS = {
|
|
11
|
-
is: 'is',
|
|
12
|
-
isNot: 'not',
|
|
13
|
-
contains: 'contains',
|
|
14
|
-
notContains: 'not contain',
|
|
15
|
-
startsWith: 'starts with',
|
|
16
|
-
endsWith: 'ends with',
|
|
17
|
-
gt: '>',
|
|
18
|
-
lt: '<',
|
|
19
|
-
gte: '≥',
|
|
20
|
-
lte: '≤',
|
|
21
|
-
in: '',
|
|
22
|
-
notIn: 'not in',
|
|
23
|
-
isEmpty: 'empty',
|
|
24
|
-
isNotEmpty: 'not empty',
|
|
25
|
-
};
|
|
26
|
-
const DEFAULT_TEXT_OPERATORS = [
|
|
27
|
-
'is',
|
|
28
|
-
'isNot',
|
|
29
|
-
'contains',
|
|
30
|
-
'notContains',
|
|
31
|
-
'startsWith',
|
|
32
|
-
'endsWith',
|
|
33
|
-
'isEmpty',
|
|
34
|
-
'isNotEmpty',
|
|
35
|
-
];
|
|
36
|
-
export const NUMBER_OPERATORS = [
|
|
37
|
-
'is',
|
|
38
|
-
'isNot',
|
|
39
|
-
'gt',
|
|
40
|
-
'lt',
|
|
41
|
-
'gte',
|
|
42
|
-
'lte',
|
|
43
|
-
'isEmpty',
|
|
44
|
-
'isNotEmpty',
|
|
45
|
-
];
|
|
46
|
-
const VALUELESS_OPERATORS = ['isEmpty', 'isNotEmpty'];
|
|
47
|
-
const INPUT_DEBOUNCE_MS = 500;
|
|
48
|
-
function OperatorDropdown({ value, onChange, operators, size = 'sm', disabled, }) {
|
|
49
|
-
const popRef = useRef(null);
|
|
50
|
-
const [activeIndex, setActiveIndex] = useState(() => Math.max(0, operators.indexOf(value)));
|
|
51
|
-
useEffect(() => {
|
|
52
|
-
setActiveIndex(Math.max(0, operators.indexOf(value)));
|
|
53
|
-
}, [operators, value]);
|
|
54
|
-
const handleSelect = (op) => {
|
|
55
|
-
var _a;
|
|
56
|
-
onChange(op);
|
|
57
|
-
setActiveIndex(operators.indexOf(op));
|
|
58
|
-
(_a = popRef.current) === null || _a === void 0 ? void 0 : _a.close();
|
|
59
|
-
};
|
|
60
|
-
return (_jsx(Popover, { ref: popRef, minWidth: "160px", trigger: (toggle, icon) => (_jsxs("button", { type: "button", onClick: toggle, disabled: disabled, "aria-label": "Skift operator", className: `${styles.operatorTrigger} ${styles[size]}`, children: [_jsx("span", { className: styles.operatorText, children: LABELS[value] }), icon] })), children: _jsx(Menu, { children: operators.map(op => {
|
|
61
|
-
const selected = op === value;
|
|
62
|
-
return (_jsx(Menu.Item, { active: selected, children: _jsxs("button", { type: "button", onClick: () => handleSelect(op), disabled: disabled, children: [_jsx("span", { style: { width: 16, display: 'inline-flex', justifyContent: 'center' }, children: selected ? _jsx(Check, { size: 16 }) : null }), LABELS[op]] }) }, op));
|
|
63
|
-
}) }) }));
|
|
64
|
-
}
|
|
65
|
-
function isFilterActive(value) {
|
|
66
|
-
if (Array.isArray(value))
|
|
67
|
-
return value.length > 0;
|
|
68
|
-
if (typeof value === 'string')
|
|
69
|
-
return value.trim().length > 0;
|
|
70
|
-
return value != null;
|
|
71
|
-
}
|
|
72
|
-
export function FilterField({ field, control, operator, value, onChange, operators, options = [], single = true, size = 'md', variant = 'surface', label, placeholder = 'Type value…', disabled, 'data-cy': dataCy, minWidth, width, maxWidth, popoverWidth, debounceTime = INPUT_DEBOUNCE_MS, ...inputProps }) {
|
|
73
|
-
var _a, _b, _c, _d, _e, _f;
|
|
74
|
-
const filterFieldRef = useRef(null);
|
|
75
|
-
const ops = useMemo(() => operators !== null && operators !== void 0 ? operators : DEFAULT_TEXT_OPERATORS, [operators]);
|
|
76
|
-
const shouldAutoFitTypeahead = control === 'select' && single && !width;
|
|
77
|
-
const [selectedOperator, setSelectedOperator] = useState(operator);
|
|
78
|
-
const active = isFilterActive(value);
|
|
79
|
-
useEffect(() => {
|
|
80
|
-
if (ops.includes(operator)) {
|
|
81
|
-
// Keep the dropdown responsive to local selection immediately, but let the
|
|
82
|
-
// controlled `operator` prop take back over once parent state catches up.
|
|
83
|
-
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
84
|
-
setSelectedOperator(operator);
|
|
85
|
-
}
|
|
86
|
-
}, [operator, ops]);
|
|
87
|
-
const [localValue, setLocalValue] = useState((_a = value) !== null && _a !== void 0 ? _a : '');
|
|
88
|
-
const debounceRef = useRef(null);
|
|
89
|
-
/**
|
|
90
|
-
* Holds the exact text value we most recently sent upward.
|
|
91
|
-
* While waiting for that value to round-trip back through URL/provider state,
|
|
92
|
-
* we ignore intermediate external churn so the input does not visually flicker.
|
|
93
|
-
*/
|
|
94
|
-
const pendingValueRef = useRef(null);
|
|
95
|
-
const emit = (next) => {
|
|
96
|
-
var _a, _b;
|
|
97
|
-
const nextOperator = (_a = next.operator) !== null && _a !== void 0 ? _a : selectedOperator;
|
|
98
|
-
const nextValue = (_b = next.value) !== null && _b !== void 0 ? _b : value;
|
|
99
|
-
if (next.operator) {
|
|
100
|
-
setSelectedOperator(nextOperator);
|
|
101
|
-
}
|
|
102
|
-
onChange({
|
|
103
|
-
field,
|
|
104
|
-
operator: nextOperator,
|
|
105
|
-
value: nextValue,
|
|
106
|
-
});
|
|
107
|
-
};
|
|
108
|
-
const clearDebounce = () => {
|
|
109
|
-
if (debounceRef.current) {
|
|
110
|
-
clearTimeout(debounceRef.current);
|
|
111
|
-
debounceRef.current = null;
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
const scheduleEmitValue = (nextVal) => {
|
|
115
|
-
clearDebounce();
|
|
116
|
-
pendingValueRef.current = nextVal;
|
|
117
|
-
debounceRef.current = setTimeout(() => {
|
|
118
|
-
emit({ value: nextVal });
|
|
119
|
-
}, debounceTime);
|
|
120
|
-
};
|
|
121
|
-
const flushPendingValue = () => {
|
|
122
|
-
if (control !== 'input')
|
|
123
|
-
return;
|
|
124
|
-
clearDebounce();
|
|
125
|
-
pendingValueRef.current = localValue;
|
|
126
|
-
emit({ value: localValue });
|
|
127
|
-
};
|
|
128
|
-
const handleOperatorChange = (op) => {
|
|
129
|
-
setSelectedOperator(op);
|
|
130
|
-
if (!active && !VALUELESS_OPERATORS.includes(op))
|
|
131
|
-
return;
|
|
132
|
-
if (VALUELESS_OPERATORS.includes(op)) {
|
|
133
|
-
clearDebounce();
|
|
134
|
-
pendingValueRef.current = null;
|
|
135
|
-
emit({ operator: op, value: null });
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
clearDebounce();
|
|
139
|
-
pendingValueRef.current =
|
|
140
|
-
control === 'input' ? localValue : typeof value === 'string' ? value : null;
|
|
141
|
-
emit({ operator: op });
|
|
142
|
-
};
|
|
143
|
-
useEffect(() => {
|
|
144
|
-
var _a;
|
|
145
|
-
if (control !== 'input')
|
|
146
|
-
return;
|
|
147
|
-
const incoming = (_a = value) !== null && _a !== void 0 ? _a : '';
|
|
148
|
-
const pending = pendingValueRef.current;
|
|
149
|
-
if (pending !== null) {
|
|
150
|
-
if (incoming === pending) {
|
|
151
|
-
pendingValueRef.current = null;
|
|
152
|
-
}
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
if (incoming !== localValue) {
|
|
156
|
-
// Keep the embedded input responsive while debounced updates are in flight,
|
|
157
|
-
// then resync to the controlled value once external state has settled.
|
|
158
|
-
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
159
|
-
setLocalValue(incoming);
|
|
160
|
-
}
|
|
161
|
-
}, [value, control, localValue]);
|
|
162
|
-
useEffect(() => {
|
|
163
|
-
return () => {
|
|
164
|
-
clearDebounce();
|
|
165
|
-
};
|
|
166
|
-
}, []);
|
|
167
|
-
return (_jsxs("div", { ref: filterFieldRef, ...(dataCy ? { 'data-cy': dataCy } : {}), className: [styles.filterField, styles[size], styles[variant], active ? styles.active : '']
|
|
168
|
-
.filter(Boolean)
|
|
169
|
-
.join(' '), children: [label ? _jsx("span", { className: `${styles.label} ${styles[size]}`, children: label }) : null, _jsx("div", { className: styles.operatorWrapper, children: _jsx(OperatorDropdown, { value: selectedOperator, onChange: handleOperatorChange, operators: ops, size: size, disabled: disabled }) }), _jsx("div", { className: [
|
|
170
|
-
styles.valueWrapper,
|
|
171
|
-
control === 'input' ? 'dbc-flex dbc-flex-grow' : '',
|
|
172
|
-
shouldAutoFitTypeahead ? styles.autoWidth : '',
|
|
173
|
-
]
|
|
174
|
-
.filter(Boolean)
|
|
175
|
-
.join(' '), style: shouldAutoFitTypeahead ? (maxWidth ? { maxWidth } : undefined) : { width, maxWidth }, children: control === 'input' ? (_jsx(Input, { variant: "embedded", ...inputProps, fieldClassName: styles.embeddedInputField, inputClassName: styles.embeddedInputElement, value: localValue, onChange: e => {
|
|
176
|
-
const next = e.currentTarget.value;
|
|
177
|
-
setLocalValue(next);
|
|
178
|
-
scheduleEmitValue(next);
|
|
179
|
-
}, onBlur: () => {
|
|
180
|
-
flushPendingValue();
|
|
181
|
-
}, fullWidth: true, inputSize: size, placeholder: placeholder, disabled: disabled, autoComplete: (_b = inputProps.autoComplete) !== null && _b !== void 0 ? _b : 'off', autoCorrect: (_c = inputProps.autoCorrect) !== null && _c !== void 0 ? _c : 'off', autoCapitalize: (_d = inputProps.autoCapitalize) !== null && _d !== void 0 ? _d : 'none', spellCheck: (_e = inputProps.spellCheck) !== null && _e !== void 0 ? _e : false, onClear: () => {
|
|
182
|
-
clearDebounce();
|
|
183
|
-
pendingValueRef.current = '';
|
|
184
|
-
setLocalValue('');
|
|
185
|
-
emit({ value: '' });
|
|
186
|
-
} })) : (_jsx(Typeahead, { options: options, mode: single ? 'single' : 'multi', selectedValue: single ? ((_f = value) !== null && _f !== void 0 ? _f : null) : Array.isArray(value) ? value : [], onChange: v => emit({ value: v }), minWidth: minWidth, popoverWidth: popoverWidth, popoverAnchorRef: filterFieldRef, placeholder: placeholder, variant: "embedded", inputProps: {
|
|
187
|
-
inputSize: size,
|
|
188
|
-
fieldClassName: styles.embeddedInputField,
|
|
189
|
-
inputClassName: styles.embeddedInputElement,
|
|
190
|
-
}, onClear: () => emit({ value: single ? '' : [] }), disabled: disabled, fullWidth: !shouldAutoFitTypeahead, fitContent: shouldAutoFitTypeahead })) })] }));
|
|
191
|
-
}
|