@akira-io/ui 1.0.0 → 1.1.1

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 (73) hide show
  1. package/README.md +15 -10
  2. package/dist/blocks.d.ts +162 -9
  3. package/dist/blocks.js +1410 -36
  4. package/dist/blocks.js.map +1 -1
  5. package/dist/button-Bj6My68b.d.ts +17 -0
  6. package/dist/chunk-2WIIRDHT.js +83 -0
  7. package/dist/chunk-2WIIRDHT.js.map +1 -0
  8. package/dist/{chunk-A2SIZOEA.js → chunk-4SOQAVUP.js} +125 -45
  9. package/dist/chunk-4SOQAVUP.js.map +1 -0
  10. package/dist/chunk-5AJFQ6C4.js +35 -0
  11. package/dist/chunk-5AJFQ6C4.js.map +1 -0
  12. package/dist/chunk-CFDDAFPJ.js +1243 -0
  13. package/dist/chunk-CFDDAFPJ.js.map +1 -0
  14. package/dist/chunk-FWQFB37J.js +45 -0
  15. package/dist/chunk-FWQFB37J.js.map +1 -0
  16. package/dist/chunk-IQMRJXEO.js +59 -0
  17. package/dist/chunk-IQMRJXEO.js.map +1 -0
  18. package/dist/chunk-L2H5GIF7.js +22 -0
  19. package/dist/chunk-L2H5GIF7.js.map +1 -0
  20. package/dist/chunk-ODYCBCKS.js +290 -0
  21. package/dist/chunk-ODYCBCKS.js.map +1 -0
  22. package/dist/{chunk-5MQWJVM2.js → chunk-QHZWW55M.js} +383 -326
  23. package/dist/chunk-QHZWW55M.js.map +1 -0
  24. package/dist/chunk-RPCL7VFQ.js +123 -0
  25. package/dist/chunk-RPCL7VFQ.js.map +1 -0
  26. package/dist/chunk-T2INZOCM.js +165 -0
  27. package/dist/chunk-T2INZOCM.js.map +1 -0
  28. package/dist/chunk-TGF54WAO.js +29 -0
  29. package/dist/chunk-TGF54WAO.js.map +1 -0
  30. package/dist/chunk-XZCC6MTE.js +26 -0
  31. package/dist/chunk-XZCC6MTE.js.map +1 -0
  32. package/dist/{chunk-UXL33CZ4.js → chunk-YOVY3KT6.js} +13 -11
  33. package/dist/chunk-YOVY3KT6.js.map +1 -0
  34. package/dist/code.d.ts +9 -0
  35. package/dist/code.js +650 -0
  36. package/dist/code.js.map +1 -0
  37. package/dist/context-YWbxMH0C.d.ts +383 -0
  38. package/dist/editor.d.ts +128 -0
  39. package/dist/editor.js +450 -0
  40. package/dist/editor.js.map +1 -0
  41. package/dist/index.d.ts +298 -222
  42. package/dist/index.js +1300 -670
  43. package/dist/index.js.map +1 -1
  44. package/dist/inertia.d.ts +47 -2
  45. package/dist/inertia.js +138 -7
  46. package/dist/inertia.js.map +1 -1
  47. package/dist/input-Dpi7pXeR.d.ts +6 -0
  48. package/dist/json-viewer-BARA2RCW.d.ts +51 -0
  49. package/dist/{language-Bft6rBBt.d.ts → language-Dgjr9bm3.d.ts} +1 -1
  50. package/dist/locales/pt.d.ts +26 -4
  51. package/dist/locales/pt.js +127 -1
  52. package/dist/locales/pt.js.map +1 -1
  53. package/dist/password-input-DcXX7SG9.d.ts +51 -0
  54. package/dist/shells.d.ts +45 -7
  55. package/dist/shells.js +96 -60
  56. package/dist/shells.js.map +1 -1
  57. package/dist/sidebar-DqkFRUxQ.d.ts +81 -0
  58. package/dist/types-B-eGPoFD.d.ts +111 -0
  59. package/dist/types-cmBL8zOc.d.ts +51 -0
  60. package/package.json +170 -130
  61. package/theme.css +20 -0
  62. package/themes/nosferry.css +4 -0
  63. package/dist/chunk-42BJBH56.js +0 -786
  64. package/dist/chunk-42BJBH56.js.map +0 -1
  65. package/dist/chunk-5MQWJVM2.js.map +0 -1
  66. package/dist/chunk-A2SIZOEA.js.map +0 -1
  67. package/dist/chunk-POE7OYET.js +0 -96
  68. package/dist/chunk-POE7OYET.js.map +0 -1
  69. package/dist/chunk-UXL33CZ4.js.map +0 -1
  70. package/dist/date-range-filter-QEa8fhUM.d.ts +0 -149
  71. package/dist/sidebar-BDhG9SUU.d.ts +0 -88
  72. package/dist/types-Cno1_Ijx.d.ts +0 -40
  73. package/dist/types-cOieac8G.d.ts +0 -77
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/blocks/tour/gate.ts","../src/blocks/tour/types.ts","../src/blocks/tour/tour.tsx"],"names":[],"mappings":"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","file":"chunk-YOVY3KT6.js","sourcesContent":["import type {\n TourBreakpoint,\n TourDefinition,\n TourStep,\n} from '@/blocks/tour/types';\n\nexport function stepsForBreakpoint(\n steps: TourStep[],\n breakpoint: TourBreakpoint,\n): TourStep[] {\n return steps.filter(\n (step) => !step.breakpoints || step.breakpoints.includes(breakpoint),\n );\n}\n\nexport function resolveSteps(\n steps: TourStep[],\n isPresent: (target: string) => boolean,\n): TourStep[] {\n return steps.filter((step) => isPresent(step.target));\n}\n\nexport function shouldStartTour(input: {\n definition: TourDefinition;\n seen: Record<string, number>;\n resolvedStepCount: number;\n force?: boolean;\n}): boolean {\n if (input.resolvedStepCount === 0) {\n return false;\n }\n\n if (input.force) {\n return true;\n }\n\n return input.definition.version > (input.seen[input.definition.id] ?? 0);\n}\n","export type TourBreakpoint = 'mobile' | 'desktop';\n\nexport type TourOutcome = 'completed' | 'skipped' | 'dismissed';\n\nexport interface TourStep {\n target: string;\n title: string;\n description: string;\n breakpoints?: TourBreakpoint[];\n}\n\nexport interface TourDefinition {\n id: string;\n version: number;\n steps: TourStep[];\n}\n\nexport interface TourProgress {\n tour: string;\n version: number;\n lastStep: number;\n outcome: TourOutcome;\n}\n\nexport interface TourLabels {\n next: string;\n previous: string;\n done: string;\n progress: string;\n}\n\nexport const DEFAULT_TOUR_LABELS: TourLabels = {\n next: 'Next',\n previous: 'Previous',\n done: 'Done',\n progress: '{{current}} of {{total}}',\n};\n","import { driver, type Driver } from 'driver.js';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n type PropsWithChildren,\n type ReactElement,\n} from 'react';\n\nimport 'driver.js/dist/driver.css';\n\nimport { shouldStartTour, stepsForBreakpoint } from '@/blocks/tour/gate';\nimport {\n DEFAULT_TOUR_LABELS,\n type TourBreakpoint,\n type TourDefinition,\n type TourLabels,\n type TourOutcome,\n type TourProgress,\n} from '@/blocks/tour/types';\nimport { useUiLabels } from '@/locales/context';\n\ninterface TourControllerValue {\n startTour: (\n definition: TourDefinition,\n options?: { force?: boolean },\n ) => void;\n}\n\nconst TourContext = createContext<TourControllerValue | null>(null);\n\nconst MOBILE_BREAKPOINT = 768;\n\nconst WAIT_FOR_TARGET = 4000;\n\nfunction currentBreakpoint(): TourBreakpoint {\n return window.innerWidth < MOBILE_BREAKPOINT ? 'mobile' : 'desktop';\n}\n\nfunction outcomeOf(instance: Driver, highlighted: boolean): TourOutcome {\n if (!highlighted) {\n return 'dismissed';\n }\n\n return instance.hasNextStep() ? 'skipped' : 'completed';\n}\n\nexport function TourProvider({\n children,\n seen,\n onProgress,\n labels,\n}: PropsWithChildren<{\n seen: Record<string, number>;\n onProgress: (progress: TourProgress) => void;\n labels?: Partial<TourLabels>;\n}>): ReactElement {\n const seenRef = useRef(seen);\n seenRef.current = seen;\n\n const onProgressRef = useRef(onProgress);\n onProgressRef.current = onProgress;\n\n const driverRef = useRef<Driver | null>(null);\n const activeRef = useRef<{\n definition: TourDefinition;\n lastStep: number;\n highlighted: boolean;\n } | null>(null);\n\n const { next, previous, done, progress } = useUiLabels(\n 'tour',\n DEFAULT_TOUR_LABELS,\n labels,\n );\n\n const report = useCallback((outcome: TourOutcome): void => {\n const active = activeRef.current;\n\n if (!active) {\n return;\n }\n\n activeRef.current = null;\n\n onProgressRef.current({\n tour: active.definition.id,\n version: active.definition.version,\n lastStep: active.lastStep,\n outcome,\n });\n }, []);\n\n const startTour = useCallback(\n (definition: TourDefinition, options?: { force?: boolean }): void => {\n const alreadyRunning =\n activeRef.current?.definition.id === definition.id;\n\n if (alreadyRunning && !options?.force) {\n return;\n }\n\n const steps = stepsForBreakpoint(\n definition.steps,\n currentBreakpoint(),\n );\n\n const allowed = shouldStartTour({\n definition,\n seen: seenRef.current,\n resolvedStepCount: steps.length,\n force: options?.force,\n });\n\n if (!allowed) {\n return;\n }\n\n driverRef.current?.destroy();\n activeRef.current = { definition, lastStep: 0, highlighted: false };\n\n const instance = driver({\n showProgress: true,\n progressText: progress,\n nextBtnText: next,\n prevBtnText: previous,\n doneBtnText: done,\n popoverClass: 'akira-tour',\n waitForElement: WAIT_FOR_TARGET,\n skipMissingElement: true,\n steps: steps.map((step) => ({\n element: step.target,\n popover: {\n title: step.title,\n description: step.description,\n },\n })),\n onHighlightStarted: () => {\n if (activeRef.current) {\n activeRef.current.lastStep =\n instance.getActiveIndex() ?? 0;\n activeRef.current.highlighted = true;\n }\n },\n onDestroyStarted: () => {\n report(\n outcomeOf(\n instance,\n activeRef.current?.highlighted ?? false,\n ),\n );\n instance.destroy();\n },\n });\n\n driverRef.current = instance;\n instance.drive();\n },\n [report, next, previous, done, progress],\n );\n\n useEffect(\n () => () => {\n report('dismissed');\n driverRef.current?.destroy();\n driverRef.current = null;\n },\n [report],\n );\n\n const value = useMemo(() => ({ startTour }), [startTour]);\n\n return (\n <TourContext.Provider value={value}>{children}</TourContext.Provider>\n );\n}\n\nexport function useTourController(): TourControllerValue {\n const context = useContext(TourContext);\n\n if (!context) {\n throw new Error(\n 'useTourController must be used inside a TourProvider.',\n );\n }\n\n return context;\n}\n\nexport function useTour(\n definition: TourDefinition,\n options?: { enabled?: boolean },\n): { restart: () => void } {\n const { startTour } = useTourController();\n const enabled = options?.enabled ?? true;\n\n const definitionRef = useRef(definition);\n definitionRef.current = definition;\n\n useEffect(() => {\n if (!enabled) {\n return;\n }\n\n const frame = window.requestAnimationFrame(() =>\n startTour(definitionRef.current),\n );\n\n return () => window.cancelAnimationFrame(frame);\n }, [definition.id, definition.version, enabled, startTour]);\n\n return { restart: () => startTour(definitionRef.current, { force: true }) };\n}\n"]}
package/dist/code.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+ import { S as SlotNameProps } from './types-cmBL8zOc.js';
3
+ export { C as CodeBlock, a as CodeBlockLabels, b as CodeBlockProps, J as JsonViewer, c as JsonViewerLabels, d as JsonViewerProps, e as codeBlockLabels, j as jsonViewerLabels } from './json-viewer-BARA2RCW.js';
4
+ import '@tanstack/react-table';
5
+ import 'lucide-react';
6
+
7
+ declare function Code({ className, slotName, ...props }: React.ComponentProps<'code'> & SlotNameProps): React.JSX.Element;
8
+
9
+ export { Code };
package/dist/code.js ADDED
@@ -0,0 +1,650 @@
1
+ import { CopyButton } from './chunk-2WIIRDHT.js';
2
+ import { useUiLabels } from './chunk-5AJFQ6C4.js';
3
+ import { cn, compactRadius, controlFill, elevatedSurface, nestedSurfaceReset, Button, focusRing } from './chunk-ODYCBCKS.js';
4
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
+ import * as React2 from 'react';
6
+ import { FileCode, ChevronRight } from 'lucide-react';
7
+
8
+ function Code({
9
+ className,
10
+ slotName = "code",
11
+ ...props
12
+ }) {
13
+ return /* @__PURE__ */ jsx(
14
+ "code",
15
+ {
16
+ className: cn(
17
+ compactRadius,
18
+ controlFill,
19
+ "px-1.5 py-0.5 font-mono font-medium text-[0.875em] text-foreground",
20
+ className
21
+ ),
22
+ ...props,
23
+ "data-slot": slotName
24
+ }
25
+ );
26
+ }
27
+ function CodeBlockHeader({
28
+ filename,
29
+ language,
30
+ code,
31
+ copyLabel,
32
+ copiedLabel,
33
+ slotName = "code-block-header"
34
+ }) {
35
+ return /* @__PURE__ */ jsxs(
36
+ "div",
37
+ {
38
+ className: "gap-2 px-4 py-2 flex items-center border-b border-border",
39
+ "data-slot": slotName,
40
+ children: [
41
+ /* @__PURE__ */ jsx(FileCode, { className: "size-4 shrink-0 text-muted-foreground" }),
42
+ /* @__PURE__ */ jsx(
43
+ "span",
44
+ {
45
+ "data-slot": "code-block-filename",
46
+ className: "text-sm font-medium truncate text-foreground",
47
+ children: filename
48
+ }
49
+ ),
50
+ language !== void 0 && /* @__PURE__ */ jsx(
51
+ "span",
52
+ {
53
+ "data-slot": "code-block-language",
54
+ className: "text-xs font-medium tracking-wide text-muted-foreground uppercase",
55
+ children: language
56
+ }
57
+ ),
58
+ /* @__PURE__ */ jsx(
59
+ CopyButton,
60
+ {
61
+ value: code,
62
+ copyLabel,
63
+ copiedLabel,
64
+ className: "ml-auto text-muted-foreground"
65
+ }
66
+ )
67
+ ]
68
+ }
69
+ );
70
+ }
71
+
72
+ // src/lib/shiki.ts
73
+ var LIGHT_THEME = "github-light";
74
+ var DARK_THEME = "github-dark";
75
+ var pending = null;
76
+ function loadCodeToHtml() {
77
+ pending ??= import('shiki').then((module) => module.codeToHtml).catch(() => null);
78
+ return pending;
79
+ }
80
+ async function highlightCode(code, language) {
81
+ const codeToHtml = await loadCodeToHtml();
82
+ if (!codeToHtml) {
83
+ return null;
84
+ }
85
+ try {
86
+ return await codeToHtml(code, {
87
+ lang: language,
88
+ themes: { light: LIGHT_THEME, dark: DARK_THEME },
89
+ defaultColor: false
90
+ });
91
+ } catch {
92
+ return null;
93
+ }
94
+ }
95
+
96
+ // src/hooks/use-highlighted-code.ts
97
+ function useHighlightedCode(code, language, html) {
98
+ const [highlighted, setHighlighted] = React2.useState(
99
+ html ?? null
100
+ );
101
+ React2.useEffect(() => {
102
+ if (html !== void 0) {
103
+ setHighlighted(html);
104
+ return;
105
+ }
106
+ if (language === void 0) {
107
+ setHighlighted(null);
108
+ return;
109
+ }
110
+ let active = true;
111
+ highlightCode(code, language).then((result) => {
112
+ if (active) {
113
+ setHighlighted(result);
114
+ }
115
+ });
116
+ return () => {
117
+ active = false;
118
+ };
119
+ }, [code, language, html]);
120
+ return highlighted;
121
+ }
122
+
123
+ // src/lib/code-lines.ts
124
+ var LINE_OPEN = '<span class="line">';
125
+ var SPAN_CLOSE = "</span>";
126
+ function splitSourceLines(code) {
127
+ return code.replace(/\n$/, "").split("\n");
128
+ }
129
+ function parseLineRanges(spec) {
130
+ const lines = /* @__PURE__ */ new Set();
131
+ if (spec === void 0) {
132
+ return lines;
133
+ }
134
+ if (Array.isArray(spec)) {
135
+ for (const line of spec) {
136
+ lines.add(line);
137
+ }
138
+ return lines;
139
+ }
140
+ for (const part of spec.split(",")) {
141
+ const [from, to] = part.split("-").map((bound) => Number.parseInt(bound.trim(), 10));
142
+ if (Number.isNaN(from)) {
143
+ continue;
144
+ }
145
+ const last = to === void 0 || Number.isNaN(to) ? from : to;
146
+ for (let line = from; line <= last; line += 1) {
147
+ lines.add(line);
148
+ }
149
+ }
150
+ return lines;
151
+ }
152
+ function closingSpan(html, from) {
153
+ let depth = 0;
154
+ let cursor = from;
155
+ while (cursor < html.length) {
156
+ const open = html.indexOf("<span", cursor);
157
+ const close = html.indexOf(SPAN_CLOSE, cursor);
158
+ if (close === -1) {
159
+ return -1;
160
+ }
161
+ if (open !== -1 && open < close) {
162
+ depth += 1;
163
+ cursor = open + 5;
164
+ continue;
165
+ }
166
+ if (depth === 0) {
167
+ return close;
168
+ }
169
+ depth -= 1;
170
+ cursor = close + SPAN_CLOSE.length;
171
+ }
172
+ return -1;
173
+ }
174
+ function splitHighlightedLines(html) {
175
+ const lines = [];
176
+ let cursor = html.indexOf(LINE_OPEN);
177
+ while (cursor !== -1) {
178
+ const start = cursor + LINE_OPEN.length;
179
+ const end = closingSpan(html, start);
180
+ if (end === -1) {
181
+ return null;
182
+ }
183
+ lines.push(html.slice(start, end));
184
+ cursor = html.indexOf(LINE_OPEN, end);
185
+ }
186
+ return lines.length > 0 ? lines : null;
187
+ }
188
+ var codeBlockLabels = {
189
+ copyLabel: "Copy",
190
+ copiedLabel: "Copied",
191
+ expandLabel: "Expand",
192
+ collapseLabel: "Collapse"
193
+ };
194
+ function CodeBlock({
195
+ code,
196
+ language,
197
+ html,
198
+ filename,
199
+ lineNumbers = false,
200
+ highlightLines,
201
+ maxHeight,
202
+ copyLabel,
203
+ copiedLabel,
204
+ expandLabel,
205
+ collapseLabel,
206
+ className,
207
+ slotName = "code-block",
208
+ ...props
209
+ }) {
210
+ const labels = useUiLabels("codeBlock", codeBlockLabels, {
211
+ copyLabel,
212
+ copiedLabel,
213
+ expandLabel,
214
+ collapseLabel
215
+ });
216
+ const highlighted = useHighlightedCode(code, language, html);
217
+ const lines = React2.useMemo(() => splitSourceLines(code), [code]);
218
+ const markup = React2.useMemo(
219
+ () => highlighted === null ? null : splitHighlightedLines(highlighted),
220
+ [highlighted]
221
+ );
222
+ const emphasised = React2.useMemo(
223
+ () => parseLineRanges(highlightLines),
224
+ [highlightLines]
225
+ );
226
+ const bodyRef = React2.useRef(null);
227
+ const [expanded, setExpanded] = React2.useState(false);
228
+ const [clipped, setClipped] = React2.useState(false);
229
+ React2.useEffect(() => {
230
+ const body = bodyRef.current;
231
+ if (!body || maxHeight === void 0 || expanded) {
232
+ return;
233
+ }
234
+ setClipped(body.scrollHeight > body.clientHeight + 1);
235
+ }, [maxHeight, expanded, lines, markup]);
236
+ return /* @__PURE__ */ jsxs(
237
+ "div",
238
+ {
239
+ className: cn(
240
+ elevatedSurface,
241
+ nestedSurfaceReset,
242
+ "relative overflow-hidden bg-card",
243
+ className
244
+ ),
245
+ ...props,
246
+ "data-slot": slotName,
247
+ children: [
248
+ filename === void 0 ? /* @__PURE__ */ jsx(
249
+ CopyButton,
250
+ {
251
+ value: code,
252
+ copyLabel: labels.copyLabel,
253
+ copiedLabel: labels.copiedLabel,
254
+ className: "top-2 right-2 absolute z-10 text-muted-foreground"
255
+ }
256
+ ) : /* @__PURE__ */ jsx(
257
+ CodeBlockHeader,
258
+ {
259
+ filename,
260
+ language,
261
+ code,
262
+ copyLabel: labels.copyLabel,
263
+ copiedLabel: labels.copiedLabel
264
+ }
265
+ ),
266
+ /* @__PURE__ */ jsx(
267
+ "div",
268
+ {
269
+ ref: bodyRef,
270
+ "data-slot": "code-block-body",
271
+ style: { maxHeight: expanded ? void 0 : maxHeight },
272
+ className: "py-4 font-mono text-sm leading-6 overflow-auto rounded-[inherit]",
273
+ children: /* @__PURE__ */ jsx("pre", { className: "w-max min-w-full", children: /* @__PURE__ */ jsx("code", { "data-slot": "code-block-code", children: lines.map((line, index) => /* @__PURE__ */ jsx(
274
+ CodeBlockLine,
275
+ {
276
+ number: index + 1,
277
+ line,
278
+ markup: markup?.[index],
279
+ lineNumbers,
280
+ emphasised: emphasised.has(index + 1)
281
+ },
282
+ index
283
+ )) }) })
284
+ }
285
+ ),
286
+ clipped && /* @__PURE__ */ jsx(
287
+ CodeBlockExpander,
288
+ {
289
+ expanded,
290
+ expandLabel: labels.expandLabel,
291
+ collapseLabel: labels.collapseLabel,
292
+ onToggle: () => setExpanded((open) => !open)
293
+ }
294
+ )
295
+ ]
296
+ }
297
+ );
298
+ }
299
+ function CodeBlockLine({
300
+ number,
301
+ line,
302
+ markup,
303
+ lineNumbers,
304
+ emphasised,
305
+ slotName = "code-block-line"
306
+ }) {
307
+ return /* @__PURE__ */ jsxs(
308
+ "span",
309
+ {
310
+ "data-highlighted": emphasised ? "" : void 0,
311
+ className: cn(
312
+ "min-h-6 px-4 grid w-full data-highlighted:bg-accent",
313
+ lineNumbers ? "grid-cols-[2.5rem_1fr]" : "grid-cols-1"
314
+ ),
315
+ "data-slot": slotName,
316
+ children: [
317
+ lineNumbers && /* @__PURE__ */ jsx(
318
+ "span",
319
+ {
320
+ "data-slot": "code-block-gutter",
321
+ "aria-hidden": "true",
322
+ className: "pr-4 text-right text-muted-foreground select-none",
323
+ children: number
324
+ }
325
+ ),
326
+ markup === void 0 ? /* @__PURE__ */ jsx("span", { "data-slot": "code-block-source", children: line }) : /* @__PURE__ */ jsx(
327
+ "span",
328
+ {
329
+ "data-slot": "code-block-source",
330
+ dangerouslySetInnerHTML: { __html: markup }
331
+ }
332
+ )
333
+ ]
334
+ }
335
+ );
336
+ }
337
+ function CodeBlockExpander({
338
+ expanded,
339
+ expandLabel,
340
+ collapseLabel,
341
+ onToggle,
342
+ slotName = "code-block-expander"
343
+ }) {
344
+ return /* @__PURE__ */ jsxs(
345
+ "div",
346
+ {
347
+ className: "inset-x-0 bottom-0 pt-10 pb-2 absolute flex justify-center",
348
+ "data-slot": slotName,
349
+ children: [
350
+ !expanded && /* @__PURE__ */ jsx(
351
+ "span",
352
+ {
353
+ "aria-hidden": "true",
354
+ className: "inset-0 pointer-events-none absolute bg-gradient-to-t from-card to-transparent"
355
+ }
356
+ ),
357
+ /* @__PURE__ */ jsx(
358
+ Button,
359
+ {
360
+ type: "button",
361
+ variant: "secondary",
362
+ size: "sm",
363
+ onClick: onToggle,
364
+ children: expanded ? collapseLabel : expandLabel
365
+ }
366
+ )
367
+ ]
368
+ }
369
+ );
370
+ }
371
+
372
+ // src/lib/json-value.ts
373
+ var CIRCULAR_MARKER = "[Circular]";
374
+ function jsonKind(value) {
375
+ if (value === null) {
376
+ return "null";
377
+ }
378
+ if (Array.isArray(value)) {
379
+ return "array";
380
+ }
381
+ switch (typeof value) {
382
+ case "string":
383
+ return "string";
384
+ case "number":
385
+ return Number.isFinite(value) ? "number" : "unsupported";
386
+ case "boolean":
387
+ return "boolean";
388
+ case "object":
389
+ return "object";
390
+ default:
391
+ return "unsupported";
392
+ }
393
+ }
394
+ function isBranch(kind) {
395
+ return kind === "object" || kind === "array";
396
+ }
397
+ function entriesOf(value) {
398
+ if (Array.isArray(value)) {
399
+ return value.map((item, index) => [String(index), item]);
400
+ }
401
+ if (value !== null && typeof value === "object") {
402
+ return Object.entries(value);
403
+ }
404
+ return [];
405
+ }
406
+ function serialisable(value, ancestors) {
407
+ if (typeof value === "bigint") {
408
+ return value.toString();
409
+ }
410
+ if (value === null || typeof value !== "object") {
411
+ return value;
412
+ }
413
+ if (ancestors.includes(value)) {
414
+ return CIRCULAR_MARKER;
415
+ }
416
+ const trail = [...ancestors, value];
417
+ if (Array.isArray(value)) {
418
+ return value.map((item) => serialisable(item, trail));
419
+ }
420
+ return Object.fromEntries(
421
+ Object.entries(value).map(([key, item]) => [
422
+ key,
423
+ serialisable(item, trail)
424
+ ])
425
+ );
426
+ }
427
+ function stringifyJson(value) {
428
+ return JSON.stringify(serialisable(value, []), null, 2) ?? "null";
429
+ }
430
+ var LEAF_CLASS = {
431
+ string: "text-success",
432
+ number: "text-primary",
433
+ boolean: "text-destructive",
434
+ null: "text-muted-foreground",
435
+ object: "text-foreground",
436
+ array: "text-foreground",
437
+ unsupported: "text-muted-foreground italic"
438
+ };
439
+ var BRACKETS = {
440
+ object: ["{", "}"],
441
+ array: ["[", "]"]
442
+ };
443
+ function leafText(value, kind) {
444
+ if (kind === "string") {
445
+ return `"${String(value)}"`;
446
+ }
447
+ if (kind === "null") {
448
+ return "null";
449
+ }
450
+ return String(value);
451
+ }
452
+ function JsonKey({
453
+ name,
454
+ slotName = "json-viewer-key"
455
+ }) {
456
+ return /* @__PURE__ */ jsxs("span", { className: "font-medium text-foreground", "data-slot": slotName, children: [
457
+ name,
458
+ ":"
459
+ ] });
460
+ }
461
+ function JsonNode({
462
+ name,
463
+ value,
464
+ depth,
465
+ initialDepth,
466
+ ancestors,
467
+ labels,
468
+ slotName = "json-viewer-node"
469
+ }) {
470
+ const kind = jsonKind(value);
471
+ const branch = isBranch(kind);
472
+ const circular = branch && ancestors.includes(value);
473
+ const [open, setOpen] = React2.useState(depth < initialDepth);
474
+ const entries = React2.useMemo(
475
+ () => branch && !circular ? entriesOf(value) : [],
476
+ [branch, circular, value]
477
+ );
478
+ const trail = React2.useMemo(
479
+ () => branch ? [...ancestors, value] : ancestors,
480
+ [branch, ancestors, value]
481
+ );
482
+ if (!branch || circular) {
483
+ return /* @__PURE__ */ jsxs("div", { className: "gap-2 py-0.5 pl-5 flex", "data-slot": slotName, children: [
484
+ name !== void 0 && /* @__PURE__ */ jsx(JsonKey, { name }),
485
+ circular ? /* @__PURE__ */ jsx(
486
+ "span",
487
+ {
488
+ "data-slot": "json-viewer-circular",
489
+ className: "text-muted-foreground italic",
490
+ children: labels.circularLabel
491
+ }
492
+ ) : /* @__PURE__ */ jsx(
493
+ "span",
494
+ {
495
+ "data-slot": "json-viewer-value",
496
+ className: cn("break-all", LEAF_CLASS[kind]),
497
+ children: leafText(value, kind)
498
+ }
499
+ )
500
+ ] });
501
+ }
502
+ const [opening, closing] = BRACKETS[kind === "array" ? "array" : "object"];
503
+ return /* @__PURE__ */ jsxs("div", { "data-slot": slotName, children: [
504
+ /* @__PURE__ */ jsxs(
505
+ "button",
506
+ {
507
+ type: "button",
508
+ "data-slot": "json-viewer-toggle",
509
+ "aria-expanded": open,
510
+ "aria-label": open ? labels.collapseLabel : labels.expandLabel,
511
+ onClick: () => setOpen((current) => !current),
512
+ className: cn(
513
+ "gap-2 rounded-xl py-0.5 flex w-full cursor-pointer items-center text-left hover:bg-accent",
514
+ focusRing
515
+ ),
516
+ children: [
517
+ /* @__PURE__ */ jsx(
518
+ ChevronRight,
519
+ {
520
+ "aria-hidden": "true",
521
+ className: cn(
522
+ "size-3.5 shrink-0 text-muted-foreground transition-transform",
523
+ open && "rotate-90"
524
+ )
525
+ }
526
+ ),
527
+ name !== void 0 && /* @__PURE__ */ jsx(JsonKey, { name }),
528
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: opening }),
529
+ !open && /* @__PURE__ */ jsxs(Fragment, { children: [
530
+ /* @__PURE__ */ jsx(
531
+ "span",
532
+ {
533
+ "data-slot": "json-viewer-summary",
534
+ className: "text-xs font-medium text-muted-foreground",
535
+ children: labels.entriesLabel(entries.length)
536
+ }
537
+ ),
538
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: closing })
539
+ ] })
540
+ ]
541
+ }
542
+ ),
543
+ open && /* @__PURE__ */ jsxs("div", { className: "ml-1.5 pl-3 border-l border-border", children: [
544
+ entries.map(([key, item]) => /* @__PURE__ */ jsx(
545
+ JsonNode,
546
+ {
547
+ name: key,
548
+ value: item,
549
+ depth: depth + 1,
550
+ initialDepth,
551
+ ancestors: trail,
552
+ labels
553
+ },
554
+ key
555
+ )),
556
+ /* @__PURE__ */ jsx("div", { className: "pl-5 text-muted-foreground", children: closing })
557
+ ] })
558
+ ] });
559
+ }
560
+ var jsonViewerLabels = {
561
+ copyLabel: "Copy",
562
+ copiedLabel: "Copied",
563
+ expandLabel: "Expand",
564
+ collapseLabel: "Collapse",
565
+ circularLabel: "Circular reference",
566
+ entriesLabel: (count) => `${count} ${count === 1 ? "entry" : "entries"}`
567
+ };
568
+ function JsonViewer({
569
+ value,
570
+ initialDepth = 1,
571
+ maxHeight,
572
+ copyLabel,
573
+ copiedLabel,
574
+ expandLabel,
575
+ collapseLabel,
576
+ circularLabel,
577
+ entriesLabel,
578
+ className,
579
+ slotName = "json-viewer",
580
+ ...props
581
+ }) {
582
+ const text = useUiLabels("jsonViewer", jsonViewerLabels, {
583
+ copyLabel,
584
+ copiedLabel,
585
+ expandLabel,
586
+ collapseLabel,
587
+ circularLabel,
588
+ entriesLabel
589
+ });
590
+ const labels = React2.useMemo(
591
+ () => ({
592
+ expandLabel: text.expandLabel,
593
+ collapseLabel: text.collapseLabel,
594
+ circularLabel: text.circularLabel,
595
+ entriesLabel: text.entriesLabel
596
+ }),
597
+ [
598
+ text.expandLabel,
599
+ text.collapseLabel,
600
+ text.circularLabel,
601
+ text.entriesLabel
602
+ ]
603
+ );
604
+ return /* @__PURE__ */ jsxs(
605
+ "div",
606
+ {
607
+ className: cn(
608
+ elevatedSurface,
609
+ nestedSurfaceReset,
610
+ "relative overflow-hidden bg-card",
611
+ className
612
+ ),
613
+ ...props,
614
+ "data-slot": slotName,
615
+ children: [
616
+ /* @__PURE__ */ jsx(
617
+ CopyButton,
618
+ {
619
+ value: stringifyJson(value),
620
+ copyLabel: text.copyLabel,
621
+ copiedLabel: text.copiedLabel,
622
+ className: "top-2 right-2 absolute z-10 text-muted-foreground"
623
+ }
624
+ ),
625
+ /* @__PURE__ */ jsx(
626
+ "div",
627
+ {
628
+ "data-slot": "json-viewer-body",
629
+ style: { maxHeight },
630
+ className: "p-4 pr-12 font-mono text-sm leading-6 overflow-auto rounded-[inherit]",
631
+ children: /* @__PURE__ */ jsx(
632
+ JsonNode,
633
+ {
634
+ value,
635
+ depth: 0,
636
+ initialDepth,
637
+ ancestors: [],
638
+ labels
639
+ }
640
+ )
641
+ }
642
+ )
643
+ ]
644
+ }
645
+ );
646
+ }
647
+
648
+ export { Code, CodeBlock, JsonViewer, codeBlockLabels, jsonViewerLabels };
649
+ //# sourceMappingURL=code.js.map
650
+ //# sourceMappingURL=code.js.map