@dbcdk/react-components 0.0.5 → 0.0.7

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.
Files changed (276) hide show
  1. package/dist/assets/logo.js +2 -85
  2. package/dist/components/__stories__/_data/table.d.ts +15 -0
  3. package/dist/components/__stories__/_data/table.js +49 -0
  4. package/dist/components/__stories__/story-components/Colors.d.ts +2 -1
  5. package/dist/components/__stories__/story-components/Colors.js +87 -142
  6. package/dist/components/__stories__/story-components/Spacing.d.ts +1 -0
  7. package/dist/components/__stories__/story-components/Spacing.js +58 -166
  8. package/dist/components/app-header/AppHeader.d.ts +4 -3
  9. package/dist/components/app-header/AppHeader.js +3 -6
  10. package/dist/components/attribute-chip/AttributeChip.d.ts +1 -0
  11. package/dist/components/attribute-chip/AttributeChip.js +3 -14
  12. package/dist/components/avatar/Avatar.d.ts +2 -2
  13. package/dist/components/avatar/Avatar.js +37 -71
  14. package/dist/components/breadcrumbs/Breadcrumbs.d.ts +4 -4
  15. package/dist/components/breadcrumbs/Breadcrumbs.js +4 -13
  16. package/dist/components/button/Button.d.ts +3 -2
  17. package/dist/components/button/Button.js +54 -56
  18. package/dist/components/button/Button.module.css +1 -1
  19. package/dist/components/card/Card.d.ts +8 -7
  20. package/dist/components/card/Card.js +19 -60
  21. package/dist/components/card-container/CardContainer.d.ts +3 -3
  22. package/dist/components/card-container/CardContainer.js +4 -16
  23. package/dist/components/chip/Chip.d.ts +6 -5
  24. package/dist/components/chip/Chip.js +14 -38
  25. package/dist/components/chip/Chip.module.css +9 -1
  26. package/dist/components/circle/Circle.d.ts +3 -2
  27. package/dist/components/circle/Circle.js +3 -10
  28. package/dist/components/clear-button/ClearButton.d.ts +2 -1
  29. package/dist/components/clear-button/ClearButton.js +6 -17
  30. package/dist/components/code-block/CodeBlock.d.ts +1 -0
  31. package/dist/components/code-block/CodeBlock.js +4 -10
  32. package/dist/components/copy-button/CopyButton.d.ts +4 -3
  33. package/dist/components/copy-button/CopyButton.js +19 -26
  34. package/dist/components/datetime-picker/DateTimePicker.d.ts +8 -5
  35. package/dist/components/datetime-picker/DateTimePicker.js +262 -475
  36. package/dist/components/datetime-picker/dateTimeHelpers.d.ts +13 -0
  37. package/dist/components/datetime-picker/dateTimeHelpers.js +119 -0
  38. package/dist/components/filter-field/FilterField.d.ts +5 -2
  39. package/dist/components/filter-field/FilterField.js +130 -173
  40. package/dist/components/filter-field/FilterField.module.css +21 -5
  41. package/dist/components/filtering/chip-multi-toggle/ChipMultiToggle.d.ts +36 -0
  42. package/dist/components/filtering/chip-multi-toggle/ChipMultiToggle.js +53 -0
  43. package/dist/components/filtering/chip-multi-toggle/ChipMultiToggle.module.css +60 -0
  44. package/dist/components/forms/checkbox/Checkbox.d.ts +31 -0
  45. package/dist/components/forms/checkbox/Checkbox.js +27 -0
  46. package/dist/components/{checkbox → forms/checkbox}/Checkbox.module.css +0 -1
  47. package/dist/components/forms/checkbox-group/CheckboxGroup.d.ts +47 -0
  48. package/dist/components/forms/checkbox-group/CheckboxGroup.js +75 -0
  49. package/dist/components/forms/checkbox-group/CheckboxGroup.module.css +115 -0
  50. package/dist/components/{input → forms/input}/Input.d.ts +9 -5
  51. package/dist/components/forms/input/Input.js +70 -0
  52. package/dist/components/{input → forms/input}/Input.module.css +1 -0
  53. package/dist/components/forms/input-container/InputContainer.d.ts +15 -0
  54. package/dist/components/forms/input-container/InputContainer.js +15 -0
  55. package/dist/components/forms/input-container/InputContainer.module.css +34 -0
  56. package/dist/components/forms/multi-select/MultiSelect.d.ts +20 -0
  57. package/dist/components/forms/multi-select/MultiSelect.js +19 -0
  58. package/dist/components/forms/select/Select.d.ts +21 -0
  59. package/dist/components/forms/select/Select.js +94 -0
  60. package/dist/components/forms/text-area/Textarea.d.ts +17 -0
  61. package/dist/components/forms/text-area/Textarea.js +33 -0
  62. package/dist/components/forms/text-area/Textarea.module.css +26 -0
  63. package/dist/components/headline/Headline.js +18 -43
  64. package/dist/components/{link/Link.d.ts → hyperlink/Hyperlink.d.ts} +2 -2
  65. package/dist/components/hyperlink/Hyperlink.js +11 -0
  66. package/dist/components/{link/Link.module.css → hyperlink/Hyperlink.module.css} +5 -14
  67. package/dist/components/icon/Icon.d.ts +4 -3
  68. package/dist/components/icon/Icon.js +11 -17
  69. package/dist/components/interval-select/IntervalSelect.d.ts +30 -0
  70. package/dist/components/interval-select/IntervalSelect.js +82 -0
  71. package/dist/components/menu/Menu.js +25 -67
  72. package/dist/components/meta-bar/MetaBar.d.ts +4 -4
  73. package/dist/components/meta-bar/MetaBar.js +7 -20
  74. package/dist/components/nav-bar/NavBar.d.ts +5 -5
  75. package/dist/components/nav-bar/NavBar.js +15 -45
  76. package/dist/components/{modal → overlay/modal}/Modal.d.ts +4 -2
  77. package/dist/components/overlay/modal/Modal.js +92 -0
  78. package/dist/components/{modal → overlay/modal}/provider/ModalProvider.d.ts +0 -1
  79. package/dist/components/overlay/modal/provider/ModalProvider.js +70 -0
  80. package/dist/components/overlay/side-panel/SidePanel.d.ts +16 -0
  81. package/dist/components/overlay/side-panel/SidePanel.js +10 -0
  82. package/dist/components/overlay/side-panel/SidePanel.module.css +56 -0
  83. package/dist/components/overlay/side-panel/useSidePanel.d.ts +5 -0
  84. package/dist/components/overlay/side-panel/useSidePanel.js +11 -0
  85. package/dist/components/overlay/tooltip/Tooltip.d.ts +13 -0
  86. package/dist/components/overlay/tooltip/Tooltip.js +17 -0
  87. package/dist/components/overlay/tooltip/Tooltip.module.css +106 -0
  88. package/dist/components/overlay/tooltip/TooltipProvider.d.ts +20 -0
  89. package/dist/components/overlay/tooltip/TooltipProvider.js +244 -0
  90. package/dist/components/overlay/tooltip/useTooltipTrigger.d.ts +24 -0
  91. package/dist/components/overlay/tooltip/useTooltipTrigger.js +108 -0
  92. package/dist/components/page/Page.d.ts +7 -6
  93. package/dist/components/page/Page.js +4 -21
  94. package/dist/components/page-layout/PageLayout.d.ts +11 -12
  95. package/dist/components/page-layout/PageLayout.js +35 -71
  96. package/dist/components/page-layout/components/page-layout-hero/PageLayoutHero.js +4 -22
  97. package/dist/components/pagination/Pagination.d.ts +2 -1
  98. package/dist/components/pagination/Pagination.js +38 -121
  99. package/dist/components/panel/Panel.d.ts +4 -3
  100. package/dist/components/panel/Panel.js +5 -10
  101. package/dist/components/popover/Popover.d.ts +1 -0
  102. package/dist/components/popover/Popover.js +116 -141
  103. package/dist/components/search-box/SearchBox.d.ts +2 -2
  104. package/dist/components/search-box/SearchBox.js +112 -162
  105. package/dist/components/segmented-progress-bar/SegmentedProgressBar.d.ts +1 -1
  106. package/dist/components/segmented-progress-bar/SegmentedProgressBar.js +47 -94
  107. package/dist/components/sidebar/Sidebar.d.ts +1 -0
  108. package/dist/components/sidebar/Sidebar.js +5 -7
  109. package/dist/components/sidebar/components/SidebarItem.js +6 -14
  110. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.d.ts +1 -1
  111. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.js +48 -88
  112. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.d.ts +3 -2
  113. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.js +11 -41
  114. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.d.ts +1 -0
  115. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.js +4 -25
  116. package/dist/components/sidebar/components/sidebar-items/SidebarItems.js +9 -23
  117. package/dist/components/sidebar/components/sidenav-filteirng/SidenavFiltering.js +19 -40
  118. package/dist/components/sidebar/providers/SidebarProvider.d.ts +2 -1
  119. package/dist/components/sidebar/providers/SidebarProvider.js +182 -165
  120. package/dist/components/skeleton-loader/SkeletonLoader.js +68 -266
  121. package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.js +11 -34
  122. package/dist/components/split-button/SplitButton.d.ts +7 -5
  123. package/dist/components/split-button/SplitButton.js +4 -27
  124. package/dist/components/split-pane/SplitPane.js +69 -105
  125. package/dist/components/split-pane/provider/SplitPaneContext.js +77 -71
  126. package/dist/components/table/Table.d.ts +9 -7
  127. package/dist/components/table/Table.js +115 -238
  128. package/dist/components/table/Table.module.css +5 -1
  129. package/dist/components/table/components/column-resizer/ColumnResizer.js +4 -15
  130. package/dist/components/table/components/empty-state/EmptyState.d.ts +6 -5
  131. package/dist/components/table/components/empty-state/EmptyState.js +22 -41
  132. package/dist/components/table/components/table-settings/TableSettings.d.ts +2 -1
  133. package/dist/components/table/components/table-settings/TableSettings.js +9 -27
  134. package/dist/components/table/tanstack.d.ts +1 -1
  135. package/dist/components/table/tanstack.js +154 -160
  136. package/dist/components/tabs/Tabs.d.ts +1 -0
  137. package/dist/components/tabs/Tabs.js +32 -81
  138. package/dist/components/toast/Toast.d.ts +1 -1
  139. package/dist/components/toast/Toast.js +4 -37
  140. package/dist/components/toast/Toast.module.css +1 -0
  141. package/dist/components/toast/provider/ToastProvider.d.ts +1 -1
  142. package/dist/components/toast/provider/ToastProvider.js +60 -87
  143. package/dist/components/user-display/UserDisplay.d.ts +2 -1
  144. package/dist/components/user-display/UserDisplay.js +4 -20
  145. package/dist/constants/severity.d.ts +1 -1
  146. package/dist/constants/severity.js +14 -16
  147. package/dist/constants/severity.types.d.ts +1 -1
  148. package/dist/constants/severity.types.js +1 -1
  149. package/dist/constants/sizes.js +6 -8
  150. package/dist/hooks/usePagination.d.ts +1 -1
  151. package/dist/hooks/usePagination.js +75 -82
  152. package/dist/hooks/useSorting.js +112 -110
  153. package/dist/hooks/useTableData.d.ts +1 -1
  154. package/dist/hooks/useTableData.js +42 -47
  155. package/dist/hooks/useTableSelection.js +121 -121
  156. package/dist/hooks/useTableSettings.js +23 -25
  157. package/dist/hooks/useTheme.d.ts +3 -7
  158. package/dist/hooks/useTheme.js +52 -47
  159. package/dist/hooks/useTimeDuration.d.ts +2 -2
  160. package/dist/hooks/useTimeDuration.js +33 -34
  161. package/dist/hooks/useViewportFill.d.ts +3 -2
  162. package/dist/hooks/useViewportFill.js +55 -48
  163. package/dist/index.d.ts +17 -8
  164. package/dist/index.js +18 -8
  165. package/dist/src/styles/styles.css +3 -3
  166. package/dist/styles/css-helper-classes/flex.css +4 -0
  167. package/dist/styles/styles.css +3 -3
  168. package/dist/styles/themes/dbc/dark.css +1 -1
  169. package/dist/styles/themes/dbc/light.css +2 -1
  170. package/dist/styles/themes/forfatterweb/light.css +1 -1
  171. package/dist/styles/themes/types.js +1 -1
  172. package/dist/types/a11y-props.types.d.ts +5 -5
  173. package/dist/types/a11y-props.types.js +1 -1
  174. package/dist/types/sizes.types.js +1 -1
  175. package/dist/utils/arrays/nested-filtering.js +43 -33
  176. package/dist/utils/date/formatDate.js +25 -16
  177. package/package.json +18 -9
  178. package/dist/assets/logo.cjs +0 -87
  179. package/dist/components/__stories__/story-components/Colors.cjs +0 -159
  180. package/dist/components/__stories__/story-components/Spacing.cjs +0 -190
  181. package/dist/components/app-header/AppHeader.cjs +0 -14
  182. package/dist/components/attribute-chip/AttributeChip.cjs +0 -22
  183. package/dist/components/avatar/Avatar.cjs +0 -101
  184. package/dist/components/breadcrumbs/Breadcrumbs.cjs +0 -22
  185. package/dist/components/button/Button.cjs +0 -87
  186. package/dist/components/card/Card.cjs +0 -69
  187. package/dist/components/card-container/CardContainer.cjs +0 -24
  188. package/dist/components/checkbox/Checkbox.cjs +0 -42
  189. package/dist/components/checkbox/Checkbox.d.ts +0 -12
  190. package/dist/components/checkbox/Checkbox.js +0 -36
  191. package/dist/components/chip/Chip.cjs +0 -50
  192. package/dist/components/circle/Circle.cjs +0 -18
  193. package/dist/components/clear-button/ClearButton.cjs +0 -26
  194. package/dist/components/code-block/CodeBlock.cjs +0 -18
  195. package/dist/components/copy-button/CopyButton.cjs +0 -35
  196. package/dist/components/datetime-picker/DateTimePicker.cjs +0 -504
  197. package/dist/components/filter-field/FilterField.cjs +0 -189
  198. package/dist/components/headline/Headline.cjs +0 -53
  199. package/dist/components/icon/Icon.cjs +0 -27
  200. package/dist/components/input/Input.cjs +0 -89
  201. package/dist/components/input/Input.js +0 -83
  202. package/dist/components/link/Link.cjs +0 -46
  203. package/dist/components/link/Link.js +0 -21
  204. package/dist/components/menu/Menu.cjs +0 -96
  205. package/dist/components/meta-bar/MetaBar.cjs +0 -29
  206. package/dist/components/modal/Modal.cjs +0 -134
  207. package/dist/components/modal/Modal.js +0 -128
  208. package/dist/components/modal/provider/ModalProvider.cjs +0 -80
  209. package/dist/components/modal/provider/ModalProvider.js +0 -77
  210. package/dist/components/multi-select/MultiSelect.cjs +0 -59
  211. package/dist/components/multi-select/MultiSelect.d.ts +0 -18
  212. package/dist/components/multi-select/MultiSelect.js +0 -57
  213. package/dist/components/nav-bar/NavBar.cjs +0 -55
  214. package/dist/components/page/Page.cjs +0 -30
  215. package/dist/components/page-layout/PageLayout.cjs +0 -84
  216. package/dist/components/page-layout/components/page-layout-hero/PageLayoutHero.cjs +0 -32
  217. package/dist/components/pagination/Pagination.cjs +0 -133
  218. package/dist/components/panel/Panel.cjs +0 -18
  219. package/dist/components/popover/Popover.cjs +0 -149
  220. package/dist/components/search-box/SearchBox.cjs +0 -175
  221. package/dist/components/segmented-progress-bar/SegmentedProgressBar.cjs +0 -103
  222. package/dist/components/select/Select.cjs +0 -121
  223. package/dist/components/select/Select.d.ts +0 -12
  224. package/dist/components/select/Select.js +0 -119
  225. package/dist/components/sidebar/Sidebar.cjs +0 -11
  226. package/dist/components/sidebar/components/SidebarItem.cjs +0 -18
  227. package/dist/components/sidebar/components/expandable-sidebar-item/ExpandableSidebarItem.cjs +0 -100
  228. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.cjs +0 -50
  229. package/dist/components/sidebar/components/sidebar-item-content/SidebarItemContent.cjs +0 -34
  230. package/dist/components/sidebar/components/sidebar-items/SidebarItems.cjs +0 -29
  231. package/dist/components/sidebar/components/sidenav-filteirng/SidenavFiltering.cjs +0 -52
  232. package/dist/components/sidebar/providers/SidebarProvider.cjs +0 -179
  233. package/dist/components/skeleton-loader/SkeletonLoader.cjs +0 -270
  234. package/dist/components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem.cjs +0 -42
  235. package/dist/components/split-button/SplitButton.cjs +0 -37
  236. package/dist/components/split-pane/SplitPane.cjs +0 -123
  237. package/dist/components/split-pane/provider/SplitPaneContext.cjs +0 -87
  238. package/dist/components/table/Table.cjs +0 -249
  239. package/dist/components/table/components/column-resizer/ColumnResizer.cjs +0 -22
  240. package/dist/components/table/components/empty-state/EmptyState.cjs +0 -52
  241. package/dist/components/table/components/table-settings/TableSettings.cjs +0 -32
  242. package/dist/components/table/tanstack.cjs +0 -193
  243. package/dist/components/tabs/Tabs.cjs +0 -90
  244. package/dist/components/text-area/Textarea.cjs +0 -62
  245. package/dist/components/text-area/Textarea.d.ts +0 -14
  246. package/dist/components/text-area/Textarea.js +0 -56
  247. package/dist/components/text-area/Textarea.module.css +0 -3
  248. package/dist/components/toast/Toast.cjs +0 -47
  249. package/dist/components/toast/provider/ToastProvider.cjs +0 -98
  250. package/dist/components/tooltip/Tooltip.cjs +0 -183
  251. package/dist/components/tooltip/Tooltip.d.ts +0 -11
  252. package/dist/components/tooltip/Tooltip.js +0 -177
  253. package/dist/components/tooltip/Tooltip.module.css +0 -66
  254. package/dist/components/user-display/UserDisplay.cjs +0 -28
  255. package/dist/constants/severity.cjs +0 -21
  256. package/dist/constants/severity.types.cjs +0 -2
  257. package/dist/constants/sizes.cjs +0 -11
  258. package/dist/hooks/usePagination.cjs +0 -88
  259. package/dist/hooks/useSorting.cjs +0 -118
  260. package/dist/hooks/useTableData.cjs +0 -52
  261. package/dist/hooks/useTableSelection.cjs +0 -130
  262. package/dist/hooks/useTableSettings.cjs +0 -28
  263. package/dist/hooks/useTheme.cjs +0 -58
  264. package/dist/hooks/useTimeDuration.cjs +0 -39
  265. package/dist/hooks/useViewportFill.cjs +0 -52
  266. package/dist/index.cjs +0 -383
  267. package/dist/styles/themes/types.cjs +0 -2
  268. package/dist/types/a11y-props.types.cjs +0 -2
  269. package/dist/types/assets.d.cjs +0 -2
  270. package/dist/types/assets.d.js +0 -1
  271. package/dist/types/css.d.cjs +0 -2
  272. package/dist/types/css.d.js +0 -1
  273. package/dist/types/sizes.types.cjs +0 -2
  274. package/dist/utils/arrays/nested-filtering.cjs +0 -40
  275. package/dist/utils/date/formatDate.cjs +0 -19
  276. /package/dist/components/{modal → overlay/modal}/Modal.module.css +0 -0
@@ -1,498 +1,285 @@
1
- import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { forwardRef, useRef, useMemo, useState, useCallback, useEffect } from 'react';
3
- import { X, ChevronLeft, ChevronRight, Clock, Calendar } from 'lucide-react';
4
- import { Popover } from '../popover/Popover';
5
- import { Input } from '../input/Input';
6
- import { Button } from '../button/Button';
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Calendar, ChevronLeft, ChevronRight, Clock, X } from 'lucide-react';
4
+ import { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
5
+ import { Button } from '../../components/button/Button';
6
+ import { Input } from '../../components/forms/input/Input';
7
+ import { Popover } from '../../components/popover/Popover';
7
8
  import styles from './DateTimePicker.module.css';
8
-
9
- const digits = (s) => (s.match(/\d/g) || []).join("");
10
- function maskDateEU(text) {
11
- const d = digits(text).slice(0, 8);
12
- const dd = d.slice(0, 2);
13
- const mm = d.slice(2, 4);
14
- const yyyy = d.slice(4, 8);
15
- let out = dd;
16
- if (mm.length) out += (out ? "-" : "") + mm;
17
- if (yyyy.length) out += (out ? "-" : "") + yyyy;
18
- return out;
19
- }
20
- function maskTimeHM(text) {
21
- const d = digits(text).slice(0, 4);
22
- const hh = d.slice(0, 2);
23
- const mm = d.slice(2, 4);
24
- return mm.length ? `${hh}:${mm}` : hh;
25
- }
26
- function maskSingle(text, enableTime) {
27
- let t = text.trim().replace(/\s+/g, " ");
28
- if (!enableTime) return maskDateEU(t);
29
- const m = /^(.*?)[ T](.*)$/.exec(t);
30
- if (!m) return maskDateEU(t);
31
- const datePart = maskDateEU(m[1]);
32
- const timePart = maskTimeHM(m[2]);
33
- return timePart ? `${datePart} ${timePart}` : datePart;
34
- }
35
- function maskRange(text, enableTime) {
36
- const sepRe = /\s*(?:–|-|to|til)\s*/i;
37
- const parts = text.split(sepRe);
38
- if (parts.length === 1) {
39
- return maskSingle(parts[0], enableTime);
40
- }
41
- const a = maskSingle(parts[0], enableTime);
42
- const b = maskSingle(parts.slice(1).join(" "), enableTime);
43
- return `${a} \u2013 ${b}`.trim();
44
- }
45
- const pad2 = (n) => String(n).padStart(2, "0");
46
- function toMaskedFromDate(d, enableTime) {
47
- const dd = pad2(d.getDate());
48
- const mm = pad2(d.getMonth() + 1);
49
- const yyyy = String(d.getFullYear());
50
- let out = `${dd}-${mm}-${yyyy}`;
51
- if (enableTime) out += ` ${pad2(d.getHours())}:${pad2(d.getMinutes())}`;
52
- return out;
53
- }
54
- function toMaskedRange(start, end, enableTime) {
55
- if (start && end)
56
- return `${toMaskedFromDate(start, enableTime)} \u2013 ${toMaskedFromDate(end, enableTime)}`;
57
- if (start) return `${toMaskedFromDate(start, enableTime)} \u2013`;
58
- if (end) return `\u2013 ${toMaskedFromDate(end, enableTime)}`;
59
- return "";
60
- }
61
- function parseLooseDateOrDateTime(input) {
62
- const txt = input.trim().replace(/\s+/g, " ");
63
- const dateTimeMatch = /^(?<date>[\d./-]{8,10})(?:[ T](?<hh>\d{1,2}):(?<mm>\d{2}))?$/i.exec(txt);
64
- if (!(dateTimeMatch == null ? void 0 : dateTimeMatch.groups)) return null;
65
- const raw = dateTimeMatch.groups.date;
66
- const hh = dateTimeMatch.groups.hh ? parseInt(dateTimeMatch.groups.hh, 10) : 0;
67
- const mm = dateTimeMatch.groups.mm ? parseInt(dateTimeMatch.groups.mm, 10) : 0;
68
- if (hh < 0 || hh > 23 || mm < 0 || mm > 59) return null;
69
- let y, m, d;
70
- let mIso = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(raw);
71
- if (mIso) {
72
- y = +mIso[1];
73
- m = +mIso[2] - 1;
74
- d = +mIso[3];
75
- } else {
76
- let mEu = /^(\d{1,2})[./-](\d{1,2})[./-](\d{4})$/.exec(raw);
77
- if (!mEu) return null;
78
- d = +mEu[1];
79
- m = +mEu[2] - 1;
80
- y = +mEu[3];
81
- }
82
- const local = new Date(y, m, d, hh, mm, 0, 0);
83
- if (Number.isNaN(local.getTime())) return null;
84
- if (local.getFullYear() !== y || local.getMonth() !== m || local.getDate() !== d) return null;
85
- return local;
86
- }
87
- function parseLooseRange(input) {
88
- const sep = /\s*(?:–|-|to|til)\s*/i;
89
- const [a, b] = input.split(sep);
90
- if (!a || !b) return null;
91
- const s = parseLooseDateOrDateTime(a);
92
- const e = parseLooseDateOrDateTime(b);
93
- if (!s || !e) return null;
94
- return s <= e ? { start: s, end: e } : { start: e, end: s };
95
- }
9
+ import { maskRange, maskSingle, parseLooseDateOrDateTime, parseLooseRange, toMaskedFromDate, toMaskedRange, } from './dateTimeHelpers';
10
+ /* ---------- Date grid helpers (UTC) ---------- */
96
11
  const dUTC = (y, m, day) => new Date(Date.UTC(y, m, day));
97
12
  const addDaysUTC = (utcDate, n) => dUTC(utcDate.getUTCFullYear(), utcDate.getUTCMonth(), utcDate.getUTCDate() + n);
98
13
  const startOfMonthUTC = (utcDate) => dUTC(utcDate.getUTCFullYear(), utcDate.getUTCMonth(), 1);
99
14
  const endOfMonthUTC = (utcDate) => dUTC(utcDate.getUTCFullYear(), utcDate.getUTCMonth() + 1, 0);
100
- const sameDayUTC = (a, b) => a.getUTCFullYear() === b.getUTCFullYear() && a.getUTCMonth() === b.getUTCMonth() && a.getUTCDate() === b.getUTCDate();
15
+ const sameDayUTC = (a, b) => a.getUTCFullYear() === b.getUTCFullYear() &&
16
+ a.getUTCMonth() === b.getUTCMonth() &&
17
+ a.getUTCDate() === b.getUTCDate();
101
18
  const toUTCDateOnly = (local) => dUTC(local.getFullYear(), local.getMonth(), local.getDate());
102
19
  const startOfWeekUTC = (utcDate, weekStartsOn) => {
103
- const dow = utcDate.getUTCDay();
104
- const diff = (dow - weekStartsOn + 7) % 7;
105
- return addDaysUTC(utcDate, -diff);
20
+ const dow = utcDate.getUTCDay();
21
+ const diff = (dow - weekStartsOn + 7) % 7;
22
+ return addDaysUTC(utcDate, -diff);
106
23
  };
107
24
  function buildMonthGrid(anchorLocalDate, weekStartsOn) {
108
- const anchorUTC = toUTCDateOnly(anchorLocalDate);
109
- const firstUTC = startOfWeekUTC(startOfMonthUTC(anchorUTC), weekStartsOn);
110
- const cells = [];
111
- for (let i = 0; i < 42; i++) cells.push(addDaysUTC(firstUTC, i));
112
- return cells;
25
+ const anchorUTC = toUTCDateOnly(anchorLocalDate);
26
+ const firstUTC = startOfWeekUTC(startOfMonthUTC(anchorUTC), weekStartsOn);
27
+ const cells = [];
28
+ for (let i = 0; i < 42; i++)
29
+ cells.push(addDaysUTC(firstUTC, i));
30
+ return cells;
113
31
  }
114
32
  const isBetweenUTC = (d, a, b) => {
115
- const t = +d, s = +a, e = +b;
116
- return t >= Math.min(s, e) && t <= Math.max(s, e);
33
+ const t = +d, s = +a, e = +b;
34
+ return t >= Math.min(s, e) && t <= Math.max(s, e);
117
35
  };
118
36
  function composeLocalDateTimeISO(utcDateOnly, hh, mm) {
119
- const y = utcDateOnly.getUTCFullYear();
120
- const m = utcDateOnly.getUTCMonth();
121
- const d = utcDateOnly.getUTCDate();
122
- const local = new Date(y, m, d, hh, mm, 0, 0);
123
- return local.toISOString();
37
+ const y = utcDateOnly.getUTCFullYear();
38
+ const m = utcDateOnly.getUTCMonth();
39
+ const d = utcDateOnly.getUTCDate();
40
+ const local = new Date(y, m, d, hh, mm, 0, 0);
41
+ return local.toISOString();
124
42
  }
43
+ /* ---------- Formatting (exposed but input uses mask) ---------- */
125
44
  function defaultFormatDate(d, { locale, enableTime }) {
126
- const opts = enableTime ? { year: "numeric", month: "short", day: "2-digit", hour: "2-digit", minute: "2-digit" } : { year: "numeric", month: "short", day: "2-digit" };
127
- return new Intl.DateTimeFormat(locale || void 0, opts).format(d);
45
+ const opts = enableTime
46
+ ? { year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }
47
+ : { year: 'numeric', month: 'short', day: '2-digit' };
48
+ return new Intl.DateTimeFormat(locale || undefined, opts).format(d);
128
49
  }
129
50
  function defaultFormatRange(s, e, opts) {
130
- if (s && e) return `${defaultFormatDate(s, opts)} \u2013 ${defaultFormatDate(e, opts)}`;
131
- if (s) return `${defaultFormatDate(s, opts)} \u2013`;
132
- if (e) return `\u2013 ${defaultFormatDate(e, opts)}`;
133
- return "";
51
+ if (s && e)
52
+ return `${defaultFormatDate(s, opts)} ${defaultFormatDate(e, opts)}`;
53
+ if (s)
54
+ return `${defaultFormatDate(s, opts)} –`;
55
+ if (e)
56
+ return `– ${defaultFormatDate(e, opts)}`;
57
+ return '';
134
58
  }
135
- const cx = (...classes) => classes.filter(Boolean).join(" ");
136
- const DateTimePicker = forwardRef(function DateTimePicker2({
137
- mode = "single",
138
- value,
139
- onChange,
140
- enableTime = false,
141
- timeStep = 15,
142
- min,
143
- max,
144
- locale = typeof navigator !== "undefined" ? navigator.language : "da-DK",
145
- weekStartsOn = 1,
146
- presets,
147
- placeholder,
148
- inputSize = "md",
149
- disabled,
150
- id,
151
- formatDate = defaultFormatDate,
152
- // still exposed, not used for input text
153
- formatRange = defaultFormatRange
154
- // still exposed, not used for input text
155
- }, _ref) {
156
- const popRef = useRef(null);
157
- const todayLocal = useMemo(() => /* @__PURE__ */ new Date(), []);
158
- const initialAnchor = useMemo(() => {
159
- if (mode === "single" && value instanceof Date && value) return value;
160
- if (mode === "range" && value && typeof value === "object" && "start" in value && value.start)
161
- return value.start;
162
- return todayLocal;
163
- }, [mode, value, todayLocal]);
164
- const [monthAnchor, setMonthAnchor] = useState(initialAnchor);
165
- const [timeHH, setTimeHH] = useState(todayLocal.getHours());
166
- const [timeMM, setTimeMM] = useState(
167
- Math.floor(todayLocal.getMinutes() / timeStep) * timeStep
168
- );
169
- const [hoverUTC, setHoverUTC] = useState(null);
170
- const cellsUTC = useMemo(
171
- () => buildMonthGrid(monthAnchor, weekStartsOn),
172
- [monthAnchor, weekStartsOn]
173
- );
174
- const monthStartUTC = useMemo(() => startOfMonthUTC(toUTCDateOnly(monthAnchor)), [monthAnchor]);
175
- const monthEndUTC = useMemo(() => endOfMonthUTC(toUTCDateOnly(monthAnchor)), [monthAnchor]);
176
- const weekdayFmt = useMemo(() => new Intl.DateTimeFormat(locale, { weekday: "short" }), [locale]);
177
- const monthFmt = useMemo(
178
- () => new Intl.DateTimeFormat(locale, { month: "long", year: "numeric" }),
179
- [locale]
180
- );
181
- const selectedUTC_single = mode === "single" && value instanceof Date && value ? toUTCDateOnly(value) : null;
182
- const selectedUTC_start = mode === "range" && value && typeof value === "object" && "start" in value && value.start ? toUTCDateOnly(value.start) : null;
183
- const selectedUTC_end = mode === "range" && value && typeof value === "object" && "end" in value && value.end ? toUTCDateOnly(value.end) : null;
184
- const isDisabledUTC = useCallback(
185
- (utcDay) => {
186
- if (min && utcDay < toUTCDateOnly(min)) return true;
187
- if (max && utcDay > toUTCDateOnly(max)) return true;
188
- return false;
189
- },
190
- [min, max]
191
- );
192
- const selectDay = (utcDay) => {
193
- var _a, _b;
194
- if (isDisabledUTC(utcDay)) return;
195
- if (mode === "single") {
196
- if (enableTime) {
197
- const iso = composeLocalDateTimeISO(utcDay, timeHH, timeMM);
198
- onChange(new Date(iso));
199
- } else {
200
- onChange(new Date(utcDay.getTime()));
201
- }
202
- (_a = popRef.current) == null ? void 0 : _a.close();
203
- return;
204
- }
205
- const curr = value && typeof value === "object" && "start" in value ? value : { start: null, end: null };
206
- if (!curr.start || curr.start && curr.end) {
207
- onChange({ start: new Date(utcDay.getTime()), end: null });
208
- } else {
209
- const startUTC = toUTCDateOnly(curr.start);
210
- const endUTC = utcDay;
211
- const s = new Date(Math.min(+startUTC, +endUTC));
212
- const e = new Date(Math.max(+startUTC, +endUTC));
213
- onChange({ start: s, end: e });
214
- (_b = popRef.current) == null ? void 0 : _b.close();
215
- }
216
- };
217
- const gridRef = useRef(null);
218
- useEffect(() => {
219
- const el = gridRef.current;
220
- if (!el) return;
221
- const onKey = (e) => {
222
- var _a;
223
- if (!((_a = popRef.current) == null ? void 0 : _a.isOpen())) return;
224
- if ([
225
- "ArrowLeft",
226
- "ArrowRight",
227
- "ArrowUp",
228
- "ArrowDown",
229
- "PageUp",
230
- "PageDown",
231
- "Home",
232
- "End"
233
- ].includes(e.key)) {
234
- e.preventDefault();
235
- }
236
- const anchor = toUTCDateOnly(monthAnchor);
237
- const move = (days) => setMonthAnchor((prev) => addDaysLocal(prev, days));
238
- switch (e.key) {
239
- case "ArrowLeft":
240
- move(-1);
241
- break;
242
- case "ArrowRight":
243
- move(1);
244
- break;
245
- case "ArrowUp":
246
- move(-7);
247
- break;
248
- case "ArrowDown":
249
- move(7);
250
- break;
251
- case "PageUp":
252
- setMonthAnchor(addMonthsLocal(monthAnchor, -1));
253
- break;
254
- case "PageDown":
255
- setMonthAnchor(addMonthsLocal(monthAnchor, 1));
256
- break;
257
- case "Home":
258
- setMonthAnchor(new Date(anchor.getUTCFullYear(), anchor.getUTCMonth(), 1));
259
- break;
260
- case "End":
261
- setMonthAnchor(new Date(anchor.getUTCFullYear(), anchor.getUTCMonth() + 1, 0));
262
- break;
263
- }
59
+ const cx = (...classes) => classes.filter(Boolean).join(' ');
60
+ export const DateTimePicker = forwardRef(function DateTimePicker({ mode = 'single', value, onChange, enableTime = false, timeStep = 15, min, max, locale = typeof navigator !== 'undefined' ? navigator.language : 'da-DK', weekStartsOn = 1, presets, inputProps, formatDate = defaultFormatDate, // still exposed, not used for input text
61
+ formatRange = defaultFormatRange, // still exposed, not used for input text
62
+ }, _ref) {
63
+ void formatDate;
64
+ void formatRange;
65
+ const popRef = useRef(null);
66
+ const todayLocal = useMemo(() => new Date(), []);
67
+ const initialAnchor = useMemo(() => {
68
+ if (mode === 'single' && value instanceof Date && value)
69
+ return value;
70
+ if (mode === 'range' && value && typeof value === 'object' && 'start' in value && value.start)
71
+ return value.start;
72
+ return todayLocal;
73
+ }, [mode, value, todayLocal]);
74
+ const [monthAnchor, setMonthAnchor] = useState(initialAnchor);
75
+ const [timeHH, setTimeHH] = useState(todayLocal.getHours());
76
+ const [timeMM, setTimeMM] = useState(Math.floor(todayLocal.getMinutes() / timeStep) * timeStep);
77
+ const [hoverUTC, setHoverUTC] = useState(null);
78
+ const cellsUTC = useMemo(() => buildMonthGrid(monthAnchor, weekStartsOn), [monthAnchor, weekStartsOn]);
79
+ const monthStartUTC = useMemo(() => startOfMonthUTC(toUTCDateOnly(monthAnchor)), [monthAnchor]);
80
+ const monthEndUTC = useMemo(() => endOfMonthUTC(toUTCDateOnly(monthAnchor)), [monthAnchor]);
81
+ const weekdayFmt = useMemo(() => new Intl.DateTimeFormat(locale, { weekday: 'short' }), [locale]);
82
+ const monthFmt = useMemo(() => new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }), [locale]);
83
+ const selectedUTC_single = mode === 'single' && value instanceof Date && value ? toUTCDateOnly(value) : null;
84
+ const selectedUTC_start = mode === 'range' && value && typeof value === 'object' && 'start' in value && value.start
85
+ ? toUTCDateOnly(value.start)
86
+ : null;
87
+ const selectedUTC_end = mode === 'range' && value && typeof value === 'object' && 'end' in value && value.end
88
+ ? toUTCDateOnly(value.end)
89
+ : null;
90
+ const isDisabledUTC = useCallback((utcDay) => {
91
+ if (min && utcDay < toUTCDateOnly(min))
92
+ return true;
93
+ if (max && utcDay > toUTCDateOnly(max))
94
+ return true;
95
+ return false;
96
+ }, [min, max]);
97
+ const selectDay = (utcDay) => {
98
+ var _a, _b;
99
+ if (isDisabledUTC(utcDay))
100
+ return;
101
+ if (mode === 'single') {
102
+ if (enableTime) {
103
+ const iso = composeLocalDateTimeISO(utcDay, timeHH, timeMM);
104
+ onChange(new Date(iso));
105
+ }
106
+ else {
107
+ onChange(new Date(utcDay.getTime()));
108
+ }
109
+ (_a = popRef.current) === null || _a === void 0 ? void 0 : _a.close();
110
+ return;
111
+ }
112
+ const curr = value && typeof value === 'object' && 'start' in value ? value : { start: null, end: null };
113
+ if (!curr.start || (curr.start && curr.end)) {
114
+ onChange({ start: new Date(utcDay.getTime()), end: null });
115
+ }
116
+ else {
117
+ const startUTC = toUTCDateOnly(curr.start);
118
+ const endUTC = utcDay;
119
+ const s = new Date(Math.min(+startUTC, +endUTC));
120
+ const e = new Date(Math.max(+startUTC, +endUTC));
121
+ onChange({ start: s, end: e });
122
+ (_b = popRef.current) === null || _b === void 0 ? void 0 : _b.close();
123
+ }
264
124
  };
265
- el.addEventListener("keydown", onKey);
266
- return () => el.removeEventListener("keydown", onKey);
267
- }, [monthAnchor]);
268
- const hours = useMemo(() => Array.from({ length: 24 }, (_, i) => i), []);
269
- const minutes = useMemo(
270
- () => Array.from({ length: Math.floor(60 / (timeStep || 1)) }, (_, i) => i * (timeStep || 1)),
271
- [timeStep]
272
- );
273
- const formatted = useMemo(() => {
274
- var _a, _b;
275
- if (mode === "single") {
276
- return value instanceof Date && value ? toMaskedFromDate(value, enableTime) : "";
277
- }
278
- const v = value;
279
- return toMaskedRange((_a = v == null ? void 0 : v.start) != null ? _a : null, (_b = v == null ? void 0 : v.end) != null ? _b : null, enableTime);
280
- }, [mode, value, enableTime]);
281
- const [text, setText] = useState(formatted);
282
- const [dirty, setDirty] = useState(false);
283
- useEffect(() => {
284
- if (!dirty) setText(formatted);
285
- }, [formatted, dirty]);
286
- const commitTypedValue = useCallback(() => {
287
- if (!text.trim()) {
288
- if (mode === "single") onChange(null);
289
- else onChange({ start: null, end: null });
290
- setDirty(false);
291
- return;
292
- }
293
- if (mode === "single") {
294
- const dLocal = parseLooseDateOrDateTime(text);
295
- if (dLocal) {
296
- onChange(dLocal);
297
- setMonthAnchor(dLocal);
298
- setDirty(false);
299
- }
300
- return;
301
- }
302
- const r = parseLooseRange(text);
303
- if (r) {
304
- onChange({ start: r.start, end: r.end });
305
- setMonthAnchor(r.start);
306
- setDirty(false);
307
- }
308
- }, [text, mode, onChange]);
309
- const clear = useCallback(() => {
310
- if (mode === "single") onChange(null);
311
- else onChange({ start: null, end: null });
312
- setDirty(false);
313
- setText("");
314
- }, [mode, onChange]);
315
- function addMonthsLocal(dt, n) {
316
- const y = dt.getFullYear(), m = dt.getMonth();
317
- return new Date(y, m + n, 1);
318
- }
319
- function addDaysLocal(dt, n) {
320
- const d = new Date(dt);
321
- d.setDate(d.getDate() + n);
322
- return d;
323
- }
324
- return /* @__PURE__ */ jsx(
325
- Popover,
326
- {
327
- ref: popRef,
328
- trigger: (toggle) => {
329
- var _a;
330
- return /* @__PURE__ */ jsx("div", { onClick: toggle, className: styles.triggerWrap, children: /* @__PURE__ */ jsx(
331
- Input,
332
- {
333
- id,
334
- placeholder: placeholder || (mode === "single" ? "V\xE6lg dato" : "V\xE6lg interval"),
335
- value: dirty ? text : formatted,
336
- onInput: (e) => {
337
- setDirty(true);
338
- const raw = e.target.value;
339
- const masked = mode === "single" ? maskSingle(raw, enableTime) : maskRange(raw, enableTime);
340
- setText(masked);
341
- },
342
- onBlur: commitTypedValue,
343
- onKeyDown: (e) => {
344
- if (e.key === "Enter") {
125
+ const gridRef = useRef(null);
126
+ useEffect(() => {
127
+ const el = gridRef.current;
128
+ if (!el)
129
+ return;
130
+ const onKey = (e) => {
131
+ var _a;
132
+ if (!((_a = popRef.current) === null || _a === void 0 ? void 0 : _a.isOpen()))
133
+ return;
134
+ if ([
135
+ 'ArrowLeft',
136
+ 'ArrowRight',
137
+ 'ArrowUp',
138
+ 'ArrowDown',
139
+ 'PageUp',
140
+ 'PageDown',
141
+ 'Home',
142
+ 'End',
143
+ ].includes(e.key)) {
345
144
  e.preventDefault();
346
- commitTypedValue();
347
- }
348
- },
349
- inputSize,
350
- icon: /* @__PURE__ */ jsx(Calendar, { size: 16 }),
351
- onClear: formatted || text ? clear : void 0,
352
- "aria-haspopup": "dialog",
353
- "aria-expanded": ((_a = popRef.current) == null ? void 0 : _a.isOpen()) ? true : false,
354
- disabled
355
- }
356
- ) });
357
- },
358
- minWidth: "320px",
359
- viewportPadding: 8,
360
- children: /* @__PURE__ */ jsxs("div", { className: cx(styles.panel, !!(presets == null ? void 0 : presets.length) && styles.panelWithPresets), children: [
361
- (presets == null ? void 0 : presets.length) ? /* @__PURE__ */ jsxs("div", { className: styles.presetsCol, children: [
362
- /* @__PURE__ */ jsx("div", { className: styles.presetsLabel, children: "Forvalg" }),
363
- /* @__PURE__ */ jsxs("div", { className: styles.presetsList, children: [
364
- presets.map((p) => /* @__PURE__ */ jsx(
365
- Button,
366
- {
367
- variant: "outlined",
368
- size: "sm",
369
- onClick: () => {
370
- var _a;
371
- const r = p.getRange();
372
- onChange({ start: r.start, end: r.end });
373
- setDirty(false);
374
- setText(toMaskedRange(r.start, r.end, enableTime));
375
- setMonthAnchor(r.start);
376
- (_a = popRef.current) == null ? void 0 : _a.close();
377
- },
378
- children: p.label
379
- },
380
- p.label
381
- )),
382
- mode === "range" && /* @__PURE__ */ jsx(Button, { variant: "danger", size: "sm", onClick: clear, icon: /* @__PURE__ */ jsx(X, { size: 14 }), children: "Ryd" })
383
- ] })
384
- ] }) : null,
385
- /* @__PURE__ */ jsxs("div", { className: styles.calendarArea, children: [
386
- /* @__PURE__ */ jsxs("div", { className: styles.header, children: [
387
- /* @__PURE__ */ jsx(
388
- Button,
389
- {
390
- variant: "outlined",
391
- size: "sm",
392
- "aria-label": "Forrige m\xE5ned",
393
- icon: /* @__PURE__ */ jsx(ChevronLeft, { size: 16 }),
394
- onClick: () => setMonthAnchor(addMonthsLocal(monthAnchor, -1))
395
- }
396
- ),
397
- /* @__PURE__ */ jsx("div", { "aria-live": "polite", className: styles.headerTitle, children: monthFmt.format(monthAnchor) }),
398
- /* @__PURE__ */ jsx(
399
- Button,
400
- {
401
- variant: "outlined",
402
- size: "sm",
403
- "aria-label": "N\xE6ste m\xE5ned",
404
- icon: /* @__PURE__ */ jsx(ChevronRight, { size: 16 }),
405
- onClick: () => setMonthAnchor(addMonthsLocal(monthAnchor, 1))
406
- }
407
- )
408
- ] }),
409
- /* @__PURE__ */ jsx("div", { className: styles.weekRow, "aria-hidden": true, children: Array.from({ length: 7 }, (_, i) => (i + weekStartsOn) % 7).map((dow) => /* @__PURE__ */ jsx("div", { className: styles.weekCell, children: weekdayFmt.format(dUTC(2024, 8, dow + 1)).slice(0, 2) }, dow)) }),
410
- /* @__PURE__ */ jsx(
411
- "div",
412
- {
413
- ref: gridRef,
414
- role: "grid",
415
- "aria-label": "Kalender",
416
- tabIndex: 0,
417
- className: styles.grid,
418
- onMouseLeave: () => setHoverUTC(null),
419
- children: cellsUTC.map((utcDay, idx) => {
420
- const inThisMonth = utcDay >= monthStartUTC && utcDay <= monthEndUTC;
421
- const isToday = sameDayUTC(utcDay, toUTCDateOnly(todayLocal));
422
- const disabledDay = isDisabledUTC(utcDay);
423
- let selected = false;
424
- let inRange = false;
425
- if (mode === "single" && selectedUTC_single)
426
- selected = sameDayUTC(utcDay, selectedUTC_single);
427
- if (mode === "range" && selectedUTC_start && selectedUTC_end) {
428
- inRange = isBetweenUTC(utcDay, selectedUTC_start, selectedUTC_end);
429
- selected = sameDayUTC(utcDay, selectedUTC_start) || sameDayUTC(utcDay, selectedUTC_end);
430
- }
431
- if (mode === "range" && selectedUTC_start && !selectedUTC_end && hoverUTC) {
432
- inRange = isBetweenUTC(utcDay, selectedUTC_start, hoverUTC);
433
- selected = sameDayUTC(utcDay, selectedUTC_start);
434
- }
435
- const dayNum = utcDay.getUTCDate();
436
- return /* @__PURE__ */ jsx(
437
- "button",
438
- {
439
- role: "gridcell",
440
- "aria-selected": selected,
441
- "aria-disabled": disabledDay,
442
- onMouseEnter: () => setHoverUTC(utcDay),
443
- onClick: () => selectDay(utcDay),
444
- disabled: disabledDay,
445
- className: cx(
446
- styles.dayCell,
447
- inThisMonth ? styles.dayInMonth : styles.dayOutside,
448
- selected && styles.daySelected,
449
- inRange && styles.dayInRange,
450
- isToday && !selected && styles.dayToday,
451
- disabledDay && styles.dayDisabled
452
- ),
453
- title: new Date(utcDay).toLocaleDateString(locale),
454
- children: dayNum
455
- },
456
- idx
457
- );
458
- })
459
145
  }
460
- ),
461
- enableTime && mode === "single" && /* @__PURE__ */ jsxs("div", { className: styles.timeRow, children: [
462
- /* @__PURE__ */ jsxs("div", { className: styles.timeLabel, children: [
463
- /* @__PURE__ */ jsx(Clock, { size: 14 }),
464
- " Tid"
465
- ] }),
466
- /* @__PURE__ */ jsx(
467
- "select",
468
- {
469
- value: timeHH,
470
- onChange: (e) => setTimeHH(parseInt(e.target.value, 10)),
471
- className: styles.timeSelect,
472
- children: hours.map((h) => /* @__PURE__ */ jsx("option", { value: h, children: String(h).padStart(2, "0") }, h))
473
- }
474
- ),
475
- /* @__PURE__ */ jsx(
476
- "select",
477
- {
478
- value: timeMM,
479
- onChange: (e) => setTimeMM(parseInt(e.target.value, 10)),
480
- className: styles.timeSelect,
481
- children: minutes.map((m) => /* @__PURE__ */ jsx("option", { value: m, children: String(m).padStart(2, "0") }, m))
482
- }
483
- )
484
- ] }),
485
- mode === "range" && /* @__PURE__ */ jsxs("div", { className: styles.footer, children: [
486
- /* @__PURE__ */ jsx(Button, { variant: "outlined", size: "sm", onClick: clear, icon: /* @__PURE__ */ jsx(X, { size: 14 }), children: "Ryd" }),
487
- /* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", onClick: () => {
488
- var _a;
489
- return (_a = popRef.current) == null ? void 0 : _a.close();
490
- }, children: "OK" })
491
- ] })
492
- ] })
493
- ] })
146
+ const anchor = toUTCDateOnly(monthAnchor);
147
+ const move = (days) => setMonthAnchor(prev => addDaysLocal(prev, days));
148
+ switch (e.key) {
149
+ case 'ArrowLeft':
150
+ move(-1);
151
+ break;
152
+ case 'ArrowRight':
153
+ move(1);
154
+ break;
155
+ case 'ArrowUp':
156
+ move(-7);
157
+ break;
158
+ case 'ArrowDown':
159
+ move(7);
160
+ break;
161
+ case 'PageUp':
162
+ setMonthAnchor(addMonthsLocal(monthAnchor, -1));
163
+ break;
164
+ case 'PageDown':
165
+ setMonthAnchor(addMonthsLocal(monthAnchor, 1));
166
+ break;
167
+ case 'Home':
168
+ setMonthAnchor(new Date(anchor.getUTCFullYear(), anchor.getUTCMonth(), 1));
169
+ break;
170
+ case 'End':
171
+ setMonthAnchor(new Date(anchor.getUTCFullYear(), anchor.getUTCMonth() + 1, 0));
172
+ break;
173
+ }
174
+ };
175
+ el.addEventListener('keydown', onKey);
176
+ return () => el.removeEventListener('keydown', onKey);
177
+ }, [monthAnchor]);
178
+ const hours = useMemo(() => Array.from({ length: 24 }, (_, i) => i), []);
179
+ const minutes = useMemo(() => Array.from({ length: Math.floor(60 / (timeStep || 1)) }, (_, i) => i * (timeStep || 1)), [timeStep]);
180
+ // ---- Input display: follow mask format (not Intl) ----
181
+ const formatted = useMemo(() => {
182
+ var _a, _b;
183
+ if (mode === 'single') {
184
+ return value instanceof Date && value ? toMaskedFromDate(value, enableTime) : '';
185
+ }
186
+ const v = value;
187
+ return toMaskedRange((_a = v === null || v === void 0 ? void 0 : v.start) !== null && _a !== void 0 ? _a : null, (_b = v === null || v === void 0 ? void 0 : v.end) !== null && _b !== void 0 ? _b : null, enableTime);
188
+ }, [mode, value, enableTime]);
189
+ const [text, setText] = useState(formatted);
190
+ const [dirty, setDirty] = useState(false); // while user is typing
191
+ useEffect(() => {
192
+ if (!dirty)
193
+ setText(formatted); // keep in sync when external value changes
194
+ }, [formatted, dirty]);
195
+ const commitTypedValue = useCallback(() => {
196
+ if (!text.trim()) {
197
+ if (mode === 'single')
198
+ onChange(null);
199
+ else
200
+ onChange({ start: null, end: null });
201
+ setDirty(false);
202
+ return;
203
+ }
204
+ if (mode === 'single') {
205
+ const dLocal = parseLooseDateOrDateTime(text);
206
+ if (dLocal) {
207
+ onChange(dLocal);
208
+ setMonthAnchor(dLocal);
209
+ setDirty(false);
210
+ }
211
+ return;
212
+ }
213
+ const r = parseLooseRange(text);
214
+ if (r) {
215
+ onChange({ start: r.start, end: r.end });
216
+ setMonthAnchor(r.start);
217
+ setDirty(false);
218
+ }
219
+ }, [text, mode, onChange]);
220
+ const clear = useCallback(() => {
221
+ if (mode === 'single')
222
+ onChange(null);
223
+ else
224
+ onChange({ start: null, end: null });
225
+ setDirty(false);
226
+ setText('');
227
+ }, [mode, onChange]);
228
+ function addMonthsLocal(dt, n) {
229
+ const y = dt.getFullYear();
230
+ const m = dt.getMonth();
231
+ return new Date(y, m + n, 1);
232
+ }
233
+ function addDaysLocal(dt, n) {
234
+ const d = new Date(dt);
235
+ d.setDate(d.getDate() + n);
236
+ return d;
494
237
  }
495
- );
238
+ const fallbackPlaceholder = mode === 'single' ? 'Vælg dato' : 'Vælg interval';
239
+ return (_jsx(Popover, { ref: popRef, trigger: toggle => {
240
+ var _a, _b;
241
+ return (_jsx("div", { onClick: toggle, className: styles.triggerWrap, children: _jsx(Input, { ...inputProps, placeholder: (_a = inputProps === null || inputProps === void 0 ? void 0 : inputProps.placeholder) !== null && _a !== void 0 ? _a : fallbackPlaceholder, value: dirty ? text : formatted, onInput: e => {
242
+ setDirty(true);
243
+ const raw = e.target.value;
244
+ const masked = mode === 'single' ? maskSingle(raw, enableTime) : maskRange(raw, enableTime);
245
+ setText(masked);
246
+ }, onBlur: commitTypedValue, onKeyDown: e => {
247
+ var _a;
248
+ (_a = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onKeyDown) === null || _a === void 0 ? void 0 : _a.call(inputProps, e);
249
+ if (e.defaultPrevented)
250
+ return;
251
+ if (e.key === 'Enter') {
252
+ e.preventDefault();
253
+ commitTypedValue();
254
+ }
255
+ }, icon: _jsx(Calendar, { size: 16 }), onClear: formatted || text ? clear : undefined, "aria-haspopup": "dialog", "aria-expanded": ((_b = popRef.current) === null || _b === void 0 ? void 0 : _b.isOpen()) ? true : false, disabled: inputProps === null || inputProps === void 0 ? void 0 : inputProps.disabled, error: inputProps === null || inputProps === void 0 ? void 0 : inputProps.error }) }));
256
+ }, viewportPadding: 8, children: _jsxs("div", { className: cx(styles.panel, !!(presets === null || presets === void 0 ? void 0 : presets.length) && styles.panelWithPresets), children: [(presets === null || presets === void 0 ? void 0 : presets.length) ? (_jsxs("div", { className: styles.presetsCol, children: [_jsx("div", { className: styles.presetsLabel, children: "Forvalg" }), _jsxs("div", { className: styles.presetsList, children: [presets.map(p => (_jsx(Button, { variant: "outlined", size: "sm", onClick: () => {
257
+ var _a;
258
+ const r = p.getRange();
259
+ onChange({ start: r.start, end: r.end });
260
+ setDirty(false);
261
+ setText(toMaskedRange(r.start, r.end, enableTime));
262
+ setMonthAnchor(r.start);
263
+ (_a = popRef.current) === null || _a === void 0 ? void 0 : _a.close();
264
+ }, children: p.label }, p.label))), mode === 'range' && (_jsx(Button, { variant: "danger", size: "sm", onClick: clear, icon: _jsx(X, { size: 14 }), children: "Ryd" }))] })] })) : null, _jsxs("div", { className: styles.calendarArea, children: [_jsxs("div", { className: styles.header, children: [_jsx(Button, { variant: "outlined", size: "sm", "aria-label": "Forrige m\u00E5ned", icon: _jsx(ChevronLeft, { size: 16 }), onClick: () => setMonthAnchor(addMonthsLocal(monthAnchor, -1)) }), _jsx("div", { "aria-live": "polite", className: styles.headerTitle, children: monthFmt.format(monthAnchor) }), _jsx(Button, { variant: "outlined", size: "sm", "aria-label": "N\u00E6ste m\u00E5ned", icon: _jsx(ChevronRight, { size: 16 }), onClick: () => setMonthAnchor(addMonthsLocal(monthAnchor, 1)) })] }), _jsx("div", { className: styles.weekRow, "aria-hidden": true, children: Array.from({ length: 7 }, (_, i) => (i + weekStartsOn) % 7).map(dow => (_jsx("div", { className: styles.weekCell, children: weekdayFmt.format(dUTC(2024, 8, dow + 1)).slice(0, 2) }, dow))) }), _jsx("div", { ref: gridRef, role: "grid", "aria-label": "Kalender", tabIndex: 0, className: styles.grid, onMouseLeave: () => setHoverUTC(null), children: cellsUTC.map((utcDay, idx) => {
265
+ const inThisMonth = utcDay >= monthStartUTC && utcDay <= monthEndUTC;
266
+ const isToday = sameDayUTC(utcDay, toUTCDateOnly(todayLocal));
267
+ const disabledDay = isDisabledUTC(utcDay);
268
+ let selected = false;
269
+ let inRange = false;
270
+ if (mode === 'single' && selectedUTC_single)
271
+ selected = sameDayUTC(utcDay, selectedUTC_single);
272
+ if (mode === 'range' && selectedUTC_start && selectedUTC_end) {
273
+ inRange = isBetweenUTC(utcDay, selectedUTC_start, selectedUTC_end);
274
+ selected =
275
+ sameDayUTC(utcDay, selectedUTC_start) || sameDayUTC(utcDay, selectedUTC_end);
276
+ }
277
+ if (mode === 'range' && selectedUTC_start && !selectedUTC_end && hoverUTC) {
278
+ inRange = isBetweenUTC(utcDay, selectedUTC_start, hoverUTC);
279
+ selected = sameDayUTC(utcDay, selectedUTC_start);
280
+ }
281
+ const dayNum = utcDay.getUTCDate();
282
+ return (_jsx("button", { role: "gridcell", "aria-selected": selected, "aria-disabled": disabledDay, onMouseEnter: () => setHoverUTC(utcDay), onClick: () => selectDay(utcDay), disabled: disabledDay, className: cx(styles.dayCell, inThisMonth ? styles.dayInMonth : styles.dayOutside, selected && styles.daySelected, inRange && styles.dayInRange, isToday && !selected && styles.dayToday, disabledDay && styles.dayDisabled), title: new Date(utcDay).toLocaleDateString(locale), children: dayNum }, idx));
283
+ }) }), enableTime && mode === 'single' && (_jsxs("div", { className: styles.timeRow, children: [_jsxs("div", { className: styles.timeLabel, children: [_jsx(Clock, { size: 14 }), " Tid"] }), _jsx("select", { value: timeHH, onChange: e => setTimeHH(parseInt(e.target.value, 10)), className: styles.timeSelect, children: hours.map(h => (_jsx("option", { value: h, children: String(h).padStart(2, '0') }, h))) }), _jsx("select", { value: timeMM, onChange: e => setTimeMM(parseInt(e.target.value, 10)), className: styles.timeSelect, children: minutes.map(m => (_jsx("option", { value: m, children: String(m).padStart(2, '0') }, m))) })] })), mode === 'range' && (_jsxs("div", { className: styles.footer, children: [_jsx(Button, { variant: "outlined", size: "sm", onClick: clear, icon: _jsx(X, { size: 14 }), children: "Ryd" }), _jsx(Button, { variant: "primary", size: "sm", onClick: () => { var _a; return (_a = popRef.current) === null || _a === void 0 ? void 0 : _a.close(); }, children: "OK" })] }))] })] }) }));
496
284
  });
497
-
498
- export { DateTimePicker };
285
+ DateTimePicker.displayName = 'DateTimePicker';