@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.
Files changed (54) hide show
  1. package/dist/client.cjs +10 -0
  2. package/dist/client.d.ts +4 -0
  3. package/dist/client.js +2 -0
  4. package/dist/components/forms/markdown-editor/MarkdownEditor.cjs +475 -0
  5. package/dist/components/forms/markdown-editor/MarkdownEditor.d.ts +68 -0
  6. package/dist/components/forms/markdown-editor/MarkdownEditor.js +468 -0
  7. package/dist/components/forms/markdown-editor/MarkdownEditor.module.css +202 -0
  8. package/dist/components/forms/markdown-editor/MarkdownViewer.cjs +29 -0
  9. package/dist/components/forms/markdown-editor/MarkdownViewer.d.ts +27 -0
  10. package/dist/components/forms/markdown-editor/MarkdownViewer.js +23 -0
  11. package/dist/components/forms/markdown-editor/MarkdownViewer.module.css +97 -0
  12. package/dist/components/forms/markdown-editor/markdown.utils.cjs +325 -0
  13. package/dist/components/forms/markdown-editor/markdown.utils.d.ts +66 -0
  14. package/dist/components/forms/markdown-editor/markdown.utils.js +310 -0
  15. package/dist/components/listbox/Listbox.cjs +2 -2
  16. package/dist/components/listbox/Listbox.d.ts +2 -2
  17. package/dist/components/listbox/Listbox.js +2 -2
  18. package/dist/components/meta-bar/MetaBar.cjs +2 -2
  19. package/dist/components/meta-bar/MetaBar.d.ts +2 -1
  20. package/dist/components/meta-bar/MetaBar.js +2 -2
  21. package/dist/components/meta-bar/MetaBar.module.css +7 -0
  22. package/dist/components/overlay/side-panel/SidePanel.cjs +80 -2
  23. package/dist/components/overlay/side-panel/SidePanel.js +80 -2
  24. package/dist/components/overlay/tooltip/TooltipProvider.cjs +10 -1
  25. package/dist/components/overlay/tooltip/TooltipProvider.js +11 -2
  26. package/dist/components/overlay/tooltip/useTooltipTrigger.cjs +9 -2
  27. package/dist/components/overlay/tooltip/useTooltipTrigger.js +9 -2
  28. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.cjs +1 -1
  29. package/dist/components/sidebar/components/sidebar-container/SidebarContainer.js +1 -1
  30. package/dist/components/split-pane/SplitPane.cjs +22 -7
  31. package/dist/components/split-pane/SplitPane.d.ts +5 -2
  32. package/dist/components/split-pane/SplitPane.js +22 -7
  33. package/dist/components/split-pane/SplitPane.module.css +9 -0
  34. package/dist/components/split-pane/provider/SplitPaneContext.cjs +5 -2
  35. package/dist/components/split-pane/provider/SplitPaneContext.d.ts +3 -1
  36. package/dist/components/split-pane/provider/SplitPaneContext.js +5 -2
  37. package/dist/components/tabs/Tabs.cjs +83 -69
  38. package/dist/components/tabs/Tabs.d.ts +5 -1
  39. package/dist/components/tabs/Tabs.js +83 -69
  40. package/dist/components/tabs/Tabs.module.css +39 -0
  41. package/dist/components/tree-view/TreeNodeRow.cjs +70 -30
  42. package/dist/components/tree-view/TreeNodeRow.d.ts +6 -1
  43. package/dist/components/tree-view/TreeNodeRow.js +70 -30
  44. package/dist/components/tree-view/TreeView.cjs +107 -19
  45. package/dist/components/tree-view/TreeView.d.ts +1 -1
  46. package/dist/components/tree-view/TreeView.js +107 -19
  47. package/dist/components/tree-view/TreeView.module.css +47 -3
  48. package/dist/components/tree-view/types.d.ts +6 -0
  49. package/dist/index.cjs +213 -208
  50. package/dist/index.css +2 -0
  51. package/dist/index.d.ts +2 -0
  52. package/dist/index.js +1 -0
  53. package/dist/styles/css-helper-classes/typography.css +4 -0
  54. 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, useEffect, useLayoutEffect } from 'react';
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: `${styles__default.default.links} hideScrollBar`, children: /* @__PURE__ */ jsxRuntime.jsx(SidebarItems.SidebarItems, { activeLink }) })
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: `${styles.links} hideScrollBar`, children: /* @__PURE__ */ jsx(SidebarItems, { activeLink }) })
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
- const maxPrimary2 = Math.max(minPrimarySize, total - minSecondarySize);
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
- setMaxPrimary(computeClamp().maxPrimary);
167
- }, [computeClamp]);
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(): JSX.Element;
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
- const maxPrimary2 = Math.max(minPrimarySize, total - minSecondarySize);
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
- setMaxPrimary(computeClamp().maxPrimary);
161
- }, [computeClamp]);
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("div", { className: `${styles__default.default.tabs} ${styles__default.default[variant]} ${panelStyle ? styles__default.default.panelStyle : ""}`, children: [
152
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.tabList, children: [
153
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.tabStrip, children: [
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
- className: onAddTab ? styles__default.default.tabButtons : `${styles__default.default.tabButtons} ${styles__default.default.tabButtonsEnd}`,
158
- role: "tablist",
159
- "aria-label": header != null ? header : "Tabs",
160
- children: visibleTabs.map((tab, index) => {
161
- const selected = index === activeIndex;
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
- onAddTab ? /* @__PURE__ */ jsxRuntime.jsx(
201
- "button",
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
  }