@underverse-ui/underverse 2.0.27 → 2.0.29

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
@@ -5148,6 +5148,172 @@ var init_url_safety = __esm({
5148
5148
  }
5149
5149
  });
5150
5150
 
5151
+ // src/components/UEditor/table-width-model.ts
5152
+ function positiveNumber(value, fallback) {
5153
+ const number = Number(value);
5154
+ return Number.isFinite(number) && number > 0 ? number : fallback;
5155
+ }
5156
+ function clampTableBasisPoints(value, fallback = TABLE_WIDTH_BASIS_POINTS, maximum = TABLE_WIDTH_BASIS_POINTS) {
5157
+ const number = Number(value);
5158
+ if (!Number.isFinite(number)) return fallback;
5159
+ return Math.min(maximum, Math.max(0, Math.round(number)));
5160
+ }
5161
+ function clampResponsiveTableWidthBp(value, fallback = DEFAULT_RESPONSIVE_TABLE_WIDTH_BP) {
5162
+ return Math.max(1, clampTableBasisPoints(value, fallback, MAX_RESPONSIVE_TABLE_WIDTH_BP));
5163
+ }
5164
+ function normalizeTableWidthMode(value) {
5165
+ return value === "responsive" || value === "full" ? "responsive" : "fixed";
5166
+ }
5167
+ function parsePercentageToBasisPoints(value, maximum = MAX_RESPONSIVE_TABLE_WIDTH_BP) {
5168
+ if (!value) return null;
5169
+ const match = value.trim().match(/^(-?\d+(?:\.\d+)?)%$/);
5170
+ if (!match) return null;
5171
+ const percentage = Number.parseFloat(match[1]);
5172
+ if (!Number.isFinite(percentage)) return null;
5173
+ return clampTableBasisPoints(percentage * 100, TABLE_WIDTH_BASIS_POINTS, maximum);
5174
+ }
5175
+ function formatBasisPointsAsPercentage(value) {
5176
+ const percentage = clampTableBasisPoints(value, 0, MAX_RESPONSIVE_TABLE_WIDTH_BP) / 100;
5177
+ return `${Number.parseFloat(percentage.toFixed(2))}%`;
5178
+ }
5179
+ function parseColumnRatios(value) {
5180
+ const parts = Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : [];
5181
+ const ratios = parts.map((part) => Number(part));
5182
+ return ratios.length > 0 && ratios.every((ratio) => Number.isFinite(ratio) && ratio > 0) ? ratios : null;
5183
+ }
5184
+ function normalizeColumnRatios(values, columnCount) {
5185
+ if (columnCount <= 0) return [];
5186
+ const source = values?.length === columnCount ? values.map((value) => positiveNumber(value, 1)) : Array.from({ length: columnCount }, () => 1);
5187
+ const sourceTotal = source.reduce((sum, value) => sum + value, 0);
5188
+ const normalized = source.map((value) => Math.max(1, Math.round(value / sourceTotal * TABLE_WIDTH_BASIS_POINTS)));
5189
+ let difference = TABLE_WIDTH_BASIS_POINTS - normalized.reduce((sum, value) => sum + value, 0);
5190
+ while (difference !== 0) {
5191
+ let changed = false;
5192
+ for (let index = normalized.length - 1; index >= 0 && difference !== 0; index -= 1) {
5193
+ if (difference < 0 && normalized[index] <= 1) continue;
5194
+ normalized[index] += difference > 0 ? 1 : -1;
5195
+ difference += difference > 0 ? -1 : 1;
5196
+ changed = true;
5197
+ }
5198
+ if (!changed) break;
5199
+ }
5200
+ return normalized;
5201
+ }
5202
+ function getLogicalTableColumnCount(table) {
5203
+ const firstRow = table.firstChild;
5204
+ if (!firstRow) return 0;
5205
+ let count = 0;
5206
+ firstRow.forEach((cell) => {
5207
+ count += Math.max(1, Number(cell.attrs.colspan) || 1);
5208
+ });
5209
+ return count;
5210
+ }
5211
+ function getLegacyTableColumnWeights(table, fallback = 100) {
5212
+ const weights = [];
5213
+ const firstRow = table.firstChild;
5214
+ if (!firstRow) return weights;
5215
+ firstRow.forEach((cell) => {
5216
+ const colspan = Math.max(1, Number(cell.attrs.colspan) || 1);
5217
+ const colwidth = Array.isArray(cell.attrs.colwidth) ? cell.attrs.colwidth : [];
5218
+ for (let index = 0; index < colspan; index += 1) {
5219
+ weights.push(positiveNumber(colwidth[index], fallback));
5220
+ }
5221
+ });
5222
+ return weights;
5223
+ }
5224
+ function getTableColumnRatios(table) {
5225
+ const columnCount = getLogicalTableColumnCount(table);
5226
+ const stored = parseColumnRatios(table.attrs.columnRatios);
5227
+ return normalizeColumnRatios(
5228
+ stored?.length === columnCount ? stored : getLegacyTableColumnWeights(table),
5229
+ columnCount
5230
+ );
5231
+ }
5232
+ function getResponsiveTableWidthBp(table) {
5233
+ return clampResponsiveTableWidthBp(table.attrs.widthBp);
5234
+ }
5235
+ function getResponsiveTableOffsetBp(table) {
5236
+ const width = getResponsiveTableWidthBp(table);
5237
+ return resolveResponsiveTableOffsetBp(width, null, table.attrs.offsetBp);
5238
+ }
5239
+ function resolveResponsiveTableOffsetBp(widthBp, tableAlign, fallbackOffsetBp = 0) {
5240
+ const availableGap = Math.max(
5241
+ 0,
5242
+ TABLE_WIDTH_BASIS_POINTS - clampResponsiveTableWidthBp(widthBp)
5243
+ );
5244
+ if (tableAlign === "center") return Math.round(availableGap / 2);
5245
+ if (tableAlign === "right") return availableGap;
5246
+ if (tableAlign === "left") return 0;
5247
+ return Math.min(availableGap, clampTableBasisPoints(fallbackOffsetBp, 0));
5248
+ }
5249
+ function insertResponsiveColumnRatio(ratios, insertIndex, sourceIndex) {
5250
+ if (ratios.length === 0) return [TABLE_WIDTH_BASIS_POINTS];
5251
+ const safeSourceIndex = Math.max(0, Math.min(sourceIndex, ratios.length - 1));
5252
+ const next = [...ratios];
5253
+ const sourceRatio = next[safeSourceIndex];
5254
+ next.splice(Math.max(0, Math.min(insertIndex, next.length)), 0, sourceRatio);
5255
+ return normalizeColumnRatios(next, next.length);
5256
+ }
5257
+ function deleteResponsiveColumnRatio(ratios, deleteIndex) {
5258
+ if (ratios.length <= 1) return [];
5259
+ const next = ratios.filter((_, index) => index !== deleteIndex);
5260
+ return normalizeColumnRatios(next, next.length);
5261
+ }
5262
+ function moveResponsiveColumnRatio(ratios, from, to) {
5263
+ if (from === to || from < 0 || from >= ratios.length || to < 0 || to >= ratios.length) return [...ratios];
5264
+ const next = [...ratios];
5265
+ const [moved] = next.splice(from, 1);
5266
+ next.splice(to, 0, moved);
5267
+ return normalizeColumnRatios(next, next.length);
5268
+ }
5269
+ function insertResponsiveColumnLayout(widthBp, ratios, insertIndex, sourceIndex) {
5270
+ if (ratios.length === 0) {
5271
+ return {
5272
+ widthBp: clampResponsiveTableWidthBp(widthBp),
5273
+ columnRatios: [TABLE_WIDTH_BASIS_POINTS]
5274
+ };
5275
+ }
5276
+ const normalized = normalizeColumnRatios(ratios, ratios.length);
5277
+ const safeSourceIndex = Math.max(0, Math.min(sourceIndex, normalized.length - 1));
5278
+ const sourceRatio = normalized[safeSourceIndex];
5279
+ return {
5280
+ // Growing by the source column's share preserves every existing column's
5281
+ // rendered width instead of squeezing the whole table back into 100%.
5282
+ widthBp: clampResponsiveTableWidthBp(
5283
+ clampResponsiveTableWidthBp(widthBp) * (TABLE_WIDTH_BASIS_POINTS + sourceRatio) / TABLE_WIDTH_BASIS_POINTS
5284
+ ),
5285
+ columnRatios: insertResponsiveColumnRatio(normalized, insertIndex, safeSourceIndex)
5286
+ };
5287
+ }
5288
+ function deleteResponsiveColumnLayout(widthBp, ratios, deleteIndex) {
5289
+ const normalized = normalizeColumnRatios(ratios, ratios.length);
5290
+ if (normalized.length <= 1 || deleteIndex < 0 || deleteIndex >= normalized.length) {
5291
+ return {
5292
+ widthBp: clampResponsiveTableWidthBp(widthBp),
5293
+ columnRatios: normalized.length <= 1 ? [] : normalized
5294
+ };
5295
+ }
5296
+ const remainingRatio = TABLE_WIDTH_BASIS_POINTS - normalized[deleteIndex];
5297
+ const nextWidthBp = clampResponsiveTableWidthBp(
5298
+ clampResponsiveTableWidthBp(widthBp) * remainingRatio / TABLE_WIDTH_BASIS_POINTS
5299
+ );
5300
+ return {
5301
+ // Deletion is the inverse operation: remaining columns keep their rendered
5302
+ // widths while the table gives the removed column's space back.
5303
+ widthBp: Math.abs(nextWidthBp - DEFAULT_RESPONSIVE_TABLE_WIDTH_BP) <= 1 ? DEFAULT_RESPONSIVE_TABLE_WIDTH_BP : nextWidthBp,
5304
+ columnRatios: deleteResponsiveColumnRatio(normalized, deleteIndex)
5305
+ };
5306
+ }
5307
+ var TABLE_WIDTH_BASIS_POINTS, DEFAULT_RESPONSIVE_TABLE_WIDTH_BP, MAX_RESPONSIVE_TABLE_WIDTH_BP;
5308
+ var init_table_width_model = __esm({
5309
+ "src/components/UEditor/table-width-model.ts"() {
5310
+ "use strict";
5311
+ TABLE_WIDTH_BASIS_POINTS = 1e4;
5312
+ DEFAULT_RESPONSIVE_TABLE_WIDTH_BP = TABLE_WIDTH_BASIS_POINTS;
5313
+ MAX_RESPONSIVE_TABLE_WIDTH_BP = 1e5;
5314
+ }
5315
+ });
5316
+
5151
5317
  // src/components/UEditor/clipboard-tables.ts
5152
5318
  function getClipboardData(dataTransfer, type) {
5153
5319
  try {
@@ -5764,13 +5930,34 @@ function createNormalizedRowContent(row, columnCount, fillerCellAttrs) {
5764
5930
  }
5765
5931
  return content;
5766
5932
  }
5767
- function createTableContent(rows, minColumnCount = 1, fillerCellAttrs) {
5933
+ function createTableContent(rows, minColumnCount = 1, fillerCellAttrs, layout) {
5768
5934
  const tableRows = rows.filter((row) => row.cells.length > 0);
5769
5935
  if (tableRows.length === 0) return null;
5770
5936
  const { positionedRows, columnCount } = normalizeTableRows(tableRows);
5771
5937
  if (columnCount < minColumnCount) return null;
5938
+ const inferredColumnWeights = Array.from({ length: columnCount }, () => 100);
5939
+ positionedRows.forEach((row) => {
5940
+ row.cells.forEach(({ cell, colspan, startColumn }) => {
5941
+ const width = colspan === 1 ? cell.attrs?.colwidth?.[0] : null;
5942
+ if (typeof width === "number" && Number.isFinite(width) && width > 0) {
5943
+ inferredColumnWeights[startColumn] = width;
5944
+ }
5945
+ });
5946
+ });
5947
+ const columnRatios = normalizeColumnRatios(
5948
+ layout?.columnRatios?.length === columnCount ? layout.columnRatios : inferredColumnWeights,
5949
+ columnCount
5950
+ );
5951
+ const widthBp = clampResponsiveTableWidthBp(layout?.widthBp, DEFAULT_RESPONSIVE_TABLE_WIDTH_BP);
5952
+ const offsetBp = resolveResponsiveTableOffsetBp(widthBp, null, layout?.offsetBp);
5772
5953
  return {
5773
5954
  type: "table",
5955
+ attrs: {
5956
+ widthMode: "responsive",
5957
+ widthBp,
5958
+ offsetBp,
5959
+ columnRatios
5960
+ },
5774
5961
  content: positionedRows.map((row) => ({
5775
5962
  type: "tableRow",
5776
5963
  ...row.attrs ? { attrs: row.attrs } : {},
@@ -5791,9 +5978,22 @@ function getClipboardTableContent(dataTransfer) {
5791
5978
  if (tables.length !== 1 || hasMeaningfulContentOutsideTable(sourceBody)) return null;
5792
5979
  const table = tables[0];
5793
5980
  if (!(table instanceof HTMLTableElement)) return null;
5794
- return createTableContent(getHtmlTableRows(table, styleMap), 1, {
5795
- backgroundColor: DEFAULT_HTML_TABLE_CELL_BACKGROUND_COLOR
5796
- });
5981
+ const storedWidthValue = table.getAttribute("data-table-width-bp");
5982
+ const storedOffsetValue = table.getAttribute("data-table-offset-bp");
5983
+ const storedWidthBp = Number(storedWidthValue);
5984
+ const storedOffsetBp = Number(storedOffsetValue);
5985
+ const widthBp = storedWidthValue !== null && Number.isFinite(storedWidthBp) && storedWidthBp > 0 ? storedWidthBp : parsePercentageToBasisPoints(table.getAttribute("data-table-width") ?? table.style.width) ?? DEFAULT_RESPONSIVE_TABLE_WIDTH_BP;
5986
+ const offsetBp = storedOffsetValue !== null && Number.isFinite(storedOffsetBp) && storedOffsetBp >= 0 ? storedOffsetBp : parsePercentageToBasisPoints(table.getAttribute("data-table-offset") ?? table.style.marginLeft) ?? 0;
5987
+ return createTableContent(
5988
+ getHtmlTableRows(table, styleMap),
5989
+ 1,
5990
+ { backgroundColor: DEFAULT_HTML_TABLE_CELL_BACKGROUND_COLOR },
5991
+ {
5992
+ widthBp,
5993
+ offsetBp,
5994
+ columnRatios: parseColumnRatios(table.getAttribute("data-table-column-ratios"))
5995
+ }
5996
+ );
5797
5997
  }
5798
5998
  function parseClipboardTsvRows(text) {
5799
5999
  const rows = [];
@@ -5860,6 +6060,7 @@ var DEFAULT_HTML_TABLE_CELL_BACKGROUND_COLOR, DEFAULT_HTML_TABLE_TEXT_COLOR, BOR
5860
6060
  var init_clipboard_tables = __esm({
5861
6061
  "src/components/UEditor/clipboard-tables.ts"() {
5862
6062
  "use strict";
6063
+ init_table_width_model();
5863
6064
  DEFAULT_HTML_TABLE_CELL_BACKGROUND_COLOR = "#ffffff";
5864
6065
  DEFAULT_HTML_TABLE_TEXT_COLOR = "#000000";
5865
6066
  BORDER_STYLES = /* @__PURE__ */ new Set([
@@ -6131,24 +6332,28 @@ function isRowResizeHotspot(cell, clientX, clientY) {
6131
6332
  }
6132
6333
  function getRelativeBoundaryMetrics(surface, table, row, cell) {
6133
6334
  const surfaceRect = surface.getBoundingClientRect();
6335
+ const originLeft = surfaceRect.left + surface.clientLeft;
6336
+ const originTop = surfaceRect.top + surface.clientTop;
6134
6337
  const tableRect = table.getBoundingClientRect();
6135
6338
  const rowRect = row.getBoundingClientRect();
6136
6339
  const cellRect = cell.getBoundingClientRect();
6137
6340
  return {
6138
- left: tableRect.left - surfaceRect.left + surface.scrollLeft,
6139
- top: tableRect.top - surfaceRect.top + surface.scrollTop,
6341
+ left: tableRect.left - originLeft + surface.scrollLeft,
6342
+ top: tableRect.top - originTop + surface.scrollTop,
6140
6343
  width: tableRect.width,
6141
6344
  height: tableRect.height,
6142
- rowBottom: rowRect.bottom - surfaceRect.top + surface.scrollTop,
6143
- columnRight: cellRect.right - surfaceRect.left + surface.scrollLeft
6345
+ rowBottom: rowRect.bottom - originTop + surface.scrollTop,
6346
+ columnRight: cellRect.right - originLeft + surface.scrollLeft
6144
6347
  };
6145
6348
  }
6146
6349
  function getRelativeCellMetrics(surface, cell) {
6147
6350
  const surfaceRect = surface.getBoundingClientRect();
6351
+ const originLeft = surfaceRect.left + surface.clientLeft;
6352
+ const originTop = surfaceRect.top + surface.clientTop;
6148
6353
  const cellRect = cell.getBoundingClientRect();
6149
6354
  return {
6150
- left: cellRect.left - surfaceRect.left + surface.scrollLeft,
6151
- top: cellRect.top - surfaceRect.top + surface.scrollTop,
6355
+ left: cellRect.left - originLeft + surface.scrollLeft,
6356
+ top: cellRect.top - originTop + surface.scrollTop,
6152
6357
  width: cellRect.width,
6153
6358
  height: cellRect.height
6154
6359
  };
@@ -6161,6 +6366,8 @@ function getRelativeSelectedCellsMetrics(surface) {
6161
6366
  return null;
6162
6367
  }
6163
6368
  const surfaceRect = surface.getBoundingClientRect();
6369
+ const originLeft = surfaceRect.left + surface.clientLeft;
6370
+ const originTop = surfaceRect.top + surface.clientTop;
6164
6371
  let left = Number.POSITIVE_INFINITY;
6165
6372
  let top = Number.POSITIVE_INFINITY;
6166
6373
  let right = Number.NEGATIVE_INFINITY;
@@ -6173,8 +6380,8 @@ function getRelativeSelectedCellsMetrics(surface) {
6173
6380
  bottom = Math.max(bottom, rect.bottom);
6174
6381
  });
6175
6382
  return {
6176
- left: left - surfaceRect.left + surface.scrollLeft,
6177
- top: top - surfaceRect.top + surface.scrollTop,
6383
+ left: left - originLeft + surface.scrollLeft,
6384
+ top: top - originTop + surface.scrollTop,
6178
6385
  width: right - left,
6179
6386
  height: bottom - top
6180
6387
  };
@@ -6217,10 +6424,14 @@ function findTableNodeInfoFromState(state, anchorPos) {
6217
6424
  function applyTableAlignment(editor, tableAlign, anchorPos) {
6218
6425
  const tableInfo = findTableNodeInfoFromState(editor.state, anchorPos);
6219
6426
  if (!tableInfo) return false;
6427
+ const responsive = normalizeTableWidthMode(tableInfo.node.attrs.widthMode) === "responsive";
6428
+ const widthBp = getResponsiveTableWidthBp(tableInfo.node);
6429
+ const offsetBp = resolveResponsiveTableOffsetBp(widthBp, tableAlign);
6220
6430
  editor.view.dispatch(
6221
6431
  editor.state.tr.setNodeMarkup(tableInfo.pos, tableInfo.node.type, {
6222
6432
  ...tableInfo.node.attrs,
6223
- textAlign: tableAlign
6433
+ textAlign: tableAlign,
6434
+ ...responsive ? { offsetBp } : null
6224
6435
  })
6225
6436
  );
6226
6437
  const domAtTable = editor.view.domAtPos(Math.min(tableInfo.pos + 1, editor.state.doc.content.size)).node;
@@ -6237,8 +6448,8 @@ function applyTableAlignment(editor, tableAlign, anchorPos) {
6237
6448
  }
6238
6449
  if (tableAlign) {
6239
6450
  tableElement.setAttribute("data-table-align", tableAlign);
6240
- tableElement.style.marginLeft = tableAlign === "center" || tableAlign === "right" ? "auto" : "0";
6241
- tableElement.style.marginRight = tableAlign === "center" ? "auto" : tableAlign === "right" ? "0" : "auto";
6451
+ tableElement.style.marginLeft = responsive ? formatBasisPointsAsPercentage(offsetBp) : tableAlign === "center" || tableAlign === "right" ? "auto" : "0";
6452
+ tableElement.style.marginRight = responsive ? "auto" : tableAlign === "center" ? "auto" : tableAlign === "right" ? "0" : "auto";
6242
6453
  } else {
6243
6454
  tableElement.removeAttribute("data-table-align");
6244
6455
  tableElement.style.removeProperty("margin-left");
@@ -6251,6 +6462,7 @@ var init_table_align_utils = __esm({
6251
6462
  "src/components/UEditor/table-align-utils.ts"() {
6252
6463
  "use strict";
6253
6464
  init_table_dom_utils();
6465
+ init_table_width_model();
6254
6466
  }
6255
6467
  });
6256
6468
 
@@ -6499,7 +6711,24 @@ function duplicateTableColumnAt(editor, columnIndex, cellPos) {
6499
6711
  cells.splice(sourceCell.index + 1, 0, createCellCopyForColumnDuplicate(sourceCell.node));
6500
6712
  return rowInfo.node.type.create(rowInfo.node.attrs, cells);
6501
6713
  });
6502
- return tableNode.type.create(tableNode.attrs, rows);
6714
+ const responsiveLayout = normalizeTableWidthMode(tableNode.attrs.widthMode) === "responsive" ? insertResponsiveColumnLayout(
6715
+ getResponsiveTableWidthBp(tableNode),
6716
+ getTableColumnRatios(tableNode),
6717
+ columnIndex + 1,
6718
+ columnIndex
6719
+ ) : null;
6720
+ const tableAttrs = responsiveLayout ? {
6721
+ ...tableNode.attrs,
6722
+ widthMode: "responsive",
6723
+ widthBp: responsiveLayout.widthBp,
6724
+ offsetBp: resolveResponsiveTableOffsetBp(
6725
+ responsiveLayout.widthBp,
6726
+ tableNode.attrs.textAlign,
6727
+ tableNode.attrs.offsetBp
6728
+ ),
6729
+ columnRatios: responsiveLayout.columnRatios
6730
+ } : tableNode.attrs;
6731
+ return tableNode.type.create(tableAttrs, rows);
6503
6732
  });
6504
6733
  }
6505
6734
  function clearTableColumnAt(editor, columnIndex, cellPos) {
@@ -6543,6 +6772,7 @@ var init_table_cell_commands = __esm({
6543
6772
  import_state9 = require("@tiptap/pm/state");
6544
6773
  import_tables4 = require("@tiptap/pm/tables");
6545
6774
  init_table_dom_utils();
6775
+ init_table_width_model();
6546
6776
  }
6547
6777
  });
6548
6778
 
@@ -8870,6 +9100,17 @@ function normalizePreviewRowHeight(row) {
8870
9100
  function normalizePreviewTable(table) {
8871
9101
  const widths = resolveColumnWidths(table);
8872
9102
  if (widths.length === 0) return;
9103
+ const storedMode = table.getAttribute("data-table-width-mode");
9104
+ const responsive = storedMode === "responsive" || storedMode === "full" || parsePercentageToBasisPoints(table.style.width) !== null;
9105
+ const storedRatios = parseColumnRatios(table.getAttribute("data-table-column-ratios"));
9106
+ const columnRatios = normalizeColumnRatios(
9107
+ storedRatios?.length === widths.length ? storedRatios : widths,
9108
+ widths.length
9109
+ );
9110
+ const widthBp = responsive ? Number(table.getAttribute("data-table-width-bp")) || parsePercentageToBasisPoints(table.getAttribute("data-table-width") ?? table.style.width) || TABLE_WIDTH_BASIS_POINTS : TABLE_WIDTH_BASIS_POINTS;
9111
+ const safeWidthBp = clampResponsiveTableWidthBp(widthBp);
9112
+ const offsetBp = responsive ? Number(table.getAttribute("data-table-offset-bp")) || parsePercentageToBasisPoints(table.getAttribute("data-table-offset") ?? table.style.marginLeft) || 0 : 0;
9113
+ const safeOffsetBp = resolveResponsiveTableOffsetBp(safeWidthBp, null, offsetBp);
8873
9114
  let colgroup = table.querySelector("colgroup");
8874
9115
  if (!colgroup) {
8875
9116
  colgroup = document.createElement("colgroup");
@@ -8878,6 +9119,7 @@ function normalizePreviewTable(table) {
8878
9119
  while (colgroup.children.length < widths.length) {
8879
9120
  colgroup.appendChild(document.createElement("col"));
8880
9121
  }
9122
+ const tableWidth = widths.reduce((sum, width) => sum + width, 0);
8881
9123
  Array.from(colgroup.children).forEach((child, index) => {
8882
9124
  if (child.tagName.toLowerCase() !== "col") return;
8883
9125
  const col = child;
@@ -8885,23 +9127,31 @@ function normalizePreviewTable(table) {
8885
9127
  child.remove();
8886
9128
  return;
8887
9129
  }
8888
- col.style.width = `${widths[index]}px`;
8889
- col.style.minWidth = `${widths[index]}px`;
9130
+ col.style.width = responsive ? formatBasisPointsAsPercentage(columnRatios[index]) : `${widths[index]}px`;
9131
+ col.style.minWidth = responsive ? "" : `${widths[index]}px`;
8890
9132
  col.setAttribute("width", String(widths[index]));
8891
9133
  });
8892
- const tableWidth = widths.reduce((sum, width) => sum + width, 0);
8893
- setStyleProperty(table, "width", `${tableWidth}px`);
8894
- setStyleProperty(table, "min-width", `${tableWidth}px`);
9134
+ setStyleProperty(table, "width", responsive ? formatBasisPointsAsPercentage(safeWidthBp) : `${tableWidth}px`);
9135
+ setStyleProperty(table, "min-width", responsive ? `${widths.length * TIPTAP_TABLE_MIN_COLUMN_WIDTH}px` : `${tableWidth}px`);
8895
9136
  setStyleProperty(table, "table-layout", "fixed");
9137
+ if (responsive) {
9138
+ table.setAttribute("data-table-width-mode", "responsive");
9139
+ table.setAttribute("data-table-width-bp", String(safeWidthBp));
9140
+ table.setAttribute("data-table-offset-bp", String(safeOffsetBp));
9141
+ table.setAttribute("data-table-column-ratios", columnRatios.join(","));
9142
+ setStyleProperty(table, "margin-left", formatBasisPointsAsPercentage(safeOffsetBp));
9143
+ setStyleProperty(table, "margin-right", "auto");
9144
+ }
8896
9145
  Array.from(table.rows).forEach((row) => {
8897
9146
  let columnIndex = 0;
8898
9147
  normalizePreviewRowHeight(row);
8899
9148
  Array.from(row.cells).forEach((cell) => {
8900
9149
  const colspan = getCellColspan(cell);
8901
9150
  const cellWidth = widths.slice(columnIndex, columnIndex + colspan).reduce((sum, width) => sum + width, 0);
9151
+ const cellRatio = columnRatios.slice(columnIndex, columnIndex + colspan).reduce((sum, ratio) => sum + ratio, 0);
8902
9152
  if (cellWidth > 0) {
8903
- cell.style.width = `${cellWidth}px`;
8904
- cell.style.minWidth = `${cellWidth}px`;
9153
+ cell.style.width = responsive ? formatBasisPointsAsPercentage(cellRatio) : `${cellWidth}px`;
9154
+ cell.style.minWidth = responsive ? "" : `${cellWidth}px`;
8905
9155
  }
8906
9156
  columnIndex += colspan;
8907
9157
  });
@@ -8919,6 +9169,7 @@ var init_preview_html = __esm({
8919
9169
  "src/components/UEditor/preview-html.ts"() {
8920
9170
  "use strict";
8921
9171
  init_table_dom_utils();
9172
+ init_table_width_model();
8922
9173
  DEFAULT_TABLE_COLUMN_WIDTH2 = 100;
8923
9174
  TIPTAP_TABLE_MIN_COLUMN_WIDTH = 25;
8924
9175
  }
@@ -36857,20 +37108,17 @@ var import_state6 = require("@tiptap/pm/state");
36857
37108
  var import_view2 = require("@tiptap/pm/view");
36858
37109
  var import_tables2 = require("@tiptap/pm/tables");
36859
37110
  init_table_dom_utils();
37111
+ init_table_width_model();
36860
37112
  var DEFAULT_TABLE_COLUMN_WIDTH = 100;
36861
37113
  var MIN_RESIZED_TABLE_COLUMN_WIDTH = 25;
36862
37114
  function getColumnResizeMinWidth(configuredMinWidth) {
36863
37115
  const normalizedMinWidth = Number.isFinite(configuredMinWidth) && configuredMinWidth > 0 ? Math.round(configuredMinWidth) : MIN_RESIZED_TABLE_COLUMN_WIDTH;
36864
37116
  return Math.max(MIN_RESIZED_TABLE_COLUMN_WIDTH, normalizedMinWidth);
36865
37117
  }
36866
- function setColumnStyle(column, width) {
36867
- if (width == null) {
36868
- column.style.width = `${DEFAULT_TABLE_COLUMN_WIDTH}px`;
36869
- column.style.minWidth = `${DEFAULT_TABLE_COLUMN_WIDTH}px`;
36870
- return;
36871
- }
36872
- column.style.width = `${Math.max(width, MIN_RESIZED_TABLE_COLUMN_WIDTH)}px`;
36873
- column.style.minWidth = "";
37118
+ function setColumnStyle(column, width, ratio, explicit, responsive) {
37119
+ column.style.width = responsive ? formatBasisPointsAsPercentage(ratio) : `${width}px`;
37120
+ column.style.minWidth = responsive || explicit ? "" : `${width}px`;
37121
+ column.setAttribute("width", String(width));
36874
37122
  }
36875
37123
  function isTableColumnElement(node) {
36876
37124
  return isCrossRealmElement(node) && String(node.tagName).toUpperCase() === "COL";
@@ -36879,6 +37127,7 @@ function updateDynamicColumns(node, colgroup, table, ownerDocument, overrideCol,
36879
37127
  let totalWidth = 0;
36880
37128
  let nextDOM = colgroup.firstChild;
36881
37129
  const row = node.firstChild;
37130
+ const columns = [];
36882
37131
  if (row) {
36883
37132
  for (let rowCellIndex = 0, col = 0; rowCellIndex < row.childCount; rowCellIndex += 1) {
36884
37133
  const { colspan, colwidth } = row.child(rowCellIndex).attrs;
@@ -36887,7 +37136,11 @@ function updateDynamicColumns(node, colgroup, table, ownerDocument, overrideCol,
36887
37136
  const width = rawWidth ? Math.max(rawWidth, MIN_RESIZED_TABLE_COLUMN_WIDTH) : null;
36888
37137
  totalWidth += width ?? DEFAULT_TABLE_COLUMN_WIDTH;
36889
37138
  const colElement = isTableColumnElement(nextDOM) ? nextDOM : colgroup.appendChild(ownerDocument.createElement("col"));
36890
- setColumnStyle(colElement, width);
37139
+ columns.push({
37140
+ element: colElement,
37141
+ explicit: width !== null,
37142
+ width: width ?? DEFAULT_TABLE_COLUMN_WIDTH
37143
+ });
36891
37144
  nextDOM = colElement.nextSibling;
36892
37145
  }
36893
37146
  }
@@ -36897,13 +37150,39 @@ function updateDynamicColumns(node, colgroup, table, ownerDocument, overrideCol,
36897
37150
  nextDOM.parentNode?.removeChild(nextDOM);
36898
37151
  nextDOM = after;
36899
37152
  }
36900
- const hasUserWidth = typeof node.attrs.style === "string" && /\bwidth\s*:/i.test(node.attrs.style);
36901
- if (!hasUserWidth) {
37153
+ const responsive = normalizeTableWidthMode(node.attrs.widthMode) === "responsive";
37154
+ const columnRatios = getTableColumnRatios(node);
37155
+ columns.forEach(({ element, explicit, width }, index) => {
37156
+ setColumnStyle(element, width, columnRatios[index] ?? 1, explicit, responsive);
37157
+ });
37158
+ if (responsive) {
37159
+ const widthBp = getResponsiveTableWidthBp(node);
37160
+ const offsetBp = getResponsiveTableOffsetBp(node);
37161
+ table.setAttribute("data-table-width-mode", "responsive");
37162
+ table.setAttribute("data-table-width", formatBasisPointsAsPercentage(widthBp));
37163
+ table.setAttribute("data-table-width-bp", String(widthBp));
37164
+ table.setAttribute("data-table-offset", formatBasisPointsAsPercentage(offsetBp));
37165
+ table.setAttribute("data-table-offset-bp", String(offsetBp));
37166
+ table.setAttribute("data-table-column-ratios", columnRatios.join(","));
37167
+ table.style.width = formatBasisPointsAsPercentage(widthBp);
37168
+ table.style.marginLeft = formatBasisPointsAsPercentage(offsetBp);
37169
+ table.style.marginRight = "auto";
37170
+ table.style.minWidth = `${Math.max(1, colgroup.childElementCount) * MIN_RESIZED_TABLE_COLUMN_WIDTH}px`;
37171
+ } else {
37172
+ table.removeAttribute("data-table-width-mode");
37173
+ table.removeAttribute("data-table-width");
37174
+ table.removeAttribute("data-table-width-bp");
37175
+ table.removeAttribute("data-table-offset");
37176
+ table.removeAttribute("data-table-offset-bp");
37177
+ table.removeAttribute("data-table-column-ratios");
36902
37178
  table.style.width = `${totalWidth}px`;
36903
37179
  table.style.minWidth = "";
36904
- } else {
36905
- table.style.minWidth = `${totalWidth}px`;
37180
+ const tableAlign = node.attrs.textAlign;
37181
+ table.style.marginLeft = tableAlign === "center" || tableAlign === "right" ? "auto" : "0px";
37182
+ table.style.marginRight = tableAlign === "center" ? "auto" : tableAlign === "right" ? "0px" : "auto";
36906
37183
  }
37184
+ if (node.attrs.textAlign) table.setAttribute("data-table-align", String(node.attrs.textAlign));
37185
+ else table.removeAttribute("data-table-align");
36907
37186
  }
36908
37187
  var UEditorTableView = class {
36909
37188
  constructor(node, _defaultColumnWidth, maybeView) {
@@ -36939,7 +37218,40 @@ var UEditorTableView = class {
36939
37218
  };
36940
37219
  function getDraggedWidth(dragging, event) {
36941
37220
  const offset = event.clientX - dragging.startX;
36942
- return Math.max(dragging.minWidth, Math.round(dragging.startWidth + offset));
37221
+ const maximum = dragging.neighborStartWidth === void 0 ? Number.POSITIVE_INFINITY : dragging.startWidth + dragging.neighborStartWidth - dragging.minWidth;
37222
+ return Math.min(maximum, Math.max(dragging.minWidth, Math.round(dragging.startWidth + offset)));
37223
+ }
37224
+ function normalizeColumnWidthsToTotal(values, total, minimum) {
37225
+ const safeTotal = Math.max(values.length * minimum, Math.round(total));
37226
+ const weights = values.map((value) => Number.isFinite(value) && value > 0 ? value : DEFAULT_TABLE_COLUMN_WIDTH);
37227
+ const weightSum = weights.reduce((sum, value) => sum + value, 0);
37228
+ const widths = weights.map((value) => Math.max(minimum, Math.round(value / weightSum * safeTotal)));
37229
+ let difference = safeTotal - widths.reduce((sum, value) => sum + value, 0);
37230
+ while (difference !== 0) {
37231
+ let changed = false;
37232
+ for (let index = widths.length - 1; index >= 0 && difference !== 0; index -= 1) {
37233
+ if (difference < 0 && widths[index] <= minimum) continue;
37234
+ widths[index] += difference > 0 ? 1 : -1;
37235
+ difference += difference > 0 ? -1 : 1;
37236
+ changed = true;
37237
+ }
37238
+ if (!changed) break;
37239
+ }
37240
+ return widths;
37241
+ }
37242
+ function getResizeColumnInfo(state, cell) {
37243
+ const $cell = state.doc.resolve(cell);
37244
+ const table = $cell.node(-1);
37245
+ const map = import_tables2.TableMap.get(table);
37246
+ const start = $cell.start(-1);
37247
+ const nodeAfter = $cell.nodeAfter;
37248
+ if (!nodeAfter) return null;
37249
+ return {
37250
+ col: map.colCount($cell.pos - start) + nodeAfter.attrs.colspan - 1,
37251
+ map,
37252
+ start,
37253
+ table
37254
+ };
36943
37255
  }
36944
37256
  function getCurrentColWidth(view, cellPos, { colspan, colwidth }) {
36945
37257
  const width = colwidth?.[colwidth.length - 1];
@@ -37008,6 +37320,12 @@ function handleMouseMove(view, event, handleWidth, lastColumnResizable) {
37008
37320
  if (event.clientX - left <= handleWidth) cell = edgeCell(view, event, "left", handleWidth);
37009
37321
  else if (right - event.clientX <= handleWidth) cell = edgeCell(view, event, "right", handleWidth);
37010
37322
  }
37323
+ if (cell !== -1) {
37324
+ const info = getResizeColumnInfo(view.state, cell);
37325
+ if (info && normalizeTableWidthMode(info.table.attrs.widthMode) === "responsive" && info.col === info.map.width - 1) {
37326
+ cell = -1;
37327
+ }
37328
+ }
37011
37329
  if (cell === pluginState.activeHandle) {
37012
37330
  clearHandleHoverTimer();
37013
37331
  return;
@@ -37054,33 +37372,47 @@ function handleMouseLeave(view) {
37054
37372
  updateHandle(view, -1);
37055
37373
  }
37056
37374
  }
37057
- function updateColumnWidth(view, cell, width) {
37058
- const $cell = view.state.doc.resolve(cell);
37059
- const table = $cell.node(-1);
37060
- const map = import_tables2.TableMap.get(table);
37061
- const start = $cell.start(-1);
37062
- const nodeAfter = $cell.nodeAfter;
37063
- if (!nodeAfter) return;
37064
- const col = map.colCount($cell.pos - start) + nodeAfter.attrs.colspan - 1;
37375
+ function updateColumnWidths(view, cell, widthsByColumn, columnRatios) {
37376
+ const info = getResizeColumnInfo(view.state, cell);
37377
+ if (!info) return;
37378
+ const { map, start, table } = info;
37065
37379
  const tr = view.state.tr;
37066
- for (let row = 0; row < map.height; row += 1) {
37067
- const mapIndex = row * map.width + col;
37068
- if (row && map.map[mapIndex] === map.map[mapIndex - map.width]) continue;
37069
- const pos = map.map[mapIndex];
37380
+ const seenCellPositions = /* @__PURE__ */ new Set();
37381
+ for (const pos of map.map) {
37382
+ if (seenCellPositions.has(pos)) continue;
37383
+ seenCellPositions.add(pos);
37070
37384
  const cellNode = table.nodeAt(pos);
37071
37385
  if (!cellNode) continue;
37072
37386
  const attrs = cellNode.attrs;
37073
- const index = attrs.colspan === 1 ? 0 : col - map.colCount(pos);
37074
- if (attrs.colwidth?.[index] === width) continue;
37075
37387
  const colwidth = attrs.colwidth ? attrs.colwidth.slice() : Array.from({ length: attrs.colspan }, () => 0);
37076
- colwidth[index] = width;
37388
+ const cellStartColumn = map.colCount(pos);
37389
+ let changed = false;
37390
+ for (let index = 0; index < attrs.colspan; index += 1) {
37391
+ const width = widthsByColumn.get(cellStartColumn + index);
37392
+ if (width === void 0 || colwidth[index] === width) continue;
37393
+ colwidth[index] = width;
37394
+ changed = true;
37395
+ }
37396
+ if (!changed) continue;
37077
37397
  tr.setNodeMarkup(start + pos, null, {
37078
37398
  ...attrs,
37079
37399
  colwidth
37080
37400
  });
37081
37401
  }
37402
+ if (columnRatios) {
37403
+ tr.setNodeMarkup(start - 1, void 0, {
37404
+ ...table.attrs,
37405
+ widthMode: "responsive",
37406
+ columnRatios: normalizeColumnRatios(columnRatios, map.width)
37407
+ });
37408
+ }
37082
37409
  if (tr.docChanged) view.dispatch(tr);
37083
37410
  }
37411
+ function updateColumnWidth(view, cell, width) {
37412
+ const info = getResizeColumnInfo(view.state, cell);
37413
+ if (!info) return;
37414
+ updateColumnWidths(view, cell, /* @__PURE__ */ new Map([[info.col, width]]));
37415
+ }
37084
37416
  function getActiveDragging(state) {
37085
37417
  const dragging = import_tables2.columnResizingPluginKey.getState(state)?.dragging;
37086
37418
  return dragging ? dragging : null;
@@ -37132,16 +37464,36 @@ function handleMouseDown(view, event, cellMinWidth) {
37132
37464
  if (!pluginState || pluginState.activeHandle === -1 || pluginState.dragging) return false;
37133
37465
  const cell = view.state.doc.nodeAt(pluginState.activeHandle);
37134
37466
  if (!cell) return false;
37467
+ const resizeInfo = getResizeColumnInfo(view.state, pluginState.activeHandle);
37468
+ if (!resizeInfo) return false;
37135
37469
  const attrs = cell.attrs;
37136
- const width = getCurrentColWidth(view, pluginState.activeHandle, {
37470
+ let width = getCurrentColWidth(view, pluginState.activeHandle, {
37137
37471
  colspan: attrs.colspan ?? 1,
37138
37472
  colwidth: attrs.colwidth
37139
37473
  });
37140
37474
  const minWidth = getColumnResizeMinWidth(cellMinWidth);
37475
+ let responsiveColumnWidths;
37476
+ let neighborStartWidth;
37477
+ if (normalizeTableWidthMode(resizeInfo.table.attrs.widthMode) === "responsive") {
37478
+ if (resizeInfo.col >= resizeInfo.map.width - 1) return false;
37479
+ const storedRatios = getTableColumnRatios(resizeInfo.table);
37480
+ const legacyWidths = getLegacyTableColumnWeights(resizeInfo.table, DEFAULT_TABLE_COLUMN_WIDTH);
37481
+ const storedTotal = legacyWidths.reduce((sum, value) => sum + value, 0);
37482
+ const tableElement = getTableElementAtCell(view, pluginState.activeHandle);
37483
+ const renderedWidth = tableElement?.getBoundingClientRect().width || storedTotal;
37484
+ responsiveColumnWidths = normalizeColumnWidthsToTotal(storedRatios, renderedWidth, minWidth);
37485
+ width = responsiveColumnWidths[resizeInfo.col];
37486
+ neighborStartWidth = responsiveColumnWidths[resizeInfo.col + 1];
37487
+ }
37141
37488
  const dragging = {
37142
37489
  startX: event.clientX,
37143
37490
  startWidth: width,
37144
- minWidth
37491
+ minWidth,
37492
+ ...responsiveColumnWidths ? {
37493
+ columnIndex: resizeInfo.col,
37494
+ responsiveColumnWidths,
37495
+ neighborStartWidth
37496
+ } : null
37145
37497
  };
37146
37498
  view.dispatch(view.state.tr.setMeta(import_tables2.columnResizingPluginKey, { setDragging: dragging }));
37147
37499
  function finish(nextEvent) {
@@ -37150,7 +37502,20 @@ function handleMouseDown(view, event, cellMinWidth) {
37150
37502
  const activeDragging = getActiveDragging(view.state);
37151
37503
  const activeHandle = import_tables2.columnResizingPluginKey.getState(view.state)?.activeHandle ?? -1;
37152
37504
  if (activeDragging && activeHandle > -1) {
37153
- updateColumnWidth(view, activeHandle, getDraggedWidth(activeDragging, nextEvent));
37505
+ const nextWidth = getDraggedWidth(activeDragging, nextEvent);
37506
+ if (activeDragging.responsiveColumnWidths && activeDragging.columnIndex !== void 0 && activeDragging.neighborStartWidth !== void 0) {
37507
+ const nextColumnWidths = activeDragging.responsiveColumnWidths.slice();
37508
+ nextColumnWidths[activeDragging.columnIndex] = nextWidth;
37509
+ nextColumnWidths[activeDragging.columnIndex + 1] = activeDragging.startWidth + activeDragging.neighborStartWidth - nextWidth;
37510
+ updateColumnWidths(
37511
+ view,
37512
+ activeHandle,
37513
+ new Map(nextColumnWidths.map((columnWidth, index) => [index, columnWidth])),
37514
+ normalizeColumnRatios(nextColumnWidths, nextColumnWidths.length)
37515
+ );
37516
+ } else {
37517
+ updateColumnWidth(view, activeHandle, nextWidth);
37518
+ }
37154
37519
  view.dispatch(view.state.tr.setMeta(import_tables2.columnResizingPluginKey, { setDragging: null }));
37155
37520
  }
37156
37521
  hideColumnResizeGhost(view);
@@ -37180,6 +37545,9 @@ function handleDecorations(state, cell, ownerDocument) {
37180
37545
  const nodeAfter = $cell.nodeAfter;
37181
37546
  if (!nodeAfter) return import_view2.DecorationSet.empty;
37182
37547
  const col = map.colCount($cell.pos - start) + nodeAfter.attrs.colspan - 1;
37548
+ if (normalizeTableWidthMode(table.attrs.widthMode) === "responsive" && col === map.width - 1) {
37549
+ return import_view2.DecorationSet.empty;
37550
+ }
37183
37551
  for (let row = 0; row < map.height; row += 1) {
37184
37552
  const index = col + row * map.width;
37185
37553
  if ((col === map.width - 1 || map.map[index] !== map.map[index + 1]) && (row === 0 || map.map[index] !== map.map[index - map.width])) {
@@ -37253,6 +37621,7 @@ function dynamicColumnResizing({
37253
37621
  // src/components/UEditor/table-align.ts
37254
37622
  init_table_align_utils();
37255
37623
  init_table_dom_utils();
37624
+ init_table_width_model();
37256
37625
  function normalizeTableAlign(value) {
37257
37626
  if (value === "left" || value === "center" || value === "right") {
37258
37627
  return value;
@@ -37269,7 +37638,7 @@ function parseTableAlign(element) {
37269
37638
  if ((marginLeft === "0px" || marginLeft === "0") && marginRight === "auto") return "left";
37270
37639
  return null;
37271
37640
  }
37272
- function renderTableAlignStyle(tableAlign) {
37641
+ function renderFixedTableAlignStyle(tableAlign) {
37273
37642
  switch (tableAlign) {
37274
37643
  case "center":
37275
37644
  return "table-layout: fixed; margin-left: auto; margin-right: auto;";
@@ -37281,28 +37650,61 @@ function renderTableAlignStyle(tableAlign) {
37281
37650
  return "";
37282
37651
  }
37283
37652
  }
37284
- function createUEditorColGroup(node) {
37285
- const columns = [];
37286
- let totalWidth = 0;
37287
- const firstRow = node.firstChild;
37288
- if (firstRow) {
37289
- for (let cellIndex = 0; cellIndex < firstRow.childCount; cellIndex += 1) {
37290
- const cell = firstRow.child(cellIndex);
37291
- const colspan = Math.max(1, Number(cell.attrs.colspan) || 1);
37292
- const colwidth = Array.isArray(cell.attrs.colwidth) ? cell.attrs.colwidth : [];
37293
- for (let spanIndex = 0; spanIndex < colspan; spanIndex += 1) {
37294
- const storedWidth = Number(colwidth[spanIndex]);
37295
- const width = Number.isFinite(storedWidth) && storedWidth > 0 ? Math.max(MIN_RESIZED_TABLE_COLUMN_WIDTH, Math.round(storedWidth)) : DEFAULT_TABLE_COLUMN_WIDTH;
37296
- totalWidth += width;
37297
- columns.push(["col", { style: `width: ${width}px; min-width: ${width}px;`, width: String(width) }]);
37298
- }
37299
- }
37653
+ function parseTableWidthMode(element) {
37654
+ const storedMode = element.getAttribute("data-table-width-mode");
37655
+ if (storedMode === "responsive" || storedMode === "full" || parsePercentageToBasisPoints(element.style.width) !== null) {
37656
+ return "responsive";
37300
37657
  }
37658
+ return "fixed";
37659
+ }
37660
+ function createUEditorColGroup(node, widthMode) {
37661
+ const columnWidths = getLegacyTableColumnWeights(node, DEFAULT_TABLE_COLUMN_WIDTH).map((width) => Math.max(MIN_RESIZED_TABLE_COLUMN_WIDTH, Math.round(width)));
37662
+ const columnRatios = getTableColumnRatios(node);
37663
+ const totalWidth = columnWidths.reduce((sum, width) => sum + width, 0);
37664
+ const columns = columnWidths.map((width, index) => ["col", {
37665
+ style: widthMode === "responsive" ? `width: ${formatBasisPointsAsPercentage(columnRatios[index])};` : `width: ${width}px; min-width: ${width}px;`,
37666
+ width: String(width)
37667
+ }]);
37301
37668
  return {
37302
37669
  colgroup: ["colgroup", {}, ...columns],
37670
+ columnCount: columns.length,
37303
37671
  tableWidth: totalWidth > 0 ? `${totalWidth}px` : ""
37304
37672
  };
37305
37673
  }
37674
+ function runResponsiveColumnStructureCommand(state, dispatch, command, updateLayout) {
37675
+ const tableInfo = findTableNodeInfoFromState(state);
37676
+ if (!tableInfo || normalizeTableWidthMode(tableInfo.node.attrs.widthMode) !== "responsive") {
37677
+ return command(state, dispatch);
37678
+ }
37679
+ const rect = (0, import_tables3.selectedRect)(state);
37680
+ const nextLayout = updateLayout({
37681
+ widthBp: getResponsiveTableWidthBp(tableInfo.node),
37682
+ columnRatios: getTableColumnRatios(tableInfo.node)
37683
+ }, rect);
37684
+ return command(state, dispatch ? (transaction) => {
37685
+ const nextTable = transaction.doc.nodeAt(tableInfo.pos);
37686
+ if (nextTable?.type.name === "table" && nextLayout.columnRatios.length > 0) {
37687
+ const widthBp = clampResponsiveTableWidthBp(nextLayout.widthBp);
37688
+ const tableAlign = normalizeTableAlign(nextTable.attrs.textAlign);
37689
+ const offsetBp = resolveResponsiveTableOffsetBp(
37690
+ widthBp,
37691
+ tableAlign,
37692
+ getResponsiveTableOffsetBp(tableInfo.node)
37693
+ );
37694
+ transaction.setNodeMarkup(tableInfo.pos, void 0, {
37695
+ ...nextTable.attrs,
37696
+ widthMode: "responsive",
37697
+ widthBp,
37698
+ offsetBp,
37699
+ columnRatios: normalizeColumnRatios(
37700
+ nextLayout.columnRatios,
37701
+ getLogicalTableColumnCount(nextTable)
37702
+ )
37703
+ });
37704
+ }
37705
+ dispatch(transaction);
37706
+ } : void 0);
37707
+ }
37306
37708
  var UEditorTable = import_extension_table.Table.extend({
37307
37709
  addGlobalAttributes() {
37308
37710
  return [
@@ -37320,10 +37722,64 @@ var UEditorTable = import_extension_table.Table.extend({
37320
37722
  const tableAlign = normalizeTableAlign(attributes.textAlign);
37321
37723
  if (!tableAlign) return {};
37322
37724
  return {
37323
- "data-table-align": tableAlign,
37324
- style: renderTableAlignStyle(tableAlign)
37725
+ "data-table-align": tableAlign
37325
37726
  };
37326
37727
  }
37728
+ },
37729
+ widthMode: {
37730
+ default: "fixed",
37731
+ parseHTML: (element) => {
37732
+ if (!(element instanceof HTMLElement)) return "fixed";
37733
+ return parseTableWidthMode(element);
37734
+ },
37735
+ renderHTML: (attributes) => {
37736
+ if (normalizeTableWidthMode(attributes.widthMode) !== "responsive") return {};
37737
+ return {
37738
+ "data-table-width-mode": "responsive"
37739
+ };
37740
+ }
37741
+ },
37742
+ widthBp: {
37743
+ default: null,
37744
+ parseHTML: (element) => {
37745
+ if (!(element instanceof HTMLElement) || parseTableWidthMode(element) !== "responsive") return null;
37746
+ const stored = Number(element.getAttribute("data-table-width-bp"));
37747
+ if (Number.isFinite(stored) && stored > 0) return clampResponsiveTableWidthBp(stored);
37748
+ return parsePercentageToBasisPoints(element.getAttribute("data-table-width") ?? element.style.width) ?? DEFAULT_RESPONSIVE_TABLE_WIDTH_BP;
37749
+ },
37750
+ renderHTML: () => ({})
37751
+ },
37752
+ offsetBp: {
37753
+ default: null,
37754
+ parseHTML: (element) => {
37755
+ if (!(element instanceof HTMLElement) || parseTableWidthMode(element) !== "responsive") return null;
37756
+ const storedValue = element.getAttribute("data-table-offset-bp");
37757
+ const stored = Number(storedValue);
37758
+ if (storedValue !== null && Number.isFinite(stored) && stored >= 0) return Math.round(stored);
37759
+ const explicitOffset = parsePercentageToBasisPoints(
37760
+ element.getAttribute("data-table-offset") ?? element.style.marginLeft
37761
+ );
37762
+ if (explicitOffset !== null) return explicitOffset;
37763
+ const widthBp = parsePercentageToBasisPoints(
37764
+ element.getAttribute("data-table-width") ?? element.style.width
37765
+ ) ?? DEFAULT_RESPONSIVE_TABLE_WIDTH_BP;
37766
+ const tableAlign = parseTableAlign(element);
37767
+ return resolveResponsiveTableOffsetBp(widthBp, tableAlign);
37768
+ },
37769
+ renderHTML: () => ({})
37770
+ },
37771
+ columnRatios: {
37772
+ default: null,
37773
+ parseHTML: (element) => {
37774
+ if (!(element instanceof HTMLElement)) return null;
37775
+ const storedRatios = parseColumnRatios(
37776
+ element.getAttribute("data-table-column-ratios") ?? element.getAttribute("data-column-ratios")
37777
+ );
37778
+ if (storedRatios) return storedRatios;
37779
+ const columnPercentages = Array.from(element.querySelectorAll("colgroup > col")).map((column) => parsePercentageToBasisPoints(column.style.width));
37780
+ return columnPercentages.length > 0 && columnPercentages.every((ratio) => ratio !== null) ? normalizeColumnRatios(columnPercentages, columnPercentages.length) : null;
37781
+ },
37782
+ renderHTML: () => ({})
37327
37783
  }
37328
37784
  }
37329
37785
  }
@@ -37332,13 +37788,86 @@ var UEditorTable = import_extension_table.Table.extend({
37332
37788
  addCommands() {
37333
37789
  return {
37334
37790
  ...this.parent?.(),
37791
+ insertTable: ({ rows = 3, cols = 3, withHeaderRow = true } = {}) => ({ tr, dispatch, editor }) => {
37792
+ const types = (0, import_tables3.tableNodeTypes)(editor.schema);
37793
+ const rowCount = Math.max(1, Math.floor(rows));
37794
+ const columnCount = Math.max(1, Math.floor(cols));
37795
+ const createCells = (type) => Array.from({ length: columnCount }, () => type.createAndFill()).filter((cell) => cell !== null);
37796
+ const bodyCells = createCells(types.cell);
37797
+ const headerCells = withHeaderRow ? createCells(types.header_cell) : bodyCells;
37798
+ const tableRows = Array.from({ length: rowCount }, (_, index) => types.row.createChecked(
37799
+ null,
37800
+ withHeaderRow && index === 0 ? headerCells : bodyCells
37801
+ ));
37802
+ const table = types.table.createChecked(
37803
+ {
37804
+ widthMode: "responsive",
37805
+ widthBp: DEFAULT_RESPONSIVE_TABLE_WIDTH_BP,
37806
+ offsetBp: 0,
37807
+ columnRatios: normalizeColumnRatios(null, columnCount)
37808
+ },
37809
+ tableRows
37810
+ );
37811
+ if (dispatch) {
37812
+ const offset = tr.selection.from + 1;
37813
+ tr.replaceSelectionWith(table).scrollIntoView().setSelection(import_state7.TextSelection.near(tr.doc.resolve(offset)));
37814
+ }
37815
+ return true;
37816
+ },
37817
+ addColumnBefore: () => ({ state, dispatch }) => {
37818
+ return runResponsiveColumnStructureCommand(
37819
+ state,
37820
+ dispatch,
37821
+ import_tables3.addColumnBefore,
37822
+ (layout, rect) => insertResponsiveColumnLayout(
37823
+ layout.widthBp,
37824
+ layout.columnRatios,
37825
+ rect.left,
37826
+ rect.left
37827
+ )
37828
+ );
37829
+ },
37830
+ addColumnAfter: () => ({ state, dispatch }) => {
37831
+ return runResponsiveColumnStructureCommand(
37832
+ state,
37833
+ dispatch,
37834
+ import_tables3.addColumnAfter,
37835
+ (layout, rect) => insertResponsiveColumnLayout(
37836
+ layout.widthBp,
37837
+ layout.columnRatios,
37838
+ rect.right,
37839
+ rect.right - 1
37840
+ )
37841
+ );
37842
+ },
37843
+ deleteColumn: () => ({ state, dispatch }) => {
37844
+ return runResponsiveColumnStructureCommand(
37845
+ state,
37846
+ dispatch,
37847
+ import_tables3.deleteColumn,
37848
+ (layout, rect) => {
37849
+ let nextLayout = layout;
37850
+ for (let index = rect.right - 1; index >= rect.left; index -= 1) {
37851
+ nextLayout = deleteResponsiveColumnLayout(
37852
+ nextLayout.widthBp,
37853
+ nextLayout.columnRatios,
37854
+ index
37855
+ );
37856
+ }
37857
+ return nextLayout;
37858
+ }
37859
+ );
37860
+ },
37335
37861
  setTableAlign: (tableAlign) => ({ state, dispatch }) => {
37336
37862
  const tableInfo = findTableNodeInfoFromState(state);
37337
37863
  if (!tableInfo) return false;
37864
+ const widthBp = getResponsiveTableWidthBp(tableInfo.node);
37865
+ const offsetBp = resolveResponsiveTableOffsetBp(widthBp, tableAlign);
37338
37866
  dispatch?.(
37339
37867
  state.tr.setNodeMarkup(tableInfo.pos, tableInfo.node.type, {
37340
37868
  ...tableInfo.node.attrs,
37341
- textAlign: tableAlign
37869
+ textAlign: tableAlign,
37870
+ ...normalizeTableWidthMode(tableInfo.node.attrs.widthMode) === "responsive" ? { offsetBp } : null
37342
37871
  })
37343
37872
  );
37344
37873
  return true;
@@ -37357,11 +37886,31 @@ var UEditorTable = import_extension_table.Table.extend({
37357
37886
  };
37358
37887
  },
37359
37888
  renderHTML({ node, HTMLAttributes }) {
37360
- const { colgroup, tableWidth } = createUEditorColGroup(node);
37889
+ const widthMode = normalizeTableWidthMode(node.attrs.widthMode);
37890
+ const { colgroup, columnCount, tableWidth } = createUEditorColGroup(node, widthMode);
37891
+ const tableAlign = normalizeTableAlign(node.attrs.textAlign);
37892
+ const widthBp = getResponsiveTableWidthBp(node);
37893
+ const offsetBp = getResponsiveTableOffsetBp(node);
37894
+ const columnRatios = getTableColumnRatios(node);
37895
+ const tableStyle = widthMode === "responsive" ? [
37896
+ `width: ${formatBasisPointsAsPercentage(widthBp)}`,
37897
+ `margin-left: ${formatBasisPointsAsPercentage(offsetBp)}`,
37898
+ "margin-right: auto",
37899
+ `min-width: ${Math.max(1, columnCount) * MIN_RESIZED_TABLE_COLUMN_WIDTH}px`,
37900
+ "table-layout: fixed"
37901
+ ].join("; ") + ";" : tableWidth ? `width: ${tableWidth}; ${renderFixedTableAlignStyle(tableAlign)}` : `table-layout: fixed; ${renderFixedTableAlignStyle(tableAlign)}`;
37361
37902
  const table = [
37362
37903
  "table",
37363
37904
  (0, import_core17.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes, {
37364
- style: tableWidth ? `width: ${tableWidth};` : "table-layout: fixed;"
37905
+ ...widthMode === "responsive" ? {
37906
+ "data-table-width-mode": "responsive",
37907
+ "data-table-width": formatBasisPointsAsPercentage(widthBp),
37908
+ "data-table-width-bp": String(widthBp),
37909
+ "data-table-offset": formatBasisPointsAsPercentage(offsetBp),
37910
+ "data-table-offset-bp": String(offsetBp),
37911
+ "data-table-column-ratios": columnRatios.join(",")
37912
+ } : null,
37913
+ style: tableStyle
37365
37914
  }),
37366
37915
  colgroup,
37367
37916
  ["tbody", 0]
@@ -37414,6 +37963,31 @@ var UEditorTable = import_extension_table.Table.extend({
37414
37963
  (0, import_tables3.tableEditing)({
37415
37964
  allowTableNodeSelection: this.options.allowTableNodeSelection
37416
37965
  }),
37966
+ new import_state7.Plugin({
37967
+ key: new import_state7.PluginKey("responsiveTableLayoutNormalizer"),
37968
+ appendTransaction(transactions, _oldState, newState) {
37969
+ if (!transactions.some((transaction) => transaction.docChanged)) return null;
37970
+ const tableInfo = findTableNodeInfoFromState(newState);
37971
+ const node = tableInfo?.node;
37972
+ if (!tableInfo || !node || normalizeTableWidthMode(node.attrs.widthMode) !== "responsive") return null;
37973
+ const columnCount = getLogicalTableColumnCount(node);
37974
+ const columnRatios = getTableColumnRatios(node);
37975
+ const widthBp = getResponsiveTableWidthBp(node);
37976
+ const offsetBp = getResponsiveTableOffsetBp(node);
37977
+ const storedRatios = parseColumnRatios(node.attrs.columnRatios);
37978
+ const ratiosMatch = storedRatios?.length === columnCount && storedRatios.every((ratio, index) => Math.round(ratio) === columnRatios[index]);
37979
+ if (ratiosMatch && node.attrs.widthBp === widthBp && node.attrs.offsetBp === offsetBp && node.attrs.widthMode === "responsive") {
37980
+ return null;
37981
+ }
37982
+ return newState.tr.setNodeMarkup(tableInfo.pos, void 0, {
37983
+ ...node.attrs,
37984
+ widthMode: "responsive",
37985
+ widthBp,
37986
+ offsetBp,
37987
+ columnRatios
37988
+ });
37989
+ }
37990
+ }),
37417
37991
  new import_state7.Plugin({
37418
37992
  appendTransaction(_transactions, _oldState, newState) {
37419
37993
  const { doc, schema } = newState;
@@ -43921,7 +44495,7 @@ var Selection = class {
43921
44495
  found.
43922
44496
  */
43923
44497
  static findFrom($pos, dir, textOnly = false) {
43924
- let inner = $pos.parent.inlineContent ? new TextSelection5($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly);
44498
+ let inner = $pos.parent.inlineContent ? new TextSelection6($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly);
43925
44499
  if (inner)
43926
44500
  return inner;
43927
44501
  for (let depth = $pos.depth - 1; depth >= 0; depth--) {
@@ -43990,7 +44564,7 @@ var Selection = class {
43990
44564
  returns the bookmark for that.
43991
44565
  */
43992
44566
  getBookmark() {
43993
- return TextSelection5.between(this.$anchor, this.$head).getBookmark();
44567
+ return TextSelection6.between(this.$anchor, this.$head).getBookmark();
43994
44568
  }
43995
44569
  };
43996
44570
  Selection.prototype.visible = true;
@@ -44010,7 +44584,7 @@ function checkTextSelection($pos) {
44010
44584
  console["warn"]("TextSelection endpoint not pointing into a node with inline content (" + $pos.parent.type.name + ")");
44011
44585
  }
44012
44586
  }
44013
- var TextSelection5 = class _TextSelection extends Selection {
44587
+ var TextSelection6 = class _TextSelection extends Selection {
44014
44588
  /**
44015
44589
  Construct a text selection between the given points.
44016
44590
  */
@@ -44096,7 +44670,7 @@ var TextSelection5 = class _TextSelection extends Selection {
44096
44670
  return new _TextSelection($anchor, $head);
44097
44671
  }
44098
44672
  };
44099
- Selection.jsonID("text", TextSelection5);
44673
+ Selection.jsonID("text", TextSelection6);
44100
44674
  var TextBookmark = class _TextBookmark {
44101
44675
  constructor(anchor, head) {
44102
44676
  this.anchor = anchor;
@@ -44106,7 +44680,7 @@ var TextBookmark = class _TextBookmark {
44106
44680
  return new _TextBookmark(mapping.map(this.anchor), mapping.map(this.head));
44107
44681
  }
44108
44682
  resolve(doc) {
44109
- return TextSelection5.between(doc.resolve(this.anchor), doc.resolve(this.head));
44683
+ return TextSelection6.between(doc.resolve(this.anchor), doc.resolve(this.head));
44110
44684
  }
44111
44685
  };
44112
44686
  var NodeSelection2 = class _NodeSelection extends Selection {
@@ -44225,7 +44799,7 @@ var AllBookmark = {
44225
44799
  };
44226
44800
  function findSelectionIn(doc, node, pos, index, dir, text = false) {
44227
44801
  if (node.inlineContent)
44228
- return TextSelection5.create(doc, pos);
44802
+ return TextSelection6.create(doc, pos);
44229
44803
  for (let i = index - (dir > 0 ? 0 : 1); dir > 0 ? i < node.childCount : i >= 0; i += dir) {
44230
44804
  let child = node.child(i);
44231
44805
  if (!child.isAtom) {
@@ -44725,7 +45299,7 @@ function freshColWidth(attrs) {
44725
45299
  for (let i = 0; i < attrs.colspan; i++) result.push(0);
44726
45300
  return result;
44727
45301
  }
44728
- function tableNodeTypes2(schema) {
45302
+ function tableNodeTypes3(schema) {
44729
45303
  let result = schema.cached.tableNodeTypes;
44730
45304
  if (!result) {
44731
45305
  result = schema.cached.tableNodeTypes = {};
@@ -44817,7 +45391,7 @@ var CellSelection2 = class CellSelection3 extends Selection {
44817
45391
  else if (tableChanged && this.isColSelection()) return CellSelection3.colSelection($anchorCell, $headCell);
44818
45392
  else return new CellSelection3($anchorCell, $headCell);
44819
45393
  }
44820
- return TextSelection5.between($anchorCell, $headCell);
45394
+ return TextSelection6.between($anchorCell, $headCell);
44821
45395
  }
44822
45396
  content() {
44823
45397
  const table = this.$anchorCell.node(-1);
@@ -45242,7 +45816,7 @@ function moveTableRow$1(table, indexesOrigin, indexesTarget, direction) {
45242
45816
  rows = moveRowInArrayOfRows(rows, indexesOrigin, indexesTarget, direction);
45243
45817
  return convertArrayOfRowsToTableNode(table, rows);
45244
45818
  }
45245
- function selectedRect4(state) {
45819
+ function selectedRect5(state) {
45246
45820
  const sel = state.selection;
45247
45821
  const $pos = selectionCell(state);
45248
45822
  const table = $pos.node(-1);
@@ -45259,8 +45833,8 @@ function deprecated_toggleHeader(type) {
45259
45833
  return function(state, dispatch) {
45260
45834
  if (!isInTable2(state)) return false;
45261
45835
  if (dispatch) {
45262
- const types = tableNodeTypes2(state.schema);
45263
- const rect = selectedRect4(state), tr = state.tr;
45836
+ const types = tableNodeTypes3(state.schema);
45837
+ const rect = selectedRect5(state), tr = state.tr;
45264
45838
  const cells = rect.map.cellsInRect(type == "column" ? {
45265
45839
  left: rect.left,
45266
45840
  top: 0,
@@ -45299,8 +45873,8 @@ function toggleHeader(type, options) {
45299
45873
  return function(state, dispatch) {
45300
45874
  if (!isInTable2(state)) return false;
45301
45875
  if (dispatch) {
45302
- const types = tableNodeTypes2(state.schema);
45303
- const rect = selectedRect4(state), tr = state.tr;
45876
+ const types = tableNodeTypes3(state.schema);
45877
+ const rect = selectedRect5(state), tr = state.tr;
45304
45878
  const isHeaderRowEnabled = isHeaderEnabledByType("row", rect, types);
45305
45879
  const isHeaderColumnEnabled = isHeaderEnabledByType("column", rect, types);
45306
45880
  const selectionStartsAt = (type === "column" ? isHeaderRowEnabled : type === "row" ? isHeaderColumnEnabled : false) ? 1 : 0;
@@ -45334,7 +45908,7 @@ function deleteCellSelection(state, dispatch) {
45334
45908
  if (!(sel instanceof CellSelection2)) return false;
45335
45909
  if (dispatch) {
45336
45910
  const tr = state.tr;
45337
- const baseContent = tableNodeTypes2(state.schema).cell.createAndFill().content;
45911
+ const baseContent = tableNodeTypes3(state.schema).cell.createAndFill().content;
45338
45912
  sel.forEachCell((cell, pos) => {
45339
45913
  if (!cell.content.eq(baseContent)) tr.replace(tr.mapping.map(pos + 1), tr.mapping.map(pos + cell.nodeSize - 1), new Slice(baseContent, 0, 0));
45340
45914
  });
@@ -45432,7 +46006,7 @@ function shiftArrow(axis, dir) {
45432
46006
  };
45433
46007
  }
45434
46008
  function atEndOfCell(view, axis, dir) {
45435
- if (!(view.state.selection instanceof TextSelection5)) return null;
46009
+ if (!(view.state.selection instanceof TextSelection6)) return null;
45436
46010
  const { $head } = view.state.selection;
45437
46011
  for (let d = $head.depth - 1; d >= 0; d--) {
45438
46012
  const parent = $head.node(d);
@@ -45459,6 +46033,7 @@ init_table_dom_utils();
45459
46033
 
45460
46034
  // src/components/UEditor/table-layout-model.ts
45461
46035
  init_table_dom_utils();
46036
+ init_table_width_model();
45462
46037
  var FALLBACK_TABLE_ROW_HEIGHT = DEFAULT_TABLE_ROW_HEIGHT;
45463
46038
  var FALLBACK_TABLE_COLUMN_WIDTH = 160;
45464
46039
  function isTableCellElement(element) {
@@ -45565,7 +46140,7 @@ function buildLogicalColumnMetrics({
45565
46140
  if (relativeCellPos == null) continue;
45566
46141
  const cellMapRect = map.findCell(relativeCellPos);
45567
46142
  const cellRect = tableCell.getBoundingClientRect();
45568
- const cellStart = cellRect.width > 0 ? cellRect.left - surfaceRect.left + surface.scrollLeft : tableLeft + cellMapRect.left * fallbackWidth;
46143
+ const cellStart = cellRect.width > 0 ? cellRect.left - surfaceRect.left - surface.clientLeft + surface.scrollLeft : tableLeft + cellMapRect.left * fallbackWidth;
45569
46144
  const size = metricOrFallback(cellRect.width, fallbackWidth * Math.max(1, cellMapRect.right - cellMapRect.left));
45570
46145
  visualColumns.push({
45571
46146
  index: cellMapRect.left,
@@ -45620,7 +46195,7 @@ function buildLogicalRowMetrics({
45620
46195
  const tableCell = isTableCellElement(cellCandidate) ? cellCandidate : null;
45621
46196
  if (tableCell) {
45622
46197
  const cellRect = tableCell.getBoundingClientRect();
45623
- const start = cellRect.height > 0 ? cellRect.top - surfaceRect.top + surface.scrollTop : tableTop + cellMapRect.top * fallbackHeight;
46198
+ const start = cellRect.height > 0 ? cellRect.top - surfaceRect.top - surface.clientTop + surface.scrollTop : tableTop + cellMapRect.top * fallbackHeight;
45624
46199
  const size = metricOrFallback(cellRect.height, fallbackHeight * Math.max(1, cellMapRect.bottom - cellMapRect.top));
45625
46200
  visualRows.push({
45626
46201
  index: cellMapRect.top,
@@ -45637,7 +46212,7 @@ function buildLogicalRowMetrics({
45637
46212
  return rows.map((tableRow, index) => {
45638
46213
  const rowRect = tableRow.getBoundingClientRect();
45639
46214
  const anchorCell = tableRow.cells.item(0) ?? cornerCell;
45640
- const start = rowRect.height > 0 ? rowRect.top - surfaceRect.top + surface.scrollTop : tableTop + index * fallbackHeight;
46215
+ const start = rowRect.height > 0 ? rowRect.top - surfaceRect.top - surface.clientTop + surface.scrollTop : tableTop + index * fallbackHeight;
45641
46216
  const size = metricOrFallback(rowRect.height, fallbackHeight);
45642
46217
  return {
45643
46218
  index,
@@ -45679,6 +46254,8 @@ function buildTableControlLayout(editor, surface, cell) {
45679
46254
  }
45680
46255
  const map = TableMap4.get(tableInfo.node);
45681
46256
  const surfaceRect = surface.getBoundingClientRect();
46257
+ const surfaceOriginLeft = surfaceRect.left + surface.clientLeft;
46258
+ const surfaceOriginTop = surfaceRect.top + surface.clientTop;
45682
46259
  const tableRect = table.getBoundingClientRect();
45683
46260
  const explicitColumnWidths = Array.from(table.querySelectorAll("colgroup > col")).slice(0, map.width).map((column) => parsePixelMetric(column.style.width));
45684
46261
  const explicitTableWidth = parsePixelMetric(table.style.width) ?? (explicitColumnWidths.length === map.width && explicitColumnWidths.every((width) => width !== null) ? explicitColumnWidths.reduce((sum, width) => sum + width, 0) : null);
@@ -45687,14 +46264,14 @@ function buildTableControlLayout(editor, surface, cell) {
45687
46264
  const wrapperElement = table.closest(".tableWrapper");
45688
46265
  const wrapper = isHTMLElement(wrapperElement) ? wrapperElement : null;
45689
46266
  const wrapperRect = wrapper?.getBoundingClientRect() ?? tableRect;
45690
- const tableLeft = tableRect.left - surfaceRect.left + surface.scrollLeft;
45691
- const tableTop = tableRect.top - surfaceRect.top + surface.scrollTop;
46267
+ const tableLeft = tableRect.left - surfaceOriginLeft + surface.scrollLeft;
46268
+ const tableTop = tableRect.top - surfaceOriginTop + surface.scrollTop;
45692
46269
  const tableWidth = metricOrFallback(tableRect.width, explicitTableWidth ?? FALLBACK_TABLE_COLUMN_WIDTH * map.width);
45693
46270
  const tableHeight = metricOrFallback(tableRect.height, explicitTableHeight ?? FALLBACK_TABLE_ROW_HEIGHT * rows.length);
45694
46271
  const avgRowHeight = metricOrFallback(tableHeight / rows.length, FALLBACK_TABLE_ROW_HEIGHT);
45695
46272
  const avgColumnWidth = metricOrFallback(tableWidth / map.width, FALLBACK_TABLE_COLUMN_WIDTH);
45696
- const wrapperLeft = wrapperRect.left - surfaceRect.left + surface.scrollLeft;
45697
- const wrapperTop = wrapperRect.top - surfaceRect.top + surface.scrollTop;
46273
+ const wrapperLeft = wrapperRect.left - surfaceOriginLeft + surface.scrollLeft;
46274
+ const wrapperTop = wrapperRect.top - surfaceOriginTop + surface.scrollTop;
45698
46275
  const wrapperWidth = metricOrFallback(wrapperRect.width, tableWidth);
45699
46276
  const wrapperHeight = metricOrFallback(wrapperRect.height, tableHeight);
45700
46277
  const viewportWidth = metricOrFallback(wrapper?.clientWidth ?? wrapperRect.width, tableWidth);
@@ -45743,7 +46320,8 @@ function buildTableControlLayout(editor, surface, cell) {
45743
46320
  avgRowHeight,
45744
46321
  avgColumnWidth,
45745
46322
  rowHandles,
45746
- columnHandles
46323
+ columnHandles,
46324
+ widthMode: normalizeTableWidthMode(tableInfo.node.attrs.widthMode)
45747
46325
  };
45748
46326
  }
45749
46327
 
@@ -45776,8 +46354,8 @@ function buildTableHoverState({
45776
46354
  return DEFAULT_TABLE_HOVER_STATE;
45777
46355
  }
45778
46356
  const surfaceRect = surface.getBoundingClientRect();
45779
- const relativeX = event.clientX - surfaceRect.left + surface.scrollLeft;
45780
- const relativeY = event.clientY - surfaceRect.top + surface.scrollTop;
46357
+ const relativeX = event.clientX - surfaceRect.left - surface.clientLeft + surface.scrollLeft;
46358
+ const relativeY = event.clientY - surfaceRect.top - surface.clientTop + surface.scrollTop;
45781
46359
  const targetElement = resolveEventElement(event.target);
45782
46360
  const directRowHandle = targetElement?.closest?.("[data-row-handle-index]");
45783
46361
  const directColumnHandle = targetElement?.closest?.("[data-column-handle-index]");
@@ -46241,11 +46819,17 @@ var HANDLE_BASE_CLASS = cn(
46241
46819
  "hover:bg-primary hover:text-primary-foreground hover:shadow-md active:scale-95",
46242
46820
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
46243
46821
  );
46822
+ var EDGE_HANDLE_CLASS = cn(
46823
+ "pointer-events-auto absolute top-0 z-10 h-full w-2 touch-none cursor-col-resize bg-transparent p-0",
46824
+ "border-transparent transition-colors duration-150 hover:border-primary",
46825
+ "focus-visible:border-primary focus-visible:outline-none"
46826
+ );
46244
46827
  function TableResizeHandles({
46245
46828
  active,
46246
46829
  ctrlHint,
46247
46830
  frameRef,
46248
46831
  layout,
46832
+ onFitWidth,
46249
46833
  onStartResize,
46250
46834
  resizeBothLabel
46251
46835
  }) {
@@ -46266,6 +46850,36 @@ function TableResizeHandles({
46266
46850
  height: layout.tableHeight
46267
46851
  },
46268
46852
  children: [
46853
+ layout.widthMode === "responsive" ? /* @__PURE__ */ (0, import_jsx_runtime101.jsxs)(import_jsx_runtime101.Fragment, { children: [
46854
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
46855
+ "button",
46856
+ {
46857
+ type: "button",
46858
+ "aria-label": `${resizeBothLabel} \u2014 \u2190`,
46859
+ title: resizeBothLabel,
46860
+ "data-table-resize-handle": "left",
46861
+ className: cn(
46862
+ EDGE_HANDLE_CLASS,
46863
+ "left-0 border-l-2"
46864
+ ),
46865
+ onPointerDown: (event) => onStartResize(event, "left")
46866
+ }
46867
+ ),
46868
+ /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
46869
+ "button",
46870
+ {
46871
+ type: "button",
46872
+ "aria-label": `${resizeBothLabel} \u2014 \u2192`,
46873
+ title: resizeBothLabel,
46874
+ "data-table-resize-handle": "right",
46875
+ className: cn(
46876
+ EDGE_HANDLE_CLASS,
46877
+ "right-0 border-r-2"
46878
+ ),
46879
+ onPointerDown: (event) => onStartResize(event, "right")
46880
+ }
46881
+ )
46882
+ ] }) : null,
46269
46883
  /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(
46270
46884
  "button",
46271
46885
  {
@@ -46278,7 +46892,8 @@ function TableResizeHandles({
46278
46892
  "bottom-[-28px] right-[-30px] h-6 w-6 cursor-nwse-resize",
46279
46893
  active && "bg-primary text-primary-foreground shadow-md"
46280
46894
  ),
46281
- onPointerDown: onStartResize,
46895
+ onDoubleClick: onFitWidth,
46896
+ onPointerDown: (event) => onStartResize(event, "both"),
46282
46897
  children: /* @__PURE__ */ (0, import_jsx_runtime101.jsx)(import_lucide_react56.MoveDiagonal2, { "aria-hidden": "true", className: "h-3.5 w-3.5", strokeWidth: 2.25 })
46283
46898
  }
46284
46899
  ),
@@ -46299,6 +46914,7 @@ function TableResizeHandles({
46299
46914
 
46300
46915
  // src/components/UEditor/table-size-utils.ts
46301
46916
  init_table_dom_utils();
46917
+ init_table_width_model();
46302
46918
  var MAX_TABLE_DIMENSION = 8192;
46303
46919
  function positiveMetric(value, fallback) {
46304
46920
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
@@ -46341,7 +46957,7 @@ function getLogicalRowHeights(table, fallback) {
46341
46957
  });
46342
46958
  return heights;
46343
46959
  }
46344
- function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight) {
46960
+ function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight, containerWidth = startWidth) {
46345
46961
  const tableInfo = findTableInfo(editor, anchorPos);
46346
46962
  if (!tableInfo) return null;
46347
46963
  const tableMap = TableMap4.get(tableInfo.node);
@@ -46350,13 +46966,16 @@ function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight) {
46350
46966
  const safeHeight = Math.max(tableMap.height * MIN_TABLE_ROW_HEIGHT, Math.round(startHeight));
46351
46967
  const fallbackColumnWidth = safeWidth / tableMap.width;
46352
46968
  const fallbackRowHeight = safeHeight / tableMap.height;
46969
+ const widthMode = normalizeTableWidthMode(tableInfo.node.attrs.widthMode);
46970
+ const safeContainerWidth = Math.max(1, Math.round(containerWidth));
46971
+ const columnWeights = widthMode === "responsive" ? getTableColumnRatios(tableInfo.node) : getLogicalColumnWidths(tableInfo.node, tableMap, fallbackColumnWidth);
46353
46972
  return {
46354
46973
  anchorPos,
46355
46974
  tablePos: tableInfo.pos,
46356
46975
  startWidth: safeWidth,
46357
46976
  startHeight: safeHeight,
46358
46977
  columnWidths: normalizeWeightsToTotal(
46359
- getLogicalColumnWidths(tableInfo.node, tableMap, fallbackColumnWidth),
46978
+ columnWeights,
46360
46979
  safeWidth,
46361
46980
  MIN_RESIZED_TABLE_COLUMN_WIDTH
46362
46981
  ),
@@ -46366,7 +46985,12 @@ function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight) {
46366
46985
  MIN_TABLE_ROW_HEIGHT
46367
46986
  ),
46368
46987
  minWidth: tableMap.width * MIN_RESIZED_TABLE_COLUMN_WIDTH,
46369
- minHeight: tableMap.height * MIN_TABLE_ROW_HEIGHT
46988
+ minHeight: tableMap.height * MIN_TABLE_ROW_HEIGHT,
46989
+ containerWidth: safeContainerWidth,
46990
+ widthMode,
46991
+ widthBp: getResponsiveTableWidthBp(tableInfo.node),
46992
+ offsetBp: getResponsiveTableOffsetBp(tableInfo.node),
46993
+ columnRatios: getTableColumnRatios(tableInfo.node)
46370
46994
  };
46371
46995
  }
46372
46996
  function resolveTableResizeDimensions({
@@ -46374,12 +46998,14 @@ function resolveTableResizeDimensions({
46374
46998
  deltaY,
46375
46999
  lockAxis,
46376
47000
  preserveRatio,
47001
+ edge = "both",
46377
47002
  snapshot
46378
47003
  }) {
46379
- let width = snapshot.startWidth + deltaX;
46380
- let height = snapshot.startHeight + deltaY;
47004
+ const horizontalDelta = edge === "left" ? -deltaX : deltaX;
47005
+ let width = snapshot.startWidth + horizontalDelta;
47006
+ let height = edge === "both" ? snapshot.startHeight + deltaY : snapshot.startHeight;
46381
47007
  if (preserveRatio) {
46382
- const horizontalDrag = Math.abs(deltaX) >= Math.abs(deltaY);
47008
+ const horizontalDrag = edge !== "both" || Math.abs(deltaX) >= Math.abs(deltaY);
46383
47009
  const scale = horizontalDrag ? width / snapshot.startWidth : height / snapshot.startHeight;
46384
47010
  const minScale = Math.max(
46385
47011
  snapshot.minWidth / snapshot.startWidth,
@@ -46392,22 +47018,56 @@ function resolveTableResizeDimensions({
46392
47018
  const safeScale = Math.min(Math.max(scale, minScale), maxScale);
46393
47019
  width = snapshot.startWidth * safeScale;
46394
47020
  height = snapshot.startHeight * safeScale;
46395
- } else if (lockAxis) {
47021
+ } else if (lockAxis && edge === "both") {
46396
47022
  if (Math.abs(deltaX) >= Math.abs(deltaY)) {
46397
47023
  height = snapshot.startHeight;
46398
47024
  } else {
46399
47025
  width = snapshot.startWidth;
46400
47026
  }
46401
47027
  }
47028
+ let nextWidth = Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minWidth, Math.round(width)));
47029
+ const nextHeight = Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minHeight, Math.round(height)));
47030
+ if (snapshot.widthMode !== "responsive") {
47031
+ return { width: nextWidth, height: nextHeight };
47032
+ }
47033
+ const containerWidth = Math.max(1, snapshot.containerWidth);
47034
+ const startOffset = snapshot.offsetBp / TABLE_WIDTH_BASIS_POINTS * containerWidth;
47035
+ let nextOffset = startOffset;
47036
+ if (edge === "left") {
47037
+ const fixedRightEdge = startOffset + snapshot.startWidth;
47038
+ nextOffset = Math.min(
47039
+ fixedRightEdge - snapshot.minWidth,
47040
+ Math.max(0, startOffset + deltaX)
47041
+ );
47042
+ nextWidth = fixedRightEdge - nextOffset;
47043
+ }
47044
+ const widthBp = clampResponsiveTableWidthBp(
47045
+ nextWidth / containerWidth * TABLE_WIDTH_BASIS_POINTS
47046
+ );
47047
+ const offsetBp = resolveResponsiveTableOffsetBp(
47048
+ widthBp,
47049
+ null,
47050
+ nextOffset / containerWidth * TABLE_WIDTH_BASIS_POINTS
47051
+ );
46402
47052
  return {
46403
- width: Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minWidth, Math.round(width))),
46404
- height: Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minHeight, Math.round(height)))
47053
+ width: Math.round(widthBp / TABLE_WIDTH_BASIS_POINTS * containerWidth),
47054
+ height: nextHeight,
47055
+ widthBp,
47056
+ offsetBp,
47057
+ leftDelta: nextOffset - startOffset
46405
47058
  };
46406
47059
  }
46407
47060
  function arraysEqual(left, right) {
46408
47061
  return Array.isArray(left) && left.length === right.length && left.every((value, index) => value === right[index]);
46409
47062
  }
46410
- function applyTableSize(editor, snapshot, dimensions) {
47063
+ function getResponsiveResizeAlignment(widthBp, offsetBp) {
47064
+ const gap = Math.max(0, TABLE_WIDTH_BASIS_POINTS - widthBp);
47065
+ if (offsetBp === 0) return "left";
47066
+ if (offsetBp === gap) return "right";
47067
+ if (Math.abs(offsetBp * 2 - gap) <= 1) return "center";
47068
+ return null;
47069
+ }
47070
+ function applyTableSize(editor, snapshot, dimensions, options = {}) {
46411
47071
  const table = editor.state.doc.nodeAt(snapshot.tablePos);
46412
47072
  if (!table || table.type.name !== "table") return false;
46413
47073
  const tableMap = TableMap4.get(table);
@@ -46416,9 +47076,32 @@ function applyTableSize(editor, snapshot, dimensions) {
46416
47076
  }
46417
47077
  const resizeWidth = dimensions.width !== snapshot.startWidth;
46418
47078
  const resizeHeight = dimensions.height !== snapshot.startHeight;
46419
- if (!resizeWidth && !resizeHeight) return false;
47079
+ const widthMode = options.widthMode ?? snapshot.widthMode;
47080
+ const widthModeChanged = normalizeTableWidthMode(table.attrs.widthMode) !== widthMode || widthMode === "responsive" && table.attrs.widthMode !== "responsive";
47081
+ const widthBp = dimensions.widthBp ?? clampResponsiveTableWidthBp(
47082
+ dimensions.width / Math.max(1, snapshot.containerWidth) * TABLE_WIDTH_BASIS_POINTS
47083
+ );
47084
+ const offsetBp = resolveResponsiveTableOffsetBp(
47085
+ widthBp,
47086
+ null,
47087
+ dimensions.offsetBp ?? snapshot.offsetBp
47088
+ );
47089
+ const responsiveLayoutChanged = widthMode === "responsive" && (table.attrs.widthBp !== widthBp || table.attrs.offsetBp !== offsetBp);
47090
+ if (!resizeWidth && !resizeHeight && !widthModeChanged && !responsiveLayoutChanged) return false;
46420
47091
  const tableStart = snapshot.tablePos + 1;
46421
47092
  const transaction = editor.state.tr;
47093
+ if (widthModeChanged || responsiveLayoutChanged) {
47094
+ transaction.setNodeMarkup(snapshot.tablePos, void 0, {
47095
+ ...table.attrs,
47096
+ widthMode,
47097
+ ...widthMode === "responsive" ? {
47098
+ widthBp,
47099
+ offsetBp,
47100
+ columnRatios: normalizeColumnRatios(snapshot.columnRatios, tableMap.width),
47101
+ textAlign: getResponsiveResizeAlignment(widthBp, offsetBp)
47102
+ } : null
47103
+ });
47104
+ }
46422
47105
  if (resizeWidth) {
46423
47106
  const nextColumnWidths = normalizeWeightsToTotal(
46424
47107
  snapshot.columnWidths,
@@ -46461,6 +47144,7 @@ function applyTableSize(editor, snapshot, dimensions) {
46461
47144
  }
46462
47145
 
46463
47146
  // src/components/UEditor/table-controls.tsx
47147
+ init_table_width_model();
46464
47148
  var import_jsx_runtime102 = require("react/jsx-runtime");
46465
47149
  var TABLE_MENU_TOP_OFFSET = 10;
46466
47150
  var AXIS_HANDLE_RADIUS = 12;
@@ -46570,6 +47254,10 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
46570
47254
  if (!frame) return;
46571
47255
  frame.style.width = `${dimensions.width}px`;
46572
47256
  frame.style.height = `${dimensions.height}px`;
47257
+ const activeLayout = layoutRef.current;
47258
+ if (activeLayout) {
47259
+ frame.style.left = `${activeLayout.tableLeft + (dimensions.leftDelta ?? 0)}px`;
47260
+ }
46573
47261
  const dimensionsLabel = frame.querySelector("[data-table-resize-dimensions]");
46574
47262
  if (dimensionsLabel) {
46575
47263
  dimensionsLabel.textContent = `${dimensions.width} \xD7 ${dimensions.height}`;
@@ -46580,7 +47268,8 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
46580
47268
  if (!activeLayout) return;
46581
47269
  updateTableResizePreview({
46582
47270
  width: Math.round(activeLayout.tableWidth),
46583
- height: Math.round(activeLayout.tableHeight)
47271
+ height: Math.round(activeLayout.tableHeight),
47272
+ leftDelta: 0
46584
47273
  });
46585
47274
  }, [updateTableResizePreview]);
46586
47275
  const clearDrag = import_react77.default.useCallback(() => {
@@ -46685,6 +47374,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
46685
47374
  surface.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleCurrentLayoutRefresh);
46686
47375
  if (!editorWindow) return void 0;
46687
47376
  const unsubscribeResize = subscribeSharedGlobalEvent(editorWindow, "resize", scheduleCurrentLayoutRefresh);
47377
+ const unsubscribeWindowScroll = subscribeSharedGlobalEvent(editorWindow, "scroll", scheduleCurrentLayoutRefresh, { passive: true });
46688
47378
  editor.on("selectionUpdate", scheduleSyncFromSelection);
46689
47379
  editor.on("update", scheduleCurrentLayoutRefresh);
46690
47380
  syncFromSelection();
@@ -46700,6 +47390,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
46700
47390
  surface.removeEventListener("scroll", scheduleCurrentLayoutRefresh, scrollListenerOptions);
46701
47391
  surface.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleCurrentLayoutRefresh);
46702
47392
  unsubscribeResize();
47393
+ unsubscribeWindowScroll();
46703
47394
  editor.off("selectionUpdate", scheduleSyncFromSelection);
46704
47395
  editor.off("update", scheduleCurrentLayoutRefresh);
46705
47396
  };
@@ -46743,7 +47434,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
46743
47434
  const canExpandTable = Boolean(layout);
46744
47435
  const controlsVisible = false;
46745
47436
  const tableMenuOpen = openMenuKey === "table";
46746
- const startTableResize = import_react77.default.useCallback((event) => {
47437
+ const startTableResize = import_react77.default.useCallback((event, edge) => {
46747
47438
  if (event.button !== 0 || dragStateRef.current) return;
46748
47439
  const activeLayout = layoutRef.current;
46749
47440
  if (!activeLayout) return;
@@ -46751,7 +47442,8 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
46751
47442
  editor,
46752
47443
  activeLayout.cellPos,
46753
47444
  activeLayout.tableWidth,
46754
- activeLayout.tableHeight
47445
+ activeLayout.tableHeight,
47446
+ activeLayout.viewportWidth
46755
47447
  );
46756
47448
  if (!snapshot) return;
46757
47449
  event.preventDefault();
@@ -46773,12 +47465,38 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
46773
47465
  pointerTarget: event.currentTarget,
46774
47466
  startX: event.clientX,
46775
47467
  startY: event.clientY,
47468
+ edge,
46776
47469
  snapshot,
46777
47470
  pendingDimensions
46778
47471
  };
46779
47472
  updateTableResizePreview(pendingDimensions);
46780
- setDocumentCursor(editorDocument, "nwse-resize");
47473
+ setDocumentCursor(editorDocument, edge === "both" ? "nwse-resize" : "ew-resize");
46781
47474
  }, [editor, editorDocument, updateTableResizePreview]);
47475
+ const fitTableToEditorWidth = import_react77.default.useCallback((event) => {
47476
+ if (event.button !== 0 || dragStateRef.current) return;
47477
+ const activeLayout = layoutRef.current;
47478
+ if (!activeLayout) return;
47479
+ const snapshot = createTableSizeSnapshot(
47480
+ editor,
47481
+ activeLayout.cellPos,
47482
+ activeLayout.tableWidth,
47483
+ activeLayout.tableHeight,
47484
+ activeLayout.viewportWidth
47485
+ );
47486
+ if (!snapshot) return;
47487
+ event.preventDefault();
47488
+ event.stopPropagation();
47489
+ const didResize = applyTableSize(editor, snapshot, {
47490
+ width: Math.round(activeLayout.viewportWidth),
47491
+ height: snapshot.startHeight,
47492
+ widthBp: TABLE_WIDTH_BASIS_POINTS,
47493
+ offsetBp: 0,
47494
+ leftDelta: -(snapshot.offsetBp / TABLE_WIDTH_BASIS_POINTS * snapshot.containerWidth)
47495
+ }, { widthMode: "responsive" });
47496
+ if (didResize) {
47497
+ scheduleSyncFromSelection();
47498
+ }
47499
+ }, [editor, scheduleSyncFromSelection]);
46782
47500
  const startAddColumnDrag = import_react77.default.useCallback(() => {
46783
47501
  setOpenMenuKey(null);
46784
47502
  dragStateRef.current = { kind: "add-column", previewCols: 1 };
@@ -46893,12 +47611,30 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
46893
47611
  scheduleSyncFromSelection();
46894
47612
  }
46895
47613
  if (dragState.kind === "column" && dragState.originIndex !== dragState.targetIndex) {
47614
+ const tableInfo = findTableInfo(editor, dragState.anchorPos);
47615
+ const responsiveRatios = tableInfo && normalizeTableWidthMode(tableInfo.node.attrs.widthMode) === "responsive" ? moveResponsiveColumnRatio(
47616
+ getTableColumnRatios(tableInfo.node),
47617
+ dragState.originIndex,
47618
+ dragState.targetIndex
47619
+ ) : null;
46896
47620
  moveTableColumn({
46897
47621
  from: dragState.originIndex,
46898
47622
  to: dragState.targetIndex,
46899
47623
  pos: dragState.anchorPos,
46900
47624
  select: true
46901
- })(editor.state, editor.view.dispatch);
47625
+ })(editor.state, (transaction) => {
47626
+ if (tableInfo && responsiveRatios) {
47627
+ const nextTable = transaction.doc.nodeAt(tableInfo.pos);
47628
+ if (nextTable?.type.name === "table") {
47629
+ transaction.setNodeMarkup(tableInfo.pos, void 0, {
47630
+ ...nextTable.attrs,
47631
+ widthMode: "responsive",
47632
+ columnRatios: responsiveRatios
47633
+ });
47634
+ }
47635
+ }
47636
+ editor.view.dispatch(transaction);
47637
+ });
46902
47638
  scheduleSyncFromSelection();
46903
47639
  }
46904
47640
  if (dragState.kind === "add-row") {
@@ -46932,6 +47668,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
46932
47668
  deltaY: event.clientY - dragState.startY,
46933
47669
  lockAxis: event.ctrlKey && !event.shiftKey,
46934
47670
  preserveRatio: event.ctrlKey && event.shiftKey,
47671
+ edge: dragState.edge,
46935
47672
  snapshot: dragState.snapshot
46936
47673
  });
46937
47674
  if (tableResizePreviewFrameRef.current === null) {
@@ -46943,7 +47680,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
46943
47680
  updateTableResizePreview(currentDragState.pendingDimensions);
46944
47681
  });
46945
47682
  }
46946
- setDocumentCursor(editorDocument, "nwse-resize");
47683
+ setDocumentCursor(editorDocument, dragState.edge === "both" ? "nwse-resize" : "ew-resize");
46947
47684
  if (event.cancelable) event.preventDefault();
46948
47685
  };
46949
47686
  const finishTableResize = (event, commit) => {
@@ -46954,7 +47691,12 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
46954
47691
  tableResizePreviewFrameRef.current = null;
46955
47692
  }
46956
47693
  updateTableResizePreview(dragState.pendingDimensions);
46957
- if (commit && applyTableSize(editor, dragState.snapshot, dragState.pendingDimensions)) {
47694
+ if (commit && applyTableSize(
47695
+ editor,
47696
+ dragState.snapshot,
47697
+ dragState.pendingDimensions,
47698
+ { widthMode: dragState.snapshot.widthMode }
47699
+ )) {
46958
47700
  scheduleSyncFromSelection();
46959
47701
  }
46960
47702
  clearDrag();
@@ -47192,6 +47934,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
47192
47934
  ctrlHint: t("tableMenu.resizeCtrlHint"),
47193
47935
  frameRef: tableResizeFrameRef,
47194
47936
  layout,
47937
+ onFitWidth: fitTableToEditorWidth,
47195
47938
  onStartResize: startTableResize,
47196
47939
  resizeBothLabel: t("tableMenu.resizeBoth")
47197
47940
  }