@canvas-components/list-table 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { stringifyDataIndex, getValueByDataIndex, clamp, copyTextSync, copyText, exportTableToXlsx, isSameDataIndex, exportTableToTxt, exportTableToCsv, downloadJsonFile, mapRowsToExportRecords, copyJson, copyRows, isPointInRect as isPointInRect$1 } from '@canvas-components/utils';
1
+ import { stringifyDataIndex, getValueByDataIndex, clamp, copyTextSync, copyText, exportTableToXlsx, exportTableToTxt, exportTableToCsv, downloadJsonFile, mapRowsToExportRecords, copyJson, copyRows, isSameDataIndex, 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';
@@ -322,6 +322,7 @@ function normalizeColumn(column, depth, parentKey) {
322
322
  minWidth: Number(column.minWidth) || DEFAULT_MIN_WIDTH,
323
323
  maxWidth: Number(column.maxWidth) || DEFAULT_MAX_WIDTH,
324
324
  align: column.align ?? "left",
325
+ headerAlign: column.headerAlign,
325
326
  fixed: column.fixed,
326
327
  hidden: column.hidden,
327
328
  ellipsis: column.ellipsis,
@@ -341,6 +342,7 @@ function normalizeColumn(column, depth, parentKey) {
341
342
  cellType: column.cellType,
342
343
  cellStyle: column.cellStyle,
343
344
  moneyFormat: column.moneyFormat,
345
+ dataFormat: column.dataFormat,
344
346
  headerStyle: column.headerStyle,
345
347
  summary: column.summary,
346
348
  summaryTitle: column.summaryTitle,
@@ -576,15 +578,28 @@ function cloneColumns(columns) {
576
578
  children: column.children ? cloneColumns(column.children) : void 0
577
579
  }));
578
580
  }
581
+ function applyInitialColumnVisibility(columns) {
582
+ columns.forEach((column) => {
583
+ if (column.hidden === void 0 && column.initialHide) {
584
+ column.hidden = true;
585
+ }
586
+ if (column.children?.length) {
587
+ applyInitialColumnVisibility(column.children);
588
+ }
589
+ });
590
+ }
579
591
  function replaceColumns(target, source) {
580
592
  target.splice(0, target.length, ...cloneColumns(source));
581
593
  }
582
594
  function buildHeaderSettingsItems(columns) {
583
595
  ensureColumnKeysInPlace(columns);
584
596
  const totalVisibleLeafCount = countVisibleLeafColumns(columns);
585
- return columns.map(
586
- (column) => buildHeaderSettingsItem(column, totalVisibleLeafCount, false)
587
- );
597
+ return columns.flatMap((column) => {
598
+ if (column.hideInSetting) {
599
+ return [];
600
+ }
601
+ return [buildHeaderSettingsItem(column, totalVisibleLeafCount, false)];
602
+ });
588
603
  }
589
604
  function setHeaderColumnVisible(columns, columnKey, visible) {
590
605
  if (!visible) {
@@ -644,9 +659,7 @@ function resolveCollapsedHeaderColumnMarkers(params) {
644
659
  if (visibleLeafKeys.length === 0) {
645
660
  return [];
646
661
  }
647
- const leafIndexMap = new Map(
648
- allLeafKeys.map((key, index) => [key, index])
649
- );
662
+ const leafIndexMap = new Map(allLeafKeys.map((key, index) => [key, index]));
650
663
  const markers = [];
651
664
  let previousVisibleIndex = -1;
652
665
  visibleLeafKeys.forEach((columnKey) => {
@@ -712,19 +725,87 @@ function restoreAllHiddenHeaderColumns(columns) {
712
725
  });
713
726
  return updated;
714
727
  }
728
+ function getColumnPresentationConfig(columns, columnKey) {
729
+ const column = findColumnNode(columns, columnKey);
730
+ if (!column) {
731
+ return null;
732
+ }
733
+ const bodyColumn = column.children?.length ? collectLeafColumns([column])[0] : column;
734
+ return {
735
+ headerHorizontal: column.headerAlign ?? column.align ?? "left",
736
+ headerVertical: column.headerStyle?.verticalAlign ?? "middle",
737
+ bodyHorizontal: bodyColumn?.align ?? "left",
738
+ bodyVertical: bodyColumn?.cellStyle?.verticalAlign ?? "middle",
739
+ dataFormat: column.dataFormat ?? "default",
740
+ dataFormatAvailable: !column.children?.length && !column.render && (column.cellType == null || column.cellType === "text" || column.cellType === "money")
741
+ };
742
+ }
743
+ function setColumnAlignment(params) {
744
+ const column = findColumnNode(params.columns, params.columnKey);
745
+ if (!column) {
746
+ return false;
747
+ }
748
+ const targets = params.area === "body" && column.children?.length ? collectLeafColumns([column]) : [column];
749
+ targets.forEach((target) => {
750
+ if (params.area === "header") {
751
+ if (params.axis === "horizontal") {
752
+ target.headerAlign = params.value;
753
+ } else {
754
+ target.headerStyle = {
755
+ ...target.headerStyle,
756
+ verticalAlign: params.value
757
+ };
758
+ }
759
+ return;
760
+ }
761
+ if (params.axis === "horizontal") {
762
+ target.align = params.value;
763
+ } else {
764
+ target.cellStyle = {
765
+ ...target.cellStyle,
766
+ verticalAlign: params.value
767
+ };
768
+ }
769
+ });
770
+ return true;
771
+ }
772
+ function setColumnDataFormat(columns, columnKey, dataFormat) {
773
+ const column = findColumnNode(columns, columnKey);
774
+ if (!column || column.children?.length || column.render) {
775
+ return false;
776
+ }
777
+ column.dataFormat = dataFormat === "default" ? void 0 : dataFormat;
778
+ return true;
779
+ }
780
+ function findColumnNode(columns, columnKey) {
781
+ for (const column of columns) {
782
+ if (resolveColumnKey(column) === columnKey) {
783
+ return column;
784
+ }
785
+ if (column.children?.length) {
786
+ const child = findColumnNode(column.children, columnKey);
787
+ if (child) {
788
+ return child;
789
+ }
790
+ }
791
+ }
792
+ return null;
793
+ }
715
794
  function buildHeaderSettingsItem(column, totalVisibleLeafCount, parentHidden) {
716
795
  const hidden = parentHidden || !!column.hidden;
717
- const children = column.children?.map(
796
+ const children = column.children?.filter((child) => !child.hideInSetting).map(
718
797
  (child) => buildHeaderSettingsItem(child, totalVisibleLeafCount, hidden)
719
798
  );
720
799
  const leafCount = countLeafColumns([column]);
721
800
  const visibleLeafCount = hidden ? 0 : countVisibleLeafColumns([column]);
722
801
  const checked = leafCount > 0 && visibleLeafCount === leafCount;
723
802
  const indeterminate = visibleLeafCount > 0 && visibleLeafCount < leafCount;
724
- const disabled = visibleLeafCount > 0 && visibleLeafCount >= totalVisibleLeafCount;
803
+ const disabled = column.disableHide && checked || visibleLeafCount > 0 && visibleLeafCount >= totalVisibleLeafCount;
725
804
  return {
726
805
  key: resolveColumnKey(column),
727
- title: String(column.title ?? resolveColumnKey(column)),
806
+ title: String(
807
+ column.settingTitle ?? column.title ?? resolveColumnKey(column)
808
+ ),
728
809
  checked,
729
810
  indeterminate,
730
811
  disabled,
@@ -734,6 +815,9 @@ function buildHeaderSettingsItem(column, totalVisibleLeafCount, parentHidden) {
734
815
  function setColumnVisible(columns, columnKey, visible, ancestors = []) {
735
816
  for (const column of columns) {
736
817
  if (column.key === columnKey) {
818
+ if (!visible && column.disableHide) {
819
+ return false;
820
+ }
737
821
  ancestors.forEach((item) => {
738
822
  item.hidden = false;
739
823
  });
@@ -741,12 +825,10 @@ function setColumnVisible(columns, columnKey, visible, ancestors = []) {
741
825
  return true;
742
826
  }
743
827
  if (column.children?.length) {
744
- const updated = setColumnVisible(
745
- column.children,
746
- columnKey,
747
- visible,
748
- [...ancestors, column]
749
- );
828
+ const updated = setColumnVisible(column.children, columnKey, visible, [
829
+ ...ancestors,
830
+ column
831
+ ]);
750
832
  if (updated) {
751
833
  return true;
752
834
  }
@@ -755,6 +837,9 @@ function setColumnVisible(columns, columnKey, visible, ancestors = []) {
755
837
  return false;
756
838
  }
757
839
  function setSubtreeVisible(column, visible) {
840
+ if (!visible && column.disableHide) {
841
+ return;
842
+ }
758
843
  column.hidden = !visible;
759
844
  column.children?.forEach((child) => {
760
845
  setSubtreeVisible(child, visible);
@@ -5308,6 +5393,10 @@ function resolveColumnFormItemProps(column, context) {
5308
5393
  var CONTENT_HORIZONTAL_PADDING = 12;
5309
5394
  var CONTENT_GAP = 8;
5310
5395
  var CONTENT_VERTICAL_PADDING = 6;
5396
+ var THOUSANDS_NUMBER_FORMAT = new Intl.NumberFormat("zh-CN", {
5397
+ useGrouping: true,
5398
+ maximumFractionDigits: 20
5399
+ });
5311
5400
  function resolveBodyCellContents(params) {
5312
5401
  const { record, rowIndex, column } = params;
5313
5402
  const value = getValueByDataIndex(record, column.dataIndex);
@@ -5321,6 +5410,14 @@ function resolveBodyCellContents(params) {
5321
5410
  record,
5322
5411
  rowIndex
5323
5412
  });
5413
+ if (column.dataFormat && column.dataFormat !== "default") {
5414
+ return [
5415
+ {
5416
+ type: "text",
5417
+ text: formattedText ?? formatListTableDataValue(value, column.dataFormat)
5418
+ }
5419
+ ];
5420
+ }
5324
5421
  if (column.cellType === "checkbox" || column.cellType === "radio" || column.cellType === "switch") {
5325
5422
  return [
5326
5423
  {
@@ -5481,6 +5578,26 @@ function formatMoneyValue(value, options) {
5481
5578
  const formattedDecimal = decimalText != null && decimalText.length > 0 ? `.${decimalText}` : "";
5482
5579
  return `${sign}${symbol}${formattedInteger}${formattedDecimal}`;
5483
5580
  }
5581
+ function formatListTableDataValue(value, dataFormat) {
5582
+ if (dataFormat === "number") {
5583
+ const numericValue = parseMoneyNumber(value);
5584
+ return numericValue == null ? String(value ?? "") : String(numericValue);
5585
+ }
5586
+ if (dataFormat === "thousands") {
5587
+ const numericValue = parseMoneyNumber(value);
5588
+ if (numericValue == null) {
5589
+ return String(value ?? "");
5590
+ }
5591
+ return THOUSANDS_NUMBER_FORMAT.format(numericValue);
5592
+ }
5593
+ if (dataFormat === "money") {
5594
+ return formatMoneyValue(value, {
5595
+ thousandsSeparator: true,
5596
+ decimalPlaces: 2
5597
+ });
5598
+ }
5599
+ return String(value ?? "");
5600
+ }
5484
5601
  function parseMoneyNumber(value) {
5485
5602
  if (typeof value === "number") {
5486
5603
  return Number.isFinite(value) ? value : null;
@@ -9189,116 +9306,363 @@ var ListTableCarouselController = class {
9189
9306
  });
9190
9307
  }
9191
9308
  };
9192
- function getCellClipboardText(record, rowIndex, column) {
9193
- const value = getValueByDataIndex(record, column.dataIndex);
9194
- const rendered = column.render?.(value, record, rowIndex, column);
9195
- if (rendered != null) {
9196
- return renderResultToClipboardText(rendered);
9309
+ var SUMMARY_ASYNC_BATCH_SIZE = 2e3;
9310
+ var SUMMARY_ASYNC_FRAME_BUDGET = 8;
9311
+ async function computeSummaryValuesAsync(params) {
9312
+ const { rows, columns, signal } = params;
9313
+ const summaryValues = /* @__PURE__ */ new Map();
9314
+ const accumulators = [];
9315
+ columns.forEach((column) => {
9316
+ const accumulator = createSummaryAccumulator(column);
9317
+ if (accumulator) {
9318
+ accumulators.push(accumulator);
9319
+ }
9320
+ });
9321
+ columns.forEach((column) => {
9322
+ if (column.summaryTitle != null) {
9323
+ summaryValues.set(column.key, column.summaryTitle);
9324
+ }
9325
+ });
9326
+ if (accumulators.length === 0) {
9327
+ return summaryValues;
9197
9328
  }
9198
- if (column.cellType === "checkbox" || column.cellType === "radio") {
9199
- return String(Boolean(value));
9329
+ for (let startIndex = 0; startIndex < rows.length; ) {
9330
+ if (signal?.aborted) {
9331
+ throw new Error("summary computation aborted");
9332
+ }
9333
+ const frameStart = now();
9334
+ let endIndex = startIndex;
9335
+ while (endIndex < rows.length) {
9336
+ if (signal?.aborted) {
9337
+ throw new Error("summary computation aborted");
9338
+ }
9339
+ const batchEndIndex = Math.min(
9340
+ endIndex + SUMMARY_ASYNC_BATCH_SIZE,
9341
+ rows.length
9342
+ );
9343
+ for (let rowIndex = endIndex; rowIndex < batchEndIndex; rowIndex += 1) {
9344
+ const record = rows[rowIndex];
9345
+ if (!record) {
9346
+ continue;
9347
+ }
9348
+ accumulators.forEach((item) => {
9349
+ updateSummaryAccumulator(item, record);
9350
+ });
9351
+ }
9352
+ endIndex = batchEndIndex;
9353
+ if (endIndex >= rows.length) {
9354
+ break;
9355
+ }
9356
+ if (now() - frameStart >= SUMMARY_ASYNC_FRAME_BUDGET) {
9357
+ break;
9358
+ }
9359
+ }
9360
+ if (endIndex < rows.length) {
9361
+ await yieldToMainThread();
9362
+ }
9363
+ startIndex = endIndex;
9200
9364
  }
9201
- return resolveFormattedCellText({
9365
+ accumulators.forEach((item) => {
9366
+ summaryValues.set(
9367
+ item.column.key,
9368
+ finalizeSummaryValue(item, rows)
9369
+ );
9370
+ });
9371
+ return summaryValues;
9372
+ }
9373
+ function createSummaryAccumulator(column) {
9374
+ const config = resolveSummaryConfig(column);
9375
+ if (!config) {
9376
+ return null;
9377
+ }
9378
+ return {
9202
9379
  column,
9203
- value,
9204
- record,
9205
- rowIndex
9206
- }) ?? String(value ?? "");
9380
+ config,
9381
+ type: config.type ?? "sum",
9382
+ valueCount: 0,
9383
+ numericCount: 0,
9384
+ sum: 0,
9385
+ min: null,
9386
+ max: null,
9387
+ uniqueValues: /* @__PURE__ */ new Set()
9388
+ };
9207
9389
  }
9208
- function createListTableSelectionCopyText(params) {
9209
- const columns = params.columns.filter(
9210
- (column2) => column2.key !== ROW_SELECTION_COLUMN_KEY && column2.key !== EXPAND_COLUMN_KEY
9211
- );
9212
- const columnRange = params.rangeHighlight.selectedColumnRange;
9213
- const rowRange = params.rangeHighlight.selectedRowRange;
9214
- const cellRange = params.rangeHighlight.selectedCellRange;
9215
- if (cellRange) {
9216
- const selectedColumns2 = params.columns.filter(
9217
- (column2, index) => index >= cellRange.startColumnIndex && index <= cellRange.endColumnIndex && column2.key !== ROW_SELECTION_COLUMN_KEY && column2.key !== EXPAND_COLUMN_KEY
9218
- );
9219
- return params.rows.slice(cellRange.startRowIndex, cellRange.endRowIndex + 1).map(
9220
- (record2, offset) => selectedColumns2.map(
9221
- (column2) => getCellClipboardText(
9222
- record2,
9223
- cellRange.startRowIndex + offset,
9224
- column2
9225
- )
9226
- ).join(" ")
9227
- ).join("\n");
9390
+ function updateSummaryAccumulator(item, record) {
9391
+ if (item.column.summaryTitle != null) {
9392
+ return;
9228
9393
  }
9229
- const mode = params.highlightMode ?? (rowRange && columnRange ? "cross" : rowRange ? "row" : "column");
9230
- const selectedColumns = columnRange ? params.columns.filter(
9231
- (column2, index) => index >= columnRange.start && index <= columnRange.end
9232
- ).filter(
9233
- (column2) => column2.key !== ROW_SELECTION_COLUMN_KEY && column2.key !== EXPAND_COLUMN_KEY
9234
- ) : columns;
9235
- rowRange ? Math.max(rowRange.start, 0) : 0;
9236
- rowRange ? Math.min(rowRange.end, params.rows.length - 1) : params.rows.length - 1;
9237
- if (mode === "column" && columnRange && params.selection.rowIndex == null) {
9238
- return params.rows.map(
9239
- (record2, rowIndex2) => selectedColumns.map((column2) => getCellClipboardText(record2, rowIndex2, column2)).join(" ")
9240
- ).join("\n");
9394
+ if (item.type === "rowCount" || item.type === "mergedRowCount") {
9395
+ return;
9241
9396
  }
9242
- const { rowIndex, columnKey } = params.selection;
9243
- const record = rowIndex == null ? void 0 : params.rows[rowIndex];
9244
- const column = columns.find((item) => item.key === columnKey);
9245
- return record && column && rowIndex != null ? getCellClipboardText(record, rowIndex, column) : null;
9246
- }
9247
- function createListTableRangeCopyText(params) {
9248
- return createListTableSelectionCopyText({
9249
- rows: params.rows,
9250
- columns: params.columns,
9251
- selection: { rowIndex: null, columnKey: null },
9252
- rangeHighlight: {
9253
- selectedCellRange: {
9254
- startRowIndex: Math.max(
9255
- Math.min(params.startRowIndex, params.endRowIndex),
9256
- 0
9257
- ),
9258
- endRowIndex: Math.min(
9259
- Math.max(params.startRowIndex, params.endRowIndex),
9260
- Math.max(params.rows.length - 1, 0)
9261
- ),
9262
- startColumnIndex: Math.max(
9263
- Math.min(params.startColumnIndex, params.endColumnIndex),
9264
- 0
9265
- ),
9266
- endColumnIndex: Math.min(
9267
- Math.max(params.startColumnIndex, params.endColumnIndex),
9268
- Math.max(params.columns.length - 1, 0)
9269
- )
9270
- }
9271
- }
9272
- });
9273
- }
9274
- async function copyBodyCellContent(params) {
9275
- const { rows, columns, rowIndex, columnKey } = params;
9276
- const record = rows[rowIndex];
9277
- const column = columns.find((item) => item.key === columnKey);
9278
- if (!record || !column) {
9397
+ const rawValue = normalizeSummaryValue(
9398
+ getColumnRawValue(record, item.column, item.config)
9399
+ );
9400
+ if (rawValue == null) {
9279
9401
  return;
9280
9402
  }
9281
- try {
9282
- await copyText(getCellClipboardText(record, rowIndex, column));
9283
- } catch (error) {
9284
- console.error("[ListTable] Failed to copy cell:", error);
9403
+ item.valueCount += 1;
9404
+ if (item.type === "unionCount") {
9405
+ item.uniqueValues.add(String(rawValue));
9406
+ return;
9285
9407
  }
9286
- }
9287
- async function copyHeaderCellContent(params) {
9288
- const headerNode = findHeaderNodeByKey(params.headerTree, params.columnKey);
9289
- try {
9290
- await copyText(headerNode?.title ?? params.columnKey);
9291
- } catch (error) {
9292
- console.error("[ListTable] Failed to copy header cell:", error);
9408
+ if (item.type === "count") {
9409
+ return;
9293
9410
  }
9294
- }
9295
- async function copyColumnContent(params) {
9296
- const { rows, columns, columnKey } = params;
9297
- const column = columns.find((item) => item.key === columnKey);
9298
- if (!column) {
9411
+ const numericValue = toNumber(rawValue);
9412
+ if (numericValue == null) {
9299
9413
  return;
9300
9414
  }
9301
- const values = rows.map((record, rowIndex) => [
9415
+ item.numericCount += 1;
9416
+ item.sum += numericValue;
9417
+ item.min = item.min == null ? numericValue : Math.min(item.min, numericValue);
9418
+ item.max = item.max == null ? numericValue : Math.max(item.max, numericValue);
9419
+ }
9420
+ function finalizeSummaryValue(item, rows) {
9421
+ if (item.column.summaryTitle != null) {
9422
+ return item.column.summaryTitle;
9423
+ }
9424
+ if (item.type === "rowCount") {
9425
+ return formatSummaryOutput(item, String(rows.length), rows);
9426
+ }
9427
+ if (item.type === "mergedRowCount") {
9428
+ return formatSummaryOutput(item, String(countMergedRows(rows)), rows);
9429
+ }
9430
+ if (item.type === "count") {
9431
+ return formatSummaryOutput(item, String(item.valueCount), rows);
9432
+ }
9433
+ if (item.type === "unionCount") {
9434
+ return formatSummaryOutput(item, String(item.uniqueValues.size), rows);
9435
+ }
9436
+ if (item.numericCount === 0) {
9437
+ if (item.type === "min" || item.type === "max") {
9438
+ return formatSummaryOutput(item, "", rows);
9439
+ }
9440
+ return formatSummaryOutput(item, "0", rows);
9441
+ }
9442
+ let result = item.sum;
9443
+ if (item.type === "avg") {
9444
+ result = item.sum / item.numericCount;
9445
+ } else if (item.type === "min") {
9446
+ result = item.min ?? 0;
9447
+ } else if (item.type === "max") {
9448
+ result = item.max ?? 0;
9449
+ }
9450
+ const rounded = roundByPrecision(result, item.config.precision);
9451
+ const formatted = formatNumber(rounded, item.config.precision);
9452
+ return formatSummaryOutput(item, formatted, rows);
9453
+ }
9454
+ function resolveSummaryConfig(column) {
9455
+ if (column.summary == null) {
9456
+ return null;
9457
+ }
9458
+ if (column.summary === true) {
9459
+ return { type: "sum" };
9460
+ }
9461
+ if (column.summary === false) {
9462
+ return null;
9463
+ }
9464
+ return { type: "sum", ...column.summary };
9465
+ }
9466
+ function getColumnRawValue(record, column, config) {
9467
+ if (config.valueGetter) {
9468
+ return config.valueGetter(record);
9469
+ }
9470
+ const sortValue = column.sortValueGetter?.(record);
9471
+ if (sortValue != null && sortValue !== "") {
9472
+ return sortValue;
9473
+ }
9474
+ const filterValue = column.filterValueGetter?.(record);
9475
+ if (filterValue != null && filterValue !== "") {
9476
+ return filterValue;
9477
+ }
9478
+ return getValueByDataIndex(record, column.dataIndex);
9479
+ }
9480
+ function normalizeSummaryValue(value) {
9481
+ if (value == null || value === "") {
9482
+ return null;
9483
+ }
9484
+ if (typeof value === "number" || typeof value === "string") {
9485
+ return value;
9486
+ }
9487
+ return null;
9488
+ }
9489
+ function toNumber(value) {
9490
+ if (value == null) {
9491
+ return null;
9492
+ }
9493
+ if (typeof value === "number") {
9494
+ return Number.isNaN(value) ? null : value;
9495
+ }
9496
+ const parsed = Number(String(value).trim());
9497
+ return Number.isNaN(parsed) ? null : parsed;
9498
+ }
9499
+ function roundByPrecision(value, precision) {
9500
+ if (precision == null) {
9501
+ return value;
9502
+ }
9503
+ return Number(value.toFixed(precision));
9504
+ }
9505
+ function formatNumber(value, precision) {
9506
+ if (precision != null) {
9507
+ return value.toFixed(precision);
9508
+ }
9509
+ if (Number.isInteger(value)) {
9510
+ return String(value);
9511
+ }
9512
+ return value.toFixed(2);
9513
+ }
9514
+ function formatSummaryOutput(item, value, rows) {
9515
+ if (item.config.formatter) {
9516
+ return item.config.formatter(
9517
+ value,
9518
+ rows,
9519
+ item.column
9520
+ );
9521
+ }
9522
+ return value;
9523
+ }
9524
+ function countMergedRows(rows) {
9525
+ return rows.reduce((count, record) => {
9526
+ if (record == null || typeof record !== "object") {
9527
+ return count + 1;
9528
+ }
9529
+ const rowSpan = record.rowSpan;
9530
+ if (typeof rowSpan !== "number") {
9531
+ return count + 1;
9532
+ }
9533
+ return rowSpan > 0 ? count + 1 : count;
9534
+ }, 0);
9535
+ }
9536
+ function yieldToMainThread() {
9537
+ return new Promise((resolve) => {
9538
+ if (typeof requestAnimationFrame === "function") {
9539
+ requestAnimationFrame(() => resolve());
9540
+ return;
9541
+ }
9542
+ setTimeout(resolve, 0);
9543
+ });
9544
+ }
9545
+ function now() {
9546
+ if (typeof performance !== "undefined" && typeof performance.now === "function") {
9547
+ return performance.now();
9548
+ }
9549
+ return Date.now();
9550
+ }
9551
+
9552
+ // src/services/clipboard-service.ts
9553
+ function getCellClipboardText(record, rowIndex, column) {
9554
+ const value = getValueByDataIndex(record, column.dataIndex);
9555
+ const rendered = column.render?.(value, record, rowIndex, column);
9556
+ if (rendered != null) {
9557
+ return renderResultToClipboardText(rendered);
9558
+ }
9559
+ if (column.dataFormat && column.dataFormat !== "default") {
9560
+ return formatListTableDataValue(value, column.dataFormat);
9561
+ }
9562
+ if (column.cellType === "checkbox" || column.cellType === "radio") {
9563
+ return String(Boolean(value));
9564
+ }
9565
+ return resolveFormattedCellText({
9566
+ column,
9567
+ value,
9568
+ record,
9569
+ rowIndex
9570
+ }) ?? String(value ?? "");
9571
+ }
9572
+ function createListTableSelectionCopyText(params) {
9573
+ const columns = params.columns.filter(
9574
+ (column2) => column2.key !== ROW_SELECTION_COLUMN_KEY && column2.key !== EXPAND_COLUMN_KEY
9575
+ );
9576
+ const columnRange = params.rangeHighlight.selectedColumnRange;
9577
+ const rowRange = params.rangeHighlight.selectedRowRange;
9578
+ const cellRange = params.rangeHighlight.selectedCellRange;
9579
+ if (cellRange) {
9580
+ const selectedColumns2 = params.columns.filter(
9581
+ (column2, index) => index >= cellRange.startColumnIndex && index <= cellRange.endColumnIndex && column2.key !== ROW_SELECTION_COLUMN_KEY && column2.key !== EXPAND_COLUMN_KEY
9582
+ );
9583
+ return params.rows.slice(cellRange.startRowIndex, cellRange.endRowIndex + 1).map(
9584
+ (record2, offset) => selectedColumns2.map(
9585
+ (column2) => getCellClipboardText(
9586
+ record2,
9587
+ cellRange.startRowIndex + offset,
9588
+ column2
9589
+ )
9590
+ ).join(" ")
9591
+ ).join("\n");
9592
+ }
9593
+ const mode = params.highlightMode ?? (rowRange && columnRange ? "cross" : rowRange ? "row" : "column");
9594
+ const selectedColumns = columnRange ? params.columns.filter(
9595
+ (column2, index) => index >= columnRange.start && index <= columnRange.end
9596
+ ).filter(
9597
+ (column2) => column2.key !== ROW_SELECTION_COLUMN_KEY && column2.key !== EXPAND_COLUMN_KEY
9598
+ ) : columns;
9599
+ rowRange ? Math.max(rowRange.start, 0) : 0;
9600
+ rowRange ? Math.min(rowRange.end, params.rows.length - 1) : params.rows.length - 1;
9601
+ if (mode === "column" && columnRange && params.selection.rowIndex == null) {
9602
+ return params.rows.map(
9603
+ (record2, rowIndex2) => selectedColumns.map((column2) => getCellClipboardText(record2, rowIndex2, column2)).join(" ")
9604
+ ).join("\n");
9605
+ }
9606
+ const { rowIndex, columnKey } = params.selection;
9607
+ const record = rowIndex == null ? void 0 : params.rows[rowIndex];
9608
+ const column = columns.find((item) => item.key === columnKey);
9609
+ return record && column && rowIndex != null ? getCellClipboardText(record, rowIndex, column) : null;
9610
+ }
9611
+ function createListTableRangeCopyText(params) {
9612
+ return createListTableSelectionCopyText({
9613
+ rows: params.rows,
9614
+ columns: params.columns,
9615
+ selection: { rowIndex: null, columnKey: null },
9616
+ rangeHighlight: {
9617
+ selectedCellRange: {
9618
+ startRowIndex: Math.max(
9619
+ Math.min(params.startRowIndex, params.endRowIndex),
9620
+ 0
9621
+ ),
9622
+ endRowIndex: Math.min(
9623
+ Math.max(params.startRowIndex, params.endRowIndex),
9624
+ Math.max(params.rows.length - 1, 0)
9625
+ ),
9626
+ startColumnIndex: Math.max(
9627
+ Math.min(params.startColumnIndex, params.endColumnIndex),
9628
+ 0
9629
+ ),
9630
+ endColumnIndex: Math.min(
9631
+ Math.max(params.startColumnIndex, params.endColumnIndex),
9632
+ Math.max(params.columns.length - 1, 0)
9633
+ )
9634
+ }
9635
+ }
9636
+ });
9637
+ }
9638
+ async function copyBodyCellContent(params) {
9639
+ const { rows, columns, rowIndex, columnKey } = params;
9640
+ const record = rows[rowIndex];
9641
+ const column = columns.find((item) => item.key === columnKey);
9642
+ if (!record || !column) {
9643
+ return;
9644
+ }
9645
+ try {
9646
+ await copyText(getCellClipboardText(record, rowIndex, column));
9647
+ } catch (error) {
9648
+ console.error("[ListTable] Failed to copy cell:", error);
9649
+ }
9650
+ }
9651
+ async function copyHeaderCellContent(params) {
9652
+ const headerNode = findHeaderNodeByKey(params.headerTree, params.columnKey);
9653
+ try {
9654
+ await copyText(headerNode?.title ?? params.columnKey);
9655
+ } catch (error) {
9656
+ console.error("[ListTable] Failed to copy header cell:", error);
9657
+ }
9658
+ }
9659
+ async function copyColumnContent(params) {
9660
+ const { rows, columns, columnKey } = params;
9661
+ const column = columns.find((item) => item.key === columnKey);
9662
+ if (!column) {
9663
+ return;
9664
+ }
9665
+ const values = rows.map((record, rowIndex) => [
9302
9666
  getCellClipboardText(record, rowIndex, column)
9303
9667
  ]);
9304
9668
  try {
@@ -9355,10 +9719,31 @@ async function exportAllRowsTxtContent(params) {
9355
9719
  });
9356
9720
  }
9357
9721
  async function exportAllRowsXlsxContent(params) {
9722
+ const columns = params.columns.filter(
9723
+ (column) => column.key !== ROW_SELECTION_COLUMN_KEY
9724
+ );
9725
+ const rows = params.rows.map((record, rowIndex) => ({
9726
+ type: "data",
9727
+ record,
9728
+ rowIndex
9729
+ }));
9730
+ if (params.includeSummary) {
9731
+ rows.push({
9732
+ type: "summary",
9733
+ values: await computeSummaryValuesAsync({
9734
+ rows: params.rows,
9735
+ columns
9736
+ })
9737
+ });
9738
+ }
9358
9739
  await exportTableToXlsx({
9359
- fileName: buildTableExportFileName("xlsx"),
9360
- rows: params.rows,
9361
- columns: buildExportColumns(params.columns),
9740
+ fileName: params.fileName?.trim() || buildTableExportFileName("xlsx"),
9741
+ rows,
9742
+ columns: columns.map((column) => ({
9743
+ key: column.key,
9744
+ title: column.title ?? column.key,
9745
+ value: (row) => row.type === "summary" ? row.values.get(column.key) ?? "" : getCellClipboardText(row.record, row.rowIndex, column)
9746
+ })),
9362
9747
  sheetName: "TableData"
9363
9748
  });
9364
9749
  }
@@ -9611,11 +9996,12 @@ var ListTableContentActionController = class {
9611
9996
  /**
9612
9997
  * 异步导出全部原始数据为 XLSX。
9613
9998
  */
9614
- exportXlsx() {
9999
+ exportXlsx(options) {
9615
10000
  this.startExportTask(
9616
10001
  () => exportAllRowsXlsxContent({
9617
10002
  rows: this.options.getOptions().dataSource,
9618
- columns: this.options.getLeafColumns()
10003
+ columns: this.options.getLeafColumns(),
10004
+ ...options
9619
10005
  }),
9620
10006
  "\u6B63\u5728\u5BFC\u51FA XLSX\u2026"
9621
10007
  );
@@ -10620,6 +11006,14 @@ function createListTableContextMenuActions(params) {
10620
11006
  onChangeSummaryPrecision: params.onChangeSummaryPrecision ? (columnKey, precision) => {
10621
11007
  params.hideMenu();
10622
11008
  params.onChangeSummaryPrecision?.(columnKey, precision);
11009
+ } : void 0,
11010
+ onChangeAlignment: params.onChangeAlignment ? (columnKey, area, axis, value) => {
11011
+ params.hideMenu();
11012
+ params.onChangeAlignment?.(columnKey, area, axis, value);
11013
+ } : void 0,
11014
+ onChangeDataFormat: params.onChangeDataFormat ? (columnKey, dataFormat) => {
11015
+ params.hideMenu();
11016
+ params.onChangeDataFormat?.(columnKey, dataFormat);
10623
11017
  } : void 0
10624
11018
  };
10625
11019
  }
@@ -10656,7 +11050,10 @@ function buildListTableContextMenuConfig(params) {
10656
11050
  const enableReset = enabledFeatures.has("reset");
10657
11051
  const enableDensity = enabledFeatures.has("density");
10658
11052
  const enableZoom = enabledFeatures.has("zoom");
11053
+ const enableAlignment = enabledFeatures.has("alignment");
11054
+ const enableDataFormat = enabledFeatures.has("dataFormat");
10659
11055
  const enableColumnVisibility = enabledFeatures.has("columnVisibility");
11056
+ const presentation = isHeaderArea ? getColumnPresentationConfig(columns, columnKey) : null;
10660
11057
  const headerItems = isHeaderArea && (enableColumnVisibility || enableColumnCollapse) ? buildHeaderSettingsItems(columns) : void 0;
10661
11058
  const currentColumnItem = headerItems ? findHeaderColumnItem(headerItems, columnKey) : null;
10662
11059
  const canToggleCurrentColumn = enableColumnCollapse && isHeaderArea && !isSelectionColumn && currentColumnItem != null && !currentColumnItem.disabled;
@@ -10667,7 +11064,7 @@ function buildListTableContextMenuConfig(params) {
10667
11064
  };
10668
11065
  if (isSummaryArea && !isSelectionColumn && actions.onChangeSummaryType) {
10669
11066
  const column = findSummaryColumn(columns, columnKey);
10670
- const summary = resolveSummaryConfig(column?.summary);
11067
+ const summary = resolveSummaryConfig2(column?.summary);
10671
11068
  summaryConfig.summaryColumnKey = columnKey;
10672
11069
  summaryConfig.summaryType = summary?.type ?? "sum";
10673
11070
  summaryConfig.summaryPrecision = summary?.precision;
@@ -10746,11 +11143,20 @@ function buildListTableContextMenuConfig(params) {
10746
11143
  onChangeDensity: enableDensity ? actions.onChangeDensity : void 0,
10747
11144
  onChangeZoom: enableZoom ? actions.onChangeZoom : void 0,
10748
11145
  onToggleColumn: enableColumnVisibility && isHeaderArea ? actions.onToggleColumn : void 0,
11146
+ alignment: enableAlignment && presentation ? {
11147
+ headerHorizontal: presentation.headerHorizontal,
11148
+ headerVertical: presentation.headerVertical,
11149
+ bodyHorizontal: presentation.bodyHorizontal,
11150
+ bodyVertical: presentation.bodyVertical
11151
+ } : void 0,
11152
+ onChangeAlignment: enableAlignment && isHeaderArea && actions.onChangeAlignment ? (area, axis, value) => actions.onChangeAlignment?.(columnKey, area, axis, value) : void 0,
11153
+ dataFormat: enableDataFormat && presentation?.dataFormatAvailable ? presentation.dataFormat : void 0,
11154
+ onChangeDataFormat: enableDataFormat && presentation?.dataFormatAvailable && actions.onChangeDataFormat ? (dataFormat) => actions.onChangeDataFormat?.(columnKey, dataFormat) : void 0,
10749
11155
  onClose: actions.onClose,
10750
11156
  ...summaryConfig
10751
11157
  };
10752
11158
  }
10753
- function resolveSummaryConfig(summary) {
11159
+ function resolveSummaryConfig2(summary) {
10754
11160
  if (summary === true) {
10755
11161
  return { type: "sum" };
10756
11162
  }
@@ -10781,6 +11187,8 @@ var DEFAULT_CONTEXT_MENU_FEATURES = [
10781
11187
  "reset",
10782
11188
  "density",
10783
11189
  "zoom",
11190
+ "alignment",
11191
+ "dataFormat",
10784
11192
  "columnVisibility"
10785
11193
  ];
10786
11194
  function resolveEnabledContextMenuFeatures(contextMenu) {
@@ -11188,7 +11596,7 @@ async function filterRowsAsync(params) {
11188
11596
  }
11189
11597
  }
11190
11598
  if (endIndex < rows.length) {
11191
- await yieldToMainThread();
11599
+ await yieldToMainThread2();
11192
11600
  }
11193
11601
  }
11194
11602
  return result;
@@ -11256,7 +11664,7 @@ async function getColumnFilterOptionsAsync(params) {
11256
11664
  optionCountMap.set(value, (optionCountMap.get(value) ?? 0) + 1);
11257
11665
  }
11258
11666
  if (endIndex < dataSource.length) {
11259
- await yieldToMainThread();
11667
+ await yieldToMainThread2();
11260
11668
  }
11261
11669
  }
11262
11670
  const optionItems = explicitOptions.length > 0 ? explicitOptions.map((item) => ({
@@ -11292,7 +11700,7 @@ async function getColumnFilterOptionsAsync(params) {
11292
11700
  ...optionItems
11293
11701
  ];
11294
11702
  }
11295
- function yieldToMainThread() {
11703
+ function yieldToMainThread2() {
11296
11704
  return new Promise((resolve) => {
11297
11705
  setTimeout(resolve, 0);
11298
11706
  });
@@ -11525,6 +11933,8 @@ function showHeaderContextMenu(params) {
11525
11933
  onToggleSummary,
11526
11934
  onChangeSummaryType,
11527
11935
  onChangeSummaryPrecision,
11936
+ onChangeAlignment,
11937
+ onChangeDataFormat,
11528
11938
  summaryVisible,
11529
11939
  getSelectionRange,
11530
11940
  onCopySelection,
@@ -11599,6 +12009,8 @@ function showHeaderContextMenu(params) {
11599
12009
  onToggleSummary,
11600
12010
  onChangeSummaryType,
11601
12011
  onChangeSummaryPrecision,
12012
+ onChangeAlignment,
12013
+ onChangeDataFormat,
11602
12014
  onCopySelection,
11603
12015
  onCopyCustomSelection
11604
12016
  })
@@ -13362,19 +13774,55 @@ var ListTableEventController = class {
13362
13774
  this.host.render();
13363
13775
  },
13364
13776
  onChangeSummaryType: (columnKey, type) => {
13365
- updateSummaryColumn(this.host.options.columns, columnKey, (summary) => ({
13366
- ...summary,
13367
- type
13368
- }));
13777
+ updateSummaryColumn(
13778
+ this.host.options.columns,
13779
+ columnKey,
13780
+ (summary) => ({
13781
+ ...summary,
13782
+ type
13783
+ })
13784
+ );
13369
13785
  this.host.refreshRuntimeColumns();
13370
13786
  this.host.persistColumnConfig();
13371
13787
  this.host.render();
13372
13788
  },
13373
13789
  onChangeSummaryPrecision: (columnKey, precision) => {
13374
- updateSummaryColumn(this.host.options.columns, columnKey, (summary) => ({
13375
- ...summary,
13376
- precision
13377
- }));
13790
+ updateSummaryColumn(
13791
+ this.host.options.columns,
13792
+ columnKey,
13793
+ (summary) => ({
13794
+ ...summary,
13795
+ precision
13796
+ })
13797
+ );
13798
+ this.host.refreshRuntimeColumns();
13799
+ this.host.persistColumnConfig();
13800
+ this.host.render();
13801
+ },
13802
+ onChangeAlignment: (columnKey, area, axis, value) => {
13803
+ const updated = setColumnAlignment({
13804
+ columns: this.host.options.columns,
13805
+ columnKey,
13806
+ area,
13807
+ axis,
13808
+ value
13809
+ });
13810
+ if (!updated) {
13811
+ return;
13812
+ }
13813
+ this.host.refreshRuntimeColumns();
13814
+ this.host.persistColumnConfig();
13815
+ this.host.render();
13816
+ },
13817
+ onChangeDataFormat: (columnKey, dataFormat) => {
13818
+ const updated = setColumnDataFormat(
13819
+ this.host.options.columns,
13820
+ columnKey,
13821
+ dataFormat
13822
+ );
13823
+ if (!updated) {
13824
+ return;
13825
+ }
13378
13826
  this.host.refreshRuntimeColumns();
13379
13827
  this.host.persistColumnConfig();
13380
13828
  this.host.render();
@@ -13841,7 +14289,10 @@ var ListTableEventController = class {
13841
14289
  const width = snapshot?.width ?? this.host.canvasElement.width;
13842
14290
  const position = {
13843
14291
  x: Math.min(Math.max(pointer.x, 0), Math.max(width - 1, 0)),
13844
- y: Math.min(Math.max(pointer.y, bodyTop + 1), Math.max(bodyBottom - 1, bodyTop + 1))
14292
+ y: Math.min(
14293
+ Math.max(pointer.y, bodyTop + 1),
14294
+ Math.max(bodyBottom - 1, bodyTop + 1)
14295
+ )
13845
14296
  };
13846
14297
  const result = this.host.resolvePointerHit(position.x, position.y);
13847
14298
  if (result.area !== "body" && result.area !== "body-content" || typeof result.rowIndex !== "number" || !result.columnKey) {
@@ -14826,6 +15277,27 @@ function applyStoredColumnConfig(columns, storedColumns) {
14826
15277
  if (stored) {
14827
15278
  col.width = stored.width;
14828
15279
  col.hidden = !!stored.hidden;
15280
+ if ("align" in stored) {
15281
+ col.align = stored.align;
15282
+ }
15283
+ if ("headerAlign" in stored) {
15284
+ col.headerAlign = stored.headerAlign;
15285
+ }
15286
+ if ("verticalAlign" in stored) {
15287
+ col.cellStyle = {
15288
+ ...col.cellStyle,
15289
+ verticalAlign: stored.verticalAlign
15290
+ };
15291
+ }
15292
+ if ("headerVerticalAlign" in stored) {
15293
+ col.headerStyle = {
15294
+ ...col.headerStyle,
15295
+ verticalAlign: stored.headerVerticalAlign
15296
+ };
15297
+ }
15298
+ if ("dataFormat" in stored) {
15299
+ col.dataFormat = stored.dataFormat;
15300
+ }
14829
15301
  if (stored.fixed) {
14830
15302
  col.fixed = stored.fixed;
14831
15303
  } else {
@@ -14859,6 +15331,11 @@ function buildStoredColumnConfig(columns, sortState, filterState, zoom, summaryR
14859
15331
  width: col.width ?? 160,
14860
15332
  fixed: col.fixed,
14861
15333
  hidden: !!col.hidden,
15334
+ ...col.align ? { align: col.align } : null,
15335
+ ...col.cellStyle?.verticalAlign ? { verticalAlign: col.cellStyle.verticalAlign } : null,
15336
+ ...col.headerAlign ? { headerAlign: col.headerAlign } : null,
15337
+ ...col.headerStyle?.verticalAlign ? { headerVerticalAlign: col.headerStyle.verticalAlign } : null,
15338
+ ...col.dataFormat ? { dataFormat: col.dataFormat } : null,
14862
15339
  summary: col.summary === true ? { type: "sum" } : col.summary ? {
14863
15340
  type: col.summary.type,
14864
15341
  precision: col.summary.precision
@@ -15178,7 +15655,7 @@ function buildHeaderNode(column, leafColumns, maxDepth) {
15178
15655
  rowSpan: 1,
15179
15656
  leafStartIndex,
15180
15657
  leafEndIndex,
15181
- align: column.align ?? "left",
15658
+ align: column.headerAlign ?? column.align ?? "left",
15182
15659
  fixed: column.fixed,
15183
15660
  style: column.headerStyle,
15184
15661
  column,
@@ -15196,7 +15673,7 @@ function buildHeaderNode(column, leafColumns, maxDepth) {
15196
15673
  rowSpan: maxDepth - column.depth + 1,
15197
15674
  leafStartIndex: leafIndex,
15198
15675
  leafEndIndex: leafIndex,
15199
- align: column.align ?? "left",
15676
+ align: column.headerAlign ?? column.align ?? "left",
15200
15677
  fixed: column.fixed,
15201
15678
  style: column.headerStyle,
15202
15679
  column,
@@ -18458,7 +18935,13 @@ function drawHeaderCell(params, cell, clipRect) {
18458
18935
  }),
18459
18936
  contentInsetEnd: cell.node.children.length === 0 && collapseMarkerSet.hasRightMarker ? COLLAPSE_TRIGGER_WIDTH / 2 + COLLAPSE_TRIGGER_GAP + ACTION_PADDING_INLINE2 : 0
18460
18937
  });
18461
- const textY = rect.y + rect.height / 2;
18938
+ const textY = resolveHeaderContentCenterY(
18939
+ rect,
18940
+ titleContent,
18941
+ theme.fontSize,
18942
+ cell.node.style?.paddingBlock ?? 6,
18943
+ cell.node.style?.verticalAlign
18944
+ );
18462
18945
  ctx.textAlign = textLayout.align;
18463
18946
  if (params.rowSelection?.columnKey === cell.node.key && cell.node.children.length === 0) {
18464
18947
  descriptors.push({
@@ -18508,6 +18991,21 @@ function drawHeaderCell(params, cell, clipRect) {
18508
18991
  }
18509
18992
  ctx.restore();
18510
18993
  }
18994
+ function resolveHeaderContentCenterY(rect, contents, fontSize, paddingBlock, verticalAlign) {
18995
+ const contentHeight = Math.max(
18996
+ fontSize,
18997
+ ...contents.map(
18998
+ (content) => content.type === "img" ? Math.max(content.height ?? content.width ?? fontSize, 1) : fontSize
18999
+ )
19000
+ );
19001
+ if (verticalAlign === "top") {
19002
+ return rect.y + paddingBlock + contentHeight / 2;
19003
+ }
19004
+ if (verticalAlign === "bottom") {
19005
+ return rect.y + rect.height - paddingBlock - contentHeight / 2;
19006
+ }
19007
+ return rect.y + rect.height / 2;
19008
+ }
18511
19009
  function measureHeaderContentWidth(ctx, contents) {
18512
19010
  const gap = 4;
18513
19011
  return contents.reduce(
@@ -20701,248 +21199,6 @@ var ListTableSelectionController = class {
20701
21199
  this.summarySelected = false;
20702
21200
  }
20703
21201
  };
20704
- var SUMMARY_ASYNC_BATCH_SIZE = 2e3;
20705
- var SUMMARY_ASYNC_FRAME_BUDGET = 8;
20706
- async function computeSummaryValuesAsync(params) {
20707
- const { rows, columns, signal } = params;
20708
- const summaryValues = /* @__PURE__ */ new Map();
20709
- const accumulators = [];
20710
- columns.forEach((column) => {
20711
- const accumulator = createSummaryAccumulator(column);
20712
- if (accumulator) {
20713
- accumulators.push(accumulator);
20714
- }
20715
- });
20716
- columns.forEach((column) => {
20717
- if (column.summaryTitle != null) {
20718
- summaryValues.set(column.key, column.summaryTitle);
20719
- }
20720
- });
20721
- if (accumulators.length === 0) {
20722
- return summaryValues;
20723
- }
20724
- for (let startIndex = 0; startIndex < rows.length; ) {
20725
- if (signal?.aborted) {
20726
- throw new Error("summary computation aborted");
20727
- }
20728
- const frameStart = now();
20729
- let endIndex = startIndex;
20730
- while (endIndex < rows.length) {
20731
- if (signal?.aborted) {
20732
- throw new Error("summary computation aborted");
20733
- }
20734
- const batchEndIndex = Math.min(
20735
- endIndex + SUMMARY_ASYNC_BATCH_SIZE,
20736
- rows.length
20737
- );
20738
- for (let rowIndex = endIndex; rowIndex < batchEndIndex; rowIndex += 1) {
20739
- const record = rows[rowIndex];
20740
- if (!record) {
20741
- continue;
20742
- }
20743
- accumulators.forEach((item) => {
20744
- updateSummaryAccumulator(item, record);
20745
- });
20746
- }
20747
- endIndex = batchEndIndex;
20748
- if (endIndex >= rows.length) {
20749
- break;
20750
- }
20751
- if (now() - frameStart >= SUMMARY_ASYNC_FRAME_BUDGET) {
20752
- break;
20753
- }
20754
- }
20755
- if (endIndex < rows.length) {
20756
- await yieldToMainThread2();
20757
- }
20758
- startIndex = endIndex;
20759
- }
20760
- accumulators.forEach((item) => {
20761
- summaryValues.set(
20762
- item.column.key,
20763
- finalizeSummaryValue(item, rows)
20764
- );
20765
- });
20766
- return summaryValues;
20767
- }
20768
- function createSummaryAccumulator(column) {
20769
- const config = resolveSummaryConfig2(column);
20770
- if (!config) {
20771
- return null;
20772
- }
20773
- return {
20774
- column,
20775
- config,
20776
- type: config.type ?? "sum",
20777
- valueCount: 0,
20778
- numericCount: 0,
20779
- sum: 0,
20780
- min: null,
20781
- max: null,
20782
- uniqueValues: /* @__PURE__ */ new Set()
20783
- };
20784
- }
20785
- function updateSummaryAccumulator(item, record) {
20786
- if (item.column.summaryTitle != null) {
20787
- return;
20788
- }
20789
- if (item.type === "rowCount" || item.type === "mergedRowCount") {
20790
- return;
20791
- }
20792
- const rawValue = normalizeSummaryValue(
20793
- getColumnRawValue(record, item.column, item.config)
20794
- );
20795
- if (rawValue == null) {
20796
- return;
20797
- }
20798
- item.valueCount += 1;
20799
- if (item.type === "unionCount") {
20800
- item.uniqueValues.add(String(rawValue));
20801
- return;
20802
- }
20803
- if (item.type === "count") {
20804
- return;
20805
- }
20806
- const numericValue = toNumber(rawValue);
20807
- if (numericValue == null) {
20808
- return;
20809
- }
20810
- item.numericCount += 1;
20811
- item.sum += numericValue;
20812
- item.min = item.min == null ? numericValue : Math.min(item.min, numericValue);
20813
- item.max = item.max == null ? numericValue : Math.max(item.max, numericValue);
20814
- }
20815
- function finalizeSummaryValue(item, rows) {
20816
- if (item.column.summaryTitle != null) {
20817
- return item.column.summaryTitle;
20818
- }
20819
- if (item.type === "rowCount") {
20820
- return formatSummaryOutput(item, String(rows.length), rows);
20821
- }
20822
- if (item.type === "mergedRowCount") {
20823
- return formatSummaryOutput(item, String(countMergedRows(rows)), rows);
20824
- }
20825
- if (item.type === "count") {
20826
- return formatSummaryOutput(item, String(item.valueCount), rows);
20827
- }
20828
- if (item.type === "unionCount") {
20829
- return formatSummaryOutput(item, String(item.uniqueValues.size), rows);
20830
- }
20831
- if (item.numericCount === 0) {
20832
- if (item.type === "min" || item.type === "max") {
20833
- return formatSummaryOutput(item, "", rows);
20834
- }
20835
- return formatSummaryOutput(item, "0", rows);
20836
- }
20837
- let result = item.sum;
20838
- if (item.type === "avg") {
20839
- result = item.sum / item.numericCount;
20840
- } else if (item.type === "min") {
20841
- result = item.min ?? 0;
20842
- } else if (item.type === "max") {
20843
- result = item.max ?? 0;
20844
- }
20845
- const rounded = roundByPrecision(result, item.config.precision);
20846
- const formatted = formatNumber(rounded, item.config.precision);
20847
- return formatSummaryOutput(item, formatted, rows);
20848
- }
20849
- function resolveSummaryConfig2(column) {
20850
- if (column.summary == null) {
20851
- return null;
20852
- }
20853
- if (column.summary === true) {
20854
- return { type: "sum" };
20855
- }
20856
- if (column.summary === false) {
20857
- return null;
20858
- }
20859
- return { type: "sum", ...column.summary };
20860
- }
20861
- function getColumnRawValue(record, column, config) {
20862
- if (config.valueGetter) {
20863
- return config.valueGetter(record);
20864
- }
20865
- const sortValue = column.sortValueGetter?.(record);
20866
- if (sortValue != null && sortValue !== "") {
20867
- return sortValue;
20868
- }
20869
- const filterValue = column.filterValueGetter?.(record);
20870
- if (filterValue != null && filterValue !== "") {
20871
- return filterValue;
20872
- }
20873
- return getValueByDataIndex(record, column.dataIndex);
20874
- }
20875
- function normalizeSummaryValue(value) {
20876
- if (value == null || value === "") {
20877
- return null;
20878
- }
20879
- if (typeof value === "number" || typeof value === "string") {
20880
- return value;
20881
- }
20882
- return null;
20883
- }
20884
- function toNumber(value) {
20885
- if (value == null) {
20886
- return null;
20887
- }
20888
- if (typeof value === "number") {
20889
- return Number.isNaN(value) ? null : value;
20890
- }
20891
- const parsed = Number(String(value).trim());
20892
- return Number.isNaN(parsed) ? null : parsed;
20893
- }
20894
- function roundByPrecision(value, precision) {
20895
- if (precision == null) {
20896
- return value;
20897
- }
20898
- return Number(value.toFixed(precision));
20899
- }
20900
- function formatNumber(value, precision) {
20901
- if (precision != null) {
20902
- return value.toFixed(precision);
20903
- }
20904
- if (Number.isInteger(value)) {
20905
- return String(value);
20906
- }
20907
- return value.toFixed(2);
20908
- }
20909
- function formatSummaryOutput(item, value, rows) {
20910
- if (item.config.formatter) {
20911
- return item.config.formatter(
20912
- value,
20913
- rows,
20914
- item.column
20915
- );
20916
- }
20917
- return value;
20918
- }
20919
- function countMergedRows(rows) {
20920
- return rows.reduce((count, record) => {
20921
- if (record == null || typeof record !== "object") {
20922
- return count + 1;
20923
- }
20924
- const rowSpan = record.rowSpan;
20925
- if (typeof rowSpan !== "number") {
20926
- return count + 1;
20927
- }
20928
- return rowSpan > 0 ? count + 1 : count;
20929
- }, 0);
20930
- }
20931
- function yieldToMainThread2() {
20932
- return new Promise((resolve) => {
20933
- if (typeof requestAnimationFrame === "function") {
20934
- requestAnimationFrame(() => resolve());
20935
- return;
20936
- }
20937
- setTimeout(resolve, 0);
20938
- });
20939
- }
20940
- function now() {
20941
- if (typeof performance !== "undefined" && typeof performance.now === "function") {
20942
- return performance.now();
20943
- }
20944
- return Date.now();
20945
- }
20946
21202
 
20947
21203
  // src/domain/summary/summary-interaction.ts
20948
21204
  function isSummaryInteractionActive(params) {
@@ -21752,6 +22008,7 @@ var ListTableCore = class {
21752
22008
  __publicField(this, "debugManager");
21753
22009
  this.container = container;
21754
22010
  this.options = options;
22011
+ applyInitialColumnVisibility(options.columns);
21755
22012
  ensureColumnKeysInPlace(options.columns);
21756
22013
  this.domHost = new ListTableDomHost();
21757
22014
  this.canvasHost = new ListTableCanvasHost();
@@ -21797,6 +22054,7 @@ var ListTableCore = class {
21797
22054
  */
21798
22055
  updateOptions(options) {
21799
22056
  this.animationController.stopCarouselScroll();
22057
+ applyInitialColumnVisibility(options.columns);
21800
22058
  ensureColumnKeysInPlace(options.columns);
21801
22059
  if (options.expandable?.expandedRowKeys !== void 0 && !areSameRowKeySet(
21802
22060
  this.storeFacade.expandedRowKeys,
@@ -21850,8 +22108,8 @@ var ListTableCore = class {
21850
22108
  /**
21851
22109
  * 异步导出全部原始数据为 XLSX。
21852
22110
  */
21853
- exportXlsx() {
21854
- this.contentActionController.exportXlsx();
22111
+ exportXlsx(options) {
22112
+ this.contentActionController.exportXlsx(options);
21855
22113
  }
21856
22114
  /**
21857
22115
  * 滚动到指定行。
@@ -21972,8 +22230,8 @@ var ListTable = class {
21972
22230
  /**
21973
22231
  * 异步导出全部原始数据为 XLSX。
21974
22232
  */
21975
- exportXlsx() {
21976
- this.core?.exportXlsx();
22233
+ exportXlsx(options) {
22234
+ this.core?.exportXlsx(options);
21977
22235
  }
21978
22236
  /**
21979
22237
  * 滚动到指定行。