@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/ueditor.cjs CHANGED
@@ -4343,6 +4343,172 @@ var init_url_safety = __esm({
4343
4343
  }
4344
4344
  });
4345
4345
 
4346
+ // src/components/UEditor/table-width-model.ts
4347
+ function positiveNumber(value, fallback) {
4348
+ const number = Number(value);
4349
+ return Number.isFinite(number) && number > 0 ? number : fallback;
4350
+ }
4351
+ function clampTableBasisPoints(value, fallback = TABLE_WIDTH_BASIS_POINTS, maximum = TABLE_WIDTH_BASIS_POINTS) {
4352
+ const number = Number(value);
4353
+ if (!Number.isFinite(number)) return fallback;
4354
+ return Math.min(maximum, Math.max(0, Math.round(number)));
4355
+ }
4356
+ function clampResponsiveTableWidthBp(value, fallback = DEFAULT_RESPONSIVE_TABLE_WIDTH_BP) {
4357
+ return Math.max(1, clampTableBasisPoints(value, fallback, MAX_RESPONSIVE_TABLE_WIDTH_BP));
4358
+ }
4359
+ function normalizeTableWidthMode(value) {
4360
+ return value === "responsive" || value === "full" ? "responsive" : "fixed";
4361
+ }
4362
+ function parsePercentageToBasisPoints(value, maximum = MAX_RESPONSIVE_TABLE_WIDTH_BP) {
4363
+ if (!value) return null;
4364
+ const match = value.trim().match(/^(-?\d+(?:\.\d+)?)%$/);
4365
+ if (!match) return null;
4366
+ const percentage = Number.parseFloat(match[1]);
4367
+ if (!Number.isFinite(percentage)) return null;
4368
+ return clampTableBasisPoints(percentage * 100, TABLE_WIDTH_BASIS_POINTS, maximum);
4369
+ }
4370
+ function formatBasisPointsAsPercentage(value) {
4371
+ const percentage = clampTableBasisPoints(value, 0, MAX_RESPONSIVE_TABLE_WIDTH_BP) / 100;
4372
+ return `${Number.parseFloat(percentage.toFixed(2))}%`;
4373
+ }
4374
+ function parseColumnRatios(value) {
4375
+ const parts = Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : [];
4376
+ const ratios = parts.map((part) => Number(part));
4377
+ return ratios.length > 0 && ratios.every((ratio) => Number.isFinite(ratio) && ratio > 0) ? ratios : null;
4378
+ }
4379
+ function normalizeColumnRatios(values, columnCount) {
4380
+ if (columnCount <= 0) return [];
4381
+ const source = values?.length === columnCount ? values.map((value) => positiveNumber(value, 1)) : Array.from({ length: columnCount }, () => 1);
4382
+ const sourceTotal = source.reduce((sum, value) => sum + value, 0);
4383
+ const normalized = source.map((value) => Math.max(1, Math.round(value / sourceTotal * TABLE_WIDTH_BASIS_POINTS)));
4384
+ let difference = TABLE_WIDTH_BASIS_POINTS - normalized.reduce((sum, value) => sum + value, 0);
4385
+ while (difference !== 0) {
4386
+ let changed = false;
4387
+ for (let index = normalized.length - 1; index >= 0 && difference !== 0; index -= 1) {
4388
+ if (difference < 0 && normalized[index] <= 1) continue;
4389
+ normalized[index] += difference > 0 ? 1 : -1;
4390
+ difference += difference > 0 ? -1 : 1;
4391
+ changed = true;
4392
+ }
4393
+ if (!changed) break;
4394
+ }
4395
+ return normalized;
4396
+ }
4397
+ function getLogicalTableColumnCount(table) {
4398
+ const firstRow = table.firstChild;
4399
+ if (!firstRow) return 0;
4400
+ let count = 0;
4401
+ firstRow.forEach((cell) => {
4402
+ count += Math.max(1, Number(cell.attrs.colspan) || 1);
4403
+ });
4404
+ return count;
4405
+ }
4406
+ function getLegacyTableColumnWeights(table, fallback = 100) {
4407
+ const weights = [];
4408
+ const firstRow = table.firstChild;
4409
+ if (!firstRow) return weights;
4410
+ firstRow.forEach((cell) => {
4411
+ const colspan = Math.max(1, Number(cell.attrs.colspan) || 1);
4412
+ const colwidth = Array.isArray(cell.attrs.colwidth) ? cell.attrs.colwidth : [];
4413
+ for (let index = 0; index < colspan; index += 1) {
4414
+ weights.push(positiveNumber(colwidth[index], fallback));
4415
+ }
4416
+ });
4417
+ return weights;
4418
+ }
4419
+ function getTableColumnRatios(table) {
4420
+ const columnCount = getLogicalTableColumnCount(table);
4421
+ const stored = parseColumnRatios(table.attrs.columnRatios);
4422
+ return normalizeColumnRatios(
4423
+ stored?.length === columnCount ? stored : getLegacyTableColumnWeights(table),
4424
+ columnCount
4425
+ );
4426
+ }
4427
+ function getResponsiveTableWidthBp(table) {
4428
+ return clampResponsiveTableWidthBp(table.attrs.widthBp);
4429
+ }
4430
+ function getResponsiveTableOffsetBp(table) {
4431
+ const width = getResponsiveTableWidthBp(table);
4432
+ return resolveResponsiveTableOffsetBp(width, null, table.attrs.offsetBp);
4433
+ }
4434
+ function resolveResponsiveTableOffsetBp(widthBp, tableAlign, fallbackOffsetBp = 0) {
4435
+ const availableGap = Math.max(
4436
+ 0,
4437
+ TABLE_WIDTH_BASIS_POINTS - clampResponsiveTableWidthBp(widthBp)
4438
+ );
4439
+ if (tableAlign === "center") return Math.round(availableGap / 2);
4440
+ if (tableAlign === "right") return availableGap;
4441
+ if (tableAlign === "left") return 0;
4442
+ return Math.min(availableGap, clampTableBasisPoints(fallbackOffsetBp, 0));
4443
+ }
4444
+ function insertResponsiveColumnRatio(ratios, insertIndex, sourceIndex) {
4445
+ if (ratios.length === 0) return [TABLE_WIDTH_BASIS_POINTS];
4446
+ const safeSourceIndex = Math.max(0, Math.min(sourceIndex, ratios.length - 1));
4447
+ const next = [...ratios];
4448
+ const sourceRatio = next[safeSourceIndex];
4449
+ next.splice(Math.max(0, Math.min(insertIndex, next.length)), 0, sourceRatio);
4450
+ return normalizeColumnRatios(next, next.length);
4451
+ }
4452
+ function deleteResponsiveColumnRatio(ratios, deleteIndex) {
4453
+ if (ratios.length <= 1) return [];
4454
+ const next = ratios.filter((_, index) => index !== deleteIndex);
4455
+ return normalizeColumnRatios(next, next.length);
4456
+ }
4457
+ function moveResponsiveColumnRatio(ratios, from, to) {
4458
+ if (from === to || from < 0 || from >= ratios.length || to < 0 || to >= ratios.length) return [...ratios];
4459
+ const next = [...ratios];
4460
+ const [moved] = next.splice(from, 1);
4461
+ next.splice(to, 0, moved);
4462
+ return normalizeColumnRatios(next, next.length);
4463
+ }
4464
+ function insertResponsiveColumnLayout(widthBp, ratios, insertIndex, sourceIndex) {
4465
+ if (ratios.length === 0) {
4466
+ return {
4467
+ widthBp: clampResponsiveTableWidthBp(widthBp),
4468
+ columnRatios: [TABLE_WIDTH_BASIS_POINTS]
4469
+ };
4470
+ }
4471
+ const normalized = normalizeColumnRatios(ratios, ratios.length);
4472
+ const safeSourceIndex = Math.max(0, Math.min(sourceIndex, normalized.length - 1));
4473
+ const sourceRatio = normalized[safeSourceIndex];
4474
+ return {
4475
+ // Growing by the source column's share preserves every existing column's
4476
+ // rendered width instead of squeezing the whole table back into 100%.
4477
+ widthBp: clampResponsiveTableWidthBp(
4478
+ clampResponsiveTableWidthBp(widthBp) * (TABLE_WIDTH_BASIS_POINTS + sourceRatio) / TABLE_WIDTH_BASIS_POINTS
4479
+ ),
4480
+ columnRatios: insertResponsiveColumnRatio(normalized, insertIndex, safeSourceIndex)
4481
+ };
4482
+ }
4483
+ function deleteResponsiveColumnLayout(widthBp, ratios, deleteIndex) {
4484
+ const normalized = normalizeColumnRatios(ratios, ratios.length);
4485
+ if (normalized.length <= 1 || deleteIndex < 0 || deleteIndex >= normalized.length) {
4486
+ return {
4487
+ widthBp: clampResponsiveTableWidthBp(widthBp),
4488
+ columnRatios: normalized.length <= 1 ? [] : normalized
4489
+ };
4490
+ }
4491
+ const remainingRatio = TABLE_WIDTH_BASIS_POINTS - normalized[deleteIndex];
4492
+ const nextWidthBp = clampResponsiveTableWidthBp(
4493
+ clampResponsiveTableWidthBp(widthBp) * remainingRatio / TABLE_WIDTH_BASIS_POINTS
4494
+ );
4495
+ return {
4496
+ // Deletion is the inverse operation: remaining columns keep their rendered
4497
+ // widths while the table gives the removed column's space back.
4498
+ widthBp: Math.abs(nextWidthBp - DEFAULT_RESPONSIVE_TABLE_WIDTH_BP) <= 1 ? DEFAULT_RESPONSIVE_TABLE_WIDTH_BP : nextWidthBp,
4499
+ columnRatios: deleteResponsiveColumnRatio(normalized, deleteIndex)
4500
+ };
4501
+ }
4502
+ var TABLE_WIDTH_BASIS_POINTS, DEFAULT_RESPONSIVE_TABLE_WIDTH_BP, MAX_RESPONSIVE_TABLE_WIDTH_BP;
4503
+ var init_table_width_model = __esm({
4504
+ "src/components/UEditor/table-width-model.ts"() {
4505
+ "use strict";
4506
+ TABLE_WIDTH_BASIS_POINTS = 1e4;
4507
+ DEFAULT_RESPONSIVE_TABLE_WIDTH_BP = TABLE_WIDTH_BASIS_POINTS;
4508
+ MAX_RESPONSIVE_TABLE_WIDTH_BP = 1e5;
4509
+ }
4510
+ });
4511
+
4346
4512
  // src/components/UEditor/clipboard-tables.ts
4347
4513
  function getClipboardData(dataTransfer, type) {
4348
4514
  try {
@@ -4959,13 +5125,34 @@ function createNormalizedRowContent(row, columnCount, fillerCellAttrs) {
4959
5125
  }
4960
5126
  return content;
4961
5127
  }
4962
- function createTableContent(rows, minColumnCount = 1, fillerCellAttrs) {
5128
+ function createTableContent(rows, minColumnCount = 1, fillerCellAttrs, layout) {
4963
5129
  const tableRows = rows.filter((row) => row.cells.length > 0);
4964
5130
  if (tableRows.length === 0) return null;
4965
5131
  const { positionedRows, columnCount } = normalizeTableRows(tableRows);
4966
5132
  if (columnCount < minColumnCount) return null;
5133
+ const inferredColumnWeights = Array.from({ length: columnCount }, () => 100);
5134
+ positionedRows.forEach((row) => {
5135
+ row.cells.forEach(({ cell, colspan, startColumn }) => {
5136
+ const width = colspan === 1 ? cell.attrs?.colwidth?.[0] : null;
5137
+ if (typeof width === "number" && Number.isFinite(width) && width > 0) {
5138
+ inferredColumnWeights[startColumn] = width;
5139
+ }
5140
+ });
5141
+ });
5142
+ const columnRatios = normalizeColumnRatios(
5143
+ layout?.columnRatios?.length === columnCount ? layout.columnRatios : inferredColumnWeights,
5144
+ columnCount
5145
+ );
5146
+ const widthBp = clampResponsiveTableWidthBp(layout?.widthBp, DEFAULT_RESPONSIVE_TABLE_WIDTH_BP);
5147
+ const offsetBp = resolveResponsiveTableOffsetBp(widthBp, null, layout?.offsetBp);
4967
5148
  return {
4968
5149
  type: "table",
5150
+ attrs: {
5151
+ widthMode: "responsive",
5152
+ widthBp,
5153
+ offsetBp,
5154
+ columnRatios
5155
+ },
4969
5156
  content: positionedRows.map((row) => ({
4970
5157
  type: "tableRow",
4971
5158
  ...row.attrs ? { attrs: row.attrs } : {},
@@ -4986,9 +5173,22 @@ function getClipboardTableContent(dataTransfer) {
4986
5173
  if (tables.length !== 1 || hasMeaningfulContentOutsideTable(sourceBody)) return null;
4987
5174
  const table = tables[0];
4988
5175
  if (!(table instanceof HTMLTableElement)) return null;
4989
- return createTableContent(getHtmlTableRows(table, styleMap), 1, {
4990
- backgroundColor: DEFAULT_HTML_TABLE_CELL_BACKGROUND_COLOR
4991
- });
5176
+ const storedWidthValue = table.getAttribute("data-table-width-bp");
5177
+ const storedOffsetValue = table.getAttribute("data-table-offset-bp");
5178
+ const storedWidthBp = Number(storedWidthValue);
5179
+ const storedOffsetBp = Number(storedOffsetValue);
5180
+ const widthBp = storedWidthValue !== null && Number.isFinite(storedWidthBp) && storedWidthBp > 0 ? storedWidthBp : parsePercentageToBasisPoints(table.getAttribute("data-table-width") ?? table.style.width) ?? DEFAULT_RESPONSIVE_TABLE_WIDTH_BP;
5181
+ const offsetBp = storedOffsetValue !== null && Number.isFinite(storedOffsetBp) && storedOffsetBp >= 0 ? storedOffsetBp : parsePercentageToBasisPoints(table.getAttribute("data-table-offset") ?? table.style.marginLeft) ?? 0;
5182
+ return createTableContent(
5183
+ getHtmlTableRows(table, styleMap),
5184
+ 1,
5185
+ { backgroundColor: DEFAULT_HTML_TABLE_CELL_BACKGROUND_COLOR },
5186
+ {
5187
+ widthBp,
5188
+ offsetBp,
5189
+ columnRatios: parseColumnRatios(table.getAttribute("data-table-column-ratios"))
5190
+ }
5191
+ );
4992
5192
  }
4993
5193
  function parseClipboardTsvRows(text) {
4994
5194
  const rows = [];
@@ -5055,6 +5255,7 @@ var DEFAULT_HTML_TABLE_CELL_BACKGROUND_COLOR, DEFAULT_HTML_TABLE_TEXT_COLOR, BOR
5055
5255
  var init_clipboard_tables = __esm({
5056
5256
  "src/components/UEditor/clipboard-tables.ts"() {
5057
5257
  "use strict";
5258
+ init_table_width_model();
5058
5259
  DEFAULT_HTML_TABLE_CELL_BACKGROUND_COLOR = "#ffffff";
5059
5260
  DEFAULT_HTML_TABLE_TEXT_COLOR = "#000000";
5060
5261
  BORDER_STYLES = /* @__PURE__ */ new Set([
@@ -5326,24 +5527,28 @@ function isRowResizeHotspot(cell, clientX, clientY) {
5326
5527
  }
5327
5528
  function getRelativeBoundaryMetrics(surface, table, row, cell) {
5328
5529
  const surfaceRect = surface.getBoundingClientRect();
5530
+ const originLeft = surfaceRect.left + surface.clientLeft;
5531
+ const originTop = surfaceRect.top + surface.clientTop;
5329
5532
  const tableRect = table.getBoundingClientRect();
5330
5533
  const rowRect = row.getBoundingClientRect();
5331
5534
  const cellRect = cell.getBoundingClientRect();
5332
5535
  return {
5333
- left: tableRect.left - surfaceRect.left + surface.scrollLeft,
5334
- top: tableRect.top - surfaceRect.top + surface.scrollTop,
5536
+ left: tableRect.left - originLeft + surface.scrollLeft,
5537
+ top: tableRect.top - originTop + surface.scrollTop,
5335
5538
  width: tableRect.width,
5336
5539
  height: tableRect.height,
5337
- rowBottom: rowRect.bottom - surfaceRect.top + surface.scrollTop,
5338
- columnRight: cellRect.right - surfaceRect.left + surface.scrollLeft
5540
+ rowBottom: rowRect.bottom - originTop + surface.scrollTop,
5541
+ columnRight: cellRect.right - originLeft + surface.scrollLeft
5339
5542
  };
5340
5543
  }
5341
5544
  function getRelativeCellMetrics(surface, cell) {
5342
5545
  const surfaceRect = surface.getBoundingClientRect();
5546
+ const originLeft = surfaceRect.left + surface.clientLeft;
5547
+ const originTop = surfaceRect.top + surface.clientTop;
5343
5548
  const cellRect = cell.getBoundingClientRect();
5344
5549
  return {
5345
- left: cellRect.left - surfaceRect.left + surface.scrollLeft,
5346
- top: cellRect.top - surfaceRect.top + surface.scrollTop,
5550
+ left: cellRect.left - originLeft + surface.scrollLeft,
5551
+ top: cellRect.top - originTop + surface.scrollTop,
5347
5552
  width: cellRect.width,
5348
5553
  height: cellRect.height
5349
5554
  };
@@ -5356,6 +5561,8 @@ function getRelativeSelectedCellsMetrics(surface) {
5356
5561
  return null;
5357
5562
  }
5358
5563
  const surfaceRect = surface.getBoundingClientRect();
5564
+ const originLeft = surfaceRect.left + surface.clientLeft;
5565
+ const originTop = surfaceRect.top + surface.clientTop;
5359
5566
  let left = Number.POSITIVE_INFINITY;
5360
5567
  let top = Number.POSITIVE_INFINITY;
5361
5568
  let right = Number.NEGATIVE_INFINITY;
@@ -5368,8 +5575,8 @@ function getRelativeSelectedCellsMetrics(surface) {
5368
5575
  bottom = Math.max(bottom, rect.bottom);
5369
5576
  });
5370
5577
  return {
5371
- left: left - surfaceRect.left + surface.scrollLeft,
5372
- top: top - surfaceRect.top + surface.scrollTop,
5578
+ left: left - originLeft + surface.scrollLeft,
5579
+ top: top - originTop + surface.scrollTop,
5373
5580
  width: right - left,
5374
5581
  height: bottom - top
5375
5582
  };
@@ -5412,10 +5619,14 @@ function findTableNodeInfoFromState(state, anchorPos) {
5412
5619
  function applyTableAlignment(editor, tableAlign, anchorPos) {
5413
5620
  const tableInfo = findTableNodeInfoFromState(editor.state, anchorPos);
5414
5621
  if (!tableInfo) return false;
5622
+ const responsive = normalizeTableWidthMode(tableInfo.node.attrs.widthMode) === "responsive";
5623
+ const widthBp = getResponsiveTableWidthBp(tableInfo.node);
5624
+ const offsetBp = resolveResponsiveTableOffsetBp(widthBp, tableAlign);
5415
5625
  editor.view.dispatch(
5416
5626
  editor.state.tr.setNodeMarkup(tableInfo.pos, tableInfo.node.type, {
5417
5627
  ...tableInfo.node.attrs,
5418
- textAlign: tableAlign
5628
+ textAlign: tableAlign,
5629
+ ...responsive ? { offsetBp } : null
5419
5630
  })
5420
5631
  );
5421
5632
  const domAtTable = editor.view.domAtPos(Math.min(tableInfo.pos + 1, editor.state.doc.content.size)).node;
@@ -5432,8 +5643,8 @@ function applyTableAlignment(editor, tableAlign, anchorPos) {
5432
5643
  }
5433
5644
  if (tableAlign) {
5434
5645
  tableElement.setAttribute("data-table-align", tableAlign);
5435
- tableElement.style.marginLeft = tableAlign === "center" || tableAlign === "right" ? "auto" : "0";
5436
- tableElement.style.marginRight = tableAlign === "center" ? "auto" : tableAlign === "right" ? "0" : "auto";
5646
+ tableElement.style.marginLeft = responsive ? formatBasisPointsAsPercentage(offsetBp) : tableAlign === "center" || tableAlign === "right" ? "auto" : "0";
5647
+ tableElement.style.marginRight = responsive ? "auto" : tableAlign === "center" ? "auto" : tableAlign === "right" ? "0" : "auto";
5437
5648
  } else {
5438
5649
  tableElement.removeAttribute("data-table-align");
5439
5650
  tableElement.style.removeProperty("margin-left");
@@ -5446,6 +5657,7 @@ var init_table_align_utils = __esm({
5446
5657
  "src/components/UEditor/table-align-utils.ts"() {
5447
5658
  "use strict";
5448
5659
  init_table_dom_utils();
5660
+ init_table_width_model();
5449
5661
  }
5450
5662
  });
5451
5663
 
@@ -5694,7 +5906,24 @@ function duplicateTableColumnAt(editor, columnIndex, cellPos) {
5694
5906
  cells.splice(sourceCell.index + 1, 0, createCellCopyForColumnDuplicate(sourceCell.node));
5695
5907
  return rowInfo.node.type.create(rowInfo.node.attrs, cells);
5696
5908
  });
5697
- return tableNode.type.create(tableNode.attrs, rows);
5909
+ const responsiveLayout = normalizeTableWidthMode(tableNode.attrs.widthMode) === "responsive" ? insertResponsiveColumnLayout(
5910
+ getResponsiveTableWidthBp(tableNode),
5911
+ getTableColumnRatios(tableNode),
5912
+ columnIndex + 1,
5913
+ columnIndex
5914
+ ) : null;
5915
+ const tableAttrs = responsiveLayout ? {
5916
+ ...tableNode.attrs,
5917
+ widthMode: "responsive",
5918
+ widthBp: responsiveLayout.widthBp,
5919
+ offsetBp: resolveResponsiveTableOffsetBp(
5920
+ responsiveLayout.widthBp,
5921
+ tableNode.attrs.textAlign,
5922
+ tableNode.attrs.offsetBp
5923
+ ),
5924
+ columnRatios: responsiveLayout.columnRatios
5925
+ } : tableNode.attrs;
5926
+ return tableNode.type.create(tableAttrs, rows);
5698
5927
  });
5699
5928
  }
5700
5929
  function clearTableColumnAt(editor, columnIndex, cellPos) {
@@ -5738,6 +5967,7 @@ var init_table_cell_commands = __esm({
5738
5967
  import_state9 = require("@tiptap/pm/state");
5739
5968
  import_tables4 = require("@tiptap/pm/tables");
5740
5969
  init_table_dom_utils();
5970
+ init_table_width_model();
5741
5971
  }
5742
5972
  });
5743
5973
 
@@ -8639,6 +8869,17 @@ function normalizePreviewRowHeight(row) {
8639
8869
  function normalizePreviewTable(table) {
8640
8870
  const widths = resolveColumnWidths(table);
8641
8871
  if (widths.length === 0) return;
8872
+ const storedMode = table.getAttribute("data-table-width-mode");
8873
+ const responsive = storedMode === "responsive" || storedMode === "full" || parsePercentageToBasisPoints(table.style.width) !== null;
8874
+ const storedRatios = parseColumnRatios(table.getAttribute("data-table-column-ratios"));
8875
+ const columnRatios = normalizeColumnRatios(
8876
+ storedRatios?.length === widths.length ? storedRatios : widths,
8877
+ widths.length
8878
+ );
8879
+ 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;
8880
+ const safeWidthBp = clampResponsiveTableWidthBp(widthBp);
8881
+ const offsetBp = responsive ? Number(table.getAttribute("data-table-offset-bp")) || parsePercentageToBasisPoints(table.getAttribute("data-table-offset") ?? table.style.marginLeft) || 0 : 0;
8882
+ const safeOffsetBp = resolveResponsiveTableOffsetBp(safeWidthBp, null, offsetBp);
8642
8883
  let colgroup = table.querySelector("colgroup");
8643
8884
  if (!colgroup) {
8644
8885
  colgroup = document.createElement("colgroup");
@@ -8647,6 +8888,7 @@ function normalizePreviewTable(table) {
8647
8888
  while (colgroup.children.length < widths.length) {
8648
8889
  colgroup.appendChild(document.createElement("col"));
8649
8890
  }
8891
+ const tableWidth = widths.reduce((sum, width) => sum + width, 0);
8650
8892
  Array.from(colgroup.children).forEach((child, index) => {
8651
8893
  if (child.tagName.toLowerCase() !== "col") return;
8652
8894
  const col = child;
@@ -8654,23 +8896,31 @@ function normalizePreviewTable(table) {
8654
8896
  child.remove();
8655
8897
  return;
8656
8898
  }
8657
- col.style.width = `${widths[index]}px`;
8658
- col.style.minWidth = `${widths[index]}px`;
8899
+ col.style.width = responsive ? formatBasisPointsAsPercentage(columnRatios[index]) : `${widths[index]}px`;
8900
+ col.style.minWidth = responsive ? "" : `${widths[index]}px`;
8659
8901
  col.setAttribute("width", String(widths[index]));
8660
8902
  });
8661
- const tableWidth = widths.reduce((sum, width) => sum + width, 0);
8662
- setStyleProperty(table, "width", `${tableWidth}px`);
8663
- setStyleProperty(table, "min-width", `${tableWidth}px`);
8903
+ setStyleProperty(table, "width", responsive ? formatBasisPointsAsPercentage(safeWidthBp) : `${tableWidth}px`);
8904
+ setStyleProperty(table, "min-width", responsive ? `${widths.length * TIPTAP_TABLE_MIN_COLUMN_WIDTH}px` : `${tableWidth}px`);
8664
8905
  setStyleProperty(table, "table-layout", "fixed");
8906
+ if (responsive) {
8907
+ table.setAttribute("data-table-width-mode", "responsive");
8908
+ table.setAttribute("data-table-width-bp", String(safeWidthBp));
8909
+ table.setAttribute("data-table-offset-bp", String(safeOffsetBp));
8910
+ table.setAttribute("data-table-column-ratios", columnRatios.join(","));
8911
+ setStyleProperty(table, "margin-left", formatBasisPointsAsPercentage(safeOffsetBp));
8912
+ setStyleProperty(table, "margin-right", "auto");
8913
+ }
8665
8914
  Array.from(table.rows).forEach((row) => {
8666
8915
  let columnIndex = 0;
8667
8916
  normalizePreviewRowHeight(row);
8668
8917
  Array.from(row.cells).forEach((cell) => {
8669
8918
  const colspan = getCellColspan(cell);
8670
8919
  const cellWidth = widths.slice(columnIndex, columnIndex + colspan).reduce((sum, width) => sum + width, 0);
8920
+ const cellRatio = columnRatios.slice(columnIndex, columnIndex + colspan).reduce((sum, ratio) => sum + ratio, 0);
8671
8921
  if (cellWidth > 0) {
8672
- cell.style.width = `${cellWidth}px`;
8673
- cell.style.minWidth = `${cellWidth}px`;
8922
+ cell.style.width = responsive ? formatBasisPointsAsPercentage(cellRatio) : `${cellWidth}px`;
8923
+ cell.style.minWidth = responsive ? "" : `${cellWidth}px`;
8674
8924
  }
8675
8925
  columnIndex += colspan;
8676
8926
  });
@@ -8688,6 +8938,7 @@ var init_preview_html = __esm({
8688
8938
  "src/components/UEditor/preview-html.ts"() {
8689
8939
  "use strict";
8690
8940
  init_table_dom_utils();
8941
+ init_table_width_model();
8691
8942
  DEFAULT_TABLE_COLUMN_WIDTH2 = 100;
8692
8943
  TIPTAP_TABLE_MIN_COLUMN_WIDTH = 25;
8693
8944
  }
@@ -12346,20 +12597,17 @@ var import_state6 = require("@tiptap/pm/state");
12346
12597
  var import_view2 = require("@tiptap/pm/view");
12347
12598
  var import_tables2 = require("@tiptap/pm/tables");
12348
12599
  init_table_dom_utils();
12600
+ init_table_width_model();
12349
12601
  var DEFAULT_TABLE_COLUMN_WIDTH = 100;
12350
12602
  var MIN_RESIZED_TABLE_COLUMN_WIDTH = 25;
12351
12603
  function getColumnResizeMinWidth(configuredMinWidth) {
12352
12604
  const normalizedMinWidth = Number.isFinite(configuredMinWidth) && configuredMinWidth > 0 ? Math.round(configuredMinWidth) : MIN_RESIZED_TABLE_COLUMN_WIDTH;
12353
12605
  return Math.max(MIN_RESIZED_TABLE_COLUMN_WIDTH, normalizedMinWidth);
12354
12606
  }
12355
- function setColumnStyle(column, width) {
12356
- if (width == null) {
12357
- column.style.width = `${DEFAULT_TABLE_COLUMN_WIDTH}px`;
12358
- column.style.minWidth = `${DEFAULT_TABLE_COLUMN_WIDTH}px`;
12359
- return;
12360
- }
12361
- column.style.width = `${Math.max(width, MIN_RESIZED_TABLE_COLUMN_WIDTH)}px`;
12362
- column.style.minWidth = "";
12607
+ function setColumnStyle(column, width, ratio, explicit, responsive) {
12608
+ column.style.width = responsive ? formatBasisPointsAsPercentage(ratio) : `${width}px`;
12609
+ column.style.minWidth = responsive || explicit ? "" : `${width}px`;
12610
+ column.setAttribute("width", String(width));
12363
12611
  }
12364
12612
  function isTableColumnElement(node) {
12365
12613
  return isCrossRealmElement(node) && String(node.tagName).toUpperCase() === "COL";
@@ -12368,6 +12616,7 @@ function updateDynamicColumns(node, colgroup, table, ownerDocument, overrideCol,
12368
12616
  let totalWidth = 0;
12369
12617
  let nextDOM = colgroup.firstChild;
12370
12618
  const row = node.firstChild;
12619
+ const columns = [];
12371
12620
  if (row) {
12372
12621
  for (let rowCellIndex = 0, col = 0; rowCellIndex < row.childCount; rowCellIndex += 1) {
12373
12622
  const { colspan, colwidth } = row.child(rowCellIndex).attrs;
@@ -12376,7 +12625,11 @@ function updateDynamicColumns(node, colgroup, table, ownerDocument, overrideCol,
12376
12625
  const width = rawWidth ? Math.max(rawWidth, MIN_RESIZED_TABLE_COLUMN_WIDTH) : null;
12377
12626
  totalWidth += width ?? DEFAULT_TABLE_COLUMN_WIDTH;
12378
12627
  const colElement = isTableColumnElement(nextDOM) ? nextDOM : colgroup.appendChild(ownerDocument.createElement("col"));
12379
- setColumnStyle(colElement, width);
12628
+ columns.push({
12629
+ element: colElement,
12630
+ explicit: width !== null,
12631
+ width: width ?? DEFAULT_TABLE_COLUMN_WIDTH
12632
+ });
12380
12633
  nextDOM = colElement.nextSibling;
12381
12634
  }
12382
12635
  }
@@ -12386,13 +12639,39 @@ function updateDynamicColumns(node, colgroup, table, ownerDocument, overrideCol,
12386
12639
  nextDOM.parentNode?.removeChild(nextDOM);
12387
12640
  nextDOM = after;
12388
12641
  }
12389
- const hasUserWidth = typeof node.attrs.style === "string" && /\bwidth\s*:/i.test(node.attrs.style);
12390
- if (!hasUserWidth) {
12642
+ const responsive = normalizeTableWidthMode(node.attrs.widthMode) === "responsive";
12643
+ const columnRatios = getTableColumnRatios(node);
12644
+ columns.forEach(({ element, explicit, width }, index) => {
12645
+ setColumnStyle(element, width, columnRatios[index] ?? 1, explicit, responsive);
12646
+ });
12647
+ if (responsive) {
12648
+ const widthBp = getResponsiveTableWidthBp(node);
12649
+ const offsetBp = getResponsiveTableOffsetBp(node);
12650
+ table.setAttribute("data-table-width-mode", "responsive");
12651
+ table.setAttribute("data-table-width", formatBasisPointsAsPercentage(widthBp));
12652
+ table.setAttribute("data-table-width-bp", String(widthBp));
12653
+ table.setAttribute("data-table-offset", formatBasisPointsAsPercentage(offsetBp));
12654
+ table.setAttribute("data-table-offset-bp", String(offsetBp));
12655
+ table.setAttribute("data-table-column-ratios", columnRatios.join(","));
12656
+ table.style.width = formatBasisPointsAsPercentage(widthBp);
12657
+ table.style.marginLeft = formatBasisPointsAsPercentage(offsetBp);
12658
+ table.style.marginRight = "auto";
12659
+ table.style.minWidth = `${Math.max(1, colgroup.childElementCount) * MIN_RESIZED_TABLE_COLUMN_WIDTH}px`;
12660
+ } else {
12661
+ table.removeAttribute("data-table-width-mode");
12662
+ table.removeAttribute("data-table-width");
12663
+ table.removeAttribute("data-table-width-bp");
12664
+ table.removeAttribute("data-table-offset");
12665
+ table.removeAttribute("data-table-offset-bp");
12666
+ table.removeAttribute("data-table-column-ratios");
12391
12667
  table.style.width = `${totalWidth}px`;
12392
12668
  table.style.minWidth = "";
12393
- } else {
12394
- table.style.minWidth = `${totalWidth}px`;
12669
+ const tableAlign = node.attrs.textAlign;
12670
+ table.style.marginLeft = tableAlign === "center" || tableAlign === "right" ? "auto" : "0px";
12671
+ table.style.marginRight = tableAlign === "center" ? "auto" : tableAlign === "right" ? "0px" : "auto";
12395
12672
  }
12673
+ if (node.attrs.textAlign) table.setAttribute("data-table-align", String(node.attrs.textAlign));
12674
+ else table.removeAttribute("data-table-align");
12396
12675
  }
12397
12676
  var UEditorTableView = class {
12398
12677
  constructor(node, _defaultColumnWidth, maybeView) {
@@ -12428,7 +12707,40 @@ var UEditorTableView = class {
12428
12707
  };
12429
12708
  function getDraggedWidth(dragging, event) {
12430
12709
  const offset = event.clientX - dragging.startX;
12431
- return Math.max(dragging.minWidth, Math.round(dragging.startWidth + offset));
12710
+ const maximum = dragging.neighborStartWidth === void 0 ? Number.POSITIVE_INFINITY : dragging.startWidth + dragging.neighborStartWidth - dragging.minWidth;
12711
+ return Math.min(maximum, Math.max(dragging.minWidth, Math.round(dragging.startWidth + offset)));
12712
+ }
12713
+ function normalizeColumnWidthsToTotal(values, total, minimum) {
12714
+ const safeTotal = Math.max(values.length * minimum, Math.round(total));
12715
+ const weights = values.map((value) => Number.isFinite(value) && value > 0 ? value : DEFAULT_TABLE_COLUMN_WIDTH);
12716
+ const weightSum = weights.reduce((sum, value) => sum + value, 0);
12717
+ const widths = weights.map((value) => Math.max(minimum, Math.round(value / weightSum * safeTotal)));
12718
+ let difference = safeTotal - widths.reduce((sum, value) => sum + value, 0);
12719
+ while (difference !== 0) {
12720
+ let changed = false;
12721
+ for (let index = widths.length - 1; index >= 0 && difference !== 0; index -= 1) {
12722
+ if (difference < 0 && widths[index] <= minimum) continue;
12723
+ widths[index] += difference > 0 ? 1 : -1;
12724
+ difference += difference > 0 ? -1 : 1;
12725
+ changed = true;
12726
+ }
12727
+ if (!changed) break;
12728
+ }
12729
+ return widths;
12730
+ }
12731
+ function getResizeColumnInfo(state, cell) {
12732
+ const $cell = state.doc.resolve(cell);
12733
+ const table = $cell.node(-1);
12734
+ const map = import_tables2.TableMap.get(table);
12735
+ const start = $cell.start(-1);
12736
+ const nodeAfter = $cell.nodeAfter;
12737
+ if (!nodeAfter) return null;
12738
+ return {
12739
+ col: map.colCount($cell.pos - start) + nodeAfter.attrs.colspan - 1,
12740
+ map,
12741
+ start,
12742
+ table
12743
+ };
12432
12744
  }
12433
12745
  function getCurrentColWidth(view, cellPos, { colspan, colwidth }) {
12434
12746
  const width = colwidth?.[colwidth.length - 1];
@@ -12497,6 +12809,12 @@ function handleMouseMove(view, event, handleWidth, lastColumnResizable) {
12497
12809
  if (event.clientX - left <= handleWidth) cell = edgeCell(view, event, "left", handleWidth);
12498
12810
  else if (right - event.clientX <= handleWidth) cell = edgeCell(view, event, "right", handleWidth);
12499
12811
  }
12812
+ if (cell !== -1) {
12813
+ const info = getResizeColumnInfo(view.state, cell);
12814
+ if (info && normalizeTableWidthMode(info.table.attrs.widthMode) === "responsive" && info.col === info.map.width - 1) {
12815
+ cell = -1;
12816
+ }
12817
+ }
12500
12818
  if (cell === pluginState.activeHandle) {
12501
12819
  clearHandleHoverTimer();
12502
12820
  return;
@@ -12543,33 +12861,47 @@ function handleMouseLeave(view) {
12543
12861
  updateHandle(view, -1);
12544
12862
  }
12545
12863
  }
12546
- function updateColumnWidth(view, cell, width) {
12547
- const $cell = view.state.doc.resolve(cell);
12548
- const table = $cell.node(-1);
12549
- const map = import_tables2.TableMap.get(table);
12550
- const start = $cell.start(-1);
12551
- const nodeAfter = $cell.nodeAfter;
12552
- if (!nodeAfter) return;
12553
- const col = map.colCount($cell.pos - start) + nodeAfter.attrs.colspan - 1;
12864
+ function updateColumnWidths(view, cell, widthsByColumn, columnRatios) {
12865
+ const info = getResizeColumnInfo(view.state, cell);
12866
+ if (!info) return;
12867
+ const { map, start, table } = info;
12554
12868
  const tr = view.state.tr;
12555
- for (let row = 0; row < map.height; row += 1) {
12556
- const mapIndex = row * map.width + col;
12557
- if (row && map.map[mapIndex] === map.map[mapIndex - map.width]) continue;
12558
- const pos = map.map[mapIndex];
12869
+ const seenCellPositions = /* @__PURE__ */ new Set();
12870
+ for (const pos of map.map) {
12871
+ if (seenCellPositions.has(pos)) continue;
12872
+ seenCellPositions.add(pos);
12559
12873
  const cellNode = table.nodeAt(pos);
12560
12874
  if (!cellNode) continue;
12561
12875
  const attrs = cellNode.attrs;
12562
- const index = attrs.colspan === 1 ? 0 : col - map.colCount(pos);
12563
- if (attrs.colwidth?.[index] === width) continue;
12564
12876
  const colwidth = attrs.colwidth ? attrs.colwidth.slice() : Array.from({ length: attrs.colspan }, () => 0);
12565
- colwidth[index] = width;
12877
+ const cellStartColumn = map.colCount(pos);
12878
+ let changed = false;
12879
+ for (let index = 0; index < attrs.colspan; index += 1) {
12880
+ const width = widthsByColumn.get(cellStartColumn + index);
12881
+ if (width === void 0 || colwidth[index] === width) continue;
12882
+ colwidth[index] = width;
12883
+ changed = true;
12884
+ }
12885
+ if (!changed) continue;
12566
12886
  tr.setNodeMarkup(start + pos, null, {
12567
12887
  ...attrs,
12568
12888
  colwidth
12569
12889
  });
12570
12890
  }
12891
+ if (columnRatios) {
12892
+ tr.setNodeMarkup(start - 1, void 0, {
12893
+ ...table.attrs,
12894
+ widthMode: "responsive",
12895
+ columnRatios: normalizeColumnRatios(columnRatios, map.width)
12896
+ });
12897
+ }
12571
12898
  if (tr.docChanged) view.dispatch(tr);
12572
12899
  }
12900
+ function updateColumnWidth(view, cell, width) {
12901
+ const info = getResizeColumnInfo(view.state, cell);
12902
+ if (!info) return;
12903
+ updateColumnWidths(view, cell, /* @__PURE__ */ new Map([[info.col, width]]));
12904
+ }
12573
12905
  function getActiveDragging(state) {
12574
12906
  const dragging = import_tables2.columnResizingPluginKey.getState(state)?.dragging;
12575
12907
  return dragging ? dragging : null;
@@ -12621,16 +12953,36 @@ function handleMouseDown(view, event, cellMinWidth) {
12621
12953
  if (!pluginState || pluginState.activeHandle === -1 || pluginState.dragging) return false;
12622
12954
  const cell = view.state.doc.nodeAt(pluginState.activeHandle);
12623
12955
  if (!cell) return false;
12956
+ const resizeInfo = getResizeColumnInfo(view.state, pluginState.activeHandle);
12957
+ if (!resizeInfo) return false;
12624
12958
  const attrs = cell.attrs;
12625
- const width = getCurrentColWidth(view, pluginState.activeHandle, {
12959
+ let width = getCurrentColWidth(view, pluginState.activeHandle, {
12626
12960
  colspan: attrs.colspan ?? 1,
12627
12961
  colwidth: attrs.colwidth
12628
12962
  });
12629
12963
  const minWidth = getColumnResizeMinWidth(cellMinWidth);
12964
+ let responsiveColumnWidths;
12965
+ let neighborStartWidth;
12966
+ if (normalizeTableWidthMode(resizeInfo.table.attrs.widthMode) === "responsive") {
12967
+ if (resizeInfo.col >= resizeInfo.map.width - 1) return false;
12968
+ const storedRatios = getTableColumnRatios(resizeInfo.table);
12969
+ const legacyWidths = getLegacyTableColumnWeights(resizeInfo.table, DEFAULT_TABLE_COLUMN_WIDTH);
12970
+ const storedTotal = legacyWidths.reduce((sum, value) => sum + value, 0);
12971
+ const tableElement = getTableElementAtCell(view, pluginState.activeHandle);
12972
+ const renderedWidth = tableElement?.getBoundingClientRect().width || storedTotal;
12973
+ responsiveColumnWidths = normalizeColumnWidthsToTotal(storedRatios, renderedWidth, minWidth);
12974
+ width = responsiveColumnWidths[resizeInfo.col];
12975
+ neighborStartWidth = responsiveColumnWidths[resizeInfo.col + 1];
12976
+ }
12630
12977
  const dragging = {
12631
12978
  startX: event.clientX,
12632
12979
  startWidth: width,
12633
- minWidth
12980
+ minWidth,
12981
+ ...responsiveColumnWidths ? {
12982
+ columnIndex: resizeInfo.col,
12983
+ responsiveColumnWidths,
12984
+ neighborStartWidth
12985
+ } : null
12634
12986
  };
12635
12987
  view.dispatch(view.state.tr.setMeta(import_tables2.columnResizingPluginKey, { setDragging: dragging }));
12636
12988
  function finish(nextEvent) {
@@ -12639,7 +12991,20 @@ function handleMouseDown(view, event, cellMinWidth) {
12639
12991
  const activeDragging = getActiveDragging(view.state);
12640
12992
  const activeHandle = import_tables2.columnResizingPluginKey.getState(view.state)?.activeHandle ?? -1;
12641
12993
  if (activeDragging && activeHandle > -1) {
12642
- updateColumnWidth(view, activeHandle, getDraggedWidth(activeDragging, nextEvent));
12994
+ const nextWidth = getDraggedWidth(activeDragging, nextEvent);
12995
+ if (activeDragging.responsiveColumnWidths && activeDragging.columnIndex !== void 0 && activeDragging.neighborStartWidth !== void 0) {
12996
+ const nextColumnWidths = activeDragging.responsiveColumnWidths.slice();
12997
+ nextColumnWidths[activeDragging.columnIndex] = nextWidth;
12998
+ nextColumnWidths[activeDragging.columnIndex + 1] = activeDragging.startWidth + activeDragging.neighborStartWidth - nextWidth;
12999
+ updateColumnWidths(
13000
+ view,
13001
+ activeHandle,
13002
+ new Map(nextColumnWidths.map((columnWidth, index) => [index, columnWidth])),
13003
+ normalizeColumnRatios(nextColumnWidths, nextColumnWidths.length)
13004
+ );
13005
+ } else {
13006
+ updateColumnWidth(view, activeHandle, nextWidth);
13007
+ }
12643
13008
  view.dispatch(view.state.tr.setMeta(import_tables2.columnResizingPluginKey, { setDragging: null }));
12644
13009
  }
12645
13010
  hideColumnResizeGhost(view);
@@ -12669,6 +13034,9 @@ function handleDecorations(state, cell, ownerDocument) {
12669
13034
  const nodeAfter = $cell.nodeAfter;
12670
13035
  if (!nodeAfter) return import_view2.DecorationSet.empty;
12671
13036
  const col = map.colCount($cell.pos - start) + nodeAfter.attrs.colspan - 1;
13037
+ if (normalizeTableWidthMode(table.attrs.widthMode) === "responsive" && col === map.width - 1) {
13038
+ return import_view2.DecorationSet.empty;
13039
+ }
12672
13040
  for (let row = 0; row < map.height; row += 1) {
12673
13041
  const index = col + row * map.width;
12674
13042
  if ((col === map.width - 1 || map.map[index] !== map.map[index + 1]) && (row === 0 || map.map[index] !== map.map[index - map.width])) {
@@ -12742,6 +13110,7 @@ function dynamicColumnResizing({
12742
13110
  // src/components/UEditor/table-align.ts
12743
13111
  init_table_align_utils();
12744
13112
  init_table_dom_utils();
13113
+ init_table_width_model();
12745
13114
  function normalizeTableAlign(value) {
12746
13115
  if (value === "left" || value === "center" || value === "right") {
12747
13116
  return value;
@@ -12758,7 +13127,7 @@ function parseTableAlign(element) {
12758
13127
  if ((marginLeft === "0px" || marginLeft === "0") && marginRight === "auto") return "left";
12759
13128
  return null;
12760
13129
  }
12761
- function renderTableAlignStyle(tableAlign) {
13130
+ function renderFixedTableAlignStyle(tableAlign) {
12762
13131
  switch (tableAlign) {
12763
13132
  case "center":
12764
13133
  return "table-layout: fixed; margin-left: auto; margin-right: auto;";
@@ -12770,28 +13139,61 @@ function renderTableAlignStyle(tableAlign) {
12770
13139
  return "";
12771
13140
  }
12772
13141
  }
12773
- function createUEditorColGroup(node) {
12774
- const columns = [];
12775
- let totalWidth = 0;
12776
- const firstRow = node.firstChild;
12777
- if (firstRow) {
12778
- for (let cellIndex = 0; cellIndex < firstRow.childCount; cellIndex += 1) {
12779
- const cell = firstRow.child(cellIndex);
12780
- const colspan = Math.max(1, Number(cell.attrs.colspan) || 1);
12781
- const colwidth = Array.isArray(cell.attrs.colwidth) ? cell.attrs.colwidth : [];
12782
- for (let spanIndex = 0; spanIndex < colspan; spanIndex += 1) {
12783
- const storedWidth = Number(colwidth[spanIndex]);
12784
- const width = Number.isFinite(storedWidth) && storedWidth > 0 ? Math.max(MIN_RESIZED_TABLE_COLUMN_WIDTH, Math.round(storedWidth)) : DEFAULT_TABLE_COLUMN_WIDTH;
12785
- totalWidth += width;
12786
- columns.push(["col", { style: `width: ${width}px; min-width: ${width}px;`, width: String(width) }]);
12787
- }
12788
- }
13142
+ function parseTableWidthMode(element) {
13143
+ const storedMode = element.getAttribute("data-table-width-mode");
13144
+ if (storedMode === "responsive" || storedMode === "full" || parsePercentageToBasisPoints(element.style.width) !== null) {
13145
+ return "responsive";
12789
13146
  }
13147
+ return "fixed";
13148
+ }
13149
+ function createUEditorColGroup(node, widthMode) {
13150
+ const columnWidths = getLegacyTableColumnWeights(node, DEFAULT_TABLE_COLUMN_WIDTH).map((width) => Math.max(MIN_RESIZED_TABLE_COLUMN_WIDTH, Math.round(width)));
13151
+ const columnRatios = getTableColumnRatios(node);
13152
+ const totalWidth = columnWidths.reduce((sum, width) => sum + width, 0);
13153
+ const columns = columnWidths.map((width, index) => ["col", {
13154
+ style: widthMode === "responsive" ? `width: ${formatBasisPointsAsPercentage(columnRatios[index])};` : `width: ${width}px; min-width: ${width}px;`,
13155
+ width: String(width)
13156
+ }]);
12790
13157
  return {
12791
13158
  colgroup: ["colgroup", {}, ...columns],
13159
+ columnCount: columns.length,
12792
13160
  tableWidth: totalWidth > 0 ? `${totalWidth}px` : ""
12793
13161
  };
12794
13162
  }
13163
+ function runResponsiveColumnStructureCommand(state, dispatch, command, updateLayout) {
13164
+ const tableInfo = findTableNodeInfoFromState(state);
13165
+ if (!tableInfo || normalizeTableWidthMode(tableInfo.node.attrs.widthMode) !== "responsive") {
13166
+ return command(state, dispatch);
13167
+ }
13168
+ const rect = (0, import_tables3.selectedRect)(state);
13169
+ const nextLayout = updateLayout({
13170
+ widthBp: getResponsiveTableWidthBp(tableInfo.node),
13171
+ columnRatios: getTableColumnRatios(tableInfo.node)
13172
+ }, rect);
13173
+ return command(state, dispatch ? (transaction) => {
13174
+ const nextTable = transaction.doc.nodeAt(tableInfo.pos);
13175
+ if (nextTable?.type.name === "table" && nextLayout.columnRatios.length > 0) {
13176
+ const widthBp = clampResponsiveTableWidthBp(nextLayout.widthBp);
13177
+ const tableAlign = normalizeTableAlign(nextTable.attrs.textAlign);
13178
+ const offsetBp = resolveResponsiveTableOffsetBp(
13179
+ widthBp,
13180
+ tableAlign,
13181
+ getResponsiveTableOffsetBp(tableInfo.node)
13182
+ );
13183
+ transaction.setNodeMarkup(tableInfo.pos, void 0, {
13184
+ ...nextTable.attrs,
13185
+ widthMode: "responsive",
13186
+ widthBp,
13187
+ offsetBp,
13188
+ columnRatios: normalizeColumnRatios(
13189
+ nextLayout.columnRatios,
13190
+ getLogicalTableColumnCount(nextTable)
13191
+ )
13192
+ });
13193
+ }
13194
+ dispatch(transaction);
13195
+ } : void 0);
13196
+ }
12795
13197
  var UEditorTable = import_extension_table.Table.extend({
12796
13198
  addGlobalAttributes() {
12797
13199
  return [
@@ -12809,10 +13211,64 @@ var UEditorTable = import_extension_table.Table.extend({
12809
13211
  const tableAlign = normalizeTableAlign(attributes.textAlign);
12810
13212
  if (!tableAlign) return {};
12811
13213
  return {
12812
- "data-table-align": tableAlign,
12813
- style: renderTableAlignStyle(tableAlign)
13214
+ "data-table-align": tableAlign
12814
13215
  };
12815
13216
  }
13217
+ },
13218
+ widthMode: {
13219
+ default: "fixed",
13220
+ parseHTML: (element) => {
13221
+ if (!(element instanceof HTMLElement)) return "fixed";
13222
+ return parseTableWidthMode(element);
13223
+ },
13224
+ renderHTML: (attributes) => {
13225
+ if (normalizeTableWidthMode(attributes.widthMode) !== "responsive") return {};
13226
+ return {
13227
+ "data-table-width-mode": "responsive"
13228
+ };
13229
+ }
13230
+ },
13231
+ widthBp: {
13232
+ default: null,
13233
+ parseHTML: (element) => {
13234
+ if (!(element instanceof HTMLElement) || parseTableWidthMode(element) !== "responsive") return null;
13235
+ const stored = Number(element.getAttribute("data-table-width-bp"));
13236
+ if (Number.isFinite(stored) && stored > 0) return clampResponsiveTableWidthBp(stored);
13237
+ return parsePercentageToBasisPoints(element.getAttribute("data-table-width") ?? element.style.width) ?? DEFAULT_RESPONSIVE_TABLE_WIDTH_BP;
13238
+ },
13239
+ renderHTML: () => ({})
13240
+ },
13241
+ offsetBp: {
13242
+ default: null,
13243
+ parseHTML: (element) => {
13244
+ if (!(element instanceof HTMLElement) || parseTableWidthMode(element) !== "responsive") return null;
13245
+ const storedValue = element.getAttribute("data-table-offset-bp");
13246
+ const stored = Number(storedValue);
13247
+ if (storedValue !== null && Number.isFinite(stored) && stored >= 0) return Math.round(stored);
13248
+ const explicitOffset = parsePercentageToBasisPoints(
13249
+ element.getAttribute("data-table-offset") ?? element.style.marginLeft
13250
+ );
13251
+ if (explicitOffset !== null) return explicitOffset;
13252
+ const widthBp = parsePercentageToBasisPoints(
13253
+ element.getAttribute("data-table-width") ?? element.style.width
13254
+ ) ?? DEFAULT_RESPONSIVE_TABLE_WIDTH_BP;
13255
+ const tableAlign = parseTableAlign(element);
13256
+ return resolveResponsiveTableOffsetBp(widthBp, tableAlign);
13257
+ },
13258
+ renderHTML: () => ({})
13259
+ },
13260
+ columnRatios: {
13261
+ default: null,
13262
+ parseHTML: (element) => {
13263
+ if (!(element instanceof HTMLElement)) return null;
13264
+ const storedRatios = parseColumnRatios(
13265
+ element.getAttribute("data-table-column-ratios") ?? element.getAttribute("data-column-ratios")
13266
+ );
13267
+ if (storedRatios) return storedRatios;
13268
+ const columnPercentages = Array.from(element.querySelectorAll("colgroup > col")).map((column) => parsePercentageToBasisPoints(column.style.width));
13269
+ return columnPercentages.length > 0 && columnPercentages.every((ratio) => ratio !== null) ? normalizeColumnRatios(columnPercentages, columnPercentages.length) : null;
13270
+ },
13271
+ renderHTML: () => ({})
12816
13272
  }
12817
13273
  }
12818
13274
  }
@@ -12821,13 +13277,86 @@ var UEditorTable = import_extension_table.Table.extend({
12821
13277
  addCommands() {
12822
13278
  return {
12823
13279
  ...this.parent?.(),
13280
+ insertTable: ({ rows = 3, cols = 3, withHeaderRow = true } = {}) => ({ tr, dispatch, editor }) => {
13281
+ const types = (0, import_tables3.tableNodeTypes)(editor.schema);
13282
+ const rowCount = Math.max(1, Math.floor(rows));
13283
+ const columnCount = Math.max(1, Math.floor(cols));
13284
+ const createCells = (type) => Array.from({ length: columnCount }, () => type.createAndFill()).filter((cell) => cell !== null);
13285
+ const bodyCells = createCells(types.cell);
13286
+ const headerCells = withHeaderRow ? createCells(types.header_cell) : bodyCells;
13287
+ const tableRows = Array.from({ length: rowCount }, (_, index) => types.row.createChecked(
13288
+ null,
13289
+ withHeaderRow && index === 0 ? headerCells : bodyCells
13290
+ ));
13291
+ const table = types.table.createChecked(
13292
+ {
13293
+ widthMode: "responsive",
13294
+ widthBp: DEFAULT_RESPONSIVE_TABLE_WIDTH_BP,
13295
+ offsetBp: 0,
13296
+ columnRatios: normalizeColumnRatios(null, columnCount)
13297
+ },
13298
+ tableRows
13299
+ );
13300
+ if (dispatch) {
13301
+ const offset = tr.selection.from + 1;
13302
+ tr.replaceSelectionWith(table).scrollIntoView().setSelection(import_state7.TextSelection.near(tr.doc.resolve(offset)));
13303
+ }
13304
+ return true;
13305
+ },
13306
+ addColumnBefore: () => ({ state, dispatch }) => {
13307
+ return runResponsiveColumnStructureCommand(
13308
+ state,
13309
+ dispatch,
13310
+ import_tables3.addColumnBefore,
13311
+ (layout, rect) => insertResponsiveColumnLayout(
13312
+ layout.widthBp,
13313
+ layout.columnRatios,
13314
+ rect.left,
13315
+ rect.left
13316
+ )
13317
+ );
13318
+ },
13319
+ addColumnAfter: () => ({ state, dispatch }) => {
13320
+ return runResponsiveColumnStructureCommand(
13321
+ state,
13322
+ dispatch,
13323
+ import_tables3.addColumnAfter,
13324
+ (layout, rect) => insertResponsiveColumnLayout(
13325
+ layout.widthBp,
13326
+ layout.columnRatios,
13327
+ rect.right,
13328
+ rect.right - 1
13329
+ )
13330
+ );
13331
+ },
13332
+ deleteColumn: () => ({ state, dispatch }) => {
13333
+ return runResponsiveColumnStructureCommand(
13334
+ state,
13335
+ dispatch,
13336
+ import_tables3.deleteColumn,
13337
+ (layout, rect) => {
13338
+ let nextLayout = layout;
13339
+ for (let index = rect.right - 1; index >= rect.left; index -= 1) {
13340
+ nextLayout = deleteResponsiveColumnLayout(
13341
+ nextLayout.widthBp,
13342
+ nextLayout.columnRatios,
13343
+ index
13344
+ );
13345
+ }
13346
+ return nextLayout;
13347
+ }
13348
+ );
13349
+ },
12824
13350
  setTableAlign: (tableAlign) => ({ state, dispatch }) => {
12825
13351
  const tableInfo = findTableNodeInfoFromState(state);
12826
13352
  if (!tableInfo) return false;
13353
+ const widthBp = getResponsiveTableWidthBp(tableInfo.node);
13354
+ const offsetBp = resolveResponsiveTableOffsetBp(widthBp, tableAlign);
12827
13355
  dispatch?.(
12828
13356
  state.tr.setNodeMarkup(tableInfo.pos, tableInfo.node.type, {
12829
13357
  ...tableInfo.node.attrs,
12830
- textAlign: tableAlign
13358
+ textAlign: tableAlign,
13359
+ ...normalizeTableWidthMode(tableInfo.node.attrs.widthMode) === "responsive" ? { offsetBp } : null
12831
13360
  })
12832
13361
  );
12833
13362
  return true;
@@ -12846,11 +13375,31 @@ var UEditorTable = import_extension_table.Table.extend({
12846
13375
  };
12847
13376
  },
12848
13377
  renderHTML({ node, HTMLAttributes }) {
12849
- const { colgroup, tableWidth } = createUEditorColGroup(node);
13378
+ const widthMode = normalizeTableWidthMode(node.attrs.widthMode);
13379
+ const { colgroup, columnCount, tableWidth } = createUEditorColGroup(node, widthMode);
13380
+ const tableAlign = normalizeTableAlign(node.attrs.textAlign);
13381
+ const widthBp = getResponsiveTableWidthBp(node);
13382
+ const offsetBp = getResponsiveTableOffsetBp(node);
13383
+ const columnRatios = getTableColumnRatios(node);
13384
+ const tableStyle = widthMode === "responsive" ? [
13385
+ `width: ${formatBasisPointsAsPercentage(widthBp)}`,
13386
+ `margin-left: ${formatBasisPointsAsPercentage(offsetBp)}`,
13387
+ "margin-right: auto",
13388
+ `min-width: ${Math.max(1, columnCount) * MIN_RESIZED_TABLE_COLUMN_WIDTH}px`,
13389
+ "table-layout: fixed"
13390
+ ].join("; ") + ";" : tableWidth ? `width: ${tableWidth}; ${renderFixedTableAlignStyle(tableAlign)}` : `table-layout: fixed; ${renderFixedTableAlignStyle(tableAlign)}`;
12850
13391
  const table = [
12851
13392
  "table",
12852
13393
  (0, import_core17.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes, {
12853
- style: tableWidth ? `width: ${tableWidth};` : "table-layout: fixed;"
13394
+ ...widthMode === "responsive" ? {
13395
+ "data-table-width-mode": "responsive",
13396
+ "data-table-width": formatBasisPointsAsPercentage(widthBp),
13397
+ "data-table-width-bp": String(widthBp),
13398
+ "data-table-offset": formatBasisPointsAsPercentage(offsetBp),
13399
+ "data-table-offset-bp": String(offsetBp),
13400
+ "data-table-column-ratios": columnRatios.join(",")
13401
+ } : null,
13402
+ style: tableStyle
12854
13403
  }),
12855
13404
  colgroup,
12856
13405
  ["tbody", 0]
@@ -12903,6 +13452,31 @@ var UEditorTable = import_extension_table.Table.extend({
12903
13452
  (0, import_tables3.tableEditing)({
12904
13453
  allowTableNodeSelection: this.options.allowTableNodeSelection
12905
13454
  }),
13455
+ new import_state7.Plugin({
13456
+ key: new import_state7.PluginKey("responsiveTableLayoutNormalizer"),
13457
+ appendTransaction(transactions, _oldState, newState) {
13458
+ if (!transactions.some((transaction) => transaction.docChanged)) return null;
13459
+ const tableInfo = findTableNodeInfoFromState(newState);
13460
+ const node = tableInfo?.node;
13461
+ if (!tableInfo || !node || normalizeTableWidthMode(node.attrs.widthMode) !== "responsive") return null;
13462
+ const columnCount = getLogicalTableColumnCount(node);
13463
+ const columnRatios = getTableColumnRatios(node);
13464
+ const widthBp = getResponsiveTableWidthBp(node);
13465
+ const offsetBp = getResponsiveTableOffsetBp(node);
13466
+ const storedRatios = parseColumnRatios(node.attrs.columnRatios);
13467
+ const ratiosMatch = storedRatios?.length === columnCount && storedRatios.every((ratio, index) => Math.round(ratio) === columnRatios[index]);
13468
+ if (ratiosMatch && node.attrs.widthBp === widthBp && node.attrs.offsetBp === offsetBp && node.attrs.widthMode === "responsive") {
13469
+ return null;
13470
+ }
13471
+ return newState.tr.setNodeMarkup(tableInfo.pos, void 0, {
13472
+ ...node.attrs,
13473
+ widthMode: "responsive",
13474
+ widthBp,
13475
+ offsetBp,
13476
+ columnRatios
13477
+ });
13478
+ }
13479
+ }),
12906
13480
  new import_state7.Plugin({
12907
13481
  appendTransaction(_transactions, _oldState, newState) {
12908
13482
  const { doc, schema } = newState;
@@ -19410,7 +19984,7 @@ var Selection = class {
19410
19984
  found.
19411
19985
  */
19412
19986
  static findFrom($pos, dir, textOnly = false) {
19413
- let inner = $pos.parent.inlineContent ? new TextSelection5($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly);
19987
+ let inner = $pos.parent.inlineContent ? new TextSelection6($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly);
19414
19988
  if (inner)
19415
19989
  return inner;
19416
19990
  for (let depth = $pos.depth - 1; depth >= 0; depth--) {
@@ -19479,7 +20053,7 @@ var Selection = class {
19479
20053
  returns the bookmark for that.
19480
20054
  */
19481
20055
  getBookmark() {
19482
- return TextSelection5.between(this.$anchor, this.$head).getBookmark();
20056
+ return TextSelection6.between(this.$anchor, this.$head).getBookmark();
19483
20057
  }
19484
20058
  };
19485
20059
  Selection.prototype.visible = true;
@@ -19499,7 +20073,7 @@ function checkTextSelection($pos) {
19499
20073
  console["warn"]("TextSelection endpoint not pointing into a node with inline content (" + $pos.parent.type.name + ")");
19500
20074
  }
19501
20075
  }
19502
- var TextSelection5 = class _TextSelection extends Selection {
20076
+ var TextSelection6 = class _TextSelection extends Selection {
19503
20077
  /**
19504
20078
  Construct a text selection between the given points.
19505
20079
  */
@@ -19585,7 +20159,7 @@ var TextSelection5 = class _TextSelection extends Selection {
19585
20159
  return new _TextSelection($anchor, $head);
19586
20160
  }
19587
20161
  };
19588
- Selection.jsonID("text", TextSelection5);
20162
+ Selection.jsonID("text", TextSelection6);
19589
20163
  var TextBookmark = class _TextBookmark {
19590
20164
  constructor(anchor, head) {
19591
20165
  this.anchor = anchor;
@@ -19595,7 +20169,7 @@ var TextBookmark = class _TextBookmark {
19595
20169
  return new _TextBookmark(mapping.map(this.anchor), mapping.map(this.head));
19596
20170
  }
19597
20171
  resolve(doc) {
19598
- return TextSelection5.between(doc.resolve(this.anchor), doc.resolve(this.head));
20172
+ return TextSelection6.between(doc.resolve(this.anchor), doc.resolve(this.head));
19599
20173
  }
19600
20174
  };
19601
20175
  var NodeSelection2 = class _NodeSelection extends Selection {
@@ -19714,7 +20288,7 @@ var AllBookmark = {
19714
20288
  };
19715
20289
  function findSelectionIn(doc, node, pos, index, dir, text = false) {
19716
20290
  if (node.inlineContent)
19717
- return TextSelection5.create(doc, pos);
20291
+ return TextSelection6.create(doc, pos);
19718
20292
  for (let i = index - (dir > 0 ? 0 : 1); dir > 0 ? i < node.childCount : i >= 0; i += dir) {
19719
20293
  let child = node.child(i);
19720
20294
  if (!child.isAtom) {
@@ -20214,7 +20788,7 @@ function freshColWidth(attrs) {
20214
20788
  for (let i = 0; i < attrs.colspan; i++) result.push(0);
20215
20789
  return result;
20216
20790
  }
20217
- function tableNodeTypes2(schema) {
20791
+ function tableNodeTypes3(schema) {
20218
20792
  let result = schema.cached.tableNodeTypes;
20219
20793
  if (!result) {
20220
20794
  result = schema.cached.tableNodeTypes = {};
@@ -20306,7 +20880,7 @@ var CellSelection2 = class CellSelection3 extends Selection {
20306
20880
  else if (tableChanged && this.isColSelection()) return CellSelection3.colSelection($anchorCell, $headCell);
20307
20881
  else return new CellSelection3($anchorCell, $headCell);
20308
20882
  }
20309
- return TextSelection5.between($anchorCell, $headCell);
20883
+ return TextSelection6.between($anchorCell, $headCell);
20310
20884
  }
20311
20885
  content() {
20312
20886
  const table = this.$anchorCell.node(-1);
@@ -20731,7 +21305,7 @@ function moveTableRow$1(table, indexesOrigin, indexesTarget, direction) {
20731
21305
  rows = moveRowInArrayOfRows(rows, indexesOrigin, indexesTarget, direction);
20732
21306
  return convertArrayOfRowsToTableNode(table, rows);
20733
21307
  }
20734
- function selectedRect4(state) {
21308
+ function selectedRect5(state) {
20735
21309
  const sel = state.selection;
20736
21310
  const $pos = selectionCell(state);
20737
21311
  const table = $pos.node(-1);
@@ -20748,8 +21322,8 @@ function deprecated_toggleHeader(type) {
20748
21322
  return function(state, dispatch) {
20749
21323
  if (!isInTable2(state)) return false;
20750
21324
  if (dispatch) {
20751
- const types = tableNodeTypes2(state.schema);
20752
- const rect = selectedRect4(state), tr = state.tr;
21325
+ const types = tableNodeTypes3(state.schema);
21326
+ const rect = selectedRect5(state), tr = state.tr;
20753
21327
  const cells = rect.map.cellsInRect(type == "column" ? {
20754
21328
  left: rect.left,
20755
21329
  top: 0,
@@ -20788,8 +21362,8 @@ function toggleHeader(type, options) {
20788
21362
  return function(state, dispatch) {
20789
21363
  if (!isInTable2(state)) return false;
20790
21364
  if (dispatch) {
20791
- const types = tableNodeTypes2(state.schema);
20792
- const rect = selectedRect4(state), tr = state.tr;
21365
+ const types = tableNodeTypes3(state.schema);
21366
+ const rect = selectedRect5(state), tr = state.tr;
20793
21367
  const isHeaderRowEnabled = isHeaderEnabledByType("row", rect, types);
20794
21368
  const isHeaderColumnEnabled = isHeaderEnabledByType("column", rect, types);
20795
21369
  const selectionStartsAt = (type === "column" ? isHeaderRowEnabled : type === "row" ? isHeaderColumnEnabled : false) ? 1 : 0;
@@ -20823,7 +21397,7 @@ function deleteCellSelection(state, dispatch) {
20823
21397
  if (!(sel instanceof CellSelection2)) return false;
20824
21398
  if (dispatch) {
20825
21399
  const tr = state.tr;
20826
- const baseContent = tableNodeTypes2(state.schema).cell.createAndFill().content;
21400
+ const baseContent = tableNodeTypes3(state.schema).cell.createAndFill().content;
20827
21401
  sel.forEachCell((cell, pos) => {
20828
21402
  if (!cell.content.eq(baseContent)) tr.replace(tr.mapping.map(pos + 1), tr.mapping.map(pos + cell.nodeSize - 1), new Slice(baseContent, 0, 0));
20829
21403
  });
@@ -20921,7 +21495,7 @@ function shiftArrow(axis, dir) {
20921
21495
  };
20922
21496
  }
20923
21497
  function atEndOfCell(view, axis, dir) {
20924
- if (!(view.state.selection instanceof TextSelection5)) return null;
21498
+ if (!(view.state.selection instanceof TextSelection6)) return null;
20925
21499
  const { $head } = view.state.selection;
20926
21500
  for (let d = $head.depth - 1; d >= 0; d--) {
20927
21501
  const parent = $head.node(d);
@@ -20948,6 +21522,7 @@ init_table_dom_utils();
20948
21522
 
20949
21523
  // src/components/UEditor/table-layout-model.ts
20950
21524
  init_table_dom_utils();
21525
+ init_table_width_model();
20951
21526
  var FALLBACK_TABLE_ROW_HEIGHT = DEFAULT_TABLE_ROW_HEIGHT;
20952
21527
  var FALLBACK_TABLE_COLUMN_WIDTH = 160;
20953
21528
  function isTableCellElement(element) {
@@ -21054,7 +21629,7 @@ function buildLogicalColumnMetrics({
21054
21629
  if (relativeCellPos == null) continue;
21055
21630
  const cellMapRect = map.findCell(relativeCellPos);
21056
21631
  const cellRect = tableCell.getBoundingClientRect();
21057
- const cellStart = cellRect.width > 0 ? cellRect.left - surfaceRect.left + surface.scrollLeft : tableLeft + cellMapRect.left * fallbackWidth;
21632
+ const cellStart = cellRect.width > 0 ? cellRect.left - surfaceRect.left - surface.clientLeft + surface.scrollLeft : tableLeft + cellMapRect.left * fallbackWidth;
21058
21633
  const size = metricOrFallback(cellRect.width, fallbackWidth * Math.max(1, cellMapRect.right - cellMapRect.left));
21059
21634
  visualColumns.push({
21060
21635
  index: cellMapRect.left,
@@ -21109,7 +21684,7 @@ function buildLogicalRowMetrics({
21109
21684
  const tableCell = isTableCellElement(cellCandidate) ? cellCandidate : null;
21110
21685
  if (tableCell) {
21111
21686
  const cellRect = tableCell.getBoundingClientRect();
21112
- const start = cellRect.height > 0 ? cellRect.top - surfaceRect.top + surface.scrollTop : tableTop + cellMapRect.top * fallbackHeight;
21687
+ const start = cellRect.height > 0 ? cellRect.top - surfaceRect.top - surface.clientTop + surface.scrollTop : tableTop + cellMapRect.top * fallbackHeight;
21113
21688
  const size = metricOrFallback(cellRect.height, fallbackHeight * Math.max(1, cellMapRect.bottom - cellMapRect.top));
21114
21689
  visualRows.push({
21115
21690
  index: cellMapRect.top,
@@ -21126,7 +21701,7 @@ function buildLogicalRowMetrics({
21126
21701
  return rows.map((tableRow, index) => {
21127
21702
  const rowRect = tableRow.getBoundingClientRect();
21128
21703
  const anchorCell = tableRow.cells.item(0) ?? cornerCell;
21129
- const start = rowRect.height > 0 ? rowRect.top - surfaceRect.top + surface.scrollTop : tableTop + index * fallbackHeight;
21704
+ const start = rowRect.height > 0 ? rowRect.top - surfaceRect.top - surface.clientTop + surface.scrollTop : tableTop + index * fallbackHeight;
21130
21705
  const size = metricOrFallback(rowRect.height, fallbackHeight);
21131
21706
  return {
21132
21707
  index,
@@ -21168,6 +21743,8 @@ function buildTableControlLayout(editor, surface, cell) {
21168
21743
  }
21169
21744
  const map = TableMap4.get(tableInfo.node);
21170
21745
  const surfaceRect = surface.getBoundingClientRect();
21746
+ const surfaceOriginLeft = surfaceRect.left + surface.clientLeft;
21747
+ const surfaceOriginTop = surfaceRect.top + surface.clientTop;
21171
21748
  const tableRect = table.getBoundingClientRect();
21172
21749
  const explicitColumnWidths = Array.from(table.querySelectorAll("colgroup > col")).slice(0, map.width).map((column) => parsePixelMetric(column.style.width));
21173
21750
  const explicitTableWidth = parsePixelMetric(table.style.width) ?? (explicitColumnWidths.length === map.width && explicitColumnWidths.every((width) => width !== null) ? explicitColumnWidths.reduce((sum, width) => sum + width, 0) : null);
@@ -21176,14 +21753,14 @@ function buildTableControlLayout(editor, surface, cell) {
21176
21753
  const wrapperElement = table.closest(".tableWrapper");
21177
21754
  const wrapper = isHTMLElement(wrapperElement) ? wrapperElement : null;
21178
21755
  const wrapperRect = wrapper?.getBoundingClientRect() ?? tableRect;
21179
- const tableLeft = tableRect.left - surfaceRect.left + surface.scrollLeft;
21180
- const tableTop = tableRect.top - surfaceRect.top + surface.scrollTop;
21756
+ const tableLeft = tableRect.left - surfaceOriginLeft + surface.scrollLeft;
21757
+ const tableTop = tableRect.top - surfaceOriginTop + surface.scrollTop;
21181
21758
  const tableWidth = metricOrFallback(tableRect.width, explicitTableWidth ?? FALLBACK_TABLE_COLUMN_WIDTH * map.width);
21182
21759
  const tableHeight = metricOrFallback(tableRect.height, explicitTableHeight ?? FALLBACK_TABLE_ROW_HEIGHT * rows.length);
21183
21760
  const avgRowHeight = metricOrFallback(tableHeight / rows.length, FALLBACK_TABLE_ROW_HEIGHT);
21184
21761
  const avgColumnWidth = metricOrFallback(tableWidth / map.width, FALLBACK_TABLE_COLUMN_WIDTH);
21185
- const wrapperLeft = wrapperRect.left - surfaceRect.left + surface.scrollLeft;
21186
- const wrapperTop = wrapperRect.top - surfaceRect.top + surface.scrollTop;
21762
+ const wrapperLeft = wrapperRect.left - surfaceOriginLeft + surface.scrollLeft;
21763
+ const wrapperTop = wrapperRect.top - surfaceOriginTop + surface.scrollTop;
21187
21764
  const wrapperWidth = metricOrFallback(wrapperRect.width, tableWidth);
21188
21765
  const wrapperHeight = metricOrFallback(wrapperRect.height, tableHeight);
21189
21766
  const viewportWidth = metricOrFallback(wrapper?.clientWidth ?? wrapperRect.width, tableWidth);
@@ -21232,7 +21809,8 @@ function buildTableControlLayout(editor, surface, cell) {
21232
21809
  avgRowHeight,
21233
21810
  avgColumnWidth,
21234
21811
  rowHandles,
21235
- columnHandles
21812
+ columnHandles,
21813
+ widthMode: normalizeTableWidthMode(tableInfo.node.attrs.widthMode)
21236
21814
  };
21237
21815
  }
21238
21816
 
@@ -21265,8 +21843,8 @@ function buildTableHoverState({
21265
21843
  return DEFAULT_TABLE_HOVER_STATE;
21266
21844
  }
21267
21845
  const surfaceRect = surface.getBoundingClientRect();
21268
- const relativeX = event.clientX - surfaceRect.left + surface.scrollLeft;
21269
- const relativeY = event.clientY - surfaceRect.top + surface.scrollTop;
21846
+ const relativeX = event.clientX - surfaceRect.left - surface.clientLeft + surface.scrollLeft;
21847
+ const relativeY = event.clientY - surfaceRect.top - surface.clientTop + surface.scrollTop;
21270
21848
  const targetElement = resolveEventElement(event.target);
21271
21849
  const directRowHandle = targetElement?.closest?.("[data-row-handle-index]");
21272
21850
  const directColumnHandle = targetElement?.closest?.("[data-column-handle-index]");
@@ -21730,11 +22308,17 @@ var HANDLE_BASE_CLASS = cn(
21730
22308
  "hover:bg-primary hover:text-primary-foreground hover:shadow-md active:scale-95",
21731
22309
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
21732
22310
  );
22311
+ var EDGE_HANDLE_CLASS = cn(
22312
+ "pointer-events-auto absolute top-0 z-10 h-full w-2 touch-none cursor-col-resize bg-transparent p-0",
22313
+ "border-transparent transition-colors duration-150 hover:border-primary",
22314
+ "focus-visible:border-primary focus-visible:outline-none"
22315
+ );
21733
22316
  function TableResizeHandles({
21734
22317
  active,
21735
22318
  ctrlHint,
21736
22319
  frameRef,
21737
22320
  layout,
22321
+ onFitWidth,
21738
22322
  onStartResize,
21739
22323
  resizeBothLabel
21740
22324
  }) {
@@ -21755,6 +22339,36 @@ function TableResizeHandles({
21755
22339
  height: layout.tableHeight
21756
22340
  },
21757
22341
  children: [
22342
+ layout.widthMode === "responsive" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
22343
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
22344
+ "button",
22345
+ {
22346
+ type: "button",
22347
+ "aria-label": `${resizeBothLabel} \u2014 \u2190`,
22348
+ title: resizeBothLabel,
22349
+ "data-table-resize-handle": "left",
22350
+ className: cn(
22351
+ EDGE_HANDLE_CLASS,
22352
+ "left-0 border-l-2"
22353
+ ),
22354
+ onPointerDown: (event) => onStartResize(event, "left")
22355
+ }
22356
+ ),
22357
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
22358
+ "button",
22359
+ {
22360
+ type: "button",
22361
+ "aria-label": `${resizeBothLabel} \u2014 \u2192`,
22362
+ title: resizeBothLabel,
22363
+ "data-table-resize-handle": "right",
22364
+ className: cn(
22365
+ EDGE_HANDLE_CLASS,
22366
+ "right-0 border-r-2"
22367
+ ),
22368
+ onPointerDown: (event) => onStartResize(event, "right")
22369
+ }
22370
+ )
22371
+ ] }) : null,
21758
22372
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
21759
22373
  "button",
21760
22374
  {
@@ -21767,7 +22381,8 @@ function TableResizeHandles({
21767
22381
  "bottom-[-28px] right-[-30px] h-6 w-6 cursor-nwse-resize",
21768
22382
  active && "bg-primary text-primary-foreground shadow-md"
21769
22383
  ),
21770
- onPointerDown: onStartResize,
22384
+ onDoubleClick: onFitWidth,
22385
+ onPointerDown: (event) => onStartResize(event, "both"),
21771
22386
  children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react17.MoveDiagonal2, { "aria-hidden": "true", className: "h-3.5 w-3.5", strokeWidth: 2.25 })
21772
22387
  }
21773
22388
  ),
@@ -21788,6 +22403,7 @@ function TableResizeHandles({
21788
22403
 
21789
22404
  // src/components/UEditor/table-size-utils.ts
21790
22405
  init_table_dom_utils();
22406
+ init_table_width_model();
21791
22407
  var MAX_TABLE_DIMENSION = 8192;
21792
22408
  function positiveMetric(value, fallback) {
21793
22409
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
@@ -21830,7 +22446,7 @@ function getLogicalRowHeights(table, fallback) {
21830
22446
  });
21831
22447
  return heights;
21832
22448
  }
21833
- function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight) {
22449
+ function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight, containerWidth = startWidth) {
21834
22450
  const tableInfo = findTableInfo(editor, anchorPos);
21835
22451
  if (!tableInfo) return null;
21836
22452
  const tableMap = TableMap4.get(tableInfo.node);
@@ -21839,13 +22455,16 @@ function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight) {
21839
22455
  const safeHeight = Math.max(tableMap.height * MIN_TABLE_ROW_HEIGHT, Math.round(startHeight));
21840
22456
  const fallbackColumnWidth = safeWidth / tableMap.width;
21841
22457
  const fallbackRowHeight = safeHeight / tableMap.height;
22458
+ const widthMode = normalizeTableWidthMode(tableInfo.node.attrs.widthMode);
22459
+ const safeContainerWidth = Math.max(1, Math.round(containerWidth));
22460
+ const columnWeights = widthMode === "responsive" ? getTableColumnRatios(tableInfo.node) : getLogicalColumnWidths(tableInfo.node, tableMap, fallbackColumnWidth);
21842
22461
  return {
21843
22462
  anchorPos,
21844
22463
  tablePos: tableInfo.pos,
21845
22464
  startWidth: safeWidth,
21846
22465
  startHeight: safeHeight,
21847
22466
  columnWidths: normalizeWeightsToTotal(
21848
- getLogicalColumnWidths(tableInfo.node, tableMap, fallbackColumnWidth),
22467
+ columnWeights,
21849
22468
  safeWidth,
21850
22469
  MIN_RESIZED_TABLE_COLUMN_WIDTH
21851
22470
  ),
@@ -21855,7 +22474,12 @@ function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight) {
21855
22474
  MIN_TABLE_ROW_HEIGHT
21856
22475
  ),
21857
22476
  minWidth: tableMap.width * MIN_RESIZED_TABLE_COLUMN_WIDTH,
21858
- minHeight: tableMap.height * MIN_TABLE_ROW_HEIGHT
22477
+ minHeight: tableMap.height * MIN_TABLE_ROW_HEIGHT,
22478
+ containerWidth: safeContainerWidth,
22479
+ widthMode,
22480
+ widthBp: getResponsiveTableWidthBp(tableInfo.node),
22481
+ offsetBp: getResponsiveTableOffsetBp(tableInfo.node),
22482
+ columnRatios: getTableColumnRatios(tableInfo.node)
21859
22483
  };
21860
22484
  }
21861
22485
  function resolveTableResizeDimensions({
@@ -21863,12 +22487,14 @@ function resolveTableResizeDimensions({
21863
22487
  deltaY,
21864
22488
  lockAxis,
21865
22489
  preserveRatio,
22490
+ edge = "both",
21866
22491
  snapshot
21867
22492
  }) {
21868
- let width = snapshot.startWidth + deltaX;
21869
- let height = snapshot.startHeight + deltaY;
22493
+ const horizontalDelta = edge === "left" ? -deltaX : deltaX;
22494
+ let width = snapshot.startWidth + horizontalDelta;
22495
+ let height = edge === "both" ? snapshot.startHeight + deltaY : snapshot.startHeight;
21870
22496
  if (preserveRatio) {
21871
- const horizontalDrag = Math.abs(deltaX) >= Math.abs(deltaY);
22497
+ const horizontalDrag = edge !== "both" || Math.abs(deltaX) >= Math.abs(deltaY);
21872
22498
  const scale = horizontalDrag ? width / snapshot.startWidth : height / snapshot.startHeight;
21873
22499
  const minScale = Math.max(
21874
22500
  snapshot.minWidth / snapshot.startWidth,
@@ -21881,22 +22507,56 @@ function resolveTableResizeDimensions({
21881
22507
  const safeScale = Math.min(Math.max(scale, minScale), maxScale);
21882
22508
  width = snapshot.startWidth * safeScale;
21883
22509
  height = snapshot.startHeight * safeScale;
21884
- } else if (lockAxis) {
22510
+ } else if (lockAxis && edge === "both") {
21885
22511
  if (Math.abs(deltaX) >= Math.abs(deltaY)) {
21886
22512
  height = snapshot.startHeight;
21887
22513
  } else {
21888
22514
  width = snapshot.startWidth;
21889
22515
  }
21890
22516
  }
22517
+ let nextWidth = Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minWidth, Math.round(width)));
22518
+ const nextHeight = Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minHeight, Math.round(height)));
22519
+ if (snapshot.widthMode !== "responsive") {
22520
+ return { width: nextWidth, height: nextHeight };
22521
+ }
22522
+ const containerWidth = Math.max(1, snapshot.containerWidth);
22523
+ const startOffset = snapshot.offsetBp / TABLE_WIDTH_BASIS_POINTS * containerWidth;
22524
+ let nextOffset = startOffset;
22525
+ if (edge === "left") {
22526
+ const fixedRightEdge = startOffset + snapshot.startWidth;
22527
+ nextOffset = Math.min(
22528
+ fixedRightEdge - snapshot.minWidth,
22529
+ Math.max(0, startOffset + deltaX)
22530
+ );
22531
+ nextWidth = fixedRightEdge - nextOffset;
22532
+ }
22533
+ const widthBp = clampResponsiveTableWidthBp(
22534
+ nextWidth / containerWidth * TABLE_WIDTH_BASIS_POINTS
22535
+ );
22536
+ const offsetBp = resolveResponsiveTableOffsetBp(
22537
+ widthBp,
22538
+ null,
22539
+ nextOffset / containerWidth * TABLE_WIDTH_BASIS_POINTS
22540
+ );
21891
22541
  return {
21892
- width: Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minWidth, Math.round(width))),
21893
- height: Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minHeight, Math.round(height)))
22542
+ width: Math.round(widthBp / TABLE_WIDTH_BASIS_POINTS * containerWidth),
22543
+ height: nextHeight,
22544
+ widthBp,
22545
+ offsetBp,
22546
+ leftDelta: nextOffset - startOffset
21894
22547
  };
21895
22548
  }
21896
22549
  function arraysEqual(left, right) {
21897
22550
  return Array.isArray(left) && left.length === right.length && left.every((value, index) => value === right[index]);
21898
22551
  }
21899
- function applyTableSize(editor, snapshot, dimensions) {
22552
+ function getResponsiveResizeAlignment(widthBp, offsetBp) {
22553
+ const gap = Math.max(0, TABLE_WIDTH_BASIS_POINTS - widthBp);
22554
+ if (offsetBp === 0) return "left";
22555
+ if (offsetBp === gap) return "right";
22556
+ if (Math.abs(offsetBp * 2 - gap) <= 1) return "center";
22557
+ return null;
22558
+ }
22559
+ function applyTableSize(editor, snapshot, dimensions, options = {}) {
21900
22560
  const table = editor.state.doc.nodeAt(snapshot.tablePos);
21901
22561
  if (!table || table.type.name !== "table") return false;
21902
22562
  const tableMap = TableMap4.get(table);
@@ -21905,9 +22565,32 @@ function applyTableSize(editor, snapshot, dimensions) {
21905
22565
  }
21906
22566
  const resizeWidth = dimensions.width !== snapshot.startWidth;
21907
22567
  const resizeHeight = dimensions.height !== snapshot.startHeight;
21908
- if (!resizeWidth && !resizeHeight) return false;
22568
+ const widthMode = options.widthMode ?? snapshot.widthMode;
22569
+ const widthModeChanged = normalizeTableWidthMode(table.attrs.widthMode) !== widthMode || widthMode === "responsive" && table.attrs.widthMode !== "responsive";
22570
+ const widthBp = dimensions.widthBp ?? clampResponsiveTableWidthBp(
22571
+ dimensions.width / Math.max(1, snapshot.containerWidth) * TABLE_WIDTH_BASIS_POINTS
22572
+ );
22573
+ const offsetBp = resolveResponsiveTableOffsetBp(
22574
+ widthBp,
22575
+ null,
22576
+ dimensions.offsetBp ?? snapshot.offsetBp
22577
+ );
22578
+ const responsiveLayoutChanged = widthMode === "responsive" && (table.attrs.widthBp !== widthBp || table.attrs.offsetBp !== offsetBp);
22579
+ if (!resizeWidth && !resizeHeight && !widthModeChanged && !responsiveLayoutChanged) return false;
21909
22580
  const tableStart = snapshot.tablePos + 1;
21910
22581
  const transaction = editor.state.tr;
22582
+ if (widthModeChanged || responsiveLayoutChanged) {
22583
+ transaction.setNodeMarkup(snapshot.tablePos, void 0, {
22584
+ ...table.attrs,
22585
+ widthMode,
22586
+ ...widthMode === "responsive" ? {
22587
+ widthBp,
22588
+ offsetBp,
22589
+ columnRatios: normalizeColumnRatios(snapshot.columnRatios, tableMap.width),
22590
+ textAlign: getResponsiveResizeAlignment(widthBp, offsetBp)
22591
+ } : null
22592
+ });
22593
+ }
21911
22594
  if (resizeWidth) {
21912
22595
  const nextColumnWidths = normalizeWeightsToTotal(
21913
22596
  snapshot.columnWidths,
@@ -21950,6 +22633,7 @@ function applyTableSize(editor, snapshot, dimensions) {
21950
22633
  }
21951
22634
 
21952
22635
  // src/components/UEditor/table-controls.tsx
22636
+ init_table_width_model();
21953
22637
  var import_jsx_runtime34 = require("react/jsx-runtime");
21954
22638
  var TABLE_MENU_TOP_OFFSET = 10;
21955
22639
  var AXIS_HANDLE_RADIUS = 12;
@@ -22059,6 +22743,10 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
22059
22743
  if (!frame) return;
22060
22744
  frame.style.width = `${dimensions.width}px`;
22061
22745
  frame.style.height = `${dimensions.height}px`;
22746
+ const activeLayout = layoutRef.current;
22747
+ if (activeLayout) {
22748
+ frame.style.left = `${activeLayout.tableLeft + (dimensions.leftDelta ?? 0)}px`;
22749
+ }
22062
22750
  const dimensionsLabel = frame.querySelector("[data-table-resize-dimensions]");
22063
22751
  if (dimensionsLabel) {
22064
22752
  dimensionsLabel.textContent = `${dimensions.width} \xD7 ${dimensions.height}`;
@@ -22069,7 +22757,8 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
22069
22757
  if (!activeLayout) return;
22070
22758
  updateTableResizePreview({
22071
22759
  width: Math.round(activeLayout.tableWidth),
22072
- height: Math.round(activeLayout.tableHeight)
22760
+ height: Math.round(activeLayout.tableHeight),
22761
+ leftDelta: 0
22073
22762
  });
22074
22763
  }, [updateTableResizePreview]);
22075
22764
  const clearDrag = import_react37.default.useCallback(() => {
@@ -22174,6 +22863,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
22174
22863
  surface.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleCurrentLayoutRefresh);
22175
22864
  if (!editorWindow) return void 0;
22176
22865
  const unsubscribeResize = subscribeSharedGlobalEvent(editorWindow, "resize", scheduleCurrentLayoutRefresh);
22866
+ const unsubscribeWindowScroll = subscribeSharedGlobalEvent(editorWindow, "scroll", scheduleCurrentLayoutRefresh, { passive: true });
22177
22867
  editor.on("selectionUpdate", scheduleSyncFromSelection);
22178
22868
  editor.on("update", scheduleCurrentLayoutRefresh);
22179
22869
  syncFromSelection();
@@ -22189,6 +22879,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
22189
22879
  surface.removeEventListener("scroll", scheduleCurrentLayoutRefresh, scrollListenerOptions);
22190
22880
  surface.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleCurrentLayoutRefresh);
22191
22881
  unsubscribeResize();
22882
+ unsubscribeWindowScroll();
22192
22883
  editor.off("selectionUpdate", scheduleSyncFromSelection);
22193
22884
  editor.off("update", scheduleCurrentLayoutRefresh);
22194
22885
  };
@@ -22232,7 +22923,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
22232
22923
  const canExpandTable = Boolean(layout);
22233
22924
  const controlsVisible = false;
22234
22925
  const tableMenuOpen = openMenuKey === "table";
22235
- const startTableResize = import_react37.default.useCallback((event) => {
22926
+ const startTableResize = import_react37.default.useCallback((event, edge) => {
22236
22927
  if (event.button !== 0 || dragStateRef.current) return;
22237
22928
  const activeLayout = layoutRef.current;
22238
22929
  if (!activeLayout) return;
@@ -22240,7 +22931,8 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
22240
22931
  editor,
22241
22932
  activeLayout.cellPos,
22242
22933
  activeLayout.tableWidth,
22243
- activeLayout.tableHeight
22934
+ activeLayout.tableHeight,
22935
+ activeLayout.viewportWidth
22244
22936
  );
22245
22937
  if (!snapshot) return;
22246
22938
  event.preventDefault();
@@ -22262,12 +22954,38 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
22262
22954
  pointerTarget: event.currentTarget,
22263
22955
  startX: event.clientX,
22264
22956
  startY: event.clientY,
22957
+ edge,
22265
22958
  snapshot,
22266
22959
  pendingDimensions
22267
22960
  };
22268
22961
  updateTableResizePreview(pendingDimensions);
22269
- setDocumentCursor(editorDocument, "nwse-resize");
22962
+ setDocumentCursor(editorDocument, edge === "both" ? "nwse-resize" : "ew-resize");
22270
22963
  }, [editor, editorDocument, updateTableResizePreview]);
22964
+ const fitTableToEditorWidth = import_react37.default.useCallback((event) => {
22965
+ if (event.button !== 0 || dragStateRef.current) return;
22966
+ const activeLayout = layoutRef.current;
22967
+ if (!activeLayout) return;
22968
+ const snapshot = createTableSizeSnapshot(
22969
+ editor,
22970
+ activeLayout.cellPos,
22971
+ activeLayout.tableWidth,
22972
+ activeLayout.tableHeight,
22973
+ activeLayout.viewportWidth
22974
+ );
22975
+ if (!snapshot) return;
22976
+ event.preventDefault();
22977
+ event.stopPropagation();
22978
+ const didResize = applyTableSize(editor, snapshot, {
22979
+ width: Math.round(activeLayout.viewportWidth),
22980
+ height: snapshot.startHeight,
22981
+ widthBp: TABLE_WIDTH_BASIS_POINTS,
22982
+ offsetBp: 0,
22983
+ leftDelta: -(snapshot.offsetBp / TABLE_WIDTH_BASIS_POINTS * snapshot.containerWidth)
22984
+ }, { widthMode: "responsive" });
22985
+ if (didResize) {
22986
+ scheduleSyncFromSelection();
22987
+ }
22988
+ }, [editor, scheduleSyncFromSelection]);
22271
22989
  const startAddColumnDrag = import_react37.default.useCallback(() => {
22272
22990
  setOpenMenuKey(null);
22273
22991
  dragStateRef.current = { kind: "add-column", previewCols: 1 };
@@ -22382,12 +23100,30 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
22382
23100
  scheduleSyncFromSelection();
22383
23101
  }
22384
23102
  if (dragState.kind === "column" && dragState.originIndex !== dragState.targetIndex) {
23103
+ const tableInfo = findTableInfo(editor, dragState.anchorPos);
23104
+ const responsiveRatios = tableInfo && normalizeTableWidthMode(tableInfo.node.attrs.widthMode) === "responsive" ? moveResponsiveColumnRatio(
23105
+ getTableColumnRatios(tableInfo.node),
23106
+ dragState.originIndex,
23107
+ dragState.targetIndex
23108
+ ) : null;
22385
23109
  moveTableColumn({
22386
23110
  from: dragState.originIndex,
22387
23111
  to: dragState.targetIndex,
22388
23112
  pos: dragState.anchorPos,
22389
23113
  select: true
22390
- })(editor.state, editor.view.dispatch);
23114
+ })(editor.state, (transaction) => {
23115
+ if (tableInfo && responsiveRatios) {
23116
+ const nextTable = transaction.doc.nodeAt(tableInfo.pos);
23117
+ if (nextTable?.type.name === "table") {
23118
+ transaction.setNodeMarkup(tableInfo.pos, void 0, {
23119
+ ...nextTable.attrs,
23120
+ widthMode: "responsive",
23121
+ columnRatios: responsiveRatios
23122
+ });
23123
+ }
23124
+ }
23125
+ editor.view.dispatch(transaction);
23126
+ });
22391
23127
  scheduleSyncFromSelection();
22392
23128
  }
22393
23129
  if (dragState.kind === "add-row") {
@@ -22421,6 +23157,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
22421
23157
  deltaY: event.clientY - dragState.startY,
22422
23158
  lockAxis: event.ctrlKey && !event.shiftKey,
22423
23159
  preserveRatio: event.ctrlKey && event.shiftKey,
23160
+ edge: dragState.edge,
22424
23161
  snapshot: dragState.snapshot
22425
23162
  });
22426
23163
  if (tableResizePreviewFrameRef.current === null) {
@@ -22432,7 +23169,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
22432
23169
  updateTableResizePreview(currentDragState.pendingDimensions);
22433
23170
  });
22434
23171
  }
22435
- setDocumentCursor(editorDocument, "nwse-resize");
23172
+ setDocumentCursor(editorDocument, dragState.edge === "both" ? "nwse-resize" : "ew-resize");
22436
23173
  if (event.cancelable) event.preventDefault();
22437
23174
  };
22438
23175
  const finishTableResize = (event, commit) => {
@@ -22443,7 +23180,12 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
22443
23180
  tableResizePreviewFrameRef.current = null;
22444
23181
  }
22445
23182
  updateTableResizePreview(dragState.pendingDimensions);
22446
- if (commit && applyTableSize(editor, dragState.snapshot, dragState.pendingDimensions)) {
23183
+ if (commit && applyTableSize(
23184
+ editor,
23185
+ dragState.snapshot,
23186
+ dragState.pendingDimensions,
23187
+ { widthMode: dragState.snapshot.widthMode }
23188
+ )) {
22447
23189
  scheduleSyncFromSelection();
22448
23190
  }
22449
23191
  clearDrag();
@@ -22681,6 +23423,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
22681
23423
  ctrlHint: t("tableMenu.resizeCtrlHint"),
22682
23424
  frameRef: tableResizeFrameRef,
22683
23425
  layout,
23426
+ onFitWidth: fitTableToEditorWidth,
22684
23427
  onStartResize: startTableResize,
22685
23428
  resizeBothLabel: t("tableMenu.resizeBoth")
22686
23429
  }