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