@promptctl/rich-js 0.26.0 → 0.28.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/README.md +1 -0
- package/THIRD-PARTY-NOTICES +42 -0
- package/dist/core/animation.d.ts +52 -15
- package/dist/core/animation.js +82 -37
- package/dist/core/ansi.d.ts +15 -8
- package/dist/core/ansi.js +106 -28
- package/dist/core/bidi-data.d.ts +14 -0
- package/dist/core/bidi-data.js +385 -0
- package/dist/core/bidi.d.ts +89 -0
- package/dist/core/bidi.js +615 -0
- package/dist/core/box.d.ts +9 -1
- package/dist/core/box.js +11 -0
- package/dist/core/cell-widths.d.ts +3 -2
- package/dist/core/cell-widths.js +93 -93
- package/dist/core/cells.d.ts +20 -0
- package/dist/core/cells.js +93 -5
- package/dist/core/color.d.ts +26 -18
- package/dist/core/color.js +37 -34
- package/dist/core/console.d.ts +26 -1
- package/dist/core/console.js +26 -6
- package/dist/core/control-codes.d.ts +61 -0
- package/dist/core/control-codes.js +157 -0
- package/dist/core/easing.js +6 -1
- package/dist/core/env.d.ts +6 -0
- package/dist/core/env.js +9 -1
- package/dist/core/export-html.js +4 -3
- package/dist/core/export-lines.d.ts +2 -0
- package/dist/core/export-lines.js +7 -3
- package/dist/core/export-svg.js +6 -5
- package/dist/core/json.js +9 -2
- package/dist/core/markup.js +4 -3
- package/dist/core/oklch.d.ts +2 -0
- package/dist/core/oklch.js +3 -3
- package/dist/core/orient.d.ts +68 -0
- package/dist/core/orient.js +224 -0
- package/dist/core/osc8.d.ts +12 -5
- package/dist/core/osc8.js +14 -7
- package/dist/core/pretty.js +22 -18
- package/dist/core/protocol.d.ts +53 -22
- package/dist/core/protocol.js +14 -6
- package/dist/core/render.d.ts +8 -3
- package/dist/core/render.js +19 -5
- package/dist/core/seal.d.ts +26 -0
- package/dist/core/seal.js +75 -0
- package/dist/core/segment.d.ts +9 -1
- package/dist/core/segment.js +11 -1
- package/dist/core/style.d.ts +29 -1
- package/dist/core/style.js +41 -5
- package/dist/core/text-order.d.ts +51 -0
- package/dist/core/text-order.js +50 -0
- package/dist/core/text.d.ts +10 -0
- package/dist/core/text.js +133 -87
- package/dist/core/timeline.js +6 -6
- package/dist/core/view.d.ts +23 -9
- package/dist/core/view.js +37 -12
- package/dist/core/wrap.d.ts +24 -6
- package/dist/core/wrap.js +82 -16
- package/dist/host/app.d.ts +48 -7
- package/dist/host/app.js +116 -11
- package/dist/host/index.d.ts +3 -2
- package/dist/host/index.js +1 -0
- package/dist/host/input.d.ts +35 -2
- package/dist/host/input.js +88 -4
- package/dist/host/terminal-colors.d.ts +18 -0
- package/dist/host/terminal-colors.js +46 -0
- package/dist/host/terminal-host.d.ts +2 -1
- package/dist/index.d.ts +10 -8
- package/dist/index.js +2 -2
- package/dist/renderables/change.d.ts +1 -3
- package/dist/renderables/change.js +4 -6
- package/dist/renderables/effect.d.ts +61 -60
- package/dist/renderables/effect.js +91 -81
- package/dist/renderables/effects.d.ts +37 -8
- package/dist/renderables/effects.js +193 -55
- package/dist/renderables/frames.d.ts +1 -10
- package/dist/renderables/frames.js +1 -16
- package/dist/renderables/glyph-effect.d.ts +12 -13
- package/dist/renderables/glyph-effect.js +34 -32
- package/dist/renderables/glyph-effects.d.ts +27 -8
- package/dist/renderables/glyph-effects.js +75 -7
- package/dist/renderables/lifecycle.d.ts +40 -32
- package/dist/renderables/lifecycle.js +87 -48
- package/dist/renderables/live.d.ts +3 -3
- package/dist/renderables/live.js +4 -4
- package/dist/renderables/markdown.js +4 -2
- package/dist/renderables/panel.js +6 -4
- package/dist/renderables/progress.d.ts +11 -4
- package/dist/renderables/progress.js +29 -17
- package/dist/renderables/progressBar.d.ts +3 -3
- package/dist/renderables/progressBar.js +16 -13
- package/dist/renderables/syntax.js +7 -2
- package/dist/renderables/table.js +2 -1
- package/dist/template-bindings/animation-funcs.d.ts +49 -18
- package/dist/template-bindings/animation-funcs.js +115 -32
- package/dist/template-bindings/index.d.ts +7 -5
- package/dist/template-bindings/index.js +8 -5
- package/dist/template-bindings/palette-funcs.d.ts +1 -1
- package/dist/template-bindings/palette-funcs.js +1 -1
- package/dist/themes/buildPalette.d.ts +15 -39
- package/dist/themes/buildPalette.js +196 -67
- package/dist/themes/colorMath.d.ts +10 -4
- package/dist/themes/colorMath.js +33 -1
- package/dist/themes/data/index.js +1 -4
- package/dist/themes/data/textual-ansi.js +0 -143
- package/dist/themes/data/types.d.ts +3 -1
- package/dist/themes/palette.d.ts +22 -6
- package/dist/themes/palette.js +13 -21
- package/dist/themes/ramp.d.ts +1 -1
- package/dist/themes/ramp.js +1 -1
- package/dist/themes/registry.d.ts +7 -10
- package/dist/themes/registry.js +9 -30
- package/dist/themes/terminalThemes.d.ts +4 -10
- package/dist/themes/terminalThemes.js +31 -46
- package/dist/themes/transpose.d.ts +5 -10
- package/dist/themes/transpose.js +13 -24
- package/dist/widgets/button.d.ts +1 -1
- package/dist/widgets/button.js +6 -6
- package/dist/widgets/checkbox.js +4 -4
- package/dist/widgets/dropdown.d.ts +1 -1
- package/dist/widgets/dropdown.js +7 -5
- package/dist/widgets/event-router.js +2 -2
- package/dist/widgets/ink.d.ts +5 -4
- package/dist/widgets/ink.js +6 -9
- package/dist/widgets/text-input.d.ts +1 -1
- package/dist/widgets/text-input.js +41 -32
- package/dist/widgets/themed-widget.js +3 -3
- package/dist/widgets/toggle.d.ts +1 -1
- package/dist/widgets/toggle.js +5 -5
- package/dist/widgets/types.d.ts +2 -2
- package/dist/widgets/widget-app.d.ts +3 -3
- package/dist/widgets/widget-app.js +5 -5
- package/package.json +5 -4
package/dist/themes/palette.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A semantic palette: a named map from
|
|
2
|
+
* A semantic palette: a named map from role → ColorRgba, holding every
|
|
3
|
+
* `PaletteRole`.
|
|
3
4
|
*
|
|
4
5
|
* Distinct from `ColorTable` (the integer-indexed quantization LUT used by
|
|
5
6
|
* the downgrade pipeline). Palettes carry aesthetic intent — `primary`,
|
|
@@ -24,26 +25,26 @@
|
|
|
24
25
|
* draws nothing on any surface, so it needs none and is handed out as it is,
|
|
25
26
|
* and a `Style` reads it as no background at all.
|
|
26
27
|
*
|
|
27
|
-
* @throws RangeError when `background` is translucent
|
|
28
|
-
* partly transparent and there is no `background` to draw it on.
|
|
28
|
+
* @throws RangeError when `background` is translucent.
|
|
29
29
|
*/
|
|
30
30
|
export class Palette {
|
|
31
31
|
name;
|
|
32
32
|
dark;
|
|
33
33
|
vars;
|
|
34
|
-
constructor(name, dark,
|
|
34
|
+
constructor(name, dark, roles) {
|
|
35
35
|
this.name = name;
|
|
36
36
|
this.dark = dark;
|
|
37
37
|
// [LAW:single-enforcer] Every palette is built through here, so this is
|
|
38
|
-
// where "a palette colour is opaque or draws nothing" holds.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const background = vars.get("background");
|
|
42
|
-
const draw = background === undefined ? opaqueOnly(name) : drawnOn(name, background);
|
|
43
|
-
this.vars = new Map([...vars].map(([key, colour]) => [key, draw(colour, key)]));
|
|
38
|
+
// where "a palette colour is opaque or draws nothing" holds.
|
|
39
|
+
const draw = drawnOn(name, roles.background);
|
|
40
|
+
this.vars = new Map(Object.entries(roles).map(([role, colour]) => [role, draw(colour)]));
|
|
44
41
|
}
|
|
45
|
-
get(
|
|
46
|
-
return this.vars.get(
|
|
42
|
+
get(role) {
|
|
43
|
+
return this.vars.get(role);
|
|
44
|
+
}
|
|
45
|
+
/** This palette's roles, each put through `colour`: what a new palette is built from. */
|
|
46
|
+
mapRoles(colour) {
|
|
47
|
+
return Object.fromEntries([...this.vars].map(([role, was]) => [role, colour(was, role)]));
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
/**
|
|
@@ -60,12 +61,3 @@ export function drawnOn(name, background) {
|
|
|
60
61
|
// A fully transparent colour is not a tint: it draws nothing on any surface.
|
|
61
62
|
return (colour) => (colour.alpha === 0 ? colour : colour.compositeOver(background));
|
|
62
63
|
}
|
|
63
|
-
// A palette with no background has nothing to draw a translucent colour on.
|
|
64
|
-
function opaqueOnly(name) {
|
|
65
|
-
return (colour, key) => {
|
|
66
|
-
if (colour.alpha !== 1 && colour.alpha !== 0) {
|
|
67
|
-
throw new RangeError(`palette ${JSON.stringify(name)}: ${key} is translucent (${colour.hex}) but the palette has no "background" to draw it on`);
|
|
68
|
-
}
|
|
69
|
-
return colour;
|
|
70
|
-
};
|
|
71
|
-
}
|
package/dist/themes/ramp.d.ts
CHANGED
|
@@ -122,7 +122,7 @@ export declare class ColorRamp {
|
|
|
122
122
|
* [LAW:one-source-of-truth] When it next changes is `Animation.all`'s
|
|
123
123
|
* answer over the two parts; nothing here says it a second time. Whether
|
|
124
124
|
* the depth it is drawn at can show the move is decided where it is drawn
|
|
125
|
-
* (`gradient`, through `
|
|
125
|
+
* (`gradient`, through `stillWhereNothingMoves`).
|
|
126
126
|
*/
|
|
127
127
|
moving(motion: RampMotion): Animation<ColorRamp>;
|
|
128
128
|
}
|
package/dist/themes/ramp.js
CHANGED
|
@@ -159,7 +159,7 @@ export class ColorRamp {
|
|
|
159
159
|
* [LAW:one-source-of-truth] When it next changes is `Animation.all`'s
|
|
160
160
|
* answer over the two parts; nothing here says it a second time. Whether
|
|
161
161
|
* the depth it is drawn at can show the move is decided where it is drawn
|
|
162
|
-
* (`gradient`, through `
|
|
162
|
+
* (`gradient`, through `stillWhereNothingMoves`).
|
|
163
163
|
*/
|
|
164
164
|
moving(motion) {
|
|
165
165
|
const still = Animation.constant(0);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ColorRgba, ColorTable } from "../core/color.js";
|
|
2
|
-
import { Palette } from "./palette.js";
|
|
2
|
+
import { type Palette } from "./palette.js";
|
|
3
3
|
import { type ThemeName } from "./data/index.js";
|
|
4
4
|
export type { ThemeName };
|
|
5
5
|
/**
|
|
@@ -11,16 +11,15 @@ export declare function listThemePalettes(): readonly ThemeName[];
|
|
|
11
11
|
*
|
|
12
12
|
* Synchronous: theme data is bundled at compile time via the data barrel,
|
|
13
13
|
* so no I/O happens here. The Palette itself (which requires hex-parsing
|
|
14
|
-
* ~150 vars into ColorRgba values) is
|
|
15
|
-
*
|
|
14
|
+
* ~150 vars into ColorRgba values) is cached on first request — subsequent
|
|
15
|
+
* calls for the same name return the same instance. `terminalThemes.ts` makes
|
|
16
|
+
* that request for every theme, on import.
|
|
16
17
|
*/
|
|
17
18
|
export declare function getThemePalette(name: ThemeName): Palette;
|
|
18
19
|
export declare function getThemePalette(name: string): Palette | null;
|
|
19
20
|
/**
|
|
20
21
|
* The eight base colors every theme must declare, and its ANSI table. Returned by
|
|
21
|
-
* `getThemeBaseColors` for callers
|
|
22
|
-
* need the substrate and would otherwise pay the cost of hydrating the
|
|
23
|
-
* full ~150-var palette and polluting the registry cache.
|
|
22
|
+
* `getThemeBaseColors` for callers that only need the substrate.
|
|
24
23
|
*/
|
|
25
24
|
export interface ThemeBaseColors {
|
|
26
25
|
readonly name: string;
|
|
@@ -36,9 +35,7 @@ export interface ThemeBaseColors {
|
|
|
36
35
|
readonly ansi: ColorTable;
|
|
37
36
|
}
|
|
38
37
|
/**
|
|
39
|
-
* Read just the eight base colors from a theme's data file.
|
|
40
|
-
* 8 hex strings, allocates no Palette, touches no cache.
|
|
41
|
-
* want a `TerminalTheme`-shaped substrate without forcing the full ~150-var
|
|
42
|
-
* palette through the registry's hydration path.
|
|
38
|
+
* Read just the eight base colors and the ANSI table from a theme's data file.
|
|
39
|
+
* Parses 8 hex strings, allocates no Palette, touches no cache.
|
|
43
40
|
*/
|
|
44
41
|
export declare function getThemeBaseColors(name: ThemeName): ThemeBaseColors;
|
package/dist/themes/registry.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ColorParseError, ColorTable, parseHexColor } from "../core/color.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { drawnOn } from "./palette.js";
|
|
3
|
+
import { buildPalette } from "./buildPalette.js";
|
|
4
4
|
import { THEMES } from "./data/index.js";
|
|
5
5
|
import { ANSI_SLOTS } from "./data/types.js";
|
|
6
6
|
import { Memo } from "../core/memo.js";
|
|
@@ -23,18 +23,16 @@ function isThemeName(name) {
|
|
|
23
23
|
return Object.hasOwn(THEMES, name);
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
* Read just the eight base colors from a theme's data file.
|
|
27
|
-
* 8 hex strings, allocates no Palette, touches no cache.
|
|
28
|
-
* want a `TerminalTheme`-shaped substrate without forcing the full ~150-var
|
|
29
|
-
* palette through the registry's hydration path.
|
|
26
|
+
* Read just the eight base colors and the ANSI table from a theme's data file.
|
|
27
|
+
* Parses 8 hex strings, allocates no Palette, touches no cache.
|
|
30
28
|
*/
|
|
31
29
|
export function getThemeBaseColors(name) {
|
|
32
30
|
const data = THEMES[name];
|
|
33
|
-
const bg =
|
|
31
|
+
const bg = parseHex(data.vars.background, data.name, "background");
|
|
34
32
|
// The colours `getThemePalette(name)` hands out for the same names: drawn on
|
|
35
33
|
// the theme's own background, as a Palette draws every colour it holds.
|
|
36
34
|
const draw = drawnOn(data.name, bg);
|
|
37
|
-
const base = (key) => draw(
|
|
35
|
+
const base = (key) => draw(parseHex(data.vars[key], data.name, key));
|
|
38
36
|
return {
|
|
39
37
|
name: data.name,
|
|
40
38
|
dark: data.dark,
|
|
@@ -49,34 +47,15 @@ export function getThemeBaseColors(name) {
|
|
|
49
47
|
ansi: new ColorTable(ANSI_SLOTS.map((slot) => parseOpaqueHex(data.ansi[slot], data.name, `ansi.${slot}`))),
|
|
50
48
|
};
|
|
51
49
|
}
|
|
52
|
-
function requireBaseVar(data, key) {
|
|
53
|
-
const v = data.vars[key];
|
|
54
|
-
if (v === undefined) {
|
|
55
|
-
throw new Error(`Theme ${data.name}: required base var "${key}" missing from data file`);
|
|
56
|
-
}
|
|
57
|
-
return parseHex(v, data.name, key);
|
|
58
|
-
}
|
|
59
50
|
/**
|
|
60
51
|
* Parse a `ThemePaletteData`'s hex strings into a Palette of ColorRgba.
|
|
61
52
|
*
|
|
62
53
|
* [LAW:single-enforcer] Hex → ColorRgba conversion for theme data lives
|
|
63
|
-
* here, not on Palette
|
|
64
|
-
* `core/color → themes/palette` one-way edge (palette.ts must not import
|
|
65
|
-
* ColorRgba as a value, or it cycles with core/color's own use of Palette
|
|
66
|
-
* for INTERNAL_DEFAULT_THEME).
|
|
54
|
+
* here, not on Palette; what a theme does not state, `buildPalette` derives.
|
|
67
55
|
*/
|
|
68
56
|
function hydrate(data) {
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
map.set(k, parseHex(v, data.name, `var ${k}`));
|
|
72
|
-
}
|
|
73
|
-
// The data is Textual's as authored; its `text-*` is held to the pair this
|
|
74
|
-
// library promises by the same rule `buildPalette` derives it with.
|
|
75
|
-
for (const key of ACCENT_KEYS) {
|
|
76
|
-
const text = requireBaseVar(data, `text-${key}`);
|
|
77
|
-
map.set(`text-${key}`, accentText(text, requireBaseVar(data, `${key}-muted`), requireBaseVar(data, "background")));
|
|
78
|
-
}
|
|
79
|
-
return new Palette(data.name, data.dark, map);
|
|
57
|
+
const stated = Object.entries(data.vars).map(([role, hex]) => [role, parseHex(hex, data.name, `var ${role}`)]);
|
|
58
|
+
return buildPalette(data.name, data.dark, Object.fromEntries(stated));
|
|
80
59
|
}
|
|
81
60
|
// Theme data is authored, so a malformed colour names the theme and the key it
|
|
82
61
|
// sits under; the grammar itself is `parseHexColor`'s.
|
|
@@ -3,16 +3,10 @@
|
|
|
3
3
|
* matching `<NAME>` export here. There is no inline-only theme; the data
|
|
4
4
|
* file is the single source of truth for every theme's hex values.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* palette
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* derive from the same authored data.
|
|
11
|
-
*
|
|
12
|
-
* [LAW:one-source-of-truth] Hex values live in `data/<name>.ts`. This
|
|
13
|
-
* module is a derived view that builds a `TerminalTheme` from each
|
|
14
|
-
* theme's eight base colors via `buildPalette` for the substrate palette,
|
|
15
|
-
* and from the theme's own ANSI table for the sixteen named colours.
|
|
6
|
+
* [LAW:one-source-of-truth] Hex values live in `data/<name>.ts`, and a theme's
|
|
7
|
+
* name means one palette: a constant here holds the very `Palette`
|
|
8
|
+
* `getThemePalette(name)` returns, and takes the background and foreground off
|
|
9
|
+
* it, with the theme's sixteen named colours beside it.
|
|
16
10
|
*
|
|
17
11
|
* [LAW:one-type-per-behavior] Every theme has the same shape — name,
|
|
18
12
|
* `dark` flag, full Palette in the registry, `TerminalTheme` constant
|
|
@@ -3,16 +3,10 @@
|
|
|
3
3
|
* matching `<NAME>` export here. There is no inline-only theme; the data
|
|
4
4
|
* file is the single source of truth for every theme's hex values.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* palette
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* derive from the same authored data.
|
|
11
|
-
*
|
|
12
|
-
* [LAW:one-source-of-truth] Hex values live in `data/<name>.ts`. This
|
|
13
|
-
* module is a derived view that builds a `TerminalTheme` from each
|
|
14
|
-
* theme's eight base colors via `buildPalette` for the substrate palette,
|
|
15
|
-
* and from the theme's own ANSI table for the sixteen named colours.
|
|
6
|
+
* [LAW:one-source-of-truth] Hex values live in `data/<name>.ts`, and a theme's
|
|
7
|
+
* name means one palette: a constant here holds the very `Palette`
|
|
8
|
+
* `getThemePalette(name)` returns, and takes the background and foreground off
|
|
9
|
+
* it, with the theme's sixteen named colours beside it.
|
|
16
10
|
*
|
|
17
11
|
* [LAW:one-type-per-behavior] Every theme has the same shape — name,
|
|
18
12
|
* `dark` flag, full Palette in the registry, `TerminalTheme` constant
|
|
@@ -24,40 +18,31 @@
|
|
|
24
18
|
* color primitives; nothing in `core/` imports back.
|
|
25
19
|
*/
|
|
26
20
|
import { TerminalTheme } from "../core/color.js";
|
|
27
|
-
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return new TerminalTheme(
|
|
31
|
-
primary: d.primary,
|
|
32
|
-
secondary: d.secondary,
|
|
33
|
-
accent: d.accent,
|
|
34
|
-
success: d.success,
|
|
35
|
-
warning: d.warning,
|
|
36
|
-
error: d.error,
|
|
37
|
-
background: d.bg,
|
|
38
|
-
foreground: d.fg,
|
|
39
|
-
}));
|
|
21
|
+
import { getThemeBaseColors, getThemePalette } from "./registry.js";
|
|
22
|
+
function defineTheme(name) {
|
|
23
|
+
const palette = getThemePalette(name);
|
|
24
|
+
return new TerminalTheme(palette.get("background"), palette.get("foreground"), getThemeBaseColors(name).ansi, palette);
|
|
40
25
|
}
|
|
41
|
-
export const DEFAULT_TERMINAL_THEME = defineTheme(
|
|
42
|
-
export const SVG_EXPORT_THEME = defineTheme(
|
|
43
|
-
export const MONOKAI = defineTheme(
|
|
44
|
-
export const NORD = defineTheme(
|
|
45
|
-
export const GRUVBOX = defineTheme(
|
|
46
|
-
export const DRACULA = defineTheme(
|
|
47
|
-
export const TOKYO_NIGHT = defineTheme(
|
|
48
|
-
export const FLEXOKI = defineTheme(
|
|
49
|
-
export const CYBERPUNK = defineTheme(
|
|
50
|
-
export const CATPPUCCIN_MOCHA = defineTheme(
|
|
51
|
-
export const CATPPUCCIN_LATTE = defineTheme(
|
|
52
|
-
export const CATPPUCCIN_FRAPPE = defineTheme(
|
|
53
|
-
export const CATPPUCCIN_MACCHIATO = defineTheme(
|
|
54
|
-
export const SOLARIZED_DARK = defineTheme(
|
|
55
|
-
export const SOLARIZED_LIGHT = defineTheme(
|
|
56
|
-
export const ROSE_PINE = defineTheme(
|
|
57
|
-
export const ROSE_PINE_MOON = defineTheme(
|
|
58
|
-
export const ROSE_PINE_DAWN = defineTheme(
|
|
59
|
-
export const ATOM_ONE_DARK = defineTheme(
|
|
60
|
-
export const ATOM_ONE_LIGHT = defineTheme(
|
|
61
|
-
export const TEXTUAL_DARK = defineTheme(
|
|
62
|
-
export const TEXTUAL_LIGHT = defineTheme(
|
|
63
|
-
export const TEXTUAL_ANSI = defineTheme(
|
|
26
|
+
export const DEFAULT_TERMINAL_THEME = defineTheme("default");
|
|
27
|
+
export const SVG_EXPORT_THEME = defineTheme("svg-export");
|
|
28
|
+
export const MONOKAI = defineTheme("monokai");
|
|
29
|
+
export const NORD = defineTheme("nord");
|
|
30
|
+
export const GRUVBOX = defineTheme("gruvbox");
|
|
31
|
+
export const DRACULA = defineTheme("dracula");
|
|
32
|
+
export const TOKYO_NIGHT = defineTheme("tokyo-night");
|
|
33
|
+
export const FLEXOKI = defineTheme("flexoki");
|
|
34
|
+
export const CYBERPUNK = defineTheme("cyberpunk");
|
|
35
|
+
export const CATPPUCCIN_MOCHA = defineTheme("catppuccin-mocha");
|
|
36
|
+
export const CATPPUCCIN_LATTE = defineTheme("catppuccin-latte");
|
|
37
|
+
export const CATPPUCCIN_FRAPPE = defineTheme("catppuccin-frappe");
|
|
38
|
+
export const CATPPUCCIN_MACCHIATO = defineTheme("catppuccin-macchiato");
|
|
39
|
+
export const SOLARIZED_DARK = defineTheme("solarized-dark");
|
|
40
|
+
export const SOLARIZED_LIGHT = defineTheme("solarized-light");
|
|
41
|
+
export const ROSE_PINE = defineTheme("rose-pine");
|
|
42
|
+
export const ROSE_PINE_MOON = defineTheme("rose-pine-moon");
|
|
43
|
+
export const ROSE_PINE_DAWN = defineTheme("rose-pine-dawn");
|
|
44
|
+
export const ATOM_ONE_DARK = defineTheme("atom-one-dark");
|
|
45
|
+
export const ATOM_ONE_LIGHT = defineTheme("atom-one-light");
|
|
46
|
+
export const TEXTUAL_DARK = defineTheme("textual-dark");
|
|
47
|
+
export const TEXTUAL_LIGHT = defineTheme("textual-light");
|
|
48
|
+
export const TEXTUAL_ANSI = defineTheme("textual-ansi");
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
* `ThemeKey` to apply (data), not *whether* to apply one (branch).
|
|
18
18
|
*
|
|
19
19
|
* [LAW:one-source-of-truth] Anchor classification lives only in
|
|
20
|
-
* `ANCHORED_ROOTS` below.
|
|
21
|
-
*
|
|
22
|
-
* (`error`, `error
|
|
23
|
-
* the whole family.
|
|
20
|
+
* `ANCHORED_ROOTS` below. Every variant of a semantic root carries the root
|
|
21
|
+
* as its first hyphen segment (`error`, `error-darken-1`, `error-muted`, ...)
|
|
22
|
+
* or after a `text-` or `on-` that draws on it (`text-error`, `on-error`), so
|
|
23
|
+
* one set covers the whole family.
|
|
24
24
|
*
|
|
25
25
|
* [LAW:one-way-deps] Imports flow `core/oklch → themes/transpose`;
|
|
26
26
|
* nothing in core/ depends back on this file.
|
|
@@ -54,12 +54,7 @@ export declare function isAnchored(varName: string): boolean;
|
|
|
54
54
|
* lightness shifts, mirror-inversions, hue rotations that don't touch L,
|
|
55
55
|
* and combinations of all three. [LAW:types-are-the-program]
|
|
56
56
|
*
|
|
57
|
-
* The
|
|
58
|
-
* `dark`-flag derivation has nothing to read). Failing loudly is preferred
|
|
59
|
-
* over a silent fallback because the alternative — trusting the source
|
|
60
|
-
* `palette.dark` after an arbitrary L-transform — produces flags that lie.
|
|
61
|
-
* The identity fast-path is exempt: it preserves the source `dark` flag
|
|
62
|
-
* verbatim (no derivation), so it needs no `background` and never throws.
|
|
57
|
+
* The identity fast-path preserves the source `dark` flag verbatim.
|
|
63
58
|
*
|
|
64
59
|
* @param name Optional override for the resulting palette name. Defaults
|
|
65
60
|
* to the source palette's name. Callers building a family of transposed
|
package/dist/themes/transpose.js
CHANGED
|
@@ -17,15 +17,16 @@
|
|
|
17
17
|
* `ThemeKey` to apply (data), not *whether* to apply one (branch).
|
|
18
18
|
*
|
|
19
19
|
* [LAW:one-source-of-truth] Anchor classification lives only in
|
|
20
|
-
* `ANCHORED_ROOTS` below.
|
|
21
|
-
*
|
|
22
|
-
* (`error`, `error
|
|
23
|
-
* the whole family.
|
|
20
|
+
* `ANCHORED_ROOTS` below. Every variant of a semantic root carries the root
|
|
21
|
+
* as its first hyphen segment (`error`, `error-darken-1`, `error-muted`, ...)
|
|
22
|
+
* or after a `text-` or `on-` that draws on it (`text-error`, `on-error`), so
|
|
23
|
+
* one set covers the whole family.
|
|
24
24
|
*
|
|
25
25
|
* [LAW:one-way-deps] Imports flow `core/oklch → themes/transpose`;
|
|
26
26
|
* nothing in core/ depends back on this file.
|
|
27
27
|
*/
|
|
28
28
|
import { Oklch, isIdentityKey } from "../core/oklch.js";
|
|
29
|
+
import { pattern } from "../core/pattern.js";
|
|
29
30
|
import { Palette } from "./palette.js";
|
|
30
31
|
/**
|
|
31
32
|
* Semantic roots whose hue is locked under transposition. `error` must
|
|
@@ -43,9 +44,11 @@ export const ANCHORED_ROOTS = new Set([
|
|
|
43
44
|
"success",
|
|
44
45
|
"warning",
|
|
45
46
|
]);
|
|
47
|
+
const DRAWN_ON = pattern(/^(?:text|on)-/);
|
|
46
48
|
function rootOf(varName) {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
+
const role = varName.replace(DRAWN_ON, "");
|
|
50
|
+
const dash = role.indexOf("-");
|
|
51
|
+
return dash === -1 ? role : role.slice(0, dash);
|
|
49
52
|
}
|
|
50
53
|
/**
|
|
51
54
|
* Whether a palette var's hue is locked under transposition. The single
|
|
@@ -68,12 +71,7 @@ export function isAnchored(varName) {
|
|
|
68
71
|
* lightness shifts, mirror-inversions, hue rotations that don't touch L,
|
|
69
72
|
* and combinations of all three. [LAW:types-are-the-program]
|
|
70
73
|
*
|
|
71
|
-
* The
|
|
72
|
-
* `dark`-flag derivation has nothing to read). Failing loudly is preferred
|
|
73
|
-
* over a silent fallback because the alternative — trusting the source
|
|
74
|
-
* `palette.dark` after an arbitrary L-transform — produces flags that lie.
|
|
75
|
-
* The identity fast-path is exempt: it preserves the source `dark` flag
|
|
76
|
-
* verbatim (no derivation), so it needs no `background` and never throws.
|
|
74
|
+
* The identity fast-path preserves the source `dark` flag verbatim.
|
|
77
75
|
*
|
|
78
76
|
* @param name Optional override for the resulting palette name. Defaults
|
|
79
77
|
* to the source palette's name. Callers building a family of transposed
|
|
@@ -81,23 +79,14 @@ export function isAnchored(varName) {
|
|
|
81
79
|
*/
|
|
82
80
|
export function transposePalette(palette, key, name) {
|
|
83
81
|
if (isIdentityKey(key)) {
|
|
84
|
-
return new Palette(name ?? palette.name, palette.dark, palette.
|
|
82
|
+
return new Palette(name ?? palette.name, palette.dark, palette.mapRoles((colour) => colour));
|
|
85
83
|
}
|
|
86
84
|
// Anchors share *everything except* hue with the user's key. They still
|
|
87
85
|
// lightness-invert in a dark↔light flip; they still chroma-scale in a
|
|
88
86
|
// saturation sweep — only their hue is held.
|
|
89
87
|
const anchorKey = { ...key, hueShift: 0 };
|
|
90
|
-
const next =
|
|
91
|
-
|
|
92
|
-
const effective = isAnchored(varName) ? anchorKey : key;
|
|
93
|
-
next.set(varName, Oklch.fromRgba(color).applyKey(effective).toRgba());
|
|
94
|
-
}
|
|
95
|
-
const newBackground = next.get("background");
|
|
96
|
-
if (newBackground === undefined) {
|
|
97
|
-
throw new Error(`transposePalette: palette "${palette.name}" has no "background" ` +
|
|
98
|
-
`var; cannot derive the dark flag without a background color.`);
|
|
99
|
-
}
|
|
100
|
-
const newDark = Oklch.fromRgba(newBackground).l < 0.5;
|
|
88
|
+
const next = palette.mapRoles((colour, role) => Oklch.fromRgba(colour).applyKey(isAnchored(role) ? anchorKey : key).toRgba());
|
|
89
|
+
const newDark = Oklch.fromRgba(next.background).l < 0.5;
|
|
101
90
|
return new Palette(name ?? palette.name, newDark, next);
|
|
102
91
|
}
|
|
103
92
|
/**
|
package/dist/widgets/button.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export declare class Button extends ThemedWidget {
|
|
|
37
37
|
handleKey(event: KeyEvent): void;
|
|
38
38
|
handleMouse(event: WidgetMouseEvent): void;
|
|
39
39
|
setActive(value: boolean): void;
|
|
40
|
-
protected draw(
|
|
40
|
+
protected draw(options: RenderOptions): Iterable<Segment>;
|
|
41
41
|
measure(_options: RenderOptions): {
|
|
42
42
|
minimum: number;
|
|
43
43
|
maximum: number;
|
package/dist/widgets/button.js
CHANGED
|
@@ -49,9 +49,9 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
|
|
|
49
49
|
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
50
50
|
done = true;
|
|
51
51
|
};
|
|
52
|
+
import { labelled } from "../core/orient.js";
|
|
52
53
|
import { action } from "mobx";
|
|
53
54
|
import { observableRef } from "./observable.js";
|
|
54
|
-
import { Segment } from "../core/segment.js";
|
|
55
55
|
import { Style } from "../core/style.js";
|
|
56
56
|
import { cellLen } from "../core/cells.js";
|
|
57
57
|
import { ThemedWidget } from "./themed-widget.js";
|
|
@@ -148,14 +148,14 @@ let Button = (() => {
|
|
|
148
148
|
// --- Active mutator (the keyboard-activation microtask uses this) ---
|
|
149
149
|
setActive(value) { this.active = value; }
|
|
150
150
|
// --- Rendering ---
|
|
151
|
-
draw(
|
|
151
|
+
draw(options) {
|
|
152
152
|
// [LAW:dataflow-not-control-flow] same segment count and width every state
|
|
153
153
|
const focused = this.focused;
|
|
154
154
|
const left = focused ? "[" : " ";
|
|
155
155
|
const right = focused ? "]" : " ";
|
|
156
|
-
const
|
|
156
|
+
const drawn = (style) => labelled(`${left} `, this.label, ` ${right}`, style, options.textOrder);
|
|
157
157
|
if (this.disabled) {
|
|
158
|
-
return
|
|
158
|
+
return drawn(new Style(this.disabledInk));
|
|
159
159
|
}
|
|
160
160
|
// Active and hover share the same colour pair (full accent bg + on-accent fg).
|
|
161
161
|
// Active is differentiated by bold, not by inverting fg/bg — inversion gives
|
|
@@ -163,9 +163,9 @@ let Button = (() => {
|
|
|
163
163
|
// accents whose contrast partner depends on luminance.
|
|
164
164
|
const keys = VARIANT_KEYS[this.variant];
|
|
165
165
|
if (this.active || this.hovered) {
|
|
166
|
-
return
|
|
166
|
+
return drawn(new Style({ ...ink(this.theme, keys.hoverFg, keys.hover), bold: this.active }));
|
|
167
167
|
}
|
|
168
|
-
return
|
|
168
|
+
return drawn(new Style(ink(this.theme, keys.fg, keys.bg)));
|
|
169
169
|
}
|
|
170
170
|
measure(_options) {
|
|
171
171
|
// [LAW:one-source-of-truth] cellLen is the cell-width authority; .length
|
package/dist/widgets/checkbox.js
CHANGED
|
@@ -44,9 +44,9 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
|
|
|
44
44
|
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
45
45
|
done = true;
|
|
46
46
|
};
|
|
47
|
+
import { labelled } from "../core/orient.js";
|
|
47
48
|
import { action } from "mobx";
|
|
48
49
|
import { observableRef } from "./observable.js";
|
|
49
|
-
import { Segment } from "../core/segment.js";
|
|
50
50
|
import { Style } from "../core/style.js";
|
|
51
51
|
import { cellLen } from "../core/cells.js";
|
|
52
52
|
import { drawable } from "../core/protocol.js";
|
|
@@ -119,12 +119,12 @@ let Checkbox = (() => {
|
|
|
119
119
|
// --- Rendering ---
|
|
120
120
|
draw(options) {
|
|
121
121
|
const indicator = this.checked ? drawable(options, "✓", "x") : " ";
|
|
122
|
-
const
|
|
122
|
+
const drawn = (style) => labelled(`[${indicator}] `, this.label, "", style, options.textOrder);
|
|
123
123
|
if (this.disabled) {
|
|
124
|
-
return
|
|
124
|
+
return drawn(new Style(this.disabledInk));
|
|
125
125
|
}
|
|
126
126
|
const colors = ink(this.theme, this.checked ? "text-primary" : "foreground", "background");
|
|
127
|
-
return
|
|
127
|
+
return drawn(new Style({ ...colors, underline: this.focused }));
|
|
128
128
|
}
|
|
129
129
|
measure(_options) {
|
|
130
130
|
// [LAW:one-source-of-truth] cellLen — see button.ts.
|
|
@@ -55,7 +55,7 @@ export declare class Dropdown extends ThemedWidget implements OverlayRenderable
|
|
|
55
55
|
handleFocus(event: WidgetFocusEvent): void;
|
|
56
56
|
protected draw(options: RenderOptions): Iterable<Segment>;
|
|
57
57
|
private headerText;
|
|
58
|
-
renderOverlay(
|
|
58
|
+
renderOverlay(options: RenderOptions): Iterable<Segment> | null;
|
|
59
59
|
private renderNoMatchRow;
|
|
60
60
|
private renderOptionRow;
|
|
61
61
|
private maxLabelLen;
|
package/dist/widgets/dropdown.js
CHANGED
|
@@ -56,6 +56,7 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
|
|
|
56
56
|
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
57
57
|
done = true;
|
|
58
58
|
};
|
|
59
|
+
import { labelled } from "../core/orient.js";
|
|
59
60
|
import { action } from "mobx";
|
|
60
61
|
import { observableRef } from "./observable.js";
|
|
61
62
|
import { Segment } from "../core/segment.js";
|
|
@@ -318,7 +319,7 @@ let Dropdown = (() => {
|
|
|
318
319
|
const headerLabel = this.headerText(maxLabelLen, caret);
|
|
319
320
|
return [
|
|
320
321
|
new Segment("[", baseStyle),
|
|
321
|
-
|
|
322
|
+
...labelled("", headerLabel, ` ${arrowChar}`, baseStyle, options.textOrder),
|
|
322
323
|
new Segment("]", baseStyle),
|
|
323
324
|
];
|
|
324
325
|
}
|
|
@@ -348,18 +349,19 @@ let Dropdown = (() => {
|
|
|
348
349
|
const [filterText] = splitText(this.filter, asCellCol(filterRoom));
|
|
349
350
|
return setCellSize(" " + filterText + caret, asCellCol(maxLabelLen));
|
|
350
351
|
}
|
|
351
|
-
renderOverlay(
|
|
352
|
+
renderOverlay(options) {
|
|
352
353
|
if (!this.expanded)
|
|
353
354
|
return null;
|
|
354
355
|
const maxLabelLen = this.maxLabelLen();
|
|
355
356
|
const fopts = this.filteredOptions;
|
|
356
357
|
if (fopts.length === 0)
|
|
357
358
|
return this.renderNoMatchRow(maxLabelLen);
|
|
359
|
+
const order = options.textOrder;
|
|
358
360
|
const segments = [];
|
|
359
361
|
for (let i = 0; i < fopts.length; i++) {
|
|
360
362
|
if (i > 0)
|
|
361
363
|
segments.push(new Segment("\n"));
|
|
362
|
-
segments.push(...this.renderOptionRow(fopts[i], i, maxLabelLen));
|
|
364
|
+
segments.push(...this.renderOptionRow(fopts[i], i, maxLabelLen, order));
|
|
363
365
|
}
|
|
364
366
|
return segments;
|
|
365
367
|
}
|
|
@@ -379,7 +381,7 @@ let Dropdown = (() => {
|
|
|
379
381
|
new Segment(" ", style),
|
|
380
382
|
];
|
|
381
383
|
}
|
|
382
|
-
renderOptionRow(entry, fpos, maxLabelLen) {
|
|
384
|
+
renderOptionRow(entry, fpos, maxLabelLen, order) {
|
|
383
385
|
// Row: " " + label.padEnd(maxLabelLen) + " "
|
|
384
386
|
// Width = 1 + 1 + maxLabelLen + 1 + 1 = maxLabelLen + 4.
|
|
385
387
|
// Overlay rows are unbracketed — selection/highlight are conveyed by bg
|
|
@@ -399,7 +401,7 @@ let Dropdown = (() => {
|
|
|
399
401
|
: new Style(ink(this.theme, "foreground", "surface"));
|
|
400
402
|
return [
|
|
401
403
|
new Segment(" ", rowStyle),
|
|
402
|
-
|
|
404
|
+
...labelled("", inner, "", rowStyle, order),
|
|
403
405
|
new Segment(" ", rowStyle),
|
|
404
406
|
];
|
|
405
407
|
}
|
|
@@ -78,7 +78,7 @@ export class EventRouter {
|
|
|
78
78
|
}
|
|
79
79
|
/** Route a key the app heard. */
|
|
80
80
|
key(press) {
|
|
81
|
-
this.dispatchKey(new KeyEvent(press, this.source.
|
|
81
|
+
this.dispatchKey(new KeyEvent(press, this.source.frameNow().time));
|
|
82
82
|
}
|
|
83
83
|
/** Route a pointer event the app heard. */
|
|
84
84
|
mouse(event) {
|
|
@@ -173,7 +173,7 @@ export class EventRouter {
|
|
|
173
173
|
y: event.y - target.originY,
|
|
174
174
|
over: drew(frame, target.widget, event.x, event.y),
|
|
175
175
|
cell: cellOf(frame, target.widget, event.x, event.y),
|
|
176
|
-
time: this.source.
|
|
176
|
+
time: this.source.frameNow().time,
|
|
177
177
|
});
|
|
178
178
|
if (event.type === "mouse_down")
|
|
179
179
|
this.captured = target;
|
package/dist/widgets/ink.d.ts
CHANGED
|
@@ -11,12 +11,13 @@
|
|
|
11
11
|
*
|
|
12
12
|
* [LAW:types-are-the-program] There is no call that takes a foreground alone,
|
|
13
13
|
* so a widget cannot draw half a pair.
|
|
14
|
-
* [LAW:single-enforcer] Every widget resolves palette
|
|
15
|
-
* where
|
|
16
|
-
*
|
|
14
|
+
* [LAW:single-enforcer] Every widget resolves palette roles here, and this is
|
|
15
|
+
* where one that draws no colour (a theme's fully transparent "no background")
|
|
16
|
+
* is reported.
|
|
17
17
|
*/
|
|
18
18
|
import { ColorSpec, type TerminalTheme } from "../core/color.js";
|
|
19
|
-
|
|
19
|
+
import type { PaletteRole } from "../themes/palette.js";
|
|
20
|
+
export declare function ink(theme: TerminalTheme, fg: PaletteRole, bg: PaletteRole): {
|
|
20
21
|
color: ColorSpec;
|
|
21
22
|
bgcolor: ColorSpec;
|
|
22
23
|
};
|
package/dist/widgets/ink.js
CHANGED
|
@@ -11,21 +11,18 @@
|
|
|
11
11
|
*
|
|
12
12
|
* [LAW:types-are-the-program] There is no call that takes a foreground alone,
|
|
13
13
|
* so a widget cannot draw half a pair.
|
|
14
|
-
* [LAW:single-enforcer] Every widget resolves palette
|
|
15
|
-
* where
|
|
16
|
-
*
|
|
14
|
+
* [LAW:single-enforcer] Every widget resolves palette roles here, and this is
|
|
15
|
+
* where one that draws no colour (a theme's fully transparent "no background")
|
|
16
|
+
* is reported.
|
|
17
17
|
*/
|
|
18
18
|
import { ColorSpec } from "../core/color.js";
|
|
19
19
|
export function ink(theme, fg, bg) {
|
|
20
20
|
return { color: paletteColor(theme, fg), bgcolor: paletteColor(theme, bg) };
|
|
21
21
|
}
|
|
22
|
-
function paletteColor(theme,
|
|
23
|
-
const rgba = theme.palette.get(
|
|
24
|
-
if (rgba === undefined) {
|
|
25
|
-
throw new RangeError(`palette ${JSON.stringify(theme.palette.name)} has no ${JSON.stringify(key)}`);
|
|
26
|
-
}
|
|
22
|
+
function paletteColor(theme, role) {
|
|
23
|
+
const rgba = theme.palette.get(role);
|
|
27
24
|
if (rgba.alpha === 0) {
|
|
28
|
-
throw new RangeError(`palette ${JSON.stringify(theme.palette.name)}: ${JSON.stringify(
|
|
25
|
+
throw new RangeError(`palette ${JSON.stringify(theme.palette.name)}: ${JSON.stringify(role)} is fully transparent, so it cannot be half of a widget's colour pair`);
|
|
29
26
|
}
|
|
30
27
|
return ColorSpec.fromRgba(rgba);
|
|
31
28
|
}
|
|
@@ -198,7 +198,7 @@ export declare class TextInput extends ThemedWidget {
|
|
|
198
198
|
readonly focusable = true;
|
|
199
199
|
private accessor _value;
|
|
200
200
|
private accessor _cursor;
|
|
201
|
-
private accessor
|
|
201
|
+
private accessor _blink;
|
|
202
202
|
get value(): string;
|
|
203
203
|
set value(v: string);
|
|
204
204
|
get cursorPosition(): CodePoint;
|