@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,78 @@
|
|
|
1
|
+
import { ThemeOverrides, ThemeScope } from "./_overrides.js";
|
|
2
|
+
//#region src/configurator/_export.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* The four things a configured theme can leave the browser as.
|
|
5
|
+
*
|
|
6
|
+
* A panel that only changes the page in front of you is a demo. These are what
|
|
7
|
+
* make it a tool: the stylesheet you paste, the token file your build reads, the
|
|
8
|
+
* generator call you check in, and the registry item someone else installs. All
|
|
9
|
+
* four are derived from the same `ThemeOverrides` value the panel is applying —
|
|
10
|
+
* the CSS one is *literally* the applied stylesheet — so an export can never
|
|
11
|
+
* describe a theme the page is not already wearing.
|
|
12
|
+
*
|
|
13
|
+
* Two of the four are lossy in a way worth stating out loud:
|
|
14
|
+
*
|
|
15
|
+
* - `createTheme()` takes **anchors**, not tokens. Move the accent and the call
|
|
16
|
+
* reproduces it exactly; move `--cue-border` and there is no anchor to put it
|
|
17
|
+
* in, because borders are derived from the ground. Rather than drop those
|
|
18
|
+
* quietly the snippet lists them in a trailing comment and points at the CSS
|
|
19
|
+
* export, which is lossless by construction.
|
|
20
|
+
* - The DTCG file speaks the tokens package's vocabulary, which is not quite the
|
|
21
|
+
* CSS one: `--cue-density` is authored as `density-factor`, and
|
|
22
|
+
* `--cue-font-scale` has no source token at all (the provider publishes it
|
|
23
|
+
* inline, per render). The first is renamed, the second is omitted.
|
|
24
|
+
*
|
|
25
|
+
* @internal Not part of the public API.
|
|
26
|
+
*/
|
|
27
|
+
/** Which export a format id refers to. */
|
|
28
|
+
type ExportFormatId = "css" | "dtcg" | "create-theme" | "registry";
|
|
29
|
+
/** One export: what it is, what to call the file, and the text itself. */
|
|
30
|
+
interface ThemeExport {
|
|
31
|
+
/** Stable id, used as the tab value. */
|
|
32
|
+
id: ExportFormatId;
|
|
33
|
+
/** Tab label. */
|
|
34
|
+
label: string;
|
|
35
|
+
/** Suggested download filename. */
|
|
36
|
+
filename: string;
|
|
37
|
+
/** MIME type for the download. */
|
|
38
|
+
mediaType: string;
|
|
39
|
+
/** One line saying what a reader does with it. */
|
|
40
|
+
description: string;
|
|
41
|
+
/** The exported text. */
|
|
42
|
+
text: string;
|
|
43
|
+
}
|
|
44
|
+
interface BuildExportsOptions {
|
|
45
|
+
/** The overrides to export. */
|
|
46
|
+
overrides: ThemeOverrides;
|
|
47
|
+
/** The theme and mode the panel is editing. */
|
|
48
|
+
scope: ThemeScope;
|
|
49
|
+
/** Name for the generated theme. Falls back to `"<preset>-custom"` when unusable. */
|
|
50
|
+
name?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The name to put on a generated theme.
|
|
54
|
+
*
|
|
55
|
+
* The name lands inside `[data-theme="…"]`, a filename and a registry id, so
|
|
56
|
+
* anything that is not a CSS identifier is refused outright rather than escaped
|
|
57
|
+
* — and refusal means falling back to a name that always works, not throwing at
|
|
58
|
+
* a user who is halfway through typing one.
|
|
59
|
+
*
|
|
60
|
+
* @param scope - The theme being edited, used for the fallback.
|
|
61
|
+
* @param name - What the user typed, if anything.
|
|
62
|
+
* @returns A usable CSS identifier.
|
|
63
|
+
* @example
|
|
64
|
+
* exportName({ theme: "terminal", mode: "dark" }); // → "terminal-custom"
|
|
65
|
+
*/
|
|
66
|
+
declare function exportName(scope: ThemeScope, name?: string): string;
|
|
67
|
+
/**
|
|
68
|
+
* The four exports for the current state of the panel.
|
|
69
|
+
*
|
|
70
|
+
* @param options - The overrides, the scope they were made in, and a name.
|
|
71
|
+
* @returns One entry per format, in the order the dialog shows them.
|
|
72
|
+
* @example
|
|
73
|
+
* const [css] = buildExports({ overrides, scope, name: "acme" });
|
|
74
|
+
* await navigator.clipboard.writeText(css.text);
|
|
75
|
+
*/
|
|
76
|
+
declare function buildExports(options: BuildExportsOptions): ThemeExport[];
|
|
77
|
+
//#endregion
|
|
78
|
+
export { BuildExportsOptions, ExportFormatId, ThemeExport, buildExports, exportName };
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { THEME_NAME_PATTERN, tokenProperty } from "../theming/serialize.js";
|
|
2
|
+
import { COLOR_TOKENS, FONT_TOKENS, configuratorCss, isOverridden, resolveValue, scopeKey, tokenKind } from "./_overrides.js";
|
|
3
|
+
//#region src/configurator/_export.ts
|
|
4
|
+
/** The anchors `ThemeAnchors` exposes at the top level, and the token each maps to. */
|
|
5
|
+
const DIRECT_ANCHORS = [
|
|
6
|
+
["bg", "bg"],
|
|
7
|
+
["fg", "fg"],
|
|
8
|
+
["accent", "accent"]
|
|
9
|
+
];
|
|
10
|
+
/** The surface ladder, as `ThemeAnchors.surfaces` spells it. */
|
|
11
|
+
const SURFACE_ANCHORS = [
|
|
12
|
+
"sunken",
|
|
13
|
+
"surface-1",
|
|
14
|
+
"surface-2",
|
|
15
|
+
"surface-3"
|
|
16
|
+
];
|
|
17
|
+
/** The status tones, as `ThemeAnchors.status` spells them. */
|
|
18
|
+
const STATUS_ANCHORS = [
|
|
19
|
+
"ok",
|
|
20
|
+
"busy",
|
|
21
|
+
"warn",
|
|
22
|
+
"danger",
|
|
23
|
+
"info"
|
|
24
|
+
];
|
|
25
|
+
/** `--cue-font-mono` → the `fonts.mono` key `ThemeAnchors` uses. */
|
|
26
|
+
const FONT_ANCHORS = {
|
|
27
|
+
"font-sans": "sans",
|
|
28
|
+
"font-mono": "mono",
|
|
29
|
+
"font-display": "display"
|
|
30
|
+
};
|
|
31
|
+
/** The DTCG source key a token is authored under, where it differs from the CSS name. */
|
|
32
|
+
const DTCG_ALIASES = { density: "density-factor" };
|
|
33
|
+
/**
|
|
34
|
+
* The name to put on a generated theme.
|
|
35
|
+
*
|
|
36
|
+
* The name lands inside `[data-theme="…"]`, a filename and a registry id, so
|
|
37
|
+
* anything that is not a CSS identifier is refused outright rather than escaped
|
|
38
|
+
* — and refusal means falling back to a name that always works, not throwing at
|
|
39
|
+
* a user who is halfway through typing one.
|
|
40
|
+
*
|
|
41
|
+
* @param scope - The theme being edited, used for the fallback.
|
|
42
|
+
* @param name - What the user typed, if anything.
|
|
43
|
+
* @returns A usable CSS identifier.
|
|
44
|
+
* @example
|
|
45
|
+
* exportName({ theme: "terminal", mode: "dark" }); // → "terminal-custom"
|
|
46
|
+
*/
|
|
47
|
+
function exportName(scope, name) {
|
|
48
|
+
const proposed = name?.trim() ?? "";
|
|
49
|
+
return THEME_NAME_PATTERN.test(proposed) ? proposed : `${scope.theme}-custom`;
|
|
50
|
+
}
|
|
51
|
+
/** A JSON string, printed the way a hand-written source file would print it. */
|
|
52
|
+
const json = (value) => `${JSON.stringify(value, null, 2)}\n`;
|
|
53
|
+
/** Both modes of a scope, so an export can carry the palette the user is not looking at. */
|
|
54
|
+
function bothModes(scope) {
|
|
55
|
+
return [{
|
|
56
|
+
theme: scope.theme,
|
|
57
|
+
mode: "dark"
|
|
58
|
+
}, {
|
|
59
|
+
theme: scope.theme,
|
|
60
|
+
mode: "light"
|
|
61
|
+
}];
|
|
62
|
+
}
|
|
63
|
+
/** The `--cue-*` properties of one kind that the user has actually moved. */
|
|
64
|
+
function movedTokens(overrides, scope, kind) {
|
|
65
|
+
const scoped = overrides.themes[scopeKey(scope)] ?? {};
|
|
66
|
+
const candidates = kind === "color" || kind === "font" ? scoped : overrides.global;
|
|
67
|
+
return Object.keys(candidates).filter((property) => tokenKind(property) === kind);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* ② The DTCG token file.
|
|
71
|
+
*
|
|
72
|
+
* A whole theme rather than a diff: the point of this format is that the result
|
|
73
|
+
* can be dropped into `packages/tokens/src/themes/` (or anyone else's DTCG
|
|
74
|
+
* pipeline) and built, which a patch file cannot. Groups follow the sources —
|
|
75
|
+
* `color` for the palette, `type` for the stacks, `density` for the multipliers
|
|
76
|
+
* — and appear only when they carry something.
|
|
77
|
+
*/
|
|
78
|
+
function dtcgFile(overrides, scope, name) {
|
|
79
|
+
const color = { $type: "color" };
|
|
80
|
+
for (const token of COLOR_TOKENS) color[token] = { $value: resolveValue(overrides, scope, token) };
|
|
81
|
+
const file = {
|
|
82
|
+
$description: `Theme: ${name} — exported from the CUE++ theme configurator, based on ${scope.theme} (${scope.mode}).`,
|
|
83
|
+
color
|
|
84
|
+
};
|
|
85
|
+
const fonts = movedTokens(overrides, scope, "font");
|
|
86
|
+
const tracking = movedTokens(overrides, scope, "flat");
|
|
87
|
+
if (fonts.length > 0 || tracking.length > 0) {
|
|
88
|
+
const type = { $type: "fontFamily" };
|
|
89
|
+
for (const property of fonts) type[property.slice(6)] = { $value: resolveValue(overrides, scope, property) };
|
|
90
|
+
for (const property of tracking) type[property.slice(6)] = {
|
|
91
|
+
$type: "dimension",
|
|
92
|
+
$value: resolveValue(overrides, scope, property)
|
|
93
|
+
};
|
|
94
|
+
file["type"] = type;
|
|
95
|
+
}
|
|
96
|
+
const multipliers = movedTokens(overrides, scope, "scaled");
|
|
97
|
+
if (multipliers.length > 0) {
|
|
98
|
+
const density = {
|
|
99
|
+
$description: "Multipliers only. They belong to the density axis, so they cross with every level rather than replacing one.",
|
|
100
|
+
$type: "dimension"
|
|
101
|
+
};
|
|
102
|
+
for (const property of multipliers) {
|
|
103
|
+
const bare = property.slice(6);
|
|
104
|
+
density[DTCG_ALIASES[bare] ?? bare] = {
|
|
105
|
+
$type: "number",
|
|
106
|
+
$value: Number(resolveValue(overrides, scope, property))
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
file["density"] = density;
|
|
110
|
+
}
|
|
111
|
+
return json(file);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* A string literal a human would have typed.
|
|
115
|
+
*
|
|
116
|
+
* Single quotes when the value carries double ones — a font stack is
|
|
117
|
+
* `"Berkeley Mono", monospace`, and `"\"Berkeley Mono\", monospace"` is a thing
|
|
118
|
+
* nobody writes on purpose.
|
|
119
|
+
*/
|
|
120
|
+
function quote(value) {
|
|
121
|
+
return value.includes("\"") && !value.includes("'") && !value.includes("\\") ? `'${value}'` : JSON.stringify(value);
|
|
122
|
+
}
|
|
123
|
+
/** One `key: "value"` line of an object literal, quoting the key only when it must. */
|
|
124
|
+
function property(key, value, indent) {
|
|
125
|
+
return `${indent}${/^[A-Za-z_$][\w$]*$/.test(key) ? key : JSON.stringify(key)}: ${quote(value)},`;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* ③ The `createTheme()` call.
|
|
129
|
+
*
|
|
130
|
+
* Anchors in, stylesheet out — the same two lines a human would have written,
|
|
131
|
+
* with whatever the user moved filled in. Tokens the generator derives rather
|
|
132
|
+
* than accepts are listed underneath instead of being silently dropped, because
|
|
133
|
+
* a snippet that quietly loses half an edit is worse than no snippet.
|
|
134
|
+
*/
|
|
135
|
+
function createThemeSnippet(overrides, scope, name) {
|
|
136
|
+
const lines = [` name: ${JSON.stringify(name)},`, ` base: ${JSON.stringify(scope.theme)},`];
|
|
137
|
+
const unrepresentable = [];
|
|
138
|
+
for (const [anchor, token] of DIRECT_ANCHORS) if (isOverridden(overrides, scope, token)) lines.push(property(anchor, resolveValue(overrides, scope, token), " "));
|
|
139
|
+
const surfaces = SURFACE_ANCHORS.filter((token) => isOverridden(overrides, scope, token));
|
|
140
|
+
if (surfaces.length > 0) {
|
|
141
|
+
lines.push(" surfaces: {");
|
|
142
|
+
for (const token of surfaces) lines.push(property(token, resolveValue(overrides, scope, token), " "));
|
|
143
|
+
lines.push(" },");
|
|
144
|
+
}
|
|
145
|
+
const statuses = STATUS_ANCHORS.filter((token) => isOverridden(overrides, scope, token));
|
|
146
|
+
if (statuses.length > 0) {
|
|
147
|
+
lines.push(" status: {");
|
|
148
|
+
for (const token of statuses) lines.push(property(token, resolveValue(overrides, scope, token), " "));
|
|
149
|
+
lines.push(" },");
|
|
150
|
+
}
|
|
151
|
+
const fonts = FONT_TOKENS.filter((token) => isOverridden(overrides, scope, token));
|
|
152
|
+
if (fonts.length > 0) {
|
|
153
|
+
lines.push(" fonts: {");
|
|
154
|
+
for (const token of fonts) lines.push(property(FONT_ANCHORS[token], resolveValue(overrides, scope, token), " "));
|
|
155
|
+
lines.push(" },");
|
|
156
|
+
}
|
|
157
|
+
if (isOverridden(overrides, scope, "radius-scale")) lines.push(` radiusScale: ${Number(resolveValue(overrides, scope, "radius-scale"))},`);
|
|
158
|
+
const anchored = new Set([
|
|
159
|
+
...DIRECT_ANCHORS.map(([, token]) => token),
|
|
160
|
+
...SURFACE_ANCHORS,
|
|
161
|
+
...STATUS_ANCHORS,
|
|
162
|
+
...FONT_TOKENS,
|
|
163
|
+
"radius-scale"
|
|
164
|
+
].map(tokenProperty));
|
|
165
|
+
for (const moved of [...Object.keys(overrides.themes[scopeKey(scope)] ?? {}), ...Object.keys(overrides.global)]) {
|
|
166
|
+
if (anchored.has(moved)) continue;
|
|
167
|
+
unrepresentable.push(`${moved}: ${resolveValue(overrides, scope, moved)}`);
|
|
168
|
+
}
|
|
169
|
+
const footer = unrepresentable.length === 0 ? "" : [
|
|
170
|
+
"",
|
|
171
|
+
"// createTheme() derives these rather than taking them as anchors, so they are not",
|
|
172
|
+
"// in the call above. Ship the CSS export alongside it — that one is lossless.",
|
|
173
|
+
...unrepresentable.map((entry) => `// ${entry}`),
|
|
174
|
+
""
|
|
175
|
+
].join("\n");
|
|
176
|
+
return [
|
|
177
|
+
"import { createTheme } from \"@cueplusplus/ui/theming\";",
|
|
178
|
+
"",
|
|
179
|
+
`export const ${/^[A-Za-z_$][\w$]*$/.test(name) ? name : "theme"} = createTheme({`,
|
|
180
|
+
...lines,
|
|
181
|
+
"});",
|
|
182
|
+
footer
|
|
183
|
+
].join("\n");
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* ④ The shadcn registry item.
|
|
187
|
+
*
|
|
188
|
+
* `cssVars` is keyed the way shadcn keys it — no leading dashes, and a `theme`
|
|
189
|
+
* bucket for the variables that do not belong to a mode. Both palettes are
|
|
190
|
+
* written in full, including the one the user was not looking at, because an
|
|
191
|
+
* installer has no way to ask.
|
|
192
|
+
*/
|
|
193
|
+
function registryItem(overrides, scope, name) {
|
|
194
|
+
const strip = (property) => property.replace(/^--/, "");
|
|
195
|
+
const palette = (mode) => Object.fromEntries(COLOR_TOKENS.map((token) => [strip(tokenProperty(token)), resolveValue(overrides, mode, token)]));
|
|
196
|
+
const [dark, light] = bothModes(scope);
|
|
197
|
+
const shared = {};
|
|
198
|
+
for (const moved of [...FONT_TOKENS.map(tokenProperty), ...Object.keys(overrides.global)]) {
|
|
199
|
+
if (!isOverridden(overrides, scope, moved)) continue;
|
|
200
|
+
shared[strip(moved)] = resolveValue(overrides, scope, moved);
|
|
201
|
+
}
|
|
202
|
+
return json({
|
|
203
|
+
$schema: "https://ui.shadcn.com/schema/registry-item.json",
|
|
204
|
+
name,
|
|
205
|
+
type: "registry:theme",
|
|
206
|
+
cssVars: {
|
|
207
|
+
...Object.keys(shared).length === 0 ? null : { theme: shared },
|
|
208
|
+
light: palette(light),
|
|
209
|
+
dark: palette(dark)
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* The four exports for the current state of the panel.
|
|
215
|
+
*
|
|
216
|
+
* @param options - The overrides, the scope they were made in, and a name.
|
|
217
|
+
* @returns One entry per format, in the order the dialog shows them.
|
|
218
|
+
* @example
|
|
219
|
+
* const [css] = buildExports({ overrides, scope, name: "acme" });
|
|
220
|
+
* await navigator.clipboard.writeText(css.text);
|
|
221
|
+
*/
|
|
222
|
+
function buildExports(options) {
|
|
223
|
+
const { overrides, scope } = options;
|
|
224
|
+
const name = exportName(scope, options.name);
|
|
225
|
+
return [
|
|
226
|
+
{
|
|
227
|
+
id: "css",
|
|
228
|
+
label: "CSS",
|
|
229
|
+
filename: `${name}.css`,
|
|
230
|
+
mediaType: "text/css",
|
|
231
|
+
description: "The override stylesheet, exactly as the panel is applying it.",
|
|
232
|
+
text: configuratorCss(overrides)
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
id: "dtcg",
|
|
236
|
+
label: "Tokens",
|
|
237
|
+
filename: `${name}.tokens.json`,
|
|
238
|
+
mediaType: "application/json",
|
|
239
|
+
description: "A DTCG token file, in the shape packages/tokens builds from.",
|
|
240
|
+
text: dtcgFile(overrides, scope, name)
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
id: "create-theme",
|
|
244
|
+
label: "createTheme()",
|
|
245
|
+
filename: `${name}.theme.ts`,
|
|
246
|
+
mediaType: "text/plain",
|
|
247
|
+
description: "The generator call that reproduces the anchors you moved.",
|
|
248
|
+
text: createThemeSnippet(overrides, scope, name)
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
id: "registry",
|
|
252
|
+
label: "Registry",
|
|
253
|
+
filename: `${name}.registry.json`,
|
|
254
|
+
mediaType: "application/json",
|
|
255
|
+
description: "A shadcn registry:theme item, both modes resolved.",
|
|
256
|
+
text: registryItem(overrides, scope, name)
|
|
257
|
+
}
|
|
258
|
+
];
|
|
259
|
+
}
|
|
260
|
+
//#endregion
|
|
261
|
+
export { buildExports, exportName };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import "react";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/configurator/_glyphs.tsx
|
|
4
|
+
/**
|
|
5
|
+
* The configurator's own glyphs.
|
|
6
|
+
*
|
|
7
|
+
* Drawn inline, like every other group's, so a panel that edits the design
|
|
8
|
+
* system does not put an icon package on its render path. `currentColor`
|
|
9
|
+
* throughout — the tone comes from the button underneath.
|
|
10
|
+
*
|
|
11
|
+
* @internal Not part of the public API.
|
|
12
|
+
*/
|
|
13
|
+
/** A counter-clockwise arrow: put this one token back. */
|
|
14
|
+
function ResetGlyph(props) {
|
|
15
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
16
|
+
viewBox: "0 0 16 16",
|
|
17
|
+
fill: "none",
|
|
18
|
+
stroke: "currentColor",
|
|
19
|
+
strokeWidth: "1.5",
|
|
20
|
+
strokeLinecap: "round",
|
|
21
|
+
strokeLinejoin: "round",
|
|
22
|
+
"aria-hidden": "true",
|
|
23
|
+
...props,
|
|
24
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M3 8a5 5 0 1 0 1.6-3.7" }), /* @__PURE__ */ jsx("path", { d: "M3 3v3.2h3.2" })]
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/** Two short rules: the grab surface of the title bar. */
|
|
28
|
+
function GripGlyph(props) {
|
|
29
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
30
|
+
viewBox: "0 0 16 16",
|
|
31
|
+
fill: "none",
|
|
32
|
+
stroke: "currentColor",
|
|
33
|
+
strokeWidth: "1.5",
|
|
34
|
+
strokeLinecap: "round",
|
|
35
|
+
"aria-hidden": "true",
|
|
36
|
+
...props,
|
|
37
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M3 6h10" }), /* @__PURE__ */ jsx("path", { d: "M3 10h10" })]
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/** A frame with a rail down its right edge: dock the panel. */
|
|
41
|
+
function DockGlyph(props) {
|
|
42
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
43
|
+
viewBox: "0 0 16 16",
|
|
44
|
+
fill: "none",
|
|
45
|
+
stroke: "currentColor",
|
|
46
|
+
strokeWidth: "1.5",
|
|
47
|
+
strokeLinejoin: "round",
|
|
48
|
+
"aria-hidden": "true",
|
|
49
|
+
...props,
|
|
50
|
+
children: [/* @__PURE__ */ jsx("rect", {
|
|
51
|
+
x: "2",
|
|
52
|
+
y: "3",
|
|
53
|
+
width: "12",
|
|
54
|
+
height: "10",
|
|
55
|
+
rx: "1.5"
|
|
56
|
+
}), /* @__PURE__ */ jsx("path", { d: "M10 3v10" })]
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/** A chevron, rotated by the caller to point at the state it will move to. */
|
|
60
|
+
function ChevronGlyph(props) {
|
|
61
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
62
|
+
viewBox: "0 0 16 16",
|
|
63
|
+
fill: "none",
|
|
64
|
+
stroke: "currentColor",
|
|
65
|
+
strokeWidth: "1.5",
|
|
66
|
+
strokeLinecap: "round",
|
|
67
|
+
strokeLinejoin: "round",
|
|
68
|
+
"aria-hidden": "true",
|
|
69
|
+
...props,
|
|
70
|
+
children: /* @__PURE__ */ jsx("path", { d: "M4 6.5 8 10.5l4-4" })
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/** An arrow into a tray: save this export to a file. */
|
|
74
|
+
function DownloadGlyph(props) {
|
|
75
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
76
|
+
viewBox: "0 0 16 16",
|
|
77
|
+
fill: "none",
|
|
78
|
+
stroke: "currentColor",
|
|
79
|
+
strokeWidth: "1.5",
|
|
80
|
+
strokeLinecap: "round",
|
|
81
|
+
strokeLinejoin: "round",
|
|
82
|
+
"aria-hidden": "true",
|
|
83
|
+
...props,
|
|
84
|
+
children: [
|
|
85
|
+
/* @__PURE__ */ jsx("path", { d: "M8 2.5v7" }),
|
|
86
|
+
/* @__PURE__ */ jsx("path", { d: "M5 7l3 3 3-3" }),
|
|
87
|
+
/* @__PURE__ */ jsx("path", { d: "M3 12.5h10" })
|
|
88
|
+
]
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
export { ChevronGlyph, DockGlyph, DownloadGlyph, GripGlyph, ResetGlyph };
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { ResolvedMode } from "../system/theme-provider.js";
|
|
2
|
+
import { Density, ThemeName } from "@cueplusplus/tokens";
|
|
3
|
+
//#region src/configurator/_overrides.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The override model behind the theme configurator: what a user may move, where
|
|
6
|
+
* the declaration has to land for it to win, and how the whole thing survives a
|
|
7
|
+
* reload.
|
|
8
|
+
*
|
|
9
|
+
* Everything here is a pure function of an immutable `ThemeOverrides` value,
|
|
10
|
+
* apart from the three functions at the bottom that talk to the document and to
|
|
11
|
+
* `localStorage`. That split is deliberate — the panel is a view over this
|
|
12
|
+
* model, the export dialog is a second view over the same model, and neither is
|
|
13
|
+
* allowed a private opinion about what the tokens are.
|
|
14
|
+
*
|
|
15
|
+
* ## Why the scoping is this fussy
|
|
16
|
+
*
|
|
17
|
+
* The token layer declares its values under *attribute* selectors on two
|
|
18
|
+
* disjoint axes (`[data-theme]` for colour, `[data-density]` for geometry), and
|
|
19
|
+
* both axes are re-declared at every element that carries the attribute — the
|
|
20
|
+
* `<html>` element, the provider root, a `<Density>` island, a portal container.
|
|
21
|
+
* An override is therefore not "set the variable on `:root`": that loses in
|
|
22
|
+
* three separate ways.
|
|
23
|
+
*
|
|
24
|
+
* - A colour written under a bare `[data-theme="x"]` (0,1,0) is outranked by the
|
|
25
|
+
* shipped `[data-theme="x"][data-mode="light"]` block (0,2,0), so the moment
|
|
26
|
+
* the user switches to light the override vanishes. Colours are therefore
|
|
27
|
+
* written **crossed with the mode**, which is also honest: a theme's two modes
|
|
28
|
+
* are two palettes, and editing one should not silently edit the other.
|
|
29
|
+
* - A geometry multiplier written flat outranks the density block that set it,
|
|
30
|
+
* freezing `ultra-compact`'s 0.75 radius scale at 1 — the same trap
|
|
31
|
+
* `createTheme()` documents. Multipliers are therefore **crossed with the
|
|
32
|
+
* density ladder**, one rule per level, with the level's own value folded in.
|
|
33
|
+
* - `--cue-font-scale` is published by `<ThemeProvider>` as an *inline* custom
|
|
34
|
+
* property, and no stylesheet outranks an inline declaration. It is the one
|
|
35
|
+
* token here that needs `!important`, and it gets its own rule so that the
|
|
36
|
+
* flag never spreads to anything that does not need it.
|
|
37
|
+
*
|
|
38
|
+
* @internal Not part of the public API; `./configurator` re-exports what a host
|
|
39
|
+
* app needs.
|
|
40
|
+
*/
|
|
41
|
+
/** The one style element the configurator writes into. */
|
|
42
|
+
declare const OVERRIDE_STYLE_ID = "cue-configurator-overrides";
|
|
43
|
+
/** Default `localStorage` key for the persisted snapshot. */
|
|
44
|
+
declare const DEFAULT_CONFIGURATOR_STORAGE_KEY = "cue-configurator";
|
|
45
|
+
/**
|
|
46
|
+
* Schema version of the persisted snapshot.
|
|
47
|
+
*
|
|
48
|
+
* A blob from another version is discarded rather than migrated: the payload is
|
|
49
|
+
* a design preference a user can rebuild in a minute, and a wrong migration
|
|
50
|
+
* would paint a page with values nobody chose.
|
|
51
|
+
*/
|
|
52
|
+
declare const CONFIGURATOR_VERSION = 1;
|
|
53
|
+
/** Banner printed at the top of the applied — and exported — stylesheet. */
|
|
54
|
+
declare const OVERRIDE_BANNER = "@cueplusplus/ui — theme configurator overrides";
|
|
55
|
+
/** The authored label tracking, and the value the "reset" arrow returns to. */
|
|
56
|
+
declare const BASE_TRACKING_LABEL = "0.12em";
|
|
57
|
+
/** The colour tokens the panel edits — the same list a theme block declares. */
|
|
58
|
+
declare const COLOR_TOKENS: readonly ["bg", "sunken", "surface-1", "surface-2", "surface-3", "fg", "fg-muted", "fg-subtle", "border", "border-strong", "border-overlay", "accent", "accent-hover", "accent-fg", "ok", "busy", "warn", "danger", "info", "selection", "focus", "data-ground", "scrim"];
|
|
59
|
+
/** The type stacks the panel edits. Mode-independent: a typeface is not a palette. */
|
|
60
|
+
declare const FONT_TOKENS: readonly ["font-sans", "font-mono", "font-display"];
|
|
61
|
+
/** Every token the configurator is allowed to write, as `--cue-*` properties, in contract order. */
|
|
62
|
+
declare const MANAGED_TOKENS: readonly string[];
|
|
63
|
+
/** Where in the cascade a token's declaration has to go. */
|
|
64
|
+
type TokenKind = "color" | "font" | "scaled" | "flat" | "inline";
|
|
65
|
+
/** A theme and the mode being looked at: the scope a colour override belongs to. */
|
|
66
|
+
interface ThemeScope {
|
|
67
|
+
/** The active preset. */
|
|
68
|
+
theme: ThemeName;
|
|
69
|
+
/** The mode as resolved — `"system"` never reaches here. */
|
|
70
|
+
mode: ResolvedMode;
|
|
71
|
+
}
|
|
72
|
+
/** Every override the user has made, ready to serialize. Treat as immutable. */
|
|
73
|
+
interface ThemeOverrides {
|
|
74
|
+
/** Theme-scoped declarations, keyed by `"<theme>/<mode>"` then by `--cue-*` property. */
|
|
75
|
+
themes: Record<string, Record<string, string>>;
|
|
76
|
+
/** Axis-free declarations, keyed by `--cue-*` property. */
|
|
77
|
+
global: Record<string, string>;
|
|
78
|
+
}
|
|
79
|
+
/** The nothing-has-moved state. Frozen: it is shared by every caller. */
|
|
80
|
+
declare const EMPTY_OVERRIDES: ThemeOverrides;
|
|
81
|
+
/** Where the panel is sitting. */
|
|
82
|
+
type ConfiguratorPosition = "floating" | "docked-right";
|
|
83
|
+
/** Everything the configurator persists between visits. */
|
|
84
|
+
interface ConfiguratorSnapshot {
|
|
85
|
+
/** {@link CONFIGURATOR_VERSION} at the time of writing. */
|
|
86
|
+
version: number;
|
|
87
|
+
/** The overrides themselves. */
|
|
88
|
+
overrides: ThemeOverrides;
|
|
89
|
+
/** Root zoom valve position. */
|
|
90
|
+
zoom: number;
|
|
91
|
+
/** Panel placement and whether it is furled to its title bar. */
|
|
92
|
+
panel: {
|
|
93
|
+
position: ConfiguratorPosition;
|
|
94
|
+
x: number;
|
|
95
|
+
y: number;
|
|
96
|
+
collapsed: boolean;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/** Which of the five buckets a token belongs to, or `null` if it is not ours to write. */
|
|
100
|
+
declare function tokenKind(token: string): TokenKind | null;
|
|
101
|
+
/** The key a theme+mode pair is stored under. */
|
|
102
|
+
declare function scopeKey(scope: ThemeScope): string;
|
|
103
|
+
/**
|
|
104
|
+
* Whether a value can be printed into a declaration without escaping it.
|
|
105
|
+
*
|
|
106
|
+
* Colours arrive from the picker already re-formatted, but a font stack is free
|
|
107
|
+
* text a user typed, and it ends up inside a stylesheet. This is the same check
|
|
108
|
+
* `theming/serialize.ts` makes — asked as a question instead of thrown as an
|
|
109
|
+
* error, so a field can mark itself invalid while the user is still typing.
|
|
110
|
+
*
|
|
111
|
+
* @param value - The proposed declaration value.
|
|
112
|
+
* @returns `true` when it stays inside its declaration.
|
|
113
|
+
* @example
|
|
114
|
+
* isSafeCssValue("Iosevka, monospace"); // → true
|
|
115
|
+
*/
|
|
116
|
+
declare function isSafeCssValue(value: string): boolean;
|
|
117
|
+
/**
|
|
118
|
+
* The value a token has before the user touches anything.
|
|
119
|
+
*
|
|
120
|
+
* Colours come from the preset for *this mode*; fonts from the preset's own
|
|
121
|
+
* override, else the base stack; the multipliers are 1 by definition, because
|
|
122
|
+
* what the panel edits is the multiplier and not the ladder underneath it.
|
|
123
|
+
*
|
|
124
|
+
* @param scope - Theme and mode being edited.
|
|
125
|
+
* @param token - A bare token name or a `--cue-*` property.
|
|
126
|
+
* @returns The shipped value, as a CSS string.
|
|
127
|
+
* @example
|
|
128
|
+
* baseValue({ theme: "terminal", mode: "dark" }, "accent"); // → "hsl(180 100% 50%)"
|
|
129
|
+
*/
|
|
130
|
+
declare function baseValue(scope: ThemeScope, token: string): string;
|
|
131
|
+
/**
|
|
132
|
+
* Move a token, returning a new state.
|
|
133
|
+
*
|
|
134
|
+
* Setting a token back to the value the preset ships is a *reset*, not an
|
|
135
|
+
* override — otherwise "I put it back" would still export a declaration and the
|
|
136
|
+
* user would carry a no-op forever.
|
|
137
|
+
*
|
|
138
|
+
* @param overrides - Current state. Never mutated.
|
|
139
|
+
* @param scope - Theme and mode being edited.
|
|
140
|
+
* @param token - A bare token name or a `--cue-*` property.
|
|
141
|
+
* @param value - The new CSS value.
|
|
142
|
+
* @returns The new state.
|
|
143
|
+
* @throws TypeError if the token is not one the configurator manages, or the
|
|
144
|
+
* value could break out of its declaration.
|
|
145
|
+
* @example
|
|
146
|
+
* setOverride(overrides, { theme: "terminal", mode: "dark" }, "accent", "#ff8800");
|
|
147
|
+
*/
|
|
148
|
+
declare function setOverride(overrides: ThemeOverrides, scope: ThemeScope, token: string, value: string): ThemeOverrides;
|
|
149
|
+
/**
|
|
150
|
+
* Put a token back to its shipped value, returning a new state.
|
|
151
|
+
*
|
|
152
|
+
* @param overrides - Current state. Never mutated.
|
|
153
|
+
* @param scope - Theme and mode being edited.
|
|
154
|
+
* @param token - A bare token name or a `--cue-*` property.
|
|
155
|
+
* @returns The new state.
|
|
156
|
+
* @example
|
|
157
|
+
* clearOverride(overrides, scope, "--cue-accent");
|
|
158
|
+
*/
|
|
159
|
+
declare function clearOverride(overrides: ThemeOverrides, scope: ThemeScope, token: string): ThemeOverrides;
|
|
160
|
+
/** Whether a token currently carries an override in this scope. */
|
|
161
|
+
declare function isOverridden(overrides: ThemeOverrides, scope: ThemeScope, token: string): boolean;
|
|
162
|
+
/**
|
|
163
|
+
* How many declarations the user has made.
|
|
164
|
+
*
|
|
165
|
+
* Counted as declarations rather than as decisions: a font family is one choice
|
|
166
|
+
* that produces two declarations, one per mode, and the number in the panel is
|
|
167
|
+
* the number that will appear in the export.
|
|
168
|
+
*/
|
|
169
|
+
declare function overrideCount(overrides: ThemeOverrides): number;
|
|
170
|
+
/** The value a token has right now: the override if there is one, else the shipped value. */
|
|
171
|
+
declare function resolveValue(overrides: ThemeOverrides, scope: ThemeScope, token: string): string;
|
|
172
|
+
/**
|
|
173
|
+
* Every token the configurator manages, resolved for one scope.
|
|
174
|
+
*
|
|
175
|
+
* This is what `onChange` hands a host app and what the registry export writes:
|
|
176
|
+
* a complete picture, not a diff, so a consumer never has to know which preset
|
|
177
|
+
* the values came from.
|
|
178
|
+
*
|
|
179
|
+
* @param overrides - Current state.
|
|
180
|
+
* @param scope - Theme and mode to resolve for.
|
|
181
|
+
* @returns `--cue-*` property → CSS value.
|
|
182
|
+
*/
|
|
183
|
+
declare function resolvedTokens(overrides: ThemeOverrides, scope: ThemeScope): Record<string, string>;
|
|
184
|
+
interface SerializeOverrideOptions {
|
|
185
|
+
/** Text of the leading `/*! … *\/` banner. Omit for a bare stylesheet. */
|
|
186
|
+
banner?: string;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Print the overrides as a stylesheet.
|
|
190
|
+
*
|
|
191
|
+
* Returns `""` when nothing has moved — an empty stylesheet is not a stylesheet
|
|
192
|
+
* with an empty rule in it, and the runtime uses the empty string as its signal
|
|
193
|
+
* to remove the style element entirely.
|
|
194
|
+
*
|
|
195
|
+
* @param overrides - Current state.
|
|
196
|
+
* @param options - Banner text.
|
|
197
|
+
* @returns The stylesheet, newline-terminated, or `""`.
|
|
198
|
+
* @example
|
|
199
|
+
* serializeOverrideCss(overrides, { banner: OVERRIDE_BANNER });
|
|
200
|
+
*/
|
|
201
|
+
declare function serializeOverrideCss(overrides: ThemeOverrides, options?: SerializeOverrideOptions): string;
|
|
202
|
+
/**
|
|
203
|
+
* The stylesheet the panel applies — and, byte for byte, the one its CSS export
|
|
204
|
+
* hands you. One function so the two can never drift.
|
|
205
|
+
*
|
|
206
|
+
* @param overrides - Current state.
|
|
207
|
+
* @returns The banner-topped stylesheet, or `""` when nothing has moved.
|
|
208
|
+
*/
|
|
209
|
+
declare function configuratorCss(overrides: ThemeOverrides): string;
|
|
210
|
+
/**
|
|
211
|
+
* Put the stylesheet into the document, creating the style element if needed.
|
|
212
|
+
*
|
|
213
|
+
* One element, identified by {@link OVERRIDE_STYLE_ID}, appended to `<head>`
|
|
214
|
+
* after everything else — later in the cascade is half of how these overrides
|
|
215
|
+
* win. An empty stylesheet removes the element instead of leaving an empty one
|
|
216
|
+
* behind, so "reset all" leaves the document exactly as it found it.
|
|
217
|
+
*
|
|
218
|
+
* @param css - The stylesheet, from {@link configuratorCss}.
|
|
219
|
+
* @param doc - Document to write into. Defaults to the ambient one.
|
|
220
|
+
* @returns The style element, or `null` when there was nothing to apply.
|
|
221
|
+
*/
|
|
222
|
+
declare function applyOverrideCss(css: string, doc?: Document | undefined): HTMLStyleElement | null;
|
|
223
|
+
/** Take the override stylesheet back out of the document. */
|
|
224
|
+
declare function removeOverrideStyles(doc?: Document | undefined): void;
|
|
225
|
+
/** The snapshot a first-time visitor gets. */
|
|
226
|
+
declare function defaultSnapshot(): ConfiguratorSnapshot;
|
|
227
|
+
/**
|
|
228
|
+
* Read the persisted snapshot.
|
|
229
|
+
*
|
|
230
|
+
* Every field is validated, and anything that fails validation is dropped
|
|
231
|
+
* rather than repaired — the blob is text a user can edit in devtools, and its
|
|
232
|
+
* values are printed straight into a stylesheet.
|
|
233
|
+
*
|
|
234
|
+
* @param storageKey - The `localStorage` key.
|
|
235
|
+
* @returns The snapshot, or `null` when there is nothing usable stored.
|
|
236
|
+
*/
|
|
237
|
+
declare function readSnapshot(storageKey: string): ConfiguratorSnapshot | null;
|
|
238
|
+
/**
|
|
239
|
+
* Persist the snapshot. A full quota or a private-mode failure is swallowed —
|
|
240
|
+
* a preference is a nicety, never a hard failure.
|
|
241
|
+
*
|
|
242
|
+
* @param storageKey - The `localStorage` key.
|
|
243
|
+
* @param snapshot - What to store.
|
|
244
|
+
*/
|
|
245
|
+
declare function writeSnapshot(storageKey: string, snapshot: ConfiguratorSnapshot): void;
|
|
246
|
+
//#endregion
|
|
247
|
+
export { BASE_TRACKING_LABEL, COLOR_TOKENS, CONFIGURATOR_VERSION, ConfiguratorPosition, ConfiguratorSnapshot, DEFAULT_CONFIGURATOR_STORAGE_KEY, EMPTY_OVERRIDES, FONT_TOKENS, MANAGED_TOKENS, OVERRIDE_BANNER, OVERRIDE_STYLE_ID, SerializeOverrideOptions, ThemeOverrides, ThemeScope, TokenKind, applyOverrideCss, baseValue, clearOverride, configuratorCss, defaultSnapshot, isOverridden, isSafeCssValue, overrideCount, readSnapshot, removeOverrideStyles, resolveValue, resolvedTokens, scopeKey, serializeOverrideCss, setOverride, tokenKind, writeSnapshot };
|