@simon_he/vue-tui 0.0.2 → 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.
Files changed (3) hide show
  1. package/dist/index.cjs +135 -389
  2. package/dist/index.js +161 -531
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3611,81 +3611,6 @@ function translateRect(rect, dx, dy) {
3611
3611
  h: rect.h
3612
3612
  };
3613
3613
  }
3614
- function normalizePadding(padding) {
3615
- const nums = [];
3616
- if (typeof padding === "number") nums.push(padding);
3617
- else if (Array.isArray(padding)) for (const v of padding) nums.push(typeof v === "number" ? v : Number(v));
3618
- else if (typeof padding === "string") for (const part of padding.trim().split(/\s+/g)) {
3619
- if (!part) continue;
3620
- nums.push(Number(part));
3621
- }
3622
- const n = nums.map((v) => Number.isFinite(v) ? Math.max(0, Math.floor(v)) : 0);
3623
- const a = n[0] ?? 0;
3624
- const b = n[1] ?? a;
3625
- const c = n[2] ?? a;
3626
- const d = n[3] ?? b;
3627
- if (n.length <= 1) return {
3628
- top: a,
3629
- right: a,
3630
- bottom: a,
3631
- left: a
3632
- };
3633
- if (n.length === 2) return {
3634
- top: a,
3635
- right: b,
3636
- bottom: a,
3637
- left: b
3638
- };
3639
- if (n.length === 3) return {
3640
- top: a,
3641
- right: b,
3642
- bottom: c,
3643
- left: b
3644
- };
3645
- return {
3646
- top: a,
3647
- right: b,
3648
- bottom: c,
3649
- left: d
3650
- };
3651
- }
3652
- function clampRectPadding(rect, padding) {
3653
- const requested = normalizePadding(padding);
3654
- const w = Math.max(0, Math.floor(rect.w));
3655
- const h$1 = Math.max(0, Math.floor(rect.h));
3656
- const maxTotalX = Math.max(0, w - (w > 0 ? 1 : 0));
3657
- const maxTotalY = Math.max(0, h$1 - (h$1 > 0 ? 1 : 0));
3658
- if (requested.top === requested.right && requested.top === requested.bottom && requested.top === requested.left) {
3659
- const maxPadX = Math.max(0, Math.floor(maxTotalX / 2));
3660
- const maxPadY = Math.max(0, Math.floor(maxTotalY / 2));
3661
- const pad = Math.min(requested.top, maxPadX, maxPadY);
3662
- return {
3663
- top: pad,
3664
- right: pad,
3665
- bottom: pad,
3666
- left: pad
3667
- };
3668
- }
3669
- const left = Math.min(requested.left, maxTotalX);
3670
- const right = Math.min(requested.right, Math.max(0, maxTotalX - left));
3671
- const top = Math.min(requested.top, maxTotalY);
3672
- const bottom = Math.min(requested.bottom, Math.max(0, maxTotalY - top));
3673
- return {
3674
- top,
3675
- right,
3676
- bottom,
3677
- left
3678
- };
3679
- }
3680
- function insetRect(rect, padding) {
3681
- const pad = clampRectPadding(rect, padding);
3682
- return {
3683
- x: rect.x + pad.left,
3684
- y: rect.y + pad.top,
3685
- w: Math.max(0, rect.w - pad.left - pad.right),
3686
- h: Math.max(0, rect.h - pad.top - pad.bottom)
3687
- };
3688
- }
3689
3614
 
3690
3615
  //#endregion
3691
3616
  //#region src/vue/components/TAnchor.ts
@@ -3726,14 +3651,6 @@ const TAnchor = defineComponent({
3726
3651
  type: Number,
3727
3652
  default: 0
3728
3653
  },
3729
- padding: {
3730
- type: [
3731
- Number,
3732
- String,
3733
- Array
3734
- ],
3735
- default: 0
3736
- },
3737
3654
  focusable: {
3738
3655
  type: Boolean,
3739
3656
  default: false
@@ -3845,11 +3762,9 @@ const TAnchor = defineComponent({
3845
3762
  const childStack = computed(() => render.createStack(parentStack.value, props.zIndex));
3846
3763
  watchEffect(() => {
3847
3764
  const translated = rawRect.value;
3848
- const content = insetRect(translated, props.padding);
3849
- const contentClip = intersectRect(content, rect.value) ?? EMPTY_RECT$1;
3850
- childLayout.originX = content.x;
3851
- childLayout.originY = content.y;
3852
- childLayout.clipRect = contentClip;
3765
+ childLayout.originX = translated.x;
3766
+ childLayout.originY = translated.y;
3767
+ childLayout.clipRect = rect.value;
3853
3768
  });
3854
3769
  provide(LayoutContextKey, childLayout);
3855
3770
  provide(RenderStackKey, childStack);
@@ -4032,11 +3947,7 @@ const TBox = defineComponent({
4032
3947
  default: ""
4033
3948
  },
4034
3949
  padding: {
4035
- type: [
4036
- Number,
4037
- String,
4038
- Array
4039
- ],
3950
+ type: Number,
4040
3951
  default: 0
4041
3952
  },
4042
3953
  scrollX: {
@@ -4129,14 +4040,17 @@ const TBox = defineComponent({
4129
4040
  watchEffect(() => {
4130
4041
  const r = absRect.value;
4131
4042
  const borderInset = props.border ? 1 : 0;
4132
- const inner = {
4133
- x: r.x + borderInset,
4134
- y: r.y + borderInset,
4135
- w: Math.max(0, r.w - borderInset * 2),
4136
- h: Math.max(0, r.h - borderInset * 2)
4043
+ const requestedPad = Math.max(0, Math.floor(props.padding));
4044
+ const maxPadX = Math.max(0, Math.floor((r.w - borderInset * 2 - 1) / 2));
4045
+ const maxPadY = Math.max(0, Math.floor((r.h - borderInset * 2 - 1) / 2));
4046
+ const pad = Math.min(requestedPad, maxPadX, maxPadY);
4047
+ const content = {
4048
+ x: r.x + borderInset + pad,
4049
+ y: r.y + borderInset + pad,
4050
+ w: Math.max(0, r.w - borderInset * 2 - pad * 2),
4051
+ h: Math.max(0, r.h - borderInset * 2 - pad * 2)
4137
4052
  };
4138
- const content = insetRect(inner, props.padding);
4139
- let contentRect$1 = intersectRect(content, inner);
4053
+ let contentRect$1 = intersectRect(content, r);
4140
4054
  if (parent.clipRect && contentRect$1) contentRect$1 = intersectRect(contentRect$1, parent.clipRect);
4141
4055
  if (!contentRect$1) contentRect$1 = {
4142
4056
  x: 0,
@@ -4230,14 +4144,6 @@ const TText = defineComponent({
4230
4144
  type: Number,
4231
4145
  default: void 0
4232
4146
  },
4233
- padding: {
4234
- type: [
4235
- Number,
4236
- String,
4237
- Array
4238
- ],
4239
- default: 0
4240
- },
4241
4147
  style: {
4242
4148
  type: Object,
4243
4149
  default: void 0
@@ -4255,21 +4161,16 @@ const TText = defineComponent({
4255
4161
  const { terminal, defaultStyle } = useTerminal();
4256
4162
  const layout = useLayout();
4257
4163
  const { visible, rootProps } = useVisibility();
4258
- const pad = computed(() => normalizePadding(props.padding));
4259
- const contentW = computed(() => {
4260
- const outerW = props.w ?? computeDefaultWidth(props.value) + pad.value.left + pad.value.right;
4261
- return Math.max(0, Math.floor(outerW) - pad.value.left - pad.value.right);
4262
- });
4263
4164
  const lines = computed(() => {
4264
- const w = contentW.value;
4165
+ const w = props.w ?? computeDefaultWidth(props.value);
4265
4166
  if (w <= 0) return [""];
4266
4167
  if (!props.wrap) return splitLines(props.value).map((l) => fitText(l, w));
4267
4168
  const safe = sanitizeTextBlock(props.value);
4268
4169
  return wrapByCells(safe, w).map((l) => fitText(l, w));
4269
4170
  });
4270
4171
  const absRect = computed(() => {
4271
- const width = Math.floor(props.w ?? computeDefaultWidth(props.value) + pad.value.left + pad.value.right);
4272
- const height = Math.floor(props.h ?? (lines.value.length || 1) + pad.value.top + pad.value.bottom);
4172
+ const width = props.w ?? computeDefaultWidth(props.value);
4173
+ const height = props.h ?? (props.wrap ? lines.value.length || 1 : lines.value.length || 1);
4273
4174
  const raw = {
4274
4175
  x: props.x,
4275
4176
  y: props.y,
@@ -4302,14 +4203,10 @@ const TText = defineComponent({
4302
4203
  if (!visible.value) return;
4303
4204
  const r = absRect.value;
4304
4205
  if (r.w <= 0 || r.h <= 0) return;
4305
- const contentX = r.x + pad.value.left;
4306
- const contentY = r.y + pad.value.top;
4307
- const w = Math.max(0, Math.floor(r.w) - pad.value.left - pad.value.right);
4308
- const h$1 = Math.max(0, Math.floor(r.h) - pad.value.top - pad.value.bottom);
4309
4206
  const style = props.style ?? defaultStyle.value;
4310
4207
  const blank = props.clear ? " ".repeat(r.w) : "";
4311
4208
  const out = lines.value;
4312
- const maxLines = Math.min(out.length, h$1);
4209
+ const maxLines = Math.min(out.length, Math.max(0, Math.floor(r.h)));
4313
4210
  const paintRow = (y) => {
4314
4211
  const i = y - r.y;
4315
4212
  if (i < 0 || i >= r.h) return;
@@ -4318,12 +4215,10 @@ const TText = defineComponent({
4318
4215
  y,
4319
4216
  style
4320
4217
  });
4321
- const contentRow = y - contentY;
4322
- if (contentRow < 0 || contentRow >= h$1) return;
4323
- if (contentRow < 0 || contentRow >= maxLines) return;
4324
- const clipped = sliceByCells(out[contentRow] ?? "", w);
4325
- terminal.write(padEndByCells(clipped, w), {
4326
- x: contentX,
4218
+ if (i < 0 || i >= maxLines) return;
4219
+ const clipped = sliceByCells(out[i] ?? "", r.w);
4220
+ terminal.write(padEndByCells(clipped, r.w), {
4221
+ x: r.x,
4327
4222
  y,
4328
4223
  style
4329
4224
  });
@@ -4370,14 +4265,6 @@ const TView = defineComponent({
4370
4265
  type: Number,
4371
4266
  default: 0
4372
4267
  },
4373
- padding: {
4374
- type: [
4375
- Number,
4376
- String,
4377
- Array
4378
- ],
4379
- default: 0
4380
- },
4381
4268
  scrollX: {
4382
4269
  type: Number,
4383
4270
  default: 0
@@ -4485,11 +4372,9 @@ const TView = defineComponent({
4485
4372
  const childStack = computed(() => render.createStack(parentStack.value, props.zIndex));
4486
4373
  watchEffect(() => {
4487
4374
  const translated = rawRect.value;
4488
- const content = insetRect(translated, props.padding);
4489
- const contentClip = intersectRect(content, rect.value) ?? EMPTY_RECT;
4490
- childLayout.originX = content.x - Math.floor(props.scrollX);
4491
- childLayout.originY = content.y - Math.floor(props.scrollY);
4492
- childLayout.clipRect = contentClip;
4375
+ childLayout.originX = translated.x - Math.floor(props.scrollX);
4376
+ childLayout.originY = translated.y - Math.floor(props.scrollY);
4377
+ childLayout.clipRect = rect.value;
4493
4378
  });
4494
4379
  provide(LayoutContextKey, childLayout);
4495
4380
  provide(RenderStackKey, childStack);
@@ -4695,10 +4580,10 @@ function computePosition(opts) {
4695
4580
  }
4696
4581
  function contentRect(opts) {
4697
4582
  const borderInset = opts.border ? 1 : 0;
4698
- const pad = normalizePadding(opts.padding);
4583
+ const pad = Math.max(0, Math.floor(opts.padding));
4699
4584
  return {
4700
- w: Math.max(0, Math.floor(opts.w) - borderInset * 2 - pad.left - pad.right),
4701
- h: Math.max(0, Math.floor(opts.h) - borderInset * 2 - pad.top - pad.bottom)
4585
+ w: Math.max(0, Math.floor(opts.w) - borderInset * 2 - pad * 2),
4586
+ h: Math.max(0, Math.floor(opts.h) - borderInset * 2 - pad * 2)
4702
4587
  };
4703
4588
  }
4704
4589
  const DialogSurface = defineComponent({
@@ -4721,11 +4606,7 @@ const DialogSurface = defineComponent({
4721
4606
  default: ""
4722
4607
  },
4723
4608
  padding: {
4724
- type: [
4725
- Number,
4726
- String,
4727
- Array
4728
- ],
4609
+ type: Number,
4729
4610
  default: 1
4730
4611
  },
4731
4612
  zIndex: {
@@ -4999,11 +4880,7 @@ const TDialog = defineComponent({
4999
4880
  default: ""
5000
4881
  },
5001
4882
  padding: {
5002
- type: [
5003
- Number,
5004
- String,
5005
- Array
5006
- ],
4883
+ type: Number,
5007
4884
  default: 1
5008
4885
  },
5009
4886
  zIndex: {
@@ -6070,14 +5947,6 @@ const TFlow = defineComponent({
6070
5947
  type: Number,
6071
5948
  required: true
6072
5949
  },
6073
- padding: {
6074
- type: [
6075
- Number,
6076
- String,
6077
- Array
6078
- ],
6079
- default: 0
6080
- },
6081
5950
  items: {
6082
5951
  type: Array,
6083
5952
  required: true
@@ -6100,29 +5969,25 @@ const TFlow = defineComponent({
6100
5969
  }
6101
5970
  },
6102
5971
  setup(props, { slots }) {
6103
- const pad = computed(() => normalizePadding(props.padding));
6104
- const innerW = computed(() => Math.max(0, Math.floor(props.w) - pad.value.left - pad.value.right));
6105
- const innerH = computed(() => Math.max(0, Math.floor(props.h) - pad.value.top - pad.value.bottom));
6106
5972
  return () => h(TView, {
6107
5973
  x: props.x,
6108
5974
  y: props.y,
6109
5975
  w: props.w,
6110
5976
  h: props.h,
6111
- zIndex: props.zIndex,
6112
- padding: props.padding
5977
+ zIndex: props.zIndex
6113
5978
  }, () => props.items.map((item, index) => {
6114
5979
  const step = Math.max(0, Math.floor(props.itemSize)) + Math.max(0, Math.floor(props.gap));
6115
5980
  const offset = index * step;
6116
5981
  const childProps = props.direction === "vertical" ? {
6117
5982
  x: 0,
6118
5983
  y: offset,
6119
- w: innerW.value,
5984
+ w: props.w,
6120
5985
  h: Math.max(0, Math.floor(props.itemSize))
6121
5986
  } : {
6122
5987
  x: offset,
6123
5988
  y: 0,
6124
5989
  w: Math.max(0, Math.floor(props.itemSize)),
6125
- h: innerH.value
5990
+ h: props.h
6126
5991
  };
6127
5992
  return h(TView, {
6128
5993
  key: index,
@@ -6530,14 +6395,6 @@ const TInput = defineComponent({
6530
6395
  type: Number,
6531
6396
  default: 0
6532
6397
  },
6533
- padding: {
6534
- type: [
6535
- Number,
6536
- String,
6537
- Array
6538
- ],
6539
- default: "0 1"
6540
- },
6541
6398
  modelValue: {
6542
6399
  type: String,
6543
6400
  required: true
@@ -6649,6 +6506,19 @@ const TInput = defineComponent({
6649
6506
  const parentEventZ = inject(EventZIndexContextKey, computed(() => 0));
6650
6507
  const eventZ = computed(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0));
6651
6508
  const promptOverlayStack = render.createStack(render.rootStack, 1e4);
6509
+ const PADDING_X = 1;
6510
+ function measureContent(r) {
6511
+ const wAll = Math.max(0, Math.floor(r.w));
6512
+ const hAll = Math.max(0, Math.floor(r.h));
6513
+ const padX = clamp$3(PADDING_X, 0, Math.floor(wAll / 2));
6514
+ const w = Math.max(0, wAll - padX * 2);
6515
+ return {
6516
+ wAll,
6517
+ hAll,
6518
+ padX,
6519
+ w
6520
+ };
6521
+ }
6652
6522
  const focused = ref(false);
6653
6523
  const cursor = ref(0);
6654
6524
  const anchor = ref(null);
@@ -6665,6 +6535,7 @@ const TInput = defineComponent({
6665
6535
  function getValue() {
6666
6536
  return pendingValue.value ?? props.modelValue;
6667
6537
  }
6538
+ const wrapMode = computed(() => Math.max(1, Math.floor(props.h)) > 1);
6668
6539
  const rawAbsRect = computed(() => {
6669
6540
  const raw = {
6670
6541
  x: props.x,
@@ -6926,8 +6797,6 @@ const TInput = defineComponent({
6926
6797
  h: 0
6927
6798
  };
6928
6799
  });
6929
- const contentRect$1 = computed(() => insetRect(absRect.value, props.padding));
6930
- const wrapMode = computed(() => Math.max(1, Math.floor(contentRect$1.value.h)) > 1);
6931
6800
  const selection = computed(() => {
6932
6801
  if (anchor.value == null || anchor.value === cursor.value) return null;
6933
6802
  const start = Math.min(anchor.value, cursor.value);
@@ -7003,16 +6872,10 @@ const TInput = defineComponent({
7003
6872
  return !focused.value || props.placeholderWhenFocused;
7004
6873
  });
7005
6874
  function ensureCursorVisible() {
7006
- const r = contentRect$1.value;
7007
- const w = Math.max(0, Math.floor(r.w));
7008
- const h$1 = Math.max(0, Math.floor(r.h));
7009
- if (w <= 0 || h$1 <= 0) {
7010
- scrollX.value = 0;
7011
- scrollY.value = 0;
7012
- return;
7013
- }
7014
- const width = w;
7015
- const height = h$1;
6875
+ const r = absRect.value;
6876
+ const { hAll, w: contentW } = measureContent(r);
6877
+ const width = Math.max(1, contentW);
6878
+ const height = Math.max(1, hAll);
7016
6879
  const value = getValue();
7017
6880
  const wrap = wrapMode.value;
7018
6881
  const prefix = buildMentionPrefix(props.mentions, width);
@@ -7031,15 +6894,13 @@ const TInput = defineComponent({
7031
6894
  else if (line > scrollY.value + height - 1) scrollY.value = clamp$3(line - (height - 1), 0, maxTop);
7032
6895
  }
7033
6896
  function setCursorByCell2D(cellX, cellY, extendSelection = false, e) {
7034
- const r = contentRect$1.value;
7035
- const w = Math.max(0, Math.floor(r.w));
7036
- const h$1 = Math.max(0, Math.floor(r.h));
7037
- if (w <= 0 || h$1 <= 0) return;
7038
- const width = w;
6897
+ const r = absRect.value;
6898
+ const { w: contentW, padX } = measureContent(r);
6899
+ const width = Math.max(1, contentW);
7039
6900
  const prefix = buildMentionPrefix(props.mentions, width);
7040
6901
  const prefixCells = prefix.cells;
7041
- const localX = clamp$3(cellX - r.x, 0, Math.max(0, w - 1));
7042
- const localY = clamp$3(cellY - r.y, 0, Math.max(0, h$1 - 1));
6902
+ const localX = clamp$3(cellX - (r.x + padX), 0, Math.max(0, contentW - 1));
6903
+ const localY = clamp$3(cellY - r.y, 0, Math.max(0, r.h - 1));
7043
6904
  const prefixVisible = scrollY.value === 0 && localY === 0 && prefixCells > 0;
7044
6905
  if (prefixVisible && localX < prefixCells) {
7045
6906
  for (const chip of prefix.chips) if (localX >= chip.start && localX < chip.end) {
@@ -7085,7 +6946,8 @@ const TInput = defineComponent({
7085
6946
  compositionText.value = "";
7086
6947
  pendingValue.value = nextValue;
7087
6948
  if (wrapMode.value) {
7088
- const w = Math.max(1, Math.floor(contentRect$1.value.w));
6949
+ const { w: contentW } = measureContent(absRect.value);
6950
+ const w = Math.max(1, contentW);
7089
6951
  const prefix = buildMentionPrefix(props.mentions, w);
7090
6952
  const firstW = Math.max(1, w - prefix.cells);
7091
6953
  desiredCol.value = indexToWrappedCellColFirstWidth(nextValue, c, firstW, w).col;
@@ -7104,7 +6966,8 @@ const TInput = defineComponent({
7104
6966
  } else anchor.value = null;
7105
6967
  cursor.value = clamp$3(nextCursor, 0, value.length);
7106
6968
  if (wrapMode.value) {
7107
- const w = Math.max(1, Math.floor(contentRect$1.value.w));
6969
+ const { w: contentW } = measureContent(absRect.value);
6970
+ const w = Math.max(1, contentW);
7108
6971
  const prefix = buildMentionPrefix(props.mentions, w);
7109
6972
  const firstW = Math.max(1, w - prefix.cells);
7110
6973
  desiredCol.value = indexToWrappedCellColFirstWidth(value, cursor.value, firstW, w).col;
@@ -7113,8 +6976,8 @@ const TInput = defineComponent({
7113
6976
  scheduler.invalidate();
7114
6977
  }
7115
6978
  watch([
7116
- () => contentRect$1.value.w,
7117
- () => contentRect$1.value.h,
6979
+ () => absRect.value.w,
6980
+ () => absRect.value.h,
7118
6981
  () => wrapMode.value
7119
6982
  ], () => {
7120
6983
  ensureCursorVisible();
@@ -7163,15 +7026,14 @@ const TInput = defineComponent({
7163
7026
  if (imeAnchor.value) imeAnchor.value = null;
7164
7027
  return;
7165
7028
  }
7166
- const r = contentRect$1.value;
7167
- const w = Math.max(0, Math.floor(r.w));
7168
- const h$1 = Math.max(0, Math.floor(r.h));
7169
- if (w <= 0 || h$1 <= 0) {
7029
+ const r = absRect.value;
7030
+ if (r.w <= 0 || r.h <= 0) {
7170
7031
  imeAnchor.value = null;
7171
7032
  return;
7172
7033
  }
7173
- const width = w;
7174
- const height = h$1;
7034
+ const { hAll, padX, w: contentW } = measureContent(r);
7035
+ const width = Math.max(1, contentW);
7036
+ const height = Math.max(1, hAll);
7175
7037
  const placeholderVisible = shouldShowPlaceholder.value;
7176
7038
  const offX = placeholderVisible ? 0 : scrollX.value;
7177
7039
  const offY = placeholderVisible ? 0 : scrollY.value;
@@ -7188,7 +7050,7 @@ const TInput = defineComponent({
7188
7050
  const cx = clamp$3(cxRaw, 0, Math.max(0, width - 1));
7189
7051
  const cy = clamp$3(cyRaw, 0, Math.max(0, height - 1));
7190
7052
  imeAnchor.value = {
7191
- cellX: r.x + cx,
7053
+ cellX: r.x + padX + cx,
7192
7054
  cellY: r.y + cy
7193
7055
  };
7194
7056
  });
@@ -7419,7 +7281,8 @@ const TInput = defineComponent({
7419
7281
  if (e.key === "ArrowUp" || e.key === "ArrowDown") {
7420
7282
  e.preventDefault();
7421
7283
  const wrap = wrapMode.value;
7422
- const width = Math.max(1, Math.floor(contentRect$1.value.w));
7284
+ const { w: contentW } = measureContent(absRect.value);
7285
+ const width = Math.max(1, contentW);
7423
7286
  const prefix = buildMentionPrefix(props.mentions, width);
7424
7287
  const firstW = Math.max(1, width - prefix.cells);
7425
7288
  const { line, col, lines } = wrap ? indexToWrappedCellColFirstWidth(value, cursor.value, firstW, width) : indexToLineCellCol(value, cursor.value);
@@ -7637,7 +7500,6 @@ const TInput = defineComponent({
7637
7500
  props.mentions,
7638
7501
  props.placeholder,
7639
7502
  props.placeholderWhenFocused,
7640
- props.padding,
7641
7503
  props.style,
7642
7504
  props.autoFocus,
7643
7505
  props.cursorBlink,
@@ -7656,10 +7518,8 @@ const TInput = defineComponent({
7656
7518
  ],
7657
7519
  paint: () => {
7658
7520
  if (!visible.value) return;
7659
- const rAll = absRect.value;
7660
- const wAll = Math.max(0, Math.floor(rAll.w));
7661
- const hAll = Math.max(0, Math.floor(rAll.h));
7662
- if (wAll <= 0 || hAll <= 0) return;
7521
+ const r = absRect.value;
7522
+ if (r.w <= 0 || r.h <= 0) return;
7663
7523
  const style = props.style ?? defaultStyle.value;
7664
7524
  const placeholderVisible = shouldShowPlaceholder.value;
7665
7525
  const offX = placeholderVisible ? 0 : scrollX.value;
@@ -7677,23 +7537,14 @@ const TInput = defineComponent({
7677
7537
  ...style,
7678
7538
  fg: "white"
7679
7539
  } : style;
7680
- const blankAll = " ".repeat(wAll);
7681
- for (let row = 0; row < hAll; row++) terminal.write(blankAll, {
7682
- x: rAll.x,
7683
- y: rAll.y + row,
7684
- style: baseStyle
7685
- });
7686
- const r = contentRect$1.value;
7687
- const w = Math.max(0, Math.floor(r.w));
7688
- const h$1 = Math.max(0, Math.floor(r.h));
7689
- if (w <= 0 || h$1 <= 0) return;
7690
- const x0 = r.x;
7691
- const width = Math.max(1, w);
7540
+ const { wAll, padX, w: contentW } = measureContent(r);
7541
+ const x0 = r.x + padX;
7542
+ const width = Math.max(1, contentW);
7692
7543
  const prefix = buildMentionPrefix(props.mentions, width);
7693
7544
  const prefixCells = prefix.cells;
7694
7545
  const firstWidth = Math.max(1, Math.max(1, width) - prefixCells);
7695
7546
  const lines = wrap ? wrapToLinesFirstWidth(text, firstWidth, width) : computeLines(text);
7696
- for (let row = 0; row < h$1; row++) {
7547
+ for (let row = 0; row < r.h; row++) {
7697
7548
  const lineIndex = offY + row;
7698
7549
  const info = lines[lineIndex];
7699
7550
  const raw = info ? text.slice(info.start, info.end).replace(/[\r\n]/g, "") : "";
@@ -7702,7 +7553,12 @@ const TInput = defineComponent({
7702
7553
  const rowTextW = hasPrefix ? firstWidth : width;
7703
7554
  const rawVisible = wrap ? sliceByCellsWindow(raw, 0, rowTextW) : sliceByCellsWindow(raw, offX, rowTextW);
7704
7555
  const visible$1 = padEndByCells$1(rawVisible, rowTextW);
7705
- const y = r.y + row;
7556
+ terminal.write(" ".repeat(wAll), {
7557
+ x: r.x,
7558
+ y: r.y + row,
7559
+ style: baseStyle
7560
+ });
7561
+ if (contentW <= 0) continue;
7706
7562
  if (hasPrefix) {
7707
7563
  const chipStyle = {
7708
7564
  ...style,
@@ -7713,18 +7569,18 @@ const TInput = defineComponent({
7713
7569
  if (!chip.label) continue;
7714
7570
  terminal.write(chip.label, {
7715
7571
  x: x0 + chip.start,
7716
- y,
7572
+ y: r.y + row,
7717
7573
  style: chipStyle
7718
7574
  });
7719
7575
  }
7720
7576
  terminal.write(visible$1, {
7721
7577
  x: x0 + rowPrefixCells,
7722
- y,
7578
+ y: r.y + row,
7723
7579
  style: baseStyle
7724
7580
  });
7725
7581
  } else terminal.write(visible$1, {
7726
7582
  x: x0,
7727
- y,
7583
+ y: r.y + row,
7728
7584
  style: baseStyle
7729
7585
  });
7730
7586
  }
@@ -7732,7 +7588,7 @@ const TInput = defineComponent({
7732
7588
  if (sel && !placeholderVisible) {
7733
7589
  const bg = "blueBright";
7734
7590
  const fg = "black";
7735
- for (let row = 0; row < h$1; row++) {
7591
+ for (let row = 0; row < r.h; row++) {
7736
7592
  const lineIndex = offY + row;
7737
7593
  const info = lines[lineIndex];
7738
7594
  if (!info) continue;
@@ -7746,14 +7602,14 @@ const TInput = defineComponent({
7746
7602
  for (let i = info.start; i < info.end;) {
7747
7603
  const ch = readCodePointAt(text, i);
7748
7604
  const nextI = i + ch.length;
7749
- const w$1 = charCellWidth(ch);
7750
- if (xCell$1 + w$1 > rowTextW) break;
7605
+ const w = charCellWidth(ch);
7606
+ if (xCell$1 + w > rowTextW) break;
7751
7607
  if (i >= sel.start && i < sel.end) terminal.put(xBase + xCell$1, y, ch, {
7752
7608
  ...style,
7753
7609
  fg,
7754
7610
  bg
7755
7611
  });
7756
- xCell$1 += w$1;
7612
+ xCell$1 += w;
7757
7613
  i = nextI;
7758
7614
  if (xCell$1 >= rowTextW) break;
7759
7615
  }
@@ -7764,8 +7620,8 @@ const TInput = defineComponent({
7764
7620
  for (let i = info.start; i < info.end;) {
7765
7621
  const ch = readCodePointAt(text, i);
7766
7622
  const nextI = i + ch.length;
7767
- const w$1 = charCellWidth(ch);
7768
- const nextCell = xCell + w$1;
7623
+ const w = charCellWidth(ch);
7624
+ const nextCell = xCell + w;
7769
7625
  if (nextCell <= offX) {
7770
7626
  xCell = nextCell;
7771
7627
  i = nextI;
@@ -7773,7 +7629,7 @@ const TInput = defineComponent({
7773
7629
  }
7774
7630
  if (xCell >= offX + rowTextW) break;
7775
7631
  const localX = xCell - offX;
7776
- if (localX + w$1 > rowTextW) break;
7632
+ if (localX + w > rowTextW) break;
7777
7633
  if (i >= sel.start && i < sel.end) terminal.put(xBase + localX, y, ch, {
7778
7634
  ...style,
7779
7635
  fg,
@@ -7795,7 +7651,7 @@ const TInput = defineComponent({
7795
7651
  const pos = wrap ? indexToWrappedCellColFirstWidth(cursorText, cursor.value, firstW, wAll$1) : indexToLineCellCol(cursorText, cursor.value);
7796
7652
  const cx0 = (pos.line === 0 ? prefixCells : 0) + (pos.col - offX);
7797
7653
  const cy = pos.line - offY;
7798
- if (cx0 >= 0 && cx0 < width && cy >= 0 && cy < h$1) {
7654
+ if (cx0 >= 0 && cx0 < width && cy >= 0 && cy < r.h) {
7799
7655
  const x = x0 + cx0;
7800
7656
  const y = r.y + cy;
7801
7657
  const avail = Math.max(0, width - cx0);
@@ -7823,7 +7679,7 @@ const TInput = defineComponent({
7823
7679
  const pos = wrap ? indexToWrappedCellColFirstWidth(cursorText, cursor.value, firstW, wAll$1) : indexToLineCellCol(cursorText, cursor.value);
7824
7680
  const cx0 = (pos.line === 0 ? prefixCells : 0) + (pos.col - offX);
7825
7681
  const cy = pos.line - offY;
7826
- if (cx0 >= 0 && cx0 < width && cy >= 0 && cy < h$1) {
7682
+ if (cx0 >= 0 && cx0 < width && cy >= 0 && cy < r.h) {
7827
7683
  const y = r.y + cy;
7828
7684
  let x = x0 + cx0;
7829
7685
  let cell = null;
@@ -8027,11 +7883,7 @@ const TInputBox = defineComponent({
8027
7883
  default: ""
8028
7884
  },
8029
7885
  padding: {
8030
- type: [
8031
- Number,
8032
- String,
8033
- Array
8034
- ],
7886
+ type: Number,
8035
7887
  default: 0
8036
7888
  },
8037
7889
  modelValue: {
@@ -8072,9 +7924,8 @@ const TInputBox = defineComponent({
8072
7924
  "blur"
8073
7925
  ],
8074
7926
  setup(props, { emit }) {
8075
- const pad = computed(() => normalizePadding(props.padding));
8076
- const innerW = computed(() => Math.max(0, Math.floor(props.w) - 2 - pad.value.left - pad.value.right));
8077
- const innerH = computed(() => Math.max(1, Math.floor(props.h) - 2 - pad.value.top - pad.value.bottom));
7927
+ const innerW = computed(() => Math.max(0, Math.floor(props.w) - 2 - Math.max(0, Math.floor(props.padding)) * 2));
7928
+ const innerH = computed(() => Math.max(1, Math.floor(props.h) - 2 - Math.max(0, Math.floor(props.padding)) * 2));
8078
7929
  return () => h(TBox, {
8079
7930
  x: props.x,
8080
7931
  y: props.y,
@@ -8135,14 +7986,6 @@ const TList = defineComponent({
8135
7986
  type: Number,
8136
7987
  default: 0
8137
7988
  },
8138
- padding: {
8139
- type: [
8140
- Number,
8141
- String,
8142
- Array
8143
- ],
8144
- default: 0
8145
- },
8146
7989
  items: {
8147
7990
  type: Array,
8148
7991
  required: true
@@ -8201,9 +8044,8 @@ const TList = defineComponent({
8201
8044
  watchEffect(() => {
8202
8045
  active.value = clamp$2(props.modelValue, 0, Math.max(0, props.items.length - 1));
8203
8046
  });
8204
- const contentRect$1 = computed(() => insetRect(absRect.value, props.padding));
8205
8047
  function ensureActiveVisible() {
8206
- const h$1 = Math.max(0, Math.floor(contentRect$1.value.h));
8048
+ const h$1 = Math.max(0, props.h);
8207
8049
  if (h$1 <= 0) return;
8208
8050
  const maxTop = Math.max(0, props.items.length - h$1);
8209
8051
  scrollTop.value = clamp$2(scrollTop.value, 0, maxTop);
@@ -8213,7 +8055,7 @@ const TList = defineComponent({
8213
8055
  watch([
8214
8056
  () => active.value,
8215
8057
  () => props.items.length,
8216
- () => contentRect$1.value.h
8058
+ () => props.h
8217
8059
  ], () => {
8218
8060
  ensureActiveVisible();
8219
8061
  }, { immediate: true });
@@ -8298,8 +8140,7 @@ const TList = defineComponent({
8298
8140
  focusable: true,
8299
8141
  handlers: {
8300
8142
  click: (e) => {
8301
- const r = contentRect$1.value;
8302
- if (e.cellY < r.y || e.cellY >= r.y + r.h) return;
8143
+ const r = absRect.value;
8303
8144
  const idx = scrollTop.value + (e.cellY - r.y);
8304
8145
  if (idx >= 0 && idx < props.items.length) {
8305
8146
  active.value = idx;
@@ -8308,8 +8149,7 @@ const TList = defineComponent({
8308
8149
  } else emit("close");
8309
8150
  },
8310
8151
  dblclick: (e) => {
8311
- const r = contentRect$1.value;
8312
- if (e.cellY < r.y || e.cellY >= r.y + r.h) return;
8152
+ const r = absRect.value;
8313
8153
  const idx = scrollTop.value + (e.cellY - r.y);
8314
8154
  if (idx >= 0 && idx < props.items.length) commit(idx);
8315
8155
  },
@@ -8317,8 +8157,7 @@ const TList = defineComponent({
8317
8157
  const delta = e.deltaY ?? 0;
8318
8158
  if (!delta) return;
8319
8159
  const dir = delta > 0 ? 1 : -1;
8320
- const h$1 = Math.max(0, Math.floor(contentRect$1.value.h));
8321
- const maxTop = Math.max(0, props.items.length - h$1);
8160
+ const maxTop = Math.max(0, props.items.length - props.h);
8322
8161
  const next = clamp$2(scrollTop.value + dir, 0, maxTop);
8323
8162
  if (next !== scrollTop.value) {
8324
8163
  scrollTop.value = next;
@@ -8367,17 +8206,9 @@ const TList = defineComponent({
8367
8206
  ],
8368
8207
  paint: () => {
8369
8208
  if (!visible.value) return;
8370
- const rAll = absRect.value;
8371
- if (rAll.w <= 0 || rAll.h <= 0) return;
8372
- const base = props.style ?? defaultStyle.value;
8373
- const r = contentRect$1.value;
8374
- const blankAll = " ".repeat(rAll.w);
8375
- for (let i = 0; i < rAll.h; i++) terminal.write(blankAll, {
8376
- x: rAll.x,
8377
- y: rAll.y + i,
8378
- style: base
8379
- });
8209
+ const r = absRect.value;
8380
8210
  if (r.w <= 0 || r.h <= 0) return;
8211
+ const base = props.style ?? defaultStyle.value;
8381
8212
  const top = clamp$2(scrollTop.value, 0, Math.max(0, props.items.length - r.h));
8382
8213
  for (let i = 0; i < r.h; i++) {
8383
8214
  const idx = top + i;
@@ -8438,14 +8269,6 @@ const TPathPicker = defineComponent({
8438
8269
  type: Number,
8439
8270
  default: 0
8440
8271
  },
8441
- padding: {
8442
- type: [
8443
- Number,
8444
- String,
8445
- Array
8446
- ],
8447
- default: 0
8448
- },
8449
8272
  workspace: {
8450
8273
  type: String,
8451
8274
  required: true
@@ -8503,12 +8326,13 @@ const TPathPicker = defineComponent({
8503
8326
  const scrollTop = ref(0);
8504
8327
  const error = ref(null);
8505
8328
  const inputH = 1;
8506
- const absRect = computed(() => {
8329
+ const listH = computed(() => Math.max(0, Math.floor(props.h) - inputH));
8330
+ const absListRect = computed(() => {
8507
8331
  const raw = {
8508
8332
  x: props.x,
8509
- y: props.y,
8333
+ y: props.y + inputH,
8510
8334
  w: props.w,
8511
- h: props.h
8335
+ h: listH.value
8512
8336
  };
8513
8337
  const translated = translateRect(raw, layout.originX, layout.originY);
8514
8338
  if (!layout.clipRect) return translated;
@@ -8519,49 +8343,6 @@ const TPathPicker = defineComponent({
8519
8343
  h: 0
8520
8344
  };
8521
8345
  });
8522
- const contentRect$1 = computed(() => insetRect(absRect.value, props.padding));
8523
- const listH = computed(() => Math.max(0, Math.floor(contentRect$1.value.h) - inputH));
8524
- const absListRect = computed(() => {
8525
- const c = contentRect$1.value;
8526
- const listRaw = {
8527
- x: c.x,
8528
- y: c.y + inputH,
8529
- w: c.w,
8530
- h: listH.value
8531
- };
8532
- return intersectRect(listRaw, absRect.value) ?? {
8533
- x: 0,
8534
- y: 0,
8535
- w: 0,
8536
- h: 0
8537
- };
8538
- });
8539
- useRenderNode(() => ({
8540
- zIndex: props.zIndex - 1,
8541
- rect: absRect.value,
8542
- deps: [
8543
- visible.value,
8544
- absRect.value,
8545
- props.style,
8546
- defaultStyle.value
8547
- ],
8548
- paint: (dirtyRows) => {
8549
- if (!visible.value) return;
8550
- const r = absRect.value;
8551
- if (r.w <= 0 || r.h <= 0) return;
8552
- const base = props.style ?? defaultStyle.value;
8553
- if (!dirtyRows) {
8554
- terminal.fill(r.x, r.y, r.w, r.h, " ", base);
8555
- return;
8556
- }
8557
- const y0 = Math.floor(r.y);
8558
- const y1 = y0 + Math.max(0, Math.floor(r.h));
8559
- for (const y of dirtyRows) {
8560
- if (y < y0 || y >= y1) continue;
8561
- terminal.fill(r.x, y, r.w, 1, " ", base);
8562
- }
8563
- }
8564
- }));
8565
8346
  function ensureActiveVisible() {
8566
8347
  const h$1 = Math.max(0, listH.value);
8567
8348
  if (h$1 <= 0) {
@@ -8779,7 +8560,7 @@ const TPathPicker = defineComponent({
8779
8560
  deps: [
8780
8561
  visible.value,
8781
8562
  absListRect.value,
8782
- contentRect$1.value.w,
8563
+ props.w,
8783
8564
  listH.value,
8784
8565
  props.style,
8785
8566
  defaultStyle.value,
@@ -8823,9 +8604,9 @@ const TPathPicker = defineComponent({
8823
8604
  }
8824
8605
  }));
8825
8606
  return () => h("span", rootProps, [h(TInput, {
8826
- "x": contentRect$1.value.x,
8827
- "y": contentRect$1.value.y,
8828
- "w": contentRect$1.value.w,
8607
+ "x": props.x,
8608
+ "y": props.y,
8609
+ "w": props.w,
8829
8610
  "h": inputH,
8830
8611
  "zIndex": props.zIndex,
8831
8612
  "modelValue": props.modelValue,
@@ -8875,14 +8656,6 @@ const TSelect = defineComponent({
8875
8656
  type: Number,
8876
8657
  default: 0
8877
8658
  },
8878
- padding: {
8879
- type: [
8880
- Number,
8881
- String,
8882
- Array
8883
- ],
8884
- default: 0
8885
- },
8886
8659
  options: {
8887
8660
  type: Array,
8888
8661
  required: true
@@ -8943,7 +8716,6 @@ const TSelect = defineComponent({
8943
8716
  return clamp(first, 0, max);
8944
8717
  })();
8945
8718
  const active = ref(initialActive);
8946
- const scrollTopLine = ref(0);
8947
8719
  const absRect = computed(() => {
8948
8720
  const raw = {
8949
8721
  x: props.x,
@@ -8960,7 +8732,6 @@ const TSelect = defineComponent({
8960
8732
  h: 0
8961
8733
  };
8962
8734
  });
8963
- const contentRect$1 = computed(() => insetRect(absRect.value, props.padding));
8964
8735
  watchEffect(() => {
8965
8736
  const max = Math.max(0, props.options.length - 1);
8966
8737
  if (!props.multiple) {
@@ -8970,9 +8741,6 @@ const TSelect = defineComponent({
8970
8741
  }
8971
8742
  active.value = clamp(active.value, 0, max);
8972
8743
  });
8973
- function getPrefixCells() {
8974
- return props.multiple ? textCellWidth$1("[x] ") : 0;
8975
- }
8976
8744
  function getOptionLabel(opt) {
8977
8745
  return typeof opt === "string" ? opt : opt.label;
8978
8746
  }
@@ -9034,105 +8802,12 @@ const TSelect = defineComponent({
9034
8802
  if (props.multiple) toggleMultiple(index);
9035
8803
  else commitSingle(index);
9036
8804
  }
9037
- function computeColumnLayout(totalW, hasDetail, prefixCells) {
9038
- totalW = Math.max(0, Math.floor(totalW));
9039
- if (!hasDetail || totalW <= 0) return {
9040
- labelW: totalW,
9041
- gapW: 0,
9042
- detailW: 0
9043
- };
9044
- const gapW = totalW >= 12 ? 2 : 1;
9045
- const minLabelText = 6;
9046
- const minLabelW = Math.min(totalW, prefixCells + minLabelText);
9047
- const minDetailW = Math.min(12, Math.max(6, Math.floor(totalW / 4)));
9048
- let detailW = clamp(Math.floor(totalW * .35), minDetailW, Math.max(0, totalW - gapW - minLabelW));
9049
- let labelW = Math.max(0, totalW - gapW - detailW);
9050
- if (labelW < minLabelW) {
9051
- detailW = Math.max(0, totalW - gapW - minLabelW);
9052
- labelW = Math.max(0, totalW - gapW - detailW);
9053
- }
9054
- if (detailW <= 0) return {
9055
- labelW: totalW,
9056
- gapW: 0,
9057
- detailW: 0
9058
- };
9059
- return {
9060
- labelW,
9061
- gapW,
9062
- detailW
9063
- };
9064
- }
9065
- function safeWrap(text, width) {
9066
- width = Math.max(0, Math.floor(width));
9067
- if (width <= 0) return [""];
9068
- return wrapByCells(text, width).map((l) => sliceByCells(l, width));
9069
- }
9070
- const optionLayouts = computed(() => {
9071
- const r = contentRect$1.value;
9072
- const w = Math.max(0, Math.floor(r.w));
9073
- const prefixCells = getPrefixCells();
9074
- const layouts = [];
9075
- const flat = [];
9076
- const starts = Array.from({ length: props.options.length }, () => 0);
9077
- let line = 0;
9078
- for (let i = 0; i < props.options.length; i++) {
9079
- const opt = props.options[i];
9080
- const label = sanitizeInlineText(getOptionLabel(opt));
9081
- const detail = getOptionDetail(opt);
9082
- const safeDetail = detail ? sanitizeInlineText(detail) : "";
9083
- const cols = computeColumnLayout(w, Boolean(safeDetail), prefixCells);
9084
- const labelTextW = Math.max(0, cols.labelW - prefixCells);
9085
- const labelLines = safeWrap(label, labelTextW);
9086
- const detailLines = cols.detailW > 0 && safeDetail ? safeWrap(safeDetail, cols.detailW) : [];
9087
- const height = Math.max(1, labelLines.length, detailLines.length || 0);
9088
- layouts.push({
9089
- labelLines,
9090
- detailLines,
9091
- height,
9092
- labelW: cols.labelW,
9093
- gapW: cols.gapW,
9094
- detailW: cols.detailW
9095
- });
9096
- starts[i] = line;
9097
- for (let j = 0; j < height; j++) flat.push({
9098
- optionIndex: i,
9099
- subLine: j
9100
- });
9101
- line += height;
9102
- }
9103
- return {
9104
- layouts,
9105
- flat,
9106
- starts,
9107
- totalLines: line,
9108
- contentW: w,
9109
- prefixCells
9110
- };
9111
- });
9112
- function ensureActiveVisible() {
9113
- var _layouts$idx;
9114
- const viewH = Math.max(0, Math.floor(contentRect$1.value.h));
9115
- const { layouts, starts, totalLines } = optionLayouts.value;
9116
- if (viewH <= 0 || totalLines <= 0) {
9117
- scrollTopLine.value = 0;
9118
- return;
9119
- }
9120
- const maxTop = Math.max(0, totalLines - viewH);
9121
- scrollTopLine.value = clamp(scrollTopLine.value, 0, maxTop);
9122
- const idx = clamp(active.value, 0, Math.max(0, layouts.length - 1));
9123
- const start = starts[idx] ?? 0;
9124
- const height = ((_layouts$idx = layouts[idx]) === null || _layouts$idx === void 0 ? void 0 : _layouts$idx.height) ?? 1;
9125
- const end = start + height - 1;
9126
- if (start < scrollTopLine.value) scrollTopLine.value = clamp(start, 0, maxTop);
9127
- else if (end >= scrollTopLine.value + viewH) scrollTopLine.value = clamp(end - (viewH - 1), 0, maxTop);
9128
- }
9129
8805
  function onKeydown(e) {
9130
8806
  emit("keydown", e);
9131
8807
  if (e.key === "ArrowUp") {
9132
8808
  e.preventDefault();
9133
8809
  active.value = clamp(active.value - 1, 0, Math.max(0, props.options.length - 1));
9134
8810
  if (!props.multiple) emit("update:modelValue", active.value);
9135
- ensureActiveVisible();
9136
8811
  scheduler.invalidate();
9137
8812
  return;
9138
8813
  }
@@ -9140,7 +8815,6 @@ const TSelect = defineComponent({
9140
8815
  e.preventDefault();
9141
8816
  active.value = clamp(active.value + 1, 0, Math.max(0, props.options.length - 1));
9142
8817
  if (!props.multiple) emit("update:modelValue", active.value);
9143
- ensureActiveVisible();
9144
8818
  scheduler.invalidate();
9145
8819
  return;
9146
8820
  }
@@ -9170,31 +8844,11 @@ const TSelect = defineComponent({
9170
8844
  focusable: true,
9171
8845
  handlers: {
9172
8846
  click: (e) => {
9173
- const r = contentRect$1.value;
9174
- if (e.cellY < r.y || e.cellY >= r.y + r.h) {
9175
- emit("close");
9176
- return;
9177
- }
9178
- const localRow = e.cellY - r.y;
9179
- const { flat } = optionLayouts.value;
9180
- const line = flat[scrollTopLine.value + localRow];
9181
- if (line) commit(line.optionIndex);
8847
+ const r = absRect.value;
8848
+ const idx = e.cellY - r.y;
8849
+ if (idx >= 0 && idx < props.options.length) commit(idx);
9182
8850
  else emit("close");
9183
8851
  },
9184
- wheel: (e) => {
9185
- const delta = e.deltaY ?? 0;
9186
- if (!delta) return;
9187
- const dir = delta > 0 ? 1 : -1;
9188
- const r = contentRect$1.value;
9189
- const viewH = Math.max(0, Math.floor(r.h));
9190
- const { totalLines } = optionLayouts.value;
9191
- const maxTop = Math.max(0, totalLines - viewH);
9192
- const next = clamp(scrollTopLine.value + dir, 0, maxTop);
9193
- if (next !== scrollTopLine.value) {
9194
- scrollTopLine.value = next;
9195
- scheduler.invalidate();
9196
- }
9197
- },
9198
8852
  focus: () => {
9199
8853
  focused.value = true;
9200
8854
  emit("focus");
@@ -9209,10 +8863,6 @@ const TSelect = defineComponent({
9209
8863
  keydown: onKeydown
9210
8864
  }
9211
8865
  }));
9212
- watchEffect(() => {
9213
- optionLayouts.value;
9214
- ensureActiveVisible();
9215
- });
9216
8866
  watchEffect(() => {
9217
8867
  if (!props.autoFocus) return;
9218
8868
  if (!visible.value) return;
@@ -9230,7 +8880,6 @@ const TSelect = defineComponent({
9230
8880
  absRect.value,
9231
8881
  props.w,
9232
8882
  props.h,
9233
- props.padding,
9234
8883
  props.options,
9235
8884
  props.modelValue,
9236
8885
  props.multiple,
@@ -9239,14 +8888,12 @@ const TSelect = defineComponent({
9239
8888
  props.highlightStyle,
9240
8889
  focused.value,
9241
8890
  active.value,
9242
- scrollTopLine.value,
9243
- optionLayouts.value,
9244
8891
  defaultStyle.value
9245
8892
  ],
9246
8893
  paint: () => {
9247
8894
  if (!visible.value) return;
9248
- const rAll = absRect.value;
9249
- if (rAll.w <= 0 || rAll.h <= 0) return;
8895
+ const r = absRect.value;
8896
+ if (r.w <= 0 || r.h <= 0) return;
9250
8897
  const base = props.style ?? defaultStyle.value;
9251
8898
  const highlightBase = props.highlightStyle ?? {
9252
8899
  ...base,
@@ -9261,75 +8908,58 @@ const TSelect = defineComponent({
9261
8908
  ...highlightBase,
9262
8909
  dim: true
9263
8910
  };
9264
- const blankAll = " ".repeat(rAll.w);
9265
- for (let i = 0; i < rAll.h; i++) terminal.write(blankAll, {
9266
- x: rAll.x,
9267
- y: rAll.y + i,
9268
- style: base
9269
- });
9270
- const r = contentRect$1.value;
9271
- if (r.w <= 0 || r.h <= 0) return;
9272
- const { layouts, flat, totalLines, prefixCells } = optionLayouts.value;
9273
8911
  const selectedSet = props.multiple ? new Set(getSelectedIndices()) : null;
9274
- const top = clamp(scrollTopLine.value, 0, Math.max(0, totalLines - r.h));
9275
- const prefixSpaces = props.multiple ? " ".repeat(prefixCells) : "";
9276
- const blank = " ".repeat(r.w);
9277
- for (let row = 0; row < r.h; row++) {
9278
- const y = r.y + row;
9279
- const lineIdx = top + row;
9280
- const line = flat[lineIdx];
9281
- if (!line) {
9282
- terminal.write(blank, {
9283
- x: r.x,
9284
- y,
9285
- style: base
9286
- });
9287
- continue;
9288
- }
9289
- const opt = props.options[line.optionIndex];
8912
+ for (let i = 0; i < r.h; i++) {
8913
+ const opt = props.options[i];
9290
8914
  if (!opt) {
9291
- terminal.write(blank, {
8915
+ terminal.write(" ".repeat(r.w), {
9292
8916
  x: r.x,
9293
- y,
8917
+ y: r.y + i,
9294
8918
  style: base
9295
8919
  });
9296
8920
  continue;
9297
8921
  }
9298
- const isActiveOpt = line.optionIndex === active.value;
9299
- const isHighlighted = props.multiple ? focused.value && isActiveOpt : isActiveOpt;
9300
- const rowStyle = isHighlighted ? highlightBase : base;
9301
- const detailStyle = isHighlighted ? highlightDetailStyle : detailDimStyle;
9302
- terminal.write(blank, {
9303
- x: r.x,
9304
- y,
9305
- style: rowStyle
9306
- });
9307
- const layout$1 = layouts[line.optionIndex];
9308
- const labelLine = (layout$1 === null || layout$1 === void 0 ? void 0 : layout$1.labelLines[line.subLine]) ?? "";
9309
- const prevVisibleLine = row > 0 ? flat[lineIdx - 1] : void 0;
9310
- const isFirstVisibleLineOfOption = !prevVisibleLine || prevVisibleLine.optionIndex !== line.optionIndex;
9311
- const detailLine = (() => {
9312
- if (!layout$1 || layout$1.detailW <= 0 || layout$1.detailLines.length === 0) return "";
9313
- if (layout$1.detailLines.length === 1) return isFirstVisibleLineOfOption ? layout$1.detailLines[0] ?? "" : "";
9314
- return layout$1.detailLines[line.subLine] ?? "";
9315
- })();
9316
- const isChecked = props.multiple ? selectedSet.has(line.optionIndex) : isActiveOpt;
8922
+ const isActiveRow = i === active.value;
8923
+ const isChecked = props.multiple ? selectedSet.has(i) : isActiveRow;
8924
+ const isHighlighted = props.multiple ? focused.value && isActiveRow : isActiveRow;
9317
8925
  const prefix = props.multiple ? isChecked ? "[x] " : "[ ] " : "";
9318
- const prefixPad = props.multiple ? isFirstVisibleLineOfOption ? prefix : prefixSpaces : "";
9319
- const labelTextW = Math.max(0, ((layout$1 === null || layout$1 === void 0 ? void 0 : layout$1.labelW) ?? r.w) - prefixCells);
9320
- const labelText = labelTextW > 0 ? sliceByCells(labelLine, labelTextW) : "";
9321
- const outLabel = padEndByCells(sliceByCells(`${prefixPad}${labelText}`, (layout$1 === null || layout$1 === void 0 ? void 0 : layout$1.labelW) ?? r.w), (layout$1 === null || layout$1 === void 0 ? void 0 : layout$1.labelW) ?? r.w);
9322
- terminal.write(outLabel, {
9323
- x: r.x,
9324
- y,
9325
- style: rowStyle
9326
- });
9327
- if (((layout$1 === null || layout$1 === void 0 ? void 0 : layout$1.detailW) ?? 0) > 0) {
9328
- const outDetail = padEndByCells(sliceByCells(detailLine, layout$1.detailW), layout$1.detailW);
9329
- terminal.write(outDetail, {
9330
- x: r.x + layout$1.labelW + layout$1.gapW,
9331
- y,
9332
- style: detailStyle
8926
+ const label = sanitizeInlineText(getOptionLabel(opt));
8927
+ const detail = getOptionDetail(opt);
8928
+ const rawDetail = detail ? sanitizeInlineText(detail) : "";
8929
+ const labelText = `${prefix}${label}`;
8930
+ const labelCells = textCellWidth$1(labelText);
8931
+ const minGap = 2;
8932
+ const availableForDetail = r.w - labelCells - minGap;
8933
+ if (rawDetail && availableForDetail >= 4) {
8934
+ const labelStyle = isHighlighted ? highlightBase : base;
8935
+ terminal.write(labelText, {
8936
+ x: r.x,
8937
+ y: r.y + i,
8938
+ style: labelStyle
8939
+ });
8940
+ const detailCells = textCellWidth$1(rawDetail);
8941
+ const actualDetailWidth = Math.min(detailCells, availableForDetail);
8942
+ const gapWidth = r.w - labelCells - actualDetailWidth;
8943
+ const gapStyle = isHighlighted ? highlightBase : base;
8944
+ terminal.write(" ".repeat(gapWidth), {
8945
+ x: r.x + labelCells,
8946
+ y: r.y + i,
8947
+ style: gapStyle
8948
+ });
8949
+ const detailText = sliceByCells(rawDetail, availableForDetail);
8950
+ const dStyle = isHighlighted ? highlightDetailStyle : detailDimStyle;
8951
+ terminal.write(detailText, {
8952
+ x: r.x + labelCells + gapWidth,
8953
+ y: r.y + i,
8954
+ style: dStyle
8955
+ });
8956
+ } else {
8957
+ const line = padEndByCells(sliceByCells(labelText, r.w), r.w);
8958
+ const style = isHighlighted ? highlightBase : base;
8959
+ terminal.write(line, {
8960
+ x: r.x,
8961
+ y: r.y + i,
8962
+ style
9333
8963
  });
9334
8964
  }
9335
8965
  }