@dbcdk/react-components 0.0.179 → 0.0.181

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 (29) hide show
  1. package/README.md +4 -3
  2. package/dist/components/clear-button/ClearButton.cjs +7 -2
  3. package/dist/components/clear-button/ClearButton.d.ts +3 -1
  4. package/dist/components/clear-button/ClearButton.js +7 -2
  5. package/dist/components/clear-button/ClearButton.module.css +9 -0
  6. package/dist/components/forms/input/Input.cjs +8 -1
  7. package/dist/components/forms/input/Input.js +8 -1
  8. package/dist/components/forms/multi-select/MultiSelect.cjs +7 -1
  9. package/dist/components/forms/multi-select/MultiSelect.js +7 -1
  10. package/dist/components/forms/select/Select.cjs +7 -1
  11. package/dist/components/forms/select/Select.js +7 -1
  12. package/dist/components/interval-select/IntervalSelect.cjs +7 -1
  13. package/dist/components/interval-select/IntervalSelect.js +7 -1
  14. package/dist/components/json-viewer/JsonViewer.cjs +196 -83
  15. package/dist/components/json-viewer/JsonViewer.d.ts +1 -1
  16. package/dist/components/json-viewer/JsonViewer.js +197 -84
  17. package/dist/components/json-viewer/JsonViewer.module.css +37 -44
  18. package/dist/components/json-viewer/types.d.ts +8 -0
  19. package/dist/components/search-box/SearchBox.cjs +9 -1
  20. package/dist/components/search-box/SearchBox.d.ts +3 -3
  21. package/dist/components/search-box/SearchBox.js +9 -1
  22. package/dist/components/tabs/Tabs.cjs +50 -21
  23. package/dist/components/tabs/Tabs.d.ts +7 -1
  24. package/dist/components/tabs/Tabs.js +50 -21
  25. package/dist/components/tabs/Tabs.module.css +91 -11
  26. package/dist/hooks/useGetActiveTheme.cjs +2 -1
  27. package/dist/hooks/useGetActiveTheme.d.ts +1 -0
  28. package/dist/hooks/useGetActiveTheme.js +2 -1
  29. package/package.json +1 -1
package/README.md CHANGED
@@ -108,15 +108,16 @@ instead of `useTheme()`:
108
108
  import { useGetActiveTheme } from '@dbcdk/react-components/client'
109
109
 
110
110
  export function ThemeBadge() {
111
- const { theme, colorScheme } = useGetActiveTheme()
111
+ const { theme, colorScheme, themeKey } = useGetActiveTheme()
112
112
 
113
- return <span>{theme} / {colorScheme}</span>
113
+ return <span>{themeKey ?? `${theme} / ${colorScheme}`}</span>
114
114
  }
115
115
  ```
116
116
 
117
117
  `useGetActiveTheme()` is intentionally read-only and takes no options. It
118
118
  reports the current active theme state as established by `ThemeScript`,
119
- persisted storage, or another mounted theme control.
119
+ persisted storage, or another mounted theme control. `themeKey` is only set
120
+ when both `theme` and `colorScheme` are resolved, and is otherwise `null`.
120
121
 
121
122
  ---
122
123
 
@@ -8,8 +8,13 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
8
 
9
9
  var styles__default = /*#__PURE__*/_interopDefault(styles);
10
10
 
11
- function ClearButton({ onClick, ariaLabel = "Ryd" }) {
12
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.clearButton, children: /* @__PURE__ */ jsxRuntime.jsx(
11
+ function ClearButton({
12
+ onClick,
13
+ ariaLabel = "Ryd",
14
+ variant = "default"
15
+ }) {
16
+ const wrapperClassName = [styles__default.default.clearButton, variant === "header" ? styles__default.default.header : ""].filter(Boolean).join(" ");
17
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: wrapperClassName, children: /* @__PURE__ */ jsxRuntime.jsx(
13
18
  "button",
14
19
  {
15
20
  className: styles__default.default.button,
@@ -3,6 +3,8 @@ import * as React from 'react';
3
3
  interface ClearButtonProps {
4
4
  onClick?: (event?: React.MouseEvent | React.KeyboardEvent) => void;
5
5
  ariaLabel?: string;
6
+ /** 'header' uses --color-navbar-fg tokens — only meaningful inside/near AppHeader */
7
+ variant?: 'default' | 'header';
6
8
  }
7
- export declare function ClearButton({ onClick, ariaLabel }: ClearButtonProps): ReactNode;
9
+ export declare function ClearButton({ onClick, ariaLabel, variant, }: ClearButtonProps): ReactNode;
8
10
  export {};
@@ -2,8 +2,13 @@ import { jsx } from 'react/jsx-runtime';
2
2
  import { X } from 'lucide-react';
3
3
  import styles from './ClearButton.module.css';
4
4
 
5
- function ClearButton({ onClick, ariaLabel = "Ryd" }) {
6
- return /* @__PURE__ */ jsx("span", { className: styles.clearButton, children: /* @__PURE__ */ jsx(
5
+ function ClearButton({
6
+ onClick,
7
+ ariaLabel = "Ryd",
8
+ variant = "default"
9
+ }) {
10
+ const wrapperClassName = [styles.clearButton, variant === "header" ? styles.header : ""].filter(Boolean).join(" ");
11
+ return /* @__PURE__ */ jsx("span", { className: wrapperClassName, children: /* @__PURE__ */ jsx(
7
12
  "button",
8
13
  {
9
14
  className: styles.button,
@@ -24,3 +24,12 @@
24
24
  .clearButton .button:hover {
25
25
  background-color: var(--color-bg-contextual);
26
26
  }
27
+
28
+ .clearButton.header .button {
29
+ color: var(--color-navbar-fg-muted);
30
+ }
31
+
32
+ .clearButton.header .button:hover {
33
+ background-color: color-mix(in srgb, var(--color-navbar-fg) 12%, transparent);
34
+ color: var(--color-navbar-fg);
35
+ }
@@ -148,7 +148,14 @@ const Input = react.forwardRef(function Input2({
148
148
  {
149
149
  className: styles__default.default.clearSlot,
150
150
  "aria-hidden": hasVisibleClear ? void 0 : "true",
151
- children: hasVisibleClear && onClear ? /* @__PURE__ */ jsxRuntime.jsx(ClearButton.ClearButton, { onClick: onClear, ariaLabel: clearAriaLabel }) : null
151
+ children: hasVisibleClear && onClear ? /* @__PURE__ */ jsxRuntime.jsx(
152
+ ClearButton.ClearButton,
153
+ {
154
+ onClick: onClear,
155
+ ariaLabel: clearAriaLabel,
156
+ variant: variant === "header" ? "header" : "default"
157
+ }
158
+ ) : null
152
159
  }
153
160
  ) : null,
154
161
  endAdornment
@@ -142,7 +142,14 @@ const Input = forwardRef(function Input2({
142
142
  {
143
143
  className: styles.clearSlot,
144
144
  "aria-hidden": hasVisibleClear ? void 0 : "true",
145
- children: hasVisibleClear && onClear ? /* @__PURE__ */ jsx(ClearButton, { onClick: onClear, ariaLabel: clearAriaLabel }) : null
145
+ children: hasVisibleClear && onClear ? /* @__PURE__ */ jsx(
146
+ ClearButton,
147
+ {
148
+ onClick: onClear,
149
+ ariaLabel: clearAriaLabel,
150
+ variant: variant === "header" ? "header" : "default"
151
+ }
152
+ ) : null
146
153
  }
147
154
  ) : null,
148
155
  endAdornment
@@ -152,7 +152,13 @@ function MultiSelect({
152
152
  selectedValues.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(Chip.Chip, { size: "sm", children: selectedValues.length }) : null
153
153
  ] }),
154
154
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "dbc-flex dbc-items-center dbc-gap-xxs", children: [
155
- onClear && selectedValues.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(ClearButton.ClearButton, { onClick: onClear }) : null,
155
+ onClear && selectedValues.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
156
+ ClearButton.ClearButton,
157
+ {
158
+ onClick: onClear,
159
+ variant: variant === "header" ? "header" : "default"
160
+ }
161
+ ) : null,
156
162
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--color-fg-subtle)", display: "inline-flex" }, children: icon })
157
163
  ] })
158
164
  ]
@@ -150,7 +150,13 @@ function MultiSelect({
150
150
  selectedValues.length > 0 ? /* @__PURE__ */ jsx(Chip, { size: "sm", children: selectedValues.length }) : null
151
151
  ] }),
152
152
  /* @__PURE__ */ jsxs("span", { className: "dbc-flex dbc-items-center dbc-gap-xxs", children: [
153
- onClear && selectedValues.length > 0 ? /* @__PURE__ */ jsx(ClearButton, { onClick: onClear }) : null,
153
+ onClear && selectedValues.length > 0 ? /* @__PURE__ */ jsx(
154
+ ClearButton,
155
+ {
156
+ onClick: onClear,
157
+ variant: variant === "header" ? "header" : "default"
158
+ }
159
+ ) : null,
154
160
  /* @__PURE__ */ jsx("span", { style: { color: "var(--color-fg-subtle)", display: "inline-flex" }, children: icon })
155
161
  ] })
156
162
  ]
@@ -230,7 +230,13 @@ function Select({
230
230
  children: [
231
231
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: selected ? selected.label : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "dbc-muted-text", children: placeholder }) }),
232
232
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "dbc-flex dbc-items-center dbc-gap-xxs", children: [
233
- onClear && selected && /* @__PURE__ */ jsxRuntime.jsx(ClearButton.ClearButton, { onClick: onClear }),
233
+ onClear && selected && /* @__PURE__ */ jsxRuntime.jsx(
234
+ ClearButton.ClearButton,
235
+ {
236
+ onClick: onClear,
237
+ variant: variant === "header" ? "header" : "default"
238
+ }
239
+ ),
234
240
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--color-fg-subtle)", display: "inline-flex" }, children: icon })
235
241
  ] })
236
242
  ]
@@ -224,7 +224,13 @@ function Select({
224
224
  children: [
225
225
  /* @__PURE__ */ jsx("span", { children: selected ? selected.label : /* @__PURE__ */ jsx("span", { className: "dbc-muted-text", children: placeholder }) }),
226
226
  /* @__PURE__ */ jsxs("span", { className: "dbc-flex dbc-items-center dbc-gap-xxs", children: [
227
- onClear && selected && /* @__PURE__ */ jsx(ClearButton, { onClick: onClear }),
227
+ onClear && selected && /* @__PURE__ */ jsx(
228
+ ClearButton,
229
+ {
230
+ onClick: onClear,
231
+ variant: variant === "header" ? "header" : "default"
232
+ }
233
+ ),
228
234
  /* @__PURE__ */ jsx("span", { style: { color: "var(--color-fg-subtle)", display: "inline-flex" }, children: icon })
229
235
  ] })
230
236
  ]
@@ -154,7 +154,13 @@ function IntervalSelect({
154
154
  style: { width: "100%" },
155
155
  children: [
156
156
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "dbc-flex dbc-items-center dbc-gap-xxs", children: selected ? selected.label : placeholder }),
157
- onClear && selected && /* @__PURE__ */ jsxRuntime.jsx(ClearButton.ClearButton, { onClick: onClear }),
157
+ onClear && selected && /* @__PURE__ */ jsxRuntime.jsx(
158
+ ClearButton.ClearButton,
159
+ {
160
+ onClick: onClear,
161
+ variant: variant === "header" ? "header" : "default"
162
+ }
163
+ ),
158
164
  icon
159
165
  ]
160
166
  }
@@ -152,7 +152,13 @@ function IntervalSelect({
152
152
  style: { width: "100%" },
153
153
  children: [
154
154
  /* @__PURE__ */ jsx("span", { className: "dbc-flex dbc-items-center dbc-gap-xxs", children: selected ? selected.label : placeholder }),
155
- onClear && selected && /* @__PURE__ */ jsx(ClearButton, { onClick: onClear }),
155
+ onClear && selected && /* @__PURE__ */ jsx(
156
+ ClearButton,
157
+ {
158
+ onClick: onClear,
159
+ variant: variant === "header" ? "header" : "default"
160
+ }
161
+ ),
156
162
  icon
157
163
  ]
158
164
  }
@@ -4,15 +4,20 @@
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var lucideReact = require('lucide-react');
6
6
  var react = require('react');
7
+ var Menu = require('../../components/menu/Menu');
8
+ var Popover = require('../../components/popover/Popover');
9
+ var usePersistentState = require('../../hooks/usePersistentState');
7
10
  var JsonNode = require('./JsonNode');
8
11
  var styles = require('./JsonViewer.module.css');
9
12
  var useClipboardStatus = require('./useClipboardStatus');
10
13
  var utils = require('./utils');
14
+ var Button = require('../button/Button');
11
15
 
12
16
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
13
17
 
14
18
  var styles__default = /*#__PURE__*/_interopDefault(styles);
15
19
 
20
+ const COPY_ALL_ID = "__json-viewer-copy-all__";
16
21
  function JsonViewer({
17
22
  value,
18
23
  defaultExpandedDepth = 2,
@@ -22,13 +27,28 @@ function JsonViewer({
22
27
  searchPlaceholder = "S\xF8g i n\xF8gler, stier og v\xE6rdier",
23
28
  emptySearchText = "Ingen matchende noder fundet.",
24
29
  className,
25
- maxHeight
30
+ maxHeight,
31
+ appearance = "dark",
32
+ storageKey
26
33
  }) {
27
34
  const [queryInput, setQueryInput] = react.useState("");
28
35
  const [query, setQuery] = react.useState("");
29
36
  const normalizedQuery = utils.normalizeSearch(query);
30
37
  const inputId = react.useId();
31
38
  const { copiedId, setCopiedId } = useClipboardStatus.useClipboardStatus();
39
+ const { value: currentAppearance, setValue: setCurrentAppearance } = usePersistentState.usePersistentState({
40
+ initialValue: appearance,
41
+ storageKey: storageKey ? `${storageKey}:appearance` : void 0,
42
+ validate: (stored) => stored === "dark" || stored === "light"
43
+ });
44
+ const { value: viewMode, setValue: setViewMode } = usePersistentState.usePersistentState({
45
+ initialValue: "tree",
46
+ storageKey: storageKey ? `${storageKey}:viewMode` : void 0,
47
+ validate: (stored) => stored === "tree" || stored === "raw"
48
+ });
49
+ const handleToggleAppearance = () => {
50
+ setCurrentAppearance((current) => current === "dark" ? "light" : "dark");
51
+ };
32
52
  react.useEffect(() => {
33
53
  const timeoutId = window.setTimeout(() => {
34
54
  setQuery(queryInput);
@@ -53,6 +73,7 @@ function JsonViewer({
53
73
  () => new Set(utils.collectInitiallyExpandedNodeIds(safeValue, defaultExpandedDepth, expandAll))
54
74
  );
55
75
  const hasResults = normalizedQuery ? matches.size > 0 : true;
76
+ const rawJson = react.useMemo(() => JSON.stringify(safeValue, null, 2), [safeValue]);
56
77
  const handleCopy = async (nodeId, rawValue) => {
57
78
  try {
58
79
  await navigator.clipboard.writeText(rawValue);
@@ -61,6 +82,7 @@ function JsonViewer({
61
82
  setCopiedId(null);
62
83
  }
63
84
  };
85
+ const handleCopyAll = () => handleCopy(COPY_ALL_ID, rawJson);
64
86
  const handleExpandAll = () => {
65
87
  setExpandedNodeIds(new Set(allExpandableNodeIds));
66
88
  };
@@ -75,90 +97,181 @@ function JsonViewer({
75
97
  return next;
76
98
  });
77
99
  };
78
- return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: [styles__default.default.viewer, className].filter(Boolean).join(" "), children: [
79
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.toolbar, children: [
80
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.toolbarTop, children: [
81
- /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: styles__default.default.searchField, children: [
82
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: styles__default.default.searchIcon, "aria-hidden": "true" }),
83
- /* @__PURE__ */ jsxRuntime.jsx(
84
- "input",
85
- {
86
- id: inputId,
87
- type: "search",
88
- value: queryInput,
89
- onChange: (event) => setQueryInput(event.target.value),
90
- placeholder: searchPlaceholder,
91
- className: styles__default.default.searchInput
92
- }
93
- ),
94
- queryInput ? /* @__PURE__ */ jsxRuntime.jsx(
95
- "button",
96
- {
97
- type: "button",
98
- className: styles__default.default.clearButton,
99
- "aria-label": "Ryd s\xF8gning",
100
- onClick: () => {
101
- setQueryInput("");
102
- setQuery("");
103
- },
104
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { "aria-hidden": "true" })
105
- }
106
- ) : null
107
- ] }),
108
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.actions, children: [
109
- /* @__PURE__ */ jsxRuntime.jsx(
110
- "button",
111
- {
112
- type: "button",
113
- className: styles__default.default.toolbarButton,
114
- onClick: handleExpandAll,
115
- disabled: Boolean(normalizedQuery),
116
- children: "Fold alle ud"
117
- }
118
- ),
119
- /* @__PURE__ */ jsxRuntime.jsx(
120
- "button",
121
- {
122
- type: "button",
123
- className: styles__default.default.toolbarButton,
124
- onClick: handleCollapseAll,
125
- disabled: Boolean(normalizedQuery),
126
- children: "Fold alle sammen"
127
- }
128
- )
129
- ] })
130
- ] }),
131
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.metaRow, children: [
132
- helperText ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.helperText, children: helperText }) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
133
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.statusText, children: normalizedQuery ? `${matches.size} matchende node${matches.size === 1 ? "" : "r"}` : "" })
134
- ] })
135
- ] }),
136
- /* @__PURE__ */ jsxRuntime.jsx(
137
- "div",
138
- {
139
- className: styles__default.default.treePane,
140
- role: "tree",
141
- "aria-label": "JSON-visning",
142
- style: maxHeight !== void 0 ? { maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight } : void 0,
143
- children: hasResults ? /* @__PURE__ */ jsxRuntime.jsx(
144
- JsonNode.JsonNode,
100
+ return /* @__PURE__ */ jsxRuntime.jsxs(
101
+ "section",
102
+ {
103
+ className: [styles__default.default.viewer, className].filter(Boolean).join(" "),
104
+ "data-appearance": currentAppearance,
105
+ children: [
106
+ /* @__PURE__ */ jsxRuntime.jsxs(
107
+ "div",
145
108
  {
146
- keyName: void 0,
147
- path: [],
148
- value: safeValue,
149
- depth: 0,
150
- defaultExpandedDepth,
151
- query: normalizedQuery,
152
- matches,
153
- expandedNodeIds,
154
- onToggleNode: handleToggleNode,
155
- copiedId,
156
- onCopy: handleCopy
109
+ className: styles__default.default.toolbar,
110
+ "data-surface": currentAppearance === "dark" ? "inverse" : void 0,
111
+ children: [
112
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.toolbarTop, children: [
113
+ viewMode === "tree" ? /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: styles__default.default.searchField, children: [
114
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: styles__default.default.searchIcon, "aria-hidden": "true" }),
115
+ /* @__PURE__ */ jsxRuntime.jsx(
116
+ "input",
117
+ {
118
+ id: inputId,
119
+ type: "search",
120
+ value: queryInput,
121
+ onChange: (event) => setQueryInput(event.target.value),
122
+ placeholder: searchPlaceholder,
123
+ className: styles__default.default.searchInput
124
+ }
125
+ ),
126
+ queryInput ? /* @__PURE__ */ jsxRuntime.jsx(
127
+ "button",
128
+ {
129
+ type: "button",
130
+ className: styles__default.default.clearButton,
131
+ "aria-label": "Ryd s\xF8gning",
132
+ onClick: () => {
133
+ setQueryInput("");
134
+ setQuery("");
135
+ },
136
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { "aria-hidden": "true" })
137
+ }
138
+ ) : null
139
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
140
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.actions, children: /* @__PURE__ */ jsxRuntime.jsx(
141
+ Popover.Popover,
142
+ {
143
+ matchTriggerWidth: false,
144
+ minWidth: "200px",
145
+ trigger: (toggle, _icon, isOpen) => /* @__PURE__ */ jsxRuntime.jsx(
146
+ Button.Button,
147
+ {
148
+ variant: "inline",
149
+ "aria-label": "Flere handlinger",
150
+ "aria-haspopup": "menu",
151
+ "aria-expanded": isOpen ? true : false,
152
+ onClick: toggle,
153
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreVertical, { "aria-hidden": "true" })
154
+ }
155
+ ),
156
+ children: (close) => /* @__PURE__ */ jsxRuntime.jsxs(Menu.Menu, { children: [
157
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Item, { disabled: viewMode === "raw" || Boolean(normalizedQuery), children: /* @__PURE__ */ jsxRuntime.jsxs(
158
+ "button",
159
+ {
160
+ type: "button",
161
+ onClick: () => {
162
+ handleExpandAll();
163
+ close();
164
+ },
165
+ children: [
166
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { "aria-hidden": "true" }),
167
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Fold alle ud" })
168
+ ]
169
+ }
170
+ ) }),
171
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Item, { disabled: viewMode === "raw" || Boolean(normalizedQuery), children: /* @__PURE__ */ jsxRuntime.jsxs(
172
+ "button",
173
+ {
174
+ type: "button",
175
+ onClick: () => {
176
+ handleCollapseAll();
177
+ close();
178
+ },
179
+ children: [
180
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { "aria-hidden": "true" }),
181
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Fold alle sammen" })
182
+ ]
183
+ }
184
+ ) }),
185
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Separator, {}),
186
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs(
187
+ "button",
188
+ {
189
+ type: "button",
190
+ onClick: () => {
191
+ setViewMode((mode) => mode === "raw" ? "tree" : "raw");
192
+ close();
193
+ },
194
+ children: [
195
+ viewMode === "raw" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListTree, { "aria-hidden": "true" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Braces, { "aria-hidden": "true" }),
196
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: viewMode === "raw" ? "Vis tr\xE6" : "Vis raw" })
197
+ ]
198
+ }
199
+ ) }),
200
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs(
201
+ "button",
202
+ {
203
+ type: "button",
204
+ onClick: () => {
205
+ handleToggleAppearance();
206
+ close();
207
+ },
208
+ children: [
209
+ currentAppearance === "dark" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sun, { "aria-hidden": "true" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Moon, { "aria-hidden": "true" }),
210
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: currentAppearance === "dark" ? "Lys visning" : "M\xF8rk visning" })
211
+ ]
212
+ }
213
+ ) }),
214
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Separator, {}),
215
+ /* @__PURE__ */ jsxRuntime.jsx(Menu.Menu.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs(
216
+ "button",
217
+ {
218
+ type: "button",
219
+ onClick: () => {
220
+ handleCopyAll();
221
+ close();
222
+ },
223
+ children: [
224
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ClipboardCopy, { "aria-hidden": "true" }),
225
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Kopi\xE9r JSON" })
226
+ ]
227
+ }
228
+ ) })
229
+ ] })
230
+ }
231
+ ) })
232
+ ] }),
233
+ helperText || viewMode === "tree" && normalizedQuery ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles__default.default.metaRow, children: [
234
+ helperText ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.helperText, children: helperText }) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
235
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles__default.default.statusText, children: viewMode === "tree" && normalizedQuery ? `${matches.size} matchende node${matches.size === 1 ? "" : "r"}` : "" })
236
+ ] }) : null
237
+ ]
157
238
  }
158
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.emptyState, children: emptySearchText })
159
- }
160
- )
161
- ] });
239
+ ),
240
+ viewMode === "raw" ? /* @__PURE__ */ jsxRuntime.jsx(
241
+ "pre",
242
+ {
243
+ className: styles__default.default.rawPane,
244
+ style: maxHeight !== void 0 ? { maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight } : void 0,
245
+ children: rawJson
246
+ }
247
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
248
+ "div",
249
+ {
250
+ className: styles__default.default.treePane,
251
+ role: "tree",
252
+ "aria-label": "JSON-visning",
253
+ style: maxHeight !== void 0 ? { maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight } : void 0,
254
+ children: hasResults ? /* @__PURE__ */ jsxRuntime.jsx(
255
+ JsonNode.JsonNode,
256
+ {
257
+ keyName: void 0,
258
+ path: [],
259
+ value: safeValue,
260
+ depth: 0,
261
+ defaultExpandedDepth,
262
+ query: normalizedQuery,
263
+ matches,
264
+ expandedNodeIds,
265
+ onToggleNode: handleToggleNode,
266
+ copiedId,
267
+ onCopy: handleCopy
268
+ }
269
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.emptyState, children: emptySearchText })
270
+ }
271
+ )
272
+ ]
273
+ }
274
+ );
162
275
  }
163
276
 
164
277
  exports.JsonViewer = JsonViewer;
@@ -1,4 +1,4 @@
1
1
  import type { JSX } from 'react';
2
2
  import type { JsonViewerProps } from './types';
3
3
  export type { JsonViewerProps } from './types';
4
- export declare function JsonViewer({ value, defaultExpandedDepth, expandAll, searchDebounceMs, helperText, searchPlaceholder, emptySearchText, className, maxHeight, }: JsonViewerProps): JSX.Element;
4
+ export declare function JsonViewer({ value, defaultExpandedDepth, expandAll, searchDebounceMs, helperText, searchPlaceholder, emptySearchText, className, maxHeight, appearance, storageKey, }: JsonViewerProps): JSX.Element;