@dbcdk/react-components 0.0.194 → 0.0.196

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 (114) hide show
  1. package/README.md +78 -10
  2. package/dist/client.cjs +486 -614
  3. package/dist/client.d.ts +176 -102
  4. package/dist/client.js +102 -102
  5. package/dist/components/color-scheme-button/ColorSchemeButton.cjs +7 -4
  6. package/dist/components/color-scheme-button/ColorSchemeButton.d.ts +7 -3
  7. package/dist/components/color-scheme-button/ColorSchemeButton.js +7 -4
  8. package/dist/components/forms/text-area/Textarea.cjs +2 -1
  9. package/dist/components/forms/text-area/Textarea.d.ts +1 -0
  10. package/dist/components/forms/text-area/Textarea.js +2 -1
  11. package/dist/components/highlighted-text/HighlightedText.cjs +6 -3
  12. package/dist/components/highlighted-text/HighlightedText.js +7 -4
  13. package/dist/components/json-viewer/JsonNode.cjs +27 -67
  14. package/dist/components/json-viewer/JsonNode.d.ts +10 -0
  15. package/dist/components/json-viewer/JsonNode.js +28 -68
  16. package/dist/components/json-viewer/JsonRow.cjs +85 -0
  17. package/dist/components/json-viewer/JsonRow.d.ts +5 -0
  18. package/dist/components/json-viewer/JsonRow.js +79 -0
  19. package/dist/components/json-viewer/JsonViewer.cjs +36 -256
  20. package/dist/components/json-viewer/JsonViewer.js +37 -253
  21. package/dist/components/json-viewer/JsonViewerShell.cjs +208 -0
  22. package/dist/components/json-viewer/JsonViewerShell.d.ts +25 -0
  23. package/dist/components/json-viewer/JsonViewerShell.js +202 -0
  24. package/dist/components/json-viewer/TanstackJsonViewer.cjs +127 -0
  25. package/dist/components/json-viewer/TanstackJsonViewer.d.ts +17 -0
  26. package/dist/components/json-viewer/TanstackJsonViewer.js +121 -0
  27. package/dist/components/json-viewer/types.d.ts +27 -0
  28. package/dist/components/json-viewer/useJsonViewerState.cjs +111 -0
  29. package/dist/components/json-viewer/useJsonViewerState.d.ts +42 -0
  30. package/dist/components/json-viewer/useJsonViewerState.js +108 -0
  31. package/dist/components/json-viewer/utils.cjs +36 -0
  32. package/dist/components/json-viewer/utils.d.ts +21 -1
  33. package/dist/components/json-viewer/utils.js +35 -1
  34. package/dist/components/lightbox/Lightbox.cjs +2 -2
  35. package/dist/components/lightbox/Lightbox.d.ts +1 -1
  36. package/dist/components/lightbox/Lightbox.js +1 -1
  37. package/dist/components/line-viewer/LineViewer.cjs +2 -3
  38. package/dist/components/line-viewer/LineViewer.js +2 -3
  39. package/dist/components/line-viewer/tokenizeLineFormat.cjs +37 -17
  40. package/dist/components/line-viewer/tokenizeLineFormat.d.ts +5 -4
  41. package/dist/components/line-viewer/tokenizeLineFormat.js +37 -17
  42. package/dist/components/menu/Menu.cjs +3 -23
  43. package/dist/components/menu/Menu.js +3 -23
  44. package/dist/components/menu/Menu.module.css +4 -3
  45. package/dist/components/metric-tile/MetricTile.cjs +3 -2
  46. package/dist/components/metric-tile/MetricTile.js +2 -1
  47. package/dist/components/overlay/tooltip/Tooltip.cjs +7 -2
  48. package/dist/components/overlay/tooltip/Tooltip.d.ts +7 -1
  49. package/dist/components/overlay/tooltip/Tooltip.js +7 -2
  50. package/dist/components/overlay/tooltip/useTooltipTrigger.cjs +7 -1
  51. package/dist/components/overlay/tooltip/useTooltipTrigger.js +7 -1
  52. package/dist/components/page-layout/PageLayout.module.css +1 -1
  53. package/dist/components/table/Table.cjs +45 -16
  54. package/dist/components/table/Table.d.ts +1 -1
  55. package/dist/components/table/Table.js +47 -18
  56. package/dist/components/table/Table.module.css +135 -7
  57. package/dist/components/table/Table.types.d.ts +47 -1
  58. package/dist/components/table/TanstackTable.cjs +30 -2
  59. package/dist/components/table/TanstackTable.js +31 -3
  60. package/dist/components/table/components/TableBody.d.ts +1 -2
  61. package/dist/components/table/components/TableHeader.cjs +6 -4
  62. package/dist/components/table/components/TableHeader.d.ts +2 -1
  63. package/dist/components/table/components/TableHeader.js +6 -4
  64. package/dist/components/table/components/TableHeaderCell.cjs +5 -4
  65. package/dist/components/table/components/TableHeaderCell.d.ts +3 -1
  66. package/dist/components/table/components/TableHeaderCell.js +5 -4
  67. package/dist/components/table/components/TableRow.cjs +1 -1
  68. package/dist/components/table/components/TableRow.d.ts +1 -2
  69. package/dist/components/table/components/TableRow.js +1 -1
  70. package/dist/components/table/components/TableSkeletonBody.cjs +30 -0
  71. package/dist/components/table/components/TableSkeletonBody.d.ts +13 -0
  72. package/dist/components/table/components/TableSkeletonBody.js +24 -0
  73. package/dist/components/table/components/table-settings/TableHeaderSettings.cjs +28 -0
  74. package/dist/components/table/components/table-settings/TableHeaderSettings.d.ts +11 -0
  75. package/dist/components/table/components/table-settings/TableHeaderSettings.js +26 -0
  76. package/dist/components/table/components/table-settings/TableSettings.cjs +82 -32
  77. package/dist/components/table/components/table-settings/TableSettings.d.ts +14 -6
  78. package/dist/components/table/components/table-settings/TableSettings.js +84 -34
  79. package/dist/components/table/table.utils.cjs +2 -0
  80. package/dist/components/table/table.utils.d.ts +6 -0
  81. package/dist/components/table/table.utils.js +2 -1
  82. package/dist/components/table/tableSettings.utils.cjs +29 -0
  83. package/dist/components/table/tableSettings.utils.d.ts +9 -0
  84. package/dist/components/table/tableSettings.utils.js +24 -0
  85. package/dist/components/table/tanstackTable.utils.cjs +18 -0
  86. package/dist/components/table/tanstackTable.utils.js +19 -1
  87. package/dist/components/theme-button/ThemeButton.cjs +9 -4
  88. package/dist/components/theme-button/ThemeButton.d.ts +4 -2
  89. package/dist/components/theme-button/ThemeButton.js +9 -4
  90. package/dist/components/theme-script/ThemeScript.cjs +10 -4
  91. package/dist/components/theme-script/ThemeScript.d.ts +9 -1
  92. package/dist/components/theme-script/ThemeScript.js +10 -4
  93. package/dist/components/xml-viewer/XmlViewer.cjs +2 -3
  94. package/dist/components/xml-viewer/XmlViewer.js +2 -3
  95. package/dist/hooks/useColorScheme.cjs +18 -14
  96. package/dist/hooks/useColorScheme.d.ts +11 -1
  97. package/dist/hooks/useColorScheme.js +19 -15
  98. package/dist/hooks/useGetActiveTheme.cjs +4 -3
  99. package/dist/hooks/useGetActiveTheme.d.ts +7 -1
  100. package/dist/hooks/useGetActiveTheme.js +4 -3
  101. package/dist/hooks/useTableData.cjs +11 -7
  102. package/dist/hooks/useTableData.d.ts +8 -2
  103. package/dist/hooks/useTableData.js +11 -7
  104. package/dist/hooks/useTableSettings.cjs +25 -9
  105. package/dist/hooks/useTableSettings.d.ts +9 -6
  106. package/dist/hooks/useTableSettings.js +25 -9
  107. package/dist/hooks/useTheme.d.ts +6 -0
  108. package/dist/styles/styles.css +7 -3
  109. package/dist/styles/themes/dbc/colors.css +1 -1
  110. package/dist/styles.css +1 -476
  111. package/dist/tanstack-virtual.cjs +12 -0
  112. package/dist/tanstack-virtual.d.ts +1 -0
  113. package/dist/tanstack-virtual.js +1 -0
  114. package/package.json +13 -1
@@ -0,0 +1,208 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var lucideReact = require('lucide-react');
6
+ var Menu = require('../../components/menu/Menu');
7
+ var Popover = require('../../components/popover/Popover');
8
+ var styles = require('./JsonViewer.module.css');
9
+ var Button = require('../button/Button');
10
+ var Icon = require('../icon/Icon');
11
+
12
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
13
+
14
+ var styles__default = /*#__PURE__*/_interopDefault(styles);
15
+
16
+ function JsonViewerShell({
17
+ state,
18
+ helperText,
19
+ searchPlaceholder,
20
+ emptySearchText,
21
+ className,
22
+ maxHeight,
23
+ borderless,
24
+ deleted = false,
25
+ children,
26
+ treePaneRef
27
+ }) {
28
+ const {
29
+ queryInput,
30
+ setQueryInput,
31
+ setQuery,
32
+ normalizedQuery,
33
+ inputId,
34
+ currentAppearance,
35
+ handleToggleAppearance,
36
+ viewMode,
37
+ setViewMode,
38
+ matches,
39
+ hasResults,
40
+ rawJson,
41
+ handleCopyAll,
42
+ handleExpandAll,
43
+ handleCollapseAll
44
+ } = state;
45
+ return /* @__PURE__ */ jsxRuntime.jsxs(
46
+ "section",
47
+ {
48
+ className: [styles__default.default.viewer, borderless ? styles__default.default.borderless : "", className].filter(Boolean).join(" "),
49
+ "data-appearance": currentAppearance,
50
+ children: [
51
+ /* @__PURE__ */ jsxRuntime.jsxs(
52
+ "div",
53
+ {
54
+ className: styles__default.default.toolbar,
55
+ "data-surface": currentAppearance === "dark" ? "inverse" : void 0,
56
+ children: [
57
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.toolbarTop, children: [
58
+ viewMode === "tree" ? /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: styles__default.default.searchField, children: [
59
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: styles__default.default.searchIcon, "aria-hidden": "true" }),
60
+ /* @__PURE__ */ jsxRuntime.jsx(
61
+ "input",
62
+ {
63
+ id: inputId,
64
+ type: "search",
65
+ value: queryInput,
66
+ onChange: (event) => setQueryInput(event.target.value),
67
+ placeholder: searchPlaceholder,
68
+ className: styles__default.default.searchInput
69
+ }
70
+ ),
71
+ queryInput ? /* @__PURE__ */ jsxRuntime.jsx(
72
+ "button",
73
+ {
74
+ type: "button",
75
+ className: styles__default.default.clearButton,
76
+ "aria-label": "Ryd s\xF8gning",
77
+ onClick: () => {
78
+ setQueryInput("");
79
+ setQuery("");
80
+ },
81
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { "aria-hidden": "true" })
82
+ }
83
+ ) : null
84
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
85
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.actions, children: /* @__PURE__ */ jsxRuntime.jsx(
86
+ Popover.Popover,
87
+ {
88
+ matchTriggerWidth: false,
89
+ minWidth: "200px",
90
+ trigger: (toggle, _icon, isOpen) => /* @__PURE__ */ jsxRuntime.jsx(
91
+ Button.Button,
92
+ {
93
+ variant: "inline",
94
+ "aria-label": "Flere handlinger",
95
+ "aria-haspopup": "menu",
96
+ "aria-expanded": isOpen ? true : false,
97
+ onClick: toggle,
98
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { customIcon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings2, { "aria-hidden": "true" }) })
99
+ }
100
+ ),
101
+ children: (close) => /* @__PURE__ */ jsxRuntime.jsxs(Menu.Menu, { children: [
102
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Item, { disabled: viewMode === "raw" || Boolean(normalizedQuery), children: /* @__PURE__ */ jsxRuntime.jsxs(
103
+ "button",
104
+ {
105
+ type: "button",
106
+ onClick: () => {
107
+ handleExpandAll();
108
+ close();
109
+ },
110
+ children: [
111
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { "aria-hidden": "true" }),
112
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Fold alle ud" })
113
+ ]
114
+ }
115
+ ) }),
116
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Item, { disabled: viewMode === "raw" || Boolean(normalizedQuery), children: /* @__PURE__ */ jsxRuntime.jsxs(
117
+ "button",
118
+ {
119
+ type: "button",
120
+ onClick: () => {
121
+ handleCollapseAll();
122
+ close();
123
+ },
124
+ children: [
125
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { "aria-hidden": "true" }),
126
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Fold alle sammen" })
127
+ ]
128
+ }
129
+ ) }),
130
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Separator, {}),
131
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs(
132
+ "button",
133
+ {
134
+ type: "button",
135
+ onClick: () => {
136
+ setViewMode((mode) => mode === "raw" ? "tree" : "raw");
137
+ close();
138
+ },
139
+ children: [
140
+ viewMode === "raw" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListTree, { "aria-hidden": "true" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Braces, { "aria-hidden": "true" }),
141
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: viewMode === "raw" ? "Vis tr\xE6" : "Vis raw" })
142
+ ]
143
+ }
144
+ ) }),
145
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs(
146
+ "button",
147
+ {
148
+ type: "button",
149
+ onClick: () => {
150
+ handleToggleAppearance();
151
+ close();
152
+ },
153
+ children: [
154
+ currentAppearance === "dark" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sun, { "aria-hidden": "true" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Moon, { "aria-hidden": "true" }),
155
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: currentAppearance === "dark" ? "Lys visning" : "M\xF8rk visning" })
156
+ ]
157
+ }
158
+ ) }),
159
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Separator, {}),
160
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs(
161
+ "button",
162
+ {
163
+ type: "button",
164
+ onClick: () => {
165
+ handleCopyAll();
166
+ close();
167
+ },
168
+ children: [
169
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ClipboardCopy, { "aria-hidden": "true" }),
170
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Kopi\xE9r JSON" })
171
+ ]
172
+ }
173
+ ) })
174
+ ] })
175
+ }
176
+ ) })
177
+ ] }),
178
+ helperText || viewMode === "tree" && normalizedQuery ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.metaRow, children: [
179
+ helperText ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.helperText, children: helperText }) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
180
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.statusText, children: viewMode === "tree" && normalizedQuery ? `${matches.size} matchende node${matches.size === 1 ? "" : "r"}` : "" })
181
+ ] }) : null
182
+ ]
183
+ }
184
+ ),
185
+ viewMode === "raw" ? /* @__PURE__ */ jsxRuntime.jsx(
186
+ "pre",
187
+ {
188
+ className: [styles__default.default.rawPane, deleted ? styles__default.default.deleted : ""].filter(Boolean).join(" "),
189
+ style: maxHeight !== void 0 ? { maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight } : void 0,
190
+ children: rawJson
191
+ }
192
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
193
+ "div",
194
+ {
195
+ className: [styles__default.default.treePane, deleted ? styles__default.default.deleted : ""].filter(Boolean).join(" "),
196
+ role: "tree",
197
+ "aria-label": "JSON-visning",
198
+ ref: treePaneRef,
199
+ style: maxHeight !== void 0 ? { maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight } : void 0,
200
+ children: hasResults ? children : /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.emptyState, children: emptySearchText })
201
+ }
202
+ )
203
+ ]
204
+ }
205
+ );
206
+ }
207
+
208
+ exports.JsonViewerShell = JsonViewerShell;
@@ -0,0 +1,25 @@
1
+ import type { JSX, ReactNode, Ref } from 'react';
2
+ import type { JsonViewerState } from './useJsonViewerState';
3
+ export type JsonViewerShellProps = {
4
+ state: JsonViewerState;
5
+ helperText?: string;
6
+ searchPlaceholder: string;
7
+ emptySearchText: string;
8
+ className?: string;
9
+ maxHeight?: number | string;
10
+ borderless: boolean;
11
+ /** Displays all JSON content in the theme's error color, for deleted or invalid content. */
12
+ deleted?: boolean;
13
+ /** The tree renderer (recursive or virtualized) - only shown when there are results. */
14
+ children: ReactNode;
15
+ /** Attached to the scrollable tree pane - lets a virtualized renderer use it as its scroll element. */
16
+ treePaneRef?: Ref<HTMLDivElement>;
17
+ };
18
+ /**
19
+ * Toolbar (search, expand-all/collapse-all/appearance/raw-view menu) plus the
20
+ * raw/tree pane switch, shared by every JsonViewer flavor. The actual tree
21
+ * rendering strategy (recursive `JsonNode`, or a virtualized flat list) is
22
+ * passed in as `children` so this stays dependency-free and reusable from an
23
+ * optional entry point that pulls in extra peer dependencies.
24
+ */
25
+ export declare function JsonViewerShell({ state, helperText, searchPlaceholder, emptySearchText, className, maxHeight, borderless, deleted, children, treePaneRef, }: JsonViewerShellProps): JSX.Element;
@@ -0,0 +1,202 @@
1
+ 'use client';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { Search, X, ArrowDown, ArrowUp, ListTree, Braces, Sun, Moon, ClipboardCopy, Settings2 } from 'lucide-react';
4
+ import { Menu } from '../../components/menu/Menu';
5
+ import { Popover } from '../../components/popover/Popover';
6
+ import styles from './JsonViewer.module.css';
7
+ import { Button } from '../button/Button';
8
+ import { Icon } from '../icon/Icon';
9
+
10
+ function JsonViewerShell({
11
+ state,
12
+ helperText,
13
+ searchPlaceholder,
14
+ emptySearchText,
15
+ className,
16
+ maxHeight,
17
+ borderless,
18
+ deleted = false,
19
+ children,
20
+ treePaneRef
21
+ }) {
22
+ const {
23
+ queryInput,
24
+ setQueryInput,
25
+ setQuery,
26
+ normalizedQuery,
27
+ inputId,
28
+ currentAppearance,
29
+ handleToggleAppearance,
30
+ viewMode,
31
+ setViewMode,
32
+ matches,
33
+ hasResults,
34
+ rawJson,
35
+ handleCopyAll,
36
+ handleExpandAll,
37
+ handleCollapseAll
38
+ } = state;
39
+ return /* @__PURE__ */ jsxs(
40
+ "section",
41
+ {
42
+ className: [styles.viewer, borderless ? styles.borderless : "", className].filter(Boolean).join(" "),
43
+ "data-appearance": currentAppearance,
44
+ children: [
45
+ /* @__PURE__ */ jsxs(
46
+ "div",
47
+ {
48
+ className: styles.toolbar,
49
+ "data-surface": currentAppearance === "dark" ? "inverse" : void 0,
50
+ children: [
51
+ /* @__PURE__ */ jsxs("div", { className: styles.toolbarTop, children: [
52
+ viewMode === "tree" ? /* @__PURE__ */ jsxs("label", { htmlFor: inputId, className: styles.searchField, children: [
53
+ /* @__PURE__ */ jsx(Search, { className: styles.searchIcon, "aria-hidden": "true" }),
54
+ /* @__PURE__ */ jsx(
55
+ "input",
56
+ {
57
+ id: inputId,
58
+ type: "search",
59
+ value: queryInput,
60
+ onChange: (event) => setQueryInput(event.target.value),
61
+ placeholder: searchPlaceholder,
62
+ className: styles.searchInput
63
+ }
64
+ ),
65
+ queryInput ? /* @__PURE__ */ jsx(
66
+ "button",
67
+ {
68
+ type: "button",
69
+ className: styles.clearButton,
70
+ "aria-label": "Ryd s\xF8gning",
71
+ onClick: () => {
72
+ setQueryInput("");
73
+ setQuery("");
74
+ },
75
+ children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true" })
76
+ }
77
+ ) : null
78
+ ] }) : /* @__PURE__ */ jsx("span", {}),
79
+ /* @__PURE__ */ jsx("div", { className: styles.actions, children: /* @__PURE__ */ jsx(
80
+ Popover,
81
+ {
82
+ matchTriggerWidth: false,
83
+ minWidth: "200px",
84
+ trigger: (toggle, _icon, isOpen) => /* @__PURE__ */ jsx(
85
+ Button,
86
+ {
87
+ variant: "inline",
88
+ "aria-label": "Flere handlinger",
89
+ "aria-haspopup": "menu",
90
+ "aria-expanded": isOpen ? true : false,
91
+ onClick: toggle,
92
+ children: /* @__PURE__ */ jsx(Icon, { customIcon: /* @__PURE__ */ jsx(Settings2, { "aria-hidden": "true" }) })
93
+ }
94
+ ),
95
+ children: (close) => /* @__PURE__ */ jsxs(Menu, { children: [
96
+ /* @__PURE__ */ jsx(Menu.Item, { disabled: viewMode === "raw" || Boolean(normalizedQuery), children: /* @__PURE__ */ jsxs(
97
+ "button",
98
+ {
99
+ type: "button",
100
+ onClick: () => {
101
+ handleExpandAll();
102
+ close();
103
+ },
104
+ children: [
105
+ /* @__PURE__ */ jsx(ArrowDown, { "aria-hidden": "true" }),
106
+ /* @__PURE__ */ jsx("span", { children: "Fold alle ud" })
107
+ ]
108
+ }
109
+ ) }),
110
+ /* @__PURE__ */ jsx(Menu.Item, { disabled: viewMode === "raw" || Boolean(normalizedQuery), children: /* @__PURE__ */ jsxs(
111
+ "button",
112
+ {
113
+ type: "button",
114
+ onClick: () => {
115
+ handleCollapseAll();
116
+ close();
117
+ },
118
+ children: [
119
+ /* @__PURE__ */ jsx(ArrowUp, { "aria-hidden": "true" }),
120
+ /* @__PURE__ */ jsx("span", { children: "Fold alle sammen" })
121
+ ]
122
+ }
123
+ ) }),
124
+ /* @__PURE__ */ jsx(Menu.Separator, {}),
125
+ /* @__PURE__ */ jsx(Menu.Item, { children: /* @__PURE__ */ jsxs(
126
+ "button",
127
+ {
128
+ type: "button",
129
+ onClick: () => {
130
+ setViewMode((mode) => mode === "raw" ? "tree" : "raw");
131
+ close();
132
+ },
133
+ children: [
134
+ viewMode === "raw" ? /* @__PURE__ */ jsx(ListTree, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Braces, { "aria-hidden": "true" }),
135
+ /* @__PURE__ */ jsx("span", { children: viewMode === "raw" ? "Vis tr\xE6" : "Vis raw" })
136
+ ]
137
+ }
138
+ ) }),
139
+ /* @__PURE__ */ jsx(Menu.Item, { children: /* @__PURE__ */ jsxs(
140
+ "button",
141
+ {
142
+ type: "button",
143
+ onClick: () => {
144
+ handleToggleAppearance();
145
+ close();
146
+ },
147
+ children: [
148
+ currentAppearance === "dark" ? /* @__PURE__ */ jsx(Sun, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Moon, { "aria-hidden": "true" }),
149
+ /* @__PURE__ */ jsx("span", { children: currentAppearance === "dark" ? "Lys visning" : "M\xF8rk visning" })
150
+ ]
151
+ }
152
+ ) }),
153
+ /* @__PURE__ */ jsx(Menu.Separator, {}),
154
+ /* @__PURE__ */ jsx(Menu.Item, { children: /* @__PURE__ */ jsxs(
155
+ "button",
156
+ {
157
+ type: "button",
158
+ onClick: () => {
159
+ handleCopyAll();
160
+ close();
161
+ },
162
+ children: [
163
+ /* @__PURE__ */ jsx(ClipboardCopy, { "aria-hidden": "true" }),
164
+ /* @__PURE__ */ jsx("span", { children: "Kopi\xE9r JSON" })
165
+ ]
166
+ }
167
+ ) })
168
+ ] })
169
+ }
170
+ ) })
171
+ ] }),
172
+ helperText || viewMode === "tree" && normalizedQuery ? /* @__PURE__ */ jsxs("div", { className: styles.metaRow, children: [
173
+ helperText ? /* @__PURE__ */ jsx("span", { className: styles.helperText, children: helperText }) : /* @__PURE__ */ jsx("span", {}),
174
+ /* @__PURE__ */ jsx("span", { className: styles.statusText, children: viewMode === "tree" && normalizedQuery ? `${matches.size} matchende node${matches.size === 1 ? "" : "r"}` : "" })
175
+ ] }) : null
176
+ ]
177
+ }
178
+ ),
179
+ viewMode === "raw" ? /* @__PURE__ */ jsx(
180
+ "pre",
181
+ {
182
+ className: [styles.rawPane, deleted ? styles.deleted : ""].filter(Boolean).join(" "),
183
+ style: maxHeight !== void 0 ? { maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight } : void 0,
184
+ children: rawJson
185
+ }
186
+ ) : /* @__PURE__ */ jsx(
187
+ "div",
188
+ {
189
+ className: [styles.treePane, deleted ? styles.deleted : ""].filter(Boolean).join(" "),
190
+ role: "tree",
191
+ "aria-label": "JSON-visning",
192
+ ref: treePaneRef,
193
+ style: maxHeight !== void 0 ? { maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight } : void 0,
194
+ children: hasResults ? children : /* @__PURE__ */ jsx("div", { className: styles.emptyState, children: emptySearchText })
195
+ }
196
+ )
197
+ ]
198
+ }
199
+ );
200
+ }
201
+
202
+ export { JsonViewerShell };
@@ -0,0 +1,127 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var reactVirtual = require('@tanstack/react-virtual');
6
+ var react = require('react');
7
+ var JsonRow = require('./JsonRow');
8
+ var styles = require('./JsonViewer.module.css');
9
+ var JsonViewerShell = require('./JsonViewerShell');
10
+ var useJsonViewerState = require('./useJsonViewerState');
11
+ var utils = require('./utils');
12
+
13
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
14
+
15
+ var styles__default = /*#__PURE__*/_interopDefault(styles);
16
+
17
+ const ESTIMATED_ROW_HEIGHT = 32;
18
+ function JsonViewer({
19
+ value,
20
+ defaultExpandedDepth = 2,
21
+ expandAll = false,
22
+ defaultViewMode = "tree",
23
+ searchDebounceMs = 800,
24
+ helperText,
25
+ searchPlaceholder = "S\xF8g i n\xF8gler, stier og v\xE6rdier",
26
+ emptySearchText = "Ingen matchende noder fundet.",
27
+ className,
28
+ maxHeight,
29
+ appearance = "dark",
30
+ deleted = false,
31
+ storageKey,
32
+ borderless = false
33
+ }) {
34
+ const state = useJsonViewerState.useJsonViewerState({
35
+ value,
36
+ defaultExpandedDepth,
37
+ expandAll,
38
+ defaultViewMode,
39
+ searchDebounceMs,
40
+ appearance,
41
+ storageKey
42
+ });
43
+ const treePaneRef = react.useRef(null);
44
+ const measuredHeightsRef = react.useRef(/* @__PURE__ */ new Map());
45
+ const measuredHeightSumRef = react.useRef(0);
46
+ const rows = utils.flattenVisibleTree(
47
+ state.safeValue,
48
+ state.expandedNodeIds,
49
+ state.matches,
50
+ state.normalizedQuery
51
+ );
52
+ const virtualizer = reactVirtual.useVirtualizer({
53
+ count: rows.length,
54
+ getScrollElement: () => treePaneRef.current,
55
+ estimateSize: () => {
56
+ const measuredCount = measuredHeightsRef.current.size;
57
+ return measuredCount > 0 ? measuredHeightSumRef.current / measuredCount : ESTIMATED_ROW_HEIGHT;
58
+ },
59
+ getItemKey: (index) => rows[index].nodeId,
60
+ overscan: 12,
61
+ measureElement: (element, entry, instance) => {
62
+ var _a, _b;
63
+ const height = reactVirtual.measureElement(element, entry, instance);
64
+ const nodeId = (_a = rows[instance.indexFromElement(element)]) == null ? void 0 : _a.nodeId;
65
+ if (nodeId) {
66
+ const previous = (_b = measuredHeightsRef.current.get(nodeId)) != null ? _b : 0;
67
+ measuredHeightSumRef.current += height - previous;
68
+ measuredHeightsRef.current.set(nodeId, height);
69
+ }
70
+ return height;
71
+ }
72
+ });
73
+ return /* @__PURE__ */ jsxRuntime.jsx(
74
+ JsonViewerShell.JsonViewerShell,
75
+ {
76
+ state,
77
+ helperText,
78
+ searchPlaceholder,
79
+ emptySearchText,
80
+ className,
81
+ maxHeight,
82
+ borderless,
83
+ deleted,
84
+ treePaneRef,
85
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: virtualizer.getTotalSize(), position: "relative", width: "100%" }, children: virtualizer.getVirtualItems().map((virtualRow) => {
86
+ const row = rows[virtualRow.index];
87
+ return /* @__PURE__ */ jsxRuntime.jsx(
88
+ "div",
89
+ {
90
+ "data-index": virtualRow.index,
91
+ ref: virtualizer.measureElement,
92
+ className: styles__default.default.node,
93
+ style: {
94
+ position: "absolute",
95
+ top: 0,
96
+ left: 0,
97
+ width: "100%",
98
+ // Matches the 1px `gap` the non-virtualized `.node`/`.children`
99
+ // rules put between rows - flex gap doesn't apply here since
100
+ // rows are absolutely positioned rather than flex siblings.
101
+ paddingBottom: "1px",
102
+ transform: `translateY(${virtualRow.start}px)`,
103
+ ["--json-indent"]: row.depth
104
+ },
105
+ children: /* @__PURE__ */ jsxRuntime.jsx(
106
+ JsonRow.JsonRow,
107
+ {
108
+ nodeId: row.nodeId,
109
+ keyName: row.keyName,
110
+ value: row.value,
111
+ query: state.normalizedQuery,
112
+ match: row.match,
113
+ isExpanded: row.isExpanded,
114
+ copied: state.copiedId === row.nodeId,
115
+ onToggleNode: state.handleToggleNode,
116
+ onCopy: state.handleCopy
117
+ }
118
+ )
119
+ },
120
+ row.nodeId
121
+ );
122
+ }) })
123
+ }
124
+ );
125
+ }
126
+
127
+ exports.JsonViewer = JsonViewer;
@@ -0,0 +1,17 @@
1
+ import type { JSX } from 'react';
2
+ import type { JsonViewerProps } from './types';
3
+ export type { JsonViewerProps, JsonViewerViewMode } from './types';
4
+ /**
5
+ * Same props and visual output as the default `JsonViewer`, but the tree body
6
+ * is rendered through `@tanstack/react-virtual` instead of a fully recursive
7
+ * component tree - only the rows currently scrolled into view are mounted.
8
+ * Worthwhile for very large payloads (thousands of visible rows); for
9
+ * everything else, prefer the default `JsonViewer` to avoid the extra
10
+ * dependency.
11
+ *
12
+ * Virtualization only has something to virtualize when the tree pane is
13
+ * actually a bounded scroll container, so pass `maxHeight` (or otherwise
14
+ * constrain height via CSS) - without it the pane grows to fit all content
15
+ * and every row ends up mounted anyway.
16
+ */
17
+ export declare function JsonViewer({ value, defaultExpandedDepth, expandAll, defaultViewMode, searchDebounceMs, helperText, searchPlaceholder, emptySearchText, className, maxHeight, appearance, deleted, storageKey, borderless, }: JsonViewerProps): JSX.Element;