@simon_he/vue-tui 0.0.1 → 0.0.2
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 +1 -1
- package/dist/index.cjs +567 -203
- package/dist/index.d.ts +8 -8
- package/dist/index.js +703 -221
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -454,33 +454,6 @@ function createNodePathPickerProvider() {
|
|
|
454
454
|
};
|
|
455
455
|
}
|
|
456
456
|
|
|
457
|
-
// src/cli/recording.ts
|
|
458
|
-
async function loadFs() {
|
|
459
|
-
return import("fs");
|
|
460
|
-
}
|
|
461
|
-
async function writeEventLog(path, events) {
|
|
462
|
-
const { writeFileSync } = await loadFs();
|
|
463
|
-
const lines = events.map((e) => JSON.stringify(e)).join("\n");
|
|
464
|
-
writeFileSync(path, `${lines}${lines ? "\n" : ""}`, "utf8");
|
|
465
|
-
}
|
|
466
|
-
async function writeSnapshot(path, lines) {
|
|
467
|
-
const { writeFileSync } = await loadFs();
|
|
468
|
-
writeFileSync(path, `${lines.join("\n")}
|
|
469
|
-
`, "utf8");
|
|
470
|
-
}
|
|
471
|
-
async function readEventLog(path) {
|
|
472
|
-
const { readFileSync } = await loadFs();
|
|
473
|
-
const raw = readFileSync(path, "utf8");
|
|
474
|
-
const out = [];
|
|
475
|
-
for (const line of raw.split(/\r?\n/g)) {
|
|
476
|
-
const trimmed = line.trim();
|
|
477
|
-
if (!trimmed)
|
|
478
|
-
continue;
|
|
479
|
-
out.push(JSON.parse(trimmed));
|
|
480
|
-
}
|
|
481
|
-
return out;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
457
|
// src/utils/path.ts
|
|
485
458
|
function normalizeSeparators(input) {
|
|
486
459
|
return input.replace(/\\/g, "/");
|
|
@@ -652,43 +625,31 @@ function resolveUserPath(workspaceAbs, input) {
|
|
|
652
625
|
return resolvePath(normalizePath(workspaceAbs), normalized);
|
|
653
626
|
}
|
|
654
627
|
|
|
655
|
-
// src/
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
[9001, 9002],
|
|
659
|
-
[11904, 42191],
|
|
660
|
-
[44032, 55203],
|
|
661
|
-
[63744, 64255],
|
|
662
|
-
[65040, 65049],
|
|
663
|
-
[65072, 65135],
|
|
664
|
-
[65280, 65376],
|
|
665
|
-
[65504, 65510]
|
|
666
|
-
];
|
|
667
|
-
function isFullWidthCodePoint(codePoint) {
|
|
668
|
-
for (const [start, end] of fullWidthRanges) {
|
|
669
|
-
if (codePoint >= start && codePoint <= end)
|
|
670
|
-
return true;
|
|
671
|
-
}
|
|
672
|
-
return false;
|
|
628
|
+
// src/cli/recording.ts
|
|
629
|
+
async function loadFs() {
|
|
630
|
+
return import("fs");
|
|
673
631
|
}
|
|
674
|
-
function
|
|
675
|
-
|
|
632
|
+
async function writeEventLog(path, events) {
|
|
633
|
+
const { writeFileSync } = await loadFs();
|
|
634
|
+
const lines = events.map((e) => JSON.stringify(e)).join("\n");
|
|
635
|
+
writeFileSync(path, `${lines}${lines ? "\n" : ""}`, "utf8");
|
|
676
636
|
}
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
extendedPictographicRe = null;
|
|
637
|
+
async function writeSnapshot(path, lines) {
|
|
638
|
+
const { writeFileSync } = await loadFs();
|
|
639
|
+
writeFileSync(path, `${lines.join("\n")}
|
|
640
|
+
`, "utf8");
|
|
682
641
|
}
|
|
683
|
-
function
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
642
|
+
async function readEventLog(path) {
|
|
643
|
+
const { readFileSync } = await loadFs();
|
|
644
|
+
const raw = readFileSync(path, "utf8");
|
|
645
|
+
const out = [];
|
|
646
|
+
for (const line of raw.split(/\r?\n/g)) {
|
|
647
|
+
const trimmed = line.trim();
|
|
648
|
+
if (!trimmed)
|
|
649
|
+
continue;
|
|
650
|
+
out.push(JSON.parse(trimmed));
|
|
651
|
+
}
|
|
652
|
+
return out;
|
|
692
653
|
}
|
|
693
654
|
|
|
694
655
|
// src/core/ansi/sgr.ts
|
|
@@ -896,6 +857,45 @@ function parseAnsiSgr(input, baseStyle = {}) {
|
|
|
896
857
|
return segments;
|
|
897
858
|
}
|
|
898
859
|
|
|
860
|
+
// src/core/buffer/width.ts
|
|
861
|
+
var fullWidthRanges = [
|
|
862
|
+
[4352, 4447],
|
|
863
|
+
[9001, 9002],
|
|
864
|
+
[11904, 42191],
|
|
865
|
+
[44032, 55203],
|
|
866
|
+
[63744, 64255],
|
|
867
|
+
[65040, 65049],
|
|
868
|
+
[65072, 65135],
|
|
869
|
+
[65280, 65376],
|
|
870
|
+
[65504, 65510]
|
|
871
|
+
];
|
|
872
|
+
function isFullWidthCodePoint(codePoint) {
|
|
873
|
+
for (const [start, end] of fullWidthRanges) {
|
|
874
|
+
if (codePoint >= start && codePoint <= end)
|
|
875
|
+
return true;
|
|
876
|
+
}
|
|
877
|
+
return false;
|
|
878
|
+
}
|
|
879
|
+
function isEmojiLike(codePoint) {
|
|
880
|
+
return codePoint >= 127744 && codePoint <= 129791 || codePoint >= 127462 && codePoint <= 127487;
|
|
881
|
+
}
|
|
882
|
+
var extendedPictographicRe = null;
|
|
883
|
+
try {
|
|
884
|
+
extendedPictographicRe = new RegExp("\\p{Extended_Pictographic}", "u");
|
|
885
|
+
} catch {
|
|
886
|
+
extendedPictographicRe = null;
|
|
887
|
+
}
|
|
888
|
+
function charCellWidth(text) {
|
|
889
|
+
if (!text)
|
|
890
|
+
return 1;
|
|
891
|
+
if (extendedPictographicRe == null ? void 0 : extendedPictographicRe.test(text))
|
|
892
|
+
return 2;
|
|
893
|
+
const codePoint = text.codePointAt(0);
|
|
894
|
+
if (codePoint == null)
|
|
895
|
+
return 1;
|
|
896
|
+
return isFullWidthCodePoint(codePoint) || isEmojiLike(codePoint) ? 2 : 1;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
899
|
// src/core/buffer/buffer.ts
|
|
900
900
|
var DEFAULT_STYLE = Object.freeze({});
|
|
901
901
|
function normalizeStyle(style) {
|
|
@@ -3690,6 +3690,60 @@ function intersectRect(a, b) {
|
|
|
3690
3690
|
function translateRect(rect, dx, dy) {
|
|
3691
3691
|
return { x: rect.x + dx, y: rect.y + dy, w: rect.w, h: rect.h };
|
|
3692
3692
|
}
|
|
3693
|
+
function normalizePadding(padding) {
|
|
3694
|
+
const nums = [];
|
|
3695
|
+
if (typeof padding === "number") {
|
|
3696
|
+
nums.push(padding);
|
|
3697
|
+
} else if (Array.isArray(padding)) {
|
|
3698
|
+
for (const v of padding)
|
|
3699
|
+
nums.push(typeof v === "number" ? v : Number(v));
|
|
3700
|
+
} else if (typeof padding === "string") {
|
|
3701
|
+
for (const part of padding.trim().split(/\s+/g)) {
|
|
3702
|
+
if (!part)
|
|
3703
|
+
continue;
|
|
3704
|
+
nums.push(Number(part));
|
|
3705
|
+
}
|
|
3706
|
+
}
|
|
3707
|
+
const n = nums.map((v) => Number.isFinite(v) ? Math.max(0, Math.floor(v)) : 0);
|
|
3708
|
+
const a = n[0] ?? 0;
|
|
3709
|
+
const b = n[1] ?? a;
|
|
3710
|
+
const c = n[2] ?? a;
|
|
3711
|
+
const d = n[3] ?? b;
|
|
3712
|
+
if (n.length <= 1)
|
|
3713
|
+
return { top: a, right: a, bottom: a, left: a };
|
|
3714
|
+
if (n.length === 2)
|
|
3715
|
+
return { top: a, right: b, bottom: a, left: b };
|
|
3716
|
+
if (n.length === 3)
|
|
3717
|
+
return { top: a, right: b, bottom: c, left: b };
|
|
3718
|
+
return { top: a, right: b, bottom: c, left: d };
|
|
3719
|
+
}
|
|
3720
|
+
function clampRectPadding(rect, padding) {
|
|
3721
|
+
const requested = normalizePadding(padding);
|
|
3722
|
+
const w = Math.max(0, Math.floor(rect.w));
|
|
3723
|
+
const h16 = Math.max(0, Math.floor(rect.h));
|
|
3724
|
+
const maxTotalX = Math.max(0, w - (w > 0 ? 1 : 0));
|
|
3725
|
+
const maxTotalY = Math.max(0, h16 - (h16 > 0 ? 1 : 0));
|
|
3726
|
+
if (requested.top === requested.right && requested.top === requested.bottom && requested.top === requested.left) {
|
|
3727
|
+
const maxPadX = Math.max(0, Math.floor(maxTotalX / 2));
|
|
3728
|
+
const maxPadY = Math.max(0, Math.floor(maxTotalY / 2));
|
|
3729
|
+
const pad = Math.min(requested.top, maxPadX, maxPadY);
|
|
3730
|
+
return { top: pad, right: pad, bottom: pad, left: pad };
|
|
3731
|
+
}
|
|
3732
|
+
const left = Math.min(requested.left, maxTotalX);
|
|
3733
|
+
const right = Math.min(requested.right, Math.max(0, maxTotalX - left));
|
|
3734
|
+
const top = Math.min(requested.top, maxTotalY);
|
|
3735
|
+
const bottom = Math.min(requested.bottom, Math.max(0, maxTotalY - top));
|
|
3736
|
+
return { top, right, bottom, left };
|
|
3737
|
+
}
|
|
3738
|
+
function insetRect(rect, padding) {
|
|
3739
|
+
const pad = clampRectPadding(rect, padding);
|
|
3740
|
+
return {
|
|
3741
|
+
x: rect.x + pad.left,
|
|
3742
|
+
y: rect.y + pad.top,
|
|
3743
|
+
w: Math.max(0, rect.w - pad.left - pad.right),
|
|
3744
|
+
h: Math.max(0, rect.h - pad.top - pad.bottom)
|
|
3745
|
+
};
|
|
3746
|
+
}
|
|
3693
3747
|
|
|
3694
3748
|
// src/vue/components/TAnchor.ts
|
|
3695
3749
|
var EMPTY_RECT = Object.freeze({ x: 0, y: 0, w: 0, h: 0 });
|
|
@@ -3703,6 +3757,7 @@ var TAnchor = (0, import_vue10.defineComponent)({
|
|
|
3703
3757
|
w: { type: Number, default: void 0 },
|
|
3704
3758
|
h: { type: Number, default: void 0 },
|
|
3705
3759
|
zIndex: { type: Number, default: 0 },
|
|
3760
|
+
padding: { type: [Number, String, Array], default: 0 },
|
|
3706
3761
|
focusable: { type: Boolean, default: false },
|
|
3707
3762
|
selectable: { type: Boolean, default: void 0 }
|
|
3708
3763
|
},
|
|
@@ -3804,9 +3859,11 @@ var TAnchor = (0, import_vue10.defineComponent)({
|
|
|
3804
3859
|
const childStack = (0, import_vue10.computed)(() => render.createStack(parentStack.value, props.zIndex));
|
|
3805
3860
|
(0, import_vue10.watchEffect)(() => {
|
|
3806
3861
|
const translated = rawRect.value;
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
childLayout.
|
|
3862
|
+
const content = insetRect(translated, props.padding);
|
|
3863
|
+
const contentClip = intersectRect(content, rect.value) ?? EMPTY_RECT;
|
|
3864
|
+
childLayout.originX = content.x;
|
|
3865
|
+
childLayout.originY = content.y;
|
|
3866
|
+
childLayout.clipRect = contentClip;
|
|
3810
3867
|
});
|
|
3811
3868
|
(0, import_vue10.provide)(LayoutContextKey, childLayout);
|
|
3812
3869
|
(0, import_vue10.provide)(RenderStackKey, childStack);
|
|
@@ -3967,7 +4024,7 @@ var TBox = (0, import_vue12.defineComponent)({
|
|
|
3967
4024
|
zIndex: { type: Number, default: 0 },
|
|
3968
4025
|
border: { type: Boolean, default: true },
|
|
3969
4026
|
title: { type: String, default: "" },
|
|
3970
|
-
padding: { type: Number, default: 0 },
|
|
4027
|
+
padding: { type: [Number, String, Array], default: 0 },
|
|
3971
4028
|
scrollX: { type: Number, default: 0 },
|
|
3972
4029
|
scrollY: { type: Number, default: 0 },
|
|
3973
4030
|
style: { type: Object, default: void 0 },
|
|
@@ -4041,17 +4098,14 @@ var TBox = (0, import_vue12.defineComponent)({
|
|
|
4041
4098
|
(0, import_vue12.watchEffect)(() => {
|
|
4042
4099
|
const r = absRect.value;
|
|
4043
4100
|
const borderInset = props.border ? 1 : 0;
|
|
4044
|
-
const
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
x: r.x + borderInset + pad,
|
|
4050
|
-
y: r.y + borderInset + pad,
|
|
4051
|
-
w: Math.max(0, r.w - borderInset * 2 - pad * 2),
|
|
4052
|
-
h: Math.max(0, r.h - borderInset * 2 - pad * 2)
|
|
4101
|
+
const inner = {
|
|
4102
|
+
x: r.x + borderInset,
|
|
4103
|
+
y: r.y + borderInset,
|
|
4104
|
+
w: Math.max(0, r.w - borderInset * 2),
|
|
4105
|
+
h: Math.max(0, r.h - borderInset * 2)
|
|
4053
4106
|
};
|
|
4054
|
-
|
|
4107
|
+
const content = insetRect(inner, props.padding);
|
|
4108
|
+
let contentRect2 = intersectRect(content, inner);
|
|
4055
4109
|
if (parent.clipRect && contentRect2)
|
|
4056
4110
|
contentRect2 = intersectRect(contentRect2, parent.clipRect);
|
|
4057
4111
|
if (!contentRect2)
|
|
@@ -4125,6 +4179,7 @@ var TText = (0, import_vue13.defineComponent)({
|
|
|
4125
4179
|
value: { type: String, required: true },
|
|
4126
4180
|
w: { type: Number, default: void 0 },
|
|
4127
4181
|
h: { type: Number, default: void 0 },
|
|
4182
|
+
padding: { type: [Number, String, Array], default: 0 },
|
|
4128
4183
|
style: { type: Object, default: void 0 },
|
|
4129
4184
|
clear: { type: Boolean, default: true },
|
|
4130
4185
|
wrap: { type: Boolean, default: false }
|
|
@@ -4133,8 +4188,13 @@ var TText = (0, import_vue13.defineComponent)({
|
|
|
4133
4188
|
const { terminal, defaultStyle } = useTerminal();
|
|
4134
4189
|
const layout = useLayout();
|
|
4135
4190
|
const { visible, rootProps } = useVisibility();
|
|
4191
|
+
const pad = (0, import_vue13.computed)(() => normalizePadding(props.padding));
|
|
4192
|
+
const contentW = (0, import_vue13.computed)(() => {
|
|
4193
|
+
const outerW = props.w ?? computeDefaultWidth(props.value) + pad.value.left + pad.value.right;
|
|
4194
|
+
return Math.max(0, Math.floor(outerW) - pad.value.left - pad.value.right);
|
|
4195
|
+
});
|
|
4136
4196
|
const lines = (0, import_vue13.computed)(() => {
|
|
4137
|
-
const w =
|
|
4197
|
+
const w = contentW.value;
|
|
4138
4198
|
if (w <= 0)
|
|
4139
4199
|
return [""];
|
|
4140
4200
|
if (!props.wrap)
|
|
@@ -4143,8 +4203,8 @@ var TText = (0, import_vue13.defineComponent)({
|
|
|
4143
4203
|
return wrapByCells(safe, w).map((l) => fitText(l, w));
|
|
4144
4204
|
});
|
|
4145
4205
|
const absRect = (0, import_vue13.computed)(() => {
|
|
4146
|
-
const width = props.w ?? computeDefaultWidth(props.value);
|
|
4147
|
-
const height = props.h ?? (
|
|
4206
|
+
const width = Math.floor(props.w ?? computeDefaultWidth(props.value) + pad.value.left + pad.value.right);
|
|
4207
|
+
const height = Math.floor(props.h ?? (lines.value.length || 1) + pad.value.top + pad.value.bottom);
|
|
4148
4208
|
const raw = { x: props.x, y: props.y, w: width, h: height };
|
|
4149
4209
|
const translated = translateRect(raw, layout.originX, layout.originY);
|
|
4150
4210
|
if (!layout.clipRect)
|
|
@@ -4161,20 +4221,27 @@ var TText = (0, import_vue13.defineComponent)({
|
|
|
4161
4221
|
const r = absRect.value;
|
|
4162
4222
|
if (r.w <= 0 || r.h <= 0)
|
|
4163
4223
|
return;
|
|
4224
|
+
const contentX = r.x + pad.value.left;
|
|
4225
|
+
const contentY = r.y + pad.value.top;
|
|
4226
|
+
const w = Math.max(0, Math.floor(r.w) - pad.value.left - pad.value.right);
|
|
4227
|
+
const h16 = Math.max(0, Math.floor(r.h) - pad.value.top - pad.value.bottom);
|
|
4164
4228
|
const style = props.style ?? defaultStyle.value;
|
|
4165
4229
|
const blank = props.clear ? " ".repeat(r.w) : "";
|
|
4166
4230
|
const out = lines.value;
|
|
4167
|
-
const maxLines = Math.min(out.length,
|
|
4231
|
+
const maxLines = Math.min(out.length, h16);
|
|
4168
4232
|
const paintRow = (y) => {
|
|
4169
4233
|
const i = y - r.y;
|
|
4170
4234
|
if (i < 0 || i >= r.h)
|
|
4171
4235
|
return;
|
|
4172
4236
|
if (props.clear)
|
|
4173
4237
|
terminal.write(blank, { x: r.x, y, style });
|
|
4174
|
-
|
|
4238
|
+
const contentRow = y - contentY;
|
|
4239
|
+
if (contentRow < 0 || contentRow >= h16)
|
|
4240
|
+
return;
|
|
4241
|
+
if (contentRow < 0 || contentRow >= maxLines)
|
|
4175
4242
|
return;
|
|
4176
|
-
const clipped = sliceByCells(out[
|
|
4177
|
-
terminal.write(padEndByCells(clipped,
|
|
4243
|
+
const clipped = sliceByCells(out[contentRow] ?? "", w);
|
|
4244
|
+
terminal.write(padEndByCells(clipped, w), { x: contentX, y, style });
|
|
4178
4245
|
};
|
|
4179
4246
|
if (!dirtyRows) {
|
|
4180
4247
|
for (let i = 0; i < r.h; i++)
|
|
@@ -4200,6 +4267,7 @@ var TView = (0, import_vue14.defineComponent)({
|
|
|
4200
4267
|
w: { type: Number, required: true },
|
|
4201
4268
|
h: { type: Number, required: true },
|
|
4202
4269
|
zIndex: { type: Number, default: 0 },
|
|
4270
|
+
padding: { type: [Number, String, Array], default: 0 },
|
|
4203
4271
|
scrollX: { type: Number, default: 0 },
|
|
4204
4272
|
scrollY: { type: Number, default: 0 },
|
|
4205
4273
|
focusable: { type: Boolean, default: false },
|
|
@@ -4292,9 +4360,11 @@ var TView = (0, import_vue14.defineComponent)({
|
|
|
4292
4360
|
const childStack = (0, import_vue14.computed)(() => render.createStack(parentStack.value, props.zIndex));
|
|
4293
4361
|
(0, import_vue14.watchEffect)(() => {
|
|
4294
4362
|
const translated = rawRect.value;
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
childLayout.
|
|
4363
|
+
const content = insetRect(translated, props.padding);
|
|
4364
|
+
const contentClip = intersectRect(content, rect.value) ?? EMPTY_RECT2;
|
|
4365
|
+
childLayout.originX = content.x - Math.floor(props.scrollX);
|
|
4366
|
+
childLayout.originY = content.y - Math.floor(props.scrollY);
|
|
4367
|
+
childLayout.clipRect = contentClip;
|
|
4298
4368
|
});
|
|
4299
4369
|
(0, import_vue14.provide)(LayoutContextKey, childLayout);
|
|
4300
4370
|
(0, import_vue14.provide)(RenderStackKey, childStack);
|
|
@@ -4451,10 +4521,10 @@ function computePosition(opts) {
|
|
|
4451
4521
|
}
|
|
4452
4522
|
function contentRect(opts) {
|
|
4453
4523
|
const borderInset = opts.border ? 1 : 0;
|
|
4454
|
-
const pad =
|
|
4524
|
+
const pad = normalizePadding(opts.padding);
|
|
4455
4525
|
return {
|
|
4456
|
-
w: Math.max(0, Math.floor(opts.w) - borderInset * 2 - pad
|
|
4457
|
-
h: Math.max(0, Math.floor(opts.h) - borderInset * 2 - pad
|
|
4526
|
+
w: Math.max(0, Math.floor(opts.w) - borderInset * 2 - pad.left - pad.right),
|
|
4527
|
+
h: Math.max(0, Math.floor(opts.h) - borderInset * 2 - pad.top - pad.bottom)
|
|
4458
4528
|
};
|
|
4459
4529
|
}
|
|
4460
4530
|
var DialogSurface = (0, import_vue16.defineComponent)({
|
|
@@ -4464,7 +4534,7 @@ var DialogSurface = (0, import_vue16.defineComponent)({
|
|
|
4464
4534
|
w: { type: Number, required: true },
|
|
4465
4535
|
h: { type: Number, required: true },
|
|
4466
4536
|
title: { type: String, default: "" },
|
|
4467
|
-
padding: { type: Number, default: 1 },
|
|
4537
|
+
padding: { type: [Number, String, Array], default: 1 },
|
|
4468
4538
|
zIndex: { type: Number, default: 1e3 },
|
|
4469
4539
|
style: { type: Object, default: void 0 },
|
|
4470
4540
|
placement: { type: String, default: "center" },
|
|
@@ -4697,7 +4767,7 @@ var TDialog = (0, import_vue16.defineComponent)({
|
|
|
4697
4767
|
w: { type: Number, required: true },
|
|
4698
4768
|
h: { type: Number, required: true },
|
|
4699
4769
|
title: { type: String, default: "" },
|
|
4700
|
-
padding: { type: Number, default: 1 },
|
|
4770
|
+
padding: { type: [Number, String, Array], default: 1 },
|
|
4701
4771
|
zIndex: { type: Number, default: 1e3 },
|
|
4702
4772
|
style: { type: Object, default: void 0 },
|
|
4703
4773
|
placement: { type: String, default: "center" },
|
|
@@ -5683,6 +5753,7 @@ var TFlow = (0, import_vue18.defineComponent)({
|
|
|
5683
5753
|
y: { type: Number, required: true },
|
|
5684
5754
|
w: { type: Number, required: true },
|
|
5685
5755
|
h: { type: Number, required: true },
|
|
5756
|
+
padding: { type: [Number, String, Array], default: 0 },
|
|
5686
5757
|
items: { type: Array, required: true },
|
|
5687
5758
|
direction: { type: String, default: "vertical" },
|
|
5688
5759
|
gap: { type: Number, default: 0 },
|
|
@@ -5690,13 +5761,16 @@ var TFlow = (0, import_vue18.defineComponent)({
|
|
|
5690
5761
|
zIndex: { type: Number, default: 0 }
|
|
5691
5762
|
},
|
|
5692
5763
|
setup(props, { slots }) {
|
|
5764
|
+
const pad = (0, import_vue18.computed)(() => normalizePadding(props.padding));
|
|
5765
|
+
const innerW = (0, import_vue18.computed)(() => Math.max(0, Math.floor(props.w) - pad.value.left - pad.value.right));
|
|
5766
|
+
const innerH = (0, import_vue18.computed)(() => Math.max(0, Math.floor(props.h) - pad.value.top - pad.value.bottom));
|
|
5693
5767
|
return () => (0, import_vue18.h)(
|
|
5694
5768
|
TView,
|
|
5695
|
-
{ x: props.x, y: props.y, w: props.w, h: props.h, zIndex: props.zIndex },
|
|
5769
|
+
{ x: props.x, y: props.y, w: props.w, h: props.h, zIndex: props.zIndex, padding: props.padding },
|
|
5696
5770
|
() => props.items.map((item, index) => {
|
|
5697
5771
|
const step = Math.max(0, Math.floor(props.itemSize)) + Math.max(0, Math.floor(props.gap));
|
|
5698
5772
|
const offset = index * step;
|
|
5699
|
-
const childProps = props.direction === "vertical" ? { x: 0, y: offset, w:
|
|
5773
|
+
const childProps = props.direction === "vertical" ? { x: 0, y: offset, w: innerW.value, h: Math.max(0, Math.floor(props.itemSize)) } : { x: offset, y: 0, w: Math.max(0, Math.floor(props.itemSize)), h: innerH.value };
|
|
5700
5774
|
return (0, import_vue18.h)(
|
|
5701
5775
|
TView,
|
|
5702
5776
|
{ key: index, ...childProps },
|
|
@@ -6057,6 +6131,7 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6057
6131
|
w: { type: Number, required: true },
|
|
6058
6132
|
h: { type: Number, default: 1 },
|
|
6059
6133
|
zIndex: { type: Number, default: 0 },
|
|
6134
|
+
padding: { type: [Number, String, Array], default: "0 1" },
|
|
6060
6135
|
modelValue: { type: String, required: true },
|
|
6061
6136
|
cursorToEndOnExternalUpdate: { type: Boolean, default: false },
|
|
6062
6137
|
placeholder: { type: String, default: "" },
|
|
@@ -6090,14 +6165,6 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6090
6165
|
const parentEventZ = (0, import_vue19.inject)(EventZIndexContextKey, (0, import_vue19.computed)(() => 0));
|
|
6091
6166
|
const eventZ = (0, import_vue19.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0));
|
|
6092
6167
|
const promptOverlayStack = render.createStack(render.rootStack, 1e4);
|
|
6093
|
-
const PADDING_X = 1;
|
|
6094
|
-
function measureContent(r) {
|
|
6095
|
-
const wAll = Math.max(0, Math.floor(r.w));
|
|
6096
|
-
const hAll = Math.max(0, Math.floor(r.h));
|
|
6097
|
-
const padX = clamp3(PADDING_X, 0, Math.floor(wAll / 2));
|
|
6098
|
-
const w = Math.max(0, wAll - padX * 2);
|
|
6099
|
-
return { wAll, hAll, padX, w };
|
|
6100
|
-
}
|
|
6101
6168
|
const focused = (0, import_vue19.ref)(false);
|
|
6102
6169
|
const cursor = (0, import_vue19.ref)(0);
|
|
6103
6170
|
const anchor = (0, import_vue19.ref)(null);
|
|
@@ -6114,7 +6181,6 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6114
6181
|
function getValue() {
|
|
6115
6182
|
return pendingValue.value ?? props.modelValue;
|
|
6116
6183
|
}
|
|
6117
|
-
const wrapMode = (0, import_vue19.computed)(() => Math.max(1, Math.floor(props.h)) > 1);
|
|
6118
6184
|
const rawAbsRect = (0, import_vue19.computed)(() => {
|
|
6119
6185
|
const raw = { x: props.x, y: props.y, w: props.w, h: Math.max(1, Math.floor(props.h)) };
|
|
6120
6186
|
return translateRect(raw, layout.originX, layout.originY);
|
|
@@ -6358,6 +6424,8 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6358
6424
|
return translated;
|
|
6359
6425
|
return intersectRect(translated, layout.clipRect) ?? { x: 0, y: 0, w: 0, h: 0 };
|
|
6360
6426
|
});
|
|
6427
|
+
const contentRect2 = (0, import_vue19.computed)(() => insetRect(absRect.value, props.padding));
|
|
6428
|
+
const wrapMode = (0, import_vue19.computed)(() => Math.max(1, Math.floor(contentRect2.value.h)) > 1);
|
|
6361
6429
|
const selection = (0, import_vue19.computed)(() => {
|
|
6362
6430
|
if (anchor.value == null || anchor.value === cursor.value)
|
|
6363
6431
|
return null;
|
|
@@ -6440,10 +6508,16 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6440
6508
|
return !focused.value || props.placeholderWhenFocused;
|
|
6441
6509
|
});
|
|
6442
6510
|
function ensureCursorVisible() {
|
|
6443
|
-
const r =
|
|
6444
|
-
const
|
|
6445
|
-
const
|
|
6446
|
-
|
|
6511
|
+
const r = contentRect2.value;
|
|
6512
|
+
const w = Math.max(0, Math.floor(r.w));
|
|
6513
|
+
const h16 = Math.max(0, Math.floor(r.h));
|
|
6514
|
+
if (w <= 0 || h16 <= 0) {
|
|
6515
|
+
scrollX.value = 0;
|
|
6516
|
+
scrollY.value = 0;
|
|
6517
|
+
return;
|
|
6518
|
+
}
|
|
6519
|
+
const width = w;
|
|
6520
|
+
const height = h16;
|
|
6447
6521
|
const value = getValue();
|
|
6448
6522
|
const wrap = wrapMode.value;
|
|
6449
6523
|
const prefix = buildMentionPrefix(props.mentions, width);
|
|
@@ -6469,13 +6543,16 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6469
6543
|
}
|
|
6470
6544
|
function setCursorByCell2D(cellX, cellY, extendSelection = false, e) {
|
|
6471
6545
|
var _a;
|
|
6472
|
-
const r =
|
|
6473
|
-
const
|
|
6474
|
-
const
|
|
6546
|
+
const r = contentRect2.value;
|
|
6547
|
+
const w = Math.max(0, Math.floor(r.w));
|
|
6548
|
+
const h16 = Math.max(0, Math.floor(r.h));
|
|
6549
|
+
if (w <= 0 || h16 <= 0)
|
|
6550
|
+
return;
|
|
6551
|
+
const width = w;
|
|
6475
6552
|
const prefix = buildMentionPrefix(props.mentions, width);
|
|
6476
6553
|
const prefixCells = prefix.cells;
|
|
6477
|
-
const localX = clamp3(cellX -
|
|
6478
|
-
const localY = clamp3(cellY - r.y, 0, Math.max(0,
|
|
6554
|
+
const localX = clamp3(cellX - r.x, 0, Math.max(0, w - 1));
|
|
6555
|
+
const localY = clamp3(cellY - r.y, 0, Math.max(0, h16 - 1));
|
|
6479
6556
|
const prefixVisible = scrollY.value === 0 && localY === 0 && prefixCells > 0;
|
|
6480
6557
|
if (prefixVisible && localX < prefixCells) {
|
|
6481
6558
|
for (const chip of prefix.chips) {
|
|
@@ -6525,8 +6602,7 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6525
6602
|
compositionText.value = "";
|
|
6526
6603
|
pendingValue.value = nextValue;
|
|
6527
6604
|
if (wrapMode.value) {
|
|
6528
|
-
const
|
|
6529
|
-
const w = Math.max(1, contentW);
|
|
6605
|
+
const w = Math.max(1, Math.floor(contentRect2.value.w));
|
|
6530
6606
|
const prefix = buildMentionPrefix(props.mentions, w);
|
|
6531
6607
|
const firstW = Math.max(1, w - prefix.cells);
|
|
6532
6608
|
desiredCol.value = indexToWrappedCellColFirstWidth(nextValue, c, firstW, w).col;
|
|
@@ -6551,8 +6627,7 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6551
6627
|
}
|
|
6552
6628
|
cursor.value = clamp3(nextCursor, 0, value.length);
|
|
6553
6629
|
if (wrapMode.value) {
|
|
6554
|
-
const
|
|
6555
|
-
const w = Math.max(1, contentW);
|
|
6630
|
+
const w = Math.max(1, Math.floor(contentRect2.value.w));
|
|
6556
6631
|
const prefix = buildMentionPrefix(props.mentions, w);
|
|
6557
6632
|
const firstW = Math.max(1, w - prefix.cells);
|
|
6558
6633
|
desiredCol.value = indexToWrappedCellColFirstWidth(value, cursor.value, firstW, w).col;
|
|
@@ -6562,7 +6637,7 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6562
6637
|
ensureCursorVisible();
|
|
6563
6638
|
scheduler.invalidate();
|
|
6564
6639
|
}
|
|
6565
|
-
(0, import_vue19.watch)([() =>
|
|
6640
|
+
(0, import_vue19.watch)([() => contentRect2.value.w, () => contentRect2.value.h, () => wrapMode.value], () => {
|
|
6566
6641
|
ensureCursorVisible();
|
|
6567
6642
|
scheduler.invalidate();
|
|
6568
6643
|
});
|
|
@@ -6609,14 +6684,15 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6609
6684
|
imeAnchor.value = null;
|
|
6610
6685
|
return;
|
|
6611
6686
|
}
|
|
6612
|
-
const r =
|
|
6613
|
-
|
|
6687
|
+
const r = contentRect2.value;
|
|
6688
|
+
const w = Math.max(0, Math.floor(r.w));
|
|
6689
|
+
const h16 = Math.max(0, Math.floor(r.h));
|
|
6690
|
+
if (w <= 0 || h16 <= 0) {
|
|
6614
6691
|
imeAnchor.value = null;
|
|
6615
6692
|
return;
|
|
6616
6693
|
}
|
|
6617
|
-
const
|
|
6618
|
-
const
|
|
6619
|
-
const height = Math.max(1, hAll);
|
|
6694
|
+
const width = w;
|
|
6695
|
+
const height = h16;
|
|
6620
6696
|
const placeholderVisible = shouldShowPlaceholder.value;
|
|
6621
6697
|
const offX = placeholderVisible ? 0 : scrollX.value;
|
|
6622
6698
|
const offY = placeholderVisible ? 0 : scrollY.value;
|
|
@@ -6632,7 +6708,7 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6632
6708
|
const cyRaw = pos.line - offY;
|
|
6633
6709
|
const cx = clamp3(cxRaw, 0, Math.max(0, width - 1));
|
|
6634
6710
|
const cy = clamp3(cyRaw, 0, Math.max(0, height - 1));
|
|
6635
|
-
imeAnchor.value = { cellX: r.x +
|
|
6711
|
+
imeAnchor.value = { cellX: r.x + cx, cellY: r.y + cy };
|
|
6636
6712
|
});
|
|
6637
6713
|
function acceptPrompt(index) {
|
|
6638
6714
|
const ctx = activeContext.value;
|
|
@@ -6770,6 +6846,30 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6770
6846
|
return;
|
|
6771
6847
|
}
|
|
6772
6848
|
}
|
|
6849
|
+
const base64EncodeBytes = (bytes) => {
|
|
6850
|
+
const table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
6851
|
+
let out = "";
|
|
6852
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
6853
|
+
const a = bytes[i] ?? 0;
|
|
6854
|
+
const b = bytes[i + 1] ?? 0;
|
|
6855
|
+
const c = bytes[i + 2] ?? 0;
|
|
6856
|
+
const triple = a << 16 | b << 8 | c;
|
|
6857
|
+
out += table[triple >> 18 & 63] ?? "";
|
|
6858
|
+
out += table[triple >> 12 & 63] ?? "";
|
|
6859
|
+
out += i + 1 < bytes.length ? table[triple >> 6 & 63] ?? "" : "=";
|
|
6860
|
+
out += i + 2 < bytes.length ? table[triple & 63] ?? "" : "=";
|
|
6861
|
+
}
|
|
6862
|
+
return out;
|
|
6863
|
+
};
|
|
6864
|
+
const base64EncodeText = (text) => {
|
|
6865
|
+
if (typeof TextEncoder !== "undefined")
|
|
6866
|
+
return base64EncodeBytes(new TextEncoder().encode(text));
|
|
6867
|
+
const bin = unescape(encodeURIComponent(text));
|
|
6868
|
+
const bytes = new Uint8Array(bin.length);
|
|
6869
|
+
for (let i = 0; i < bin.length; i++)
|
|
6870
|
+
bytes[i] = bin.charCodeAt(i);
|
|
6871
|
+
return base64EncodeBytes(bytes);
|
|
6872
|
+
};
|
|
6773
6873
|
const copyText = async (text) => {
|
|
6774
6874
|
var _a, _b, _c, _d, _e, _f;
|
|
6775
6875
|
if (!text)
|
|
@@ -6785,7 +6885,7 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6785
6885
|
const proc = globalThis.process;
|
|
6786
6886
|
if (((_b = proc == null ? void 0 : proc.stdout) == null ? void 0 : _b.write) && ((_c = proc == null ? void 0 : proc.stdout) == null ? void 0 : _c.isTTY)) {
|
|
6787
6887
|
try {
|
|
6788
|
-
const base64 =
|
|
6888
|
+
const base64 = base64EncodeText(text);
|
|
6789
6889
|
proc.stdout.write(`\x1B]52;c;${base64}\x07`);
|
|
6790
6890
|
return true;
|
|
6791
6891
|
} catch {
|
|
@@ -6853,8 +6953,7 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6853
6953
|
if (e.key === "ArrowUp" || e.key === "ArrowDown") {
|
|
6854
6954
|
e.preventDefault();
|
|
6855
6955
|
const wrap = wrapMode.value;
|
|
6856
|
-
const
|
|
6857
|
-
const width = Math.max(1, contentW);
|
|
6956
|
+
const width = Math.max(1, Math.floor(contentRect2.value.w));
|
|
6858
6957
|
const prefix = buildMentionPrefix(props.mentions, width);
|
|
6859
6958
|
const firstW = Math.max(1, width - prefix.cells);
|
|
6860
6959
|
const { line, col, lines } = wrap ? indexToWrappedCellColFirstWidth(value, cursor.value, firstW, width) : indexToLineCellCol(value, cursor.value);
|
|
@@ -7089,6 +7188,7 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
7089
7188
|
props.mentions,
|
|
7090
7189
|
props.placeholder,
|
|
7091
7190
|
props.placeholderWhenFocused,
|
|
7191
|
+
props.padding,
|
|
7092
7192
|
props.style,
|
|
7093
7193
|
props.autoFocus,
|
|
7094
7194
|
props.cursorBlink,
|
|
@@ -7108,8 +7208,10 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
7108
7208
|
paint: () => {
|
|
7109
7209
|
if (!visible.value)
|
|
7110
7210
|
return;
|
|
7111
|
-
const
|
|
7112
|
-
|
|
7211
|
+
const rAll = absRect.value;
|
|
7212
|
+
const wAll = Math.max(0, Math.floor(rAll.w));
|
|
7213
|
+
const hAll = Math.max(0, Math.floor(rAll.h));
|
|
7214
|
+
if (wAll <= 0 || hAll <= 0)
|
|
7113
7215
|
return;
|
|
7114
7216
|
const style = props.style ?? defaultStyle.value;
|
|
7115
7217
|
const placeholderVisible = shouldShowPlaceholder.value;
|
|
@@ -7125,14 +7227,21 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
7125
7227
|
}
|
|
7126
7228
|
const text = props.secret && !placeholderVisible ? maskText(textRaw) : textRaw;
|
|
7127
7229
|
const baseStyle = placeholderVisible ? { ...style, fg: "white" } : style;
|
|
7128
|
-
const
|
|
7129
|
-
|
|
7130
|
-
|
|
7230
|
+
const blankAll = " ".repeat(wAll);
|
|
7231
|
+
for (let row = 0; row < hAll; row++)
|
|
7232
|
+
terminal.write(blankAll, { x: rAll.x, y: rAll.y + row, style: baseStyle });
|
|
7233
|
+
const r = contentRect2.value;
|
|
7234
|
+
const w = Math.max(0, Math.floor(r.w));
|
|
7235
|
+
const h16 = Math.max(0, Math.floor(r.h));
|
|
7236
|
+
if (w <= 0 || h16 <= 0)
|
|
7237
|
+
return;
|
|
7238
|
+
const x0 = r.x;
|
|
7239
|
+
const width = Math.max(1, w);
|
|
7131
7240
|
const prefix = buildMentionPrefix(props.mentions, width);
|
|
7132
7241
|
const prefixCells = prefix.cells;
|
|
7133
7242
|
const firstWidth = Math.max(1, Math.max(1, width) - prefixCells);
|
|
7134
7243
|
const lines = wrap ? wrapToLinesFirstWidth(text, firstWidth, width) : computeLines(text);
|
|
7135
|
-
for (let row = 0; row <
|
|
7244
|
+
for (let row = 0; row < h16; row++) {
|
|
7136
7245
|
const lineIndex = offY + row;
|
|
7137
7246
|
const info = lines[lineIndex];
|
|
7138
7247
|
const raw = info ? text.slice(info.start, info.end).replace(/[\r\n]/g, "") : "";
|
|
@@ -7141,26 +7250,24 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
7141
7250
|
const rowTextW = hasPrefix ? firstWidth : width;
|
|
7142
7251
|
const rawVisible = wrap ? sliceByCellsWindow(raw, 0, rowTextW) : sliceByCellsWindow(raw, offX, rowTextW);
|
|
7143
7252
|
const visible2 = padEndByCells2(rawVisible, rowTextW);
|
|
7144
|
-
|
|
7145
|
-
if (contentW <= 0)
|
|
7146
|
-
continue;
|
|
7253
|
+
const y = r.y + row;
|
|
7147
7254
|
if (hasPrefix) {
|
|
7148
7255
|
const chipStyle = { ...style, fg: "cyanBright", underline: true };
|
|
7149
7256
|
for (const chip of prefix.chips) {
|
|
7150
7257
|
if (!chip.label)
|
|
7151
7258
|
continue;
|
|
7152
|
-
terminal.write(chip.label, { x: x0 + chip.start, y
|
|
7259
|
+
terminal.write(chip.label, { x: x0 + chip.start, y, style: chipStyle });
|
|
7153
7260
|
}
|
|
7154
|
-
terminal.write(visible2, { x: x0 + rowPrefixCells, y
|
|
7261
|
+
terminal.write(visible2, { x: x0 + rowPrefixCells, y, style: baseStyle });
|
|
7155
7262
|
} else {
|
|
7156
|
-
terminal.write(visible2, { x: x0, y
|
|
7263
|
+
terminal.write(visible2, { x: x0, y, style: baseStyle });
|
|
7157
7264
|
}
|
|
7158
7265
|
}
|
|
7159
7266
|
const sel = selection.value;
|
|
7160
7267
|
if (sel && !placeholderVisible) {
|
|
7161
7268
|
const bg = "blueBright";
|
|
7162
7269
|
const fg = "black";
|
|
7163
|
-
for (let row = 0; row <
|
|
7270
|
+
for (let row = 0; row < h16; row++) {
|
|
7164
7271
|
const lineIndex = offY + row;
|
|
7165
7272
|
const info = lines[lineIndex];
|
|
7166
7273
|
if (!info)
|
|
@@ -7175,12 +7282,12 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
7175
7282
|
for (let i = info.start; i < info.end; ) {
|
|
7176
7283
|
const ch = readCodePointAt(text, i);
|
|
7177
7284
|
const nextI = i + ch.length;
|
|
7178
|
-
const
|
|
7179
|
-
if (xCell2 +
|
|
7285
|
+
const w2 = charCellWidth(ch);
|
|
7286
|
+
if (xCell2 + w2 > rowTextW)
|
|
7180
7287
|
break;
|
|
7181
7288
|
if (i >= sel.start && i < sel.end)
|
|
7182
7289
|
terminal.put(xBase + xCell2, y, ch, { ...style, fg, bg });
|
|
7183
|
-
xCell2 +=
|
|
7290
|
+
xCell2 += w2;
|
|
7184
7291
|
i = nextI;
|
|
7185
7292
|
if (xCell2 >= rowTextW)
|
|
7186
7293
|
break;
|
|
@@ -7192,8 +7299,8 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
7192
7299
|
for (let i = info.start; i < info.end; ) {
|
|
7193
7300
|
const ch = readCodePointAt(text, i);
|
|
7194
7301
|
const nextI = i + ch.length;
|
|
7195
|
-
const
|
|
7196
|
-
const nextCell = xCell +
|
|
7302
|
+
const w2 = charCellWidth(ch);
|
|
7303
|
+
const nextCell = xCell + w2;
|
|
7197
7304
|
if (nextCell <= offX) {
|
|
7198
7305
|
xCell = nextCell;
|
|
7199
7306
|
i = nextI;
|
|
@@ -7202,7 +7309,7 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
7202
7309
|
if (xCell >= offX + rowTextW)
|
|
7203
7310
|
break;
|
|
7204
7311
|
const localX = xCell - offX;
|
|
7205
|
-
if (localX +
|
|
7312
|
+
if (localX + w2 > rowTextW)
|
|
7206
7313
|
break;
|
|
7207
7314
|
if (i >= sel.start && i < sel.end)
|
|
7208
7315
|
terminal.put(xBase + localX, y, ch, { ...style, fg, bg });
|
|
@@ -7223,7 +7330,7 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
7223
7330
|
const pos = wrap ? indexToWrappedCellColFirstWidth(cursorText, cursor.value, firstW, wAll2) : indexToLineCellCol(cursorText, cursor.value);
|
|
7224
7331
|
const cx0 = (pos.line === 0 ? prefixCells : 0) + (pos.col - offX);
|
|
7225
7332
|
const cy = pos.line - offY;
|
|
7226
|
-
if (cx0 >= 0 && cx0 < width && cy >= 0 && cy <
|
|
7333
|
+
if (cx0 >= 0 && cx0 < width && cy >= 0 && cy < h16) {
|
|
7227
7334
|
const x = x0 + cx0;
|
|
7228
7335
|
const y = r.y + cy;
|
|
7229
7336
|
const avail = Math.max(0, width - cx0);
|
|
@@ -7243,7 +7350,7 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
7243
7350
|
const pos = wrap ? indexToWrappedCellColFirstWidth(cursorText, cursor.value, firstW, wAll2) : indexToLineCellCol(cursorText, cursor.value);
|
|
7244
7351
|
const cx0 = (pos.line === 0 ? prefixCells : 0) + (pos.col - offX);
|
|
7245
7352
|
const cy = pos.line - offY;
|
|
7246
|
-
if (cx0 >= 0 && cx0 < width && cy >= 0 && cy <
|
|
7353
|
+
if (cx0 >= 0 && cx0 < width && cy >= 0 && cy < h16) {
|
|
7247
7354
|
const y = r.y + cy;
|
|
7248
7355
|
let x = x0 + cx0;
|
|
7249
7356
|
let cell = null;
|
|
@@ -7377,7 +7484,7 @@ var TInputBox = (0, import_vue20.defineComponent)({
|
|
|
7377
7484
|
h: { type: Number, required: true },
|
|
7378
7485
|
zIndex: { type: Number, default: 0 },
|
|
7379
7486
|
title: { type: String, default: "" },
|
|
7380
|
-
padding: { type: Number, default: 0 },
|
|
7487
|
+
padding: { type: [Number, String, Array], default: 0 },
|
|
7381
7488
|
modelValue: { type: String, required: true },
|
|
7382
7489
|
placeholder: { type: String, default: "" },
|
|
7383
7490
|
style: { type: Object, default: void 0 },
|
|
@@ -7388,8 +7495,9 @@ var TInputBox = (0, import_vue20.defineComponent)({
|
|
|
7388
7495
|
},
|
|
7389
7496
|
emits: ["update:modelValue", "input", "change", "keydown", "focus", "blur"],
|
|
7390
7497
|
setup(props, { emit }) {
|
|
7391
|
-
const
|
|
7392
|
-
const
|
|
7498
|
+
const pad = (0, import_vue20.computed)(() => normalizePadding(props.padding));
|
|
7499
|
+
const innerW = (0, import_vue20.computed)(() => Math.max(0, Math.floor(props.w) - 2 - pad.value.left - pad.value.right));
|
|
7500
|
+
const innerH = (0, import_vue20.computed)(() => Math.max(1, Math.floor(props.h) - 2 - pad.value.top - pad.value.bottom));
|
|
7393
7501
|
return () => (0, import_vue20.h)(
|
|
7394
7502
|
TBox,
|
|
7395
7503
|
{
|
|
@@ -7439,6 +7547,7 @@ var TList = (0, import_vue21.defineComponent)({
|
|
|
7439
7547
|
w: { type: Number, required: true },
|
|
7440
7548
|
h: { type: Number, required: true },
|
|
7441
7549
|
zIndex: { type: Number, default: 0 },
|
|
7550
|
+
padding: { type: [Number, String, Array], default: 0 },
|
|
7442
7551
|
items: { type: Array, required: true },
|
|
7443
7552
|
modelValue: { type: Number, default: 0 },
|
|
7444
7553
|
style: { type: Object, default: void 0 },
|
|
@@ -7465,8 +7574,9 @@ var TList = (0, import_vue21.defineComponent)({
|
|
|
7465
7574
|
(0, import_vue21.watchEffect)(() => {
|
|
7466
7575
|
active.value = clamp4(props.modelValue, 0, Math.max(0, props.items.length - 1));
|
|
7467
7576
|
});
|
|
7577
|
+
const contentRect2 = (0, import_vue21.computed)(() => insetRect(absRect.value, props.padding));
|
|
7468
7578
|
function ensureActiveVisible() {
|
|
7469
|
-
const h16 = Math.max(0,
|
|
7579
|
+
const h16 = Math.max(0, Math.floor(contentRect2.value.h));
|
|
7470
7580
|
if (h16 <= 0)
|
|
7471
7581
|
return;
|
|
7472
7582
|
const maxTop = Math.max(0, props.items.length - h16);
|
|
@@ -7476,7 +7586,7 @@ var TList = (0, import_vue21.defineComponent)({
|
|
|
7476
7586
|
else if (active.value >= scrollTop.value + h16)
|
|
7477
7587
|
scrollTop.value = clamp4(active.value - (h16 - 1), 0, maxTop);
|
|
7478
7588
|
}
|
|
7479
|
-
(0, import_vue21.watch)([() => active.value, () => props.items.length, () =>
|
|
7589
|
+
(0, import_vue21.watch)([() => active.value, () => props.items.length, () => contentRect2.value.h], () => {
|
|
7480
7590
|
ensureActiveVisible();
|
|
7481
7591
|
}, { immediate: true });
|
|
7482
7592
|
function commit(index) {
|
|
@@ -7557,7 +7667,9 @@ var TList = (0, import_vue21.defineComponent)({
|
|
|
7557
7667
|
focusable: true,
|
|
7558
7668
|
handlers: {
|
|
7559
7669
|
click: (e) => {
|
|
7560
|
-
const r =
|
|
7670
|
+
const r = contentRect2.value;
|
|
7671
|
+
if (e.cellY < r.y || e.cellY >= r.y + r.h)
|
|
7672
|
+
return;
|
|
7561
7673
|
const idx = scrollTop.value + (e.cellY - r.y);
|
|
7562
7674
|
if (idx >= 0 && idx < props.items.length) {
|
|
7563
7675
|
active.value = idx;
|
|
@@ -7568,7 +7680,9 @@ var TList = (0, import_vue21.defineComponent)({
|
|
|
7568
7680
|
}
|
|
7569
7681
|
},
|
|
7570
7682
|
dblclick: (e) => {
|
|
7571
|
-
const r =
|
|
7683
|
+
const r = contentRect2.value;
|
|
7684
|
+
if (e.cellY < r.y || e.cellY >= r.y + r.h)
|
|
7685
|
+
return;
|
|
7572
7686
|
const idx = scrollTop.value + (e.cellY - r.y);
|
|
7573
7687
|
if (idx >= 0 && idx < props.items.length)
|
|
7574
7688
|
commit(idx);
|
|
@@ -7578,7 +7692,8 @@ var TList = (0, import_vue21.defineComponent)({
|
|
|
7578
7692
|
if (!delta)
|
|
7579
7693
|
return;
|
|
7580
7694
|
const dir = delta > 0 ? 1 : -1;
|
|
7581
|
-
const
|
|
7695
|
+
const h16 = Math.max(0, Math.floor(contentRect2.value.h));
|
|
7696
|
+
const maxTop = Math.max(0, props.items.length - h16);
|
|
7582
7697
|
const next = clamp4(scrollTop.value + dir, 0, maxTop);
|
|
7583
7698
|
if (next !== scrollTop.value) {
|
|
7584
7699
|
scrollTop.value = next;
|
|
@@ -7633,10 +7748,16 @@ var TList = (0, import_vue21.defineComponent)({
|
|
|
7633
7748
|
paint: () => {
|
|
7634
7749
|
if (!visible.value)
|
|
7635
7750
|
return;
|
|
7636
|
-
const
|
|
7637
|
-
if (
|
|
7751
|
+
const rAll = absRect.value;
|
|
7752
|
+
if (rAll.w <= 0 || rAll.h <= 0)
|
|
7638
7753
|
return;
|
|
7639
7754
|
const base = props.style ?? defaultStyle.value;
|
|
7755
|
+
const r = contentRect2.value;
|
|
7756
|
+
const blankAll = " ".repeat(rAll.w);
|
|
7757
|
+
for (let i = 0; i < rAll.h; i++)
|
|
7758
|
+
terminal.write(blankAll, { x: rAll.x, y: rAll.y + i, style: base });
|
|
7759
|
+
if (r.w <= 0 || r.h <= 0)
|
|
7760
|
+
return;
|
|
7640
7761
|
const top = clamp4(scrollTop.value, 0, Math.max(0, props.items.length - r.h));
|
|
7641
7762
|
for (let i = 0; i < r.h; i++) {
|
|
7642
7763
|
const idx = top + i;
|
|
@@ -7670,6 +7791,7 @@ var TPathPicker = (0, import_vue22.defineComponent)({
|
|
|
7670
7791
|
w: { type: Number, required: true },
|
|
7671
7792
|
h: { type: Number, required: true },
|
|
7672
7793
|
zIndex: { type: Number, default: 0 },
|
|
7794
|
+
padding: { type: [Number, String, Array], default: 0 },
|
|
7673
7795
|
workspace: { type: String, required: true },
|
|
7674
7796
|
mode: { type: String, default: "any" },
|
|
7675
7797
|
modelValue: { type: String, required: true },
|
|
@@ -7693,14 +7815,44 @@ var TPathPicker = (0, import_vue22.defineComponent)({
|
|
|
7693
7815
|
const scrollTop = (0, import_vue22.ref)(0);
|
|
7694
7816
|
const error = (0, import_vue22.ref)(null);
|
|
7695
7817
|
const inputH = 1;
|
|
7696
|
-
const
|
|
7697
|
-
|
|
7698
|
-
const raw = { x: props.x, y: props.y + inputH, w: props.w, h: listH.value };
|
|
7818
|
+
const absRect = (0, import_vue22.computed)(() => {
|
|
7819
|
+
const raw = { x: props.x, y: props.y, w: props.w, h: props.h };
|
|
7699
7820
|
const translated = translateRect(raw, layout.originX, layout.originY);
|
|
7700
7821
|
if (!layout.clipRect)
|
|
7701
7822
|
return translated;
|
|
7702
7823
|
return intersectRect(translated, layout.clipRect) ?? { x: 0, y: 0, w: 0, h: 0 };
|
|
7703
7824
|
});
|
|
7825
|
+
const contentRect2 = (0, import_vue22.computed)(() => insetRect(absRect.value, props.padding));
|
|
7826
|
+
const listH = (0, import_vue22.computed)(() => Math.max(0, Math.floor(contentRect2.value.h) - inputH));
|
|
7827
|
+
const absListRect = (0, import_vue22.computed)(() => {
|
|
7828
|
+
const c = contentRect2.value;
|
|
7829
|
+
const listRaw = { x: c.x, y: c.y + inputH, w: c.w, h: listH.value };
|
|
7830
|
+
return intersectRect(listRaw, absRect.value) ?? { x: 0, y: 0, w: 0, h: 0 };
|
|
7831
|
+
});
|
|
7832
|
+
useRenderNode(() => ({
|
|
7833
|
+
zIndex: props.zIndex - 1,
|
|
7834
|
+
rect: absRect.value,
|
|
7835
|
+
deps: [visible.value, absRect.value, props.style, defaultStyle.value],
|
|
7836
|
+
paint: (dirtyRows) => {
|
|
7837
|
+
if (!visible.value)
|
|
7838
|
+
return;
|
|
7839
|
+
const r = absRect.value;
|
|
7840
|
+
if (r.w <= 0 || r.h <= 0)
|
|
7841
|
+
return;
|
|
7842
|
+
const base = props.style ?? defaultStyle.value;
|
|
7843
|
+
if (!dirtyRows) {
|
|
7844
|
+
terminal.fill(r.x, r.y, r.w, r.h, " ", base);
|
|
7845
|
+
return;
|
|
7846
|
+
}
|
|
7847
|
+
const y0 = Math.floor(r.y);
|
|
7848
|
+
const y1 = y0 + Math.max(0, Math.floor(r.h));
|
|
7849
|
+
for (const y of dirtyRows) {
|
|
7850
|
+
if (y < y0 || y >= y1)
|
|
7851
|
+
continue;
|
|
7852
|
+
terminal.fill(r.x, y, r.w, 1, " ", base);
|
|
7853
|
+
}
|
|
7854
|
+
}
|
|
7855
|
+
}));
|
|
7704
7856
|
function ensureActiveVisible() {
|
|
7705
7857
|
const h16 = Math.max(0, listH.value);
|
|
7706
7858
|
if (h16 <= 0) {
|
|
@@ -7910,7 +8062,7 @@ var TPathPicker = (0, import_vue22.defineComponent)({
|
|
|
7910
8062
|
deps: [
|
|
7911
8063
|
visible.value,
|
|
7912
8064
|
absListRect.value,
|
|
7913
|
-
|
|
8065
|
+
contentRect2.value.w,
|
|
7914
8066
|
listH.value,
|
|
7915
8067
|
props.style,
|
|
7916
8068
|
defaultStyle.value,
|
|
@@ -7943,9 +8095,9 @@ var TPathPicker = (0, import_vue22.defineComponent)({
|
|
|
7943
8095
|
}));
|
|
7944
8096
|
return () => (0, import_vue22.h)("span", rootProps, [
|
|
7945
8097
|
(0, import_vue22.h)(TInput, {
|
|
7946
|
-
"x":
|
|
7947
|
-
"y":
|
|
7948
|
-
"w":
|
|
8098
|
+
"x": contentRect2.value.x,
|
|
8099
|
+
"y": contentRect2.value.y,
|
|
8100
|
+
"w": contentRect2.value.w,
|
|
7949
8101
|
"h": inputH,
|
|
7950
8102
|
"zIndex": props.zIndex,
|
|
7951
8103
|
"modelValue": props.modelValue,
|
|
@@ -7984,14 +8136,17 @@ var TSelect = (0, import_vue23.defineComponent)({
|
|
|
7984
8136
|
w: { type: Number, required: true },
|
|
7985
8137
|
h: { type: Number, required: true },
|
|
7986
8138
|
zIndex: { type: Number, default: 0 },
|
|
8139
|
+
padding: { type: [Number, String, Array], default: 0 },
|
|
7987
8140
|
options: { type: Array, required: true },
|
|
7988
|
-
modelValue: { type: Number, default: 0 },
|
|
8141
|
+
modelValue: { type: [Number, Array], default: 0 },
|
|
8142
|
+
multiple: { type: Boolean, default: false },
|
|
8143
|
+
multipleEmit: { type: String, default: "value" },
|
|
7989
8144
|
style: { type: Object, default: void 0 },
|
|
7990
8145
|
highlightStyle: { type: Object, default: void 0 },
|
|
7991
8146
|
autoFocus: { type: Boolean, default: false },
|
|
7992
8147
|
closeOnBlur: { type: Boolean, default: false }
|
|
7993
8148
|
},
|
|
7994
|
-
emits: ["update:modelValue", "change", "close", "focus", "blur", "keydown"],
|
|
8149
|
+
emits: ["update:modelValue", "change", "confirm", "close", "focus", "blur", "keydown"],
|
|
7995
8150
|
setup(props, { emit }) {
|
|
7996
8151
|
const { terminal, scheduler, defaultStyle, events } = useTerminal();
|
|
7997
8152
|
const layout = useLayout();
|
|
@@ -7999,7 +8154,18 @@ var TSelect = (0, import_vue23.defineComponent)({
|
|
|
7999
8154
|
const parentEventZ = (0, import_vue23.inject)(EventZIndexContextKey, (0, import_vue23.computed)(() => 0));
|
|
8000
8155
|
const eventZ = (0, import_vue23.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0));
|
|
8001
8156
|
const focused = (0, import_vue23.ref)(false);
|
|
8002
|
-
const
|
|
8157
|
+
const initialActive = (() => {
|
|
8158
|
+
const max = Math.max(0, props.options.length - 1);
|
|
8159
|
+
if (!props.multiple) {
|
|
8160
|
+
const idx = typeof props.modelValue === "number" ? props.modelValue : 0;
|
|
8161
|
+
return clamp6(idx, 0, max);
|
|
8162
|
+
}
|
|
8163
|
+
const selected = Array.isArray(props.modelValue) ? props.modelValue : [];
|
|
8164
|
+
const first = selected[0] ?? 0;
|
|
8165
|
+
return clamp6(first, 0, max);
|
|
8166
|
+
})();
|
|
8167
|
+
const active = (0, import_vue23.ref)(initialActive);
|
|
8168
|
+
const scrollTopLine = (0, import_vue23.ref)(0);
|
|
8003
8169
|
const absRect = (0, import_vue23.computed)(() => {
|
|
8004
8170
|
const raw = { x: props.x, y: props.y, w: props.w, h: props.h };
|
|
8005
8171
|
const translated = translateRect(raw, layout.originX, layout.originY);
|
|
@@ -8007,39 +8173,190 @@ var TSelect = (0, import_vue23.defineComponent)({
|
|
|
8007
8173
|
return translated;
|
|
8008
8174
|
return intersectRect(translated, layout.clipRect) ?? { x: 0, y: 0, w: 0, h: 0 };
|
|
8009
8175
|
});
|
|
8176
|
+
const contentRect2 = (0, import_vue23.computed)(() => insetRect(absRect.value, props.padding));
|
|
8010
8177
|
(0, import_vue23.watchEffect)(() => {
|
|
8011
|
-
|
|
8178
|
+
const max = Math.max(0, props.options.length - 1);
|
|
8179
|
+
if (!props.multiple) {
|
|
8180
|
+
const idx = typeof props.modelValue === "number" ? props.modelValue : 0;
|
|
8181
|
+
active.value = clamp6(idx, 0, max);
|
|
8182
|
+
return;
|
|
8183
|
+
}
|
|
8184
|
+
active.value = clamp6(active.value, 0, max);
|
|
8012
8185
|
});
|
|
8186
|
+
function getPrefixCells() {
|
|
8187
|
+
return props.multiple ? textCellWidth3("[x] ") : 0;
|
|
8188
|
+
}
|
|
8013
8189
|
function getOptionLabel(opt) {
|
|
8014
8190
|
return typeof opt === "string" ? opt : opt.label;
|
|
8015
8191
|
}
|
|
8016
8192
|
function getOptionDetail(opt) {
|
|
8017
8193
|
return typeof opt === "string" ? void 0 : opt.detail;
|
|
8018
8194
|
}
|
|
8019
|
-
function
|
|
8195
|
+
function commitSingle(index) {
|
|
8020
8196
|
const next = clamp6(index, 0, Math.max(0, props.options.length - 1));
|
|
8021
8197
|
active.value = next;
|
|
8022
8198
|
emit("update:modelValue", next);
|
|
8023
8199
|
const opt = props.options[next];
|
|
8024
8200
|
emit("change", opt ? getOptionLabel(opt) : null);
|
|
8025
8201
|
}
|
|
8202
|
+
function getSelectedIndices() {
|
|
8203
|
+
if (!props.multiple)
|
|
8204
|
+
return [];
|
|
8205
|
+
const max = Math.max(0, props.options.length - 1);
|
|
8206
|
+
const raw = Array.isArray(props.modelValue) ? props.modelValue : [];
|
|
8207
|
+
const set = /* @__PURE__ */ new Set();
|
|
8208
|
+
for (const v of raw) {
|
|
8209
|
+
if (typeof v !== "number" || !Number.isFinite(v))
|
|
8210
|
+
continue;
|
|
8211
|
+
set.add(clamp6(Math.trunc(v), 0, max));
|
|
8212
|
+
}
|
|
8213
|
+
return [...set].sort((a, b) => a - b);
|
|
8214
|
+
}
|
|
8215
|
+
function makeMultiplePayload(indices) {
|
|
8216
|
+
const values = indices.map((i) => props.options[i]).filter(Boolean).map((opt) => getOptionLabel(opt));
|
|
8217
|
+
return { indices, values };
|
|
8218
|
+
}
|
|
8219
|
+
function emitMultiple(name, indices) {
|
|
8220
|
+
const payload = makeMultiplePayload(indices);
|
|
8221
|
+
if (props.multipleEmit === "index") {
|
|
8222
|
+
emit(name, payload.indices);
|
|
8223
|
+
return;
|
|
8224
|
+
}
|
|
8225
|
+
if (props.multipleEmit === "both") {
|
|
8226
|
+
emit(name, payload);
|
|
8227
|
+
return;
|
|
8228
|
+
}
|
|
8229
|
+
emit(name, payload.values);
|
|
8230
|
+
}
|
|
8231
|
+
function toggleMultiple(index) {
|
|
8232
|
+
const nextIndex = clamp6(index, 0, Math.max(0, props.options.length - 1));
|
|
8233
|
+
active.value = nextIndex;
|
|
8234
|
+
const set = new Set(getSelectedIndices());
|
|
8235
|
+
if (set.has(nextIndex))
|
|
8236
|
+
set.delete(nextIndex);
|
|
8237
|
+
else
|
|
8238
|
+
set.add(nextIndex);
|
|
8239
|
+
const indices = [...set].sort((a, b) => a - b);
|
|
8240
|
+
emit("update:modelValue", indices);
|
|
8241
|
+
emitMultiple("change", indices);
|
|
8242
|
+
}
|
|
8243
|
+
function confirmMultiple() {
|
|
8244
|
+
const indices = getSelectedIndices();
|
|
8245
|
+
emitMultiple("confirm", indices);
|
|
8246
|
+
}
|
|
8247
|
+
function commit(index) {
|
|
8248
|
+
if (props.multiple)
|
|
8249
|
+
toggleMultiple(index);
|
|
8250
|
+
else
|
|
8251
|
+
commitSingle(index);
|
|
8252
|
+
}
|
|
8253
|
+
function computeColumnLayout(totalW, hasDetail, prefixCells) {
|
|
8254
|
+
totalW = Math.max(0, Math.floor(totalW));
|
|
8255
|
+
if (!hasDetail || totalW <= 0)
|
|
8256
|
+
return { labelW: totalW, gapW: 0, detailW: 0 };
|
|
8257
|
+
const gapW = totalW >= 12 ? 2 : 1;
|
|
8258
|
+
const minLabelText = 6;
|
|
8259
|
+
const minLabelW = Math.min(totalW, prefixCells + minLabelText);
|
|
8260
|
+
const minDetailW = Math.min(12, Math.max(6, Math.floor(totalW / 4)));
|
|
8261
|
+
let detailW = clamp6(Math.floor(totalW * 0.35), minDetailW, Math.max(0, totalW - gapW - minLabelW));
|
|
8262
|
+
let labelW = Math.max(0, totalW - gapW - detailW);
|
|
8263
|
+
if (labelW < minLabelW) {
|
|
8264
|
+
detailW = Math.max(0, totalW - gapW - minLabelW);
|
|
8265
|
+
labelW = Math.max(0, totalW - gapW - detailW);
|
|
8266
|
+
}
|
|
8267
|
+
if (detailW <= 0)
|
|
8268
|
+
return { labelW: totalW, gapW: 0, detailW: 0 };
|
|
8269
|
+
return { labelW, gapW, detailW };
|
|
8270
|
+
}
|
|
8271
|
+
function safeWrap(text, width) {
|
|
8272
|
+
width = Math.max(0, Math.floor(width));
|
|
8273
|
+
if (width <= 0)
|
|
8274
|
+
return [""];
|
|
8275
|
+
return wrapByCells(text, width).map((l) => sliceByCells(l, width));
|
|
8276
|
+
}
|
|
8277
|
+
const optionLayouts = (0, import_vue23.computed)(() => {
|
|
8278
|
+
const r = contentRect2.value;
|
|
8279
|
+
const w = Math.max(0, Math.floor(r.w));
|
|
8280
|
+
const prefixCells = getPrefixCells();
|
|
8281
|
+
const layouts = [];
|
|
8282
|
+
const flat = [];
|
|
8283
|
+
const starts = Array.from({ length: props.options.length }, () => 0);
|
|
8284
|
+
let line = 0;
|
|
8285
|
+
for (let i = 0; i < props.options.length; i++) {
|
|
8286
|
+
const opt = props.options[i];
|
|
8287
|
+
const label = sanitizeInlineText(getOptionLabel(opt));
|
|
8288
|
+
const detail = getOptionDetail(opt);
|
|
8289
|
+
const safeDetail = detail ? sanitizeInlineText(detail) : "";
|
|
8290
|
+
const cols = computeColumnLayout(w, Boolean(safeDetail), prefixCells);
|
|
8291
|
+
const labelTextW = Math.max(0, cols.labelW - prefixCells);
|
|
8292
|
+
const labelLines = safeWrap(label, labelTextW);
|
|
8293
|
+
const detailLines = cols.detailW > 0 && safeDetail ? safeWrap(safeDetail, cols.detailW) : [];
|
|
8294
|
+
const height = Math.max(1, labelLines.length, detailLines.length || 0);
|
|
8295
|
+
layouts.push({
|
|
8296
|
+
labelLines,
|
|
8297
|
+
detailLines,
|
|
8298
|
+
height,
|
|
8299
|
+
labelW: cols.labelW,
|
|
8300
|
+
gapW: cols.gapW,
|
|
8301
|
+
detailW: cols.detailW
|
|
8302
|
+
});
|
|
8303
|
+
starts[i] = line;
|
|
8304
|
+
for (let j = 0; j < height; j++)
|
|
8305
|
+
flat.push({ optionIndex: i, subLine: j });
|
|
8306
|
+
line += height;
|
|
8307
|
+
}
|
|
8308
|
+
return { layouts, flat, starts, totalLines: line, contentW: w, prefixCells };
|
|
8309
|
+
});
|
|
8310
|
+
function ensureActiveVisible() {
|
|
8311
|
+
var _a;
|
|
8312
|
+
const viewH = Math.max(0, Math.floor(contentRect2.value.h));
|
|
8313
|
+
const { layouts, starts, totalLines } = optionLayouts.value;
|
|
8314
|
+
if (viewH <= 0 || totalLines <= 0) {
|
|
8315
|
+
scrollTopLine.value = 0;
|
|
8316
|
+
return;
|
|
8317
|
+
}
|
|
8318
|
+
const maxTop = Math.max(0, totalLines - viewH);
|
|
8319
|
+
scrollTopLine.value = clamp6(scrollTopLine.value, 0, maxTop);
|
|
8320
|
+
const idx = clamp6(active.value, 0, Math.max(0, layouts.length - 1));
|
|
8321
|
+
const start = starts[idx] ?? 0;
|
|
8322
|
+
const height = ((_a = layouts[idx]) == null ? void 0 : _a.height) ?? 1;
|
|
8323
|
+
const end = start + height - 1;
|
|
8324
|
+
if (start < scrollTopLine.value)
|
|
8325
|
+
scrollTopLine.value = clamp6(start, 0, maxTop);
|
|
8326
|
+
else if (end >= scrollTopLine.value + viewH)
|
|
8327
|
+
scrollTopLine.value = clamp6(end - (viewH - 1), 0, maxTop);
|
|
8328
|
+
}
|
|
8026
8329
|
function onKeydown(e) {
|
|
8027
8330
|
emit("keydown", e);
|
|
8028
8331
|
if (e.key === "ArrowUp") {
|
|
8029
8332
|
e.preventDefault();
|
|
8030
8333
|
active.value = clamp6(active.value - 1, 0, Math.max(0, props.options.length - 1));
|
|
8031
|
-
|
|
8334
|
+
if (!props.multiple)
|
|
8335
|
+
emit("update:modelValue", active.value);
|
|
8336
|
+
ensureActiveVisible();
|
|
8032
8337
|
scheduler.invalidate();
|
|
8033
8338
|
return;
|
|
8034
8339
|
}
|
|
8035
8340
|
if (e.key === "ArrowDown") {
|
|
8036
8341
|
e.preventDefault();
|
|
8037
8342
|
active.value = clamp6(active.value + 1, 0, Math.max(0, props.options.length - 1));
|
|
8038
|
-
|
|
8343
|
+
if (!props.multiple)
|
|
8344
|
+
emit("update:modelValue", active.value);
|
|
8345
|
+
ensureActiveVisible();
|
|
8039
8346
|
scheduler.invalidate();
|
|
8040
8347
|
return;
|
|
8041
8348
|
}
|
|
8349
|
+
if (props.multiple && (e.code === "Space" || e.key === " " || e.key === "Spacebar")) {
|
|
8350
|
+
e.preventDefault();
|
|
8351
|
+
toggleMultiple(active.value);
|
|
8352
|
+
return;
|
|
8353
|
+
}
|
|
8042
8354
|
if (e.key === "Enter") {
|
|
8355
|
+
if (props.multiple) {
|
|
8356
|
+
e.preventDefault();
|
|
8357
|
+
confirmMultiple();
|
|
8358
|
+
return;
|
|
8359
|
+
}
|
|
8043
8360
|
commit(active.value);
|
|
8044
8361
|
return;
|
|
8045
8362
|
}
|
|
@@ -8055,13 +8372,34 @@ var TSelect = (0, import_vue23.defineComponent)({
|
|
|
8055
8372
|
focusable: true,
|
|
8056
8373
|
handlers: {
|
|
8057
8374
|
click: (e) => {
|
|
8058
|
-
const r =
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
|
|
8375
|
+
const r = contentRect2.value;
|
|
8376
|
+
if (e.cellY < r.y || e.cellY >= r.y + r.h) {
|
|
8377
|
+
emit("close");
|
|
8378
|
+
return;
|
|
8379
|
+
}
|
|
8380
|
+
const localRow = e.cellY - r.y;
|
|
8381
|
+
const { flat } = optionLayouts.value;
|
|
8382
|
+
const line = flat[scrollTopLine.value + localRow];
|
|
8383
|
+
if (line)
|
|
8384
|
+
commit(line.optionIndex);
|
|
8062
8385
|
else
|
|
8063
8386
|
emit("close");
|
|
8064
8387
|
},
|
|
8388
|
+
wheel: (e) => {
|
|
8389
|
+
const delta = e.deltaY ?? 0;
|
|
8390
|
+
if (!delta)
|
|
8391
|
+
return;
|
|
8392
|
+
const dir = delta > 0 ? 1 : -1;
|
|
8393
|
+
const r = contentRect2.value;
|
|
8394
|
+
const viewH = Math.max(0, Math.floor(r.h));
|
|
8395
|
+
const { totalLines } = optionLayouts.value;
|
|
8396
|
+
const maxTop = Math.max(0, totalLines - viewH);
|
|
8397
|
+
const next = clamp6(scrollTopLine.value + dir, 0, maxTop);
|
|
8398
|
+
if (next !== scrollTopLine.value) {
|
|
8399
|
+
scrollTopLine.value = next;
|
|
8400
|
+
scheduler.invalidate();
|
|
8401
|
+
}
|
|
8402
|
+
},
|
|
8065
8403
|
focus: () => {
|
|
8066
8404
|
focused.value = true;
|
|
8067
8405
|
emit("focus");
|
|
@@ -8077,6 +8415,10 @@ var TSelect = (0, import_vue23.defineComponent)({
|
|
|
8077
8415
|
keydown: onKeydown
|
|
8078
8416
|
}
|
|
8079
8417
|
}));
|
|
8418
|
+
(0, import_vue23.watchEffect)(() => {
|
|
8419
|
+
void optionLayouts.value;
|
|
8420
|
+
ensureActiveVisible();
|
|
8421
|
+
});
|
|
8080
8422
|
(0, import_vue23.watchEffect)(() => {
|
|
8081
8423
|
if (!props.autoFocus)
|
|
8082
8424
|
return;
|
|
@@ -8093,45 +8435,67 @@ var TSelect = (0, import_vue23.defineComponent)({
|
|
|
8093
8435
|
useRenderNode(() => ({
|
|
8094
8436
|
zIndex: props.zIndex,
|
|
8095
8437
|
rect: absRect.value,
|
|
8096
|
-
deps: [visible.value, absRect.value, props.w, props.h, props.options, props.modelValue, props.style, props.highlightStyle, focused.value, active.value, defaultStyle.value],
|
|
8438
|
+
deps: [visible.value, absRect.value, props.w, props.h, props.padding, props.options, props.modelValue, props.multiple, props.multipleEmit, props.style, props.highlightStyle, focused.value, active.value, scrollTopLine.value, optionLayouts.value, defaultStyle.value],
|
|
8097
8439
|
paint: () => {
|
|
8098
8440
|
if (!visible.value)
|
|
8099
8441
|
return;
|
|
8100
|
-
const
|
|
8101
|
-
if (
|
|
8442
|
+
const rAll = absRect.value;
|
|
8443
|
+
if (rAll.w <= 0 || rAll.h <= 0)
|
|
8102
8444
|
return;
|
|
8103
8445
|
const base = props.style ?? defaultStyle.value;
|
|
8104
|
-
const
|
|
8446
|
+
const highlightBase = props.highlightStyle ?? { ...base, bg: "yellow", fg: "black" };
|
|
8105
8447
|
const detailDimStyle = { ...base, dim: true };
|
|
8106
|
-
const
|
|
8107
|
-
|
|
8108
|
-
|
|
8448
|
+
const highlightDetailStyle = { ...highlightBase, dim: true };
|
|
8449
|
+
const blankAll = " ".repeat(rAll.w);
|
|
8450
|
+
for (let i = 0; i < rAll.h; i++)
|
|
8451
|
+
terminal.write(blankAll, { x: rAll.x, y: rAll.y + i, style: base });
|
|
8452
|
+
const r = contentRect2.value;
|
|
8453
|
+
if (r.w <= 0 || r.h <= 0)
|
|
8454
|
+
return;
|
|
8455
|
+
const { layouts, flat, totalLines, prefixCells } = optionLayouts.value;
|
|
8456
|
+
const selectedSet = props.multiple ? new Set(getSelectedIndices()) : null;
|
|
8457
|
+
const top = clamp6(scrollTopLine.value, 0, Math.max(0, totalLines - r.h));
|
|
8458
|
+
const prefixSpaces = props.multiple ? " ".repeat(prefixCells) : "";
|
|
8459
|
+
const blank = " ".repeat(r.w);
|
|
8460
|
+
for (let row = 0; row < r.h; row++) {
|
|
8461
|
+
const y = r.y + row;
|
|
8462
|
+
const lineIdx = top + row;
|
|
8463
|
+
const line = flat[lineIdx];
|
|
8464
|
+
if (!line) {
|
|
8465
|
+
terminal.write(blank, { x: r.x, y, style: base });
|
|
8466
|
+
continue;
|
|
8467
|
+
}
|
|
8468
|
+
const opt = props.options[line.optionIndex];
|
|
8109
8469
|
if (!opt) {
|
|
8110
|
-
terminal.write(
|
|
8470
|
+
terminal.write(blank, { x: r.x, y, style: base });
|
|
8111
8471
|
continue;
|
|
8112
8472
|
}
|
|
8113
|
-
const
|
|
8114
|
-
const
|
|
8115
|
-
const
|
|
8116
|
-
const
|
|
8117
|
-
|
|
8118
|
-
const
|
|
8119
|
-
const
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8473
|
+
const isActiveOpt = line.optionIndex === active.value;
|
|
8474
|
+
const isHighlighted = props.multiple ? focused.value && isActiveOpt : isActiveOpt;
|
|
8475
|
+
const rowStyle = isHighlighted ? highlightBase : base;
|
|
8476
|
+
const detailStyle = isHighlighted ? highlightDetailStyle : detailDimStyle;
|
|
8477
|
+
terminal.write(blank, { x: r.x, y, style: rowStyle });
|
|
8478
|
+
const layout2 = layouts[line.optionIndex];
|
|
8479
|
+
const labelLine = (layout2 == null ? void 0 : layout2.labelLines[line.subLine]) ?? "";
|
|
8480
|
+
const prevVisibleLine = row > 0 ? flat[lineIdx - 1] : void 0;
|
|
8481
|
+
const isFirstVisibleLineOfOption = !prevVisibleLine || prevVisibleLine.optionIndex !== line.optionIndex;
|
|
8482
|
+
const detailLine = (() => {
|
|
8483
|
+
if (!layout2 || layout2.detailW <= 0 || layout2.detailLines.length === 0)
|
|
8484
|
+
return "";
|
|
8485
|
+
if (layout2.detailLines.length === 1)
|
|
8486
|
+
return isFirstVisibleLineOfOption ? layout2.detailLines[0] ?? "" : "";
|
|
8487
|
+
return layout2.detailLines[line.subLine] ?? "";
|
|
8488
|
+
})();
|
|
8489
|
+
const isChecked = props.multiple ? selectedSet.has(line.optionIndex) : isActiveOpt;
|
|
8490
|
+
const prefix = props.multiple ? isChecked ? "[x] " : "[ ] " : "";
|
|
8491
|
+
const prefixPad = props.multiple ? isFirstVisibleLineOfOption ? prefix : prefixSpaces : "";
|
|
8492
|
+
const labelTextW = Math.max(0, ((layout2 == null ? void 0 : layout2.labelW) ?? r.w) - prefixCells);
|
|
8493
|
+
const labelText = labelTextW > 0 ? sliceByCells(labelLine, labelTextW) : "";
|
|
8494
|
+
const outLabel = padEndByCells(sliceByCells(`${prefixPad}${labelText}`, (layout2 == null ? void 0 : layout2.labelW) ?? r.w), (layout2 == null ? void 0 : layout2.labelW) ?? r.w);
|
|
8495
|
+
terminal.write(outLabel, { x: r.x, y, style: rowStyle });
|
|
8496
|
+
if (((layout2 == null ? void 0 : layout2.detailW) ?? 0) > 0) {
|
|
8497
|
+
const outDetail = padEndByCells(sliceByCells(detailLine, layout2.detailW), layout2.detailW);
|
|
8498
|
+
terminal.write(outDetail, { x: r.x + layout2.labelW + layout2.gapW, y, style: detailStyle });
|
|
8135
8499
|
}
|
|
8136
8500
|
}
|
|
8137
8501
|
}
|