@dbcdk/react-components 0.0.197 → 0.0.199

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 (68) hide show
  1. package/dist/components/json-viewer/JsonViewer.module.css +53 -0
  2. package/dist/components/json-viewer/JsonViewerShell.cjs +147 -143
  3. package/dist/components/json-viewer/JsonViewerShell.js +149 -145
  4. package/dist/components/line-viewer/LineViewer.cjs +15 -21
  5. package/dist/components/line-viewer/LineViewer.d.ts +1 -1
  6. package/dist/components/line-viewer/LineViewer.js +16 -22
  7. package/dist/components/line-viewer/LineViewer.module.css +58 -3
  8. package/dist/components/page-layout/PageLayout.module.css +1 -1
  9. package/dist/components/scroll-fade/ScrollFade.cjs +42 -0
  10. package/dist/components/scroll-fade/ScrollFade.d.ts +18 -0
  11. package/dist/components/scroll-fade/ScrollFade.js +36 -0
  12. package/dist/components/scroll-fade/ScrollFade.module.css +71 -0
  13. package/dist/components/search-box/SearchBox.cjs +39 -35
  14. package/dist/components/search-box/SearchBox.d.ts +2 -0
  15. package/dist/components/search-box/SearchBox.js +39 -35
  16. package/dist/components/table/Table.cjs +52 -23
  17. package/dist/components/table/Table.d.ts +1 -1
  18. package/dist/components/table/Table.js +53 -24
  19. package/dist/components/table/Table.module.css +4 -0
  20. package/dist/components/table/Table.types.d.ts +27 -0
  21. package/dist/components/table/TanstackTable.cjs +63 -106
  22. package/dist/components/table/TanstackTable.d.ts +5 -0
  23. package/dist/components/table/TanstackTable.js +66 -106
  24. package/dist/components/table/columnLayout.utils.cjs +146 -0
  25. package/dist/components/table/columnLayout.utils.d.ts +44 -0
  26. package/dist/components/table/columnLayout.utils.js +141 -0
  27. package/dist/components/table/components/TableHeader.cjs +3 -1
  28. package/dist/components/table/components/TableHeader.d.ts +2 -1
  29. package/dist/components/table/components/TableHeader.js +3 -1
  30. package/dist/components/table/components/TableHeaderCell.cjs +29 -19
  31. package/dist/components/table/components/TableHeaderCell.d.ts +2 -1
  32. package/dist/components/table/components/TableHeaderCell.js +29 -19
  33. package/dist/components/table/hooks/useClientPagination.cjs +66 -0
  34. package/dist/components/table/hooks/useClientPagination.d.ts +32 -0
  35. package/dist/components/table/hooks/useClientPagination.js +64 -0
  36. package/dist/components/table/hooks/useDistributedLayout.cjs +44 -0
  37. package/dist/components/table/hooks/useDistributedLayout.d.ts +16 -0
  38. package/dist/components/table/hooks/useDistributedLayout.js +42 -0
  39. package/dist/components/table/hooks/useElementWidth.cjs +40 -0
  40. package/dist/components/table/hooks/useElementWidth.d.ts +7 -0
  41. package/dist/components/table/hooks/useElementWidth.js +38 -0
  42. package/dist/components/table/hooks/useResizeHeaderExtras.cjs +87 -0
  43. package/dist/components/table/hooks/useResizeHeaderExtras.d.ts +17 -0
  44. package/dist/components/table/hooks/useResizeHeaderExtras.js +62 -0
  45. package/dist/components/table/hooks/useUiSorting.cjs +18 -0
  46. package/dist/components/table/hooks/useUiSorting.d.ts +3 -0
  47. package/dist/components/table/hooks/useUiSorting.js +16 -0
  48. package/dist/components/table/table.utils.cjs +24 -2
  49. package/dist/components/table/table.utils.d.ts +40 -2
  50. package/dist/components/table/table.utils.js +20 -2
  51. package/dist/components/table/tanstackTable.utils.cjs +33 -97
  52. package/dist/components/table/tanstackTable.utils.d.ts +24 -8
  53. package/dist/components/table/tanstackTable.utils.js +34 -99
  54. package/dist/components/xml-viewer/XmlViewer.cjs +15 -21
  55. package/dist/components/xml-viewer/XmlViewer.d.ts +1 -1
  56. package/dist/components/xml-viewer/XmlViewer.js +16 -22
  57. package/dist/components/xml-viewer/XmlViewer.module.css +58 -3
  58. package/dist/hooks/useScrollOverflow.cjs +71 -0
  59. package/dist/hooks/useScrollOverflow.d.ts +23 -0
  60. package/dist/hooks/useScrollOverflow.js +69 -0
  61. package/dist/hooks/useTableSettings.cjs +2 -1
  62. package/dist/hooks/useTableSettings.d.ts +1 -0
  63. package/dist/hooks/useTableSettings.js +2 -1
  64. package/dist/index.css +1 -0
  65. package/dist/utils/refs.utils.cjs +13 -0
  66. package/dist/utils/refs.utils.d.ts +7 -0
  67. package/dist/utils/refs.utils.js +11 -0
  68. package/package.json +1 -1
@@ -6,6 +6,7 @@ var lucideReact = require('lucide-react');
6
6
  var react = require('react');
7
7
  var Menu = require('../../components/menu/Menu');
8
8
  var Popover = require('../../components/popover/Popover');
9
+ var ScrollFade = require('../../components/scroll-fade/ScrollFade');
9
10
  var usePersistentState = require('../../hooks/usePersistentState');
10
11
  var tokenizeXml = require('./tokenizeXml');
11
12
  var styles = require('./XmlViewer.module.css');
@@ -38,7 +39,6 @@ function XmlViewer({
38
39
  borderless = false
39
40
  }) {
40
41
  const tokens = react.useMemo(() => tokenizeXml.tokenizeXml(xml), [xml]);
41
- const codeRef = react.useRef(null);
42
42
  const { value: currentAppearance, setValue: setCurrentAppearance } = usePersistentState.usePersistentState({
43
43
  initialValue: appearance,
44
44
  storageKey: storageKey ? `${storageKey}:appearance` : void 0,
@@ -57,25 +57,16 @@ function XmlViewer({
57
57
  const handleCopy = () => {
58
58
  void clipboard_utils.copyToClipboard(xml);
59
59
  };
60
- const handleDoubleClick = () => {
61
- const el = codeRef.current;
62
- const selection = typeof window !== "undefined" ? window.getSelection() : null;
63
- if (!el || !selection) return;
64
- const range = document.createRange();
65
- range.selectNodeContents(el);
66
- selection.removeAllRanges();
67
- selection.addRange(range);
68
- };
69
60
  return /* @__PURE__ */ jsxRuntime.jsxs(
70
61
  "section",
71
62
  {
72
63
  className: [styles__default.default.viewer, borderless ? styles__default.default.borderless : ""].filter(Boolean).join(" "),
73
64
  "data-appearance": currentAppearance,
74
65
  children: [
75
- /* @__PURE__ */ jsxRuntime.jsx(
76
- "div",
66
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.toolbar, children: /* @__PURE__ */ jsxRuntime.jsx(
67
+ "span",
77
68
  {
78
- className: styles__default.default.toolbar,
69
+ className: styles__default.default.toolbarButton,
79
70
  "data-surface": currentAppearance === "dark" ? "inverse" : void 0,
80
71
  children: /* @__PURE__ */ jsxRuntime.jsx(
81
72
  Popover.Popover,
@@ -156,10 +147,11 @@ function XmlViewer({
156
147
  }
157
148
  )
158
149
  }
159
- ),
160
- /* @__PURE__ */ jsxRuntime.jsx(
150
+ ) }),
151
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollFade.ScrollFade, { children: (scrollRef) => /* @__PURE__ */ jsxRuntime.jsxs(
161
152
  "pre",
162
153
  {
154
+ ref: scrollRef,
163
155
  className: [
164
156
  styles__default.default.codePane,
165
157
  styles__default.default[size],
@@ -167,13 +159,15 @@ function XmlViewer({
167
159
  deleted ? styles__default.default.deleted : ""
168
160
  ].filter(Boolean).join(" "),
169
161
  tabIndex: 0,
170
- onDoubleClick: handleDoubleClick,
171
- children: /* @__PURE__ */ jsxRuntime.jsx("code", { ref: codeRef, children: viewMode === "raw" ? xml : tokens.map((token, index) => {
172
- const tokenClassName = TOKEN_CLASS[token.type];
173
- return tokenClassName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: tokenClassName, children: token.value }, index) : token.value;
174
- }) })
162
+ children: [
163
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.toolbarSpacer, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Button.Button, { variant: "inline", tabIndex: -1, children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { customIcon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings2, {}) }) }) }),
164
+ /* @__PURE__ */ jsxRuntime.jsx("code", { children: viewMode === "raw" ? xml : tokens.map((token, index) => {
165
+ const tokenClassName = TOKEN_CLASS[token.type];
166
+ return tokenClassName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: tokenClassName, children: token.value }, index) : token.value;
167
+ }) })
168
+ ]
175
169
  }
176
- )
170
+ ) })
177
171
  ]
178
172
  }
179
173
  );
@@ -16,7 +16,7 @@ export interface XmlViewerProps {
16
16
  */
17
17
  storageKey?: string;
18
18
  /**
19
- * Removes the outer border, shadow and corner radius, so the viewer sits
19
+ * Removes the outer border, shadow, corner radius and padding, so the viewer sits
20
20
  * flush in a container that already provides its own framing (e.g. a
21
21
  * modal).
22
22
  */
@@ -1,9 +1,10 @@
1
1
  'use client';
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { TextWrap, ListTree, Code2, Sun, Moon, ClipboardCopy, Settings2 } from 'lucide-react';
4
- import { useMemo, useRef } from 'react';
4
+ import { useMemo } from 'react';
5
5
  import { Menu } from '../../components/menu/Menu';
6
6
  import { Popover } from '../../components/popover/Popover';
7
+ import { ScrollFade } from '../../components/scroll-fade/ScrollFade';
7
8
  import { usePersistentState } from '../../hooks/usePersistentState';
8
9
  import { tokenizeXml } from './tokenizeXml';
9
10
  import styles from './XmlViewer.module.css';
@@ -32,7 +33,6 @@ function XmlViewer({
32
33
  borderless = false
33
34
  }) {
34
35
  const tokens = useMemo(() => tokenizeXml(xml), [xml]);
35
- const codeRef = useRef(null);
36
36
  const { value: currentAppearance, setValue: setCurrentAppearance } = usePersistentState({
37
37
  initialValue: appearance,
38
38
  storageKey: storageKey ? `${storageKey}:appearance` : void 0,
@@ -51,25 +51,16 @@ function XmlViewer({
51
51
  const handleCopy = () => {
52
52
  void copyToClipboard(xml);
53
53
  };
54
- const handleDoubleClick = () => {
55
- const el = codeRef.current;
56
- const selection = typeof window !== "undefined" ? window.getSelection() : null;
57
- if (!el || !selection) return;
58
- const range = document.createRange();
59
- range.selectNodeContents(el);
60
- selection.removeAllRanges();
61
- selection.addRange(range);
62
- };
63
54
  return /* @__PURE__ */ jsxs(
64
55
  "section",
65
56
  {
66
57
  className: [styles.viewer, borderless ? styles.borderless : ""].filter(Boolean).join(" "),
67
58
  "data-appearance": currentAppearance,
68
59
  children: [
69
- /* @__PURE__ */ jsx(
70
- "div",
60
+ /* @__PURE__ */ jsx("div", { className: styles.toolbar, children: /* @__PURE__ */ jsx(
61
+ "span",
71
62
  {
72
- className: styles.toolbar,
63
+ className: styles.toolbarButton,
73
64
  "data-surface": currentAppearance === "dark" ? "inverse" : void 0,
74
65
  children: /* @__PURE__ */ jsx(
75
66
  Popover,
@@ -150,10 +141,11 @@ function XmlViewer({
150
141
  }
151
142
  )
152
143
  }
153
- ),
154
- /* @__PURE__ */ jsx(
144
+ ) }),
145
+ /* @__PURE__ */ jsx(ScrollFade, { children: (scrollRef) => /* @__PURE__ */ jsxs(
155
146
  "pre",
156
147
  {
148
+ ref: scrollRef,
157
149
  className: [
158
150
  styles.codePane,
159
151
  styles[size],
@@ -161,13 +153,15 @@ function XmlViewer({
161
153
  deleted ? styles.deleted : ""
162
154
  ].filter(Boolean).join(" "),
163
155
  tabIndex: 0,
164
- onDoubleClick: handleDoubleClick,
165
- children: /* @__PURE__ */ jsx("code", { ref: codeRef, children: viewMode === "raw" ? xml : tokens.map((token, index) => {
166
- const tokenClassName = TOKEN_CLASS[token.type];
167
- return tokenClassName ? /* @__PURE__ */ jsx("span", { className: tokenClassName, children: token.value }, index) : token.value;
168
- }) })
156
+ children: [
157
+ /* @__PURE__ */ jsx("span", { className: styles.toolbarSpacer, "aria-hidden": "true", children: /* @__PURE__ */ jsx(Button, { variant: "inline", tabIndex: -1, children: /* @__PURE__ */ jsx(Icon, { customIcon: /* @__PURE__ */ jsx(Settings2, {}) }) }) }),
158
+ /* @__PURE__ */ jsx("code", { children: viewMode === "raw" ? xml : tokens.map((token, index) => {
159
+ const tokenClassName = TOKEN_CLASS[token.type];
160
+ return tokenClassName ? /* @__PURE__ */ jsx("span", { className: tokenClassName, children: token.value }, index) : token.value;
161
+ }) })
162
+ ]
169
163
  }
170
- )
164
+ ) })
171
165
  ]
172
166
  }
173
167
  );
@@ -2,6 +2,7 @@
2
2
  --xml-pane-bg: var(--color-bg-inverse);
3
3
  --xml-pane-border: color-mix(in oklab, var(--color-fg-inverse) 12%, transparent);
4
4
  --xml-pane-text: var(--color-fg-inverse);
5
+ --scroll-fade-color: var(--xml-pane-bg);
5
6
 
6
7
  --xml-tag: color-mix(in oklab, var(--color-fg-inverse) 66%, var(--color-syntax-accent) 34%);
7
8
  --xml-attr-name: color-mix(in oklab, var(--color-fg-inverse) 50%, var(--color-syntax-accent) 50%);
@@ -14,6 +15,10 @@
14
15
  --xml-punctuation: color-mix(in oklab, var(--color-fg-inverse) 60%, transparent);
15
16
 
16
17
  position: relative;
18
+ display: flex;
19
+ flex-direction: column;
20
+ /* In a parent with a definite height, scroll inside instead of overflowing it. */
21
+ max-height: 100%;
17
22
  background: var(--xml-pane-bg);
18
23
  border: var(--border-width-thin) solid var(--xml-pane-border);
19
24
  border-radius: var(--border-radius-default);
@@ -41,11 +46,61 @@
41
46
  box-shadow: none;
42
47
  }
43
48
 
49
+ .borderless .codePane {
50
+ padding: 0;
51
+ }
52
+
53
+ /* Zero-height sticky row: sticks within the nearest scrolling ancestor, which may be outside the viewer. */
44
54
  .toolbar {
45
- position: absolute;
46
- top: var(--spacing-xs);
47
- right: var(--spacing-xs);
55
+ position: sticky;
56
+ top: 0;
48
57
  z-index: 1;
58
+ display: flex;
59
+ justify-content: flex-end;
60
+ flex: none;
61
+ height: 0;
62
+ }
63
+
64
+ .toolbar,
65
+ .toolbarSpacer {
66
+ font-size: var(--font-size-md);
67
+ line-height: normal;
68
+ white-space: normal;
69
+ }
70
+
71
+ .toolbarButton {
72
+ display: block;
73
+ margin: var(--spacing-xs) var(--spacing-xs) 0 0;
74
+ border-radius: var(--border-radius-default);
75
+ /* Opaque so scrolled text doesn't show through once it's stuck. */
76
+ background: var(--xml-pane-bg);
77
+ }
78
+
79
+ .toolbarSpacer {
80
+ float: right;
81
+ visibility: hidden;
82
+ margin-block-start: calc(var(--spacing-xs) - var(--spacing-sm));
83
+ margin-inline: var(--spacing-xs) calc(var(--spacing-xs) - var(--spacing-sm));
84
+ }
85
+
86
+ .borderless .toolbarSpacer {
87
+ margin: 0;
88
+ padding: var(--spacing-xs) var(--spacing-xs) 0;
89
+ }
90
+
91
+ /* While the pane scrolls vertically, keep the button clear of its scrollbar
92
+ (overlay scrollbars take no space, so nothing else moves it). */
93
+ .viewer:has([data-scrollable-y='true']) .toolbarButton {
94
+ margin-inline-end: var(--spacing-md);
95
+ }
96
+
97
+ .viewer:has([data-scrollable-y='true']) .toolbarSpacer {
98
+ margin-inline-end: calc(var(--spacing-md) - var(--spacing-sm));
99
+ }
100
+
101
+ .viewer.borderless:has([data-scrollable-y='true']) .toolbarSpacer {
102
+ margin-inline-end: 0;
103
+ padding-inline-end: var(--spacing-md);
49
104
  }
50
105
 
51
106
  .codePane {
@@ -0,0 +1,71 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ var react = require('react');
5
+
6
+ const NONE = {
7
+ top: false,
8
+ bottom: false,
9
+ left: false,
10
+ right: false,
11
+ scrollbarWidth: 0,
12
+ scrollbarHeight: 0
13
+ };
14
+ const THRESHOLD_PX = 1;
15
+ function measureScrollbars(el) {
16
+ const style = getComputedStyle(el);
17
+ const borderX = parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth) || 0;
18
+ const borderY = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth) || 0;
19
+ return {
20
+ scrollbarWidth: Math.max(0, el.offsetWidth - el.clientWidth - borderX),
21
+ scrollbarHeight: Math.max(0, el.offsetHeight - el.clientHeight - borderY)
22
+ };
23
+ }
24
+ function measure(el, scrollbars) {
25
+ const { scrollTop, scrollLeft, scrollHeight, scrollWidth, clientHeight, clientWidth } = el;
26
+ return {
27
+ top: scrollTop > THRESHOLD_PX,
28
+ bottom: scrollHeight - clientHeight - scrollTop > THRESHOLD_PX,
29
+ left: scrollLeft > THRESHOLD_PX,
30
+ right: scrollWidth - clientWidth - scrollLeft > THRESHOLD_PX,
31
+ ...scrollbars
32
+ };
33
+ }
34
+ function sameOverflow(a, b) {
35
+ return Object.keys(a).every((key) => a[key] === b[key]);
36
+ }
37
+ function useScrollOverflow(el) {
38
+ const [overflow, setOverflow] = react.useState(NONE);
39
+ react.useLayoutEffect(() => {
40
+ if (!el) return;
41
+ let scrollbars = measureScrollbars(el);
42
+ const update = () => {
43
+ const next = measure(el, scrollbars);
44
+ setOverflow((prev) => sameOverflow(prev, next) ? prev : next);
45
+ };
46
+ const updateLayout = () => {
47
+ scrollbars = measureScrollbars(el);
48
+ update();
49
+ };
50
+ update();
51
+ el.addEventListener("scroll", update, { passive: true });
52
+ const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(updateLayout) : null;
53
+ resizeObserver == null ? void 0 : resizeObserver.observe(el);
54
+ const mutationObserver = typeof MutationObserver !== "undefined" ? new MutationObserver(updateLayout) : null;
55
+ mutationObserver == null ? void 0 : mutationObserver.observe(el, {
56
+ subtree: true,
57
+ childList: true,
58
+ characterData: true,
59
+ attributes: true,
60
+ attributeFilter: ["class", "style"]
61
+ });
62
+ return () => {
63
+ el.removeEventListener("scroll", update);
64
+ resizeObserver == null ? void 0 : resizeObserver.disconnect();
65
+ mutationObserver == null ? void 0 : mutationObserver.disconnect();
66
+ };
67
+ }, [el]);
68
+ return el ? overflow : NONE;
69
+ }
70
+
71
+ exports.useScrollOverflow = useScrollOverflow;
@@ -0,0 +1,23 @@
1
+ /** Which edges of a scroll container have more content beyond them. */
2
+ export type ScrollOverflow = {
3
+ top: boolean;
4
+ bottom: boolean;
5
+ left: boolean;
6
+ right: boolean;
7
+ /**
8
+ * Space taken by classic (non-overlay) scrollbars, in pixels: the vertical
9
+ * scrollbar's width and the horizontal one's height. Lets edge hints stay
10
+ * clear of the scrollbars. 0 for overlay scrollbars.
11
+ */
12
+ scrollbarWidth: number;
13
+ scrollbarHeight: number;
14
+ };
15
+ /**
16
+ * Tracks which edges of the scroll container `el` hide more content, so the
17
+ * caller can hint at it (e.g. with edge fades) without restyling the native
18
+ * scrollbars. Updates on scroll, on resize and when the content changes.
19
+ * Takes the element rather than a ref so it follows the element when it's
20
+ * replaced; keep it in state via a callback ref. All edges are `false` on the
21
+ * server and until the first client measurement.
22
+ */
23
+ export declare function useScrollOverflow(el: HTMLElement | null): ScrollOverflow;
@@ -0,0 +1,69 @@
1
+ 'use client';
2
+ import { useState, useLayoutEffect } from 'react';
3
+
4
+ const NONE = {
5
+ top: false,
6
+ bottom: false,
7
+ left: false,
8
+ right: false,
9
+ scrollbarWidth: 0,
10
+ scrollbarHeight: 0
11
+ };
12
+ const THRESHOLD_PX = 1;
13
+ function measureScrollbars(el) {
14
+ const style = getComputedStyle(el);
15
+ const borderX = parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth) || 0;
16
+ const borderY = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth) || 0;
17
+ return {
18
+ scrollbarWidth: Math.max(0, el.offsetWidth - el.clientWidth - borderX),
19
+ scrollbarHeight: Math.max(0, el.offsetHeight - el.clientHeight - borderY)
20
+ };
21
+ }
22
+ function measure(el, scrollbars) {
23
+ const { scrollTop, scrollLeft, scrollHeight, scrollWidth, clientHeight, clientWidth } = el;
24
+ return {
25
+ top: scrollTop > THRESHOLD_PX,
26
+ bottom: scrollHeight - clientHeight - scrollTop > THRESHOLD_PX,
27
+ left: scrollLeft > THRESHOLD_PX,
28
+ right: scrollWidth - clientWidth - scrollLeft > THRESHOLD_PX,
29
+ ...scrollbars
30
+ };
31
+ }
32
+ function sameOverflow(a, b) {
33
+ return Object.keys(a).every((key) => a[key] === b[key]);
34
+ }
35
+ function useScrollOverflow(el) {
36
+ const [overflow, setOverflow] = useState(NONE);
37
+ useLayoutEffect(() => {
38
+ if (!el) return;
39
+ let scrollbars = measureScrollbars(el);
40
+ const update = () => {
41
+ const next = measure(el, scrollbars);
42
+ setOverflow((prev) => sameOverflow(prev, next) ? prev : next);
43
+ };
44
+ const updateLayout = () => {
45
+ scrollbars = measureScrollbars(el);
46
+ update();
47
+ };
48
+ update();
49
+ el.addEventListener("scroll", update, { passive: true });
50
+ const resizeObserver = typeof ResizeObserver !== "undefined" ? new ResizeObserver(updateLayout) : null;
51
+ resizeObserver == null ? void 0 : resizeObserver.observe(el);
52
+ const mutationObserver = typeof MutationObserver !== "undefined" ? new MutationObserver(updateLayout) : null;
53
+ mutationObserver == null ? void 0 : mutationObserver.observe(el, {
54
+ subtree: true,
55
+ childList: true,
56
+ characterData: true,
57
+ attributes: true,
58
+ attributeFilter: ["class", "style"]
59
+ });
60
+ return () => {
61
+ el.removeEventListener("scroll", update);
62
+ resizeObserver == null ? void 0 : resizeObserver.disconnect();
63
+ mutationObserver == null ? void 0 : mutationObserver.disconnect();
64
+ };
65
+ }, [el]);
66
+ return el ? overflow : NONE;
67
+ }
68
+
69
+ export { useScrollOverflow };
@@ -2,6 +2,7 @@
2
2
  'use strict';
3
3
 
4
4
  var react = require('react');
5
+ var table_utils = require('../components/table/table.utils');
5
6
  var tableSettings_utils = require('../components/table/tableSettings.utils');
6
7
  var localStorage_utils = require('../utils/localStorage.utils');
7
8
 
@@ -27,7 +28,7 @@ const localStorageTableSettingsStorage = {
27
28
  function useTableSettings({
28
29
  storageKey,
29
30
  tableColumns,
30
- defaultViewMode = "compact",
31
+ defaultViewMode = table_utils.DEFAULT_VIEW_MODE,
31
32
  defaultVisibleColumnIds,
32
33
  defaultStriped = false,
33
34
  storage = localStorageTableSettingsStorage
@@ -13,6 +13,7 @@ export declare const localStorageTableSettingsStorage: TableSettingsStorage;
13
13
  export interface UseTableSettingsOptions<T = unknown> {
14
14
  storageKey: string;
15
15
  tableColumns?: ReadonlyArray<ColumnItem<T> | TableSettingsColumn>;
16
+ /** View mode until the user picks one. Defaults to `'wrapped'`; pass `'compact'` for even row heights. */
16
17
  defaultViewMode?: ViewMode;
17
18
  defaultVisibleColumnIds?: string[];
18
19
  defaultStriped?: boolean;
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
  import { useMemo, useState, useEffect, useCallback } from 'react';
3
+ import { DEFAULT_VIEW_MODE } from '../components/table/table.utils';
3
4
  import { isSettingsColumnHidden, getSettingsColumnId } from '../components/table/tableSettings.utils';
4
5
  import { writeLocalStorage, readLocalStorage } from '../utils/localStorage.utils';
5
6
 
@@ -25,7 +26,7 @@ const localStorageTableSettingsStorage = {
25
26
  function useTableSettings({
26
27
  storageKey,
27
28
  tableColumns,
28
- defaultViewMode = "compact",
29
+ defaultViewMode = DEFAULT_VIEW_MODE,
29
30
  defaultVisibleColumnIds,
30
31
  defaultStriped = false,
31
32
  storage = localStorageTableSettingsStorage
package/dist/index.css CHANGED
@@ -56,6 +56,7 @@
56
56
  @import './components/pagination/Pagination.module.css';
57
57
  @import './components/panel/Panel.module.css';
58
58
  @import './components/popover/Popover.module.css';
59
+ @import './components/scroll-fade/ScrollFade.module.css';
59
60
  @import './components/search-box/SearchBox.module.css';
60
61
  @import './components/section-label/SectionLabel.module.css';
61
62
  @import './components/segmented-progress-bar/SegmentedProgressBar.module.css';
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ function mergeRefs(...refs) {
4
+ return (node) => {
5
+ for (const ref of refs) {
6
+ if (!ref) continue;
7
+ if (typeof ref === "function") ref(node);
8
+ else ref.current = node;
9
+ }
10
+ };
11
+ }
12
+
13
+ exports.mergeRefs = mergeRefs;
@@ -0,0 +1,7 @@
1
+ import type { Ref } from 'react';
2
+ /**
3
+ * Combines refs into one callback ref. Returns a new function on every call,
4
+ * so memoize it (e.g. with `useMemo`) when a stable ref matters, such as when
5
+ * one of the refs sets state.
6
+ */
7
+ export declare function mergeRefs<T>(...refs: Array<Ref<T> | undefined>): (node: T | null) => void;
@@ -0,0 +1,11 @@
1
+ function mergeRefs(...refs) {
2
+ return (node) => {
3
+ for (const ref of refs) {
4
+ if (!ref) continue;
5
+ if (typeof ref === "function") ref(node);
6
+ else ref.current = node;
7
+ }
8
+ };
9
+ }
10
+
11
+ export { mergeRefs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dbcdk/react-components",
3
- "version": "0.0.197",
3
+ "version": "0.0.199",
4
4
  "description": "Reusable React components for DBC projects",
5
5
  "license": "ISC",
6
6
  "author": "",