@kitlangton/knobs 0.3.0 → 0.4.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +350 -45
  2. package/dist/dev/{chunk-jx1ktap3.js → chunk-1qzffbpa.js} +497 -422
  3. package/dist/dev/{chunk-7xgkerd2.js → chunk-3ygqgy1x.js} +23 -1
  4. package/dist/dev/{chunk-pmkvb9ep.js → chunk-8mabjeyk.js} +1920 -507
  5. package/dist/dev/{chunk-v8ssbcbk.js → chunk-ayb292zj.js} +13 -11
  6. package/dist/dev/index.js +10 -5
  7. package/dist/index.js +25 -1
  8. package/dist/panel.js +2954 -1291
  9. package/dist/react.js +294 -6
  10. package/dist/solid.js +292 -4
  11. package/dist/themes.js +1509 -7
  12. package/dist/types/core/adapter.d.ts +6 -2
  13. package/dist/types/core/appearance.d.ts +44 -0
  14. package/dist/types/core/glide.d.ts +7 -0
  15. package/dist/types/core/motion.d.ts +66 -0
  16. package/dist/types/core/root.d.ts +13 -0
  17. package/dist/types/core/store.d.ts +18 -5
  18. package/dist/types/core/theme.d.ts +10 -3
  19. package/dist/types/index.d.ts +2 -1
  20. package/dist/types/panel/gpu/color.d.ts +6 -0
  21. package/dist/types/panel/motion.d.ts +1 -1
  22. package/dist/types/panel/styles.d.ts +2 -3
  23. package/dist/types/themes/define.d.ts +104 -0
  24. package/dist/types/themes/index.d.ts +11 -0
  25. package/dist/types/themes/knobs.d.ts +5 -0
  26. package/dist/types/themes/void.d.ts +8 -0
  27. package/dist/types/tokens/color.d.ts +42 -0
  28. package/dist/types/tokens/css.d.ts +13 -0
  29. package/dist/types/tokens/evaluate.d.ts +8 -0
  30. package/dist/types/tokens/index.d.ts +4 -0
  31. package/dist/types/tokens/schema.d.ts +1100 -0
  32. package/dist/types/ui/bento-css.d.ts +1 -1
  33. package/dist/types/ui/compare-css.d.ts +1 -0
  34. package/dist/types/ui/compare-frames.d.ts +41 -0
  35. package/dist/types/ui/compare-gpu.d.ts +58 -0
  36. package/dist/types/ui/compare-model.d.ts +169 -0
  37. package/dist/types/ui/compare-mp4.d.ts +29 -0
  38. package/dist/types/ui/compare-strip.d.ts +28 -0
  39. package/dist/types/ui/compare.d.ts +103 -0
  40. package/dist/types/ui/diff-css.d.ts +1 -0
  41. package/dist/types/ui/diff-model.d.ts +128 -0
  42. package/dist/types/ui/diff-scroll.d.ts +29 -0
  43. package/dist/types/ui/diff.d.ts +158 -0
  44. package/dist/types/ui/index.d.ts +10 -2
  45. package/dist/types/ui/look.d.ts +18 -13
  46. package/dist/types/ui/overlay-css.d.ts +1 -1
  47. package/dist/types/ui/react.d.ts +66 -0
  48. package/dist/types/ui/readout-css.d.ts +1 -1
  49. package/dist/types/ui/readout-model.d.ts +5 -1
  50. package/dist/types/ui/rgba.d.ts +11 -0
  51. package/dist/types/ui/scrollbar.d.ts +2 -2
  52. package/dist/types/ui/solid.d.ts +52 -0
  53. package/dist/types/ui/timeline.d.ts +35 -2
  54. package/dist/types/ui/tree.d.ts +7 -2
  55. package/dist/types/ui/walkthrough-css.d.ts +1 -0
  56. package/dist/types/ui/walkthrough-media.d.ts +29 -0
  57. package/dist/types/ui/walkthrough-model.d.ts +447 -0
  58. package/dist/types/ui/walkthrough.d.ts +63 -0
  59. package/dist/ui-react.js +18352 -8462
  60. package/dist/ui-solid.js +17947 -8148
  61. package/dist/ui.js +19240 -9701
  62. package/package.json +6 -1
@@ -1,6 +1,7 @@
1
1
  import type { ControlDescriptor } from "./remote.js";
2
2
  import type { Choice, Schema, State } from "./schema.js";
3
- import type { Controls, DensityMode, MountPanelOptions, ThemeMode } from "./store.js";
3
+ import type { Controls, DensityMode, MountPanelOptions } from "./store.js";
4
+ import { type LookOptions } from "./appearance.js";
4
5
  export type ChoiceKey<S extends Schema> = {
5
6
  [K in keyof S]: S[K] extends Choice ? K : never;
6
7
  }[keyof S] & string;
@@ -16,6 +17,9 @@ export type KnobsPanelProps<S extends Schema = Schema> = MountPanelOptions & {
16
17
  /** While true, a different item is arriving: values land without springing or rolling. */
17
18
  land?: boolean;
18
19
  };
19
- export declare function syncPanelLook<S extends Schema>(host: HTMLElement | null | undefined, controls: Controls<S>, theme?: ThemeMode, density?: DensityMode): void;
20
+ /** The look a panel takes: its props' over its store's. */
21
+ export declare const panelLook: <S extends Schema>(controls: Controls<S>, look?: LookOptions) => import("./appearance.js").Look;
22
+ /** Restyles the mounted panel in place (theme, appearance, preset, density), so its tokens glide. */
23
+ export declare function syncPanelLook<S extends Schema>(host: HTMLElement | null | undefined, controls: Controls<S>, look?: LookOptions, density?: DensityMode): void;
20
24
  export declare function syncPanelValues<S extends Schema>(controls: Controls<S>, descriptors?: readonly ControlDescriptor[], values?: State, land?: boolean): void;
21
25
  export declare function mountPanelAdapter<S extends Schema>(host: HTMLElement, controls: Controls<S>, getProps: () => KnobsPanelProps<S>): () => void;
@@ -0,0 +1,44 @@
1
+ import type { Theme } from "../themes/define.js";
2
+ import { type TokenPreset } from "./theme.js";
3
+ /**
4
+ * Light or dark: `dark` and `light` fix it, `system` follows the OS, and `inherit` (the default)
5
+ * follows the page: a `color-scheme`, a `.dark`/`.light` class, `[data-theme]` or
6
+ * `[data-appearance]` on an ancestor, or an outer knobs element, else the OS.
7
+ */
8
+ export type Appearance = "dark" | "light" | "system" | "inherit";
9
+ /** @deprecated The old name for an appearance: `auto` is `system`. Use `appearance`. */
10
+ export type ThemeMode = "dark" | "light" | "auto";
11
+ /** How a panel, chip or knobs/ui piece looks: its theme, its appearance (and an old preset). */
12
+ export interface LookOptions {
13
+ /**
14
+ * A theme from `defineTheme` (or `themes.knobs`, `themes.void`). Knobs' own when unset.
15
+ * `"dark" | "light" | "auto"` is the old spelling of `appearance` and still works.
16
+ */
17
+ readonly theme?: Theme | ThemeMode;
18
+ readonly appearance?: Appearance;
19
+ /** @deprecated A `TokenPreset` (`labPreset`): its tokens over the theme's. */
20
+ readonly preset?: TokenPreset;
21
+ }
22
+ /** A look with every part decided. */
23
+ export interface Look {
24
+ readonly theme?: Theme;
25
+ readonly appearance: Appearance;
26
+ readonly preset?: TokenPreset;
27
+ }
28
+ /** `options` over `base`: a theme object, an appearance (or an old mode), a preset. */
29
+ export declare function resolveLook(options?: LookOptions, base?: Partial<Look>): Look;
30
+ /** The theme an element shows: the nearest themed knobs element's, else knobs' own (undefined). */
31
+ export declare function themeOf(el: Element): Theme | undefined;
32
+ /** The selector a theme's tokens sit under: any knobs element marked with its name. */
33
+ export declare const themeSelector: (name: string) => string;
34
+ /** Adds a theme's tokens once per document, under `[data-knobs-theme="<name>"]`. */
35
+ export declare function injectTheme(doc: Document, theme: Theme): void;
36
+ /** Adds a preset's tokens once per document, for any knobs element marked `data-preset`. */
37
+ export declare function injectPreset(doc: Document, preset: TokenPreset): void;
38
+ /** Marks `el` (a knobs root) with `look`: its theme's tokens, its appearance and its preset. */
39
+ export declare function applyLook(el: HTMLElement, look: Look): void;
40
+ /**
41
+ * The look `el` shows, fixed: its theme and preset, and the appearance it shows now. For something
42
+ * floated out of it (a drag ghost, a menu) to match it wherever it lands.
43
+ */
44
+ export declare function lookAt(el: Element): Look;
@@ -0,0 +1,7 @@
1
+ /** The transitions that glide every driver, for a root that also transitions its own properties. */
2
+ export declare const TOKEN_TRANSITIONS: string;
3
+ /** Elements whose tokens glide: each declares the drivers. */
4
+ export declare const GLIDING = ".knobs-panel,.knobs-chip,.knobs-notice,.knobs-ui";
5
+ export declare const DRIVERS: string;
6
+ /** Rules read the gliding aliases of what glides, and what the knobs root resolved otherwise. */
7
+ export declare const aliased: (css: string) => string;
@@ -0,0 +1,66 @@
1
+ import { type SpringValue } from "./spring.js";
2
+ /**
3
+ * The five named springs (SwiftUI duration and bounce), all without bounce. Every motion in knobs
4
+ * uses one of these unless it's tuned for one feature.
5
+ */
6
+ export declare const SPRINGS: {
7
+ /** Press feedback, focus, selection, pointer-tied moves. */
8
+ readonly instant: {
9
+ readonly duration: 0.1;
10
+ readonly bounce: 0;
11
+ };
12
+ /** Value fills, thumbs, toggles, small controls, menus, exits. */
13
+ readonly snappy: {
14
+ readonly duration: 0.25;
15
+ readonly bounce: 0;
16
+ };
17
+ /** Most state changes: popovers, panel open and close, restyle glides (`--k-spring`). */
18
+ readonly default: {
19
+ readonly duration: 0.3;
20
+ readonly bounce: 0;
21
+ };
22
+ /** Layout reflow, split panes, list reorders. */
23
+ readonly calm: {
24
+ readonly duration: 0.4;
25
+ readonly bounce: 0;
26
+ };
27
+ /** Appearance and theme changes, drawers, page-scale moves. */
28
+ readonly smooth: {
29
+ readonly duration: 0.45;
30
+ readonly bounce: 0;
31
+ };
32
+ };
33
+ export type SpringName = keyof typeof SPRINGS;
34
+ /** A quick fade that isn't travel (and what any fade becomes under reduced motion). */
35
+ export declare const FADE: SpringValue;
36
+ /** A popover or menu closing: a little shorter than snappy. */
37
+ export declare const CLOSE: SpringValue;
38
+ /** The named springs as ω/ζ, for `new Spring(x, omega, zeta)`. */
39
+ export declare const MOTION: { readonly [K in SpringName]: {
40
+ readonly omega: number;
41
+ readonly zeta: number;
42
+ }; };
43
+ export declare const reducedMotion: (win: Window | null | undefined) => boolean;
44
+ /**
45
+ * The reduced-motion policy: movement doesn't travel (`null`: go straight to the end), and a fade
46
+ * keeps a short fade (at most `FADE`).
47
+ */
48
+ export declare function reducedSpring(spring: SpringValue, kind: "move" | "fade", reduced: boolean): SpringValue | null;
49
+ /** A spring as a CSS `linear()` easing and its settle time (ms). */
50
+ export declare const springLinear: (spring: SpringValue) => {
51
+ easing: string;
52
+ ms: number;
53
+ };
54
+ /** `--k-spring`'s default: the default spring as "duration bounce". */
55
+ export declare const SPRING_TOKEN: string;
56
+ /** The default spring as CSS, for `--k-fill-ease` and `--k-fill-ms`. */
57
+ export declare const DEFAULT_LINEAR: {
58
+ easing: string;
59
+ ms: number;
60
+ };
61
+ /**
62
+ * Each named spring as CSS on :root: `--_k-motion-<name>` (a `linear()` easing) and
63
+ * `--_k-motion-<name>-ms` (its settle time, a number of ms). Under reduced motion they take 0 ms:
64
+ * movement doesn't travel.
65
+ */
66
+ export declare const motionCss: string;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The class every knobs top-level element carries: panels, chips, menus, the status notice, and
3
+ * every knobs/ui piece's root. Each resolves the design tokens for itself (see tokens/css.ts), so
4
+ * a theme, an appearance or a host's token on any ancestor reaches what's derived from it.
5
+ */
6
+ export declare const ROOT_CLASS = "knobs-root";
7
+ /**
8
+ * The token sheet: the Knobs theme's defaults, every root's resolution and appearance, the
9
+ * drivers that make tokens glide, and the motion tokens.
10
+ */
11
+ export declare const rootCss: string;
12
+ /** Adds the token sheet once per document. */
13
+ export declare function injectTokens(doc: Document): void;
@@ -1,9 +1,11 @@
1
1
  import { type CodeFormat } from "./code.js";
2
2
  import type { TokenPreset } from "./theme.js";
3
+ import type { Appearance, ThemeMode } from "./appearance.js";
4
+ import type { Theme } from "../themes/define.js";
3
5
  import { type ReadoutInput, type ReadoutKeys, type Schema, type State, type Values } from "./schema.js";
4
6
  import { type StoragePort } from "./storage.js";
5
7
  import { type Variants } from "./variants.js";
6
- export type ThemeMode = "dark" | "light" | "auto";
8
+ export type { Appearance, ThemeMode } from "./appearance.js";
7
9
  export type DensityMode = "compact" | "default" | "comfortable";
8
10
  export type RendererMode = "gpu" | "dom" | "auto";
9
11
  /** When a store's chip shows; see `ChipOptions.reveal`. */
@@ -157,7 +159,7 @@ export interface MountPanelOptions extends LabelOptions {
157
159
  * (a prototype's settings), where "default" means nothing. The store's `marks` by default.
158
160
  */
159
161
  readonly marks?: boolean;
160
- /** Token values to style the panel with, e.g. `problemsPreset` (see `TokenPreset`). */
162
+ /** @deprecated Token values to style the panel with (see `TokenPreset`); use `theme`. */
161
163
  readonly preset?: TokenPreset;
162
164
  /**
163
165
  * `false` drops the header (title and buttons) for a host that draws its own. An object keeps
@@ -231,7 +233,13 @@ export interface MountPanelOptions extends LabelOptions {
231
233
  readonly onReady?: (panel: PanelHandle) => void;
232
234
  /** What Copy (and ⇧C) puts on the clipboard; `controls.code()` by default. */
233
235
  readonly copy?: () => string;
234
- readonly theme?: ThemeMode;
236
+ /**
237
+ * A theme from `defineTheme` (`themes.knobs`, `themes.void`); the store's by default. The old
238
+ * `"dark" | "light" | "auto"` still sets the appearance.
239
+ */
240
+ readonly theme?: Theme | ThemeMode;
241
+ /** dark | light | system | inherit (the default: follow the page, else the OS). */
242
+ readonly appearance?: Appearance;
235
243
  readonly density?: DensityMode;
236
244
  readonly renderer?: RendererMode;
237
245
  readonly variants?: boolean;
@@ -347,7 +355,10 @@ export interface ControlsOptions<S extends Schema> extends LabelOptions {
347
355
  */
348
356
  groupPresets?: Readonly<Record<string, readonly GroupPreset<Values<S>>[]>>;
349
357
  actions?: readonly ControlAction<Values<S>>[];
350
- theme?: ThemeMode;
358
+ /** Its panels' theme (see `MountPanelOptions.theme`). */
359
+ theme?: Theme | ThemeMode;
360
+ /** Its panels' appearance (see `MountPanelOptions.appearance`). */
361
+ appearance?: Appearance;
351
362
  density?: DensityMode;
352
363
  renderer?: RendererMode;
353
364
  /** Default key bindings for this store's panels (see `MountPanelOptions.keys`). */
@@ -385,7 +396,9 @@ export interface Controls<S extends Schema = Schema> {
385
396
  readonly presets: Readonly<Record<string, Values<S>>>;
386
397
  readonly variants: Variants<Values<S>>;
387
398
  readonly actions: readonly ControlAction<Values<S>>[];
388
- readonly theme: ThemeMode;
399
+ /** Its panels' theme, as given (see `ControlsOptions.theme`). */
400
+ readonly theme: Theme | ThemeMode | undefined;
401
+ readonly appearance: Appearance | undefined;
389
402
  readonly density: DensityMode;
390
403
  readonly renderer: RendererMode;
391
404
  readonly keys: PanelKeys | undefined;
@@ -1,7 +1,10 @@
1
1
  /**
2
- * A named set of `--k-*` token values for dark and light, applied to panels mounted with
2
+ * A named set of `--k-*` token values for dark and light, applied to knobs elements mounted with
3
3
  * `{ preset }` (or with `data-preset="<name>"` and `presetCss(preset)` in your own stylesheet).
4
- * `css` adds rules for anything tokens don't cover; `&` stands for the panel.
4
+ * `css` adds rules for anything tokens don't cover; `&` stands for the element.
5
+ *
6
+ * @deprecated Use `defineTheme` (from `knobs/themes`), which generates both appearances from a
7
+ * few dials. Presets keep working; their token names go through the deprecated aliases.
5
8
  */
6
9
  export interface TokenPreset {
7
10
  readonly name: string;
@@ -9,7 +12,11 @@ export interface TokenPreset {
9
12
  readonly light?: Readonly<Record<string, string | number>>;
10
13
  readonly css?: string;
11
14
  }
12
- /** The stylesheet for a preset: its dark tokens, its light ones wherever a panel is light. */
15
+ /**
16
+ * The stylesheet for a preset. A token it gives for both appearances becomes `light-dark(light,
17
+ * dark)`, so it follows the element's appearance (its `color-scheme`) like the theme's colours
18
+ * do; anything else holds in both.
19
+ */
13
20
  export declare function presetCss(preset: TokenPreset): string;
14
21
  /**
15
22
  * A dense, square editor (Arcade's Lab): radius 0, compact 26 px rows, the flat frame (groups as
@@ -1,10 +1,11 @@
1
1
  export { knob, choice, toggle, spring, color, point, easing, action, flatSpring, vec2, vec3, range, angle, seed, keybind, gradient, curve, toolbar, toolbarShortcut, actionShortcut, watch, sparkline, graph, meter, table, log, hasValue, isReadout, wrapAngle, SPRING, type FieldMeta, type ActionField, type SpringPart, type ValueField, type Knob, type Choice, type Toggle, type SpringField, type ColorField, type PointField, type EasingField, type VecField, type Vec3, type RangeField, type AngleField, type SeedField, type KeybindField, type GradientField, type CurveField, type ToolbarField, type ToolbarItem, type ToolbarShortcut, type WatchField, type SparklineField, type GraphField, type GraphSeries, type GraphThreshold, type MeterField, type TableField, type LogField, type ReadoutField, type ReadoutKeys, type ReadoutInput, type Point, type Field, type Schema, type Values, type Value, type State, } from "./core/schema.js";
2
2
  export { springCss, springMotion, type SpringValue } from "./core/spring.js";
3
+ export { reducedSpring, SPRINGS, type SpringName } from "./core/motion.js";
3
4
  export { colorHex, parseColor, type Oklch } from "./core/color.js";
4
5
  export { sampleGradient, sampleCurve, gradientCss, CURVE_SHAPES, type GradientStop, type GradientSpace, type CurvePoint, type CurveInterp, type SampleGradientOptions, type SampleCurveOptions, } from "./core/ramp.js";
5
6
  export { bezierCss, bezierPoint, EASINGS, type Bezier, type EasingName } from "./core/easing.js";
6
7
  export { AROUND } from "./core/random.js";
7
- export { defineControls, type ChangeMeta, type GestureEvent, type ChangeSource, type ChipOptions, type ControlAction, type Controls, type ControlsOptions, type DensityMode, type GroupPreset, type GroupPresetDisplay, type PresetRef, type HeaderButton, type HeaderOptions, type HostHistory, type LabelOptions, type MountPanelOptions, type PanelCommand, type PanelHandle, type PanelModule, type PanelKeys, type PersistMode, type SearchChip, type SearchOptions, type SyncOptions, type RendererMode, type RevealMode, type SectionFolded, type SoundOptions, type SoundTheme, type ThemeMode, } from "./core/store.js";
8
+ export { defineControls, type ChangeMeta, type GestureEvent, type ChangeSource, type ChipOptions, type ControlAction, type Controls, type ControlsOptions, type DensityMode, type GroupPreset, type GroupPresetDisplay, type PresetRef, type HeaderButton, type HeaderOptions, type HostHistory, type LabelOptions, type MountPanelOptions, type PanelCommand, type PanelHandle, type PanelModule, type PanelKeys, type PersistMode, type SearchChip, type SearchOptions, type SyncOptions, type RendererMode, type RevealMode, type SectionFolded, type SoundOptions, type SoundTheme, type ThemeMode, type Appearance, } from "./core/store.js";
8
9
  export { createRemoteControls, descriptorToField, formatSwift, fromDescriptors, fromSettings, type SettingsGroup, type SettingsItem, type ActionDescriptor, type ChoiceOption, type ControlDescriptor, type SpringBindingDescriptor, type ToolbarDescriptor, type ReadoutDescriptor, type ValueDescriptor, type RemoteControls, type RemoteControlsOptions, } from "./core/remote.js";
9
10
  export type { LogEntry, LogLevel, TableRows, WatchValue } from "./core/readout.js";
10
11
  export { memoryStorage, urlFlag, type StoragePort } from "./core/storage.js";
@@ -1,4 +1,5 @@
1
1
  import { mixRgba as mixColor, parseCssColor, type Rgba, withAlpha } from "../../ui/rgba.js";
2
+ import type { GpuColors, Theme } from "../../themes/define.js";
2
3
  export { mixColor, parseCssColor, type Rgba, withAlpha };
3
4
  /** CSS `color-mix(in srgb, a p, b)`, interpolated with premultiplied alpha like the browser. */
4
5
  export declare function cssMix(a: Rgba, b: Rgba, p: number): Rgba;
@@ -126,3 +127,8 @@ export interface PanelThemeTokens {
126
127
  readonly shadowStrength: number;
127
128
  }
128
129
  export declare function readPanelTokens(panel: HTMLElement, version?: number): PanelThemeTokens;
130
+ /**
131
+ * A theme's colours for one appearance, as the renderer draws them (sRGB, straight alpha): what
132
+ * the panel shows where no CSS (a host's override, a preset, a glide) says otherwise.
133
+ */
134
+ export declare function gpuDefaults(theme: Theme | undefined, light: boolean): GpuColors;
@@ -1,6 +1,6 @@
1
1
  import { Spring } from "../core/spring.js";
2
2
  export { Spring, springEasing } from "../core/spring.js";
3
- /** The slider fill, and its rubber band springing back from past an end. */
3
+ /** The slider fill (the default spring, as --k-spring), and its rubber band springing back from past an end. */
4
4
  export declare const FILL: {
5
5
  omega: number;
6
6
  zeta: number;
@@ -1,11 +1,10 @@
1
- import { type TokenPreset } from "../core/theme.js";
2
1
  /**
3
2
  * What DELAY times: a row's turn in a preset's cascade is set on these (see `showValues` in
4
3
  * panel.ts) rather than on the row, where the custom property would restyle all of the row.
5
4
  */
6
5
  export declare const DELAYED = ".knobs-fill,.knobs-handle,.knobs-seg-pill,.knobs-toggle,.knobs-toggle i,.knobs-arm,.knobs-curve,.knobs-swatch,.knobs-strip-thumb,.knobs-pad>i,.knobs-ease-handle,.knobs-range-track,.knobs-range-fill,.knobs-range-thumb,.knobs-dial-hand,.knobs-grad,.knobs-grad-mini,.knobs-grad-mini>i,.knobs-grad-stop,.knobs-graph-pt";
7
- /** Adds a token preset's stylesheet once per document. */
8
- export declare function injectPreset(doc: Document, preset: TokenPreset): void;
9
6
  /** The rules' `:has()` as the attributes has.ts keeps (see there for why). */
10
7
  export declare const withoutHas: (css: string) => string;
8
+ /** The panel stylesheet, as `injectStyles` writes it (after the token sheet). */
9
+ export declare const panelCss: () => string;
11
10
  export declare function injectStyles(doc: Document): void;
@@ -0,0 +1,104 @@
1
+ import { type Rgba } from "../tokens/color.js";
2
+ import { type ColorTokenName, type TokenName } from "../tokens/schema.js";
3
+ export type Appearance = "dark" | "light";
4
+ export type Density = "compact" | "default" | "comfortable";
5
+ export type Material = "glass" | "solid" | "flat";
6
+ export type TokenOverrides = Partial<Record<TokenName, string>>;
7
+ /** What `defineTheme` takes. Everything but `name` is optional and deep-merges over `extends`. */
8
+ export interface ThemeSpec {
9
+ readonly name: string;
10
+ readonly extends?: Theme;
11
+ /** Tint of the neutral ladder. Chroma 0–0.02; 0.004 reads as neutral with a hint of hue. */
12
+ readonly gray?: {
13
+ readonly hue?: number;
14
+ readonly chroma?: number;
15
+ };
16
+ /** The accent: one colour (its dark-appearance value; light is derived) or one per appearance. */
17
+ readonly accent?: string | {
18
+ readonly dark: string;
19
+ readonly light: string;
20
+ };
21
+ /** 0–100, 50 by default: spreads the surface ladder and text tiers, scales fills and borders. */
22
+ readonly contrast?: number;
23
+ /** Control radius in px. */
24
+ readonly radius?: number;
25
+ readonly density?: Density;
26
+ readonly material?: Material;
27
+ readonly font?: {
28
+ readonly sans?: string;
29
+ readonly mono?: string;
30
+ };
31
+ /** Escape hatch: any token's value, per appearance. Applied after generation. */
32
+ readonly tokens?: {
33
+ readonly dark?: TokenOverrides;
34
+ readonly light?: TokenOverrides;
35
+ };
36
+ }
37
+ /** A spec with every dial filled in. */
38
+ export interface ThemeInputs {
39
+ readonly gray: {
40
+ readonly hue: number;
41
+ readonly chroma: number;
42
+ };
43
+ readonly accent: string | {
44
+ readonly dark: string;
45
+ readonly light: string;
46
+ };
47
+ readonly contrast: number;
48
+ readonly radius: number;
49
+ readonly density: Density;
50
+ readonly material: Material;
51
+ readonly font: {
52
+ readonly sans: string;
53
+ readonly mono: string;
54
+ };
55
+ readonly tokens: {
56
+ readonly dark: TokenOverrides;
57
+ readonly light: TokenOverrides;
58
+ };
59
+ }
60
+ export type ResolvedTokens = Readonly<Record<TokenName, string>>;
61
+ export type GpuColors = Readonly<Record<ColorTokenName, Rgba>>;
62
+ export interface Theme {
63
+ readonly name: string;
64
+ readonly inputs: ThemeInputs;
65
+ /**
66
+ * Every token for each appearance. Colours are fully resolved hex (`#rrggbb` or `#rrggbbaa`);
67
+ * other tokens carry their CSS value or derivation.
68
+ */
69
+ readonly dark: ResolvedTokens;
70
+ readonly light: ResolvedTokens;
71
+ /** What the theme itself declares (generated values plus overrides); the CSS is built from it. */
72
+ readonly declared: {
73
+ readonly dark: TokenOverrides;
74
+ readonly light: TokenOverrides;
75
+ };
76
+ /** Every colour token as linear-light sRGB floats `[r, g, b, a]` (straight alpha), for WebGPU. */
77
+ readonly gpu: {
78
+ readonly dark: GpuColors;
79
+ readonly light: GpuColors;
80
+ };
81
+ /**
82
+ * The theme's CSS in `@layer knobs.tokens`. With no selector, the full default sheet (its values
83
+ * on `:root`, every token resolved on `.knobs-root`, appearance rules). With a selector, one
84
+ * block of what this theme declares, to scope it to part of a page.
85
+ */
86
+ css(options?: {
87
+ readonly selector?: string;
88
+ }): string;
89
+ }
90
+ /** The APCA budget each ink must meet on `bg`. */
91
+ export declare const APCA_BUDGET: {
92
+ readonly fg: 90;
93
+ readonly "fg-2": 75;
94
+ readonly "fg-3": 45;
95
+ readonly "fg-4": 30;
96
+ readonly "accent-fg": 60;
97
+ readonly "border-strong": 15;
98
+ };
99
+ /**
100
+ * Builds a theme from a few dials: a neutral ladder generated in OKLCH and checked against the
101
+ * APCA budget, an accent with its text and on-accent colours, a shared status palette, chart
102
+ * series and material values, resolved for both appearances.
103
+ */
104
+ export declare function defineTheme(spec: ThemeSpec): Theme;
@@ -1 +1,12 @@
1
+ import { knobs } from "./knobs.js";
2
+ import { voidTheme } from "./void.js";
3
+ export { APCA_BUDGET, type Appearance as ThemeAppearance, type Density, defineTheme, type GpuColors, type Material, type ResolvedTokens, type Theme, type ThemeInputs, type ThemeSpec, type TokenOverrides, } from "./define.js";
4
+ export { knobs, voidTheme };
5
+ export type { Appearance } from "../core/appearance.js";
6
+ export type { PublicTokenName, TokenName, TokenProperty } from "../tokens/schema.js";
7
+ /** The shipped themes: Knobs (the default) and Void (true black, flat, for OLED and video). */
8
+ export declare const themes: {
9
+ readonly knobs: import("./define.js").Theme;
10
+ readonly void: import("./define.js").Theme;
11
+ };
1
12
  export { labPreset, presetCss, problemsPreset, type TokenPreset } from "../core/theme.js";
@@ -0,0 +1,5 @@
1
+ /**
2
+ * The main look: a `#1c1c1e`-class panel floating on a near-black page, glass, a white
3
+ * monochrome accent and alpha hairlines. Its light pair keeps `#f5f5f7` / `#1a1a1c` / `#1c1c1e`.
4
+ */
5
+ export declare const knobs: import("./define.js").Theme;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * For OLED and video review: true black page and panel with Apple's `#1c1c1e` / `#2c2c2e` raised
3
+ * surfaces, text capped at `#ededed` to limit halation, a white accent, flat with solid
4
+ * hairlines, and a black stage behind compared media. Neutral (no tint) so the chrome doesn't
5
+ * bias colour judgement. The light pair is generated from the same dials, with a neutral
6
+ * near-black accent.
7
+ */
8
+ export declare const voidTheme: import("./define.js").Theme;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The colour maths the theme generator needs and nothing more: OKLCH ↔ sRGB (Björn Ottosson's
3
+ * OKLab matrices), hex parsing and formatting with alpha, and APCA 0.0.98G contrast.
4
+ */
5
+ /** Linear-light sRGB, each channel 0–1, plus straight (not premultiplied) alpha. */
6
+ export type Rgba = readonly [r: number, g: number, b: number, a: number];
7
+ export interface Oklch {
8
+ /** Perceived lightness, 0–1. */
9
+ readonly l: number;
10
+ readonly c: number;
11
+ /** Hue in degrees. */
12
+ readonly h: number;
13
+ readonly alpha?: number;
14
+ }
15
+ export declare const toLinear: (c: number) => number;
16
+ export declare const toGamma: (c: number) => number;
17
+ /** Linear sRGB → OKLCH. */
18
+ export declare function linearToOklch([r, g, b, a]: Rgba): Oklch;
19
+ /** OKLCH → linear sRGB, unclamped (may fall outside the gamut). */
20
+ export declare function oklchToLinear({ l: L, c, h, alpha }: Oklch): Rgba;
21
+ /** OKLCH → linear sRGB inside the gamut, reducing chroma (keeping L and h) when it doesn't fit. */
22
+ export declare function oklchToLinearInGamut(color: Oklch): Rgba;
23
+ /** Parses `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `oklch(L% C H / A)` and `rgb()/rgba()`. */
24
+ export declare function parseColor(input: string): Rgba;
25
+ export declare const toOklch: (input: string) => Oklch;
26
+ /** Linear sRGB → `#rrggbb`, or `#rrggbbaa` when not opaque. */
27
+ export declare function formatHex([r, g, b, a]: Rgba): string;
28
+ export declare const oklchToHex: (color: Oklch) => string;
29
+ /** Rounds to the 8-bit hex grid, so values compare and serialise the same everywhere. */
30
+ export declare const normalize: (input: string) => string;
31
+ /** `color` at `alpha` (multiplying any alpha it already has). */
32
+ export declare function withAlpha(input: string, alpha: number): string;
33
+ /** `top` composited over an opaque `bottom` in gamma-encoded sRGB (what browsers paint). */
34
+ export declare function over(top: string, bottom: string): string;
35
+ /** `a` mixed toward `b` by `t` (0–1) in OKLCH, the hue taking the shorter arc. */
36
+ export declare function mixOklch(a: string, b: string, t: number): string;
37
+ /**
38
+ * APCA 0.0.98G lightness contrast of `text` on `background`, as an absolute Lc (light text on
39
+ * dark is negative in APCA; this returns its magnitude). A translucent text colour is composited
40
+ * over the background first.
41
+ */
42
+ export declare function apca(text: string, background: string): number;
@@ -0,0 +1,13 @@
1
+ import type { Theme } from "../themes/define.js";
2
+ export declare const APPEARANCE_CSS: string;
3
+ /**
4
+ * The default token sheet for `theme`, in `@layer knobs.tokens` so any host assignment wins: the
5
+ * theme's values (inputs, generated colours as `light-dark()` pairs, literals) as public tokens on
6
+ * `:where(:root,:host)`, every token resolved privately (`--_k-*`) on `:where(.knobs-root)`, and
7
+ * the appearance rules. Component styles read only the private names.
8
+ */
9
+ export declare function tokensCss(theme: Theme): string;
10
+ /** One block of everything `theme` declares, under `selector`, to theme part of a page. */
11
+ export declare function themeCss(theme: Theme, selector: string): string;
12
+ /** The README token reference: every public token with its values in `theme`, then the renames. */
13
+ export declare function tokensTable(theme: Theme): string;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Evaluates the small CSS colour language the token derivations are written in: `var(--k-…)`
3
+ * (with fallbacks), `color-mix(in oklch, A p, B q)` (premultiplied, shorter hue, as browsers do),
4
+ * `calc(N% * var(--k-contrast))` percentages, and plain colours. The same strings are emitted as
5
+ * CSS, so the TypeScript-resolved maps and the browser agree by construction.
6
+ */
7
+ export type Lookup = (cssName: string) => string | undefined;
8
+ export declare function evaluate(input: string, lookup: Lookup): string;
@@ -0,0 +1,4 @@
1
+ export { apca, formatHex, mixOklch, normalize, type Oklch, oklchToHex, over, parseColor, type Rgba, toOklch, withAlpha, } from "./color.js";
2
+ export { APPEARANCE_CSS, themeCss, tokensCss, tokensTable } from "./css.js";
3
+ export { evaluate } from "./evaluate.js";
4
+ export { type ColorTokenName, cssName, DEPRECATED, type HookName, type PublicTokenName, RETIRED_INTERNAL, type SemanticTokenName, THEME_DIALS, type ThemeTokenName, type Tier, TOKEN_BY_NAME, TOKENS, type TokenDef, type TokenName, type TokenProperty, type TokenSource, type TokenType, tokenForProperty, } from "./schema.js";