@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,256 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { CopyButton } from "./copy-button.js";
|
|
4
|
+
import { toRem } from "./_rem.js";
|
|
5
|
+
import { mulberry32, usePrefersReducedMotion } from "./_motion.js";
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
//#region src/instruments/terminal-frame.tsx
|
|
9
|
+
const LINE_TONES = {
|
|
10
|
+
neutral: "text-fg-muted",
|
|
11
|
+
accent: "text-accent",
|
|
12
|
+
ok: "text-ok",
|
|
13
|
+
warn: "text-warn",
|
|
14
|
+
danger: "text-danger",
|
|
15
|
+
info: "text-info"
|
|
16
|
+
};
|
|
17
|
+
/** The braille spinner every CLI in the portfolio uses. */
|
|
18
|
+
const SPINNER_GLYPHS = [
|
|
19
|
+
"⠋",
|
|
20
|
+
"⠙",
|
|
21
|
+
"⠹",
|
|
22
|
+
"⠸",
|
|
23
|
+
"⠼",
|
|
24
|
+
"⠴",
|
|
25
|
+
"⠦",
|
|
26
|
+
"⠧",
|
|
27
|
+
"⠇",
|
|
28
|
+
"⠏"
|
|
29
|
+
];
|
|
30
|
+
const SPINNER_MS = 80;
|
|
31
|
+
const DEFAULT_KEYSTROKE_MS = 55;
|
|
32
|
+
const DEFAULT_HOLD_MS = 600;
|
|
33
|
+
const DEFAULT_PENDING_MS = 900;
|
|
34
|
+
const DEFAULT_SEED = 1;
|
|
35
|
+
const IDLE = {
|
|
36
|
+
lines: [],
|
|
37
|
+
typing: null,
|
|
38
|
+
spinner: null,
|
|
39
|
+
done: true
|
|
40
|
+
};
|
|
41
|
+
/** Normalise the shorthand so the renderer only ever sees one shape. */
|
|
42
|
+
function toLine(line) {
|
|
43
|
+
return typeof line === "string" ? { text: line } : line;
|
|
44
|
+
}
|
|
45
|
+
/** Every line a script ends on — what reduced motion renders straight away. */
|
|
46
|
+
function finalLines(script) {
|
|
47
|
+
return script.steps.flatMap((step) => [...step.command === void 0 ? [] : [{
|
|
48
|
+
text: step.command,
|
|
49
|
+
command: true
|
|
50
|
+
}], ...(step.output ?? []).map(toLine)]);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* A recessed terminal: mono, `$`-prefixed commands, optional typed playback.
|
|
54
|
+
*
|
|
55
|
+
* Recessed rather than raised — `bg-sunken` sits the transcript *into* the page
|
|
56
|
+
* the way a real console does (the snuffle convention, where the terminal
|
|
57
|
+
* surface is the only thing darker than the background).
|
|
58
|
+
*
|
|
59
|
+
* The `simulate` player is deliberately not a GIF or a video: it is text, so it
|
|
60
|
+
* copies, it scales with the type ramp, it re-themes, and it costs nothing to
|
|
61
|
+
* load. Keystrokes are jittered from a seed so a marketing screenshot is
|
|
62
|
+
* reproducible, and the whole animation is replaced by its final frame under
|
|
63
|
+
* `prefers-reduced-motion` — with no timers scheduled at all, rather than an
|
|
64
|
+
* animation that runs invisibly.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* <TerminalFrame
|
|
68
|
+
* title="install"
|
|
69
|
+
* copy
|
|
70
|
+
* lines={[{ text: "pnpm add @cueplusplus/ui", command: true }, "+ 1 package"]}
|
|
71
|
+
* />
|
|
72
|
+
* @example
|
|
73
|
+
* const SCRIPT = { steps: [{ command: "cue build", pending: "compiling", output: ["12 cues"] }] };
|
|
74
|
+
* <TerminalFrame simulate={SCRIPT} />
|
|
75
|
+
*/
|
|
76
|
+
const TerminalFrame = React.forwardRef(function TerminalFrame({ className, title, lines, prompt = "$", copy = false, copyValue, simulate, height, children, ...elementProps }, ref) {
|
|
77
|
+
const reduced = usePrefersReducedMotion();
|
|
78
|
+
const [transcript, setTranscript] = React.useState(IDLE);
|
|
79
|
+
React.useEffect(() => {
|
|
80
|
+
if (simulate === void 0) {
|
|
81
|
+
setTranscript(IDLE);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (reduced) {
|
|
85
|
+
setTranscript({
|
|
86
|
+
lines: finalLines(simulate),
|
|
87
|
+
typing: null,
|
|
88
|
+
spinner: null,
|
|
89
|
+
done: true
|
|
90
|
+
});
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
let cancelled = false;
|
|
94
|
+
let timer;
|
|
95
|
+
const sleep = (ms) => new Promise((resolve) => {
|
|
96
|
+
timer = setTimeout(resolve, ms);
|
|
97
|
+
});
|
|
98
|
+
const random = mulberry32(simulate.seed ?? DEFAULT_SEED);
|
|
99
|
+
const keystrokeMs = simulate.keystrokeMs ?? DEFAULT_KEYSTROKE_MS;
|
|
100
|
+
const holdMs = simulate.holdMs ?? DEFAULT_HOLD_MS;
|
|
101
|
+
const printed = [];
|
|
102
|
+
setTranscript({
|
|
103
|
+
lines: [],
|
|
104
|
+
typing: null,
|
|
105
|
+
spinner: null,
|
|
106
|
+
done: false
|
|
107
|
+
});
|
|
108
|
+
(async () => {
|
|
109
|
+
for (const step of simulate.steps) {
|
|
110
|
+
if (step.command !== void 0) {
|
|
111
|
+
for (let index = 1; index <= step.command.length; index += 1) {
|
|
112
|
+
await sleep(keystrokeMs * (.6 + random()));
|
|
113
|
+
if (cancelled) return;
|
|
114
|
+
setTranscript({
|
|
115
|
+
lines: [...printed],
|
|
116
|
+
typing: step.command.slice(0, index),
|
|
117
|
+
spinner: null,
|
|
118
|
+
done: false
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
await sleep(holdMs);
|
|
122
|
+
if (cancelled) return;
|
|
123
|
+
printed.push({
|
|
124
|
+
text: step.command,
|
|
125
|
+
command: true
|
|
126
|
+
});
|
|
127
|
+
setTranscript({
|
|
128
|
+
lines: [...printed],
|
|
129
|
+
typing: null,
|
|
130
|
+
spinner: null,
|
|
131
|
+
done: false
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
if (step.pending !== void 0) {
|
|
135
|
+
const frames = Math.max(1, Math.round((step.pendingMs ?? DEFAULT_PENDING_MS) / SPINNER_MS));
|
|
136
|
+
for (let index = 0; index < frames; index += 1) {
|
|
137
|
+
setTranscript({
|
|
138
|
+
lines: [...printed],
|
|
139
|
+
typing: null,
|
|
140
|
+
spinner: {
|
|
141
|
+
label: step.pending,
|
|
142
|
+
index
|
|
143
|
+
},
|
|
144
|
+
done: false
|
|
145
|
+
});
|
|
146
|
+
await sleep(SPINNER_MS);
|
|
147
|
+
if (cancelled) return;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
for (const line of step.output ?? []) printed.push(toLine(line));
|
|
151
|
+
setTranscript({
|
|
152
|
+
lines: [...printed],
|
|
153
|
+
typing: null,
|
|
154
|
+
spinner: null,
|
|
155
|
+
done: false
|
|
156
|
+
});
|
|
157
|
+
await sleep(holdMs);
|
|
158
|
+
if (cancelled) return;
|
|
159
|
+
}
|
|
160
|
+
setTranscript({
|
|
161
|
+
lines: [...printed],
|
|
162
|
+
typing: null,
|
|
163
|
+
spinner: null,
|
|
164
|
+
done: true
|
|
165
|
+
});
|
|
166
|
+
})();
|
|
167
|
+
return () => {
|
|
168
|
+
cancelled = true;
|
|
169
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
170
|
+
};
|
|
171
|
+
}, [reduced, simulate]);
|
|
172
|
+
const preamble = (lines ?? []).map(toLine);
|
|
173
|
+
const rendered = [...preamble, ...transcript.lines];
|
|
174
|
+
const commands = [...preamble, ...simulate === void 0 ? [] : finalLines(simulate)].filter((line) => line.command === true);
|
|
175
|
+
const clipboard = copyValue ?? commands.map((line) => line.text).join("\n");
|
|
176
|
+
const simulating = simulate !== void 0 && !transcript.done;
|
|
177
|
+
const promptGlyph = /* @__PURE__ */ jsx("span", {
|
|
178
|
+
"aria-hidden": "true",
|
|
179
|
+
"data-slot": "terminal-frame-prompt",
|
|
180
|
+
className: "mr-(--cue-space-3) shrink-0 text-accent select-none",
|
|
181
|
+
children: prompt
|
|
182
|
+
});
|
|
183
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
184
|
+
ref,
|
|
185
|
+
"data-slot": "terminal-frame",
|
|
186
|
+
"data-simulating": simulate === void 0 ? void 0 : String(simulating),
|
|
187
|
+
className: cn("flex min-w-0 flex-col overflow-hidden rounded-(--radius-surface) border border-border bg-sunken font-mono text-(length:--cue-text-ui) text-fg-muted", className),
|
|
188
|
+
...elementProps,
|
|
189
|
+
children: [title === void 0 && !copy ? null : /* @__PURE__ */ jsxs("div", {
|
|
190
|
+
"data-slot": "terminal-frame-bar",
|
|
191
|
+
className: "flex h-control-md shrink-0 items-center justify-between gap-(--cue-space-3) border-b border-border px-(--cue-pad-row-x)",
|
|
192
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
193
|
+
"data-slot": "terminal-frame-title",
|
|
194
|
+
className: "min-w-0 truncate text-(length:--cue-text-label) tracking-[0.15em] text-fg-subtle uppercase",
|
|
195
|
+
children: title
|
|
196
|
+
}), copy ? /* @__PURE__ */ jsx("span", {
|
|
197
|
+
"data-slot": "terminal-frame-copy",
|
|
198
|
+
"data-value": clipboard,
|
|
199
|
+
className: "shrink-0",
|
|
200
|
+
children: /* @__PURE__ */ jsx(CopyButton, {
|
|
201
|
+
value: clipboard,
|
|
202
|
+
variant: "ghost",
|
|
203
|
+
size: "sm"
|
|
204
|
+
})
|
|
205
|
+
}) : null]
|
|
206
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
207
|
+
"data-slot": "terminal-frame-body",
|
|
208
|
+
className: "min-w-0 flex-1 overflow-auto p-(--cue-space-5) leading-relaxed whitespace-pre-wrap",
|
|
209
|
+
style: height === void 0 ? void 0 : { height: toRem(height) },
|
|
210
|
+
children: [
|
|
211
|
+
rendered.map((line, index) => /* @__PURE__ */ jsxs("div", {
|
|
212
|
+
"data-slot": "terminal-frame-line",
|
|
213
|
+
"data-command": line.command === true ? "" : void 0,
|
|
214
|
+
className: cn("flex min-w-0", LINE_TONES[line.tone ?? "neutral"]),
|
|
215
|
+
children: [line.command === true ? promptGlyph : null, /* @__PURE__ */ jsx("span", {
|
|
216
|
+
className: "min-w-0 break-all",
|
|
217
|
+
children: line.text
|
|
218
|
+
})]
|
|
219
|
+
}, index)),
|
|
220
|
+
transcript.typing === null ? null : /* @__PURE__ */ jsxs("div", {
|
|
221
|
+
"data-slot": "terminal-frame-line",
|
|
222
|
+
"data-typing": "",
|
|
223
|
+
className: "flex min-w-0 text-fg",
|
|
224
|
+
children: [
|
|
225
|
+
promptGlyph,
|
|
226
|
+
/* @__PURE__ */ jsx("span", {
|
|
227
|
+
className: "min-w-0 break-all",
|
|
228
|
+
children: transcript.typing
|
|
229
|
+
}),
|
|
230
|
+
/* @__PURE__ */ jsx("span", {
|
|
231
|
+
"aria-hidden": "true",
|
|
232
|
+
className: "animate-pulse motion-reduce:animate-none",
|
|
233
|
+
children: "▍"
|
|
234
|
+
})
|
|
235
|
+
]
|
|
236
|
+
}),
|
|
237
|
+
transcript.spinner === null ? null : /* @__PURE__ */ jsxs("div", {
|
|
238
|
+
"data-slot": "terminal-frame-line",
|
|
239
|
+
"data-pending": "",
|
|
240
|
+
className: "flex min-w-0 text-fg-subtle",
|
|
241
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
242
|
+
"aria-hidden": "true",
|
|
243
|
+
className: "mr-(--cue-space-3) shrink-0 text-accent",
|
|
244
|
+
children: SPINNER_GLYPHS[transcript.spinner.index % SPINNER_GLYPHS.length]
|
|
245
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
246
|
+
className: "min-w-0 break-all",
|
|
247
|
+
children: transcript.spinner.label
|
|
248
|
+
})]
|
|
249
|
+
}),
|
|
250
|
+
children
|
|
251
|
+
]
|
|
252
|
+
})]
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
//#endregion
|
|
256
|
+
export { TerminalFrame };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ButtonProps } from "../primitives/button.js";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
//#region src/instruments/two-step-button.d.ts
|
|
4
|
+
/** Which end of the warning scale this action sits at. */
|
|
5
|
+
type TwoStepTone = "danger" | "warn";
|
|
6
|
+
interface TwoStepButtonProps extends Omit<ButtonProps, "onClick" | "variant" | "onConfirm" | "children"> {
|
|
7
|
+
/** Fired once, when the *second* press lands. */
|
|
8
|
+
onConfirm: () => void;
|
|
9
|
+
/** The idle label — name the action, not the button ("Delete rig", not "Delete"). */
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
/** Label on the armed half. Defaults to `"Confirm"`. */
|
|
12
|
+
confirmLabel?: React.ReactNode;
|
|
13
|
+
/** Label on the escape hatch. Defaults to `"Cancel"`. */
|
|
14
|
+
cancelLabel?: React.ReactNode;
|
|
15
|
+
/** How severe this is. Defaults to `"danger"`. */
|
|
16
|
+
tone?: TwoStepTone;
|
|
17
|
+
/** ms before an untouched armed state disarms itself. `0` disables. Defaults to `4000`. */
|
|
18
|
+
timeout?: number;
|
|
19
|
+
/** Called with the new armed state on every arm and disarm. */
|
|
20
|
+
onArmedChange?: (armed: boolean) => void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Arm, then confirm: a destructive action that takes two deliberate presses.
|
|
24
|
+
*
|
|
25
|
+
* The most-reused interaction in the portfolio (fifteen call sites, three
|
|
26
|
+
* hand-rolled implementations) and the right shape for a destructive action
|
|
27
|
+
* that is *routine* — deleting a cue, clearing a patch. A modal
|
|
28
|
+
* `AlertDialog` is the right shape for a rare and expensive one; putting a
|
|
29
|
+
* dialog in front of an action people take twenty times an hour just teaches
|
|
30
|
+
* them to dismiss dialogs.
|
|
31
|
+
*
|
|
32
|
+
* Four ways out, because an armed button left lying around is a trap: Cancel,
|
|
33
|
+
* Escape, moving focus away, and a timeout. Focus lands on **Cancel** when the
|
|
34
|
+
* pair arms, never on the destructive half — the same ruling as a destructive
|
|
35
|
+
* dialog's default button, and it means a stuck Enter key cannot walk through
|
|
36
|
+
* both steps.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* <TwoStepButton onConfirm={() => deleteRig(id)}>Delete rig</TwoStepButton>
|
|
40
|
+
* @example
|
|
41
|
+
* <TwoStepButton tone="warn" timeout={0} confirmLabel="Reset it" onConfirm={reset}>
|
|
42
|
+
* Reset patch
|
|
43
|
+
* </TwoStepButton>
|
|
44
|
+
*/
|
|
45
|
+
declare const TwoStepButton: React.ForwardRefExoticComponent<TwoStepButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
46
|
+
//#endregion
|
|
47
|
+
export { TwoStepButton, TwoStepButtonProps, TwoStepTone };
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { Button } from "../primitives/button.js";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/instruments/two-step-button.tsx
|
|
7
|
+
/**
|
|
8
|
+
* The armed confirm button's fill.
|
|
9
|
+
*
|
|
10
|
+
* The ink is a literal rather than a token because there is no `--cue-warn-fg`
|
|
11
|
+
* or `--cue-danger-fg` in the palette — the same pragmatism as `Button`'s
|
|
12
|
+
* `danger` variant, which is also `text-white`. Every theme's `warn` is an
|
|
13
|
+
* amber and every theme's `danger` is a red, so the two literals hold.
|
|
14
|
+
*/
|
|
15
|
+
const CONFIRM_TONES = {
|
|
16
|
+
danger: "border-transparent bg-danger text-white hover:opacity-90",
|
|
17
|
+
warn: "border-transparent bg-warn text-black hover:opacity-90"
|
|
18
|
+
};
|
|
19
|
+
/** The idle trigger: outline only, so a destructive action is never the loudest thing on screen. */
|
|
20
|
+
const IDLE_TONES = {
|
|
21
|
+
danger: "border-danger/40 text-danger hover:border-danger hover:bg-danger/10",
|
|
22
|
+
warn: "border-warn/40 text-warn hover:border-warn hover:bg-warn/10"
|
|
23
|
+
};
|
|
24
|
+
/** ms the armed state survives without input before it gives up. */
|
|
25
|
+
const DEFAULT_TIMEOUT_MS = 4e3;
|
|
26
|
+
/**
|
|
27
|
+
* Arm, then confirm: a destructive action that takes two deliberate presses.
|
|
28
|
+
*
|
|
29
|
+
* The most-reused interaction in the portfolio (fifteen call sites, three
|
|
30
|
+
* hand-rolled implementations) and the right shape for a destructive action
|
|
31
|
+
* that is *routine* — deleting a cue, clearing a patch. A modal
|
|
32
|
+
* `AlertDialog` is the right shape for a rare and expensive one; putting a
|
|
33
|
+
* dialog in front of an action people take twenty times an hour just teaches
|
|
34
|
+
* them to dismiss dialogs.
|
|
35
|
+
*
|
|
36
|
+
* Four ways out, because an armed button left lying around is a trap: Cancel,
|
|
37
|
+
* Escape, moving focus away, and a timeout. Focus lands on **Cancel** when the
|
|
38
|
+
* pair arms, never on the destructive half — the same ruling as a destructive
|
|
39
|
+
* dialog's default button, and it means a stuck Enter key cannot walk through
|
|
40
|
+
* both steps.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* <TwoStepButton onConfirm={() => deleteRig(id)}>Delete rig</TwoStepButton>
|
|
44
|
+
* @example
|
|
45
|
+
* <TwoStepButton tone="warn" timeout={0} confirmLabel="Reset it" onConfirm={reset}>
|
|
46
|
+
* Reset patch
|
|
47
|
+
* </TwoStepButton>
|
|
48
|
+
*/
|
|
49
|
+
const TwoStepButton = React.forwardRef(function TwoStepButton({ className, onConfirm, children, confirmLabel = "Confirm", cancelLabel = "Cancel", tone = "danger", timeout = DEFAULT_TIMEOUT_MS, onArmedChange, size, disabled, ...buttonProps }, ref) {
|
|
50
|
+
const [armed, setArmed] = React.useState(false);
|
|
51
|
+
const triggerRef = React.useRef(null);
|
|
52
|
+
const cancelRef = React.useRef(null);
|
|
53
|
+
const groupRef = React.useRef(null);
|
|
54
|
+
const timerRef = React.useRef(void 0);
|
|
55
|
+
const restoreFocusRef = React.useRef(false);
|
|
56
|
+
const setTriggerRef = React.useCallback((element) => {
|
|
57
|
+
triggerRef.current = element;
|
|
58
|
+
if (typeof ref === "function") ref(element);
|
|
59
|
+
else if (ref !== null) ref.current = element;
|
|
60
|
+
}, [ref]);
|
|
61
|
+
const clearTimer = React.useCallback(() => {
|
|
62
|
+
if (timerRef.current !== void 0) clearTimeout(timerRef.current);
|
|
63
|
+
timerRef.current = void 0;
|
|
64
|
+
}, []);
|
|
65
|
+
React.useEffect(() => clearTimer, [clearTimer]);
|
|
66
|
+
const disarm = React.useCallback((restoreFocus) => {
|
|
67
|
+
clearTimer();
|
|
68
|
+
restoreFocusRef.current = restoreFocus;
|
|
69
|
+
setArmed(false);
|
|
70
|
+
onArmedChange?.(false);
|
|
71
|
+
}, [clearTimer, onArmedChange]);
|
|
72
|
+
const arm = React.useCallback(() => {
|
|
73
|
+
setArmed(true);
|
|
74
|
+
onArmedChange?.(true);
|
|
75
|
+
if (timeout > 0) {
|
|
76
|
+
clearTimer();
|
|
77
|
+
timerRef.current = setTimeout(() => {
|
|
78
|
+
timerRef.current = void 0;
|
|
79
|
+
disarm(true);
|
|
80
|
+
}, timeout);
|
|
81
|
+
}
|
|
82
|
+
}, [
|
|
83
|
+
clearTimer,
|
|
84
|
+
disarm,
|
|
85
|
+
onArmedChange,
|
|
86
|
+
timeout
|
|
87
|
+
]);
|
|
88
|
+
React.useEffect(() => {
|
|
89
|
+
if (armed) {
|
|
90
|
+
cancelRef.current?.focus();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (!restoreFocusRef.current) return;
|
|
94
|
+
restoreFocusRef.current = false;
|
|
95
|
+
triggerRef.current?.focus();
|
|
96
|
+
}, [armed]);
|
|
97
|
+
if (!armed) return /* @__PURE__ */ jsx(Button, {
|
|
98
|
+
ref: setTriggerRef,
|
|
99
|
+
variant: "outline",
|
|
100
|
+
size,
|
|
101
|
+
disabled,
|
|
102
|
+
"data-slot": "two-step-button",
|
|
103
|
+
"data-tone": tone,
|
|
104
|
+
"data-armed": "false",
|
|
105
|
+
className: cn(IDLE_TONES[tone], className),
|
|
106
|
+
onClick: arm,
|
|
107
|
+
...buttonProps,
|
|
108
|
+
children
|
|
109
|
+
});
|
|
110
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
111
|
+
ref: groupRef,
|
|
112
|
+
"data-slot": "two-step-button-armed",
|
|
113
|
+
"data-tone": tone,
|
|
114
|
+
className: "inline-flex items-center gap-(--cue-space-2)",
|
|
115
|
+
onKeyDown: (event) => {
|
|
116
|
+
if (event.key !== "Escape") return;
|
|
117
|
+
event.stopPropagation();
|
|
118
|
+
disarm(true);
|
|
119
|
+
},
|
|
120
|
+
onBlur: (event) => {
|
|
121
|
+
const next = event.relatedTarget;
|
|
122
|
+
if (next !== null && groupRef.current?.contains(next) === true) return;
|
|
123
|
+
disarm(false);
|
|
124
|
+
},
|
|
125
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
126
|
+
ref: cancelRef,
|
|
127
|
+
variant: "ghost",
|
|
128
|
+
size,
|
|
129
|
+
"data-slot": "two-step-button-cancel",
|
|
130
|
+
onClick: () => disarm(true),
|
|
131
|
+
children: cancelLabel
|
|
132
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
133
|
+
variant: "outline",
|
|
134
|
+
size,
|
|
135
|
+
"data-slot": "two-step-button-confirm",
|
|
136
|
+
className: cn(CONFIRM_TONES[tone], className),
|
|
137
|
+
onClick: () => {
|
|
138
|
+
disarm(true);
|
|
139
|
+
onConfirm();
|
|
140
|
+
},
|
|
141
|
+
...buttonProps,
|
|
142
|
+
children: confirmLabel
|
|
143
|
+
})]
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
//#endregion
|
|
147
|
+
export { TwoStepButton };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/instruments/usage-chart.d.ts
|
|
3
|
+
/** One sample: a timestamp in ms, and a percentage. */
|
|
4
|
+
interface UsageChartPoint {
|
|
5
|
+
/** Epoch ms. Non-finite and non-positive timestamps are dropped. */
|
|
6
|
+
t: number;
|
|
7
|
+
/** Percentage of the ceiling. Clamped to 0–100 on the way in. */
|
|
8
|
+
v: number;
|
|
9
|
+
}
|
|
10
|
+
/** Stroke colour, in the shared status vocabulary. */
|
|
11
|
+
type UsageChartTone = "accent" | "ok" | "busy" | "warn" | "danger" | "info";
|
|
12
|
+
interface UsageChartProps extends Omit<React.ComponentPropsWithoutRef<"div">, "children"> {
|
|
13
|
+
/** The series. Sorted and cleaned internally; order in is not order out. */
|
|
14
|
+
points: readonly UsageChartPoint[];
|
|
15
|
+
/** Stroke tone. Defaults to `"accent"`. */
|
|
16
|
+
tone?: UsageChartTone;
|
|
17
|
+
/** Plot height in px at the 16px root. Defaults to `120`. */
|
|
18
|
+
height?: number;
|
|
19
|
+
/** Break the line when consecutive samples are further apart than this, in ms. */
|
|
20
|
+
gapMs?: number;
|
|
21
|
+
/** Draw a dashed rule at this percentage — where throttling starts, say. */
|
|
22
|
+
threshold?: number;
|
|
23
|
+
/** The accessible name. Name the series; the shape is not self-describing. */
|
|
24
|
+
label?: string;
|
|
25
|
+
/** What to say when there is nothing to plot. Defaults to `"No data yet"`. */
|
|
26
|
+
emptyLabel?: string;
|
|
27
|
+
/** Format a sample's timestamp for the tooltip. Defaults to a short local date-time. */
|
|
28
|
+
formatTimestamp?: (t: number) => string;
|
|
29
|
+
/** Format a sample's value for the tooltip. Defaults to `"87%"`. */
|
|
30
|
+
formatValue?: (v: number) => string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A quota trace: where you sit against the ceiling, over time.
|
|
34
|
+
*
|
|
35
|
+
* Dependency-free inline SVG — a charting library is a large price for one
|
|
36
|
+
* line and five gridlines, and none of them draws the three things that make
|
|
37
|
+
* this chart honest:
|
|
38
|
+
*
|
|
39
|
+
* 1. **The y axis is always 0–100.** A quota chart auto-scaled to its own range
|
|
40
|
+
* makes a flat 3% look identical to a flat 95%. The ceiling is the reading,
|
|
41
|
+
* so the ceiling is always drawn.
|
|
42
|
+
* 2. **Gaps are gaps.** When the sweep does not run, the line breaks. Joining
|
|
43
|
+
* across a hole invents data — and worse, invents a *smooth* trend across
|
|
44
|
+
* exactly the window nothing is known about. The area fill stops at the
|
|
45
|
+
* break for the same reason.
|
|
46
|
+
* 3. **Out-of-range values are clamped, not plotted.** Upstream numbers are
|
|
47
|
+
* reverse-engineered and can be anything; 140% should read as a flat line on
|
|
48
|
+
* the ceiling, not as a path drawn over the axis labels.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* <UsageChart label="API requests" points={series} threshold={80} tone="warn" />
|
|
52
|
+
*/
|
|
53
|
+
declare const UsageChart: React.ForwardRefExoticComponent<UsageChartProps & React.RefAttributes<HTMLDivElement>>;
|
|
54
|
+
//#endregion
|
|
55
|
+
export { UsageChart, UsageChartPoint, UsageChartProps, UsageChartTone };
|