@canvas-components/list-table 0.3.2 → 0.3.4

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.js CHANGED
@@ -1,4 +1,4 @@
1
- import { stringifyDataIndex, getValueByDataIndex, clamp, copyTextSync, copyText, exportTableToXlsx, formatPreciseNumber, addPreciseNumbers, comparePreciseNumbers, dividePreciseNumber, roundPreciseNumber, parseNumberValue, formatNumberValue, formatPercentValue, formatScientificValue, formatChineseNumber, parseChineseNumber, exportTableToTxt, exportTableToCsv, downloadJsonFile, mapRowsToExportRecords, copyJson, copyRows, isDateTimeFormatPattern, normalizeDecimalPlaces, formatDateTimeValue, formatCustomNumberPattern, isSameDataIndex, isPointInRect as isPointInRect$1 } from '@canvas-components/utils';
1
+ import { stringifyDataIndex, getValueByDataIndex, clamp, copyTextSync, copyText, exportTableToXlsx, formatPreciseNumber, addPreciseNumbers, comparePreciseNumbers, isSameDataIndex, dividePreciseNumber, roundPreciseNumber, parseNumberValue, formatNumberValue, formatPercentValue, formatScientificValue, formatChineseNumber, parseChineseNumber, exportTableToTxt, exportTableToCsv, downloadJsonFile, mapRowsToExportRecords, copyJson, copyRows, isDateTimeFormatPattern, normalizeDecimalPlaces, formatDateTimeValue, formatCustomNumberPattern, isPointInRect as isPointInRect$1 } from '@canvas-components/utils';
2
2
  import { drawBarcodeToCanvas } from '@canvas-components/barcode';
3
3
  import { drawCanvasChartToCanvas, getCanvasChartRenderer, resolveCanvasChartTooltipText } from '@canvas-components/chart';
4
4
  import { drawQrCodeToCanvas } from '@canvas-components/qrcode';
@@ -333,6 +333,30 @@ function stretchColumnWidths(columns, containerWidth) {
333
333
  stretchableColumns[stretchableColumns.length - 1].width += remain;
334
334
  }
335
335
  }
336
+ function shrinkColumnWidthsToFit(columns, containerWidth) {
337
+ let remaining = Math.max(
338
+ Math.ceil(computeColumnWidths(columns) - containerWidth),
339
+ 0
340
+ );
341
+ let shrinkableColumns = columns.filter(
342
+ (column) => column.width > column.minWidth
343
+ );
344
+ while (remaining > 0 && shrinkableColumns.length > 0) {
345
+ const share = Math.max(Math.floor(remaining / shrinkableColumns.length), 1);
346
+ shrinkableColumns.forEach((column) => {
347
+ if (remaining <= 0) {
348
+ return;
349
+ }
350
+ const shrink = Math.min(column.width - column.minWidth, share, remaining);
351
+ column.width -= shrink;
352
+ remaining -= shrink;
353
+ });
354
+ shrinkableColumns = shrinkableColumns.filter(
355
+ (column) => column.width > column.minWidth
356
+ );
357
+ }
358
+ return remaining === 0;
359
+ }
336
360
 
337
361
  // src/domain/columns/flatten-leaf-columns.ts
338
362
  function flattenLeafColumns(columns) {
@@ -640,6 +664,40 @@ function cloneColumns(columns) {
640
664
  children: column.children ? cloneColumns(column.children) : void 0
641
665
  }));
642
666
  }
667
+ function preserveRuntimeColumnWidths(params) {
668
+ const runtimeByKey = collectColumnsByKey(params.runtimeColumns);
669
+ const initialByKey = collectColumnsByKey(params.initialColumns);
670
+ let changed = false;
671
+ const visit = (columns) => {
672
+ columns.forEach((column) => {
673
+ const key = resolveColumnKey(column);
674
+ const runtimeColumn = runtimeByKey.get(key);
675
+ const initialColumn = initialByKey.get(key);
676
+ if (runtimeColumn && initialColumn && column.width === initialColumn.width && runtimeColumn.width !== initialColumn.width) {
677
+ column.width = runtimeColumn.width;
678
+ changed = true;
679
+ }
680
+ if (column.children?.length) {
681
+ visit(column.children);
682
+ }
683
+ });
684
+ };
685
+ visit(params.nextColumns);
686
+ return changed;
687
+ }
688
+ function collectColumnsByKey(columns) {
689
+ const result = /* @__PURE__ */ new Map();
690
+ const visit = (items) => {
691
+ items.forEach((column) => {
692
+ result.set(resolveColumnKey(column), column);
693
+ if (column.children?.length) {
694
+ visit(column.children);
695
+ }
696
+ });
697
+ };
698
+ visit(columns);
699
+ return result;
700
+ }
643
701
  function applyInitialColumnVisibility(columns) {
644
702
  columns.forEach((column) => {
645
703
  if (column.hidden === void 0 && column.initialHide) {
@@ -1758,11 +1816,20 @@ function clampPageNumber(page, totalPages) {
1758
1816
  }
1759
1817
  var maximumTreeDepthCache = /* @__PURE__ */ new WeakMap();
1760
1818
  var sourceRowIndexCache = /* @__PURE__ */ new WeakMap();
1819
+ var selectedRowKeySetCache = /* @__PURE__ */ new WeakMap();
1761
1820
  var headerSelectionStateCache = /* @__PURE__ */ new WeakMap();
1762
1821
  var ROW_SELECTION_COLUMN_KEY = "__row_selection__";
1763
1822
  var ROW_SELECTOR_COLUMN_KEY = "__row_selector__";
1764
1823
  var EXPAND_COLUMN_KEY = "__row_expand__";
1765
1824
  var DEFAULT_ROW_SELECTOR_WIDTH = DEFAULT_SCROLLBAR_THICKNESS;
1825
+ function getSelectedRowKeySet(selectedRowKeys) {
1826
+ let cached = selectedRowKeySetCache.get(selectedRowKeys);
1827
+ if (!cached) {
1828
+ cached = new Set(selectedRowKeys);
1829
+ selectedRowKeySetCache.set(selectedRowKeys, cached);
1830
+ }
1831
+ return cached;
1832
+ }
1766
1833
  function getInitialSelectedRowKeys(options) {
1767
1834
  const rowSelection = options.rowSelection;
1768
1835
  if (!rowSelection) {
@@ -1825,6 +1892,7 @@ function createRowSelectionColumn(params) {
1825
1892
  const { options, selectedRowKeys } = params;
1826
1893
  const rowSelection = options.rowSelection;
1827
1894
  const type = rowSelection?.type === "radio" ? "radio" : "checkbox";
1895
+ const selectedRowKeySet = getSelectedRowKeySet(selectedRowKeys);
1828
1896
  const selectionColumn = {
1829
1897
  key: ROW_SELECTION_COLUMN_KEY,
1830
1898
  dataIndex: ROW_SELECTION_COLUMN_KEY,
@@ -1841,7 +1909,7 @@ function createRowSelectionColumn(params) {
1841
1909
  const rowKey = getRowKey(options, record, rowIndex);
1842
1910
  return {
1843
1911
  type,
1844
- checked: selectedRowKeys.includes(rowKey),
1912
+ checked: selectedRowKeySet.has(rowKey),
1845
1913
  disabled: isRowSelectionDisabled(rowSelection, record)
1846
1914
  };
1847
1915
  },
@@ -1960,40 +2028,39 @@ function getResolvedColumns(options, selectedRowKeys) {
1960
2028
  return rowSelectorColumn ? [rowSelectorColumn, ...resolvedColumns] : resolvedColumns;
1961
2029
  }
1962
2030
  function getSelectedRows(options, selectedRowKeys) {
2031
+ const selectedRowKeySet = getSelectedRowKeySet(selectedRowKeys);
1963
2032
  return options.dataSource.filter(
1964
- (record, index) => selectedRowKeys.includes(getRowKey(options, record, index))
2033
+ (record, index) => selectedRowKeySet.has(getRowKey(options, record, index))
1965
2034
  );
1966
2035
  }
1967
- function getVisibleSelectableRows(params) {
1968
- const { rowSelection, displayData } = params;
1969
- return displayData.filter((record) => !isRowSelectionDisabled(rowSelection, record));
1970
- }
1971
2036
  function getHeaderSelectionState(params) {
1972
- const { options, selectedRowKeys, displayData } = params;
1973
- const cached = headerSelectionStateCache.get(displayData);
2037
+ const { options, selectedRowKeys } = params;
2038
+ const selectableData = options.dataSource;
2039
+ const cached = headerSelectionStateCache.get(selectableData);
1974
2040
  if (cached && cached.options === options && cached.selectedRowKeys === selectedRowKeys) {
1975
2041
  return cached.state;
1976
2042
  }
1977
2043
  const rowSelection = options.rowSelection;
1978
- const visibleRows = getVisibleSelectableRows({
1979
- rowSelection,
1980
- displayData
1981
- });
1982
- const selectedKeySet = new Set(selectedRowKeys);
1983
- let selectedVisibleCount = 0;
1984
- visibleRows.forEach((record, index) => {
2044
+ const selectedKeySet = getSelectedRowKeySet(selectedRowKeys);
2045
+ let selectableCount = 0;
2046
+ let selectedCount = 0;
2047
+ selectableData.forEach((record, index) => {
2048
+ if (isRowSelectionDisabled(rowSelection, record)) {
2049
+ return;
2050
+ }
2051
+ selectableCount += 1;
1985
2052
  if (selectedKeySet.has(getRowKey(options, record, index))) {
1986
- selectedVisibleCount += 1;
2053
+ selectedCount += 1;
1987
2054
  }
1988
2055
  });
1989
2056
  const type = rowSelection?.type === "radio" ? "radio" : "checkbox";
1990
2057
  const state = {
1991
2058
  type,
1992
- checked: visibleRows.length > 0 && selectedVisibleCount === visibleRows.length,
1993
- indeterminate: selectedVisibleCount > 0 && selectedVisibleCount < visibleRows.length,
1994
- disabled: visibleRows.length === 0
2059
+ checked: selectableCount > 0 && selectedCount === selectableCount,
2060
+ indeterminate: selectedCount > 0 && selectedCount < selectableCount,
2061
+ disabled: selectableCount === 0
1995
2062
  };
1996
- headerSelectionStateCache.set(displayData, {
2063
+ headerSelectionStateCache.set(selectableData, {
1997
2064
  options,
1998
2065
  selectedRowKeys,
1999
2066
  state
@@ -2016,24 +2083,31 @@ function resolveToggledRowSelectionKeys(params) {
2016
2083
  };
2017
2084
  }
2018
2085
  function resolveToggleAllVisibleRowKeys(params) {
2019
- const { options, selectedRowKeys, displayData } = params;
2086
+ const { options, selectedRowKeys } = params;
2020
2087
  const rowSelection = options.rowSelection;
2021
2088
  if (!rowSelection || rowSelection.type === "radio") {
2022
2089
  return null;
2023
2090
  }
2024
- const visibleRows = getVisibleSelectableRows({
2025
- rowSelection,
2026
- displayData
2027
- });
2028
- const visibleKeys = visibleRows.map(
2029
- (record, index) => getRowKey(options, record, index)
2030
- );
2031
- const headerState = getHeaderSelectionState({
2032
- options,
2033
- selectedRowKeys,
2034
- displayData
2091
+ const selectedKeySet = getSelectedRowKeySet(selectedRowKeys);
2092
+ const selectableKeys = [];
2093
+ let allSelected = true;
2094
+ options.dataSource.forEach((record, index) => {
2095
+ if (isRowSelectionDisabled(rowSelection, record)) {
2096
+ return;
2097
+ }
2098
+ const key = getRowKey(options, record, index);
2099
+ selectableKeys.push(key);
2100
+ if (!selectedKeySet.has(key)) {
2101
+ allSelected = false;
2102
+ }
2035
2103
  });
2036
- return headerState.checked ? selectedRowKeys.filter((key) => !visibleKeys.includes(key)) : Array.from(/* @__PURE__ */ new Set([...selectedRowKeys, ...visibleKeys]));
2104
+ if (allSelected && selectableKeys.length > 0) {
2105
+ const selectableKeySet = new Set(selectableKeys);
2106
+ return selectedRowKeys.filter((key) => !selectableKeySet.has(key));
2107
+ }
2108
+ const nextKeySet = new Set(selectedRowKeys);
2109
+ selectableKeys.forEach((key) => nextKeySet.add(key));
2110
+ return Array.from(nextKeySet);
2037
2111
  }
2038
2112
 
2039
2113
  // src/engine/store/state.ts
@@ -3216,7 +3290,7 @@ function drawBodyButtonContent(params) {
3216
3290
  const top = rect.y + (rect.height - height) / 2;
3217
3291
  const palette = resolveButtonPalette(content);
3218
3292
  const textIndent = resolveContentTextIndent(content);
3219
- const paddingInline = BUTTON_PADDING_INLINE_MAP[size];
3293
+ const paddingInline = resolveButtonPaddingInline(content, size);
3220
3294
  const radius = BUTTON_RADIUS_MAP[size];
3221
3295
  ctx.save();
3222
3296
  ctx.globalAlpha *= resolveContentOpacity(content);
@@ -3324,9 +3398,12 @@ function measureButtonContentWidth(ctx, content, theme) {
3324
3398
  const intrinsicWidth = Math.max(
3325
3399
  ctx.measureText(content.text).width + resolveContentTextIndent(content),
3326
3400
  0
3327
- ) + BUTTON_PADDING_INLINE_MAP[size] * 2;
3401
+ ) + resolveButtonPaddingInline(content, size) * 2;
3328
3402
  return resolveContentLayoutWidth(content, intrinsicWidth);
3329
3403
  }
3404
+ function resolveButtonPaddingInline(content, size) {
3405
+ return content.buttonType === "link" || content.buttonType === "text" ? 4 : BUTTON_PADDING_INLINE_MAP[size];
3406
+ }
3330
3407
  function measureButtonContentHeight(content) {
3331
3408
  return BUTTON_HEIGHT_MAP[resolveButtonSize(content.size)];
3332
3409
  }
@@ -6853,7 +6930,7 @@ function expandBodyContents(contents) {
6853
6930
  expanded.push({
6854
6931
  content,
6855
6932
  contentIndex,
6856
- gapBefore: expanded.length === 0 || textOnly ? 0 : previousContent?.type === "link" && content.type === "link" ? LINK_CONTENT_GAP : CONTENT_GAP
6933
+ gapBefore: expanded.length === 0 || textOnly ? 0 : resolveInlineContentGap(previousContent, content)
6857
6934
  });
6858
6935
  if ((content.type === "checkbox" || content.type === "radio") && content.label) {
6859
6936
  const textLabelContent = {
@@ -6872,6 +6949,12 @@ function expandBodyContents(contents) {
6872
6949
  });
6873
6950
  return expanded;
6874
6951
  }
6952
+ function resolveInlineContentGap(previous, current) {
6953
+ return isInlineActionContent(previous) && isInlineActionContent(current) ? LINK_CONTENT_GAP : CONTENT_GAP;
6954
+ }
6955
+ function isInlineActionContent(content) {
6956
+ return content?.type === "link" || content?.type === "button" && (content.buttonType === "link" || content.buttonType === "text");
6957
+ }
6875
6958
  function buildSingleLineLayout(ctx, contents, availableWidth, theme) {
6876
6959
  const line = {
6877
6960
  items: [],
@@ -10461,7 +10544,7 @@ var ListTableCarouselController = class {
10461
10544
  var SUMMARY_ASYNC_BATCH_SIZE = 2e3;
10462
10545
  var SUMMARY_ASYNC_FRAME_BUDGET = 8;
10463
10546
  async function computeSummaryValuesAsync(params) {
10464
- const { rows, columns, signal } = params;
10547
+ const { rows, columns, mergeCell, signal } = params;
10465
10548
  const summaryValues = /* @__PURE__ */ new Map();
10466
10549
  const accumulators = [];
10467
10550
  columns.forEach((column) => {
@@ -10514,8 +10597,14 @@ async function computeSummaryValuesAsync(params) {
10514
10597
  }
10515
10598
  startIndex = endIndex;
10516
10599
  }
10600
+ const mergedRowCount = accumulators.some(
10601
+ (item) => item.type === "mergedRowCount"
10602
+ ) ? countMergedRows(rows, columns, mergeCell) : null;
10517
10603
  accumulators.forEach((item) => {
10518
- summaryValues.set(item.column.key, finalizeSummaryValue(item, rows));
10604
+ summaryValues.set(
10605
+ item.column.key,
10606
+ finalizeSummaryValue(item, rows, mergedRowCount)
10607
+ );
10519
10608
  });
10520
10609
  return summaryValues;
10521
10610
  }
@@ -10570,7 +10659,7 @@ function updateSummaryAccumulator(item, record) {
10570
10659
  item.max = numericValue;
10571
10660
  }
10572
10661
  }
10573
- function finalizeSummaryValue(item, rows) {
10662
+ function finalizeSummaryValue(item, rows, mergedRowCount) {
10574
10663
  if (item.column.summaryTitle != null) {
10575
10664
  return item.column.summaryTitle;
10576
10665
  }
@@ -10578,7 +10667,11 @@ function finalizeSummaryValue(item, rows) {
10578
10667
  return formatSummaryOutput(item, String(rows.length), rows);
10579
10668
  }
10580
10669
  if (item.type === "mergedRowCount") {
10581
- return formatSummaryOutput(item, String(countMergedRows(rows)), rows);
10670
+ return formatSummaryOutput(
10671
+ item,
10672
+ String(mergedRowCount ?? rows.length),
10673
+ rows
10674
+ );
10582
10675
  }
10583
10676
  if (item.type === "count") {
10584
10677
  return formatSummaryOutput(item, String(item.valueCount), rows);
@@ -10669,7 +10762,76 @@ function formatSummaryOutput(item, value, rows) {
10669
10762
  }
10670
10763
  return value;
10671
10764
  }
10672
- function countMergedRows(rows) {
10765
+ function countMergedRows(rows, columns, mergeCell) {
10766
+ const coveredRowIndexes = /* @__PURE__ */ new Set();
10767
+ const explicitRowSpans = /* @__PURE__ */ new Map();
10768
+ columns.forEach((column) => {
10769
+ if (!column.onCell) {
10770
+ return;
10771
+ }
10772
+ rows.forEach((record, rowIndex) => {
10773
+ const value = getValueByDataIndex(record, column.dataIndex);
10774
+ const span = column.onCell?.(value, record, rowIndex, column);
10775
+ if (!span || !Object.prototype.hasOwnProperty.call(span, "rowSpan")) {
10776
+ return;
10777
+ }
10778
+ const rowSpan = span.rowSpan ?? 1;
10779
+ explicitRowSpans.set(`${rowIndex}::${column.key}`, rowSpan);
10780
+ if (rowSpan === 0) {
10781
+ coveredRowIndexes.add(rowIndex);
10782
+ return;
10783
+ }
10784
+ if (!Number.isFinite(rowSpan) || rowSpan <= 1) {
10785
+ return;
10786
+ }
10787
+ const spanEnd = Math.min(
10788
+ rows.length,
10789
+ rowIndex + Math.floor(rowSpan)
10790
+ );
10791
+ for (let index = rowIndex + 1; index < spanEnd; index += 1) {
10792
+ coveredRowIndexes.add(index);
10793
+ }
10794
+ });
10795
+ });
10796
+ const rowMergeRule = mergeCell?.row;
10797
+ const targetDataIndexes = rowMergeRule?.columns?.length ? rowMergeRule.columns : rowMergeRule?.keys;
10798
+ const targetMergeColumns = columns.filter(
10799
+ (column) => targetDataIndexes?.some(
10800
+ (dataIndex) => isSameDataIndex(column.dataIndex, dataIndex)
10801
+ )
10802
+ );
10803
+ if (rowMergeRule?.keys.length && targetMergeColumns.length) {
10804
+ targetMergeColumns.forEach((column) => {
10805
+ let rowIndex = 0;
10806
+ while (rowIndex < rows.length) {
10807
+ if (explicitRowSpans.has(`${rowIndex}::${column.key}`)) {
10808
+ rowIndex += 1;
10809
+ continue;
10810
+ }
10811
+ const currentGroupKey = getMergeGroupKey(
10812
+ rows[rowIndex],
10813
+ rowMergeRule.keys
10814
+ );
10815
+ let rowSpan = 1;
10816
+ for (let index = rowIndex + 1; index < rows.length; index += 1) {
10817
+ if (explicitRowSpans.has(`${index}::${column.key}`)) {
10818
+ break;
10819
+ }
10820
+ if (getMergeGroupKey(rows[index], rowMergeRule.keys) !== currentGroupKey) {
10821
+ break;
10822
+ }
10823
+ rowSpan += 1;
10824
+ }
10825
+ for (let index = rowIndex + 1; index < rowIndex + rowSpan; index += 1) {
10826
+ coveredRowIndexes.add(index);
10827
+ }
10828
+ rowIndex += rowSpan;
10829
+ }
10830
+ });
10831
+ }
10832
+ if (coveredRowIndexes.size > 0) {
10833
+ return rows.length - coveredRowIndexes.size;
10834
+ }
10673
10835
  return rows.reduce((count, record) => {
10674
10836
  if (record == null || typeof record !== "object") {
10675
10837
  return count + 1;
@@ -10681,6 +10843,20 @@ function countMergedRows(rows) {
10681
10843
  return rowSpan > 0 ? count + 1 : count;
10682
10844
  }, 0);
10683
10845
  }
10846
+ function getMergeGroupKey(record, keys) {
10847
+ return keys.map(
10848
+ (dataIndex) => normalizeMergeValue(getValueByDataIndex(record, dataIndex))
10849
+ ).join("|");
10850
+ }
10851
+ function normalizeMergeValue(value) {
10852
+ if (value == null) {
10853
+ return "";
10854
+ }
10855
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
10856
+ return String(value);
10857
+ }
10858
+ return JSON.stringify(value) ?? "";
10859
+ }
10684
10860
  function yieldToMainThread() {
10685
10861
  return new Promise((resolve) => {
10686
10862
  if (typeof requestAnimationFrame === "function") {
@@ -13464,7 +13640,7 @@ async function getBaseDisplayRowsAsync(params) {
13464
13640
  }
13465
13641
  function getDisplayRows(params) {
13466
13642
  const rows = getBaseDisplayRows(params);
13467
- if (!params.options.pagination || params.options.query?.mode === "remote") {
13643
+ if (!params.options.pagination || isRemotePaginationResult(params.options)) {
13468
13644
  return rows;
13469
13645
  }
13470
13646
  return sliceDisplayRowsByPagination({
@@ -13474,7 +13650,7 @@ function getDisplayRows(params) {
13474
13650
  });
13475
13651
  }
13476
13652
  function sliceDisplayRowsFromBaseRows(params) {
13477
- if (!params.options.pagination || params.options.query?.mode === "remote") {
13653
+ if (!params.options.pagination || isRemotePaginationResult(params.options)) {
13478
13654
  return params.rows;
13479
13655
  }
13480
13656
  return sliceDisplayRowsByPagination({
@@ -13483,6 +13659,13 @@ function sliceDisplayRowsFromBaseRows(params) {
13483
13659
  state: params.query.pagination
13484
13660
  });
13485
13661
  }
13662
+ function isRemotePaginationResult(options) {
13663
+ if (options.query?.mode === "remote") {
13664
+ return true;
13665
+ }
13666
+ const total = options.pagination && options.pagination.total;
13667
+ return typeof total === "number" && Number.isFinite(total) && total > options.dataSource.length;
13668
+ }
13486
13669
  function emitListTableQueryChange(params) {
13487
13670
  const {
13488
13671
  options,
@@ -15010,6 +15193,7 @@ var TEXT_SELECTION_DRAG_THRESHOLD = 5;
15010
15193
  var TEXT_SELECTION_AUTO_SCROLL_EDGE_SIZE = 36;
15011
15194
  var TEXT_SELECTION_AUTO_SCROLL_MAX_VERTICAL_SPEED = 1200;
15012
15195
  var TEXT_SELECTION_AUTO_SCROLL_MAX_HORIZONTAL_SPEED = 900;
15196
+ var EDITABLE_CELL_ROW_SELECTION_DELAY = 300;
15013
15197
  var ListTableEventController = class {
15014
15198
  constructor(host) {
15015
15199
  __publicField(this, "searchKeyword", "");
@@ -15031,6 +15215,7 @@ var ListTableEventController = class {
15031
15215
  __publicField(this, "cellSelectionAutoScrollVelocity", { x: 0, y: 0 });
15032
15216
  __publicField(this, "cellSelectionAutoScrollTargetVelocity", { x: 0, y: 0 });
15033
15217
  __publicField(this, "continuousScrollTimer", null);
15218
+ __publicField(this, "pendingEditableCellRowSelectionTimer", null);
15034
15219
  __publicField(this, "outsideClickDocument", null);
15035
15220
  __publicField(this, "outsideClickStarted", null);
15036
15221
  __publicField(this, "host");
@@ -15432,6 +15617,7 @@ var ListTableEventController = class {
15432
15617
  );
15433
15618
  });
15434
15619
  __publicField(this, "handleDoubleClick", (event) => {
15620
+ this.cancelPendingEditableCellRowSelection();
15435
15621
  if (!this.host.canvasElement) {
15436
15622
  return;
15437
15623
  }
@@ -15961,7 +16147,24 @@ var ListTableEventController = class {
15961
16147
  if ((result.area === "body" || result.area === "body-content") && typeof result.rowIndex === "number" && this.host.options.rowSelection?.selectRowByClick && result.columnKey && !isSystemColumnKey(result.columnKey)) {
15962
16148
  const record = this.host.getDisplayData()[result.rowIndex];
15963
16149
  if (record !== void 0) {
15964
- this.host.toggleRowSelection(record, result.rowIndex);
16150
+ const column = this.host.leafColumns.find(
16151
+ (item) => item.key === result.columnKey
16152
+ );
16153
+ const value = column?.dataIndex != null ? getValueByDataIndex(record, column.dataIndex) : void 0;
16154
+ const canOpenEditorByDoubleClick = shouldOpenCellEditorOnClick(
16155
+ column,
16156
+ 2,
16157
+ {
16158
+ value,
16159
+ record,
16160
+ rowIndex: result.rowIndex
16161
+ }
16162
+ );
16163
+ if (canOpenEditorByDoubleClick && event.detail === 1) {
16164
+ this.scheduleEditableCellRowSelection(record, result.rowIndex);
16165
+ } else if (!canOpenEditorByDoubleClick || event.detail !== 2) {
16166
+ this.host.toggleRowSelection(record, result.rowIndex);
16167
+ }
15965
16168
  }
15966
16169
  }
15967
16170
  if (result.area === "body" && typeof result.rowIndex === "number" && this.host.options.expandable?.expandRowByClick && result.columnKey && !isSystemColumnKey(result.columnKey) && this.host.toggleRowExpand(result.rowIndex)) {
@@ -16435,6 +16638,7 @@ var ListTableEventController = class {
16435
16638
  this.host.render();
16436
16639
  }
16437
16640
  destroy() {
16641
+ this.cancelPendingEditableCellRowSelection();
16438
16642
  this.stopContinuousScroll();
16439
16643
  this.stopTextSelectionAutoScroll();
16440
16644
  this.stopCellSelectionAutoScroll();
@@ -16499,6 +16703,20 @@ var ListTableEventController = class {
16499
16703
  event.preventDefault();
16500
16704
  this.host.editingController.open(rowIndex, columnKey, event.key);
16501
16705
  }
16706
+ scheduleEditableCellRowSelection(record, rowIndex) {
16707
+ this.cancelPendingEditableCellRowSelection();
16708
+ this.pendingEditableCellRowSelectionTimer = globalThis.setTimeout(() => {
16709
+ this.pendingEditableCellRowSelectionTimer = null;
16710
+ this.host.toggleRowSelection(record, rowIndex);
16711
+ }, EDITABLE_CELL_ROW_SELECTION_DELAY);
16712
+ }
16713
+ cancelPendingEditableCellRowSelection() {
16714
+ if (this.pendingEditableCellRowSelectionTimer == null) {
16715
+ return;
16716
+ }
16717
+ globalThis.clearTimeout(this.pendingEditableCellRowSelectionTimer);
16718
+ this.pendingEditableCellRowSelectionTimer = null;
16719
+ }
16502
16720
  async autoFitColumnWidths(columnKey) {
16503
16721
  const ctx = this.host.canvasElement?.getContext("2d");
16504
16722
  if (!ctx) {
@@ -18237,6 +18455,47 @@ function persistListTableColumnConfig(params) {
18237
18455
  )
18238
18456
  );
18239
18457
  }
18458
+ async function resetListTableStoredColumnConfig(params) {
18459
+ const { storageKey, columns } = params;
18460
+ if (!storageKey) {
18461
+ return;
18462
+ }
18463
+ const initialColumnTree = columns.map(cloneColumnTree);
18464
+ ensureColumnKeysInPlace(initialColumnTree);
18465
+ const stored = await getColumnConfig(storageKey);
18466
+ if (!stored) {
18467
+ return;
18468
+ }
18469
+ const initialColumns = buildStoredColumnConfig(
18470
+ initialColumnTree,
18471
+ { key: null, order: null },
18472
+ {}
18473
+ ).columns;
18474
+ const nextColumns = {};
18475
+ Object.entries(initialColumns).forEach(([key, initial]) => {
18476
+ const next = {
18477
+ ...stored.columns[key] ?? initial,
18478
+ width: initial.width,
18479
+ hidden: initial.hidden
18480
+ };
18481
+ if (initial.fixed) {
18482
+ next.fixed = initial.fixed;
18483
+ } else {
18484
+ delete next.fixed;
18485
+ }
18486
+ nextColumns[key] = next;
18487
+ });
18488
+ await saveColumnConfig(storageKey, {
18489
+ ...stored,
18490
+ columns: nextColumns
18491
+ });
18492
+ }
18493
+ function cloneColumnTree(column) {
18494
+ return {
18495
+ ...column,
18496
+ children: column.children?.map(cloneColumnTree)
18497
+ };
18498
+ }
18240
18499
  async function loadListTableStoredConfig(params) {
18241
18500
  const { storageKey, columns } = params;
18242
18501
  if (!storageKey) {
@@ -20189,6 +20448,10 @@ function buildListTableRenderSnapshot(params) {
20189
20448
  groupedColumnKeys
20190
20449
  );
20191
20450
  const leafColumns = flattenLeafColumns(normalizedColumns);
20451
+ const totalColumnWidth = computeColumnWidths(leafColumns);
20452
+ if (width > 0 && totalColumnWidth > width && totalColumnWidth <= hostWidth) {
20453
+ shrinkColumnWidthsToFit(leafColumns, width);
20454
+ }
20192
20455
  if (options.stretchColumns !== false && width > 0 && !draggingResize) {
20193
20456
  stretchColumnWidths(leafColumns, width);
20194
20457
  }
@@ -20732,8 +20995,8 @@ function updateListTableRenderSnapshotScroll(params) {
20732
20995
  } : snapshot.frozenRows;
20733
20996
  return {
20734
20997
  ...snapshot,
20735
- width,
20736
- height,
20998
+ width: snapshot.width,
20999
+ height: snapshot.height,
20737
21000
  columnSegments,
20738
21001
  headerRows,
20739
21002
  scrollbarLayout,
@@ -21118,13 +21381,8 @@ function drawScrollbars(ctx, layout, descriptors, borderColor, opacity = 1, inte
21118
21381
  verticalFrame.bodyBackgroundColor
21119
21382
  );
21120
21383
  }
21121
- if (layout.vertical && verticalFrame) {
21122
- drawVerticalScrollbarFrame(
21123
- ctx,
21124
- layout.vertical,
21125
- verticalFrame,
21126
- borderColor
21127
- );
21384
+ if (verticalFrame) {
21385
+ drawVerticalScrollbarFrame(ctx, verticalFrame, borderColor);
21128
21386
  }
21129
21387
  if (layout.horizontal) {
21130
21388
  drawAxisScrollbar(
@@ -21242,28 +21500,28 @@ function drawTrackBorder(ctx, rect, axis, borderColor) {
21242
21500
  ctx.stroke();
21243
21501
  ctx.restore();
21244
21502
  }
21245
- function drawVerticalScrollbarFrame(ctx, layout, frame, borderColor) {
21246
- const left = Math.round(layout.decreaseButton.x) + 0.5;
21247
- const right = Math.round(layout.decreaseButton.x + layout.decreaseButton.width) - 0.5;
21503
+ function drawVerticalScrollbarFrame(ctx, frame, borderColor) {
21504
+ const left = Math.round(frame.x) + 0.5;
21505
+ const right = Math.round(frame.x + frame.width) - 0.5;
21248
21506
  const top = Math.round(frame.top) + 0.5;
21249
21507
  const bottom = Math.round(frame.top + frame.height) - 0.5;
21250
21508
  const headerBottom = Math.round(frame.headerBottom) + 0.5;
21251
- if (right <= left || bottom <= top) {
21509
+ if (frame.width <= 0 || right <= left || bottom <= top) {
21252
21510
  return;
21253
21511
  }
21254
21512
  ctx.save();
21255
21513
  ctx.fillStyle = frame.headerBackgroundColor;
21256
21514
  ctx.fillRect(
21257
- layout.decreaseButton.x,
21515
+ frame.x,
21258
21516
  frame.top,
21259
- layout.decreaseButton.width,
21517
+ frame.width,
21260
21518
  Math.max(frame.headerBottom - frame.top, 0)
21261
21519
  );
21262
21520
  ctx.fillStyle = frame.bodyBackgroundColor;
21263
21521
  ctx.fillRect(
21264
- layout.decreaseButton.x,
21522
+ frame.x,
21265
21523
  frame.headerBottom,
21266
- layout.decreaseButton.width,
21524
+ frame.width,
21267
21525
  Math.max(frame.top + frame.height - frame.headerBottom, 0)
21268
21526
  );
21269
21527
  ctx.strokeStyle = borderColor;
@@ -22109,7 +22367,7 @@ function buildAutoRowSpanMap(rows, columns, rule, spanConfigMap, sourceRowIndexM
22109
22367
  rowIndex += 1;
22110
22368
  continue;
22111
22369
  }
22112
- const currentGroupKey = getMergeGroupKey(rows[rowIndex], groupKeys);
22370
+ const currentGroupKey = getMergeGroupKey2(rows[rowIndex], groupKeys);
22113
22371
  let rowSpan = 1;
22114
22372
  for (let index = rowIndex + 1; index < rows.length; index += 1) {
22115
22373
  if (sourceRowIndexMap[index] !== (sourceRowIndexMap[index - 1] ?? index - 1) + 1) {
@@ -22119,7 +22377,7 @@ function buildAutoRowSpanMap(rows, columns, rule, spanConfigMap, sourceRowIndexM
22119
22377
  if (hasExplicitSpan(spanConfigMap.get(nextCellKey), "rowSpan")) {
22120
22378
  break;
22121
22379
  }
22122
- if (getMergeGroupKey(rows[index], groupKeys) !== currentGroupKey) {
22380
+ if (getMergeGroupKey2(rows[index], groupKeys) !== currentGroupKey) {
22123
22381
  break;
22124
22382
  }
22125
22383
  rowSpan += 1;
@@ -22222,13 +22480,13 @@ function clampSpan(span, max) {
22222
22480
  }
22223
22481
  return Math.max(1, Math.min(Math.floor(span), max));
22224
22482
  }
22225
- function getMergeGroupKey(record, keys) {
22483
+ function getMergeGroupKey2(record, keys) {
22226
22484
  if (!keys?.length) {
22227
22485
  return "";
22228
22486
  }
22229
- return keys.map((key) => normalizeMergeValue(getValueByDataIndex(record, key))).join("|");
22487
+ return keys.map((key) => normalizeMergeValue2(getValueByDataIndex(record, key))).join("|");
22230
22488
  }
22231
- function normalizeMergeValue(value) {
22489
+ function normalizeMergeValue2(value) {
22232
22490
  if (value == null) {
22233
22491
  return "";
22234
22492
  }
@@ -22238,7 +22496,7 @@ function normalizeMergeValue(value) {
22238
22496
  return JSON.stringify(value) ?? "";
22239
22497
  }
22240
22498
  function isSameMergeValue(left, right) {
22241
- return normalizeMergeValue(left) === normalizeMergeValue(right);
22499
+ return normalizeMergeValue2(left) === normalizeMergeValue2(right);
22242
22500
  }
22243
22501
  function getMergedCellWidth(columns, startIndex, colSpan) {
22244
22502
  let width = 0;
@@ -23836,9 +24094,7 @@ function drawListTableHeader(params) {
23836
24094
  columnKey: ROW_SELECTION_COLUMN_KEY,
23837
24095
  ...getHeaderSelectionState({
23838
24096
  options,
23839
- selectedRowKeys,
23840
- displayData
23841
- })
24097
+ selectedRowKeys})
23842
24098
  } : null,
23843
24099
  inlineContentInset,
23844
24100
  collapsedColumnMarkers,
@@ -24501,6 +24757,11 @@ function executeListTableRenderPipeline(params) {
24501
24757
  scrollbarOpacity,
24502
24758
  isScrollbarInteractive,
24503
24759
  {
24760
+ x: width,
24761
+ width: options.scrollbar?.visible === false ? 0 : Math.max(
24762
+ options.scrollbar?.thickness ?? DEFAULT_SCROLLBAR_THICKNESS,
24763
+ 6
24764
+ ),
24504
24765
  top: 0,
24505
24766
  height,
24506
24767
  headerBottom: headerHeight,
@@ -26002,6 +26263,7 @@ var ListTableSummaryController = class {
26002
26263
  const summaryTask = computeSummaryValuesAsync({
26003
26264
  rows: snapshot.displayRows,
26004
26265
  columns: snapshot.leafColumns,
26266
+ mergeCell: this.options.getOptions().query?.mergeCell,
26005
26267
  signal
26006
26268
  }).then((summaryValues) => {
26007
26269
  if (signal.aborted || taskId !== this.summaryTaskId) {
@@ -26892,6 +27154,19 @@ var ListTableCore = class {
26892
27154
  */
26893
27155
  updateOptions(options) {
26894
27156
  this.animationController.stopCarouselScroll();
27157
+ const host = this.asAssemblyHost();
27158
+ const incomingColumnsAreRuntimeColumns = options.columns === this.options.columns;
27159
+ const nextInitialColumns = incomingColumnsAreRuntimeColumns ? cloneColumns(host.initialColumns) : cloneColumns(options.columns);
27160
+ const nextInitialStretchColumns = incomingColumnsAreRuntimeColumns ? host.initialStretchColumns : options.stretchColumns;
27161
+ const shouldPreserveRuntimeWidths = this.options.stretchColumns === false && options.stretchColumns === host.initialStretchColumns;
27162
+ if (shouldPreserveRuntimeWidths) {
27163
+ preserveRuntimeColumnWidths({
27164
+ nextColumns: options.columns,
27165
+ runtimeColumns: this.options.columns,
27166
+ initialColumns: host.initialColumns
27167
+ });
27168
+ options.stretchColumns = false;
27169
+ }
26895
27170
  applyInitialColumnVisibility(options.columns);
26896
27171
  ensureColumnKeysInPlace(options.columns);
26897
27172
  if (options.expandable?.expandedRowKeys !== void 0 && !areSameRowKeySet(
@@ -26907,10 +27182,9 @@ var ListTableCore = class {
26907
27182
  this.queryController.reset();
26908
27183
  this.summaryController.reset();
26909
27184
  this.options = options;
26910
- const host = this.asAssemblyHost();
26911
27185
  host.syncGroupingFromOptions();
26912
- host.initialColumns = cloneColumns(options.columns);
26913
- host.initialStretchColumns = options.stretchColumns;
27186
+ host.initialColumns = nextInitialColumns;
27187
+ host.initialStretchColumns = nextInitialStretchColumns;
26914
27188
  this.store.dispatch(
26915
27189
  replaceStateAction(
26916
27190
  resolveListTableStateOnOptionsUpdate(options, this.store.getSnapshot())
@@ -27113,6 +27387,6 @@ var ListTable = class {
27113
27387
  }
27114
27388
  };
27115
27389
 
27116
- export { ListTable };
27390
+ export { ListTable, resetListTableStoredColumnConfig };
27117
27391
  //# sourceMappingURL=index.js.map
27118
27392
  //# sourceMappingURL=index.js.map