@ny4n/tui 0.0.0-stage → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +948 -2
- package/dist/alt-screen-search.d.ts +46 -0
- package/dist/alt-screen-search.d.ts.map +1 -0
- package/dist/alt-screen-search.js +282 -0
- package/dist/alt-screen-search.js.map +1 -0
- package/dist/autocomplete.d.ts +57 -0
- package/dist/autocomplete.d.ts.map +1 -0
- package/dist/autocomplete.js +693 -0
- package/dist/autocomplete.js.map +1 -0
- package/dist/colors.d.ts +73 -0
- package/dist/colors.d.ts.map +1 -0
- package/dist/colors.js +273 -0
- package/dist/colors.js.map +1 -0
- package/dist/components/alt-screen-flash.d.ts +13 -0
- package/dist/components/alt-screen-flash.d.ts.map +1 -0
- package/dist/components/alt-screen-flash.js +37 -0
- package/dist/components/alt-screen-flash.js.map +1 -0
- package/dist/components/box.d.ts +25 -0
- package/dist/components/box.d.ts.map +1 -0
- package/dist/components/box.js +138 -0
- package/dist/components/box.js.map +1 -0
- package/dist/components/cancellable-loader.d.ts +22 -0
- package/dist/components/cancellable-loader.d.ts.map +1 -0
- package/dist/components/cancellable-loader.js +35 -0
- package/dist/components/cancellable-loader.js.map +1 -0
- package/dist/components/editor.d.ts +260 -0
- package/dist/components/editor.d.ts.map +1 -0
- package/dist/components/editor.js +2044 -0
- package/dist/components/editor.js.map +1 -0
- package/dist/components/h-stack.d.ts +7 -0
- package/dist/components/h-stack.d.ts.map +1 -0
- package/dist/components/h-stack.js +43 -0
- package/dist/components/h-stack.js.map +1 -0
- package/dist/components/image.d.ts +40 -0
- package/dist/components/image.d.ts.map +1 -0
- package/dist/components/image.js +123 -0
- package/dist/components/image.js.map +1 -0
- package/dist/components/input.d.ts +48 -0
- package/dist/components/input.d.ts.map +1 -0
- package/dist/components/input.js +417 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/loader.d.ts +33 -0
- package/dist/components/loader.d.ts.map +1 -0
- package/dist/components/loader.js +76 -0
- package/dist/components/loader.js.map +1 -0
- package/dist/components/markdown.d.ts +104 -0
- package/dist/components/markdown.d.ts.map +1 -0
- package/dist/components/markdown.js +821 -0
- package/dist/components/markdown.js.map +1 -0
- package/dist/components/mouse-region.d.ts +12 -0
- package/dist/components/mouse-region.d.ts.map +1 -0
- package/dist/components/mouse-region.js +21 -0
- package/dist/components/mouse-region.js.map +1 -0
- package/dist/components/scroll-view.d.ts +59 -0
- package/dist/components/scroll-view.d.ts.map +1 -0
- package/dist/components/scroll-view.js +195 -0
- package/dist/components/scroll-view.js.map +1 -0
- package/dist/components/select-list.d.ts +53 -0
- package/dist/components/select-list.d.ts.map +1 -0
- package/dist/components/select-list.js +206 -0
- package/dist/components/select-list.js.map +1 -0
- package/dist/components/settings-list.d.ts +60 -0
- package/dist/components/settings-list.d.ts.map +1 -0
- package/dist/components/settings-list.js +252 -0
- package/dist/components/settings-list.js.map +1 -0
- package/dist/components/spacer.d.ts +12 -0
- package/dist/components/spacer.d.ts.map +1 -0
- package/dist/components/spacer.js +23 -0
- package/dist/components/spacer.js.map +1 -0
- package/dist/components/stack.d.ts +32 -0
- package/dist/components/stack.d.ts.map +1 -0
- package/dist/components/stack.js +111 -0
- package/dist/components/stack.js.map +1 -0
- package/dist/components/text.d.ts +20 -0
- package/dist/components/text.d.ts.map +1 -0
- package/dist/components/text.js +95 -0
- package/dist/components/text.js.map +1 -0
- package/dist/components/truncated-text.d.ts +13 -0
- package/dist/components/truncated-text.d.ts.map +1 -0
- package/dist/components/truncated-text.js +51 -0
- package/dist/components/truncated-text.js.map +1 -0
- package/dist/components/v-stack.d.ts +8 -0
- package/dist/components/v-stack.d.ts.map +1 -0
- package/dist/components/v-stack.js +26 -0
- package/dist/components/v-stack.js.map +1 -0
- package/dist/editor-component.d.ts +39 -0
- package/dist/editor-component.d.ts.map +1 -0
- package/dist/editor-component.js +2 -0
- package/dist/editor-component.js.map +1 -0
- package/dist/fuzzy.d.ts +16 -0
- package/dist/fuzzy.d.ts.map +1 -0
- package/dist/fuzzy.js +111 -0
- package/dist/fuzzy.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/keybindings.d.ts +273 -0
- package/dist/keybindings.d.ts.map +1 -0
- package/dist/keybindings.js +233 -0
- package/dist/keybindings.js.map +1 -0
- package/dist/keys.d.ts +184 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +1206 -0
- package/dist/keys.js.map +1 -0
- package/dist/kill-ring.d.ts +28 -0
- package/dist/kill-ring.d.ts.map +1 -0
- package/dist/kill-ring.js +44 -0
- package/dist/kill-ring.js.map +1 -0
- package/dist/latex.d.ts +10 -0
- package/dist/latex.d.ts.map +1 -0
- package/dist/latex.js +1378 -0
- package/dist/latex.js.map +1 -0
- package/dist/layout-node.d.ts +40 -0
- package/dist/layout-node.d.ts.map +1 -0
- package/dist/layout-node.js +6 -0
- package/dist/layout-node.js.map +1 -0
- package/dist/layout.d.ts +42 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +344 -0
- package/dist/layout.js.map +1 -0
- package/dist/native-modifiers.d.ts +4 -0
- package/dist/native-modifiers.d.ts.map +1 -0
- package/dist/native-modifiers.js +13 -0
- package/dist/native-modifiers.js.map +1 -0
- package/dist/native-module-path.d.ts +7 -0
- package/dist/native-module-path.d.ts.map +1 -0
- package/dist/native-module-path.js +19 -0
- package/dist/native-module-path.js.map +1 -0
- package/dist/native-platform.d.ts +20 -0
- package/dist/native-platform.d.ts.map +1 -0
- package/dist/native-platform.js +42 -0
- package/dist/native-platform.js.map +1 -0
- package/dist/oklab.d.ts +43 -0
- package/dist/oklab.d.ts.map +1 -0
- package/dist/oklab.js +210 -0
- package/dist/oklab.js.map +1 -0
- package/dist/program-status.d.ts +23 -0
- package/dist/program-status.d.ts.map +1 -0
- package/dist/program-status.js +43 -0
- package/dist/program-status.js.map +1 -0
- package/dist/stdin-buffer.d.ts +56 -0
- package/dist/stdin-buffer.d.ts.map +1 -0
- package/dist/stdin-buffer.js +366 -0
- package/dist/stdin-buffer.js.map +1 -0
- package/dist/terminal-colors.d.ts +27 -0
- package/dist/terminal-colors.d.ts.map +1 -0
- package/dist/terminal-colors.js +64 -0
- package/dist/terminal-colors.js.map +1 -0
- package/dist/terminal-image.d.ts +123 -0
- package/dist/terminal-image.d.ts.map +1 -0
- package/dist/terminal-image.js +603 -0
- package/dist/terminal-image.js.map +1 -0
- package/dist/terminal.d.ts +143 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +493 -0
- package/dist/terminal.js.map +1 -0
- package/dist/tui-alt-screen.d.ts +168 -0
- package/dist/tui-alt-screen.d.ts.map +1 -0
- package/dist/tui-alt-screen.js +1552 -0
- package/dist/tui-alt-screen.js.map +1 -0
- package/dist/tui-main-screen.d.ts +39 -0
- package/dist/tui-main-screen.d.ts.map +1 -0
- package/dist/tui-main-screen.js +595 -0
- package/dist/tui-main-screen.js.map +1 -0
- package/dist/tui.d.ts +398 -0
- package/dist/tui.d.ts.map +1 -0
- package/dist/tui.js +1096 -0
- package/dist/tui.js.map +1 -0
- package/dist/undo-stack.d.ts +17 -0
- package/dist/undo-stack.d.ts.map +1 -0
- package/dist/undo-stack.js +25 -0
- package/dist/undo-stack.js.map +1 -0
- package/dist/utils.d.ts +107 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +1263 -0
- package/dist/utils.js.map +1 -0
- package/dist/wheel-scroll.d.ts +23 -0
- package/dist/wheel-scroll.d.ts.map +1 -0
- package/dist/wheel-scroll.js +73 -0
- package/dist/wheel-scroll.js.map +1 -0
- package/dist/word-navigation.d.ts +25 -0
- package/dist/word-navigation.d.ts.map +1 -0
- package/dist/word-navigation.js +96 -0
- package/dist/word-navigation.js.map +1 -0
- package/native/clipboard.h +208 -0
- package/native/darwin/README.md +22 -0
- package/native/darwin/build.sh +69 -0
- package/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
- package/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
- package/native/darwin/src/darwin-platform.m +132 -0
- package/native/linux/README.md +23 -0
- package/native/linux/build.sh +65 -0
- package/native/linux/prebuilds/linux-arm64/linux-platform-x11.node +0 -0
- package/native/linux/prebuilds/linux-x64/linux-platform-x11.node +0 -0
- package/native/linux/src/clipboard-worker.h +70 -0
- package/native/linux/src/linux-platform-x11.c +274 -0
- package/native/napi.h +91 -0
- package/native/win32/README.md +31 -0
- package/native/win32/build.mjs +232 -0
- package/native/win32/prebuilds/win32-arm64/win32-platform.node +0 -0
- package/native/win32/prebuilds/win32-x64/win32-platform.node +0 -0
- package/native/win32/src/win32-platform.c +241 -0
- package/package.json +61 -5
package/dist/oklab.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Oklab and OKHSL <-> sRGB conversion. `colors.ts` builds its OKLCH, OKHSL, and color mixing on it.
|
|
3
|
+
*
|
|
4
|
+
* Oklab and OKHSL are Björn Ottosson's color spaces; OKHSL's saturation is relative to the sRGB gamut at
|
|
5
|
+
* each hue and lightness. This is a port of his reference implementation (https://bottosson.github.io/posts/colorpicker/),
|
|
6
|
+
* Copyright (c) 2021 Björn Ottosson, used under the MIT license:
|
|
7
|
+
*
|
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
9
|
+
* associated documentation files (the "Software"), to deal in the Software without restriction, including
|
|
10
|
+
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
|
12
|
+
* following conditions: The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
* copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
14
|
+
* KIND, EXPRESS OR IMPLIED.
|
|
15
|
+
*/
|
|
16
|
+
const multiply = (m, [x, y, z]) => m.map((row) => row[0] * x + row[1] * y + row[2] * z);
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// OKHSL <-> sRGB
|
|
19
|
+
// ============================================================================
|
|
20
|
+
const LINEAR_SRGB_TO_LMS = [
|
|
21
|
+
[0.4122214694707629, 0.5363325372617349, 0.0514459932675022],
|
|
22
|
+
[0.2119034958178251, 0.6806995506452344, 0.1073969535369405],
|
|
23
|
+
[0.0883024591900564, 0.2817188391361215, 0.6299787016738222],
|
|
24
|
+
];
|
|
25
|
+
const LMS_TO_LAB = [
|
|
26
|
+
[0.210454268309314, 0.793617774702305, -0.0040720430116193],
|
|
27
|
+
[1.9779985324311684, -2.42859224204858, 0.450593709617411],
|
|
28
|
+
[0.0259040424655478, 0.7827717124575296, -0.8086757549230774],
|
|
29
|
+
];
|
|
30
|
+
const LAB_TO_LMS = [
|
|
31
|
+
[1, 0.3963377773761749, 0.2158037573099136],
|
|
32
|
+
[1, -0.1055613458156586, -0.0638541728258133],
|
|
33
|
+
[1, -0.0894841775298119, -1.2914855480194092],
|
|
34
|
+
];
|
|
35
|
+
const LMS_TO_LINEAR_SRGB = [
|
|
36
|
+
[4.0767416360759583, -3.3077115392580629, 0.2309699031821043],
|
|
37
|
+
[-1.2684379732850315, 2.6097573492876882, -0.341319376002657],
|
|
38
|
+
[-0.0041960761386756, -0.7034186179359362, 1.7076146940746117],
|
|
39
|
+
];
|
|
40
|
+
/**
|
|
41
|
+
* Per sRGB channel (red, green, blue): the (a, b) half-plane where that channel clips
|
|
42
|
+
* first, and the polynomial approximating the maximum saturation there.
|
|
43
|
+
*/
|
|
44
|
+
const SATURATION_FIT = [
|
|
45
|
+
[
|
|
46
|
+
[-1.8817031, -0.80936501],
|
|
47
|
+
[1.19086277, 1.76576728, 0.59662641, 0.75515197, 0.56771245],
|
|
48
|
+
],
|
|
49
|
+
[
|
|
50
|
+
[1.8144408, -1.19445267],
|
|
51
|
+
[0.73956515, -0.45954404, 0.08285427, 0.12541073, -0.14503204],
|
|
52
|
+
],
|
|
53
|
+
[
|
|
54
|
+
[0.13110758, 1.81333971],
|
|
55
|
+
[1.35733652, -0.00915799, -1.1513021, -0.50559606, 0.00692167],
|
|
56
|
+
],
|
|
57
|
+
];
|
|
58
|
+
const K1 = 0.206;
|
|
59
|
+
const K2 = 0.03;
|
|
60
|
+
const K3 = (1 + K1) / (1 + K2);
|
|
61
|
+
/** Oklab lightness to OKHSL lightness. */
|
|
62
|
+
export const oklabToOkhslLightness = (x) => 0.5 * (K3 * x - K1 + Math.sqrt((K3 * x - K1) ** 2 + 4 * K2 * K3 * x));
|
|
63
|
+
/** OKHSL lightness to Oklab lightness. */
|
|
64
|
+
const okhslToOklabLightness = (x) => (x * x + K1 * x) / (K3 * (x + K2));
|
|
65
|
+
/** sRGB transfer function: linear to encoded channel, both 0-1. */
|
|
66
|
+
const linearToSrgb = (value) => value > 0.0031308 ? 1.055 * value ** (1 / 2.4) - 0.055 : 12.92 * value;
|
|
67
|
+
/** Inverse sRGB transfer function: encoded to linear channel, both 0-1. */
|
|
68
|
+
const srgbToLinear = (value) => (value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4);
|
|
69
|
+
/** Oklab [L, a, b] to linear sRGB [r, g, b] (0-1, may leave the gamut). */
|
|
70
|
+
export function oklabToLinearSrgb(lab) {
|
|
71
|
+
return multiply(LMS_TO_LINEAR_SRGB, multiply(LAB_TO_LMS, lab).map((value) => value ** 3));
|
|
72
|
+
}
|
|
73
|
+
/** Linear sRGB [r, g, b] (0-1) to Oklab [L, a, b]. */
|
|
74
|
+
function linearSrgbToOklab(rgb) {
|
|
75
|
+
return multiply(LMS_TO_LAB, multiply(LINEAR_SRGB_TO_LMS, rgb).map(Math.cbrt));
|
|
76
|
+
}
|
|
77
|
+
/** sRGB channels (0-255) to Oklab [L, a, b]. */
|
|
78
|
+
export function rgbToOklab({ r, g, b }) {
|
|
79
|
+
return linearSrgbToOklab([r / 255, g / 255, b / 255].map(srgbToLinear));
|
|
80
|
+
}
|
|
81
|
+
/** Linear sRGB [r, g, b] to sRGB channels (0-255, rounded), clipping out-of-gamut channels. */
|
|
82
|
+
export function linearSrgbToRgb(linear) {
|
|
83
|
+
const [r, g, b] = linear.map((value) => Math.round(Math.min(1, Math.max(0, linearToSrgb(value))) * 255));
|
|
84
|
+
return { r, g, b };
|
|
85
|
+
}
|
|
86
|
+
/** Rate of change of each cube-root LMS component along a chroma direction (a, b). */
|
|
87
|
+
function lmsSlopes(a, b) {
|
|
88
|
+
return [LAB_TO_LMS[0], LAB_TO_LMS[1], LAB_TO_LMS[2]].map((row) => row[1] * a + row[2] * b);
|
|
89
|
+
}
|
|
90
|
+
/** Largest saturation (C/L) inside sRGB for hue (a, b): polynomial fit plus one Halley step. */
|
|
91
|
+
function maxSaturation(a, b) {
|
|
92
|
+
const channel = SATURATION_FIT.findIndex(([[x, y]], index) => index === 2 || x * a + y * b > 1);
|
|
93
|
+
const [k0, k1, k2, k3, k4] = SATURATION_FIT[channel][1];
|
|
94
|
+
const weights = LMS_TO_LINEAR_SRGB[channel];
|
|
95
|
+
const saturation = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;
|
|
96
|
+
const slopes = lmsSlopes(a, b);
|
|
97
|
+
const base = slopes.map((k) => 1 + saturation * k);
|
|
98
|
+
const dot = (values) => values.reduce((sum, value, index) => sum + weights[index] * value, 0);
|
|
99
|
+
const f = dot(base.map((value) => value ** 3));
|
|
100
|
+
const f1 = dot(base.map((value, index) => 3 * slopes[index] * value ** 2));
|
|
101
|
+
const f2 = dot(base.map((value, index) => 6 * slopes[index] ** 2 * value));
|
|
102
|
+
return saturation - (f * f1) / (f1 * f1 - 0.5 * f * f2);
|
|
103
|
+
}
|
|
104
|
+
/** Oklab lightness and chroma of the most saturated sRGB color of hue (a, b). */
|
|
105
|
+
function cusp(a, b) {
|
|
106
|
+
const saturation = maxSaturation(a, b);
|
|
107
|
+
const lightness = Math.cbrt(1 / Math.max(...oklabToLinearSrgb([1, saturation * a, saturation * b])));
|
|
108
|
+
return [lightness, lightness * saturation];
|
|
109
|
+
}
|
|
110
|
+
/** Chroma where the constant-lightness line at `lightness` leaves the sRGB gamut. */
|
|
111
|
+
function maxChroma(a, b, lightness, [cuspL, cuspC]) {
|
|
112
|
+
if (lightness <= cuspL)
|
|
113
|
+
return (cuspC * lightness) / cuspL;
|
|
114
|
+
// Upper half: triangle edge, then one Halley step against each channel reaching 1.
|
|
115
|
+
const t = (cuspC * (lightness - 1)) / (cuspL - 1);
|
|
116
|
+
const slopes = lmsSlopes(a, b);
|
|
117
|
+
const lms = slopes.map((k) => lightness + t * k);
|
|
118
|
+
const cubes = lms.map((value) => value ** 3);
|
|
119
|
+
const first = lms.map((value, index) => 3 * slopes[index] * value ** 2);
|
|
120
|
+
const second = lms.map((value, index) => 6 * slopes[index] ** 2 * value);
|
|
121
|
+
const dot = (row, values) => row[0] * values[0] + row[1] * values[1] + row[2] * values[2];
|
|
122
|
+
const steps = LMS_TO_LINEAR_SRGB.map((row) => {
|
|
123
|
+
const f = dot(row, cubes) - 1;
|
|
124
|
+
const f1 = dot(row, first);
|
|
125
|
+
const f2 = dot(row, second);
|
|
126
|
+
const u = f1 / (f1 * f1 - 0.5 * f * f2);
|
|
127
|
+
return u >= 0 ? -f * u : Number.MAX_VALUE;
|
|
128
|
+
});
|
|
129
|
+
return t + Math.min(...steps);
|
|
130
|
+
}
|
|
131
|
+
/** OKHSL's chroma reference points at lightness L and hue (a, b): [c0, cMid, cMax]. */
|
|
132
|
+
function chromaStops(L, a, b) {
|
|
133
|
+
const peak = cusp(a, b);
|
|
134
|
+
const cMax = maxChroma(a, b, L, peak);
|
|
135
|
+
const k = cMax / Math.min(L * (peak[1] / peak[0]), (1 - L) * (peak[1] / (1 - peak[0])));
|
|
136
|
+
const midS = 0.11516993 +
|
|
137
|
+
1 /
|
|
138
|
+
(7.4477897 +
|
|
139
|
+
4.1590124 * b +
|
|
140
|
+
a *
|
|
141
|
+
(-2.19557347 +
|
|
142
|
+
1.75198401 * b +
|
|
143
|
+
a * (-2.13704948 - 10.02301043 * b + a * (-4.24894561 + 5.38770819 * b + 4.69891013 * a))));
|
|
144
|
+
const midT = 0.11239642 +
|
|
145
|
+
1 /
|
|
146
|
+
(1.6132032 -
|
|
147
|
+
0.68124379 * b +
|
|
148
|
+
a *
|
|
149
|
+
(0.40370612 +
|
|
150
|
+
0.90148123 * b +
|
|
151
|
+
a * (-0.27087943 + 0.6122399 * b + a * (0.00299215 - 0.45399568 * b - 0.14661872 * a))));
|
|
152
|
+
const cMid = 0.9 * k * Math.sqrt(Math.sqrt(1 / (1 / (L * midS) ** 4 + 1 / ((1 - L) * midT) ** 4)));
|
|
153
|
+
const c0 = Math.sqrt(1 / (1 / (L * 0.4) ** 2 + 1 / ((1 - L) * 0.8) ** 2));
|
|
154
|
+
return [c0, cMid, cMax];
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Convert OKHSL to sRGB channels (0-255, rounded), clipping out-of-gamut channels.
|
|
158
|
+
* @param hue Hue in degrees.
|
|
159
|
+
* @param saturation Saturation, 0-1.
|
|
160
|
+
* @param lightness Lightness, 0-1.
|
|
161
|
+
*/
|
|
162
|
+
export function okhslToRgb(hue, saturation, lightness) {
|
|
163
|
+
const L = okhslToOklabLightness(lightness);
|
|
164
|
+
let lab = [L, 0, 0];
|
|
165
|
+
if (L > 0 && L < 1 && saturation > 0) {
|
|
166
|
+
const angle = (2 * Math.PI * (((hue % 360) + 360) % 360)) / 360;
|
|
167
|
+
const a = Math.cos(angle);
|
|
168
|
+
const b = Math.sin(angle);
|
|
169
|
+
const [c0, cMid, cMax] = chromaStops(L, a, b);
|
|
170
|
+
// Chroma rises from 0 through cMid at s = 0.8 to cMax at s = 1.
|
|
171
|
+
let chroma;
|
|
172
|
+
if (saturation < 0.8) {
|
|
173
|
+
const t = 1.25 * saturation;
|
|
174
|
+
const k1 = 0.8 * c0;
|
|
175
|
+
chroma = (t * k1) / (1 - (1 - k1 / cMid) * t);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
const t = 5 * (saturation - 0.8);
|
|
179
|
+
const k1 = (0.2 * cMid ** 2 * 1.25 ** 2) / c0;
|
|
180
|
+
chroma = cMid + (t * k1) / (1 - (1 - k1 / (cMax - cMid)) * t);
|
|
181
|
+
}
|
|
182
|
+
lab = [L, chroma * a, chroma * b];
|
|
183
|
+
}
|
|
184
|
+
return linearSrgbToRgb(oklabToLinearSrgb(lab));
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Convert sRGB channels (0-255) to OKHSL.
|
|
188
|
+
* @returns Hue `h` in degrees (0 for grays), saturation `s` and lightness `l` 0-1.
|
|
189
|
+
*/
|
|
190
|
+
export function rgbToOkhsl(rgb) {
|
|
191
|
+
const [L, labA, labB] = rgbToOklab(rgb);
|
|
192
|
+
const chroma = Math.hypot(labA, labB);
|
|
193
|
+
const lightness = oklabToOkhslLightness(L);
|
|
194
|
+
if (chroma < 1e-9 || lightness <= 0 || lightness >= 1)
|
|
195
|
+
return { h: 0, s: 0, l: lightness };
|
|
196
|
+
const hue = ((Math.atan2(labB, labA) * 180) / Math.PI + 360) % 360;
|
|
197
|
+
const [c0, cMid, cMax] = chromaStops(L, labA / chroma, labB / chroma);
|
|
198
|
+
let saturation;
|
|
199
|
+
if (chroma < cMid) {
|
|
200
|
+
const k1 = 0.8 * c0;
|
|
201
|
+
saturation = 0.8 * (chroma / (k1 + (1 - k1 / cMid) * chroma));
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
const k1 = (0.2 * cMid ** 2 * 1.25 ** 2) / c0;
|
|
205
|
+
const offset = chroma - cMid;
|
|
206
|
+
saturation = 0.8 + 0.2 * (offset / (k1 + (1 - k1 / (cMax - cMid)) * offset));
|
|
207
|
+
}
|
|
208
|
+
return { h: hue, s: Math.min(1, Math.max(0, saturation)), l: lightness };
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=oklab.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oklab.js","sourceRoot":"","sources":["../src/oklab.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAS,EAAU,EAAE,CACzD,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAW,CAAC;AAEhE,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E,MAAM,kBAAkB,GAAW;IAClC,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,kBAAkB,CAAC;IAC5D,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,kBAAkB,CAAC;IAC5D,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,kBAAkB,CAAC;CAC5D,CAAC;AACF,MAAM,UAAU,GAAW;IAC1B,CAAC,iBAAiB,EAAE,iBAAiB,EAAE,CAAC,kBAAkB,CAAC;IAC3D,CAAC,kBAAkB,EAAE,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;IAC1D,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,CAAC,kBAAkB,CAAC;CAC7D,CAAC;AACF,MAAM,UAAU,GAAW;IAC1B,CAAC,CAAC,EAAE,kBAAkB,EAAE,kBAAkB,CAAC;IAC3C,CAAC,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,kBAAkB,CAAC;IAC7C,CAAC,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,kBAAkB,CAAC;CAC7C,CAAC;AACF,MAAM,kBAAkB,GAAW;IAClC,CAAC,kBAAkB,EAAE,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;IAC7D,CAAC,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,CAAC,iBAAiB,CAAC;IAC7D,CAAC,CAAC,kBAAkB,EAAE,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;CAC9D,CAAC;AACF;;;GAGG;AACH,MAAM,cAAc,GAAmC;IACtD;QACC,CAAC,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QACzB,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC;KAC5D;IACD;QACC,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC;QACxB,CAAC,UAAU,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,UAAU,CAAC;KAC9D;IACD;QACC,CAAC,UAAU,EAAE,UAAU,CAAC;QACxB,CAAC,UAAU,EAAE,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC;KAC9D;CACD,CAAC;AACF,MAAM,EAAE,GAAG,KAAK,CAAC;AACjB,MAAM,EAAE,GAAG,IAAI,CAAC;AAChB,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;AAE/B,0CAA0C;AAC1C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAS,EAAU,EAAE,CAC1D,GAAG,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;AACvE,0CAA0C;AAC1C,MAAM,qBAAqB,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AAExF,mEAAmE;AACnE,MAAM,YAAY,GAAG,CAAC,KAAa,EAAU,EAAE,CAC9C,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC;AACxE,2EAA2E;AAC3E,MAAM,YAAY,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;AAEtH,2EAA2E;AAC3E,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC5C,OAAO,QAAQ,CAAC,kBAAkB,EAAE,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,CAAW,CAAC,CAAC;AACrG,CAAC;AAED,sDAAsD;AACtD,SAAS,iBAAiB,CAAC,GAAW;IACrC,OAAO,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAW,CAAC,CAAC;AACzF,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAY;IAC/C,OAAO,iBAAiB,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,YAAY,CAAW,CAAC,CAAC;AACnF,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,eAAe,CAAC,MAAc;IAC7C,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IACzG,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AACpB,CAAC;AAED,sFAAsF;AACtF,SAAS,SAAS,CAAC,CAAS,EAAE,CAAS;IACtC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAW,CAAC;AACtG,CAAC;AAED,gGAAgG;AAChG,SAAS,aAAa,CAAC,CAAS,EAAE,CAAS;IAC1C,MAAM,OAAO,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAChG,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IAElE,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,CAAC,MAAgB,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;IACxG,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/C,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3E,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAC3E,OAAO,UAAU,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;AACzD,CAAC;AAED,iFAAiF;AACjF,SAAS,IAAI,CAAC,CAAS,EAAE,CAAS;IACjC,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrG,OAAO,CAAC,SAAS,EAAE,SAAS,GAAG,UAAU,CAAC,CAAC;AAC5C,CAAC;AAED,qFAAqF;AACrF,SAAS,SAAS,CAAC,CAAS,EAAE,CAAS,EAAE,SAAiB,EAAE,CAAC,KAAK,EAAE,KAAK,CAAmB;IAC3F,IAAI,SAAS,IAAI,KAAK;QAAE,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC;IAC3D,mFAAmF;IACnF,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC;IACxE,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;IACzE,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,MAAgB,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC5G,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QAC5C,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC3B,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC5B,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC;IAC3C,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,uFAAuF;AACvF,SAAS,WAAW,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxF,MAAM,IAAI,GACT,UAAU;QACV,CAAC;YACA,CAAC,SAAS;gBACT,SAAS,GAAG,CAAC;gBACb,CAAC;oBACA,CAAC,CAAC,UAAU;wBACX,UAAU,GAAG,CAAC;wBACd,CAAC,GAAG,CAAC,CAAC,UAAU,GAAG,WAAW,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,GAAG,UAAU,GAAG,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjG,MAAM,IAAI,GACT,UAAU;QACV,CAAC;YACA,CAAC,SAAS;gBACT,UAAU,GAAG,CAAC;gBACd,CAAC;oBACA,CAAC,UAAU;wBACV,UAAU,GAAG,CAAC;wBACd,CAAC,GAAG,CAAC,CAAC,UAAU,GAAG,SAAS,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,GAAG,UAAU,GAAG,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9F,MAAM,IAAI,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACnG,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1E,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACzB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,UAAkB,EAAE,SAAiB;IAC5E,MAAM,CAAC,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC3C,IAAI,GAAG,GAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;QAChE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1B,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9C,gEAAgE;QAChE,IAAI,MAAc,CAAC;QACnB,IAAI,UAAU,GAAG,GAAG,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,IAAI,GAAG,UAAU,CAAC;YAC5B,MAAM,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;YACpB,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACP,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC;YACjC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;YAC9C,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,GAAG,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,eAAe,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,GAAa;IACvC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC3C,IAAI,MAAM,GAAG,IAAI,IAAI,SAAS,IAAI,CAAC,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC;IAE3F,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;IACnE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC;IACtE,IAAI,UAAkB,CAAC;IACvB,IAAI,MAAM,GAAG,IAAI,EAAE,CAAC;QACnB,MAAM,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;QACpB,UAAU,GAAG,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAC/D,CAAC;SAAM,CAAC;QACP,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;QAC7B,UAAU,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC;AAC1E,CAAC","sourcesContent":["/**\n * Oklab and OKHSL <-> sRGB conversion. `colors.ts` builds its OKLCH, OKHSL, and color mixing on it.\n *\n * Oklab and OKHSL are Björn Ottosson's color spaces; OKHSL's saturation is relative to the sRGB gamut at\n * each hue and lightness. This is a port of his reference implementation (https://bottosson.github.io/posts/colorpicker/),\n * Copyright (c) 2021 Björn Ottosson, used under the MIT license:\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\n * associated documentation files (the \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\n * following conditions: The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY\n * KIND, EXPRESS OR IMPLIED.\n */\n\nimport type { RgbColor } from \"./terminal-colors.ts\";\n\ntype Vector = [number, number, number];\ntype Matrix = [Vector, Vector, Vector];\n\nconst multiply = (m: Matrix, [x, y, z]: Vector): Vector =>\n\tm.map((row) => row[0] * x + row[1] * y + row[2] * z) as Vector;\n\n// ============================================================================\n// OKHSL <-> sRGB\n// ============================================================================\n\nconst LINEAR_SRGB_TO_LMS: Matrix = [\n\t[0.4122214694707629, 0.5363325372617349, 0.0514459932675022],\n\t[0.2119034958178251, 0.6806995506452344, 0.1073969535369405],\n\t[0.0883024591900564, 0.2817188391361215, 0.6299787016738222],\n];\nconst LMS_TO_LAB: Matrix = [\n\t[0.210454268309314, 0.793617774702305, -0.0040720430116193],\n\t[1.9779985324311684, -2.42859224204858, 0.450593709617411],\n\t[0.0259040424655478, 0.7827717124575296, -0.8086757549230774],\n];\nconst LAB_TO_LMS: Matrix = [\n\t[1, 0.3963377773761749, 0.2158037573099136],\n\t[1, -0.1055613458156586, -0.0638541728258133],\n\t[1, -0.0894841775298119, -1.2914855480194092],\n];\nconst LMS_TO_LINEAR_SRGB: Matrix = [\n\t[4.0767416360759583, -3.3077115392580629, 0.2309699031821043],\n\t[-1.2684379732850315, 2.6097573492876882, -0.341319376002657],\n\t[-0.0041960761386756, -0.7034186179359362, 1.7076146940746117],\n];\n/**\n * Per sRGB channel (red, green, blue): the (a, b) half-plane where that channel clips\n * first, and the polynomial approximating the maximum saturation there.\n */\nconst SATURATION_FIT: [[number, number], number[]][] = [\n\t[\n\t\t[-1.8817031, -0.80936501],\n\t\t[1.19086277, 1.76576728, 0.59662641, 0.75515197, 0.56771245],\n\t],\n\t[\n\t\t[1.8144408, -1.19445267],\n\t\t[0.73956515, -0.45954404, 0.08285427, 0.12541073, -0.14503204],\n\t],\n\t[\n\t\t[0.13110758, 1.81333971],\n\t\t[1.35733652, -0.00915799, -1.1513021, -0.50559606, 0.00692167],\n\t],\n];\nconst K1 = 0.206;\nconst K2 = 0.03;\nconst K3 = (1 + K1) / (1 + K2);\n\n/** Oklab lightness to OKHSL lightness. */\nexport const oklabToOkhslLightness = (x: number): number =>\n\t0.5 * (K3 * x - K1 + Math.sqrt((K3 * x - K1) ** 2 + 4 * K2 * K3 * x));\n/** OKHSL lightness to Oklab lightness. */\nconst okhslToOklabLightness = (x: number): number => (x * x + K1 * x) / (K3 * (x + K2));\n\n/** sRGB transfer function: linear to encoded channel, both 0-1. */\nconst linearToSrgb = (value: number): number =>\n\tvalue > 0.0031308 ? 1.055 * value ** (1 / 2.4) - 0.055 : 12.92 * value;\n/** Inverse sRGB transfer function: encoded to linear channel, both 0-1. */\nconst srgbToLinear = (value: number): number => (value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4);\n\n/** Oklab [L, a, b] to linear sRGB [r, g, b] (0-1, may leave the gamut). */\nexport function oklabToLinearSrgb(lab: Vector): Vector {\n\treturn multiply(LMS_TO_LINEAR_SRGB, multiply(LAB_TO_LMS, lab).map((value) => value ** 3) as Vector);\n}\n\n/** Linear sRGB [r, g, b] (0-1) to Oklab [L, a, b]. */\nfunction linearSrgbToOklab(rgb: Vector): Vector {\n\treturn multiply(LMS_TO_LAB, multiply(LINEAR_SRGB_TO_LMS, rgb).map(Math.cbrt) as Vector);\n}\n\n/** sRGB channels (0-255) to Oklab [L, a, b]. */\nexport function rgbToOklab({ r, g, b }: RgbColor): Vector {\n\treturn linearSrgbToOklab([r / 255, g / 255, b / 255].map(srgbToLinear) as Vector);\n}\n\n/** Linear sRGB [r, g, b] to sRGB channels (0-255, rounded), clipping out-of-gamut channels. */\nexport function linearSrgbToRgb(linear: Vector): RgbColor {\n\tconst [r, g, b] = linear.map((value) => Math.round(Math.min(1, Math.max(0, linearToSrgb(value))) * 255));\n\treturn { r, g, b };\n}\n\n/** Rate of change of each cube-root LMS component along a chroma direction (a, b). */\nfunction lmsSlopes(a: number, b: number): Vector {\n\treturn [LAB_TO_LMS[0], LAB_TO_LMS[1], LAB_TO_LMS[2]].map((row) => row[1] * a + row[2] * b) as Vector;\n}\n\n/** Largest saturation (C/L) inside sRGB for hue (a, b): polynomial fit plus one Halley step. */\nfunction maxSaturation(a: number, b: number): number {\n\tconst channel = SATURATION_FIT.findIndex(([[x, y]], index) => index === 2 || x * a + y * b > 1);\n\tconst [k0, k1, k2, k3, k4] = SATURATION_FIT[channel][1];\n\tconst weights = LMS_TO_LINEAR_SRGB[channel];\n\tconst saturation = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;\n\n\tconst slopes = lmsSlopes(a, b);\n\tconst base = slopes.map((k) => 1 + saturation * k);\n\tconst dot = (values: number[]) => values.reduce((sum, value, index) => sum + weights[index] * value, 0);\n\tconst f = dot(base.map((value) => value ** 3));\n\tconst f1 = dot(base.map((value, index) => 3 * slopes[index] * value ** 2));\n\tconst f2 = dot(base.map((value, index) => 6 * slopes[index] ** 2 * value));\n\treturn saturation - (f * f1) / (f1 * f1 - 0.5 * f * f2);\n}\n\n/** Oklab lightness and chroma of the most saturated sRGB color of hue (a, b). */\nfunction cusp(a: number, b: number): [number, number] {\n\tconst saturation = maxSaturation(a, b);\n\tconst lightness = Math.cbrt(1 / Math.max(...oklabToLinearSrgb([1, saturation * a, saturation * b])));\n\treturn [lightness, lightness * saturation];\n}\n\n/** Chroma where the constant-lightness line at `lightness` leaves the sRGB gamut. */\nfunction maxChroma(a: number, b: number, lightness: number, [cuspL, cuspC]: [number, number]): number {\n\tif (lightness <= cuspL) return (cuspC * lightness) / cuspL;\n\t// Upper half: triangle edge, then one Halley step against each channel reaching 1.\n\tconst t = (cuspC * (lightness - 1)) / (cuspL - 1);\n\tconst slopes = lmsSlopes(a, b);\n\tconst lms = slopes.map((k) => lightness + t * k);\n\tconst cubes = lms.map((value) => value ** 3);\n\tconst first = lms.map((value, index) => 3 * slopes[index] * value ** 2);\n\tconst second = lms.map((value, index) => 6 * slopes[index] ** 2 * value);\n\tconst dot = (row: Vector, values: number[]) => row[0] * values[0] + row[1] * values[1] + row[2] * values[2];\n\tconst steps = LMS_TO_LINEAR_SRGB.map((row) => {\n\t\tconst f = dot(row, cubes) - 1;\n\t\tconst f1 = dot(row, first);\n\t\tconst f2 = dot(row, second);\n\t\tconst u = f1 / (f1 * f1 - 0.5 * f * f2);\n\t\treturn u >= 0 ? -f * u : Number.MAX_VALUE;\n\t});\n\treturn t + Math.min(...steps);\n}\n\n/** OKHSL's chroma reference points at lightness L and hue (a, b): [c0, cMid, cMax]. */\nfunction chromaStops(L: number, a: number, b: number): [number, number, number] {\n\tconst peak = cusp(a, b);\n\tconst cMax = maxChroma(a, b, L, peak);\n\tconst k = cMax / Math.min(L * (peak[1] / peak[0]), (1 - L) * (peak[1] / (1 - peak[0])));\n\tconst midS =\n\t\t0.11516993 +\n\t\t1 /\n\t\t\t(7.4477897 +\n\t\t\t\t4.1590124 * b +\n\t\t\t\ta *\n\t\t\t\t\t(-2.19557347 +\n\t\t\t\t\t\t1.75198401 * b +\n\t\t\t\t\t\ta * (-2.13704948 - 10.02301043 * b + a * (-4.24894561 + 5.38770819 * b + 4.69891013 * a))));\n\tconst midT =\n\t\t0.11239642 +\n\t\t1 /\n\t\t\t(1.6132032 -\n\t\t\t\t0.68124379 * b +\n\t\t\t\ta *\n\t\t\t\t\t(0.40370612 +\n\t\t\t\t\t\t0.90148123 * b +\n\t\t\t\t\t\ta * (-0.27087943 + 0.6122399 * b + a * (0.00299215 - 0.45399568 * b - 0.14661872 * a))));\n\tconst cMid = 0.9 * k * Math.sqrt(Math.sqrt(1 / (1 / (L * midS) ** 4 + 1 / ((1 - L) * midT) ** 4)));\n\tconst c0 = Math.sqrt(1 / (1 / (L * 0.4) ** 2 + 1 / ((1 - L) * 0.8) ** 2));\n\treturn [c0, cMid, cMax];\n}\n\n/**\n * Convert OKHSL to sRGB channels (0-255, rounded), clipping out-of-gamut channels.\n * @param hue Hue in degrees.\n * @param saturation Saturation, 0-1.\n * @param lightness Lightness, 0-1.\n */\nexport function okhslToRgb(hue: number, saturation: number, lightness: number): RgbColor {\n\tconst L = okhslToOklabLightness(lightness);\n\tlet lab: Vector = [L, 0, 0];\n\tif (L > 0 && L < 1 && saturation > 0) {\n\t\tconst angle = (2 * Math.PI * (((hue % 360) + 360) % 360)) / 360;\n\t\tconst a = Math.cos(angle);\n\t\tconst b = Math.sin(angle);\n\t\tconst [c0, cMid, cMax] = chromaStops(L, a, b);\n\t\t// Chroma rises from 0 through cMid at s = 0.8 to cMax at s = 1.\n\t\tlet chroma: number;\n\t\tif (saturation < 0.8) {\n\t\t\tconst t = 1.25 * saturation;\n\t\t\tconst k1 = 0.8 * c0;\n\t\t\tchroma = (t * k1) / (1 - (1 - k1 / cMid) * t);\n\t\t} else {\n\t\t\tconst t = 5 * (saturation - 0.8);\n\t\t\tconst k1 = (0.2 * cMid ** 2 * 1.25 ** 2) / c0;\n\t\t\tchroma = cMid + (t * k1) / (1 - (1 - k1 / (cMax - cMid)) * t);\n\t\t}\n\t\tlab = [L, chroma * a, chroma * b];\n\t}\n\treturn linearSrgbToRgb(oklabToLinearSrgb(lab));\n}\n\n/**\n * Convert sRGB channels (0-255) to OKHSL.\n * @returns Hue `h` in degrees (0 for grays), saturation `s` and lightness `l` 0-1.\n */\nexport function rgbToOkhsl(rgb: RgbColor): { h: number; s: number; l: number } {\n\tconst [L, labA, labB] = rgbToOklab(rgb);\n\tconst chroma = Math.hypot(labA, labB);\n\tconst lightness = oklabToOkhslLightness(L);\n\tif (chroma < 1e-9 || lightness <= 0 || lightness >= 1) return { h: 0, s: 0, l: lightness };\n\n\tconst hue = ((Math.atan2(labB, labA) * 180) / Math.PI + 360) % 360;\n\tconst [c0, cMid, cMax] = chromaStops(L, labA / chroma, labB / chroma);\n\tlet saturation: number;\n\tif (chroma < cMid) {\n\t\tconst k1 = 0.8 * c0;\n\t\tsaturation = 0.8 * (chroma / (k1 + (1 - k1 / cMid) * chroma));\n\t} else {\n\t\tconst k1 = (0.2 * cMid ** 2 * 1.25 ** 2) / c0;\n\t\tconst offset = chroma - cMid;\n\t\tsaturation = 0.8 + 0.2 * (offset / (k1 + (1 - k1 / (cMax - cMid)) * offset));\n\t}\n\treturn { h: hue, s: Math.min(1, Math.max(0, saturation)), l: lightness };\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Program Status Protocol (OSC 7501): a program tells the terminal whether it is idle, working,
|
|
3
|
+
* blocked on the user, done, or failed. Only the root record is supported.
|
|
4
|
+
*
|
|
5
|
+
* Spec: https://www.superlogical.com/rex/docs/build/program-status
|
|
6
|
+
*/
|
|
7
|
+
export interface ProgramStatus {
|
|
8
|
+
/** `clear` removes the status instead of reporting one. */
|
|
9
|
+
state: "idle" | "working" | "blocked" | "done" | "error" | "clear";
|
|
10
|
+
/** Stable program name, `[A-Za-z0-9_.+-]{1,32}`. Other values are omitted. */
|
|
11
|
+
app?: string;
|
|
12
|
+
/** What a blocked program waits for. Omitted for other states. */
|
|
13
|
+
kind?: "permission" | "question" | "auth";
|
|
14
|
+
/** One human-readable line. Control characters become spaces; longer text is cut to the spec limit. */
|
|
15
|
+
message?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Feature detection query. A supporting terminal replies with the same body. */
|
|
18
|
+
export declare const PROGRAM_STATUS_QUERY = "\u001B]7501;?\u001B\\";
|
|
19
|
+
/** The reply to {@link PROGRAM_STATUS_QUERY}. Later spec revisions may add pairs after the `?`. */
|
|
20
|
+
export declare function isProgramStatusReply(sequence: string): boolean;
|
|
21
|
+
/** Encode a status report. Terminals discard reports whose text contains control characters, so they are replaced. */
|
|
22
|
+
export declare function formatProgramStatus(status: ProgramStatus): string;
|
|
23
|
+
//# sourceMappingURL=program-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program-status.d.ts","sourceRoot":"","sources":["../src/program-status.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC7B,2DAA2D;IAC3D,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IACnE,8EAA8E;IAC9E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,IAAI,CAAC,EAAE,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;IAC1C,uGAAuG;IACvG,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,iFAAiF;AACjF,eAAO,MAAM,oBAAoB,0BAAsB,CAAC;AAExD,mGAAmG;AACnG,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE9D;AAoBD,sHAAsH;AACtH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAOjE"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Program Status Protocol (OSC 7501): a program tells the terminal whether it is idle, working,
|
|
3
|
+
* blocked on the user, done, or failed. Only the root record is supported.
|
|
4
|
+
*
|
|
5
|
+
* Spec: https://www.superlogical.com/rex/docs/build/program-status
|
|
6
|
+
*/
|
|
7
|
+
/** Feature detection query. A supporting terminal replies with the same body. */
|
|
8
|
+
export const PROGRAM_STATUS_QUERY = "\x1b]7501;?\x1b\\";
|
|
9
|
+
/** The reply to {@link PROGRAM_STATUS_QUERY}. Later spec revisions may add pairs after the `?`. */
|
|
10
|
+
export function isProgramStatusReply(sequence) {
|
|
11
|
+
return /^\x1b\]7501;\?[^\x07\x1b]*(?:\x07|\x1b\\)$/.test(sequence);
|
|
12
|
+
}
|
|
13
|
+
const APP_PATTERN = /^[A-Za-z0-9_.+-]{1,32}$/;
|
|
14
|
+
const CONTROL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f]+/g;
|
|
15
|
+
/** Decoded `msg` limit. Its base64 encoding stays under the 2732-byte encoded limit. */
|
|
16
|
+
const MAX_MESSAGE_BYTES = 2048;
|
|
17
|
+
function truncateUtf8(text, maxBytes) {
|
|
18
|
+
if (Buffer.byteLength(text, "utf8") <= maxBytes)
|
|
19
|
+
return text;
|
|
20
|
+
let bytes = 0;
|
|
21
|
+
let end = 0;
|
|
22
|
+
for (const char of text) {
|
|
23
|
+
const size = Buffer.byteLength(char, "utf8");
|
|
24
|
+
if (bytes + size > maxBytes)
|
|
25
|
+
break;
|
|
26
|
+
bytes += size;
|
|
27
|
+
end += char.length;
|
|
28
|
+
}
|
|
29
|
+
return text.slice(0, end);
|
|
30
|
+
}
|
|
31
|
+
/** Encode a status report. Terminals discard reports whose text contains control characters, so they are replaced. */
|
|
32
|
+
export function formatProgramStatus(status) {
|
|
33
|
+
const pairs = [`state=${status.state}`];
|
|
34
|
+
if (status.app !== undefined && APP_PATTERN.test(status.app))
|
|
35
|
+
pairs.push(`app=${status.app}`);
|
|
36
|
+
if (status.state === "blocked" && status.kind)
|
|
37
|
+
pairs.push(`kind=${status.kind}`);
|
|
38
|
+
const message = truncateUtf8((status.message ?? "").replace(CONTROL_CHARACTERS, " ").trim(), MAX_MESSAGE_BYTES);
|
|
39
|
+
if (message)
|
|
40
|
+
pairs.push(`msg=${Buffer.from(message, "utf8").toString("base64")}`);
|
|
41
|
+
return `\x1b]7501;${pairs.join(":")}\x1b\\`;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=program-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program-status.js","sourceRoot":"","sources":["../src/program-status.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,iFAAiF;AACjF,MAAM,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAC;AAExD,mGAAmG;AACnG,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACpD,OAAO,4CAA4C,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,WAAW,GAAG,yBAAyB,CAAC;AAC9C,MAAM,kBAAkB,GAAG,gCAAgC,CAAC;AAC5D,wFAAwF;AACxF,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAE/B,SAAS,YAAY,CAAC,IAAY,EAAE,QAAgB;IACnD,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC7D,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC7C,IAAI,KAAK,GAAG,IAAI,GAAG,QAAQ;YAAE,MAAM;QACnC,KAAK,IAAI,IAAI,CAAC;QACd,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC3B,CAAC;AAED,sHAAsH;AACtH,MAAM,UAAU,mBAAmB,CAAC,MAAqB;IACxD,MAAM,KAAK,GAAG,CAAC,SAAS,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IACxC,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IAC9F,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACjF,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,iBAAiB,CAAC,CAAC;IAChH,IAAI,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAClF,OAAO,aAAa,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;AAC7C,CAAC","sourcesContent":["/**\n * Program Status Protocol (OSC 7501): a program tells the terminal whether it is idle, working,\n * blocked on the user, done, or failed. Only the root record is supported.\n *\n * Spec: https://www.superlogical.com/rex/docs/build/program-status\n */\n\nexport interface ProgramStatus {\n\t/** `clear` removes the status instead of reporting one. */\n\tstate: \"idle\" | \"working\" | \"blocked\" | \"done\" | \"error\" | \"clear\";\n\t/** Stable program name, `[A-Za-z0-9_.+-]{1,32}`. Other values are omitted. */\n\tapp?: string;\n\t/** What a blocked program waits for. Omitted for other states. */\n\tkind?: \"permission\" | \"question\" | \"auth\";\n\t/** One human-readable line. Control characters become spaces; longer text is cut to the spec limit. */\n\tmessage?: string;\n}\n\n/** Feature detection query. A supporting terminal replies with the same body. */\nexport const PROGRAM_STATUS_QUERY = \"\\x1b]7501;?\\x1b\\\\\";\n\n/** The reply to {@link PROGRAM_STATUS_QUERY}. Later spec revisions may add pairs after the `?`. */\nexport function isProgramStatusReply(sequence: string): boolean {\n\treturn /^\\x1b\\]7501;\\?[^\\x07\\x1b]*(?:\\x07|\\x1b\\\\)$/.test(sequence);\n}\n\nconst APP_PATTERN = /^[A-Za-z0-9_.+-]{1,32}$/;\nconst CONTROL_CHARACTERS = /[\\u0000-\\u001f\\u007f-\\u009f]+/g;\n/** Decoded `msg` limit. Its base64 encoding stays under the 2732-byte encoded limit. */\nconst MAX_MESSAGE_BYTES = 2048;\n\nfunction truncateUtf8(text: string, maxBytes: number): string {\n\tif (Buffer.byteLength(text, \"utf8\") <= maxBytes) return text;\n\tlet bytes = 0;\n\tlet end = 0;\n\tfor (const char of text) {\n\t\tconst size = Buffer.byteLength(char, \"utf8\");\n\t\tif (bytes + size > maxBytes) break;\n\t\tbytes += size;\n\t\tend += char.length;\n\t}\n\treturn text.slice(0, end);\n}\n\n/** Encode a status report. Terminals discard reports whose text contains control characters, so they are replaced. */\nexport function formatProgramStatus(status: ProgramStatus): string {\n\tconst pairs = [`state=${status.state}`];\n\tif (status.app !== undefined && APP_PATTERN.test(status.app)) pairs.push(`app=${status.app}`);\n\tif (status.state === \"blocked\" && status.kind) pairs.push(`kind=${status.kind}`);\n\tconst message = truncateUtf8((status.message ?? \"\").replace(CONTROL_CHARACTERS, \" \").trim(), MAX_MESSAGE_BYTES);\n\tif (message) pairs.push(`msg=${Buffer.from(message, \"utf8\").toString(\"base64\")}`);\n\treturn `\\x1b]7501;${pairs.join(\":\")}\\x1b\\\\`;\n}\n"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StdinBuffer buffers input and emits complete sequences.
|
|
3
|
+
*
|
|
4
|
+
* This is necessary because stdin data events can arrive in partial chunks,
|
|
5
|
+
* especially for escape sequences like mouse events. Without buffering,
|
|
6
|
+
* partial sequences can be misinterpreted as regular keypresses.
|
|
7
|
+
*
|
|
8
|
+
* For example, the mouse SGR sequence `\x1b[<35;20;5m` might arrive as:
|
|
9
|
+
* - Event 1: `\x1b`
|
|
10
|
+
* - Event 2: `[<35`
|
|
11
|
+
* - Event 3: `;20;5m`
|
|
12
|
+
*
|
|
13
|
+
* The buffer accumulates these until a complete sequence is detected.
|
|
14
|
+
* Call the `process()` method to feed input data.
|
|
15
|
+
*
|
|
16
|
+
* Based on code from OpenTUI (https://github.com/anomalyco/opentui)
|
|
17
|
+
* MIT License - Copyright (c) 2025 opentui
|
|
18
|
+
*/
|
|
19
|
+
import { EventEmitter } from "events";
|
|
20
|
+
export type StdinBufferOptions = {
|
|
21
|
+
/**
|
|
22
|
+
* Maximum time to wait for an incomplete sequence such as CSI or mouse
|
|
23
|
+
* (default: 50ms).
|
|
24
|
+
*/
|
|
25
|
+
timeout?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Maximum time to wait after a lone ESC before treating it as Escape
|
|
28
|
+
* (default: 10ms). Increase for high-latency Alt+key input (SSH).
|
|
29
|
+
*/
|
|
30
|
+
escapeTimeout?: number;
|
|
31
|
+
};
|
|
32
|
+
export type StdinBufferEventMap = {
|
|
33
|
+
data: [string];
|
|
34
|
+
paste: [string];
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Buffers stdin input and emits complete sequences via the 'data' event.
|
|
38
|
+
* Handles partial escape sequences that arrive across multiple chunks.
|
|
39
|
+
*/
|
|
40
|
+
export declare class StdinBuffer extends EventEmitter<StdinBufferEventMap> {
|
|
41
|
+
private buffer;
|
|
42
|
+
private timeout;
|
|
43
|
+
private readonly timeoutMs;
|
|
44
|
+
private readonly escapeTimeoutMs;
|
|
45
|
+
private pasteMode;
|
|
46
|
+
private pasteBuffer;
|
|
47
|
+
private pendingKittyPrintableCodepoint;
|
|
48
|
+
constructor(options?: StdinBufferOptions);
|
|
49
|
+
process(data: string | Buffer): void;
|
|
50
|
+
private emitDataSequence;
|
|
51
|
+
flush(): string[];
|
|
52
|
+
clear(): void;
|
|
53
|
+
getBuffer(): string;
|
|
54
|
+
destroy(): void;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=stdin-buffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdin-buffer.d.ts","sourceRoot":"","sources":["../src/stdin-buffer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AA+OtC,MAAM,MAAM,kBAAkB,GAAG;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC;IACf,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC;CAChB,CAAC;AAEF;;;GAGG;AACH,qBAAa,WAAY,SAAQ,YAAY,CAAC,mBAAmB,CAAC;IACjE,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAA8C;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,8BAA8B,CAAqB;IAE3D,YAAY,OAAO,GAAE,kBAAuB,EAI3C;IAEM,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAqG1C;IAED,OAAO,CAAC,gBAAgB;IAWxB,KAAK,IAAI,MAAM,EAAE,CAchB;IAED,KAAK,IAAI,IAAI,CASZ;IAED,SAAS,IAAI,MAAM,CAElB;IAED,OAAO,IAAI,IAAI,CAEd;CACD"}
|