@simon_he/vue-tui 1.0.0 → 1.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.
@@ -4,7 +4,7 @@ import "./wheel-scroll-vBRaQ7p-.js";
4
4
  import "./linkify-D_gzn9Xq.js";
5
5
  import "./terminal-selection-DBinO6p5.js";
6
6
  import "./frame-perf-C6Xfg85O.js";
7
- import { TLogLinksPanel, TLogMinimap, TLogScrollbar, TLogSearchBar, TLogSearchPager, TLogSearchResults, TLogView, TLogVirtualLinksPanel, TLogVirtualSearchResults, TTranscriptView, TVirtualList, createAppendOnlyLogStore, createTLogDensityBucketsFromMarkers, createTLogLevelPlugin, createTLogLineMatcherPlugin, createTLogLinkActionPlugin, createTLogOsc8LinkPlugin, createTLogUrlPlugin, detectTLogUrls, dispatchTLogPluginLinkAction, getTLogPluginMetadata, handleTLogKeymapEvent, matchesTLogKeyBinding, parseTLogAnnotatedText, resolveTLogLinksPanelTheme, resolveTLogMinimapTheme, resolveTLogScrollbarTheme, resolveTLogSearchBarTheme, resolveTLogSearchPagerTheme, resolveTLogSearchResultsTheme, resolveTLogViewTheme, stripTLogAnsiText, tlogDarkPreset, tlogDarkTheme, tlogDefaultKeymap, tlogDefaultPreset, tlogDefaultTheme, tlogHighContrastKeymap, tlogHighContrastPreset, tlogHighContrastTheme, toTLogExternalLinkFromVisibleLink, useTLogLinkController, useTLogRetainedIndex, useTLogSearchController, useTLogSearchResultsPage, useTLogVirtualSearchResults } from "./tlog-theme-qPBt5rge.js";
7
+ import { TLogLinksPanel, TLogMinimap, TLogScrollbar, TLogSearchBar, TLogSearchPager, TLogSearchResults, TLogView, TLogVirtualLinksPanel, TLogVirtualSearchResults, TTranscriptView, TVirtualList, createAppendOnlyLogStore, createTLogDensityBucketsFromMarkers, createTLogLevelPlugin, createTLogLineMatcherPlugin, createTLogLinkActionPlugin, createTLogOsc8LinkPlugin, createTLogUrlPlugin, detectTLogUrls, dispatchTLogPluginLinkAction, getTLogPluginMetadata, handleTLogKeymapEvent, matchesTLogKeyBinding, parseTLogAnnotatedText, resolveTLogLinksPanelTheme, resolveTLogMinimapTheme, resolveTLogScrollbarTheme, resolveTLogSearchBarTheme, resolveTLogSearchPagerTheme, resolveTLogSearchResultsTheme, resolveTLogViewTheme, stripTLogAnsiText, tlogDarkPreset, tlogDarkTheme, tlogDefaultKeymap, tlogDefaultPreset, tlogDefaultTheme, tlogHighContrastKeymap, tlogHighContrastPreset, tlogHighContrastTheme, toTLogExternalLinkFromVisibleLink, useTLogLinkController, useTLogRetainedIndex, useTLogSearchController, useTLogSearchResultsPage, useTLogVirtualSearchResults } from "./tlog-theme-CvLFNMwk.js";
8
8
  import { ref } from "vue";
9
9
 
10
10
  //#region src/vue/log/tlog-session.ts
package/dist/index.cjs CHANGED
@@ -714,7 +714,7 @@ function clamp(n, min, max) {
714
714
  function setFingerprintFn(buffer, fn) {
715
715
  buffer.fingerprintFn = fn;
716
716
  const len = buffer.rows * buffer.cols;
717
- if (!len) {
717
+ if (!fn || !len) {
718
718
  buffer.soaFingerprints = null;
719
719
  return;
720
720
  }
@@ -732,7 +732,12 @@ function setFingerprintFn(buffer, fn) {
732
732
  function getRowFingerprints(buffer, y) {
733
733
  if (!buffer.soaFingerprints)
734
734
  return null;
735
- const physY = physicalRowIndex(buffer, y);
735
+ if (buffer.rows <= 0 || buffer.cols <= 0)
736
+ return null;
737
+ const yy = Math.floor(y);
738
+ if (!Number.isFinite(yy) || yy < 0 || yy >= buffer.rows)
739
+ return null;
740
+ const physY = physicalRowIndex(buffer, yy);
736
741
  const base = physY * buffer.cols;
737
742
  return buffer.soaFingerprints.subarray(base, base + buffer.cols);
738
743
  }
@@ -2015,11 +2020,17 @@ function createTerminal(opts) {
2015
2020
  },
2016
2021
  setFingerprintFn(fn) {
2017
2022
  assertNotDisposed();
2018
- base.setFingerprintFn(fn);
2023
+ const state = getPlaneState(plane);
2024
+ setFingerprintFn(state.buffer, fn);
2019
2025
  },
2020
2026
  getRowFingerprints(y) {
2021
2027
  assertNotDisposed();
2022
- return base.getRowFingerprints(y);
2028
+ const yy = Math.floor(y);
2029
+ const state = getPlaneState(plane);
2030
+ if (!Number.isFinite(yy) || yy < 0 || yy >= state.buffer.rows) {
2031
+ throw new RangeError("Row out of bounds");
2032
+ }
2033
+ return getRowFingerprints(state.buffer, yy);
2023
2034
  }
2024
2035
  };
2025
2036
  planeTerminals.set(plane, api);
@@ -2213,7 +2224,11 @@ function createTerminal(opts) {
2213
2224
  },
2214
2225
  getRowFingerprints(y) {
2215
2226
  assertNotDisposed();
2216
- return getRowFingerprints(compositeBuffer, y);
2227
+ const yy = Math.floor(y);
2228
+ if (!Number.isFinite(yy) || yy < 0 || yy >= compositeBuffer.rows) {
2229
+ throw new RangeError("Row out of bounds");
2230
+ }
2231
+ return getRowFingerprints(compositeBuffer, yy);
2217
2232
  }
2218
2233
  };
2219
2234
  base[TERMINAL_PLANE_INTERNALS] = {
@@ -14463,22 +14478,40 @@ function normalizeVisibleLimit(value) {
14463
14478
  function isCommandPaletteRowSelectable(item) {
14464
14479
  return Boolean(item && item.kind !== "separator" && item.kind !== "group" && !item.disabled);
14465
14480
  }
14466
- function substringMatcher(item, query) {
14467
- const q = query.trim().toLowerCase();
14468
- if (!q)
14469
- return { score: 0 };
14470
- const labelRanges = computeCommandPaletteMatchRanges(item.label, q);
14471
- const detailRanges = item.detail ? computeCommandPaletteMatchRanges(item.detail, q) : [];
14472
- const keywordMatch = (item.keywords ?? []).some(
14473
- (keyword) => String(keyword ?? "").toLowerCase().includes(q)
14474
- );
14475
- if (!labelRanges.length && !detailRanges.length && !keywordMatch)
14476
- return null;
14477
- return {
14478
- score: labelRanges.length ? 100 : detailRanges.length ? 50 : 10,
14479
- labelRanges,
14480
- detailRanges
14481
- };
14481
+ function defaultSubstringEntries(sourceItems, query) {
14482
+ const q = query.trim();
14483
+ if (!q) {
14484
+ return sourceItems.map((item, sourceIndex) => ({
14485
+ item,
14486
+ sourceIndex,
14487
+ match: { score: 0 }
14488
+ }));
14489
+ }
14490
+ const needle = q.toLowerCase();
14491
+ const labelMatches = [];
14492
+ const detailMatches = [];
14493
+ const keywordMatches = [];
14494
+ for (let sourceIndex = 0; sourceIndex < sourceItems.length; sourceIndex++) {
14495
+ const item = sourceItems[sourceIndex];
14496
+ if (item.kind === "separator" || item.kind === "group")
14497
+ continue;
14498
+ const label = String(item.label ?? "");
14499
+ const detail = item.detail == null ? "" : String(item.detail);
14500
+ if (label.toLowerCase().includes(needle)) {
14501
+ labelMatches.push({ item, sourceIndex, match: { score: 100 } });
14502
+ continue;
14503
+ }
14504
+ if (detail.toLowerCase().includes(needle)) {
14505
+ detailMatches.push({ item, sourceIndex, match: { score: 50 } });
14506
+ continue;
14507
+ }
14508
+ if ((item.keywords ?? []).some(
14509
+ (keyword) => String(keyword ?? "").toLowerCase().includes(needle)
14510
+ )) {
14511
+ keywordMatches.push({ item, sourceIndex, match: { score: 10 } });
14512
+ }
14513
+ }
14514
+ return labelMatches.concat(detailMatches, keywordMatches);
14482
14515
  }
14483
14516
  function fuzzyMatcher(item, query) {
14484
14517
  const q = query.trim().toLowerCase();
@@ -14646,14 +14679,22 @@ var TCommandPalette = (0, import_vue20.defineComponent)({
14646
14679
  const filteredEntries = (0, import_vue20.computed)(() => {
14647
14680
  const q = query.value.trim();
14648
14681
  const sourceItems = props.itemsProvider ? providerItems.value ?? [] : props.items;
14649
- const matcher = props.matcher ?? (props.filterStrategy === "fuzzy" ? fuzzyMatcher : substringMatcher);
14650
- const entries = sourceItems.flatMap((item, sourceIndex) => {
14682
+ if (!props.matcher && props.filterStrategy === "substring") {
14683
+ return defaultSubstringEntries(sourceItems, q);
14684
+ }
14685
+ const matcher = props.matcher ?? fuzzyMatcher;
14686
+ const entries = [];
14687
+ for (let sourceIndex = 0; sourceIndex < sourceItems.length; sourceIndex++) {
14688
+ const item = sourceItems[sourceIndex];
14651
14689
  if (item.kind === "separator" || item.kind === "group") {
14652
- return q ? [] : [{ item, sourceIndex, match: { score: 0 } }];
14690
+ if (!q)
14691
+ entries.push({ item, sourceIndex, match: { score: 0 } });
14692
+ continue;
14653
14693
  }
14654
14694
  const match = matcher(item, q);
14655
- return match ? [{ item, sourceIndex, match }] : [];
14656
- });
14695
+ if (match)
14696
+ entries.push({ item, sourceIndex, match });
14697
+ }
14657
14698
  entries.sort((a, b) => b.match.score - a.match.score || a.sourceIndex - b.sourceIndex);
14658
14699
  return entries;
14659
14700
  });
@@ -15273,6 +15314,20 @@ function rowKey(row, index, key) {
15273
15314
  function sameRowKey(a, b) {
15274
15315
  return Object.is(a, b);
15275
15316
  }
15317
+ function selectedRowKeyIndex(keys) {
15318
+ if (!keys?.length)
15319
+ return null;
15320
+ const indexed = /* @__PURE__ */ new Set();
15321
+ for (let index = 0; index < keys.length; index++) {
15322
+ if (!(index in keys))
15323
+ continue;
15324
+ const key = keys[index];
15325
+ if (typeof key === "number" && key === 0)
15326
+ return null;
15327
+ indexed.add(key);
15328
+ }
15329
+ return indexed;
15330
+ }
15276
15331
  var TTable = (0, import_vue21.defineComponent)({
15277
15332
  name: "TTable",
15278
15333
  props: {
@@ -15345,10 +15400,22 @@ var TTable = (0, import_vue21.defineComponent)({
15345
15400
  const activeRowStyle = (0, import_vue21.computed)(
15346
15401
  () => mergeStyle(theme.value.components.TTable?.activeStyle, props.activeStyle)
15347
15402
  );
15403
+ const selectedRowKeysIndex = (0, import_vue21.computed)(() => selectedRowKeyIndex(props.selectedRowKeys));
15348
15404
  const bodyRows = (0, import_vue21.computed)(() => {
15349
15405
  const top = props.header ? 2 : 0;
15350
15406
  return props.rows.slice(0, Math.max(0, props.h - top));
15351
15407
  });
15408
+ function isRowSelected(key) {
15409
+ if (props.selectedRowKey !== void 0 && sameRowKey(key, props.selectedRowKey))
15410
+ return true;
15411
+ const selectedKeys = props.selectedRowKeys;
15412
+ if (!selectedKeys?.length)
15413
+ return false;
15414
+ const indexed = selectedRowKeysIndex.value;
15415
+ if (indexed)
15416
+ return indexed.has(key);
15417
+ return selectedKeys.some((candidate) => sameRowKey(candidate, key));
15418
+ }
15352
15419
  return () => {
15353
15420
  const children = [];
15354
15421
  if (props.header && props.h > 0) {
@@ -15426,7 +15493,7 @@ var TTable = (0, import_vue21.defineComponent)({
15426
15493
  const row = bodyRows.value[index];
15427
15494
  const y = (props.header ? 2 : 0) + index;
15428
15495
  const key = rowKey(row, index, props.rowKey);
15429
- const selected = props.selectedRowKey !== void 0 && sameRowKey(key, props.selectedRowKey) || Boolean(props.selectedRowKeys?.some((candidate) => sameRowKey(candidate, key)));
15496
+ const selected = isRowSelected(key);
15430
15497
  const active = props.activeRowKey !== void 0 && sameRowKey(key, props.activeRowKey);
15431
15498
  children.push(
15432
15499
  (0, import_vue21.h)(
@@ -15595,44 +15662,59 @@ var TDataTable = (0, import_vue22.defineComponent)({
15595
15662
  },
15596
15663
  setup(props, { emit }) {
15597
15664
  const innerScrollTop = (0, import_vue22.ref)(0);
15598
- const indexedRows = (0, import_vue22.computed)(
15599
- () => props.rows.map((row, originalIndex) => ({ row, originalIndex }))
15665
+ const hasLocalFilter = (0, import_vue22.computed)(
15666
+ () => !props.manualFilter && props.filterable && Boolean(props.filter.trim())
15600
15667
  );
15668
+ const hasLocalSort = (0, import_vue22.computed)(
15669
+ () => !props.manualSort && props.sortable && Boolean(props.sortBy)
15670
+ );
15671
+ const indexedRows = (0, import_vue22.computed)(() => {
15672
+ if (!hasLocalFilter.value && !hasLocalSort.value)
15673
+ return null;
15674
+ return props.rows.map((row, originalIndex) => ({ row, originalIndex }));
15675
+ });
15601
15676
  const filteredRows = (0, import_vue22.computed)(() => {
15602
- if (props.manualFilter)
15603
- return indexedRows.value;
15604
- if (!props.filterable || !props.filter.trim())
15605
- return indexedRows.value;
15677
+ const rows = indexedRows.value;
15678
+ if (!rows)
15679
+ return null;
15680
+ if (!hasLocalFilter.value)
15681
+ return rows;
15606
15682
  const query = props.filter.trim().toLowerCase();
15607
15683
  if (props.filterPredicate) {
15608
- return indexedRows.value.filter(
15684
+ return rows.filter(
15609
15685
  ({ row, originalIndex }) => props.filterPredicate(row, query, props.columns, originalIndex)
15610
15686
  );
15611
15687
  }
15612
- return indexedRows.value.filter(
15688
+ return rows.filter(
15613
15689
  ({ row, originalIndex }) => props.columns.some(
15614
15690
  (column) => displayValue(column, row, originalIndex).toLowerCase().includes(query)
15615
15691
  )
15616
15692
  );
15617
15693
  });
15618
15694
  const sortedRows = (0, import_vue22.computed)(() => {
15619
- const rows = [...filteredRows.value];
15620
- if (props.manualSort || !props.sortable || !props.sortBy)
15695
+ const rows = filteredRows.value;
15696
+ if (!rows)
15697
+ return null;
15698
+ if (!hasLocalSort.value)
15621
15699
  return rows;
15700
+ const sorted = [...rows];
15622
15701
  const column = props.columns.find((candidate) => candidate.key === props.sortBy);
15623
- rows.sort((a, b) => {
15702
+ sorted.sort((a, b) => {
15624
15703
  const result = props.sorter && column ? props.sorter(a.row, b.row, column) : compareValues(a.row[props.sortBy], b.row[props.sortBy]);
15625
15704
  return props.sortDirection === "desc" ? -result : result;
15626
15705
  });
15627
- return rows;
15706
+ return sorted;
15628
15707
  });
15629
15708
  function nonNegativeInteger(value) {
15630
15709
  const n = Math.floor(Number(value));
15631
15710
  return Number.isFinite(n) ? Math.max(0, n) : 0;
15632
15711
  }
15633
15712
  const visibleRowCapacity = (0, import_vue22.computed)(() => Math.max(0, nonNegativeInteger(props.h) - 2));
15713
+ function processedRowCount() {
15714
+ return sortedRows.value?.length ?? props.rows.length;
15715
+ }
15634
15716
  function maxScrollTop2() {
15635
- return Math.max(0, sortedRows.value.length - visibleRowCapacity.value);
15717
+ return Math.max(0, processedRowCount() - visibleRowCapacity.value);
15636
15718
  }
15637
15719
  function clampScrollTop2(value) {
15638
15720
  return Math.min(maxScrollTop2(), nonNegativeInteger(value));
@@ -15656,12 +15738,27 @@ var TDataTable = (0, import_vue22.defineComponent)({
15656
15738
  },
15657
15739
  { immediate: true }
15658
15740
  );
15659
- const visibleRows = (0, import_vue22.computed)(
15660
- () => sortedRows.value.slice(
15661
- normalizedScrollTop.value,
15662
- normalizedScrollTop.value + visibleRowCapacity.value
15663
- )
15664
- );
15741
+ function dataEntryAt(absoluteIndex) {
15742
+ const rows = sortedRows.value;
15743
+ if (rows)
15744
+ return rows[absoluteIndex];
15745
+ const row = props.rows[absoluteIndex];
15746
+ return row ? { row, originalIndex: absoluteIndex } : void 0;
15747
+ }
15748
+ function originalIndexForAbsoluteIndex(absoluteIndex) {
15749
+ return dataEntryAt(absoluteIndex)?.originalIndex ?? absoluteIndex;
15750
+ }
15751
+ const visibleRows = (0, import_vue22.computed)(() => {
15752
+ const top = normalizedScrollTop.value;
15753
+ const bottom = top + visibleRowCapacity.value;
15754
+ const rows = sortedRows.value;
15755
+ if (rows)
15756
+ return rows.slice(top, bottom);
15757
+ return props.rows.slice(top, bottom).map((row, index) => ({
15758
+ row,
15759
+ originalIndex: top + index
15760
+ }));
15761
+ });
15665
15762
  const tableRows = (0, import_vue22.computed)(() => visibleRows.value.map(({ row }) => row));
15666
15763
  const activeAbsoluteIndex = (0, import_vue22.ref)(null);
15667
15764
  const activeRowIdentity = (0, import_vue22.ref)(NO_ACTIVE_ROW);
@@ -15670,7 +15767,7 @@ var TDataTable = (0, import_vue22.defineComponent)({
15670
15767
  () => props.columns.map((column) => {
15671
15768
  const format = column.format ? (value, row, visibleIndex) => {
15672
15769
  const absoluteIndex = normalizedScrollTop.value + visibleIndex;
15673
- const originalIndex = sortedRows.value[absoluteIndex]?.originalIndex ?? absoluteIndex;
15770
+ const originalIndex = originalIndexForAbsoluteIndex(absoluteIndex);
15674
15771
  return column.format(value, row, originalIndex);
15675
15772
  } : void 0;
15676
15773
  if (!props.sortable || column.key !== props.sortBy) {
@@ -15682,7 +15779,7 @@ var TDataTable = (0, import_vue22.defineComponent)({
15682
15779
  );
15683
15780
  function originalIndexAt(index) {
15684
15781
  const absoluteIndex = normalizedScrollTop.value + index;
15685
- return sortedRows.value[absoluteIndex]?.originalIndex ?? absoluteIndex;
15782
+ return originalIndexForAbsoluteIndex(absoluteIndex);
15686
15783
  }
15687
15784
  function dataTableRowKey(row, index) {
15688
15785
  return rowKey2(row, originalIndexAt(index), props.rowKey);
@@ -15703,14 +15800,28 @@ var TDataTable = (0, import_vue22.defineComponent)({
15703
15800
  const activeRowKey = (0, import_vue22.computed)(
15704
15801
  () => activeRowIdentity.value === NO_ACTIVE_ROW ? void 0 : activeRowIdentity.value
15705
15802
  );
15803
+ const activeRawRowKey = (0, import_vue22.computed)(() => {
15804
+ if (activeAbsoluteIndex.value == null || sortedRows.value)
15805
+ return NO_ACTIVE_ROW;
15806
+ const index = activeAbsoluteIndex.value;
15807
+ const row = props.rows[index];
15808
+ return row ? rowKey2(row, index, props.rowKey) : NO_ACTIVE_ROW;
15809
+ });
15810
+ function findDataIndexByKey(key) {
15811
+ const rows = sortedRows.value;
15812
+ if (rows) {
15813
+ return rows.findIndex((entry) => Object.is(dataRowKey(entry), key));
15814
+ }
15815
+ return props.rows.findIndex(
15816
+ (row, index) => Object.is(rowKey2(row, index, props.rowKey), key)
15817
+ );
15818
+ }
15706
15819
  (0, import_vue22.watch)(
15707
- () => [props.rowKey, ...sortedRows.value.map((entry) => dataRowKey(entry))],
15820
+ () => [props.rowKey, props.rows, sortedRows.value, activeRowIdentity.value],
15708
15821
  () => {
15709
15822
  if (activeRowIdentity.value === NO_ACTIVE_ROW)
15710
15823
  return;
15711
- const nextIndex = sortedRows.value.findIndex(
15712
- (entry) => Object.is(dataRowKey(entry), activeRowIdentity.value)
15713
- );
15824
+ const nextIndex = findDataIndexByKey(activeRowIdentity.value);
15714
15825
  if (nextIndex < 0) {
15715
15826
  clearActiveRow();
15716
15827
  return;
@@ -15718,9 +15829,22 @@ var TDataTable = (0, import_vue22.defineComponent)({
15718
15829
  activeAbsoluteIndex.value = nextIndex;
15719
15830
  }
15720
15831
  );
15832
+ (0, import_vue22.watch)(
15833
+ () => [props.rowKey, activeRawRowKey.value],
15834
+ ([, key]) => {
15835
+ if (activeRowIdentity.value === NO_ACTIVE_ROW)
15836
+ return;
15837
+ if (key === NO_ACTIVE_ROW) {
15838
+ clearActiveRow();
15839
+ return;
15840
+ }
15841
+ if (!Object.is(activeRowIdentity.value, key))
15842
+ activeRowIdentity.value = key;
15843
+ }
15844
+ );
15721
15845
  function setActiveAbsoluteIndex(absoluteIndex) {
15722
- const clamped = Math.max(0, Math.min(sortedRows.value.length - 1, absoluteIndex));
15723
- const entry = sortedRows.value[clamped];
15846
+ const clamped = Math.max(0, Math.min(processedRowCount() - 1, absoluteIndex));
15847
+ const entry = dataEntryAt(clamped);
15724
15848
  if (!entry) {
15725
15849
  clearActiveRow();
15726
15850
  return null;
@@ -15796,7 +15920,7 @@ var TDataTable = (0, import_vue22.defineComponent)({
15796
15920
  const active = setActiveAbsoluteIndex(current);
15797
15921
  if (!active)
15798
15922
  return;
15799
- const entry = sortedRows.value[active.dataIndex];
15923
+ const entry = dataEntryAt(active.dataIndex);
15800
15924
  if (!entry)
15801
15925
  return;
15802
15926
  const visibleIndex = active.dataIndex - active.scrollTop;
@@ -18786,6 +18910,49 @@ var TSelect = (0, import_vue28.defineComponent)({
18786
18910
  const typeaheadQuery = (0, import_vue28.ref)("");
18787
18911
  const query = (0, import_vue28.computed)(() => props.query ?? innerQuery.value);
18788
18912
  const options = (0, import_vue28.computed)(() => providerOptions.value ?? props.options);
18913
+ function getOptionLabel(opt) {
18914
+ return isOptionObject(opt) ? opt.label : opt;
18915
+ }
18916
+ function getOptionKind(opt) {
18917
+ return isOptionObject(opt) ? opt.kind : void 0;
18918
+ }
18919
+ function getOptionValue(opt, index) {
18920
+ if (props.valueMode === "index")
18921
+ return index;
18922
+ if (props.valueMode === "option")
18923
+ return opt;
18924
+ return isOptionObject(opt) && "value" in opt ? opt.value : getOptionLabel(opt);
18925
+ }
18926
+ const optionValueIndex = (0, import_vue28.computed)(() => {
18927
+ if (props.valueMode === "index")
18928
+ return null;
18929
+ const indexed = /* @__PURE__ */ new Map();
18930
+ const opts = options.value;
18931
+ for (let index = 0; index < opts.length; index++) {
18932
+ const value = getOptionValue(opts[index], index);
18933
+ if (typeof value === "number" && value === 0)
18934
+ continue;
18935
+ if (!indexed.has(value))
18936
+ indexed.set(value, index);
18937
+ }
18938
+ return indexed;
18939
+ });
18940
+ function valuesEqual(a, b) {
18941
+ return Object.is(a, b);
18942
+ }
18943
+ function modelIndex(value, useValueIndex = props.multiple) {
18944
+ if (props.valueMode === "index")
18945
+ return normalizeModelIndex(value);
18946
+ if (useValueIndex) {
18947
+ const indexed = optionValueIndex.value;
18948
+ const cached = indexed?.get(value);
18949
+ if (cached != null)
18950
+ return cached;
18951
+ }
18952
+ return options.value.findIndex(
18953
+ (opt, optIndex) => valuesEqual(getOptionValue(opt, optIndex), value)
18954
+ );
18955
+ }
18789
18956
  const initialActive = (() => {
18790
18957
  const max = Math.max(0, options.value.length - 1);
18791
18958
  if (!props.multiple) {
@@ -18843,29 +19010,6 @@ var TSelect = (0, import_vue28.defineComponent)({
18843
19010
  }
18844
19011
  innerActive.value = clamp10(active.value, 0, max);
18845
19012
  });
18846
- function getOptionLabel(opt) {
18847
- return isOptionObject(opt) ? opt.label : opt;
18848
- }
18849
- function getOptionKind(opt) {
18850
- return isOptionObject(opt) ? opt.kind : void 0;
18851
- }
18852
- function getOptionValue(opt, index) {
18853
- if (props.valueMode === "index")
18854
- return index;
18855
- if (props.valueMode === "option")
18856
- return opt;
18857
- return isOptionObject(opt) && "value" in opt ? opt.value : getOptionLabel(opt);
18858
- }
18859
- function valuesEqual(a, b) {
18860
- return Object.is(a, b);
18861
- }
18862
- function modelIndex(value) {
18863
- if (props.valueMode === "index")
18864
- return normalizeModelIndex(value);
18865
- return options.value.findIndex(
18866
- (opt, optIndex) => valuesEqual(getOptionValue(opt, optIndex), value)
18867
- );
18868
- }
18869
19013
  function isOptionInteractive(opt) {
18870
19014
  if (!opt)
18871
19015
  return false;
@@ -19517,16 +19661,24 @@ var TSelect = (0, import_vue28.defineComponent)({
19517
19661
 
19518
19662
  // src/vue/components/TTree.ts
19519
19663
  var import_vue29 = require("vue");
19520
- function flattenTree(nodes, expanded, depth = 0, out = []) {
19664
+ function flattenTree(nodes, expanded, limit, depth = 0, out = []) {
19665
+ if (out.length >= limit)
19666
+ return out;
19521
19667
  for (const node of nodes) {
19668
+ if (out.length >= limit)
19669
+ break;
19522
19670
  const expandable = Boolean(node.children?.length);
19523
19671
  const isExpanded = expanded.has(node.id);
19524
19672
  out.push({ node, depth, expandable, expanded: isExpanded });
19525
19673
  if (expandable && isExpanded)
19526
- flattenTree(node.children, expanded, depth + 1, out);
19674
+ flattenTree(node.children, expanded, limit, depth + 1, out);
19527
19675
  }
19528
19676
  return out;
19529
19677
  }
19678
+ function visibleRowLimit(height) {
19679
+ const limit = Math.floor(height);
19680
+ return Number.isFinite(limit) ? Math.max(0, limit) : 0;
19681
+ }
19530
19682
  var TTree = (0, import_vue29.defineComponent)({
19531
19683
  name: "TTree",
19532
19684
  props: {
@@ -19560,7 +19712,9 @@ var TTree = (0, import_vue29.defineComponent)({
19560
19712
  const { defaultStyle } = useTerminal();
19561
19713
  const baseStyle = (0, import_vue29.computed)(() => mergeStyle(defaultStyle.value, props.style));
19562
19714
  const expandedSet = (0, import_vue29.computed)(() => new Set(props.expandedIds));
19563
- const rows = (0, import_vue29.computed)(() => flattenTree(props.nodes, expandedSet.value).slice(0, props.h));
19715
+ const rows = (0, import_vue29.computed)(
19716
+ () => flattenTree(props.nodes, expandedSet.value, visibleRowLimit(props.h))
19717
+ );
19564
19718
  function toggle(item) {
19565
19719
  if (item.node.disabled || !item.expandable)
19566
19720
  return;
package/dist/index.js CHANGED
@@ -1,16 +1,16 @@
1
- import { createTerminal } from "./create-terminal-C2oiWFJU.js";
1
+ import { createTerminal } from "./create-terminal-DBFNYr8f.js";
2
2
  import "./hyperlink-Bn02UXJb.js";
3
3
  import "./sgr-BmzxEjAO.js";
4
4
  import "./ansi-palette-CNXqFciC.js";
5
- import { createDomRenderer } from "./dom-renderer-BqGijQID.js";
5
+ import { createDomRenderer } from "./dom-renderer-BniJSQyX.js";
6
6
  import "./wheel-scroll-vBRaQ7p-.js";
7
7
  import { TView, createTheme, linkifyTextSegments, tuiDefaultTheme } from "./linkify-D_gzn9Xq.js";
8
8
  import "./runtime-rfcZCyJq.js";
9
9
  import "./trace-CjzYeIxN.js";
10
10
  import "./env-Cl8qmNFN.js";
11
- import { TAutocompleteInput, TBadge, TCheckbox, TCode, TDataTable, TDivider, TFormField, TLink, TLinkifyText, TList, TPasswordInput, TRadioGroup, TSlider, TSwitch, TTable, TTag, TTree, TerminalProvider, createTInputHostPlugin } from "./TTree-DK_DQBYm.js";
11
+ import { TAutocompleteInput, TBadge, TCheckbox, TCode, TDataTable, TDivider, TFormField, TLink, TLinkifyText, TList, TPasswordInput, TRadioGroup, TSlider, TSwitch, TTable, TTag, TTree, TerminalProvider, createTInputHostPlugin } from "./TTree-kzhlB5P0.js";
12
12
  import "./terminal-selection-DBinO6p5.js";
13
- import { TBox, TCommandPalette, TDialog, TInput, TSelect, TText, computeCommandPaletteMatchRanges } from "./TSelect-BwJJbuTt.js";
13
+ import { TBox, TCommandPalette, TDialog, TInput, TSelect, TText, computeCommandPaletteMatchRanges } from "./TSelect-DR0FomSu.js";
14
14
  import "./frame-perf-C6Xfg85O.js";
15
15
  import "./path-mnSgEpCm.js";
16
16
 
@@ -1,2 +1,2 @@
1
- export type { StdoutRenderer } from "./stdout-renderer.js";
1
+ export type { CliOutput, DirtyRowPatchMode, StdoutColorMode, StdoutRenderer, StdoutRendererOptions, ThemePalette, } from "./stdout-renderer.js";
2
2
  export { createStdoutRenderer } from "./stdout-renderer.js";
@@ -4,6 +4,11 @@ import type { ThemePalette } from "../../core/ansi-palette.js";
4
4
  export type CliOutput = Readonly<{
5
5
  write: (chunk: string) => unknown;
6
6
  isTTY?: boolean;
7
+ fd?: number;
8
+ columns?: number;
9
+ rows?: number;
10
+ on?: (event: "resize", listener: () => void) => unknown;
11
+ off?: (event: "resize", listener: () => void) => unknown;
7
12
  }>;
8
13
  export type StdoutRenderer = Readonly<{
9
14
  capabilities: RendererCapabilities;
@@ -20,29 +25,67 @@ export type StdoutRenderer = Readonly<{
20
25
  }>) => void;
21
26
  }>;
22
27
  export type StdoutColorMode = "auto" | "truecolor" | "ansi256" | "ansi16" | "ansi8";
28
+ export type DirtyRowPatchMode = "auto" | "row" | "span";
23
29
  export type { ThemePalette } from "../../core/ansi-palette.js";
24
- export declare function createStdoutRenderer(terminal: Terminal, options?: Readonly<{
30
+ export type StdoutRendererOptions = Readonly<{
25
31
  output?: CliOutput;
26
32
  clear?: boolean;
27
33
  hideCursor?: boolean;
28
34
  altScreen?: boolean;
29
- /** Fallback background color when a cell has no explicit bg. `null` = transparent (terminal default). */
35
+ /** Fallback background color when a cell has no explicit bg. `null` = terminal default. */
30
36
  defaultBg?: string | null;
31
37
  /** Optional ANSI-name palette used when emitting ansi256/truecolor sequences. */
32
38
  palette?: ThemePalette | null;
33
- /** Track TTY resize events (process.stdout 'resize') and call terminal.resize(). */
39
+ /** Track TTY resize events and call terminal.resize(). */
34
40
  trackResize?: boolean;
35
- /** Color mode for ANSI output (auto detects truecolor via env). */
41
+ /** Color mode for ANSI output. */
36
42
  colorMode?: StdoutColorMode;
37
- /** Optional function to get IME cursor position, included in render output for atomic write */
43
+ /**
44
+ * Dirty-row stdout patch strategy.
45
+ *
46
+ * - "auto": prefer span patching, with conservative row fallback on
47
+ * terminals that are sensitive to fragmented cursor-addressed writes.
48
+ * - "row": repaint each dirty row.
49
+ * - "span": force row-internal span/contiguous patching where possible.
50
+ * This skips terminal-sensitive conservative row fallback and is intended
51
+ * as an escape hatch when the caller wants maximum partial-row patching.
52
+ * Safety expansion for wide glyphs and stale-tail handling still applies.
53
+ *
54
+ * Env fallback when this option is not provided:
55
+ * VUE_TUI_DIRTY_ROW_PATCH_MODE, DIMCODE_TUI_DIRTY_ROW_RENDER_MODE,
56
+ * or DIMCODE_TUI_DIRTY_ROW_PATCH_MODE.
57
+ */
58
+ dirtyRowPatchMode?: DirtyRowPatchMode;
59
+ /**
60
+ * Max changed-cell coverage to patch in auto mode on conservative TTYs.
61
+ * Larger dirty rows fall back to full-row repaint.
62
+ *
63
+ * Env fallback when this option is not provided:
64
+ * VUE_TUI_DIRTY_SPAN_MAX_CELLS or DIMCODE_TUI_DIRTY_SPAN_MAX_CELLS.
65
+ */
66
+ dirtySpanConservativeMaxCells?: number;
67
+ /**
68
+ * Alias for dirtyRowPatchMode.
69
+ *
70
+ * - true => "span"
71
+ * - false => "row"
72
+ * - "auto" => "auto"
73
+ *
74
+ * When both are provided, dirtyRowPatchMode wins.
75
+ *
76
+ * @deprecated Use dirtyRowPatchMode instead.
77
+ */
78
+ columnDiff?: boolean | "auto";
79
+ /** Optional function to get IME cursor position, included in render output atomically. */
38
80
  getImeAnchor?: () => {
39
81
  cellX: number;
40
82
  cellY: number;
41
83
  } | null;
42
- /** Use DEC 2026 synchronized output mode (default: false for compatibility) */
84
+ /** Use DEC 2026 synchronized output mode. */
43
85
  useSyncOutput?: boolean;
44
86
  allowFileUrls?: boolean;
45
87
  profileFileWriter?: {
46
88
  appendFileSync?: (path: string, data: string) => void;
47
89
  };
48
- }>): StdoutRenderer;
90
+ }>;
91
+ export declare function createStdoutRenderer(terminal: Terminal, options?: StdoutRendererOptions): StdoutRenderer;
@@ -1,7 +1,7 @@
1
- import "./create-terminal-C2oiWFJU.js";
1
+ import "./create-terminal-DBFNYr8f.js";
2
2
  import "./hyperlink-Bn02UXJb.js";
3
3
  import "./sgr-BmzxEjAO.js";
4
4
  import "./ansi-palette-CNXqFciC.js";
5
- import { DOM_RENDERER_CAPABILITIES, createDomRenderer } from "./dom-renderer-BqGijQID.js";
5
+ import { DOM_RENDERER_CAPABILITIES, createDomRenderer } from "./dom-renderer-BniJSQyX.js";
6
6
 
7
7
  export { DOM_RENDERER_CAPABILITIES, createDomRenderer };