@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.
- package/THIRD_PARTY_NOTICES.md +28 -0
- package/dist/ansi.d.ts +53 -53
- package/dist/capabilities.js +1 -1
- package/dist/{color-policy-DlrZXC0f.js → color-policy-BAC9-TZX.js} +15 -1
- package/dist/color.d.ts +8 -8
- package/dist/{devtools-DbthxoD1.js → devtools-B_2SDRaO.js} +3 -0
- package/dist/index.d.ts +39 -37
- package/dist/index.js +189 -181
- package/dist/jsx-dev-runtime.d.ts +3 -0
- package/dist/jsx-dev-runtime.js +7 -0
- package/dist/jsx-runtime-BS_OosoY.js +42 -0
- package/dist/jsx-runtime.d.ts +2 -0
- package/dist/jsx-runtime.js +8 -0
- package/dist/react-CeO3oT_g.js +394 -0
- package/dist/react.d.ts +2 -0
- package/dist/react.js +50 -0
- package/dist/rolldown-runtime-BPOCksWG.js +24 -0
- package/dist/router.d.ts +26 -26
- package/dist/router.js +45 -42
- package/dist/{session-Cg6STjFV.js → session-DDQ5V300.js} +34 -11
- package/dist/terminal.d.ts +9 -10
- package/dist/terminal.js +1 -1
- package/dist/use-focus-B1WVNBQm.js +8383 -0
- package/package.json +27 -15
- package/src/ansi/strip.ts +2 -2
- package/src/capabilities/query.ts +22 -0
- package/src/devtools.ts +5 -0
- package/src/hooks/use-window-size.ts +10 -3
- package/src/input-parser.ts +31 -11
- package/src/jsx-dev-runtime.ts +3 -0
- package/src/jsx-runtime.ts +6 -0
- package/src/react.ts +53 -0
- package/src/reconciler.ts +51 -0
- package/src/terminal/input.ts +11 -5
- package/dist/use-focus-Basd0ksv.js +0 -1337
|
@@ -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 };
|