@alchemy.run/sigil 0.0.0-alpha.1 → 0.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/README.md +499 -313
  2. package/THIRD_PARTY_NOTICES.md +70 -23
  3. package/dist/Text-DV9CuzAT.d.ts +452 -0
  4. package/dist/ansi.d.ts +217 -0
  5. package/dist/ansi.js +87 -0
  6. package/dist/capabilities.d.ts +5 -0
  7. package/dist/capabilities.js +3 -0
  8. package/dist/cell-_ZVhbfl0.js +44 -0
  9. package/dist/color-CkbalRqK.js +2 -0
  10. package/dist/color-policy-BAC9-TZX.js +592 -0
  11. package/dist/color-policy-CCxuHIdD.d.ts +22 -0
  12. package/dist/color-profile-CyeHnG1T.d.ts +97 -0
  13. package/dist/color-profile-DHhQHY55.js +36 -0
  14. package/dist/color.d.ts +21 -0
  15. package/dist/color.js +3 -0
  16. package/dist/cursor-position-D2LAkRG0.d.ts +7 -0
  17. package/dist/detect-B3dL4Q11.js +374 -0
  18. package/dist/detect-Db6GbKOm.d.ts +195 -0
  19. package/dist/{devtools-QpCMm9JH.mjs → devtools-DbthxoD1.js} +23 -24
  20. package/dist/env-YVw64yZS.js +9 -0
  21. package/dist/escapes-CB_6CWOE.d.ts +72 -0
  22. package/dist/geometry-BxXOzJgo.d.ts +11 -0
  23. package/dist/index-D48vQhhe.d.ts +21 -0
  24. package/dist/index-DDVME65c.d.ts +919 -0
  25. package/dist/index.d.ts +1310 -0
  26. package/dist/index.js +3209 -0
  27. package/dist/osc-BFKKSqpg.js +71 -0
  28. package/dist/osc-Cn0fw77g.d.ts +23 -0
  29. package/dist/paint-Cx-zC_sX.d.ts +81 -0
  30. package/dist/query-BNc2B8GD.d.ts +152 -0
  31. package/dist/router.d.ts +392 -0
  32. package/dist/router.js +709 -0
  33. package/dist/sample-Cqw1bjUL.js +445 -0
  34. package/dist/screen-CgC2WlVM.d.ts +49 -0
  35. package/dist/screen-CiPytswf.js +342 -0
  36. package/dist/screen.d.ts +5 -0
  37. package/dist/screen.js +5 -0
  38. package/dist/semantic-text-style-DIMzC7xt.js +91 -0
  39. package/dist/serialize-BTkAZgw1.js +79 -0
  40. package/dist/session-DDQ5V300.js +723 -0
  41. package/dist/sgr-BhwaWAJB.js +246 -0
  42. package/dist/store-C1P5fOUi.d.ts +72 -0
  43. package/dist/string-width-CijQwpIk.js +69 -0
  44. package/dist/strip-BvU4toXG.js +6 -0
  45. package/dist/terminal.d.ts +121 -0
  46. package/dist/terminal.js +2 -0
  47. package/dist/tokenize-AjqbvtiT.js +1242 -0
  48. package/dist/tokenize-Dx1y_l5H.d.ts +57 -0
  49. package/dist/truncate-D31fhU6i.js +562 -0
  50. package/dist/use-focus-CcCIdCWA.js +1337 -0
  51. package/dist/yoga-5jKhYCJC.js +3465 -0
  52. package/dist/yoga.d.ts +2 -0
  53. package/dist/yoga.js +2 -0
  54. package/package.json +70 -24
  55. package/src/ansi/chalk.ts +138 -0
  56. package/src/ansi/cursor.ts +46 -0
  57. package/src/ansi/east-asian-width.ts +259 -0
  58. package/src/ansi/escapes.ts +120 -0
  59. package/src/ansi/graphemes.ts +8 -0
  60. package/src/ansi/hyperlink.ts +44 -0
  61. package/src/ansi/index.ts +27 -0
  62. package/src/ansi/osc.ts +77 -0
  63. package/src/ansi/sgr.ts +234 -0
  64. package/src/ansi/slice.ts +43 -0
  65. package/src/ansi/string-width.ts +121 -0
  66. package/src/ansi/strip.ts +13 -0
  67. package/src/ansi/tokenize.ts +380 -0
  68. package/src/ansi/truncate.ts +196 -0
  69. package/src/ansi/wrap.ts +765 -0
  70. package/src/ansi-tokenizer.ts +510 -0
  71. package/src/capabilities/color-policy.ts +34 -0
  72. package/src/capabilities/detect.ts +608 -0
  73. package/src/capabilities/index.ts +37 -0
  74. package/src/capabilities/query.ts +679 -0
  75. package/src/capabilities/store.ts +394 -0
  76. package/src/code-excerpt.ts +39 -0
  77. package/src/color/index.ts +3 -0
  78. package/src/color/paint.ts +169 -0
  79. package/src/color/palette.ts +48 -0
  80. package/src/color/sample.ts +323 -0
  81. package/src/color.ts +1 -0
  82. package/src/components/AccessibilityContext.ts +5 -0
  83. package/src/components/AnimationContext.ts +24 -0
  84. package/src/components/AnsiText.tsx +42 -0
  85. package/src/components/App.tsx +878 -0
  86. package/src/components/AppContext.ts +111 -0
  87. package/src/components/BackgroundContext.ts +7 -0
  88. package/src/components/Box.tsx +100 -0
  89. package/src/components/CursorContext.ts +19 -0
  90. package/src/components/ErrorBoundary.tsx +39 -0
  91. package/src/components/ErrorOverview.tsx +135 -0
  92. package/src/components/FocusContext.ts +30 -0
  93. package/src/components/Hyperlink.tsx +56 -0
  94. package/src/components/Newline.tsx +16 -0
  95. package/src/components/Spacer.tsx +11 -0
  96. package/src/components/Static.tsx +60 -0
  97. package/src/components/StderrContext.ts +24 -0
  98. package/src/components/StdinContext.ts +48 -0
  99. package/src/components/StdoutContext.ts +26 -0
  100. package/src/components/TerminalOscContext.ts +25 -0
  101. package/src/components/Text.tsx +122 -0
  102. package/src/components/Transform.tsx +38 -0
  103. package/src/components/VirtualList.tsx +128 -0
  104. package/src/cursor-position.ts +103 -0
  105. package/src/devtools.ts +103 -0
  106. package/src/dom.ts +301 -0
  107. package/src/env.ts +12 -0
  108. package/src/get-max-width.ts +11 -0
  109. package/src/global.d.ts +38 -0
  110. package/src/glyphs.ts +99 -0
  111. package/src/hooks/use-animation.ts +142 -0
  112. package/src/hooks/use-app.ts +8 -0
  113. package/src/hooks/use-box-metrics.ts +134 -0
  114. package/src/hooks/use-capabilities.ts +73 -0
  115. package/src/hooks/use-cursor.ts +33 -0
  116. package/src/hooks/use-focus-manager.ts +62 -0
  117. package/src/hooks/use-focus.ts +82 -0
  118. package/src/hooks/use-input.ts +267 -0
  119. package/src/hooks/use-is-screen-reader-enabled.ts +12 -0
  120. package/src/hooks/use-paste.ts +78 -0
  121. package/src/hooks/use-stderr.ts +8 -0
  122. package/src/hooks/use-stdin.ts +10 -0
  123. package/src/hooks/use-stdout.ts +8 -0
  124. package/src/hooks/use-terminal-osc.ts +59 -0
  125. package/src/hooks/use-virtual-scroll.ts +84 -0
  126. package/src/hooks/use-window-size.ts +37 -0
  127. package/src/index.ts +96 -0
  128. package/src/ink.tsx +1452 -0
  129. package/src/input-parser.ts +303 -0
  130. package/src/instances.ts +9 -0
  131. package/src/kitty-keyboard.ts +185 -0
  132. package/src/measure-element.ts +62 -0
  133. package/src/measure-text.ts +31 -0
  134. package/src/paint-tree.ts +220 -0
  135. package/src/parse-keypress.ts +515 -0
  136. package/src/parse-stack-line.ts +138 -0
  137. package/src/patch-console.ts +106 -0
  138. package/src/quick-lru.ts +85 -0
  139. package/src/reconciler.ts +425 -0
  140. package/src/render-background.ts +59 -0
  141. package/src/render-border.ts +167 -0
  142. package/src/render-frame.ts +83 -0
  143. package/src/render-to-string.ts +146 -0
  144. package/src/render.ts +284 -0
  145. package/src/router/components.tsx +343 -0
  146. package/src/router/context.ts +41 -0
  147. package/src/router/history.ts +194 -0
  148. package/src/router/hooks.tsx +391 -0
  149. package/src/router/index.ts +34 -0
  150. package/src/router/matcher.ts +571 -0
  151. package/src/sanitize-ansi.ts +33 -0
  152. package/src/screen/ansi.ts +184 -0
  153. package/src/screen/canvas.ts +160 -0
  154. package/src/screen/cell.ts +138 -0
  155. package/src/screen/color-profile.ts +47 -0
  156. package/src/screen/geometry.ts +9 -0
  157. package/src/screen/index.ts +6 -0
  158. package/src/screen/screen.ts +305 -0
  159. package/src/screen/serialize.ts +129 -0
  160. package/src/screen.ts +1 -0
  161. package/src/semantic-text-style.ts +118 -0
  162. package/src/signal-exit.ts +106 -0
  163. package/src/squash-text-nodes.ts +37 -0
  164. package/src/stream.ts +28 -0
  165. package/src/structured-text.ts +325 -0
  166. package/src/styles.ts +753 -0
  167. package/src/terminal/index.ts +2 -0
  168. package/src/terminal/inline-presenter.ts +120 -0
  169. package/src/terminal/input.ts +92 -0
  170. package/src/terminal/render-scheduler.ts +37 -0
  171. package/src/terminal/screen-presenter.ts +242 -0
  172. package/src/terminal/session.ts +408 -0
  173. package/src/terminal-size.ts +58 -0
  174. package/src/terminal.ts +1 -0
  175. package/src/testing/browser.ts +588 -0
  176. package/src/testing/emulators.ts +205 -0
  177. package/src/testing/explorer-app/index.html +12 -0
  178. package/src/testing/explorer-app/main.ts +381 -0
  179. package/src/testing/explorer-app/style.css +194 -0
  180. package/src/testing/explorer-app/tsconfig.json +15 -0
  181. package/src/testing/explorer-app/vite-env.d.ts +1 -0
  182. package/src/testing/index.ts +26 -0
  183. package/src/testing/keys.ts +56 -0
  184. package/src/testing/live.ts +85 -0
  185. package/src/testing/matchers.ts +70 -0
  186. package/src/testing/public.ts +94 -0
  187. package/src/testing/terminal.ts +361 -0
  188. package/src/testing/vitest.ts +157 -0
  189. package/src/throttle.ts +73 -0
  190. package/src/transform-adapter.ts +14 -0
  191. package/src/types.ts +10 -0
  192. package/src/virtual-scroll.ts +133 -0
  193. package/src/wrap-text.ts +54 -0
  194. package/src/yoga/config.ts +57 -0
  195. package/src/yoga/core/absoluteLayout.ts +626 -0
  196. package/src/yoga/core/baseline.ts +66 -0
  197. package/src/yoga/core/cache.ts +136 -0
  198. package/src/yoga/core/calculateLayout.ts +2926 -0
  199. package/src/yoga/core/config.ts +104 -0
  200. package/src/yoga/core/flexLine.ts +177 -0
  201. package/src/yoga/core/helpers.ts +293 -0
  202. package/src/yoga/core/layoutResults.ts +167 -0
  203. package/src/yoga/core/node.ts +611 -0
  204. package/src/yoga/core/numeric.ts +44 -0
  205. package/src/yoga/core/pixelGrid.ts +151 -0
  206. package/src/yoga/core/style.ts +887 -0
  207. package/src/yoga/core/types.ts +224 -0
  208. package/src/yoga/generated/YGEnums.ts +263 -0
  209. package/src/yoga/index.ts +19 -0
  210. package/src/yoga/node.ts +1140 -0
  211. package/dist/index.d.mts +0 -2379
  212. package/dist/index.mjs +0 -10072
@@ -0,0 +1,323 @@
1
+ import {
2
+ rgb,
3
+ type GradientStop,
4
+ type InterpolationSpace,
5
+ type LinearGradient,
6
+ type Paint,
7
+ type PaintContext,
8
+ type PerimeterGradient,
9
+ } from "#/color/paint.ts";
10
+ import { colorToRgb } from "#/color/palette.ts";
11
+ import type { Color, RgbColor } from "#/screen/cell.ts";
12
+ import type { Rect } from "#/screen/geometry.ts";
13
+ import { parseSemanticColor } from "#/semantic-text-style.ts";
14
+
15
+ export function samplePaint(
16
+ paint: Paint,
17
+ x: number,
18
+ y: number,
19
+ bounds: Rect,
20
+ context: PaintContext = {},
21
+ ): Color | undefined {
22
+ const resolved = resolveConditional(paint, context);
23
+ if (resolved && typeof resolved === "object" && "type" in resolved) {
24
+ if (resolved.type === "perimeter-gradient") {
25
+ return samplePerimeterGradient(resolved, x, y, bounds, context);
26
+ }
27
+ }
28
+ if (isLinearGradient(resolved)) {
29
+ return sampleGradient(resolved, x, y, bounds, context);
30
+ }
31
+ return resolveColor(resolved);
32
+ }
33
+
34
+ export function blend(source: Color, destination: Color, palette?: PaintContext["palette"]): Color {
35
+ const foreground = colorToRgb(source, palette);
36
+ if (foreground.alpha >= 255) return foreground;
37
+ const background = colorToRgb(destination, palette);
38
+ const alpha = foreground.alpha / 255;
39
+ return rgb(
40
+ foreground.red * alpha + background.red * (1 - alpha),
41
+ foreground.green * alpha + background.green * (1 - alpha),
42
+ foreground.blue * alpha + background.blue * (1 - alpha),
43
+ );
44
+ }
45
+
46
+ /** Progressively moves a color toward white in perceptual OKLab space. */
47
+ export function lighten(color: Color, amount: number, palette?: PaintContext["palette"]): RgbColor {
48
+ return interpolateColor(color, rgb(255, 255, 255), amount, "oklab", palette);
49
+ }
50
+
51
+ /** Progressively moves a color toward black in perceptual OKLab space. */
52
+ export function darken(color: Color, amount: number, palette?: PaintContext["palette"]): RgbColor {
53
+ return interpolateColor(color, rgb(0, 0, 0), amount, "oklab", palette);
54
+ }
55
+
56
+ function sampleGradient(
57
+ gradient: LinearGradient,
58
+ x: number,
59
+ y: number,
60
+ bounds: Rect,
61
+ context: PaintContext,
62
+ ): Color | undefined {
63
+ const radians = (gradient.angle * Math.PI) / 180;
64
+ const dx = Math.cos(radians);
65
+ const dy = Math.sin(radians);
66
+ const width = Math.max(1, bounds.width - 1);
67
+ const height = Math.max(1, bounds.height - 1);
68
+ const projections = [0, width * dx, height * dy, width * dx + height * dy];
69
+ const minimum = Math.min(...projections);
70
+ const maximum = Math.max(...projections);
71
+ const projection = (x - bounds.x) * dx + (y - bounds.y) * dy;
72
+ const position = maximum === minimum ? 0 : (projection - minimum) / (maximum - minimum);
73
+ return sampleStops(gradient.stops, position, gradient.space, x, y, bounds, context);
74
+ }
75
+
76
+ function samplePerimeterGradient(
77
+ gradient: PerimeterGradient,
78
+ x: number,
79
+ y: number,
80
+ bounds: Rect,
81
+ context: PaintContext,
82
+ ): Color | undefined {
83
+ const width = Math.max(1, bounds.width);
84
+ const height = Math.max(1, bounds.height);
85
+ const steps = width === 1 || height === 1 ? Math.max(width, height) : 2 * width + 2 * height - 4;
86
+ if (steps <= 1) return samplePaint(gradient.stops[0]!.color, x, y, bounds, context);
87
+
88
+ const left = bounds.x;
89
+ const top = bounds.y;
90
+ const right = left + width - 1;
91
+ const bottom = top + height - 1;
92
+ let index: number;
93
+
94
+ if (height === 1) index = x - left;
95
+ else if (width === 1) index = y - top;
96
+ else if (y <= top) index = Math.max(0, Math.min(width - 1, x - left));
97
+ else if (x >= right) index = width + Math.max(0, Math.min(height - 2, y - top - 1));
98
+ else if (y >= bottom) index = width + height - 2 + Math.max(0, Math.min(width - 1, right - x));
99
+ else index = 2 * width + height - 2 + Math.max(0, Math.min(height - 2, bottom - y - 1));
100
+
101
+ index = modulo(index - gradient.offset, steps);
102
+ const position = blendPosition(index, steps, gradient.stops.length);
103
+ return sampleStops(gradient.stops, position, gradient.space, x, y, bounds, context);
104
+ }
105
+
106
+ /** Matches Lip Gloss Blend1D's even, discrete distribution of stops. */
107
+ function blendPosition(index: number, steps: number, stopCount: number): number {
108
+ if (steps <= stopCount) return index / Math.max(1, stopCount - 1);
109
+ const segments = stopCount - 1;
110
+ const baseSize = Math.floor(steps / segments);
111
+ const remainder = steps % segments;
112
+ let start = 0;
113
+ for (let segment = 0; segment < segments; segment++) {
114
+ const size = baseSize + (segment < remainder ? 1 : 0);
115
+ if (index < start + size) {
116
+ const local = size <= 1 ? 0 : (index - start) / (size - 1);
117
+ return (segment + local) / segments;
118
+ }
119
+ start += size;
120
+ }
121
+ return 1;
122
+ }
123
+
124
+ function sampleStops(
125
+ stops: readonly GradientStop[],
126
+ position: number,
127
+ space: InterpolationSpace,
128
+ x: number,
129
+ y: number,
130
+ bounds: Rect,
131
+ context: PaintContext,
132
+ ): Color | undefined {
133
+ let right = 1;
134
+ while (right < stops.length - 1 && position > stops[right]!.offset!) right++;
135
+ const left = right - 1;
136
+ const start = stops[left]!;
137
+ const end = stops[right]!;
138
+ const span = end.offset! - start.offset!;
139
+ const amount = span === 0 ? 0 : Math.max(0, Math.min(1, (position - start.offset!) / span));
140
+ const startColor = samplePaint(start.color, x, y, bounds, context);
141
+ const endColor = samplePaint(end.color, x, y, bounds, context);
142
+ if (!startColor || !endColor) return startColor ?? endColor;
143
+ return interpolateColor(startColor, endColor, amount, space, context.palette);
144
+ }
145
+
146
+ export function interpolateColor(
147
+ from: Color,
148
+ to: Color,
149
+ amount: number,
150
+ space: InterpolationSpace = "oklab",
151
+ palette?: PaintContext["palette"],
152
+ ): RgbColor {
153
+ const a = colorToRgb(from, palette);
154
+ const b = colorToRgb(to, palette);
155
+ const t = Math.max(0, Math.min(1, amount));
156
+ if (space === "rgb")
157
+ return rgb(
158
+ mix(a.red, b.red, t),
159
+ mix(a.green, b.green, t),
160
+ mix(a.blue, b.blue, t),
161
+ mix(a.alpha, b.alpha, t),
162
+ );
163
+ if (space === "hsv") {
164
+ const ah = toHsv(a),
165
+ bh = toHsv(b);
166
+ let delta = bh[0] - ah[0];
167
+ if (delta > 180) delta -= 360;
168
+ if (delta < -180) delta += 360;
169
+ return fromHsv(
170
+ ah[0] + delta * t,
171
+ mix(ah[1], bh[1], t),
172
+ mix(ah[2], bh[2], t),
173
+ mix(a.alpha, b.alpha, t),
174
+ );
175
+ }
176
+ if (space === "lab") {
177
+ const al = toLab(a),
178
+ bl = toLab(b);
179
+ return fromLab(
180
+ mix(al[0], bl[0], t),
181
+ mix(al[1], bl[1], t),
182
+ mix(al[2], bl[2], t),
183
+ mix(a.alpha, b.alpha, t),
184
+ );
185
+ }
186
+ const al = toOklab(a),
187
+ bl = toOklab(b);
188
+ return fromOklab(
189
+ mix(al[0], bl[0], t),
190
+ mix(al[1], bl[1], t),
191
+ mix(al[2], bl[2], t),
192
+ mix(a.alpha, b.alpha, t),
193
+ );
194
+ }
195
+
196
+ const D65 = [0.95047, 1, 1.08883] as const;
197
+ function labCurve(value: number): number {
198
+ return value > (6 / 29) ** 3 ? Math.cbrt(value) : (value / 3) * (29 / 6) ** 2 + 4 / 29;
199
+ }
200
+ function inverseLabCurve(value: number): number {
201
+ return value > 6 / 29 ? value ** 3 : 3 * (6 / 29) ** 2 * (value - 4 / 29);
202
+ }
203
+ function toLab(color: RgbColor): [number, number, number] {
204
+ const r = linear(color.red),
205
+ g = linear(color.green),
206
+ b = linear(color.blue);
207
+ const x = 0.4123907992659595 * r + 0.357584339383878 * g + 0.1804807884018343 * b;
208
+ const y = 0.2126390058715104 * r + 0.7151686787677559 * g + 0.0721923153607337 * b;
209
+ const z = 0.0193308187155919 * r + 0.119194779794626 * g + 0.9505321522496606 * b;
210
+ const fy = labCurve(y / D65[1]);
211
+ return [1.16 * fy - 0.16, 5 * (labCurve(x / D65[0]) - fy), 2 * (fy - labCurve(z / D65[2]))];
212
+ }
213
+ function fromLab(l: number, a: number, b: number, alpha: number): RgbColor {
214
+ const center = (l + 0.16) / 1.16;
215
+ const x = D65[0] * inverseLabCurve(center + a / 5);
216
+ const y = D65[1] * inverseLabCurve(center);
217
+ const z = D65[2] * inverseLabCurve(center - b / 2);
218
+ return rgb(
219
+ colorfulChannel(3.240969941904521 * x - 1.5373831775700935 * y - 0.4986107602930033 * z),
220
+ colorfulChannel(-0.9692436362808798 * x + 1.8759675015077206 * y + 0.0415550574071756 * z),
221
+ colorfulChannel(0.0556300796969936 * x - 0.2039769588889766 * y + 1.0569715142428786 * z),
222
+ alpha,
223
+ );
224
+ }
225
+
226
+ const mix = (a: number, b: number, t: number) => a + (b - a) * t;
227
+ const linear = (value: number) => {
228
+ const x = value / 255;
229
+ return x <= 0.04045 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4;
230
+ };
231
+ const gamma = (value: number) =>
232
+ 255 * (value <= 0.0031308 ? 12.92 * value : 1.055 * value ** (1 / 2.4) - 0.055);
233
+ const colorfulChannel = (value: number) => {
234
+ const encoded = value <= 0.0031308 ? 12.92 * value : 1.055 * value ** (1 / 2.4) - 0.055;
235
+ return Math.floor(Math.round(Math.max(0, Math.min(1, encoded)) * 65_535) / 256);
236
+ };
237
+ function toOklab(c: RgbColor): [number, number, number] {
238
+ const r = linear(c.red),
239
+ g = linear(c.green),
240
+ b = linear(c.blue);
241
+ const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b),
242
+ m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b),
243
+ s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
244
+ return [
245
+ 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
246
+ 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
247
+ 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,
248
+ ];
249
+ }
250
+ function fromOklab(L: number, a: number, b: number, alpha: number): RgbColor {
251
+ const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3,
252
+ m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3,
253
+ s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;
254
+ return rgb(
255
+ gamma(4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s),
256
+ gamma(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s),
257
+ gamma(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s),
258
+ alpha,
259
+ );
260
+ }
261
+ function toHsv(c: RgbColor): [number, number, number] {
262
+ const r = c.red / 255,
263
+ g = c.green / 255,
264
+ b = c.blue / 255,
265
+ max = Math.max(r, g, b),
266
+ min = Math.min(r, g, b),
267
+ d = max - min;
268
+ let h = 0;
269
+ if (d)
270
+ h =
271
+ max === r
272
+ ? 60 * (((g - b) / d) % 6)
273
+ : max === g
274
+ ? 60 * ((b - r) / d + 2)
275
+ : 60 * ((r - g) / d + 4);
276
+ return [(h + 360) % 360, max === 0 ? 0 : d / max, max];
277
+ }
278
+ function fromHsv(h: number, s: number, v: number, alpha: number): RgbColor {
279
+ const c = v * s,
280
+ x = c * (1 - Math.abs(((h / 60) % 2) - 1)),
281
+ m = v - c;
282
+ const [r, g, b] =
283
+ h < 60
284
+ ? [c, x, 0]
285
+ : h < 120
286
+ ? [x, c, 0]
287
+ : h < 180
288
+ ? [0, c, x]
289
+ : h < 240
290
+ ? [0, x, c]
291
+ : h < 300
292
+ ? [x, 0, c]
293
+ : [c, 0, x];
294
+ return rgb((r + m) * 255, (g + m) * 255, (b + m) * 255, alpha);
295
+ }
296
+ function resolveConditional(paint: Paint, context: PaintContext): Paint {
297
+ if (typeof paint !== "object" || paint === null || "model" in paint) return paint;
298
+ if (paint.type === "adaptive-color")
299
+ return resolveConditional(context.appearance === "light" ? paint.light : paint.dark, context);
300
+ if (paint.type === "profile-color")
301
+ return resolveConditional(
302
+ (context.profile && paint.colors[context.profile]) ?? paint.fallback,
303
+ context,
304
+ );
305
+ return paint;
306
+ }
307
+ function resolveColor(value: Paint): Color | undefined {
308
+ return typeof value === "string"
309
+ ? parseSemanticColor(value)
310
+ : typeof value === "object" && value !== null && "model" in value
311
+ ? value
312
+ : undefined;
313
+ }
314
+ function isLinearGradient(value: Paint): value is LinearGradient {
315
+ return (
316
+ typeof value === "object" &&
317
+ value !== null &&
318
+ "type" in value &&
319
+ value.type === "linear-gradient"
320
+ );
321
+ }
322
+
323
+ const modulo = (value: number, divisor: number) => ((value % divisor) + divisor) % divisor;
package/src/color.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "#/color/index.ts";
@@ -0,0 +1,5 @@
1
+ import { createContext } from "react";
2
+
3
+ export const accessibilityContext = createContext({
4
+ isScreenReaderEnabled: false,
5
+ });
@@ -0,0 +1,24 @@
1
+ import { createContext } from "react";
2
+
3
+ type AnimationContextValue = {
4
+ readonly renderThrottleMs: number;
5
+ readonly subscribe: (
6
+ callback: (currentTime: number) => void,
7
+ interval: number,
8
+ ) => {
9
+ readonly startTime: number;
10
+ readonly unsubscribe: () => void;
11
+ };
12
+ };
13
+
14
+ export const animationContext = createContext<AnimationContextValue>({
15
+ renderThrottleMs: 0,
16
+ subscribe() {
17
+ return {
18
+ startTime: 0,
19
+ unsubscribe() {},
20
+ };
21
+ },
22
+ });
23
+
24
+ animationContext.displayName = "InternalAnimationContext";
@@ -0,0 +1,42 @@
1
+ /** @jsxImportSource react */
2
+ import { useContext } from "react";
3
+
4
+ import { stripAnsi } from "#/ansi/strip.ts";
5
+ import { accessibilityContext } from "#/components/AccessibilityContext.ts";
6
+ import { Text } from "#/components/Text.tsx";
7
+ import type { Styles } from "#/styles.ts";
8
+
9
+ export type Props = {
10
+ /** External text containing ANSI SGR styling or OSC 8 hyperlinks. */
11
+ readonly children: string;
12
+ readonly wrap?: Styles["textWrap"];
13
+ readonly "aria-label"?: string;
14
+ readonly "aria-hidden"?: boolean;
15
+ };
16
+
17
+ /**
18
+ * Renders explicitly trusted ANSI-styled output as structured terminal cells.
19
+ * Ordinary `Text` continues to strip terminal control sequences.
20
+ */
21
+ export function AnsiText({
22
+ children,
23
+ wrap = "wrap",
24
+ "aria-label": ariaLabel,
25
+ "aria-hidden": ariaHidden = false,
26
+ }: Props) {
27
+ const { isScreenReaderEnabled } = useContext(accessibilityContext);
28
+
29
+ if (isScreenReaderEnabled) {
30
+ if (ariaHidden) return null;
31
+ return <Text>{ariaLabel ?? stripAnsi(children)}</Text>;
32
+ }
33
+
34
+ return (
35
+ <ink-text
36
+ style={{ flexGrow: 0, flexShrink: 1, flexDirection: "row", textWrap: wrap }}
37
+ internal_ansi
38
+ >
39
+ {children}
40
+ </ink-text>
41
+ );
42
+ }