@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.cjs CHANGED
@@ -335,6 +335,30 @@ function stretchColumnWidths(columns, containerWidth) {
335
335
  stretchableColumns[stretchableColumns.length - 1].width += remain;
336
336
  }
337
337
  }
338
+ function shrinkColumnWidthsToFit(columns, containerWidth) {
339
+ let remaining = Math.max(
340
+ Math.ceil(computeColumnWidths(columns) - containerWidth),
341
+ 0
342
+ );
343
+ let shrinkableColumns = columns.filter(
344
+ (column) => column.width > column.minWidth
345
+ );
346
+ while (remaining > 0 && shrinkableColumns.length > 0) {
347
+ const share = Math.max(Math.floor(remaining / shrinkableColumns.length), 1);
348
+ shrinkableColumns.forEach((column) => {
349
+ if (remaining <= 0) {
350
+ return;
351
+ }
352
+ const shrink = Math.min(column.width - column.minWidth, share, remaining);
353
+ column.width -= shrink;
354
+ remaining -= shrink;
355
+ });
356
+ shrinkableColumns = shrinkableColumns.filter(
357
+ (column) => column.width > column.minWidth
358
+ );
359
+ }
360
+ return remaining === 0;
361
+ }
338
362
 
339
363
  // src/domain/columns/flatten-leaf-columns.ts
340
364
  function flattenLeafColumns(columns) {
@@ -642,6 +666,40 @@ function cloneColumns(columns) {
642
666
  children: column.children ? cloneColumns(column.children) : void 0
643
667
  }));
644
668
  }
669
+ function preserveRuntimeColumnWidths(params) {
670
+ const runtimeByKey = collectColumnsByKey(params.runtimeColumns);
671
+ const initialByKey = collectColumnsByKey(params.initialColumns);
672
+ let changed = false;
673
+ const visit = (columns) => {
674
+ columns.forEach((column) => {
675
+ const key = resolveColumnKey(column);
676
+ const runtimeColumn = runtimeByKey.get(key);
677
+ const initialColumn = initialByKey.get(key);
678
+ if (runtimeColumn && initialColumn && column.width === initialColumn.width && runtimeColumn.width !== initialColumn.width) {
679
+ column.width = runtimeColumn.width;
680
+ changed = true;
681
+ }
682
+ if (column.children?.length) {
683
+ visit(column.children);
684
+ }
685
+ });
686
+ };
687
+ visit(params.nextColumns);
688
+ return changed;
689
+ }
690
+ function collectColumnsByKey(columns) {
691
+ const result = /* @__PURE__ */ new Map();
692
+ const visit = (items) => {
693
+ items.forEach((column) => {
694
+ result.set(resolveColumnKey(column), column);
695
+ if (column.children?.length) {
696
+ visit(column.children);
697
+ }
698
+ });
699
+ };
700
+ visit(columns);
701
+ return result;
702
+ }
645
703
  function applyInitialColumnVisibility(columns) {
646
704
  columns.forEach((column) => {
647
705
  if (column.hidden === void 0 && column.initialHide) {
@@ -1760,11 +1818,20 @@ function clampPageNumber(page, totalPages) {
1760
1818
  }
1761
1819
  var maximumTreeDepthCache = /* @__PURE__ */ new WeakMap();
1762
1820
  var sourceRowIndexCache = /* @__PURE__ */ new WeakMap();
1821
+ var selectedRowKeySetCache = /* @__PURE__ */ new WeakMap();
1763
1822
  var headerSelectionStateCache = /* @__PURE__ */ new WeakMap();
1764
1823
  var ROW_SELECTION_COLUMN_KEY = "__row_selection__";
1765
1824
  var ROW_SELECTOR_COLUMN_KEY = "__row_selector__";
1766
1825
  var EXPAND_COLUMN_KEY = "__row_expand__";
1767
1826
  var DEFAULT_ROW_SELECTOR_WIDTH = DEFAULT_SCROLLBAR_THICKNESS;
1827
+ function getSelectedRowKeySet(selectedRowKeys) {
1828
+ let cached = selectedRowKeySetCache.get(selectedRowKeys);
1829
+ if (!cached) {
1830
+ cached = new Set(selectedRowKeys);
1831
+ selectedRowKeySetCache.set(selectedRowKeys, cached);
1832
+ }
1833
+ return cached;
1834
+ }
1768
1835
  function getInitialSelectedRowKeys(options) {
1769
1836
  const rowSelection = options.rowSelection;
1770
1837
  if (!rowSelection) {
@@ -1827,6 +1894,7 @@ function createRowSelectionColumn(params) {
1827
1894
  const { options, selectedRowKeys } = params;
1828
1895
  const rowSelection = options.rowSelection;
1829
1896
  const type = rowSelection?.type === "radio" ? "radio" : "checkbox";
1897
+ const selectedRowKeySet = getSelectedRowKeySet(selectedRowKeys);
1830
1898
  const selectionColumn = {
1831
1899
  key: ROW_SELECTION_COLUMN_KEY,
1832
1900
  dataIndex: ROW_SELECTION_COLUMN_KEY,
@@ -1843,7 +1911,7 @@ function createRowSelectionColumn(params) {
1843
1911
  const rowKey = getRowKey(options, record, rowIndex);
1844
1912
  return {
1845
1913
  type,
1846
- checked: selectedRowKeys.includes(rowKey),
1914
+ checked: selectedRowKeySet.has(rowKey),
1847
1915
  disabled: isRowSelectionDisabled(rowSelection, record)
1848
1916
  };
1849
1917
  },
@@ -1962,40 +2030,39 @@ function getResolvedColumns(options, selectedRowKeys) {
1962
2030
  return rowSelectorColumn ? [rowSelectorColumn, ...resolvedColumns] : resolvedColumns;
1963
2031
  }
1964
2032
  function getSelectedRows(options, selectedRowKeys) {
2033
+ const selectedRowKeySet = getSelectedRowKeySet(selectedRowKeys);
1965
2034
  return options.dataSource.filter(
1966
- (record, index) => selectedRowKeys.includes(getRowKey(options, record, index))
2035
+ (record, index) => selectedRowKeySet.has(getRowKey(options, record, index))
1967
2036
  );
1968
2037
  }
1969
- function getVisibleSelectableRows(params) {
1970
- const { rowSelection, displayData } = params;
1971
- return displayData.filter((record) => !isRowSelectionDisabled(rowSelection, record));
1972
- }
1973
2038
  function getHeaderSelectionState(params) {
1974
- const { options, selectedRowKeys, displayData } = params;
1975
- const cached = headerSelectionStateCache.get(displayData);
2039
+ const { options, selectedRowKeys } = params;
2040
+ const selectableData = options.dataSource;
2041
+ const cached = headerSelectionStateCache.get(selectableData);
1976
2042
  if (cached && cached.options === options && cached.selectedRowKeys === selectedRowKeys) {
1977
2043
  return cached.state;
1978
2044
  }
1979
2045
  const rowSelection = options.rowSelection;
1980
- const visibleRows = getVisibleSelectableRows({
1981
- rowSelection,
1982
- displayData
1983
- });
1984
- const selectedKeySet = new Set(selectedRowKeys);
1985
- let selectedVisibleCount = 0;
1986
- visibleRows.forEach((record, index) => {
2046
+ const selectedKeySet = getSelectedRowKeySet(selectedRowKeys);
2047
+ let selectableCount = 0;
2048
+ let selectedCount = 0;
2049
+ selectableData.forEach((record, index) => {
2050
+ if (isRowSelectionDisabled(rowSelection, record)) {
2051
+ return;
2052
+ }
2053
+ selectableCount += 1;
1987
2054
  if (selectedKeySet.has(getRowKey(options, record, index))) {
1988
- selectedVisibleCount += 1;
2055
+ selectedCount += 1;
1989
2056
  }
1990
2057
  });
1991
2058
  const type = rowSelection?.type === "radio" ? "radio" : "checkbox";
1992
2059
  const state = {
1993
2060
  type,
1994
- checked: visibleRows.length > 0 && selectedVisibleCount === visibleRows.length,
1995
- indeterminate: selectedVisibleCount > 0 && selectedVisibleCount < visibleRows.length,
1996
- disabled: visibleRows.length === 0
2061
+ checked: selectableCount > 0 && selectedCount === selectableCount,
2062
+ indeterminate: selectedCount > 0 && selectedCount < selectableCount,
2063
+ disabled: selectableCount === 0
1997
2064
  };
1998
- headerSelectionStateCache.set(displayData, {
2065
+ headerSelectionStateCache.set(selectableData, {
1999
2066
  options,
2000
2067
  selectedRowKeys,
2001
2068
  state
@@ -2018,24 +2085,31 @@ function resolveToggledRowSelectionKeys(params) {
2018
2085
  };
2019
2086
  }
2020
2087
  function resolveToggleAllVisibleRowKeys(params) {
2021
- const { options, selectedRowKeys, displayData } = params;
2088
+ const { options, selectedRowKeys } = params;
2022
2089
  const rowSelection = options.rowSelection;
2023
2090
  if (!rowSelection || rowSelection.type === "radio") {
2024
2091
  return null;
2025
2092
  }
2026
- const visibleRows = getVisibleSelectableRows({
2027
- rowSelection,
2028
- displayData
2029
- });
2030
- const visibleKeys = visibleRows.map(
2031
- (record, index) => getRowKey(options, record, index)
2032
- );
2033
- const headerState = getHeaderSelectionState({
2034
- options,
2035
- selectedRowKeys,
2036
- displayData
2093
+ const selectedKeySet = getSelectedRowKeySet(selectedRowKeys);
2094
+ const selectableKeys = [];
2095
+ let allSelected = true;
2096
+ options.dataSource.forEach((record, index) => {
2097
+ if (isRowSelectionDisabled(rowSelection, record)) {
2098
+ return;
2099
+ }
2100
+ const key = getRowKey(options, record, index);
2101
+ selectableKeys.push(key);
2102
+ if (!selectedKeySet.has(key)) {
2103
+ allSelected = false;
2104
+ }
2037
2105
  });
2038
- return headerState.checked ? selectedRowKeys.filter((key) => !visibleKeys.includes(key)) : Array.from(/* @__PURE__ */ new Set([...selectedRowKeys, ...visibleKeys]));
2106
+ if (allSelected && selectableKeys.length > 0) {
2107
+ const selectableKeySet = new Set(selectableKeys);
2108
+ return selectedRowKeys.filter((key) => !selectableKeySet.has(key));
2109
+ }
2110
+ const nextKeySet = new Set(selectedRowKeys);
2111
+ selectableKeys.forEach((key) => nextKeySet.add(key));
2112
+ return Array.from(nextKeySet);
2039
2113
  }
2040
2114
 
2041
2115
  // src/engine/store/state.ts
@@ -3218,7 +3292,7 @@ function drawBodyButtonContent(params) {
3218
3292
  const top = rect.y + (rect.height - height) / 2;
3219
3293
  const palette = resolveButtonPalette(content);
3220
3294
  const textIndent = resolveContentTextIndent(content);
3221
- const paddingInline = BUTTON_PADDING_INLINE_MAP[size];
3295
+ const paddingInline = resolveButtonPaddingInline(content, size);
3222
3296
  const radius = BUTTON_RADIUS_MAP[size];
3223
3297
  ctx.save();
3224
3298
  ctx.globalAlpha *= resolveContentOpacity(content);
@@ -3326,9 +3400,12 @@ function measureButtonContentWidth(ctx, content, theme) {
3326
3400
  const intrinsicWidth = Math.max(
3327
3401
  ctx.measureText(content.text).width + resolveContentTextIndent(content),
3328
3402
  0
3329
- ) + BUTTON_PADDING_INLINE_MAP[size] * 2;
3403
+ ) + resolveButtonPaddingInline(content, size) * 2;
3330
3404
  return resolveContentLayoutWidth(content, intrinsicWidth);
3331
3405
  }
3406
+ function resolveButtonPaddingInline(content, size) {
3407
+ return content.buttonType === "link" || content.buttonType === "text" ? 4 : BUTTON_PADDING_INLINE_MAP[size];
3408
+ }
3332
3409
  function measureButtonContentHeight(content) {
3333
3410
  return BUTTON_HEIGHT_MAP[resolveButtonSize(content.size)];
3334
3411
  }
@@ -6855,7 +6932,7 @@ function expandBodyContents(contents) {
6855
6932
  expanded.push({
6856
6933
  content,
6857
6934
  contentIndex,
6858
- gapBefore: expanded.length === 0 || textOnly ? 0 : previousContent?.type === "link" && content.type === "link" ? LINK_CONTENT_GAP : CONTENT_GAP
6935
+ gapBefore: expanded.length === 0 || textOnly ? 0 : resolveInlineContentGap(previousContent, content)
6859
6936
  });
6860
6937
  if ((content.type === "checkbox" || content.type === "radio") && content.label) {
6861
6938
  const textLabelContent = {
@@ -6874,6 +6951,12 @@ function expandBodyContents(contents) {
6874
6951
  });
6875
6952
  return expanded;
6876
6953
  }
6954
+ function resolveInlineContentGap(previous, current) {
6955
+ return isInlineActionContent(previous) && isInlineActionContent(current) ? LINK_CONTENT_GAP : CONTENT_GAP;
6956
+ }
6957
+ function isInlineActionContent(content) {
6958
+ return content?.type === "link" || content?.type === "button" && (content.buttonType === "link" || content.buttonType === "text");
6959
+ }
6877
6960
  function buildSingleLineLayout(ctx, contents, availableWidth, theme) {
6878
6961
  const line = {
6879
6962
  items: [],
@@ -10463,7 +10546,7 @@ var ListTableCarouselController = class {
10463
10546
  var SUMMARY_ASYNC_BATCH_SIZE = 2e3;
10464
10547
  var SUMMARY_ASYNC_FRAME_BUDGET = 8;
10465
10548
  async function computeSummaryValuesAsync(params) {
10466
- const { rows, columns, signal } = params;
10549
+ const { rows, columns, mergeCell, signal } = params;
10467
10550
  const summaryValues = /* @__PURE__ */ new Map();
10468
10551
  const accumulators = [];
10469
10552
  columns.forEach((column) => {
@@ -10516,8 +10599,14 @@ async function computeSummaryValuesAsync(params) {
10516
10599
  }
10517
10600
  startIndex = endIndex;
10518
10601
  }
10602
+ const mergedRowCount = accumulators.some(
10603
+ (item) => item.type === "mergedRowCount"
10604
+ ) ? countMergedRows(rows, columns, mergeCell) : null;
10519
10605
  accumulators.forEach((item) => {
10520
- summaryValues.set(item.column.key, finalizeSummaryValue(item, rows));
10606
+ summaryValues.set(
10607
+ item.column.key,
10608
+ finalizeSummaryValue(item, rows, mergedRowCount)
10609
+ );
10521
10610
  });
10522
10611
  return summaryValues;
10523
10612
  }
@@ -10572,7 +10661,7 @@ function updateSummaryAccumulator(item, record) {
10572
10661
  item.max = numericValue;
10573
10662
  }
10574
10663
  }
10575
- function finalizeSummaryValue(item, rows) {
10664
+ function finalizeSummaryValue(item, rows, mergedRowCount) {
10576
10665
  if (item.column.summaryTitle != null) {
10577
10666
  return item.column.summaryTitle;
10578
10667
  }
@@ -10580,7 +10669,11 @@ function finalizeSummaryValue(item, rows) {
10580
10669
  return formatSummaryOutput(item, String(rows.length), rows);
10581
10670
  }
10582
10671
  if (item.type === "mergedRowCount") {
10583
- return formatSummaryOutput(item, String(countMergedRows(rows)), rows);
10672
+ return formatSummaryOutput(
10673
+ item,
10674
+ String(mergedRowCount ?? rows.length),
10675
+ rows
10676
+ );
10584
10677
  }
10585
10678
  if (item.type === "count") {
10586
10679
  return formatSummaryOutput(item, String(item.valueCount), rows);
@@ -10671,7 +10764,76 @@ function formatSummaryOutput(item, value, rows) {
10671
10764
  }
10672
10765
  return value;
10673
10766
  }
10674
- function countMergedRows(rows) {
10767
+ function countMergedRows(rows, columns, mergeCell) {
10768
+ const coveredRowIndexes = /* @__PURE__ */ new Set();
10769
+ const explicitRowSpans = /* @__PURE__ */ new Map();
10770
+ columns.forEach((column) => {
10771
+ if (!column.onCell) {
10772
+ return;
10773
+ }
10774
+ rows.forEach((record, rowIndex) => {
10775
+ const value = utils.getValueByDataIndex(record, column.dataIndex);
10776
+ const span = column.onCell?.(value, record, rowIndex, column);
10777
+ if (!span || !Object.prototype.hasOwnProperty.call(span, "rowSpan")) {
10778
+ return;
10779
+ }
10780
+ const rowSpan = span.rowSpan ?? 1;
10781
+ explicitRowSpans.set(`${rowIndex}::${column.key}`, rowSpan);
10782
+ if (rowSpan === 0) {
10783
+ coveredRowIndexes.add(rowIndex);
10784
+ return;
10785
+ }
10786
+ if (!Number.isFinite(rowSpan) || rowSpan <= 1) {
10787
+ return;
10788
+ }
10789
+ const spanEnd = Math.min(
10790
+ rows.length,
10791
+ rowIndex + Math.floor(rowSpan)
10792
+ );
10793
+ for (let index = rowIndex + 1; index < spanEnd; index += 1) {
10794
+ coveredRowIndexes.add(index);
10795
+ }
10796
+ });
10797
+ });
10798
+ const rowMergeRule = mergeCell?.row;
10799
+ const targetDataIndexes = rowMergeRule?.columns?.length ? rowMergeRule.columns : rowMergeRule?.keys;
10800
+ const targetMergeColumns = columns.filter(
10801
+ (column) => targetDataIndexes?.some(
10802
+ (dataIndex) => utils.isSameDataIndex(column.dataIndex, dataIndex)
10803
+ )
10804
+ );
10805
+ if (rowMergeRule?.keys.length && targetMergeColumns.length) {
10806
+ targetMergeColumns.forEach((column) => {
10807
+ let rowIndex = 0;
10808
+ while (rowIndex < rows.length) {
10809
+ if (explicitRowSpans.has(`${rowIndex}::${column.key}`)) {
10810
+ rowIndex += 1;
10811
+ continue;
10812
+ }
10813
+ const currentGroupKey = getMergeGroupKey(
10814
+ rows[rowIndex],
10815
+ rowMergeRule.keys
10816
+ );
10817
+ let rowSpan = 1;
10818
+ for (let index = rowIndex + 1; index < rows.length; index += 1) {
10819
+ if (explicitRowSpans.has(`${index}::${column.key}`)) {
10820
+ break;
10821
+ }
10822
+ if (getMergeGroupKey(rows[index], rowMergeRule.keys) !== currentGroupKey) {
10823
+ break;
10824
+ }
10825
+ rowSpan += 1;
10826
+ }
10827
+ for (let index = rowIndex + 1; index < rowIndex + rowSpan; index += 1) {
10828
+ coveredRowIndexes.add(index);
10829
+ }
10830
+ rowIndex += rowSpan;
10831
+ }
10832
+ });
10833
+ }
10834
+ if (coveredRowIndexes.size > 0) {
10835
+ return rows.length - coveredRowIndexes.size;
10836
+ }
10675
10837
  return rows.reduce((count, record) => {
10676
10838
  if (record == null || typeof record !== "object") {
10677
10839
  return count + 1;
@@ -10683,6 +10845,20 @@ function countMergedRows(rows) {
10683
10845
  return rowSpan > 0 ? count + 1 : count;
10684
10846
  }, 0);
10685
10847
  }
10848
+ function getMergeGroupKey(record, keys) {
10849
+ return keys.map(
10850
+ (dataIndex) => normalizeMergeValue(utils.getValueByDataIndex(record, dataIndex))
10851
+ ).join("|");
10852
+ }
10853
+ function normalizeMergeValue(value) {
10854
+ if (value == null) {
10855
+ return "";
10856
+ }
10857
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
10858
+ return String(value);
10859
+ }
10860
+ return JSON.stringify(value) ?? "";
10861
+ }
10686
10862
  function yieldToMainThread() {
10687
10863
  return new Promise((resolve) => {
10688
10864
  if (typeof requestAnimationFrame === "function") {
@@ -13466,7 +13642,7 @@ async function getBaseDisplayRowsAsync(params) {
13466
13642
  }
13467
13643
  function getDisplayRows(params) {
13468
13644
  const rows = getBaseDisplayRows(params);
13469
- if (!params.options.pagination || params.options.query?.mode === "remote") {
13645
+ if (!params.options.pagination || isRemotePaginationResult(params.options)) {
13470
13646
  return rows;
13471
13647
  }
13472
13648
  return sliceDisplayRowsByPagination({
@@ -13476,7 +13652,7 @@ function getDisplayRows(params) {
13476
13652
  });
13477
13653
  }
13478
13654
  function sliceDisplayRowsFromBaseRows(params) {
13479
- if (!params.options.pagination || params.options.query?.mode === "remote") {
13655
+ if (!params.options.pagination || isRemotePaginationResult(params.options)) {
13480
13656
  return params.rows;
13481
13657
  }
13482
13658
  return sliceDisplayRowsByPagination({
@@ -13485,6 +13661,13 @@ function sliceDisplayRowsFromBaseRows(params) {
13485
13661
  state: params.query.pagination
13486
13662
  });
13487
13663
  }
13664
+ function isRemotePaginationResult(options) {
13665
+ if (options.query?.mode === "remote") {
13666
+ return true;
13667
+ }
13668
+ const total = options.pagination && options.pagination.total;
13669
+ return typeof total === "number" && Number.isFinite(total) && total > options.dataSource.length;
13670
+ }
13488
13671
  function emitListTableQueryChange(params) {
13489
13672
  const {
13490
13673
  options,
@@ -15012,6 +15195,7 @@ var TEXT_SELECTION_DRAG_THRESHOLD = 5;
15012
15195
  var TEXT_SELECTION_AUTO_SCROLL_EDGE_SIZE = 36;
15013
15196
  var TEXT_SELECTION_AUTO_SCROLL_MAX_VERTICAL_SPEED = 1200;
15014
15197
  var TEXT_SELECTION_AUTO_SCROLL_MAX_HORIZONTAL_SPEED = 900;
15198
+ var EDITABLE_CELL_ROW_SELECTION_DELAY = 300;
15015
15199
  var ListTableEventController = class {
15016
15200
  constructor(host) {
15017
15201
  __publicField(this, "searchKeyword", "");
@@ -15033,6 +15217,7 @@ var ListTableEventController = class {
15033
15217
  __publicField(this, "cellSelectionAutoScrollVelocity", { x: 0, y: 0 });
15034
15218
  __publicField(this, "cellSelectionAutoScrollTargetVelocity", { x: 0, y: 0 });
15035
15219
  __publicField(this, "continuousScrollTimer", null);
15220
+ __publicField(this, "pendingEditableCellRowSelectionTimer", null);
15036
15221
  __publicField(this, "outsideClickDocument", null);
15037
15222
  __publicField(this, "outsideClickStarted", null);
15038
15223
  __publicField(this, "host");
@@ -15434,6 +15619,7 @@ var ListTableEventController = class {
15434
15619
  );
15435
15620
  });
15436
15621
  __publicField(this, "handleDoubleClick", (event) => {
15622
+ this.cancelPendingEditableCellRowSelection();
15437
15623
  if (!this.host.canvasElement) {
15438
15624
  return;
15439
15625
  }
@@ -15963,7 +16149,24 @@ var ListTableEventController = class {
15963
16149
  if ((result.area === "body" || result.area === "body-content") && typeof result.rowIndex === "number" && this.host.options.rowSelection?.selectRowByClick && result.columnKey && !isSystemColumnKey(result.columnKey)) {
15964
16150
  const record = this.host.getDisplayData()[result.rowIndex];
15965
16151
  if (record !== void 0) {
15966
- this.host.toggleRowSelection(record, result.rowIndex);
16152
+ const column = this.host.leafColumns.find(
16153
+ (item) => item.key === result.columnKey
16154
+ );
16155
+ const value = column?.dataIndex != null ? utils.getValueByDataIndex(record, column.dataIndex) : void 0;
16156
+ const canOpenEditorByDoubleClick = shouldOpenCellEditorOnClick(
16157
+ column,
16158
+ 2,
16159
+ {
16160
+ value,
16161
+ record,
16162
+ rowIndex: result.rowIndex
16163
+ }
16164
+ );
16165
+ if (canOpenEditorByDoubleClick && event.detail === 1) {
16166
+ this.scheduleEditableCellRowSelection(record, result.rowIndex);
16167
+ } else if (!canOpenEditorByDoubleClick || event.detail !== 2) {
16168
+ this.host.toggleRowSelection(record, result.rowIndex);
16169
+ }
15967
16170
  }
15968
16171
  }
15969
16172
  if (result.area === "body" && typeof result.rowIndex === "number" && this.host.options.expandable?.expandRowByClick && result.columnKey && !isSystemColumnKey(result.columnKey) && this.host.toggleRowExpand(result.rowIndex)) {
@@ -16437,6 +16640,7 @@ var ListTableEventController = class {
16437
16640
  this.host.render();
16438
16641
  }
16439
16642
  destroy() {
16643
+ this.cancelPendingEditableCellRowSelection();
16440
16644
  this.stopContinuousScroll();
16441
16645
  this.stopTextSelectionAutoScroll();
16442
16646
  this.stopCellSelectionAutoScroll();
@@ -16501,6 +16705,20 @@ var ListTableEventController = class {
16501
16705
  event.preventDefault();
16502
16706
  this.host.editingController.open(rowIndex, columnKey, event.key);
16503
16707
  }
16708
+ scheduleEditableCellRowSelection(record, rowIndex) {
16709
+ this.cancelPendingEditableCellRowSelection();
16710
+ this.pendingEditableCellRowSelectionTimer = globalThis.setTimeout(() => {
16711
+ this.pendingEditableCellRowSelectionTimer = null;
16712
+ this.host.toggleRowSelection(record, rowIndex);
16713
+ }, EDITABLE_CELL_ROW_SELECTION_DELAY);
16714
+ }
16715
+ cancelPendingEditableCellRowSelection() {
16716
+ if (this.pendingEditableCellRowSelectionTimer == null) {
16717
+ return;
16718
+ }
16719
+ globalThis.clearTimeout(this.pendingEditableCellRowSelectionTimer);
16720
+ this.pendingEditableCellRowSelectionTimer = null;
16721
+ }
16504
16722
  async autoFitColumnWidths(columnKey) {
16505
16723
  const ctx = this.host.canvasElement?.getContext("2d");
16506
16724
  if (!ctx) {
@@ -18239,6 +18457,47 @@ function persistListTableColumnConfig(params) {
18239
18457
  )
18240
18458
  );
18241
18459
  }
18460
+ async function resetListTableStoredColumnConfig(params) {
18461
+ const { storageKey, columns } = params;
18462
+ if (!storageKey) {
18463
+ return;
18464
+ }
18465
+ const initialColumnTree = columns.map(cloneColumnTree);
18466
+ ensureColumnKeysInPlace(initialColumnTree);
18467
+ const stored = await getColumnConfig(storageKey);
18468
+ if (!stored) {
18469
+ return;
18470
+ }
18471
+ const initialColumns = buildStoredColumnConfig(
18472
+ initialColumnTree,
18473
+ { key: null, order: null },
18474
+ {}
18475
+ ).columns;
18476
+ const nextColumns = {};
18477
+ Object.entries(initialColumns).forEach(([key, initial]) => {
18478
+ const next = {
18479
+ ...stored.columns[key] ?? initial,
18480
+ width: initial.width,
18481
+ hidden: initial.hidden
18482
+ };
18483
+ if (initial.fixed) {
18484
+ next.fixed = initial.fixed;
18485
+ } else {
18486
+ delete next.fixed;
18487
+ }
18488
+ nextColumns[key] = next;
18489
+ });
18490
+ await saveColumnConfig(storageKey, {
18491
+ ...stored,
18492
+ columns: nextColumns
18493
+ });
18494
+ }
18495
+ function cloneColumnTree(column) {
18496
+ return {
18497
+ ...column,
18498
+ children: column.children?.map(cloneColumnTree)
18499
+ };
18500
+ }
18242
18501
  async function loadListTableStoredConfig(params) {
18243
18502
  const { storageKey, columns } = params;
18244
18503
  if (!storageKey) {
@@ -20191,6 +20450,10 @@ function buildListTableRenderSnapshot(params) {
20191
20450
  groupedColumnKeys
20192
20451
  );
20193
20452
  const leafColumns = flattenLeafColumns(normalizedColumns);
20453
+ const totalColumnWidth = computeColumnWidths(leafColumns);
20454
+ if (width > 0 && totalColumnWidth > width && totalColumnWidth <= hostWidth) {
20455
+ shrinkColumnWidthsToFit(leafColumns, width);
20456
+ }
20194
20457
  if (options.stretchColumns !== false && width > 0 && !draggingResize) {
20195
20458
  stretchColumnWidths(leafColumns, width);
20196
20459
  }
@@ -20734,8 +20997,8 @@ function updateListTableRenderSnapshotScroll(params) {
20734
20997
  } : snapshot.frozenRows;
20735
20998
  return {
20736
20999
  ...snapshot,
20737
- width,
20738
- height,
21000
+ width: snapshot.width,
21001
+ height: snapshot.height,
20739
21002
  columnSegments,
20740
21003
  headerRows,
20741
21004
  scrollbarLayout,
@@ -21120,13 +21383,8 @@ function drawScrollbars(ctx, layout, descriptors, borderColor, opacity = 1, inte
21120
21383
  verticalFrame.bodyBackgroundColor
21121
21384
  );
21122
21385
  }
21123
- if (layout.vertical && verticalFrame) {
21124
- drawVerticalScrollbarFrame(
21125
- ctx,
21126
- layout.vertical,
21127
- verticalFrame,
21128
- borderColor
21129
- );
21386
+ if (verticalFrame) {
21387
+ drawVerticalScrollbarFrame(ctx, verticalFrame, borderColor);
21130
21388
  }
21131
21389
  if (layout.horizontal) {
21132
21390
  drawAxisScrollbar(
@@ -21244,28 +21502,28 @@ function drawTrackBorder(ctx, rect, axis, borderColor) {
21244
21502
  ctx.stroke();
21245
21503
  ctx.restore();
21246
21504
  }
21247
- function drawVerticalScrollbarFrame(ctx, layout, frame, borderColor) {
21248
- const left = Math.round(layout.decreaseButton.x) + 0.5;
21249
- const right = Math.round(layout.decreaseButton.x + layout.decreaseButton.width) - 0.5;
21505
+ function drawVerticalScrollbarFrame(ctx, frame, borderColor) {
21506
+ const left = Math.round(frame.x) + 0.5;
21507
+ const right = Math.round(frame.x + frame.width) - 0.5;
21250
21508
  const top = Math.round(frame.top) + 0.5;
21251
21509
  const bottom = Math.round(frame.top + frame.height) - 0.5;
21252
21510
  const headerBottom = Math.round(frame.headerBottom) + 0.5;
21253
- if (right <= left || bottom <= top) {
21511
+ if (frame.width <= 0 || right <= left || bottom <= top) {
21254
21512
  return;
21255
21513
  }
21256
21514
  ctx.save();
21257
21515
  ctx.fillStyle = frame.headerBackgroundColor;
21258
21516
  ctx.fillRect(
21259
- layout.decreaseButton.x,
21517
+ frame.x,
21260
21518
  frame.top,
21261
- layout.decreaseButton.width,
21519
+ frame.width,
21262
21520
  Math.max(frame.headerBottom - frame.top, 0)
21263
21521
  );
21264
21522
  ctx.fillStyle = frame.bodyBackgroundColor;
21265
21523
  ctx.fillRect(
21266
- layout.decreaseButton.x,
21524
+ frame.x,
21267
21525
  frame.headerBottom,
21268
- layout.decreaseButton.width,
21526
+ frame.width,
21269
21527
  Math.max(frame.top + frame.height - frame.headerBottom, 0)
21270
21528
  );
21271
21529
  ctx.strokeStyle = borderColor;
@@ -22111,7 +22369,7 @@ function buildAutoRowSpanMap(rows, columns, rule, spanConfigMap, sourceRowIndexM
22111
22369
  rowIndex += 1;
22112
22370
  continue;
22113
22371
  }
22114
- const currentGroupKey = getMergeGroupKey(rows[rowIndex], groupKeys);
22372
+ const currentGroupKey = getMergeGroupKey2(rows[rowIndex], groupKeys);
22115
22373
  let rowSpan = 1;
22116
22374
  for (let index = rowIndex + 1; index < rows.length; index += 1) {
22117
22375
  if (sourceRowIndexMap[index] !== (sourceRowIndexMap[index - 1] ?? index - 1) + 1) {
@@ -22121,7 +22379,7 @@ function buildAutoRowSpanMap(rows, columns, rule, spanConfigMap, sourceRowIndexM
22121
22379
  if (hasExplicitSpan(spanConfigMap.get(nextCellKey), "rowSpan")) {
22122
22380
  break;
22123
22381
  }
22124
- if (getMergeGroupKey(rows[index], groupKeys) !== currentGroupKey) {
22382
+ if (getMergeGroupKey2(rows[index], groupKeys) !== currentGroupKey) {
22125
22383
  break;
22126
22384
  }
22127
22385
  rowSpan += 1;
@@ -22224,13 +22482,13 @@ function clampSpan(span, max) {
22224
22482
  }
22225
22483
  return Math.max(1, Math.min(Math.floor(span), max));
22226
22484
  }
22227
- function getMergeGroupKey(record, keys) {
22485
+ function getMergeGroupKey2(record, keys) {
22228
22486
  if (!keys?.length) {
22229
22487
  return "";
22230
22488
  }
22231
- return keys.map((key) => normalizeMergeValue(utils.getValueByDataIndex(record, key))).join("|");
22489
+ return keys.map((key) => normalizeMergeValue2(utils.getValueByDataIndex(record, key))).join("|");
22232
22490
  }
22233
- function normalizeMergeValue(value) {
22491
+ function normalizeMergeValue2(value) {
22234
22492
  if (value == null) {
22235
22493
  return "";
22236
22494
  }
@@ -22240,7 +22498,7 @@ function normalizeMergeValue(value) {
22240
22498
  return JSON.stringify(value) ?? "";
22241
22499
  }
22242
22500
  function isSameMergeValue(left, right) {
22243
- return normalizeMergeValue(left) === normalizeMergeValue(right);
22501
+ return normalizeMergeValue2(left) === normalizeMergeValue2(right);
22244
22502
  }
22245
22503
  function getMergedCellWidth(columns, startIndex, colSpan) {
22246
22504
  let width = 0;
@@ -23838,9 +24096,7 @@ function drawListTableHeader(params) {
23838
24096
  columnKey: ROW_SELECTION_COLUMN_KEY,
23839
24097
  ...getHeaderSelectionState({
23840
24098
  options,
23841
- selectedRowKeys,
23842
- displayData
23843
- })
24099
+ selectedRowKeys})
23844
24100
  } : null,
23845
24101
  inlineContentInset,
23846
24102
  collapsedColumnMarkers,
@@ -24503,6 +24759,11 @@ function executeListTableRenderPipeline(params) {
24503
24759
  scrollbarOpacity,
24504
24760
  isScrollbarInteractive,
24505
24761
  {
24762
+ x: width,
24763
+ width: options.scrollbar?.visible === false ? 0 : Math.max(
24764
+ options.scrollbar?.thickness ?? DEFAULT_SCROLLBAR_THICKNESS,
24765
+ 6
24766
+ ),
24506
24767
  top: 0,
24507
24768
  height,
24508
24769
  headerBottom: headerHeight,
@@ -26004,6 +26265,7 @@ var ListTableSummaryController = class {
26004
26265
  const summaryTask = computeSummaryValuesAsync({
26005
26266
  rows: snapshot.displayRows,
26006
26267
  columns: snapshot.leafColumns,
26268
+ mergeCell: this.options.getOptions().query?.mergeCell,
26007
26269
  signal
26008
26270
  }).then((summaryValues) => {
26009
26271
  if (signal.aborted || taskId !== this.summaryTaskId) {
@@ -26894,6 +27156,19 @@ var ListTableCore = class {
26894
27156
  */
26895
27157
  updateOptions(options) {
26896
27158
  this.animationController.stopCarouselScroll();
27159
+ const host = this.asAssemblyHost();
27160
+ const incomingColumnsAreRuntimeColumns = options.columns === this.options.columns;
27161
+ const nextInitialColumns = incomingColumnsAreRuntimeColumns ? cloneColumns(host.initialColumns) : cloneColumns(options.columns);
27162
+ const nextInitialStretchColumns = incomingColumnsAreRuntimeColumns ? host.initialStretchColumns : options.stretchColumns;
27163
+ const shouldPreserveRuntimeWidths = this.options.stretchColumns === false && options.stretchColumns === host.initialStretchColumns;
27164
+ if (shouldPreserveRuntimeWidths) {
27165
+ preserveRuntimeColumnWidths({
27166
+ nextColumns: options.columns,
27167
+ runtimeColumns: this.options.columns,
27168
+ initialColumns: host.initialColumns
27169
+ });
27170
+ options.stretchColumns = false;
27171
+ }
26897
27172
  applyInitialColumnVisibility(options.columns);
26898
27173
  ensureColumnKeysInPlace(options.columns);
26899
27174
  if (options.expandable?.expandedRowKeys !== void 0 && !areSameRowKeySet(
@@ -26909,10 +27184,9 @@ var ListTableCore = class {
26909
27184
  this.queryController.reset();
26910
27185
  this.summaryController.reset();
26911
27186
  this.options = options;
26912
- const host = this.asAssemblyHost();
26913
27187
  host.syncGroupingFromOptions();
26914
- host.initialColumns = cloneColumns(options.columns);
26915
- host.initialStretchColumns = options.stretchColumns;
27188
+ host.initialColumns = nextInitialColumns;
27189
+ host.initialStretchColumns = nextInitialStretchColumns;
26916
27190
  this.store.dispatch(
26917
27191
  replaceStateAction(
26918
27192
  resolveListTableStateOnOptionsUpdate(options, this.store.getSnapshot())
@@ -27116,5 +27390,6 @@ var ListTable = class {
27116
27390
  };
27117
27391
 
27118
27392
  exports.ListTable = ListTable;
27393
+ exports.resetListTableStoredColumnConfig = resetListTableStoredColumnConfig;
27119
27394
  //# sourceMappingURL=index.cjs.map
27120
27395
  //# sourceMappingURL=index.cjs.map