@canvas-components/list-table 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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();
@@ -13418,6 +13866,12 @@ var ListTableEventController = class {
13418
13866
  this.host.suppressNextClick = false;
13419
13867
  return;
13420
13868
  }
13869
+ if ((result.area === "body" || result.area === "body-content") && typeof result.rowIndex === "number") {
13870
+ const record = this.host.getDisplayData()[result.rowIndex];
13871
+ if (record !== void 0) {
13872
+ this.host.options.onRow?.(record, result.rowIndex)?.onClick?.(event);
13873
+ }
13874
+ }
13421
13875
  this.host.summarySelected = result.area === "summary";
13422
13876
  if ((result.area === "header" || result.area === "header-selection" || result.area === "sort-trigger" || result.area === "filter-trigger" || result.area === "fixed-trigger" || event.shiftKey && result.area === "column-collapse-trigger") && result.columnKey) {
13423
13877
  this.host.clearBodySelection();
@@ -13521,6 +13975,12 @@ var ListTableEventController = class {
13521
13975
  }
13522
13976
  return;
13523
13977
  }
13978
+ if ((result.area === "body" || result.area === "body-content") && typeof result.rowIndex === "number" && this.host.options.rowSelection?.selectRowByClick && result.columnKey !== ROW_SELECTION_COLUMN_KEY && result.columnKey !== EXPAND_COLUMN_KEY) {
13979
+ const record = this.host.getDisplayData()[result.rowIndex];
13980
+ if (record !== void 0) {
13981
+ this.host.toggleRowSelection(record, result.rowIndex);
13982
+ }
13983
+ }
13524
13984
  if (result.area === "body" && typeof result.rowIndex === "number" && this.host.options.expandable?.expandRowByClick && result.columnKey !== ROW_SELECTION_COLUMN_KEY && result.columnKey !== EXPAND_COLUMN_KEY && this.host.toggleRowExpand(result.rowIndex)) {
13525
13985
  return;
13526
13986
  }
@@ -13841,7 +14301,10 @@ var ListTableEventController = class {
13841
14301
  const width = snapshot?.width ?? this.host.canvasElement.width;
13842
14302
  const position = {
13843
14303
  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))
14304
+ y: Math.min(
14305
+ Math.max(pointer.y, bodyTop + 1),
14306
+ Math.max(bodyBottom - 1, bodyTop + 1)
14307
+ )
13845
14308
  };
13846
14309
  const result = this.host.resolvePointerHit(position.x, position.y);
13847
14310
  if (result.area !== "body" && result.area !== "body-content" || typeof result.rowIndex !== "number" || !result.columnKey) {
@@ -14826,6 +15289,27 @@ function applyStoredColumnConfig(columns, storedColumns) {
14826
15289
  if (stored) {
14827
15290
  col.width = stored.width;
14828
15291
  col.hidden = !!stored.hidden;
15292
+ if ("align" in stored) {
15293
+ col.align = stored.align;
15294
+ }
15295
+ if ("headerAlign" in stored) {
15296
+ col.headerAlign = stored.headerAlign;
15297
+ }
15298
+ if ("verticalAlign" in stored) {
15299
+ col.cellStyle = {
15300
+ ...col.cellStyle,
15301
+ verticalAlign: stored.verticalAlign
15302
+ };
15303
+ }
15304
+ if ("headerVerticalAlign" in stored) {
15305
+ col.headerStyle = {
15306
+ ...col.headerStyle,
15307
+ verticalAlign: stored.headerVerticalAlign
15308
+ };
15309
+ }
15310
+ if ("dataFormat" in stored) {
15311
+ col.dataFormat = stored.dataFormat;
15312
+ }
14829
15313
  if (stored.fixed) {
14830
15314
  col.fixed = stored.fixed;
14831
15315
  } else {
@@ -14859,6 +15343,11 @@ function buildStoredColumnConfig(columns, sortState, filterState, zoom, summaryR
14859
15343
  width: col.width ?? 160,
14860
15344
  fixed: col.fixed,
14861
15345
  hidden: !!col.hidden,
15346
+ ...col.align ? { align: col.align } : null,
15347
+ ...col.cellStyle?.verticalAlign ? { verticalAlign: col.cellStyle.verticalAlign } : null,
15348
+ ...col.headerAlign ? { headerAlign: col.headerAlign } : null,
15349
+ ...col.headerStyle?.verticalAlign ? { headerVerticalAlign: col.headerStyle.verticalAlign } : null,
15350
+ ...col.dataFormat ? { dataFormat: col.dataFormat } : null,
14862
15351
  summary: col.summary === true ? { type: "sum" } : col.summary ? {
14863
15352
  type: col.summary.type,
14864
15353
  precision: col.summary.precision
@@ -15178,7 +15667,7 @@ function buildHeaderNode(column, leafColumns, maxDepth) {
15178
15667
  rowSpan: 1,
15179
15668
  leafStartIndex,
15180
15669
  leafEndIndex,
15181
- align: column.align ?? "left",
15670
+ align: column.headerAlign ?? column.align ?? "left",
15182
15671
  fixed: column.fixed,
15183
15672
  style: column.headerStyle,
15184
15673
  column,
@@ -15196,7 +15685,7 @@ function buildHeaderNode(column, leafColumns, maxDepth) {
15196
15685
  rowSpan: maxDepth - column.depth + 1,
15197
15686
  leafStartIndex: leafIndex,
15198
15687
  leafEndIndex: leafIndex,
15199
- align: column.align ?? "left",
15688
+ align: column.headerAlign ?? column.align ?? "left",
15200
15689
  fixed: column.fixed,
15201
15690
  style: column.headerStyle,
15202
15691
  column,
@@ -18458,7 +18947,13 @@ function drawHeaderCell(params, cell, clipRect) {
18458
18947
  }),
18459
18948
  contentInsetEnd: cell.node.children.length === 0 && collapseMarkerSet.hasRightMarker ? COLLAPSE_TRIGGER_WIDTH / 2 + COLLAPSE_TRIGGER_GAP + ACTION_PADDING_INLINE2 : 0
18460
18949
  });
18461
- const textY = rect.y + rect.height / 2;
18950
+ const textY = resolveHeaderContentCenterY(
18951
+ rect,
18952
+ titleContent,
18953
+ theme.fontSize,
18954
+ cell.node.style?.paddingBlock ?? 6,
18955
+ cell.node.style?.verticalAlign
18956
+ );
18462
18957
  ctx.textAlign = textLayout.align;
18463
18958
  if (params.rowSelection?.columnKey === cell.node.key && cell.node.children.length === 0) {
18464
18959
  descriptors.push({
@@ -18508,6 +19003,21 @@ function drawHeaderCell(params, cell, clipRect) {
18508
19003
  }
18509
19004
  ctx.restore();
18510
19005
  }
19006
+ function resolveHeaderContentCenterY(rect, contents, fontSize, paddingBlock, verticalAlign) {
19007
+ const contentHeight = Math.max(
19008
+ fontSize,
19009
+ ...contents.map(
19010
+ (content) => content.type === "img" ? Math.max(content.height ?? content.width ?? fontSize, 1) : fontSize
19011
+ )
19012
+ );
19013
+ if (verticalAlign === "top") {
19014
+ return rect.y + paddingBlock + contentHeight / 2;
19015
+ }
19016
+ if (verticalAlign === "bottom") {
19017
+ return rect.y + rect.height - paddingBlock - contentHeight / 2;
19018
+ }
19019
+ return rect.y + rect.height / 2;
19020
+ }
18511
19021
  function measureHeaderContentWidth(ctx, contents) {
18512
19022
  const gap = 4;
18513
19023
  return contents.reduce(
@@ -20701,248 +21211,6 @@ var ListTableSelectionController = class {
20701
21211
  this.summarySelected = false;
20702
21212
  }
20703
21213
  };
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
21214
 
20947
21215
  // src/domain/summary/summary-interaction.ts
20948
21216
  function isSummaryInteractionActive(params) {
@@ -21752,6 +22020,7 @@ var ListTableCore = class {
21752
22020
  __publicField(this, "debugManager");
21753
22021
  this.container = container;
21754
22022
  this.options = options;
22023
+ applyInitialColumnVisibility(options.columns);
21755
22024
  ensureColumnKeysInPlace(options.columns);
21756
22025
  this.domHost = new ListTableDomHost();
21757
22026
  this.canvasHost = new ListTableCanvasHost();
@@ -21797,6 +22066,7 @@ var ListTableCore = class {
21797
22066
  */
21798
22067
  updateOptions(options) {
21799
22068
  this.animationController.stopCarouselScroll();
22069
+ applyInitialColumnVisibility(options.columns);
21800
22070
  ensureColumnKeysInPlace(options.columns);
21801
22071
  if (options.expandable?.expandedRowKeys !== void 0 && !areSameRowKeySet(
21802
22072
  this.storeFacade.expandedRowKeys,
@@ -21850,8 +22120,8 @@ var ListTableCore = class {
21850
22120
  /**
21851
22121
  * 异步导出全部原始数据为 XLSX。
21852
22122
  */
21853
- exportXlsx() {
21854
- this.contentActionController.exportXlsx();
22123
+ exportXlsx(options) {
22124
+ this.contentActionController.exportXlsx(options);
21855
22125
  }
21856
22126
  /**
21857
22127
  * 滚动到指定行。
@@ -21972,8 +22242,8 @@ var ListTable = class {
21972
22242
  /**
21973
22243
  * 异步导出全部原始数据为 XLSX。
21974
22244
  */
21975
- exportXlsx() {
21976
- this.core?.exportXlsx();
22245
+ exportXlsx(options) {
22246
+ this.core?.exportXlsx(options);
21977
22247
  }
21978
22248
  /**
21979
22249
  * 滚动到指定行。