@dbcdk/react-components 0.0.180 → 0.0.182

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.
@@ -8,23 +8,46 @@ 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
+ as = "button"
16
+ }) {
17
+ const wrapperClassName = [styles__default.default.clearButton, variant === "header" ? styles__default.default.header : ""].filter(Boolean).join(" ");
18
+ const handleMouseDown = (e) => {
19
+ e.preventDefault();
20
+ e.stopPropagation();
21
+ };
22
+ const handleClick = (e) => {
23
+ e.preventDefault();
24
+ e.stopPropagation();
25
+ onClick == null ? void 0 : onClick(e);
26
+ };
27
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: wrapperClassName, children: as === "span" ? /* @__PURE__ */ jsxRuntime.jsx(
28
+ "span",
29
+ {
30
+ className: styles__default.default.button,
31
+ role: "button",
32
+ tabIndex: 0,
33
+ "aria-label": ariaLabel,
34
+ "data-input-role": "clear",
35
+ onMouseDown: handleMouseDown,
36
+ onClick: handleClick,
37
+ onKeyDown: (e) => {
38
+ if (e.key === "Enter" || e.key === " ") handleClick(e);
39
+ },
40
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 16 })
41
+ }
42
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
13
43
  "button",
14
44
  {
15
45
  className: styles__default.default.button,
16
46
  type: "button",
17
47
  "aria-label": ariaLabel,
18
48
  "data-input-role": "clear",
19
- onMouseDown: (e) => {
20
- e.preventDefault();
21
- e.stopPropagation();
22
- },
23
- onClick: (e) => {
24
- e.preventDefault();
25
- e.stopPropagation();
26
- onClick == null ? void 0 : onClick(e);
27
- },
49
+ onMouseDown: handleMouseDown,
50
+ onClick: handleClick,
28
51
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 16 })
29
52
  }
30
53
  ) });
@@ -3,6 +3,17 @@ 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';
8
+ /**
9
+ * 'button' (default) renders a native <button>. Pass 'span' when this is
10
+ * nested inside another interactive <button> (e.g. a Select/MultiSelect/
11
+ * IntervalSelect trigger) - a <button> descendant of a <button> is invalid
12
+ * HTML and breaks hydration. The span variant keeps the same class,
13
+ * click/mousedown handling, and adds role="button" + Enter/Space
14
+ * activation so it stays keyboard-operable without the invalid nesting.
15
+ */
16
+ as?: 'button' | 'span';
6
17
  }
7
- export declare function ClearButton({ onClick, ariaLabel }: ClearButtonProps): ReactNode;
18
+ export declare function ClearButton({ onClick, ariaLabel, variant, as, }: ClearButtonProps): ReactNode;
8
19
  export {};
@@ -2,23 +2,46 @@ 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
+ as = "button"
10
+ }) {
11
+ const wrapperClassName = [styles.clearButton, variant === "header" ? styles.header : ""].filter(Boolean).join(" ");
12
+ const handleMouseDown = (e) => {
13
+ e.preventDefault();
14
+ e.stopPropagation();
15
+ };
16
+ const handleClick = (e) => {
17
+ e.preventDefault();
18
+ e.stopPropagation();
19
+ onClick == null ? void 0 : onClick(e);
20
+ };
21
+ return /* @__PURE__ */ jsx("span", { className: wrapperClassName, children: as === "span" ? /* @__PURE__ */ jsx(
22
+ "span",
23
+ {
24
+ className: styles.button,
25
+ role: "button",
26
+ tabIndex: 0,
27
+ "aria-label": ariaLabel,
28
+ "data-input-role": "clear",
29
+ onMouseDown: handleMouseDown,
30
+ onClick: handleClick,
31
+ onKeyDown: (e) => {
32
+ if (e.key === "Enter" || e.key === " ") handleClick(e);
33
+ },
34
+ children: /* @__PURE__ */ jsx(X, { size: 16 })
35
+ }
36
+ ) : /* @__PURE__ */ jsx(
7
37
  "button",
8
38
  {
9
39
  className: styles.button,
10
40
  type: "button",
11
41
  "aria-label": ariaLabel,
12
42
  "data-input-role": "clear",
13
- onMouseDown: (e) => {
14
- e.preventDefault();
15
- e.stopPropagation();
16
- },
17
- onClick: (e) => {
18
- e.preventDefault();
19
- e.stopPropagation();
20
- onClick == null ? void 0 : onClick(e);
21
- },
43
+ onMouseDown: handleMouseDown,
44
+ onClick: handleClick,
22
45
  children: /* @__PURE__ */ jsx(X, { size: 16 })
23
46
  }
24
47
  ) });
@@ -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,14 @@ 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
+ as: "span"
161
+ }
162
+ ) : null,
156
163
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--color-fg-subtle)", display: "inline-flex" }, children: icon })
157
164
  ] })
158
165
  ]
@@ -150,7 +150,14 @@ 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
+ as: "span"
159
+ }
160
+ ) : null,
154
161
  /* @__PURE__ */ jsx("span", { style: { color: "var(--color-fg-subtle)", display: "inline-flex" }, children: icon })
155
162
  ] })
156
163
  ]
@@ -230,7 +230,14 @@ 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
+ as: "span"
239
+ }
240
+ ),
234
241
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "var(--color-fg-subtle)", display: "inline-flex" }, children: icon })
235
242
  ] })
236
243
  ]
@@ -224,7 +224,14 @@ 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
+ as: "span"
233
+ }
234
+ ),
228
235
  /* @__PURE__ */ jsx("span", { style: { color: "var(--color-fg-subtle)", display: "inline-flex" }, children: icon })
229
236
  ] })
230
237
  ]
@@ -154,7 +154,14 @@ 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
+ as: "span"
163
+ }
164
+ ),
158
165
  icon
159
166
  ]
160
167
  }
@@ -152,7 +152,14 @@ 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
+ as: "span"
161
+ }
162
+ ),
156
163
  icon
157
164
  ]
158
165
  }
@@ -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;