@simon_he/vue-tui 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +145 -470
- package/dist/experimental.cjs +8847 -0
- package/dist/experimental.d.ts +825 -0
- package/dist/experimental.js +7475 -0
- package/dist/index.cjs +7695 -4695
- package/dist/index.d.ts +396 -164
- package/dist/index.js +6086 -4232
- package/dist/markdown.cjs +20560 -0
- package/dist/markdown.d.ts +112 -0
- package/dist/markdown.js +1581 -0
- package/dist/path-suggest-BeV6n7m-.js +3 -0
- package/dist/sgr-Tko2EQ0U.js +484 -0
- package/dist/theme-Bsm65g8k.d.ts +32 -0
- package/dist/types-ClIV2h1o.d.ts +103 -0
- package/dist/wheel-scroll-CiNsasLf.js +825 -0
- package/package.json +83 -45
- package/dist/path-suggest-DIMby3r0.js +0 -3
- /package/dist/{path-suggest-CZQYJIIg.js → path-suggest-DmrmeueH.js} +0 -0
|
@@ -0,0 +1,825 @@
|
|
|
1
|
+
import { computed, inject, onBeforeUnmount, provide, ref, vShow, watchEffect } from "vue";
|
|
2
|
+
|
|
3
|
+
//#region src/vue/context.ts
|
|
4
|
+
const TerminalContextKey = Symbol("TerminalContext");
|
|
5
|
+
const LayoutContextKey = Symbol("LayoutContext");
|
|
6
|
+
const VisibilityContextKey = Symbol("VisibilityContext");
|
|
7
|
+
const EventZIndexContextKey = Symbol("EventZIndex");
|
|
8
|
+
const RenderPlaneContextKey = Symbol("RenderPlane");
|
|
9
|
+
const ImeAnchorContextKey = Symbol("ImeAnchor");
|
|
10
|
+
const TInputPluginsContextKey = Symbol("TInputPlugins");
|
|
11
|
+
const TPathPickerProviderContextKey = Symbol("TPathPickerProvider");
|
|
12
|
+
const DialogContextKey = Symbol("DialogContext");
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/vue/composables/use-layout.ts
|
|
16
|
+
function useLayout() {
|
|
17
|
+
const ctx = inject(LayoutContextKey, null);
|
|
18
|
+
if (!ctx) throw new Error("LayoutContext is missing (TerminalProvider/TView)");
|
|
19
|
+
return ctx;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/vue/render/context.ts
|
|
24
|
+
const RenderStackKey = Symbol("RenderStack");
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/vue/composables/use-render-stack.ts
|
|
28
|
+
function useRenderStack() {
|
|
29
|
+
const stack = inject(RenderStackKey, null);
|
|
30
|
+
if (!stack) throw new Error("RenderStack is missing");
|
|
31
|
+
return stack;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/vue/composables/use-terminal.ts
|
|
36
|
+
function useTerminal() {
|
|
37
|
+
const ctx = inject(TerminalContextKey, null);
|
|
38
|
+
if (!ctx) throw new Error("TerminalProvider is missing");
|
|
39
|
+
return ctx;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/vue/composables/use-render-node.ts
|
|
44
|
+
const pendingInvalidateByScheduler = new WeakMap();
|
|
45
|
+
function mergePriority(prev, next) {
|
|
46
|
+
if (prev === "high" || next === "high") return "high";
|
|
47
|
+
if (prev === "normal" || next === "normal") return "normal";
|
|
48
|
+
return "low";
|
|
49
|
+
}
|
|
50
|
+
function requestBatchedInvalidate(scheduler, plane, priority) {
|
|
51
|
+
let state = pendingInvalidateByScheduler.get(scheduler);
|
|
52
|
+
if (!state) {
|
|
53
|
+
state = {
|
|
54
|
+
queued: false,
|
|
55
|
+
plane: null,
|
|
56
|
+
priority: "low"
|
|
57
|
+
};
|
|
58
|
+
pendingInvalidateByScheduler.set(scheduler, state);
|
|
59
|
+
}
|
|
60
|
+
if (state.queued) {
|
|
61
|
+
if (state.plane !== null && state.plane !== plane) state.plane = null;
|
|
62
|
+
state.priority = mergePriority(state.priority, priority);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
state.plane = plane;
|
|
66
|
+
state.priority = priority;
|
|
67
|
+
state.queued = true;
|
|
68
|
+
queueMicrotask(() => {
|
|
69
|
+
state.queued = false;
|
|
70
|
+
const queuedPlane = state.plane;
|
|
71
|
+
const queuedPriority = state.priority;
|
|
72
|
+
state.plane = null;
|
|
73
|
+
state.priority = "low";
|
|
74
|
+
scheduler.invalidate({
|
|
75
|
+
plane: queuedPlane ?? void 0,
|
|
76
|
+
priority: queuedPriority
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function useRenderNode(getOptions) {
|
|
81
|
+
const { scheduler, render } = useTerminal();
|
|
82
|
+
const parentStack = useRenderStack();
|
|
83
|
+
const plane = inject(RenderPlaneContextKey, ref("default"));
|
|
84
|
+
const id = ref(null);
|
|
85
|
+
const lastPlane = ref(plane.value);
|
|
86
|
+
const options = computed(() => getOptions());
|
|
87
|
+
const stop = watchEffect(() => {
|
|
88
|
+
const opt = options.value;
|
|
89
|
+
opt.deps;
|
|
90
|
+
const stack = opt.stack ?? parentStack.value;
|
|
91
|
+
const nextPlane = plane.value;
|
|
92
|
+
if (!stack) return;
|
|
93
|
+
if (!id.value) {
|
|
94
|
+
const node = render.register({
|
|
95
|
+
stack,
|
|
96
|
+
zIndex: opt.zIndex,
|
|
97
|
+
rect: opt.rect,
|
|
98
|
+
plane: nextPlane,
|
|
99
|
+
paint: opt.paint
|
|
100
|
+
});
|
|
101
|
+
id.value = node.id;
|
|
102
|
+
lastPlane.value = nextPlane;
|
|
103
|
+
requestBatchedInvalidate(scheduler, nextPlane, opt.priority ?? "normal");
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const prevPlane = lastPlane.value;
|
|
107
|
+
const updatePayload = {
|
|
108
|
+
stack,
|
|
109
|
+
zIndex: opt.zIndex ?? 0,
|
|
110
|
+
dirtyRowsHint: opt.dirtyRowsHint,
|
|
111
|
+
plane: nextPlane,
|
|
112
|
+
paint: opt.paint
|
|
113
|
+
};
|
|
114
|
+
if (Object.prototype.hasOwnProperty.call(opt, "rect")) updatePayload.rect = opt.rect ?? null;
|
|
115
|
+
render.update(id.value, updatePayload);
|
|
116
|
+
lastPlane.value = nextPlane;
|
|
117
|
+
const priority = opt.priority ?? "normal";
|
|
118
|
+
requestBatchedInvalidate(scheduler, prevPlane, priority);
|
|
119
|
+
if (prevPlane !== nextPlane) requestBatchedInvalidate(scheduler, nextPlane, priority);
|
|
120
|
+
});
|
|
121
|
+
onBeforeUnmount(() => {
|
|
122
|
+
stop();
|
|
123
|
+
if (id.value) {
|
|
124
|
+
render.unregister(id.value);
|
|
125
|
+
requestBatchedInvalidate(scheduler, lastPlane.value, "normal");
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
return { id };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region src/vue/composables/use-terminal-node.ts
|
|
133
|
+
function useTerminalNode(getOptions) {
|
|
134
|
+
const { events } = useTerminal();
|
|
135
|
+
const id = ref(null);
|
|
136
|
+
const options = computed(() => getOptions());
|
|
137
|
+
const stop = watchEffect(() => {
|
|
138
|
+
const manager = events.value;
|
|
139
|
+
if (!manager) return;
|
|
140
|
+
const opt = options.value;
|
|
141
|
+
if (!id.value) {
|
|
142
|
+
const node = manager.register({
|
|
143
|
+
rect: opt.rect,
|
|
144
|
+
zIndex: opt.zIndex ?? 0,
|
|
145
|
+
visible: opt.visible,
|
|
146
|
+
focusable: opt.focusable,
|
|
147
|
+
selectable: opt.selectable,
|
|
148
|
+
handlers: opt.handlers ?? {}
|
|
149
|
+
});
|
|
150
|
+
id.value = node.id;
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
manager.update(id.value, {
|
|
154
|
+
rect: opt.rect,
|
|
155
|
+
zIndex: opt.zIndex ?? 0,
|
|
156
|
+
visible: opt.visible,
|
|
157
|
+
focusable: opt.focusable,
|
|
158
|
+
selectable: opt.selectable,
|
|
159
|
+
handlers: opt.handlers ?? {}
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
onBeforeUnmount(() => {
|
|
163
|
+
stop();
|
|
164
|
+
const manager = events.value;
|
|
165
|
+
if (manager && id.value) manager.unregister(id.value);
|
|
166
|
+
});
|
|
167
|
+
return { id };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
//#endregion
|
|
171
|
+
//#region src/vue/composables/use-visibility.ts
|
|
172
|
+
const VUE_TERMINAL_SHOW_CB = "__vueTerminalOnShow";
|
|
173
|
+
let vShowPatched = false;
|
|
174
|
+
function patchVShow() {
|
|
175
|
+
if (vShowPatched) return;
|
|
176
|
+
vShowPatched = true;
|
|
177
|
+
const dir = vShow;
|
|
178
|
+
const origBeforeMount = dir.beforeMount;
|
|
179
|
+
const origUpdated = dir.updated;
|
|
180
|
+
const origBeforeUnmount = dir.beforeUnmount;
|
|
181
|
+
const notify = (el, value) => {
|
|
182
|
+
if (!el || typeof el !== "object") return;
|
|
183
|
+
const cb = el[VUE_TERMINAL_SHOW_CB];
|
|
184
|
+
cb === null || cb === void 0 || cb(Boolean(value));
|
|
185
|
+
};
|
|
186
|
+
if (typeof origBeforeMount === "function") dir.beforeMount = (el, binding, vnode) => {
|
|
187
|
+
origBeforeMount(el, binding, vnode);
|
|
188
|
+
notify(el, binding === null || binding === void 0 ? void 0 : binding.value);
|
|
189
|
+
};
|
|
190
|
+
if (typeof origUpdated === "function") dir.updated = (el, binding, vnode) => {
|
|
191
|
+
origUpdated(el, binding, vnode);
|
|
192
|
+
notify(el, binding === null || binding === void 0 ? void 0 : binding.value);
|
|
193
|
+
};
|
|
194
|
+
if (typeof origBeforeUnmount === "function") dir.beforeUnmount = (el, binding, vnode) => {
|
|
195
|
+
origBeforeUnmount(el, binding, vnode);
|
|
196
|
+
notify(el, binding === null || binding === void 0 ? void 0 : binding.value);
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
const PLACEHOLDER_STYLE = Object.freeze({
|
|
200
|
+
position: "absolute",
|
|
201
|
+
left: "-9999px",
|
|
202
|
+
top: "0",
|
|
203
|
+
width: "0",
|
|
204
|
+
height: "0",
|
|
205
|
+
overflow: "hidden"
|
|
206
|
+
});
|
|
207
|
+
function useVisibility(options) {
|
|
208
|
+
patchVShow();
|
|
209
|
+
const { scheduler } = useTerminal();
|
|
210
|
+
const parentVisible = inject(VisibilityContextKey, ref(true));
|
|
211
|
+
const localVisible = ref(true);
|
|
212
|
+
const visible = computed(() => parentVisible.value && localVisible.value);
|
|
213
|
+
if (options === null || options === void 0 ? void 0 : options.provide) provide(VisibilityContextKey, visible);
|
|
214
|
+
const onShow = (value) => {
|
|
215
|
+
localVisible.value = value;
|
|
216
|
+
scheduler.invalidate();
|
|
217
|
+
};
|
|
218
|
+
const rootProps = {
|
|
219
|
+
style: PLACEHOLDER_STYLE,
|
|
220
|
+
onVnodeBeforeMount: (vnode) => {
|
|
221
|
+
const el = vnode.el;
|
|
222
|
+
if (el && typeof el === "object") el[VUE_TERMINAL_SHOW_CB] = onShow;
|
|
223
|
+
},
|
|
224
|
+
onVnodeBeforeUnmount: (vnode) => {
|
|
225
|
+
const el = vnode.el;
|
|
226
|
+
if (el && typeof el === "object" && el[VUE_TERMINAL_SHOW_CB] === onShow) delete el[VUE_TERMINAL_SHOW_CB];
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
return {
|
|
230
|
+
visible,
|
|
231
|
+
rootProps
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
//#endregion
|
|
236
|
+
//#region src/vue/utils/rect.ts
|
|
237
|
+
function intersectRect(a, b) {
|
|
238
|
+
const x0 = Math.max(a.x, b.x);
|
|
239
|
+
const y0 = Math.max(a.y, b.y);
|
|
240
|
+
const x1 = Math.min(a.x + a.w, b.x + b.w);
|
|
241
|
+
const y1 = Math.min(a.y + a.h, b.y + b.h);
|
|
242
|
+
if (x1 <= x0 || y1 <= y0) return null;
|
|
243
|
+
return {
|
|
244
|
+
x: x0,
|
|
245
|
+
y: y0,
|
|
246
|
+
w: x1 - x0,
|
|
247
|
+
h: y1 - y0
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function translateRect(rect, dx, dy) {
|
|
251
|
+
return {
|
|
252
|
+
x: rect.x + dx,
|
|
253
|
+
y: rect.y + dy,
|
|
254
|
+
w: rect.w,
|
|
255
|
+
h: rect.h
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function normalizeCellRect(rect) {
|
|
259
|
+
const x0 = Math.floor(rect.x);
|
|
260
|
+
const y0 = Math.floor(rect.y);
|
|
261
|
+
const x1 = Math.floor(rect.x + rect.w);
|
|
262
|
+
const y1 = Math.floor(rect.y + rect.h);
|
|
263
|
+
return {
|
|
264
|
+
x: x0,
|
|
265
|
+
y: y0,
|
|
266
|
+
w: Math.max(0, x1 - x0),
|
|
267
|
+
h: Math.max(0, y1 - y0)
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
//#endregion
|
|
272
|
+
//#region src/core/buffer/width.ts
|
|
273
|
+
const fullWidthRanges = [
|
|
274
|
+
[4352, 4447],
|
|
275
|
+
[9001, 9002],
|
|
276
|
+
[11904, 42191],
|
|
277
|
+
[44032, 55203],
|
|
278
|
+
[63744, 64255],
|
|
279
|
+
[65040, 65049],
|
|
280
|
+
[65072, 65135],
|
|
281
|
+
[65280, 65376],
|
|
282
|
+
[65504, 65510]
|
|
283
|
+
];
|
|
284
|
+
function isFullWidthCodePoint(codePoint) {
|
|
285
|
+
if (codePoint < 4352 || codePoint > 65510) return false;
|
|
286
|
+
for (const [start, end] of fullWidthRanges) {
|
|
287
|
+
if (codePoint < start) return false;
|
|
288
|
+
if (codePoint <= end) return true;
|
|
289
|
+
}
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
function isEmojiLike(codePoint) {
|
|
293
|
+
return codePoint >= 127744 && codePoint <= 129791 || codePoint >= 127462 && codePoint <= 127487;
|
|
294
|
+
}
|
|
295
|
+
let extendedPictographicRe = null;
|
|
296
|
+
try {
|
|
297
|
+
extendedPictographicRe = new RegExp("\\p{Extended_Pictographic}", "u");
|
|
298
|
+
} catch {
|
|
299
|
+
extendedPictographicRe = null;
|
|
300
|
+
}
|
|
301
|
+
let emojiPresentationRe = null;
|
|
302
|
+
try {
|
|
303
|
+
emojiPresentationRe = new RegExp("\\p{Emoji_Presentation}", "u");
|
|
304
|
+
} catch {
|
|
305
|
+
emojiPresentationRe = null;
|
|
306
|
+
}
|
|
307
|
+
let emojiRe = null;
|
|
308
|
+
try {
|
|
309
|
+
emojiRe = new RegExp("\\p{Emoji}", "u");
|
|
310
|
+
} catch {
|
|
311
|
+
emojiRe = null;
|
|
312
|
+
}
|
|
313
|
+
function charCellWidth(text) {
|
|
314
|
+
if (!text) return 1;
|
|
315
|
+
if (text.length === 1) {
|
|
316
|
+
const code = text.charCodeAt(0);
|
|
317
|
+
if (code < 4352) return 1;
|
|
318
|
+
}
|
|
319
|
+
const codePoint = text.codePointAt(0);
|
|
320
|
+
if (codePoint == null) return 1;
|
|
321
|
+
const hasVs16 = text.includes("️");
|
|
322
|
+
if (isFullWidthCodePoint(codePoint)) return 2;
|
|
323
|
+
if (isEmojiLike(codePoint)) return 2;
|
|
324
|
+
if (emojiPresentationRe === null || emojiPresentationRe === void 0 ? void 0 : emojiPresentationRe.test(text)) return 2;
|
|
325
|
+
if (text.includes("⃣")) return 2;
|
|
326
|
+
if (hasVs16 && (emojiRe === null || emojiRe === void 0 ? void 0 : emojiRe.test(text))) return 2;
|
|
327
|
+
if (extendedPictographicRe === null || extendedPictographicRe === void 0 ? void 0 : extendedPictographicRe.test(text)) {
|
|
328
|
+
if (codePoint <= 65535) return hasVs16 ? 2 : 1;
|
|
329
|
+
return 2;
|
|
330
|
+
}
|
|
331
|
+
return 1;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
//#endregion
|
|
335
|
+
//#region src/vue/utils/text.ts
|
|
336
|
+
let renderPassDepth = 0;
|
|
337
|
+
const renderPassTextWidthCache = new Map();
|
|
338
|
+
function withTextRenderPass(fn) {
|
|
339
|
+
renderPassDepth++;
|
|
340
|
+
try {
|
|
341
|
+
if (renderPassDepth === 1) renderPassTextWidthCache.clear();
|
|
342
|
+
return fn();
|
|
343
|
+
} finally {
|
|
344
|
+
renderPassDepth--;
|
|
345
|
+
if (renderPassDepth === 0) renderPassTextWidthCache.clear();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function isAscii(text) {
|
|
349
|
+
for (let i = 0; i < text.length; i++) if (text.charCodeAt(i) > 127) return false;
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
function needsGraphemeSegmentation(text) {
|
|
353
|
+
for (const ch of text) {
|
|
354
|
+
const cp = ch.codePointAt(0);
|
|
355
|
+
if (cp === 8205) return true;
|
|
356
|
+
if (cp >= 65024 && cp <= 65039 || cp >= 917760 && cp <= 917999) return true;
|
|
357
|
+
if (cp >= 768 && cp <= 879 || cp >= 6832 && cp <= 6911 || cp >= 7616 && cp <= 7679 || cp >= 8400 && cp <= 8447 || cp >= 65056 && cp <= 65071) return true;
|
|
358
|
+
if (cp >= 127995 && cp <= 127999) return true;
|
|
359
|
+
if (cp >= 127462 && cp <= 127487) return true;
|
|
360
|
+
}
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
363
|
+
let graphemeSegmenter = null;
|
|
364
|
+
try {
|
|
365
|
+
graphemeSegmenter = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : null;
|
|
366
|
+
} catch {
|
|
367
|
+
graphemeSegmenter = null;
|
|
368
|
+
}
|
|
369
|
+
function forEachGrapheme(text, cb) {
|
|
370
|
+
if (!text) return;
|
|
371
|
+
const seg = graphemeSegmenter;
|
|
372
|
+
if (!seg || !needsGraphemeSegmentation(text)) {
|
|
373
|
+
for (const ch of text) {
|
|
374
|
+
const r = cb(ch);
|
|
375
|
+
if (r === false) return;
|
|
376
|
+
}
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
for (const part of seg.segment(text)) {
|
|
380
|
+
const r = cb(part.segment);
|
|
381
|
+
if (r === false) return;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
function forEachTextCellSegment(text, cb) {
|
|
385
|
+
if (!text) return;
|
|
386
|
+
const seg = graphemeSegmenter;
|
|
387
|
+
if (!seg || !needsGraphemeSegmentation(text)) {
|
|
388
|
+
let index$1 = 0;
|
|
389
|
+
for (const ch of text) {
|
|
390
|
+
const next = index$1 + ch.length;
|
|
391
|
+
const result = cb({
|
|
392
|
+
text: ch,
|
|
393
|
+
cells: charCellWidth(ch),
|
|
394
|
+
start: index$1,
|
|
395
|
+
end: next
|
|
396
|
+
});
|
|
397
|
+
if (result === false) return;
|
|
398
|
+
index$1 = next;
|
|
399
|
+
}
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
let index = 0;
|
|
403
|
+
for (const part of seg.segment(text)) {
|
|
404
|
+
const start = part.index ?? index;
|
|
405
|
+
const end = start + part.segment.length;
|
|
406
|
+
const result = cb({
|
|
407
|
+
text: part.segment,
|
|
408
|
+
cells: charCellWidth(part.segment),
|
|
409
|
+
start,
|
|
410
|
+
end
|
|
411
|
+
});
|
|
412
|
+
if (result === false) return;
|
|
413
|
+
index = end;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
function graphemeRangeAt(text, index) {
|
|
417
|
+
if (!text) return null;
|
|
418
|
+
const len = text.length;
|
|
419
|
+
if (index < 0 || index >= len) return null;
|
|
420
|
+
if (isAscii(text)) return {
|
|
421
|
+
start: index,
|
|
422
|
+
end: index + 1
|
|
423
|
+
};
|
|
424
|
+
const seg = graphemeSegmenter;
|
|
425
|
+
if (seg && needsGraphemeSegmentation(text)) {
|
|
426
|
+
let pos$1 = 0;
|
|
427
|
+
for (const part of seg.segment(text)) {
|
|
428
|
+
const start = pos$1;
|
|
429
|
+
const end = start + part.segment.length;
|
|
430
|
+
if (index >= start && index < end) return {
|
|
431
|
+
start,
|
|
432
|
+
end
|
|
433
|
+
};
|
|
434
|
+
pos$1 = end;
|
|
435
|
+
}
|
|
436
|
+
return null;
|
|
437
|
+
}
|
|
438
|
+
let pos = 0;
|
|
439
|
+
for (const ch of text) {
|
|
440
|
+
const start = pos;
|
|
441
|
+
const end = start + ch.length;
|
|
442
|
+
if (index >= start && index < end) return {
|
|
443
|
+
start,
|
|
444
|
+
end
|
|
445
|
+
};
|
|
446
|
+
pos = end;
|
|
447
|
+
}
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
function sanitizeInlineText(text) {
|
|
451
|
+
if (!text) return "";
|
|
452
|
+
if (!/[\n\r\t]/.test(text)) return text;
|
|
453
|
+
return text.replace(/[\n\r\t]/g, " ");
|
|
454
|
+
}
|
|
455
|
+
function sanitizeTextBlock(text) {
|
|
456
|
+
if (!text) return "";
|
|
457
|
+
if (!/[\t\x00-\x08\x0B-\x1F\x7F]/.test(text)) return text;
|
|
458
|
+
const out = [];
|
|
459
|
+
out.length = 0;
|
|
460
|
+
for (const ch of text) {
|
|
461
|
+
const cp = ch.codePointAt(0);
|
|
462
|
+
if (cp === 13) continue;
|
|
463
|
+
if (cp === 9) {
|
|
464
|
+
out.push(" ");
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
if (cp <= 31 && cp !== 10 || cp === 127) continue;
|
|
468
|
+
out.push(ch);
|
|
469
|
+
}
|
|
470
|
+
return out.join("");
|
|
471
|
+
}
|
|
472
|
+
function textCellWidth(text) {
|
|
473
|
+
if (!text) return 0;
|
|
474
|
+
if (isAscii(text)) return text.length;
|
|
475
|
+
if (renderPassDepth > 0) {
|
|
476
|
+
const cached$1 = renderPassTextWidthCache.get(text);
|
|
477
|
+
if (cached$1 != null) return cached$1;
|
|
478
|
+
}
|
|
479
|
+
const cached = textWidthCacheGet(text);
|
|
480
|
+
if (cached != null) return cached;
|
|
481
|
+
let cells = 0;
|
|
482
|
+
forEachGrapheme(text, (g) => {
|
|
483
|
+
cells += charCellWidth(g);
|
|
484
|
+
});
|
|
485
|
+
if (renderPassDepth > 0) renderPassTextWidthCache.set(text, cells);
|
|
486
|
+
textWidthCacheSet(text, cells);
|
|
487
|
+
return cells;
|
|
488
|
+
}
|
|
489
|
+
const spaceCache = new Map();
|
|
490
|
+
const MAX_CACHED_SPACES = 256;
|
|
491
|
+
function spaces(count) {
|
|
492
|
+
count = Math.max(0, Math.floor(count));
|
|
493
|
+
if (count === 0) return "";
|
|
494
|
+
const cached = spaceCache.get(count);
|
|
495
|
+
if (cached) return cached;
|
|
496
|
+
const v = " ".repeat(count);
|
|
497
|
+
if (spaceCache.size >= MAX_CACHED_SPACES) spaceCache.clear();
|
|
498
|
+
spaceCache.set(count, v);
|
|
499
|
+
return v;
|
|
500
|
+
}
|
|
501
|
+
const repeatCharCache = new Map();
|
|
502
|
+
const MAX_REPEAT_CHAR_KEYS = 8;
|
|
503
|
+
const MAX_CACHED_REPEAT_CHAR = 256;
|
|
504
|
+
function repeatChar(ch, count) {
|
|
505
|
+
count = Math.max(0, Math.floor(count));
|
|
506
|
+
if (count === 0) return "";
|
|
507
|
+
if (!ch) return "";
|
|
508
|
+
let bucket = repeatCharCache.get(ch);
|
|
509
|
+
if (!bucket) {
|
|
510
|
+
if (repeatCharCache.size >= MAX_REPEAT_CHAR_KEYS) repeatCharCache.clear();
|
|
511
|
+
bucket = new Map();
|
|
512
|
+
repeatCharCache.set(ch, bucket);
|
|
513
|
+
}
|
|
514
|
+
const cached = bucket.get(count);
|
|
515
|
+
if (cached) return cached;
|
|
516
|
+
const v = ch.repeat(count);
|
|
517
|
+
if (bucket.size >= MAX_CACHED_REPEAT_CHAR) bucket.clear();
|
|
518
|
+
bucket.set(count, v);
|
|
519
|
+
return v;
|
|
520
|
+
}
|
|
521
|
+
function sliceByCells(text, maxCells) {
|
|
522
|
+
maxCells = Math.max(0, Math.floor(maxCells));
|
|
523
|
+
if (maxCells <= 0) return "";
|
|
524
|
+
if (text && isAscii(text)) return text.slice(0, maxCells);
|
|
525
|
+
const out = [];
|
|
526
|
+
let cells = 0;
|
|
527
|
+
forEachGrapheme(text, (g) => {
|
|
528
|
+
const w = charCellWidth(g);
|
|
529
|
+
if (cells + w > maxCells) return false;
|
|
530
|
+
out.push(g);
|
|
531
|
+
cells += w;
|
|
532
|
+
return void 0;
|
|
533
|
+
});
|
|
534
|
+
return out.length ? out.join("") : "";
|
|
535
|
+
}
|
|
536
|
+
function sliceByCellsRange(text, startCells, endCells) {
|
|
537
|
+
startCells = Math.max(0, Math.floor(startCells));
|
|
538
|
+
endCells = Math.max(0, Math.floor(endCells));
|
|
539
|
+
if (endCells <= startCells) return "";
|
|
540
|
+
if (!text) return "";
|
|
541
|
+
if (isAscii(text)) return text.slice(startCells, endCells);
|
|
542
|
+
const out = [];
|
|
543
|
+
let cells = 0;
|
|
544
|
+
forEachGrapheme(text, (g) => {
|
|
545
|
+
const w = charCellWidth(g);
|
|
546
|
+
const next = cells + w;
|
|
547
|
+
if (cells >= endCells) return false;
|
|
548
|
+
if (next <= startCells) {
|
|
549
|
+
cells = next;
|
|
550
|
+
return void 0;
|
|
551
|
+
}
|
|
552
|
+
if (cells < startCells && next > startCells) {
|
|
553
|
+
out.push(spaces(Math.min(next, endCells) - startCells));
|
|
554
|
+
cells = next;
|
|
555
|
+
return void 0;
|
|
556
|
+
}
|
|
557
|
+
if (next > endCells) {
|
|
558
|
+
out.push(spaces(endCells - cells));
|
|
559
|
+
return false;
|
|
560
|
+
}
|
|
561
|
+
out.push(g);
|
|
562
|
+
cells = next;
|
|
563
|
+
return void 0;
|
|
564
|
+
});
|
|
565
|
+
return out.length ? out.join("") : "";
|
|
566
|
+
}
|
|
567
|
+
function padEndByCells(text, width) {
|
|
568
|
+
width = Math.max(0, Math.floor(width));
|
|
569
|
+
const cells = text && isAscii(text) ? text.length : textCellWidth(text);
|
|
570
|
+
if (cells >= width) return text;
|
|
571
|
+
return `${text}${spaces(width - cells)}`;
|
|
572
|
+
}
|
|
573
|
+
const inlineLineCacheByWidth = new Map();
|
|
574
|
+
const MAX_INLINE_LINE_CACHE_BUCKETS = 32;
|
|
575
|
+
const MAX_INLINE_LINE_CACHE_PER_WIDTH = 512;
|
|
576
|
+
function getInlineLineBucket(width) {
|
|
577
|
+
let bucket = inlineLineCacheByWidth.get(width);
|
|
578
|
+
if (bucket) return bucket;
|
|
579
|
+
if (inlineLineCacheByWidth.size >= MAX_INLINE_LINE_CACHE_BUCKETS) inlineLineCacheByWidth.clear();
|
|
580
|
+
bucket = new Map();
|
|
581
|
+
inlineLineCacheByWidth.set(width, bucket);
|
|
582
|
+
return bucket;
|
|
583
|
+
}
|
|
584
|
+
function formatInlineCellLine(text, width) {
|
|
585
|
+
width = Math.max(0, Math.floor(width));
|
|
586
|
+
if (width === 0) return "";
|
|
587
|
+
if (!text) return spaces(width);
|
|
588
|
+
const bucket = getInlineLineBucket(width);
|
|
589
|
+
const cached = bucket.get(text);
|
|
590
|
+
if (cached != null) return cached;
|
|
591
|
+
const sanitized = sanitizeInlineText(text);
|
|
592
|
+
if (sanitized && isAscii(sanitized)) {
|
|
593
|
+
const out$1 = sanitized.length >= width ? sanitized.slice(0, width) : `${sanitized}${spaces(width - sanitized.length)}`;
|
|
594
|
+
if (bucket.size >= MAX_INLINE_LINE_CACHE_PER_WIDTH) bucket.clear();
|
|
595
|
+
bucket.set(text, out$1);
|
|
596
|
+
return out$1;
|
|
597
|
+
}
|
|
598
|
+
const out = padEndByCells(sliceByCells(sanitized, width), width);
|
|
599
|
+
if (bucket.size >= MAX_INLINE_LINE_CACHE_PER_WIDTH) bucket.clear();
|
|
600
|
+
bucket.set(text, out);
|
|
601
|
+
return out;
|
|
602
|
+
}
|
|
603
|
+
const wrapCacheByWidth = new Map();
|
|
604
|
+
const MAX_WRAP_CACHE_BUCKETS = 32;
|
|
605
|
+
const MAX_WRAP_CACHE_PER_WIDTH = 256;
|
|
606
|
+
function getWrapBucket(width) {
|
|
607
|
+
let bucket = wrapCacheByWidth.get(width);
|
|
608
|
+
if (bucket) return bucket;
|
|
609
|
+
if (wrapCacheByWidth.size >= MAX_WRAP_CACHE_BUCKETS) wrapCacheByWidth.clear();
|
|
610
|
+
bucket = new Map();
|
|
611
|
+
wrapCacheByWidth.set(width, bucket);
|
|
612
|
+
return bucket;
|
|
613
|
+
}
|
|
614
|
+
const textWidthCache = new Map();
|
|
615
|
+
const MAX_TEXT_WIDTH_CACHE = 1024;
|
|
616
|
+
function textWidthCacheGet(text) {
|
|
617
|
+
const cached = textWidthCache.get(text);
|
|
618
|
+
if (cached == null) return null;
|
|
619
|
+
textWidthCache.delete(text);
|
|
620
|
+
textWidthCache.set(text, cached);
|
|
621
|
+
return cached;
|
|
622
|
+
}
|
|
623
|
+
function textWidthCacheSet(text, cells) {
|
|
624
|
+
textWidthCache.set(text, cells);
|
|
625
|
+
if (textWidthCache.size > MAX_TEXT_WIDTH_CACHE) {
|
|
626
|
+
const firstKey = textWidthCache.keys().next().value;
|
|
627
|
+
if (firstKey != null) textWidthCache.delete(firstKey);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
function clearTextCaches() {
|
|
631
|
+
wrapCacheByWidth.clear();
|
|
632
|
+
spaceCache.clear();
|
|
633
|
+
repeatCharCache.clear();
|
|
634
|
+
textWidthCache.clear();
|
|
635
|
+
inlineLineCacheByWidth.clear();
|
|
636
|
+
}
|
|
637
|
+
function wrapByCells(text, width) {
|
|
638
|
+
width = Math.max(1, Math.floor(width));
|
|
639
|
+
const bucket = getWrapBucket(width);
|
|
640
|
+
if (text && isAscii(text)) {
|
|
641
|
+
const cached$1 = bucket.get(text);
|
|
642
|
+
if (cached$1) return cached$1;
|
|
643
|
+
const out$1 = [];
|
|
644
|
+
for (const rawLine of text.replace(/\r/g, "").split("\n")) {
|
|
645
|
+
if (rawLine.length === 0) {
|
|
646
|
+
out$1.push("");
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
for (let i = 0; i < rawLine.length; i += width) out$1.push(rawLine.slice(i, i + width));
|
|
650
|
+
}
|
|
651
|
+
if (bucket.size >= MAX_WRAP_CACHE_PER_WIDTH) bucket.clear();
|
|
652
|
+
bucket.set(text, out$1);
|
|
653
|
+
return out$1;
|
|
654
|
+
}
|
|
655
|
+
const cached = bucket.get(text);
|
|
656
|
+
if (cached) return cached;
|
|
657
|
+
const out = [];
|
|
658
|
+
for (const rawLine of text.replace(/\r/g, "").split("\n")) {
|
|
659
|
+
if (rawLine.length === 0) {
|
|
660
|
+
out.push("");
|
|
661
|
+
continue;
|
|
662
|
+
}
|
|
663
|
+
const seg = graphemeSegmenter;
|
|
664
|
+
if (seg && needsGraphemeSegmentation(rawLine)) {
|
|
665
|
+
let lineStart = 0;
|
|
666
|
+
let cells = 0;
|
|
667
|
+
for (const part of seg.segment(rawLine)) {
|
|
668
|
+
const g = part.segment;
|
|
669
|
+
const gIdx = part.index;
|
|
670
|
+
const w = charCellWidth(g);
|
|
671
|
+
if (cells > 0 && cells + w > width) {
|
|
672
|
+
out.push(rawLine.slice(lineStart, gIdx));
|
|
673
|
+
lineStart = gIdx;
|
|
674
|
+
cells = 0;
|
|
675
|
+
}
|
|
676
|
+
cells += w;
|
|
677
|
+
if (cells >= width) {
|
|
678
|
+
const end = gIdx + g.length;
|
|
679
|
+
out.push(rawLine.slice(lineStart, end));
|
|
680
|
+
lineStart = end;
|
|
681
|
+
cells = 0;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
if (lineStart < rawLine.length) out.push(rawLine.slice(lineStart));
|
|
685
|
+
} else {
|
|
686
|
+
let lineStart = 0;
|
|
687
|
+
let pos = 0;
|
|
688
|
+
let cells = 0;
|
|
689
|
+
for (const ch of rawLine) {
|
|
690
|
+
const w = charCellWidth(ch);
|
|
691
|
+
if (cells > 0 && cells + w > width) {
|
|
692
|
+
out.push(rawLine.slice(lineStart, pos));
|
|
693
|
+
lineStart = pos;
|
|
694
|
+
cells = 0;
|
|
695
|
+
}
|
|
696
|
+
pos += ch.length;
|
|
697
|
+
cells += w;
|
|
698
|
+
if (cells >= width) {
|
|
699
|
+
out.push(rawLine.slice(lineStart, pos));
|
|
700
|
+
lineStart = pos;
|
|
701
|
+
cells = 0;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
if (lineStart < rawLine.length) out.push(rawLine.slice(lineStart));
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
const res = out.length ? out : [""];
|
|
708
|
+
if (bucket.size >= MAX_WRAP_CACHE_PER_WIDTH) bucket.clear();
|
|
709
|
+
bucket.set(text, res);
|
|
710
|
+
return res;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
//#endregion
|
|
714
|
+
//#region src/vue/utils/wheel-scroll.ts
|
|
715
|
+
const LINE_UNIT_THRESHOLD = 3;
|
|
716
|
+
const PIXELS_PER_LINE = 16;
|
|
717
|
+
const ACCEL_WINDOW_MS = 120;
|
|
718
|
+
const MAX_ACCEL = 26;
|
|
719
|
+
const EDGE_BOUNCE_MS = 120;
|
|
720
|
+
const MIN_TICK_INTERVAL_MS = 6;
|
|
721
|
+
function clamp(n, min, max) {
|
|
722
|
+
return Math.max(min, Math.min(max, n));
|
|
723
|
+
}
|
|
724
|
+
function isLineUnitDelta(deltaY, mode = "auto") {
|
|
725
|
+
if (mode === "line") return true;
|
|
726
|
+
if (mode === "pixel") return false;
|
|
727
|
+
const abs = Math.abs(deltaY);
|
|
728
|
+
return abs > 0 && abs <= LINE_UNIT_THRESHOLD && Number.isInteger(deltaY);
|
|
729
|
+
}
|
|
730
|
+
function normalizeDelta(deltaY, mode = "auto") {
|
|
731
|
+
if (mode === "line") return deltaY;
|
|
732
|
+
if (mode === "pixel") return deltaY / PIXELS_PER_LINE;
|
|
733
|
+
const abs = Math.abs(deltaY);
|
|
734
|
+
if (abs <= LINE_UNIT_THRESHOLD && Number.isInteger(deltaY)) return deltaY;
|
|
735
|
+
return deltaY / PIXELS_PER_LINE;
|
|
736
|
+
}
|
|
737
|
+
function accelFactor(now, lastAt) {
|
|
738
|
+
const dt = now - lastAt;
|
|
739
|
+
if (!Number.isFinite(dt) || dt <= 0 || dt > ACCEL_WINDOW_MS) return 1;
|
|
740
|
+
const t = 1 - dt / ACCEL_WINDOW_MS;
|
|
741
|
+
return 1 + t * (MAX_ACCEL - 1);
|
|
742
|
+
}
|
|
743
|
+
function createWheelScrollState() {
|
|
744
|
+
return {
|
|
745
|
+
accumulator: 0,
|
|
746
|
+
lastAt: 0,
|
|
747
|
+
lastEdgeDir: 0,
|
|
748
|
+
lastEdgeAt: 0
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
function resetWheelScrollState(state) {
|
|
752
|
+
state.accumulator = 0;
|
|
753
|
+
state.lastAt = 0;
|
|
754
|
+
state.lastEdgeDir = 0;
|
|
755
|
+
state.lastEdgeAt = 0;
|
|
756
|
+
}
|
|
757
|
+
function applyWheelScroll(state, deltaY, scrollTop, maxTop, now = Date.now(), deltaMode = "auto", options = {}) {
|
|
758
|
+
if (!Number.isFinite(deltaY) || deltaY === 0 || maxTop <= 0) {
|
|
759
|
+
if (maxTop <= 0) {
|
|
760
|
+
state.accumulator = 0;
|
|
761
|
+
state.lastEdgeDir = 0;
|
|
762
|
+
state.lastEdgeAt = 0;
|
|
763
|
+
}
|
|
764
|
+
return {
|
|
765
|
+
nextTop: scrollTop,
|
|
766
|
+
dir: 0,
|
|
767
|
+
lines: 0
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
const dt = state.lastAt ? now - state.lastAt : Infinity;
|
|
771
|
+
const lineUnits = isLineUnitDelta(deltaY, deltaMode);
|
|
772
|
+
if (lineUnits && dt !== Infinity && dt >= 0 && dt < MIN_TICK_INTERVAL_MS) return {
|
|
773
|
+
nextTop: scrollTop,
|
|
774
|
+
dir: 0,
|
|
775
|
+
lines: 0
|
|
776
|
+
};
|
|
777
|
+
const accel = lineUnits ? 1 : options.disableAcceleration ? 1 : state.lastAt ? accelFactor(now, state.lastAt) : 1;
|
|
778
|
+
state.lastAt = now;
|
|
779
|
+
state.accumulator += normalizeDelta(deltaY, deltaMode) * accel;
|
|
780
|
+
const lines = Math.trunc(state.accumulator);
|
|
781
|
+
if (lines === 0) return {
|
|
782
|
+
nextTop: scrollTop,
|
|
783
|
+
dir: 0,
|
|
784
|
+
lines: 0
|
|
785
|
+
};
|
|
786
|
+
state.accumulator -= lines;
|
|
787
|
+
const dir = lines > 0 ? 1 : -1;
|
|
788
|
+
const atTop = scrollTop <= 0;
|
|
789
|
+
const atBottom = scrollTop >= maxTop;
|
|
790
|
+
if (dir < 0 && atTop || dir > 0 && atBottom) {
|
|
791
|
+
state.lastEdgeDir = dir;
|
|
792
|
+
state.lastEdgeAt = now;
|
|
793
|
+
state.accumulator = 0;
|
|
794
|
+
return {
|
|
795
|
+
nextTop: scrollTop,
|
|
796
|
+
dir: 0,
|
|
797
|
+
lines: 0
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
if (state.lastEdgeDir !== 0 && now - state.lastEdgeAt < EDGE_BOUNCE_MS && dir === -state.lastEdgeDir && (atTop || atBottom)) return {
|
|
801
|
+
nextTop: scrollTop,
|
|
802
|
+
dir: 0,
|
|
803
|
+
lines: 0
|
|
804
|
+
};
|
|
805
|
+
const unclamped = scrollTop + lines;
|
|
806
|
+
const nextTop = clamp(unclamped, 0, maxTop);
|
|
807
|
+
if (nextTop === scrollTop) {
|
|
808
|
+
state.accumulator = 0;
|
|
809
|
+
return {
|
|
810
|
+
nextTop: scrollTop,
|
|
811
|
+
dir: 0,
|
|
812
|
+
lines: 0
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
if (nextTop !== unclamped) state.accumulator = 0;
|
|
816
|
+
state.lastEdgeDir = 0;
|
|
817
|
+
return {
|
|
818
|
+
nextTop,
|
|
819
|
+
dir: nextTop > scrollTop ? 1 : -1,
|
|
820
|
+
lines: nextTop - scrollTop
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
//#endregion
|
|
825
|
+
export { DialogContextKey, EventZIndexContextKey, ImeAnchorContextKey, LayoutContextKey, RenderPlaneContextKey, RenderStackKey, TInputPluginsContextKey, TPathPickerProviderContextKey, TerminalContextKey, VisibilityContextKey, applyWheelScroll, charCellWidth, clearTextCaches, createWheelScrollState, forEachTextCellSegment, formatInlineCellLine, graphemeRangeAt, intersectRect, normalizeCellRect, padEndByCells, repeatChar, resetWheelScrollState, sanitizeInlineText, sanitizeTextBlock, sliceByCells, sliceByCellsRange, spaces, textCellWidth, translateRect, useLayout, useRenderNode, useRenderStack, useTerminal, useTerminalNode, useVisibility, withTextRenderPass, wrapByCells };
|