@dbcdk/react-components 0.0.208 → 0.0.210
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/client.cjs +10 -0
- package/dist/client.d.ts +4 -0
- package/dist/client.js +2 -0
- package/dist/components/forms/markdown-editor/MarkdownEditor.cjs +475 -0
- package/dist/components/forms/markdown-editor/MarkdownEditor.d.ts +68 -0
- package/dist/components/forms/markdown-editor/MarkdownEditor.js +468 -0
- package/dist/components/forms/markdown-editor/MarkdownEditor.module.css +202 -0
- package/dist/components/forms/markdown-editor/MarkdownViewer.cjs +29 -0
- package/dist/components/forms/markdown-editor/MarkdownViewer.d.ts +27 -0
- package/dist/components/forms/markdown-editor/MarkdownViewer.js +23 -0
- package/dist/components/forms/markdown-editor/MarkdownViewer.module.css +97 -0
- package/dist/components/forms/markdown-editor/markdown.utils.cjs +325 -0
- package/dist/components/forms/markdown-editor/markdown.utils.d.ts +66 -0
- package/dist/components/forms/markdown-editor/markdown.utils.js +310 -0
- package/dist/components/listbox/Listbox.cjs +2 -2
- package/dist/components/listbox/Listbox.d.ts +2 -2
- package/dist/components/listbox/Listbox.js +2 -2
- package/dist/components/meta-bar/MetaBar.cjs +2 -2
- package/dist/components/meta-bar/MetaBar.d.ts +2 -1
- package/dist/components/meta-bar/MetaBar.js +2 -2
- package/dist/components/meta-bar/MetaBar.module.css +7 -0
- package/dist/components/overlay/side-panel/SidePanel.cjs +80 -2
- package/dist/components/overlay/side-panel/SidePanel.js +80 -2
- package/dist/components/overlay/tooltip/TooltipProvider.cjs +10 -1
- package/dist/components/overlay/tooltip/TooltipProvider.js +11 -2
- package/dist/components/overlay/tooltip/useTooltipTrigger.cjs +9 -2
- package/dist/components/overlay/tooltip/useTooltipTrigger.js +9 -2
- package/dist/components/sidebar/components/sidebar-container/SidebarContainer.cjs +1 -1
- package/dist/components/sidebar/components/sidebar-container/SidebarContainer.js +1 -1
- package/dist/components/split-pane/SplitPane.cjs +22 -7
- package/dist/components/split-pane/SplitPane.d.ts +5 -2
- package/dist/components/split-pane/SplitPane.js +22 -7
- package/dist/components/split-pane/SplitPane.module.css +9 -0
- package/dist/components/split-pane/provider/SplitPaneContext.cjs +5 -2
- package/dist/components/split-pane/provider/SplitPaneContext.d.ts +3 -1
- package/dist/components/split-pane/provider/SplitPaneContext.js +5 -2
- package/dist/components/tabs/Tabs.cjs +83 -69
- package/dist/components/tabs/Tabs.d.ts +5 -1
- package/dist/components/tabs/Tabs.js +83 -69
- package/dist/components/tabs/Tabs.module.css +39 -0
- package/dist/components/tree-view/TreeNodeRow.cjs +70 -30
- package/dist/components/tree-view/TreeNodeRow.d.ts +6 -1
- package/dist/components/tree-view/TreeNodeRow.js +70 -30
- package/dist/components/tree-view/TreeView.cjs +107 -19
- package/dist/components/tree-view/TreeView.d.ts +1 -1
- package/dist/components/tree-view/TreeView.js +107 -19
- package/dist/components/tree-view/TreeView.module.css +47 -3
- package/dist/components/tree-view/types.d.ts +6 -0
- package/dist/index.cjs +213 -208
- package/dist/index.css +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/styles/css-helper-classes/typography.css +4 -0
- package/package.json +4 -1
|
@@ -64,10 +64,18 @@ function shallowEqualActive(a, b) {
|
|
|
64
64
|
function TooltipProvider({ children }) {
|
|
65
65
|
const [active, setActive] = react.useState(null);
|
|
66
66
|
const showTimerRef = react.useRef(null);
|
|
67
|
+
const pendingIdRef = react.useRef(null);
|
|
68
|
+
react.useEffect(() => {
|
|
69
|
+
return () => {
|
|
70
|
+
if (showTimerRef.current) clearTimeout(showTimerRef.current);
|
|
71
|
+
};
|
|
72
|
+
}, []);
|
|
67
73
|
const show = react.useCallback((next) => {
|
|
68
74
|
if (showTimerRef.current) clearTimeout(showTimerRef.current);
|
|
75
|
+
pendingIdRef.current = next.id;
|
|
69
76
|
showTimerRef.current = setTimeout(() => {
|
|
70
77
|
showTimerRef.current = null;
|
|
78
|
+
pendingIdRef.current = null;
|
|
71
79
|
setActive((curr) => {
|
|
72
80
|
const proposed = { ...next, open: true };
|
|
73
81
|
return shallowEqualActive(curr, proposed) ? curr : proposed;
|
|
@@ -75,9 +83,10 @@ function TooltipProvider({ children }) {
|
|
|
75
83
|
}, SHOW_DELAY_MS);
|
|
76
84
|
}, []);
|
|
77
85
|
const hide = react.useCallback((id) => {
|
|
78
|
-
if (showTimerRef.current) {
|
|
86
|
+
if (showTimerRef.current && pendingIdRef.current === id) {
|
|
79
87
|
clearTimeout(showTimerRef.current);
|
|
80
88
|
showTimerRef.current = null;
|
|
89
|
+
pendingIdRef.current = null;
|
|
81
90
|
}
|
|
82
91
|
setActive((curr) => {
|
|
83
92
|
if (!curr || curr.id !== id) return curr;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { createContext, useState, useRef, useCallback, useMemo, useContext,
|
|
3
|
+
import { createContext, useState, useRef, useEffect, useCallback, useMemo, useContext, useLayoutEffect } from 'react';
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
5
5
|
import styles from './Tooltip.module.css';
|
|
6
6
|
|
|
@@ -58,10 +58,18 @@ function shallowEqualActive(a, b) {
|
|
|
58
58
|
function TooltipProvider({ children }) {
|
|
59
59
|
const [active, setActive] = useState(null);
|
|
60
60
|
const showTimerRef = useRef(null);
|
|
61
|
+
const pendingIdRef = useRef(null);
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
return () => {
|
|
64
|
+
if (showTimerRef.current) clearTimeout(showTimerRef.current);
|
|
65
|
+
};
|
|
66
|
+
}, []);
|
|
61
67
|
const show = useCallback((next) => {
|
|
62
68
|
if (showTimerRef.current) clearTimeout(showTimerRef.current);
|
|
69
|
+
pendingIdRef.current = next.id;
|
|
63
70
|
showTimerRef.current = setTimeout(() => {
|
|
64
71
|
showTimerRef.current = null;
|
|
72
|
+
pendingIdRef.current = null;
|
|
65
73
|
setActive((curr) => {
|
|
66
74
|
const proposed = { ...next, open: true };
|
|
67
75
|
return shallowEqualActive(curr, proposed) ? curr : proposed;
|
|
@@ -69,9 +77,10 @@ function TooltipProvider({ children }) {
|
|
|
69
77
|
}, SHOW_DELAY_MS);
|
|
70
78
|
}, []);
|
|
71
79
|
const hide = useCallback((id) => {
|
|
72
|
-
if (showTimerRef.current) {
|
|
80
|
+
if (showTimerRef.current && pendingIdRef.current === id) {
|
|
73
81
|
clearTimeout(showTimerRef.current);
|
|
74
82
|
showTimerRef.current = null;
|
|
83
|
+
pendingIdRef.current = null;
|
|
75
84
|
}
|
|
76
85
|
setActive((curr) => {
|
|
77
86
|
if (!curr || curr.id !== id) return curr;
|
|
@@ -26,12 +26,19 @@ function useTooltipTrigger(options) {
|
|
|
26
26
|
const openTimer = react.useRef(null);
|
|
27
27
|
const closeTimer = react.useRef(null);
|
|
28
28
|
const openedByFocusRef = react.useRef(false);
|
|
29
|
-
const clearTimers = () => {
|
|
29
|
+
const clearTimers = react.useCallback(() => {
|
|
30
30
|
if (openTimer.current) window.clearTimeout(openTimer.current);
|
|
31
31
|
if (closeTimer.current) window.clearTimeout(closeTimer.current);
|
|
32
32
|
openTimer.current = null;
|
|
33
33
|
closeTimer.current = null;
|
|
34
|
-
};
|
|
34
|
+
}, []);
|
|
35
|
+
const hideTooltip = ctx.hide;
|
|
36
|
+
react.useEffect(() => {
|
|
37
|
+
return () => {
|
|
38
|
+
clearTimers();
|
|
39
|
+
hideTooltip(id);
|
|
40
|
+
};
|
|
41
|
+
}, [clearTimers, hideTooltip, id]);
|
|
35
42
|
const lastSentRef = react.useRef(null);
|
|
36
43
|
const show = react.useCallback(() => {
|
|
37
44
|
if (!content) return;
|
|
@@ -24,12 +24,19 @@ function useTooltipTrigger(options) {
|
|
|
24
24
|
const openTimer = useRef(null);
|
|
25
25
|
const closeTimer = useRef(null);
|
|
26
26
|
const openedByFocusRef = useRef(false);
|
|
27
|
-
const clearTimers = () => {
|
|
27
|
+
const clearTimers = useCallback(() => {
|
|
28
28
|
if (openTimer.current) window.clearTimeout(openTimer.current);
|
|
29
29
|
if (closeTimer.current) window.clearTimeout(closeTimer.current);
|
|
30
30
|
openTimer.current = null;
|
|
31
31
|
closeTimer.current = null;
|
|
32
|
-
};
|
|
32
|
+
}, []);
|
|
33
|
+
const hideTooltip = ctx.hide;
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
return () => {
|
|
36
|
+
clearTimers();
|
|
37
|
+
hideTooltip(id);
|
|
38
|
+
};
|
|
39
|
+
}, [clearTimers, hideTooltip, id]);
|
|
33
40
|
const lastSentRef = useRef(null);
|
|
34
41
|
const show = useCallback(() => {
|
|
35
42
|
if (!content) return;
|
|
@@ -186,7 +186,7 @@ function SidebarContainer({
|
|
|
186
186
|
] }) }),
|
|
187
187
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.content, children: [
|
|
188
188
|
!hideSearch && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.filter, children: /* @__PURE__ */ jsxRuntime.jsx(SidenavFiltering__default.default, { placeholder: searchPlaceholder, showSettings }) }),
|
|
189
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className:
|
|
189
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.links, children: /* @__PURE__ */ jsxRuntime.jsx(SidebarItems.SidebarItems, { activeLink }) })
|
|
190
190
|
] }),
|
|
191
191
|
footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.footerSlot, children: footer }),
|
|
192
192
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.footer, children: [
|
|
@@ -179,7 +179,7 @@ function SidebarContainer({
|
|
|
179
179
|
] }) }),
|
|
180
180
|
/* @__PURE__ */ jsxs("div", { className: styles.content, children: [
|
|
181
181
|
!hideSearch && /* @__PURE__ */ jsx("div", { className: styles.filter, children: /* @__PURE__ */ jsx(SidenavFiltering, { placeholder: searchPlaceholder, showSettings }) }),
|
|
182
|
-
/* @__PURE__ */ jsx("div", { className:
|
|
182
|
+
/* @__PURE__ */ jsx("div", { className: styles.links, children: /* @__PURE__ */ jsx(SidebarItems, { activeLink }) })
|
|
183
183
|
] }),
|
|
184
184
|
footer && /* @__PURE__ */ jsx("div", { className: styles.footerSlot, children: footer }),
|
|
185
185
|
/* @__PURE__ */ jsxs("div", { className: styles.footer, children: [
|
|
@@ -22,7 +22,8 @@ function SplitPane({
|
|
|
22
22
|
showDivider = "hover",
|
|
23
23
|
gutterSize = 16,
|
|
24
24
|
storageKey,
|
|
25
|
-
fillViewport = false
|
|
25
|
+
fillViewport = false,
|
|
26
|
+
secondaryVisible = true
|
|
26
27
|
}) {
|
|
27
28
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
28
29
|
SplitPaneContext.SplitPaneProvider,
|
|
@@ -31,6 +32,7 @@ function SplitPane({
|
|
|
31
32
|
initialPrimarySize,
|
|
32
33
|
minPrimarySize,
|
|
33
34
|
minSecondarySize,
|
|
35
|
+
gutterSize,
|
|
34
36
|
storageKey,
|
|
35
37
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
36
38
|
SplitPaneContainer,
|
|
@@ -38,6 +40,7 @@ function SplitPane({
|
|
|
38
40
|
showDivider,
|
|
39
41
|
gutterSize,
|
|
40
42
|
fillViewport,
|
|
43
|
+
secondaryVisible,
|
|
41
44
|
children
|
|
42
45
|
}
|
|
43
46
|
)
|
|
@@ -48,7 +51,8 @@ function SplitPaneContainer({
|
|
|
48
51
|
children,
|
|
49
52
|
showDivider,
|
|
50
53
|
gutterSize,
|
|
51
|
-
fillViewport
|
|
54
|
+
fillViewport,
|
|
55
|
+
secondaryVisible
|
|
52
56
|
}) {
|
|
53
57
|
const { direction, primarySize, containerRef } = SplitPaneContext.useSplitPaneContext();
|
|
54
58
|
const style = react.useMemo(
|
|
@@ -66,6 +70,7 @@ function SplitPaneContainer({
|
|
|
66
70
|
"data-direction": direction,
|
|
67
71
|
"data-divider": showDivider,
|
|
68
72
|
"data-fill-viewport": fillViewport,
|
|
73
|
+
"data-secondary-visible": secondaryVisible,
|
|
69
74
|
style,
|
|
70
75
|
children
|
|
71
76
|
}
|
|
@@ -77,13 +82,14 @@ function SplitPanePrimary({ children }) {
|
|
|
77
82
|
function SplitPaneSecondary({ children }) {
|
|
78
83
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.secondary, children });
|
|
79
84
|
}
|
|
80
|
-
function SplitPaneGutter() {
|
|
85
|
+
function SplitPaneGutter({ label = "Resize panes" }) {
|
|
81
86
|
const {
|
|
82
87
|
direction,
|
|
83
88
|
primarySize,
|
|
84
89
|
setPrimarySize,
|
|
85
90
|
minPrimarySize,
|
|
86
91
|
minSecondarySize,
|
|
92
|
+
gutterSize,
|
|
87
93
|
containerRef,
|
|
88
94
|
resetDefault
|
|
89
95
|
} = SplitPaneContext.useSplitPaneContext();
|
|
@@ -101,9 +107,10 @@ function SplitPaneGutter() {
|
|
|
101
107
|
if (!el) return { maxPrimary: Infinity, total: 0 };
|
|
102
108
|
const rect = el.getBoundingClientRect();
|
|
103
109
|
const total = direction === "horizontal" ? rect.width : rect.height;
|
|
104
|
-
|
|
110
|
+
if (!Number.isFinite(total) || total <= 0) return { maxPrimary: Infinity, total };
|
|
111
|
+
const maxPrimary2 = Math.max(minPrimarySize, total - minSecondarySize - gutterSize);
|
|
105
112
|
return { maxPrimary: maxPrimary2, total };
|
|
106
|
-
}, [containerRef, direction, minPrimarySize, minSecondarySize]);
|
|
113
|
+
}, [containerRef, direction, gutterSize, minPrimarySize, minSecondarySize]);
|
|
107
114
|
const onPointerDown = react.useCallback(
|
|
108
115
|
(e) => {
|
|
109
116
|
const el = containerRef.current;
|
|
@@ -163,13 +170,21 @@ function SplitPaneGutter() {
|
|
|
163
170
|
const ariaOrientation = direction === "horizontal" ? "vertical" : "horizontal";
|
|
164
171
|
const [maxPrimary, setMaxPrimary] = react.useState(Infinity);
|
|
165
172
|
react.useEffect(() => {
|
|
166
|
-
|
|
167
|
-
|
|
173
|
+
const container = containerRef.current;
|
|
174
|
+
if (!container) return;
|
|
175
|
+
const updateMax = () => setMaxPrimary(computeClamp().maxPrimary);
|
|
176
|
+
updateMax();
|
|
177
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
178
|
+
const observer = new ResizeObserver(updateMax);
|
|
179
|
+
observer.observe(container);
|
|
180
|
+
return () => observer.disconnect();
|
|
181
|
+
}, [computeClamp, containerRef]);
|
|
168
182
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.gutter, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
169
183
|
"div",
|
|
170
184
|
{
|
|
171
185
|
className: styles__default.default.resizer,
|
|
172
186
|
role: "separator",
|
|
187
|
+
"aria-label": label,
|
|
173
188
|
"aria-orientation": ariaOrientation,
|
|
174
189
|
"aria-valuemin": Math.round(minPrimarySize),
|
|
175
190
|
"aria-valuemax": Number.isFinite(maxPrimary) ? Math.round(maxPrimary) : void 0,
|
|
@@ -10,12 +10,15 @@ export interface SplitPaneProps {
|
|
|
10
10
|
gutterSize?: number;
|
|
11
11
|
storageKey?: string;
|
|
12
12
|
fillViewport?: boolean;
|
|
13
|
+
secondaryVisible?: boolean;
|
|
13
14
|
}
|
|
14
|
-
export declare function SplitPane({ children, initialPrimarySize, minPrimarySize, minSecondarySize, direction, showDivider, gutterSize, storageKey, fillViewport, }: SplitPaneProps): JSX.Element;
|
|
15
|
+
export declare function SplitPane({ children, initialPrimarySize, minPrimarySize, minSecondarySize, direction, showDivider, gutterSize, storageKey, fillViewport, secondaryVisible, }: SplitPaneProps): JSX.Element;
|
|
15
16
|
export declare function SplitPanePrimary({ children }: {
|
|
16
17
|
children: ReactNode;
|
|
17
18
|
}): JSX.Element;
|
|
18
19
|
export declare function SplitPaneSecondary({ children }: {
|
|
19
20
|
children: ReactNode;
|
|
20
21
|
}): JSX.Element;
|
|
21
|
-
export declare function SplitPaneGutter(
|
|
22
|
+
export declare function SplitPaneGutter({ label }: {
|
|
23
|
+
label?: string;
|
|
24
|
+
}): JSX.Element;
|
|
@@ -16,7 +16,8 @@ function SplitPane({
|
|
|
16
16
|
showDivider = "hover",
|
|
17
17
|
gutterSize = 16,
|
|
18
18
|
storageKey,
|
|
19
|
-
fillViewport = false
|
|
19
|
+
fillViewport = false,
|
|
20
|
+
secondaryVisible = true
|
|
20
21
|
}) {
|
|
21
22
|
return /* @__PURE__ */ jsx(
|
|
22
23
|
SplitPaneProvider,
|
|
@@ -25,6 +26,7 @@ function SplitPane({
|
|
|
25
26
|
initialPrimarySize,
|
|
26
27
|
minPrimarySize,
|
|
27
28
|
minSecondarySize,
|
|
29
|
+
gutterSize,
|
|
28
30
|
storageKey,
|
|
29
31
|
children: /* @__PURE__ */ jsx(
|
|
30
32
|
SplitPaneContainer,
|
|
@@ -32,6 +34,7 @@ function SplitPane({
|
|
|
32
34
|
showDivider,
|
|
33
35
|
gutterSize,
|
|
34
36
|
fillViewport,
|
|
37
|
+
secondaryVisible,
|
|
35
38
|
children
|
|
36
39
|
}
|
|
37
40
|
)
|
|
@@ -42,7 +45,8 @@ function SplitPaneContainer({
|
|
|
42
45
|
children,
|
|
43
46
|
showDivider,
|
|
44
47
|
gutterSize,
|
|
45
|
-
fillViewport
|
|
48
|
+
fillViewport,
|
|
49
|
+
secondaryVisible
|
|
46
50
|
}) {
|
|
47
51
|
const { direction, primarySize, containerRef } = useSplitPaneContext();
|
|
48
52
|
const style = useMemo(
|
|
@@ -60,6 +64,7 @@ function SplitPaneContainer({
|
|
|
60
64
|
"data-direction": direction,
|
|
61
65
|
"data-divider": showDivider,
|
|
62
66
|
"data-fill-viewport": fillViewport,
|
|
67
|
+
"data-secondary-visible": secondaryVisible,
|
|
63
68
|
style,
|
|
64
69
|
children
|
|
65
70
|
}
|
|
@@ -71,13 +76,14 @@ function SplitPanePrimary({ children }) {
|
|
|
71
76
|
function SplitPaneSecondary({ children }) {
|
|
72
77
|
return /* @__PURE__ */ jsx("div", { className: styles.secondary, children });
|
|
73
78
|
}
|
|
74
|
-
function SplitPaneGutter() {
|
|
79
|
+
function SplitPaneGutter({ label = "Resize panes" }) {
|
|
75
80
|
const {
|
|
76
81
|
direction,
|
|
77
82
|
primarySize,
|
|
78
83
|
setPrimarySize,
|
|
79
84
|
minPrimarySize,
|
|
80
85
|
minSecondarySize,
|
|
86
|
+
gutterSize,
|
|
81
87
|
containerRef,
|
|
82
88
|
resetDefault
|
|
83
89
|
} = useSplitPaneContext();
|
|
@@ -95,9 +101,10 @@ function SplitPaneGutter() {
|
|
|
95
101
|
if (!el) return { maxPrimary: Infinity, total: 0 };
|
|
96
102
|
const rect = el.getBoundingClientRect();
|
|
97
103
|
const total = direction === "horizontal" ? rect.width : rect.height;
|
|
98
|
-
|
|
104
|
+
if (!Number.isFinite(total) || total <= 0) return { maxPrimary: Infinity, total };
|
|
105
|
+
const maxPrimary2 = Math.max(minPrimarySize, total - minSecondarySize - gutterSize);
|
|
99
106
|
return { maxPrimary: maxPrimary2, total };
|
|
100
|
-
}, [containerRef, direction, minPrimarySize, minSecondarySize]);
|
|
107
|
+
}, [containerRef, direction, gutterSize, minPrimarySize, minSecondarySize]);
|
|
101
108
|
const onPointerDown = useCallback(
|
|
102
109
|
(e) => {
|
|
103
110
|
const el = containerRef.current;
|
|
@@ -157,13 +164,21 @@ function SplitPaneGutter() {
|
|
|
157
164
|
const ariaOrientation = direction === "horizontal" ? "vertical" : "horizontal";
|
|
158
165
|
const [maxPrimary, setMaxPrimary] = useState(Infinity);
|
|
159
166
|
useEffect(() => {
|
|
160
|
-
|
|
161
|
-
|
|
167
|
+
const container = containerRef.current;
|
|
168
|
+
if (!container) return;
|
|
169
|
+
const updateMax = () => setMaxPrimary(computeClamp().maxPrimary);
|
|
170
|
+
updateMax();
|
|
171
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
172
|
+
const observer = new ResizeObserver(updateMax);
|
|
173
|
+
observer.observe(container);
|
|
174
|
+
return () => observer.disconnect();
|
|
175
|
+
}, [computeClamp, containerRef]);
|
|
162
176
|
return /* @__PURE__ */ jsx("div", { className: styles.gutter, children: /* @__PURE__ */ jsx(
|
|
163
177
|
"div",
|
|
164
178
|
{
|
|
165
179
|
className: styles.resizer,
|
|
166
180
|
role: "separator",
|
|
181
|
+
"aria-label": label,
|
|
167
182
|
"aria-orientation": ariaOrientation,
|
|
168
183
|
"aria-valuemin": Math.round(minPrimarySize),
|
|
169
184
|
"aria-valuemax": Number.isFinite(maxPrimary) ? Math.round(maxPrimary) : void 0,
|
|
@@ -13,6 +13,15 @@
|
|
|
13
13
|
max-height: 100%;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
.container[data-secondary-visible='false'] > .primary {
|
|
17
|
+
flex: 1 1 auto;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.container[data-secondary-visible='false'] > .gutter,
|
|
21
|
+
.container[data-secondary-visible='false'] > .secondary {
|
|
22
|
+
display: none;
|
|
23
|
+
}
|
|
24
|
+
|
|
16
25
|
.container[data-direction='horizontal'] {
|
|
17
26
|
flex-direction: row;
|
|
18
27
|
}
|
|
@@ -44,6 +44,7 @@ function SplitPaneProvider({
|
|
|
44
44
|
initialPrimarySize,
|
|
45
45
|
minPrimarySize,
|
|
46
46
|
minSecondarySize,
|
|
47
|
+
gutterSize,
|
|
47
48
|
storageKey
|
|
48
49
|
}) {
|
|
49
50
|
const containerRef = React.useRef(null);
|
|
@@ -55,8 +56,8 @@ function SplitPaneProvider({
|
|
|
55
56
|
const rect = el.getBoundingClientRect();
|
|
56
57
|
const total = direction === "horizontal" ? rect.width : rect.height;
|
|
57
58
|
if (!Number.isFinite(total) || total <= 0) return null;
|
|
58
|
-
return Math.max(minPrimarySize, total - minSecondarySize);
|
|
59
|
-
}, [direction, minPrimarySize, minSecondarySize]);
|
|
59
|
+
return Math.max(minPrimarySize, total - minSecondarySize - gutterSize);
|
|
60
|
+
}, [direction, gutterSize, minPrimarySize, minSecondarySize]);
|
|
60
61
|
React.useEffect(() => {
|
|
61
62
|
if (!storageKey) return;
|
|
62
63
|
const stored = readStoredSize(storageKey);
|
|
@@ -108,6 +109,7 @@ function SplitPaneProvider({
|
|
|
108
109
|
resetDefault,
|
|
109
110
|
minPrimarySize,
|
|
110
111
|
minSecondarySize,
|
|
112
|
+
gutterSize,
|
|
111
113
|
containerRef,
|
|
112
114
|
storageKey
|
|
113
115
|
}),
|
|
@@ -118,6 +120,7 @@ function SplitPaneProvider({
|
|
|
118
120
|
resetDefault,
|
|
119
121
|
minPrimarySize,
|
|
120
122
|
minSecondarySize,
|
|
123
|
+
gutterSize,
|
|
121
124
|
storageKey
|
|
122
125
|
]
|
|
123
126
|
);
|
|
@@ -6,6 +6,7 @@ export interface SplitPaneContextValue {
|
|
|
6
6
|
setPrimarySize: (newSize: number) => void;
|
|
7
7
|
minPrimarySize: number;
|
|
8
8
|
minSecondarySize: number;
|
|
9
|
+
gutterSize: number;
|
|
9
10
|
containerRef: React.RefObject<HTMLDivElement | null>;
|
|
10
11
|
storageKey?: string;
|
|
11
12
|
resetDefault: () => void;
|
|
@@ -18,7 +19,8 @@ type SplitPaneProviderProps = {
|
|
|
18
19
|
initialPrimarySize: number;
|
|
19
20
|
minPrimarySize: number;
|
|
20
21
|
minSecondarySize: number;
|
|
22
|
+
gutterSize: number;
|
|
21
23
|
storageKey?: string;
|
|
22
24
|
};
|
|
23
|
-
export declare function SplitPaneProvider({ children, direction, initialPrimarySize, minPrimarySize, minSecondarySize, storageKey, }: SplitPaneProviderProps): React.ReactNode;
|
|
25
|
+
export declare function SplitPaneProvider({ children, direction, initialPrimarySize, minPrimarySize, minSecondarySize, gutterSize, storageKey, }: SplitPaneProviderProps): React.ReactNode;
|
|
24
26
|
export {};
|
|
@@ -38,6 +38,7 @@ function SplitPaneProvider({
|
|
|
38
38
|
initialPrimarySize,
|
|
39
39
|
minPrimarySize,
|
|
40
40
|
minSecondarySize,
|
|
41
|
+
gutterSize,
|
|
41
42
|
storageKey
|
|
42
43
|
}) {
|
|
43
44
|
const containerRef = useRef(null);
|
|
@@ -49,8 +50,8 @@ function SplitPaneProvider({
|
|
|
49
50
|
const rect = el.getBoundingClientRect();
|
|
50
51
|
const total = direction === "horizontal" ? rect.width : rect.height;
|
|
51
52
|
if (!Number.isFinite(total) || total <= 0) return null;
|
|
52
|
-
return Math.max(minPrimarySize, total - minSecondarySize);
|
|
53
|
-
}, [direction, minPrimarySize, minSecondarySize]);
|
|
53
|
+
return Math.max(minPrimarySize, total - minSecondarySize - gutterSize);
|
|
54
|
+
}, [direction, gutterSize, minPrimarySize, minSecondarySize]);
|
|
54
55
|
useEffect(() => {
|
|
55
56
|
if (!storageKey) return;
|
|
56
57
|
const stored = readStoredSize(storageKey);
|
|
@@ -102,6 +103,7 @@ function SplitPaneProvider({
|
|
|
102
103
|
resetDefault,
|
|
103
104
|
minPrimarySize,
|
|
104
105
|
minSecondarySize,
|
|
106
|
+
gutterSize,
|
|
105
107
|
containerRef,
|
|
106
108
|
storageKey
|
|
107
109
|
}),
|
|
@@ -112,6 +114,7 @@ function SplitPaneProvider({
|
|
|
112
114
|
resetDefault,
|
|
113
115
|
minPrimarySize,
|
|
114
116
|
minSecondarySize,
|
|
117
|
+
gutterSize,
|
|
115
118
|
storageKey
|
|
116
119
|
]
|
|
117
120
|
);
|
|
@@ -49,6 +49,8 @@ function Tabs({
|
|
|
49
49
|
subheader,
|
|
50
50
|
variant,
|
|
51
51
|
panelStyle = false,
|
|
52
|
+
flushContent = false,
|
|
53
|
+
stackTabListAdditionOnMobile = false,
|
|
52
54
|
tabs,
|
|
53
55
|
value,
|
|
54
56
|
defaultValue,
|
|
@@ -148,79 +150,91 @@ function Tabs({
|
|
|
148
150
|
children: /* @__PURE__ */ jsxRuntime.jsx(Headline.Headline, { disableMargin: true, size: 2, subheader, addition, children: header })
|
|
149
151
|
}
|
|
150
152
|
) : null,
|
|
151
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
152
|
-
|
|
153
|
-
|
|
153
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
154
|
+
"div",
|
|
155
|
+
{
|
|
156
|
+
className: [
|
|
157
|
+
styles__default.default.tabs,
|
|
158
|
+
styles__default.default[variant],
|
|
159
|
+
panelStyle && styles__default.default.panelStyle,
|
|
160
|
+
flushContent && styles__default.default.flushContent,
|
|
161
|
+
stackTabListAdditionOnMobile && styles__default.default.stackTabListAdditionOnMobile
|
|
162
|
+
].filter(Boolean).join(" "),
|
|
163
|
+
children: [
|
|
164
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.tabList, children: [
|
|
165
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.tabStrip, children: [
|
|
166
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
167
|
+
"div",
|
|
168
|
+
{
|
|
169
|
+
className: onAddTab ? styles__default.default.tabButtons : `${styles__default.default.tabButtons} ${styles__default.default.tabButtonsEnd}`,
|
|
170
|
+
role: "tablist",
|
|
171
|
+
"aria-label": header != null ? header : "Tabs",
|
|
172
|
+
children: visibleTabs.map((tab, index) => {
|
|
173
|
+
const selected = index === activeIndex;
|
|
174
|
+
const tabDomId = `${uid}-tab-${String(tab.id)}`;
|
|
175
|
+
const panelDomId = `${uid}-panel-${String(tab.id)}`;
|
|
176
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.tab} ${selected ? styles__default.default.active : ""}`, children: [
|
|
177
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
178
|
+
"button",
|
|
179
|
+
{
|
|
180
|
+
id: tabDomId,
|
|
181
|
+
type: "button",
|
|
182
|
+
className: styles__default.default.tabButton,
|
|
183
|
+
role: "tab",
|
|
184
|
+
"aria-selected": selected,
|
|
185
|
+
"aria-controls": panelDomId,
|
|
186
|
+
tabIndex: selected ? 0 : -1,
|
|
187
|
+
disabled: tab.disabled,
|
|
188
|
+
onClick: () => setValue(tab.id),
|
|
189
|
+
onKeyDown: (e) => onKeyDownTab(e, index),
|
|
190
|
+
children: [
|
|
191
|
+
tab.headerIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.icon, children: tab.headerIcon }) : null,
|
|
192
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.label, children: tab.header }),
|
|
193
|
+
tab.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.badge, children: /* @__PURE__ */ jsxRuntime.jsx(Chip.Chip, { size: "sm", children: tab.badge.toLocaleString("da-DK") }) }) : null
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
),
|
|
197
|
+
tab.removable && onRemoveTab ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
198
|
+
"button",
|
|
199
|
+
{
|
|
200
|
+
type: "button",
|
|
201
|
+
className: styles__default.default.removeTabButton,
|
|
202
|
+
"aria-label": `Fjern fane ${tab.header}`,
|
|
203
|
+
disabled: tab.disabled,
|
|
204
|
+
onClick: () => onRemoveTab(tab.id, tab, index),
|
|
205
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { "aria-hidden": "true" })
|
|
206
|
+
}
|
|
207
|
+
) : null
|
|
208
|
+
] }, tab.id);
|
|
209
|
+
})
|
|
210
|
+
}
|
|
211
|
+
),
|
|
212
|
+
onAddTab ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
213
|
+
"button",
|
|
214
|
+
{
|
|
215
|
+
type: "button",
|
|
216
|
+
className: styles__default.default.addTabButton,
|
|
217
|
+
onClick: onAddTab,
|
|
218
|
+
"aria-label": "Tilf\xF8j fane",
|
|
219
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { "aria-hidden": "true" })
|
|
220
|
+
}
|
|
221
|
+
) : null
|
|
222
|
+
] }),
|
|
223
|
+
tabListAddition ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.tabListAddition, children: tabListAddition }) : null
|
|
224
|
+
] }),
|
|
154
225
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
155
226
|
"div",
|
|
156
227
|
{
|
|
157
|
-
|
|
158
|
-
role: "
|
|
159
|
-
"aria-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const tabDomId = `${uid}-tab-${String(tab.id)}`;
|
|
163
|
-
const panelDomId = `${uid}-panel-${String(tab.id)}`;
|
|
164
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${styles__default.default.tab} ${selected ? styles__default.default.active : ""}`, children: [
|
|
165
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
166
|
-
"button",
|
|
167
|
-
{
|
|
168
|
-
id: tabDomId,
|
|
169
|
-
type: "button",
|
|
170
|
-
className: styles__default.default.tabButton,
|
|
171
|
-
role: "tab",
|
|
172
|
-
"aria-selected": selected,
|
|
173
|
-
"aria-controls": panelDomId,
|
|
174
|
-
tabIndex: selected ? 0 : -1,
|
|
175
|
-
disabled: tab.disabled,
|
|
176
|
-
onClick: () => setValue(tab.id),
|
|
177
|
-
onKeyDown: (e) => onKeyDownTab(e, index),
|
|
178
|
-
children: [
|
|
179
|
-
tab.headerIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.icon, children: tab.headerIcon }) : null,
|
|
180
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.label, children: tab.header }),
|
|
181
|
-
tab.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.badge, children: /* @__PURE__ */ jsxRuntime.jsx(Chip.Chip, { size: "sm", children: tab.badge.toLocaleString("da-DK") }) }) : null
|
|
182
|
-
]
|
|
183
|
-
}
|
|
184
|
-
),
|
|
185
|
-
tab.removable && onRemoveTab ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
186
|
-
"button",
|
|
187
|
-
{
|
|
188
|
-
type: "button",
|
|
189
|
-
className: styles__default.default.removeTabButton,
|
|
190
|
-
"aria-label": `Fjern fane ${tab.header}`,
|
|
191
|
-
disabled: tab.disabled,
|
|
192
|
-
onClick: () => onRemoveTab(tab.id, tab, index),
|
|
193
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { "aria-hidden": "true" })
|
|
194
|
-
}
|
|
195
|
-
) : null
|
|
196
|
-
] }, tab.id);
|
|
197
|
-
})
|
|
228
|
+
id: activeTab ? `${uid}-panel-${String(activeTab.id)}` : void 0,
|
|
229
|
+
role: "tabpanel",
|
|
230
|
+
"aria-labelledby": activeTab ? `${uid}-tab-${String(activeTab.id)}` : void 0,
|
|
231
|
+
className: styles__default.default.tabContent,
|
|
232
|
+
children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.loadingContent, children: /* @__PURE__ */ jsxRuntime.jsx(SkeletonLoader.SkeletonLoader, { type: "squares", rows: 1, columns: 1 }) }) : activeTab == null ? void 0 : activeTab.content
|
|
198
233
|
}
|
|
199
|
-
)
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
type: "button",
|
|
204
|
-
className: styles__default.default.addTabButton,
|
|
205
|
-
onClick: onAddTab,
|
|
206
|
-
"aria-label": "Tilf\xF8j fane",
|
|
207
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { "aria-hidden": "true" })
|
|
208
|
-
}
|
|
209
|
-
) : null
|
|
210
|
-
] }),
|
|
211
|
-
tabListAddition ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.tabListAddition, children: tabListAddition }) : null
|
|
212
|
-
] }),
|
|
213
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
214
|
-
"div",
|
|
215
|
-
{
|
|
216
|
-
id: activeTab ? `${uid}-panel-${String(activeTab.id)}` : void 0,
|
|
217
|
-
role: "tabpanel",
|
|
218
|
-
"aria-labelledby": activeTab ? `${uid}-tab-${String(activeTab.id)}` : void 0,
|
|
219
|
-
className: styles__default.default.tabContent,
|
|
220
|
-
children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.loadingContent, children: /* @__PURE__ */ jsxRuntime.jsx(SkeletonLoader.SkeletonLoader, { type: "squares", rows: 1, columns: 1 }) }) : activeTab == null ? void 0 : activeTab.content
|
|
221
|
-
}
|
|
222
|
-
)
|
|
223
|
-
] })
|
|
234
|
+
)
|
|
235
|
+
]
|
|
236
|
+
}
|
|
237
|
+
)
|
|
224
238
|
] });
|
|
225
239
|
}
|
|
226
240
|
Tabs.Item = TabsItem;
|
|
@@ -16,6 +16,10 @@ export interface TabsProps {
|
|
|
16
16
|
subheader?: ReactNode;
|
|
17
17
|
variant: TabsVariant;
|
|
18
18
|
panelStyle?: boolean;
|
|
19
|
+
/** Removes the built-in gap between the tab list and its content panel. */
|
|
20
|
+
flushContent?: boolean;
|
|
21
|
+
/** Moves tab-list additions below the tab buttons on narrow screens. */
|
|
22
|
+
stackTabListAdditionOnMobile?: boolean;
|
|
19
23
|
/** Data-driven API */
|
|
20
24
|
tabs?: TabItem[];
|
|
21
25
|
/** Controlled */
|
|
@@ -53,7 +57,7 @@ type SlotName = 'Item';
|
|
|
53
57
|
type TabsItemComponent = ((props: TabsItemProps) => JSX.Element) & {
|
|
54
58
|
__TABS_SLOT__?: SlotName;
|
|
55
59
|
};
|
|
56
|
-
export declare function Tabs({ header, subheader, variant, panelStyle, tabs, value, defaultValue, storageKey, onValueChange, onRemoveTab, onAddTab, addition, tabListAddition, loading, children, }: TabsProps): JSX.Element;
|
|
60
|
+
export declare function Tabs({ header, subheader, variant, panelStyle, flushContent, stackTabListAdditionOnMobile, tabs, value, defaultValue, storageKey, onValueChange, onRemoveTab, onAddTab, addition, tabListAddition, loading, children, }: TabsProps): JSX.Element;
|
|
57
61
|
export declare namespace Tabs {
|
|
58
62
|
var Item: TabsItemComponent;
|
|
59
63
|
}
|