@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.js
CHANGED
|
@@ -417,32 +417,6 @@ function createNodePathPickerProvider() {
|
|
|
417
417
|
};
|
|
418
418
|
}
|
|
419
419
|
|
|
420
|
-
//#endregion
|
|
421
|
-
//#region src/cli/recording.ts
|
|
422
|
-
async function loadFs() {
|
|
423
|
-
return import("node:fs");
|
|
424
|
-
}
|
|
425
|
-
async function writeEventLog(path, events) {
|
|
426
|
-
const { writeFileSync } = await loadFs();
|
|
427
|
-
const lines = events.map((e) => JSON.stringify(e)).join("\n");
|
|
428
|
-
writeFileSync(path, `${lines}${lines ? "\n" : ""}`, "utf8");
|
|
429
|
-
}
|
|
430
|
-
async function writeSnapshot(path, lines) {
|
|
431
|
-
const { writeFileSync } = await loadFs();
|
|
432
|
-
writeFileSync(path, `${lines.join("\n")}\n`, "utf8");
|
|
433
|
-
}
|
|
434
|
-
async function readEventLog(path) {
|
|
435
|
-
const { readFileSync } = await loadFs();
|
|
436
|
-
const raw = readFileSync(path, "utf8");
|
|
437
|
-
const out = [];
|
|
438
|
-
for (const line of raw.split(/\r?\n/g)) {
|
|
439
|
-
const trimmed = line.trim();
|
|
440
|
-
if (!trimmed) continue;
|
|
441
|
-
out.push(JSON.parse(trimmed));
|
|
442
|
-
}
|
|
443
|
-
return out;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
420
|
//#endregion
|
|
447
421
|
//#region src/utils/path.ts
|
|
448
422
|
function normalizeSeparators(input) {
|
|
@@ -617,37 +591,29 @@ function resolveUserPath(workspaceAbs, input) {
|
|
|
617
591
|
}
|
|
618
592
|
|
|
619
593
|
//#endregion
|
|
620
|
-
//#region src/
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
[9001, 9002],
|
|
624
|
-
[11904, 42191],
|
|
625
|
-
[44032, 55203],
|
|
626
|
-
[63744, 64255],
|
|
627
|
-
[65040, 65049],
|
|
628
|
-
[65072, 65135],
|
|
629
|
-
[65280, 65376],
|
|
630
|
-
[65504, 65510]
|
|
631
|
-
];
|
|
632
|
-
function isFullWidthCodePoint(codePoint) {
|
|
633
|
-
for (const [start, end] of fullWidthRanges) if (codePoint >= start && codePoint <= end) return true;
|
|
634
|
-
return false;
|
|
594
|
+
//#region src/cli/recording.ts
|
|
595
|
+
async function loadFs() {
|
|
596
|
+
return import("node:fs");
|
|
635
597
|
}
|
|
636
|
-
function
|
|
637
|
-
|
|
598
|
+
async function writeEventLog(path, events) {
|
|
599
|
+
const { writeFileSync } = await loadFs();
|
|
600
|
+
const lines = events.map((e) => JSON.stringify(e)).join("\n");
|
|
601
|
+
writeFileSync(path, `${lines}${lines ? "\n" : ""}`, "utf8");
|
|
638
602
|
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
} catch {
|
|
643
|
-
extendedPictographicRe = null;
|
|
603
|
+
async function writeSnapshot(path, lines) {
|
|
604
|
+
const { writeFileSync } = await loadFs();
|
|
605
|
+
writeFileSync(path, `${lines.join("\n")}\n`, "utf8");
|
|
644
606
|
}
|
|
645
|
-
function
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
const
|
|
649
|
-
|
|
650
|
-
|
|
607
|
+
async function readEventLog(path) {
|
|
608
|
+
const { readFileSync } = await loadFs();
|
|
609
|
+
const raw = readFileSync(path, "utf8");
|
|
610
|
+
const out = [];
|
|
611
|
+
for (const line of raw.split(/\r?\n/g)) {
|
|
612
|
+
const trimmed = line.trim();
|
|
613
|
+
if (!trimmed) continue;
|
|
614
|
+
out.push(JSON.parse(trimmed));
|
|
615
|
+
}
|
|
616
|
+
return out;
|
|
651
617
|
}
|
|
652
618
|
|
|
653
619
|
//#endregion
|
|
@@ -953,6 +919,40 @@ function parseAnsiSgr(input, baseStyle = {}) {
|
|
|
953
919
|
return segments;
|
|
954
920
|
}
|
|
955
921
|
|
|
922
|
+
//#endregion
|
|
923
|
+
//#region src/core/buffer/width.ts
|
|
924
|
+
const fullWidthRanges = [
|
|
925
|
+
[4352, 4447],
|
|
926
|
+
[9001, 9002],
|
|
927
|
+
[11904, 42191],
|
|
928
|
+
[44032, 55203],
|
|
929
|
+
[63744, 64255],
|
|
930
|
+
[65040, 65049],
|
|
931
|
+
[65072, 65135],
|
|
932
|
+
[65280, 65376],
|
|
933
|
+
[65504, 65510]
|
|
934
|
+
];
|
|
935
|
+
function isFullWidthCodePoint(codePoint) {
|
|
936
|
+
for (const [start, end] of fullWidthRanges) if (codePoint >= start && codePoint <= end) return true;
|
|
937
|
+
return false;
|
|
938
|
+
}
|
|
939
|
+
function isEmojiLike(codePoint) {
|
|
940
|
+
return codePoint >= 127744 && codePoint <= 129791 || codePoint >= 127462 && codePoint <= 127487;
|
|
941
|
+
}
|
|
942
|
+
let extendedPictographicRe = null;
|
|
943
|
+
try {
|
|
944
|
+
extendedPictographicRe = new RegExp("\\p{Extended_Pictographic}", "u");
|
|
945
|
+
} catch {
|
|
946
|
+
extendedPictographicRe = null;
|
|
947
|
+
}
|
|
948
|
+
function charCellWidth(text) {
|
|
949
|
+
if (!text) return 1;
|
|
950
|
+
if (extendedPictographicRe === null || extendedPictographicRe === void 0 ? void 0 : extendedPictographicRe.test(text)) return 2;
|
|
951
|
+
const codePoint = text.codePointAt(0);
|
|
952
|
+
if (codePoint == null) return 1;
|
|
953
|
+
return isFullWidthCodePoint(codePoint) || isEmojiLike(codePoint) ? 2 : 1;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
956
|
//#endregion
|
|
957
957
|
//#region src/core/buffer/buffer.ts
|
|
958
958
|
const DEFAULT_STYLE = Object.freeze({});
|
|
@@ -3611,6 +3611,81 @@ function translateRect(rect, dx, dy) {
|
|
|
3611
3611
|
h: rect.h
|
|
3612
3612
|
};
|
|
3613
3613
|
}
|
|
3614
|
+
function normalizePadding(padding) {
|
|
3615
|
+
const nums = [];
|
|
3616
|
+
if (typeof padding === "number") nums.push(padding);
|
|
3617
|
+
else if (Array.isArray(padding)) for (const v of padding) nums.push(typeof v === "number" ? v : Number(v));
|
|
3618
|
+
else if (typeof padding === "string") for (const part of padding.trim().split(/\s+/g)) {
|
|
3619
|
+
if (!part) continue;
|
|
3620
|
+
nums.push(Number(part));
|
|
3621
|
+
}
|
|
3622
|
+
const n = nums.map((v) => Number.isFinite(v) ? Math.max(0, Math.floor(v)) : 0);
|
|
3623
|
+
const a = n[0] ?? 0;
|
|
3624
|
+
const b = n[1] ?? a;
|
|
3625
|
+
const c = n[2] ?? a;
|
|
3626
|
+
const d = n[3] ?? b;
|
|
3627
|
+
if (n.length <= 1) return {
|
|
3628
|
+
top: a,
|
|
3629
|
+
right: a,
|
|
3630
|
+
bottom: a,
|
|
3631
|
+
left: a
|
|
3632
|
+
};
|
|
3633
|
+
if (n.length === 2) return {
|
|
3634
|
+
top: a,
|
|
3635
|
+
right: b,
|
|
3636
|
+
bottom: a,
|
|
3637
|
+
left: b
|
|
3638
|
+
};
|
|
3639
|
+
if (n.length === 3) return {
|
|
3640
|
+
top: a,
|
|
3641
|
+
right: b,
|
|
3642
|
+
bottom: c,
|
|
3643
|
+
left: b
|
|
3644
|
+
};
|
|
3645
|
+
return {
|
|
3646
|
+
top: a,
|
|
3647
|
+
right: b,
|
|
3648
|
+
bottom: c,
|
|
3649
|
+
left: d
|
|
3650
|
+
};
|
|
3651
|
+
}
|
|
3652
|
+
function clampRectPadding(rect, padding) {
|
|
3653
|
+
const requested = normalizePadding(padding);
|
|
3654
|
+
const w = Math.max(0, Math.floor(rect.w));
|
|
3655
|
+
const h$1 = Math.max(0, Math.floor(rect.h));
|
|
3656
|
+
const maxTotalX = Math.max(0, w - (w > 0 ? 1 : 0));
|
|
3657
|
+
const maxTotalY = Math.max(0, h$1 - (h$1 > 0 ? 1 : 0));
|
|
3658
|
+
if (requested.top === requested.right && requested.top === requested.bottom && requested.top === requested.left) {
|
|
3659
|
+
const maxPadX = Math.max(0, Math.floor(maxTotalX / 2));
|
|
3660
|
+
const maxPadY = Math.max(0, Math.floor(maxTotalY / 2));
|
|
3661
|
+
const pad = Math.min(requested.top, maxPadX, maxPadY);
|
|
3662
|
+
return {
|
|
3663
|
+
top: pad,
|
|
3664
|
+
right: pad,
|
|
3665
|
+
bottom: pad,
|
|
3666
|
+
left: pad
|
|
3667
|
+
};
|
|
3668
|
+
}
|
|
3669
|
+
const left = Math.min(requested.left, maxTotalX);
|
|
3670
|
+
const right = Math.min(requested.right, Math.max(0, maxTotalX - left));
|
|
3671
|
+
const top = Math.min(requested.top, maxTotalY);
|
|
3672
|
+
const bottom = Math.min(requested.bottom, Math.max(0, maxTotalY - top));
|
|
3673
|
+
return {
|
|
3674
|
+
top,
|
|
3675
|
+
right,
|
|
3676
|
+
bottom,
|
|
3677
|
+
left
|
|
3678
|
+
};
|
|
3679
|
+
}
|
|
3680
|
+
function insetRect(rect, padding) {
|
|
3681
|
+
const pad = clampRectPadding(rect, padding);
|
|
3682
|
+
return {
|
|
3683
|
+
x: rect.x + pad.left,
|
|
3684
|
+
y: rect.y + pad.top,
|
|
3685
|
+
w: Math.max(0, rect.w - pad.left - pad.right),
|
|
3686
|
+
h: Math.max(0, rect.h - pad.top - pad.bottom)
|
|
3687
|
+
};
|
|
3688
|
+
}
|
|
3614
3689
|
|
|
3615
3690
|
//#endregion
|
|
3616
3691
|
//#region src/vue/components/TAnchor.ts
|
|
@@ -3651,6 +3726,14 @@ const TAnchor = defineComponent({
|
|
|
3651
3726
|
type: Number,
|
|
3652
3727
|
default: 0
|
|
3653
3728
|
},
|
|
3729
|
+
padding: {
|
|
3730
|
+
type: [
|
|
3731
|
+
Number,
|
|
3732
|
+
String,
|
|
3733
|
+
Array
|
|
3734
|
+
],
|
|
3735
|
+
default: 0
|
|
3736
|
+
},
|
|
3654
3737
|
focusable: {
|
|
3655
3738
|
type: Boolean,
|
|
3656
3739
|
default: false
|
|
@@ -3762,9 +3845,11 @@ const TAnchor = defineComponent({
|
|
|
3762
3845
|
const childStack = computed(() => render.createStack(parentStack.value, props.zIndex));
|
|
3763
3846
|
watchEffect(() => {
|
|
3764
3847
|
const translated = rawRect.value;
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
childLayout.
|
|
3848
|
+
const content = insetRect(translated, props.padding);
|
|
3849
|
+
const contentClip = intersectRect(content, rect.value) ?? EMPTY_RECT$1;
|
|
3850
|
+
childLayout.originX = content.x;
|
|
3851
|
+
childLayout.originY = content.y;
|
|
3852
|
+
childLayout.clipRect = contentClip;
|
|
3768
3853
|
});
|
|
3769
3854
|
provide(LayoutContextKey, childLayout);
|
|
3770
3855
|
provide(RenderStackKey, childStack);
|
|
@@ -3947,7 +4032,11 @@ const TBox = defineComponent({
|
|
|
3947
4032
|
default: ""
|
|
3948
4033
|
},
|
|
3949
4034
|
padding: {
|
|
3950
|
-
type:
|
|
4035
|
+
type: [
|
|
4036
|
+
Number,
|
|
4037
|
+
String,
|
|
4038
|
+
Array
|
|
4039
|
+
],
|
|
3951
4040
|
default: 0
|
|
3952
4041
|
},
|
|
3953
4042
|
scrollX: {
|
|
@@ -4040,17 +4129,14 @@ const TBox = defineComponent({
|
|
|
4040
4129
|
watchEffect(() => {
|
|
4041
4130
|
const r = absRect.value;
|
|
4042
4131
|
const borderInset = props.border ? 1 : 0;
|
|
4043
|
-
const
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
x: r.x + borderInset + pad,
|
|
4049
|
-
y: r.y + borderInset + pad,
|
|
4050
|
-
w: Math.max(0, r.w - borderInset * 2 - pad * 2),
|
|
4051
|
-
h: Math.max(0, r.h - borderInset * 2 - pad * 2)
|
|
4132
|
+
const inner = {
|
|
4133
|
+
x: r.x + borderInset,
|
|
4134
|
+
y: r.y + borderInset,
|
|
4135
|
+
w: Math.max(0, r.w - borderInset * 2),
|
|
4136
|
+
h: Math.max(0, r.h - borderInset * 2)
|
|
4052
4137
|
};
|
|
4053
|
-
|
|
4138
|
+
const content = insetRect(inner, props.padding);
|
|
4139
|
+
let contentRect$1 = intersectRect(content, inner);
|
|
4054
4140
|
if (parent.clipRect && contentRect$1) contentRect$1 = intersectRect(contentRect$1, parent.clipRect);
|
|
4055
4141
|
if (!contentRect$1) contentRect$1 = {
|
|
4056
4142
|
x: 0,
|
|
@@ -4144,6 +4230,14 @@ const TText = defineComponent({
|
|
|
4144
4230
|
type: Number,
|
|
4145
4231
|
default: void 0
|
|
4146
4232
|
},
|
|
4233
|
+
padding: {
|
|
4234
|
+
type: [
|
|
4235
|
+
Number,
|
|
4236
|
+
String,
|
|
4237
|
+
Array
|
|
4238
|
+
],
|
|
4239
|
+
default: 0
|
|
4240
|
+
},
|
|
4147
4241
|
style: {
|
|
4148
4242
|
type: Object,
|
|
4149
4243
|
default: void 0
|
|
@@ -4161,16 +4255,21 @@ const TText = defineComponent({
|
|
|
4161
4255
|
const { terminal, defaultStyle } = useTerminal();
|
|
4162
4256
|
const layout = useLayout();
|
|
4163
4257
|
const { visible, rootProps } = useVisibility();
|
|
4258
|
+
const pad = computed(() => normalizePadding(props.padding));
|
|
4259
|
+
const contentW = computed(() => {
|
|
4260
|
+
const outerW = props.w ?? computeDefaultWidth(props.value) + pad.value.left + pad.value.right;
|
|
4261
|
+
return Math.max(0, Math.floor(outerW) - pad.value.left - pad.value.right);
|
|
4262
|
+
});
|
|
4164
4263
|
const lines = computed(() => {
|
|
4165
|
-
const w =
|
|
4264
|
+
const w = contentW.value;
|
|
4166
4265
|
if (w <= 0) return [""];
|
|
4167
4266
|
if (!props.wrap) return splitLines(props.value).map((l) => fitText(l, w));
|
|
4168
4267
|
const safe = sanitizeTextBlock(props.value);
|
|
4169
4268
|
return wrapByCells(safe, w).map((l) => fitText(l, w));
|
|
4170
4269
|
});
|
|
4171
4270
|
const absRect = computed(() => {
|
|
4172
|
-
const width = props.w ?? computeDefaultWidth(props.value);
|
|
4173
|
-
const height = props.h ?? (
|
|
4271
|
+
const width = Math.floor(props.w ?? computeDefaultWidth(props.value) + pad.value.left + pad.value.right);
|
|
4272
|
+
const height = Math.floor(props.h ?? (lines.value.length || 1) + pad.value.top + pad.value.bottom);
|
|
4174
4273
|
const raw = {
|
|
4175
4274
|
x: props.x,
|
|
4176
4275
|
y: props.y,
|
|
@@ -4203,10 +4302,14 @@ const TText = defineComponent({
|
|
|
4203
4302
|
if (!visible.value) return;
|
|
4204
4303
|
const r = absRect.value;
|
|
4205
4304
|
if (r.w <= 0 || r.h <= 0) return;
|
|
4305
|
+
const contentX = r.x + pad.value.left;
|
|
4306
|
+
const contentY = r.y + pad.value.top;
|
|
4307
|
+
const w = Math.max(0, Math.floor(r.w) - pad.value.left - pad.value.right);
|
|
4308
|
+
const h$1 = Math.max(0, Math.floor(r.h) - pad.value.top - pad.value.bottom);
|
|
4206
4309
|
const style = props.style ?? defaultStyle.value;
|
|
4207
4310
|
const blank = props.clear ? " ".repeat(r.w) : "";
|
|
4208
4311
|
const out = lines.value;
|
|
4209
|
-
const maxLines = Math.min(out.length,
|
|
4312
|
+
const maxLines = Math.min(out.length, h$1);
|
|
4210
4313
|
const paintRow = (y) => {
|
|
4211
4314
|
const i = y - r.y;
|
|
4212
4315
|
if (i < 0 || i >= r.h) return;
|
|
@@ -4215,10 +4318,12 @@ const TText = defineComponent({
|
|
|
4215
4318
|
y,
|
|
4216
4319
|
style
|
|
4217
4320
|
});
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4321
|
+
const contentRow = y - contentY;
|
|
4322
|
+
if (contentRow < 0 || contentRow >= h$1) return;
|
|
4323
|
+
if (contentRow < 0 || contentRow >= maxLines) return;
|
|
4324
|
+
const clipped = sliceByCells(out[contentRow] ?? "", w);
|
|
4325
|
+
terminal.write(padEndByCells(clipped, w), {
|
|
4326
|
+
x: contentX,
|
|
4222
4327
|
y,
|
|
4223
4328
|
style
|
|
4224
4329
|
});
|
|
@@ -4265,6 +4370,14 @@ const TView = defineComponent({
|
|
|
4265
4370
|
type: Number,
|
|
4266
4371
|
default: 0
|
|
4267
4372
|
},
|
|
4373
|
+
padding: {
|
|
4374
|
+
type: [
|
|
4375
|
+
Number,
|
|
4376
|
+
String,
|
|
4377
|
+
Array
|
|
4378
|
+
],
|
|
4379
|
+
default: 0
|
|
4380
|
+
},
|
|
4268
4381
|
scrollX: {
|
|
4269
4382
|
type: Number,
|
|
4270
4383
|
default: 0
|
|
@@ -4372,9 +4485,11 @@ const TView = defineComponent({
|
|
|
4372
4485
|
const childStack = computed(() => render.createStack(parentStack.value, props.zIndex));
|
|
4373
4486
|
watchEffect(() => {
|
|
4374
4487
|
const translated = rawRect.value;
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
childLayout.
|
|
4488
|
+
const content = insetRect(translated, props.padding);
|
|
4489
|
+
const contentClip = intersectRect(content, rect.value) ?? EMPTY_RECT;
|
|
4490
|
+
childLayout.originX = content.x - Math.floor(props.scrollX);
|
|
4491
|
+
childLayout.originY = content.y - Math.floor(props.scrollY);
|
|
4492
|
+
childLayout.clipRect = contentClip;
|
|
4378
4493
|
});
|
|
4379
4494
|
provide(LayoutContextKey, childLayout);
|
|
4380
4495
|
provide(RenderStackKey, childStack);
|
|
@@ -4580,10 +4695,10 @@ function computePosition(opts) {
|
|
|
4580
4695
|
}
|
|
4581
4696
|
function contentRect(opts) {
|
|
4582
4697
|
const borderInset = opts.border ? 1 : 0;
|
|
4583
|
-
const pad =
|
|
4698
|
+
const pad = normalizePadding(opts.padding);
|
|
4584
4699
|
return {
|
|
4585
|
-
w: Math.max(0, Math.floor(opts.w) - borderInset * 2 - pad
|
|
4586
|
-
h: Math.max(0, Math.floor(opts.h) - borderInset * 2 - pad
|
|
4700
|
+
w: Math.max(0, Math.floor(opts.w) - borderInset * 2 - pad.left - pad.right),
|
|
4701
|
+
h: Math.max(0, Math.floor(opts.h) - borderInset * 2 - pad.top - pad.bottom)
|
|
4587
4702
|
};
|
|
4588
4703
|
}
|
|
4589
4704
|
const DialogSurface = defineComponent({
|
|
@@ -4606,7 +4721,11 @@ const DialogSurface = defineComponent({
|
|
|
4606
4721
|
default: ""
|
|
4607
4722
|
},
|
|
4608
4723
|
padding: {
|
|
4609
|
-
type:
|
|
4724
|
+
type: [
|
|
4725
|
+
Number,
|
|
4726
|
+
String,
|
|
4727
|
+
Array
|
|
4728
|
+
],
|
|
4610
4729
|
default: 1
|
|
4611
4730
|
},
|
|
4612
4731
|
zIndex: {
|
|
@@ -4880,7 +4999,11 @@ const TDialog = defineComponent({
|
|
|
4880
4999
|
default: ""
|
|
4881
5000
|
},
|
|
4882
5001
|
padding: {
|
|
4883
|
-
type:
|
|
5002
|
+
type: [
|
|
5003
|
+
Number,
|
|
5004
|
+
String,
|
|
5005
|
+
Array
|
|
5006
|
+
],
|
|
4884
5007
|
default: 1
|
|
4885
5008
|
},
|
|
4886
5009
|
zIndex: {
|
|
@@ -5947,6 +6070,14 @@ const TFlow = defineComponent({
|
|
|
5947
6070
|
type: Number,
|
|
5948
6071
|
required: true
|
|
5949
6072
|
},
|
|
6073
|
+
padding: {
|
|
6074
|
+
type: [
|
|
6075
|
+
Number,
|
|
6076
|
+
String,
|
|
6077
|
+
Array
|
|
6078
|
+
],
|
|
6079
|
+
default: 0
|
|
6080
|
+
},
|
|
5950
6081
|
items: {
|
|
5951
6082
|
type: Array,
|
|
5952
6083
|
required: true
|
|
@@ -5969,25 +6100,29 @@ const TFlow = defineComponent({
|
|
|
5969
6100
|
}
|
|
5970
6101
|
},
|
|
5971
6102
|
setup(props, { slots }) {
|
|
6103
|
+
const pad = computed(() => normalizePadding(props.padding));
|
|
6104
|
+
const innerW = computed(() => Math.max(0, Math.floor(props.w) - pad.value.left - pad.value.right));
|
|
6105
|
+
const innerH = computed(() => Math.max(0, Math.floor(props.h) - pad.value.top - pad.value.bottom));
|
|
5972
6106
|
return () => h(TView, {
|
|
5973
6107
|
x: props.x,
|
|
5974
6108
|
y: props.y,
|
|
5975
6109
|
w: props.w,
|
|
5976
6110
|
h: props.h,
|
|
5977
|
-
zIndex: props.zIndex
|
|
6111
|
+
zIndex: props.zIndex,
|
|
6112
|
+
padding: props.padding
|
|
5978
6113
|
}, () => props.items.map((item, index) => {
|
|
5979
6114
|
const step = Math.max(0, Math.floor(props.itemSize)) + Math.max(0, Math.floor(props.gap));
|
|
5980
6115
|
const offset = index * step;
|
|
5981
6116
|
const childProps = props.direction === "vertical" ? {
|
|
5982
6117
|
x: 0,
|
|
5983
6118
|
y: offset,
|
|
5984
|
-
w:
|
|
6119
|
+
w: innerW.value,
|
|
5985
6120
|
h: Math.max(0, Math.floor(props.itemSize))
|
|
5986
6121
|
} : {
|
|
5987
6122
|
x: offset,
|
|
5988
6123
|
y: 0,
|
|
5989
6124
|
w: Math.max(0, Math.floor(props.itemSize)),
|
|
5990
|
-
h:
|
|
6125
|
+
h: innerH.value
|
|
5991
6126
|
};
|
|
5992
6127
|
return h(TView, {
|
|
5993
6128
|
key: index,
|
|
@@ -6395,6 +6530,14 @@ const TInput = defineComponent({
|
|
|
6395
6530
|
type: Number,
|
|
6396
6531
|
default: 0
|
|
6397
6532
|
},
|
|
6533
|
+
padding: {
|
|
6534
|
+
type: [
|
|
6535
|
+
Number,
|
|
6536
|
+
String,
|
|
6537
|
+
Array
|
|
6538
|
+
],
|
|
6539
|
+
default: "0 1"
|
|
6540
|
+
},
|
|
6398
6541
|
modelValue: {
|
|
6399
6542
|
type: String,
|
|
6400
6543
|
required: true
|
|
@@ -6506,19 +6649,6 @@ const TInput = defineComponent({
|
|
|
6506
6649
|
const parentEventZ = inject(EventZIndexContextKey, computed(() => 0));
|
|
6507
6650
|
const eventZ = computed(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0));
|
|
6508
6651
|
const promptOverlayStack = render.createStack(render.rootStack, 1e4);
|
|
6509
|
-
const PADDING_X = 1;
|
|
6510
|
-
function measureContent(r) {
|
|
6511
|
-
const wAll = Math.max(0, Math.floor(r.w));
|
|
6512
|
-
const hAll = Math.max(0, Math.floor(r.h));
|
|
6513
|
-
const padX = clamp$3(PADDING_X, 0, Math.floor(wAll / 2));
|
|
6514
|
-
const w = Math.max(0, wAll - padX * 2);
|
|
6515
|
-
return {
|
|
6516
|
-
wAll,
|
|
6517
|
-
hAll,
|
|
6518
|
-
padX,
|
|
6519
|
-
w
|
|
6520
|
-
};
|
|
6521
|
-
}
|
|
6522
6652
|
const focused = ref(false);
|
|
6523
6653
|
const cursor = ref(0);
|
|
6524
6654
|
const anchor = ref(null);
|
|
@@ -6535,7 +6665,6 @@ const TInput = defineComponent({
|
|
|
6535
6665
|
function getValue() {
|
|
6536
6666
|
return pendingValue.value ?? props.modelValue;
|
|
6537
6667
|
}
|
|
6538
|
-
const wrapMode = computed(() => Math.max(1, Math.floor(props.h)) > 1);
|
|
6539
6668
|
const rawAbsRect = computed(() => {
|
|
6540
6669
|
const raw = {
|
|
6541
6670
|
x: props.x,
|
|
@@ -6797,6 +6926,8 @@ const TInput = defineComponent({
|
|
|
6797
6926
|
h: 0
|
|
6798
6927
|
};
|
|
6799
6928
|
});
|
|
6929
|
+
const contentRect$1 = computed(() => insetRect(absRect.value, props.padding));
|
|
6930
|
+
const wrapMode = computed(() => Math.max(1, Math.floor(contentRect$1.value.h)) > 1);
|
|
6800
6931
|
const selection = computed(() => {
|
|
6801
6932
|
if (anchor.value == null || anchor.value === cursor.value) return null;
|
|
6802
6933
|
const start = Math.min(anchor.value, cursor.value);
|
|
@@ -6872,10 +7003,16 @@ const TInput = defineComponent({
|
|
|
6872
7003
|
return !focused.value || props.placeholderWhenFocused;
|
|
6873
7004
|
});
|
|
6874
7005
|
function ensureCursorVisible() {
|
|
6875
|
-
const r =
|
|
6876
|
-
const
|
|
6877
|
-
const
|
|
6878
|
-
|
|
7006
|
+
const r = contentRect$1.value;
|
|
7007
|
+
const w = Math.max(0, Math.floor(r.w));
|
|
7008
|
+
const h$1 = Math.max(0, Math.floor(r.h));
|
|
7009
|
+
if (w <= 0 || h$1 <= 0) {
|
|
7010
|
+
scrollX.value = 0;
|
|
7011
|
+
scrollY.value = 0;
|
|
7012
|
+
return;
|
|
7013
|
+
}
|
|
7014
|
+
const width = w;
|
|
7015
|
+
const height = h$1;
|
|
6879
7016
|
const value = getValue();
|
|
6880
7017
|
const wrap = wrapMode.value;
|
|
6881
7018
|
const prefix = buildMentionPrefix(props.mentions, width);
|
|
@@ -6894,13 +7031,15 @@ const TInput = defineComponent({
|
|
|
6894
7031
|
else if (line > scrollY.value + height - 1) scrollY.value = clamp$3(line - (height - 1), 0, maxTop);
|
|
6895
7032
|
}
|
|
6896
7033
|
function setCursorByCell2D(cellX, cellY, extendSelection = false, e) {
|
|
6897
|
-
const r =
|
|
6898
|
-
const
|
|
6899
|
-
const
|
|
7034
|
+
const r = contentRect$1.value;
|
|
7035
|
+
const w = Math.max(0, Math.floor(r.w));
|
|
7036
|
+
const h$1 = Math.max(0, Math.floor(r.h));
|
|
7037
|
+
if (w <= 0 || h$1 <= 0) return;
|
|
7038
|
+
const width = w;
|
|
6900
7039
|
const prefix = buildMentionPrefix(props.mentions, width);
|
|
6901
7040
|
const prefixCells = prefix.cells;
|
|
6902
|
-
const localX = clamp$3(cellX -
|
|
6903
|
-
const localY = clamp$3(cellY - r.y, 0, Math.max(0,
|
|
7041
|
+
const localX = clamp$3(cellX - r.x, 0, Math.max(0, w - 1));
|
|
7042
|
+
const localY = clamp$3(cellY - r.y, 0, Math.max(0, h$1 - 1));
|
|
6904
7043
|
const prefixVisible = scrollY.value === 0 && localY === 0 && prefixCells > 0;
|
|
6905
7044
|
if (prefixVisible && localX < prefixCells) {
|
|
6906
7045
|
for (const chip of prefix.chips) if (localX >= chip.start && localX < chip.end) {
|
|
@@ -6946,8 +7085,7 @@ const TInput = defineComponent({
|
|
|
6946
7085
|
compositionText.value = "";
|
|
6947
7086
|
pendingValue.value = nextValue;
|
|
6948
7087
|
if (wrapMode.value) {
|
|
6949
|
-
const
|
|
6950
|
-
const w = Math.max(1, contentW);
|
|
7088
|
+
const w = Math.max(1, Math.floor(contentRect$1.value.w));
|
|
6951
7089
|
const prefix = buildMentionPrefix(props.mentions, w);
|
|
6952
7090
|
const firstW = Math.max(1, w - prefix.cells);
|
|
6953
7091
|
desiredCol.value = indexToWrappedCellColFirstWidth(nextValue, c, firstW, w).col;
|
|
@@ -6966,8 +7104,7 @@ const TInput = defineComponent({
|
|
|
6966
7104
|
} else anchor.value = null;
|
|
6967
7105
|
cursor.value = clamp$3(nextCursor, 0, value.length);
|
|
6968
7106
|
if (wrapMode.value) {
|
|
6969
|
-
const
|
|
6970
|
-
const w = Math.max(1, contentW);
|
|
7107
|
+
const w = Math.max(1, Math.floor(contentRect$1.value.w));
|
|
6971
7108
|
const prefix = buildMentionPrefix(props.mentions, w);
|
|
6972
7109
|
const firstW = Math.max(1, w - prefix.cells);
|
|
6973
7110
|
desiredCol.value = indexToWrappedCellColFirstWidth(value, cursor.value, firstW, w).col;
|
|
@@ -6976,8 +7113,8 @@ const TInput = defineComponent({
|
|
|
6976
7113
|
scheduler.invalidate();
|
|
6977
7114
|
}
|
|
6978
7115
|
watch([
|
|
6979
|
-
() =>
|
|
6980
|
-
() =>
|
|
7116
|
+
() => contentRect$1.value.w,
|
|
7117
|
+
() => contentRect$1.value.h,
|
|
6981
7118
|
() => wrapMode.value
|
|
6982
7119
|
], () => {
|
|
6983
7120
|
ensureCursorVisible();
|
|
@@ -7026,14 +7163,15 @@ const TInput = defineComponent({
|
|
|
7026
7163
|
if (imeAnchor.value) imeAnchor.value = null;
|
|
7027
7164
|
return;
|
|
7028
7165
|
}
|
|
7029
|
-
const r =
|
|
7030
|
-
|
|
7166
|
+
const r = contentRect$1.value;
|
|
7167
|
+
const w = Math.max(0, Math.floor(r.w));
|
|
7168
|
+
const h$1 = Math.max(0, Math.floor(r.h));
|
|
7169
|
+
if (w <= 0 || h$1 <= 0) {
|
|
7031
7170
|
imeAnchor.value = null;
|
|
7032
7171
|
return;
|
|
7033
7172
|
}
|
|
7034
|
-
const
|
|
7035
|
-
const
|
|
7036
|
-
const height = Math.max(1, hAll);
|
|
7173
|
+
const width = w;
|
|
7174
|
+
const height = h$1;
|
|
7037
7175
|
const placeholderVisible = shouldShowPlaceholder.value;
|
|
7038
7176
|
const offX = placeholderVisible ? 0 : scrollX.value;
|
|
7039
7177
|
const offY = placeholderVisible ? 0 : scrollY.value;
|
|
@@ -7050,7 +7188,7 @@ const TInput = defineComponent({
|
|
|
7050
7188
|
const cx = clamp$3(cxRaw, 0, Math.max(0, width - 1));
|
|
7051
7189
|
const cy = clamp$3(cyRaw, 0, Math.max(0, height - 1));
|
|
7052
7190
|
imeAnchor.value = {
|
|
7053
|
-
cellX: r.x +
|
|
7191
|
+
cellX: r.x + cx,
|
|
7054
7192
|
cellY: r.y + cy
|
|
7055
7193
|
};
|
|
7056
7194
|
});
|
|
@@ -7182,6 +7320,28 @@ const TInput = defineComponent({
|
|
|
7182
7320
|
return;
|
|
7183
7321
|
}
|
|
7184
7322
|
}
|
|
7323
|
+
const base64EncodeBytes = (bytes) => {
|
|
7324
|
+
const table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
7325
|
+
let out = "";
|
|
7326
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
7327
|
+
const a = bytes[i] ?? 0;
|
|
7328
|
+
const b = bytes[i + 1] ?? 0;
|
|
7329
|
+
const c = bytes[i + 2] ?? 0;
|
|
7330
|
+
const triple = a << 16 | b << 8 | c;
|
|
7331
|
+
out += table[triple >> 18 & 63] ?? "";
|
|
7332
|
+
out += table[triple >> 12 & 63] ?? "";
|
|
7333
|
+
out += i + 1 < bytes.length ? table[triple >> 6 & 63] ?? "" : "=";
|
|
7334
|
+
out += i + 2 < bytes.length ? table[triple & 63] ?? "" : "=";
|
|
7335
|
+
}
|
|
7336
|
+
return out;
|
|
7337
|
+
};
|
|
7338
|
+
const base64EncodeText = (text) => {
|
|
7339
|
+
if (typeof TextEncoder !== "undefined") return base64EncodeBytes(new TextEncoder().encode(text));
|
|
7340
|
+
const bin = unescape(encodeURIComponent(text));
|
|
7341
|
+
const bytes = new Uint8Array(bin.length);
|
|
7342
|
+
for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
|
|
7343
|
+
return base64EncodeBytes(bytes);
|
|
7344
|
+
};
|
|
7185
7345
|
const copyText = async (text) => {
|
|
7186
7346
|
var _nav$clipboard, _proc$stdout, _proc$stdout2, _doc$body;
|
|
7187
7347
|
if (!text) return false;
|
|
@@ -7192,7 +7352,7 @@ const TInput = defineComponent({
|
|
|
7192
7352
|
} catch {}
|
|
7193
7353
|
const proc = globalThis.process;
|
|
7194
7354
|
if ((proc === null || proc === void 0 || (_proc$stdout = proc.stdout) === null || _proc$stdout === void 0 ? void 0 : _proc$stdout.write) && (proc === null || proc === void 0 || (_proc$stdout2 = proc.stdout) === null || _proc$stdout2 === void 0 ? void 0 : _proc$stdout2.isTTY)) try {
|
|
7195
|
-
const base64 =
|
|
7355
|
+
const base64 = base64EncodeText(text);
|
|
7196
7356
|
proc.stdout.write(`\u001B]52;c;${base64}\u0007`);
|
|
7197
7357
|
return true;
|
|
7198
7358
|
} catch {}
|
|
@@ -7259,8 +7419,7 @@ const TInput = defineComponent({
|
|
|
7259
7419
|
if (e.key === "ArrowUp" || e.key === "ArrowDown") {
|
|
7260
7420
|
e.preventDefault();
|
|
7261
7421
|
const wrap = wrapMode.value;
|
|
7262
|
-
const
|
|
7263
|
-
const width = Math.max(1, contentW);
|
|
7422
|
+
const width = Math.max(1, Math.floor(contentRect$1.value.w));
|
|
7264
7423
|
const prefix = buildMentionPrefix(props.mentions, width);
|
|
7265
7424
|
const firstW = Math.max(1, width - prefix.cells);
|
|
7266
7425
|
const { line, col, lines } = wrap ? indexToWrappedCellColFirstWidth(value, cursor.value, firstW, width) : indexToLineCellCol(value, cursor.value);
|
|
@@ -7478,6 +7637,7 @@ const TInput = defineComponent({
|
|
|
7478
7637
|
props.mentions,
|
|
7479
7638
|
props.placeholder,
|
|
7480
7639
|
props.placeholderWhenFocused,
|
|
7640
|
+
props.padding,
|
|
7481
7641
|
props.style,
|
|
7482
7642
|
props.autoFocus,
|
|
7483
7643
|
props.cursorBlink,
|
|
@@ -7496,8 +7656,10 @@ const TInput = defineComponent({
|
|
|
7496
7656
|
],
|
|
7497
7657
|
paint: () => {
|
|
7498
7658
|
if (!visible.value) return;
|
|
7499
|
-
const
|
|
7500
|
-
|
|
7659
|
+
const rAll = absRect.value;
|
|
7660
|
+
const wAll = Math.max(0, Math.floor(rAll.w));
|
|
7661
|
+
const hAll = Math.max(0, Math.floor(rAll.h));
|
|
7662
|
+
if (wAll <= 0 || hAll <= 0) return;
|
|
7501
7663
|
const style = props.style ?? defaultStyle.value;
|
|
7502
7664
|
const placeholderVisible = shouldShowPlaceholder.value;
|
|
7503
7665
|
const offX = placeholderVisible ? 0 : scrollX.value;
|
|
@@ -7515,14 +7677,23 @@ const TInput = defineComponent({
|
|
|
7515
7677
|
...style,
|
|
7516
7678
|
fg: "white"
|
|
7517
7679
|
} : style;
|
|
7518
|
-
const
|
|
7519
|
-
|
|
7520
|
-
|
|
7680
|
+
const blankAll = " ".repeat(wAll);
|
|
7681
|
+
for (let row = 0; row < hAll; row++) terminal.write(blankAll, {
|
|
7682
|
+
x: rAll.x,
|
|
7683
|
+
y: rAll.y + row,
|
|
7684
|
+
style: baseStyle
|
|
7685
|
+
});
|
|
7686
|
+
const r = contentRect$1.value;
|
|
7687
|
+
const w = Math.max(0, Math.floor(r.w));
|
|
7688
|
+
const h$1 = Math.max(0, Math.floor(r.h));
|
|
7689
|
+
if (w <= 0 || h$1 <= 0) return;
|
|
7690
|
+
const x0 = r.x;
|
|
7691
|
+
const width = Math.max(1, w);
|
|
7521
7692
|
const prefix = buildMentionPrefix(props.mentions, width);
|
|
7522
7693
|
const prefixCells = prefix.cells;
|
|
7523
7694
|
const firstWidth = Math.max(1, Math.max(1, width) - prefixCells);
|
|
7524
7695
|
const lines = wrap ? wrapToLinesFirstWidth(text, firstWidth, width) : computeLines(text);
|
|
7525
|
-
for (let row = 0; row <
|
|
7696
|
+
for (let row = 0; row < h$1; row++) {
|
|
7526
7697
|
const lineIndex = offY + row;
|
|
7527
7698
|
const info = lines[lineIndex];
|
|
7528
7699
|
const raw = info ? text.slice(info.start, info.end).replace(/[\r\n]/g, "") : "";
|
|
@@ -7531,12 +7702,7 @@ const TInput = defineComponent({
|
|
|
7531
7702
|
const rowTextW = hasPrefix ? firstWidth : width;
|
|
7532
7703
|
const rawVisible = wrap ? sliceByCellsWindow(raw, 0, rowTextW) : sliceByCellsWindow(raw, offX, rowTextW);
|
|
7533
7704
|
const visible$1 = padEndByCells$1(rawVisible, rowTextW);
|
|
7534
|
-
|
|
7535
|
-
x: r.x,
|
|
7536
|
-
y: r.y + row,
|
|
7537
|
-
style: baseStyle
|
|
7538
|
-
});
|
|
7539
|
-
if (contentW <= 0) continue;
|
|
7705
|
+
const y = r.y + row;
|
|
7540
7706
|
if (hasPrefix) {
|
|
7541
7707
|
const chipStyle = {
|
|
7542
7708
|
...style,
|
|
@@ -7547,18 +7713,18 @@ const TInput = defineComponent({
|
|
|
7547
7713
|
if (!chip.label) continue;
|
|
7548
7714
|
terminal.write(chip.label, {
|
|
7549
7715
|
x: x0 + chip.start,
|
|
7550
|
-
y
|
|
7716
|
+
y,
|
|
7551
7717
|
style: chipStyle
|
|
7552
7718
|
});
|
|
7553
7719
|
}
|
|
7554
7720
|
terminal.write(visible$1, {
|
|
7555
7721
|
x: x0 + rowPrefixCells,
|
|
7556
|
-
y
|
|
7722
|
+
y,
|
|
7557
7723
|
style: baseStyle
|
|
7558
7724
|
});
|
|
7559
7725
|
} else terminal.write(visible$1, {
|
|
7560
7726
|
x: x0,
|
|
7561
|
-
y
|
|
7727
|
+
y,
|
|
7562
7728
|
style: baseStyle
|
|
7563
7729
|
});
|
|
7564
7730
|
}
|
|
@@ -7566,7 +7732,7 @@ const TInput = defineComponent({
|
|
|
7566
7732
|
if (sel && !placeholderVisible) {
|
|
7567
7733
|
const bg = "blueBright";
|
|
7568
7734
|
const fg = "black";
|
|
7569
|
-
for (let row = 0; row <
|
|
7735
|
+
for (let row = 0; row < h$1; row++) {
|
|
7570
7736
|
const lineIndex = offY + row;
|
|
7571
7737
|
const info = lines[lineIndex];
|
|
7572
7738
|
if (!info) continue;
|
|
@@ -7580,14 +7746,14 @@ const TInput = defineComponent({
|
|
|
7580
7746
|
for (let i = info.start; i < info.end;) {
|
|
7581
7747
|
const ch = readCodePointAt(text, i);
|
|
7582
7748
|
const nextI = i + ch.length;
|
|
7583
|
-
const w = charCellWidth(ch);
|
|
7584
|
-
if (xCell$1 + w > rowTextW) break;
|
|
7749
|
+
const w$1 = charCellWidth(ch);
|
|
7750
|
+
if (xCell$1 + w$1 > rowTextW) break;
|
|
7585
7751
|
if (i >= sel.start && i < sel.end) terminal.put(xBase + xCell$1, y, ch, {
|
|
7586
7752
|
...style,
|
|
7587
7753
|
fg,
|
|
7588
7754
|
bg
|
|
7589
7755
|
});
|
|
7590
|
-
xCell$1 += w;
|
|
7756
|
+
xCell$1 += w$1;
|
|
7591
7757
|
i = nextI;
|
|
7592
7758
|
if (xCell$1 >= rowTextW) break;
|
|
7593
7759
|
}
|
|
@@ -7598,8 +7764,8 @@ const TInput = defineComponent({
|
|
|
7598
7764
|
for (let i = info.start; i < info.end;) {
|
|
7599
7765
|
const ch = readCodePointAt(text, i);
|
|
7600
7766
|
const nextI = i + ch.length;
|
|
7601
|
-
const w = charCellWidth(ch);
|
|
7602
|
-
const nextCell = xCell + w;
|
|
7767
|
+
const w$1 = charCellWidth(ch);
|
|
7768
|
+
const nextCell = xCell + w$1;
|
|
7603
7769
|
if (nextCell <= offX) {
|
|
7604
7770
|
xCell = nextCell;
|
|
7605
7771
|
i = nextI;
|
|
@@ -7607,7 +7773,7 @@ const TInput = defineComponent({
|
|
|
7607
7773
|
}
|
|
7608
7774
|
if (xCell >= offX + rowTextW) break;
|
|
7609
7775
|
const localX = xCell - offX;
|
|
7610
|
-
if (localX + w > rowTextW) break;
|
|
7776
|
+
if (localX + w$1 > rowTextW) break;
|
|
7611
7777
|
if (i >= sel.start && i < sel.end) terminal.put(xBase + localX, y, ch, {
|
|
7612
7778
|
...style,
|
|
7613
7779
|
fg,
|
|
@@ -7629,7 +7795,7 @@ const TInput = defineComponent({
|
|
|
7629
7795
|
const pos = wrap ? indexToWrappedCellColFirstWidth(cursorText, cursor.value, firstW, wAll$1) : indexToLineCellCol(cursorText, cursor.value);
|
|
7630
7796
|
const cx0 = (pos.line === 0 ? prefixCells : 0) + (pos.col - offX);
|
|
7631
7797
|
const cy = pos.line - offY;
|
|
7632
|
-
if (cx0 >= 0 && cx0 < width && cy >= 0 && cy <
|
|
7798
|
+
if (cx0 >= 0 && cx0 < width && cy >= 0 && cy < h$1) {
|
|
7633
7799
|
const x = x0 + cx0;
|
|
7634
7800
|
const y = r.y + cy;
|
|
7635
7801
|
const avail = Math.max(0, width - cx0);
|
|
@@ -7657,7 +7823,7 @@ const TInput = defineComponent({
|
|
|
7657
7823
|
const pos = wrap ? indexToWrappedCellColFirstWidth(cursorText, cursor.value, firstW, wAll$1) : indexToLineCellCol(cursorText, cursor.value);
|
|
7658
7824
|
const cx0 = (pos.line === 0 ? prefixCells : 0) + (pos.col - offX);
|
|
7659
7825
|
const cy = pos.line - offY;
|
|
7660
|
-
if (cx0 >= 0 && cx0 < width && cy >= 0 && cy <
|
|
7826
|
+
if (cx0 >= 0 && cx0 < width && cy >= 0 && cy < h$1) {
|
|
7661
7827
|
const y = r.y + cy;
|
|
7662
7828
|
let x = x0 + cx0;
|
|
7663
7829
|
let cell = null;
|
|
@@ -7861,7 +8027,11 @@ const TInputBox = defineComponent({
|
|
|
7861
8027
|
default: ""
|
|
7862
8028
|
},
|
|
7863
8029
|
padding: {
|
|
7864
|
-
type:
|
|
8030
|
+
type: [
|
|
8031
|
+
Number,
|
|
8032
|
+
String,
|
|
8033
|
+
Array
|
|
8034
|
+
],
|
|
7865
8035
|
default: 0
|
|
7866
8036
|
},
|
|
7867
8037
|
modelValue: {
|
|
@@ -7902,8 +8072,9 @@ const TInputBox = defineComponent({
|
|
|
7902
8072
|
"blur"
|
|
7903
8073
|
],
|
|
7904
8074
|
setup(props, { emit }) {
|
|
7905
|
-
const
|
|
7906
|
-
const
|
|
8075
|
+
const pad = computed(() => normalizePadding(props.padding));
|
|
8076
|
+
const innerW = computed(() => Math.max(0, Math.floor(props.w) - 2 - pad.value.left - pad.value.right));
|
|
8077
|
+
const innerH = computed(() => Math.max(1, Math.floor(props.h) - 2 - pad.value.top - pad.value.bottom));
|
|
7907
8078
|
return () => h(TBox, {
|
|
7908
8079
|
x: props.x,
|
|
7909
8080
|
y: props.y,
|
|
@@ -7964,6 +8135,14 @@ const TList = defineComponent({
|
|
|
7964
8135
|
type: Number,
|
|
7965
8136
|
default: 0
|
|
7966
8137
|
},
|
|
8138
|
+
padding: {
|
|
8139
|
+
type: [
|
|
8140
|
+
Number,
|
|
8141
|
+
String,
|
|
8142
|
+
Array
|
|
8143
|
+
],
|
|
8144
|
+
default: 0
|
|
8145
|
+
},
|
|
7967
8146
|
items: {
|
|
7968
8147
|
type: Array,
|
|
7969
8148
|
required: true
|
|
@@ -8022,8 +8201,9 @@ const TList = defineComponent({
|
|
|
8022
8201
|
watchEffect(() => {
|
|
8023
8202
|
active.value = clamp$2(props.modelValue, 0, Math.max(0, props.items.length - 1));
|
|
8024
8203
|
});
|
|
8204
|
+
const contentRect$1 = computed(() => insetRect(absRect.value, props.padding));
|
|
8025
8205
|
function ensureActiveVisible() {
|
|
8026
|
-
const h$1 = Math.max(0,
|
|
8206
|
+
const h$1 = Math.max(0, Math.floor(contentRect$1.value.h));
|
|
8027
8207
|
if (h$1 <= 0) return;
|
|
8028
8208
|
const maxTop = Math.max(0, props.items.length - h$1);
|
|
8029
8209
|
scrollTop.value = clamp$2(scrollTop.value, 0, maxTop);
|
|
@@ -8033,7 +8213,7 @@ const TList = defineComponent({
|
|
|
8033
8213
|
watch([
|
|
8034
8214
|
() => active.value,
|
|
8035
8215
|
() => props.items.length,
|
|
8036
|
-
() =>
|
|
8216
|
+
() => contentRect$1.value.h
|
|
8037
8217
|
], () => {
|
|
8038
8218
|
ensureActiveVisible();
|
|
8039
8219
|
}, { immediate: true });
|
|
@@ -8118,7 +8298,8 @@ const TList = defineComponent({
|
|
|
8118
8298
|
focusable: true,
|
|
8119
8299
|
handlers: {
|
|
8120
8300
|
click: (e) => {
|
|
8121
|
-
const r =
|
|
8301
|
+
const r = contentRect$1.value;
|
|
8302
|
+
if (e.cellY < r.y || e.cellY >= r.y + r.h) return;
|
|
8122
8303
|
const idx = scrollTop.value + (e.cellY - r.y);
|
|
8123
8304
|
if (idx >= 0 && idx < props.items.length) {
|
|
8124
8305
|
active.value = idx;
|
|
@@ -8127,7 +8308,8 @@ const TList = defineComponent({
|
|
|
8127
8308
|
} else emit("close");
|
|
8128
8309
|
},
|
|
8129
8310
|
dblclick: (e) => {
|
|
8130
|
-
const r =
|
|
8311
|
+
const r = contentRect$1.value;
|
|
8312
|
+
if (e.cellY < r.y || e.cellY >= r.y + r.h) return;
|
|
8131
8313
|
const idx = scrollTop.value + (e.cellY - r.y);
|
|
8132
8314
|
if (idx >= 0 && idx < props.items.length) commit(idx);
|
|
8133
8315
|
},
|
|
@@ -8135,7 +8317,8 @@ const TList = defineComponent({
|
|
|
8135
8317
|
const delta = e.deltaY ?? 0;
|
|
8136
8318
|
if (!delta) return;
|
|
8137
8319
|
const dir = delta > 0 ? 1 : -1;
|
|
8138
|
-
const
|
|
8320
|
+
const h$1 = Math.max(0, Math.floor(contentRect$1.value.h));
|
|
8321
|
+
const maxTop = Math.max(0, props.items.length - h$1);
|
|
8139
8322
|
const next = clamp$2(scrollTop.value + dir, 0, maxTop);
|
|
8140
8323
|
if (next !== scrollTop.value) {
|
|
8141
8324
|
scrollTop.value = next;
|
|
@@ -8184,9 +8367,17 @@ const TList = defineComponent({
|
|
|
8184
8367
|
],
|
|
8185
8368
|
paint: () => {
|
|
8186
8369
|
if (!visible.value) return;
|
|
8187
|
-
const
|
|
8188
|
-
if (
|
|
8370
|
+
const rAll = absRect.value;
|
|
8371
|
+
if (rAll.w <= 0 || rAll.h <= 0) return;
|
|
8189
8372
|
const base = props.style ?? defaultStyle.value;
|
|
8373
|
+
const r = contentRect$1.value;
|
|
8374
|
+
const blankAll = " ".repeat(rAll.w);
|
|
8375
|
+
for (let i = 0; i < rAll.h; i++) terminal.write(blankAll, {
|
|
8376
|
+
x: rAll.x,
|
|
8377
|
+
y: rAll.y + i,
|
|
8378
|
+
style: base
|
|
8379
|
+
});
|
|
8380
|
+
if (r.w <= 0 || r.h <= 0) return;
|
|
8190
8381
|
const top = clamp$2(scrollTop.value, 0, Math.max(0, props.items.length - r.h));
|
|
8191
8382
|
for (let i = 0; i < r.h; i++) {
|
|
8192
8383
|
const idx = top + i;
|
|
@@ -8247,6 +8438,14 @@ const TPathPicker = defineComponent({
|
|
|
8247
8438
|
type: Number,
|
|
8248
8439
|
default: 0
|
|
8249
8440
|
},
|
|
8441
|
+
padding: {
|
|
8442
|
+
type: [
|
|
8443
|
+
Number,
|
|
8444
|
+
String,
|
|
8445
|
+
Array
|
|
8446
|
+
],
|
|
8447
|
+
default: 0
|
|
8448
|
+
},
|
|
8250
8449
|
workspace: {
|
|
8251
8450
|
type: String,
|
|
8252
8451
|
required: true
|
|
@@ -8304,13 +8503,12 @@ const TPathPicker = defineComponent({
|
|
|
8304
8503
|
const scrollTop = ref(0);
|
|
8305
8504
|
const error = ref(null);
|
|
8306
8505
|
const inputH = 1;
|
|
8307
|
-
const
|
|
8308
|
-
const absListRect = computed(() => {
|
|
8506
|
+
const absRect = computed(() => {
|
|
8309
8507
|
const raw = {
|
|
8310
8508
|
x: props.x,
|
|
8311
|
-
y: props.y
|
|
8509
|
+
y: props.y,
|
|
8312
8510
|
w: props.w,
|
|
8313
|
-
h:
|
|
8511
|
+
h: props.h
|
|
8314
8512
|
};
|
|
8315
8513
|
const translated = translateRect(raw, layout.originX, layout.originY);
|
|
8316
8514
|
if (!layout.clipRect) return translated;
|
|
@@ -8321,6 +8519,49 @@ const TPathPicker = defineComponent({
|
|
|
8321
8519
|
h: 0
|
|
8322
8520
|
};
|
|
8323
8521
|
});
|
|
8522
|
+
const contentRect$1 = computed(() => insetRect(absRect.value, props.padding));
|
|
8523
|
+
const listH = computed(() => Math.max(0, Math.floor(contentRect$1.value.h) - inputH));
|
|
8524
|
+
const absListRect = computed(() => {
|
|
8525
|
+
const c = contentRect$1.value;
|
|
8526
|
+
const listRaw = {
|
|
8527
|
+
x: c.x,
|
|
8528
|
+
y: c.y + inputH,
|
|
8529
|
+
w: c.w,
|
|
8530
|
+
h: listH.value
|
|
8531
|
+
};
|
|
8532
|
+
return intersectRect(listRaw, absRect.value) ?? {
|
|
8533
|
+
x: 0,
|
|
8534
|
+
y: 0,
|
|
8535
|
+
w: 0,
|
|
8536
|
+
h: 0
|
|
8537
|
+
};
|
|
8538
|
+
});
|
|
8539
|
+
useRenderNode(() => ({
|
|
8540
|
+
zIndex: props.zIndex - 1,
|
|
8541
|
+
rect: absRect.value,
|
|
8542
|
+
deps: [
|
|
8543
|
+
visible.value,
|
|
8544
|
+
absRect.value,
|
|
8545
|
+
props.style,
|
|
8546
|
+
defaultStyle.value
|
|
8547
|
+
],
|
|
8548
|
+
paint: (dirtyRows) => {
|
|
8549
|
+
if (!visible.value) return;
|
|
8550
|
+
const r = absRect.value;
|
|
8551
|
+
if (r.w <= 0 || r.h <= 0) return;
|
|
8552
|
+
const base = props.style ?? defaultStyle.value;
|
|
8553
|
+
if (!dirtyRows) {
|
|
8554
|
+
terminal.fill(r.x, r.y, r.w, r.h, " ", base);
|
|
8555
|
+
return;
|
|
8556
|
+
}
|
|
8557
|
+
const y0 = Math.floor(r.y);
|
|
8558
|
+
const y1 = y0 + Math.max(0, Math.floor(r.h));
|
|
8559
|
+
for (const y of dirtyRows) {
|
|
8560
|
+
if (y < y0 || y >= y1) continue;
|
|
8561
|
+
terminal.fill(r.x, y, r.w, 1, " ", base);
|
|
8562
|
+
}
|
|
8563
|
+
}
|
|
8564
|
+
}));
|
|
8324
8565
|
function ensureActiveVisible() {
|
|
8325
8566
|
const h$1 = Math.max(0, listH.value);
|
|
8326
8567
|
if (h$1 <= 0) {
|
|
@@ -8538,7 +8779,7 @@ const TPathPicker = defineComponent({
|
|
|
8538
8779
|
deps: [
|
|
8539
8780
|
visible.value,
|
|
8540
8781
|
absListRect.value,
|
|
8541
|
-
|
|
8782
|
+
contentRect$1.value.w,
|
|
8542
8783
|
listH.value,
|
|
8543
8784
|
props.style,
|
|
8544
8785
|
defaultStyle.value,
|
|
@@ -8582,9 +8823,9 @@ const TPathPicker = defineComponent({
|
|
|
8582
8823
|
}
|
|
8583
8824
|
}));
|
|
8584
8825
|
return () => h("span", rootProps, [h(TInput, {
|
|
8585
|
-
"x":
|
|
8586
|
-
"y":
|
|
8587
|
-
"w":
|
|
8826
|
+
"x": contentRect$1.value.x,
|
|
8827
|
+
"y": contentRect$1.value.y,
|
|
8828
|
+
"w": contentRect$1.value.w,
|
|
8588
8829
|
"h": inputH,
|
|
8589
8830
|
"zIndex": props.zIndex,
|
|
8590
8831
|
"modelValue": props.modelValue,
|
|
@@ -8634,14 +8875,30 @@ const TSelect = defineComponent({
|
|
|
8634
8875
|
type: Number,
|
|
8635
8876
|
default: 0
|
|
8636
8877
|
},
|
|
8878
|
+
padding: {
|
|
8879
|
+
type: [
|
|
8880
|
+
Number,
|
|
8881
|
+
String,
|
|
8882
|
+
Array
|
|
8883
|
+
],
|
|
8884
|
+
default: 0
|
|
8885
|
+
},
|
|
8637
8886
|
options: {
|
|
8638
8887
|
type: Array,
|
|
8639
8888
|
required: true
|
|
8640
8889
|
},
|
|
8641
8890
|
modelValue: {
|
|
8642
|
-
type: Number,
|
|
8891
|
+
type: [Number, Array],
|
|
8643
8892
|
default: 0
|
|
8644
8893
|
},
|
|
8894
|
+
multiple: {
|
|
8895
|
+
type: Boolean,
|
|
8896
|
+
default: false
|
|
8897
|
+
},
|
|
8898
|
+
multipleEmit: {
|
|
8899
|
+
type: String,
|
|
8900
|
+
default: "value"
|
|
8901
|
+
},
|
|
8645
8902
|
style: {
|
|
8646
8903
|
type: Object,
|
|
8647
8904
|
default: void 0
|
|
@@ -8662,6 +8919,7 @@ const TSelect = defineComponent({
|
|
|
8662
8919
|
emits: [
|
|
8663
8920
|
"update:modelValue",
|
|
8664
8921
|
"change",
|
|
8922
|
+
"confirm",
|
|
8665
8923
|
"close",
|
|
8666
8924
|
"focus",
|
|
8667
8925
|
"blur",
|
|
@@ -8674,7 +8932,18 @@ const TSelect = defineComponent({
|
|
|
8674
8932
|
const parentEventZ = inject(EventZIndexContextKey, computed(() => 0));
|
|
8675
8933
|
const eventZ = computed(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0));
|
|
8676
8934
|
const focused = ref(false);
|
|
8677
|
-
const
|
|
8935
|
+
const initialActive = (() => {
|
|
8936
|
+
const max = Math.max(0, props.options.length - 1);
|
|
8937
|
+
if (!props.multiple) {
|
|
8938
|
+
const idx = typeof props.modelValue === "number" ? props.modelValue : 0;
|
|
8939
|
+
return clamp(idx, 0, max);
|
|
8940
|
+
}
|
|
8941
|
+
const selected = Array.isArray(props.modelValue) ? props.modelValue : [];
|
|
8942
|
+
const first = selected[0] ?? 0;
|
|
8943
|
+
return clamp(first, 0, max);
|
|
8944
|
+
})();
|
|
8945
|
+
const active = ref(initialActive);
|
|
8946
|
+
const scrollTopLine = ref(0);
|
|
8678
8947
|
const absRect = computed(() => {
|
|
8679
8948
|
const raw = {
|
|
8680
8949
|
x: props.x,
|
|
@@ -8691,39 +8960,201 @@ const TSelect = defineComponent({
|
|
|
8691
8960
|
h: 0
|
|
8692
8961
|
};
|
|
8693
8962
|
});
|
|
8963
|
+
const contentRect$1 = computed(() => insetRect(absRect.value, props.padding));
|
|
8694
8964
|
watchEffect(() => {
|
|
8695
|
-
|
|
8965
|
+
const max = Math.max(0, props.options.length - 1);
|
|
8966
|
+
if (!props.multiple) {
|
|
8967
|
+
const idx = typeof props.modelValue === "number" ? props.modelValue : 0;
|
|
8968
|
+
active.value = clamp(idx, 0, max);
|
|
8969
|
+
return;
|
|
8970
|
+
}
|
|
8971
|
+
active.value = clamp(active.value, 0, max);
|
|
8696
8972
|
});
|
|
8973
|
+
function getPrefixCells() {
|
|
8974
|
+
return props.multiple ? textCellWidth$1("[x] ") : 0;
|
|
8975
|
+
}
|
|
8697
8976
|
function getOptionLabel(opt) {
|
|
8698
8977
|
return typeof opt === "string" ? opt : opt.label;
|
|
8699
8978
|
}
|
|
8700
8979
|
function getOptionDetail(opt) {
|
|
8701
8980
|
return typeof opt === "string" ? void 0 : opt.detail;
|
|
8702
8981
|
}
|
|
8703
|
-
function
|
|
8982
|
+
function commitSingle(index) {
|
|
8704
8983
|
const next = clamp(index, 0, Math.max(0, props.options.length - 1));
|
|
8705
8984
|
active.value = next;
|
|
8706
8985
|
emit("update:modelValue", next);
|
|
8707
8986
|
const opt = props.options[next];
|
|
8708
8987
|
emit("change", opt ? getOptionLabel(opt) : null);
|
|
8709
8988
|
}
|
|
8989
|
+
function getSelectedIndices() {
|
|
8990
|
+
if (!props.multiple) return [];
|
|
8991
|
+
const max = Math.max(0, props.options.length - 1);
|
|
8992
|
+
const raw = Array.isArray(props.modelValue) ? props.modelValue : [];
|
|
8993
|
+
const set = new Set();
|
|
8994
|
+
for (const v of raw) {
|
|
8995
|
+
if (typeof v !== "number" || !Number.isFinite(v)) continue;
|
|
8996
|
+
set.add(clamp(Math.trunc(v), 0, max));
|
|
8997
|
+
}
|
|
8998
|
+
return [...set].sort((a, b) => a - b);
|
|
8999
|
+
}
|
|
9000
|
+
function makeMultiplePayload(indices) {
|
|
9001
|
+
const values = indices.map((i) => props.options[i]).filter(Boolean).map((opt) => getOptionLabel(opt));
|
|
9002
|
+
return {
|
|
9003
|
+
indices,
|
|
9004
|
+
values
|
|
9005
|
+
};
|
|
9006
|
+
}
|
|
9007
|
+
function emitMultiple(name, indices) {
|
|
9008
|
+
const payload = makeMultiplePayload(indices);
|
|
9009
|
+
if (props.multipleEmit === "index") {
|
|
9010
|
+
emit(name, payload.indices);
|
|
9011
|
+
return;
|
|
9012
|
+
}
|
|
9013
|
+
if (props.multipleEmit === "both") {
|
|
9014
|
+
emit(name, payload);
|
|
9015
|
+
return;
|
|
9016
|
+
}
|
|
9017
|
+
emit(name, payload.values);
|
|
9018
|
+
}
|
|
9019
|
+
function toggleMultiple(index) {
|
|
9020
|
+
const nextIndex = clamp(index, 0, Math.max(0, props.options.length - 1));
|
|
9021
|
+
active.value = nextIndex;
|
|
9022
|
+
const set = new Set(getSelectedIndices());
|
|
9023
|
+
if (set.has(nextIndex)) set.delete(nextIndex);
|
|
9024
|
+
else set.add(nextIndex);
|
|
9025
|
+
const indices = [...set].sort((a, b) => a - b);
|
|
9026
|
+
emit("update:modelValue", indices);
|
|
9027
|
+
emitMultiple("change", indices);
|
|
9028
|
+
}
|
|
9029
|
+
function confirmMultiple() {
|
|
9030
|
+
const indices = getSelectedIndices();
|
|
9031
|
+
emitMultiple("confirm", indices);
|
|
9032
|
+
}
|
|
9033
|
+
function commit(index) {
|
|
9034
|
+
if (props.multiple) toggleMultiple(index);
|
|
9035
|
+
else commitSingle(index);
|
|
9036
|
+
}
|
|
9037
|
+
function computeColumnLayout(totalW, hasDetail, prefixCells) {
|
|
9038
|
+
totalW = Math.max(0, Math.floor(totalW));
|
|
9039
|
+
if (!hasDetail || totalW <= 0) return {
|
|
9040
|
+
labelW: totalW,
|
|
9041
|
+
gapW: 0,
|
|
9042
|
+
detailW: 0
|
|
9043
|
+
};
|
|
9044
|
+
const gapW = totalW >= 12 ? 2 : 1;
|
|
9045
|
+
const minLabelText = 6;
|
|
9046
|
+
const minLabelW = Math.min(totalW, prefixCells + minLabelText);
|
|
9047
|
+
const minDetailW = Math.min(12, Math.max(6, Math.floor(totalW / 4)));
|
|
9048
|
+
let detailW = clamp(Math.floor(totalW * .35), minDetailW, Math.max(0, totalW - gapW - minLabelW));
|
|
9049
|
+
let labelW = Math.max(0, totalW - gapW - detailW);
|
|
9050
|
+
if (labelW < minLabelW) {
|
|
9051
|
+
detailW = Math.max(0, totalW - gapW - minLabelW);
|
|
9052
|
+
labelW = Math.max(0, totalW - gapW - detailW);
|
|
9053
|
+
}
|
|
9054
|
+
if (detailW <= 0) return {
|
|
9055
|
+
labelW: totalW,
|
|
9056
|
+
gapW: 0,
|
|
9057
|
+
detailW: 0
|
|
9058
|
+
};
|
|
9059
|
+
return {
|
|
9060
|
+
labelW,
|
|
9061
|
+
gapW,
|
|
9062
|
+
detailW
|
|
9063
|
+
};
|
|
9064
|
+
}
|
|
9065
|
+
function safeWrap(text, width) {
|
|
9066
|
+
width = Math.max(0, Math.floor(width));
|
|
9067
|
+
if (width <= 0) return [""];
|
|
9068
|
+
return wrapByCells(text, width).map((l) => sliceByCells(l, width));
|
|
9069
|
+
}
|
|
9070
|
+
const optionLayouts = computed(() => {
|
|
9071
|
+
const r = contentRect$1.value;
|
|
9072
|
+
const w = Math.max(0, Math.floor(r.w));
|
|
9073
|
+
const prefixCells = getPrefixCells();
|
|
9074
|
+
const layouts = [];
|
|
9075
|
+
const flat = [];
|
|
9076
|
+
const starts = Array.from({ length: props.options.length }, () => 0);
|
|
9077
|
+
let line = 0;
|
|
9078
|
+
for (let i = 0; i < props.options.length; i++) {
|
|
9079
|
+
const opt = props.options[i];
|
|
9080
|
+
const label = sanitizeInlineText(getOptionLabel(opt));
|
|
9081
|
+
const detail = getOptionDetail(opt);
|
|
9082
|
+
const safeDetail = detail ? sanitizeInlineText(detail) : "";
|
|
9083
|
+
const cols = computeColumnLayout(w, Boolean(safeDetail), prefixCells);
|
|
9084
|
+
const labelTextW = Math.max(0, cols.labelW - prefixCells);
|
|
9085
|
+
const labelLines = safeWrap(label, labelTextW);
|
|
9086
|
+
const detailLines = cols.detailW > 0 && safeDetail ? safeWrap(safeDetail, cols.detailW) : [];
|
|
9087
|
+
const height = Math.max(1, labelLines.length, detailLines.length || 0);
|
|
9088
|
+
layouts.push({
|
|
9089
|
+
labelLines,
|
|
9090
|
+
detailLines,
|
|
9091
|
+
height,
|
|
9092
|
+
labelW: cols.labelW,
|
|
9093
|
+
gapW: cols.gapW,
|
|
9094
|
+
detailW: cols.detailW
|
|
9095
|
+
});
|
|
9096
|
+
starts[i] = line;
|
|
9097
|
+
for (let j = 0; j < height; j++) flat.push({
|
|
9098
|
+
optionIndex: i,
|
|
9099
|
+
subLine: j
|
|
9100
|
+
});
|
|
9101
|
+
line += height;
|
|
9102
|
+
}
|
|
9103
|
+
return {
|
|
9104
|
+
layouts,
|
|
9105
|
+
flat,
|
|
9106
|
+
starts,
|
|
9107
|
+
totalLines: line,
|
|
9108
|
+
contentW: w,
|
|
9109
|
+
prefixCells
|
|
9110
|
+
};
|
|
9111
|
+
});
|
|
9112
|
+
function ensureActiveVisible() {
|
|
9113
|
+
var _layouts$idx;
|
|
9114
|
+
const viewH = Math.max(0, Math.floor(contentRect$1.value.h));
|
|
9115
|
+
const { layouts, starts, totalLines } = optionLayouts.value;
|
|
9116
|
+
if (viewH <= 0 || totalLines <= 0) {
|
|
9117
|
+
scrollTopLine.value = 0;
|
|
9118
|
+
return;
|
|
9119
|
+
}
|
|
9120
|
+
const maxTop = Math.max(0, totalLines - viewH);
|
|
9121
|
+
scrollTopLine.value = clamp(scrollTopLine.value, 0, maxTop);
|
|
9122
|
+
const idx = clamp(active.value, 0, Math.max(0, layouts.length - 1));
|
|
9123
|
+
const start = starts[idx] ?? 0;
|
|
9124
|
+
const height = ((_layouts$idx = layouts[idx]) === null || _layouts$idx === void 0 ? void 0 : _layouts$idx.height) ?? 1;
|
|
9125
|
+
const end = start + height - 1;
|
|
9126
|
+
if (start < scrollTopLine.value) scrollTopLine.value = clamp(start, 0, maxTop);
|
|
9127
|
+
else if (end >= scrollTopLine.value + viewH) scrollTopLine.value = clamp(end - (viewH - 1), 0, maxTop);
|
|
9128
|
+
}
|
|
8710
9129
|
function onKeydown(e) {
|
|
8711
9130
|
emit("keydown", e);
|
|
8712
9131
|
if (e.key === "ArrowUp") {
|
|
8713
9132
|
e.preventDefault();
|
|
8714
9133
|
active.value = clamp(active.value - 1, 0, Math.max(0, props.options.length - 1));
|
|
8715
|
-
emit("update:modelValue", active.value);
|
|
9134
|
+
if (!props.multiple) emit("update:modelValue", active.value);
|
|
9135
|
+
ensureActiveVisible();
|
|
8716
9136
|
scheduler.invalidate();
|
|
8717
9137
|
return;
|
|
8718
9138
|
}
|
|
8719
9139
|
if (e.key === "ArrowDown") {
|
|
8720
9140
|
e.preventDefault();
|
|
8721
9141
|
active.value = clamp(active.value + 1, 0, Math.max(0, props.options.length - 1));
|
|
8722
|
-
emit("update:modelValue", active.value);
|
|
9142
|
+
if (!props.multiple) emit("update:modelValue", active.value);
|
|
9143
|
+
ensureActiveVisible();
|
|
8723
9144
|
scheduler.invalidate();
|
|
8724
9145
|
return;
|
|
8725
9146
|
}
|
|
9147
|
+
if (props.multiple && (e.code === "Space" || e.key === " " || e.key === "Spacebar")) {
|
|
9148
|
+
e.preventDefault();
|
|
9149
|
+
toggleMultiple(active.value);
|
|
9150
|
+
return;
|
|
9151
|
+
}
|
|
8726
9152
|
if (e.key === "Enter") {
|
|
9153
|
+
if (props.multiple) {
|
|
9154
|
+
e.preventDefault();
|
|
9155
|
+
confirmMultiple();
|
|
9156
|
+
return;
|
|
9157
|
+
}
|
|
8727
9158
|
commit(active.value);
|
|
8728
9159
|
return;
|
|
8729
9160
|
}
|
|
@@ -8739,11 +9170,31 @@ const TSelect = defineComponent({
|
|
|
8739
9170
|
focusable: true,
|
|
8740
9171
|
handlers: {
|
|
8741
9172
|
click: (e) => {
|
|
8742
|
-
const r =
|
|
8743
|
-
|
|
8744
|
-
|
|
9173
|
+
const r = contentRect$1.value;
|
|
9174
|
+
if (e.cellY < r.y || e.cellY >= r.y + r.h) {
|
|
9175
|
+
emit("close");
|
|
9176
|
+
return;
|
|
9177
|
+
}
|
|
9178
|
+
const localRow = e.cellY - r.y;
|
|
9179
|
+
const { flat } = optionLayouts.value;
|
|
9180
|
+
const line = flat[scrollTopLine.value + localRow];
|
|
9181
|
+
if (line) commit(line.optionIndex);
|
|
8745
9182
|
else emit("close");
|
|
8746
9183
|
},
|
|
9184
|
+
wheel: (e) => {
|
|
9185
|
+
const delta = e.deltaY ?? 0;
|
|
9186
|
+
if (!delta) return;
|
|
9187
|
+
const dir = delta > 0 ? 1 : -1;
|
|
9188
|
+
const r = contentRect$1.value;
|
|
9189
|
+
const viewH = Math.max(0, Math.floor(r.h));
|
|
9190
|
+
const { totalLines } = optionLayouts.value;
|
|
9191
|
+
const maxTop = Math.max(0, totalLines - viewH);
|
|
9192
|
+
const next = clamp(scrollTopLine.value + dir, 0, maxTop);
|
|
9193
|
+
if (next !== scrollTopLine.value) {
|
|
9194
|
+
scrollTopLine.value = next;
|
|
9195
|
+
scheduler.invalidate();
|
|
9196
|
+
}
|
|
9197
|
+
},
|
|
8747
9198
|
focus: () => {
|
|
8748
9199
|
focused.value = true;
|
|
8749
9200
|
emit("focus");
|
|
@@ -8758,6 +9209,10 @@ const TSelect = defineComponent({
|
|
|
8758
9209
|
keydown: onKeydown
|
|
8759
9210
|
}
|
|
8760
9211
|
}));
|
|
9212
|
+
watchEffect(() => {
|
|
9213
|
+
optionLayouts.value;
|
|
9214
|
+
ensureActiveVisible();
|
|
9215
|
+
});
|
|
8761
9216
|
watchEffect(() => {
|
|
8762
9217
|
if (!props.autoFocus) return;
|
|
8763
9218
|
if (!visible.value) return;
|
|
@@ -8775,20 +9230,25 @@ const TSelect = defineComponent({
|
|
|
8775
9230
|
absRect.value,
|
|
8776
9231
|
props.w,
|
|
8777
9232
|
props.h,
|
|
9233
|
+
props.padding,
|
|
8778
9234
|
props.options,
|
|
8779
9235
|
props.modelValue,
|
|
9236
|
+
props.multiple,
|
|
9237
|
+
props.multipleEmit,
|
|
8780
9238
|
props.style,
|
|
8781
9239
|
props.highlightStyle,
|
|
8782
9240
|
focused.value,
|
|
8783
9241
|
active.value,
|
|
9242
|
+
scrollTopLine.value,
|
|
9243
|
+
optionLayouts.value,
|
|
8784
9244
|
defaultStyle.value
|
|
8785
9245
|
],
|
|
8786
9246
|
paint: () => {
|
|
8787
9247
|
if (!visible.value) return;
|
|
8788
|
-
const
|
|
8789
|
-
if (
|
|
9248
|
+
const rAll = absRect.value;
|
|
9249
|
+
if (rAll.w <= 0 || rAll.h <= 0) return;
|
|
8790
9250
|
const base = props.style ?? defaultStyle.value;
|
|
8791
|
-
const
|
|
9251
|
+
const highlightBase = props.highlightStyle ?? {
|
|
8792
9252
|
...base,
|
|
8793
9253
|
bg: "yellow",
|
|
8794
9254
|
fg: "black"
|
|
@@ -8797,57 +9257,79 @@ const TSelect = defineComponent({
|
|
|
8797
9257
|
...base,
|
|
8798
9258
|
dim: true
|
|
8799
9259
|
};
|
|
8800
|
-
const
|
|
8801
|
-
...
|
|
9260
|
+
const highlightDetailStyle = {
|
|
9261
|
+
...highlightBase,
|
|
8802
9262
|
dim: true
|
|
8803
9263
|
};
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
9264
|
+
const blankAll = " ".repeat(rAll.w);
|
|
9265
|
+
for (let i = 0; i < rAll.h; i++) terminal.write(blankAll, {
|
|
9266
|
+
x: rAll.x,
|
|
9267
|
+
y: rAll.y + i,
|
|
9268
|
+
style: base
|
|
9269
|
+
});
|
|
9270
|
+
const r = contentRect$1.value;
|
|
9271
|
+
if (r.w <= 0 || r.h <= 0) return;
|
|
9272
|
+
const { layouts, flat, totalLines, prefixCells } = optionLayouts.value;
|
|
9273
|
+
const selectedSet = props.multiple ? new Set(getSelectedIndices()) : null;
|
|
9274
|
+
const top = clamp(scrollTopLine.value, 0, Math.max(0, totalLines - r.h));
|
|
9275
|
+
const prefixSpaces = props.multiple ? " ".repeat(prefixCells) : "";
|
|
9276
|
+
const blank = " ".repeat(r.w);
|
|
9277
|
+
for (let row = 0; row < r.h; row++) {
|
|
9278
|
+
const y = r.y + row;
|
|
9279
|
+
const lineIdx = top + row;
|
|
9280
|
+
const line = flat[lineIdx];
|
|
9281
|
+
if (!line) {
|
|
9282
|
+
terminal.write(blank, {
|
|
8808
9283
|
x: r.x,
|
|
8809
|
-
y
|
|
9284
|
+
y,
|
|
8810
9285
|
style: base
|
|
8811
9286
|
});
|
|
8812
9287
|
continue;
|
|
8813
9288
|
}
|
|
8814
|
-
const
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
const rawDetail = detail ? sanitizeInlineText(detail) : "";
|
|
8818
|
-
const labelCells = textCellWidth$1(label);
|
|
8819
|
-
const minGap = 2;
|
|
8820
|
-
const availableForDetail = r.w - labelCells - minGap;
|
|
8821
|
-
if (rawDetail && availableForDetail >= 4) {
|
|
8822
|
-
const labelStyle = isSelected ? selectedBase : base;
|
|
8823
|
-
terminal.write(label, {
|
|
9289
|
+
const opt = props.options[line.optionIndex];
|
|
9290
|
+
if (!opt) {
|
|
9291
|
+
terminal.write(blank, {
|
|
8824
9292
|
x: r.x,
|
|
8825
|
-
y
|
|
8826
|
-
style:
|
|
8827
|
-
});
|
|
8828
|
-
const detailCells = textCellWidth$1(rawDetail);
|
|
8829
|
-
const actualDetailWidth = Math.min(detailCells, availableForDetail);
|
|
8830
|
-
const gapWidth = r.w - labelCells - actualDetailWidth;
|
|
8831
|
-
const gapStyle = isSelected ? selectedBase : base;
|
|
8832
|
-
terminal.write(" ".repeat(gapWidth), {
|
|
8833
|
-
x: r.x + labelCells,
|
|
8834
|
-
y: r.y + i,
|
|
8835
|
-
style: gapStyle
|
|
8836
|
-
});
|
|
8837
|
-
const detailText = sliceByCells(rawDetail, availableForDetail);
|
|
8838
|
-
const dStyle = isSelected ? selectedDetailStyle : detailDimStyle;
|
|
8839
|
-
terminal.write(detailText, {
|
|
8840
|
-
x: r.x + labelCells + gapWidth,
|
|
8841
|
-
y: r.y + i,
|
|
8842
|
-
style: dStyle
|
|
9293
|
+
y,
|
|
9294
|
+
style: base
|
|
8843
9295
|
});
|
|
8844
|
-
|
|
8845
|
-
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8849
|
-
|
|
8850
|
-
|
|
9296
|
+
continue;
|
|
9297
|
+
}
|
|
9298
|
+
const isActiveOpt = line.optionIndex === active.value;
|
|
9299
|
+
const isHighlighted = props.multiple ? focused.value && isActiveOpt : isActiveOpt;
|
|
9300
|
+
const rowStyle = isHighlighted ? highlightBase : base;
|
|
9301
|
+
const detailStyle = isHighlighted ? highlightDetailStyle : detailDimStyle;
|
|
9302
|
+
terminal.write(blank, {
|
|
9303
|
+
x: r.x,
|
|
9304
|
+
y,
|
|
9305
|
+
style: rowStyle
|
|
9306
|
+
});
|
|
9307
|
+
const layout$1 = layouts[line.optionIndex];
|
|
9308
|
+
const labelLine = (layout$1 === null || layout$1 === void 0 ? void 0 : layout$1.labelLines[line.subLine]) ?? "";
|
|
9309
|
+
const prevVisibleLine = row > 0 ? flat[lineIdx - 1] : void 0;
|
|
9310
|
+
const isFirstVisibleLineOfOption = !prevVisibleLine || prevVisibleLine.optionIndex !== line.optionIndex;
|
|
9311
|
+
const detailLine = (() => {
|
|
9312
|
+
if (!layout$1 || layout$1.detailW <= 0 || layout$1.detailLines.length === 0) return "";
|
|
9313
|
+
if (layout$1.detailLines.length === 1) return isFirstVisibleLineOfOption ? layout$1.detailLines[0] ?? "" : "";
|
|
9314
|
+
return layout$1.detailLines[line.subLine] ?? "";
|
|
9315
|
+
})();
|
|
9316
|
+
const isChecked = props.multiple ? selectedSet.has(line.optionIndex) : isActiveOpt;
|
|
9317
|
+
const prefix = props.multiple ? isChecked ? "[x] " : "[ ] " : "";
|
|
9318
|
+
const prefixPad = props.multiple ? isFirstVisibleLineOfOption ? prefix : prefixSpaces : "";
|
|
9319
|
+
const labelTextW = Math.max(0, ((layout$1 === null || layout$1 === void 0 ? void 0 : layout$1.labelW) ?? r.w) - prefixCells);
|
|
9320
|
+
const labelText = labelTextW > 0 ? sliceByCells(labelLine, labelTextW) : "";
|
|
9321
|
+
const outLabel = padEndByCells(sliceByCells(`${prefixPad}${labelText}`, (layout$1 === null || layout$1 === void 0 ? void 0 : layout$1.labelW) ?? r.w), (layout$1 === null || layout$1 === void 0 ? void 0 : layout$1.labelW) ?? r.w);
|
|
9322
|
+
terminal.write(outLabel, {
|
|
9323
|
+
x: r.x,
|
|
9324
|
+
y,
|
|
9325
|
+
style: rowStyle
|
|
9326
|
+
});
|
|
9327
|
+
if (((layout$1 === null || layout$1 === void 0 ? void 0 : layout$1.detailW) ?? 0) > 0) {
|
|
9328
|
+
const outDetail = padEndByCells(sliceByCells(detailLine, layout$1.detailW), layout$1.detailW);
|
|
9329
|
+
terminal.write(outDetail, {
|
|
9330
|
+
x: r.x + layout$1.labelW + layout$1.gapW,
|
|
9331
|
+
y,
|
|
9332
|
+
style: detailStyle
|
|
8851
9333
|
});
|
|
8852
9334
|
}
|
|
8853
9335
|
}
|