@cueplusplus/ui 0.1.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/charts/_token.js +39 -0
- package/dist/charts/container.d.ts +58 -0
- package/dist/charts/container.js +77 -0
- package/dist/charts/index.d.ts +5 -0
- package/dist/charts/index.js +5 -0
- package/dist/charts/ramps.d.ts +140 -0
- package/dist/charts/ramps.js +615 -0
- package/dist/charts/theme.d.ts +112 -0
- package/dist/charts/theme.js +165 -0
- package/dist/charts/tones.d.ts +111 -0
- package/dist/charts/tones.js +127 -0
- package/dist/chat/_glyphs.js +55 -0
- package/dist/chat/agent-color.d.ts +84 -0
- package/dist/chat/agent-color.js +101 -0
- package/dist/chat/agent-pile.d.ts +55 -0
- package/dist/chat/agent-pile.js +121 -0
- package/dist/chat/ask-box.d.ts +88 -0
- package/dist/chat/ask-box.js +341 -0
- package/dist/chat/composer.d.ts +66 -0
- package/dist/chat/composer.js +144 -0
- package/dist/chat/delegation-card.d.ts +60 -0
- package/dist/chat/delegation-card.js +129 -0
- package/dist/chat/index.d.ts +8 -0
- package/dist/chat/index.js +8 -0
- package/dist/chat/message-list.d.ts +39 -0
- package/dist/chat/message-list.js +105 -0
- package/dist/chat/message.d.ts +47 -0
- package/dist/chat/message.js +108 -0
- package/dist/chrome/_glyphs.js +101 -0
- package/dist/chrome/_tabs-scroll.d.ts +62 -0
- package/dist/chrome/_tabs-scroll.js +68 -0
- package/dist/chrome/_tree.d.ts +75 -0
- package/dist/chrome/_tree.js +49 -0
- package/dist/chrome/empty-state.d.ts +37 -0
- package/dist/chrome/empty-state.js +57 -0
- package/dist/chrome/eyebrow.d.ts +29 -0
- package/dist/chrome/eyebrow.js +36 -0
- package/dist/chrome/index.d.ts +17 -0
- package/dist/chrome/index.js +17 -0
- package/dist/chrome/navigation-menu.d.ts +80 -0
- package/dist/chrome/navigation-menu.js +121 -0
- package/dist/chrome/page-shell.d.ts +38 -0
- package/dist/chrome/page-shell.js +66 -0
- package/dist/chrome/panel.d.ts +55 -0
- package/dist/chrome/panel.js +67 -0
- package/dist/chrome/row.d.ts +82 -0
- package/dist/chrome/row.js +106 -0
- package/dist/chrome/scroll-area.d.ts +39 -0
- package/dist/chrome/scroll-area.js +70 -0
- package/dist/chrome/section-header.d.ts +42 -0
- package/dist/chrome/section-header.js +79 -0
- package/dist/chrome/segmented-control.d.ts +58 -0
- package/dist/chrome/segmented-control.js +76 -0
- package/dist/chrome/status-bar.d.ts +46 -0
- package/dist/chrome/status-bar.js +56 -0
- package/dist/chrome/tabs.d.ts +80 -0
- package/dist/chrome/tabs.js +176 -0
- package/dist/chrome/title-bar.d.ts +37 -0
- package/dist/chrome/title-bar.js +45 -0
- package/dist/chrome/toolbar.d.ts +46 -0
- package/dist/chrome/toolbar.js +62 -0
- package/dist/chrome/tree.d.ts +98 -0
- package/dist/chrome/tree.js +248 -0
- package/dist/color/_checker.js +14 -0
- package/dist/color/_convert.d.ts +52 -0
- package/dist/color/_convert.js +66 -0
- package/dist/color/_glyphs.js +28 -0
- package/dist/color/_thumb.js +15 -0
- package/dist/color/_value.js +28 -0
- package/dist/color/color-area.d.ts +27 -0
- package/dist/color/color-area.js +40 -0
- package/dist/color/color-field.d.ts +32 -0
- package/dist/color/color-field.js +43 -0
- package/dist/color/color-picker.d.ts +71 -0
- package/dist/color/color-picker.js +178 -0
- package/dist/color/color-slider.d.ts +31 -0
- package/dist/color/color-slider.js +51 -0
- package/dist/color/color-swatch.d.ts +32 -0
- package/dist/color/color-swatch.js +44 -0
- package/dist/color/index.d.ts +7 -0
- package/dist/color/index.js +7 -0
- package/dist/configurator/_export.d.ts +78 -0
- package/dist/configurator/_export.js +261 -0
- package/dist/configurator/_glyphs.js +92 -0
- package/dist/configurator/_overrides.d.ts +247 -0
- package/dist/configurator/_overrides.js +514 -0
- package/dist/configurator/configurator.d.ts +71 -0
- package/dist/configurator/configurator.js +279 -0
- package/dist/configurator/export-dialog.d.ts +30 -0
- package/dist/configurator/export-dialog.js +121 -0
- package/dist/configurator/index.d.ts +8 -0
- package/dist/configurator/index.js +8 -0
- package/dist/configurator/panel-sections.d.ts +86 -0
- package/dist/configurator/panel-sections.js +316 -0
- package/dist/configurator/token-editor.d.ts +74 -0
- package/dist/configurator/token-editor.js +149 -0
- package/dist/configurator/use-zoom.d.ts +87 -0
- package/dist/configurator/use-zoom.js +113 -0
- package/dist/date/_glyphs.js +34 -0
- package/dist/date/_segments.js +55 -0
- package/dist/date/_trigger.js +31 -0
- package/dist/date/calendar.d.ts +25 -0
- package/dist/date/calendar.js +125 -0
- package/dist/date/date-field.d.ts +34 -0
- package/dist/date/date-field.js +41 -0
- package/dist/date/date-picker.d.ts +69 -0
- package/dist/date/date-picker.js +89 -0
- package/dist/date/date-range-picker.d.ts +65 -0
- package/dist/date/date-range-picker.js +92 -0
- package/dist/date/index.d.ts +6 -0
- package/dist/date/index.js +6 -0
- package/dist/date/time-field.d.ts +29 -0
- package/dist/date/time-field.js +36 -0
- package/dist/dmx/_ramp.d.ts +77 -0
- package/dist/dmx/_ramp.js +169 -0
- package/dist/dmx/_readout.js +53 -0
- package/dist/dmx/_universe.d.ts +105 -0
- package/dist/dmx/_universe.js +112 -0
- package/dist/dmx/channel-matrix.d.ts +81 -0
- package/dist/dmx/channel-matrix.js +285 -0
- package/dist/dmx/dmx-bar.d.ts +50 -0
- package/dist/dmx/dmx-bar.js +107 -0
- package/dist/dmx/dmx-strip.d.ts +41 -0
- package/dist/dmx/dmx-strip.js +196 -0
- package/dist/dmx/index.d.ts +7 -0
- package/dist/dmx/index.js +7 -0
- package/dist/dmx/universe-grid.d.ts +61 -0
- package/dist/dmx/universe-grid.js +182 -0
- package/dist/flow/_frame.d.ts +52 -0
- package/dist/flow/_frame.js +38 -0
- package/dist/flow/controls.d.ts +41 -0
- package/dist/flow/controls.js +53 -0
- package/dist/flow/flow.css +121 -0
- package/dist/flow/handles.d.ts +40 -0
- package/dist/flow/handles.js +61 -0
- package/dist/flow/index.d.ts +7 -0
- package/dist/flow/index.js +7 -0
- package/dist/flow/node-card.d.ts +71 -0
- package/dist/flow/node-card.js +102 -0
- package/dist/flow/signal-edge.d.ts +60 -0
- package/dist/flow/signal-edge.js +108 -0
- package/dist/flow/use-flow-theme.d.ts +69 -0
- package/dist/flow/use-flow-theme.js +109 -0
- package/dist/forms/_chassis.d.ts +64 -0
- package/dist/forms/_chassis.js +59 -0
- package/dist/forms/_glyphs.js +143 -0
- package/dist/forms/_listbox.js +55 -0
- package/dist/forms/autocomplete.d.ts +61 -0
- package/dist/forms/autocomplete.js +88 -0
- package/dist/forms/button-group.d.ts +47 -0
- package/dist/forms/button-group.js +52 -0
- package/dist/forms/checkbox.d.ts +51 -0
- package/dist/forms/checkbox.js +98 -0
- package/dist/forms/combobox.d.ts +73 -0
- package/dist/forms/combobox.js +108 -0
- package/dist/forms/env-var-input.d.ts +74 -0
- package/dist/forms/env-var-input.js +116 -0
- package/dist/forms/field.d.ts +89 -0
- package/dist/forms/field.js +102 -0
- package/dist/forms/file-upload.d.ts +113 -0
- package/dist/forms/file-upload.js +232 -0
- package/dist/forms/index.d.ts +26 -0
- package/dist/forms/index.js +26 -0
- package/dist/forms/input-group.d.ts +31 -0
- package/dist/forms/input-group.js +54 -0
- package/dist/forms/input.d.ts +33 -0
- package/dist/forms/input.js +36 -0
- package/dist/forms/multi-select.d.ts +62 -0
- package/dist/forms/multi-select.js +107 -0
- package/dist/forms/number-field.d.ts +38 -0
- package/dist/forms/number-field.js +64 -0
- package/dist/forms/otp-field.d.ts +54 -0
- package/dist/forms/otp-field.js +59 -0
- package/dist/forms/password-input.d.ts +46 -0
- package/dist/forms/password-input.js +62 -0
- package/dist/forms/radio-group.d.ts +50 -0
- package/dist/forms/radio-group.js +64 -0
- package/dist/forms/rating.d.ts +69 -0
- package/dist/forms/rating.js +103 -0
- package/dist/forms/scrub-input.d.ts +81 -0
- package/dist/forms/scrub-input.js +249 -0
- package/dist/forms/search-input.d.ts +54 -0
- package/dist/forms/search-input.js +112 -0
- package/dist/forms/select.d.ts +75 -0
- package/dist/forms/select.js +91 -0
- package/dist/forms/slider.d.ts +44 -0
- package/dist/forms/slider.js +65 -0
- package/dist/forms/switch.d.ts +36 -0
- package/dist/forms/switch.js +71 -0
- package/dist/forms/tags-input.d.ts +69 -0
- package/dist/forms/tags-input.js +148 -0
- package/dist/forms/textarea.d.ts +27 -0
- package/dist/forms/textarea.js +37 -0
- package/dist/forms/toggle-group.d.ts +41 -0
- package/dist/forms/toggle-group.js +56 -0
- package/dist/forms/toggle.d.ts +41 -0
- package/dist/forms/toggle.js +100 -0
- package/dist/index.d.ts +112 -0
- package/dist/index.js +104 -0
- package/dist/instruments/_ansi.js +116 -0
- package/dist/instruments/_glyphs.js +90 -0
- package/dist/instruments/_motion.js +56 -0
- package/dist/instruments/_rem.js +21 -0
- package/dist/instruments/app-window-frame.d.ts +48 -0
- package/dist/instruments/app-window-frame.js +76 -0
- package/dist/instruments/copy-button.d.ts +41 -0
- package/dist/instruments/copy-button.js +112 -0
- package/dist/instruments/data-table.d.ts +168 -0
- package/dist/instruments/data-table.js +212 -0
- package/dist/instruments/group-bar.d.ts +63 -0
- package/dist/instruments/group-bar.js +122 -0
- package/dist/instruments/index.d.ts +13 -0
- package/dist/instruments/index.js +13 -0
- package/dist/instruments/log-viewer.d.ts +74 -0
- package/dist/instruments/log-viewer.js +215 -0
- package/dist/instruments/meter.d.ts +77 -0
- package/dist/instruments/meter.js +96 -0
- package/dist/instruments/progress.d.ts +45 -0
- package/dist/instruments/progress.js +61 -0
- package/dist/instruments/seam-grid.d.ts +66 -0
- package/dist/instruments/seam-grid.js +78 -0
- package/dist/instruments/sparkline.d.ts +39 -0
- package/dist/instruments/sparkline.js +85 -0
- package/dist/instruments/stat.d.ts +35 -0
- package/dist/instruments/stat.js +59 -0
- package/dist/instruments/table.d.ts +51 -0
- package/dist/instruments/table.js +92 -0
- package/dist/instruments/terminal-frame.d.ts +89 -0
- package/dist/instruments/terminal-frame.js +256 -0
- package/dist/instruments/two-step-button.d.ts +47 -0
- package/dist/instruments/two-step-button.js +147 -0
- package/dist/instruments/usage-chart.d.ts +55 -0
- package/dist/instruments/usage-chart.js +235 -0
- package/dist/layout/_collapse.js +46 -0
- package/dist/layout/_glyphs.js +45 -0
- package/dist/layout/accordion.d.ts +52 -0
- package/dist/layout/accordion.js +81 -0
- package/dist/layout/breadcrumb.d.ts +35 -0
- package/dist/layout/breadcrumb.js +67 -0
- package/dist/layout/card.d.ts +51 -0
- package/dist/layout/card.js +76 -0
- package/dist/layout/carousel.d.ts +96 -0
- package/dist/layout/carousel.js +211 -0
- package/dist/layout/collapsible.d.ts +74 -0
- package/dist/layout/collapsible.js +126 -0
- package/dist/layout/container.d.ts +27 -0
- package/dist/layout/container.js +40 -0
- package/dist/layout/description-list.d.ts +24 -0
- package/dist/layout/description-list.js +37 -0
- package/dist/layout/grid.d.ts +40 -0
- package/dist/layout/grid.js +48 -0
- package/dist/layout/index.d.ts +15 -0
- package/dist/layout/index.js +15 -0
- package/dist/layout/item.d.ts +65 -0
- package/dist/layout/item.js +100 -0
- package/dist/layout/link.d.ts +48 -0
- package/dist/layout/link.js +63 -0
- package/dist/layout/pagination.d.ts +54 -0
- package/dist/layout/pagination.js +121 -0
- package/dist/layout/resizable.d.ts +38 -0
- package/dist/layout/resizable.js +68 -0
- package/dist/layout/sidebar.d.ts +67 -0
- package/dist/layout/sidebar.js +129 -0
- package/dist/layout/stack.d.ts +46 -0
- package/dist/layout/stack.js +62 -0
- package/dist/layout/stepper.d.ts +49 -0
- package/dist/layout/stepper.js +81 -0
- package/dist/layout/timeline.d.ts +43 -0
- package/dist/layout/timeline.js +63 -0
- package/dist/lib/aria-class.js +24 -0
- package/dist/lib/cn.js +18 -0
- package/dist/lib/compose.js +38 -0
- package/dist/lib/cva.d.ts +18 -0
- package/dist/lib/cva.js +65 -0
- package/dist/midi/_notes.d.ts +101 -0
- package/dist/midi/_notes.js +183 -0
- package/dist/midi/_ruler.d.ts +100 -0
- package/dist/midi/_ruler.js +105 -0
- package/dist/midi/_time.d.ts +107 -0
- package/dist/midi/_time.js +130 -0
- package/dist/midi/index.d.ts +9 -0
- package/dist/midi/index.js +9 -0
- package/dist/midi/musical-time-input.d.ts +48 -0
- package/dist/midi/musical-time-input.js +154 -0
- package/dist/midi/piano-keyboard.d.ts +50 -0
- package/dist/midi/piano-keyboard.js +193 -0
- package/dist/midi/spectrum-visualizer.d.ts +65 -0
- package/dist/midi/spectrum-visualizer.js +213 -0
- package/dist/midi/threshold-rail.d.ts +72 -0
- package/dist/midi/threshold-rail.js +214 -0
- package/dist/midi/timeline-ruler.d.ts +83 -0
- package/dist/midi/timeline-ruler.js +152 -0
- package/dist/overlays/_debounce.js +34 -0
- package/dist/overlays/_glyphs.js +59 -0
- package/dist/overlays/_surface.d.ts +70 -0
- package/dist/overlays/_surface.js +70 -0
- package/dist/overlays/_wheel.js +42 -0
- package/dist/overlays/alert-dialog.d.ts +67 -0
- package/dist/overlays/alert-dialog.js +117 -0
- package/dist/overlays/command-palette.d.ts +93 -0
- package/dist/overlays/command-palette.js +193 -0
- package/dist/overlays/context-menu.d.ts +64 -0
- package/dist/overlays/context-menu.js +78 -0
- package/dist/overlays/dialog.d.ts +72 -0
- package/dist/overlays/dialog.js +124 -0
- package/dist/overlays/drawer.d.ts +75 -0
- package/dist/overlays/drawer.js +151 -0
- package/dist/overlays/dropdown-menu.d.ts +79 -0
- package/dist/overlays/dropdown-menu.js +156 -0
- package/dist/overlays/hover-card.d.ts +58 -0
- package/dist/overlays/hover-card.js +91 -0
- package/dist/overlays/index.d.ts +15 -0
- package/dist/overlays/index.js +15 -0
- package/dist/overlays/info-tip.d.ts +41 -0
- package/dist/overlays/info-tip.js +45 -0
- package/dist/overlays/menubar.d.ts +72 -0
- package/dist/overlays/menubar.js +100 -0
- package/dist/overlays/popover.d.ts +66 -0
- package/dist/overlays/popover.js +114 -0
- package/dist/overlays/sheet.d.ts +78 -0
- package/dist/overlays/sheet.js +131 -0
- package/dist/overlays/toast.d.ts +106 -0
- package/dist/overlays/toast.js +146 -0
- package/dist/overlays/tooltip.d.ts +57 -0
- package/dist/overlays/tooltip.js +95 -0
- package/dist/primitives/avatar.d.ts +51 -0
- package/dist/primitives/avatar.js +93 -0
- package/dist/primitives/button.d.ts +46 -0
- package/dist/primitives/button.js +94 -0
- package/dist/primitives/chip.d.ts +47 -0
- package/dist/primitives/chip.js +152 -0
- package/dist/primitives/icon-button.d.ts +41 -0
- package/dist/primitives/icon-button.js +59 -0
- package/dist/primitives/index.d.ts +10 -0
- package/dist/primitives/index.js +10 -0
- package/dist/primitives/kbd.d.ts +17 -0
- package/dist/primitives/kbd.js +24 -0
- package/dist/primitives/separator.d.ts +25 -0
- package/dist/primitives/separator.js +30 -0
- package/dist/primitives/skeleton.d.ts +20 -0
- package/dist/primitives/skeleton.js +27 -0
- package/dist/primitives/spinner.d.ts +26 -0
- package/dist/primitives/spinner.js +31 -0
- package/dist/primitives/status-dot.d.ts +44 -0
- package/dist/primitives/status-dot.js +50 -0
- package/dist/styles.css +19 -0
- package/dist/system/density.d.ts +33 -0
- package/dist/system/density.js +49 -0
- package/dist/system/index.d.ts +8 -0
- package/dist/system/index.js +7 -0
- package/dist/system/portal.d.ts +51 -0
- package/dist/system/portal.js +122 -0
- package/dist/system/prepaint.d.ts +38 -0
- package/dist/system/prepaint.js +37 -0
- package/dist/system/theme-provider.d.ts +72 -0
- package/dist/system/theme-provider.js +252 -0
- package/dist/system/use-density.d.ts +33 -0
- package/dist/system/use-density.js +84 -0
- package/dist/system/use-isomorphic-layout-effect.js +15 -0
- package/dist/system/use-theme.d.ts +19 -0
- package/dist/system/use-theme.js +25 -0
- package/dist/theming/_presets.d.ts +11 -0
- package/dist/theming/_presets.js +487 -0
- package/dist/theming/contrast.d.ts +110 -0
- package/dist/theming/contrast.js +167 -0
- package/dist/theming/create-theme.d.ts +165 -0
- package/dist/theming/create-theme.js +442 -0
- package/dist/theming/index.d.ts +5 -0
- package/dist/theming/index.js +5 -0
- package/dist/theming/serialize.d.ts +145 -0
- package/dist/theming/serialize.js +165 -0
- package/package.json +216 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { toRem } from "./_rem.js";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/instruments/usage-chart.tsx
|
|
7
|
+
const TONE_CLASSES = {
|
|
8
|
+
accent: "text-accent",
|
|
9
|
+
ok: "text-ok",
|
|
10
|
+
busy: "text-busy",
|
|
11
|
+
warn: "text-warn",
|
|
12
|
+
danger: "text-danger",
|
|
13
|
+
info: "text-info"
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Fixed viewBox width. The SVG stretches to its container, so the internal
|
|
17
|
+
* width can be a constant and the path maths stays integer-friendly.
|
|
18
|
+
*/
|
|
19
|
+
const VIEW_WIDTH = 600;
|
|
20
|
+
/** Room for the axis labels, in viewBox units, without a layout pass. */
|
|
21
|
+
const PAD = {
|
|
22
|
+
top: 6,
|
|
23
|
+
right: 4,
|
|
24
|
+
bottom: 14,
|
|
25
|
+
left: 22
|
|
26
|
+
};
|
|
27
|
+
/** The horizontal rules. 0 and 100 are the ceiling and the floor; the rest are guides. */
|
|
28
|
+
const GRID_LINES = [
|
|
29
|
+
0,
|
|
30
|
+
25,
|
|
31
|
+
50,
|
|
32
|
+
75,
|
|
33
|
+
100
|
|
34
|
+
];
|
|
35
|
+
/** Default plot height in px at the 16px root. */
|
|
36
|
+
const DEFAULT_HEIGHT_PX = 120;
|
|
37
|
+
/** Default hole width before the line breaks: one missed quarter-hourly sweep. */
|
|
38
|
+
const DEFAULT_GAP_MS = 9e5;
|
|
39
|
+
/** Axis label size, in viewBox units — not a token, because the viewBox is not in rem. */
|
|
40
|
+
const AXIS_FONT_SIZE = 8;
|
|
41
|
+
/** Sorted, finite samples split into runs no wider than `gapMs`. */
|
|
42
|
+
function segment(points, gapMs) {
|
|
43
|
+
const clean = points.filter((point) => Number.isFinite(point.t) && Number.isFinite(point.v) && point.t >= 0).sort((a, b) => a.t - b.t);
|
|
44
|
+
if (clean.length === 0) return [];
|
|
45
|
+
const runs = [];
|
|
46
|
+
let run = [clean[0]];
|
|
47
|
+
for (let index = 1; index < clean.length; index += 1) {
|
|
48
|
+
const point = clean[index];
|
|
49
|
+
const previous = clean[index - 1];
|
|
50
|
+
if (point.t - previous.t > gapMs) {
|
|
51
|
+
runs.push(run);
|
|
52
|
+
run = [];
|
|
53
|
+
}
|
|
54
|
+
run.push(point);
|
|
55
|
+
}
|
|
56
|
+
runs.push(run);
|
|
57
|
+
return runs;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A quota trace: where you sit against the ceiling, over time.
|
|
61
|
+
*
|
|
62
|
+
* Dependency-free inline SVG — a charting library is a large price for one
|
|
63
|
+
* line and five gridlines, and none of them draws the three things that make
|
|
64
|
+
* this chart honest:
|
|
65
|
+
*
|
|
66
|
+
* 1. **The y axis is always 0–100.** A quota chart auto-scaled to its own range
|
|
67
|
+
* makes a flat 3% look identical to a flat 95%. The ceiling is the reading,
|
|
68
|
+
* so the ceiling is always drawn.
|
|
69
|
+
* 2. **Gaps are gaps.** When the sweep does not run, the line breaks. Joining
|
|
70
|
+
* across a hole invents data — and worse, invents a *smooth* trend across
|
|
71
|
+
* exactly the window nothing is known about. The area fill stops at the
|
|
72
|
+
* break for the same reason.
|
|
73
|
+
* 3. **Out-of-range values are clamped, not plotted.** Upstream numbers are
|
|
74
|
+
* reverse-engineered and can be anything; 140% should read as a flat line on
|
|
75
|
+
* the ceiling, not as a path drawn over the axis labels.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* <UsageChart label="API requests" points={series} threshold={80} tone="warn" />
|
|
79
|
+
*/
|
|
80
|
+
const UsageChart = React.forwardRef(function UsageChart({ className, points, tone = "accent", height = DEFAULT_HEIGHT_PX, gapMs = DEFAULT_GAP_MS, threshold, label, emptyLabel = "No data yet", formatTimestamp, formatValue = (value) => `${Math.round(value)}%`, ...elementProps }, ref) {
|
|
81
|
+
const gradientId = React.useId();
|
|
82
|
+
const [hover, setHover] = React.useState(null);
|
|
83
|
+
const segments = React.useMemo(() => segment(points, gapMs), [points, gapMs]);
|
|
84
|
+
const plotWidth = VIEW_WIDTH - PAD.left - PAD.right;
|
|
85
|
+
const plotHeight = height - PAD.top - PAD.bottom;
|
|
86
|
+
const floor = PAD.top + plotHeight;
|
|
87
|
+
const all = React.useMemo(() => segments.flat(), [segments]);
|
|
88
|
+
const first = all[0];
|
|
89
|
+
const last = all[all.length - 1];
|
|
90
|
+
const start = first?.t ?? 0;
|
|
91
|
+
const span = Math.max(1, (last?.t ?? start + 1) - start);
|
|
92
|
+
const round = (value) => Math.round(value * 100) / 100;
|
|
93
|
+
const x = (t) => round(PAD.left + (t - start) / span * plotWidth);
|
|
94
|
+
const y = (value) => round(PAD.top + (1 - Math.min(100, Math.max(0, value)) / 100) * plotHeight);
|
|
95
|
+
if (segments.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
96
|
+
ref,
|
|
97
|
+
"data-slot": "usage-chart",
|
|
98
|
+
"data-empty": "true",
|
|
99
|
+
className: cn("flex items-center justify-center font-mono text-(length:--cue-text-label) text-fg-subtle", className),
|
|
100
|
+
style: { height: toRem(height) },
|
|
101
|
+
...elementProps,
|
|
102
|
+
children: emptyLabel
|
|
103
|
+
});
|
|
104
|
+
const linePath = (run) => run.map((point, index) => `${index === 0 ? "M" : "L"}${x(point.t).toFixed(1)},${y(point.v).toFixed(1)}`).join(" ");
|
|
105
|
+
const areaPath = (run) => `${linePath(run)} L${x(run[run.length - 1].t).toFixed(1)},${floor.toFixed(1)} L${x(run[0].t).toFixed(1)},${floor.toFixed(1)} Z`;
|
|
106
|
+
const onMove = (event) => {
|
|
107
|
+
const box = event.currentTarget.getBoundingClientRect();
|
|
108
|
+
if (box.width === 0) return;
|
|
109
|
+
const viewX = (event.clientX - box.left) / box.width * VIEW_WIDTH;
|
|
110
|
+
const t = start + (viewX - PAD.left) / plotWidth * span;
|
|
111
|
+
let nearest = all[0];
|
|
112
|
+
for (const point of all) if (Math.abs(point.t - t) < Math.abs(nearest.t - t)) nearest = point;
|
|
113
|
+
setHover({
|
|
114
|
+
x: viewX,
|
|
115
|
+
point: nearest
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
119
|
+
ref,
|
|
120
|
+
"data-slot": "usage-chart",
|
|
121
|
+
className: cn("relative min-w-0", className),
|
|
122
|
+
...elementProps,
|
|
123
|
+
children: [/* @__PURE__ */ jsxs("svg", {
|
|
124
|
+
role: "img",
|
|
125
|
+
"aria-label": label ?? "Usage over time",
|
|
126
|
+
"data-tone": tone,
|
|
127
|
+
viewBox: `0 0 ${VIEW_WIDTH} ${height}`,
|
|
128
|
+
preserveAspectRatio: "none",
|
|
129
|
+
className: cn("block w-full", TONE_CLASSES[tone]),
|
|
130
|
+
style: { height: toRem(height) },
|
|
131
|
+
onMouseMove: onMove,
|
|
132
|
+
onMouseLeave: () => setHover(null),
|
|
133
|
+
children: [
|
|
134
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", {
|
|
135
|
+
id: gradientId,
|
|
136
|
+
x1: "0",
|
|
137
|
+
y1: "0",
|
|
138
|
+
x2: "0",
|
|
139
|
+
y2: "1",
|
|
140
|
+
children: [/* @__PURE__ */ jsx("stop", {
|
|
141
|
+
offset: "0%",
|
|
142
|
+
stopColor: "currentColor",
|
|
143
|
+
stopOpacity: "0.22"
|
|
144
|
+
}), /* @__PURE__ */ jsx("stop", {
|
|
145
|
+
offset: "100%",
|
|
146
|
+
stopColor: "currentColor",
|
|
147
|
+
stopOpacity: "0"
|
|
148
|
+
})]
|
|
149
|
+
}) }),
|
|
150
|
+
/* @__PURE__ */ jsx("g", {
|
|
151
|
+
className: "text-border",
|
|
152
|
+
children: GRID_LINES.map((value) => /* @__PURE__ */ jsx("line", {
|
|
153
|
+
"data-slot": "usage-chart-grid",
|
|
154
|
+
x1: PAD.left,
|
|
155
|
+
x2: VIEW_WIDTH - PAD.right,
|
|
156
|
+
y1: y(value),
|
|
157
|
+
y2: y(value),
|
|
158
|
+
stroke: "currentColor",
|
|
159
|
+
strokeWidth: "0.5",
|
|
160
|
+
opacity: value === 0 || value === 100 ? .9 : .45
|
|
161
|
+
}, value))
|
|
162
|
+
}),
|
|
163
|
+
/* @__PURE__ */ jsx("g", {
|
|
164
|
+
className: "fill-fg-subtle font-mono",
|
|
165
|
+
children: GRID_LINES.map((value) => /* @__PURE__ */ jsx("text", {
|
|
166
|
+
"data-slot": "usage-chart-axis",
|
|
167
|
+
x: PAD.left - 4,
|
|
168
|
+
y: y(value) + 3,
|
|
169
|
+
textAnchor: "end",
|
|
170
|
+
fontSize: AXIS_FONT_SIZE,
|
|
171
|
+
children: value
|
|
172
|
+
}, value))
|
|
173
|
+
}),
|
|
174
|
+
threshold === void 0 ? null : /* @__PURE__ */ jsx("line", {
|
|
175
|
+
"data-slot": "usage-chart-threshold",
|
|
176
|
+
className: "text-danger",
|
|
177
|
+
x1: PAD.left,
|
|
178
|
+
x2: VIEW_WIDTH - PAD.right,
|
|
179
|
+
y1: y(threshold),
|
|
180
|
+
y2: y(threshold),
|
|
181
|
+
stroke: "currentColor",
|
|
182
|
+
strokeWidth: "0.75",
|
|
183
|
+
strokeDasharray: "3 3",
|
|
184
|
+
opacity: "0.7"
|
|
185
|
+
}),
|
|
186
|
+
segments.map((run, index) => /* @__PURE__ */ jsxs("g", { children: [run.length > 1 ? /* @__PURE__ */ jsx("path", {
|
|
187
|
+
"data-slot": "usage-chart-area",
|
|
188
|
+
d: areaPath(run),
|
|
189
|
+
fill: `url(#${gradientId})`
|
|
190
|
+
}) : null, /* @__PURE__ */ jsx("path", {
|
|
191
|
+
"data-slot": "usage-chart-line",
|
|
192
|
+
d: linePath(run),
|
|
193
|
+
fill: "none",
|
|
194
|
+
stroke: "currentColor",
|
|
195
|
+
strokeWidth: "1.25",
|
|
196
|
+
strokeLinejoin: "round",
|
|
197
|
+
strokeLinecap: "round",
|
|
198
|
+
vectorEffect: "non-scaling-stroke"
|
|
199
|
+
})] }, index)),
|
|
200
|
+
hover === null ? null : /* @__PURE__ */ jsxs("g", {
|
|
201
|
+
pointerEvents: "none",
|
|
202
|
+
children: [/* @__PURE__ */ jsx("line", {
|
|
203
|
+
"data-slot": "usage-chart-crosshair",
|
|
204
|
+
className: "text-fg",
|
|
205
|
+
x1: x(hover.point.t),
|
|
206
|
+
x2: x(hover.point.t),
|
|
207
|
+
y1: PAD.top,
|
|
208
|
+
y2: floor,
|
|
209
|
+
stroke: "currentColor",
|
|
210
|
+
strokeWidth: "0.5",
|
|
211
|
+
opacity: "0.5"
|
|
212
|
+
}), /* @__PURE__ */ jsx("circle", {
|
|
213
|
+
"data-slot": "usage-chart-marker",
|
|
214
|
+
cx: x(hover.point.t),
|
|
215
|
+
cy: y(hover.point.v),
|
|
216
|
+
r: "2.5",
|
|
217
|
+
fill: "currentColor"
|
|
218
|
+
})]
|
|
219
|
+
})
|
|
220
|
+
]
|
|
221
|
+
}), hover === null ? null : /* @__PURE__ */ jsx("div", {
|
|
222
|
+
"data-slot": "usage-chart-tooltip",
|
|
223
|
+
className: "pointer-events-none absolute top-0 -translate-x-1/2 rounded-(--radius-control) border border-border-overlay bg-surface-2 px-(--cue-space-3) py-(--cue-space-1) font-mono text-(length:--cue-text-label) tabular-nums text-fg",
|
|
224
|
+
style: { left: `${Math.min(88, Math.max(2, hover.x / VIEW_WIDTH * 100))}%` },
|
|
225
|
+
children: `${formatValue(hover.point.v)} · ${formatTimestamp === void 0 ? new Date(hover.point.t).toLocaleString(void 0, {
|
|
226
|
+
month: "short",
|
|
227
|
+
day: "numeric",
|
|
228
|
+
hour: "2-digit",
|
|
229
|
+
minute: "2-digit"
|
|
230
|
+
}) : formatTimestamp(hover.point.t)}`
|
|
231
|
+
})]
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
//#endregion
|
|
235
|
+
export { UsageChart };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//#region src/layout/_collapse.ts
|
|
2
|
+
/**
|
|
3
|
+
* The one disclosure recipe, shared by `Accordion` and `Collapsible`.
|
|
4
|
+
*
|
|
5
|
+
* Both wrap a Base UI primitive that speaks the same state vocabulary
|
|
6
|
+
* (`data-panel-open` on the trigger, a measured `--*-panel-height` on the
|
|
7
|
+
* panel), so the skin is written once here rather than twice — a change to how
|
|
8
|
+
* a section opens is then a one-line change, and the tests can assert the same
|
|
9
|
+
* recipe on both.
|
|
10
|
+
*
|
|
11
|
+
* @internal Not part of the public API.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The summary row: one rung of the density control ladder, mono, padded to the
|
|
15
|
+
* same gutters as a `Row` so a stack of sections lines up with a stack of rows.
|
|
16
|
+
*
|
|
17
|
+
* `focus-visible:outline-solid` re-declares the outline style the sibling
|
|
18
|
+
* `outline-none` switched off — see the note on `buttonChassis`. The ring is
|
|
19
|
+
* inset (`-outline-offset-2`) because sections live inside `overflow-hidden`
|
|
20
|
+
* panels, where an outset ring on the first row would be clipped by the rim.
|
|
21
|
+
*/
|
|
22
|
+
const collapseTriggerClasses = "group/collapse flex h-control-md w-full cursor-pointer items-center gap-(--cue-space-3) px-(--cue-pad-row-x) text-left font-mono text-(length:--cue-text-ui) text-fg-muted transition-colors duration-150 outline-none select-none hover:text-fg focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-2 focus-visible:outline-accent data-[panel-open]:text-fg data-[disabled]:pointer-events-none data-[disabled]:opacity-40";
|
|
23
|
+
/** The label between the summary row's gutters — truncates, never wraps. */
|
|
24
|
+
const collapseLabelClasses = "min-w-0 flex-1 truncate";
|
|
25
|
+
/**
|
|
26
|
+
* The caret at the end of a summary row. Rotation is driven off the trigger's
|
|
27
|
+
* own `data-panel-open`, so nothing in React has to know the section is open.
|
|
28
|
+
*/
|
|
29
|
+
const collapseCaretClasses = "size-icon-sm shrink-0 text-fg-subtle transition-transform duration-150 ease-out group-data-[panel-open]/collapse:rotate-90 motion-reduce:transition-none";
|
|
30
|
+
/**
|
|
31
|
+
* Enter/exit for a panel, animated from the height Base UI measures for us.
|
|
32
|
+
*
|
|
33
|
+
* The animating element carries no padding on purpose: padding is part of the
|
|
34
|
+
* box's height, so it would be counted into the `0 → measured` transition and
|
|
35
|
+
* make the panel jump at both ends. The body lives one element in — see
|
|
36
|
+
* {@link collapsePanelBodyClasses}.
|
|
37
|
+
*/
|
|
38
|
+
const PANEL_MOTION = "overflow-hidden transition-[height] duration-150 ease-out motion-reduce:transition-none data-[starting-style]:h-0 data-[ending-style]:h-0";
|
|
39
|
+
/** {@link PANEL_MOTION} against the accordion's measured height. */
|
|
40
|
+
const accordionPanelClasses = `${PANEL_MOTION} h-(--accordion-panel-height)`;
|
|
41
|
+
/** {@link PANEL_MOTION} against the collapsible's measured height. */
|
|
42
|
+
const collapsiblePanelClasses = `${PANEL_MOTION} h-(--collapsible-panel-height)`;
|
|
43
|
+
/** The padded body inside a panel: aligned to the summary row's gutters. */
|
|
44
|
+
const collapsePanelBodyClasses = "px-(--cue-pad-row-x) pt-(--cue-space-1) pb-(--cue-space-4) font-mono text-(length:--cue-text-ui) leading-relaxed text-fg-muted";
|
|
45
|
+
//#endregion
|
|
46
|
+
export { accordionPanelClasses, collapseCaretClasses, collapseLabelClasses, collapsePanelBodyClasses, collapseTriggerClasses, collapsiblePanelClasses };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import "react";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/layout/_glyphs.tsx
|
|
4
|
+
/**
|
|
5
|
+
* Shared layout glyphs.
|
|
6
|
+
*
|
|
7
|
+
* Drawn inline rather than pulled from `lucide-react` for the same reason as
|
|
8
|
+
* `chrome/_glyphs.tsx` and `overlays/_glyphs.tsx`: a caret on an accordion row
|
|
9
|
+
* and a chevron on a pager should not put an icon dependency on the render path
|
|
10
|
+
* of every page, and hand-set strokes stay hairline-thin at the 8–12px sizes
|
|
11
|
+
* console density asks for. `currentColor` everywhere — the tone comes from the
|
|
12
|
+
* parent.
|
|
13
|
+
*
|
|
14
|
+
* @internal Not part of the public API.
|
|
15
|
+
*/
|
|
16
|
+
/** A right-pointing chevron. Rotate it 90° to point down. */
|
|
17
|
+
function ChevronRightGlyph(props) {
|
|
18
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
19
|
+
viewBox: "0 0 16 16",
|
|
20
|
+
fill: "none",
|
|
21
|
+
stroke: "currentColor",
|
|
22
|
+
strokeWidth: "2",
|
|
23
|
+
strokeLinecap: "round",
|
|
24
|
+
strokeLinejoin: "round",
|
|
25
|
+
"aria-hidden": "true",
|
|
26
|
+
...props,
|
|
27
|
+
children: /* @__PURE__ */ jsx("path", { d: "m6 3 5 5-5 5" })
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/** A left-pointing chevron. */
|
|
31
|
+
function ChevronLeftGlyph(props) {
|
|
32
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
33
|
+
viewBox: "0 0 16 16",
|
|
34
|
+
fill: "none",
|
|
35
|
+
stroke: "currentColor",
|
|
36
|
+
strokeWidth: "2",
|
|
37
|
+
strokeLinecap: "round",
|
|
38
|
+
strokeLinejoin: "round",
|
|
39
|
+
"aria-hidden": "true",
|
|
40
|
+
...props,
|
|
41
|
+
children: /* @__PURE__ */ jsx("path", { d: "m10 3-5 5 5 5" })
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { ChevronLeftGlyph, ChevronRightGlyph };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Accordion } from "@base-ui/react/accordion";
|
|
3
|
+
//#region src/layout/accordion.d.ts
|
|
4
|
+
interface AccordionRootProps extends Omit<Accordion.Root.Props, "className"> {
|
|
5
|
+
/** Extra classes for the accordion frame. */
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
interface AccordionItemProps extends Omit<Accordion.Item.Props, "className"> {
|
|
9
|
+
/** Extra classes for the section. */
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
interface AccordionHeaderProps extends Omit<Accordion.Header.Props, "className"> {
|
|
13
|
+
/** Extra classes for the heading. */
|
|
14
|
+
className?: string;
|
|
15
|
+
}
|
|
16
|
+
interface AccordionTriggerProps extends Omit<Accordion.Trigger.Props, "className"> {
|
|
17
|
+
/** Extra classes for the summary row. */
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
interface AccordionPanelProps extends Omit<Accordion.Panel.Props, "className"> {
|
|
21
|
+
/** Extra classes for the animating box. Padding belongs on `bodyClassName`. */
|
|
22
|
+
className?: string;
|
|
23
|
+
/** Extra classes for the padded body inside it. */
|
|
24
|
+
bodyClassName?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A stack of sections, one (or several) open at a time.
|
|
28
|
+
*
|
|
29
|
+
* Wraps Base UI's `Accordion`, so the disclosure ARIA, keyboard handling and
|
|
30
|
+
* open-state bookkeeping are the primitive's. This layer adds the console skin:
|
|
31
|
+
* hairline separation, mono summary rows on the control ladder, and a height
|
|
32
|
+
* transition that respects `prefers-reduced-motion`.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* <Accordion.Root>
|
|
36
|
+
* <Accordion.Item value="routing">
|
|
37
|
+
* <Accordion.Header><Accordion.Trigger>routing</Accordion.Trigger></Accordion.Header>
|
|
38
|
+
* <Accordion.Panel>…</Accordion.Panel>
|
|
39
|
+
* </Accordion.Item>
|
|
40
|
+
* </Accordion.Root>
|
|
41
|
+
* @example
|
|
42
|
+
* <Accordion.Root multiple defaultValue={["routing"]}>…</Accordion.Root>
|
|
43
|
+
*/
|
|
44
|
+
declare const Accordion$1: {
|
|
45
|
+
Root: React.ForwardRefExoticComponent<Omit<AccordionRootProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
46
|
+
Item: React.ForwardRefExoticComponent<Omit<AccordionItemProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
47
|
+
Header: React.ForwardRefExoticComponent<Omit<AccordionHeaderProps, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
|
|
48
|
+
Trigger: React.ForwardRefExoticComponent<Omit<AccordionTriggerProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
49
|
+
Panel: React.ForwardRefExoticComponent<Omit<AccordionPanelProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
50
|
+
};
|
|
51
|
+
//#endregion
|
|
52
|
+
export { Accordion$1 as Accordion, AccordionHeaderProps, AccordionItemProps, AccordionPanelProps, AccordionRootProps, AccordionTriggerProps };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { accordionPanelClasses, collapseCaretClasses, collapseLabelClasses, collapsePanelBodyClasses, collapseTriggerClasses } from "./_collapse.js";
|
|
4
|
+
import { ChevronRightGlyph } from "./_glyphs.js";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Accordion } from "@base-ui/react/accordion";
|
|
8
|
+
/**
|
|
9
|
+
* A stack of sections, one (or several) open at a time.
|
|
10
|
+
*
|
|
11
|
+
* Wraps Base UI's `Accordion`, so the disclosure ARIA, keyboard handling and
|
|
12
|
+
* open-state bookkeeping are the primitive's. This layer adds the console skin:
|
|
13
|
+
* hairline separation, mono summary rows on the control ladder, and a height
|
|
14
|
+
* transition that respects `prefers-reduced-motion`.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* <Accordion.Root>
|
|
18
|
+
* <Accordion.Item value="routing">
|
|
19
|
+
* <Accordion.Header><Accordion.Trigger>routing</Accordion.Trigger></Accordion.Header>
|
|
20
|
+
* <Accordion.Panel>…</Accordion.Panel>
|
|
21
|
+
* </Accordion.Item>
|
|
22
|
+
* </Accordion.Root>
|
|
23
|
+
* @example
|
|
24
|
+
* <Accordion.Root multiple defaultValue={["routing"]}>…</Accordion.Root>
|
|
25
|
+
*/
|
|
26
|
+
const Accordion$1 = {
|
|
27
|
+
Root: React.forwardRef(function AccordionRoot({ className, ...elementProps }, ref) {
|
|
28
|
+
return /* @__PURE__ */ jsx(Accordion.Root, {
|
|
29
|
+
ref,
|
|
30
|
+
"data-slot": "accordion",
|
|
31
|
+
className: cn("flex min-w-0 flex-col", className),
|
|
32
|
+
...elementProps
|
|
33
|
+
});
|
|
34
|
+
}),
|
|
35
|
+
Item: React.forwardRef(function AccordionItem({ className, ...elementProps }, ref) {
|
|
36
|
+
return /* @__PURE__ */ jsx(Accordion.Item, {
|
|
37
|
+
ref,
|
|
38
|
+
"data-slot": "accordion-item",
|
|
39
|
+
className: cn("border-t border-border first:border-t-0", className),
|
|
40
|
+
...elementProps
|
|
41
|
+
});
|
|
42
|
+
}),
|
|
43
|
+
Header: React.forwardRef(function AccordionHeader({ className, ...elementProps }, ref) {
|
|
44
|
+
return /* @__PURE__ */ jsx(Accordion.Header, {
|
|
45
|
+
ref,
|
|
46
|
+
"data-slot": "accordion-header",
|
|
47
|
+
className: cn("m-0 flex", className),
|
|
48
|
+
...elementProps
|
|
49
|
+
});
|
|
50
|
+
}),
|
|
51
|
+
Trigger: React.forwardRef(function AccordionTrigger({ className, children, ...elementProps }, ref) {
|
|
52
|
+
return /* @__PURE__ */ jsxs(Accordion.Trigger, {
|
|
53
|
+
ref,
|
|
54
|
+
"data-slot": "accordion-trigger",
|
|
55
|
+
className: cn(collapseTriggerClasses, className),
|
|
56
|
+
...elementProps,
|
|
57
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
58
|
+
className: collapseLabelClasses,
|
|
59
|
+
children
|
|
60
|
+
}), /* @__PURE__ */ jsx(ChevronRightGlyph, {
|
|
61
|
+
"data-slot": "accordion-caret",
|
|
62
|
+
className: collapseCaretClasses
|
|
63
|
+
})]
|
|
64
|
+
});
|
|
65
|
+
}),
|
|
66
|
+
Panel: React.forwardRef(function AccordionPanel({ className, bodyClassName, children, ...elementProps }, ref) {
|
|
67
|
+
return /* @__PURE__ */ jsx(Accordion.Panel, {
|
|
68
|
+
ref,
|
|
69
|
+
"data-slot": "accordion-panel",
|
|
70
|
+
className: cn(accordionPanelClasses, className),
|
|
71
|
+
...elementProps,
|
|
72
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
73
|
+
"data-slot": "accordion-panel-body",
|
|
74
|
+
className: cn(collapsePanelBodyClasses, bodyClassName),
|
|
75
|
+
children
|
|
76
|
+
})
|
|
77
|
+
});
|
|
78
|
+
})
|
|
79
|
+
};
|
|
80
|
+
//#endregion
|
|
81
|
+
export { Accordion$1 as Accordion };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/layout/breadcrumb.d.ts
|
|
3
|
+
/** One crumb in the trail. */
|
|
4
|
+
interface BreadcrumbItem {
|
|
5
|
+
/** What the crumb says. */
|
|
6
|
+
label: React.ReactNode;
|
|
7
|
+
/** Where it goes. Renders an `<a>`. */
|
|
8
|
+
href?: string;
|
|
9
|
+
/** What it does. Renders a `<button>` when there is no `href`. */
|
|
10
|
+
onClick?: React.MouseEventHandler<HTMLElement>;
|
|
11
|
+
}
|
|
12
|
+
interface BreadcrumbProps extends Omit<React.ComponentPropsWithoutRef<"nav">, "children"> {
|
|
13
|
+
/** The trail, root first. The last entry is the current page. */
|
|
14
|
+
items: readonly BreadcrumbItem[];
|
|
15
|
+
/** What sits between crumbs. Defaults to `"/"`. */
|
|
16
|
+
separator?: React.ReactNode;
|
|
17
|
+
/** The nav's accessible name. Defaults to `"Breadcrumb"`. */
|
|
18
|
+
label?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Where you are, and how to get back.
|
|
22
|
+
*
|
|
23
|
+
* The last crumb is never a link: it is the page you are on, marked
|
|
24
|
+
* `aria-current="page"` and set in full-strength ink so the trail has one
|
|
25
|
+
* visible end. Separators are `aria-hidden` — a screen reader announcing
|
|
26
|
+
* "console slash patch slash universe 1" is reading punctuation, not structure.
|
|
27
|
+
*
|
|
28
|
+
* Static markup — no `"use client"`.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* <Breadcrumb items={[{ label: "Console", href: "/" }, { label: "Patch" }]} />
|
|
32
|
+
*/
|
|
33
|
+
declare const Breadcrumb: React.ForwardRefExoticComponent<BreadcrumbProps & React.RefAttributes<HTMLElement>>;
|
|
34
|
+
//#endregion
|
|
35
|
+
export { Breadcrumb, BreadcrumbItem, BreadcrumbProps };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { cn } from "../lib/cn.js";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/layout/breadcrumb.tsx
|
|
5
|
+
/**
|
|
6
|
+
* A crumb that goes somewhere. Muted until hovered, never underlined — the
|
|
7
|
+
* trail is navigation furniture and should not read as body-copy links.
|
|
8
|
+
*/
|
|
9
|
+
const CRUMB_LINK_CLASSES = "cursor-pointer rounded-(--radius-control) border-0 bg-transparent p-0 font-mono text-(length:--cue-text-label) text-fg-muted no-underline transition-colors duration-150 outline-none hover:text-accent focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-accent";
|
|
10
|
+
/**
|
|
11
|
+
* Where you are, and how to get back.
|
|
12
|
+
*
|
|
13
|
+
* The last crumb is never a link: it is the page you are on, marked
|
|
14
|
+
* `aria-current="page"` and set in full-strength ink so the trail has one
|
|
15
|
+
* visible end. Separators are `aria-hidden` — a screen reader announcing
|
|
16
|
+
* "console slash patch slash universe 1" is reading punctuation, not structure.
|
|
17
|
+
*
|
|
18
|
+
* Static markup — no `"use client"`.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* <Breadcrumb items={[{ label: "Console", href: "/" }, { label: "Patch" }]} />
|
|
22
|
+
*/
|
|
23
|
+
const Breadcrumb = React.forwardRef(function Breadcrumb({ className, items, separator = "/", label = "Breadcrumb", ...elementProps }, ref) {
|
|
24
|
+
return /* @__PURE__ */ jsx("nav", {
|
|
25
|
+
ref,
|
|
26
|
+
"data-slot": "breadcrumb",
|
|
27
|
+
"aria-label": label,
|
|
28
|
+
className: cn("min-w-0", className),
|
|
29
|
+
...elementProps,
|
|
30
|
+
children: /* @__PURE__ */ jsx("ol", {
|
|
31
|
+
className: "m-0 flex list-none flex-wrap items-center gap-(--cue-space-2) p-0 font-mono text-(length:--cue-text-label) text-fg-muted",
|
|
32
|
+
children: items.map((item, index) => {
|
|
33
|
+
const last = index === items.length - 1;
|
|
34
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [index === 0 ? null : /* @__PURE__ */ jsx("li", {
|
|
35
|
+
"data-slot": "breadcrumb-separator",
|
|
36
|
+
"aria-hidden": "true",
|
|
37
|
+
className: "text-fg-subtle select-none",
|
|
38
|
+
children: separator
|
|
39
|
+
}), /* @__PURE__ */ jsx("li", {
|
|
40
|
+
"data-slot": "breadcrumb-item",
|
|
41
|
+
className: "min-w-0",
|
|
42
|
+
children: last ? /* @__PURE__ */ jsx("span", {
|
|
43
|
+
"data-slot": "breadcrumb-current",
|
|
44
|
+
"aria-current": "page",
|
|
45
|
+
className: "truncate text-fg",
|
|
46
|
+
children: item.label
|
|
47
|
+
}) : item.href !== void 0 ? /* @__PURE__ */ jsx("a", {
|
|
48
|
+
href: item.href,
|
|
49
|
+
onClick: item.onClick,
|
|
50
|
+
className: CRUMB_LINK_CLASSES,
|
|
51
|
+
children: item.label
|
|
52
|
+
}) : item.onClick !== void 0 ? /* @__PURE__ */ jsx("button", {
|
|
53
|
+
type: "button",
|
|
54
|
+
onClick: item.onClick,
|
|
55
|
+
className: CRUMB_LINK_CLASSES,
|
|
56
|
+
children: item.label
|
|
57
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
58
|
+
className: "truncate",
|
|
59
|
+
children: item.label
|
|
60
|
+
})
|
|
61
|
+
})] }, index);
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
//#endregion
|
|
67
|
+
export { Breadcrumb };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/layout/card.d.ts
|
|
3
|
+
interface CardRootProps extends React.ComponentPropsWithoutRef<"div"> {
|
|
4
|
+
/**
|
|
5
|
+
* Separate the card's sections with hairline seams instead of whitespace.
|
|
6
|
+
*
|
|
7
|
+
* The card is then filled with the border colour and its sections sit `1px`
|
|
8
|
+
* apart, each painting its own opaque ground — the same idiom as `SeamList`,
|
|
9
|
+
* where the gap *is* the rule and can never double up with a border.
|
|
10
|
+
*/
|
|
11
|
+
seam?: boolean;
|
|
12
|
+
}
|
|
13
|
+
interface CardHeaderProps extends React.ComponentPropsWithoutRef<"div"> {
|
|
14
|
+
/**
|
|
15
|
+
* Right-hand slot: the controls that act on the whole card (a menu, a status
|
|
16
|
+
* chip, a count).
|
|
17
|
+
*/
|
|
18
|
+
actions?: React.ReactNode;
|
|
19
|
+
/** The leading cluster — normally a {@link CardTitle} and a description. */
|
|
20
|
+
children?: React.ReactNode;
|
|
21
|
+
}
|
|
22
|
+
/** Props for {@link CardTitle}: the native `<h3>` surface plus `className`. */
|
|
23
|
+
type CardTitleProps = React.ComponentPropsWithoutRef<"h3">;
|
|
24
|
+
/** Props for {@link CardDescription}: the native `<p>` surface plus `className`. */
|
|
25
|
+
type CardDescriptionProps = React.ComponentPropsWithoutRef<"p">;
|
|
26
|
+
/** Props for {@link CardContent}: the native `<div>` surface plus `className`. */
|
|
27
|
+
type CardContentProps = React.ComponentPropsWithoutRef<"div">;
|
|
28
|
+
/** Props for {@link CardFooter}: the native `<div>` surface plus `className`. */
|
|
29
|
+
type CardFooterProps = React.ComponentPropsWithoutRef<"div">;
|
|
30
|
+
/**
|
|
31
|
+
* A padded container for one thing: a summary, a setting group, a preview.
|
|
32
|
+
*
|
|
33
|
+
* Every section paints its own `surface-1` ground, which is what lets the root
|
|
34
|
+
* switch to the seam idiom without any of the parts knowing.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* <Card.Root seam>
|
|
38
|
+
* <Card.Header><Card.Title>Failover</Card.Title></Card.Header>
|
|
39
|
+
* <Card.Content>…</Card.Content>
|
|
40
|
+
* </Card.Root>
|
|
41
|
+
*/
|
|
42
|
+
declare const Card: {
|
|
43
|
+
Root: React.ForwardRefExoticComponent<CardRootProps & React.RefAttributes<HTMLDivElement>>;
|
|
44
|
+
Header: React.ForwardRefExoticComponent<CardHeaderProps & React.RefAttributes<HTMLDivElement>>;
|
|
45
|
+
Title: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
|
|
46
|
+
Description: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
|
|
47
|
+
Content: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
48
|
+
Footer: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
export { Card, CardContentProps, CardDescriptionProps, CardFooterProps, CardHeaderProps, CardRootProps, CardTitleProps };
|