@usetheo/ui 0.17.0 → 0.19.0
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.
- package/dist/components/composites/trend-chart/index.d.ts +1 -0
- package/dist/components/composites/trend-chart/trend-chart.d.ts +44 -0
- package/dist/components/primitives/description-list/description-list.d.ts +33 -0
- package/dist/components/primitives/description-list/index.d.ts +1 -0
- package/dist/components/primitives/json-viewer/index.d.ts +1 -0
- package/dist/components/primitives/json-viewer/json-viewer.d.ts +32 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +520 -132
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { linScale, niceMax, seriesPath, TrendChart, type TrendChartProps, type TrendPoint, type TrendSeries, } from "./trend-chart.js";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* TrendChart — multi-series time-trend chart in pure SVG (no chart lib —
|
|
4
|
+
* keeps the registry copy-pasteable). Promoted from the theo-cloud dashboard
|
|
5
|
+
* (production since M51, with the M76 sparse-marker and M90 ragged-series
|
|
6
|
+
* lessons pinned by tests).
|
|
7
|
+
*
|
|
8
|
+
* Input contract: `y` values are expected finite and >= 0 (latency, counts);
|
|
9
|
+
* non-finite points are skipped in the line and read as "—" in the table;
|
|
10
|
+
* gaps are modeled by OMITTING the point (the a11y table reads each value
|
|
11
|
+
* under its own period — never positionally). Points are connected in the
|
|
12
|
+
* order given; sort by `x` upstream. Series `color` is any CSS color — prefer
|
|
13
|
+
* theme tokens (e.g. `var(--primary)`).
|
|
14
|
+
*
|
|
15
|
+
* <TrendChart title="Latency" valueFormatter={(v) => `${v}ms`}
|
|
16
|
+
* series={[{ name: "p50", color: "var(--primary)", points }]} />
|
|
17
|
+
*/
|
|
18
|
+
export interface TrendPoint {
|
|
19
|
+
/** X in the series' own units (bucket index or epoch-ms); scaled linearly. */
|
|
20
|
+
x: number;
|
|
21
|
+
/** Y value for this point. */
|
|
22
|
+
y: number;
|
|
23
|
+
}
|
|
24
|
+
export interface TrendSeries {
|
|
25
|
+
name: string;
|
|
26
|
+
/** CSS color for the line + legend swatch (prefer theme tokens). */
|
|
27
|
+
color: string;
|
|
28
|
+
points: TrendPoint[];
|
|
29
|
+
}
|
|
30
|
+
/** Linear scale mapping a value in `domain` to `range`. A zero-width domain maps everything to r0. */
|
|
31
|
+
export declare function linScale(domain: [number, number], range: [number, number]): (v: number) => number;
|
|
32
|
+
/** A clean upper Y bound ≥ max(values). Returns 0 when there is no positive value. */
|
|
33
|
+
export declare function niceMax(values: number[]): number;
|
|
34
|
+
/** SVG path `d` for a polyline over the given scales. Non-finite points are skipped. */
|
|
35
|
+
export declare function seriesPath(points: TrendPoint[], xScale: (x: number) => number, yScale: (y: number) => number): string;
|
|
36
|
+
export interface TrendChartProps extends HTMLAttributes<HTMLElement> {
|
|
37
|
+
title: string;
|
|
38
|
+
series: TrendSeries[];
|
|
39
|
+
height?: number;
|
|
40
|
+
/** Formats y-axis labels and table cells (tremor vocabulary). */
|
|
41
|
+
valueFormatter?: (v: number) => string;
|
|
42
|
+
}
|
|
43
|
+
declare const TrendChart: import("react").ForwardRefExoticComponent<TrendChartProps & import("react").RefAttributes<HTMLElement>>;
|
|
44
|
+
export { TrendChart };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* DescriptionList — semantic key/value pairs on native `dl/dt/dd`.
|
|
4
|
+
*
|
|
5
|
+
* Layouts: `vertical` (default — stacked groups) and `horizontal` (two-column
|
|
6
|
+
* grid: terms in a fixed max-content column, details beside them; the Item
|
|
7
|
+
* wrapper uses `display: contents` so dt/dd participate in the root grid).
|
|
8
|
+
* `dense` tightens the gaps for crowded detail panels.
|
|
9
|
+
*
|
|
10
|
+
* <DescriptionList layout="horizontal">
|
|
11
|
+
* <DescriptionList.Item>
|
|
12
|
+
* <DescriptionList.Term>Status</DescriptionList.Term>
|
|
13
|
+
* <DescriptionList.Detail><Badge>live</Badge></DescriptionList.Detail>
|
|
14
|
+
* </DescriptionList.Item>
|
|
15
|
+
* </DescriptionList>
|
|
16
|
+
*
|
|
17
|
+
* One Term per Item; multiple Details per Term are valid HTML and supported.
|
|
18
|
+
* Composing dd without a preceding dt is the consumer's responsibility
|
|
19
|
+
* (invalid HTML — same contract as Breadcrumb.Page placement).
|
|
20
|
+
*/
|
|
21
|
+
interface DescriptionListProps extends HTMLAttributes<HTMLDListElement> {
|
|
22
|
+
/** vertical (default): stacked groups. horizontal: term column + detail column. */
|
|
23
|
+
layout?: "vertical" | "horizontal";
|
|
24
|
+
/** Compact spacing for dense detail panels. */
|
|
25
|
+
dense?: boolean;
|
|
26
|
+
}
|
|
27
|
+
declare const DescriptionList: import("react").ForwardRefExoticComponent<DescriptionListProps & import("react").RefAttributes<HTMLDListElement>> & {
|
|
28
|
+
Item: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
29
|
+
Term: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
|
|
30
|
+
Detail: import("react").ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
|
|
31
|
+
};
|
|
32
|
+
export { DescriptionList };
|
|
33
|
+
export type { DescriptionListProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DescriptionList, type DescriptionListProps } from "./description-list.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { JsonViewer, type JsonViewerProps } from "./json-viewer.js";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* JsonViewer — read-only collapsible JSON tree, dependency-free.
|
|
4
|
+
*
|
|
5
|
+
* Collapse: `collapsed` mirrors the SOTA contract — `true` collapses every
|
|
6
|
+
* node, a number collapses everything at depth >= N (root is depth 0).
|
|
7
|
+
* Collapsed subtrees are NOT rendered (lazy): that is the performance guard —
|
|
8
|
+
* a huge payload fully expanded is the consumer's responsibility (ADR D1);
|
|
9
|
+
* prefer `collapsed={1}` for large payloads.
|
|
10
|
+
*
|
|
11
|
+
* Safety: circular references render a "[Circular]" marker (and serialize as
|
|
12
|
+
* such on copy) instead of overflowing the stack. Copy limitation: the
|
|
13
|
+
* serializer conservatively marks REPEATED (shared, non-circular) references
|
|
14
|
+
* as "[Circular]" too — output is always JSON.parse-able — the studied SOTA reference
|
|
15
|
+
* does not handle this. BigInt renders with the `n` suffix; NaN/Infinity
|
|
16
|
+
* follow JSON semantics on copy (null).
|
|
17
|
+
*
|
|
18
|
+
* <JsonViewer value={eventPayload} collapsed={1} enableCopy />
|
|
19
|
+
*/
|
|
20
|
+
interface JsonViewerProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
|
|
21
|
+
/** Data to render. Any value — objects, arrays, primitives, BigInt, Date. */
|
|
22
|
+
value: unknown;
|
|
23
|
+
/** true = all collapsed; number = collapse at depth >= N. Default: all expanded. */
|
|
24
|
+
collapsed?: boolean | number;
|
|
25
|
+
/** Truncate strings longer than this (click to reveal). Default 60. */
|
|
26
|
+
shortenTextAfterLength?: number;
|
|
27
|
+
/** Show a copy button on the root and on object/array nodes. */
|
|
28
|
+
enableCopy?: boolean;
|
|
29
|
+
}
|
|
30
|
+
declare const JsonViewer: import("react").ForwardRefExoticComponent<JsonViewerProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
31
|
+
export { JsonViewer };
|
|
32
|
+
export type { JsonViewerProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export { cn } from "./lib/cn.js";
|
|
|
2
2
|
export { Button, buttonVariants, type ButtonProps } from "./components/primitives/button/index.js";
|
|
3
3
|
export { Badge, badgeVariants, type BadgeProps } from "./components/primitives/badge/index.js";
|
|
4
4
|
export { Breadcrumb, type BreadcrumbLinkProps, } from "./components/primitives/breadcrumb/index.js";
|
|
5
|
+
export { DescriptionList, type DescriptionListProps, } from "./components/primitives/description-list/index.js";
|
|
6
|
+
export { JsonViewer, type JsonViewerProps } from "./components/primitives/json-viewer/index.js";
|
|
5
7
|
export { Combobox, type ComboboxContentProps, type ComboboxInputProps, type ComboboxItemProps, type ComboboxProps, } from "./components/primitives/combobox/index.js";
|
|
6
8
|
export { Slider, type SliderMark, type SliderProps, } from "./components/primitives/slider/index.js";
|
|
7
9
|
export { UpdateBanner, type UpdateBannerProps, } from "./components/primitives/update-banner/index.js";
|
|
@@ -45,6 +47,7 @@ export { ActionBar, type ActionBarProps } from "./components/primitives/action-b
|
|
|
45
47
|
export { PinInput, type PinInputProps } from "./components/primitives/pin-input/index.js";
|
|
46
48
|
export { DataTable, type DataTableColumn, type DataTableProps, type DataTableSort, } from "./components/composites/data-table/index.js";
|
|
47
49
|
export { PageShell, type PageShellProps } from "./components/composites/page-shell/index.js";
|
|
50
|
+
export { linScale, niceMax, seriesPath, TrendChart, type TrendChartProps, type TrendPoint, type TrendSeries, } from "./components/composites/trend-chart/index.js";
|
|
48
51
|
export { MetricsPanel, type Metric } from "./components/primitives/metrics-panel/index.js";
|
|
49
52
|
export { SocialAuthRow, type SocialProvider, } from "./components/primitives/social-auth-row/index.js";
|
|
50
53
|
export { LoginSplit } from "./components/primitives/login-split/index.js";
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,9 @@ import { clsx } from 'clsx';
|
|
|
2
2
|
import { extendTailwindMerge } from 'tailwind-merge';
|
|
3
3
|
import { Slot } from '@radix-ui/react-slot';
|
|
4
4
|
import { cva } from 'class-variance-authority';
|
|
5
|
-
import { forwardRef,
|
|
5
|
+
import { forwardRef, useState, useRef, useEffect, useCallback, createContext, useId, useMemo, Children, isValidElement, cloneElement, Fragment as Fragment$1, useContext, createElement } from 'react';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
|
-
import {
|
|
7
|
+
import { Check, X, Copy, Loader2, ArrowUpCircle, AlertCircle, ChevronDown, ChevronUp, Minus, Circle, ChevronRight, ChevronsUpDown, TrendingDown, TrendingUp, ArrowUpRight, TriangleAlert, CheckCircle2, Info, ChevronsLeft, ChevronLeft, ChevronsRight, Search, Filter, GitCommit, GitBranch, Activity, Plus, Lock, EyeOff, Eye, Trash2, GitPullRequest, Server, ExternalLink, Globe, ShieldCheck, ShieldX, Clock, RotateCcw, ArrowDownLeft, MoreHorizontal } from 'lucide-react';
|
|
8
8
|
import { Command, useCommandState } from 'cmdk';
|
|
9
9
|
import * as SliderPrimitive from '@radix-ui/react-slider';
|
|
10
10
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
@@ -287,6 +287,329 @@ var Breadcrumb = Object.assign(Root, {
|
|
|
287
287
|
Separator,
|
|
288
288
|
Ellipsis
|
|
289
289
|
});
|
|
290
|
+
function sub2(tag, slot, displayName, baseClass) {
|
|
291
|
+
const Component = forwardRef(
|
|
292
|
+
({ className, children, ...props }, ref) => createElement(
|
|
293
|
+
tag,
|
|
294
|
+
{ "data-slot": slot, ref, className: cn(baseClass, className), ...props },
|
|
295
|
+
children
|
|
296
|
+
)
|
|
297
|
+
);
|
|
298
|
+
Component.displayName = displayName;
|
|
299
|
+
return Component;
|
|
300
|
+
}
|
|
301
|
+
var Root2 = forwardRef(
|
|
302
|
+
({ className, layout = "vertical", dense, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
303
|
+
"dl",
|
|
304
|
+
{
|
|
305
|
+
"data-slot": "description-list",
|
|
306
|
+
"data-layout": layout,
|
|
307
|
+
"data-dense": dense ? "true" : void 0,
|
|
308
|
+
ref,
|
|
309
|
+
className: cn(
|
|
310
|
+
"text-body-sm",
|
|
311
|
+
layout === "vertical" && (dense ? "grid gap-2" : "grid gap-4"),
|
|
312
|
+
layout === "horizontal" && "grid grid-cols-[max-content_1fr] items-baseline [&>div]:contents [&_dd]:col-start-2",
|
|
313
|
+
layout === "horizontal" && (dense ? "gap-x-4 gap-y-1.5" : "gap-x-6 gap-y-3"),
|
|
314
|
+
className
|
|
315
|
+
),
|
|
316
|
+
...props
|
|
317
|
+
}
|
|
318
|
+
)
|
|
319
|
+
);
|
|
320
|
+
Root2.displayName = "DescriptionList";
|
|
321
|
+
var Item2 = sub2(
|
|
322
|
+
"div",
|
|
323
|
+
"description-list-item",
|
|
324
|
+
"DescriptionList.Item",
|
|
325
|
+
"grid gap-1"
|
|
326
|
+
);
|
|
327
|
+
var Term = sub2(
|
|
328
|
+
"dt",
|
|
329
|
+
"description-list-term",
|
|
330
|
+
"DescriptionList.Term",
|
|
331
|
+
"font-medium text-muted-foreground"
|
|
332
|
+
);
|
|
333
|
+
var Detail = sub2(
|
|
334
|
+
"dd",
|
|
335
|
+
"description-list-detail",
|
|
336
|
+
"DescriptionList.Detail",
|
|
337
|
+
"m-0 text-foreground"
|
|
338
|
+
);
|
|
339
|
+
var DescriptionList = Object.assign(Root2, { Item: Item2, Term, Detail });
|
|
340
|
+
var VARIANT = {
|
|
341
|
+
ghost: "hover:bg-muted",
|
|
342
|
+
outline: "border border-border/60 rounded-md"
|
|
343
|
+
};
|
|
344
|
+
var SIZE = {
|
|
345
|
+
sm: "px-2 py-1 text-label",
|
|
346
|
+
md: "px-2.5 py-1.5 text-body-sm"
|
|
347
|
+
};
|
|
348
|
+
var CopyButton = forwardRef(
|
|
349
|
+
({
|
|
350
|
+
className,
|
|
351
|
+
value,
|
|
352
|
+
label,
|
|
353
|
+
variant = "ghost",
|
|
354
|
+
size = "sm",
|
|
355
|
+
onCopied,
|
|
356
|
+
feedbackDuration = 1500,
|
|
357
|
+
...props
|
|
358
|
+
}, ref) => {
|
|
359
|
+
const [state, setState] = useState("idle");
|
|
360
|
+
const timerRef = useRef(null);
|
|
361
|
+
useEffect(() => {
|
|
362
|
+
return () => {
|
|
363
|
+
if (timerRef.current !== null) {
|
|
364
|
+
clearTimeout(timerRef.current);
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
}, []);
|
|
368
|
+
const scheduleRevert = useCallback(() => {
|
|
369
|
+
if (timerRef.current !== null) {
|
|
370
|
+
clearTimeout(timerRef.current);
|
|
371
|
+
}
|
|
372
|
+
timerRef.current = setTimeout(() => {
|
|
373
|
+
setState("idle");
|
|
374
|
+
timerRef.current = null;
|
|
375
|
+
}, feedbackDuration);
|
|
376
|
+
}, [feedbackDuration]);
|
|
377
|
+
const handleClick = useCallback(() => {
|
|
378
|
+
if (state !== "idle") return;
|
|
379
|
+
if (typeof navigator === "undefined" || !navigator.clipboard?.writeText) {
|
|
380
|
+
setState("failed");
|
|
381
|
+
scheduleRevert();
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
navigator.clipboard.writeText(value).then(
|
|
385
|
+
() => {
|
|
386
|
+
setState("copied");
|
|
387
|
+
onCopied?.(value);
|
|
388
|
+
scheduleRevert();
|
|
389
|
+
},
|
|
390
|
+
() => {
|
|
391
|
+
setState("failed");
|
|
392
|
+
scheduleRevert();
|
|
393
|
+
}
|
|
394
|
+
);
|
|
395
|
+
}, [state, value, onCopied, scheduleRevert]);
|
|
396
|
+
const Icon2 = state === "copied" ? Check : state === "failed" ? X : Copy;
|
|
397
|
+
const liveMessage = state === "copied" ? "Copied to clipboard" : state === "failed" ? "Copy failed" : "";
|
|
398
|
+
const labelText = label !== void 0 ? state === "copied" ? "Copied!" : state === "failed" ? "Failed" : label : null;
|
|
399
|
+
return /* @__PURE__ */ jsxs(
|
|
400
|
+
"button",
|
|
401
|
+
{
|
|
402
|
+
"data-slot": "copy-button",
|
|
403
|
+
ref,
|
|
404
|
+
type: "button",
|
|
405
|
+
onClick: handleClick,
|
|
406
|
+
"data-state": state,
|
|
407
|
+
className: cn(
|
|
408
|
+
"inline-flex items-center gap-1.5",
|
|
409
|
+
"font-sans transition-colors",
|
|
410
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-card",
|
|
411
|
+
VARIANT[variant],
|
|
412
|
+
SIZE[size],
|
|
413
|
+
className
|
|
414
|
+
),
|
|
415
|
+
...props,
|
|
416
|
+
children: [
|
|
417
|
+
/* @__PURE__ */ jsx(
|
|
418
|
+
Icon2,
|
|
419
|
+
{
|
|
420
|
+
"aria-hidden": "true",
|
|
421
|
+
className: cn(
|
|
422
|
+
"size-3.5 shrink-0 transition-opacity duration-200",
|
|
423
|
+
state === "copied" && "text-success",
|
|
424
|
+
state === "failed" && "text-destructive"
|
|
425
|
+
)
|
|
426
|
+
}
|
|
427
|
+
),
|
|
428
|
+
labelText !== null ? /* @__PURE__ */ jsx("span", { children: labelText }) : null,
|
|
429
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", "aria-live": "polite", children: liveMessage })
|
|
430
|
+
]
|
|
431
|
+
}
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
);
|
|
435
|
+
CopyButton.displayName = "CopyButton";
|
|
436
|
+
var PATH_SEP = "";
|
|
437
|
+
var EMPTY_CHAIN = { has: () => false };
|
|
438
|
+
function isPlainContainer(value) {
|
|
439
|
+
return typeof value === "object" && value !== null && !(value instanceof Date);
|
|
440
|
+
}
|
|
441
|
+
function safeStringify(value) {
|
|
442
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
443
|
+
return JSON.stringify(
|
|
444
|
+
value,
|
|
445
|
+
(_key, entry) => {
|
|
446
|
+
if (typeof entry === "bigint") return `${entry}n`;
|
|
447
|
+
if (typeof entry === "object" && entry !== null) {
|
|
448
|
+
if (seen.has(entry)) return "[Circular]";
|
|
449
|
+
seen.add(entry);
|
|
450
|
+
}
|
|
451
|
+
return entry;
|
|
452
|
+
},
|
|
453
|
+
2
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
function defaultExpanded(depth, collapsed) {
|
|
457
|
+
if (collapsed === true) return false;
|
|
458
|
+
if (typeof collapsed === "number") return depth < collapsed;
|
|
459
|
+
return true;
|
|
460
|
+
}
|
|
461
|
+
function PrimitiveValue({
|
|
462
|
+
value,
|
|
463
|
+
shortenAfter
|
|
464
|
+
}) {
|
|
465
|
+
const [revealed, setRevealed] = useState(false);
|
|
466
|
+
if (typeof value === "string") {
|
|
467
|
+
const shorten = !revealed && value.length > shortenAfter;
|
|
468
|
+
const text2 = shorten ? `${value.slice(0, shortenAfter)}\u2026` : `"${value}"`;
|
|
469
|
+
return /* @__PURE__ */ jsx(
|
|
470
|
+
"span",
|
|
471
|
+
{
|
|
472
|
+
"data-slot": "json-viewer-value",
|
|
473
|
+
"data-type": "string",
|
|
474
|
+
className: cn("text-success", shorten && "cursor-pointer underline decoration-dotted"),
|
|
475
|
+
onClick: shorten ? () => setRevealed(true) : void 0,
|
|
476
|
+
onKeyDown: shorten ? (e) => {
|
|
477
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
478
|
+
e.preventDefault();
|
|
479
|
+
setRevealed(true);
|
|
480
|
+
}
|
|
481
|
+
} : void 0,
|
|
482
|
+
role: shorten ? "button" : void 0,
|
|
483
|
+
tabIndex: shorten ? 0 : void 0,
|
|
484
|
+
children: text2
|
|
485
|
+
}
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
let text;
|
|
489
|
+
let type = typeof value;
|
|
490
|
+
if (typeof value === "bigint") text = `${value}n`;
|
|
491
|
+
else if (value === null) {
|
|
492
|
+
text = "null";
|
|
493
|
+
type = "null";
|
|
494
|
+
} else if (value === void 0) text = "undefined";
|
|
495
|
+
else if (typeof value === "function") text = "\u0192";
|
|
496
|
+
else if (value instanceof Date) {
|
|
497
|
+
text = value.toISOString();
|
|
498
|
+
type = "date";
|
|
499
|
+
} else text = String(value);
|
|
500
|
+
return /* @__PURE__ */ jsx("span", { "data-slot": "json-viewer-value", "data-type": type, className: "text-info", children: text });
|
|
501
|
+
}
|
|
502
|
+
function JsonNode(props) {
|
|
503
|
+
const { nodeKey, value, path, depth, ancestors, viewer, expandedOverrides, onToggle } = props;
|
|
504
|
+
const copyValue = useMemo(
|
|
505
|
+
() => viewer.enableCopy && isPlainContainer(value) ? safeStringify(value) : "",
|
|
506
|
+
[value, viewer.enableCopy]
|
|
507
|
+
);
|
|
508
|
+
const keyLabel = nodeKey !== void 0 ? /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
509
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "json-viewer-key", children: nodeKey === "" ? '""' : nodeKey }),
|
|
510
|
+
":"
|
|
511
|
+
] }) : null;
|
|
512
|
+
if (isPlainContainer(value) && ancestors.has(value)) {
|
|
513
|
+
return /* @__PURE__ */ jsxs("li", { "data-slot": "json-viewer-node", className: "flex items-baseline gap-1.5", children: [
|
|
514
|
+
keyLabel,
|
|
515
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "json-viewer-value", "data-type": "circular", className: "text-warning", children: "[Circular]" })
|
|
516
|
+
] });
|
|
517
|
+
}
|
|
518
|
+
if (!isPlainContainer(value)) {
|
|
519
|
+
return /* @__PURE__ */ jsxs("li", { "data-slot": "json-viewer-node", className: "flex items-baseline gap-1.5", children: [
|
|
520
|
+
keyLabel,
|
|
521
|
+
/* @__PURE__ */ jsx(PrimitiveValue, { value, shortenAfter: viewer.shortenTextAfterLength })
|
|
522
|
+
] });
|
|
523
|
+
}
|
|
524
|
+
const isArray = Array.isArray(value);
|
|
525
|
+
const entries = isArray ? value.map((entry, index) => [String(index), entry]) : Object.entries(value);
|
|
526
|
+
if (entries.length === 0) {
|
|
527
|
+
return /* @__PURE__ */ jsxs("li", { "data-slot": "json-viewer-node", className: "flex items-baseline gap-1.5", children: [
|
|
528
|
+
keyLabel,
|
|
529
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "json-viewer-value", "data-type": isArray ? "array" : "object", children: isArray ? "[]" : "{}" })
|
|
530
|
+
] });
|
|
531
|
+
}
|
|
532
|
+
const expanded = expandedOverrides.get(path) ?? defaultExpanded(depth, viewer.collapsed);
|
|
533
|
+
const badge = isArray ? `[${entries.length}]` : `{${entries.length}}`;
|
|
534
|
+
return /* @__PURE__ */ jsxs("li", { "data-slot": "json-viewer-node", children: [
|
|
535
|
+
/* @__PURE__ */ jsxs("span", { className: "group/node flex items-baseline gap-1.5", children: [
|
|
536
|
+
/* @__PURE__ */ jsx(
|
|
537
|
+
"button",
|
|
538
|
+
{
|
|
539
|
+
type: "button",
|
|
540
|
+
"data-slot": "json-viewer-toggle",
|
|
541
|
+
"aria-expanded": expanded,
|
|
542
|
+
"aria-label": `Toggle ${nodeKey ?? "root"}`,
|
|
543
|
+
onClick: () => onToggle(path, !expanded),
|
|
544
|
+
className: "inline-flex size-4 shrink-0 translate-y-0.5 items-center justify-center rounded text-muted-foreground hover:text-foreground",
|
|
545
|
+
children: /* @__PURE__ */ jsx(
|
|
546
|
+
ChevronRight,
|
|
547
|
+
{
|
|
548
|
+
"aria-hidden": true,
|
|
549
|
+
className: cn("size-3.5 transition-transform", expanded && "rotate-90")
|
|
550
|
+
}
|
|
551
|
+
)
|
|
552
|
+
}
|
|
553
|
+
),
|
|
554
|
+
keyLabel,
|
|
555
|
+
!expanded && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: badge }),
|
|
556
|
+
viewer.enableCopy && /* @__PURE__ */ jsx(
|
|
557
|
+
"span",
|
|
558
|
+
{
|
|
559
|
+
"data-slot": "json-viewer-copy",
|
|
560
|
+
className: "opacity-0 transition-opacity group-focus-within/node:opacity-100 group-hover/node:opacity-100",
|
|
561
|
+
children: /* @__PURE__ */ jsx(CopyButton, { value: copyValue, "aria-label": `Copy ${nodeKey ?? "JSON"}` })
|
|
562
|
+
}
|
|
563
|
+
)
|
|
564
|
+
] }),
|
|
565
|
+
expanded && /* @__PURE__ */ jsx("ul", { className: "m-0 grid list-none gap-0.5 border-border/40 border-l pl-4", children: entries.map(([entryKey, entryValue]) => /* @__PURE__ */ jsx(
|
|
566
|
+
JsonNode,
|
|
567
|
+
{
|
|
568
|
+
nodeKey: entryKey,
|
|
569
|
+
value: entryValue,
|
|
570
|
+
path: path + PATH_SEP + entryKey,
|
|
571
|
+
depth: depth + 1,
|
|
572
|
+
ancestors: {
|
|
573
|
+
has: (candidate) => candidate === value || ancestors.has(candidate)
|
|
574
|
+
},
|
|
575
|
+
viewer,
|
|
576
|
+
expandedOverrides,
|
|
577
|
+
onToggle
|
|
578
|
+
},
|
|
579
|
+
entryKey
|
|
580
|
+
)) })
|
|
581
|
+
] });
|
|
582
|
+
}
|
|
583
|
+
var JsonViewer = forwardRef(
|
|
584
|
+
({ value, collapsed, shortenTextAfterLength = 60, enableCopy = false, className, ...props }, ref) => {
|
|
585
|
+
const [expandedOverrides, setExpandedOverrides] = useState(/* @__PURE__ */ new Map());
|
|
586
|
+
const onToggle = (path, next) => {
|
|
587
|
+
setExpandedOverrides((prev) => new Map(prev).set(path, next));
|
|
588
|
+
};
|
|
589
|
+
return /* @__PURE__ */ jsx(
|
|
590
|
+
"div",
|
|
591
|
+
{
|
|
592
|
+
"data-slot": "json-viewer",
|
|
593
|
+
ref,
|
|
594
|
+
className: cn("font-mono text-code-sm", className),
|
|
595
|
+
...props,
|
|
596
|
+
children: /* @__PURE__ */ jsx("ul", { className: "m-0 grid list-none gap-0.5 p-0", children: /* @__PURE__ */ jsx(
|
|
597
|
+
JsonNode,
|
|
598
|
+
{
|
|
599
|
+
value,
|
|
600
|
+
path: "$",
|
|
601
|
+
depth: 0,
|
|
602
|
+
ancestors: EMPTY_CHAIN,
|
|
603
|
+
viewer: { collapsed, shortenTextAfterLength, enableCopy },
|
|
604
|
+
expandedOverrides,
|
|
605
|
+
onToggle
|
|
606
|
+
}
|
|
607
|
+
) })
|
|
608
|
+
}
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
);
|
|
612
|
+
JsonViewer.displayName = "JsonViewer";
|
|
290
613
|
var inputVariants = cva(
|
|
291
614
|
[
|
|
292
615
|
"flex w-full rounded-md border border-input bg-card",
|
|
@@ -331,12 +654,12 @@ function composeRefs(local, forwarded) {
|
|
|
331
654
|
else if (forwarded) forwarded.current = node;
|
|
332
655
|
};
|
|
333
656
|
}
|
|
334
|
-
function useComboboxContext(
|
|
657
|
+
function useComboboxContext(sub3) {
|
|
335
658
|
const ctx = useContext(ComboboxContext);
|
|
336
|
-
if (!ctx) throw new Error(`<Combobox.${
|
|
659
|
+
if (!ctx) throw new Error(`<Combobox.${sub3}> must be used inside <Combobox>`);
|
|
337
660
|
return ctx;
|
|
338
661
|
}
|
|
339
|
-
var
|
|
662
|
+
var Root3 = forwardRef(
|
|
340
663
|
({
|
|
341
664
|
className,
|
|
342
665
|
children,
|
|
@@ -389,7 +712,7 @@ var Root2 = forwardRef(
|
|
|
389
712
|
) });
|
|
390
713
|
}
|
|
391
714
|
);
|
|
392
|
-
|
|
715
|
+
Root3.displayName = "Combobox";
|
|
393
716
|
var Input2 = forwardRef(
|
|
394
717
|
({ className, onFocus, onKeyDown, onValueChange, ...props }, ref) => {
|
|
395
718
|
const { open, setOpen, listId } = useComboboxContext("Input");
|
|
@@ -471,7 +794,7 @@ var Content = forwardRef(
|
|
|
471
794
|
}
|
|
472
795
|
);
|
|
473
796
|
Content.displayName = "Combobox.Content";
|
|
474
|
-
var
|
|
797
|
+
var Item3 = forwardRef(
|
|
475
798
|
({ className, children, value, onSelect, ...props }, ref) => {
|
|
476
799
|
const ctx = useComboboxContext("Item");
|
|
477
800
|
const selected = value !== void 0 && ctx.value === value;
|
|
@@ -506,7 +829,7 @@ var Item2 = forwardRef(
|
|
|
506
829
|
);
|
|
507
830
|
}
|
|
508
831
|
);
|
|
509
|
-
|
|
832
|
+
Item3.displayName = "Combobox.Item";
|
|
510
833
|
var Empty = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
511
834
|
Command.Empty,
|
|
512
835
|
{
|
|
@@ -517,7 +840,7 @@ var Empty = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
|
517
840
|
}
|
|
518
841
|
));
|
|
519
842
|
Empty.displayName = "Combobox.Empty";
|
|
520
|
-
var Combobox = Object.assign(
|
|
843
|
+
var Combobox = Object.assign(Root3, { Input: Input2, Content, Item: Item3, Empty });
|
|
521
844
|
var Slider = forwardRef(
|
|
522
845
|
({
|
|
523
846
|
className,
|
|
@@ -690,7 +1013,7 @@ var UpdateBanner = forwardRef(
|
|
|
690
1013
|
UpdateBanner.displayName = "UpdateBanner";
|
|
691
1014
|
var CardContext = createContext({ size: "md" });
|
|
692
1015
|
var useCardSize = () => useContext(CardContext).size;
|
|
693
|
-
var
|
|
1016
|
+
var Root5 = forwardRef(
|
|
694
1017
|
({ className, size = "md", ...props }, ref) => /* @__PURE__ */ jsx(CardContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx(
|
|
695
1018
|
"div",
|
|
696
1019
|
{
|
|
@@ -705,7 +1028,7 @@ var Root4 = forwardRef(
|
|
|
705
1028
|
}
|
|
706
1029
|
) })
|
|
707
1030
|
);
|
|
708
|
-
|
|
1031
|
+
Root5.displayName = "Card";
|
|
709
1032
|
var headerPadBySize = {
|
|
710
1033
|
sm: "gap-1 p-3 pb-1.5",
|
|
711
1034
|
md: "gap-1.5 p-5 pb-2.5",
|
|
@@ -807,7 +1130,7 @@ var Footer = forwardRef(
|
|
|
807
1130
|
}
|
|
808
1131
|
);
|
|
809
1132
|
Footer.displayName = "Card.Footer";
|
|
810
|
-
var Card = /* @__PURE__ */ Object.assign(
|
|
1133
|
+
var Card = /* @__PURE__ */ Object.assign(Root5, {
|
|
811
1134
|
Header,
|
|
812
1135
|
Title,
|
|
813
1136
|
Description,
|
|
@@ -967,7 +1290,7 @@ var Tabs = /* @__PURE__ */ Object.assign(TabsPrimitive.Root, {
|
|
|
967
1290
|
Content: Content5
|
|
968
1291
|
});
|
|
969
1292
|
var Provider2 = TooltipPrimitive.Provider;
|
|
970
|
-
var
|
|
1293
|
+
var Root9 = TooltipPrimitive.Root;
|
|
971
1294
|
var Trigger5 = TooltipPrimitive.Trigger;
|
|
972
1295
|
var Content7 = forwardRef(({ className, sideOffset = 6, ...props }, ref) => /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
973
1296
|
TooltipPrimitive.Content,
|
|
@@ -995,13 +1318,13 @@ var Tooltip = ({
|
|
|
995
1318
|
delayDuration = 200,
|
|
996
1319
|
children,
|
|
997
1320
|
...rootProps
|
|
998
|
-
}) => /* @__PURE__ */ jsx(Provider2, { delayDuration, children: /* @__PURE__ */ jsxs(
|
|
1321
|
+
}) => /* @__PURE__ */ jsx(Provider2, { delayDuration, children: /* @__PURE__ */ jsxs(Root9, { ...rootProps, children: [
|
|
999
1322
|
/* @__PURE__ */ jsx(Trigger5, { asChild: true, children }),
|
|
1000
1323
|
/* @__PURE__ */ jsx(Content7, { side, align, children: label })
|
|
1001
1324
|
] }) });
|
|
1002
1325
|
var TooltipWithStatics = Tooltip;
|
|
1003
1326
|
TooltipWithStatics.Provider = Provider2;
|
|
1004
|
-
TooltipWithStatics.Root =
|
|
1327
|
+
TooltipWithStatics.Root = Root9;
|
|
1005
1328
|
TooltipWithStatics.Trigger = Trigger5;
|
|
1006
1329
|
TooltipWithStatics.Content = Content7;
|
|
1007
1330
|
var ScrollAreaRoot = forwardRef(
|
|
@@ -1853,7 +2176,7 @@ var Textarea = forwardRef(
|
|
|
1853
2176
|
)
|
|
1854
2177
|
);
|
|
1855
2178
|
Textarea.displayName = "Textarea";
|
|
1856
|
-
var
|
|
2179
|
+
var Root19 = forwardRef(
|
|
1857
2180
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1858
2181
|
"aside",
|
|
1859
2182
|
{
|
|
@@ -1867,7 +2190,7 @@ var Root18 = forwardRef(
|
|
|
1867
2190
|
}
|
|
1868
2191
|
)
|
|
1869
2192
|
);
|
|
1870
|
-
|
|
2193
|
+
Root19.displayName = "Sidebar";
|
|
1871
2194
|
var Header3 = forwardRef(
|
|
1872
2195
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1873
2196
|
"div",
|
|
@@ -1896,7 +2219,7 @@ var Section = forwardRef(
|
|
|
1896
2219
|
)
|
|
1897
2220
|
);
|
|
1898
2221
|
Section.displayName = "Sidebar.Section";
|
|
1899
|
-
var
|
|
2222
|
+
var Item6 = forwardRef(
|
|
1900
2223
|
({ className, icon: Icon2, active, count, as = "button", href, children, ...props }, ref) => {
|
|
1901
2224
|
const classes = cn(
|
|
1902
2225
|
"group flex w-full items-center gap-3 rounded-lg px-2 py-2",
|
|
@@ -1956,7 +2279,7 @@ var Item5 = forwardRef(
|
|
|
1956
2279
|
);
|
|
1957
2280
|
}
|
|
1958
2281
|
);
|
|
1959
|
-
|
|
2282
|
+
Item6.displayName = "Sidebar.Item";
|
|
1960
2283
|
var Footer3 = forwardRef(
|
|
1961
2284
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1962
2285
|
"div",
|
|
@@ -1969,13 +2292,13 @@ var Footer3 = forwardRef(
|
|
|
1969
2292
|
)
|
|
1970
2293
|
);
|
|
1971
2294
|
Footer3.displayName = "Sidebar.Footer";
|
|
1972
|
-
var Sidebar = /* @__PURE__ */ Object.assign(
|
|
2295
|
+
var Sidebar = /* @__PURE__ */ Object.assign(Root19, {
|
|
1973
2296
|
Header: Header3,
|
|
1974
2297
|
Section,
|
|
1975
|
-
Item:
|
|
2298
|
+
Item: Item6,
|
|
1976
2299
|
Footer: Footer3
|
|
1977
2300
|
});
|
|
1978
|
-
var
|
|
2301
|
+
var Root20 = forwardRef(
|
|
1979
2302
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1980
2303
|
"header",
|
|
1981
2304
|
{
|
|
@@ -1989,7 +2312,7 @@ var Root19 = forwardRef(
|
|
|
1989
2312
|
}
|
|
1990
2313
|
)
|
|
1991
2314
|
);
|
|
1992
|
-
|
|
2315
|
+
Root20.displayName = "TopNav";
|
|
1993
2316
|
var Left = forwardRef(
|
|
1994
2317
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1995
2318
|
"div",
|
|
@@ -2124,7 +2447,7 @@ var ModeSwitcher = forwardRef(
|
|
|
2124
2447
|
}
|
|
2125
2448
|
);
|
|
2126
2449
|
ModeSwitcher.displayName = "TopNav.ModeSwitcher";
|
|
2127
|
-
var TopNav = /* @__PURE__ */ Object.assign(
|
|
2450
|
+
var TopNav = /* @__PURE__ */ Object.assign(Root20, {
|
|
2128
2451
|
Left,
|
|
2129
2452
|
Center,
|
|
2130
2453
|
Right,
|
|
@@ -2420,7 +2743,7 @@ var alignClass = {
|
|
|
2420
2743
|
center: "text-center",
|
|
2421
2744
|
right: "text-right"
|
|
2422
2745
|
};
|
|
2423
|
-
var
|
|
2746
|
+
var Root22 = forwardRef(
|
|
2424
2747
|
({ className, density = "default", children, ...props }, ref) => /* @__PURE__ */ jsx(TableDensityContext.Provider, { value: density, children: /* @__PURE__ */ jsx(
|
|
2425
2748
|
"table",
|
|
2426
2749
|
{
|
|
@@ -2432,7 +2755,7 @@ var Root21 = forwardRef(
|
|
|
2432
2755
|
}
|
|
2433
2756
|
) })
|
|
2434
2757
|
);
|
|
2435
|
-
|
|
2758
|
+
Root22.displayName = "Table";
|
|
2436
2759
|
var Header5 = forwardRef(
|
|
2437
2760
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2438
2761
|
"thead",
|
|
@@ -2552,7 +2875,7 @@ var HeaderCell = forwardRef(
|
|
|
2552
2875
|
}
|
|
2553
2876
|
);
|
|
2554
2877
|
HeaderCell.displayName = "Table.HeaderCell";
|
|
2555
|
-
var Table = Object.assign(
|
|
2878
|
+
var Table = Object.assign(Root22, { Header: Header5, Body: Body4, Row, Cell, HeaderCell });
|
|
2556
2879
|
|
|
2557
2880
|
// src/lib/env.ts
|
|
2558
2881
|
function readNodeEnv() {
|
|
@@ -2575,7 +2898,7 @@ var LABEL_COLOR = {
|
|
|
2575
2898
|
idle: "text-muted-foreground",
|
|
2576
2899
|
warning: "text-warning"
|
|
2577
2900
|
};
|
|
2578
|
-
var
|
|
2901
|
+
var SIZE2 = {
|
|
2579
2902
|
xs: "size-1.5",
|
|
2580
2903
|
sm: "size-2",
|
|
2581
2904
|
md: "size-2.5"
|
|
@@ -2598,7 +2921,7 @@ var StatusDot = forwardRef(
|
|
|
2598
2921
|
"aria-hidden": hasVisibleLabel ? "true" : void 0,
|
|
2599
2922
|
className: cn(
|
|
2600
2923
|
"inline-block shrink-0 rounded-full",
|
|
2601
|
-
|
|
2924
|
+
SIZE2[size],
|
|
2602
2925
|
DOT_COLOR[status],
|
|
2603
2926
|
shouldPulse && "animate-pulse"
|
|
2604
2927
|
)
|
|
@@ -2639,102 +2962,6 @@ var StatusDot = forwardRef(
|
|
|
2639
2962
|
}
|
|
2640
2963
|
);
|
|
2641
2964
|
StatusDot.displayName = "StatusDot";
|
|
2642
|
-
var VARIANT = {
|
|
2643
|
-
ghost: "hover:bg-muted",
|
|
2644
|
-
outline: "border border-border/60 rounded-md"
|
|
2645
|
-
};
|
|
2646
|
-
var SIZE2 = {
|
|
2647
|
-
sm: "px-2 py-1 text-label",
|
|
2648
|
-
md: "px-2.5 py-1.5 text-body-sm"
|
|
2649
|
-
};
|
|
2650
|
-
var CopyButton = forwardRef(
|
|
2651
|
-
({
|
|
2652
|
-
className,
|
|
2653
|
-
value,
|
|
2654
|
-
label,
|
|
2655
|
-
variant = "ghost",
|
|
2656
|
-
size = "sm",
|
|
2657
|
-
onCopied,
|
|
2658
|
-
feedbackDuration = 1500,
|
|
2659
|
-
...props
|
|
2660
|
-
}, ref) => {
|
|
2661
|
-
const [state, setState] = useState("idle");
|
|
2662
|
-
const timerRef = useRef(null);
|
|
2663
|
-
useEffect(() => {
|
|
2664
|
-
return () => {
|
|
2665
|
-
if (timerRef.current !== null) {
|
|
2666
|
-
clearTimeout(timerRef.current);
|
|
2667
|
-
}
|
|
2668
|
-
};
|
|
2669
|
-
}, []);
|
|
2670
|
-
const scheduleRevert = useCallback(() => {
|
|
2671
|
-
if (timerRef.current !== null) {
|
|
2672
|
-
clearTimeout(timerRef.current);
|
|
2673
|
-
}
|
|
2674
|
-
timerRef.current = setTimeout(() => {
|
|
2675
|
-
setState("idle");
|
|
2676
|
-
timerRef.current = null;
|
|
2677
|
-
}, feedbackDuration);
|
|
2678
|
-
}, [feedbackDuration]);
|
|
2679
|
-
const handleClick = useCallback(() => {
|
|
2680
|
-
if (state !== "idle") return;
|
|
2681
|
-
if (typeof navigator === "undefined" || !navigator.clipboard?.writeText) {
|
|
2682
|
-
setState("failed");
|
|
2683
|
-
scheduleRevert();
|
|
2684
|
-
return;
|
|
2685
|
-
}
|
|
2686
|
-
navigator.clipboard.writeText(value).then(
|
|
2687
|
-
() => {
|
|
2688
|
-
setState("copied");
|
|
2689
|
-
onCopied?.(value);
|
|
2690
|
-
scheduleRevert();
|
|
2691
|
-
},
|
|
2692
|
-
() => {
|
|
2693
|
-
setState("failed");
|
|
2694
|
-
scheduleRevert();
|
|
2695
|
-
}
|
|
2696
|
-
);
|
|
2697
|
-
}, [state, value, onCopied, scheduleRevert]);
|
|
2698
|
-
const Icon2 = state === "copied" ? Check : state === "failed" ? X : Copy;
|
|
2699
|
-
const liveMessage = state === "copied" ? "Copied to clipboard" : state === "failed" ? "Copy failed" : "";
|
|
2700
|
-
const labelText = label !== void 0 ? state === "copied" ? "Copied!" : state === "failed" ? "Failed" : label : null;
|
|
2701
|
-
return /* @__PURE__ */ jsxs(
|
|
2702
|
-
"button",
|
|
2703
|
-
{
|
|
2704
|
-
"data-slot": "copy-button",
|
|
2705
|
-
ref,
|
|
2706
|
-
type: "button",
|
|
2707
|
-
onClick: handleClick,
|
|
2708
|
-
"data-state": state,
|
|
2709
|
-
className: cn(
|
|
2710
|
-
"inline-flex items-center gap-1.5",
|
|
2711
|
-
"font-sans transition-colors",
|
|
2712
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-card",
|
|
2713
|
-
VARIANT[variant],
|
|
2714
|
-
SIZE2[size],
|
|
2715
|
-
className
|
|
2716
|
-
),
|
|
2717
|
-
...props,
|
|
2718
|
-
children: [
|
|
2719
|
-
/* @__PURE__ */ jsx(
|
|
2720
|
-
Icon2,
|
|
2721
|
-
{
|
|
2722
|
-
"aria-hidden": "true",
|
|
2723
|
-
className: cn(
|
|
2724
|
-
"size-3.5 shrink-0 transition-opacity duration-200",
|
|
2725
|
-
state === "copied" && "text-success",
|
|
2726
|
-
state === "failed" && "text-destructive"
|
|
2727
|
-
)
|
|
2728
|
-
}
|
|
2729
|
-
),
|
|
2730
|
-
labelText !== null ? /* @__PURE__ */ jsx("span", { children: labelText }) : null,
|
|
2731
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", "aria-live": "polite", children: liveMessage })
|
|
2732
|
-
]
|
|
2733
|
-
}
|
|
2734
|
-
);
|
|
2735
|
-
}
|
|
2736
|
-
);
|
|
2737
|
-
CopyButton.displayName = "CopyButton";
|
|
2738
2965
|
function toDate(value) {
|
|
2739
2966
|
const d = value instanceof Date ? value : new Date(value);
|
|
2740
2967
|
return Number.isNaN(d.getTime()) ? null : d;
|
|
@@ -2929,7 +3156,7 @@ var StatTile = forwardRef(
|
|
|
2929
3156
|
}
|
|
2930
3157
|
);
|
|
2931
3158
|
StatTile.displayName = "StatTile";
|
|
2932
|
-
var
|
|
3159
|
+
var Root23 = forwardRef(
|
|
2933
3160
|
({ className, title = "Danger Zone", children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
2934
3161
|
"section",
|
|
2935
3162
|
{
|
|
@@ -2945,7 +3172,7 @@ var Root22 = forwardRef(
|
|
|
2945
3172
|
}
|
|
2946
3173
|
)
|
|
2947
3174
|
);
|
|
2948
|
-
|
|
3175
|
+
Root23.displayName = "DangerZone";
|
|
2949
3176
|
var Action2 = forwardRef(
|
|
2950
3177
|
({ className, title, description, action, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
2951
3178
|
"div",
|
|
@@ -2968,7 +3195,7 @@ var Action2 = forwardRef(
|
|
|
2968
3195
|
)
|
|
2969
3196
|
);
|
|
2970
3197
|
Action2.displayName = "DangerZone.Action";
|
|
2971
|
-
var DangerZone = Object.assign(
|
|
3198
|
+
var DangerZone = Object.assign(Root23, { Action: Action2 });
|
|
2972
3199
|
var ConfirmDialog = forwardRef(
|
|
2973
3200
|
({
|
|
2974
3201
|
open,
|
|
@@ -3497,7 +3724,7 @@ var Content12 = forwardRef(({ className, sideOffset = 4, ...props }, ref) => /*
|
|
|
3497
3724
|
}
|
|
3498
3725
|
) }));
|
|
3499
3726
|
Content12.displayName = "DropdownMenu.Content";
|
|
3500
|
-
var
|
|
3727
|
+
var Item8 = forwardRef(
|
|
3501
3728
|
({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
3502
3729
|
DropdownMenuPrimitive.Item,
|
|
3503
3730
|
{
|
|
@@ -3516,7 +3743,7 @@ var Item7 = forwardRef(
|
|
|
3516
3743
|
}
|
|
3517
3744
|
)
|
|
3518
3745
|
);
|
|
3519
|
-
|
|
3746
|
+
Item8.displayName = "DropdownMenu.Item";
|
|
3520
3747
|
var CheckboxItem2 = forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
3521
3748
|
DropdownMenuPrimitive.CheckboxItem,
|
|
3522
3749
|
{
|
|
@@ -3632,7 +3859,7 @@ var DropdownMenu = Object.assign(DropdownMenuPrimitive.Root, {
|
|
|
3632
3859
|
Trigger: Trigger9,
|
|
3633
3860
|
Portal: Portal6,
|
|
3634
3861
|
Content: Content12,
|
|
3635
|
-
Item:
|
|
3862
|
+
Item: Item8,
|
|
3636
3863
|
CheckboxItem: CheckboxItem2,
|
|
3637
3864
|
RadioItem: RadioItem2,
|
|
3638
3865
|
Label: Label4,
|
|
@@ -4151,6 +4378,167 @@ var PageShell = forwardRef(
|
|
|
4151
4378
|
}
|
|
4152
4379
|
);
|
|
4153
4380
|
PageShell.displayName = "PageShell";
|
|
4381
|
+
function linScale(domain, range) {
|
|
4382
|
+
const [d0, d1] = domain;
|
|
4383
|
+
const [r0, r1] = range;
|
|
4384
|
+
const span = d1 - d0;
|
|
4385
|
+
return (v) => span === 0 ? r0 : r0 + (v - d0) / span * (r1 - r0);
|
|
4386
|
+
}
|
|
4387
|
+
function niceMax(values) {
|
|
4388
|
+
const m = Math.max(0, ...values.filter((v) => Number.isFinite(v)));
|
|
4389
|
+
if (m <= 0) return 0;
|
|
4390
|
+
const pow = 10 ** Math.floor(Math.log10(m));
|
|
4391
|
+
return Math.ceil(m / pow) * pow;
|
|
4392
|
+
}
|
|
4393
|
+
function seriesPath(points, xScale, yScale) {
|
|
4394
|
+
const finite = points.filter((p) => Number.isFinite(p.y));
|
|
4395
|
+
if (finite.length === 0) return "";
|
|
4396
|
+
return finite.map((p, i) => `${i === 0 ? "M" : "L"}${xScale(p.x).toFixed(2)},${yScale(p.y).toFixed(2)}`).join(" ");
|
|
4397
|
+
}
|
|
4398
|
+
var VIEW_W = 600;
|
|
4399
|
+
var PAD = { top: 8, right: 8, bottom: 4, left: 40 };
|
|
4400
|
+
var SPARSE_MARKER_MAX = 5;
|
|
4401
|
+
var TrendChart = forwardRef(
|
|
4402
|
+
({ title, series, height = 180, valueFormatter = (v) => String(v), className, ...props }, ref) => {
|
|
4403
|
+
const allPoints = series.flatMap((s) => s.points);
|
|
4404
|
+
const hasData = allPoints.some((p) => Number.isFinite(p.y));
|
|
4405
|
+
if (!hasData) {
|
|
4406
|
+
return /* @__PURE__ */ jsxs(
|
|
4407
|
+
"figure",
|
|
4408
|
+
{
|
|
4409
|
+
"data-slot": "trend-chart",
|
|
4410
|
+
ref,
|
|
4411
|
+
className: cn("space-y-1", className),
|
|
4412
|
+
"aria-label": `${title} \u2014 no data`,
|
|
4413
|
+
...props,
|
|
4414
|
+
children: [
|
|
4415
|
+
/* @__PURE__ */ jsx("figcaption", { className: "font-semibold text-label-caps text-muted-foreground uppercase", children: title }),
|
|
4416
|
+
/* @__PURE__ */ jsx(
|
|
4417
|
+
"div",
|
|
4418
|
+
{
|
|
4419
|
+
"data-slot": "trend-chart-empty",
|
|
4420
|
+
className: "flex items-center justify-center rounded-md border border-dashed text-body-sm text-muted-foreground",
|
|
4421
|
+
style: { height },
|
|
4422
|
+
children: "No data in this time range."
|
|
4423
|
+
}
|
|
4424
|
+
)
|
|
4425
|
+
]
|
|
4426
|
+
}
|
|
4427
|
+
);
|
|
4428
|
+
}
|
|
4429
|
+
const xs = allPoints.map((p) => p.x);
|
|
4430
|
+
const xMin = Math.min(...xs);
|
|
4431
|
+
const xMax = Math.max(...xs);
|
|
4432
|
+
const yMax = niceMax(allPoints.map((p) => p.y)) || 1;
|
|
4433
|
+
const axisXs = Array.from(new Set(allPoints.map((p) => p.x))).sort((a, b) => a - b);
|
|
4434
|
+
const yByX = series.map((s) => new Map(s.points.map((p) => [p.x, p.y])));
|
|
4435
|
+
const xScale = linScale([xMin, xMax], [PAD.left, VIEW_W - PAD.right]);
|
|
4436
|
+
const yScale = linScale([0, yMax], [height - PAD.bottom, PAD.top]);
|
|
4437
|
+
return /* @__PURE__ */ jsxs("figure", { "data-slot": "trend-chart", ref, className: cn("space-y-1", className), ...props, children: [
|
|
4438
|
+
/* @__PURE__ */ jsx("figcaption", { className: "font-semibold text-label-caps text-muted-foreground uppercase", children: title }),
|
|
4439
|
+
/* @__PURE__ */ jsxs(
|
|
4440
|
+
"svg",
|
|
4441
|
+
{
|
|
4442
|
+
viewBox: `0 0 ${VIEW_W} ${height}`,
|
|
4443
|
+
preserveAspectRatio: "none",
|
|
4444
|
+
role: "img",
|
|
4445
|
+
"aria-label": `${title} trend`,
|
|
4446
|
+
className: "w-full",
|
|
4447
|
+
style: { height },
|
|
4448
|
+
children: [
|
|
4449
|
+
/* @__PURE__ */ jsx(
|
|
4450
|
+
"line",
|
|
4451
|
+
{
|
|
4452
|
+
x1: PAD.left,
|
|
4453
|
+
y1: height - PAD.bottom,
|
|
4454
|
+
x2: VIEW_W - PAD.right,
|
|
4455
|
+
y2: height - PAD.bottom,
|
|
4456
|
+
className: "stroke-border",
|
|
4457
|
+
strokeWidth: 1
|
|
4458
|
+
}
|
|
4459
|
+
),
|
|
4460
|
+
/* @__PURE__ */ jsx(
|
|
4461
|
+
"line",
|
|
4462
|
+
{
|
|
4463
|
+
x1: PAD.left,
|
|
4464
|
+
y1: PAD.top,
|
|
4465
|
+
x2: VIEW_W - PAD.right,
|
|
4466
|
+
y2: PAD.top,
|
|
4467
|
+
className: "stroke-border/50",
|
|
4468
|
+
strokeWidth: 1,
|
|
4469
|
+
strokeDasharray: "2 3"
|
|
4470
|
+
}
|
|
4471
|
+
),
|
|
4472
|
+
/* @__PURE__ */ jsx("text", { x: 4, y: PAD.top + 8, className: "fill-muted-foreground text-[10px]", children: valueFormatter(yMax) }),
|
|
4473
|
+
/* @__PURE__ */ jsx("text", { x: 4, y: height - PAD.bottom, className: "fill-muted-foreground text-[10px]", children: "0" }),
|
|
4474
|
+
series.map((s) => /* @__PURE__ */ jsxs("g", { children: [
|
|
4475
|
+
/* @__PURE__ */ jsx(
|
|
4476
|
+
"path",
|
|
4477
|
+
{
|
|
4478
|
+
"data-slot": "trend-chart-line",
|
|
4479
|
+
"data-series": s.name,
|
|
4480
|
+
d: seriesPath(s.points, xScale, yScale),
|
|
4481
|
+
fill: "none",
|
|
4482
|
+
stroke: s.color,
|
|
4483
|
+
strokeWidth: 1.5,
|
|
4484
|
+
children: /* @__PURE__ */ jsx("title", { children: s.name })
|
|
4485
|
+
}
|
|
4486
|
+
),
|
|
4487
|
+
s.points.length < SPARSE_MARKER_MAX ? s.points.filter((p) => Number.isFinite(p.y)).map((p, i) => /* @__PURE__ */ jsx(
|
|
4488
|
+
"circle",
|
|
4489
|
+
{
|
|
4490
|
+
"data-slot": "trend-chart-dot",
|
|
4491
|
+
cx: xScale(p.x),
|
|
4492
|
+
cy: yScale(p.y),
|
|
4493
|
+
r: 2.5,
|
|
4494
|
+
fill: s.color,
|
|
4495
|
+
children: /* @__PURE__ */ jsx("title", { children: s.name })
|
|
4496
|
+
},
|
|
4497
|
+
`${s.name}-${p.x}-${i}`
|
|
4498
|
+
)) : null
|
|
4499
|
+
] }, s.name))
|
|
4500
|
+
]
|
|
4501
|
+
}
|
|
4502
|
+
),
|
|
4503
|
+
/* @__PURE__ */ jsx(
|
|
4504
|
+
"ul",
|
|
4505
|
+
{
|
|
4506
|
+
"data-slot": "trend-chart-legend",
|
|
4507
|
+
className: "flex flex-wrap gap-3 text-body-sm text-muted-foreground",
|
|
4508
|
+
children: series.map((s) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-1", children: [
|
|
4509
|
+
/* @__PURE__ */ jsx(
|
|
4510
|
+
"span",
|
|
4511
|
+
{
|
|
4512
|
+
"aria-hidden": "true",
|
|
4513
|
+
className: "inline-block h-2 w-2 rounded-sm",
|
|
4514
|
+
style: { backgroundColor: s.color }
|
|
4515
|
+
}
|
|
4516
|
+
),
|
|
4517
|
+
s.name
|
|
4518
|
+
] }, s.name))
|
|
4519
|
+
}
|
|
4520
|
+
),
|
|
4521
|
+
/* @__PURE__ */ jsxs("table", { "data-slot": "trend-chart-table", className: "sr-only", children: [
|
|
4522
|
+
/* @__PURE__ */ jsxs("caption", { children: [
|
|
4523
|
+
title,
|
|
4524
|
+
" \u2014 data table"
|
|
4525
|
+
] }),
|
|
4526
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
4527
|
+
/* @__PURE__ */ jsx("th", { children: "Point" }),
|
|
4528
|
+
series.map((s) => /* @__PURE__ */ jsx("th", { children: s.name }, s.name))
|
|
4529
|
+
] }) }),
|
|
4530
|
+
/* @__PURE__ */ jsx("tbody", { children: axisXs.map((x, i) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
4531
|
+
/* @__PURE__ */ jsx("td", { children: i + 1 }),
|
|
4532
|
+
series.map((s, si) => {
|
|
4533
|
+
const y = yByX[si]?.get(x);
|
|
4534
|
+
return /* @__PURE__ */ jsx("td", { children: y !== void 0 && Number.isFinite(y) ? valueFormatter(y) : "\u2014" }, s.name);
|
|
4535
|
+
})
|
|
4536
|
+
] }, x)) })
|
|
4537
|
+
] })
|
|
4538
|
+
] });
|
|
4539
|
+
}
|
|
4540
|
+
);
|
|
4541
|
+
TrendChart.displayName = "TrendChart";
|
|
4154
4542
|
var MetricsPanel = forwardRef(
|
|
4155
4543
|
({ className, title, description, metrics, columns, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
4156
4544
|
"div",
|
|
@@ -5081,4 +5469,4 @@ function CommandPalette({
|
|
|
5081
5469
|
] }) });
|
|
5082
5470
|
}
|
|
5083
5471
|
|
|
5084
|
-
export { AccountMenu, ActionBar, Alert, Avatar, BadgeWithDot as Badge, Breadcrumb, Button, Card, Checkbox, CodeBlock, Combobox, CommandPalette, ConfirmDialog, CopyButton, DangerZone, DataTable, DeploymentRow, Dialog, DomainConfig, DropdownMenu, EmptyState, EnvVarEditor, FormField, Input, Label, LoginSplit, MetricCard, MetricsPanel, PageShell, Pagination, PinInput, PlanBadge, PreviewEnvCard, Progress, ProjectCard, RadioGroup, RollbackUI, ScrollArea, Select, Sheet, Sidebar, Skeleton, Slider, SocialAuthRow, StatTile, StatusDot, StatusIndicator, Switch, Table, Tabs, TaskHeader, Textarea, Timestamp, Toast, Toaster, TooltipWithStatics as Tooltip, TopNav, UpdateBanner, avatarVariants, badgeVariants, buttonVariants, cn, computePageRange, isNearBottom, sheetVariants, useStickToBottom, useToast };
|
|
5472
|
+
export { AccountMenu, ActionBar, Alert, Avatar, BadgeWithDot as Badge, Breadcrumb, Button, Card, Checkbox, CodeBlock, Combobox, CommandPalette, ConfirmDialog, CopyButton, DangerZone, DataTable, DeploymentRow, DescriptionList, Dialog, DomainConfig, DropdownMenu, EmptyState, EnvVarEditor, FormField, Input, JsonViewer, Label, LoginSplit, MetricCard, MetricsPanel, PageShell, Pagination, PinInput, PlanBadge, PreviewEnvCard, Progress, ProjectCard, RadioGroup, RollbackUI, ScrollArea, Select, Sheet, Sidebar, Skeleton, Slider, SocialAuthRow, StatTile, StatusDot, StatusIndicator, Switch, Table, Tabs, TaskHeader, Textarea, Timestamp, Toast, Toaster, TooltipWithStatics as Tooltip, TopNav, TrendChart, UpdateBanner, avatarVariants, badgeVariants, buttonVariants, cn, computePageRange, isNearBottom, linScale, niceMax, seriesPath, sheetVariants, useStickToBottom, useToast };
|
package/package.json
CHANGED