@dbcdk/react-components 0.0.185 → 0.0.186

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 (65) hide show
  1. package/dist/client.cjs +28 -0
  2. package/dist/client.d.ts +4 -0
  3. package/dist/client.js +4 -0
  4. package/dist/components/accordion/components/AccordionRow.cjs +2 -36
  5. package/dist/components/accordion/components/AccordionRow.js +2 -36
  6. package/dist/components/button-select/ButtonSelect.cjs +30 -21
  7. package/dist/components/button-select/ButtonSelect.d.ts +8 -4
  8. package/dist/components/button-select/ButtonSelect.js +30 -21
  9. package/dist/components/page/Page.module.css +1 -0
  10. package/dist/components/pagination/Pagination.module.css +1 -0
  11. package/dist/components/panel/Panel.module.css +0 -1
  12. package/dist/components/popover/Popover.cjs +1 -1
  13. package/dist/components/popover/Popover.js +1 -1
  14. package/dist/components/print-friendly/PrintFriendlyCard.cjs +39 -0
  15. package/dist/components/print-friendly/PrintFriendlyCard.d.ts +23 -0
  16. package/dist/components/print-friendly/PrintFriendlyCard.js +37 -0
  17. package/dist/components/print-friendly/PrintFriendlyMetaBar.cjs +25 -0
  18. package/dist/components/print-friendly/PrintFriendlyMetaBar.d.ts +19 -0
  19. package/dist/components/print-friendly/PrintFriendlyMetaBar.js +23 -0
  20. package/dist/components/print-friendly/PrintFriendlyTable.cjs +51 -0
  21. package/dist/components/print-friendly/PrintFriendlyTable.d.ts +34 -0
  22. package/dist/components/print-friendly/PrintFriendlyTable.js +49 -0
  23. package/dist/components/print-friendly/components/AccumulationFooter.cjs +42 -0
  24. package/dist/components/print-friendly/components/AccumulationFooter.d.ts +9 -0
  25. package/dist/components/print-friendly/components/AccumulationFooter.js +40 -0
  26. package/dist/components/print-friendly/emptyValue.cjs +9 -0
  27. package/dist/components/print-friendly/emptyValue.d.ts +2 -0
  28. package/dist/components/print-friendly/emptyValue.js +6 -0
  29. package/dist/components/print-friendly/printSelection.cjs +14 -0
  30. package/dist/components/print-friendly/printSelection.d.ts +19 -0
  31. package/dist/components/print-friendly/printSelection.js +10 -0
  32. package/dist/components/stack/Stack.cjs +6 -5
  33. package/dist/components/stack/Stack.d.ts +2 -1
  34. package/dist/components/stack/Stack.js +6 -5
  35. package/dist/components/table/Table.cjs +20 -4
  36. package/dist/components/table/Table.js +21 -5
  37. package/dist/components/table/Table.module.css +6 -0
  38. package/dist/components/table/Table.types.d.ts +1 -0
  39. package/dist/components/table/components/TableHeader.cjs +1 -0
  40. package/dist/components/table/components/TableHeader.js +1 -0
  41. package/dist/components/tabs/Tabs.cjs +49 -39
  42. package/dist/components/tabs/Tabs.d.ts +3 -1
  43. package/dist/components/tabs/Tabs.js +49 -39
  44. package/dist/components/tabs/Tabs.module.css +24 -6
  45. package/dist/components/timeline/Timeline.cjs +102 -0
  46. package/dist/components/timeline/Timeline.d.ts +60 -0
  47. package/dist/components/timeline/Timeline.js +96 -0
  48. package/dist/components/timeline/Timeline.module.css +22 -0
  49. package/dist/components/timeline/components/TimelineRow.cjs +147 -0
  50. package/dist/components/timeline/components/TimelineRow.d.ts +15 -0
  51. package/dist/components/timeline/components/TimelineRow.js +141 -0
  52. package/dist/components/timeline/components/TimelineRow.module.css +195 -0
  53. package/dist/hooks/useCollapsibleHeight.cjs +41 -0
  54. package/dist/hooks/useCollapsibleHeight.d.ts +6 -0
  55. package/dist/hooks/useCollapsibleHeight.js +39 -0
  56. package/dist/hooks/useViewportFill.cjs +11 -3
  57. package/dist/hooks/useViewportFill.js +11 -3
  58. package/dist/index.cjs +7 -0
  59. package/dist/index.css +2 -0
  60. package/dist/index.d.ts +1 -0
  61. package/dist/index.js +1 -0
  62. package/dist/styles/styles.css +74 -2
  63. package/dist/styles.css +74 -2
  64. package/dist/utils/date/formatDate.d.ts +3 -2
  65. package/package.json +1 -1
@@ -51,6 +51,7 @@ function Tabs({
51
51
  onRemoveTab,
52
52
  onAddTab,
53
53
  addition,
54
+ tabListAddition,
54
55
  loading = false,
55
56
  children
56
57
  }) {
@@ -143,44 +144,52 @@ function Tabs({
143
144
  ) : null,
144
145
  /* @__PURE__ */ jsxs("div", { className: `${styles.tabs} ${styles[variant]} ${panelStyle ? styles.panelStyle : ""}`, children: [
145
146
  /* @__PURE__ */ jsxs("div", { className: styles.tabList, children: [
146
- /* @__PURE__ */ jsx("div", { className: styles.tabButtons, role: "tablist", "aria-label": header != null ? header : "Tabs", children: visibleTabs.map((tab, index) => {
147
- const selected = index === activeIndex;
148
- const tabDomId = `${uid}-tab-${String(tab.id)}`;
149
- const panelDomId = `${uid}-panel-${String(tab.id)}`;
150
- return /* @__PURE__ */ jsxs("div", { className: `${styles.tab} ${selected ? styles.active : ""}`, children: [
151
- /* @__PURE__ */ jsxs(
152
- "button",
153
- {
154
- id: tabDomId,
155
- type: "button",
156
- className: styles.tabButton,
157
- role: "tab",
158
- "aria-selected": selected,
159
- "aria-controls": panelDomId,
160
- tabIndex: selected ? 0 : -1,
161
- disabled: tab.disabled,
162
- onClick: () => setValue(tab.id),
163
- onKeyDown: (e) => onKeyDownTab(e, index),
164
- children: [
165
- tab.headerIcon ? /* @__PURE__ */ jsx("span", { className: styles.icon, children: tab.headerIcon }) : null,
166
- /* @__PURE__ */ jsx("span", { className: styles.label, children: tab.header }),
167
- tab.badge ? /* @__PURE__ */ jsx("span", { className: styles.badge, children: /* @__PURE__ */ jsx(Chip, { size: "sm", children: tab.badge.toLocaleString("da-DK") }) }) : null
168
- ]
169
- }
170
- ),
171
- tab.removable && onRemoveTab ? /* @__PURE__ */ jsx(
172
- "button",
173
- {
174
- type: "button",
175
- className: styles.removeTabButton,
176
- "aria-label": `Fjern fane ${tab.header}`,
177
- disabled: tab.disabled,
178
- onClick: () => onRemoveTab(tab.id, tab, index),
179
- children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true" })
180
- }
181
- ) : null
182
- ] }, tab.id);
183
- }) }),
147
+ /* @__PURE__ */ jsx(
148
+ "div",
149
+ {
150
+ className: onAddTab ? styles.tabButtons : `${styles.tabButtons} ${styles.tabButtonsEnd}`,
151
+ role: "tablist",
152
+ "aria-label": header != null ? header : "Tabs",
153
+ children: visibleTabs.map((tab, index) => {
154
+ const selected = index === activeIndex;
155
+ const tabDomId = `${uid}-tab-${String(tab.id)}`;
156
+ const panelDomId = `${uid}-panel-${String(tab.id)}`;
157
+ return /* @__PURE__ */ jsxs("div", { className: `${styles.tab} ${selected ? styles.active : ""}`, children: [
158
+ /* @__PURE__ */ jsxs(
159
+ "button",
160
+ {
161
+ id: tabDomId,
162
+ type: "button",
163
+ className: styles.tabButton,
164
+ role: "tab",
165
+ "aria-selected": selected,
166
+ "aria-controls": panelDomId,
167
+ tabIndex: selected ? 0 : -1,
168
+ disabled: tab.disabled,
169
+ onClick: () => setValue(tab.id),
170
+ onKeyDown: (e) => onKeyDownTab(e, index),
171
+ children: [
172
+ tab.headerIcon ? /* @__PURE__ */ jsx("span", { className: styles.icon, children: tab.headerIcon }) : null,
173
+ /* @__PURE__ */ jsx("span", { className: styles.label, children: tab.header }),
174
+ tab.badge ? /* @__PURE__ */ jsx("span", { className: styles.badge, children: /* @__PURE__ */ jsx(Chip, { size: "sm", children: tab.badge.toLocaleString("da-DK") }) }) : null
175
+ ]
176
+ }
177
+ ),
178
+ tab.removable && onRemoveTab ? /* @__PURE__ */ jsx(
179
+ "button",
180
+ {
181
+ type: "button",
182
+ className: styles.removeTabButton,
183
+ "aria-label": `Fjern fane ${tab.header}`,
184
+ disabled: tab.disabled,
185
+ onClick: () => onRemoveTab(tab.id, tab, index),
186
+ children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true" })
187
+ }
188
+ ) : null
189
+ ] }, tab.id);
190
+ })
191
+ }
192
+ ),
184
193
  onAddTab ? /* @__PURE__ */ jsx(
185
194
  "button",
186
195
  {
@@ -190,7 +199,8 @@ function Tabs({
190
199
  "aria-label": "Tilf\xF8j fane",
191
200
  children: /* @__PURE__ */ jsx(Plus, { "aria-hidden": "true" })
192
201
  }
193
- ) : null
202
+ ) : null,
203
+ tabListAddition ? /* @__PURE__ */ jsx("div", { className: styles.tabListAddition, children: tabListAddition }) : null
194
204
  ] }),
195
205
  /* @__PURE__ */ jsx(
196
206
  "div",
@@ -36,6 +36,15 @@
36
36
  min-width: 0;
37
37
  }
38
38
 
39
+ /* Extra content next to the tab buttons, pushed into the free space on the right */
40
+ .tabListAddition {
41
+ display: flex;
42
+ align-items: center;
43
+ gap: var(--spacing-sm);
44
+ margin-inline-start: auto;
45
+ padding-inline-start: var(--spacing-md);
46
+ }
47
+
39
48
  /* Individual tab wrapper */
40
49
  .tab {
41
50
  display: flex;
@@ -201,17 +210,26 @@
201
210
 
202
211
  .filled > .tabList {
203
212
  border-block-end: 1px solid var(--color-border-subtle);
204
- background: var(--color-bg-toolbar);
205
- inline-size: 100%;
206
213
  }
207
214
 
215
+ /* One continuous backdrop behind the whole button row, so the curved gap
216
+ next to the active tab's rounded corners shows toolbar gray, not the
217
+ surface color behind the row. */
208
218
  .filled > .tabList > .tabButtons {
209
219
  display: flex;
220
+ background: var(--color-bg-toolbar);
221
+ border-start-start-radius: var(--border-radius-md);
222
+ }
223
+
224
+ .filled > .tabList > .tabButtons.tabButtonsEnd {
225
+ border-start-end-radius: var(--border-radius-md);
210
226
  }
211
227
 
212
228
  .filled > .tabList > .addTabButton {
229
+ background: var(--color-bg-toolbar);
213
230
  border: 1px solid transparent;
214
231
  border-block-end: 0;
232
+ border-start-end-radius: var(--border-radius-md);
215
233
  }
216
234
 
217
235
  .filled > .tabList > .addTabButton:hover {
@@ -253,7 +271,7 @@
253
271
  border-block-start: none;
254
272
  border-radius: 0 0 var(--border-radius-md) var(--border-radius-md);
255
273
  box-shadow: var(--shadow-xs);
256
- padding: var(--spacing-lg);
274
+ padding: var(--spacing-md);
257
275
  }
258
276
 
259
277
  /* =========================
@@ -307,7 +325,7 @@
307
325
  .panelStyle.outlined > .tabContent {
308
326
  border: var(--border-width-thin) solid var(--color-border-default);
309
327
  background: var(--color-bg-surface);
310
- padding: var(--spacing-lg);
328
+ padding: var(--spacing-md);
311
329
  }
312
330
 
313
331
  @media (max-width: 767px) {
@@ -333,8 +351,8 @@
333
351
 
334
352
  .filled > .tabContent,
335
353
  .panelStyle.outlined > .tabContent {
336
- padding-block: var(--spacing-md);
337
- padding-inline: var(--spacing-md);
354
+ padding-block: var(--spacing-sm);
355
+ padding-inline: var(--spacing-sm);
338
356
  }
339
357
 
340
358
  .panelStyle > .tabList {
@@ -0,0 +1,102 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var react = require('react');
6
+ var TimelineRow = require('./components/TimelineRow');
7
+ var styles = require('./Timeline.module.css');
8
+
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var styles__default = /*#__PURE__*/_interopDefault(styles);
12
+
13
+ function uniqSorted(nums) {
14
+ return Array.from(new Set(nums)).sort((a, b) => a - b);
15
+ }
16
+ function collapsibleIndexesOf(items) {
17
+ return items.reduce((acc, item, i) => {
18
+ if (item.collapsible) acc.push(i);
19
+ return acc;
20
+ }, []);
21
+ }
22
+ function normalizeOpenIndexes(indexes, items) {
23
+ const collapsible = collapsibleIndexesOf(items);
24
+ if (indexes === "all") {
25
+ return collapsible;
26
+ }
27
+ const collapsibleSet = new Set(collapsible);
28
+ return uniqSorted((indexes != null ? indexes : []).filter((n) => collapsibleSet.has(n)));
29
+ }
30
+ function Timeline({
31
+ items,
32
+ size = "md",
33
+ variant = "default",
34
+ renderMode = "lazy",
35
+ defaultOpenIndexes = [],
36
+ openIndexes,
37
+ onOpenIndexesChange,
38
+ className,
39
+ ...rest
40
+ }) {
41
+ const uid = react.useId();
42
+ const isControlled = openIndexes !== void 0;
43
+ const [hasMounted, setHasMounted] = react.useState(false);
44
+ react.useEffect(() => {
45
+ setHasMounted(true);
46
+ }, []);
47
+ const [internalOpenIndexes, setInternalOpenIndexes] = react.useState(
48
+ () => normalizeOpenIndexes(defaultOpenIndexes, items)
49
+ );
50
+ const currentOpenIndexes = react.useMemo(
51
+ () => normalizeOpenIndexes(isControlled ? openIndexes : internalOpenIndexes, items),
52
+ [isControlled, openIndexes, internalOpenIndexes, items]
53
+ );
54
+ const openSet = react.useMemo(() => new Set(currentOpenIndexes), [currentOpenIndexes]);
55
+ function commit(nextIndexes) {
56
+ const normalized = normalizeOpenIndexes(nextIndexes, items);
57
+ if (isControlled) {
58
+ onOpenIndexesChange == null ? void 0 : onOpenIndexesChange(normalized);
59
+ } else {
60
+ setInternalOpenIndexes(normalized);
61
+ onOpenIndexesChange == null ? void 0 : onOpenIndexesChange(normalized);
62
+ }
63
+ }
64
+ function toggle(index) {
65
+ const item = items[index];
66
+ if (!item || !item.collapsible || item.disabled) return;
67
+ const isOpen = openSet.has(index);
68
+ if (isOpen) {
69
+ commit(currentOpenIndexes.filter((i) => i !== index));
70
+ } else {
71
+ commit([...currentOpenIndexes, index]);
72
+ }
73
+ }
74
+ return /* @__PURE__ */ jsxRuntime.jsx(
75
+ "div",
76
+ {
77
+ ...rest,
78
+ className: [styles__default.default.container, styles__default.default[size], className].filter(Boolean).join(" "),
79
+ children: items.map((item, i) => {
80
+ var _a;
81
+ return /* @__PURE__ */ jsxRuntime.jsx(
82
+ TimelineRow.TimelineRow,
83
+ {
84
+ uid,
85
+ index: i,
86
+ item,
87
+ isLast: i === items.length - 1,
88
+ isOpen: openSet.has(i),
89
+ onToggle: toggle,
90
+ shouldAnimate: hasMounted,
91
+ size,
92
+ variant,
93
+ renderMode
94
+ },
95
+ (_a = item.id) != null ? _a : i
96
+ );
97
+ })
98
+ }
99
+ );
100
+ }
101
+
102
+ exports.Timeline = Timeline;
@@ -0,0 +1,60 @@
1
+ import type { HTMLAttributes, JSX, ReactNode } from 'react';
2
+ import type { Severity } from '../../constants/severity.types';
3
+ import type { FormatDateOptions } from '../../utils/date/formatDate';
4
+ export type TimelineContextMenuActionItem = {
5
+ type?: 'item';
6
+ label: ReactNode;
7
+ icon?: ReactNode;
8
+ onClick: () => void;
9
+ active?: boolean;
10
+ selected?: boolean;
11
+ disabled?: boolean;
12
+ variant?: 'default' | 'danger';
13
+ };
14
+ export type TimelineContextMenuHeaderItem = {
15
+ type: 'header';
16
+ label: ReactNode;
17
+ };
18
+ export type TimelineContextMenuItem = TimelineContextMenuActionItem | TimelineContextMenuHeaderItem;
19
+ export interface TimelineItem {
20
+ id?: string;
21
+ label: ReactNode;
22
+ content: ReactNode;
23
+ collapsible?: boolean;
24
+ severity?: Severity;
25
+ icon?: ReactNode;
26
+ disabled?: boolean;
27
+ /**
28
+ * When set, renders a muted timestamp next to the label using the
29
+ * component's own date formatting (see `dateOptions`) instead of the
30
+ * consumer building one into `label`/`content` by hand.
31
+ */
32
+ date?: Date | string | number;
33
+ /** Passed through to the internal `formatDate` call for `date`. */
34
+ dateOptions?: FormatDateOptions;
35
+ /**
36
+ * Renders a kebab menu next to the label (same pattern as `Table`'s row
37
+ * actions), instead of the consumer putting action buttons directly in
38
+ * `label` — those inflate the header's height and throw off its
39
+ * alignment with the marker dot.
40
+ */
41
+ contextMenuItems?: TimelineContextMenuItem[];
42
+ }
43
+ type Size = 'sm' | 'md' | 'lg';
44
+ type Variant = 'default' | 'outlined';
45
+ type OpenIndexes = number[] | 'all';
46
+ type RenderMode = 'lazy' | 'eager';
47
+ export interface TimelineProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
48
+ items: TimelineItem[];
49
+ size?: Size;
50
+ variant?: Variant;
51
+ renderMode?: RenderMode;
52
+ /** Uncontrolled default */
53
+ defaultOpenIndexes?: OpenIndexes;
54
+ /** Controlled state */
55
+ openIndexes?: OpenIndexes;
56
+ /** Change callback */
57
+ onOpenIndexesChange?: (indexes: number[]) => void;
58
+ }
59
+ export declare function Timeline({ items, size, variant, renderMode, defaultOpenIndexes, openIndexes, onOpenIndexesChange, className, ...rest }: TimelineProps): JSX.Element;
60
+ export {};
@@ -0,0 +1,96 @@
1
+ 'use client';
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { useId, useState, useEffect, useMemo } from 'react';
4
+ import { TimelineRow } from './components/TimelineRow';
5
+ import styles from './Timeline.module.css';
6
+
7
+ function uniqSorted(nums) {
8
+ return Array.from(new Set(nums)).sort((a, b) => a - b);
9
+ }
10
+ function collapsibleIndexesOf(items) {
11
+ return items.reduce((acc, item, i) => {
12
+ if (item.collapsible) acc.push(i);
13
+ return acc;
14
+ }, []);
15
+ }
16
+ function normalizeOpenIndexes(indexes, items) {
17
+ const collapsible = collapsibleIndexesOf(items);
18
+ if (indexes === "all") {
19
+ return collapsible;
20
+ }
21
+ const collapsibleSet = new Set(collapsible);
22
+ return uniqSorted((indexes != null ? indexes : []).filter((n) => collapsibleSet.has(n)));
23
+ }
24
+ function Timeline({
25
+ items,
26
+ size = "md",
27
+ variant = "default",
28
+ renderMode = "lazy",
29
+ defaultOpenIndexes = [],
30
+ openIndexes,
31
+ onOpenIndexesChange,
32
+ className,
33
+ ...rest
34
+ }) {
35
+ const uid = useId();
36
+ const isControlled = openIndexes !== void 0;
37
+ const [hasMounted, setHasMounted] = useState(false);
38
+ useEffect(() => {
39
+ setHasMounted(true);
40
+ }, []);
41
+ const [internalOpenIndexes, setInternalOpenIndexes] = useState(
42
+ () => normalizeOpenIndexes(defaultOpenIndexes, items)
43
+ );
44
+ const currentOpenIndexes = useMemo(
45
+ () => normalizeOpenIndexes(isControlled ? openIndexes : internalOpenIndexes, items),
46
+ [isControlled, openIndexes, internalOpenIndexes, items]
47
+ );
48
+ const openSet = useMemo(() => new Set(currentOpenIndexes), [currentOpenIndexes]);
49
+ function commit(nextIndexes) {
50
+ const normalized = normalizeOpenIndexes(nextIndexes, items);
51
+ if (isControlled) {
52
+ onOpenIndexesChange == null ? void 0 : onOpenIndexesChange(normalized);
53
+ } else {
54
+ setInternalOpenIndexes(normalized);
55
+ onOpenIndexesChange == null ? void 0 : onOpenIndexesChange(normalized);
56
+ }
57
+ }
58
+ function toggle(index) {
59
+ const item = items[index];
60
+ if (!item || !item.collapsible || item.disabled) return;
61
+ const isOpen = openSet.has(index);
62
+ if (isOpen) {
63
+ commit(currentOpenIndexes.filter((i) => i !== index));
64
+ } else {
65
+ commit([...currentOpenIndexes, index]);
66
+ }
67
+ }
68
+ return /* @__PURE__ */ jsx(
69
+ "div",
70
+ {
71
+ ...rest,
72
+ className: [styles.container, styles[size], className].filter(Boolean).join(" "),
73
+ children: items.map((item, i) => {
74
+ var _a;
75
+ return /* @__PURE__ */ jsx(
76
+ TimelineRow,
77
+ {
78
+ uid,
79
+ index: i,
80
+ item,
81
+ isLast: i === items.length - 1,
82
+ isOpen: openSet.has(i),
83
+ onToggle: toggle,
84
+ shouldAnimate: hasMounted,
85
+ size,
86
+ variant,
87
+ renderMode
88
+ },
89
+ (_a = item.id) != null ? _a : i
90
+ );
91
+ })
92
+ }
93
+ );
94
+ }
95
+
96
+ export { Timeline };
@@ -0,0 +1,22 @@
1
+ .container {
2
+ display: flex;
3
+ flex-direction: column;
4
+ }
5
+
6
+ .sm {
7
+ --tl-gap: var(--spacing-xs);
8
+ --tl-row-gap: var(--spacing-sm);
9
+ --tl-font-size: var(--font-size-sm);
10
+ }
11
+
12
+ .md {
13
+ --tl-gap: var(--spacing-sm);
14
+ --tl-row-gap: var(--spacing-md);
15
+ --tl-font-size: var(--font-size-md);
16
+ }
17
+
18
+ .lg {
19
+ --tl-gap: var(--spacing-sm);
20
+ --tl-row-gap: var(--spacing-lg);
21
+ --tl-font-size: var(--font-size-md);
22
+ }
@@ -0,0 +1,147 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var lucideReact = require('lucide-react');
5
+ var react = require('react');
6
+ var Button = require('../../../components/button/Button');
7
+ var Circle = require('../../../components/circle/Circle');
8
+ var Menu = require('../../../components/menu/Menu');
9
+ var Popover = require('../../../components/popover/Popover');
10
+ var useCollapsibleHeight = require('../../../hooks/useCollapsibleHeight');
11
+ var formatDate = require('../../../utils/date/formatDate');
12
+ var styles = require('./TimelineRow.module.css');
13
+
14
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
15
+
16
+ var styles__default = /*#__PURE__*/_interopDefault(styles);
17
+
18
+ function TimelineRow({
19
+ uid,
20
+ index,
21
+ item,
22
+ isLast,
23
+ isOpen,
24
+ onToggle,
25
+ shouldAnimate = true,
26
+ variant = "default",
27
+ renderMode = "lazy",
28
+ size = "md"
29
+ }) {
30
+ var _a, _b;
31
+ const isDisabled = !!item.disabled;
32
+ const isCollapsible = !!item.collapsible;
33
+ const hasContextMenu = Boolean((_a = item.contextMenuItems) == null ? void 0 : _a.length);
34
+ const buttonId = `${uid}-tl-btn-${index}`;
35
+ const panelId = `${uid}-tl-panel-${index}`;
36
+ const { innerRef, height, onTransitionEnd } = useCollapsibleHeight.useCollapsibleHeight(
37
+ isCollapsible ? isOpen : true,
38
+ shouldAnimate
39
+ );
40
+ const [hasBeenOpened, setHasBeenOpened] = react.useState(isOpen);
41
+ const shouldRenderContent = !isCollapsible || renderMode === "eager" || isOpen || hasBeenOpened;
42
+ const contentClassName = [styles__default.default.content, variant === "outlined" ? styles__default.default.outlined : ""].filter(Boolean).join(" ");
43
+ function handleToggle() {
44
+ if (!isOpen) {
45
+ setHasBeenOpened(true);
46
+ }
47
+ onToggle(index);
48
+ }
49
+ return /* @__PURE__ */ jsxRuntime.jsxs(
50
+ "div",
51
+ {
52
+ className: `${styles__default.default.row} ${isDisabled ? styles__default.default.disabled : ""}`,
53
+ "data-state": isCollapsible ? isOpen ? "open" : "closed" : void 0,
54
+ children: [
55
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.markerColumn, children: [
56
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.markerSlot, children: item.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.icon, children: item.icon }) : /* @__PURE__ */ jsxRuntime.jsx(Circle.Circle, { severity: (_b = item.severity) != null ? _b : "neutral", size }) }),
57
+ !isLast ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.connector, "aria-hidden": "true" }) : null
58
+ ] }),
59
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.body, children: [
60
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.headerRow} ${hasContextMenu ? styles__default.default.headerRowWithActions : ""}`, children: [
61
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.label, children: item.label }),
62
+ item.date !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.date, children: formatDate.formatDate(item.date, { userFriendlyLabel: true, ...item.dateOptions }) }) : null,
63
+ isCollapsible ? /* @__PURE__ */ jsxRuntime.jsx(
64
+ "button",
65
+ {
66
+ type: "button",
67
+ id: buttonId,
68
+ className: styles__default.default.trigger,
69
+ "aria-expanded": isOpen,
70
+ "aria-controls": panelId,
71
+ "aria-label": isOpen ? "Collapse" : "Expand",
72
+ onClick: handleToggle,
73
+ disabled: isDisabled,
74
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${styles__default.default.chevron} ${isOpen ? styles__default.default.open : ""}`, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, {}) })
75
+ }
76
+ ) : null,
77
+ hasContextMenu ? /* @__PURE__ */ jsxRuntime.jsx(TimelineRowActions, { items: item.contextMenuItems }) : null
78
+ ] }),
79
+ isCollapsible ? /* @__PURE__ */ jsxRuntime.jsx(
80
+ "div",
81
+ {
82
+ id: panelId,
83
+ role: "region",
84
+ "aria-labelledby": buttonId,
85
+ className: `${styles__default.default.panel} ${shouldAnimate ? styles__default.default.animate : styles__default.default.noAnimate}`,
86
+ style: { height },
87
+ onTransitionEnd,
88
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: innerRef, className: contentClassName, children: shouldRenderContent ? item.content : null })
89
+ }
90
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: contentClassName, children: item.content })
91
+ ] })
92
+ ]
93
+ }
94
+ );
95
+ }
96
+ function TimelineRowActions({ items }) {
97
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.contextMenuOverlay, children: /* @__PURE__ */ jsxRuntime.jsx(
98
+ Popover.Popover,
99
+ {
100
+ matchTriggerWidth: false,
101
+ minWidth: "180px",
102
+ trigger: (toggle, _icon, isOpen) => /* @__PURE__ */ jsxRuntime.jsx(
103
+ Button.Button,
104
+ {
105
+ type: "button",
106
+ size: "sm",
107
+ variant: "inline",
108
+ shape: "round",
109
+ className: styles__default.default.contextMenuTrigger,
110
+ "aria-label": "Flere handlinger",
111
+ "aria-haspopup": "menu",
112
+ "aria-expanded": isOpen ? true : false,
113
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreVertical, { size: 16 }),
114
+ onClick: toggle
115
+ }
116
+ ),
117
+ children: (close) => /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu, { children: items.map(
118
+ (item, index) => item.type === "header" ? /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Header, { children: item.label }, index) : /* @__PURE__ */ jsxRuntime.jsx(
119
+ Menu.Menu.Item,
120
+ {
121
+ active: item.active,
122
+ selected: item.selected,
123
+ disabled: item.disabled,
124
+ variant: item.variant,
125
+ children: /* @__PURE__ */ jsxRuntime.jsx(
126
+ "button",
127
+ {
128
+ type: "button",
129
+ onClick: () => {
130
+ item.onClick();
131
+ close();
132
+ },
133
+ children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.contextMenuItemLabel, children: [
134
+ item.icon,
135
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.contextMenuItemText, children: item.label })
136
+ ] })
137
+ }
138
+ )
139
+ },
140
+ index
141
+ )
142
+ ) })
143
+ }
144
+ ) });
145
+ }
146
+
147
+ exports.TimelineRow = TimelineRow;
@@ -0,0 +1,15 @@
1
+ import type { JSX } from 'react';
2
+ import { TimelineItem } from '../Timeline';
3
+ export type TimelineRowProps = {
4
+ uid: string;
5
+ index: number;
6
+ item: TimelineItem;
7
+ isLast: boolean;
8
+ isOpen: boolean;
9
+ onToggle: (index: number) => void;
10
+ shouldAnimate?: boolean;
11
+ variant?: 'default' | 'outlined';
12
+ renderMode?: 'lazy' | 'eager';
13
+ size?: 'sm' | 'md' | 'lg';
14
+ };
15
+ export declare function TimelineRow({ uid, index, item, isLast, isOpen, onToggle, shouldAnimate, variant, renderMode, size, }: TimelineRowProps): JSX.Element;