@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.
@@ -7,6 +7,7 @@ import {
7
7
  CellBgColorIcon,
8
8
  CellBorderIcon,
9
9
  ClipboardImages,
10
+ DEFAULT_RESPONSIVE_TABLE_WIDTH_BP,
10
11
  DEFAULT_TABLE_ROW_HEIGHT,
11
12
  DropdownMenu,
12
13
  DropdownMenuItem,
@@ -18,6 +19,7 @@ import {
18
19
  MIN_TABLE_ROW_HEIGHT,
19
20
  Popover,
20
21
  ROW_RESIZE_LINE_THICKNESS,
22
+ TABLE_WIDTH_BASIS_POINTS,
21
23
  TextColorIcon,
22
24
  ToolbarButton,
23
25
  UEDITOR_PROSEMIRROR_CLASS_NAME,
@@ -26,8 +28,10 @@ import {
26
28
  applyImageLayout,
27
29
  applyImageWidthPreset,
28
30
  applyTableAlignment,
31
+ clampResponsiveTableWidthBp,
29
32
  clearTableColumnAt,
30
33
  clearTableRowAt,
34
+ deleteResponsiveColumnLayout,
31
35
  deleteSelectedImage,
32
36
  dispatchTableLayoutChange,
33
37
  duplicateTableColumnAt,
@@ -35,12 +39,19 @@ import {
35
39
  expandTableFromCell,
36
40
  findTableNodeInfoFromState,
37
41
  findTableRowNodeInfo,
42
+ formatBasisPointsAsPercentage,
38
43
  getDefaultFontSizes,
39
44
  getDefaultLineHeights,
45
+ getLegacyTableColumnWeights,
46
+ getLogicalTableColumnCount,
40
47
  getRelativeBoundaryMetrics,
41
48
  getRelativeCellMetrics,
42
49
  getRelativeSelectedCellsMetrics,
50
+ getResponsiveTableOffsetBp,
51
+ getResponsiveTableWidthBp,
43
52
  getSelectionTableCell,
53
+ getTableColumnRatios,
54
+ insertResponsiveColumnLayout,
44
55
  isCrossRealmElement,
45
56
  isCrossRealmHTMLElement,
46
57
  isCrossRealmNode,
@@ -52,16 +63,22 @@ import {
52
63
  isRowResizingGlobal,
53
64
  isSafeUEditorUrl,
54
65
  mergeTableCellsPreservingColumnWidths,
66
+ moveResponsiveColumnRatio,
67
+ normalizeColumnRatios,
55
68
  normalizeStyleValue,
69
+ normalizeTableWidthMode,
70
+ parseColumnRatios,
71
+ parsePercentageToBasisPoints,
56
72
  resetImageSize,
57
73
  resolveColumnResizeTarget,
58
74
  resolveEventElement,
75
+ resolveResponsiveTableOffsetBp,
59
76
  resolveRowResizeTarget,
60
77
  runTableCommandAtCellPos,
61
78
  sanitizeUEditorUrl,
62
79
  useEditorColors,
63
80
  useSharedEditorUiRenderState
64
- } from "./chunk-BDRCOIYR.js";
81
+ } from "./chunk-5QWYO527.js";
65
82
  import {
66
83
  Tooltip,
67
84
  UEditorPortalProvider,
@@ -3339,8 +3356,15 @@ var indent_default = Indent;
3339
3356
  // src/components/UEditor/table-align.ts
3340
3357
  import { mergeAttributes as mergeAttributes7 } from "@tiptap/core";
3341
3358
  import { Table as Table2 } from "@tiptap/extension-table";
3342
- import { Plugin as Plugin4, PluginKey as PluginKey5 } from "@tiptap/pm/state";
3343
- import { tableEditing } from "@tiptap/pm/tables";
3359
+ import { Plugin as Plugin4, PluginKey as PluginKey5, TextSelection } from "@tiptap/pm/state";
3360
+ import {
3361
+ addColumnAfter as addColumnAfterCommand,
3362
+ addColumnBefore as addColumnBeforeCommand,
3363
+ deleteColumn as deleteColumnCommand,
3364
+ selectedRect,
3365
+ tableEditing,
3366
+ tableNodeTypes as tableNodeTypes2
3367
+ } from "@tiptap/pm/tables";
3344
3368
 
3345
3369
  // src/components/UEditor/table-column-resize.ts
3346
3370
  import { Plugin as Plugin3 } from "@tiptap/pm/state";
@@ -3361,14 +3385,10 @@ function getColumnResizeMinWidth(configuredMinWidth) {
3361
3385
  const normalizedMinWidth = Number.isFinite(configuredMinWidth) && configuredMinWidth > 0 ? Math.round(configuredMinWidth) : MIN_RESIZED_TABLE_COLUMN_WIDTH;
3362
3386
  return Math.max(MIN_RESIZED_TABLE_COLUMN_WIDTH, normalizedMinWidth);
3363
3387
  }
3364
- function setColumnStyle(column, width) {
3365
- if (width == null) {
3366
- column.style.width = `${DEFAULT_TABLE_COLUMN_WIDTH}px`;
3367
- column.style.minWidth = `${DEFAULT_TABLE_COLUMN_WIDTH}px`;
3368
- return;
3369
- }
3370
- column.style.width = `${Math.max(width, MIN_RESIZED_TABLE_COLUMN_WIDTH)}px`;
3371
- column.style.minWidth = "";
3388
+ function setColumnStyle(column, width, ratio, explicit, responsive) {
3389
+ column.style.width = responsive ? formatBasisPointsAsPercentage(ratio) : `${width}px`;
3390
+ column.style.minWidth = responsive || explicit ? "" : `${width}px`;
3391
+ column.setAttribute("width", String(width));
3372
3392
  }
3373
3393
  function isTableColumnElement(node) {
3374
3394
  return isCrossRealmElement(node) && String(node.tagName).toUpperCase() === "COL";
@@ -3377,6 +3397,7 @@ function updateDynamicColumns(node, colgroup, table, ownerDocument, overrideCol,
3377
3397
  let totalWidth = 0;
3378
3398
  let nextDOM = colgroup.firstChild;
3379
3399
  const row = node.firstChild;
3400
+ const columns = [];
3380
3401
  if (row) {
3381
3402
  for (let rowCellIndex = 0, col = 0; rowCellIndex < row.childCount; rowCellIndex += 1) {
3382
3403
  const { colspan, colwidth } = row.child(rowCellIndex).attrs;
@@ -3385,7 +3406,11 @@ function updateDynamicColumns(node, colgroup, table, ownerDocument, overrideCol,
3385
3406
  const width = rawWidth ? Math.max(rawWidth, MIN_RESIZED_TABLE_COLUMN_WIDTH) : null;
3386
3407
  totalWidth += width ?? DEFAULT_TABLE_COLUMN_WIDTH;
3387
3408
  const colElement = isTableColumnElement(nextDOM) ? nextDOM : colgroup.appendChild(ownerDocument.createElement("col"));
3388
- setColumnStyle(colElement, width);
3409
+ columns.push({
3410
+ element: colElement,
3411
+ explicit: width !== null,
3412
+ width: width ?? DEFAULT_TABLE_COLUMN_WIDTH
3413
+ });
3389
3414
  nextDOM = colElement.nextSibling;
3390
3415
  }
3391
3416
  }
@@ -3395,13 +3420,39 @@ function updateDynamicColumns(node, colgroup, table, ownerDocument, overrideCol,
3395
3420
  nextDOM.parentNode?.removeChild(nextDOM);
3396
3421
  nextDOM = after;
3397
3422
  }
3398
- const hasUserWidth = typeof node.attrs.style === "string" && /\bwidth\s*:/i.test(node.attrs.style);
3399
- if (!hasUserWidth) {
3423
+ const responsive = normalizeTableWidthMode(node.attrs.widthMode) === "responsive";
3424
+ const columnRatios = getTableColumnRatios(node);
3425
+ columns.forEach(({ element, explicit, width }, index) => {
3426
+ setColumnStyle(element, width, columnRatios[index] ?? 1, explicit, responsive);
3427
+ });
3428
+ if (responsive) {
3429
+ const widthBp = getResponsiveTableWidthBp(node);
3430
+ const offsetBp = getResponsiveTableOffsetBp(node);
3431
+ table.setAttribute("data-table-width-mode", "responsive");
3432
+ table.setAttribute("data-table-width", formatBasisPointsAsPercentage(widthBp));
3433
+ table.setAttribute("data-table-width-bp", String(widthBp));
3434
+ table.setAttribute("data-table-offset", formatBasisPointsAsPercentage(offsetBp));
3435
+ table.setAttribute("data-table-offset-bp", String(offsetBp));
3436
+ table.setAttribute("data-table-column-ratios", columnRatios.join(","));
3437
+ table.style.width = formatBasisPointsAsPercentage(widthBp);
3438
+ table.style.marginLeft = formatBasisPointsAsPercentage(offsetBp);
3439
+ table.style.marginRight = "auto";
3440
+ table.style.minWidth = `${Math.max(1, colgroup.childElementCount) * MIN_RESIZED_TABLE_COLUMN_WIDTH}px`;
3441
+ } else {
3442
+ table.removeAttribute("data-table-width-mode");
3443
+ table.removeAttribute("data-table-width");
3444
+ table.removeAttribute("data-table-width-bp");
3445
+ table.removeAttribute("data-table-offset");
3446
+ table.removeAttribute("data-table-offset-bp");
3447
+ table.removeAttribute("data-table-column-ratios");
3400
3448
  table.style.width = `${totalWidth}px`;
3401
3449
  table.style.minWidth = "";
3402
- } else {
3403
- table.style.minWidth = `${totalWidth}px`;
3450
+ const tableAlign = node.attrs.textAlign;
3451
+ table.style.marginLeft = tableAlign === "center" || tableAlign === "right" ? "auto" : "0px";
3452
+ table.style.marginRight = tableAlign === "center" ? "auto" : tableAlign === "right" ? "0px" : "auto";
3404
3453
  }
3454
+ if (node.attrs.textAlign) table.setAttribute("data-table-align", String(node.attrs.textAlign));
3455
+ else table.removeAttribute("data-table-align");
3405
3456
  }
3406
3457
  var UEditorTableView = class {
3407
3458
  constructor(node, _defaultColumnWidth, maybeView) {
@@ -3437,7 +3488,40 @@ var UEditorTableView = class {
3437
3488
  };
3438
3489
  function getDraggedWidth(dragging, event) {
3439
3490
  const offset = event.clientX - dragging.startX;
3440
- return Math.max(dragging.minWidth, Math.round(dragging.startWidth + offset));
3491
+ const maximum = dragging.neighborStartWidth === void 0 ? Number.POSITIVE_INFINITY : dragging.startWidth + dragging.neighborStartWidth - dragging.minWidth;
3492
+ return Math.min(maximum, Math.max(dragging.minWidth, Math.round(dragging.startWidth + offset)));
3493
+ }
3494
+ function normalizeColumnWidthsToTotal(values, total, minimum) {
3495
+ const safeTotal = Math.max(values.length * minimum, Math.round(total));
3496
+ const weights = values.map((value) => Number.isFinite(value) && value > 0 ? value : DEFAULT_TABLE_COLUMN_WIDTH);
3497
+ const weightSum = weights.reduce((sum, value) => sum + value, 0);
3498
+ const widths = weights.map((value) => Math.max(minimum, Math.round(value / weightSum * safeTotal)));
3499
+ let difference = safeTotal - widths.reduce((sum, value) => sum + value, 0);
3500
+ while (difference !== 0) {
3501
+ let changed = false;
3502
+ for (let index = widths.length - 1; index >= 0 && difference !== 0; index -= 1) {
3503
+ if (difference < 0 && widths[index] <= minimum) continue;
3504
+ widths[index] += difference > 0 ? 1 : -1;
3505
+ difference += difference > 0 ? -1 : 1;
3506
+ changed = true;
3507
+ }
3508
+ if (!changed) break;
3509
+ }
3510
+ return widths;
3511
+ }
3512
+ function getResizeColumnInfo(state, cell) {
3513
+ const $cell = state.doc.resolve(cell);
3514
+ const table = $cell.node(-1);
3515
+ const map = TableMap.get(table);
3516
+ const start = $cell.start(-1);
3517
+ const nodeAfter = $cell.nodeAfter;
3518
+ if (!nodeAfter) return null;
3519
+ return {
3520
+ col: map.colCount($cell.pos - start) + nodeAfter.attrs.colspan - 1,
3521
+ map,
3522
+ start,
3523
+ table
3524
+ };
3441
3525
  }
3442
3526
  function getCurrentColWidth(view, cellPos, { colspan, colwidth }) {
3443
3527
  const width = colwidth?.[colwidth.length - 1];
@@ -3506,6 +3590,12 @@ function handleMouseMove(view, event, handleWidth, lastColumnResizable) {
3506
3590
  if (event.clientX - left <= handleWidth) cell = edgeCell(view, event, "left", handleWidth);
3507
3591
  else if (right - event.clientX <= handleWidth) cell = edgeCell(view, event, "right", handleWidth);
3508
3592
  }
3593
+ if (cell !== -1) {
3594
+ const info = getResizeColumnInfo(view.state, cell);
3595
+ if (info && normalizeTableWidthMode(info.table.attrs.widthMode) === "responsive" && info.col === info.map.width - 1) {
3596
+ cell = -1;
3597
+ }
3598
+ }
3509
3599
  if (cell === pluginState.activeHandle) {
3510
3600
  clearHandleHoverTimer();
3511
3601
  return;
@@ -3552,33 +3642,47 @@ function handleMouseLeave(view) {
3552
3642
  updateHandle(view, -1);
3553
3643
  }
3554
3644
  }
3555
- function updateColumnWidth(view, cell, width) {
3556
- const $cell = view.state.doc.resolve(cell);
3557
- const table = $cell.node(-1);
3558
- const map = TableMap.get(table);
3559
- const start = $cell.start(-1);
3560
- const nodeAfter = $cell.nodeAfter;
3561
- if (!nodeAfter) return;
3562
- const col = map.colCount($cell.pos - start) + nodeAfter.attrs.colspan - 1;
3645
+ function updateColumnWidths(view, cell, widthsByColumn, columnRatios) {
3646
+ const info = getResizeColumnInfo(view.state, cell);
3647
+ if (!info) return;
3648
+ const { map, start, table } = info;
3563
3649
  const tr = view.state.tr;
3564
- for (let row = 0; row < map.height; row += 1) {
3565
- const mapIndex = row * map.width + col;
3566
- if (row && map.map[mapIndex] === map.map[mapIndex - map.width]) continue;
3567
- const pos = map.map[mapIndex];
3650
+ const seenCellPositions = /* @__PURE__ */ new Set();
3651
+ for (const pos of map.map) {
3652
+ if (seenCellPositions.has(pos)) continue;
3653
+ seenCellPositions.add(pos);
3568
3654
  const cellNode = table.nodeAt(pos);
3569
3655
  if (!cellNode) continue;
3570
3656
  const attrs = cellNode.attrs;
3571
- const index = attrs.colspan === 1 ? 0 : col - map.colCount(pos);
3572
- if (attrs.colwidth?.[index] === width) continue;
3573
3657
  const colwidth = attrs.colwidth ? attrs.colwidth.slice() : Array.from({ length: attrs.colspan }, () => 0);
3574
- colwidth[index] = width;
3658
+ const cellStartColumn = map.colCount(pos);
3659
+ let changed = false;
3660
+ for (let index = 0; index < attrs.colspan; index += 1) {
3661
+ const width = widthsByColumn.get(cellStartColumn + index);
3662
+ if (width === void 0 || colwidth[index] === width) continue;
3663
+ colwidth[index] = width;
3664
+ changed = true;
3665
+ }
3666
+ if (!changed) continue;
3575
3667
  tr.setNodeMarkup(start + pos, null, {
3576
3668
  ...attrs,
3577
3669
  colwidth
3578
3670
  });
3579
3671
  }
3672
+ if (columnRatios) {
3673
+ tr.setNodeMarkup(start - 1, void 0, {
3674
+ ...table.attrs,
3675
+ widthMode: "responsive",
3676
+ columnRatios: normalizeColumnRatios(columnRatios, map.width)
3677
+ });
3678
+ }
3580
3679
  if (tr.docChanged) view.dispatch(tr);
3581
3680
  }
3681
+ function updateColumnWidth(view, cell, width) {
3682
+ const info = getResizeColumnInfo(view.state, cell);
3683
+ if (!info) return;
3684
+ updateColumnWidths(view, cell, /* @__PURE__ */ new Map([[info.col, width]]));
3685
+ }
3582
3686
  function getActiveDragging(state) {
3583
3687
  const dragging = columnResizingPluginKey.getState(state)?.dragging;
3584
3688
  return dragging ? dragging : null;
@@ -3630,16 +3734,36 @@ function handleMouseDown(view, event, cellMinWidth) {
3630
3734
  if (!pluginState || pluginState.activeHandle === -1 || pluginState.dragging) return false;
3631
3735
  const cell = view.state.doc.nodeAt(pluginState.activeHandle);
3632
3736
  if (!cell) return false;
3737
+ const resizeInfo = getResizeColumnInfo(view.state, pluginState.activeHandle);
3738
+ if (!resizeInfo) return false;
3633
3739
  const attrs = cell.attrs;
3634
- const width = getCurrentColWidth(view, pluginState.activeHandle, {
3740
+ let width = getCurrentColWidth(view, pluginState.activeHandle, {
3635
3741
  colspan: attrs.colspan ?? 1,
3636
3742
  colwidth: attrs.colwidth
3637
3743
  });
3638
3744
  const minWidth = getColumnResizeMinWidth(cellMinWidth);
3745
+ let responsiveColumnWidths;
3746
+ let neighborStartWidth;
3747
+ if (normalizeTableWidthMode(resizeInfo.table.attrs.widthMode) === "responsive") {
3748
+ if (resizeInfo.col >= resizeInfo.map.width - 1) return false;
3749
+ const storedRatios = getTableColumnRatios(resizeInfo.table);
3750
+ const legacyWidths = getLegacyTableColumnWeights(resizeInfo.table, DEFAULT_TABLE_COLUMN_WIDTH);
3751
+ const storedTotal = legacyWidths.reduce((sum, value) => sum + value, 0);
3752
+ const tableElement = getTableElementAtCell(view, pluginState.activeHandle);
3753
+ const renderedWidth = tableElement?.getBoundingClientRect().width || storedTotal;
3754
+ responsiveColumnWidths = normalizeColumnWidthsToTotal(storedRatios, renderedWidth, minWidth);
3755
+ width = responsiveColumnWidths[resizeInfo.col];
3756
+ neighborStartWidth = responsiveColumnWidths[resizeInfo.col + 1];
3757
+ }
3639
3758
  const dragging = {
3640
3759
  startX: event.clientX,
3641
3760
  startWidth: width,
3642
- minWidth
3761
+ minWidth,
3762
+ ...responsiveColumnWidths ? {
3763
+ columnIndex: resizeInfo.col,
3764
+ responsiveColumnWidths,
3765
+ neighborStartWidth
3766
+ } : null
3643
3767
  };
3644
3768
  view.dispatch(view.state.tr.setMeta(columnResizingPluginKey, { setDragging: dragging }));
3645
3769
  function finish(nextEvent) {
@@ -3648,7 +3772,20 @@ function handleMouseDown(view, event, cellMinWidth) {
3648
3772
  const activeDragging = getActiveDragging(view.state);
3649
3773
  const activeHandle = columnResizingPluginKey.getState(view.state)?.activeHandle ?? -1;
3650
3774
  if (activeDragging && activeHandle > -1) {
3651
- updateColumnWidth(view, activeHandle, getDraggedWidth(activeDragging, nextEvent));
3775
+ const nextWidth = getDraggedWidth(activeDragging, nextEvent);
3776
+ if (activeDragging.responsiveColumnWidths && activeDragging.columnIndex !== void 0 && activeDragging.neighborStartWidth !== void 0) {
3777
+ const nextColumnWidths = activeDragging.responsiveColumnWidths.slice();
3778
+ nextColumnWidths[activeDragging.columnIndex] = nextWidth;
3779
+ nextColumnWidths[activeDragging.columnIndex + 1] = activeDragging.startWidth + activeDragging.neighborStartWidth - nextWidth;
3780
+ updateColumnWidths(
3781
+ view,
3782
+ activeHandle,
3783
+ new Map(nextColumnWidths.map((columnWidth, index) => [index, columnWidth])),
3784
+ normalizeColumnRatios(nextColumnWidths, nextColumnWidths.length)
3785
+ );
3786
+ } else {
3787
+ updateColumnWidth(view, activeHandle, nextWidth);
3788
+ }
3652
3789
  view.dispatch(view.state.tr.setMeta(columnResizingPluginKey, { setDragging: null }));
3653
3790
  }
3654
3791
  hideColumnResizeGhost(view);
@@ -3678,6 +3815,9 @@ function handleDecorations(state, cell, ownerDocument) {
3678
3815
  const nodeAfter = $cell.nodeAfter;
3679
3816
  if (!nodeAfter) return DecorationSet2.empty;
3680
3817
  const col = map.colCount($cell.pos - start) + nodeAfter.attrs.colspan - 1;
3818
+ if (normalizeTableWidthMode(table.attrs.widthMode) === "responsive" && col === map.width - 1) {
3819
+ return DecorationSet2.empty;
3820
+ }
3681
3821
  for (let row = 0; row < map.height; row += 1) {
3682
3822
  const index = col + row * map.width;
3683
3823
  if ((col === map.width - 1 || map.map[index] !== map.map[index + 1]) && (row === 0 || map.map[index] !== map.map[index - map.width])) {
@@ -3765,7 +3905,7 @@ function parseTableAlign(element) {
3765
3905
  if ((marginLeft === "0px" || marginLeft === "0") && marginRight === "auto") return "left";
3766
3906
  return null;
3767
3907
  }
3768
- function renderTableAlignStyle(tableAlign) {
3908
+ function renderFixedTableAlignStyle(tableAlign) {
3769
3909
  switch (tableAlign) {
3770
3910
  case "center":
3771
3911
  return "table-layout: fixed; margin-left: auto; margin-right: auto;";
@@ -3777,28 +3917,61 @@ function renderTableAlignStyle(tableAlign) {
3777
3917
  return "";
3778
3918
  }
3779
3919
  }
3780
- function createUEditorColGroup(node) {
3781
- const columns = [];
3782
- let totalWidth = 0;
3783
- const firstRow = node.firstChild;
3784
- if (firstRow) {
3785
- for (let cellIndex = 0; cellIndex < firstRow.childCount; cellIndex += 1) {
3786
- const cell = firstRow.child(cellIndex);
3787
- const colspan = Math.max(1, Number(cell.attrs.colspan) || 1);
3788
- const colwidth = Array.isArray(cell.attrs.colwidth) ? cell.attrs.colwidth : [];
3789
- for (let spanIndex = 0; spanIndex < colspan; spanIndex += 1) {
3790
- const storedWidth = Number(colwidth[spanIndex]);
3791
- const width = Number.isFinite(storedWidth) && storedWidth > 0 ? Math.max(MIN_RESIZED_TABLE_COLUMN_WIDTH, Math.round(storedWidth)) : DEFAULT_TABLE_COLUMN_WIDTH;
3792
- totalWidth += width;
3793
- columns.push(["col", { style: `width: ${width}px; min-width: ${width}px;`, width: String(width) }]);
3794
- }
3795
- }
3920
+ function parseTableWidthMode(element) {
3921
+ const storedMode = element.getAttribute("data-table-width-mode");
3922
+ if (storedMode === "responsive" || storedMode === "full" || parsePercentageToBasisPoints(element.style.width) !== null) {
3923
+ return "responsive";
3796
3924
  }
3925
+ return "fixed";
3926
+ }
3927
+ function createUEditorColGroup(node, widthMode) {
3928
+ const columnWidths = getLegacyTableColumnWeights(node, DEFAULT_TABLE_COLUMN_WIDTH).map((width) => Math.max(MIN_RESIZED_TABLE_COLUMN_WIDTH, Math.round(width)));
3929
+ const columnRatios = getTableColumnRatios(node);
3930
+ const totalWidth = columnWidths.reduce((sum, width) => sum + width, 0);
3931
+ const columns = columnWidths.map((width, index) => ["col", {
3932
+ style: widthMode === "responsive" ? `width: ${formatBasisPointsAsPercentage(columnRatios[index])};` : `width: ${width}px; min-width: ${width}px;`,
3933
+ width: String(width)
3934
+ }]);
3797
3935
  return {
3798
3936
  colgroup: ["colgroup", {}, ...columns],
3937
+ columnCount: columns.length,
3799
3938
  tableWidth: totalWidth > 0 ? `${totalWidth}px` : ""
3800
3939
  };
3801
3940
  }
3941
+ function runResponsiveColumnStructureCommand(state, dispatch, command, updateLayout) {
3942
+ const tableInfo = findTableNodeInfoFromState(state);
3943
+ if (!tableInfo || normalizeTableWidthMode(tableInfo.node.attrs.widthMode) !== "responsive") {
3944
+ return command(state, dispatch);
3945
+ }
3946
+ const rect = selectedRect(state);
3947
+ const nextLayout = updateLayout({
3948
+ widthBp: getResponsiveTableWidthBp(tableInfo.node),
3949
+ columnRatios: getTableColumnRatios(tableInfo.node)
3950
+ }, rect);
3951
+ return command(state, dispatch ? (transaction) => {
3952
+ const nextTable = transaction.doc.nodeAt(tableInfo.pos);
3953
+ if (nextTable?.type.name === "table" && nextLayout.columnRatios.length > 0) {
3954
+ const widthBp = clampResponsiveTableWidthBp(nextLayout.widthBp);
3955
+ const tableAlign = normalizeTableAlign(nextTable.attrs.textAlign);
3956
+ const offsetBp = resolveResponsiveTableOffsetBp(
3957
+ widthBp,
3958
+ tableAlign,
3959
+ getResponsiveTableOffsetBp(tableInfo.node)
3960
+ );
3961
+ transaction.setNodeMarkup(tableInfo.pos, void 0, {
3962
+ ...nextTable.attrs,
3963
+ widthMode: "responsive",
3964
+ widthBp,
3965
+ offsetBp,
3966
+ columnRatios: normalizeColumnRatios(
3967
+ nextLayout.columnRatios,
3968
+ getLogicalTableColumnCount(nextTable)
3969
+ )
3970
+ });
3971
+ }
3972
+ dispatch(transaction);
3973
+ } : void 0);
3974
+ }
3802
3975
  var UEditorTable = Table2.extend({
3803
3976
  addGlobalAttributes() {
3804
3977
  return [
@@ -3816,10 +3989,64 @@ var UEditorTable = Table2.extend({
3816
3989
  const tableAlign = normalizeTableAlign(attributes.textAlign);
3817
3990
  if (!tableAlign) return {};
3818
3991
  return {
3819
- "data-table-align": tableAlign,
3820
- style: renderTableAlignStyle(tableAlign)
3992
+ "data-table-align": tableAlign
3993
+ };
3994
+ }
3995
+ },
3996
+ widthMode: {
3997
+ default: "fixed",
3998
+ parseHTML: (element) => {
3999
+ if (!(element instanceof HTMLElement)) return "fixed";
4000
+ return parseTableWidthMode(element);
4001
+ },
4002
+ renderHTML: (attributes) => {
4003
+ if (normalizeTableWidthMode(attributes.widthMode) !== "responsive") return {};
4004
+ return {
4005
+ "data-table-width-mode": "responsive"
3821
4006
  };
3822
4007
  }
4008
+ },
4009
+ widthBp: {
4010
+ default: null,
4011
+ parseHTML: (element) => {
4012
+ if (!(element instanceof HTMLElement) || parseTableWidthMode(element) !== "responsive") return null;
4013
+ const stored = Number(element.getAttribute("data-table-width-bp"));
4014
+ if (Number.isFinite(stored) && stored > 0) return clampResponsiveTableWidthBp(stored);
4015
+ return parsePercentageToBasisPoints(element.getAttribute("data-table-width") ?? element.style.width) ?? DEFAULT_RESPONSIVE_TABLE_WIDTH_BP;
4016
+ },
4017
+ renderHTML: () => ({})
4018
+ },
4019
+ offsetBp: {
4020
+ default: null,
4021
+ parseHTML: (element) => {
4022
+ if (!(element instanceof HTMLElement) || parseTableWidthMode(element) !== "responsive") return null;
4023
+ const storedValue = element.getAttribute("data-table-offset-bp");
4024
+ const stored = Number(storedValue);
4025
+ if (storedValue !== null && Number.isFinite(stored) && stored >= 0) return Math.round(stored);
4026
+ const explicitOffset = parsePercentageToBasisPoints(
4027
+ element.getAttribute("data-table-offset") ?? element.style.marginLeft
4028
+ );
4029
+ if (explicitOffset !== null) return explicitOffset;
4030
+ const widthBp = parsePercentageToBasisPoints(
4031
+ element.getAttribute("data-table-width") ?? element.style.width
4032
+ ) ?? DEFAULT_RESPONSIVE_TABLE_WIDTH_BP;
4033
+ const tableAlign = parseTableAlign(element);
4034
+ return resolveResponsiveTableOffsetBp(widthBp, tableAlign);
4035
+ },
4036
+ renderHTML: () => ({})
4037
+ },
4038
+ columnRatios: {
4039
+ default: null,
4040
+ parseHTML: (element) => {
4041
+ if (!(element instanceof HTMLElement)) return null;
4042
+ const storedRatios = parseColumnRatios(
4043
+ element.getAttribute("data-table-column-ratios") ?? element.getAttribute("data-column-ratios")
4044
+ );
4045
+ if (storedRatios) return storedRatios;
4046
+ const columnPercentages = Array.from(element.querySelectorAll("colgroup > col")).map((column) => parsePercentageToBasisPoints(column.style.width));
4047
+ return columnPercentages.length > 0 && columnPercentages.every((ratio) => ratio !== null) ? normalizeColumnRatios(columnPercentages, columnPercentages.length) : null;
4048
+ },
4049
+ renderHTML: () => ({})
3823
4050
  }
3824
4051
  }
3825
4052
  }
@@ -3828,13 +4055,86 @@ var UEditorTable = Table2.extend({
3828
4055
  addCommands() {
3829
4056
  return {
3830
4057
  ...this.parent?.(),
4058
+ insertTable: ({ rows = 3, cols = 3, withHeaderRow = true } = {}) => ({ tr, dispatch, editor }) => {
4059
+ const types = tableNodeTypes2(editor.schema);
4060
+ const rowCount = Math.max(1, Math.floor(rows));
4061
+ const columnCount = Math.max(1, Math.floor(cols));
4062
+ const createCells = (type) => Array.from({ length: columnCount }, () => type.createAndFill()).filter((cell) => cell !== null);
4063
+ const bodyCells = createCells(types.cell);
4064
+ const headerCells = withHeaderRow ? createCells(types.header_cell) : bodyCells;
4065
+ const tableRows = Array.from({ length: rowCount }, (_, index) => types.row.createChecked(
4066
+ null,
4067
+ withHeaderRow && index === 0 ? headerCells : bodyCells
4068
+ ));
4069
+ const table = types.table.createChecked(
4070
+ {
4071
+ widthMode: "responsive",
4072
+ widthBp: DEFAULT_RESPONSIVE_TABLE_WIDTH_BP,
4073
+ offsetBp: 0,
4074
+ columnRatios: normalizeColumnRatios(null, columnCount)
4075
+ },
4076
+ tableRows
4077
+ );
4078
+ if (dispatch) {
4079
+ const offset = tr.selection.from + 1;
4080
+ tr.replaceSelectionWith(table).scrollIntoView().setSelection(TextSelection.near(tr.doc.resolve(offset)));
4081
+ }
4082
+ return true;
4083
+ },
4084
+ addColumnBefore: () => ({ state, dispatch }) => {
4085
+ return runResponsiveColumnStructureCommand(
4086
+ state,
4087
+ dispatch,
4088
+ addColumnBeforeCommand,
4089
+ (layout, rect) => insertResponsiveColumnLayout(
4090
+ layout.widthBp,
4091
+ layout.columnRatios,
4092
+ rect.left,
4093
+ rect.left
4094
+ )
4095
+ );
4096
+ },
4097
+ addColumnAfter: () => ({ state, dispatch }) => {
4098
+ return runResponsiveColumnStructureCommand(
4099
+ state,
4100
+ dispatch,
4101
+ addColumnAfterCommand,
4102
+ (layout, rect) => insertResponsiveColumnLayout(
4103
+ layout.widthBp,
4104
+ layout.columnRatios,
4105
+ rect.right,
4106
+ rect.right - 1
4107
+ )
4108
+ );
4109
+ },
4110
+ deleteColumn: () => ({ state, dispatch }) => {
4111
+ return runResponsiveColumnStructureCommand(
4112
+ state,
4113
+ dispatch,
4114
+ deleteColumnCommand,
4115
+ (layout, rect) => {
4116
+ let nextLayout = layout;
4117
+ for (let index = rect.right - 1; index >= rect.left; index -= 1) {
4118
+ nextLayout = deleteResponsiveColumnLayout(
4119
+ nextLayout.widthBp,
4120
+ nextLayout.columnRatios,
4121
+ index
4122
+ );
4123
+ }
4124
+ return nextLayout;
4125
+ }
4126
+ );
4127
+ },
3831
4128
  setTableAlign: (tableAlign) => ({ state, dispatch }) => {
3832
4129
  const tableInfo = findTableNodeInfoFromState(state);
3833
4130
  if (!tableInfo) return false;
4131
+ const widthBp = getResponsiveTableWidthBp(tableInfo.node);
4132
+ const offsetBp = resolveResponsiveTableOffsetBp(widthBp, tableAlign);
3834
4133
  dispatch?.(
3835
4134
  state.tr.setNodeMarkup(tableInfo.pos, tableInfo.node.type, {
3836
4135
  ...tableInfo.node.attrs,
3837
- textAlign: tableAlign
4136
+ textAlign: tableAlign,
4137
+ ...normalizeTableWidthMode(tableInfo.node.attrs.widthMode) === "responsive" ? { offsetBp } : null
3838
4138
  })
3839
4139
  );
3840
4140
  return true;
@@ -3853,11 +4153,31 @@ var UEditorTable = Table2.extend({
3853
4153
  };
3854
4154
  },
3855
4155
  renderHTML({ node, HTMLAttributes }) {
3856
- const { colgroup, tableWidth } = createUEditorColGroup(node);
4156
+ const widthMode = normalizeTableWidthMode(node.attrs.widthMode);
4157
+ const { colgroup, columnCount, tableWidth } = createUEditorColGroup(node, widthMode);
4158
+ const tableAlign = normalizeTableAlign(node.attrs.textAlign);
4159
+ const widthBp = getResponsiveTableWidthBp(node);
4160
+ const offsetBp = getResponsiveTableOffsetBp(node);
4161
+ const columnRatios = getTableColumnRatios(node);
4162
+ const tableStyle = widthMode === "responsive" ? [
4163
+ `width: ${formatBasisPointsAsPercentage(widthBp)}`,
4164
+ `margin-left: ${formatBasisPointsAsPercentage(offsetBp)}`,
4165
+ "margin-right: auto",
4166
+ `min-width: ${Math.max(1, columnCount) * MIN_RESIZED_TABLE_COLUMN_WIDTH}px`,
4167
+ "table-layout: fixed"
4168
+ ].join("; ") + ";" : tableWidth ? `width: ${tableWidth}; ${renderFixedTableAlignStyle(tableAlign)}` : `table-layout: fixed; ${renderFixedTableAlignStyle(tableAlign)}`;
3857
4169
  const table = [
3858
4170
  "table",
3859
4171
  mergeAttributes7(this.options.HTMLAttributes, HTMLAttributes, {
3860
- style: tableWidth ? `width: ${tableWidth};` : "table-layout: fixed;"
4172
+ ...widthMode === "responsive" ? {
4173
+ "data-table-width-mode": "responsive",
4174
+ "data-table-width": formatBasisPointsAsPercentage(widthBp),
4175
+ "data-table-width-bp": String(widthBp),
4176
+ "data-table-offset": formatBasisPointsAsPercentage(offsetBp),
4177
+ "data-table-offset-bp": String(offsetBp),
4178
+ "data-table-column-ratios": columnRatios.join(",")
4179
+ } : null,
4180
+ style: tableStyle
3861
4181
  }),
3862
4182
  colgroup,
3863
4183
  ["tbody", 0]
@@ -3910,6 +4230,31 @@ var UEditorTable = Table2.extend({
3910
4230
  tableEditing({
3911
4231
  allowTableNodeSelection: this.options.allowTableNodeSelection
3912
4232
  }),
4233
+ new Plugin4({
4234
+ key: new PluginKey5("responsiveTableLayoutNormalizer"),
4235
+ appendTransaction(transactions, _oldState, newState) {
4236
+ if (!transactions.some((transaction) => transaction.docChanged)) return null;
4237
+ const tableInfo = findTableNodeInfoFromState(newState);
4238
+ const node = tableInfo?.node;
4239
+ if (!tableInfo || !node || normalizeTableWidthMode(node.attrs.widthMode) !== "responsive") return null;
4240
+ const columnCount = getLogicalTableColumnCount(node);
4241
+ const columnRatios = getTableColumnRatios(node);
4242
+ const widthBp = getResponsiveTableWidthBp(node);
4243
+ const offsetBp = getResponsiveTableOffsetBp(node);
4244
+ const storedRatios = parseColumnRatios(node.attrs.columnRatios);
4245
+ const ratiosMatch = storedRatios?.length === columnCount && storedRatios.every((ratio, index) => Math.round(ratio) === columnRatios[index]);
4246
+ if (ratiosMatch && node.attrs.widthBp === widthBp && node.attrs.offsetBp === offsetBp && node.attrs.widthMode === "responsive") {
4247
+ return null;
4248
+ }
4249
+ return newState.tr.setNodeMarkup(tableInfo.pos, void 0, {
4250
+ ...node.attrs,
4251
+ widthMode: "responsive",
4252
+ widthBp,
4253
+ offsetBp,
4254
+ columnRatios
4255
+ });
4256
+ }
4257
+ }),
3913
4258
  new Plugin4({
3914
4259
  appendTransaction(_transactions, _oldState, newState) {
3915
4260
  const { doc, schema } = newState;
@@ -4237,8 +4582,8 @@ import { Extension as Extension10 } from "@tiptap/core";
4237
4582
  import { Plugin as Plugin6 } from "@tiptap/pm/state";
4238
4583
 
4239
4584
  // src/components/UEditor/table-formula-commands.ts
4240
- import { TextSelection } from "@tiptap/pm/state";
4241
- import { selectedRect, setCellAttr, TableMap as TableMap2 } from "@tiptap/pm/tables";
4585
+ import { TextSelection as TextSelection2 } from "@tiptap/pm/state";
4586
+ import { selectedRect as selectedRect2, setCellAttr, TableMap as TableMap2 } from "@tiptap/pm/tables";
4242
4587
 
4243
4588
  // src/components/UEditor/table-formula.ts
4244
4589
  var CELL_ADDRESS_RE = /^([A-Z]+)([1-9]\d*)$/i;
@@ -4891,7 +5236,7 @@ function restoreSelectionAtTableCell(editor, anchor) {
4891
5236
  if (!cellNode || cellNode.type.name !== "tableCell" && cellNode.type.name !== "tableHeader") return false;
4892
5237
  const selectionPos = Math.min(cellPos + 2, editor.state.doc.content.size);
4893
5238
  editor.view.dispatch(
4894
- editor.state.tr.setSelection(TextSelection.near(editor.state.doc.resolve(selectionPos))).setMeta("addToHistory", false)
5239
+ editor.state.tr.setSelection(TextSelection2.near(editor.state.doc.resolve(selectionPos))).setMeta("addToHistory", false)
4895
5240
  );
4896
5241
  return true;
4897
5242
  }
@@ -5021,7 +5366,7 @@ function removeSelectedTableCellFormula(editor, clearContent) {
5021
5366
  );
5022
5367
  let transaction = editor.state.tr.replaceWith(selectedCell.cellPos, selectedCell.cellPos + selectedCell.node.nodeSize, nextCell2).setMeta(UEDITOR_TABLE_FORMULA_RECALCULATE_META, true);
5023
5368
  const selectionPos = Math.min(selectedCell.cellPos + 2, transaction.doc.content.size);
5024
- transaction = transaction.setSelection(TextSelection.near(transaction.doc.resolve(selectionPos)));
5369
+ transaction = transaction.setSelection(TextSelection2.near(transaction.doc.resolve(selectionPos)));
5025
5370
  editor.view.dispatch(transaction);
5026
5371
  recalculateActiveTableFormulas(editor);
5027
5372
  restoreSelectionAtTableCell(editor, selectedCell);
@@ -5221,7 +5566,7 @@ function createActiveTableFormulaRecalculationTransaction(state, options) {
5221
5566
  return applyTableCellReplacements(state.tr, replacements).setMeta(UEDITOR_TABLE_FORMULA_RECALCULATE_META, true);
5222
5567
  }
5223
5568
  function recalculateSelectedTable(editor) {
5224
- const rect = selectedRect(editor.state);
5569
+ const rect = selectedRect2(editor.state);
5225
5570
  const tableNode = rect.table;
5226
5571
  return dispatchTableCellReplacements(
5227
5572
  editor,
@@ -5819,7 +6164,7 @@ import {
5819
6164
  } from "lucide-react";
5820
6165
 
5821
6166
  // src/components/UEditor/table-border-commands.ts
5822
- import { selectedRect as selectedRect2 } from "@tiptap/pm/tables";
6167
+ import { selectedRect as selectedRect3 } from "@tiptap/pm/tables";
5823
6168
  var SIDES = ["top", "right", "bottom", "left"];
5824
6169
  var OPPOSITE_SIDE = {
5825
6170
  top: "bottom",
@@ -5890,7 +6235,7 @@ function getAppliedSides(position, cell, selection) {
5890
6235
  }
5891
6236
  function applyTableCellBorders(editor, position, format, options = {}) {
5892
6237
  const { state, view } = editor;
5893
- const selection = selectedRect2(state);
6238
+ const selection = selectedRect3(state);
5894
6239
  const transaction = state.tr;
5895
6240
  const cellPositions = new Set(selection.map.cellsInRect(selection));
5896
6241
  const sidesByCell = /* @__PURE__ */ new Map();
@@ -10008,7 +10353,7 @@ var Selection = class {
10008
10353
  found.
10009
10354
  */
10010
10355
  static findFrom($pos, dir, textOnly = false) {
10011
- let inner = $pos.parent.inlineContent ? new TextSelection2($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly);
10356
+ let inner = $pos.parent.inlineContent ? new TextSelection3($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly);
10012
10357
  if (inner)
10013
10358
  return inner;
10014
10359
  for (let depth = $pos.depth - 1; depth >= 0; depth--) {
@@ -10077,7 +10422,7 @@ var Selection = class {
10077
10422
  returns the bookmark for that.
10078
10423
  */
10079
10424
  getBookmark() {
10080
- return TextSelection2.between(this.$anchor, this.$head).getBookmark();
10425
+ return TextSelection3.between(this.$anchor, this.$head).getBookmark();
10081
10426
  }
10082
10427
  };
10083
10428
  Selection.prototype.visible = true;
@@ -10097,7 +10442,7 @@ function checkTextSelection($pos) {
10097
10442
  console["warn"]("TextSelection endpoint not pointing into a node with inline content (" + $pos.parent.type.name + ")");
10098
10443
  }
10099
10444
  }
10100
- var TextSelection2 = class _TextSelection extends Selection {
10445
+ var TextSelection3 = class _TextSelection extends Selection {
10101
10446
  /**
10102
10447
  Construct a text selection between the given points.
10103
10448
  */
@@ -10183,7 +10528,7 @@ var TextSelection2 = class _TextSelection extends Selection {
10183
10528
  return new _TextSelection($anchor, $head);
10184
10529
  }
10185
10530
  };
10186
- Selection.jsonID("text", TextSelection2);
10531
+ Selection.jsonID("text", TextSelection3);
10187
10532
  var TextBookmark = class _TextBookmark {
10188
10533
  constructor(anchor, head) {
10189
10534
  this.anchor = anchor;
@@ -10193,7 +10538,7 @@ var TextBookmark = class _TextBookmark {
10193
10538
  return new _TextBookmark(mapping.map(this.anchor), mapping.map(this.head));
10194
10539
  }
10195
10540
  resolve(doc) {
10196
- return TextSelection2.between(doc.resolve(this.anchor), doc.resolve(this.head));
10541
+ return TextSelection3.between(doc.resolve(this.anchor), doc.resolve(this.head));
10197
10542
  }
10198
10543
  };
10199
10544
  var NodeSelection = class _NodeSelection extends Selection {
@@ -10312,7 +10657,7 @@ var AllBookmark = {
10312
10657
  };
10313
10658
  function findSelectionIn(doc, node, pos, index, dir, text = false) {
10314
10659
  if (node.inlineContent)
10315
- return TextSelection2.create(doc, pos);
10660
+ return TextSelection3.create(doc, pos);
10316
10661
  for (let i = index - (dir > 0 ? 0 : 1); dir > 0 ? i < node.childCount : i >= 0; i += dir) {
10317
10662
  let child = node.child(i);
10318
10663
  if (!child.isAtom) {
@@ -10812,7 +11157,7 @@ function freshColWidth(attrs) {
10812
11157
  for (let i = 0; i < attrs.colspan; i++) result.push(0);
10813
11158
  return result;
10814
11159
  }
10815
- function tableNodeTypes2(schema) {
11160
+ function tableNodeTypes3(schema) {
10816
11161
  let result = schema.cached.tableNodeTypes;
10817
11162
  if (!result) {
10818
11163
  result = schema.cached.tableNodeTypes = {};
@@ -10904,7 +11249,7 @@ var CellSelection2 = class CellSelection3 extends Selection {
10904
11249
  else if (tableChanged && this.isColSelection()) return CellSelection3.colSelection($anchorCell, $headCell);
10905
11250
  else return new CellSelection3($anchorCell, $headCell);
10906
11251
  }
10907
- return TextSelection2.between($anchorCell, $headCell);
11252
+ return TextSelection3.between($anchorCell, $headCell);
10908
11253
  }
10909
11254
  content() {
10910
11255
  const table = this.$anchorCell.node(-1);
@@ -11329,7 +11674,7 @@ function moveTableRow$1(table, indexesOrigin, indexesTarget, direction) {
11329
11674
  rows = moveRowInArrayOfRows(rows, indexesOrigin, indexesTarget, direction);
11330
11675
  return convertArrayOfRowsToTableNode(table, rows);
11331
11676
  }
11332
- function selectedRect3(state) {
11677
+ function selectedRect4(state) {
11333
11678
  const sel = state.selection;
11334
11679
  const $pos = selectionCell(state);
11335
11680
  const table = $pos.node(-1);
@@ -11346,8 +11691,8 @@ function deprecated_toggleHeader(type) {
11346
11691
  return function(state, dispatch) {
11347
11692
  if (!isInTable2(state)) return false;
11348
11693
  if (dispatch) {
11349
- const types = tableNodeTypes2(state.schema);
11350
- const rect = selectedRect3(state), tr = state.tr;
11694
+ const types = tableNodeTypes3(state.schema);
11695
+ const rect = selectedRect4(state), tr = state.tr;
11351
11696
  const cells = rect.map.cellsInRect(type == "column" ? {
11352
11697
  left: rect.left,
11353
11698
  top: 0,
@@ -11386,8 +11731,8 @@ function toggleHeader(type, options) {
11386
11731
  return function(state, dispatch) {
11387
11732
  if (!isInTable2(state)) return false;
11388
11733
  if (dispatch) {
11389
- const types = tableNodeTypes2(state.schema);
11390
- const rect = selectedRect3(state), tr = state.tr;
11734
+ const types = tableNodeTypes3(state.schema);
11735
+ const rect = selectedRect4(state), tr = state.tr;
11391
11736
  const isHeaderRowEnabled = isHeaderEnabledByType("row", rect, types);
11392
11737
  const isHeaderColumnEnabled = isHeaderEnabledByType("column", rect, types);
11393
11738
  const selectionStartsAt = (type === "column" ? isHeaderRowEnabled : type === "row" ? isHeaderColumnEnabled : false) ? 1 : 0;
@@ -11421,7 +11766,7 @@ function deleteCellSelection(state, dispatch) {
11421
11766
  if (!(sel instanceof CellSelection2)) return false;
11422
11767
  if (dispatch) {
11423
11768
  const tr = state.tr;
11424
- const baseContent = tableNodeTypes2(state.schema).cell.createAndFill().content;
11769
+ const baseContent = tableNodeTypes3(state.schema).cell.createAndFill().content;
11425
11770
  sel.forEachCell((cell, pos) => {
11426
11771
  if (!cell.content.eq(baseContent)) tr.replace(tr.mapping.map(pos + 1), tr.mapping.map(pos + cell.nodeSize - 1), new Slice(baseContent, 0, 0));
11427
11772
  });
@@ -11519,7 +11864,7 @@ function shiftArrow(axis, dir) {
11519
11864
  };
11520
11865
  }
11521
11866
  function atEndOfCell(view, axis, dir) {
11522
- if (!(view.state.selection instanceof TextSelection2)) return null;
11867
+ if (!(view.state.selection instanceof TextSelection3)) return null;
11523
11868
  const { $head } = view.state.selection;
11524
11869
  for (let d = $head.depth - 1; d >= 0; d--) {
11525
11870
  const parent = $head.node(d);
@@ -11656,7 +12001,7 @@ function buildLogicalColumnMetrics({
11656
12001
  if (relativeCellPos == null) continue;
11657
12002
  const cellMapRect = map.findCell(relativeCellPos);
11658
12003
  const cellRect = tableCell.getBoundingClientRect();
11659
- const cellStart = cellRect.width > 0 ? cellRect.left - surfaceRect.left + surface.scrollLeft : tableLeft + cellMapRect.left * fallbackWidth;
12004
+ const cellStart = cellRect.width > 0 ? cellRect.left - surfaceRect.left - surface.clientLeft + surface.scrollLeft : tableLeft + cellMapRect.left * fallbackWidth;
11660
12005
  const size = metricOrFallback(cellRect.width, fallbackWidth * Math.max(1, cellMapRect.right - cellMapRect.left));
11661
12006
  visualColumns.push({
11662
12007
  index: cellMapRect.left,
@@ -11711,7 +12056,7 @@ function buildLogicalRowMetrics({
11711
12056
  const tableCell = isTableCellElement(cellCandidate) ? cellCandidate : null;
11712
12057
  if (tableCell) {
11713
12058
  const cellRect = tableCell.getBoundingClientRect();
11714
- const start = cellRect.height > 0 ? cellRect.top - surfaceRect.top + surface.scrollTop : tableTop + cellMapRect.top * fallbackHeight;
12059
+ const start = cellRect.height > 0 ? cellRect.top - surfaceRect.top - surface.clientTop + surface.scrollTop : tableTop + cellMapRect.top * fallbackHeight;
11715
12060
  const size = metricOrFallback(cellRect.height, fallbackHeight * Math.max(1, cellMapRect.bottom - cellMapRect.top));
11716
12061
  visualRows.push({
11717
12062
  index: cellMapRect.top,
@@ -11728,7 +12073,7 @@ function buildLogicalRowMetrics({
11728
12073
  return rows.map((tableRow, index) => {
11729
12074
  const rowRect = tableRow.getBoundingClientRect();
11730
12075
  const anchorCell = tableRow.cells.item(0) ?? cornerCell;
11731
- const start = rowRect.height > 0 ? rowRect.top - surfaceRect.top + surface.scrollTop : tableTop + index * fallbackHeight;
12076
+ const start = rowRect.height > 0 ? rowRect.top - surfaceRect.top - surface.clientTop + surface.scrollTop : tableTop + index * fallbackHeight;
11732
12077
  const size = metricOrFallback(rowRect.height, fallbackHeight);
11733
12078
  return {
11734
12079
  index,
@@ -11770,6 +12115,8 @@ function buildTableControlLayout(editor, surface, cell) {
11770
12115
  }
11771
12116
  const map = TableMap3.get(tableInfo.node);
11772
12117
  const surfaceRect = surface.getBoundingClientRect();
12118
+ const surfaceOriginLeft = surfaceRect.left + surface.clientLeft;
12119
+ const surfaceOriginTop = surfaceRect.top + surface.clientTop;
11773
12120
  const tableRect = table.getBoundingClientRect();
11774
12121
  const explicitColumnWidths = Array.from(table.querySelectorAll("colgroup > col")).slice(0, map.width).map((column) => parsePixelMetric(column.style.width));
11775
12122
  const explicitTableWidth = parsePixelMetric(table.style.width) ?? (explicitColumnWidths.length === map.width && explicitColumnWidths.every((width) => width !== null) ? explicitColumnWidths.reduce((sum, width) => sum + width, 0) : null);
@@ -11778,14 +12125,14 @@ function buildTableControlLayout(editor, surface, cell) {
11778
12125
  const wrapperElement = table.closest(".tableWrapper");
11779
12126
  const wrapper = isHTMLElement(wrapperElement) ? wrapperElement : null;
11780
12127
  const wrapperRect = wrapper?.getBoundingClientRect() ?? tableRect;
11781
- const tableLeft = tableRect.left - surfaceRect.left + surface.scrollLeft;
11782
- const tableTop = tableRect.top - surfaceRect.top + surface.scrollTop;
12128
+ const tableLeft = tableRect.left - surfaceOriginLeft + surface.scrollLeft;
12129
+ const tableTop = tableRect.top - surfaceOriginTop + surface.scrollTop;
11783
12130
  const tableWidth = metricOrFallback(tableRect.width, explicitTableWidth ?? FALLBACK_TABLE_COLUMN_WIDTH * map.width);
11784
12131
  const tableHeight = metricOrFallback(tableRect.height, explicitTableHeight ?? FALLBACK_TABLE_ROW_HEIGHT * rows.length);
11785
12132
  const avgRowHeight = metricOrFallback(tableHeight / rows.length, FALLBACK_TABLE_ROW_HEIGHT);
11786
12133
  const avgColumnWidth = metricOrFallback(tableWidth / map.width, FALLBACK_TABLE_COLUMN_WIDTH);
11787
- const wrapperLeft = wrapperRect.left - surfaceRect.left + surface.scrollLeft;
11788
- const wrapperTop = wrapperRect.top - surfaceRect.top + surface.scrollTop;
12134
+ const wrapperLeft = wrapperRect.left - surfaceOriginLeft + surface.scrollLeft;
12135
+ const wrapperTop = wrapperRect.top - surfaceOriginTop + surface.scrollTop;
11789
12136
  const wrapperWidth = metricOrFallback(wrapperRect.width, tableWidth);
11790
12137
  const wrapperHeight = metricOrFallback(wrapperRect.height, tableHeight);
11791
12138
  const viewportWidth = metricOrFallback(wrapper?.clientWidth ?? wrapperRect.width, tableWidth);
@@ -11834,7 +12181,8 @@ function buildTableControlLayout(editor, surface, cell) {
11834
12181
  avgRowHeight,
11835
12182
  avgColumnWidth,
11836
12183
  rowHandles,
11837
- columnHandles
12184
+ columnHandles,
12185
+ widthMode: normalizeTableWidthMode(tableInfo.node.attrs.widthMode)
11838
12186
  };
11839
12187
  }
11840
12188
 
@@ -11867,8 +12215,8 @@ function buildTableHoverState({
11867
12215
  return DEFAULT_TABLE_HOVER_STATE;
11868
12216
  }
11869
12217
  const surfaceRect = surface.getBoundingClientRect();
11870
- const relativeX = event.clientX - surfaceRect.left + surface.scrollLeft;
11871
- const relativeY = event.clientY - surfaceRect.top + surface.scrollTop;
12218
+ const relativeX = event.clientX - surfaceRect.left - surface.clientLeft + surface.scrollLeft;
12219
+ const relativeY = event.clientY - surfaceRect.top - surface.clientTop + surface.scrollTop;
11872
12220
  const targetElement = resolveEventElement(event.target);
11873
12221
  const directRowHandle = targetElement?.closest?.("[data-row-handle-index]");
11874
12222
  const directColumnHandle = targetElement?.closest?.("[data-column-handle-index]");
@@ -12315,7 +12663,7 @@ function TableColumnHandles({
12315
12663
 
12316
12664
  // src/components/UEditor/table-resize-handles.tsx
12317
12665
  import { MoveDiagonal2 } from "lucide-react";
12318
- import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
12666
+ import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
12319
12667
  var HANDLE_BASE_CLASS = cn(
12320
12668
  "pointer-events-auto absolute z-10 inline-flex touch-none items-center justify-center rounded-md",
12321
12669
  "bg-background/95 text-primary shadow-sm backdrop-blur-sm",
@@ -12323,11 +12671,17 @@ var HANDLE_BASE_CLASS = cn(
12323
12671
  "hover:bg-primary hover:text-primary-foreground hover:shadow-md active:scale-95",
12324
12672
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
12325
12673
  );
12674
+ var EDGE_HANDLE_CLASS = cn(
12675
+ "pointer-events-auto absolute top-0 z-10 h-full w-2 touch-none cursor-col-resize bg-transparent p-0",
12676
+ "border-transparent transition-colors duration-150 hover:border-primary",
12677
+ "focus-visible:border-primary focus-visible:outline-none"
12678
+ );
12326
12679
  function TableResizeHandles({
12327
12680
  active,
12328
12681
  ctrlHint,
12329
12682
  frameRef,
12330
12683
  layout,
12684
+ onFitWidth,
12331
12685
  onStartResize,
12332
12686
  resizeBothLabel
12333
12687
  }) {
@@ -12348,6 +12702,36 @@ function TableResizeHandles({
12348
12702
  height: layout.tableHeight
12349
12703
  },
12350
12704
  children: [
12705
+ layout.widthMode === "responsive" ? /* @__PURE__ */ jsxs14(Fragment6, { children: [
12706
+ /* @__PURE__ */ jsx17(
12707
+ "button",
12708
+ {
12709
+ type: "button",
12710
+ "aria-label": `${resizeBothLabel} \u2014 \u2190`,
12711
+ title: resizeBothLabel,
12712
+ "data-table-resize-handle": "left",
12713
+ className: cn(
12714
+ EDGE_HANDLE_CLASS,
12715
+ "left-0 border-l-2"
12716
+ ),
12717
+ onPointerDown: (event) => onStartResize(event, "left")
12718
+ }
12719
+ ),
12720
+ /* @__PURE__ */ jsx17(
12721
+ "button",
12722
+ {
12723
+ type: "button",
12724
+ "aria-label": `${resizeBothLabel} \u2014 \u2192`,
12725
+ title: resizeBothLabel,
12726
+ "data-table-resize-handle": "right",
12727
+ className: cn(
12728
+ EDGE_HANDLE_CLASS,
12729
+ "right-0 border-r-2"
12730
+ ),
12731
+ onPointerDown: (event) => onStartResize(event, "right")
12732
+ }
12733
+ )
12734
+ ] }) : null,
12351
12735
  /* @__PURE__ */ jsx17(
12352
12736
  "button",
12353
12737
  {
@@ -12360,7 +12744,8 @@ function TableResizeHandles({
12360
12744
  "bottom-[-28px] right-[-30px] h-6 w-6 cursor-nwse-resize",
12361
12745
  active && "bg-primary text-primary-foreground shadow-md"
12362
12746
  ),
12363
- onPointerDown: onStartResize,
12747
+ onDoubleClick: onFitWidth,
12748
+ onPointerDown: (event) => onStartResize(event, "both"),
12364
12749
  children: /* @__PURE__ */ jsx17(MoveDiagonal2, { "aria-hidden": "true", className: "h-3.5 w-3.5", strokeWidth: 2.25 })
12365
12750
  }
12366
12751
  ),
@@ -12422,7 +12807,7 @@ function getLogicalRowHeights(table, fallback) {
12422
12807
  });
12423
12808
  return heights;
12424
12809
  }
12425
- function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight) {
12810
+ function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight, containerWidth = startWidth) {
12426
12811
  const tableInfo = findTableInfo(editor, anchorPos);
12427
12812
  if (!tableInfo) return null;
12428
12813
  const tableMap = TableMap3.get(tableInfo.node);
@@ -12431,13 +12816,16 @@ function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight) {
12431
12816
  const safeHeight = Math.max(tableMap.height * MIN_TABLE_ROW_HEIGHT, Math.round(startHeight));
12432
12817
  const fallbackColumnWidth = safeWidth / tableMap.width;
12433
12818
  const fallbackRowHeight = safeHeight / tableMap.height;
12819
+ const widthMode = normalizeTableWidthMode(tableInfo.node.attrs.widthMode);
12820
+ const safeContainerWidth = Math.max(1, Math.round(containerWidth));
12821
+ const columnWeights = widthMode === "responsive" ? getTableColumnRatios(tableInfo.node) : getLogicalColumnWidths(tableInfo.node, tableMap, fallbackColumnWidth);
12434
12822
  return {
12435
12823
  anchorPos,
12436
12824
  tablePos: tableInfo.pos,
12437
12825
  startWidth: safeWidth,
12438
12826
  startHeight: safeHeight,
12439
12827
  columnWidths: normalizeWeightsToTotal(
12440
- getLogicalColumnWidths(tableInfo.node, tableMap, fallbackColumnWidth),
12828
+ columnWeights,
12441
12829
  safeWidth,
12442
12830
  MIN_RESIZED_TABLE_COLUMN_WIDTH
12443
12831
  ),
@@ -12447,7 +12835,12 @@ function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight) {
12447
12835
  MIN_TABLE_ROW_HEIGHT
12448
12836
  ),
12449
12837
  minWidth: tableMap.width * MIN_RESIZED_TABLE_COLUMN_WIDTH,
12450
- minHeight: tableMap.height * MIN_TABLE_ROW_HEIGHT
12838
+ minHeight: tableMap.height * MIN_TABLE_ROW_HEIGHT,
12839
+ containerWidth: safeContainerWidth,
12840
+ widthMode,
12841
+ widthBp: getResponsiveTableWidthBp(tableInfo.node),
12842
+ offsetBp: getResponsiveTableOffsetBp(tableInfo.node),
12843
+ columnRatios: getTableColumnRatios(tableInfo.node)
12451
12844
  };
12452
12845
  }
12453
12846
  function resolveTableResizeDimensions({
@@ -12455,12 +12848,14 @@ function resolveTableResizeDimensions({
12455
12848
  deltaY,
12456
12849
  lockAxis,
12457
12850
  preserveRatio,
12851
+ edge = "both",
12458
12852
  snapshot
12459
12853
  }) {
12460
- let width = snapshot.startWidth + deltaX;
12461
- let height = snapshot.startHeight + deltaY;
12854
+ const horizontalDelta = edge === "left" ? -deltaX : deltaX;
12855
+ let width = snapshot.startWidth + horizontalDelta;
12856
+ let height = edge === "both" ? snapshot.startHeight + deltaY : snapshot.startHeight;
12462
12857
  if (preserveRatio) {
12463
- const horizontalDrag = Math.abs(deltaX) >= Math.abs(deltaY);
12858
+ const horizontalDrag = edge !== "both" || Math.abs(deltaX) >= Math.abs(deltaY);
12464
12859
  const scale = horizontalDrag ? width / snapshot.startWidth : height / snapshot.startHeight;
12465
12860
  const minScale = Math.max(
12466
12861
  snapshot.minWidth / snapshot.startWidth,
@@ -12473,22 +12868,56 @@ function resolveTableResizeDimensions({
12473
12868
  const safeScale = Math.min(Math.max(scale, minScale), maxScale);
12474
12869
  width = snapshot.startWidth * safeScale;
12475
12870
  height = snapshot.startHeight * safeScale;
12476
- } else if (lockAxis) {
12871
+ } else if (lockAxis && edge === "both") {
12477
12872
  if (Math.abs(deltaX) >= Math.abs(deltaY)) {
12478
12873
  height = snapshot.startHeight;
12479
12874
  } else {
12480
12875
  width = snapshot.startWidth;
12481
12876
  }
12482
12877
  }
12878
+ let nextWidth = Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minWidth, Math.round(width)));
12879
+ const nextHeight = Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minHeight, Math.round(height)));
12880
+ if (snapshot.widthMode !== "responsive") {
12881
+ return { width: nextWidth, height: nextHeight };
12882
+ }
12883
+ const containerWidth = Math.max(1, snapshot.containerWidth);
12884
+ const startOffset = snapshot.offsetBp / TABLE_WIDTH_BASIS_POINTS * containerWidth;
12885
+ let nextOffset = startOffset;
12886
+ if (edge === "left") {
12887
+ const fixedRightEdge = startOffset + snapshot.startWidth;
12888
+ nextOffset = Math.min(
12889
+ fixedRightEdge - snapshot.minWidth,
12890
+ Math.max(0, startOffset + deltaX)
12891
+ );
12892
+ nextWidth = fixedRightEdge - nextOffset;
12893
+ }
12894
+ const widthBp = clampResponsiveTableWidthBp(
12895
+ nextWidth / containerWidth * TABLE_WIDTH_BASIS_POINTS
12896
+ );
12897
+ const offsetBp = resolveResponsiveTableOffsetBp(
12898
+ widthBp,
12899
+ null,
12900
+ nextOffset / containerWidth * TABLE_WIDTH_BASIS_POINTS
12901
+ );
12483
12902
  return {
12484
- width: Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minWidth, Math.round(width))),
12485
- height: Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minHeight, Math.round(height)))
12903
+ width: Math.round(widthBp / TABLE_WIDTH_BASIS_POINTS * containerWidth),
12904
+ height: nextHeight,
12905
+ widthBp,
12906
+ offsetBp,
12907
+ leftDelta: nextOffset - startOffset
12486
12908
  };
12487
12909
  }
12488
12910
  function arraysEqual(left, right) {
12489
12911
  return Array.isArray(left) && left.length === right.length && left.every((value, index) => value === right[index]);
12490
12912
  }
12491
- function applyTableSize(editor, snapshot, dimensions) {
12913
+ function getResponsiveResizeAlignment(widthBp, offsetBp) {
12914
+ const gap = Math.max(0, TABLE_WIDTH_BASIS_POINTS - widthBp);
12915
+ if (offsetBp === 0) return "left";
12916
+ if (offsetBp === gap) return "right";
12917
+ if (Math.abs(offsetBp * 2 - gap) <= 1) return "center";
12918
+ return null;
12919
+ }
12920
+ function applyTableSize(editor, snapshot, dimensions, options = {}) {
12492
12921
  const table = editor.state.doc.nodeAt(snapshot.tablePos);
12493
12922
  if (!table || table.type.name !== "table") return false;
12494
12923
  const tableMap = TableMap3.get(table);
@@ -12497,9 +12926,32 @@ function applyTableSize(editor, snapshot, dimensions) {
12497
12926
  }
12498
12927
  const resizeWidth = dimensions.width !== snapshot.startWidth;
12499
12928
  const resizeHeight = dimensions.height !== snapshot.startHeight;
12500
- if (!resizeWidth && !resizeHeight) return false;
12929
+ const widthMode = options.widthMode ?? snapshot.widthMode;
12930
+ const widthModeChanged = normalizeTableWidthMode(table.attrs.widthMode) !== widthMode || widthMode === "responsive" && table.attrs.widthMode !== "responsive";
12931
+ const widthBp = dimensions.widthBp ?? clampResponsiveTableWidthBp(
12932
+ dimensions.width / Math.max(1, snapshot.containerWidth) * TABLE_WIDTH_BASIS_POINTS
12933
+ );
12934
+ const offsetBp = resolveResponsiveTableOffsetBp(
12935
+ widthBp,
12936
+ null,
12937
+ dimensions.offsetBp ?? snapshot.offsetBp
12938
+ );
12939
+ const responsiveLayoutChanged = widthMode === "responsive" && (table.attrs.widthBp !== widthBp || table.attrs.offsetBp !== offsetBp);
12940
+ if (!resizeWidth && !resizeHeight && !widthModeChanged && !responsiveLayoutChanged) return false;
12501
12941
  const tableStart = snapshot.tablePos + 1;
12502
12942
  const transaction = editor.state.tr;
12943
+ if (widthModeChanged || responsiveLayoutChanged) {
12944
+ transaction.setNodeMarkup(snapshot.tablePos, void 0, {
12945
+ ...table.attrs,
12946
+ widthMode,
12947
+ ...widthMode === "responsive" ? {
12948
+ widthBp,
12949
+ offsetBp,
12950
+ columnRatios: normalizeColumnRatios(snapshot.columnRatios, tableMap.width),
12951
+ textAlign: getResponsiveResizeAlignment(widthBp, offsetBp)
12952
+ } : null
12953
+ });
12954
+ }
12503
12955
  if (resizeWidth) {
12504
12956
  const nextColumnWidths = normalizeWeightsToTotal(
12505
12957
  snapshot.columnWidths,
@@ -12542,7 +12994,7 @@ function applyTableSize(editor, snapshot, dimensions) {
12542
12994
  }
12543
12995
 
12544
12996
  // src/components/UEditor/table-controls.tsx
12545
- import { Fragment as Fragment6, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
12997
+ import { Fragment as Fragment7, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
12546
12998
  var TABLE_MENU_TOP_OFFSET = 10;
12547
12999
  var AXIS_HANDLE_RADIUS = 12;
12548
13000
  function nearestIndex(centers, position) {
@@ -12651,6 +13103,10 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
12651
13103
  if (!frame) return;
12652
13104
  frame.style.width = `${dimensions.width}px`;
12653
13105
  frame.style.height = `${dimensions.height}px`;
13106
+ const activeLayout = layoutRef.current;
13107
+ if (activeLayout) {
13108
+ frame.style.left = `${activeLayout.tableLeft + (dimensions.leftDelta ?? 0)}px`;
13109
+ }
12654
13110
  const dimensionsLabel = frame.querySelector("[data-table-resize-dimensions]");
12655
13111
  if (dimensionsLabel) {
12656
13112
  dimensionsLabel.textContent = `${dimensions.width} \xD7 ${dimensions.height}`;
@@ -12661,7 +13117,8 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
12661
13117
  if (!activeLayout) return;
12662
13118
  updateTableResizePreview({
12663
13119
  width: Math.round(activeLayout.tableWidth),
12664
- height: Math.round(activeLayout.tableHeight)
13120
+ height: Math.round(activeLayout.tableHeight),
13121
+ leftDelta: 0
12665
13122
  });
12666
13123
  }, [updateTableResizePreview]);
12667
13124
  const clearDrag = React10.useCallback(() => {
@@ -12766,6 +13223,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
12766
13223
  surface.addEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleCurrentLayoutRefresh);
12767
13224
  if (!editorWindow) return void 0;
12768
13225
  const unsubscribeResize = subscribeSharedGlobalEvent(editorWindow, "resize", scheduleCurrentLayoutRefresh);
13226
+ const unsubscribeWindowScroll = subscribeSharedGlobalEvent(editorWindow, "scroll", scheduleCurrentLayoutRefresh, { passive: true });
12769
13227
  editor.on("selectionUpdate", scheduleSyncFromSelection);
12770
13228
  editor.on("update", scheduleCurrentLayoutRefresh);
12771
13229
  syncFromSelection();
@@ -12781,6 +13239,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
12781
13239
  surface.removeEventListener("scroll", scheduleCurrentLayoutRefresh, scrollListenerOptions);
12782
13240
  surface.removeEventListener(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT, scheduleCurrentLayoutRefresh);
12783
13241
  unsubscribeResize();
13242
+ unsubscribeWindowScroll();
12784
13243
  editor.off("selectionUpdate", scheduleSyncFromSelection);
12785
13244
  editor.off("update", scheduleCurrentLayoutRefresh);
12786
13245
  };
@@ -12824,7 +13283,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
12824
13283
  const canExpandTable = Boolean(layout);
12825
13284
  const controlsVisible = false;
12826
13285
  const tableMenuOpen = openMenuKey === "table";
12827
- const startTableResize = React10.useCallback((event) => {
13286
+ const startTableResize = React10.useCallback((event, edge) => {
12828
13287
  if (event.button !== 0 || dragStateRef.current) return;
12829
13288
  const activeLayout = layoutRef.current;
12830
13289
  if (!activeLayout) return;
@@ -12832,7 +13291,8 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
12832
13291
  editor,
12833
13292
  activeLayout.cellPos,
12834
13293
  activeLayout.tableWidth,
12835
- activeLayout.tableHeight
13294
+ activeLayout.tableHeight,
13295
+ activeLayout.viewportWidth
12836
13296
  );
12837
13297
  if (!snapshot) return;
12838
13298
  event.preventDefault();
@@ -12854,12 +13314,38 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
12854
13314
  pointerTarget: event.currentTarget,
12855
13315
  startX: event.clientX,
12856
13316
  startY: event.clientY,
13317
+ edge,
12857
13318
  snapshot,
12858
13319
  pendingDimensions
12859
13320
  };
12860
13321
  updateTableResizePreview(pendingDimensions);
12861
- setDocumentCursor(editorDocument, "nwse-resize");
13322
+ setDocumentCursor(editorDocument, edge === "both" ? "nwse-resize" : "ew-resize");
12862
13323
  }, [editor, editorDocument, updateTableResizePreview]);
13324
+ const fitTableToEditorWidth = React10.useCallback((event) => {
13325
+ if (event.button !== 0 || dragStateRef.current) return;
13326
+ const activeLayout = layoutRef.current;
13327
+ if (!activeLayout) return;
13328
+ const snapshot = createTableSizeSnapshot(
13329
+ editor,
13330
+ activeLayout.cellPos,
13331
+ activeLayout.tableWidth,
13332
+ activeLayout.tableHeight,
13333
+ activeLayout.viewportWidth
13334
+ );
13335
+ if (!snapshot) return;
13336
+ event.preventDefault();
13337
+ event.stopPropagation();
13338
+ const didResize = applyTableSize(editor, snapshot, {
13339
+ width: Math.round(activeLayout.viewportWidth),
13340
+ height: snapshot.startHeight,
13341
+ widthBp: TABLE_WIDTH_BASIS_POINTS,
13342
+ offsetBp: 0,
13343
+ leftDelta: -(snapshot.offsetBp / TABLE_WIDTH_BASIS_POINTS * snapshot.containerWidth)
13344
+ }, { widthMode: "responsive" });
13345
+ if (didResize) {
13346
+ scheduleSyncFromSelection();
13347
+ }
13348
+ }, [editor, scheduleSyncFromSelection]);
12863
13349
  const startAddColumnDrag = React10.useCallback(() => {
12864
13350
  setOpenMenuKey(null);
12865
13351
  dragStateRef.current = { kind: "add-column", previewCols: 1 };
@@ -12974,12 +13460,30 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
12974
13460
  scheduleSyncFromSelection();
12975
13461
  }
12976
13462
  if (dragState.kind === "column" && dragState.originIndex !== dragState.targetIndex) {
13463
+ const tableInfo = findTableInfo(editor, dragState.anchorPos);
13464
+ const responsiveRatios = tableInfo && normalizeTableWidthMode(tableInfo.node.attrs.widthMode) === "responsive" ? moveResponsiveColumnRatio(
13465
+ getTableColumnRatios(tableInfo.node),
13466
+ dragState.originIndex,
13467
+ dragState.targetIndex
13468
+ ) : null;
12977
13469
  moveTableColumn({
12978
13470
  from: dragState.originIndex,
12979
13471
  to: dragState.targetIndex,
12980
13472
  pos: dragState.anchorPos,
12981
13473
  select: true
12982
- })(editor.state, editor.view.dispatch);
13474
+ })(editor.state, (transaction) => {
13475
+ if (tableInfo && responsiveRatios) {
13476
+ const nextTable = transaction.doc.nodeAt(tableInfo.pos);
13477
+ if (nextTable?.type.name === "table") {
13478
+ transaction.setNodeMarkup(tableInfo.pos, void 0, {
13479
+ ...nextTable.attrs,
13480
+ widthMode: "responsive",
13481
+ columnRatios: responsiveRatios
13482
+ });
13483
+ }
13484
+ }
13485
+ editor.view.dispatch(transaction);
13486
+ });
12983
13487
  scheduleSyncFromSelection();
12984
13488
  }
12985
13489
  if (dragState.kind === "add-row") {
@@ -13013,6 +13517,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
13013
13517
  deltaY: event.clientY - dragState.startY,
13014
13518
  lockAxis: event.ctrlKey && !event.shiftKey,
13015
13519
  preserveRatio: event.ctrlKey && event.shiftKey,
13520
+ edge: dragState.edge,
13016
13521
  snapshot: dragState.snapshot
13017
13522
  });
13018
13523
  if (tableResizePreviewFrameRef.current === null) {
@@ -13024,7 +13529,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
13024
13529
  updateTableResizePreview(currentDragState.pendingDimensions);
13025
13530
  });
13026
13531
  }
13027
- setDocumentCursor(editorDocument, "nwse-resize");
13532
+ setDocumentCursor(editorDocument, dragState.edge === "both" ? "nwse-resize" : "ew-resize");
13028
13533
  if (event.cancelable) event.preventDefault();
13029
13534
  };
13030
13535
  const finishTableResize = (event, commit) => {
@@ -13035,7 +13540,12 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
13035
13540
  tableResizePreviewFrameRef.current = null;
13036
13541
  }
13037
13542
  updateTableResizePreview(dragState.pendingDimensions);
13038
- if (commit && applyTableSize(editor, dragState.snapshot, dragState.pendingDimensions)) {
13543
+ if (commit && applyTableSize(
13544
+ editor,
13545
+ dragState.snapshot,
13546
+ dragState.pendingDimensions,
13547
+ { widthMode: dragState.snapshot.widthMode }
13548
+ )) {
13039
13549
  scheduleSyncFromSelection();
13040
13550
  }
13041
13551
  clearDrag();
@@ -13216,7 +13726,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
13216
13726
  const menuLeft = Math.max(8, layout.tableLeft);
13217
13727
  const rowHandleLeft = layout.tableLeft - AXIS_HANDLE_RADIUS;
13218
13728
  const columnHandleTop = layout.tableTop - AXIS_HANDLE_RADIUS;
13219
- return /* @__PURE__ */ jsxs15(Fragment6, { children: [
13729
+ return /* @__PURE__ */ jsxs15(Fragment7, { children: [
13220
13730
  /* @__PURE__ */ jsx18(
13221
13731
  TableRowHandles,
13222
13732
  {
@@ -13273,6 +13783,7 @@ function TableControls({ editor, containerRef, showCellInspector = true }) {
13273
13783
  ctrlHint: t("tableMenu.resizeCtrlHint"),
13274
13784
  frameRef: tableResizeFrameRef,
13275
13785
  layout,
13786
+ onFitWidth: fitTableToEditorWidth,
13276
13787
  onStartResize: startTableResize,
13277
13788
  resizeBothLabel: t("tableMenu.resizeBoth")
13278
13789
  }
@@ -13826,7 +14337,7 @@ import { useEffect as useEffect7, useRef as useRef7 } from "react";
13826
14337
  import { TableMap as TableMap5 } from "@tiptap/pm/tables";
13827
14338
 
13828
14339
  // src/components/UEditor/table-formula-range-picker.ts
13829
- import { TextSelection as TextSelection3 } from "@tiptap/pm/state";
14340
+ import { TextSelection as TextSelection4 } from "@tiptap/pm/state";
13830
14341
  import { TableMap as TableMap4 } from "@tiptap/pm/tables";
13831
14342
  function getCellText2(cellNode) {
13832
14343
  return cellNode.textBetween(0, cellNode.content.size, "\n").trim();
@@ -13904,7 +14415,7 @@ function cancelFormulaEditing(view) {
13904
14415
  if (!context) return false;
13905
14416
  let tr = view.state.tr.delete(context.cellContentStart, context.cellContentEnd);
13906
14417
  const selectionPos = Math.min(context.cellContentStart, tr.doc.content.size);
13907
- tr = tr.setSelection(TextSelection3.near(tr.doc.resolve(selectionPos)));
14418
+ tr = tr.setSelection(TextSelection4.near(tr.doc.resolve(selectionPos)));
13908
14419
  view.dispatch(tr);
13909
14420
  view.focus();
13910
14421
  return true;
@@ -13981,7 +14492,7 @@ function replacePickedLabel(view, pickState, nextLabel, currentCell) {
13981
14492
  }
13982
14493
  let tr = view.state.tr.insertText(nextLabel, pickState.insertedFrom, pickState.insertedTo);
13983
14494
  const nextTo = pickState.insertedFrom + nextLabel.length;
13984
- tr = tr.setSelection(TextSelection3.create(tr.doc, nextTo));
14495
+ tr = tr.setSelection(TextSelection4.create(tr.doc, nextTo));
13985
14496
  view.dispatch(tr);
13986
14497
  return {
13987
14498
  ...pickState,
@@ -14018,7 +14529,7 @@ function beginFormulaRangePick(view, event) {
14018
14529
  const insertedText = `${prefix}${picked.label}`;
14019
14530
  const insertedFrom = from + prefix.length;
14020
14531
  let tr = view.state.tr.insertText(insertedText, from, to);
14021
- tr = tr.setSelection(TextSelection3.create(tr.doc, from + insertedText.length));
14532
+ tr = tr.setSelection(TextSelection4.create(tr.doc, from + insertedText.length));
14022
14533
  view.dispatch(tr);
14023
14534
  view.focus();
14024
14535
  event.preventDefault();
@@ -14538,7 +15049,7 @@ function useUEditorOutput({
14538
15049
  // src/components/UEditor/UEditor.tsx
14539
15050
  import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
14540
15051
  var LazyMenuBar = React15.lazy(async () => {
14541
- const { MenuBar } = await import("./menu-bar-GKJEVLQU.js");
15052
+ const { MenuBar } = await import("./menu-bar-AHG64PEB.js");
14542
15053
  return { default: MenuBar };
14543
15054
  });
14544
15055
  var UEditor = React15.forwardRef(({
@@ -15007,4 +15518,4 @@ export {
15007
15518
  prepareUEditorContentForSave,
15008
15519
  UEditor_default
15009
15520
  };
15010
- //# sourceMappingURL=chunk-5ODK33CL.js.map
15521
+ //# sourceMappingURL=chunk-XTZTUDRE.js.map