@cssints/tui 0.0.0-stage → 0.2.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.
@@ -0,0 +1,49 @@
1
+ import { TuiProps, TuiProps as TuiProps$1, TuiShape, TuiShape as TuiShape$1 } from "cssints/tui";
2
+ //#region src/index.d.ts
3
+ /** The states a renderable is in. */
4
+ export interface TuiState {
5
+ hover?: boolean;
6
+ focus?: boolean;
7
+ active?: boolean;
8
+ }
9
+ /**
10
+ * The theme in use.
11
+ *
12
+ * @returns {string} a name of `createGlobalTheme(tokens, name, ...)`, `""` for the default values
13
+ */
14
+ export declare const theme: () => string;
15
+ /**
16
+ * Swaps the theme of every renderable an adapter has attached: their props are resolved again.
17
+ *
18
+ * @param {string} name a name of `createGlobalTheme(tokens, name, ...)`, `""` for the default values
19
+ */
20
+ export declare const setTheme: (name: string) => void;
21
+ /**
22
+ * Registers (or replaces) a theme of the run-time table: the value of each token, by name (`color-bg` for `var(--color-bg)`), laid over
23
+ * the static theme `base` (`""`: the default values) for every prop a site set to that token. A token it leaves out
24
+ * keeps the value of `base`. When `name` is the theme in use, every attached renderable is resolved again.
25
+ *
26
+ * @param {string} name the theme, for `setTheme(name)`
27
+ * @param {Record<string, string>} values a colour (`#rrggbb`, `ansi:N` or `default`) per token name
28
+ * @param {string} base a name of `createGlobalTheme(tokens, name, ...)`, `""` for the default values
29
+ */
30
+ export declare const defineTheme: (name: string, values: Record<string, string>, base?: string) => void;
31
+ /**
32
+ * Calls `fn` on every theme change.
33
+ *
34
+ * @param {Function} fn called with the name of the new theme
35
+ * @returns {Function} the function that stops it
36
+ */
37
+ export declare const onTheme: (fn: (name: string) => void) => (() => void);
38
+ /**
39
+ * The props of `style` in `state` and theme `name` (default: the one in use): the props, then what the theme changes,
40
+ * then the `:hover`, `:focus` and `:active` overlays that are on, in that order, each with the theme's.
41
+ *
42
+ * @param {TuiShape} style a style of cssints/tui
43
+ * @param {TuiState} state the states that are on
44
+ * @param {string} name the theme
45
+ * @returns {TuiProps} the props, renderer-neutral
46
+ */
47
+ export declare const resolve: (style: TuiShape$1, state?: TuiState, name?: string) => TuiProps$1;
48
+ //#endregion
49
+ export type { TuiProps, TuiShape };
package/dist/index.mjs ADDED
@@ -0,0 +1,88 @@
1
+ //#region src/index.ts
2
+ const STATES = [
3
+ ":hover",
4
+ ":focus",
5
+ ":active"
6
+ ];
7
+ const own = (out, layer) => {
8
+ if (layer) {
9
+ for (const [k, v] of Object.entries(layer)) if (k !== "themes" && k !== "vars" && !k.startsWith(":")) out[k] = v;
10
+ }
11
+ };
12
+ let current = "";
13
+ const listeners = /* @__PURE__ */ new Set();
14
+ const table = /* @__PURE__ */ new Map();
15
+ /**
16
+ * The theme in use.
17
+ *
18
+ * @returns {string} a name of `createGlobalTheme(tokens, name, ...)`, `""` for the default values
19
+ */
20
+ const theme = () => current;
21
+ /**
22
+ * Swaps the theme of every renderable an adapter has attached: their props are resolved again.
23
+ *
24
+ * @param {string} name a name of `createGlobalTheme(tokens, name, ...)`, `""` for the default values
25
+ */
26
+ const setTheme = (name) => {
27
+ if (name === current) return;
28
+ current = name;
29
+ for (const l of listeners) l(name);
30
+ };
31
+ /**
32
+ * Registers (or replaces) a theme of the run-time table: the value of each token, by name (`color-bg` for `var(--color-bg)`), laid over
33
+ * the static theme `base` (`""`: the default values) for every prop a site set to that token. A token it leaves out
34
+ * keeps the value of `base`. When `name` is the theme in use, every attached renderable is resolved again.
35
+ *
36
+ * @param {string} name the theme, for `setTheme(name)`
37
+ * @param {Record<string, string>} values a colour (`#rrggbb`, `ansi:N` or `default`) per token name
38
+ * @param {string} base a name of `createGlobalTheme(tokens, name, ...)`, `""` for the default values
39
+ */
40
+ const defineTheme = (name, values, base = "") => {
41
+ table.set(name, {
42
+ values,
43
+ base
44
+ });
45
+ if (name === current) for (const l of listeners) l(name);
46
+ };
47
+ /**
48
+ * Calls `fn` on every theme change.
49
+ *
50
+ * @param {Function} fn called with the name of the new theme
51
+ * @returns {Function} the function that stops it
52
+ */
53
+ const onTheme = (fn) => {
54
+ listeners.add(fn);
55
+ return () => listeners.delete(fn);
56
+ };
57
+ /**
58
+ * The props of `style` in `state` and theme `name` (default: the one in use): the props, then what the theme changes,
59
+ * then the `:hover`, `:focus` and `:active` overlays that are on, in that order, each with the theme's.
60
+ *
61
+ * @param {TuiShape} style a style of cssints/tui
62
+ * @param {TuiState} state the states that are on
63
+ * @param {string} name the theme
64
+ * @returns {TuiProps} the props, renderer-neutral
65
+ */
66
+ const resolve = (style, state = {}, name = current) => {
67
+ const run = table.get(name);
68
+ const base = run ? run.base : name;
69
+ const themed = base ? style.themes?.[base] : void 0;
70
+ const vars = style.vars;
71
+ const out = {};
72
+ const tokens = (layer) => {
73
+ if (run && layer) {
74
+ for (const [k, v] of Object.entries(layer)) if (typeof v === "string" && Object.hasOwn(run.values, v)) out[k] = run.values[v];
75
+ }
76
+ };
77
+ own(out, style);
78
+ own(out, themed);
79
+ tokens(vars);
80
+ for (const s of STATES) if (state[s === ":hover" ? "hover" : s === ":focus" ? "focus" : "active"]) {
81
+ own(out, style[s]);
82
+ own(out, themed?.[s]);
83
+ tokens(vars?.[s]);
84
+ }
85
+ return out;
86
+ };
87
+ //#endregion
88
+ export { defineTheme, onTheme, resolve, setTheme, theme };
@@ -0,0 +1,66 @@
1
+ import { TuiState, resolve, setTheme, theme } from "./index.mjs";
2
+ import { c as Report, g as SystemTheme } from "./system-CFyJGOUM.mjs";
3
+ import { CliRenderer, Renderable, TerminalColors, TextNodeRenderable, ThemeMode } from "@opentui/core";
4
+ import { TuiProps, TuiShape } from "cssints/tui";
5
+ //#region src/opentui-system.d.ts
6
+ /**
7
+ * The report of OpenTUI's palette and theme mode.
8
+ *
9
+ * @param {TerminalColors} colors what `renderer.getPalette()` gave (none yet: `undefined`)
10
+ * @param {ThemeMode} mode `renderer.themeMode`
11
+ * @returns {Report} the report for `theme.solve`
12
+ */
13
+ export declare const reportOf: (colors: TerminalColors | undefined, mode: ThemeMode | null) => Report;
14
+ /**
15
+ * Follows the terminal's colours: sets the system theme (`setTheme`) with the fallback at once, asks OpenTUI for the
16
+ * palette, and rebuilds the theme when it comes, on a `palette` event and on a `theme_mode` change.
17
+ *
18
+ * @param {CliRenderer} renderer the renderer
19
+ * @param {SystemTheme} theme the theme of `createSystemTheme`
20
+ * @param {object} options `wait`: how long to wait for the palette, in ms (default 100)
21
+ * @returns {Promise<Function>} after the palette or `wait`, whichever is first: the function that stops following
22
+ */
23
+ export declare const followSystemTheme: (renderer: CliRenderer, theme: SystemTheme, options?: {
24
+ wait?: number;
25
+ }) => Promise<() => void>;
26
+ //#endregion
27
+ //#region src/opentui.d.ts
28
+ /**
29
+ * The OpenTUI props of a style (`has` tells which props the renderable has: a box takes `backgroundColor`, a text `bg`):
30
+ * `color` is `fg` (`textColor` on an editable or a select), the text attributes are the bits of `attributes`, the
31
+ * caret is `cursorStyle` and `cursorColor` (Input, Textarea). `cursor` is not a prop: `attach` sets the mouse pointer.
32
+ *
33
+ * @param {TuiProps} p the props of `resolve()`
34
+ * @param {Function} has whether the renderable has a prop
35
+ * @returns {Record<string, unknown>} the props of an OpenTUI renderable
36
+ */
37
+ export declare const props: (p: TuiProps, has?: (key: string) => boolean) => Record<string, unknown>;
38
+ type Node = Renderable | TextNodeRenderable;
39
+ /**
40
+ * Sets the props of `style` on `r` and keeps them up to date: `:hover` from `over` to `out`, `:active` from `down` to
41
+ * `up` (or `out`), `:focus` while it has focus (a box needs `focusable: true`), and the theme of `setTheme`. The mouse
42
+ * pointer is the style's `cursor` on `over`, `default` again on `out`. Handlers of your own (`onMouseOver`) still run.
43
+ * A focused renderable draws its `focused*` colours (`focusedBorderColor` of a box): they follow the style too. A text
44
+ * node (`<span>`, `<a>`) has no mouse events and no focus: it takes the props and the theme, not the states.
45
+ * On a renderable it has attached already, it swaps the style (cssints-332g): the states, the theme and the hooks stay,
46
+ * a prop only the old style set goes back to the renderable's own value, and the pointer follows the new `cursor`.
47
+ *
48
+ * @param {Renderable | TextNodeRenderable} r a renderable or a text node of OpenTUI
49
+ * @param {TuiShape} style a style of cssints/tui
50
+ * @returns {Renderable | TextNodeRenderable} `r`
51
+ */
52
+ export declare const attach: <R extends Node>(r: R, style: TuiShape) => R;
53
+ /**
54
+ * Props to spread on an OpenTUI element of Solid or React: `<box {...use(card)} />`. The `ref` attaches the style
55
+ * (`attach`) when the renderable is made, before its first frame. A style that changes is an accessor,
56
+ * `use(() => (active() ? a : b))`: Solid calls a ref in a render effect, so the signals it reads run it again, and each
57
+ * run swaps the style (React calls the new ref of each render). The adapter imports no framework.
58
+ *
59
+ * @param {TuiShape | Function} style a style of cssints/tui, or a function that returns one
60
+ * @returns {object} `{ ref }`
61
+ */
62
+ export declare const use: (style: TuiShape | (() => TuiShape)) => {
63
+ ref: (r: Node | null) => void;
64
+ };
65
+ //#endregion
66
+ export { type TuiState, resolve, setTheme, theme };
@@ -0,0 +1,209 @@
1
+ import { onTheme, resolve, setTheme, theme } from "./index.mjs";
2
+ import { RGBA } from "@opentui/core";
3
+ //#region src/opentui-system.ts
4
+ /**
5
+ * The report of OpenTUI's palette and theme mode.
6
+ *
7
+ * @param {TerminalColors} colors what `renderer.getPalette()` gave (none yet: `undefined`)
8
+ * @param {ThemeMode} mode `renderer.themeMode`
9
+ * @returns {Report} the report for `theme.solve`
10
+ */
11
+ const reportOf = (colors, mode) => ({
12
+ fg: colors?.defaultForeground,
13
+ bg: colors?.defaultBackground,
14
+ ansi: colors?.palette ?? [],
15
+ scheme: mode
16
+ });
17
+ /**
18
+ * Follows the terminal's colours: sets the system theme (`setTheme`) with the fallback at once, asks OpenTUI for the
19
+ * palette, and rebuilds the theme when it comes, on a `palette` event and on a `theme_mode` change.
20
+ *
21
+ * @param {CliRenderer} renderer the renderer
22
+ * @param {SystemTheme} theme the theme of `createSystemTheme`
23
+ * @param {object} options `wait`: how long to wait for the palette, in ms (default 100)
24
+ * @returns {Promise<Function>} after the palette or `wait`, whichever is first: the function that stops following
25
+ */
26
+ const followSystemTheme = async (renderer, theme, options = {}) => {
27
+ let colors;
28
+ const apply = () => theme.apply(reportOf(colors, renderer.themeMode), { indexed: true });
29
+ const onPalette = (c) => {
30
+ colors = c;
31
+ apply();
32
+ };
33
+ const query = () => renderer.getPalette({ size: 16 }).then(onPalette, () => {});
34
+ const onMode = () => {
35
+ apply();
36
+ query();
37
+ };
38
+ renderer.on("palette", onPalette);
39
+ renderer.on("theme_mode", onMode);
40
+ const stop = () => {
41
+ renderer.off("palette", onPalette);
42
+ renderer.off("theme_mode", onMode);
43
+ };
44
+ renderer.once("destroy", stop);
45
+ apply();
46
+ setTheme(theme.name);
47
+ const waited = Promise.withResolvers();
48
+ const timer = setTimeout(waited.resolve, options.wait ?? 100);
49
+ await Promise.race([query(), waited.promise]);
50
+ clearTimeout(timer);
51
+ return stop;
52
+ };
53
+ //#endregion
54
+ //#region src/opentui.ts
55
+ const BITS = {
56
+ bold: 1,
57
+ dim: 2,
58
+ italic: 4,
59
+ underline: 8,
60
+ strikethrough: 128
61
+ };
62
+ const SHAPE = {
63
+ auto: "default",
64
+ bar: "line",
65
+ block: "block",
66
+ underscore: "underline"
67
+ };
68
+ const FOCUSED = [
69
+ ["borderColor", "focusedBorderColor"],
70
+ ["backgroundColor", "focusedBackgroundColor"],
71
+ ["textColor", "focusedTextColor"]
72
+ ];
73
+ const drawn = (v, bg) => v === "default" ? bg ? RGBA.defaultBackground() : RGBA.defaultForeground() : typeof v === "string" && v.startsWith("ansi:") ? RGBA.fromIndex(Number(v.slice(5))) : v;
74
+ /**
75
+ * The OpenTUI props of a style (`has` tells which props the renderable has: a box takes `backgroundColor`, a text `bg`):
76
+ * `color` is `fg` (`textColor` on an editable or a select), the text attributes are the bits of `attributes`, the
77
+ * caret is `cursorStyle` and `cursorColor` (Input, Textarea). `cursor` is not a prop: `attach` sets the mouse pointer.
78
+ *
79
+ * @param {TuiProps} p the props of `resolve()`
80
+ * @param {Function} has whether the renderable has a prop
81
+ * @returns {Record<string, unknown>} the props of an OpenTUI renderable
82
+ */
83
+ const props = (p, has = () => true) => {
84
+ const out = {};
85
+ let bits;
86
+ for (const [k, v] of Object.entries(p)) if (Object.hasOwn(BITS, k)) bits = (bits ?? 0) | (v ? BITS[k] : 0);
87
+ else if (k === "color") out[has("fg") || !has("textColor") ? "fg" : "textColor"] = drawn(v, false);
88
+ else if (k === "backgroundColor") out[has("backgroundColor") ? "backgroundColor" : "bg"] = drawn(v, true);
89
+ else if (k === "caretColor") out.cursorColor = drawn(v, false);
90
+ else if (k === "borderColor") out.borderColor = drawn(v, false);
91
+ else if (k !== "cursor" && k !== "caretShape" && k !== "caretAnimation") out[k] = v;
92
+ if (bits !== void 0) out.attributes = bits;
93
+ if (p.caretShape || p.caretAnimation) out.cursorStyle = {
94
+ style: SHAPE[p.caretShape ?? "auto"],
95
+ blinking: p.caretAnimation !== "manual"
96
+ };
97
+ return out;
98
+ };
99
+ const attached = /* @__PURE__ */ new WeakMap();
100
+ /**
101
+ * Sets the props of `style` on `r` and keeps them up to date: `:hover` from `over` to `out`, `:active` from `down` to
102
+ * `up` (or `out`), `:focus` while it has focus (a box needs `focusable: true`), and the theme of `setTheme`. The mouse
103
+ * pointer is the style's `cursor` on `over`, `default` again on `out`. Handlers of your own (`onMouseOver`) still run.
104
+ * A focused renderable draws its `focused*` colours (`focusedBorderColor` of a box): they follow the style too. A text
105
+ * node (`<span>`, `<a>`) has no mouse events and no focus: it takes the props and the theme, not the states.
106
+ * On a renderable it has attached already, it swaps the style (cssints-332g): the states, the theme and the hooks stay,
107
+ * a prop only the old style set goes back to the renderable's own value, and the pointer follows the new `cursor`.
108
+ *
109
+ * @param {Renderable | TextNodeRenderable} r a renderable or a text node of OpenTUI
110
+ * @param {TuiShape} style a style of cssints/tui
111
+ * @returns {Renderable | TextNodeRenderable} `r`
112
+ */
113
+ const attach = (r, style) => {
114
+ const again = attached.get(r);
115
+ if (again) {
116
+ again(style);
117
+ return r;
118
+ }
119
+ const state = {};
120
+ const target = r;
121
+ const saved = /* @__PURE__ */ new Map();
122
+ const last = /* @__PURE__ */ new Map();
123
+ let pointer = false;
124
+ const apply = () => {
125
+ const next = props(resolve(style, state), (k) => k in r);
126
+ for (const [from, to] of FOCUSED) if (Object.hasOwn(next, from)) next[to] = next[from];
127
+ const attrs = next.attributes;
128
+ for (const k of /* @__PURE__ */ new Set([...saved.keys(), ...Object.keys(next)])) {
129
+ if (!(k in r)) continue;
130
+ if (!saved.has(k)) saved.set(k, target[k]);
131
+ let v = Object.hasOwn(next, k) ? next[k] : saved.get(k);
132
+ if (k === "attributes" && attrs !== void 0) v = saved.get(k) & -144 | attrs;
133
+ if (last.get(k) === v) continue;
134
+ last.set(k, v);
135
+ target[k] = v;
136
+ }
137
+ r.requestRender();
138
+ };
139
+ const set = (key, on) => {
140
+ if (!!state[key] === on) return false;
141
+ state[key] = on;
142
+ return true;
143
+ };
144
+ const stop = onTheme(apply);
145
+ if (!("onMouseEvent" in r)) {
146
+ attached.set(r, (next) => {
147
+ style = next;
148
+ apply();
149
+ });
150
+ const end = r.destroyRecursively.bind(r);
151
+ r.destroyRecursively = () => {
152
+ stop();
153
+ for (const child of r.getChildren()) child.destroyRecursively();
154
+ end();
155
+ };
156
+ apply();
157
+ return r;
158
+ }
159
+ const hooked = r;
160
+ const own = hooked.onMouseEvent.bind(r);
161
+ hooked.onMouseEvent = (event) => {
162
+ let changed = false;
163
+ if (event.type === "over") {
164
+ changed = set("hover", true);
165
+ const cursor = resolve(style, {
166
+ ...state,
167
+ hover: true
168
+ }).cursor;
169
+ if (cursor) hooked.ctx.setMousePointer(cursor);
170
+ pointer = !!cursor;
171
+ } else if (event.type === "out") {
172
+ changed = set("hover", false);
173
+ changed = set("active", false) || changed;
174
+ if (pointer) hooked.ctx.setMousePointer("default");
175
+ pointer = false;
176
+ } else if (event.type === "down") changed = set("active", true);
177
+ else if (event.type === "up") changed = set("active", false);
178
+ if (changed || pointer) apply();
179
+ own(event);
180
+ };
181
+ hooked.on("focused", () => set("focus", true) && apply());
182
+ hooked.on("blurred", () => set("focus", false) && apply());
183
+ hooked.once("destroyed", stop);
184
+ attached.set(r, (next) => {
185
+ style = next;
186
+ if (state.hover) {
187
+ const cursor = resolve(style, state).cursor;
188
+ if (cursor || pointer) hooked.ctx.setMousePointer(cursor ?? "default");
189
+ pointer = !!cursor;
190
+ }
191
+ apply();
192
+ });
193
+ apply();
194
+ return r;
195
+ };
196
+ /**
197
+ * Props to spread on an OpenTUI element of Solid or React: `<box {...use(card)} />`. The `ref` attaches the style
198
+ * (`attach`) when the renderable is made, before its first frame. A style that changes is an accessor,
199
+ * `use(() => (active() ? a : b))`: Solid calls a ref in a render effect, so the signals it reads run it again, and each
200
+ * run swaps the style (React calls the new ref of each render). The adapter imports no framework.
201
+ *
202
+ * @param {TuiShape | Function} style a style of cssints/tui, or a function that returns one
203
+ * @returns {object} `{ ref }`
204
+ */
205
+ const use = (style) => ({ ref: (r) => {
206
+ if (r) attach(r, typeof style === "function" ? style() : style);
207
+ } });
208
+ //#endregion
209
+ export { attach, followSystemTheme, props, reportOf, resolve, setTheme, theme, use };
@@ -0,0 +1,118 @@
1
+ //#region src/system.d.ts
2
+ /** The 16 ANSI colours, by their index. */
3
+ declare const SLOTS: readonly ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "brightBlack", "brightRed", "brightGreen", "brightYellow", "brightBlue", "brightMagenta", "brightCyan", "brightWhite"];
4
+ type Slot = (typeof SLOTS)[number];
5
+ /** Where a role takes its hue: an ANSI colour, or the terminal's default foreground or background. */
6
+ type Hue = Slot | "fg" | "bg";
7
+ type Appearance = "dark" | "light";
8
+ /** A colour token of `createTokens` (its text at run time: `var(--name)`). */
9
+ type ColourToken = string | {
10
+ readonly "~token": "color";
11
+ };
12
+ /** A colour token as a role of the system theme. */
13
+ interface Role {
14
+ /** The hue source (default `"fg"`, `"bg"` for a surface). */
15
+ hue?: Hue;
16
+ /** The tokens it sits on (each must have a role). */
17
+ on?: readonly ColourToken[];
18
+ /** The WCAG 2 ratio against each of `on`: the least for text, the exact one (to the first) for a surface. */
19
+ contrast?: number;
20
+ /** A background: placed at `contrast` from its first `on`, toward the foreground; the terminal's background without. */
21
+ surface?: boolean;
22
+ /** What the terminal draws when it reports nothing: an ANSI index, or its default colour. */
23
+ ansi?: number | "default";
24
+ }
25
+ /** The roles of a token set, in its shape: a role per colour token, any left out. */
26
+ type Roles<T> = { [K in keyof T]?: T[K] extends ColourToken ? Role : T[K] extends {
27
+ readonly "~token": unknown;
28
+ } ? never : Roles<T[K]>; };
29
+ /** What a terminal reported: `#rrggbb` colours (`undefined` or `null`: no answer) and its colour scheme. */
30
+ interface Report {
31
+ fg?: string | null;
32
+ bg?: string | null;
33
+ ansi?: readonly (string | null | undefined)[];
34
+ scheme?: Appearance | null;
35
+ }
36
+ interface SolveOptions {
37
+ /** Whether the renderer draws ANSI indices (`ansi:N`, `default`); without, a terminal that reports nothing keeps the static theme. */
38
+ indexed?: boolean;
39
+ /** The `COLORFGBG` variable (default: the environment's). */
40
+ colorfgbg?: string;
41
+ }
42
+ interface Solved {
43
+ appearance: Appearance;
44
+ /** A colour per token name (`color-bg` for `var(--color-bg)`). */
45
+ values: Record<string, string>;
46
+ /** The static theme under it: what a token without a role, or every token without a palette, keeps. */
47
+ base: string;
48
+ }
49
+ interface SystemOptions {
50
+ /** The theme's name for `setTheme` (default `"system"`). */
51
+ name?: string;
52
+ /** The app's own colour per slot, for what the terminal did not report (default: an xterm-like palette). */
53
+ hues?: Partial<Record<Hue, string>>;
54
+ /** The static theme under the system theme, per appearance (default `""`, the default values). */
55
+ themes?: Partial<Record<Appearance, string>>;
56
+ }
57
+ interface SystemTheme {
58
+ readonly name: string;
59
+ /** The values of every role for a report. */
60
+ solve(report: Report, options?: SolveOptions): Solved;
61
+ /** `solve`, then `defineTheme(name, values, base)`. */
62
+ apply(report: Report, options?: SolveOptions): Solved;
63
+ }
64
+ /**
65
+ * The relative luminance of a colour (WCAG 2), as check.contrast reads it.
66
+ *
67
+ * @param {string} hex a colour
68
+ * @returns {number} its luminance, 0 to 1
69
+ */
70
+ declare const luminance: (hex: string) => number;
71
+ /**
72
+ * The WCAG 2 contrast ratio of two colours.
73
+ *
74
+ * @param {string} a a colour
75
+ * @param {string} b another
76
+ * @returns {number} the ratio, 1 to 21
77
+ */
78
+ declare const contrast: (a: string, b: string) => number;
79
+ /**
80
+ * A system theme: each token of `roles` takes its hue from a colour of the terminal and its lightness from its contrast
81
+ * rules against the tokens it sits on. Checks the roles (an `on` without a role, a cycle) and orders them.
82
+ *
83
+ * @param {object} tokens the tokens of `createTokens` (cssints/tui)
84
+ * @param {Roles} roles a role per colour token, in the shape of `tokens`
85
+ * @param {SystemOptions} options the name, the app's own hues, the static theme under it
86
+ * @returns {SystemTheme} the theme, for `followSystemTheme` of an adapter, or `solve` and `apply`
87
+ */
88
+ declare const createSystemTheme: <T extends object>(tokens: T, roles: Roles<T>, options?: SystemOptions) => SystemTheme;
89
+ /** OSC 10 and 11 (the default colours) and OSC 4 for the 16 ANSI colours. */
90
+ declare const COLOURS: string;
91
+ /** The colours and the colour-scheme report (`CSI ? 996 n`). */
92
+ declare const QUERY: string;
93
+ /** Mode 2031 on: the terminal sends `CSI ? 997 ; 1|2 n` when its palette changes. */
94
+ declare const NOTIFY = "[?2031h";
95
+ /** Mode 2031 off. */
96
+ declare const UNNOTIFY = "[?2031l";
97
+ /** What one chunk of input held of the terminal's replies. */
98
+ interface Replies {
99
+ fg?: string;
100
+ bg?: string;
101
+ /** The ANSI colours it reported, by index. */
102
+ ansi: Map<number, string>;
103
+ /** The colour scheme of a `CSI ? 997 ; 1|2 n` (a reply to the query, or a notification of a change). */
104
+ scheme?: Appearance;
105
+ }
106
+ /**
107
+ * Takes the terminal's replies (OSC 10, 11 and 4, `CSI ? 997 n`) out of a chunk of input, as text of one char per byte.
108
+ *
109
+ * @param {string} text the chunk, after what `tail` of the last one kept
110
+ * @returns {object} the replies, the rest of the input (keys, mouse), and the tail of a reply cut off at the end
111
+ */
112
+ declare const scan: (text: string) => {
113
+ replies: Replies;
114
+ rest: string;
115
+ tail: string;
116
+ };
117
+ //#endregion
118
+ export { UNNOTIFY as _, NOTIFY as a, luminance as b, Report as c, SLOTS as d, Slot as f, SystemTheme as g, SystemOptions as h, Hue as i, Role as l, Solved as m, COLOURS as n, QUERY as o, SolveOptions as p, ColourToken as r, Replies as s, Appearance as t, Roles as u, contrast as v, scan as x, createSystemTheme as y };
@@ -0,0 +1,2 @@
1
+ import { _ as UNNOTIFY, a as NOTIFY, b as luminance, c as Report, d as SLOTS, f as Slot, g as SystemTheme, h as SystemOptions, i as Hue, l as Role, m as Solved, n as COLOURS, o as QUERY, p as SolveOptions, r as ColourToken, s as Replies, t as Appearance, u as Roles, v as contrast, x as scan, y as createSystemTheme } from "./system-CFyJGOUM.mjs";
2
+ export { Appearance, COLOURS, ColourToken, Hue, NOTIFY, QUERY, Replies, Report, Role, Roles, SLOTS, Slot, SolveOptions, Solved, SystemOptions, SystemTheme, UNNOTIFY, contrast, createSystemTheme, luminance, scan };