@alchemy.run/sigil 0.0.0-alpha.9 → 0.1.0-alpha.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.
@@ -1,1337 +0,0 @@
1
- import { U as kittyQuery } from "./sgr-BhwaWAJB.js";
2
- import { d as tokenize, h as tokenizeAnsi, l as styledCharsFromTokens, m as hasAnsiControlCharacters } from "./tokenize-AjqbvtiT.js";
3
- import { n as widestLine } from "./string-width-CijQwpIk.js";
4
- import { r as wrapAnsi, t as cliTruncate } from "./truncate-D31fhU6i.js";
5
- import { i as isSigilDev } from "./env-YVw64yZS.js";
6
- import { t as Yoga } from "./yoga-5jKhYCJC.js";
7
- import { t as cellAttributes } from "./cell-_ZVhbfl0.js";
8
- import { r as parseSemanticColor } from "./semantic-text-style-DIMzC7xt.js";
9
- import { createContext, useContext, useEffect, useEffectEvent, useId } from "react";
10
- import createReconciler from "react-reconciler";
11
- import { DefaultEventPriority, NoEventPriority } from "react-reconciler/constants.js";
12
- import { EventEmitter } from "node:events";
13
- import { jsx } from "react/jsx-runtime";
14
- import * as Scheduler from "scheduler";
15
- //#region src/components/AccessibilityContext.ts
16
- const accessibilityContext = createContext({ isScreenReaderEnabled: false });
17
- //#endregion
18
- //#region src/quick-lru.ts
19
- var QuickLru = class {
20
- #size = 0;
21
- #cache = /* @__PURE__ */ new Map();
22
- #oldCache = /* @__PURE__ */ new Map();
23
- #maxSize;
24
- constructor({ maxSize }) {
25
- if (!(maxSize && maxSize > 0)) throw new TypeError("`maxSize` must be a number greater than 0");
26
- this.#maxSize = maxSize;
27
- }
28
- get size() {
29
- let oldCacheSize = 0;
30
- for (const key of this.#oldCache.keys()) if (!this.#cache.has(key)) oldCacheSize++;
31
- return Math.min(this.#size + oldCacheSize, this.#maxSize);
32
- }
33
- get(key) {
34
- if (this.#cache.has(key)) return this.#cache.get(key);
35
- if (this.#oldCache.has(key)) {
36
- const value = this.#oldCache.get(key);
37
- this.#oldCache.delete(key);
38
- this.#set(key, value);
39
- return value;
40
- }
41
- }
42
- set(key, value) {
43
- if (this.#cache.has(key)) this.#cache.set(key, value);
44
- else this.#set(key, value);
45
- return this;
46
- }
47
- has(key) {
48
- return this.#cache.has(key) || this.#oldCache.has(key);
49
- }
50
- delete(key) {
51
- const deleted = this.#cache.delete(key);
52
- if (deleted) this.#size--;
53
- return this.#oldCache.delete(key) || deleted;
54
- }
55
- clear() {
56
- this.#cache.clear();
57
- this.#oldCache.clear();
58
- this.#size = 0;
59
- }
60
- #set(key, value) {
61
- this.#cache.set(key, value);
62
- this.#size++;
63
- if (this.#size >= this.#maxSize) {
64
- this.#size = 0;
65
- this.#oldCache = this.#cache;
66
- this.#cache = /* @__PURE__ */ new Map();
67
- }
68
- }
69
- };
70
- //#endregion
71
- //#region src/measure-text.ts
72
- const cache = new QuickLru({ maxSize: 4096 });
73
- const measureText = (text) => {
74
- if (text.length === 0) return {
75
- width: 0,
76
- height: 0
77
- };
78
- const cachedDimensions = cache.get(text);
79
- if (cachedDimensions) return cachedDimensions;
80
- const dimensions = {
81
- width: widestLine(text),
82
- height: text.split("\n").length
83
- };
84
- cache.set(text, dimensions);
85
- return dimensions;
86
- };
87
- //#endregion
88
- //#region src/sanitize-ansi.ts
89
- const sgrParametersRegex = /^[\d:;]*$/;
90
- const sanitizeAnsi = (text) => {
91
- if (!hasAnsiControlCharacters(text)) return text;
92
- let output = "";
93
- for (const token of tokenizeAnsi(text)) {
94
- if (token.type === "text" || token.type === "osc") {
95
- output += token.value;
96
- continue;
97
- }
98
- if (token.type === "csi" && token.finalCharacter === "m" && token.intermediateString === "" && sgrParametersRegex.test(token.parameterString)) output += token.value;
99
- }
100
- return output;
101
- };
102
- //#endregion
103
- //#region src/squash-text-nodes.ts
104
- const squashTextNodes = (node) => {
105
- let text = "";
106
- for (let index = 0; index < node.childNodes.length; index++) {
107
- const childNode = node.childNodes[index];
108
- if (childNode === void 0) continue;
109
- let nodeText = "";
110
- if (childNode.nodeName === "#text") nodeText = childNode.nodeValue;
111
- else {
112
- if (childNode.nodeName === "ink-text" || childNode.nodeName === "ink-virtual-text") nodeText = squashTextNodes(childNode);
113
- if (nodeText.length > 0 && typeof childNode.internal_transform === "function") nodeText = childNode.internal_transform(nodeText, index);
114
- }
115
- text += nodeText;
116
- }
117
- return sanitizeAnsi(text);
118
- };
119
- //#endregion
120
- //#region src/styles.ts
121
- const positionEdges = [
122
- ["top", Yoga.EDGE_TOP],
123
- ["right", Yoga.EDGE_RIGHT],
124
- ["bottom", Yoga.EDGE_BOTTOM],
125
- ["left", Yoga.EDGE_LEFT]
126
- ];
127
- const applyPositionStyles = (node, style) => {
128
- if ("position" in style) {
129
- let positionType = Yoga.POSITION_TYPE_RELATIVE;
130
- if (style.position === "absolute") positionType = Yoga.POSITION_TYPE_ABSOLUTE;
131
- else if (style.position === "static") positionType = Yoga.POSITION_TYPE_STATIC;
132
- node.setPositionType(positionType);
133
- }
134
- for (const [property, edge] of positionEdges) {
135
- if (!(property in style)) continue;
136
- const value = style[property];
137
- if (typeof value === "string") {
138
- node.setPositionPercent(edge, Number.parseFloat(value));
139
- continue;
140
- }
141
- node.setPosition(edge, value);
142
- }
143
- };
144
- const applyMarginStyles = (node, style) => {
145
- if ("margin" in style) node.setMargin(Yoga.EDGE_ALL, style.margin ?? 0);
146
- if ("marginX" in style) node.setMargin(Yoga.EDGE_HORIZONTAL, style.marginX ?? 0);
147
- if ("marginY" in style) node.setMargin(Yoga.EDGE_VERTICAL, style.marginY ?? 0);
148
- if ("marginLeft" in style) node.setMargin(Yoga.EDGE_START, style.marginLeft ?? 0);
149
- if ("marginRight" in style) node.setMargin(Yoga.EDGE_END, style.marginRight ?? 0);
150
- if ("marginTop" in style) node.setMargin(Yoga.EDGE_TOP, style.marginTop ?? 0);
151
- if ("marginBottom" in style) node.setMargin(Yoga.EDGE_BOTTOM, style.marginBottom ?? 0);
152
- };
153
- const applyPaddingStyles = (node, style) => {
154
- if ("padding" in style) node.setPadding(Yoga.EDGE_ALL, style.padding ?? 0);
155
- if ("paddingX" in style) node.setPadding(Yoga.EDGE_HORIZONTAL, style.paddingX ?? 0);
156
- if ("paddingY" in style) node.setPadding(Yoga.EDGE_VERTICAL, style.paddingY ?? 0);
157
- if ("paddingLeft" in style) node.setPadding(Yoga.EDGE_LEFT, style.paddingLeft ?? 0);
158
- if ("paddingRight" in style) node.setPadding(Yoga.EDGE_RIGHT, style.paddingRight ?? 0);
159
- if ("paddingTop" in style) node.setPadding(Yoga.EDGE_TOP, style.paddingTop ?? 0);
160
- if ("paddingBottom" in style) node.setPadding(Yoga.EDGE_BOTTOM, style.paddingBottom ?? 0);
161
- };
162
- const applyFlexStyles = (node, style) => {
163
- if ("flexGrow" in style) node.setFlexGrow(style.flexGrow ?? 0);
164
- if ("flexShrink" in style) node.setFlexShrink(typeof style.flexShrink === "number" ? style.flexShrink : 1);
165
- if ("flexWrap" in style) {
166
- if (style.flexWrap === "nowrap") node.setFlexWrap(Yoga.WRAP_NO_WRAP);
167
- if (style.flexWrap === "wrap") node.setFlexWrap(Yoga.WRAP_WRAP);
168
- if (style.flexWrap === "wrap-reverse") node.setFlexWrap(Yoga.WRAP_WRAP_REVERSE);
169
- }
170
- if ("flexDirection" in style) {
171
- if (style.flexDirection === "row") node.setFlexDirection(Yoga.FLEX_DIRECTION_ROW);
172
- if (style.flexDirection === "row-reverse") node.setFlexDirection(Yoga.FLEX_DIRECTION_ROW_REVERSE);
173
- if (style.flexDirection === "column") node.setFlexDirection(Yoga.FLEX_DIRECTION_COLUMN);
174
- if (style.flexDirection === "column-reverse") node.setFlexDirection(Yoga.FLEX_DIRECTION_COLUMN_REVERSE);
175
- }
176
- if ("flexBasis" in style) {
177
- if (typeof style.flexBasis === "number") node.setFlexBasis(style.flexBasis);
178
- else if (typeof style.flexBasis === "string") node.setFlexBasisPercent(Number.parseInt(style.flexBasis, 10));
179
- else node.setFlexBasisAuto();
180
- }
181
- if ("alignItems" in style) {
182
- if (style.alignItems === "stretch" || !style.alignItems) node.setAlignItems(Yoga.ALIGN_STRETCH);
183
- if (style.alignItems === "flex-start") node.setAlignItems(Yoga.ALIGN_FLEX_START);
184
- if (style.alignItems === "center") node.setAlignItems(Yoga.ALIGN_CENTER);
185
- if (style.alignItems === "flex-end") node.setAlignItems(Yoga.ALIGN_FLEX_END);
186
- if (style.alignItems === "baseline") node.setAlignItems(Yoga.ALIGN_BASELINE);
187
- }
188
- if ("alignSelf" in style) {
189
- if (style.alignSelf === "auto" || !style.alignSelf) node.setAlignSelf(Yoga.ALIGN_AUTO);
190
- if (style.alignSelf === "flex-start") node.setAlignSelf(Yoga.ALIGN_FLEX_START);
191
- if (style.alignSelf === "center") node.setAlignSelf(Yoga.ALIGN_CENTER);
192
- if (style.alignSelf === "flex-end") node.setAlignSelf(Yoga.ALIGN_FLEX_END);
193
- if (style.alignSelf === "stretch") node.setAlignSelf(Yoga.ALIGN_STRETCH);
194
- if (style.alignSelf === "baseline") node.setAlignSelf(Yoga.ALIGN_BASELINE);
195
- }
196
- if ("alignContent" in style) {
197
- if (style.alignContent === "flex-start" || !style.alignContent) node.setAlignContent(Yoga.ALIGN_FLEX_START);
198
- if (style.alignContent === "center") node.setAlignContent(Yoga.ALIGN_CENTER);
199
- if (style.alignContent === "flex-end") node.setAlignContent(Yoga.ALIGN_FLEX_END);
200
- if (style.alignContent === "space-between") node.setAlignContent(Yoga.ALIGN_SPACE_BETWEEN);
201
- if (style.alignContent === "space-around") node.setAlignContent(Yoga.ALIGN_SPACE_AROUND);
202
- if (style.alignContent === "space-evenly") node.setAlignContent(Yoga.ALIGN_SPACE_EVENLY);
203
- if (style.alignContent === "stretch") node.setAlignContent(Yoga.ALIGN_STRETCH);
204
- }
205
- if ("justifyContent" in style) {
206
- if (style.justifyContent === "flex-start" || !style.justifyContent) node.setJustifyContent(Yoga.JUSTIFY_FLEX_START);
207
- if (style.justifyContent === "center") node.setJustifyContent(Yoga.JUSTIFY_CENTER);
208
- if (style.justifyContent === "flex-end") node.setJustifyContent(Yoga.JUSTIFY_FLEX_END);
209
- if (style.justifyContent === "space-between") node.setJustifyContent(Yoga.JUSTIFY_SPACE_BETWEEN);
210
- if (style.justifyContent === "space-around") node.setJustifyContent(Yoga.JUSTIFY_SPACE_AROUND);
211
- if (style.justifyContent === "space-evenly") node.setJustifyContent(Yoga.JUSTIFY_SPACE_EVENLY);
212
- }
213
- };
214
- const applyDimensionStyles = (node, style) => {
215
- if ("width" in style) {
216
- if (typeof style.width === "number") node.setWidth(style.width);
217
- else if (typeof style.width === "string") node.setWidthPercent(Number.parseInt(style.width, 10));
218
- else node.setWidthAuto();
219
- }
220
- if ("height" in style) {
221
- if (typeof style.height === "number") node.setHeight(style.height);
222
- else if (typeof style.height === "string") node.setHeightPercent(Number.parseInt(style.height, 10));
223
- else node.setHeightAuto();
224
- }
225
- if ("minWidth" in style) {
226
- if (typeof style.minWidth === "string") node.setMinWidthPercent(Number.parseInt(style.minWidth, 10));
227
- else node.setMinWidth(style.minWidth ?? 0);
228
- }
229
- if ("minHeight" in style) {
230
- if (typeof style.minHeight === "string") node.setMinHeightPercent(Number.parseInt(style.minHeight, 10));
231
- else node.setMinHeight(style.minHeight ?? 0);
232
- }
233
- if ("maxWidth" in style) {
234
- if (typeof style.maxWidth === "string") node.setMaxWidthPercent(Number.parseInt(style.maxWidth, 10));
235
- else node.setMaxWidth(style.maxWidth);
236
- }
237
- if ("maxHeight" in style) {
238
- if (typeof style.maxHeight === "string") node.setMaxHeightPercent(Number.parseInt(style.maxHeight, 10));
239
- else node.setMaxHeight(style.maxHeight);
240
- }
241
- if ("aspectRatio" in style) node.setAspectRatio(style.aspectRatio);
242
- };
243
- const applyDisplayStyles = (node, style) => {
244
- if ("display" in style) node.setDisplay(style.display === "flex" ? Yoga.DISPLAY_FLEX : Yoga.DISPLAY_NONE);
245
- };
246
- const applyBorderStyles = (node, style, currentStyle) => {
247
- if (!("borderStyle" in style || "borderTop" in style || "borderBottom" in style || "borderLeft" in style || "borderRight" in style)) return;
248
- const borderWidth = currentStyle.borderStyle ? 1 : 0;
249
- node.setBorder(Yoga.EDGE_TOP, currentStyle.borderTop === false ? 0 : borderWidth);
250
- node.setBorder(Yoga.EDGE_BOTTOM, currentStyle.borderBottom === false ? 0 : borderWidth);
251
- node.setBorder(Yoga.EDGE_LEFT, currentStyle.borderLeft === false ? 0 : borderWidth);
252
- node.setBorder(Yoga.EDGE_RIGHT, currentStyle.borderRight === false ? 0 : borderWidth);
253
- };
254
- const applyGapStyles = (node, style) => {
255
- if ("gap" in style) node.setGap(Yoga.GUTTER_ALL, style.gap ?? 0);
256
- if ("columnGap" in style) node.setGap(Yoga.GUTTER_COLUMN, style.columnGap ?? 0);
257
- if ("rowGap" in style) node.setGap(Yoga.GUTTER_ROW, style.rowGap ?? 0);
258
- };
259
- const styles = (node, style = {}, currentStyle = style) => {
260
- applyPositionStyles(node, style);
261
- applyMarginStyles(node, style);
262
- applyPaddingStyles(node, style);
263
- applyFlexStyles(node, style);
264
- applyDimensionStyles(node, style);
265
- applyDisplayStyles(node, style);
266
- applyBorderStyles(node, style, currentStyle);
267
- applyGapStyles(node, style);
268
- };
269
- //#endregion
270
- //#region src/transform-adapter.ts
271
- /** The single ANSI compatibility boundary used by Transform and external styled strings. */
272
- function transformAnsiLine(serializedSubtree, lineIndex, transformers) {
273
- let transformed = serializedSubtree;
274
- for (const transformer of transformers) transformed = transformer(transformed, lineIndex);
275
- return styledCharsFromTokens(tokenize(transformed));
276
- }
277
- //#endregion
278
- //#region src/wrap-text.ts
279
- const wrapTextCache = new QuickLru({ maxSize: 4096 });
280
- const wrapText = (text, maxWidth, wrapType) => {
281
- if (wrapType === "none") return text;
282
- const cacheKey = text + String(maxWidth) + String(wrapType);
283
- const cachedText = wrapTextCache.get(cacheKey);
284
- if (cachedText !== void 0) return cachedText;
285
- let wrappedText = text;
286
- if (wrapType === "wrap") wrappedText = wrapAnsi(text, maxWidth, {
287
- trim: false,
288
- hard: true
289
- });
290
- if (wrapType === "hard") wrappedText = wrapAnsi(text, maxWidth, {
291
- trim: false,
292
- hard: true,
293
- wordWrap: false
294
- });
295
- if (wrapType.startsWith("truncate")) {
296
- let position = "end";
297
- if (wrapType === "truncate-middle") position = "middle";
298
- if (wrapType === "truncate-start") position = "start";
299
- wrappedText = cliTruncate(text, maxWidth, { position });
300
- }
301
- wrapTextCache.set(cacheKey, wrappedText);
302
- return wrappedText;
303
- };
304
- //#endregion
305
- //#region src/dom.ts
306
- const createNode = (nodeName) => {
307
- const node = {
308
- nodeName,
309
- style: {},
310
- attributes: {},
311
- childNodes: [],
312
- parentNode: void 0,
313
- yogaNode: nodeName === "ink-virtual-text" ? void 0 : Yoga.Node.create(),
314
- internal_accessibility: {}
315
- };
316
- if (nodeName === "ink-text") node.yogaNode?.setMeasureFunc((width) => measureTextNode(node, width));
317
- return node;
318
- };
319
- const appendChildNode = (node, childNode) => {
320
- if (childNode.parentNode) removeChildNode(childNode.parentNode, childNode);
321
- childNode.parentNode = node;
322
- node.childNodes.push(childNode);
323
- if (childNode.yogaNode) node.yogaNode?.insertChild(childNode.yogaNode, node.yogaNode.getChildCount());
324
- if (node.nodeName === "ink-text" || node.nodeName === "ink-virtual-text") markNodeAsDirty(node);
325
- };
326
- const insertBeforeNode = (node, newChildNode, beforeChildNode) => {
327
- if (newChildNode.parentNode) removeChildNode(newChildNode.parentNode, newChildNode);
328
- newChildNode.parentNode = node;
329
- const index = node.childNodes.indexOf(beforeChildNode);
330
- if (index >= 0) {
331
- node.childNodes.splice(index, 0, newChildNode);
332
- if (newChildNode.yogaNode) node.yogaNode?.insertChild(newChildNode.yogaNode, index);
333
- } else {
334
- node.childNodes.push(newChildNode);
335
- if (newChildNode.yogaNode) node.yogaNode?.insertChild(newChildNode.yogaNode, node.yogaNode.getChildCount());
336
- }
337
- if (node.nodeName === "ink-text" || node.nodeName === "ink-virtual-text") markNodeAsDirty(node);
338
- };
339
- const removeChildNode = (node, removeNode) => {
340
- if (removeNode.yogaNode) removeNode.parentNode?.yogaNode?.removeChild(removeNode.yogaNode);
341
- removeNode.parentNode = void 0;
342
- const index = node.childNodes.indexOf(removeNode);
343
- if (index >= 0) node.childNodes.splice(index, 1);
344
- if (node.nodeName === "ink-text" || node.nodeName === "ink-virtual-text") markNodeAsDirty(node);
345
- };
346
- const nullifyYogaNodes = (node) => {
347
- node.yogaNode = void 0;
348
- if (node.nodeName !== "#text") for (const childNode of node.childNodes) nullifyYogaNodes(childNode);
349
- };
350
- /**
351
- Detach a removed subtree from the layout engine: drop the measure callback
352
- and null the `yogaNode` reference on every DOM node within it.
353
-
354
- Nulling the references makes every `?.yogaNode` guard in the codebase
355
- effective for removed nodes, turns lingering access into a safe no-op (see
356
- QwenLM/qwen-code#6820), and lets the garbage collector reclaim the Yoga
357
- tree along with its closures.
358
- */
359
- const detachYogaSubtree = (removeNode) => {
360
- removeNode.yogaNode?.unsetMeasureFunc();
361
- nullifyYogaNodes(removeNode);
362
- };
363
- const setAttribute = (node, key, value) => {
364
- if (key === "internal_accessibility") {
365
- node.internal_accessibility = value;
366
- return;
367
- }
368
- node.attributes[key] = value;
369
- };
370
- const setStyle = (node, style) => {
371
- node.style = style ?? {};
372
- };
373
- const createTextNode = (text) => {
374
- const node = {
375
- nodeName: "#text",
376
- nodeValue: text,
377
- yogaNode: void 0,
378
- parentNode: void 0,
379
- style: {}
380
- };
381
- setTextNodeValue(node, text);
382
- return node;
383
- };
384
- const measureTextNode = function(node, width) {
385
- const text = node.nodeName === "#text" ? node.nodeValue : squashTextNodes(node);
386
- const dimensions = measureText(text);
387
- if (dimensions.width <= width) return dimensions;
388
- if (dimensions.width >= 1 && width > 0 && width < 1) return dimensions;
389
- const textWrap = node.style?.textWrap ?? "wrap";
390
- if (textWrap === "none") return dimensions;
391
- const wrappedText = wrapText(text, width, textWrap);
392
- return measureText(wrappedText);
393
- };
394
- const findClosestYogaNode = (node) => {
395
- if (!node?.parentNode) return;
396
- return node.yogaNode ?? findClosestYogaNode(node.parentNode);
397
- };
398
- const markNodeAsDirty = (node) => {
399
- findClosestYogaNode(node)?.markDirty();
400
- };
401
- const setTextNodeValue = (node, text) => {
402
- if (typeof text !== "string") text = String(text);
403
- node.nodeValue = text;
404
- markNodeAsDirty(node);
405
- };
406
- const addLayoutListener = (rootNode, listener) => {
407
- if (rootNode.nodeName !== "ink-root") return () => {};
408
- rootNode.internal_layoutListeners ??= /* @__PURE__ */ new Set();
409
- rootNode.internal_layoutListeners.add(listener);
410
- return () => {
411
- rootNode.internal_layoutListeners?.delete(listener);
412
- };
413
- };
414
- const emitLayoutListeners = (rootNode) => {
415
- if (rootNode.nodeName !== "ink-root" || !rootNode.internal_layoutListeners) return;
416
- for (const listener of rootNode.internal_layoutListeners) listener();
417
- };
418
- //#endregion
419
- //#region src/components/Text.tsx
420
- /** @jsxImportSource react */
421
- /**
422
- This component can display text and change its style to make it bold, underlined, italic, or strikethrough.
423
- */
424
- function Text({ color, backgroundColor, dimColor = false, bold = false, italic = false, underline = false, strikethrough = false, inverse = false, wrap = "wrap", children, "aria-label": ariaLabel, "aria-hidden": ariaHidden = false }) {
425
- const { isScreenReaderEnabled } = useContext(accessibilityContext);
426
- const childrenOrAriaLabel = isScreenReaderEnabled && ariaLabel ? ariaLabel : children;
427
- if (childrenOrAriaLabel === void 0 || childrenOrAriaLabel === null) return null;
428
- const foreground = typeof color === "object" ? color : parseSemanticColor(color);
429
- const background = typeof backgroundColor === "object" ? backgroundColor : parseSemanticColor(backgroundColor);
430
- const semanticStyle = {
431
- ...foreground ? { foreground } : {},
432
- ...background ? { background } : {},
433
- ...color === "" ? { resetForeground: true } : {},
434
- ...backgroundColor === "" ? { resetBackground: true } : {},
435
- ...underline ? { underline: "single" } : {},
436
- attributes: (dimColor ? cellAttributes.faint : 0) + (bold ? cellAttributes.bold : 0) + (italic ? cellAttributes.italic : 0) + (strikethrough ? cellAttributes.strikethrough : 0) + (inverse ? cellAttributes.inverse : 0)
437
- };
438
- if (isScreenReaderEnabled && ariaHidden) return null;
439
- return /* @__PURE__ */ jsx("ink-text", {
440
- style: {
441
- flexGrow: 0,
442
- flexShrink: 1,
443
- flexDirection: "row",
444
- textWrap: wrap
445
- },
446
- internal_textStyle: semanticStyle,
447
- children: childrenOrAriaLabel
448
- });
449
- }
450
- //#endregion
451
- //#region src/components/FocusContext.ts
452
- const FocusContext = createContext({
453
- activeId: void 0,
454
- add() {},
455
- remove() {},
456
- activate() {},
457
- deactivate() {},
458
- enableFocus() {},
459
- disableFocus() {},
460
- focusNext() {},
461
- focusPrevious() {},
462
- focus() {}
463
- });
464
- FocusContext.displayName = "InternalFocusContext";
465
- //#endregion
466
- //#region src/components/StdinContext.ts
467
- /**
468
- `StdinContext` is a React context that exposes the input stream.
469
- */
470
- const StdinContext = createContext({
471
- stdin: process.stdin,
472
- internal_eventEmitter: new EventEmitter(),
473
- setRawMode() {},
474
- setBracketedPasteMode() {},
475
- isRawModeSupported: false,
476
- internal_exitOnCtrlC: true
477
- });
478
- StdinContext.displayName = "InternalStdinContext";
479
- //#endregion
480
- //#region src/kitty-keyboard.ts
481
- const kittyFlags = {
482
- disambiguateEscapeCodes: 1,
483
- reportEventTypes: 2,
484
- reportAlternateKeys: 4,
485
- reportAllKeysAsEscapeCodes: 8,
486
- reportAssociatedText: 16
487
- };
488
- function resolveFlags(flags) {
489
- let result = 0;
490
- for (const flag of flags) result |= kittyFlags[flag];
491
- return result;
492
- }
493
- const kittyModifiers = {
494
- shift: 1,
495
- alt: 2,
496
- ctrl: 4,
497
- super: 8,
498
- hyper: 16,
499
- meta: 32,
500
- capsLock: 64,
501
- numLock: 128
502
- };
503
- const textEncoder = new TextEncoder();
504
- const kittyQueryEscapeByte = 27;
505
- const kittyQueryOpenBracketByte = 91;
506
- const kittyQueryQuestionMarkByte = 63;
507
- const kittyQueryLetterByte = 117;
508
- const zeroByte = 48;
509
- const nineByte = 57;
510
- const isDigitByte = (byte) => byte >= zeroByte && byte <= nineByte;
511
- const matchKittyQueryResponse = (buffer, startIndex) => {
512
- if (buffer[startIndex] !== kittyQueryEscapeByte || buffer[startIndex + 1] !== kittyQueryOpenBracketByte || buffer[startIndex + 2] !== kittyQueryQuestionMarkByte) return;
513
- let index = startIndex + 3;
514
- const digitsStartIndex = index;
515
- while (index < buffer.length && isDigitByte(buffer[index])) index++;
516
- if (index === digitsStartIndex) return;
517
- if (index === buffer.length) return { state: "partial" };
518
- if (buffer[index] === kittyQueryLetterByte) return {
519
- state: "complete",
520
- endIndex: index
521
- };
522
- };
523
- const hasCompleteKittyQueryResponse = (buffer) => {
524
- for (let index = 0; index < buffer.length; index++) if (matchKittyQueryResponse(buffer, index)?.state === "complete") return true;
525
- return false;
526
- };
527
- const stripKittyQueryResponsesAndTrailingPartial = (buffer) => {
528
- const keptBytes = [];
529
- let index = 0;
530
- while (index < buffer.length) {
531
- const match = matchKittyQueryResponse(buffer, index);
532
- if (match?.state === "complete") {
533
- index = match.endIndex + 1;
534
- continue;
535
- }
536
- if (match?.state === "partial") break;
537
- keptBytes.push(buffer[index]);
538
- index++;
539
- }
540
- return keptBytes;
541
- };
542
- const detectKittySupport = (stdin, stdout, onSupported) => {
543
- let responseBuffer = [];
544
- const cleanup = () => {
545
- clearTimeout(timer);
546
- stdin.removeListener("data", onData);
547
- const remaining = stripKittyQueryResponsesAndTrailingPartial(responseBuffer);
548
- responseBuffer = [];
549
- if (remaining.length > 0) stdin.unshift(Uint8Array.from(remaining));
550
- };
551
- const onData = (data) => {
552
- const chunk = typeof data === "string" ? textEncoder.encode(data) : data;
553
- for (const byte of chunk) responseBuffer.push(byte);
554
- if (hasCompleteKittyQueryResponse(responseBuffer)) {
555
- cleanup();
556
- onSupported();
557
- }
558
- };
559
- stdin.on("data", onData);
560
- const timer = setTimeout(cleanup, 200);
561
- stdout.write(kittyQuery);
562
- return cleanup;
563
- };
564
- //#endregion
565
- //#region package.json
566
- var name = "@alchemy.run/sigil";
567
- var version = "0.0.0-alpha.9";
568
- //#endregion
569
- //#region src/reconciler.ts
570
- if (isSigilDev) await import("./devtools-DbthxoD1.js").catch(() => {});
571
- const diff = (before, after) => {
572
- if (before === after) return;
573
- if (!before) return after;
574
- const changed = {};
575
- let isChanged = false;
576
- for (const key of Object.keys(before)) if (after ? !Object.hasOwn(after, key) : true) {
577
- changed[key] = void 0;
578
- isChanged = true;
579
- }
580
- if (after) {
581
- for (const key of Object.keys(after)) if (after[key] !== before[key]) {
582
- changed[key] = after[key];
583
- isChanged = true;
584
- }
585
- }
586
- return isChanged ? changed : void 0;
587
- };
588
- const findRootNode = (node) => {
589
- let current = node;
590
- while (current) {
591
- if (current.nodeName === "ink-root") return current;
592
- current = current.parentNode;
593
- }
594
- };
595
- /**
596
- * Clear the root's cached `staticNode` when the node it points at is being
597
- * removed as part of a larger subtree.
598
- *
599
- * The previous identity check (`staticNode === removeNode`) only caught direct
600
- * removal of the `<Static>` element. When an *ancestor* of `<Static>` is
601
- * removed, the stale `staticNode` reference survives and the next render would
602
- * replay stale static output (and, before `detachYogaSubtree`, trap on detached
603
- * WASM memory — see QwenLM/qwen-code#6820).
604
- *
605
- * The owning root is derived from the host parent passed to the removal hook,
606
- * not a module-level global, so instances with separate stdout streams don't
607
- * clobber each other's pointers.
608
- */
609
- const clearStaticNodeIfContained = (rootNode, removeNode) => {
610
- if (!rootNode?.staticNode) return;
611
- let current = rootNode.staticNode;
612
- while (current) {
613
- if (current === removeNode) {
614
- rootNode.staticNode = void 0;
615
- return;
616
- }
617
- current = current.parentNode;
618
- }
619
- };
620
- let currentUpdatePriority = NoEventPriority;
621
- const reconciler = createReconciler({
622
- getRootHostContext: () => ({ isInsideText: false }),
623
- prepareForCommit: () => null,
624
- preparePortalMount: () => null,
625
- clearContainer: () => false,
626
- resetAfterCommit(rootNode) {
627
- if (typeof rootNode.onComputeLayout === "function") rootNode.onComputeLayout();
628
- emitLayoutListeners(rootNode);
629
- if (rootNode.staticNode !== rootNode.previousStaticNode) {
630
- rootNode.previousStaticNode = rootNode.staticNode;
631
- if (typeof rootNode.onStaticChange === "function") rootNode.onStaticChange();
632
- }
633
- if (rootNode.isStaticDirty) {
634
- rootNode.isStaticDirty = false;
635
- if (typeof rootNode.onImmediateRender === "function") rootNode.onImmediateRender();
636
- return;
637
- }
638
- if (typeof rootNode.onRender === "function") rootNode.onRender();
639
- },
640
- getChildHostContext(parentHostContext, type) {
641
- const previousIsInsideText = parentHostContext.isInsideText;
642
- const isInsideText = type === "ink-text" || type === "ink-virtual-text";
643
- if (previousIsInsideText === isInsideText) return parentHostContext;
644
- return { isInsideText };
645
- },
646
- shouldSetTextContent: () => false,
647
- createInstance(originalType, newProps, rootNode, hostContext) {
648
- if (hostContext.isInsideText && originalType === "ink-box") throw new Error(`<Box> can't be nested inside <Text> component`);
649
- const type = originalType === "ink-text" && hostContext.isInsideText ? "ink-virtual-text" : originalType;
650
- const node = createNode(type);
651
- for (const [key, value] of Object.entries(newProps)) {
652
- if (key === "children") continue;
653
- if (key === "style") {
654
- setStyle(node, value);
655
- if (node.yogaNode) styles(node.yogaNode, value);
656
- continue;
657
- }
658
- if (key === "internal_transform") {
659
- node.internal_transform = value;
660
- continue;
661
- }
662
- if (key === "internal_ansi") {
663
- node.internal_ansi = value === true;
664
- continue;
665
- }
666
- if (key === "internal_textStyle") {
667
- node.internal_textStyle = value;
668
- continue;
669
- }
670
- if (key === "internal_static") {
671
- node.internal_static = true;
672
- rootNode.isStaticDirty = true;
673
- rootNode.staticNode = node;
674
- continue;
675
- }
676
- setAttribute(node, key, value);
677
- }
678
- return node;
679
- },
680
- createTextInstance(text, _root, hostContext) {
681
- if (!hostContext.isInsideText) throw new Error(`Text string "${text}" must be rendered inside <Text> component`);
682
- return createTextNode(text);
683
- },
684
- resetTextContent() {},
685
- hideTextInstance(node) {
686
- setTextNodeValue(node, "");
687
- },
688
- unhideTextInstance(node, text) {
689
- setTextNodeValue(node, text);
690
- },
691
- getPublicInstance: (instance) => instance,
692
- hideInstance(node) {
693
- node.yogaNode?.setDisplay(Yoga.DISPLAY_NONE);
694
- },
695
- unhideInstance(node) {
696
- node.yogaNode?.setDisplay(Yoga.DISPLAY_FLEX);
697
- },
698
- appendInitialChild: appendChildNode,
699
- appendChild: appendChildNode,
700
- insertBefore: insertBeforeNode,
701
- finalizeInitialChildren() {
702
- return false;
703
- },
704
- isPrimaryRenderer: true,
705
- supportsMutation: true,
706
- supportsPersistence: false,
707
- supportsHydration: false,
708
- supportsMicrotasks: true,
709
- scheduleMicrotask: queueMicrotask,
710
- scheduleCallback: Scheduler.unstable_scheduleCallback,
711
- cancelCallback: Scheduler.unstable_cancelCallback,
712
- shouldYield: Scheduler.unstable_shouldYield,
713
- now: Scheduler.unstable_now,
714
- scheduleTimeout: setTimeout,
715
- cancelTimeout: clearTimeout,
716
- noTimeout: -1,
717
- beforeActiveInstanceBlur() {},
718
- afterActiveInstanceBlur() {},
719
- detachDeletedInstance() {},
720
- getInstanceFromNode: () => null,
721
- prepareScopeUpdate() {},
722
- getInstanceFromScope: () => null,
723
- appendChildToContainer: appendChildNode,
724
- insertInContainerBefore: insertBeforeNode,
725
- removeChildFromContainer(node, removeNode) {
726
- clearStaticNodeIfContained(findRootNode(node), removeNode);
727
- removeChildNode(node, removeNode);
728
- detachYogaSubtree(removeNode);
729
- },
730
- commitUpdate(node, _type, oldProps, newProps) {
731
- if (node.internal_static) {
732
- const rootNode = findRootNode(node);
733
- if (rootNode) rootNode.isStaticDirty = true;
734
- }
735
- const props = diff(oldProps, newProps);
736
- const style = diff(oldProps["style"], newProps["style"]);
737
- if (!props && !style) return;
738
- if (props) for (const [key, value] of Object.entries(props)) {
739
- if (key === "style") {
740
- setStyle(node, value);
741
- continue;
742
- }
743
- if (key === "internal_transform") {
744
- node.internal_transform = value;
745
- continue;
746
- }
747
- if (key === "internal_ansi") {
748
- node.internal_ansi = value === true;
749
- continue;
750
- }
751
- if (key === "internal_textStyle") {
752
- node.internal_textStyle = value;
753
- continue;
754
- }
755
- if (key === "internal_static") {
756
- node.internal_static = true;
757
- continue;
758
- }
759
- setAttribute(node, key, value);
760
- }
761
- if (style && node.yogaNode) styles(node.yogaNode, style, newProps["style"] ?? {});
762
- },
763
- commitTextUpdate(node, _oldText, newText) {
764
- setTextNodeValue(node, newText);
765
- },
766
- removeChild(node, removeNode) {
767
- clearStaticNodeIfContained(findRootNode(node), removeNode);
768
- removeChildNode(node, removeNode);
769
- detachYogaSubtree(removeNode);
770
- },
771
- setCurrentUpdatePriority(newPriority) {
772
- currentUpdatePriority = newPriority;
773
- },
774
- getCurrentUpdatePriority: () => currentUpdatePriority,
775
- resolveUpdatePriority() {
776
- if (currentUpdatePriority !== NoEventPriority) return currentUpdatePriority;
777
- return DefaultEventPriority;
778
- },
779
- maySuspendCommit() {
780
- return true;
781
- },
782
- NotPendingTransition: void 0,
783
- HostTransitionContext: createContext(null),
784
- resetFormInstance() {},
785
- requestPostPaintCallback() {},
786
- shouldAttemptEagerTransition() {
787
- return false;
788
- },
789
- trackSchedulerEvent() {},
790
- resolveEventType() {
791
- return null;
792
- },
793
- resolveEventTimeStamp() {
794
- return -1.1;
795
- },
796
- preloadInstance() {
797
- return true;
798
- },
799
- startSuspendingCommit() {},
800
- suspendInstance() {},
801
- waitForCommitToBeReady() {
802
- return null;
803
- },
804
- rendererPackageName: name,
805
- rendererVersion: version
806
- });
807
- //#endregion
808
- //#region src/hooks/use-stdin.ts
809
- /**
810
- A React hook that returns the stdin stream and stdin-related utilities.
811
- */
812
- const useStdin = () => useContext(StdinContext);
813
- const useStdinContext = () => useContext(StdinContext);
814
- //#endregion
815
- //#region src/parse-keypress.ts
816
- const textDecoder = new TextDecoder();
817
- const metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/;
818
- const fnKeyRe = /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/;
819
- const keyName = {
820
- OP: "f1",
821
- OQ: "f2",
822
- OR: "f3",
823
- OS: "f4",
824
- "[P": "f1",
825
- "[Q": "f2",
826
- "[R": "f3",
827
- "[S": "f4",
828
- "[11~": "f1",
829
- "[12~": "f2",
830
- "[13~": "f3",
831
- "[14~": "f4",
832
- "[[A": "f1",
833
- "[[B": "f2",
834
- "[[C": "f3",
835
- "[[D": "f4",
836
- "[[E": "f5",
837
- "[15~": "f5",
838
- "[17~": "f6",
839
- "[18~": "f7",
840
- "[19~": "f8",
841
- "[20~": "f9",
842
- "[21~": "f10",
843
- "[23~": "f11",
844
- "[24~": "f12",
845
- "[A": "up",
846
- "[B": "down",
847
- "[C": "right",
848
- "[D": "left",
849
- "[E": "clear",
850
- "[F": "end",
851
- "[H": "home",
852
- OA: "up",
853
- OB: "down",
854
- OC: "right",
855
- OD: "left",
856
- OE: "clear",
857
- OF: "end",
858
- OH: "home",
859
- "[1~": "home",
860
- "[2~": "insert",
861
- "[3~": "delete",
862
- "[4~": "end",
863
- "[5~": "pageup",
864
- "[6~": "pagedown",
865
- "[[5~": "pageup",
866
- "[[6~": "pagedown",
867
- "[7~": "home",
868
- "[8~": "end",
869
- "[a": "up",
870
- "[b": "down",
871
- "[c": "right",
872
- "[d": "left",
873
- "[e": "clear",
874
- "[2$": "insert",
875
- "[3$": "delete",
876
- "[5$": "pageup",
877
- "[6$": "pagedown",
878
- "[7$": "home",
879
- "[8$": "end",
880
- Oa: "up",
881
- Ob: "down",
882
- Oc: "right",
883
- Od: "left",
884
- Oe: "clear",
885
- "[2^": "insert",
886
- "[3^": "delete",
887
- "[5^": "pageup",
888
- "[6^": "pagedown",
889
- "[7^": "home",
890
- "[8^": "end",
891
- "[Z": "tab"
892
- };
893
- const nonAlphanumericKeys = [...Object.values(keyName), "backspace"];
894
- const isShiftKey = (code) => {
895
- return [
896
- "[a",
897
- "[b",
898
- "[c",
899
- "[d",
900
- "[e",
901
- "[2$",
902
- "[3$",
903
- "[5$",
904
- "[6$",
905
- "[7$",
906
- "[8$",
907
- "[Z"
908
- ].includes(code);
909
- };
910
- const isCtrlKey = (code) => {
911
- return [
912
- "Oa",
913
- "Ob",
914
- "Oc",
915
- "Od",
916
- "Oe",
917
- "[2^",
918
- "[3^",
919
- "[5^",
920
- "[6^",
921
- "[7^",
922
- "[8^"
923
- ].includes(code);
924
- };
925
- const kittyKeyRe = /^\x1b\[(\d+)(?:;(\d+)(?::(\d+))?(?:;([\d:]+))?)?u$/;
926
- const kittySpecialKeyRe = /^\x1b\[(\d+);(\d+):(\d+)([A-Za-z~])$/;
927
- const kittySpecialLetterKeys = {
928
- A: "up",
929
- B: "down",
930
- C: "right",
931
- D: "left",
932
- E: "clear",
933
- F: "end",
934
- H: "home",
935
- P: "f1",
936
- Q: "f2",
937
- R: "f3",
938
- S: "f4"
939
- };
940
- const kittySpecialNumberKeys = {
941
- 2: "insert",
942
- 3: "delete",
943
- 5: "pageup",
944
- 6: "pagedown",
945
- 7: "home",
946
- 8: "end",
947
- 11: "f1",
948
- 12: "f2",
949
- 13: "f3",
950
- 14: "f4",
951
- 15: "f5",
952
- 17: "f6",
953
- 18: "f7",
954
- 19: "f8",
955
- 20: "f9",
956
- 21: "f10",
957
- 23: "f11",
958
- 24: "f12"
959
- };
960
- const kittyCodepointNames = {
961
- 27: "escape",
962
- 9: "tab",
963
- 127: "backspace",
964
- 8: "backspace",
965
- 57358: "capslock",
966
- 57359: "scrolllock",
967
- 57360: "numlock",
968
- 57361: "printscreen",
969
- 57362: "pause",
970
- 57363: "menu",
971
- 57376: "f13",
972
- 57377: "f14",
973
- 57378: "f15",
974
- 57379: "f16",
975
- 57380: "f17",
976
- 57381: "f18",
977
- 57382: "f19",
978
- 57383: "f20",
979
- 57384: "f21",
980
- 57385: "f22",
981
- 57386: "f23",
982
- 57387: "f24",
983
- 57388: "f25",
984
- 57389: "f26",
985
- 57390: "f27",
986
- 57391: "f28",
987
- 57392: "f29",
988
- 57393: "f30",
989
- 57394: "f31",
990
- 57395: "f32",
991
- 57396: "f33",
992
- 57397: "f34",
993
- 57398: "f35",
994
- 57399: "kp0",
995
- 57400: "kp1",
996
- 57401: "kp2",
997
- 57402: "kp3",
998
- 57403: "kp4",
999
- 57404: "kp5",
1000
- 57405: "kp6",
1001
- 57406: "kp7",
1002
- 57407: "kp8",
1003
- 57408: "kp9",
1004
- 57409: "kpdecimal",
1005
- 57410: "kpdivide",
1006
- 57411: "kpmultiply",
1007
- 57412: "kpsubtract",
1008
- 57413: "kpadd",
1009
- 57414: "kpenter",
1010
- 57415: "kpequal",
1011
- 57416: "kpseparator",
1012
- 57417: "kpleft",
1013
- 57418: "kpright",
1014
- 57419: "kpup",
1015
- 57420: "kpdown",
1016
- 57421: "kppageup",
1017
- 57422: "kppagedown",
1018
- 57423: "kphome",
1019
- 57424: "kpend",
1020
- 57425: "kpinsert",
1021
- 57426: "kpdelete",
1022
- 57427: "kpbegin",
1023
- 57428: "mediaplay",
1024
- 57429: "mediapause",
1025
- 57430: "mediaplaypause",
1026
- 57431: "mediareverse",
1027
- 57432: "mediastop",
1028
- 57433: "mediafastforward",
1029
- 57434: "mediarewind",
1030
- 57435: "mediatracknext",
1031
- 57436: "mediatrackprevious",
1032
- 57437: "mediarecord",
1033
- 57438: "lowervolume",
1034
- 57439: "raisevolume",
1035
- 57440: "mutevolume",
1036
- 57441: "leftshift",
1037
- 57442: "leftcontrol",
1038
- 57443: "leftalt",
1039
- 57444: "leftsuper",
1040
- 57445: "lefthyper",
1041
- 57446: "leftmeta",
1042
- 57447: "rightshift",
1043
- 57448: "rightcontrol",
1044
- 57449: "rightalt",
1045
- 57450: "rightsuper",
1046
- 57451: "righthyper",
1047
- 57452: "rightmeta",
1048
- 57453: "isoLevel3Shift",
1049
- 57454: "isoLevel5Shift"
1050
- };
1051
- const isValidCodepoint = (cp) => cp >= 0 && cp <= 1114111 && !(cp >= 55296 && cp <= 57343);
1052
- const safeFromCodePoint = (cp) => isValidCodepoint(cp) ? String.fromCodePoint(cp) : "?";
1053
- function resolveEventType(value) {
1054
- if (value === 3) return "release";
1055
- if (value === 2) return "repeat";
1056
- return "press";
1057
- }
1058
- function parseKittyModifiers(modifiers) {
1059
- return {
1060
- ctrl: !!(modifiers & kittyModifiers.ctrl),
1061
- shift: !!(modifiers & kittyModifiers.shift),
1062
- meta: !!(modifiers & (kittyModifiers.meta | kittyModifiers.alt)),
1063
- super: !!(modifiers & kittyModifiers.super),
1064
- hyper: !!(modifiers & kittyModifiers.hyper),
1065
- capsLock: !!(modifiers & kittyModifiers.capsLock),
1066
- numLock: !!(modifiers & kittyModifiers.numLock)
1067
- };
1068
- }
1069
- const parseKittyKeypress = (s) => {
1070
- const match = kittyKeyRe.exec(s);
1071
- if (!match) return null;
1072
- const codepoint = parseInt(match[1], 10);
1073
- const modifiers = match[2] ? Math.max(0, parseInt(match[2], 10) - 1) : 0;
1074
- const eventType = match[3] ? parseInt(match[3], 10) : 1;
1075
- const textField = match[4];
1076
- if (!isValidCodepoint(codepoint)) return null;
1077
- let text;
1078
- if (textField) text = textField.split(":").map((cp) => safeFromCodePoint(parseInt(cp, 10))).join("");
1079
- let name;
1080
- let isPrintable;
1081
- if (codepoint === 32) {
1082
- name = "space";
1083
- isPrintable = true;
1084
- } else if (codepoint === 13) {
1085
- name = "return";
1086
- isPrintable = true;
1087
- } else if (kittyCodepointNames[codepoint]) {
1088
- name = kittyCodepointNames[codepoint];
1089
- isPrintable = false;
1090
- } else if (codepoint >= 1 && codepoint <= 26) {
1091
- name = String.fromCodePoint(codepoint + 96);
1092
- isPrintable = false;
1093
- } else {
1094
- name = safeFromCodePoint(codepoint).toLowerCase();
1095
- isPrintable = true;
1096
- }
1097
- if (isPrintable && !text) text = safeFromCodePoint(codepoint);
1098
- return {
1099
- name,
1100
- ...parseKittyModifiers(modifiers),
1101
- eventType: resolveEventType(eventType),
1102
- sequence: s,
1103
- raw: s,
1104
- isKittyProtocol: true,
1105
- isPrintable,
1106
- text
1107
- };
1108
- };
1109
- const parseKittySpecialKey = (s) => {
1110
- const match = kittySpecialKeyRe.exec(s);
1111
- if (!match) return null;
1112
- const number = parseInt(match[1], 10);
1113
- const modifiers = Math.max(0, parseInt(match[2], 10) - 1);
1114
- const eventType = parseInt(match[3], 10);
1115
- const terminator = match[4];
1116
- const name = terminator === "~" ? kittySpecialNumberKeys[number] : kittySpecialLetterKeys[terminator];
1117
- if (!name) return null;
1118
- return {
1119
- name,
1120
- ...parseKittyModifiers(modifiers),
1121
- eventType: resolveEventType(eventType),
1122
- sequence: s,
1123
- raw: s,
1124
- isKittyProtocol: true,
1125
- isPrintable: false
1126
- };
1127
- };
1128
- const parseKeypress = (s = "") => {
1129
- let parts;
1130
- if (s instanceof Uint8Array) {
1131
- if (s[0] > 127 && s[1] === void 0) s = "\x1B" + textDecoder.decode(Uint8Array.of(s[0] - 128));
1132
- else s = textDecoder.decode(s);
1133
- } else if (s !== void 0 && typeof s !== "string") s = String(s);
1134
- else if (!s) s = "";
1135
- const kittyResult = parseKittyKeypress(s);
1136
- if (kittyResult) return kittyResult;
1137
- const kittySpecialResult = parseKittySpecialKey(s);
1138
- if (kittySpecialResult) return kittySpecialResult;
1139
- if (kittyKeyRe.test(s)) return {
1140
- name: "",
1141
- ctrl: false,
1142
- meta: false,
1143
- shift: false,
1144
- sequence: s,
1145
- raw: s,
1146
- isKittyProtocol: true,
1147
- isPrintable: false
1148
- };
1149
- const key = {
1150
- name: "",
1151
- ctrl: false,
1152
- meta: false,
1153
- shift: false,
1154
- sequence: s,
1155
- raw: s
1156
- };
1157
- key.sequence = key.sequence || s || key.name;
1158
- if (s === "\r" || s === "\x1B\r") {
1159
- key.raw = void 0;
1160
- key.name = "return";
1161
- key.meta = s.length === 2;
1162
- } else if (s === "\n") key.name = "enter";
1163
- else if (s === " ") key.name = "tab";
1164
- else if (s === "\b" || s === "\x1B\b") {
1165
- key.name = "backspace";
1166
- key.meta = s.charAt(0) === "\x1B";
1167
- } else if (s === "" || s === "\x1B") {
1168
- key.name = "backspace";
1169
- key.meta = s.charAt(0) === "\x1B";
1170
- } else if (s === "\x1B" || s === "\x1B\x1B") {
1171
- key.name = "escape";
1172
- key.meta = s.length === 2;
1173
- } else if (s === " " || s === "\x1B ") {
1174
- key.name = "space";
1175
- key.meta = s.length === 2;
1176
- } else if (s.length === 1 && s <= "") {
1177
- key.name = String.fromCharCode(s.charCodeAt(0) + "a".charCodeAt(0) - 1);
1178
- key.ctrl = true;
1179
- } else if (s.length === 1 && s >= "0" && s <= "9") key.name = "number";
1180
- else if (s.length === 1 && s >= "a" && s <= "z") key.name = s;
1181
- else if (s.length === 1 && s >= "A" && s <= "Z") {
1182
- key.name = s.toLowerCase();
1183
- key.shift = true;
1184
- } else if (parts = metaKeyCodeRe.exec(s)) {
1185
- key.name = parts[1].toLowerCase();
1186
- key.meta = true;
1187
- key.shift = /^[A-Z]$/.test(parts[1]);
1188
- } else if (parts = fnKeyRe.exec(s)) {
1189
- const segs = [...s];
1190
- if (segs[0] === "\x1B" && segs[1] === "\x1B") key.meta = true;
1191
- const code = [
1192
- parts[1],
1193
- parts[2],
1194
- parts[4],
1195
- parts[6]
1196
- ].filter(Boolean).join("");
1197
- const modifier = Number(parts[3] || parts[5] || 1) - 1;
1198
- key.ctrl = !!(modifier & 4);
1199
- key.meta = key.meta || !!(modifier & 10);
1200
- key.shift = !!(modifier & 1);
1201
- key.code = code;
1202
- key.name = keyName[code] ?? "";
1203
- key.shift = isShiftKey(code) || key.shift;
1204
- key.ctrl = isCtrlKey(code) || key.ctrl;
1205
- }
1206
- return key;
1207
- };
1208
- //#endregion
1209
- //#region src/hooks/use-input.ts
1210
- /**
1211
- A React hook that returns `void` and handles user input.
1212
- It's a more convenient alternative to using `StdinContext` and listening for `data` events. The callback you pass to `useInput` is called for each character when the user enters any input. However, if the user pastes text and it's more than one character, the callback will be called only once, and the whole string will be passed as `input`.
1213
-
1214
- ```
1215
- import {useInput} from 'ink';
1216
-
1217
- const UserInput = () => {
1218
- useInput((input, key) => {
1219
- if (input === 'q') {
1220
- // Exit program
1221
- }
1222
-
1223
- if (key.leftArrow) {
1224
- // Left arrow key pressed
1225
- }
1226
- });
1227
-
1228
- return …
1229
- };
1230
- ```
1231
- */
1232
- const useInput = (inputHandler, options = {}) => {
1233
- const { setRawMode, internal_exitOnCtrlC, internal_eventEmitter } = useStdinContext();
1234
- useEffect(() => {
1235
- if (options.isActive === false) return;
1236
- setRawMode(true);
1237
- return () => {
1238
- setRawMode(false);
1239
- };
1240
- }, [options.isActive, setRawMode]);
1241
- const handleData = useEffectEvent((data) => {
1242
- const keypress = parseKeypress(data);
1243
- const key = {
1244
- upArrow: keypress.name === "up",
1245
- downArrow: keypress.name === "down",
1246
- leftArrow: keypress.name === "left",
1247
- rightArrow: keypress.name === "right",
1248
- pageDown: keypress.name === "pagedown",
1249
- pageUp: keypress.name === "pageup",
1250
- home: keypress.name === "home",
1251
- end: keypress.name === "end",
1252
- return: keypress.name === "return",
1253
- escape: keypress.name === "escape",
1254
- ctrl: keypress.ctrl,
1255
- shift: keypress.shift,
1256
- tab: keypress.name === "tab",
1257
- backspace: keypress.name === "backspace",
1258
- delete: keypress.name === "delete",
1259
- meta: keypress.meta,
1260
- super: keypress.super ?? false,
1261
- hyper: keypress.hyper ?? false,
1262
- capsLock: keypress.capsLock ?? false,
1263
- numLock: keypress.numLock ?? false,
1264
- eventType: keypress.eventType
1265
- };
1266
- let input;
1267
- if (keypress.isKittyProtocol) {
1268
- if (keypress.isPrintable) input = keypress.text ?? keypress.name;
1269
- else if (keypress.ctrl && keypress.name.length === 1) input = keypress.name;
1270
- else input = "";
1271
- } else if (keypress.ctrl) input = keypress.name ?? "";
1272
- else input = keypress.sequence;
1273
- if (!keypress.isKittyProtocol && nonAlphanumericKeys.includes(keypress.name)) input = "";
1274
- if (input.startsWith("\x1B")) input = input.slice(1);
1275
- if (input.length === 1 && /[A-Z]/.test(input)) key.shift = true;
1276
- if (input === "c" && key.ctrl && internal_exitOnCtrlC) return;
1277
- reconciler.discreteUpdates(() => {
1278
- inputHandler(input, key);
1279
- });
1280
- });
1281
- useEffect(() => {
1282
- if (options.isActive === false) return;
1283
- internal_eventEmitter.on("input", handleData);
1284
- return () => {
1285
- internal_eventEmitter.removeListener("input", handleData);
1286
- };
1287
- }, [options.isActive, internal_eventEmitter]);
1288
- };
1289
- //#endregion
1290
- //#region src/hooks/use-focus.ts
1291
- /**
1292
- A React hook that returns focus state and focus controls for the current component.
1293
- A component that uses the `useFocus` hook becomes "focusable" to Ink, so when the user presses <kbd>Tab</kbd>, Ink will switch focus to this component. If there are multiple components that execute the `useFocus` hook, focus will be given to them in the order in which these components are rendered.
1294
- */
1295
- const useFocus = ({ isActive = true, autoFocus = false, id: customId } = {}) => {
1296
- const { isRawModeSupported, setRawMode } = useStdin();
1297
- const { activeId, add, remove, activate, deactivate, focus } = useContext(FocusContext);
1298
- const autoId = useId();
1299
- const id = customId ?? autoId;
1300
- useEffect(() => {
1301
- add(id, { autoFocus });
1302
- return () => {
1303
- remove(id);
1304
- };
1305
- }, [
1306
- id,
1307
- autoFocus,
1308
- add,
1309
- remove
1310
- ]);
1311
- useEffect(() => {
1312
- if (isActive) activate(id);
1313
- else deactivate(id);
1314
- }, [
1315
- isActive,
1316
- id,
1317
- activate,
1318
- deactivate
1319
- ]);
1320
- useEffect(() => {
1321
- if (!isRawModeSupported || !isActive) return;
1322
- setRawMode(true);
1323
- return () => {
1324
- setRawMode(false);
1325
- };
1326
- }, [
1327
- isActive,
1328
- isRawModeSupported,
1329
- setRawMode
1330
- ]);
1331
- return {
1332
- isFocused: Boolean(id) && activeId === id,
1333
- focus
1334
- };
1335
- };
1336
- //#endregion
1337
- export { squashTextNodes as _, reconciler as a, kittyModifiers as c, FocusContext as d, Text as f, transformAnsiLine as g, emitLayoutListeners as h, useStdinContext as i, resolveFlags as l, createNode as m, useInput as n, detectKittySupport as o, addLayoutListener as p, useStdin as r, kittyFlags as s, useFocus as t, StdinContext as u, accessibilityContext as v };