@dmitryvim/form-builder 0.2.20 → 0.2.22

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.
@@ -4778,18 +4778,54 @@ function updateGroupField(element, fieldPath, value, context) {
4778
4778
  }
4779
4779
 
4780
4780
  // src/components/table.ts
4781
+ function isLegacyMerge(m) {
4782
+ return m !== null && typeof m === "object" && "row" in m && "col" in m && "rowspan" in m && "colspan" in m;
4783
+ }
4784
+ function isValidMergeShape(m) {
4785
+ if (m === null || typeof m !== "object") return false;
4786
+ const o = m;
4787
+ return typeof o.top === "number" && typeof o.left === "number" && typeof o.bottom === "number" && typeof o.right === "number";
4788
+ }
4789
+ function migrateMerge(m) {
4790
+ if (isLegacyMerge(m)) {
4791
+ return {
4792
+ top: m.row,
4793
+ left: m.col,
4794
+ bottom: m.row + m.rowspan - 1,
4795
+ right: m.col + m.colspan - 1
4796
+ };
4797
+ }
4798
+ if (isValidMergeShape(m)) return m;
4799
+ return null;
4800
+ }
4801
+ function migrateMerges(merges) {
4802
+ return merges.map(migrateMerge).filter((m) => m !== null);
4803
+ }
4781
4804
  function createEmptyCells(rows, cols) {
4782
4805
  return Array.from(
4783
4806
  { length: rows },
4784
4807
  () => Array.from({ length: cols }, () => "")
4785
4808
  );
4786
4809
  }
4810
+ function validateMerges(merges, rows, cols) {
4811
+ for (let i = 0; i < merges.length; i++) {
4812
+ const a = merges[i];
4813
+ if (a.top < 0 || a.left < 0 || a.bottom >= rows || a.right >= cols || a.top > a.bottom || a.left > a.right)
4814
+ return `Merge ${i} out of bounds`;
4815
+ for (let j = i + 1; j < merges.length; j++) {
4816
+ const b = merges[j];
4817
+ if (a.top <= b.bottom && a.bottom >= b.top && a.left <= b.right && a.right >= b.left)
4818
+ return `Merges ${i} and ${j} overlap`;
4819
+ }
4820
+ }
4821
+ return null;
4822
+ }
4787
4823
  function getShadowingMerge(row, col, merges) {
4788
4824
  for (const m of merges) {
4789
- if (m.row === row && m.col === col) {
4825
+ if (m.top === row && m.left === col) {
4790
4826
  return null;
4791
4827
  }
4792
- if (row >= m.row && row < m.row + m.rowspan && col >= m.col && col < m.col + m.colspan) {
4828
+ if (row >= m.top && row <= m.bottom && col >= m.left && col <= m.right) {
4793
4829
  return m;
4794
4830
  }
4795
4831
  }
@@ -4797,7 +4833,7 @@ function getShadowingMerge(row, col, merges) {
4797
4833
  }
4798
4834
  function getMergeAt(row, col, merges) {
4799
4835
  var _a;
4800
- return (_a = merges.find((m) => m.row === row && m.col === col)) != null ? _a : null;
4836
+ return (_a = merges.find((m) => m.top === row && m.left === col)) != null ? _a : null;
4801
4837
  }
4802
4838
  function selectionRange(sel) {
4803
4839
  var _a;
@@ -4873,8 +4909,10 @@ function renderReadonlyTable(data, wrapper) {
4873
4909
  const merge = getMergeAt(rIdx, cIdx, merges);
4874
4910
  const td = document.createElement(rIdx === 0 ? "th" : "td");
4875
4911
  if (merge) {
4876
- if (merge.rowspan > 1) td.rowSpan = merge.rowspan;
4877
- if (merge.colspan > 1) td.colSpan = merge.colspan;
4912
+ const rowspan = merge.bottom - merge.top + 1;
4913
+ const colspan = merge.right - merge.left + 1;
4914
+ if (rowspan > 1) td.rowSpan = rowspan;
4915
+ if (colspan > 1) td.colSpan = colspan;
4878
4916
  }
4879
4917
  td.textContent = (_b = rowData[cIdx]) != null ? _b : "";
4880
4918
  td.style.cssText = `
@@ -4961,22 +4999,56 @@ function startCellEditing(span, r, c, getCells, persistValue, selectCell) {
4961
4999
  span.addEventListener("keydown", onKeyDown);
4962
5000
  span.addEventListener("blur", onBlur);
4963
5001
  }
5002
+ function ensureSpinKeyframes() {
5003
+ if (document.getElementById("fb-spin-keyframes")) return;
5004
+ const style = document.createElement("style");
5005
+ style.id = "fb-spin-keyframes";
5006
+ style.textContent = `@keyframes fb-spin { to { transform: rotate(360deg); } }`;
5007
+ document.head.appendChild(style);
5008
+ }
5009
+ function showLoadingOverlay(parent, text) {
5010
+ ensureSpinKeyframes();
5011
+ const overlay = document.createElement("div");
5012
+ overlay.className = "fb-table-loading-overlay";
5013
+ overlay.style.cssText = `
5014
+ position: absolute; top: 0; left: 0; right: 0; bottom: 0;
5015
+ background: rgba(255,255,255,0.8); display: flex;
5016
+ align-items: center; justify-content: center; flex-direction: column;
5017
+ gap: 8px; z-index: 100;
5018
+ `;
5019
+ const spinner = document.createElement("div");
5020
+ spinner.style.cssText = `
5021
+ width: 24px; height: 24px; border: 3px solid var(--fb-border-color, #ccc);
5022
+ border-top-color: var(--fb-primary-color, #0066cc); border-radius: 50%;
5023
+ animation: fb-spin 0.8s linear infinite;
5024
+ `;
5025
+ const label = document.createElement("span");
5026
+ label.textContent = text;
5027
+ label.style.cssText = `font-size: var(--fb-font-size-small, 12px); color: var(--fb-text-color, #333);`;
5028
+ overlay.appendChild(spinner);
5029
+ overlay.appendChild(label);
5030
+ parent.appendChild(overlay);
5031
+ return overlay;
5032
+ }
4964
5033
  function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
4965
- var _a, _b;
5034
+ var _a, _b, _c, _d, _e, _f, _g, _h;
4966
5035
  const state = ctx.state;
4967
5036
  const instance = ctx.instance;
4968
- const cells = initialData.cells.length > 0 ? initialData.cells.map((r) => [...r]) : createEmptyCells((_a = element.rows) != null ? _a : 3, (_b = element.columns) != null ? _b : 3);
5037
+ const mergeAllowed = element.mergeAllowed !== false;
5038
+ const cellsKey = (_b = (_a = element.fieldNames) == null ? void 0 : _a.cells) != null ? _b : "cells";
5039
+ const mergesKey = (_d = (_c = element.fieldNames) == null ? void 0 : _c.merges) != null ? _d : "merges";
5040
+ const cells = initialData.cells.length > 0 ? initialData.cells.map((r) => [...r]) : createEmptyCells((_e = element.rows) != null ? _e : 3, (_f = element.columns) != null ? _f : 3);
4969
5041
  let merges = initialData.merges ? [...initialData.merges] : [];
4970
5042
  const sel = { anchor: null, focus: null, dragging: false };
4971
5043
  const hiddenInput = document.createElement("input");
4972
5044
  hiddenInput.type = "hidden";
4973
5045
  hiddenInput.name = pathKey;
4974
- hiddenInput.value = JSON.stringify({ cells, merges });
5046
+ hiddenInput.value = JSON.stringify({ [cellsKey]: cells, [mergesKey]: merges });
4975
5047
  wrapper.appendChild(hiddenInput);
4976
5048
  function persistValue() {
4977
- hiddenInput.value = JSON.stringify({ cells, merges });
5049
+ hiddenInput.value = JSON.stringify({ [cellsKey]: cells, [mergesKey]: merges });
4978
5050
  if (instance) {
4979
- instance.triggerOnChange(pathKey, { cells, merges });
5051
+ instance.triggerOnChange(pathKey, { [cellsKey]: cells, [mergesKey]: merges });
4980
5052
  }
4981
5053
  }
4982
5054
  hiddenInput._applyExternalUpdate = (data) => {
@@ -5002,6 +5074,116 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5002
5074
  table-layout: fixed;
5003
5075
  `;
5004
5076
  tableWrapper.appendChild(tableEl);
5077
+ const acceptExts = (_h = (_g = element.importAccept) == null ? void 0 : _g.map((ext) => `.${ext.toLowerCase()}`)) != null ? _h : [];
5078
+ async function importFile(file) {
5079
+ var _a2, _b2, _c2;
5080
+ if (!state.config.parseTableFile) return;
5081
+ if (acceptExts.length > 0) {
5082
+ const ext = file.name.toLowerCase().replace(/^.*(\.[^.]+)$/, "$1");
5083
+ if (!acceptExts.includes(ext)) return;
5084
+ }
5085
+ const overlay = showLoadingOverlay(
5086
+ tableWrapper,
5087
+ t("tableImporting", state)
5088
+ );
5089
+ try {
5090
+ const result = await state.config.parseTableFile(file);
5091
+ const importedCells = result.cells;
5092
+ const importedMerges = (_a2 = result.merges) != null ? _a2 : [];
5093
+ if (importedMerges.length > 0) {
5094
+ const err = validateMerges(
5095
+ importedMerges,
5096
+ importedCells.length,
5097
+ (_c2 = (_b2 = importedCells[0]) == null ? void 0 : _b2.length) != null ? _c2 : 0
5098
+ );
5099
+ if (err) throw new Error(err);
5100
+ }
5101
+ cells.length = 0;
5102
+ importedCells.forEach((row) => cells.push([...row]));
5103
+ merges.length = 0;
5104
+ importedMerges.forEach((m) => merges.push({ ...m }));
5105
+ sel.anchor = null;
5106
+ sel.focus = null;
5107
+ persistValue();
5108
+ rebuild();
5109
+ } catch (e) {
5110
+ const errMsg = e instanceof Error ? e.message : String(e);
5111
+ console.error(
5112
+ t("tableImportError", state).replace("{error}", errMsg)
5113
+ );
5114
+ } finally {
5115
+ overlay.remove();
5116
+ }
5117
+ }
5118
+ if (element.importAccept && state.config.parseTableFile) {
5119
+ const importBtn = document.createElement("button");
5120
+ importBtn.type = "button";
5121
+ importBtn.title = t("tableImportFile", state);
5122
+ importBtn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48"/></svg>`;
5123
+ importBtn.style.cssText = `
5124
+ position: absolute; top: 2px; left: 2px;
5125
+ width: 20px; height: 20px;
5126
+ padding: 0;
5127
+ display: flex; align-items: center; justify-content: center;
5128
+ color: var(--fb-text-color, #999);
5129
+ border: none;
5130
+ background: transparent;
5131
+ cursor: pointer;
5132
+ z-index: 2;
5133
+ `;
5134
+ importBtn.addEventListener("mouseenter", () => {
5135
+ importBtn.style.color = "var(--fb-primary-color, #0066cc)";
5136
+ });
5137
+ importBtn.addEventListener("mouseleave", () => {
5138
+ importBtn.style.color = "var(--fb-text-color, #999)";
5139
+ });
5140
+ const importInput = document.createElement("input");
5141
+ importInput.type = "file";
5142
+ importInput.accept = acceptExts.join(",");
5143
+ importInput.style.display = "none";
5144
+ tableWrapper.appendChild(importInput);
5145
+ importBtn.addEventListener("click", () => {
5146
+ importInput.click();
5147
+ });
5148
+ importInput.addEventListener("change", () => {
5149
+ var _a2;
5150
+ const file = (_a2 = importInput.files) == null ? void 0 : _a2[0];
5151
+ if (file) importFile(file);
5152
+ importInput.value = "";
5153
+ });
5154
+ tableWrapper.appendChild(importBtn);
5155
+ let dragCounter = 0;
5156
+ tableWrapper.addEventListener("dragenter", (e) => {
5157
+ e.preventDefault();
5158
+ dragCounter++;
5159
+ if (dragCounter === 1) {
5160
+ tableWrapper.style.outline = "2px dashed var(--fb-primary-color, #0066cc)";
5161
+ tableWrapper.style.outlineOffset = "-2px";
5162
+ }
5163
+ });
5164
+ tableWrapper.addEventListener("dragover", (e) => {
5165
+ e.preventDefault();
5166
+ if (e.dataTransfer) e.dataTransfer.dropEffect = "copy";
5167
+ });
5168
+ tableWrapper.addEventListener("dragleave", (e) => {
5169
+ e.preventDefault();
5170
+ dragCounter--;
5171
+ if (dragCounter <= 0) {
5172
+ dragCounter = 0;
5173
+ tableWrapper.style.outline = "";
5174
+ tableWrapper.style.outlineOffset = "";
5175
+ }
5176
+ });
5177
+ tableWrapper.addEventListener("drop", (e) => {
5178
+ var _a2, _b2;
5179
+ e.preventDefault();
5180
+ dragCounter = 0;
5181
+ tableWrapper.style.outline = "";
5182
+ tableWrapper.style.outlineOffset = "";
5183
+ const file = (_b2 = (_a2 = e.dataTransfer) == null ? void 0 : _a2.files) == null ? void 0 : _b2[0];
5184
+ if (file) importFile(file);
5185
+ });
5186
+ }
5005
5187
  wrapper.appendChild(tableWrapper);
5006
5188
  const contextMenu = document.createElement("div");
5007
5189
  contextMenu.style.cssText = `
@@ -5045,6 +5227,7 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5045
5227
  return btn;
5046
5228
  }
5047
5229
  function showContextMenu(x, y) {
5230
+ if (!mergeAllowed) return;
5048
5231
  contextMenu.innerHTML = "";
5049
5232
  contextMenu.style.display = "flex";
5050
5233
  const range = selectionRange(sel);
@@ -5128,11 +5311,11 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5128
5311
  const insertAt = afterIndex !== void 0 ? afterIndex + 1 : cells.length;
5129
5312
  cells.splice(insertAt, 0, newRow);
5130
5313
  merges = merges.map((m) => {
5131
- if (m.row >= insertAt) {
5132
- return { ...m, row: m.row + 1 };
5314
+ if (m.top >= insertAt) {
5315
+ return { ...m, top: m.top + 1, bottom: m.bottom + 1 };
5133
5316
  }
5134
- if (m.row < insertAt && m.row + m.rowspan > insertAt) {
5135
- return { ...m, rowspan: m.rowspan + 1 };
5317
+ if (m.top < insertAt && m.bottom >= insertAt) {
5318
+ return { ...m, bottom: m.bottom + 1 };
5136
5319
  }
5137
5320
  return m;
5138
5321
  });
@@ -5143,19 +5326,18 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5143
5326
  if (cells.length <= 1) return;
5144
5327
  const rowToRemove = targetRow !== void 0 ? targetRow : sel.anchor ? sel.anchor.row : cells.length - 1;
5145
5328
  merges = merges.map((m) => {
5146
- const mEndRow = m.row + m.rowspan - 1;
5147
- if (m.row === rowToRemove && m.rowspan === 1) return null;
5148
- if (m.row === rowToRemove) {
5149
- return { ...m, row: m.row + 1, rowspan: m.rowspan - 1 };
5329
+ if (m.top === rowToRemove && m.bottom === rowToRemove) return null;
5330
+ if (m.top === rowToRemove) {
5331
+ return { ...m, bottom: m.bottom - 1 };
5150
5332
  }
5151
- if (mEndRow === rowToRemove) {
5152
- return { ...m, rowspan: m.rowspan - 1 };
5333
+ if (m.bottom === rowToRemove) {
5334
+ return { ...m, bottom: m.bottom - 1 };
5153
5335
  }
5154
- if (m.row < rowToRemove && mEndRow > rowToRemove) {
5155
- return { ...m, rowspan: m.rowspan - 1 };
5336
+ if (m.top < rowToRemove && m.bottom > rowToRemove) {
5337
+ return { ...m, bottom: m.bottom - 1 };
5156
5338
  }
5157
- if (m.row > rowToRemove) {
5158
- return { ...m, row: m.row - 1 };
5339
+ if (m.top > rowToRemove) {
5340
+ return { ...m, top: m.top - 1, bottom: m.bottom - 1 };
5159
5341
  }
5160
5342
  return m;
5161
5343
  }).filter((m) => m !== null);
@@ -5171,11 +5353,11 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5171
5353
  const insertAt = afterIndex !== void 0 ? afterIndex + 1 : (_b2 = (_a2 = cells[0]) == null ? void 0 : _a2.length) != null ? _b2 : 0;
5172
5354
  cells.forEach((row) => row.splice(insertAt, 0, ""));
5173
5355
  merges = merges.map((m) => {
5174
- if (m.col >= insertAt) {
5175
- return { ...m, col: m.col + 1 };
5356
+ if (m.left >= insertAt) {
5357
+ return { ...m, left: m.left + 1, right: m.right + 1 };
5176
5358
  }
5177
- if (m.col < insertAt && m.col + m.colspan > insertAt) {
5178
- return { ...m, colspan: m.colspan + 1 };
5359
+ if (m.left < insertAt && m.right >= insertAt) {
5360
+ return { ...m, right: m.right + 1 };
5179
5361
  }
5180
5362
  return m;
5181
5363
  });
@@ -5186,19 +5368,18 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5186
5368
  if (cells.length === 0 || cells[0].length <= 1) return;
5187
5369
  const colToRemove = targetCol !== void 0 ? targetCol : sel.anchor ? sel.anchor.col : cells[0].length - 1;
5188
5370
  merges = merges.map((m) => {
5189
- const mEndCol = m.col + m.colspan - 1;
5190
- if (m.col === colToRemove && m.colspan === 1) return null;
5191
- if (m.col === colToRemove) {
5192
- return { ...m, col: m.col + 1, colspan: m.colspan - 1 };
5371
+ if (m.left === colToRemove && m.right === colToRemove) return null;
5372
+ if (m.left === colToRemove) {
5373
+ return { ...m, right: m.right - 1 };
5193
5374
  }
5194
- if (mEndCol === colToRemove) {
5195
- return { ...m, colspan: m.colspan - 1 };
5375
+ if (m.right === colToRemove) {
5376
+ return { ...m, right: m.right - 1 };
5196
5377
  }
5197
- if (m.col < colToRemove && mEndCol > colToRemove) {
5198
- return { ...m, colspan: m.colspan - 1 };
5378
+ if (m.left < colToRemove && m.right > colToRemove) {
5379
+ return { ...m, right: m.right - 1 };
5199
5380
  }
5200
- if (m.col > colToRemove) {
5201
- return { ...m, col: m.col - 1 };
5381
+ if (m.left > colToRemove) {
5382
+ return { ...m, left: m.left - 1, right: m.right - 1 };
5202
5383
  }
5203
5384
  return m;
5204
5385
  }).filter((m) => m !== null);
@@ -5210,14 +5391,14 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5210
5391
  rebuild();
5211
5392
  }
5212
5393
  function mergeCells() {
5394
+ var _a2, _b2;
5395
+ if (!mergeAllowed) return;
5213
5396
  const range = selectionRange(sel);
5214
5397
  if (!range) return;
5215
5398
  const { r1, c1, r2, c2 } = range;
5216
5399
  if (r1 === r2 && c1 === c2) return;
5217
5400
  merges = merges.filter((m) => {
5218
- const mEndRow = m.row + m.rowspan - 1;
5219
- const mEndCol = m.col + m.colspan - 1;
5220
- const overlaps = m.row <= r2 && mEndRow >= r1 && m.col <= c2 && mEndCol >= c1;
5401
+ const overlaps = m.top <= r2 && m.bottom >= r1 && m.left <= c2 && m.right >= c1;
5221
5402
  return !overlaps;
5222
5403
  });
5223
5404
  const anchorText = cells[r1][c1];
@@ -5229,16 +5410,24 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5229
5410
  }
5230
5411
  }
5231
5412
  cells[r1][c1] = anchorText;
5232
- merges.push({ row: r1, col: c1, rowspan: r2 - r1 + 1, colspan: c2 - c1 + 1 });
5413
+ const newMerge = { top: r1, left: c1, bottom: r2, right: c2 };
5414
+ const testMerges = [...merges, newMerge];
5415
+ const err = validateMerges(testMerges, cells.length, (_b2 = (_a2 = cells[0]) == null ? void 0 : _a2.length) != null ? _b2 : 0);
5416
+ if (err) {
5417
+ console.warn("Merge validation failed:", err);
5418
+ return;
5419
+ }
5420
+ merges.push(newMerge);
5233
5421
  sel.anchor = { row: r1, col: c1 };
5234
5422
  sel.focus = null;
5235
5423
  persistValue();
5236
5424
  rebuild();
5237
5425
  }
5238
5426
  function splitCell() {
5427
+ if (!mergeAllowed) return;
5239
5428
  if (!sel.anchor) return;
5240
5429
  const { row, col } = sel.anchor;
5241
- const mIdx = merges.findIndex((m) => m.row === row && m.col === col);
5430
+ const mIdx = merges.findIndex((m) => m.top === row && m.left === col);
5242
5431
  if (mIdx === -1) return;
5243
5432
  merges.splice(mIdx, 1);
5244
5433
  sel.focus = null;
@@ -5263,8 +5452,10 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5263
5452
  td.setAttribute("data-row", String(rIdx));
5264
5453
  td.setAttribute("data-col", String(cIdx));
5265
5454
  if (merge) {
5266
- if (merge.rowspan > 1) td.rowSpan = merge.rowspan;
5267
- if (merge.colspan > 1) td.colSpan = merge.colspan;
5455
+ const rowspan = merge.bottom - merge.top + 1;
5456
+ const colspan = merge.right - merge.left + 1;
5457
+ if (rowspan > 1) td.rowSpan = rowspan;
5458
+ if (colspan > 1) td.colSpan = colspan;
5268
5459
  }
5269
5460
  const inRange = range !== null && rIdx >= range.r1 && rIdx <= range.r2 && cIdx >= range.c1 && cIdx <= range.c2;
5270
5461
  const isAnchor = sel.anchor !== null && sel.anchor.row === rIdx && sel.anchor.col === cIdx;
@@ -5327,6 +5518,7 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5327
5518
  }
5328
5519
  });
5329
5520
  td.addEventListener("contextmenu", (e) => {
5521
+ if (!mergeAllowed) return;
5330
5522
  const currentRange = selectionRange(sel);
5331
5523
  const isMulti = currentRange && (currentRange.r1 !== currentRange.r2 || currentRange.c1 !== currentRange.c2);
5332
5524
  const isMerged = sel.anchor && getMergeAt(sel.anchor.row, sel.anchor.col, merges);
@@ -5388,18 +5580,18 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5388
5580
  selectCell(nr, nc);
5389
5581
  return;
5390
5582
  }
5391
- if (e.key === "m" && e.ctrlKey && !e.shiftKey) {
5583
+ if (mergeAllowed && e.key === "m" && e.ctrlKey && !e.shiftKey) {
5392
5584
  e.preventDefault();
5393
5585
  mergeCells();
5394
5586
  return;
5395
5587
  }
5396
- if (e.key === "M" && e.ctrlKey && e.shiftKey) {
5588
+ if (mergeAllowed && e.key === "M" && e.ctrlKey && e.shiftKey) {
5397
5589
  e.preventDefault();
5398
5590
  splitCell();
5399
5591
  }
5400
5592
  };
5401
5593
  tableEl.oncopy = (e) => {
5402
- var _a3, _b3, _c, _d;
5594
+ var _a3, _b3, _c2, _d2;
5403
5595
  const range2 = selectionRange(sel);
5404
5596
  if (!range2) return;
5405
5597
  e.preventDefault();
@@ -5420,11 +5612,11 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5420
5612
  }
5421
5613
  const tsvText = tsvRows.join("\n");
5422
5614
  const htmlText = `<table>${htmlRows.join("")}</table>`;
5423
- (_c = e.clipboardData) == null ? void 0 : _c.setData("text/plain", tsvText);
5424
- (_d = e.clipboardData) == null ? void 0 : _d.setData("text/html", htmlText);
5615
+ (_c2 = e.clipboardData) == null ? void 0 : _c2.setData("text/plain", tsvText);
5616
+ (_d2 = e.clipboardData) == null ? void 0 : _d2.setData("text/html", htmlText);
5425
5617
  };
5426
5618
  tableEl.onpaste = (e) => {
5427
- var _a3, _b3, _c, _d, _e, _f, _g, _h, _i;
5619
+ var _a3, _b3, _c2, _d2, _e2, _f2, _g2, _h2, _i;
5428
5620
  const anchor = sel.anchor;
5429
5621
  if (!anchor) return;
5430
5622
  const text = (_b3 = (_a3 = e.clipboardData) == null ? void 0 : _a3.getData("text/plain")) != null ? _b3 : "";
@@ -5435,15 +5627,15 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5435
5627
  if (editing) {
5436
5628
  editing.contentEditable = "inherit";
5437
5629
  const r = parseInt(
5438
- (_d = (_c = editing.closest("td")) == null ? void 0 : _c.getAttribute("data-row")) != null ? _d : "0",
5630
+ (_d2 = (_c2 = editing.closest("td")) == null ? void 0 : _c2.getAttribute("data-row")) != null ? _d2 : "0",
5439
5631
  10
5440
5632
  );
5441
5633
  const c = parseInt(
5442
- (_f = (_e = editing.closest("td")) == null ? void 0 : _e.getAttribute("data-col")) != null ? _f : "0",
5634
+ (_f2 = (_e2 = editing.closest("td")) == null ? void 0 : _e2.getAttribute("data-col")) != null ? _f2 : "0",
5443
5635
  10
5444
5636
  );
5445
5637
  if (cells[r]) {
5446
- cells[r][c] = (_g = editing.textContent) != null ? _g : "";
5638
+ cells[r][c] = (_g2 = editing.textContent) != null ? _g2 : "";
5447
5639
  }
5448
5640
  }
5449
5641
  if (!text.trim()) return;
@@ -5455,7 +5647,7 @@ function renderEditTable(element, initialData, pathKey, ctx, wrapper) {
5455
5647
  const startC = anchor.col;
5456
5648
  const neededRows = startR + pasteRows.length;
5457
5649
  while (cells.length < neededRows) {
5458
- cells.push(Array((_i = (_h = cells[0]) == null ? void 0 : _h.length) != null ? _i : 1).fill(""));
5650
+ cells.push(Array((_i = (_h2 = cells[0]) == null ? void 0 : _h2.length) != null ? _i : 1).fill(""));
5459
5651
  }
5460
5652
  const maxPasteCols = Math.max(...pasteRows.map((r) => r.length));
5461
5653
  const neededCols = startC + maxPasteCols;
@@ -5744,10 +5936,50 @@ function defaultTableData(element) {
5744
5936
  function isTableData(v) {
5745
5937
  return v !== null && typeof v === "object" && "cells" in v && Array.isArray(v.cells);
5746
5938
  }
5939
+ function isTableDataWithFieldNames(v, cellsKey) {
5940
+ return v !== null && typeof v === "object" && cellsKey in v && Array.isArray(v[cellsKey]);
5941
+ }
5747
5942
  function renderTableElement(element, ctx, wrapper, pathKey) {
5943
+ var _a, _b, _c, _d;
5748
5944
  const state = ctx.state;
5749
5945
  const rawPrefill = ctx.prefill[element.key];
5750
- const initialData = isTableData(rawPrefill) ? rawPrefill : isTableData(element.default) ? element.default : defaultTableData(element);
5946
+ const cellsKey = (_b = (_a = element.fieldNames) == null ? void 0 : _a.cells) != null ? _b : "cells";
5947
+ const mergesKey = (_d = (_c = element.fieldNames) == null ? void 0 : _c.merges) != null ? _d : "merges";
5948
+ let initialData;
5949
+ if (isTableData(rawPrefill)) {
5950
+ initialData = {
5951
+ cells: rawPrefill.cells,
5952
+ merges: rawPrefill.merges ? migrateMerges(rawPrefill.merges) : []
5953
+ };
5954
+ } else if (rawPrefill && isTableDataWithFieldNames(rawPrefill, cellsKey)) {
5955
+ const rawMerges = rawPrefill[mergesKey];
5956
+ initialData = {
5957
+ cells: rawPrefill[cellsKey],
5958
+ merges: rawMerges ? migrateMerges(rawMerges) : []
5959
+ };
5960
+ } else if (isTableData(element.default)) {
5961
+ initialData = {
5962
+ cells: element.default.cells,
5963
+ merges: element.default.merges ? migrateMerges(element.default.merges) : []
5964
+ };
5965
+ } else if (element.default && isTableDataWithFieldNames(element.default, cellsKey)) {
5966
+ const rawMerges = element.default[mergesKey];
5967
+ initialData = {
5968
+ cells: element.default[cellsKey],
5969
+ merges: rawMerges ? migrateMerges(rawMerges) : []
5970
+ };
5971
+ } else {
5972
+ initialData = defaultTableData(element);
5973
+ }
5974
+ if (initialData.merges && initialData.merges.length > 0) {
5975
+ const rows = initialData.cells.length;
5976
+ const cols = rows > 0 ? initialData.cells[0].length : 0;
5977
+ const err = validateMerges(initialData.merges, rows, cols);
5978
+ if (err) {
5979
+ console.warn(`Table "${element.key}": invalid prefill merges stripped (${err})`);
5980
+ initialData = { ...initialData, merges: [] };
5981
+ }
5982
+ }
5751
5983
  if (state.config.readonly) {
5752
5984
  renderReadonlyTable(initialData, wrapper);
5753
5985
  } else {
@@ -5755,8 +5987,10 @@ function renderTableElement(element, ctx, wrapper, pathKey) {
5755
5987
  }
5756
5988
  }
5757
5989
  function validateTableElement(element, key, context) {
5990
+ var _a, _b;
5758
5991
  const { scopeRoot, skipValidation } = context;
5759
5992
  const errors = [];
5993
+ const cellsKey = (_b = (_a = element.fieldNames) == null ? void 0 : _a.cells) != null ? _b : "cells";
5760
5994
  const hiddenInput = scopeRoot.querySelector(
5761
5995
  `[name="${key}"]`
5762
5996
  );
@@ -5771,7 +6005,8 @@ function validateTableElement(element, key, context) {
5771
6005
  return { value: null, errors };
5772
6006
  }
5773
6007
  if (!skipValidation && element.required) {
5774
- const hasContent = value.cells.some(
6008
+ const cells = value[cellsKey];
6009
+ const hasContent = cells == null ? void 0 : cells.some(
5775
6010
  (row) => row.some((cell) => cell.trim() !== "")
5776
6011
  );
5777
6012
  if (!hasContent) {
@@ -5780,8 +6015,11 @@ function validateTableElement(element, key, context) {
5780
6015
  }
5781
6016
  return { value, errors };
5782
6017
  }
5783
- function updateTableField(_element, fieldPath, value, context) {
6018
+ function updateTableField(element, fieldPath, value, context) {
6019
+ var _a, _b, _c, _d;
5784
6020
  const { scopeRoot } = context;
6021
+ const cellsKey = (_b = (_a = element.fieldNames) == null ? void 0 : _a.cells) != null ? _b : "cells";
6022
+ const mergesKey = (_d = (_c = element.fieldNames) == null ? void 0 : _c.merges) != null ? _d : "merges";
5785
6023
  const hiddenInput = scopeRoot.querySelector(
5786
6024
  `[name="${fieldPath}"]`
5787
6025
  );
@@ -5791,8 +6029,21 @@ function updateTableField(_element, fieldPath, value, context) {
5791
6029
  );
5792
6030
  return;
5793
6031
  }
5794
- if (isTableData(value) && hiddenInput._applyExternalUpdate) {
5795
- hiddenInput._applyExternalUpdate(value);
6032
+ let tableData = null;
6033
+ if (isTableData(value)) {
6034
+ tableData = {
6035
+ cells: value.cells,
6036
+ merges: value.merges ? migrateMerges(value.merges) : []
6037
+ };
6038
+ } else if (value && isTableDataWithFieldNames(value, cellsKey)) {
6039
+ const rawMerges = value[mergesKey];
6040
+ tableData = {
6041
+ cells: value[cellsKey],
6042
+ merges: rawMerges ? migrateMerges(rawMerges) : []
6043
+ };
6044
+ }
6045
+ if (tableData && hiddenInput._applyExternalUpdate) {
6046
+ hiddenInput._applyExternalUpdate(tableData);
5796
6047
  } else {
5797
6048
  hiddenInput.value = JSON.stringify(value);
5798
6049
  }
@@ -7501,6 +7752,7 @@ var defaultConfig = {
7501
7752
  enableFilePreview: true,
7502
7753
  maxPreviewSize: "200px",
7503
7754
  readonly: false,
7755
+ parseTableFile: null,
7504
7756
  locale: "en",
7505
7757
  translations: {
7506
7758
  en: {
@@ -7554,6 +7806,9 @@ var defaultConfig = {
7554
7806
  tableRemoveColumn: "Remove column",
7555
7807
  tableMergeCells: "Merge cells (Ctrl+M)",
7556
7808
  tableSplitCell: "Split cell (Ctrl+Shift+M)",
7809
+ tableImportFile: "Import",
7810
+ tableImporting: "Importing...",
7811
+ tableImportError: "Import failed: {error}",
7557
7812
  richinputPlaceholder: "Type text...",
7558
7813
  richinputAttachFile: "Attach file",
7559
7814
  richinputMention: "Mention",
@@ -7610,6 +7865,9 @@ var defaultConfig = {
7610
7865
  tableRemoveColumn: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u0442\u043E\u043B\u0431\u0435\u0446",
7611
7866
  tableMergeCells: "\u041E\u0431\u044A\u0435\u0434\u0438\u043D\u0438\u0442\u044C \u044F\u0447\u0435\u0439\u043A\u0438 (Ctrl+M)",
7612
7867
  tableSplitCell: "\u0420\u0430\u0437\u0434\u0435\u043B\u0438\u0442\u044C \u044F\u0447\u0435\u0439\u043A\u0443 (Ctrl+Shift+M)",
7868
+ tableImportFile: "\u0418\u043C\u043F\u043E\u0440\u0442",
7869
+ tableImporting: "\u0418\u043C\u043F\u043E\u0440\u0442...",
7870
+ tableImportError: "\u041E\u0448\u0438\u0431\u043A\u0430 \u0438\u043C\u043F\u043E\u0440\u0442\u0430: {error}",
7613
7871
  richinputPlaceholder: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442...",
7614
7872
  richinputAttachFile: "\u041F\u0440\u0438\u043A\u0440\u0435\u043F\u0438\u0442\u044C \u0444\u0430\u0439\u043B",
7615
7873
  richinputMention: "\u0423\u043F\u043E\u043C\u044F\u043D\u0443\u0442\u044C",