@canvas-components/list-table 0.3.22 → 0.3.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1112,16 +1112,149 @@ function applyInitialColumnVisibility(columns) {
1112
1112
  function replaceColumns(target, source) {
1113
1113
  target.splice(0, target.length, ...cloneColumns(source));
1114
1114
  }
1115
+ function preserveUserAddedColumns(params) {
1116
+ const keys = /* @__PURE__ */ new Set();
1117
+ const collect = (columns) => {
1118
+ columns.forEach((column) => {
1119
+ keys.add(resolveColumnKey(column));
1120
+ if (column.children?.length) collect(column.children);
1121
+ });
1122
+ };
1123
+ collect(params.nextColumns);
1124
+ const preserve = (source, target) => {
1125
+ source.forEach((column) => {
1126
+ const key = resolveColumnKey(column);
1127
+ if (column.userDefined && !keys.has(key)) {
1128
+ target.push({ ...column });
1129
+ keys.add(key);
1130
+ } else if (column.children?.length) {
1131
+ const matching = findColumnNode(params.nextColumns, key);
1132
+ if (matching?.children) preserve(column.children, matching.children);
1133
+ }
1134
+ });
1135
+ };
1136
+ preserve(params.runtimeColumns, params.nextColumns);
1137
+ }
1115
1138
  function buildHeaderSettingsItems(columns) {
1116
1139
  ensureColumnKeysInPlace(columns);
1117
1140
  const totalVisibleLeafCount = countVisibleLeafColumns(columns);
1118
- return columns.flatMap((column) => {
1141
+ return columns.flatMap((column, index) => {
1119
1142
  if (column.hideInSetting) {
1120
1143
  return [];
1121
1144
  }
1122
- return [buildHeaderSettingsItem(column, totalVisibleLeafCount, false)];
1145
+ return [
1146
+ buildHeaderSettingsItem(
1147
+ column,
1148
+ totalVisibleLeafCount,
1149
+ false,
1150
+ index + 1,
1151
+ columns.length
1152
+ )
1153
+ ];
1123
1154
  });
1124
1155
  }
1156
+ function saveHeaderSettingsColumn(columns, draft) {
1157
+ const title = draft.title.trim();
1158
+ if (!title) return "\u8BF7\u8F93\u5165\u5217\u540D\u79F0";
1159
+ const existing = draft.key ? findColumnNode(columns, draft.key) : null;
1160
+ if (draft.key && !existing) return "\u5217\u4E0D\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u5217\u663E\u793A\u83DC\u5355";
1161
+ const parent = !existing && draft.parentKey ? findColumnNode(columns, draft.parentKey) : null;
1162
+ if (draft.parentKey && !existing && !parent?.children?.length) {
1163
+ return "\u6240\u5C5E\u591A\u7EA7\u8868\u5934\u4E0D\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u5217\u663E\u793A\u83DC\u5355";
1164
+ }
1165
+ const siblings = existing ? findSiblingColumnsByKey(columns, draft.key) : parent?.children ?? columns;
1166
+ if (!siblings) return "\u5217\u4E0D\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u5217\u663E\u793A\u83DC\u5355";
1167
+ const maxOrder = siblings.length + (existing ? 0 : 1);
1168
+ if (draft.order != null && (!Number.isInteger(draft.order) || draft.order < 1 || draft.order > maxOrder)) {
1169
+ return `\u5217\u987A\u5E8F\u987B\u4ECB\u4E8E 1 \u548C ${maxOrder} \u4E4B\u95F4`;
1170
+ }
1171
+ const minWidth = draft.minWidth ?? 40;
1172
+ const maxWidth = draft.maxWidth ?? 2e3;
1173
+ const width = draft.width ?? 160;
1174
+ if (![minWidth, maxWidth, width].every(
1175
+ (value) => Number.isFinite(value) && value > 0
1176
+ ) || minWidth > maxWidth || width < minWidth || width > maxWidth) {
1177
+ return "\u5BBD\u5EA6\u987B\u4ECB\u4E8E\u6700\u5C0F\u5BBD\u5EA6\u548C\u6700\u5927\u5BBD\u5EA6\u4E4B\u95F4";
1178
+ }
1179
+ if (existing && !existing.userDefined) {
1180
+ existing.title = title;
1181
+ existing.settingTitle = title;
1182
+ existing.userTitle = title;
1183
+ existing.width = width;
1184
+ existing.minWidth = minWidth;
1185
+ existing.maxWidth = maxWidth;
1186
+ if (draft.order != null) moveColumnToOrder(siblings, existing, draft.order);
1187
+ return null;
1188
+ }
1189
+ const dataIndex = draft.dataIndex?.trim();
1190
+ if (!dataIndex || dataIndex.split(".").some((part) => !part.trim())) {
1191
+ return "dataIndex \u4E3A\u5FC5\u586B\u9879";
1192
+ }
1193
+ if (isHeaderDataIndexUsed(columns, dataIndex, draft.key)) {
1194
+ return "\u8BE5 dataIndex \u5DF2\u88AB\u5176\u4ED6\u5217\u4F7F\u7528";
1195
+ }
1196
+ const column = existing ?? { key: createUserColumnKey(columns) };
1197
+ column.title = title;
1198
+ column.settingTitle = title;
1199
+ column.dataIndex = dataIndex.split(".");
1200
+ column.width = width;
1201
+ column.minWidth = minWidth;
1202
+ column.maxWidth = maxWidth;
1203
+ column.fixed = draft.fixed;
1204
+ column.userDefined = true;
1205
+ column.allowSort = true;
1206
+ column.sorter = true;
1207
+ if (existing && draft.order != null) {
1208
+ moveColumnToOrder(siblings, existing, draft.order);
1209
+ } else if (!existing) {
1210
+ siblings.splice((draft.order ?? maxOrder) - 1, 0, column);
1211
+ }
1212
+ return null;
1213
+ }
1214
+ function findSiblingColumnsByKey(columns, key) {
1215
+ if (columns.some((column) => resolveColumnKey(column) === key))
1216
+ return columns;
1217
+ for (const column of columns) {
1218
+ if (!column.children?.length) continue;
1219
+ const siblings = findSiblingColumnsByKey(column.children, key);
1220
+ if (siblings) return siblings;
1221
+ }
1222
+ return null;
1223
+ }
1224
+ function moveColumnToOrder(siblings, column, order) {
1225
+ const currentIndex = siblings.indexOf(column);
1226
+ if (currentIndex < 0 || currentIndex === order - 1) return;
1227
+ siblings.splice(currentIndex, 1);
1228
+ siblings.splice(order - 1, 0, column);
1229
+ }
1230
+ function deleteHeaderSettingsColumn(columns, columnKey) {
1231
+ const target = findColumnNode(columns, columnKey);
1232
+ if (!target?.userDefined || countVisibleLeafColumns(columns) <= countVisibleLeafColumns([target]))
1233
+ return false;
1234
+ const remove = (items) => {
1235
+ const index = items.findIndex(
1236
+ (column) => resolveColumnKey(column) === columnKey
1237
+ );
1238
+ if (index >= 0) {
1239
+ items.splice(index, 1);
1240
+ return true;
1241
+ }
1242
+ return items.some(
1243
+ (column) => column.children?.length && remove(column.children)
1244
+ );
1245
+ };
1246
+ return remove(columns);
1247
+ }
1248
+ function createUserColumnKey(columns) {
1249
+ let index = 1;
1250
+ while (findColumnNode(columns, `user-column-${index}`)) index += 1;
1251
+ return `user-column-${index}`;
1252
+ }
1253
+ function isHeaderDataIndexUsed(columns, dataIndex, excludeKey) {
1254
+ return columns.some(
1255
+ (column) => resolveColumnKey(column) !== excludeKey && column.dataIndex != null && utils.stringifyDataIndex(column.dataIndex) === dataIndex || column.children?.length && isHeaderDataIndexUsed(column.children, dataIndex, excludeKey)
1256
+ );
1257
+ }
1125
1258
  function setHeaderColumnVisible(columns, columnKey, visible) {
1126
1259
  if (!visible) {
1127
1260
  const targetLeafCount = getColumnLeafCount(columns, columnKey);
@@ -1320,10 +1453,18 @@ function findColumnNode(columns, columnKey) {
1320
1453
  }
1321
1454
  return null;
1322
1455
  }
1323
- function buildHeaderSettingsItem(column, totalVisibleLeafCount, parentHidden) {
1456
+ function buildHeaderSettingsItem(column, totalVisibleLeafCount, parentHidden, order, siblingCount) {
1324
1457
  const hidden = parentHidden || !!column.hidden;
1325
- const children = column.children?.filter((child) => !child.hideInSetting).map(
1326
- (child) => buildHeaderSettingsItem(child, totalVisibleLeafCount, hidden)
1458
+ const children = column.children?.flatMap(
1459
+ (child, index) => child.hideInSetting ? [] : [
1460
+ buildHeaderSettingsItem(
1461
+ child,
1462
+ totalVisibleLeafCount,
1463
+ hidden,
1464
+ index + 1,
1465
+ column.children.length
1466
+ )
1467
+ ]
1327
1468
  );
1328
1469
  const leafCount = countLeafColumns([column]);
1329
1470
  const visibleLeafCount = hidden ? 0 : countVisibleLeafColumns([column]);
@@ -1335,6 +1476,14 @@ function buildHeaderSettingsItem(column, totalVisibleLeafCount, parentHidden) {
1335
1476
  title: String(
1336
1477
  column.settingTitle ?? column.title ?? resolveColumnKey(column)
1337
1478
  ),
1479
+ dataIndex: column.dataIndex == null ? void 0 : utils.stringifyDataIndex(column.dataIndex),
1480
+ userDefined: column.userDefined === true,
1481
+ width: column.width,
1482
+ minWidth: column.minWidth,
1483
+ maxWidth: column.maxWidth,
1484
+ fixed: column.fixed,
1485
+ order,
1486
+ siblingCount,
1338
1487
  checked,
1339
1488
  indeterminate,
1340
1489
  disabled,
@@ -6511,12 +6660,12 @@ function queryFilterWorkerEntrypoint() {
6511
6660
  let filters = [];
6512
6661
  const matchedIndices = [];
6513
6662
  const now2 = () => typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
6514
- const escapeRegExp2 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6663
+ const escapeRegExp3 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6515
6664
  const wildcardToRegExp2 = (value) => {
6516
6665
  const pattern = Array.from(value).map((char) => {
6517
6666
  if (char === "%") return ".*";
6518
6667
  if (char === "_") return ".";
6519
- return escapeRegExp2(char);
6668
+ return escapeRegExp3(char);
6520
6669
  }).join("");
6521
6670
  return new RegExp(`^${pattern}$`, "i");
6522
6671
  };
@@ -11233,7 +11382,6 @@ function roundRectPath3(ctx, x, y, width, height, radius) {
11233
11382
  var TAG_HORIZONTAL_PADDING = 8;
11234
11383
  var TAG_HEIGHT = 22;
11235
11384
  var TAG_RADIUS = 4;
11236
- var TAG_TEXT_OPTICAL_OFFSET_Y = 1;
11237
11385
  var ANT_TAG_PRESET_MAP = {
11238
11386
  default: {
11239
11387
  backgroundColor: "#fafafa",
@@ -11379,7 +11527,7 @@ function drawBodyTagContent(params) {
11379
11527
  textIndent,
11380
11528
  textAlign: resolveContentTextAlign(content, "center")
11381
11529
  });
11382
- const centerY = top + height / 2 + TAG_TEXT_OPTICAL_OFFSET_Y;
11530
+ const centerY = rect.y + rect.height / 2;
11383
11531
  const textY = resolveCenteredTextBaselineY({
11384
11532
  centerY,
11385
11533
  ascent: bounds.ascent,
@@ -11588,7 +11736,7 @@ function drawBodyTextContent(params) {
11588
11736
  textHeight: bounds.height,
11589
11737
  color: theme.textSelectionBackgroundColor ?? "#99c2ff"
11590
11738
  });
11591
- if (searchMatch && searchMatch.rowIndex === rowIndex && searchMatch.columnKey === column.key && searchMatch.keyword) {
11739
+ if (searchMatch && searchMatch.rowIndex === rowIndex && searchMatch.columnKey === column.key && (searchMatch.contentIndex == null || searchMatch.contentIndex === contentIndex) && searchMatch.keyword) {
11592
11740
  const start = Math.max(0, Math.min(searchMatch.start, content.text.length));
11593
11741
  const end = Math.max(start, Math.min(searchMatch.end, content.text.length));
11594
11742
  const prefixWidth = ctx.measureText(content.text.slice(0, start)).width;
@@ -12344,6 +12492,12 @@ function resolveRawBodyCellContents(params) {
12344
12492
  }
12345
12493
  ];
12346
12494
  }
12495
+ if (column.cellType === "emoji") {
12496
+ return normalizeCellContents({
12497
+ type: "emoji",
12498
+ emoji: formattedText ?? String(value ?? "")
12499
+ });
12500
+ }
12347
12501
  if (column.cellType === "money") {
12348
12502
  return [
12349
12503
  {
@@ -12401,6 +12555,21 @@ function normalizeDrawableCellContents(contents) {
12401
12555
  ).map(normalizeCellContentItem);
12402
12556
  }
12403
12557
  function normalizeCellContentItem(content) {
12558
+ if (content.type === "emoji") {
12559
+ const { emoji, size, ...rest } = content;
12560
+ return {
12561
+ ...rest,
12562
+ type: "text",
12563
+ text: emoji,
12564
+ fontSize: size ?? 20,
12565
+ style: {
12566
+ ...content.style,
12567
+ fontSize: content.style?.fontSize ?? size ?? 20,
12568
+ fontWeight: content.style?.fontWeight ?? "normal",
12569
+ fontFamily: content.style?.fontFamily ?? '"Segoe UI Emoji", "Apple Color Emoji", "Noto Color Emoji", "Segoe UI Symbol", sans-serif'
12570
+ }
12571
+ };
12572
+ }
12404
12573
  if (content.type === "timeline") {
12405
12574
  return { ...content, style: { ...content.style, display: "block" } };
12406
12575
  }
@@ -13862,6 +14031,9 @@ function buildBodyContentsPlainText(contents) {
13862
14031
  if (content.type === "icon") {
13863
14032
  return content.icon;
13864
14033
  }
14034
+ if (content.type === "emoji") {
14035
+ return content.emoji;
14036
+ }
13865
14037
  if (content.type === "text" || content.type === "link" || content.type === "tag") {
13866
14038
  return content.text;
13867
14039
  }
@@ -14199,6 +14371,9 @@ function isCellContentDisabled(content) {
14199
14371
  if (content.type === "tag") {
14200
14372
  return false;
14201
14373
  }
14374
+ if (content.type === "emoji") {
14375
+ return false;
14376
+ }
14202
14377
  if (content.type === "money") {
14203
14378
  return false;
14204
14379
  }
@@ -17815,9 +17990,7 @@ async function exportAllRowsTxtContent(params) {
17815
17990
  });
17816
17991
  }
17817
17992
  async function exportAllRowsXlsxContent(params) {
17818
- const columns = params.columns.filter(
17819
- (column) => column.key !== ROW_SELECTION_COLUMN_KEY && column.key !== ROW_SELECTOR_COLUMN_KEY
17820
- );
17993
+ const columns = params.columns.filter(isExportableColumn);
17821
17994
  const footerRows = [];
17822
17995
  if (params.includeSummary) {
17823
17996
  const values = await computeSummaryValuesAsync({
@@ -17916,14 +18089,21 @@ function resolveProgressClipboardPercent(content) {
17916
18089
  return Math.min(Math.max((content.value - min) / range * 100, 0), 100);
17917
18090
  }
17918
18091
  function buildExportColumns(columns) {
17919
- return columns.filter(
17920
- (column) => column.key !== ROW_SELECTION_COLUMN_KEY && column.key !== ROW_SELECTOR_COLUMN_KEY
17921
- ).map((column) => ({
18092
+ return columns.filter(isExportableColumn).map((column) => ({
17922
18093
  key: column.key,
17923
18094
  title: column.title ?? column.key,
17924
18095
  value: (row, rowIndex) => getCellClipboardText(row, rowIndex, column)
17925
18096
  }));
17926
18097
  }
18098
+ function isExportableColumn(column) {
18099
+ if (column.key === ROW_SELECTION_COLUMN_KEY || column.key === ROW_SELECTOR_COLUMN_KEY || column.key === EXPAND_COLUMN_KEY) {
18100
+ return false;
18101
+ }
18102
+ if (column.exportable !== void 0) return column.exportable;
18103
+ return !(/^(?:action|actions|operate|operation|operations)$/i.test(column.key) || /^(?:操作|操作列|操作按钮|action|actions|operation|operations)$/i.test(
18104
+ column.title.trim()
18105
+ ));
18106
+ }
17927
18107
  function buildTableExportFileName(extension) {
17928
18108
  const now2 = /* @__PURE__ */ new Date();
17929
18109
  const stamp = [
@@ -18099,13 +18279,14 @@ var ListTableContentActionController = class {
18099
18279
  * 异步导出全部原始数据为 XLSX。
18100
18280
  */
18101
18281
  exportXlsx(options) {
18282
+ const includeSummary = options?.includeSummary ?? this.options.getSummaryVisible?.() ?? false;
18102
18283
  options = { ...this.options.getOptions().exportOptions, ...options };
18103
18284
  this.startExportTask(
18104
18285
  (fileName) => exportAllRowsXlsxContent({
18105
18286
  rows: this.options.getOptions().dataSource,
18106
18287
  columns: this.options.getLeafColumns(),
18107
18288
  ...options,
18108
- includeSummary: options?.includeSummary ?? this.options.getSummaryVisible?.() ?? false,
18289
+ includeSummary,
18109
18290
  fileName: fileName ?? options?.fileName,
18110
18291
  onProgress: (progress) => {
18111
18292
  const fileLabel = progress.fileCount && progress.fileCount > 1 ? `\uFF08\u7B2C ${progress.fileIndex}/${progress.fileCount} \u4EFD\uFF09` : "";
@@ -18799,7 +18980,7 @@ function openCellEditingSession(params) {
18799
18980
  }
18800
18981
  const editorConfig = resolveEditorConfig(editConfig);
18801
18982
  const editingValue = initialValue === void 0 ? currentValue : initialValue;
18802
- const selectOnFocus = !(initialValue !== void 0 && (currentValue == null || currentValue === ""));
18983
+ const selectOnFocus = initialValue === void 0;
18803
18984
  const hostRect = toHostRect ? toHostRect(descriptor.rect) : descriptor.rect;
18804
18985
  const zoom = typeof theme.contentZoom === "number" && Number.isFinite(theme.contentZoom) && theme.contentZoom > 0 ? theme.contentZoom : 1;
18805
18986
  const paddingInline = (column.cellStyle?.paddingInline ?? DEFAULT_EDITOR_PADDING_INLINE) * zoom;
@@ -26225,6 +26406,134 @@ function measureHeaderWidth(ctx, column, theme) {
26225
26406
  return Math.ceil(contentWidth + HEADER_PADDING_INLINE * 2 + actionWidth);
26226
26407
  }
26227
26408
 
26409
+ // src/features/search/search-matcher.ts
26410
+ function createListTableSearchMatcher(keyword, options) {
26411
+ const pattern = options.mode === "regex" ? keyword : keyword.trim();
26412
+ if (!pattern) {
26413
+ return { findMatches: () => [], error: null, active: false };
26414
+ }
26415
+ if (options.mode === "fuzzy") {
26416
+ const needle = options.caseSensitive ? pattern : pattern.toLocaleLowerCase();
26417
+ return {
26418
+ error: null,
26419
+ active: true,
26420
+ findMatches: (text) => {
26421
+ const source = options.caseSensitive ? text : text.toLocaleLowerCase();
26422
+ const matches = [];
26423
+ let start = source.indexOf(needle);
26424
+ while (start >= 0) {
26425
+ matches.push({ start, end: start + pattern.length });
26426
+ start = source.indexOf(needle, start + needle.length);
26427
+ }
26428
+ return matches;
26429
+ }
26430
+ };
26431
+ }
26432
+ if (options.mode === "exact") {
26433
+ const needle = options.caseSensitive ? pattern : pattern.toLocaleLowerCase();
26434
+ return {
26435
+ error: null,
26436
+ active: true,
26437
+ findMatches: (text) => {
26438
+ const source = options.caseSensitive ? text : text.toLocaleLowerCase();
26439
+ return source === needle ? [{ start: 0, end: text.length }] : [];
26440
+ }
26441
+ };
26442
+ }
26443
+ try {
26444
+ const source = options.mode === "wildcard" ? wildcardToRegExpSource(pattern) : pattern;
26445
+ const expression = new RegExp(source, options.caseSensitive ? "g" : "gi");
26446
+ return {
26447
+ error: null,
26448
+ active: true,
26449
+ findMatches: (text) => {
26450
+ const matches = [];
26451
+ expression.lastIndex = 0;
26452
+ let result;
26453
+ while ((result = expression.exec(text)) !== null) {
26454
+ if (result[0].length > 0) {
26455
+ matches.push({ start: result.index, end: expression.lastIndex });
26456
+ } else {
26457
+ expression.lastIndex += 1;
26458
+ }
26459
+ }
26460
+ return matches;
26461
+ }
26462
+ };
26463
+ } catch {
26464
+ return { findMatches: () => [], error: "\u6B63\u5219\u8868\u8FBE\u5F0F\u65E0\u6548", active: false };
26465
+ }
26466
+ }
26467
+ function wildcardToRegExpSource(pattern) {
26468
+ let source = "";
26469
+ for (let index = 0; index < pattern.length; index += 1) {
26470
+ const char = pattern[index];
26471
+ if (char === "\\" && index + 1 < pattern.length) {
26472
+ source += escapeRegExp2(pattern[++index]);
26473
+ } else if (char === "*") {
26474
+ source += ".*";
26475
+ } else if (char === "?") {
26476
+ source += ".";
26477
+ } else {
26478
+ source += escapeRegExp2(char);
26479
+ }
26480
+ }
26481
+ return source;
26482
+ }
26483
+ function escapeRegExp2(value) {
26484
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
26485
+ }
26486
+ function resolveListTableSearchCellTexts(params) {
26487
+ const { record, rowIndex, column } = params;
26488
+ if (!column.render && !column.dataFormat && !column.cellType) {
26489
+ return [
26490
+ {
26491
+ contentIndex: 0,
26492
+ text: String(utils.getValueByDataIndex(record, column.dataIndex) ?? "")
26493
+ }
26494
+ ];
26495
+ }
26496
+ return resolveBodyCellContents({ record, rowIndex, column }).flatMap(
26497
+ (content, contentIndex) => content.type === "text" ? [{ contentIndex, text: content.text }] : []
26498
+ );
26499
+ }
26500
+ function buildHeaderDataIndexOptions(rows, columns) {
26501
+ const paths = /* @__PURE__ */ new Set();
26502
+ const used = /* @__PURE__ */ new Map();
26503
+ const visitColumns = (items) => {
26504
+ items.forEach((column) => {
26505
+ if (column.dataIndex != null) {
26506
+ const path = utils.stringifyDataIndex(column.dataIndex);
26507
+ if (!used.has(path)) {
26508
+ used.set(
26509
+ path,
26510
+ String(column.settingTitle ?? column.title ?? column.key ?? path)
26511
+ );
26512
+ }
26513
+ }
26514
+ if (column.children?.length) visitColumns(column.children);
26515
+ });
26516
+ };
26517
+ visitColumns(columns);
26518
+ const visitValue = (value, prefix, depth) => {
26519
+ if (!value || typeof value !== "object" || Array.isArray(value) || value instanceof Date)
26520
+ return;
26521
+ Object.entries(value).forEach(([key, child]) => {
26522
+ if (paths.size >= 200) return;
26523
+ const path = prefix ? `${prefix}.${key}` : key;
26524
+ paths.add(path);
26525
+ if (depth < 3) visitValue(child, path, depth + 1);
26526
+ });
26527
+ };
26528
+ rows.slice(0, 50).forEach((row) => visitValue(row, "", 0));
26529
+ used.forEach((_label, path) => paths.add(path));
26530
+ return [...paths].map((value) => ({
26531
+ value,
26532
+ disabled: used.has(value),
26533
+ ...used.has(value) ? { label: used.get(value) } : null
26534
+ }));
26535
+ }
26536
+
26228
26537
  // src/features/overlay/context-menu-builder.ts
26229
26538
  function createListTableContextMenuActions(params) {
26230
26539
  return {
@@ -26387,6 +26696,8 @@ function createListTableContextMenuActions(params) {
26387
26696
  onChangeZoom: params.onChangeZoom,
26388
26697
  onToggleCurrentColumn: params.onToggleCurrentColumn ?? params.onToggleColumn,
26389
26698
  onToggleColumn: params.onToggleColumn,
26699
+ onSaveColumn: params.onSaveColumn,
26700
+ onDeleteColumn: params.onDeleteColumn,
26390
26701
  onChangeCachePreference: params.onChangeCachePreference ? (category, enabled) => {
26391
26702
  params.hideMenu();
26392
26703
  params.onChangeCachePreference?.(category, enabled);
@@ -26455,6 +26766,7 @@ function buildListTableContextMenuConfig(params) {
26455
26766
  x,
26456
26767
  y,
26457
26768
  columns,
26769
+ dataSource,
26458
26770
  columnKey,
26459
26771
  isHeaderArea,
26460
26772
  isSummaryArea = false,
@@ -26479,6 +26791,7 @@ function buildListTableContextMenuConfig(params) {
26479
26791
  const isBodyArea = bodyRowIndex != null;
26480
26792
  const isSelectionColumn = columnKey === ROW_SELECTION_COLUMN_KEY || columnKey === ROW_SELECTOR_COLUMN_KEY;
26481
26793
  const enableCopy = enabledFeatures.has("copy");
26794
+ const enableChart = enabledFeatures.has("chart");
26482
26795
  const enableSearch = enabledFeatures.has("search");
26483
26796
  const enableExport = enabledFeatures.has("export");
26484
26797
  const enableDownloadContent = enabledFeatures.has("downloadContent");
@@ -26526,6 +26839,7 @@ function buildListTableContextMenuConfig(params) {
26526
26839
  return {
26527
26840
  x,
26528
26841
  y,
26842
+ onCreateChart: enableChart && (isBodyArea || isExpandedArea || isHeaderArea && columnKey !== ROW_SELECTION_COLUMN_KEY) ? params.onCreateChart : void 0,
26529
26843
  columns: enableColumnVisibility ? headerItems : void 0,
26530
26844
  density: enableDensity ? density : void 0,
26531
26845
  zoom: enableZoom ? normalizeContextMenuZoom(zoom) : void 0,
@@ -26614,6 +26928,9 @@ function buildListTableContextMenuConfig(params) {
26614
26928
  onChangeDensity: enableDensity ? actions.onChangeDensity : void 0,
26615
26929
  onChangeZoom: enableZoom ? actions.onChangeZoom : void 0,
26616
26930
  onToggleColumn: enableColumnVisibility && isTableSettingsArea ? actions.onToggleColumn : void 0,
26931
+ dataIndexOptions: enableColumnVisibility && isTableSettingsArea ? buildHeaderDataIndexOptions(dataSource ?? [], columns) : void 0,
26932
+ onSaveColumn: enableColumnVisibility && isTableSettingsArea ? actions.onSaveColumn : void 0,
26933
+ onDeleteColumn: enableColumnVisibility && isTableSettingsArea ? actions.onDeleteColumn : void 0,
26617
26934
  columnSettingsCacheAvailable: Boolean(params.storageKey),
26618
26935
  cachePreferences: params.cachePreferences,
26619
26936
  onChangeCachePreference: enabledFeatures.has("cache") ? actions.onChangeCachePreference : void 0,
@@ -26669,6 +26986,7 @@ function findSummaryColumn(columns, columnKey) {
26669
26986
  }
26670
26987
  var DEFAULT_CONTEXT_MENU_FEATURES = [
26671
26988
  "copy",
26989
+ "chart",
26672
26990
  "search",
26673
26991
  "export",
26674
26992
  "downloadContent",
@@ -26825,6 +27143,8 @@ function showHeaderContextMenu(params) {
26825
27143
  onChangeZoom,
26826
27144
  onToggleCurrentColumn,
26827
27145
  onToggleColumn,
27146
+ onSaveColumn,
27147
+ onDeleteColumn,
26828
27148
  onExpandAllCollapsedColumns,
26829
27149
  onClose,
26830
27150
  onToggleSummary,
@@ -26852,7 +27172,8 @@ function showHeaderContextMenu(params) {
26852
27172
  const isSummaryArea = result.area === "summary";
26853
27173
  const isExpandedArea = result.area === "expanded-row" || result.columnKey === "__expanded_row__";
26854
27174
  const isSelectionColumn = result.columnKey === ROW_SELECTION_COLUMN_KEY || result.columnKey === ROW_SELECTOR_COLUMN_KEY;
26855
- if (!isHeaderArea && !isBodyArea && !groupingBarArea && !isExpandedArea || !result.columnKey && !groupingBarArea && !isExpandedArea || isHeaderArea && isSelectionColumn) {
27175
+ const isChartCorner = isHeaderArea && result.columnKey === ROW_SELECTOR_COLUMN_KEY && resolveEnabledContextMenuFeatures(options.contextMenu).has("chart");
27176
+ if (!isHeaderArea && !isBodyArea && !groupingBarArea && !isExpandedArea || !result.columnKey && !groupingBarArea && !isExpandedArea || isHeaderArea && isSelectionColumn && !isChartCorner) {
26856
27177
  headerContextMenu.hide();
26857
27178
  return false;
26858
27179
  }
@@ -26865,7 +27186,7 @@ function showHeaderContextMenu(params) {
26865
27186
  fixedPopup.hide();
26866
27187
  hideBodyTooltip();
26867
27188
  const contextColumnKey = result.columnKey ?? "";
26868
- if (isHeaderArea) {
27189
+ if (isHeaderArea && !isChartCorner) {
26869
27190
  onSelectHeader(contextColumnKey, result.rect);
26870
27191
  }
26871
27192
  const bodyRowIndex = isBodyArea && !isSummaryArea && !isExpandedArea && typeof result.rowIndex === "number" ? result.rowIndex : null;
@@ -26881,11 +27202,13 @@ function showHeaderContextMenu(params) {
26881
27202
  x: event.clientX,
26882
27203
  y: event.clientY,
26883
27204
  columns: options.columns,
27205
+ dataSource: options.dataSource,
26884
27206
  columnKey: result.columnKey ?? "",
26885
27207
  isHeaderArea,
26886
27208
  isSummaryArea,
26887
27209
  isExpandedArea,
26888
27210
  onCopySummaryRowText: params.onCopySummaryRowText,
27211
+ onCreateChart: params.onCreateChart,
26889
27212
  onCopyImage: params.onCopyImage,
26890
27213
  onExportImage: params.onExportImage,
26891
27214
  canCopySelectionImage: params.canCopySelectionImage,
@@ -26937,6 +27260,8 @@ function showHeaderContextMenu(params) {
26937
27260
  onChangeZoom,
26938
27261
  onToggleCurrentColumn,
26939
27262
  onToggleColumn,
27263
+ onSaveColumn,
27264
+ onDeleteColumn,
26940
27265
  onExpandAllCollapsedColumns,
26941
27266
  onClose,
26942
27267
  onToggleSummary,
@@ -26976,6 +27301,77 @@ function resolveContextMenuDensity(rowHeight) {
26976
27301
  return rowHeight === 48 ? "middle" : "compact";
26977
27302
  }
26978
27303
 
27304
+ // src/features/overlay/chart-data.ts
27305
+ function createListTableChartData(params) {
27306
+ const {
27307
+ rows,
27308
+ columns,
27309
+ columnKey,
27310
+ rowIndex,
27311
+ selectionRange,
27312
+ selectedRowRange,
27313
+ selectedColumnRange
27314
+ } = params;
27315
+ const startRow = Math.max(
27316
+ selectionRange?.startRowIndex ?? selectedRowRange?.start ?? Math.max((rowIndex ?? 0) - 10, 0),
27317
+ 0
27318
+ );
27319
+ const endRow = Math.min(
27320
+ selectionRange?.endRowIndex ?? selectedRowRange?.end ?? startRow + 199,
27321
+ rows.length - 1
27322
+ );
27323
+ const selectedColumns = selectionRange ? columns.slice(
27324
+ Math.max(selectionRange.startColumnIndex, 0),
27325
+ selectionRange.endColumnIndex + 1
27326
+ ) : selectedRowRange ? columns : selectedColumnRange ? columns.slice(
27327
+ Math.max(selectedColumnRange.start, 0),
27328
+ selectedColumnRange.end + 1
27329
+ ) : columns.filter((column) => column.key === columnKey);
27330
+ const chartColumns = selectedColumns.filter(
27331
+ (column) => column.key !== ROW_SELECTION_COLUMN_KEY && column.key !== ROW_SELECTOR_COLUMN_KEY && column.key !== EXPAND_COLUMN_KEY
27332
+ ).slice(0, 12);
27333
+ if (startRow > endRow || chartColumns.length === 0) return null;
27334
+ const sampledRows = rows.slice(
27335
+ startRow,
27336
+ Math.min(endRow + 1, startRow + 200)
27337
+ );
27338
+ const values = chartColumns.map(
27339
+ (column) => sampledRows.map(
27340
+ (record, offset) => getCellClipboardText(record, startRow + offset, column)
27341
+ )
27342
+ );
27343
+ const numericColumns = chartColumns.flatMap((column, index) => {
27344
+ const numbers = values[index]?.map(parseChartNumber) ?? [];
27345
+ return numbers.some((value) => value !== null) ? [{ name: column.title, data: numbers.map((value) => value ?? 0) }] : [];
27346
+ });
27347
+ if (numericColumns.length === 0) return null;
27348
+ const labelIndex = chartColumns.findIndex(
27349
+ (_, index) => values[index]?.every((value) => parseChartNumber(value) === null)
27350
+ );
27351
+ if (sampledRows.length === 1 && chartColumns.length > 1) {
27352
+ return {
27353
+ labels: numericColumns.map((series) => series.name),
27354
+ series: [
27355
+ {
27356
+ name: values[labelIndex]?.[0] || String(startRow + 1),
27357
+ data: numericColumns.map((series) => series.data[0] ?? 0)
27358
+ }
27359
+ ]
27360
+ };
27361
+ }
27362
+ const labels = sampledRows.map(
27363
+ (_, index) => labelIndex >= 0 ? values[labelIndex]?.[index] || String(startRow + index + 1) : String(startRow + index + 1)
27364
+ );
27365
+ return { labels, series: numericColumns };
27366
+ }
27367
+ function parseChartNumber(value) {
27368
+ const normalized = value.trim().replace(/[,,\s¥¥$]/g, "");
27369
+ if (!normalized) return null;
27370
+ const percentage = normalized.endsWith("%");
27371
+ const parsed = Number(percentage ? normalized.slice(0, -1) : normalized);
27372
+ return Number.isFinite(parsed) ? parsed : null;
27373
+ }
27374
+
26979
27375
  // src/features/tooltip/tooltip-feature.ts
26980
27376
  function getHeaderActionTooltipText(result, sortState) {
26981
27377
  const area = result.area;
@@ -27997,6 +28393,11 @@ var EDITABLE_CELL_ROW_SELECTION_DELAY = 300;
27997
28393
  var ListTableEventController = class {
27998
28394
  constructor(host) {
27999
28395
  __publicField(this, "searchKeyword", "");
28396
+ __publicField(this, "searchOptions", {
28397
+ mode: "fuzzy",
28398
+ caseSensitive: false
28399
+ });
28400
+ __publicField(this, "searchError", null);
28000
28401
  __publicField(this, "searchMatches", []);
28001
28402
  __publicField(this, "searchCurrentIndex", -1);
28002
28403
  __publicField(this, "textSelectionDrag", null);
@@ -28559,6 +28960,15 @@ var ListTableEventController = class {
28559
28960
  getAllRows: () => this.host.options.dataSource,
28560
28961
  getExportSummaryEnabled: () => Boolean(this.host.currentRenderSnapshot?.hasSummary),
28561
28962
  onCopyImage: (scope) => this.copyImage(scope, event),
28963
+ onCreateChart: () => createListTableChartData({
28964
+ rows: this.host.getDisplayData(),
28965
+ columns: this.host.leafColumns,
28966
+ columnKey: contextResult.columnKey ?? "",
28967
+ rowIndex: typeof contextResult.rowIndex === "number" ? contextResult.rowIndex : null,
28968
+ selectionRange: this.host.rangeHighlight.selectedCellRange,
28969
+ selectedRowRange: this.host.rangeHighlight.selectedRowRange,
28970
+ selectedColumnRange: this.host.rangeHighlight.selectedColumnRange
28971
+ }),
28562
28972
  onExportImage: (scope) => this.copyImage(scope, event, true),
28563
28973
  canCopySelectionImage: resolveImageSelection(this.host) != null,
28564
28974
  onCopySummaryRowText: () => {
@@ -28591,15 +29001,21 @@ var ListTableEventController = class {
28591
29001
  this.host.selectHeader(columnKey, rect);
28592
29002
  },
28593
29003
  onSelectBodyRow: (rowIndex, columnKey) => {
29004
+ const selectedCellRange = this.host.rangeHighlight.selectedCellRange;
29005
+ const columnIndex = this.host.leafColumns.findIndex(
29006
+ (column) => column.key === columnKey
29007
+ );
28594
29008
  this.host.selection = {
28595
29009
  rowIndex,
28596
29010
  columnKey
28597
29011
  };
28598
29012
  this.host.clearSelectedHeader();
28599
- this.host.rangeHighlight = resolveNextRowHighlightForContextMenu({
28600
- current: this.host.rangeHighlight,
28601
- rowIndex
28602
- });
29013
+ if (!selectedCellRange || rowIndex < selectedCellRange.startRowIndex || rowIndex > selectedCellRange.endRowIndex || columnIndex < selectedCellRange.startColumnIndex || columnIndex > selectedCellRange.endColumnIndex) {
29014
+ this.host.rangeHighlight = resolveNextRowHighlightForContextMenu({
29015
+ current: this.host.rangeHighlight,
29016
+ rowIndex
29017
+ });
29018
+ }
28603
29019
  this.host.summarySelected = false;
28604
29020
  },
28605
29021
  getSelectionRange: () => this.host.rangeHighlight.selectedCellRange ?? null,
@@ -28730,6 +29146,8 @@ var ListTableEventController = class {
28730
29146
  onToggleColumn: (columnKey, visible) => {
28731
29147
  this.host.toggleHeaderColumnVisible(columnKey, visible);
28732
29148
  },
29149
+ onSaveColumn: (draft) => this.host.saveHeaderColumn(draft),
29150
+ onDeleteColumn: (columnKey) => this.host.deleteHeaderColumn(columnKey),
28733
29151
  onExpandAllCollapsedColumns: () => {
28734
29152
  this.host.expandAllCollapsedColumns();
28735
29153
  },
@@ -29530,11 +29948,17 @@ var ListTableEventController = class {
29530
29948
  publishSearchRequest() {
29531
29949
  const request = {
29532
29950
  keyword: this.searchKeyword,
29951
+ mode: this.searchOptions.mode,
29952
+ caseSensitive: this.searchOptions.caseSensitive,
29953
+ error: this.searchError,
29533
29954
  matchCount: this.searchMatches.length,
29534
29955
  currentIndex: this.searchCurrentIndex,
29535
- onSubmit: (keyword) => {
29956
+ onSubmit: (keyword, options) => {
29536
29957
  this.searchKeyword = keyword;
29537
- this.searchMatches = this.resolveSearchMatches(keyword);
29958
+ this.searchOptions = options;
29959
+ const matcher = createListTableSearchMatcher(keyword, options);
29960
+ this.searchError = matcher.error;
29961
+ this.searchMatches = matcher.active ? this.resolveSearchMatches(matcher.findMatches) : [];
29538
29962
  this.searchCurrentIndex = this.searchMatches.length > 0 ? 0 : -1;
29539
29963
  this.applyCurrentSearchMatch();
29540
29964
  this.publishSearchRequest();
@@ -29548,6 +29972,7 @@ var ListTableEventController = class {
29548
29972
  },
29549
29973
  onClose: () => {
29550
29974
  this.searchKeyword = "";
29975
+ this.searchError = null;
29551
29976
  this.searchMatches = [];
29552
29977
  this.searchCurrentIndex = -1;
29553
29978
  this.host.rangeHighlight = {
@@ -29560,30 +29985,24 @@ var ListTableEventController = class {
29560
29985
  };
29561
29986
  this.host.options.ui?.onSearchRequest?.(request);
29562
29987
  }
29563
- resolveSearchMatches(keyword) {
29564
- const normalizedKeyword = keyword.trim().toLocaleLowerCase();
29565
- if (!normalizedKeyword) return [];
29988
+ resolveSearchMatches(findMatches) {
29566
29989
  const matches = [];
29567
29990
  this.host.getDisplayData().forEach((record, rowIndex) => {
29568
29991
  this.host.leafColumns.forEach((column) => {
29569
29992
  if (isSystemColumnKey(column.key)) return;
29570
- const text = String(
29571
- utils.getValueByDataIndex(record, column.dataIndex) ?? ""
29993
+ resolveListTableSearchCellTexts({ record, rowIndex, column }).forEach(
29994
+ ({ text, contentIndex }) => {
29995
+ findMatches(text).forEach(({ start, end }) => {
29996
+ matches.push({
29997
+ rowIndex,
29998
+ columnKey: column.key,
29999
+ contentIndex,
30000
+ start,
30001
+ end
30002
+ });
30003
+ });
30004
+ }
29572
30005
  );
29573
- const source = text.toLocaleLowerCase();
29574
- let start = source.indexOf(normalizedKeyword);
29575
- while (start >= 0) {
29576
- matches.push({
29577
- rowIndex,
29578
- columnKey: column.key,
29579
- start,
29580
- end: start + normalizedKeyword.length
29581
- });
29582
- start = source.indexOf(
29583
- normalizedKeyword,
29584
- start + normalizedKeyword.length
29585
- );
29586
- }
29587
30006
  });
29588
30007
  });
29589
30008
  return matches;
@@ -31122,6 +31541,8 @@ function createListTableEventHost(core) {
31122
31541
  changeTableDensity: (density) => core.headerActionController.changeTableDensity(density),
31123
31542
  changeTableZoom: (zoom) => core.headerActionController.changeTableZoom(zoom),
31124
31543
  toggleHeaderColumnVisible: (columnKey, visible) => core.headerActionController.toggleHeaderColumnVisible(columnKey, visible),
31544
+ saveHeaderColumn: (draft) => core.headerActionController.saveHeaderColumn(draft),
31545
+ deleteHeaderColumn: (columnKey) => core.headerActionController.deleteHeaderColumn(columnKey),
31125
31546
  toggleHighlightedHeaderColumns: (columnKey, visible) => core.headerActionController.toggleHighlightedHeaderColumns(
31126
31547
  columnKey,
31127
31548
  visible
@@ -31473,6 +31894,34 @@ var ListTableHeaderActionController = class {
31473
31894
  });
31474
31895
  this.options.headerContextMenu.updateColumns(resolved.menuItems);
31475
31896
  }
31897
+ saveHeaderColumn(draft) {
31898
+ const columns = this.options.getOptions().columns;
31899
+ const error = saveHeaderSettingsColumn(columns, draft);
31900
+ if (error) return error;
31901
+ this.options.refreshRuntimeColumns();
31902
+ this.options.resetSummaryValues();
31903
+ this.options.persistColumnConfig();
31904
+ this.options.headerContextMenu.updateColumns(
31905
+ buildHeaderSettingsItems(columns)
31906
+ );
31907
+ this.options.requestRender();
31908
+ return null;
31909
+ }
31910
+ deleteHeaderColumn(columnKey) {
31911
+ const columns = this.options.getOptions().columns;
31912
+ if (!deleteHeaderSettingsColumn(columns, columnKey)) return false;
31913
+ this.options.setSortState(
31914
+ this.options.getSortState().filter((entry) => entry.key !== columnKey)
31915
+ );
31916
+ this.options.refreshRuntimeColumns();
31917
+ this.options.resetSummaryValues();
31918
+ this.options.persistColumnConfig();
31919
+ this.options.headerContextMenu.updateColumns(
31920
+ buildHeaderSettingsItems(columns)
31921
+ );
31922
+ this.options.requestRender();
31923
+ return true;
31924
+ }
31476
31925
  toggleHighlightedHeaderColumns(columnKey, visible) {
31477
31926
  if (visible) {
31478
31927
  this.toggleHeaderColumnVisible(columnKey, true);
@@ -31797,20 +32246,74 @@ function applyStoredColumnConfig(columns, storedColumns, cacheColumnSettings = t
31797
32246
  return false;
31798
32247
  }
31799
32248
  let columnWidthsChanged = false;
32249
+ if (cacheColumnSettings) {
32250
+ const existingKeys = /* @__PURE__ */ new Set();
32251
+ const collectKeys = (items) => {
32252
+ items.forEach((column) => {
32253
+ if (column.key) existingKeys.add(column.key);
32254
+ if (column.children?.length) collectKeys(column.children);
32255
+ });
32256
+ };
32257
+ collectKeys(columns);
32258
+ const findChildren = (items, parentKey) => {
32259
+ for (const column of items) {
32260
+ if (column.key === parentKey) return column.children ?? null;
32261
+ if (column.children?.length) {
32262
+ const children = findChildren(column.children, parentKey);
32263
+ if (children) return children;
32264
+ }
32265
+ }
32266
+ return null;
32267
+ };
32268
+ Object.entries(storedColumns).forEach(([key, stored]) => {
32269
+ if (!stored.userDefined || existingKeys.has(key) || !stored.dataIndex)
32270
+ return;
32271
+ const target = stored.parentKey ? findChildren(columns, stored.parentKey) : columns;
32272
+ (target ?? columns).push({
32273
+ key,
32274
+ title: stored.title ?? key,
32275
+ settingTitle: stored.title ?? key,
32276
+ dataIndex: stored.dataIndex,
32277
+ width: stored.width,
32278
+ minWidth: stored.minWidth,
32279
+ maxWidth: stored.maxWidth,
32280
+ fixed: stored.fixed,
32281
+ hidden: stored.hidden,
32282
+ userDefined: true,
32283
+ allowSort: true,
32284
+ sorter: true
32285
+ });
32286
+ existingKeys.add(key);
32287
+ });
32288
+ }
31800
32289
  const applyToColumns = (cols) => {
31801
32290
  if (cacheColumnSettings && columnOrder?.length) {
31802
- const rank = new Map(columnOrder.map((key, index) => [key, index]));
31803
- cols.sort(
31804
- (a, b) => (rank.get(a.key ?? "") ?? Infinity) - (rank.get(b.key ?? "") ?? Infinity)
31805
- );
32291
+ const rank = new Map(columnOrder.map((key, index2) => [key, index2]));
32292
+ const ranked = cols.filter((column) => rank.has(column.key ?? "")).sort((a, b) => rank.get(a.key ?? "") - rank.get(b.key ?? ""));
32293
+ let index = 0;
32294
+ cols.forEach((column, position) => {
32295
+ if (rank.has(column.key ?? "")) cols[position] = ranked[index++];
32296
+ });
31806
32297
  }
31807
32298
  for (const col of cols) {
31808
32299
  if (!col.key) {
31809
32300
  continue;
31810
32301
  }
31811
32302
  const stored = storedColumns[col.key];
31812
- if (stored) {
32303
+ if (stored && (!stored.userDefined || col.userDefined)) {
32304
+ if (cacheColumnSettings && stored.userTitle != null) {
32305
+ col.title = stored.userTitle;
32306
+ col.settingTitle = stored.userTitle;
32307
+ col.userTitle = stored.userTitle;
32308
+ }
31813
32309
  if (cacheColumnSettings) {
32310
+ if (col.userDefined && stored.userDefined) {
32311
+ col.title = stored.title ?? col.title;
32312
+ col.settingTitle = stored.title ?? col.settingTitle;
32313
+ col.dataIndex = stored.dataIndex ?? col.dataIndex;
32314
+ }
32315
+ if ("minWidth" in stored) col.minWidth = stored.minWidth;
32316
+ if ("maxWidth" in stored) col.maxWidth = stored.maxWidth;
31814
32317
  if (stored.width != null) {
31815
32318
  if ((col.width ?? 160) !== stored.width) columnWidthsChanged = true;
31816
32319
  col.width = stored.width;
@@ -31873,7 +32376,7 @@ function applyStoredColumnConfig(columns, storedColumns, cacheColumnSettings = t
31873
32376
  function buildStoredColumnConfig(columns, sortState, filterState, zoom, summaryRowHeight, density, cacheColumnSettings = true, cachePreferences) {
31874
32377
  const result = {};
31875
32378
  const columnOrder = [];
31876
- const collectColumns = (cols) => {
32379
+ const collectColumns = (cols, parentKey) => {
31877
32380
  for (const col of cols) {
31878
32381
  if (!col.key) {
31879
32382
  continue;
@@ -31882,8 +32385,19 @@ function buildStoredColumnConfig(columns, sortState, filterState, zoom, summaryR
31882
32385
  result[col.key] = {
31883
32386
  ...cacheColumnSettings ? {
31884
32387
  width: col.width ?? 160,
32388
+ minWidth: col.minWidth,
32389
+ maxWidth: col.maxWidth,
31885
32390
  fixed: col.fixed,
31886
- hidden: !!col.hidden
32391
+ hidden: !!col.hidden,
32392
+ ...col.userTitle ? { userTitle: col.userTitle } : null,
32393
+ ...col.userDefined && col.dataIndex != null ? {
32394
+ userDefined: true,
32395
+ ...parentKey ? { parentKey } : null,
32396
+ title: String(col.settingTitle ?? col.title ?? col.key),
32397
+ dataIndex: col.dataIndex,
32398
+ minWidth: col.minWidth,
32399
+ maxWidth: col.maxWidth
32400
+ } : null
31887
32401
  } : null,
31888
32402
  // IndexedDB 保留 undefined 属性;字段存在即表示显式恢复/清除,避免默认配置回弹。
31889
32403
  align: col.align,
@@ -31907,7 +32421,7 @@ function buildStoredColumnConfig(columns, sortState, filterState, zoom, summaryR
31907
32421
  } : false
31908
32422
  };
31909
32423
  if (col.children?.length) {
31910
- collectColumns(col.children);
32424
+ collectColumns(col.children, col.key);
31911
32425
  }
31912
32426
  }
31913
32427
  };
@@ -35295,6 +35809,12 @@ var ListTableCore = class {
35295
35809
  const incomingColumnsAreRuntimeColumns = options.columns === this.options.columns;
35296
35810
  const nextInitialColumns = incomingColumnsAreRuntimeColumns ? cloneColumns(host.initialColumns) : cloneColumns(options.columns);
35297
35811
  const nextInitialStretchColumns = incomingColumnsAreRuntimeColumns ? host.initialStretchColumns : options.stretchColumns;
35812
+ if (!shouldResetColumnConfig && !incomingColumnsAreRuntimeColumns && this.options.storageKey === options.storageKey) {
35813
+ preserveUserAddedColumns({
35814
+ nextColumns: options.columns,
35815
+ runtimeColumns: this.options.columns
35816
+ });
35817
+ }
35298
35818
  const shouldPreserveRuntimeWidths = !shouldResetColumnConfig && this.options.stretchColumns === false && options.stretchColumns === host.initialStretchColumns;
35299
35819
  if (shouldPreserveRuntimeWidths) {
35300
35820
  preserveRuntimeColumnWidths({