@simon_he/vue-tui 0.0.1 → 0.0.3
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 +190 -80
- package/dist/index.d.ts +8 -8
- package/dist/index.js +184 -72
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
```vue
|
|
14
14
|
<script setup lang="ts">
|
|
15
15
|
import { computed, ref } from 'vue'
|
|
16
|
-
import { TerminalProvider, TBox, TInput, TText, useLayout } from 'vue-
|
|
16
|
+
import { TerminalProvider, TBox, TInput, TText, useLayout } from '@simon_he/vue-tui'
|
|
17
17
|
|
|
18
18
|
const layout = useLayout()
|
|
19
19
|
const cols = computed(() => layout.clipRect?.w ?? 80)
|
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) {
|
|
@@ -6770,6 +6770,30 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6770
6770
|
return;
|
|
6771
6771
|
}
|
|
6772
6772
|
}
|
|
6773
|
+
const base64EncodeBytes = (bytes) => {
|
|
6774
|
+
const table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
6775
|
+
let out = "";
|
|
6776
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
6777
|
+
const a = bytes[i] ?? 0;
|
|
6778
|
+
const b = bytes[i + 1] ?? 0;
|
|
6779
|
+
const c = bytes[i + 2] ?? 0;
|
|
6780
|
+
const triple = a << 16 | b << 8 | c;
|
|
6781
|
+
out += table[triple >> 18 & 63] ?? "";
|
|
6782
|
+
out += table[triple >> 12 & 63] ?? "";
|
|
6783
|
+
out += i + 1 < bytes.length ? table[triple >> 6 & 63] ?? "" : "=";
|
|
6784
|
+
out += i + 2 < bytes.length ? table[triple & 63] ?? "" : "=";
|
|
6785
|
+
}
|
|
6786
|
+
return out;
|
|
6787
|
+
};
|
|
6788
|
+
const base64EncodeText = (text) => {
|
|
6789
|
+
if (typeof TextEncoder !== "undefined")
|
|
6790
|
+
return base64EncodeBytes(new TextEncoder().encode(text));
|
|
6791
|
+
const bin = unescape(encodeURIComponent(text));
|
|
6792
|
+
const bytes = new Uint8Array(bin.length);
|
|
6793
|
+
for (let i = 0; i < bin.length; i++)
|
|
6794
|
+
bytes[i] = bin.charCodeAt(i);
|
|
6795
|
+
return base64EncodeBytes(bytes);
|
|
6796
|
+
};
|
|
6773
6797
|
const copyText = async (text) => {
|
|
6774
6798
|
var _a, _b, _c, _d, _e, _f;
|
|
6775
6799
|
if (!text)
|
|
@@ -6785,7 +6809,7 @@ var TInput = (0, import_vue19.defineComponent)({
|
|
|
6785
6809
|
const proc = globalThis.process;
|
|
6786
6810
|
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
6811
|
try {
|
|
6788
|
-
const base64 =
|
|
6812
|
+
const base64 = base64EncodeText(text);
|
|
6789
6813
|
proc.stdout.write(`\x1B]52;c;${base64}\x07`);
|
|
6790
6814
|
return true;
|
|
6791
6815
|
} catch {
|
|
@@ -7985,13 +8009,15 @@ var TSelect = (0, import_vue23.defineComponent)({
|
|
|
7985
8009
|
h: { type: Number, required: true },
|
|
7986
8010
|
zIndex: { type: Number, default: 0 },
|
|
7987
8011
|
options: { type: Array, required: true },
|
|
7988
|
-
modelValue: { type: Number, default: 0 },
|
|
8012
|
+
modelValue: { type: [Number, Array], default: 0 },
|
|
8013
|
+
multiple: { type: Boolean, default: false },
|
|
8014
|
+
multipleEmit: { type: String, default: "value" },
|
|
7989
8015
|
style: { type: Object, default: void 0 },
|
|
7990
8016
|
highlightStyle: { type: Object, default: void 0 },
|
|
7991
8017
|
autoFocus: { type: Boolean, default: false },
|
|
7992
8018
|
closeOnBlur: { type: Boolean, default: false }
|
|
7993
8019
|
},
|
|
7994
|
-
emits: ["update:modelValue", "change", "close", "focus", "blur", "keydown"],
|
|
8020
|
+
emits: ["update:modelValue", "change", "confirm", "close", "focus", "blur", "keydown"],
|
|
7995
8021
|
setup(props, { emit }) {
|
|
7996
8022
|
const { terminal, scheduler, defaultStyle, events } = useTerminal();
|
|
7997
8023
|
const layout = useLayout();
|
|
@@ -7999,7 +8025,17 @@ var TSelect = (0, import_vue23.defineComponent)({
|
|
|
7999
8025
|
const parentEventZ = (0, import_vue23.inject)(EventZIndexContextKey, (0, import_vue23.computed)(() => 0));
|
|
8000
8026
|
const eventZ = (0, import_vue23.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0));
|
|
8001
8027
|
const focused = (0, import_vue23.ref)(false);
|
|
8002
|
-
const
|
|
8028
|
+
const initialActive = (() => {
|
|
8029
|
+
const max = Math.max(0, props.options.length - 1);
|
|
8030
|
+
if (!props.multiple) {
|
|
8031
|
+
const idx = typeof props.modelValue === "number" ? props.modelValue : 0;
|
|
8032
|
+
return clamp6(idx, 0, max);
|
|
8033
|
+
}
|
|
8034
|
+
const selected = Array.isArray(props.modelValue) ? props.modelValue : [];
|
|
8035
|
+
const first = selected[0] ?? 0;
|
|
8036
|
+
return clamp6(first, 0, max);
|
|
8037
|
+
})();
|
|
8038
|
+
const active = (0, import_vue23.ref)(initialActive);
|
|
8003
8039
|
const absRect = (0, import_vue23.computed)(() => {
|
|
8004
8040
|
const raw = { x: props.x, y: props.y, w: props.w, h: props.h };
|
|
8005
8041
|
const translated = translateRect(raw, layout.originX, layout.originY);
|
|
@@ -8008,7 +8044,13 @@ var TSelect = (0, import_vue23.defineComponent)({
|
|
|
8008
8044
|
return intersectRect(translated, layout.clipRect) ?? { x: 0, y: 0, w: 0, h: 0 };
|
|
8009
8045
|
});
|
|
8010
8046
|
(0, import_vue23.watchEffect)(() => {
|
|
8011
|
-
|
|
8047
|
+
const max = Math.max(0, props.options.length - 1);
|
|
8048
|
+
if (!props.multiple) {
|
|
8049
|
+
const idx = typeof props.modelValue === "number" ? props.modelValue : 0;
|
|
8050
|
+
active.value = clamp6(idx, 0, max);
|
|
8051
|
+
return;
|
|
8052
|
+
}
|
|
8053
|
+
active.value = clamp6(active.value, 0, max);
|
|
8012
8054
|
});
|
|
8013
8055
|
function getOptionLabel(opt) {
|
|
8014
8056
|
return typeof opt === "string" ? opt : opt.label;
|
|
@@ -8016,30 +8058,93 @@ var TSelect = (0, import_vue23.defineComponent)({
|
|
|
8016
8058
|
function getOptionDetail(opt) {
|
|
8017
8059
|
return typeof opt === "string" ? void 0 : opt.detail;
|
|
8018
8060
|
}
|
|
8019
|
-
function
|
|
8061
|
+
function commitSingle(index) {
|
|
8020
8062
|
const next = clamp6(index, 0, Math.max(0, props.options.length - 1));
|
|
8021
8063
|
active.value = next;
|
|
8022
8064
|
emit("update:modelValue", next);
|
|
8023
8065
|
const opt = props.options[next];
|
|
8024
8066
|
emit("change", opt ? getOptionLabel(opt) : null);
|
|
8025
8067
|
}
|
|
8068
|
+
function getSelectedIndices() {
|
|
8069
|
+
if (!props.multiple)
|
|
8070
|
+
return [];
|
|
8071
|
+
const max = Math.max(0, props.options.length - 1);
|
|
8072
|
+
const raw = Array.isArray(props.modelValue) ? props.modelValue : [];
|
|
8073
|
+
const set = /* @__PURE__ */ new Set();
|
|
8074
|
+
for (const v of raw) {
|
|
8075
|
+
if (typeof v !== "number" || !Number.isFinite(v))
|
|
8076
|
+
continue;
|
|
8077
|
+
set.add(clamp6(Math.trunc(v), 0, max));
|
|
8078
|
+
}
|
|
8079
|
+
return [...set].sort((a, b) => a - b);
|
|
8080
|
+
}
|
|
8081
|
+
function makeMultiplePayload(indices) {
|
|
8082
|
+
const values = indices.map((i) => props.options[i]).filter(Boolean).map((opt) => getOptionLabel(opt));
|
|
8083
|
+
return { indices, values };
|
|
8084
|
+
}
|
|
8085
|
+
function emitMultiple(name, indices) {
|
|
8086
|
+
const payload = makeMultiplePayload(indices);
|
|
8087
|
+
if (props.multipleEmit === "index") {
|
|
8088
|
+
emit(name, payload.indices);
|
|
8089
|
+
return;
|
|
8090
|
+
}
|
|
8091
|
+
if (props.multipleEmit === "both") {
|
|
8092
|
+
emit(name, payload);
|
|
8093
|
+
return;
|
|
8094
|
+
}
|
|
8095
|
+
emit(name, payload.values);
|
|
8096
|
+
}
|
|
8097
|
+
function toggleMultiple(index) {
|
|
8098
|
+
const nextIndex = clamp6(index, 0, Math.max(0, props.options.length - 1));
|
|
8099
|
+
active.value = nextIndex;
|
|
8100
|
+
const set = new Set(getSelectedIndices());
|
|
8101
|
+
if (set.has(nextIndex))
|
|
8102
|
+
set.delete(nextIndex);
|
|
8103
|
+
else
|
|
8104
|
+
set.add(nextIndex);
|
|
8105
|
+
const indices = [...set].sort((a, b) => a - b);
|
|
8106
|
+
emit("update:modelValue", indices);
|
|
8107
|
+
emitMultiple("change", indices);
|
|
8108
|
+
}
|
|
8109
|
+
function confirmMultiple() {
|
|
8110
|
+
const indices = getSelectedIndices();
|
|
8111
|
+
emitMultiple("confirm", indices);
|
|
8112
|
+
}
|
|
8113
|
+
function commit(index) {
|
|
8114
|
+
if (props.multiple)
|
|
8115
|
+
toggleMultiple(index);
|
|
8116
|
+
else
|
|
8117
|
+
commitSingle(index);
|
|
8118
|
+
}
|
|
8026
8119
|
function onKeydown(e) {
|
|
8027
8120
|
emit("keydown", e);
|
|
8028
8121
|
if (e.key === "ArrowUp") {
|
|
8029
8122
|
e.preventDefault();
|
|
8030
8123
|
active.value = clamp6(active.value - 1, 0, Math.max(0, props.options.length - 1));
|
|
8031
|
-
|
|
8124
|
+
if (!props.multiple)
|
|
8125
|
+
emit("update:modelValue", active.value);
|
|
8032
8126
|
scheduler.invalidate();
|
|
8033
8127
|
return;
|
|
8034
8128
|
}
|
|
8035
8129
|
if (e.key === "ArrowDown") {
|
|
8036
8130
|
e.preventDefault();
|
|
8037
8131
|
active.value = clamp6(active.value + 1, 0, Math.max(0, props.options.length - 1));
|
|
8038
|
-
|
|
8132
|
+
if (!props.multiple)
|
|
8133
|
+
emit("update:modelValue", active.value);
|
|
8039
8134
|
scheduler.invalidate();
|
|
8040
8135
|
return;
|
|
8041
8136
|
}
|
|
8137
|
+
if (props.multiple && (e.code === "Space" || e.key === " " || e.key === "Spacebar")) {
|
|
8138
|
+
e.preventDefault();
|
|
8139
|
+
toggleMultiple(active.value);
|
|
8140
|
+
return;
|
|
8141
|
+
}
|
|
8042
8142
|
if (e.key === "Enter") {
|
|
8143
|
+
if (props.multiple) {
|
|
8144
|
+
e.preventDefault();
|
|
8145
|
+
confirmMultiple();
|
|
8146
|
+
return;
|
|
8147
|
+
}
|
|
8043
8148
|
commit(active.value);
|
|
8044
8149
|
return;
|
|
8045
8150
|
}
|
|
@@ -8093,7 +8198,7 @@ var TSelect = (0, import_vue23.defineComponent)({
|
|
|
8093
8198
|
useRenderNode(() => ({
|
|
8094
8199
|
zIndex: props.zIndex,
|
|
8095
8200
|
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],
|
|
8201
|
+
deps: [visible.value, absRect.value, props.w, props.h, props.options, props.modelValue, props.multiple, props.multipleEmit, props.style, props.highlightStyle, focused.value, active.value, defaultStyle.value],
|
|
8097
8202
|
paint: () => {
|
|
8098
8203
|
if (!visible.value)
|
|
8099
8204
|
return;
|
|
@@ -8101,36 +8206,41 @@ var TSelect = (0, import_vue23.defineComponent)({
|
|
|
8101
8206
|
if (r.w <= 0 || r.h <= 0)
|
|
8102
8207
|
return;
|
|
8103
8208
|
const base = props.style ?? defaultStyle.value;
|
|
8104
|
-
const
|
|
8209
|
+
const highlightBase = props.highlightStyle ?? { ...base, bg: "yellow", fg: "black" };
|
|
8105
8210
|
const detailDimStyle = { ...base, dim: true };
|
|
8106
|
-
const
|
|
8211
|
+
const highlightDetailStyle = { ...highlightBase, dim: true };
|
|
8212
|
+
const selectedSet = props.multiple ? new Set(getSelectedIndices()) : null;
|
|
8107
8213
|
for (let i = 0; i < r.h; i++) {
|
|
8108
8214
|
const opt = props.options[i];
|
|
8109
8215
|
if (!opt) {
|
|
8110
8216
|
terminal.write(" ".repeat(r.w), { x: r.x, y: r.y + i, style: base });
|
|
8111
8217
|
continue;
|
|
8112
8218
|
}
|
|
8113
|
-
const
|
|
8219
|
+
const isActiveRow = i === active.value;
|
|
8220
|
+
const isChecked = props.multiple ? selectedSet.has(i) : isActiveRow;
|
|
8221
|
+
const isHighlighted = props.multiple ? focused.value && isActiveRow : isActiveRow;
|
|
8222
|
+
const prefix = props.multiple ? isChecked ? "[x] " : "[ ] " : "";
|
|
8114
8223
|
const label = sanitizeInlineText(getOptionLabel(opt));
|
|
8115
8224
|
const detail = getOptionDetail(opt);
|
|
8116
8225
|
const rawDetail = detail ? sanitizeInlineText(detail) : "";
|
|
8117
|
-
const
|
|
8226
|
+
const labelText = `${prefix}${label}`;
|
|
8227
|
+
const labelCells = textCellWidth3(labelText);
|
|
8118
8228
|
const minGap = 2;
|
|
8119
8229
|
const availableForDetail = r.w - labelCells - minGap;
|
|
8120
8230
|
if (rawDetail && availableForDetail >= 4) {
|
|
8121
|
-
const labelStyle =
|
|
8122
|
-
terminal.write(
|
|
8231
|
+
const labelStyle = isHighlighted ? highlightBase : base;
|
|
8232
|
+
terminal.write(labelText, { x: r.x, y: r.y + i, style: labelStyle });
|
|
8123
8233
|
const detailCells = textCellWidth3(rawDetail);
|
|
8124
8234
|
const actualDetailWidth = Math.min(detailCells, availableForDetail);
|
|
8125
8235
|
const gapWidth = r.w - labelCells - actualDetailWidth;
|
|
8126
|
-
const gapStyle =
|
|
8236
|
+
const gapStyle = isHighlighted ? highlightBase : base;
|
|
8127
8237
|
terminal.write(" ".repeat(gapWidth), { x: r.x + labelCells, y: r.y + i, style: gapStyle });
|
|
8128
8238
|
const detailText = sliceByCells(rawDetail, availableForDetail);
|
|
8129
|
-
const dStyle =
|
|
8239
|
+
const dStyle = isHighlighted ? highlightDetailStyle : detailDimStyle;
|
|
8130
8240
|
terminal.write(detailText, { x: r.x + labelCells + gapWidth, y: r.y + i, style: dStyle });
|
|
8131
8241
|
} else {
|
|
8132
|
-
const line = padEndByCells(sliceByCells(
|
|
8133
|
-
const style =
|
|
8242
|
+
const line = padEndByCells(sliceByCells(labelText, r.w), r.w);
|
|
8243
|
+
const style = isHighlighted ? highlightBase : base;
|
|
8134
8244
|
terminal.write(line, { x: r.x, y: r.y + i, style });
|
|
8135
8245
|
}
|
|
8136
8246
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -77,19 +77,15 @@ type PathPickerProvider = Readonly<{
|
|
|
77
77
|
}>;
|
|
78
78
|
declare function createNodePathPickerProvider(): PathPickerProvider;
|
|
79
79
|
|
|
80
|
-
//#endregion
|
|
81
|
-
//#region src/cli/recording.d.ts
|
|
82
|
-
declare function writeEventLog(path: string, events: readonly TerminalEventRecord[]): Promise<void>;
|
|
83
|
-
declare function writeSnapshot(path: string, lines: readonly string[]): Promise<void>;
|
|
84
|
-
declare function readEventLog(path: string): Promise<TerminalEventRecord[]>;
|
|
85
|
-
|
|
86
80
|
//#endregion
|
|
87
81
|
//#region src/cli/path-suggest.d.ts
|
|
88
82
|
declare function resolveUserPath(workspaceAbs: string, input: string): string;
|
|
89
83
|
|
|
90
84
|
//#endregion
|
|
91
|
-
//#region src/
|
|
92
|
-
declare function
|
|
85
|
+
//#region src/cli/recording.d.ts
|
|
86
|
+
declare function writeEventLog(path: string, events: readonly TerminalEventRecord[]): Promise<void>;
|
|
87
|
+
declare function writeSnapshot(path: string, lines: readonly string[]): Promise<void>;
|
|
88
|
+
declare function readEventLog(path: string): Promise<TerminalEventRecord[]>;
|
|
93
89
|
|
|
94
90
|
//#endregion
|
|
95
91
|
//#region src/core/types.d.ts
|
|
@@ -160,6 +156,10 @@ interface AnsiSegment {
|
|
|
160
156
|
}
|
|
161
157
|
declare function parseAnsiSgr(input: string, baseStyle?: Style): AnsiSegment[];
|
|
162
158
|
|
|
159
|
+
//#endregion
|
|
160
|
+
//#region src/core/buffer/width.d.ts
|
|
161
|
+
declare function charCellWidth(text: string): 1 | 2;
|
|
162
|
+
|
|
163
163
|
//#endregion
|
|
164
164
|
//#region src/core/terminal/create-terminal.d.ts
|
|
165
165
|
declare function createTerminal(opts: {
|
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({});
|
|
@@ -7182,6 +7182,28 @@ const TInput = defineComponent({
|
|
|
7182
7182
|
return;
|
|
7183
7183
|
}
|
|
7184
7184
|
}
|
|
7185
|
+
const base64EncodeBytes = (bytes) => {
|
|
7186
|
+
const table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
7187
|
+
let out = "";
|
|
7188
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
7189
|
+
const a = bytes[i] ?? 0;
|
|
7190
|
+
const b = bytes[i + 1] ?? 0;
|
|
7191
|
+
const c = bytes[i + 2] ?? 0;
|
|
7192
|
+
const triple = a << 16 | b << 8 | c;
|
|
7193
|
+
out += table[triple >> 18 & 63] ?? "";
|
|
7194
|
+
out += table[triple >> 12 & 63] ?? "";
|
|
7195
|
+
out += i + 1 < bytes.length ? table[triple >> 6 & 63] ?? "" : "=";
|
|
7196
|
+
out += i + 2 < bytes.length ? table[triple & 63] ?? "" : "=";
|
|
7197
|
+
}
|
|
7198
|
+
return out;
|
|
7199
|
+
};
|
|
7200
|
+
const base64EncodeText = (text) => {
|
|
7201
|
+
if (typeof TextEncoder !== "undefined") return base64EncodeBytes(new TextEncoder().encode(text));
|
|
7202
|
+
const bin = unescape(encodeURIComponent(text));
|
|
7203
|
+
const bytes = new Uint8Array(bin.length);
|
|
7204
|
+
for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
|
|
7205
|
+
return base64EncodeBytes(bytes);
|
|
7206
|
+
};
|
|
7185
7207
|
const copyText = async (text) => {
|
|
7186
7208
|
var _nav$clipboard, _proc$stdout, _proc$stdout2, _doc$body;
|
|
7187
7209
|
if (!text) return false;
|
|
@@ -7192,7 +7214,7 @@ const TInput = defineComponent({
|
|
|
7192
7214
|
} catch {}
|
|
7193
7215
|
const proc = globalThis.process;
|
|
7194
7216
|
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 =
|
|
7217
|
+
const base64 = base64EncodeText(text);
|
|
7196
7218
|
proc.stdout.write(`\u001B]52;c;${base64}\u0007`);
|
|
7197
7219
|
return true;
|
|
7198
7220
|
} catch {}
|
|
@@ -8639,9 +8661,17 @@ const TSelect = defineComponent({
|
|
|
8639
8661
|
required: true
|
|
8640
8662
|
},
|
|
8641
8663
|
modelValue: {
|
|
8642
|
-
type: Number,
|
|
8664
|
+
type: [Number, Array],
|
|
8643
8665
|
default: 0
|
|
8644
8666
|
},
|
|
8667
|
+
multiple: {
|
|
8668
|
+
type: Boolean,
|
|
8669
|
+
default: false
|
|
8670
|
+
},
|
|
8671
|
+
multipleEmit: {
|
|
8672
|
+
type: String,
|
|
8673
|
+
default: "value"
|
|
8674
|
+
},
|
|
8645
8675
|
style: {
|
|
8646
8676
|
type: Object,
|
|
8647
8677
|
default: void 0
|
|
@@ -8662,6 +8692,7 @@ const TSelect = defineComponent({
|
|
|
8662
8692
|
emits: [
|
|
8663
8693
|
"update:modelValue",
|
|
8664
8694
|
"change",
|
|
8695
|
+
"confirm",
|
|
8665
8696
|
"close",
|
|
8666
8697
|
"focus",
|
|
8667
8698
|
"blur",
|
|
@@ -8674,7 +8705,17 @@ const TSelect = defineComponent({
|
|
|
8674
8705
|
const parentEventZ = inject(EventZIndexContextKey, computed(() => 0));
|
|
8675
8706
|
const eventZ = computed(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0));
|
|
8676
8707
|
const focused = ref(false);
|
|
8677
|
-
const
|
|
8708
|
+
const initialActive = (() => {
|
|
8709
|
+
const max = Math.max(0, props.options.length - 1);
|
|
8710
|
+
if (!props.multiple) {
|
|
8711
|
+
const idx = typeof props.modelValue === "number" ? props.modelValue : 0;
|
|
8712
|
+
return clamp(idx, 0, max);
|
|
8713
|
+
}
|
|
8714
|
+
const selected = Array.isArray(props.modelValue) ? props.modelValue : [];
|
|
8715
|
+
const first = selected[0] ?? 0;
|
|
8716
|
+
return clamp(first, 0, max);
|
|
8717
|
+
})();
|
|
8718
|
+
const active = ref(initialActive);
|
|
8678
8719
|
const absRect = computed(() => {
|
|
8679
8720
|
const raw = {
|
|
8680
8721
|
x: props.x,
|
|
@@ -8692,7 +8733,13 @@ const TSelect = defineComponent({
|
|
|
8692
8733
|
};
|
|
8693
8734
|
});
|
|
8694
8735
|
watchEffect(() => {
|
|
8695
|
-
|
|
8736
|
+
const max = Math.max(0, props.options.length - 1);
|
|
8737
|
+
if (!props.multiple) {
|
|
8738
|
+
const idx = typeof props.modelValue === "number" ? props.modelValue : 0;
|
|
8739
|
+
active.value = clamp(idx, 0, max);
|
|
8740
|
+
return;
|
|
8741
|
+
}
|
|
8742
|
+
active.value = clamp(active.value, 0, max);
|
|
8696
8743
|
});
|
|
8697
8744
|
function getOptionLabel(opt) {
|
|
8698
8745
|
return typeof opt === "string" ? opt : opt.label;
|
|
@@ -8700,30 +8747,88 @@ const TSelect = defineComponent({
|
|
|
8700
8747
|
function getOptionDetail(opt) {
|
|
8701
8748
|
return typeof opt === "string" ? void 0 : opt.detail;
|
|
8702
8749
|
}
|
|
8703
|
-
function
|
|
8750
|
+
function commitSingle(index) {
|
|
8704
8751
|
const next = clamp(index, 0, Math.max(0, props.options.length - 1));
|
|
8705
8752
|
active.value = next;
|
|
8706
8753
|
emit("update:modelValue", next);
|
|
8707
8754
|
const opt = props.options[next];
|
|
8708
8755
|
emit("change", opt ? getOptionLabel(opt) : null);
|
|
8709
8756
|
}
|
|
8757
|
+
function getSelectedIndices() {
|
|
8758
|
+
if (!props.multiple) return [];
|
|
8759
|
+
const max = Math.max(0, props.options.length - 1);
|
|
8760
|
+
const raw = Array.isArray(props.modelValue) ? props.modelValue : [];
|
|
8761
|
+
const set = new Set();
|
|
8762
|
+
for (const v of raw) {
|
|
8763
|
+
if (typeof v !== "number" || !Number.isFinite(v)) continue;
|
|
8764
|
+
set.add(clamp(Math.trunc(v), 0, max));
|
|
8765
|
+
}
|
|
8766
|
+
return [...set].sort((a, b) => a - b);
|
|
8767
|
+
}
|
|
8768
|
+
function makeMultiplePayload(indices) {
|
|
8769
|
+
const values = indices.map((i) => props.options[i]).filter(Boolean).map((opt) => getOptionLabel(opt));
|
|
8770
|
+
return {
|
|
8771
|
+
indices,
|
|
8772
|
+
values
|
|
8773
|
+
};
|
|
8774
|
+
}
|
|
8775
|
+
function emitMultiple(name, indices) {
|
|
8776
|
+
const payload = makeMultiplePayload(indices);
|
|
8777
|
+
if (props.multipleEmit === "index") {
|
|
8778
|
+
emit(name, payload.indices);
|
|
8779
|
+
return;
|
|
8780
|
+
}
|
|
8781
|
+
if (props.multipleEmit === "both") {
|
|
8782
|
+
emit(name, payload);
|
|
8783
|
+
return;
|
|
8784
|
+
}
|
|
8785
|
+
emit(name, payload.values);
|
|
8786
|
+
}
|
|
8787
|
+
function toggleMultiple(index) {
|
|
8788
|
+
const nextIndex = clamp(index, 0, Math.max(0, props.options.length - 1));
|
|
8789
|
+
active.value = nextIndex;
|
|
8790
|
+
const set = new Set(getSelectedIndices());
|
|
8791
|
+
if (set.has(nextIndex)) set.delete(nextIndex);
|
|
8792
|
+
else set.add(nextIndex);
|
|
8793
|
+
const indices = [...set].sort((a, b) => a - b);
|
|
8794
|
+
emit("update:modelValue", indices);
|
|
8795
|
+
emitMultiple("change", indices);
|
|
8796
|
+
}
|
|
8797
|
+
function confirmMultiple() {
|
|
8798
|
+
const indices = getSelectedIndices();
|
|
8799
|
+
emitMultiple("confirm", indices);
|
|
8800
|
+
}
|
|
8801
|
+
function commit(index) {
|
|
8802
|
+
if (props.multiple) toggleMultiple(index);
|
|
8803
|
+
else commitSingle(index);
|
|
8804
|
+
}
|
|
8710
8805
|
function onKeydown(e) {
|
|
8711
8806
|
emit("keydown", e);
|
|
8712
8807
|
if (e.key === "ArrowUp") {
|
|
8713
8808
|
e.preventDefault();
|
|
8714
8809
|
active.value = clamp(active.value - 1, 0, Math.max(0, props.options.length - 1));
|
|
8715
|
-
emit("update:modelValue", active.value);
|
|
8810
|
+
if (!props.multiple) emit("update:modelValue", active.value);
|
|
8716
8811
|
scheduler.invalidate();
|
|
8717
8812
|
return;
|
|
8718
8813
|
}
|
|
8719
8814
|
if (e.key === "ArrowDown") {
|
|
8720
8815
|
e.preventDefault();
|
|
8721
8816
|
active.value = clamp(active.value + 1, 0, Math.max(0, props.options.length - 1));
|
|
8722
|
-
emit("update:modelValue", active.value);
|
|
8817
|
+
if (!props.multiple) emit("update:modelValue", active.value);
|
|
8723
8818
|
scheduler.invalidate();
|
|
8724
8819
|
return;
|
|
8725
8820
|
}
|
|
8821
|
+
if (props.multiple && (e.code === "Space" || e.key === " " || e.key === "Spacebar")) {
|
|
8822
|
+
e.preventDefault();
|
|
8823
|
+
toggleMultiple(active.value);
|
|
8824
|
+
return;
|
|
8825
|
+
}
|
|
8726
8826
|
if (e.key === "Enter") {
|
|
8827
|
+
if (props.multiple) {
|
|
8828
|
+
e.preventDefault();
|
|
8829
|
+
confirmMultiple();
|
|
8830
|
+
return;
|
|
8831
|
+
}
|
|
8727
8832
|
commit(active.value);
|
|
8728
8833
|
return;
|
|
8729
8834
|
}
|
|
@@ -8777,6 +8882,8 @@ const TSelect = defineComponent({
|
|
|
8777
8882
|
props.h,
|
|
8778
8883
|
props.options,
|
|
8779
8884
|
props.modelValue,
|
|
8885
|
+
props.multiple,
|
|
8886
|
+
props.multipleEmit,
|
|
8780
8887
|
props.style,
|
|
8781
8888
|
props.highlightStyle,
|
|
8782
8889
|
focused.value,
|
|
@@ -8788,7 +8895,7 @@ const TSelect = defineComponent({
|
|
|
8788
8895
|
const r = absRect.value;
|
|
8789
8896
|
if (r.w <= 0 || r.h <= 0) return;
|
|
8790
8897
|
const base = props.style ?? defaultStyle.value;
|
|
8791
|
-
const
|
|
8898
|
+
const highlightBase = props.highlightStyle ?? {
|
|
8792
8899
|
...base,
|
|
8793
8900
|
bg: "yellow",
|
|
8794
8901
|
fg: "black"
|
|
@@ -8797,10 +8904,11 @@ const TSelect = defineComponent({
|
|
|
8797
8904
|
...base,
|
|
8798
8905
|
dim: true
|
|
8799
8906
|
};
|
|
8800
|
-
const
|
|
8801
|
-
...
|
|
8907
|
+
const highlightDetailStyle = {
|
|
8908
|
+
...highlightBase,
|
|
8802
8909
|
dim: true
|
|
8803
8910
|
};
|
|
8911
|
+
const selectedSet = props.multiple ? new Set(getSelectedIndices()) : null;
|
|
8804
8912
|
for (let i = 0; i < r.h; i++) {
|
|
8805
8913
|
const opt = props.options[i];
|
|
8806
8914
|
if (!opt) {
|
|
@@ -8811,16 +8919,20 @@ const TSelect = defineComponent({
|
|
|
8811
8919
|
});
|
|
8812
8920
|
continue;
|
|
8813
8921
|
}
|
|
8814
|
-
const
|
|
8922
|
+
const isActiveRow = i === active.value;
|
|
8923
|
+
const isChecked = props.multiple ? selectedSet.has(i) : isActiveRow;
|
|
8924
|
+
const isHighlighted = props.multiple ? focused.value && isActiveRow : isActiveRow;
|
|
8925
|
+
const prefix = props.multiple ? isChecked ? "[x] " : "[ ] " : "";
|
|
8815
8926
|
const label = sanitizeInlineText(getOptionLabel(opt));
|
|
8816
8927
|
const detail = getOptionDetail(opt);
|
|
8817
8928
|
const rawDetail = detail ? sanitizeInlineText(detail) : "";
|
|
8818
|
-
const
|
|
8929
|
+
const labelText = `${prefix}${label}`;
|
|
8930
|
+
const labelCells = textCellWidth$1(labelText);
|
|
8819
8931
|
const minGap = 2;
|
|
8820
8932
|
const availableForDetail = r.w - labelCells - minGap;
|
|
8821
8933
|
if (rawDetail && availableForDetail >= 4) {
|
|
8822
|
-
const labelStyle =
|
|
8823
|
-
terminal.write(
|
|
8934
|
+
const labelStyle = isHighlighted ? highlightBase : base;
|
|
8935
|
+
terminal.write(labelText, {
|
|
8824
8936
|
x: r.x,
|
|
8825
8937
|
y: r.y + i,
|
|
8826
8938
|
style: labelStyle
|
|
@@ -8828,22 +8940,22 @@ const TSelect = defineComponent({
|
|
|
8828
8940
|
const detailCells = textCellWidth$1(rawDetail);
|
|
8829
8941
|
const actualDetailWidth = Math.min(detailCells, availableForDetail);
|
|
8830
8942
|
const gapWidth = r.w - labelCells - actualDetailWidth;
|
|
8831
|
-
const gapStyle =
|
|
8943
|
+
const gapStyle = isHighlighted ? highlightBase : base;
|
|
8832
8944
|
terminal.write(" ".repeat(gapWidth), {
|
|
8833
8945
|
x: r.x + labelCells,
|
|
8834
8946
|
y: r.y + i,
|
|
8835
8947
|
style: gapStyle
|
|
8836
8948
|
});
|
|
8837
8949
|
const detailText = sliceByCells(rawDetail, availableForDetail);
|
|
8838
|
-
const dStyle =
|
|
8950
|
+
const dStyle = isHighlighted ? highlightDetailStyle : detailDimStyle;
|
|
8839
8951
|
terminal.write(detailText, {
|
|
8840
8952
|
x: r.x + labelCells + gapWidth,
|
|
8841
8953
|
y: r.y + i,
|
|
8842
8954
|
style: dStyle
|
|
8843
8955
|
});
|
|
8844
8956
|
} else {
|
|
8845
|
-
const line = padEndByCells(sliceByCells(
|
|
8846
|
-
const style =
|
|
8957
|
+
const line = padEndByCells(sliceByCells(labelText, r.w), r.w);
|
|
8958
|
+
const style = isHighlighted ? highlightBase : base;
|
|
8847
8959
|
terminal.write(line, {
|
|
8848
8960
|
x: r.x,
|
|
8849
8961
|
y: r.y + i,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simon_he/vue-tui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.3",
|
|
5
5
|
"description": "A Vue 3 terminal UI component library",
|
|
6
6
|
"author": "Simon He",
|
|
7
7
|
"license": "MIT",
|
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
"build:examples": "pnpm run build:goatchain && pnpm -C examples/basic build && pnpm -C examples/goatchain build",
|
|
78
78
|
"build:examples:terminal": "pnpm run build:goatchain && pnpm -C examples/basic build:terminal && pnpm -C examples/goatchain build:terminal",
|
|
79
79
|
"run:basic:terminal": "pnpm run build && pnpm -C examples/basic terminal",
|
|
80
|
+
"run:basic:multi-select:terminal": "pnpm run build && pnpm -C examples/basic build:terminal:multi-select && pnpm -C examples/basic terminal:multi-select",
|
|
80
81
|
"run:goatchain:terminal": "pnpm run build:goatchain && pnpm -C examples/goatchain terminal",
|
|
81
82
|
"format": "prettier --cache --write .",
|
|
82
83
|
"lint": "eslint . --cache",
|