@promptctl/rich-js 0.18.0 → 0.19.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 +9 -7
- package/dist/core/anchor.d.ts +45 -0
- package/dist/core/anchor.js +39 -0
- package/dist/core/ansi.d.ts +65 -0
- package/dist/core/ansi.js +231 -0
- package/dist/core/box.d.ts +145 -0
- package/dist/core/box.js +372 -0
- package/dist/core/cells.d.ts +192 -0
- package/dist/core/cells.js +334 -0
- package/dist/core/clock.d.ts +48 -0
- package/dist/core/clock.js +42 -0
- package/dist/core/color.d.ts +326 -0
- package/dist/core/color.js +1225 -0
- package/dist/core/console.d.ts +196 -0
- package/dist/core/console.js +596 -0
- package/dist/core/easing.d.ts +86 -0
- package/dist/core/easing.js +171 -0
- package/dist/core/emoji.d.ts +24 -0
- package/dist/core/emoji.js +391 -0
- package/dist/core/env.d.ts +16 -0
- package/dist/core/env.js +16 -0
- package/dist/core/export-html.d.ts +59 -0
- package/dist/core/export-html.js +197 -0
- package/dist/core/export-lines.d.ts +130 -0
- package/dist/core/export-lines.js +159 -0
- package/dist/core/export-svg.d.ts +49 -0
- package/dist/core/export-svg.js +213 -0
- package/dist/core/fnv1a.d.ts +10 -0
- package/dist/core/fnv1a.js +17 -0
- package/dist/core/highlighter.d.ts +33 -0
- package/dist/core/highlighter.js +190 -0
- package/dist/core/json.d.ts +27 -0
- package/dist/core/json.js +53 -0
- package/dist/core/markup.d.ts +140 -0
- package/dist/core/markup.js +654 -0
- package/dist/core/measure.d.ts +27 -0
- package/dist/core/measure.js +67 -0
- package/dist/core/memo.d.ts +19 -0
- package/dist/core/memo.js +34 -0
- package/dist/core/oklch.d.ts +161 -0
- package/dist/core/oklch.js +312 -0
- package/dist/core/osc8.d.ts +68 -0
- package/dist/core/osc8.js +78 -0
- package/dist/core/paint.d.ts +107 -0
- package/dist/core/paint.js +150 -0
- package/dist/core/place.d.ts +30 -0
- package/dist/core/place.js +49 -0
- package/dist/core/pretty.d.ts +247 -0
- package/dist/core/pretty.js +906 -0
- package/dist/core/protocol.d.ts +305 -0
- package/dist/core/protocol.js +183 -0
- package/dist/core/render.d.ts +87 -0
- package/dist/core/render.js +105 -0
- package/dist/core/segment.d.ts +162 -0
- package/dist/core/segment.js +488 -0
- package/dist/core/spinnerData.d.ts +12 -0
- package/dist/core/spinnerData.js +117 -0
- package/dist/core/strip.d.ts +152 -0
- package/dist/core/strip.js +326 -0
- package/dist/core/style.d.ts +189 -0
- package/dist/core/style.js +758 -0
- package/dist/core/subscription.d.ts +12 -0
- package/dist/core/subscription.js +12 -0
- package/dist/core/text.d.ts +283 -0
- package/dist/core/text.js +1097 -0
- package/dist/core/wrap.d.ts +46 -0
- package/dist/core/wrap.js +140 -0
- package/dist/host/app.d.ts +133 -0
- package/dist/host/app.js +285 -0
- package/dist/host/host-environment.d.ts +26 -0
- package/dist/host/host-environment.js +44 -0
- package/dist/host/index.d.ts +6 -0
- package/dist/host/index.js +3 -0
- package/dist/host/terminal-host.d.ts +180 -0
- package/dist/host/terminal-host.js +186 -0
- package/dist/index.d.ts +98 -0
- package/dist/index.js +114 -0
- package/dist/node/prompt.d.ts +34 -0
- package/dist/node/prompt.js +51 -0
- package/dist/node/save.d.ts +18 -0
- package/dist/node/save.js +24 -0
- package/dist/node/terminal-host.d.ts +114 -0
- package/dist/node/terminal-host.js +227 -0
- package/dist/node/traceback.d.ts +38 -0
- package/dist/node/traceback.js +98 -0
- package/dist/renderables/align.d.ts +16 -0
- package/dist/renderables/align.js +26 -0
- package/dist/renderables/columns.d.ts +77 -0
- package/dist/renderables/columns.js +191 -0
- package/dist/renderables/constrain.d.ts +15 -0
- package/dist/renderables/constrain.js +31 -0
- package/dist/renderables/effect.d.ts +98 -0
- package/dist/renderables/effect.js +160 -0
- package/dist/renderables/embed.d.ts +107 -0
- package/dist/renderables/embed.js +160 -0
- package/dist/renderables/flexStrip.d.ts +41 -0
- package/dist/renderables/flexStrip.js +200 -0
- package/dist/renderables/group.d.ts +14 -0
- package/dist/renderables/group.js +22 -0
- package/dist/renderables/layout.d.ts +75 -0
- package/dist/renderables/layout.js +223 -0
- package/dist/renderables/live.d.ts +74 -0
- package/dist/renderables/live.js +188 -0
- package/dist/renderables/markdown.d.ts +38 -0
- package/dist/renderables/markdown.js +587 -0
- package/dist/renderables/padding.d.ts +59 -0
- package/dist/renderables/padding.js +147 -0
- package/dist/renderables/panel.d.ts +114 -0
- package/dist/renderables/panel.js +303 -0
- package/dist/renderables/progress.d.ts +178 -0
- package/dist/renderables/progress.js +362 -0
- package/dist/renderables/progressBar.d.ts +31 -0
- package/dist/renderables/progressBar.js +64 -0
- package/dist/renderables/prompt.d.ts +71 -0
- package/dist/renderables/prompt.js +165 -0
- package/dist/renderables/ratio.d.ts +123 -0
- package/dist/renderables/ratio.js +213 -0
- package/dist/renderables/rule.d.ts +26 -0
- package/dist/renderables/rule.js +86 -0
- package/dist/renderables/spinner.d.ts +57 -0
- package/dist/renderables/spinner.js +103 -0
- package/dist/renderables/status.d.ts +29 -0
- package/dist/renderables/status.js +46 -0
- package/dist/renderables/syntax.d.ts +65 -0
- package/dist/renderables/syntax.js +166 -0
- package/dist/renderables/table.d.ts +232 -0
- package/dist/renderables/table.js +973 -0
- package/dist/renderables/traceback.d.ts +32 -0
- package/dist/renderables/traceback.js +279 -0
- package/dist/renderables/tree.d.ts +76 -0
- package/dist/renderables/tree.js +177 -0
- package/dist/renderables/viewport.d.ts +114 -0
- package/dist/renderables/viewport.js +196 -0
- package/dist/template-bindings/color-funcs.d.ts +109 -0
- package/dist/template-bindings/color-funcs.js +243 -0
- package/dist/template-bindings/helpers.d.ts +26 -0
- package/dist/template-bindings/helpers.js +33 -0
- package/dist/template-bindings/index.d.ts +119 -0
- package/dist/template-bindings/index.js +162 -0
- package/dist/template-bindings/palette-funcs.d.ts +96 -0
- package/dist/template-bindings/palette-funcs.js +145 -0
- package/dist/template-bindings/style-funcs.d.ts +28 -0
- package/dist/template-bindings/style-funcs.js +157 -0
- package/dist/themes/buildPalette.d.ts +57 -0
- package/dist/themes/buildPalette.js +100 -0
- package/dist/themes/colorMath.d.ts +94 -0
- package/dist/themes/colorMath.js +280 -0
- package/dist/themes/colorRef.d.ts +36 -0
- package/dist/themes/colorRef.js +78 -0
- package/dist/themes/data/ansi-tables.d.ts +14 -0
- package/dist/themes/data/ansi-tables.js +49 -0
- package/dist/themes/data/atom-one-dark.d.ts +3 -0
- package/dist/themes/data/atom-one-dark.js +177 -0
- package/dist/themes/data/atom-one-light.d.ts +3 -0
- package/dist/themes/data/atom-one-light.js +177 -0
- package/dist/themes/data/catppuccin-frappe.d.ts +3 -0
- package/dist/themes/data/catppuccin-frappe.js +177 -0
- package/dist/themes/data/catppuccin-latte.d.ts +3 -0
- package/dist/themes/data/catppuccin-latte.js +177 -0
- package/dist/themes/data/catppuccin-macchiato.d.ts +3 -0
- package/dist/themes/data/catppuccin-macchiato.js +177 -0
- package/dist/themes/data/catppuccin-mocha.d.ts +3 -0
- package/dist/themes/data/catppuccin-mocha.js +177 -0
- package/dist/themes/data/cyberpunk.d.ts +17 -0
- package/dist/themes/data/cyberpunk.js +193 -0
- package/dist/themes/data/default.d.ts +3 -0
- package/dist/themes/data/default.js +160 -0
- package/dist/themes/data/dracula.d.ts +3 -0
- package/dist/themes/data/dracula.js +177 -0
- package/dist/themes/data/flexoki.d.ts +3 -0
- package/dist/themes/data/flexoki.js +177 -0
- package/dist/themes/data/gruvbox.d.ts +3 -0
- package/dist/themes/data/gruvbox.js +177 -0
- package/dist/themes/data/index.d.ts +35 -0
- package/dist/themes/data/index.js +64 -0
- package/dist/themes/data/monokai.d.ts +3 -0
- package/dist/themes/data/monokai.js +177 -0
- package/dist/themes/data/nord.d.ts +3 -0
- package/dist/themes/data/nord.js +177 -0
- package/dist/themes/data/rose-pine-dawn.d.ts +3 -0
- package/dist/themes/data/rose-pine-dawn.js +177 -0
- package/dist/themes/data/rose-pine-moon.d.ts +3 -0
- package/dist/themes/data/rose-pine-moon.js +177 -0
- package/dist/themes/data/rose-pine.d.ts +3 -0
- package/dist/themes/data/rose-pine.js +177 -0
- package/dist/themes/data/solarized-dark.d.ts +3 -0
- package/dist/themes/data/solarized-dark.js +177 -0
- package/dist/themes/data/solarized-light.d.ts +3 -0
- package/dist/themes/data/solarized-light.js +177 -0
- package/dist/themes/data/svg-export.d.ts +3 -0
- package/dist/themes/data/svg-export.js +177 -0
- package/dist/themes/data/textual-ansi.d.ts +3 -0
- package/dist/themes/data/textual-ansi.js +160 -0
- package/dist/themes/data/textual-dark.d.ts +3 -0
- package/dist/themes/data/textual-dark.js +160 -0
- package/dist/themes/data/textual-light.d.ts +3 -0
- package/dist/themes/data/textual-light.js +160 -0
- package/dist/themes/data/tokyo-night.d.ts +3 -0
- package/dist/themes/data/tokyo-night.js +177 -0
- package/dist/themes/data/types.d.ts +31 -0
- package/dist/themes/data/types.js +10 -0
- package/dist/themes/palette.d.ts +45 -0
- package/dist/themes/palette.js +71 -0
- package/dist/themes/ramp.d.ts +70 -0
- package/dist/themes/ramp.js +103 -0
- package/dist/themes/registry.d.ts +44 -0
- package/dist/themes/registry.js +105 -0
- package/dist/themes/terminalThemes.d.ts +49 -0
- package/dist/themes/terminalThemes.js +63 -0
- package/dist/themes/transpose.d.ts +87 -0
- package/dist/themes/transpose.js +138 -0
- package/dist/widgets/button.d.ts +45 -0
- package/dist/widgets/button.js +177 -0
- package/dist/widgets/checkbox.d.ts +38 -0
- package/dist/widgets/checkbox.js +135 -0
- package/dist/widgets/dropdown.d.ts +64 -0
- package/dist/widgets/dropdown.js +416 -0
- package/dist/widgets/event-router.d.ts +71 -0
- package/dist/widgets/event-router.js +629 -0
- package/dist/widgets/focus-manager.d.ts +45 -0
- package/dist/widgets/focus-manager.js +191 -0
- package/dist/widgets/hit.d.ts +64 -0
- package/dist/widgets/hit.js +113 -0
- package/dist/widgets/index.d.ts +20 -0
- package/dist/widgets/index.js +14 -0
- package/dist/widgets/ink.d.ts +22 -0
- package/dist/widgets/ink.js +31 -0
- package/dist/widgets/slider.d.ts +54 -0
- package/dist/widgets/slider.js +247 -0
- package/dist/widgets/static-item.d.ts +34 -0
- package/dist/widgets/static-item.js +54 -0
- package/dist/widgets/text-input.d.ts +283 -0
- package/dist/widgets/text-input.js +1174 -0
- package/dist/widgets/themed-widget.d.ts +20 -0
- package/dist/widgets/themed-widget.js +89 -0
- package/dist/widgets/toggle.d.ts +41 -0
- package/dist/widgets/toggle.js +157 -0
- package/dist/widgets/types.d.ts +87 -0
- package/dist/widgets/types.js +30 -0
- package/dist/widgets/widget-app.d.ts +65 -0
- package/dist/widgets/widget-app.js +206 -0
- package/dist/widgets/widget-base.d.ts +42 -0
- package/dist/widgets/widget-base.js +172 -0
- package/package.json +16 -2
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
const theme = {
|
|
2
|
+
name: "tokyo-night",
|
|
3
|
+
dark: true,
|
|
4
|
+
// iTerm2-Color-Schemes "TokyoNight Night"
|
|
5
|
+
ansi: {
|
|
6
|
+
black: "#15161E",
|
|
7
|
+
red: "#F7768E",
|
|
8
|
+
green: "#9ECE6A",
|
|
9
|
+
yellow: "#E0AF68",
|
|
10
|
+
blue: "#7AA2F7",
|
|
11
|
+
magenta: "#BB9AF7",
|
|
12
|
+
cyan: "#7DCFFF",
|
|
13
|
+
white: "#A9B1D6",
|
|
14
|
+
brightBlack: "#414868",
|
|
15
|
+
brightRed: "#F7768E",
|
|
16
|
+
brightGreen: "#9ECE6A",
|
|
17
|
+
brightYellow: "#E0AF68",
|
|
18
|
+
brightBlue: "#7AA2F7",
|
|
19
|
+
brightMagenta: "#BB9AF7",
|
|
20
|
+
brightCyan: "#7DCFFF",
|
|
21
|
+
brightWhite: "#C0CAF5",
|
|
22
|
+
},
|
|
23
|
+
vars: {
|
|
24
|
+
"accent": "#FE9E64",
|
|
25
|
+
"accent-darken-1": "#E78A51",
|
|
26
|
+
"accent-darken-2": "#D0763E",
|
|
27
|
+
"accent-darken-3": "#BA632C",
|
|
28
|
+
"accent-lighten-1": "#FFB277",
|
|
29
|
+
"accent-lighten-2": "#FFC78A",
|
|
30
|
+
"accent-lighten-3": "#FFDC9E",
|
|
31
|
+
"accent-muted": "#5E4238",
|
|
32
|
+
"background": "#1A1B26",
|
|
33
|
+
"background-darken-1": "#070817",
|
|
34
|
+
"background-darken-2": "#000000",
|
|
35
|
+
"background-darken-3": "#000000",
|
|
36
|
+
"background-lighten-1": "#292A36",
|
|
37
|
+
"background-lighten-2": "#3A3A47",
|
|
38
|
+
"background-lighten-3": "#4B4B58",
|
|
39
|
+
"block-cursor-background": "#BB9AF7",
|
|
40
|
+
"block-cursor-blurred-background": "#BB9AF74C",
|
|
41
|
+
"block-cursor-blurred-foreground": "#A9B1D6",
|
|
42
|
+
"block-cursor-foreground": "#FFFFFFDD",
|
|
43
|
+
"block-hover-background": "#FFFFFF19",
|
|
44
|
+
"boost": "#FFFFFF0A",
|
|
45
|
+
"boost-darken-1": "#E9E9E90A",
|
|
46
|
+
"boost-darken-2": "#D4D4D40A",
|
|
47
|
+
"boost-darken-3": "#BFBFBF0A",
|
|
48
|
+
"boost-lighten-1": "#FFFFFF0A",
|
|
49
|
+
"boost-lighten-2": "#FFFFFF0A",
|
|
50
|
+
"boost-lighten-3": "#FFFFFF0A",
|
|
51
|
+
"border": "#BB9AF7",
|
|
52
|
+
"border-blurred": "#1E2235",
|
|
53
|
+
"button-color-foreground": "#24283B",
|
|
54
|
+
"button-foreground": "#A9B1D6",
|
|
55
|
+
"error": "#F6768E",
|
|
56
|
+
"error-darken-1": "#E0617A",
|
|
57
|
+
"error-darken-2": "#C94D68",
|
|
58
|
+
"error-darken-3": "#B33856",
|
|
59
|
+
"error-lighten-1": "#FF8AA1",
|
|
60
|
+
"error-lighten-2": "#FF9FB5",
|
|
61
|
+
"error-lighten-3": "#FFB4CA",
|
|
62
|
+
"error-muted": "#5C3645",
|
|
63
|
+
"footer-background": "#414868",
|
|
64
|
+
"footer-description-background": "#00000000",
|
|
65
|
+
"footer-description-foreground": "#A9B1D6",
|
|
66
|
+
"footer-foreground": "#A9B1D6",
|
|
67
|
+
"footer-item-background": "#00000000",
|
|
68
|
+
"footer-key-background": "#00000000",
|
|
69
|
+
"footer-key-foreground": "#FF9E64",
|
|
70
|
+
"foreground": "#A9B1D6",
|
|
71
|
+
"foreground-darken-1": "#949CC1",
|
|
72
|
+
"foreground-darken-2": "#8189AC",
|
|
73
|
+
"foreground-darken-3": "#6D7698",
|
|
74
|
+
"foreground-disabled": "#A9B1D660",
|
|
75
|
+
"foreground-lighten-1": "#BDC5EB",
|
|
76
|
+
"foreground-lighten-2": "#D2DAFF",
|
|
77
|
+
"foreground-lighten-3": "#E7EFFF",
|
|
78
|
+
"foreground-muted": "#A9B1D699",
|
|
79
|
+
"input-cursor-background": "#A9B1D6",
|
|
80
|
+
"input-cursor-foreground": "#1A1B26",
|
|
81
|
+
"input-selection-background": "#D0AEFF66",
|
|
82
|
+
"link-background": "#00000000",
|
|
83
|
+
"link-background-hover": "#BB9AF7",
|
|
84
|
+
"link-color": "#FFFFFFDD",
|
|
85
|
+
"link-color-hover": "#FFFFFFDD",
|
|
86
|
+
"markdown-h1-background": "#00000000",
|
|
87
|
+
"markdown-h1-color": "#BB9AF7",
|
|
88
|
+
"markdown-h2-background": "#00000000",
|
|
89
|
+
"markdown-h2-color": "#BB9AF7",
|
|
90
|
+
"markdown-h3-background": "#00000000",
|
|
91
|
+
"markdown-h3-color": "#BB9AF7",
|
|
92
|
+
"markdown-h4-background": "#00000000",
|
|
93
|
+
"markdown-h4-color": "#A9B1D6",
|
|
94
|
+
"markdown-h5-background": "#00000000",
|
|
95
|
+
"markdown-h5-color": "#A9B1D6",
|
|
96
|
+
"markdown-h6-background": "#00000000",
|
|
97
|
+
"markdown-h6-color": "#A9B1D699",
|
|
98
|
+
"panel": "#414868",
|
|
99
|
+
"panel-darken-1": "#2F3755",
|
|
100
|
+
"panel-darken-2": "#1E2744",
|
|
101
|
+
"panel-darken-3": "#0C1733",
|
|
102
|
+
"panel-lighten-1": "#53597A",
|
|
103
|
+
"panel-lighten-2": "#656B8E",
|
|
104
|
+
"panel-lighten-3": "#787EA1",
|
|
105
|
+
"primary": "#BB9AF7",
|
|
106
|
+
"primary-background": "#504D60",
|
|
107
|
+
"primary-background-darken-1": "#413D52",
|
|
108
|
+
"primary-background-darken-2": "#322E45",
|
|
109
|
+
"primary-background-darken-3": "#322E45",
|
|
110
|
+
"primary-background-lighten-1": "#605D6E",
|
|
111
|
+
"primary-background-lighten-2": "#6F6C7C",
|
|
112
|
+
"primary-background-lighten-3": "#7E7C8A",
|
|
113
|
+
"primary-darken-1": "#A686E1",
|
|
114
|
+
"primary-darken-2": "#9173CC",
|
|
115
|
+
"primary-darken-3": "#7D60B7",
|
|
116
|
+
"primary-lighten-1": "#D0AEFF",
|
|
117
|
+
"primary-lighten-2": "#E5C2FF",
|
|
118
|
+
"primary-lighten-3": "#FBD7FF",
|
|
119
|
+
"primary-muted": "#4A4164",
|
|
120
|
+
"scrollbar": "#4F4270",
|
|
121
|
+
"scrollbar-active": "#BB9AF7",
|
|
122
|
+
"scrollbar-background": "#070817",
|
|
123
|
+
"scrollbar-background-active": "#070817",
|
|
124
|
+
"scrollbar-background-hover": "#070817",
|
|
125
|
+
"scrollbar-corner-color": "#070817",
|
|
126
|
+
"scrollbar-hover": "#615187",
|
|
127
|
+
"secondary": "#7AA2F7",
|
|
128
|
+
"secondary-background": "#484E60",
|
|
129
|
+
"secondary-background-darken-1": "#383E52",
|
|
130
|
+
"secondary-background-darken-2": "#282F45",
|
|
131
|
+
"secondary-background-darken-3": "#282F45",
|
|
132
|
+
"secondary-background-lighten-1": "#585D6E",
|
|
133
|
+
"secondary-background-lighten-2": "#686D7C",
|
|
134
|
+
"secondary-background-lighten-3": "#787D8A",
|
|
135
|
+
"secondary-darken-1": "#648EE1",
|
|
136
|
+
"secondary-darken-2": "#4D7BCC",
|
|
137
|
+
"secondary-darken-3": "#3468B7",
|
|
138
|
+
"secondary-lighten-1": "#8FB6FF",
|
|
139
|
+
"secondary-lighten-2": "#A5CAFF",
|
|
140
|
+
"secondary-lighten-3": "#BBDFFF",
|
|
141
|
+
"secondary-muted": "#364364",
|
|
142
|
+
"success": "#9ECE6A",
|
|
143
|
+
"success-darken-1": "#89B956",
|
|
144
|
+
"success-darken-2": "#75A443",
|
|
145
|
+
"success-darken-3": "#619030",
|
|
146
|
+
"success-lighten-1": "#B2E37D",
|
|
147
|
+
"success-lighten-2": "#C8F891",
|
|
148
|
+
"success-lighten-3": "#DDFFA6",
|
|
149
|
+
"success-muted": "#41503A",
|
|
150
|
+
"surface": "#24283B",
|
|
151
|
+
"surface-active": "#313448",
|
|
152
|
+
"surface-darken-1": "#14182A",
|
|
153
|
+
"surface-darken-2": "#00031B",
|
|
154
|
+
"surface-darken-3": "#000009",
|
|
155
|
+
"surface-lighten-1": "#34384C",
|
|
156
|
+
"surface-lighten-2": "#45495E",
|
|
157
|
+
"surface-lighten-3": "#575A70",
|
|
158
|
+
"text": "#FFFFFFDD",
|
|
159
|
+
"text-accent": "#FFBE98",
|
|
160
|
+
"text-disabled": "#FFFFFF60",
|
|
161
|
+
"text-error": "#F9A4B4",
|
|
162
|
+
"text-muted": "#FFFFFF99",
|
|
163
|
+
"text-primary": "#D2BCF9",
|
|
164
|
+
"text-secondary": "#A7C1F9",
|
|
165
|
+
"text-success": "#BEDE9C",
|
|
166
|
+
"text-warning": "#EACA9B",
|
|
167
|
+
"warning": "#DFAF68",
|
|
168
|
+
"warning-darken-1": "#C99A55",
|
|
169
|
+
"warning-darken-2": "#B48742",
|
|
170
|
+
"warning-darken-3": "#9E7430",
|
|
171
|
+
"warning-lighten-1": "#F6C37B",
|
|
172
|
+
"warning-lighten-2": "#FFD88F",
|
|
173
|
+
"warning-lighten-3": "#FFEDA3",
|
|
174
|
+
"warning-muted": "#554739",
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
export default theme;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static shape of a theme palette as authored. Each `data/<name>.ts` file
|
|
3
|
+
* exports one of these as its default export. The barrel (`./index.ts`)
|
|
4
|
+
* collects them into a single typed map; the registry consumes that map.
|
|
5
|
+
*
|
|
6
|
+
* Distinct from `Palette` — this is the on-disk authoring format (hex
|
|
7
|
+
* strings); `Palette` is the runtime form (parsed ColorRgba values). The
|
|
8
|
+
* registry's `getThemePalette` is the single boundary that hydrates one
|
|
9
|
+
* into the other.
|
|
10
|
+
*/
|
|
11
|
+
export interface ThemePaletteData {
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly dark: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* The sixteen colours a terminal showing this theme draws `red`, `blue`,
|
|
16
|
+
* `bright_black` and the rest in. A theme without its own table would draw
|
|
17
|
+
* them in the VGA defaults (`blue` as #000080), which belong to no theme.
|
|
18
|
+
*/
|
|
19
|
+
readonly ansi: AnsiColorsData;
|
|
20
|
+
readonly vars: Readonly<Record<string, string>>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* ANSI colour numbers 0–15 in order: the eight normal colours, then their
|
|
24
|
+
* bright forms. Named rather than positional so a data file cannot shift a
|
|
25
|
+
* colour into its neighbour's slot by miscounting.
|
|
26
|
+
*/
|
|
27
|
+
export declare const ANSI_SLOTS: readonly ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "brightBlack", "brightRed", "brightGreen", "brightYellow", "brightBlue", "brightMagenta", "brightCyan", "brightWhite"];
|
|
28
|
+
/** One `#RRGGBB` per ANSI colour number, keyed by `ANSI_SLOTS`. */
|
|
29
|
+
export type AnsiColorsData = {
|
|
30
|
+
readonly [K in (typeof ANSI_SLOTS)[number]]: string;
|
|
31
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ANSI colour numbers 0–15 in order: the eight normal colours, then their
|
|
3
|
+
* bright forms. Named rather than positional so a data file cannot shift a
|
|
4
|
+
* colour into its neighbour's slot by miscounting.
|
|
5
|
+
*/
|
|
6
|
+
export const ANSI_SLOTS = [
|
|
7
|
+
"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white",
|
|
8
|
+
"brightBlack", "brightRed", "brightGreen", "brightYellow",
|
|
9
|
+
"brightBlue", "brightMagenta", "brightCyan", "brightWhite",
|
|
10
|
+
];
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ColorRgba } from "../core/color.js";
|
|
2
|
+
/**
|
|
3
|
+
* A semantic palette: a named map from variable name → ColorRgba.
|
|
4
|
+
*
|
|
5
|
+
* Distinct from `ColorTable` (the integer-indexed quantization LUT used by
|
|
6
|
+
* the downgrade pipeline). Palettes carry aesthetic intent — `primary`,
|
|
7
|
+
* `accent`, `error`, etc. — and are the foundation of the theming system.
|
|
8
|
+
*
|
|
9
|
+
* Storage is uniformly ColorRgba; consumers that load from hex JSON
|
|
10
|
+
* parse to ColorRgba at load time. `get` is a bare lookup — turning an
|
|
11
|
+
* author-written *reference* (a name, or a `#RRGGBB` literal) into a colour
|
|
12
|
+
* is `resolveColorRef`'s job in `colorRef.ts`, so a Palette never has to
|
|
13
|
+
* know about the syntax callers write.
|
|
14
|
+
*
|
|
15
|
+
* Every colour a Palette hands out is opaque or fully transparent. A theme's translucent variable
|
|
16
|
+
* (Textual's `boost`, a hover overlay) is a tint meant for that theme's own
|
|
17
|
+
* background, and a colour leaving the palette no longer knows which
|
|
18
|
+
* background that was: the SGR writer would composite it over the terminal's
|
|
19
|
+
* black, which is not the theme's background, and draw a tint the theme never
|
|
20
|
+
* meant.
|
|
21
|
+
* So it is drawn onto `background` here, once, and the writer, the exporters
|
|
22
|
+
* and the contrast choosers all read the colour it has there. On any other
|
|
23
|
+
* surface it keeps that colour: the tint does not follow what is under it.
|
|
24
|
+
* The exception is a fully transparent colour, Textual's "no background": it
|
|
25
|
+
* draws nothing on any surface, so it needs none and is handed out as it is,
|
|
26
|
+
* and a `Style` reads it as no background at all.
|
|
27
|
+
*
|
|
28
|
+
* @throws RangeError when `background` is translucent, or when a colour is
|
|
29
|
+
* partly transparent and there is no `background` to draw it on.
|
|
30
|
+
*/
|
|
31
|
+
export declare class Palette {
|
|
32
|
+
readonly name: string;
|
|
33
|
+
readonly dark: boolean;
|
|
34
|
+
readonly vars: ReadonlyMap<string, ColorRgba>;
|
|
35
|
+
constructor(name: string, dark: boolean, vars: ReadonlyMap<string, ColorRgba>);
|
|
36
|
+
get(key: string): ColorRgba | undefined;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A palette colour as it is drawn: composited onto the palette's own
|
|
40
|
+
* `background`, which has nothing under it and so must itself be opaque.
|
|
41
|
+
* [LAW:one-source-of-truth] The one statement of what a translucent palette
|
|
42
|
+
* colour means; `buildPalette` draws its base colours through it before
|
|
43
|
+
* deriving from them.
|
|
44
|
+
*/
|
|
45
|
+
export declare function drawnOn(name: string, background: ColorRgba): (colour: ColorRgba) => ColorRgba;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A semantic palette: a named map from variable name → ColorRgba.
|
|
3
|
+
*
|
|
4
|
+
* Distinct from `ColorTable` (the integer-indexed quantization LUT used by
|
|
5
|
+
* the downgrade pipeline). Palettes carry aesthetic intent — `primary`,
|
|
6
|
+
* `accent`, `error`, etc. — and are the foundation of the theming system.
|
|
7
|
+
*
|
|
8
|
+
* Storage is uniformly ColorRgba; consumers that load from hex JSON
|
|
9
|
+
* parse to ColorRgba at load time. `get` is a bare lookup — turning an
|
|
10
|
+
* author-written *reference* (a name, or a `#RRGGBB` literal) into a colour
|
|
11
|
+
* is `resolveColorRef`'s job in `colorRef.ts`, so a Palette never has to
|
|
12
|
+
* know about the syntax callers write.
|
|
13
|
+
*
|
|
14
|
+
* Every colour a Palette hands out is opaque or fully transparent. A theme's translucent variable
|
|
15
|
+
* (Textual's `boost`, a hover overlay) is a tint meant for that theme's own
|
|
16
|
+
* background, and a colour leaving the palette no longer knows which
|
|
17
|
+
* background that was: the SGR writer would composite it over the terminal's
|
|
18
|
+
* black, which is not the theme's background, and draw a tint the theme never
|
|
19
|
+
* meant.
|
|
20
|
+
* So it is drawn onto `background` here, once, and the writer, the exporters
|
|
21
|
+
* and the contrast choosers all read the colour it has there. On any other
|
|
22
|
+
* surface it keeps that colour: the tint does not follow what is under it.
|
|
23
|
+
* The exception is a fully transparent colour, Textual's "no background": it
|
|
24
|
+
* draws nothing on any surface, so it needs none and is handed out as it is,
|
|
25
|
+
* and a `Style` reads it as no background at all.
|
|
26
|
+
*
|
|
27
|
+
* @throws RangeError when `background` is translucent, or when a colour is
|
|
28
|
+
* partly transparent and there is no `background` to draw it on.
|
|
29
|
+
*/
|
|
30
|
+
export class Palette {
|
|
31
|
+
name;
|
|
32
|
+
dark;
|
|
33
|
+
vars;
|
|
34
|
+
constructor(name, dark, vars) {
|
|
35
|
+
this.name = name;
|
|
36
|
+
this.dark = dark;
|
|
37
|
+
// [LAW:single-enforcer] Every palette is built through here, so this is
|
|
38
|
+
// where "a palette colour is opaque or draws nothing" holds. The fresh map is also the
|
|
39
|
+
// defensive copy: ReadonlyMap is a compile-time aliasing constraint, not a
|
|
40
|
+
// runtime one.
|
|
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)]));
|
|
44
|
+
}
|
|
45
|
+
get(key) {
|
|
46
|
+
return this.vars.get(key);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A palette colour as it is drawn: composited onto the palette's own
|
|
51
|
+
* `background`, which has nothing under it and so must itself be opaque.
|
|
52
|
+
* [LAW:one-source-of-truth] The one statement of what a translucent palette
|
|
53
|
+
* colour means; `buildPalette` draws its base colours through it before
|
|
54
|
+
* deriving from them.
|
|
55
|
+
*/
|
|
56
|
+
export function drawnOn(name, background) {
|
|
57
|
+
if (background.alpha !== 1) {
|
|
58
|
+
throw new RangeError(`palette ${JSON.stringify(name)}: background is the surface its translucent colours are drawn on, so it must be opaque; got ${background.hex}`);
|
|
59
|
+
}
|
|
60
|
+
// A fully transparent colour is not a tint: it draws nothing on any surface.
|
|
61
|
+
return (colour) => (colour.alpha === 0 ? colour : colour.compositeOver(background));
|
|
62
|
+
}
|
|
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
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A color ramp: a number mapped onto a color through ordered stops.
|
|
3
|
+
*
|
|
4
|
+
* "What does 73 % spent look like" has no answer in a vocabulary of discrete
|
|
5
|
+
* adjustments (`darken`, `mix`, `contrastOn`): each takes colors and returns a
|
|
6
|
+
* color, and none takes a *measurement*. Without a ramp the answer gets
|
|
7
|
+
* computed outside the theme system — a script emits a hex, a template
|
|
8
|
+
* branches `if ge .pct 80 … else if ge .pct 50 …` — and that color decision
|
|
9
|
+
* can no longer transpose with the palette it was meant to belong to. A ramp
|
|
10
|
+
* is the one function whose input is a number, so the decision stays inside.
|
|
11
|
+
*
|
|
12
|
+
* A threshold cascade is a ramp too: the same stops with the `step` ease hold
|
|
13
|
+
* each color until the next position, which is exactly `≥ threshold → hotter`
|
|
14
|
+
* written as data. [LAW:one-type-per-behavior] One primitive; the easing is a
|
|
15
|
+
* value — any `Ease` from `core/easing`, the vocabulary every effect shares —
|
|
16
|
+
* so a gradient and a cascade differ by one word, not by which function was
|
|
17
|
+
* called. [LAW:dataflow-not-control-flow] `at` applies it unconditionally.
|
|
18
|
+
*
|
|
19
|
+
* Interpolation is in OKLCH (`Oklch.mix`), so a `linear` ramp between two
|
|
20
|
+
* theme colors passes through perceptually even steps rather than the muddy
|
|
21
|
+
* midpoints of an sRGB blend.
|
|
22
|
+
*
|
|
23
|
+
* [LAW:one-way-deps] Imports `core/color`, `core/easing` and `core/oklch`
|
|
24
|
+
* only; nothing here knows what a palette is. Resolving stop *names* is the template binding's
|
|
25
|
+
* job (`paletteFuncs`), which hands this module resolved colors.
|
|
26
|
+
*/
|
|
27
|
+
import type { ColorRgba } from "../core/color.js";
|
|
28
|
+
import type { Ease } from "../core/easing.js";
|
|
29
|
+
/** One stop: the color the ramp is exactly `color` at position `at`. */
|
|
30
|
+
export interface ColorStop {
|
|
31
|
+
readonly at: number;
|
|
32
|
+
readonly color: ColorRgba;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* An immutable ramp over stops sorted by position.
|
|
36
|
+
*
|
|
37
|
+
* [LAW:single-enforcer] The constructor is the one place a ramp's shape is
|
|
38
|
+
* checked — at least one stop, every position finite, positions
|
|
39
|
+
* non-decreasing — matching the `ColorRgba`/`Oklch` pattern. Positions are
|
|
40
|
+
* required to arrive in order rather than being sorted here: a ramp whose
|
|
41
|
+
* stops are read from configuration (`warning at 80, error at 50`) is an
|
|
42
|
+
* authoring mistake, and sorting would quietly render a different ramp than
|
|
43
|
+
* the one written. [LAW:no-silent-failure]
|
|
44
|
+
*
|
|
45
|
+
* Two stops may share a position: that is a hard edge, the later color
|
|
46
|
+
* taking over at exactly that value (CSS gradients spell a hard stop the
|
|
47
|
+
* same way).
|
|
48
|
+
*/
|
|
49
|
+
export declare class ColorRamp {
|
|
50
|
+
readonly ease: Ease;
|
|
51
|
+
readonly stops: readonly ColorStop[];
|
|
52
|
+
constructor(ease: Ease, stops: readonly ColorStop[]);
|
|
53
|
+
/**
|
|
54
|
+
* The color at `value`. Below the first stop it is the first color; at or
|
|
55
|
+
* above the last stop it is the last; between two stops the raw progress
|
|
56
|
+
* from the lower to the upper goes through `ease`, and the eased progress
|
|
57
|
+
* says how far to mix.
|
|
58
|
+
*
|
|
59
|
+
* Eased progress 0 is the lower stop's color and 1 the upper's, byte for
|
|
60
|
+
* byte — the exactness contract, not a shortcut: the sRGB → OKLCH → sRGB
|
|
61
|
+
* round-trip can land a channel one unit off, and a ramp that did not hit
|
|
62
|
+
* its own stops exactly would make a `step` ramp paint a color the author
|
|
63
|
+
* never wrote. So a value on a stop is that stop's color whenever the ease
|
|
64
|
+
* starts at 0, as every built-in does but `step-start` and the
|
|
65
|
+
* `jump-start`/`jump-both` steps, which jump at the start of the interval as
|
|
66
|
+
* CSS defines them. An ease that overshoots [0, 1] holds the end colors
|
|
67
|
+
* where it does: a ramp never paints outside its stops.
|
|
68
|
+
*/
|
|
69
|
+
at(value: number): ColorRgba;
|
|
70
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A color ramp: a number mapped onto a color through ordered stops.
|
|
3
|
+
*
|
|
4
|
+
* "What does 73 % spent look like" has no answer in a vocabulary of discrete
|
|
5
|
+
* adjustments (`darken`, `mix`, `contrastOn`): each takes colors and returns a
|
|
6
|
+
* color, and none takes a *measurement*. Without a ramp the answer gets
|
|
7
|
+
* computed outside the theme system — a script emits a hex, a template
|
|
8
|
+
* branches `if ge .pct 80 … else if ge .pct 50 …` — and that color decision
|
|
9
|
+
* can no longer transpose with the palette it was meant to belong to. A ramp
|
|
10
|
+
* is the one function whose input is a number, so the decision stays inside.
|
|
11
|
+
*
|
|
12
|
+
* A threshold cascade is a ramp too: the same stops with the `step` ease hold
|
|
13
|
+
* each color until the next position, which is exactly `≥ threshold → hotter`
|
|
14
|
+
* written as data. [LAW:one-type-per-behavior] One primitive; the easing is a
|
|
15
|
+
* value — any `Ease` from `core/easing`, the vocabulary every effect shares —
|
|
16
|
+
* so a gradient and a cascade differ by one word, not by which function was
|
|
17
|
+
* called. [LAW:dataflow-not-control-flow] `at` applies it unconditionally.
|
|
18
|
+
*
|
|
19
|
+
* Interpolation is in OKLCH (`Oklch.mix`), so a `linear` ramp between two
|
|
20
|
+
* theme colors passes through perceptually even steps rather than the muddy
|
|
21
|
+
* midpoints of an sRGB blend.
|
|
22
|
+
*
|
|
23
|
+
* [LAW:one-way-deps] Imports `core/color`, `core/easing` and `core/oklch`
|
|
24
|
+
* only; nothing here knows what a palette is. Resolving stop *names* is the template binding's
|
|
25
|
+
* job (`paletteFuncs`), which hands this module resolved colors.
|
|
26
|
+
*/
|
|
27
|
+
import { Oklch } from "../core/oklch.js";
|
|
28
|
+
/**
|
|
29
|
+
* An immutable ramp over stops sorted by position.
|
|
30
|
+
*
|
|
31
|
+
* [LAW:single-enforcer] The constructor is the one place a ramp's shape is
|
|
32
|
+
* checked — at least one stop, every position finite, positions
|
|
33
|
+
* non-decreasing — matching the `ColorRgba`/`Oklch` pattern. Positions are
|
|
34
|
+
* required to arrive in order rather than being sorted here: a ramp whose
|
|
35
|
+
* stops are read from configuration (`warning at 80, error at 50`) is an
|
|
36
|
+
* authoring mistake, and sorting would quietly render a different ramp than
|
|
37
|
+
* the one written. [LAW:no-silent-failure]
|
|
38
|
+
*
|
|
39
|
+
* Two stops may share a position: that is a hard edge, the later color
|
|
40
|
+
* taking over at exactly that value (CSS gradients spell a hard stop the
|
|
41
|
+
* same way).
|
|
42
|
+
*/
|
|
43
|
+
export class ColorRamp {
|
|
44
|
+
ease;
|
|
45
|
+
stops;
|
|
46
|
+
constructor(ease, stops) {
|
|
47
|
+
this.ease = ease;
|
|
48
|
+
this.stops = stops;
|
|
49
|
+
if (stops.length === 0) {
|
|
50
|
+
throw new RangeError("a ColorRamp needs at least one stop");
|
|
51
|
+
}
|
|
52
|
+
for (const [i, stop] of stops.entries()) {
|
|
53
|
+
if (!Number.isFinite(stop.at)) {
|
|
54
|
+
throw new RangeError(`ColorRamp stop ${i} has a non-finite position ${stop.at}`);
|
|
55
|
+
}
|
|
56
|
+
const prev = stops[i - 1];
|
|
57
|
+
if (prev !== undefined && stop.at < prev.at) {
|
|
58
|
+
throw new RangeError(`ColorRamp stops must be in ascending position order; ` +
|
|
59
|
+
`stop ${i} at ${stop.at} follows stop ${i - 1} at ${prev.at}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The color at `value`. Below the first stop it is the first color; at or
|
|
65
|
+
* above the last stop it is the last; between two stops the raw progress
|
|
66
|
+
* from the lower to the upper goes through `ease`, and the eased progress
|
|
67
|
+
* says how far to mix.
|
|
68
|
+
*
|
|
69
|
+
* Eased progress 0 is the lower stop's color and 1 the upper's, byte for
|
|
70
|
+
* byte — the exactness contract, not a shortcut: the sRGB → OKLCH → sRGB
|
|
71
|
+
* round-trip can land a channel one unit off, and a ramp that did not hit
|
|
72
|
+
* its own stops exactly would make a `step` ramp paint a color the author
|
|
73
|
+
* never wrote. So a value on a stop is that stop's color whenever the ease
|
|
74
|
+
* starts at 0, as every built-in does but `step-start` and the
|
|
75
|
+
* `jump-start`/`jump-both` steps, which jump at the start of the interval as
|
|
76
|
+
* CSS defines them. An ease that overshoots [0, 1] holds the end colors
|
|
77
|
+
* where it does: a ramp never paints outside its stops.
|
|
78
|
+
*/
|
|
79
|
+
at(value) {
|
|
80
|
+
if (!Number.isFinite(value)) {
|
|
81
|
+
throw new RangeError(`ColorRamp.at needs a finite value, got ${value}`);
|
|
82
|
+
}
|
|
83
|
+
const stops = this.stops;
|
|
84
|
+
// The last stop at or below `value`; -1 when `value` is below them all.
|
|
85
|
+
let lower = -1;
|
|
86
|
+
while (lower + 1 < stops.length && stops[lower + 1].at <= value)
|
|
87
|
+
lower++;
|
|
88
|
+
if (lower < 0)
|
|
89
|
+
return stops[0].color;
|
|
90
|
+
const from = stops[lower];
|
|
91
|
+
if (lower === stops.length - 1)
|
|
92
|
+
return from.color;
|
|
93
|
+
// `to.at > value >= from.at` by construction of `lower`, so the segment
|
|
94
|
+
// has positive width and raw progress is in [0, 1).
|
|
95
|
+
const to = stops[lower + 1];
|
|
96
|
+
const t = this.ease((value - from.at) / (to.at - from.at));
|
|
97
|
+
if (t <= 0)
|
|
98
|
+
return from.color;
|
|
99
|
+
if (t >= 1)
|
|
100
|
+
return to.color;
|
|
101
|
+
return Oklch.fromRgba(from.color).mix(Oklch.fromRgba(to.color), t).toRgba();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ColorRgba, ColorTable } from "../core/color.js";
|
|
2
|
+
import { Palette } from "./palette.js";
|
|
3
|
+
import { type ThemeName } from "./data/index.js";
|
|
4
|
+
export type { ThemeName };
|
|
5
|
+
/**
|
|
6
|
+
* Returns the static list of available theme names. Pure and synchronous.
|
|
7
|
+
*/
|
|
8
|
+
export declare function listThemePalettes(): readonly ThemeName[];
|
|
9
|
+
/**
|
|
10
|
+
* Returns the Palette for `name`, or `null` if unknown.
|
|
11
|
+
*
|
|
12
|
+
* Synchronous: theme data is bundled at compile time via the data barrel,
|
|
13
|
+
* so no I/O happens here. The Palette itself (which requires hex-parsing
|
|
14
|
+
* ~150 vars into ColorRgba values) is constructed lazily on first request
|
|
15
|
+
* and cached — subsequent calls for the same name return the same instance.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getThemePalette(name: ThemeName): Palette;
|
|
18
|
+
export declare function getThemePalette(name: string): Palette | null;
|
|
19
|
+
/**
|
|
20
|
+
* The eight base colors every theme must declare, and its ANSI table. Returned by
|
|
21
|
+
* `getThemeBaseColors` for callers (notably `terminalThemes.ts`) that only
|
|
22
|
+
* need the substrate and would otherwise pay the cost of hydrating the
|
|
23
|
+
* full ~150-var palette and polluting the registry cache.
|
|
24
|
+
*/
|
|
25
|
+
export interface ThemeBaseColors {
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly dark: boolean;
|
|
28
|
+
readonly bg: ColorRgba;
|
|
29
|
+
readonly fg: ColorRgba;
|
|
30
|
+
readonly primary: ColorRgba;
|
|
31
|
+
readonly secondary: ColorRgba;
|
|
32
|
+
readonly accent: ColorRgba;
|
|
33
|
+
readonly success: ColorRgba;
|
|
34
|
+
readonly warning: ColorRgba;
|
|
35
|
+
readonly error: ColorRgba;
|
|
36
|
+
readonly ansi: ColorTable;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Read just the eight base colors from a theme's data file. Cheap — parses
|
|
40
|
+
* 8 hex strings, allocates no Palette, touches no cache. Use this when you
|
|
41
|
+
* want a `TerminalTheme`-shaped substrate without forcing the full ~150-var
|
|
42
|
+
* palette through the registry's hydration path.
|
|
43
|
+
*/
|
|
44
|
+
export declare function getThemeBaseColors(name: ThemeName): ThemeBaseColors;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { ColorParseError, ColorTable, parseHexColor } from "../core/color.js";
|
|
2
|
+
import { Palette, drawnOn } from "./palette.js";
|
|
3
|
+
import { ACCENT_KEYS, accentText } from "./buildPalette.js";
|
|
4
|
+
import { THEMES } from "./data/index.js";
|
|
5
|
+
import { ANSI_SLOTS } from "./data/types.js";
|
|
6
|
+
const THEME_NAMES = Object.freeze(Object.keys(THEMES).sort());
|
|
7
|
+
const cache = new Map();
|
|
8
|
+
/**
|
|
9
|
+
* Returns the static list of available theme names. Pure and synchronous.
|
|
10
|
+
*/
|
|
11
|
+
export function listThemePalettes() {
|
|
12
|
+
return THEME_NAMES;
|
|
13
|
+
}
|
|
14
|
+
export function getThemePalette(name) {
|
|
15
|
+
if (!isThemeName(name))
|
|
16
|
+
return null;
|
|
17
|
+
const cached = cache.get(name);
|
|
18
|
+
if (cached !== undefined)
|
|
19
|
+
return cached;
|
|
20
|
+
const palette = hydrate(THEMES[name]);
|
|
21
|
+
cache.set(name, palette);
|
|
22
|
+
return palette;
|
|
23
|
+
}
|
|
24
|
+
function isThemeName(name) {
|
|
25
|
+
return Object.hasOwn(THEMES, name);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Read just the eight base colors from a theme's data file. Cheap — parses
|
|
29
|
+
* 8 hex strings, allocates no Palette, touches no cache. Use this when you
|
|
30
|
+
* want a `TerminalTheme`-shaped substrate without forcing the full ~150-var
|
|
31
|
+
* palette through the registry's hydration path.
|
|
32
|
+
*/
|
|
33
|
+
export function getThemeBaseColors(name) {
|
|
34
|
+
const data = THEMES[name];
|
|
35
|
+
const bg = requireBaseVar(data, "background");
|
|
36
|
+
// The colours `getThemePalette(name)` hands out for the same names: drawn on
|
|
37
|
+
// the theme's own background, as a Palette draws every colour it holds.
|
|
38
|
+
const draw = drawnOn(data.name, bg);
|
|
39
|
+
const base = (key) => draw(requireBaseVar(data, key));
|
|
40
|
+
return {
|
|
41
|
+
name: data.name,
|
|
42
|
+
dark: data.dark,
|
|
43
|
+
bg,
|
|
44
|
+
fg: base("foreground"),
|
|
45
|
+
primary: base("primary"),
|
|
46
|
+
secondary: base("secondary"),
|
|
47
|
+
accent: base("accent"),
|
|
48
|
+
success: base("success"),
|
|
49
|
+
warning: base("warning"),
|
|
50
|
+
error: base("error"),
|
|
51
|
+
ansi: new ColorTable(ANSI_SLOTS.map((slot) => parseOpaqueHex(data.ansi[slot], data.name, `ansi.${slot}`))),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function requireBaseVar(data, key) {
|
|
55
|
+
const v = data.vars[key];
|
|
56
|
+
if (v === undefined) {
|
|
57
|
+
throw new Error(`Theme ${data.name}: required base var "${key}" missing from data file`);
|
|
58
|
+
}
|
|
59
|
+
return parseHex(v, data.name, key);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Parse a `ThemePaletteData`'s hex strings into a Palette of ColorRgba.
|
|
63
|
+
*
|
|
64
|
+
* [LAW:single-enforcer] Hex → ColorRgba conversion for theme data lives
|
|
65
|
+
* here, not on Palette. Keeping the parser in this module preserves the
|
|
66
|
+
* `core/color → themes/palette` one-way edge (palette.ts must not import
|
|
67
|
+
* ColorRgba as a value, or it cycles with core/color's own use of Palette
|
|
68
|
+
* for INTERNAL_DEFAULT_THEME).
|
|
69
|
+
*/
|
|
70
|
+
function hydrate(data) {
|
|
71
|
+
const map = new Map();
|
|
72
|
+
for (const [k, v] of Object.entries(data.vars)) {
|
|
73
|
+
map.set(k, parseHex(v, data.name, `var ${k}`));
|
|
74
|
+
}
|
|
75
|
+
// The data is Textual's as authored; its `text-*` is held to the pair this
|
|
76
|
+
// library promises by the same rule `buildPalette` derives it with.
|
|
77
|
+
for (const key of ACCENT_KEYS) {
|
|
78
|
+
const text = requireBaseVar(data, `text-${key}`);
|
|
79
|
+
map.set(`text-${key}`, accentText(text, requireBaseVar(data, `${key}-muted`), requireBaseVar(data, "background")));
|
|
80
|
+
}
|
|
81
|
+
return new Palette(data.name, data.dark, map);
|
|
82
|
+
}
|
|
83
|
+
// Theme data is authored, so a malformed colour names the theme and the key it
|
|
84
|
+
// sits under; the grammar itself is `parseHexColor`'s.
|
|
85
|
+
function parseHex(value, theme, key) {
|
|
86
|
+
try {
|
|
87
|
+
return parseHexColor(value);
|
|
88
|
+
}
|
|
89
|
+
catch (cause) {
|
|
90
|
+
if (!(cause instanceof ColorParseError))
|
|
91
|
+
throw cause;
|
|
92
|
+
throw new Error(`Theme ${theme}: ${key}: ${cause.message}`, { cause });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* An ANSI slot is a colour a terminal paints, never a blend, so it takes no
|
|
97
|
+
* alpha: `flattenAlpha` leaves a STANDARD spec alone and would pass one through.
|
|
98
|
+
*/
|
|
99
|
+
function parseOpaqueHex(value, theme, key) {
|
|
100
|
+
const color = parseHex(value, theme, key);
|
|
101
|
+
if (color.alpha !== 1) {
|
|
102
|
+
throw new Error(`Theme ${theme}: ${key} has alpha in ${JSON.stringify(value)} (expected #RRGGBB)`);
|
|
103
|
+
}
|
|
104
|
+
return color;
|
|
105
|
+
}
|