@lumir-company/editor 0.4.16 → 0.4.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -45,10 +45,10 @@ __export(index_exports, {
45
45
  module.exports = __toCommonJS(index_exports);
46
46
 
47
47
  // src/components/LumirEditor.tsx
48
- var import_react34 = require("react");
49
- var import_react35 = require("@blocknote/react");
48
+ var import_react37 = require("react");
49
+ var import_react38 = require("@blocknote/react");
50
50
  var import_mantine = require("@blocknote/mantine");
51
- var import_core5 = require("@blocknote/core");
51
+ var import_core9 = require("@blocknote/core");
52
52
  var import_locales = require("@blocknote/core/locales");
53
53
 
54
54
  // src/utils/cn.ts
@@ -286,7 +286,7 @@ var createS3Uploader = (config) => {
286
286
 
287
287
  // src/blocks/HtmlPreview.tsx
288
288
  var import_react6 = require("@blocknote/react");
289
- var import_core = require("@blocknote/core");
289
+ var import_core3 = require("@blocknote/core");
290
290
 
291
291
  // src/blocks/LinkPreview.tsx
292
292
  var import_react = require("@blocknote/react");
@@ -1246,6 +1246,310 @@ var VideoBlock = (0, import_react3.createReactBlockSpec)(
1246
1246
  }
1247
1247
  );
1248
1248
 
1249
+ // src/blocks/columns/ColumnList.ts
1250
+ var import_core = require("@blocknote/core");
1251
+
1252
+ // src/blocks/columns/columnNormalization.ts
1253
+ var import_prosemirror_state = require("prosemirror-state");
1254
+ var columnNormalizationKey = new import_prosemirror_state.PluginKey("lumirColumnNormalization");
1255
+ function columnNormalization() {
1256
+ return new import_prosemirror_state.Plugin({
1257
+ key: columnNormalizationKey,
1258
+ appendTransaction(transactions, _oldState, newState) {
1259
+ if (!transactions.some((tr2) => tr2.docChanged)) {
1260
+ return null;
1261
+ }
1262
+ const lists = [];
1263
+ newState.doc.descendants((node, pos) => {
1264
+ if (node.type.name === "columnList") {
1265
+ lists.push({ pos, node });
1266
+ return false;
1267
+ }
1268
+ return void 0;
1269
+ });
1270
+ if (lists.length === 0) {
1271
+ return null;
1272
+ }
1273
+ const tr = newState.tr;
1274
+ let modified = false;
1275
+ for (let i = lists.length - 1; i >= 0; i--) {
1276
+ const { pos, node } = lists[i];
1277
+ const nonEmptyColumns = [];
1278
+ node.forEach((col) => {
1279
+ if (col.type.name === "column" && col.childCount > 0) {
1280
+ nonEmptyColumns.push(col);
1281
+ }
1282
+ });
1283
+ if (nonEmptyColumns.length >= 2) {
1284
+ continue;
1285
+ }
1286
+ const from = tr.mapping.map(pos);
1287
+ const to = tr.mapping.map(pos + node.nodeSize);
1288
+ const blocks = [];
1289
+ nonEmptyColumns.forEach((col) => {
1290
+ col.forEach((bc) => blocks.push(bc));
1291
+ });
1292
+ if (blocks.length > 0) {
1293
+ tr.replaceWith(from, to, blocks);
1294
+ } else {
1295
+ tr.delete(from, to);
1296
+ }
1297
+ modified = true;
1298
+ }
1299
+ return modified ? tr : null;
1300
+ }
1301
+ });
1302
+ }
1303
+
1304
+ // src/blocks/columns/columnDnd.ts
1305
+ var import_prosemirror_state2 = require("prosemirror-state");
1306
+ var import_prosemirror_view = require("prosemirror-view");
1307
+
1308
+ // src/blocks/columns/mergeColumns.ts
1309
+ function mergeBlocksIntoColumns(editor, draggedId, targetId, side) {
1310
+ if (!editor || !draggedId || !targetId || draggedId === targetId) {
1311
+ return false;
1312
+ }
1313
+ const dragged = editor.getBlock?.(draggedId);
1314
+ const target = editor.getBlock?.(targetId);
1315
+ if (!dragged || !target) {
1316
+ return false;
1317
+ }
1318
+ if (dragged.type === "columnList" || dragged.type === "column" || target.type === "columnList" || target.type === "column") {
1319
+ return false;
1320
+ }
1321
+ const columnList = {
1322
+ type: "columnList",
1323
+ children: side === "left" ? [
1324
+ { type: "column", children: [dragged] },
1325
+ { type: "column", children: [target] }
1326
+ ] : [
1327
+ { type: "column", children: [target] },
1328
+ { type: "column", children: [dragged] }
1329
+ ]
1330
+ };
1331
+ try {
1332
+ const run = () => {
1333
+ editor.removeBlocks([draggedId]);
1334
+ editor.replaceBlocks([targetId], [columnList]);
1335
+ };
1336
+ if (typeof editor.transact === "function") {
1337
+ editor.transact(run);
1338
+ } else {
1339
+ run();
1340
+ }
1341
+ return true;
1342
+ } catch {
1343
+ return false;
1344
+ }
1345
+ }
1346
+
1347
+ // src/blocks/columns/columnDnd.ts
1348
+ var columnDndKey = new import_prosemirror_state2.PluginKey("lumirColumnDnd");
1349
+ function edgeThreshold(width) {
1350
+ return Math.min(80, width * 0.3);
1351
+ }
1352
+ function topLevelBlockAtCoords(view, x, y) {
1353
+ const found = view.posAtCoords({ left: x, top: y });
1354
+ if (!found) {
1355
+ return null;
1356
+ }
1357
+ const $pos = view.state.doc.resolve(found.pos);
1358
+ for (let d = $pos.depth; d > 0; d--) {
1359
+ if ($pos.node(d).type.name === "blockContainer") {
1360
+ if (d !== 2 || $pos.node(d - 1).type.name !== "blockGroup") {
1361
+ return null;
1362
+ }
1363
+ const pos = $pos.before(d);
1364
+ const node = $pos.node(d);
1365
+ const dom = view.nodeDOM(pos);
1366
+ if (!dom || !node.attrs?.id) {
1367
+ return null;
1368
+ }
1369
+ return { pos, nodeSize: node.nodeSize, id: node.attrs.id, dom };
1370
+ }
1371
+ }
1372
+ return null;
1373
+ }
1374
+ function draggedBlockId(view) {
1375
+ const sel = view.state.selection;
1376
+ return sel?.node?.attrs?.id ?? null;
1377
+ }
1378
+ function setDnd(view, next) {
1379
+ const cur = columnDndKey.getState(view.state);
1380
+ if (cur && cur.targetPos === next.targetPos && cur.side === next.side) {
1381
+ return;
1382
+ }
1383
+ view.dispatch(view.state.tr.setMeta(columnDndKey, next));
1384
+ }
1385
+ var CLEARED = { targetPos: null, side: null };
1386
+ function columnDnd() {
1387
+ return new import_prosemirror_state2.Plugin({
1388
+ key: columnDndKey,
1389
+ state: {
1390
+ init: () => CLEARED,
1391
+ apply(tr, prev) {
1392
+ const meta = tr.getMeta(columnDndKey);
1393
+ if (meta) {
1394
+ return meta;
1395
+ }
1396
+ if (tr.docChanged && prev.targetPos !== null) {
1397
+ return CLEARED;
1398
+ }
1399
+ return prev;
1400
+ }
1401
+ },
1402
+ props: {
1403
+ handleDOMEvents: {
1404
+ dragover: (view, event) => {
1405
+ if (!view.dragging) {
1406
+ return false;
1407
+ }
1408
+ const target = topLevelBlockAtCoords(
1409
+ view,
1410
+ event.clientX,
1411
+ event.clientY
1412
+ );
1413
+ const draggedId = draggedBlockId(view);
1414
+ if (!target || !draggedId || target.id === draggedId) {
1415
+ setDnd(view, CLEARED);
1416
+ view.dom.classList.remove("lumir-col-dnd-active");
1417
+ return false;
1418
+ }
1419
+ const rect = target.dom.getBoundingClientRect();
1420
+ const th = edgeThreshold(rect.width);
1421
+ let side = null;
1422
+ if (event.clientX - rect.left <= th) {
1423
+ side = "left";
1424
+ } else if (rect.right - event.clientX <= th) {
1425
+ side = "right";
1426
+ }
1427
+ if (side) {
1428
+ setDnd(view, { targetPos: target.pos, side });
1429
+ view.dom.classList.add("lumir-col-dnd-active");
1430
+ } else {
1431
+ setDnd(view, CLEARED);
1432
+ view.dom.classList.remove("lumir-col-dnd-active");
1433
+ }
1434
+ return false;
1435
+ },
1436
+ dragend: (view) => {
1437
+ setDnd(view, CLEARED);
1438
+ view.dom.classList.remove("lumir-col-dnd-active");
1439
+ return false;
1440
+ },
1441
+ dragleave: (view, event) => {
1442
+ if (!event.relatedTarget) {
1443
+ setDnd(view, CLEARED);
1444
+ view.dom.classList.remove("lumir-col-dnd-active");
1445
+ }
1446
+ return false;
1447
+ }
1448
+ },
1449
+ handleDrop: (view, _event, _slice, _moved) => {
1450
+ const st = columnDndKey.getState(view.state);
1451
+ view.dom.classList.remove("lumir-col-dnd-active");
1452
+ if (!st || st.side === null || st.targetPos === null) {
1453
+ return false;
1454
+ }
1455
+ const draggedId = draggedBlockId(view);
1456
+ const targetNode = view.state.doc.nodeAt(st.targetPos);
1457
+ const targetId = targetNode?.attrs?.id;
1458
+ view.dispatch(view.state.tr.setMeta(columnDndKey, CLEARED));
1459
+ if (!draggedId || !targetId) {
1460
+ return false;
1461
+ }
1462
+ const editor = view.__lumirEditor;
1463
+ if (!editor) {
1464
+ return false;
1465
+ }
1466
+ const ok = mergeBlocksIntoColumns(editor, draggedId, targetId, st.side);
1467
+ return ok;
1468
+ },
1469
+ decorations: (state) => {
1470
+ const st = columnDndKey.getState(state);
1471
+ if (!st || st.side === null || st.targetPos === null) {
1472
+ return null;
1473
+ }
1474
+ const node = state.doc.nodeAt(st.targetPos);
1475
+ if (!node) {
1476
+ return null;
1477
+ }
1478
+ return import_prosemirror_view.DecorationSet.create(state.doc, [
1479
+ import_prosemirror_view.Decoration.node(st.targetPos, st.targetPos + node.nodeSize, {
1480
+ class: st.side === "left" ? "lumir-col-drop-left" : "lumir-col-drop-right"
1481
+ })
1482
+ ]);
1483
+ }
1484
+ }
1485
+ });
1486
+ }
1487
+
1488
+ // src/blocks/columns/ColumnList.ts
1489
+ var ColumnList = (0, import_core.createStronglyTypedTiptapNode)({
1490
+ name: "columnList",
1491
+ group: "childContainer bnBlock blockGroupChild",
1492
+ content: "column column+",
1493
+ parseHTML() {
1494
+ return [{ tag: 'div[data-node-type="columnList"]' }];
1495
+ },
1496
+ renderHTML({ HTMLAttributes }) {
1497
+ const dom = document.createElement("div");
1498
+ dom.className = "bn-column-list";
1499
+ dom.setAttribute("data-node-type", "columnList");
1500
+ for (const [attribute, value] of Object.entries(HTMLAttributes)) {
1501
+ if (attribute !== "class") {
1502
+ dom.setAttribute(attribute, value);
1503
+ }
1504
+ }
1505
+ return { dom, contentDOM: dom };
1506
+ },
1507
+ // columnNormalization: 빈 컬럼/1단 columnList 자동 복구(unwrap).
1508
+ // columnDnd: 블록을 다른 블록 좌/우로 드롭하면 2단 컬럼 생성.
1509
+ addProseMirrorPlugins() {
1510
+ return [columnNormalization(), columnDnd()];
1511
+ }
1512
+ });
1513
+
1514
+ // src/blocks/columns/Column.ts
1515
+ var import_core2 = require("@blocknote/core");
1516
+ var Column = (0, import_core2.createStronglyTypedTiptapNode)({
1517
+ name: "column",
1518
+ group: "bnBlock childContainer",
1519
+ content: "blockContainer+",
1520
+ addAttributes() {
1521
+ return {
1522
+ width: {
1523
+ default: 1,
1524
+ parseHTML: (element) => {
1525
+ const w = parseFloat(element.getAttribute("data-column-width") || "");
1526
+ return Number.isFinite(w) && w > 0 ? w : 1;
1527
+ },
1528
+ renderHTML: (attributes) => {
1529
+ if (!attributes.width || attributes.width === 1) {
1530
+ return {};
1531
+ }
1532
+ return { "data-column-width": String(attributes.width) };
1533
+ }
1534
+ }
1535
+ };
1536
+ },
1537
+ parseHTML() {
1538
+ return [{ tag: 'div[data-node-type="column"]' }];
1539
+ },
1540
+ renderHTML({ HTMLAttributes }) {
1541
+ const dom = document.createElement("div");
1542
+ dom.className = "bn-column";
1543
+ dom.setAttribute("data-node-type", "column");
1544
+ for (const [attribute, value] of Object.entries(HTMLAttributes)) {
1545
+ if (attribute !== "class") {
1546
+ dom.setAttribute(attribute, value);
1547
+ }
1548
+ }
1549
+ return { dom, contentDOM: dom };
1550
+ }
1551
+ });
1552
+
1249
1553
  // src/styles/FontSizeStyle.tsx
1250
1554
  var import_react5 = require("@blocknote/react");
1251
1555
  var import_jsx_runtime3 = require("react/jsx-runtime");
@@ -1351,7 +1655,7 @@ var HtmlPreviewBlock = (0, import_react6.createReactBlockSpec)(
1351
1655
  setIsResizing(true);
1352
1656
  const startY = e.clientY;
1353
1657
  const startHeight = currentHeight;
1354
- const handleMouseMove = (moveEvent) => {
1658
+ const handleMouseMove2 = (moveEvent) => {
1355
1659
  const deltaY = moveEvent.clientY - startY;
1356
1660
  const newHeight = Math.min(
1357
1661
  MAX_HEIGHT,
@@ -1363,10 +1667,10 @@ var HtmlPreviewBlock = (0, import_react6.createReactBlockSpec)(
1363
1667
  };
1364
1668
  const handleMouseUp = () => {
1365
1669
  setIsResizing(false);
1366
- document.removeEventListener("mousemove", handleMouseMove);
1670
+ document.removeEventListener("mousemove", handleMouseMove2);
1367
1671
  document.removeEventListener("mouseup", handleMouseUp);
1368
1672
  };
1369
- document.addEventListener("mousemove", handleMouseMove);
1673
+ document.addEventListener("mousemove", handleMouseMove2);
1370
1674
  document.addEventListener("mouseup", handleMouseUp);
1371
1675
  },
1372
1676
  [currentHeight, props.editor, props.block]
@@ -1632,16 +1936,23 @@ var HtmlPreviewBlock = (0, import_react6.createReactBlockSpec)(
1632
1936
  }
1633
1937
  }
1634
1938
  );
1635
- var schema = import_core.BlockNoteSchema.create({
1939
+ var ColumnListBlock = (0, import_core3.createBlockSpecFromStronglyTypedTiptapNode)(
1940
+ ColumnList,
1941
+ {}
1942
+ );
1943
+ var ColumnBlock = (0, import_core3.createBlockSpecFromStronglyTypedTiptapNode)(Column, {});
1944
+ var schema = import_core3.BlockNoteSchema.create({
1636
1945
  blockSpecs: {
1637
- ...import_core.defaultBlockSpecs,
1946
+ ...import_core3.defaultBlockSpecs,
1638
1947
  htmlPreview: HtmlPreviewBlock,
1639
1948
  linkPreview: LinkPreviewBlock,
1640
- video: VideoBlock
1949
+ video: VideoBlock,
1950
+ columnList: ColumnListBlock,
1951
+ column: ColumnBlock
1641
1952
  },
1642
- inlineContentSpecs: import_core.defaultInlineContentSpecs,
1953
+ inlineContentSpecs: import_core3.defaultInlineContentSpecs,
1643
1954
  styleSpecs: {
1644
- ...import_core.defaultStyleSpecs,
1955
+ ...import_core3.defaultStyleSpecs,
1645
1956
  // 인라인 글자 크기. 저장 JSON 직렬화는 형제 키 방식(font-size-serialization.ts) 사용.
1646
1957
  fontSize: FontSize
1647
1958
  }
@@ -1785,7 +2096,7 @@ var UndoRedoButtons = ({ editor }) => {
1785
2096
  console.error("Redo failed:", err);
1786
2097
  }
1787
2098
  }, [editor]);
1788
- const handleMouseDown = (0, import_react8.useCallback)((e) => {
2099
+ const handleMouseDown2 = (0, import_react8.useCallback)((e) => {
1789
2100
  e.preventDefault();
1790
2101
  }, []);
1791
2102
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "lumir-toolbar-group", children: [
@@ -1794,7 +2105,7 @@ var UndoRedoButtons = ({ editor }) => {
1794
2105
  {
1795
2106
  className: "lumir-toolbar-btn",
1796
2107
  onClick: handleUndo,
1797
- onMouseDown: handleMouseDown,
2108
+ onMouseDown: handleMouseDown2,
1798
2109
  title: "\uC2E4\uD589 \uCDE8\uC18C",
1799
2110
  type: "button",
1800
2111
  children: Icons.undo
@@ -1805,7 +2116,7 @@ var UndoRedoButtons = ({ editor }) => {
1805
2116
  {
1806
2117
  className: "lumir-toolbar-btn",
1807
2118
  onClick: handleRedo,
1808
- onMouseDown: handleMouseDown,
2119
+ onMouseDown: handleMouseDown2,
1809
2120
  title: "\uB2E4\uC2DC \uC2E4\uD589",
1810
2121
  type: "button",
1811
2122
  children: Icons.redo
@@ -1849,7 +2160,7 @@ var TextStyleButton = ({
1849
2160
  console.error(`Toggle ${style} failed:`, err);
1850
2161
  }
1851
2162
  }, [editor, style]);
1852
- const handleMouseDown = (0, import_react9.useCallback)((e) => {
2163
+ const handleMouseDown2 = (0, import_react9.useCallback)((e) => {
1853
2164
  e.preventDefault();
1854
2165
  }, []);
1855
2166
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
@@ -1857,7 +2168,7 @@ var TextStyleButton = ({
1857
2168
  {
1858
2169
  className: cn("lumir-toolbar-btn", isActive && "is-active"),
1859
2170
  onClick: handleClick,
1860
- onMouseDown: handleMouseDown,
2171
+ onMouseDown: handleMouseDown2,
1861
2172
  title: titleMap[style],
1862
2173
  type: "button",
1863
2174
  children: iconMap[style]
@@ -1925,6 +2236,41 @@ function getFirstSelectedCellAttr(editor, attr) {
1925
2236
  const node = tiptap.state.doc.nodeAt(positions[0]);
1926
2237
  return node?.attrs?.[attr];
1927
2238
  }
2239
+ function findTableNodePos(tiptap, blockId) {
2240
+ let tablePos = -1;
2241
+ tiptap.state.doc.descendants((node, pos) => {
2242
+ if (tablePos !== -1) return false;
2243
+ if (node.type.name === "blockContainer" && node.attrs?.id === blockId && node.firstChild?.type.name === "table") {
2244
+ tablePos = pos + 1;
2245
+ return false;
2246
+ }
2247
+ return void 0;
2248
+ });
2249
+ return tablePos;
2250
+ }
2251
+ function setTableAlignment(editor, blockId, alignment) {
2252
+ const tiptap = editor?._tiptapEditor;
2253
+ if (!tiptap || !blockId) return false;
2254
+ const tablePos = findTableNodePos(tiptap, blockId);
2255
+ if (tablePos < 0) return false;
2256
+ const node = tiptap.state.doc.nodeAt(tablePos);
2257
+ if (!node || node.type.name !== "table") return false;
2258
+ tiptap.view?.dispatch(
2259
+ tiptap.state.tr.setNodeMarkup(tablePos, void 0, {
2260
+ ...node.attrs,
2261
+ tableAlignment: alignment
2262
+ })
2263
+ );
2264
+ return true;
2265
+ }
2266
+ function getTableAlignment(editor, blockId) {
2267
+ const tiptap = editor?._tiptapEditor;
2268
+ if (!tiptap || !blockId) return "left";
2269
+ const tablePos = findTableNodePos(tiptap, blockId);
2270
+ if (tablePos < 0) return "left";
2271
+ const node = tiptap.state.doc.nodeAt(tablePos);
2272
+ return node?.attrs?.tableAlignment || "left";
2273
+ }
1928
2274
 
1929
2275
  // src/components/FloatingMenu/components/AlignButton.tsx
1930
2276
  var import_jsx_runtime9 = require("react/jsx-runtime");
@@ -1967,7 +2313,7 @@ var AlignButton = ({
1967
2313
  console.error(`Set alignment ${alignment} failed:`, err);
1968
2314
  }
1969
2315
  }, [editor, alignment]);
1970
- const handleMouseDown = (0, import_react10.useCallback)((e) => {
2316
+ const handleMouseDown2 = (0, import_react10.useCallback)((e) => {
1971
2317
  e.preventDefault();
1972
2318
  }, []);
1973
2319
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
@@ -1975,7 +2321,7 @@ var AlignButton = ({
1975
2321
  {
1976
2322
  className: cn("lumir-toolbar-btn", isActive && "is-active"),
1977
2323
  onClick: handleClick,
1978
- onMouseDown: handleMouseDown,
2324
+ onMouseDown: handleMouseDown2,
1979
2325
  title: titleMap2[alignment],
1980
2326
  type: "button",
1981
2327
  children: iconMap2[alignment]
@@ -2017,7 +2363,7 @@ var ListButton = ({ editor, type }) => {
2017
2363
  console.error(`List toggle failed:`, err);
2018
2364
  }
2019
2365
  }, [editor, type]);
2020
- const handleMouseDown = (0, import_react11.useCallback)((e) => {
2366
+ const handleMouseDown2 = (0, import_react11.useCallback)((e) => {
2021
2367
  e.preventDefault();
2022
2368
  }, []);
2023
2369
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
@@ -2025,7 +2371,7 @@ var ListButton = ({ editor, type }) => {
2025
2371
  {
2026
2372
  className: cn("lumir-toolbar-btn", isActive && "is-active"),
2027
2373
  onClick: handleClick,
2028
- onMouseDown: handleMouseDown,
2374
+ onMouseDown: handleMouseDown2,
2029
2375
  title: titleMap3[type],
2030
2376
  type: "button",
2031
2377
  children: iconMap3[type]
@@ -2065,7 +2411,7 @@ var ImageButton = ({
2065
2411
  input.click();
2066
2412
  }
2067
2413
  }, [editor, onImageUpload]);
2068
- const handleMouseDown = (0, import_react12.useCallback)((e) => {
2414
+ const handleMouseDown2 = (0, import_react12.useCallback)((e) => {
2069
2415
  e.preventDefault();
2070
2416
  }, []);
2071
2417
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
@@ -2073,7 +2419,7 @@ var ImageButton = ({
2073
2419
  {
2074
2420
  className: "lumir-toolbar-btn",
2075
2421
  onClick: handleClick,
2076
- onMouseDown: handleMouseDown,
2422
+ onMouseDown: handleMouseDown2,
2077
2423
  title: "\uC774\uBBF8\uC9C0 \uC0BD\uC785",
2078
2424
  type: "button",
2079
2425
  children: Icons.image
@@ -2172,7 +2518,7 @@ var ColorButton = ({ editor, type }) => {
2172
2518
  },
2173
2519
  [editor, type]
2174
2520
  );
2175
- const handleMouseDown = (0, import_react13.useCallback)((e) => {
2521
+ const handleMouseDown2 = (0, import_react13.useCallback)((e) => {
2176
2522
  e.preventDefault();
2177
2523
  }, []);
2178
2524
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "lumir-dropdown-wrapper", ref: dropdownRef, children: [
@@ -2181,7 +2527,7 @@ var ColorButton = ({ editor, type }) => {
2181
2527
  {
2182
2528
  className: "lumir-toolbar-btn lumir-color-btn",
2183
2529
  onClick: () => setIsOpen(!isOpen),
2184
- onMouseDown: handleMouseDown,
2530
+ onMouseDown: handleMouseDown2,
2185
2531
  title: type === "text" ? "\uD14D\uC2A4\uD2B8 \uC0C9\uC0C1" : "\uBC30\uACBD \uC0C9\uC0C1",
2186
2532
  type: "button",
2187
2533
  children: [
@@ -2206,7 +2552,7 @@ var ColorButton = ({ editor, type }) => {
2206
2552
  currentColor === color.value && "is-active"
2207
2553
  ),
2208
2554
  onClick: () => handleColorSelect(color.value),
2209
- onMouseDown: handleMouseDown,
2555
+ onMouseDown: handleMouseDown2,
2210
2556
  title: color.name,
2211
2557
  style: { backgroundColor: color.hex },
2212
2558
  type: "button"
@@ -2258,7 +2604,7 @@ var FontSizeButton = ({ editor }) => {
2258
2604
  },
2259
2605
  [editor]
2260
2606
  );
2261
- const handleMouseDown = (0, import_react14.useCallback)((e) => {
2607
+ const handleMouseDown2 = (0, import_react14.useCallback)((e) => {
2262
2608
  e.preventDefault();
2263
2609
  }, []);
2264
2610
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "lumir-dropdown-wrapper", ref: dropdownRef, children: [
@@ -2267,7 +2613,7 @@ var FontSizeButton = ({ editor }) => {
2267
2613
  {
2268
2614
  className: "lumir-dropdown-btn lumir-font-size-btn",
2269
2615
  onClick: () => setIsOpen(!isOpen),
2270
- onMouseDown: handleMouseDown,
2616
+ onMouseDown: handleMouseDown2,
2271
2617
  title: "\uAE00\uC790 \uD06C\uAE30",
2272
2618
  type: "button",
2273
2619
  children: [
@@ -2285,7 +2631,7 @@ var FontSizeButton = ({ editor }) => {
2285
2631
  currentSize === "" && "is-active"
2286
2632
  ),
2287
2633
  onClick: () => handleSizeSelect(""),
2288
- onMouseDown: handleMouseDown,
2634
+ onMouseDown: handleMouseDown2,
2289
2635
  type: "button",
2290
2636
  children: DEFAULT_LABEL
2291
2637
  }
@@ -2298,7 +2644,7 @@ var FontSizeButton = ({ editor }) => {
2298
2644
  currentSize === size && "is-active"
2299
2645
  ),
2300
2646
  onClick: () => handleSizeSelect(size),
2301
- onMouseDown: handleMouseDown,
2647
+ onMouseDown: handleMouseDown2,
2302
2648
  type: "button",
2303
2649
  children: toLabel(size)
2304
2650
  },
@@ -2396,7 +2742,7 @@ var LinkButton = ({ editor }) => {
2396
2742
  setLinkUrl("");
2397
2743
  setErrorMsg(null);
2398
2744
  }, []);
2399
- const handleMouseDown = (0, import_react15.useCallback)((e) => {
2745
+ const handleMouseDown2 = (0, import_react15.useCallback)((e) => {
2400
2746
  e.preventDefault();
2401
2747
  }, []);
2402
2748
  const handleKeyDown = (0, import_react15.useCallback)(
@@ -2415,7 +2761,7 @@ var LinkButton = ({ editor }) => {
2415
2761
  {
2416
2762
  className: "lumir-toolbar-btn",
2417
2763
  onClick: () => setIsOpen(!isOpen),
2418
- onMouseDown: handleMouseDown,
2764
+ onMouseDown: handleMouseDown2,
2419
2765
  title: "\uB9C1\uD06C \uC0BD\uC785",
2420
2766
  type: "button",
2421
2767
  children: Icons.link
@@ -2435,7 +2781,7 @@ var LinkButton = ({ editor }) => {
2435
2781
  setErrorMsg(null);
2436
2782
  },
2437
2783
  onKeyDown: handleKeyDown,
2438
- onMouseDown: handleMouseDown
2784
+ onMouseDown: handleMouseDown2
2439
2785
  }
2440
2786
  ),
2441
2787
  errorMsg && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
@@ -2457,7 +2803,7 @@ var LinkButton = ({ editor }) => {
2457
2803
  type: "button",
2458
2804
  className: "lumir-link-btn lumir-link-cancel",
2459
2805
  onClick: handleCancel,
2460
- onMouseDown: handleMouseDown,
2806
+ onMouseDown: handleMouseDown2,
2461
2807
  children: "\uCDE8\uC18C"
2462
2808
  }
2463
2809
  ),
@@ -2466,7 +2812,7 @@ var LinkButton = ({ editor }) => {
2466
2812
  {
2467
2813
  type: "submit",
2468
2814
  className: "lumir-link-btn lumir-link-submit",
2469
- onMouseDown: handleMouseDown,
2815
+ onMouseDown: handleMouseDown2,
2470
2816
  disabled: !linkUrl.trim(),
2471
2817
  children: "\uD655\uC778"
2472
2818
  }
@@ -2502,7 +2848,7 @@ var TableButton = ({ editor }) => {
2502
2848
  console.error("Table insert failed:", err);
2503
2849
  }
2504
2850
  }, [editor]);
2505
- const handleMouseDown = (0, import_react16.useCallback)((e) => {
2851
+ const handleMouseDown2 = (0, import_react16.useCallback)((e) => {
2506
2852
  e.preventDefault();
2507
2853
  }, []);
2508
2854
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
@@ -2510,7 +2856,7 @@ var TableButton = ({ editor }) => {
2510
2856
  {
2511
2857
  className: "lumir-toolbar-btn",
2512
2858
  onClick: handleClick,
2513
- onMouseDown: handleMouseDown,
2859
+ onMouseDown: handleMouseDown2,
2514
2860
  title: "\uD14C\uC774\uBE14 \uC0BD\uC785",
2515
2861
  type: "button",
2516
2862
  children: Icons.table
@@ -2564,7 +2910,7 @@ var HTMLImportButton = ({
2564
2910
  const handleClick = (0, import_react17.useCallback)(() => {
2565
2911
  fileInputRef.current?.click();
2566
2912
  }, []);
2567
- const handleMouseDown = (0, import_react17.useCallback)((e) => {
2913
+ const handleMouseDown2 = (0, import_react17.useCallback)((e) => {
2568
2914
  e.preventDefault();
2569
2915
  }, []);
2570
2916
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
@@ -2583,7 +2929,7 @@ var HTMLImportButton = ({
2583
2929
  {
2584
2930
  className: "lumir-toolbar-btn",
2585
2931
  onClick: handleClick,
2586
- onMouseDown: handleMouseDown,
2932
+ onMouseDown: handleMouseDown2,
2587
2933
  title: "HTML Import",
2588
2934
  type: "button",
2589
2935
  children: Icons.htmlFile
@@ -2666,7 +3012,7 @@ var BlockTypeSelect = ({ editor }) => {
2666
3012
  console.error("Block type change failed:", err);
2667
3013
  }
2668
3014
  };
2669
- const handleMouseDown = (0, import_react18.useCallback)((e) => {
3015
+ const handleMouseDown2 = (0, import_react18.useCallback)((e) => {
2670
3016
  e.preventDefault();
2671
3017
  }, []);
2672
3018
  const getCurrentLabel = () => {
@@ -2703,7 +3049,7 @@ var BlockTypeSelect = ({ editor }) => {
2703
3049
  {
2704
3050
  className: "lumir-dropdown-btn lumir-block-type-btn",
2705
3051
  onClick: () => setIsOpen(!isOpen),
2706
- onMouseDown: handleMouseDown,
3052
+ onMouseDown: handleMouseDown2,
2707
3053
  type: "button",
2708
3054
  children: [
2709
3055
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "lumir-block-icon", children: BlockTypeIcons[getCurrentIcon()] }),
@@ -2722,7 +3068,7 @@ var BlockTypeSelect = ({ editor }) => {
2722
3068
  isActiveItem(bt) && "is-active"
2723
3069
  ),
2724
3070
  onClick: () => handleTypeChange(bt.type, bt.level, bt.isToggle),
2725
- onMouseDown: handleMouseDown,
3071
+ onMouseDown: handleMouseDown2,
2726
3072
  children: [
2727
3073
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "lumir-block-icon", children: BlockTypeIcons[bt.icon] }),
2728
3074
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "lumir-block-item-title", children: bt.label })
@@ -3032,8 +3378,8 @@ var LumirEditorError = class _LumirEditorError extends Error {
3032
3378
  };
3033
3379
 
3034
3380
  // src/extensions/VerticalAlignmentExtension.ts
3035
- var import_core2 = require("@tiptap/core");
3036
- var VerticalAlignmentExtension = import_core2.Extension.create({
3381
+ var import_core4 = require("@tiptap/core");
3382
+ var VerticalAlignmentExtension = import_core4.Extension.create({
3037
3383
  name: "verticalAlignment",
3038
3384
  addGlobalAttributes() {
3039
3385
  return [
@@ -3063,11 +3409,585 @@ var VerticalAlignmentExtension = import_core2.Extension.create({
3063
3409
  }
3064
3410
  });
3065
3411
 
3412
+ // src/extensions/RowHeightExtension.ts
3413
+ var import_core5 = require("@tiptap/core");
3414
+
3415
+ // src/extensions/rowResizing.ts
3416
+ var import_prosemirror_state3 = require("prosemirror-state");
3417
+ var import_prosemirror_view2 = require("prosemirror-view");
3418
+ var import_prosemirror_tables = require("prosemirror-tables");
3419
+
3420
+ // src/constants/limits.ts
3421
+ var MAX_FILE_SIZE = 10 * 1024 * 1024;
3422
+ var MAX_VIDEO_FILE_SIZE = 100 * 1024 * 1024;
3423
+ var BLOCKED_EXTENSIONS = [".svg", ".svgz"];
3424
+ var ALLOWED_VIDEO_MIME_TYPES = /* @__PURE__ */ new Set([
3425
+ "video/mp4",
3426
+ "video/webm",
3427
+ "video/ogg",
3428
+ "video/quicktime"
3429
+ // .mov
3430
+ ]);
3431
+ var ALLOWED_VIDEO_EXTENSIONS = [
3432
+ ".mp4",
3433
+ ".webm",
3434
+ ".ogg",
3435
+ ".mov"
3436
+ ];
3437
+ var ROW_RESIZE_MIN_HEIGHT = 24;
3438
+ var ROW_RESIZE_HANDLE_WIDTH = 5;
3439
+
3440
+ // src/extensions/rowResizing.ts
3441
+ var rowResizingPluginKey = new import_prosemirror_state3.PluginKey(
3442
+ "lumirRowResizing"
3443
+ );
3444
+ var RowResizeState = class _RowResizeState {
3445
+ constructor(activeHandle, dragging) {
3446
+ this.activeHandle = activeHandle;
3447
+ this.dragging = dragging;
3448
+ }
3449
+ apply(tr) {
3450
+ const action = tr.getMeta(rowResizingPluginKey);
3451
+ if (action && action.setHandle != null) {
3452
+ return new _RowResizeState(action.setHandle, null);
3453
+ }
3454
+ if (action && action.setDragging !== void 0) {
3455
+ return new _RowResizeState(this.activeHandle, action.setDragging);
3456
+ }
3457
+ if (this.activeHandle > -1 && tr.docChanged) {
3458
+ let handle = tr.mapping.map(this.activeHandle, -1);
3459
+ if (!(0, import_prosemirror_tables.pointsAtCell)(tr.doc.resolve(handle))) {
3460
+ handle = -1;
3461
+ }
3462
+ return new _RowResizeState(handle, this.dragging);
3463
+ }
3464
+ return this;
3465
+ }
3466
+ };
3467
+ function rowResizing({
3468
+ handleWidth = ROW_RESIZE_HANDLE_WIDTH,
3469
+ minHeight = ROW_RESIZE_MIN_HEIGHT
3470
+ } = {}) {
3471
+ return new import_prosemirror_state3.Plugin({
3472
+ key: rowResizingPluginKey,
3473
+ state: {
3474
+ init() {
3475
+ return new RowResizeState(-1, null);
3476
+ },
3477
+ apply(tr, prev) {
3478
+ return prev.apply(tr);
3479
+ }
3480
+ },
3481
+ props: {
3482
+ attributes: (state) => {
3483
+ const pluginState = rowResizingPluginKey.getState(state);
3484
+ return pluginState && pluginState.activeHandle > -1 ? { class: "row-resize-cursor" } : {};
3485
+ },
3486
+ handleDOMEvents: {
3487
+ mousemove: (view, event) => {
3488
+ handleMouseMove(view, event, handleWidth);
3489
+ },
3490
+ mouseleave: (view) => {
3491
+ handleMouseLeave(view);
3492
+ },
3493
+ mousedown: (view, event) => {
3494
+ handleMouseDown(view, event, minHeight);
3495
+ }
3496
+ },
3497
+ decorations: (state) => {
3498
+ const pluginState = rowResizingPluginKey.getState(state);
3499
+ if (pluginState && pluginState.activeHandle > -1) {
3500
+ return handleDecorations(state, pluginState);
3501
+ }
3502
+ return void 0;
3503
+ }
3504
+ }
3505
+ });
3506
+ }
3507
+ function handleMouseMove(view, event, handleWidth) {
3508
+ if (!view.editable) {
3509
+ return;
3510
+ }
3511
+ const pluginState = rowResizingPluginKey.getState(view.state);
3512
+ if (!pluginState) {
3513
+ return;
3514
+ }
3515
+ if (!pluginState.dragging) {
3516
+ const target = domCellAround(event.target);
3517
+ let cell = -1;
3518
+ if (target) {
3519
+ const { top, bottom } = target.getBoundingClientRect();
3520
+ if (event.clientY - top <= handleWidth) {
3521
+ cell = edgeCell(view, event, "top", handleWidth);
3522
+ } else if (bottom - event.clientY <= handleWidth) {
3523
+ cell = edgeCell(view, event, "bottom", handleWidth);
3524
+ }
3525
+ }
3526
+ if (cell !== pluginState.activeHandle) {
3527
+ updateHandle(view, cell);
3528
+ }
3529
+ }
3530
+ }
3531
+ function handleMouseLeave(view) {
3532
+ if (!view.editable) {
3533
+ return;
3534
+ }
3535
+ const pluginState = rowResizingPluginKey.getState(view.state);
3536
+ if (pluginState && pluginState.activeHandle > -1 && !pluginState.dragging) {
3537
+ updateHandle(view, -1);
3538
+ }
3539
+ }
3540
+ function handleMouseDown(view, event, minHeight) {
3541
+ if (!view.editable) {
3542
+ return false;
3543
+ }
3544
+ const win = view.dom.ownerDocument.defaultView ?? window;
3545
+ const pluginState = rowResizingPluginKey.getState(view.state);
3546
+ if (!pluginState || pluginState.activeHandle === -1 || pluginState.dragging) {
3547
+ return false;
3548
+ }
3549
+ const startHeight = currentRowHeight(view, pluginState.activeHandle);
3550
+ setDragging(view, {
3551
+ startY: event.clientY,
3552
+ startHeight,
3553
+ currentHeight: startHeight
3554
+ });
3555
+ function finish(finishEvent) {
3556
+ win.removeEventListener("mouseup", finish);
3557
+ win.removeEventListener("mousemove", move);
3558
+ const ps = rowResizingPluginKey.getState(view.state);
3559
+ if (ps?.dragging) {
3560
+ const finalHeight = draggedHeight(ps.dragging, finishEvent, minHeight);
3561
+ setDragging(view, null);
3562
+ commitRowHeight(view, ps.activeHandle, finalHeight);
3563
+ }
3564
+ }
3565
+ function move(moveEvent) {
3566
+ if (moveEvent.buttons === 0 || moveEvent.buttons === void 0 && !moveEvent.which) {
3567
+ return finish(moveEvent);
3568
+ }
3569
+ const ps = rowResizingPluginKey.getState(view.state);
3570
+ if (!ps?.dragging) {
3571
+ return;
3572
+ }
3573
+ const h = draggedHeight(ps.dragging, moveEvent, minHeight);
3574
+ if (h !== ps.dragging.currentHeight) {
3575
+ setDragging(view, { ...ps.dragging, currentHeight: h });
3576
+ }
3577
+ }
3578
+ win.addEventListener("mouseup", finish);
3579
+ win.addEventListener("mousemove", move);
3580
+ event.preventDefault();
3581
+ return true;
3582
+ }
3583
+ function setDragging(view, dragging) {
3584
+ view.dispatch(
3585
+ view.state.tr.setMeta(rowResizingPluginKey, { setDragging: dragging })
3586
+ );
3587
+ }
3588
+ function currentRowHeight(view, cellPos) {
3589
+ const info = targetRowInfo(view, cellPos);
3590
+ const tr = rowTrElement(view, cellPos, info.row);
3591
+ return tr ? tr.offsetHeight : ROW_RESIZE_MIN_HEIGHT;
3592
+ }
3593
+ function commitRowHeight(view, cellPos, height) {
3594
+ const { table, map, start, row } = targetRowInfo(view, cellPos);
3595
+ const tr = view.state.tr;
3596
+ const seen = /* @__PURE__ */ new Set();
3597
+ for (let col = 0; col < map.width; col++) {
3598
+ const cellRelPos = map.map[row * map.width + col];
3599
+ if (seen.has(cellRelPos)) {
3600
+ continue;
3601
+ }
3602
+ seen.add(cellRelPos);
3603
+ const rect = map.findCell(cellRelPos);
3604
+ if (rect.bottom - 1 !== row) {
3605
+ continue;
3606
+ }
3607
+ const node = table.nodeAt(cellRelPos);
3608
+ if (!node || node.attrs.rowHeight === height) {
3609
+ continue;
3610
+ }
3611
+ tr.setNodeMarkup(start + cellRelPos, void 0, {
3612
+ ...node.attrs,
3613
+ rowHeight: height
3614
+ });
3615
+ }
3616
+ if (tr.docChanged) {
3617
+ view.dispatch(tr);
3618
+ }
3619
+ }
3620
+ function targetRowInfo(view, cellPos) {
3621
+ const $cell = view.state.doc.resolve(cellPos);
3622
+ const table = $cell.node(-1);
3623
+ const map = import_prosemirror_tables.TableMap.get(table);
3624
+ const start = $cell.start(-1);
3625
+ const rect = map.findCell($cell.pos - start);
3626
+ return { table, map, start, row: rect.bottom - 1, $cell };
3627
+ }
3628
+ function rowTrElement(view, cellPos, row) {
3629
+ let dom = view.nodeDOM(cellPos);
3630
+ while (dom && dom.nodeName !== "TABLE") {
3631
+ dom = dom.parentNode;
3632
+ }
3633
+ if (!dom) {
3634
+ return null;
3635
+ }
3636
+ return dom.rows[row] ?? null;
3637
+ }
3638
+ function domCellAround(target) {
3639
+ let node = target;
3640
+ while (node && node.nodeName !== "TD" && node.nodeName !== "TH") {
3641
+ node = node.classList?.contains("ProseMirror") ? null : node.parentNode;
3642
+ }
3643
+ return node;
3644
+ }
3645
+ function edgeCell(view, event, side, handleWidth) {
3646
+ const offset2 = side === "bottom" ? -handleWidth : handleWidth;
3647
+ const found = view.posAtCoords({
3648
+ left: event.clientX,
3649
+ top: event.clientY + offset2
3650
+ });
3651
+ if (!found) {
3652
+ return -1;
3653
+ }
3654
+ const $cell = (0, import_prosemirror_tables.cellAround)(view.state.doc.resolve(found.pos));
3655
+ if (!$cell) {
3656
+ return -1;
3657
+ }
3658
+ if (side === "bottom") {
3659
+ return $cell.pos;
3660
+ }
3661
+ const map = import_prosemirror_tables.TableMap.get($cell.node(-1));
3662
+ const start = $cell.start(-1);
3663
+ const index = map.map.indexOf($cell.pos - start);
3664
+ return index < map.width ? -1 : start + map.map[index - map.width];
3665
+ }
3666
+ function updateHandle(view, value) {
3667
+ view.dispatch(
3668
+ view.state.tr.setMeta(rowResizingPluginKey, { setHandle: value })
3669
+ );
3670
+ }
3671
+ function draggedHeight(dragging, event, minHeight) {
3672
+ const offset2 = event.clientY - dragging.startY;
3673
+ return Math.max(minHeight, dragging.startHeight + offset2);
3674
+ }
3675
+ function handleDecorations(state, pluginState) {
3676
+ const decorations = [];
3677
+ const $cell = state.doc.resolve(pluginState.activeHandle);
3678
+ const table = $cell.node(-1);
3679
+ if (!table) {
3680
+ return import_prosemirror_view2.DecorationSet.empty;
3681
+ }
3682
+ const map = import_prosemirror_tables.TableMap.get(table);
3683
+ const start = $cell.start(-1);
3684
+ const row = map.findCell($cell.pos - start).bottom - 1;
3685
+ const dragging = pluginState.dragging;
3686
+ const seen = /* @__PURE__ */ new Set();
3687
+ for (let col = 0; col < map.width; col++) {
3688
+ const cellRelPos = map.map[row * map.width + col];
3689
+ if (seen.has(cellRelPos)) {
3690
+ continue;
3691
+ }
3692
+ seen.add(cellRelPos);
3693
+ if (map.findCell(cellRelPos).bottom - 1 !== row) {
3694
+ continue;
3695
+ }
3696
+ const node = table.nodeAt(cellRelPos);
3697
+ if (!node) {
3698
+ continue;
3699
+ }
3700
+ const from = start + cellRelPos;
3701
+ const to = from + node.nodeSize;
3702
+ if (dragging) {
3703
+ decorations.push(
3704
+ import_prosemirror_view2.Decoration.node(from, to, {
3705
+ class: "row-resize-dragging",
3706
+ style: `height: ${dragging.currentHeight}px`
3707
+ })
3708
+ );
3709
+ }
3710
+ const handle = document.createElement("div");
3711
+ handle.className = "row-resize-handle";
3712
+ decorations.push(import_prosemirror_view2.Decoration.widget(to - 1, handle));
3713
+ }
3714
+ return import_prosemirror_view2.DecorationSet.create(state.doc, decorations);
3715
+ }
3716
+
3717
+ // src/extensions/tableCellAttrPreserve.ts
3718
+ var import_prosemirror_state4 = require("prosemirror-state");
3719
+ var tableCellAttrPreserveKey = new import_prosemirror_state4.PluginKey(
3720
+ "lumirTableCellAttrPreserve"
3721
+ );
3722
+ var PRESERVED_ATTRS = [
3723
+ { name: "rowHeight", default: null },
3724
+ { name: "verticalAlignment", default: "top" }
3725
+ ];
3726
+ function isMeaningful(attrName, value, def) {
3727
+ if (value === null || value === void 0) {
3728
+ return false;
3729
+ }
3730
+ return value !== def;
3731
+ }
3732
+ function meaningfulAttrs(node) {
3733
+ let out = null;
3734
+ for (const { name, default: def } of PRESERVED_ATTRS) {
3735
+ const v = node.attrs?.[name];
3736
+ if (isMeaningful(name, v, def)) {
3737
+ (out ?? (out = {}))[name] = v;
3738
+ }
3739
+ }
3740
+ return out;
3741
+ }
3742
+ function collectCellAttrs(doc) {
3743
+ const result = /* @__PURE__ */ new Map();
3744
+ doc.descendants((node) => {
3745
+ if (node.type.name !== "blockContainer") {
3746
+ return void 0;
3747
+ }
3748
+ const id = node.attrs?.id;
3749
+ const table = node.firstChild;
3750
+ if (!id || table?.type.name !== "table") {
3751
+ return void 0;
3752
+ }
3753
+ const cells = /* @__PURE__ */ new Map();
3754
+ let rowIndex = 0;
3755
+ table.forEach((rowNode) => {
3756
+ if (rowNode.type.name === "tableRow") {
3757
+ let cellIndex = 0;
3758
+ rowNode.forEach((cellNode) => {
3759
+ const attrs = meaningfulAttrs(cellNode);
3760
+ if (attrs) {
3761
+ cells.set(`${rowIndex}:${cellIndex}`, attrs);
3762
+ }
3763
+ cellIndex++;
3764
+ });
3765
+ rowIndex++;
3766
+ }
3767
+ });
3768
+ if (cells.size > 0) {
3769
+ result.set(id, cells);
3770
+ }
3771
+ return false;
3772
+ });
3773
+ return result;
3774
+ }
3775
+ function tableCellAttrPreserve() {
3776
+ return new import_prosemirror_state4.Plugin({
3777
+ key: tableCellAttrPreserveKey,
3778
+ appendTransaction(transactions, oldState, newState) {
3779
+ if (!transactions.some((tr2) => tr2.docChanged)) {
3780
+ return null;
3781
+ }
3782
+ const oldMap = collectCellAttrs(oldState.doc);
3783
+ if (oldMap.size === 0) {
3784
+ return null;
3785
+ }
3786
+ const tr = newState.tr;
3787
+ let changed = false;
3788
+ let curTableCells = null;
3789
+ let curRowIndex = -1;
3790
+ let curCellIndex = 0;
3791
+ newState.doc.descendants((node, pos) => {
3792
+ const name = node.type.name;
3793
+ if (name === "blockContainer") {
3794
+ const id = node.attrs?.id;
3795
+ const table = node.firstChild;
3796
+ if (id && table?.type.name === "table" && oldMap.has(id)) {
3797
+ curTableCells = oldMap.get(id);
3798
+ curRowIndex = -1;
3799
+ } else {
3800
+ curTableCells = null;
3801
+ }
3802
+ return void 0;
3803
+ }
3804
+ if (!curTableCells) {
3805
+ return void 0;
3806
+ }
3807
+ if (name === "tableRow") {
3808
+ curRowIndex++;
3809
+ curCellIndex = 0;
3810
+ return void 0;
3811
+ }
3812
+ if (name === "tableCell" || name === "tableHeader") {
3813
+ const wanted = curTableCells.get(`${curRowIndex}:${curCellIndex}`);
3814
+ curCellIndex++;
3815
+ if (wanted) {
3816
+ const patch = {};
3817
+ let needs = false;
3818
+ for (const { name: attrName, default: def } of PRESERVED_ATTRS) {
3819
+ if (!(attrName in wanted)) {
3820
+ continue;
3821
+ }
3822
+ const cur = node.attrs?.[attrName];
3823
+ if (cur === null || cur === void 0 || cur === def) {
3824
+ patch[attrName] = wanted[attrName];
3825
+ needs = true;
3826
+ }
3827
+ }
3828
+ if (needs) {
3829
+ tr.setNodeMarkup(pos, void 0, { ...node.attrs, ...patch });
3830
+ changed = true;
3831
+ }
3832
+ }
3833
+ return false;
3834
+ }
3835
+ return void 0;
3836
+ });
3837
+ return changed ? tr : null;
3838
+ }
3839
+ });
3840
+ }
3841
+
3842
+ // src/extensions/RowHeightExtension.ts
3843
+ var RowHeightExtension = import_core5.Extension.create({
3844
+ name: "rowHeight",
3845
+ addOptions() {
3846
+ return { resizable: true };
3847
+ },
3848
+ addGlobalAttributes() {
3849
+ return [
3850
+ {
3851
+ types: ["tableCell", "tableHeader"],
3852
+ attributes: {
3853
+ rowHeight: {
3854
+ default: null,
3855
+ parseHTML: (element) => {
3856
+ const fromStyle = parseInt(element.style?.height ?? "", 10);
3857
+ if (Number.isFinite(fromStyle) && fromStyle > 0) {
3858
+ return fromStyle;
3859
+ }
3860
+ const fromAttr = parseInt(
3861
+ element.getAttribute("data-row-height") ?? "",
3862
+ 10
3863
+ );
3864
+ return Number.isFinite(fromAttr) && fromAttr > 0 ? fromAttr : null;
3865
+ },
3866
+ renderHTML: (attributes) => {
3867
+ const h = attributes.rowHeight;
3868
+ if (!h || typeof h !== "number") {
3869
+ return {};
3870
+ }
3871
+ return { style: `height: ${h}px` };
3872
+ }
3873
+ }
3874
+ }
3875
+ }
3876
+ ];
3877
+ },
3878
+ addProseMirrorPlugins() {
3879
+ const plugins = [tableCellAttrPreserve()];
3880
+ if (this.options.resizable) {
3881
+ plugins.push(rowResizing());
3882
+ }
3883
+ return plugins;
3884
+ }
3885
+ });
3886
+
3887
+ // src/extensions/TableAlignmentExtension.ts
3888
+ var import_core6 = require("@tiptap/core");
3889
+ var import_prosemirror_state5 = require("prosemirror-state");
3890
+ var import_prosemirror_view3 = require("prosemirror-view");
3891
+ var tableAlignmentDecoKey = new import_prosemirror_state5.PluginKey("lumirTableAlignmentDeco");
3892
+ function tableAlignmentDecorationPlugin() {
3893
+ return new import_prosemirror_state5.Plugin({
3894
+ key: tableAlignmentDecoKey,
3895
+ props: {
3896
+ decorations(state) {
3897
+ const decorations = [];
3898
+ state.doc.descendants((node, pos) => {
3899
+ if (node.type.name === "table") {
3900
+ const align = node.attrs.tableAlignment;
3901
+ if (align && align !== "left") {
3902
+ decorations.push(
3903
+ import_prosemirror_view3.Decoration.node(pos, pos + node.nodeSize, {
3904
+ "data-table-alignment": align
3905
+ })
3906
+ );
3907
+ }
3908
+ return false;
3909
+ }
3910
+ return void 0;
3911
+ });
3912
+ return import_prosemirror_view3.DecorationSet.create(state.doc, decorations);
3913
+ }
3914
+ }
3915
+ });
3916
+ }
3917
+ var TableAlignmentExtension = import_core6.Extension.create({
3918
+ name: "tableAlignment",
3919
+ addGlobalAttributes() {
3920
+ return [
3921
+ {
3922
+ types: ["table"],
3923
+ attributes: {
3924
+ tableAlignment: {
3925
+ default: "left",
3926
+ parseHTML: (element) => element.getAttribute("data-table-alignment") || "left",
3927
+ renderHTML: (attributes) => {
3928
+ if (!attributes.tableAlignment || attributes.tableAlignment === "left") {
3929
+ return {};
3930
+ }
3931
+ return { "data-table-alignment": attributes.tableAlignment };
3932
+ }
3933
+ }
3934
+ }
3935
+ }
3936
+ ];
3937
+ },
3938
+ addProseMirrorPlugins() {
3939
+ return [tableAlignmentDecorationPlugin()];
3940
+ }
3941
+ });
3942
+
3943
+ // src/blocks/columns/insertColumns.ts
3944
+ var import_prosemirror_state6 = require("prosemirror-state");
3945
+ function insertTwoColumns(editor) {
3946
+ const tiptap = editor?._tiptapEditor;
3947
+ if (!tiptap) {
3948
+ return false;
3949
+ }
3950
+ const { state, schema: schema2 } = tiptap;
3951
+ const { blockContainer, paragraph, column, columnList } = schema2.nodes;
3952
+ if (!blockContainer || !paragraph || !column || !columnList) {
3953
+ return false;
3954
+ }
3955
+ const $from = state.selection.$from;
3956
+ for (let d = $from.depth; d > 0; d--) {
3957
+ const name = $from.node(d).type.name;
3958
+ if (name === "column" || name === "columnList") {
3959
+ return false;
3960
+ }
3961
+ }
3962
+ let depth = $from.depth;
3963
+ while (depth > 0 && $from.node(depth).type.name !== "blockContainer") {
3964
+ depth--;
3965
+ }
3966
+ if (depth === 0) {
3967
+ return false;
3968
+ }
3969
+ const insertPos = $from.after(depth);
3970
+ const mkBlock = () => blockContainer.create(null, paragraph.create());
3971
+ const mkColumn = () => column.create(null, mkBlock());
3972
+ const list = columnList.create(null, [mkColumn(), mkColumn()]);
3973
+ try {
3974
+ let tr = state.tr.insert(insertPos, list);
3975
+ try {
3976
+ tr = tr.setSelection(import_prosemirror_state6.TextSelection.create(tr.doc, insertPos + 4));
3977
+ } catch {
3978
+ }
3979
+ tiptap.view.dispatch(tr.scrollIntoView());
3980
+ return true;
3981
+ } catch {
3982
+ return false;
3983
+ }
3984
+ }
3985
+
3066
3986
  // src/components/CustomFormattingToolbar.tsx
3067
- var import_react28 = require("@blocknote/react");
3987
+ var import_react30 = require("@blocknote/react");
3068
3988
 
3069
3989
  // src/components/TextAlignButtonWithVA.tsx
3070
- var import_core3 = require("@blocknote/core");
3990
+ var import_core7 = require("@blocknote/core");
3071
3991
  var import_react20 = require("react");
3072
3992
  var import_react21 = require("@blocknote/react");
3073
3993
  var import_jsx_runtime19 = require("react/jsx-runtime");
@@ -3089,7 +4009,7 @@ var TextAlignButtonWithVA = (props) => {
3089
4009
  const selectedBlocks = (0, import_react21.useSelectedBlocks)(editor);
3090
4010
  const textAlignment = (0, import_react20.useMemo)(() => {
3091
4011
  const block = selectedBlocks[0];
3092
- if ((0, import_core3.checkBlockHasDefaultProp)("textAlignment", block, editor)) {
4012
+ if ((0, import_core7.checkBlockHasDefaultProp)("textAlignment", block, editor)) {
3093
4013
  return block.props.textAlignment;
3094
4014
  }
3095
4015
  if (block.type === "table") {
@@ -3098,7 +4018,7 @@ var TextAlignButtonWithVA = (props) => {
3098
4018
  return;
3099
4019
  }
3100
4020
  const allCellsInTable = cellSelection.cells.map(
3101
- ({ row, col }) => (0, import_core3.mapTableCell)(
4021
+ ({ row, col }) => (0, import_core7.mapTableCell)(
3102
4022
  block.content.rows[row].cells[col]
3103
4023
  ).props.textAlignment
3104
4024
  );
@@ -3130,7 +4050,7 @@ var TextAlignButtonWithVA = (props) => {
3130
4050
  }
3131
4051
  }
3132
4052
  tiptap.view?.dispatch(tr);
3133
- } else if ((0, import_core3.checkBlockTypeHasDefaultProp)("textAlignment", block.type, editor)) {
4053
+ } else if ((0, import_core7.checkBlockTypeHasDefaultProp)("textAlignment", block.type, editor)) {
3134
4054
  editor.updateBlock(block, {
3135
4055
  props: { textAlignment: newAlignment }
3136
4056
  });
@@ -3246,14 +4166,74 @@ var VerticalAlignButton = (props) => {
3246
4166
  );
3247
4167
  };
3248
4168
 
3249
- // src/components/FontSizeButton.tsx
3250
- var import_react24 = require("@blocknote/react");
3251
- var import_react25 = require("react");
4169
+ // src/components/TableAlignButton.tsx
4170
+ var import_react24 = require("react");
4171
+ var import_react25 = require("@blocknote/react");
3252
4172
  var import_jsx_runtime21 = require("react/jsx-runtime");
4173
+ var icons3 = {
4174
+ left: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
4175
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("rect", { x: "1.5", y: "4", width: "7", height: "8", rx: "1", fill: "currentColor", stroke: "none" }),
4176
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("line", { x1: "1.5", y1: "1.5", x2: "14.5", y2: "1.5" }),
4177
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("line", { x1: "1.5", y1: "14.5", x2: "14.5", y2: "14.5" })
4178
+ ] }),
4179
+ center: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
4180
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("rect", { x: "4.5", y: "4", width: "7", height: "8", rx: "1", fill: "currentColor", stroke: "none" }),
4181
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("line", { x1: "1.5", y1: "1.5", x2: "14.5", y2: "1.5" }),
4182
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("line", { x1: "1.5", y1: "14.5", x2: "14.5", y2: "14.5" })
4183
+ ] }),
4184
+ right: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
4185
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("rect", { x: "7.5", y: "4", width: "7", height: "8", rx: "1", fill: "currentColor", stroke: "none" }),
4186
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("line", { x1: "1.5", y1: "1.5", x2: "14.5", y2: "1.5" }),
4187
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("line", { x1: "1.5", y1: "14.5", x2: "14.5", y2: "14.5" })
4188
+ ] })
4189
+ };
4190
+ var tooltips2 = {
4191
+ left: "\uD45C \uC67C\uCABD \uC815\uB82C",
4192
+ center: "\uD45C \uAC00\uC6B4\uB370 \uC815\uB82C",
4193
+ right: "\uD45C \uC624\uB978\uCABD \uC815\uB82C"
4194
+ };
4195
+ var TableAlignButton = (props) => {
4196
+ const Components = (0, import_react25.useComponentsContext)();
4197
+ const editor = (0, import_react25.useBlockNoteEditor)();
4198
+ const selectedBlocks = (0, import_react25.useSelectedBlocks)(editor);
4199
+ const tableBlock = (0, import_react24.useMemo)(
4200
+ () => selectedBlocks.find((block) => block.type === "table"),
4201
+ [selectedBlocks]
4202
+ );
4203
+ const current = (0, import_react24.useMemo)(() => {
4204
+ if (!tableBlock?.id) return "left";
4205
+ return getTableAlignment(editor, tableBlock.id);
4206
+ }, [editor, tableBlock, selectedBlocks]);
4207
+ const apply = (0, import_react24.useCallback)(() => {
4208
+ if (!tableBlock?.id) return;
4209
+ editor.focus();
4210
+ setTableAlignment(editor, tableBlock.id, props.alignment);
4211
+ }, [editor, tableBlock, props.alignment]);
4212
+ if (!tableBlock || !editor.isEditable) {
4213
+ return null;
4214
+ }
4215
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4216
+ Components.FormattingToolbar.Button,
4217
+ {
4218
+ className: "bn-button",
4219
+ "data-test": `tableAlign${props.alignment.charAt(0).toUpperCase() + props.alignment.slice(1)}`,
4220
+ onClick: apply,
4221
+ isSelected: current === props.alignment,
4222
+ label: tooltips2[props.alignment],
4223
+ mainTooltip: tooltips2[props.alignment],
4224
+ icon: icons3[props.alignment]
4225
+ }
4226
+ );
4227
+ };
4228
+
4229
+ // src/components/FontSizeButton.tsx
4230
+ var import_react26 = require("@blocknote/react");
4231
+ var import_react27 = require("react");
4232
+ var import_jsx_runtime22 = require("react/jsx-runtime");
3253
4233
  var DEFAULT_LABEL2 = "\uAE30\uBCF8";
3254
4234
  var toLabel2 = (size) => size.replace(/px$/, "");
3255
4235
  function FontSizeIcon({ size }) {
3256
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4236
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3257
4237
  "span",
3258
4238
  {
3259
4239
  style: {
@@ -3268,21 +4248,21 @@ function FontSizeIcon({ size }) {
3268
4248
  );
3269
4249
  }
3270
4250
  function FontSizeButton2() {
3271
- const Components = (0, import_react24.useComponentsContext)();
3272
- const editor = (0, import_react24.useBlockNoteEditor)();
4251
+ const Components = (0, import_react26.useComponentsContext)();
4252
+ const editor = (0, import_react26.useBlockNoteEditor)();
3273
4253
  const ed = editor;
3274
4254
  const styleSchema = editor.schema.styleSchema;
3275
4255
  const fontSizeInSchema = styleSchema.fontSize?.type === "fontSize" && styleSchema.fontSize?.propSchema === "string";
3276
- const selectedBlocks = (0, import_react24.useSelectedBlocks)(editor);
3277
- const [currentSize, setCurrentSize] = (0, import_react25.useState)(
4256
+ const selectedBlocks = (0, import_react26.useSelectedBlocks)(editor);
4257
+ const [currentSize, setCurrentSize] = (0, import_react27.useState)(
3278
4258
  fontSizeInSchema ? ed.getActiveStyles().fontSize || "" : ""
3279
4259
  );
3280
- (0, import_react24.useEditorContentOrSelectionChange)(() => {
4260
+ (0, import_react26.useEditorContentOrSelectionChange)(() => {
3281
4261
  if (fontSizeInSchema) {
3282
4262
  setCurrentSize(ed.getActiveStyles().fontSize || "");
3283
4263
  }
3284
4264
  }, editor);
3285
- const setFontSize = (0, import_react25.useCallback)(
4265
+ const setFontSize = (0, import_react27.useCallback)(
3286
4266
  (size) => {
3287
4267
  size === "" ? ed.removeStyles({ fontSize: "" }) : ed.addStyles({ fontSize: size });
3288
4268
  setTimeout(() => editor.focus());
@@ -3290,7 +4270,7 @@ function FontSizeButton2() {
3290
4270
  // eslint-disable-next-line react-hooks/exhaustive-deps
3291
4271
  [editor]
3292
4272
  );
3293
- const show = (0, import_react25.useMemo)(() => {
4273
+ const show = (0, import_react27.useMemo)(() => {
3294
4274
  if (!fontSizeInSchema) {
3295
4275
  return false;
3296
4276
  }
@@ -3305,20 +4285,20 @@ function FontSizeButton2() {
3305
4285
  return null;
3306
4286
  }
3307
4287
  const tooltip = "\uAE00\uC790 \uD06C\uAE30";
3308
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Components.Generic.Menu.Root, { children: [
3309
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4288
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Components.Generic.Menu.Root, { children: [
4289
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3310
4290
  Components.FormattingToolbar.Button,
3311
4291
  {
3312
4292
  className: "bn-button",
3313
4293
  "data-test": "font-size",
3314
4294
  label: tooltip,
3315
4295
  mainTooltip: tooltip,
3316
- icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FontSizeIcon, { size: currentSize })
4296
+ icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FontSizeIcon, { size: currentSize })
3317
4297
  }
3318
4298
  ) }),
3319
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Components.Generic.Menu.Dropdown, { className: "bn-menu-dropdown", children: [
3320
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Components.Generic.Menu.Label, { children: "\uAE00\uC790 \uD06C\uAE30" }),
3321
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4299
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Components.Generic.Menu.Dropdown, { className: "bn-menu-dropdown", children: [
4300
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Components.Generic.Menu.Label, { children: "\uAE00\uC790 \uD06C\uAE30" }),
4301
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3322
4302
  Components.Generic.Menu.Item,
3323
4303
  {
3324
4304
  onClick: () => setFontSize(""),
@@ -3328,7 +4308,7 @@ function FontSizeButton2() {
3328
4308
  },
3329
4309
  "font-size-default"
3330
4310
  ),
3331
- FONT_SIZE_PRESETS.map((size) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4311
+ FONT_SIZE_PRESETS.map((size) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3332
4312
  Components.Generic.Menu.Item,
3333
4313
  {
3334
4314
  onClick: () => setFontSize(size),
@@ -3343,10 +4323,10 @@ function FontSizeButton2() {
3343
4323
  }
3344
4324
 
3345
4325
  // src/components/color/LumirColorControls.tsx
3346
- var import_core4 = require("@blocknote/core");
3347
- var import_react26 = require("@blocknote/react");
3348
- var import_react27 = require("react");
3349
- var import_jsx_runtime22 = require("react/jsx-runtime");
4326
+ var import_core8 = require("@blocknote/core");
4327
+ var import_react28 = require("@blocknote/react");
4328
+ var import_react29 = require("react");
4329
+ var import_jsx_runtime23 = require("react/jsx-runtime");
3350
4330
  var COLORS = [
3351
4331
  "default",
3352
4332
  "gray",
@@ -3363,7 +4343,7 @@ function ColorIcon(props) {
3363
4343
  const textColor = props.textColor || "default";
3364
4344
  const backgroundColor = props.backgroundColor || "default";
3365
4345
  const size = props.size || 16;
3366
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4346
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3367
4347
  "div",
3368
4348
  {
3369
4349
  className: "bn-color-icon",
@@ -3382,7 +4362,7 @@ function ColorIcon(props) {
3382
4362
  );
3383
4363
  }
3384
4364
  function CellFillIcon({ size = 18 }) {
3385
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4365
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3386
4366
  "svg",
3387
4367
  {
3388
4368
  width: size,
@@ -3391,17 +4371,17 @@ function CellFillIcon({ size = 18 }) {
3391
4371
  fill: "currentColor",
3392
4372
  style: { pointerEvents: "none" },
3393
4373
  "aria-hidden": "true",
3394
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M16.56 8.94 7.62 0 6.21 1.41l2.38 2.38-5.15 5.15c-.59.59-.59 1.54 0 2.12l5.5 5.5c.29.29.68.44 1.06.44s.77-.15 1.06-.44l5.5-5.5c.59-.58.59-1.53 0-2.12zM5.21 10 10 5.21 14.79 10H5.21zM19 11.5s-2 2.17-2 3.5c0 1.1.9 2 2 2s2-.9 2-2c0-1.33-2-3.5-2-3.5z" })
4374
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { d: "M16.56 8.94 7.62 0 6.21 1.41l2.38 2.38-5.15 5.15c-.59.59-.59 1.54 0 2.12l5.5 5.5c.29.29.68.44 1.06.44s.77-.15 1.06-.44l5.5-5.5c.59-.58.59-1.53 0-2.12zM5.21 10 10 5.21 14.79 10H5.21zM19 11.5s-2 2.17-2 3.5c0 1.1.9 2 2 2s2-.9 2-2c0-1.33-2-3.5-2-3.5z" })
3395
4375
  }
3396
4376
  );
3397
4377
  }
3398
4378
  function LumirColorPicker(props) {
3399
- const Components = (0, import_react26.useComponentsContext)();
3400
- const dict = (0, import_react26.useDictionary)();
3401
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
3402
- props.text ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
3403
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Components.Generic.Menu.Label, { children: props.textTitle ?? dict.color_picker.text_title }),
3404
- COLORS.map((color) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4379
+ const Components = (0, import_react28.useComponentsContext)();
4380
+ const dict = (0, import_react28.useDictionary)();
4381
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
4382
+ props.text ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
4383
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Components.Generic.Menu.Label, { children: props.textTitle ?? dict.color_picker.text_title }),
4384
+ COLORS.map((color) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3405
4385
  Components.Generic.Menu.Item,
3406
4386
  {
3407
4387
  onClick: () => {
@@ -3409,16 +4389,16 @@ function LumirColorPicker(props) {
3409
4389
  props.text.setColor(color);
3410
4390
  },
3411
4391
  "data-test": "text-color-" + color,
3412
- icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ColorIcon, { textColor: color, size: props.iconSize }),
4392
+ icon: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ColorIcon, { textColor: color, size: props.iconSize }),
3413
4393
  checked: props.text.color === color,
3414
4394
  children: dict.color_picker.colors[color]
3415
4395
  },
3416
4396
  "text-color-" + color
3417
4397
  ))
3418
4398
  ] }) : null,
3419
- props.background ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
3420
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Components.Generic.Menu.Label, { children: props.backgroundTitle ?? dict.color_picker.background_title }),
3421
- COLORS.map((color) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4399
+ props.background ? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
4400
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Components.Generic.Menu.Label, { children: props.backgroundTitle ?? dict.color_picker.background_title }),
4401
+ COLORS.map((color) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3422
4402
  Components.Generic.Menu.Item,
3423
4403
  {
3424
4404
  onClick: () => {
@@ -3426,7 +4406,7 @@ function LumirColorPicker(props) {
3426
4406
  props.background.setColor(color);
3427
4407
  },
3428
4408
  "data-test": "background-color-" + color,
3429
- icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ColorIcon, { backgroundColor: color, size: props.iconSize }),
4409
+ icon: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ColorIcon, { backgroundColor: color, size: props.iconSize }),
3430
4410
  checked: props.background.color === color,
3431
4411
  children: dict.color_picker.colors[color]
3432
4412
  },
@@ -3436,20 +4416,20 @@ function LumirColorPicker(props) {
3436
4416
  ] });
3437
4417
  }
3438
4418
  function LumirColorStyleButton() {
3439
- const Components = (0, import_react26.useComponentsContext)();
3440
- const editor = (0, import_react26.useBlockNoteEditor)();
4419
+ const Components = (0, import_react28.useComponentsContext)();
4420
+ const editor = (0, import_react28.useBlockNoteEditor)();
3441
4421
  const ed = editor;
3442
4422
  const styleSchema = editor.schema.styleSchema;
3443
4423
  const textColorInSchema = styleSchema.textColor?.type === "textColor" && styleSchema.textColor?.propSchema === "string";
3444
4424
  const backgroundColorInSchema = styleSchema.backgroundColor?.type === "backgroundColor" && styleSchema.backgroundColor?.propSchema === "string";
3445
- const selectedBlocks = (0, import_react26.useSelectedBlocks)(editor);
3446
- const [currentTextColor, setCurrentTextColor] = (0, import_react27.useState)(
4425
+ const selectedBlocks = (0, import_react28.useSelectedBlocks)(editor);
4426
+ const [currentTextColor, setCurrentTextColor] = (0, import_react29.useState)(
3447
4427
  textColorInSchema ? ed.getActiveStyles().textColor || "default" : "default"
3448
4428
  );
3449
- const [currentBackgroundColor, setCurrentBackgroundColor] = (0, import_react27.useState)(
4429
+ const [currentBackgroundColor, setCurrentBackgroundColor] = (0, import_react29.useState)(
3450
4430
  backgroundColorInSchema ? ed.getActiveStyles().backgroundColor || "default" : "default"
3451
4431
  );
3452
- (0, import_react26.useEditorContentOrSelectionChange)(() => {
4432
+ (0, import_react28.useEditorContentOrSelectionChange)(() => {
3453
4433
  const active = ed.getActiveStyles();
3454
4434
  if (textColorInSchema) {
3455
4435
  setCurrentTextColor(active.textColor || "default");
@@ -3458,7 +4438,7 @@ function LumirColorStyleButton() {
3458
4438
  setCurrentBackgroundColor(active.backgroundColor || "default");
3459
4439
  }
3460
4440
  }, editor);
3461
- const setTextColor = (0, import_react27.useCallback)(
4441
+ const setTextColor = (0, import_react29.useCallback)(
3462
4442
  (color) => {
3463
4443
  color === "default" ? ed.removeStyles({ textColor: color }) : ed.addStyles({ textColor: color });
3464
4444
  setTimeout(() => editor.focus());
@@ -3466,7 +4446,7 @@ function LumirColorStyleButton() {
3466
4446
  // eslint-disable-next-line react-hooks/exhaustive-deps
3467
4447
  [editor]
3468
4448
  );
3469
- const setBackgroundColor = (0, import_react27.useCallback)(
4449
+ const setBackgroundColor = (0, import_react29.useCallback)(
3470
4450
  (color) => {
3471
4451
  color === "default" ? ed.removeStyles({ backgroundColor: color }) : ed.addStyles({ backgroundColor: color });
3472
4452
  setTimeout(() => editor.focus());
@@ -3474,7 +4454,7 @@ function LumirColorStyleButton() {
3474
4454
  // eslint-disable-next-line react-hooks/exhaustive-deps
3475
4455
  [editor]
3476
4456
  );
3477
- const show = (0, import_react27.useMemo)(() => {
4457
+ const show = (0, import_react29.useMemo)(() => {
3478
4458
  if (!textColorInSchema && !backgroundColorInSchema) {
3479
4459
  return false;
3480
4460
  }
@@ -3489,15 +4469,15 @@ function LumirColorStyleButton() {
3489
4469
  return null;
3490
4470
  }
3491
4471
  const tooltip = "\uD14D\uC2A4\uD2B8 \uC0C9\xB7\uBC30\uACBD";
3492
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Components.Generic.Menu.Root, { children: [
3493
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4472
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Components.Generic.Menu.Root, { children: [
4473
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3494
4474
  Components.FormattingToolbar.Button,
3495
4475
  {
3496
4476
  className: "bn-button",
3497
4477
  "data-test": "colors",
3498
4478
  label: tooltip,
3499
4479
  mainTooltip: tooltip,
3500
- icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4480
+ icon: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3501
4481
  ColorIcon,
3502
4482
  {
3503
4483
  textColor: currentTextColor,
@@ -3507,11 +4487,11 @@ function LumirColorStyleButton() {
3507
4487
  )
3508
4488
  }
3509
4489
  ) }),
3510
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4490
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3511
4491
  Components.Generic.Menu.Dropdown,
3512
4492
  {
3513
4493
  className: "bn-menu-dropdown bn-color-picker-dropdown",
3514
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4494
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3515
4495
  LumirColorPicker,
3516
4496
  {
3517
4497
  textTitle: "\uD14D\uC2A4\uD2B8 \uC0C9",
@@ -3525,18 +4505,18 @@ function LumirColorStyleButton() {
3525
4505
  ] });
3526
4506
  }
3527
4507
  function LumirCellColorToolbarButton() {
3528
- const Components = (0, import_react26.useComponentsContext)();
3529
- const editor = (0, import_react26.useBlockNoteEditor)();
3530
- const selectedBlocks = (0, import_react26.useSelectedBlocks)(editor);
3531
- const isMultiCell = (0, import_react27.useMemo)(() => {
4508
+ const Components = (0, import_react28.useComponentsContext)();
4509
+ const editor = (0, import_react28.useBlockNoteEditor)();
4510
+ const selectedBlocks = (0, import_react28.useSelectedBlocks)(editor);
4511
+ const isMultiCell = (0, import_react29.useMemo)(() => {
3532
4512
  if (selectedBlocks.length !== 1 || selectedBlocks[0].type !== "table") {
3533
4513
  return false;
3534
4514
  }
3535
4515
  const cs = editor.tableHandles?.getCellSelection();
3536
4516
  return !!cs && cs.cells.length > 1;
3537
4517
  }, [editor, selectedBlocks]);
3538
- const stashRef = (0, import_react27.useRef)([]);
3539
- const applyBackground = (0, import_react27.useCallback)(
4518
+ const stashRef = (0, import_react29.useRef)([]);
4519
+ const applyBackground = (0, import_react29.useCallback)(
3540
4520
  (color) => {
3541
4521
  const live = getSelectedCellPositions(editor);
3542
4522
  const positions = live.length > 0 ? live : stashRef.current;
@@ -3549,7 +4529,7 @@ function LumirCellColorToolbarButton() {
3549
4529
  return null;
3550
4530
  }
3551
4531
  const tooltip = "\uC140 \uBC30\uACBD\uC0C9";
3552
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4532
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
3553
4533
  Components.Generic.Menu.Root,
3554
4534
  {
3555
4535
  onOpenChange: (open) => {
@@ -3558,21 +4538,21 @@ function LumirCellColorToolbarButton() {
3558
4538
  }
3559
4539
  },
3560
4540
  children: [
3561
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4541
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3562
4542
  Components.FormattingToolbar.Button,
3563
4543
  {
3564
4544
  className: "bn-button",
3565
4545
  "data-test": "cell-colors",
3566
4546
  label: tooltip,
3567
4547
  mainTooltip: tooltip,
3568
- icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CellFillIcon, { size: 18 })
4548
+ icon: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CellFillIcon, { size: 18 })
3569
4549
  }
3570
4550
  ) }),
3571
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4551
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3572
4552
  Components.Generic.Menu.Dropdown,
3573
4553
  {
3574
4554
  className: "bn-menu-dropdown bn-color-picker-dropdown",
3575
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4555
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3576
4556
  LumirColorPicker,
3577
4557
  {
3578
4558
  backgroundTitle: "\uC140 \uBC30\uACBD",
@@ -3586,12 +4566,12 @@ function LumirCellColorToolbarButton() {
3586
4566
  );
3587
4567
  }
3588
4568
  function LumirCellColorPickerButton(props) {
3589
- const Components = (0, import_react26.useComponentsContext)();
3590
- const editor = (0, import_react26.useBlockNoteEditor)();
4569
+ const Components = (0, import_react28.useComponentsContext)();
4570
+ const editor = (0, import_react28.useBlockNoteEditor)();
3591
4571
  const updateColor = (color, type) => {
3592
4572
  const newTable = props.block.content.rows.map((row) => ({
3593
4573
  ...row,
3594
- cells: row.cells.map((cell) => (0, import_core4.mapTableCell)(cell))
4574
+ cells: row.cells.map((cell) => (0, import_core8.mapTableCell)(cell))
3595
4575
  }));
3596
4576
  if (type === "text") {
3597
4577
  newTable[props.rowIndex].cells[props.colIndex].props.textColor = color;
@@ -3608,25 +4588,25 @@ function LumirCellColorPickerButton(props) {
3608
4588
  if (!currentCell || editor.settings.tables.cellTextColor === false && editor.settings.tables.cellBackgroundColor === false) {
3609
4589
  return null;
3610
4590
  }
3611
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Components.Generic.Menu.Root, { position: "right", sub: true, children: [
3612
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Components.Generic.Menu.Trigger, { sub: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Components.Generic.Menu.Item, { className: "bn-menu-item", subTrigger: true, children: "\uC140 \uC0C9\xB7\uBC30\uACBD" }) }),
3613
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4591
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Components.Generic.Menu.Root, { position: "right", sub: true, children: [
4592
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Components.Generic.Menu.Trigger, { sub: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Components.Generic.Menu.Item, { className: "bn-menu-item", subTrigger: true, children: "\uC140 \uC0C9\xB7\uBC30\uACBD" }) }),
4593
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3614
4594
  Components.Generic.Menu.Dropdown,
3615
4595
  {
3616
4596
  sub: true,
3617
4597
  className: "bn-menu-dropdown bn-color-picker-dropdown",
3618
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4598
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3619
4599
  LumirColorPicker,
3620
4600
  {
3621
4601
  iconSize: 18,
3622
4602
  textTitle: "\uC140 \uAE00\uC790\uC0C9",
3623
4603
  backgroundTitle: "\uC140 \uBC30\uACBD",
3624
4604
  text: editor.settings.tables.cellTextColor ? {
3625
- color: (0, import_core4.isTableCell)(currentCell) ? currentCell.props.textColor : "default",
4605
+ color: (0, import_core8.isTableCell)(currentCell) ? currentCell.props.textColor : "default",
3626
4606
  setColor: (color) => updateColor(color, "text")
3627
4607
  } : void 0,
3628
4608
  background: editor.settings.tables.cellBackgroundColor ? {
3629
- color: (0, import_core4.isTableCell)(currentCell) ? currentCell.props.backgroundColor : "default",
4609
+ color: (0, import_core8.isTableCell)(currentCell) ? currentCell.props.backgroundColor : "default",
3630
4610
  setColor: (color) => updateColor(color, "background")
3631
4611
  } : void 0
3632
4612
  }
@@ -3636,21 +4616,21 @@ function LumirCellColorPickerButton(props) {
3636
4616
  ] });
3637
4617
  }
3638
4618
  function LumirTableCellMenu(props) {
3639
- const Components = (0, import_react26.useComponentsContext)();
3640
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4619
+ const Components = (0, import_react28.useComponentsContext)();
4620
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3641
4621
  Components.Generic.Menu.Dropdown,
3642
4622
  {
3643
4623
  className: "bn-menu-dropdown bn-drag-handle-menu",
3644
- children: props.children || /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
3645
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3646
- import_react26.SplitButton,
4624
+ children: props.children || /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
4625
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4626
+ import_react28.SplitButton,
3647
4627
  {
3648
4628
  block: props.block,
3649
4629
  rowIndex: props.rowIndex,
3650
4630
  colIndex: props.colIndex
3651
4631
  }
3652
4632
  ),
3653
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4633
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3654
4634
  LumirCellColorPickerButton,
3655
4635
  {
3656
4636
  block: props.block,
@@ -3664,96 +4644,164 @@ function LumirTableCellMenu(props) {
3664
4644
  }
3665
4645
 
3666
4646
  // src/components/CustomFormattingToolbar.tsx
3667
- var import_jsx_runtime23 = require("react/jsx-runtime");
4647
+ var import_jsx_runtime24 = require("react/jsx-runtime");
3668
4648
  var CustomFormattingToolbar = () => {
3669
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react28.FormattingToolbar, { children: [
3670
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react28.BlockTypeSelect, {}, "blockTypeSelect"),
3671
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react28.TableCellMergeButton, {}, "tableCellMergeButton"),
3672
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react28.FileCaptionButton, {}, "fileCaptionButton"),
3673
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react28.FileReplaceButton, {}, "replaceFileButton"),
3674
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react28.FileRenameButton, {}, "fileRenameButton"),
3675
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react28.FileDeleteButton, {}, "fileDeleteButton"),
3676
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react28.FileDownloadButton, {}, "fileDownloadButton"),
3677
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react28.FilePreviewButton, {}, "filePreviewButton"),
3678
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react28.BasicTextStyleButton, { basicTextStyle: "bold" }, "boldStyleButton"),
3679
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3680
- import_react28.BasicTextStyleButton,
4649
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react30.FormattingToolbar, { children: [
4650
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react30.BlockTypeSelect, {}, "blockTypeSelect"),
4651
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react30.TableCellMergeButton, {}, "tableCellMergeButton"),
4652
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react30.FileCaptionButton, {}, "fileCaptionButton"),
4653
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react30.FileReplaceButton, {}, "replaceFileButton"),
4654
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react30.FileRenameButton, {}, "fileRenameButton"),
4655
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react30.FileDeleteButton, {}, "fileDeleteButton"),
4656
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react30.FileDownloadButton, {}, "fileDownloadButton"),
4657
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react30.FilePreviewButton, {}, "filePreviewButton"),
4658
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react30.BasicTextStyleButton, { basicTextStyle: "bold" }, "boldStyleButton"),
4659
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4660
+ import_react30.BasicTextStyleButton,
3681
4661
  {
3682
4662
  basicTextStyle: "italic"
3683
4663
  },
3684
4664
  "italicStyleButton"
3685
4665
  ),
3686
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3687
- import_react28.BasicTextStyleButton,
4666
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4667
+ import_react30.BasicTextStyleButton,
3688
4668
  {
3689
4669
  basicTextStyle: "underline"
3690
4670
  },
3691
4671
  "underlineStyleButton"
3692
4672
  ),
3693
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3694
- import_react28.BasicTextStyleButton,
4673
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4674
+ import_react30.BasicTextStyleButton,
3695
4675
  {
3696
4676
  basicTextStyle: "strike"
3697
4677
  },
3698
4678
  "strikeStyleButton"
3699
4679
  ),
3700
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TextAlignButtonWithVA, { textAlignment: "left" }, "textAlignLeftButton"),
3701
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4680
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TextAlignButtonWithVA, { textAlignment: "left" }, "textAlignLeftButton"),
4681
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3702
4682
  TextAlignButtonWithVA,
3703
4683
  {
3704
4684
  textAlignment: "center"
3705
4685
  },
3706
4686
  "textAlignCenterButton"
3707
4687
  ),
3708
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TextAlignButtonWithVA, { textAlignment: "right" }, "textAlignRightButton"),
3709
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4688
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TextAlignButtonWithVA, { textAlignment: "right" }, "textAlignRightButton"),
4689
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3710
4690
  VerticalAlignButton,
3711
4691
  {
3712
4692
  verticalAlignment: "top"
3713
4693
  },
3714
4694
  "verticalAlignTop"
3715
4695
  ),
3716
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4696
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3717
4697
  VerticalAlignButton,
3718
4698
  {
3719
4699
  verticalAlignment: "middle"
3720
4700
  },
3721
4701
  "verticalAlignMiddle"
3722
4702
  ),
3723
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4703
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3724
4704
  VerticalAlignButton,
3725
4705
  {
3726
4706
  verticalAlignment: "bottom"
3727
4707
  },
3728
4708
  "verticalAlignBottom"
3729
4709
  ),
3730
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(FontSizeButton2, {}, "fontSizeButton"),
3731
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(LumirColorStyleButton, {}, "colorStyleButton"),
3732
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(LumirCellColorToolbarButton, {}, "cellColorButton"),
3733
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react28.NestBlockButton, {}, "nestBlockButton"),
3734
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react28.UnnestBlockButton, {}, "unnestBlockButton"),
3735
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react28.CreateLinkButton, {}, "createLinkButton")
4710
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TableAlignButton, { alignment: "left" }, "tableAlignLeft"),
4711
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TableAlignButton, { alignment: "center" }, "tableAlignCenter"),
4712
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TableAlignButton, { alignment: "right" }, "tableAlignRight"),
4713
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(FontSizeButton2, {}, "fontSizeButton"),
4714
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LumirColorStyleButton, {}, "colorStyleButton"),
4715
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(LumirCellColorToolbarButton, {}, "cellColorButton"),
4716
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react30.NestBlockButton, {}, "nestBlockButton"),
4717
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react30.UnnestBlockButton, {}, "unnestBlockButton"),
4718
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react30.CreateLinkButton, {}, "createLinkButton")
3736
4719
  ] });
3737
4720
  };
3738
4721
 
3739
- // src/components/LumirTableHandlesController.tsx
4722
+ // src/components/LumirDragHandleMenu.tsx
3740
4723
  var import_react31 = require("@blocknote/react");
3741
- var import_react32 = require("@floating-ui/react");
3742
- var import_react33 = require("react");
4724
+ var import_jsx_runtime25 = require("react/jsx-runtime");
4725
+ var TABLE_ALIGN_ICONS = {
4726
+ left: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
4727
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("rect", { x: "1.5", y: "4", width: "7", height: "8", rx: "1", fill: "currentColor", stroke: "none" }),
4728
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("line", { x1: "1.5", y1: "1.5", x2: "14.5", y2: "1.5" }),
4729
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("line", { x1: "1.5", y1: "14.5", x2: "14.5", y2: "14.5" })
4730
+ ] }),
4731
+ center: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
4732
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("rect", { x: "4.5", y: "4", width: "7", height: "8", rx: "1", fill: "currentColor", stroke: "none" }),
4733
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("line", { x1: "1.5", y1: "1.5", x2: "14.5", y2: "1.5" }),
4734
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("line", { x1: "1.5", y1: "14.5", x2: "14.5", y2: "14.5" })
4735
+ ] }),
4736
+ right: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
4737
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("rect", { x: "7.5", y: "4", width: "7", height: "8", rx: "1", fill: "currentColor", stroke: "none" }),
4738
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("line", { x1: "1.5", y1: "1.5", x2: "14.5", y2: "1.5" }),
4739
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("line", { x1: "1.5", y1: "14.5", x2: "14.5", y2: "14.5" })
4740
+ ] })
4741
+ };
4742
+ var TABLE_ALIGN_LABELS = {
4743
+ left: "\uD45C \uC67C\uCABD \uC815\uB82C",
4744
+ center: "\uD45C \uAC00\uC6B4\uB370 \uC815\uB82C",
4745
+ right: "\uD45C \uC624\uB978\uCABD \uC815\uB82C"
4746
+ };
4747
+ function TableAlignmentItems(props) {
4748
+ const Components = (0, import_react31.useComponentsContext)();
4749
+ const editor = (0, import_react31.useBlockNoteEditor)();
4750
+ if (props.block?.type !== "table" || !props.block?.id) {
4751
+ return null;
4752
+ }
4753
+ const current = getTableAlignment(editor, props.block.id);
4754
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_jsx_runtime25.Fragment, { children: ["left", "center", "right"].map((align) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4755
+ Components.Generic.Menu.Item,
4756
+ {
4757
+ icon: TABLE_ALIGN_ICONS[align],
4758
+ checked: current === align,
4759
+ onClick: () => {
4760
+ setTableAlignment(editor, props.block.id, align);
4761
+ editor.setTextCursorPosition(props.block.id);
4762
+ },
4763
+ children: TABLE_ALIGN_LABELS[align]
4764
+ },
4765
+ `tableAlign-${align}`
4766
+ )) });
4767
+ }
4768
+ var LumirDragHandleMenu = (props) => {
4769
+ const dict = (0, import_react31.useDictionary)();
4770
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react31.DragHandleMenu, { ...props, children: [
4771
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react31.RemoveBlockItem, { ...props, children: dict.drag_handle.delete_menuitem }),
4772
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react31.BlockColorsItem, { ...props, children: dict.drag_handle.colors_menuitem }),
4773
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react31.TableRowHeaderItem, { ...props, children: dict.drag_handle.header_row_menuitem }),
4774
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react31.TableColumnHeaderItem, { ...props, children: dict.drag_handle.header_column_menuitem }),
4775
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TableAlignmentItems, { block: props.block })
4776
+ ] });
4777
+ };
4778
+
4779
+ // src/components/LumirTableHandlesController.tsx
4780
+ var import_react34 = require("@blocknote/react");
4781
+ var import_react35 = require("@floating-ui/react");
4782
+ var import_react36 = require("react");
3743
4783
 
3744
4784
  // src/components/hooks/useFocusedCellHandlePositioning.ts
3745
- var import_react29 = require("@floating-ui/react");
3746
- var import_react30 = require("react");
4785
+ var import_react32 = require("@floating-ui/react");
4786
+ var import_react33 = require("react");
3747
4787
  function useFocusedCellHandlePositioning(cellEl, tbodyEl, orientation, show) {
3748
- const { refs, floatingStyles, context } = (0, import_react29.useFloating)({
4788
+ const { refs, floatingStyles, context, update } = (0, import_react32.useFloating)({
3749
4789
  open: show,
3750
4790
  placement: orientation === "row" ? "left" : orientation === "col" ? "top" : "right",
3751
4791
  // col/row: 가장자리 선(zero-size)에, cell: 셀 우측 보더에 14px hit-area 중앙 정렬(-7).
3752
- middleware: [(0, import_react29.offset)(-7)],
3753
- whileElementsMounted: import_react29.autoUpdate
4792
+ middleware: [(0, import_react32.offset)(-7)],
4793
+ whileElementsMounted: import_react32.autoUpdate
3754
4794
  });
3755
- const { isMounted, styles } = (0, import_react29.useTransitionStyles)(context);
3756
- (0, import_react30.useEffect)(() => {
4795
+ const { isMounted, styles } = (0, import_react32.useTransitionStyles)(context);
4796
+ (0, import_react33.useEffect)(() => {
4797
+ if (!show || !tbodyEl) {
4798
+ return;
4799
+ }
4800
+ const ro = new ResizeObserver(() => update());
4801
+ ro.observe(tbodyEl);
4802
+ return () => ro.disconnect();
4803
+ }, [show, tbodyEl, update]);
4804
+ (0, import_react33.useEffect)(() => {
3757
4805
  if (!cellEl) {
3758
4806
  refs.setReference(null);
3759
4807
  return;
@@ -3773,7 +4821,7 @@ function useFocusedCellHandlePositioning(cellEl, tbodyEl, orientation, show) {
3773
4821
  }
3774
4822
  });
3775
4823
  }, [cellEl, tbodyEl, orientation, refs]);
3776
- return (0, import_react30.useMemo)(
4824
+ return (0, import_react33.useMemo)(
3777
4825
  () => ({
3778
4826
  isMounted,
3779
4827
  ref: refs.setFloating,
@@ -3788,7 +4836,7 @@ function useFocusedCellHandlePositioning(cellEl, tbodyEl, orientation, show) {
3788
4836
  }
3789
4837
 
3790
4838
  // src/components/LumirTableHandlesController.tsx
3791
- var import_jsx_runtime24 = require("react/jsx-runtime");
4839
+ var import_jsx_runtime26 = require("react/jsx-runtime");
3792
4840
  function syncCoreHoverToFocusedCell(cellEl) {
3793
4841
  const r = cellEl.getBoundingClientRect();
3794
4842
  cellEl.dispatchEvent(
@@ -3802,15 +4850,15 @@ function syncCoreHoverToFocusedCell(cellEl) {
3802
4850
  );
3803
4851
  }
3804
4852
  function LumirTableHandlesController() {
3805
- const editor = (0, import_react31.useBlockNoteEditor)();
3806
- const [focused, setFocused] = (0, import_react33.useState)(null);
3807
- const [menuContainerRef, setMenuContainerRef] = (0, import_react33.useState)(null);
3808
- const [overlayEl, setOverlayEl] = (0, import_react33.useState)(null);
3809
- const [openMenu, setOpenMenu] = (0, import_react33.useState)(null);
3810
- const frozenRef = (0, import_react33.useRef)(false);
3811
- const menuOpenRef = (0, import_react33.useRef)(false);
3812
- const draggingRef = (0, import_react33.useRef)(false);
3813
- const recompute = (0, import_react33.useCallback)(() => {
4853
+ const editor = (0, import_react34.useBlockNoteEditor)();
4854
+ const [focused, setFocused] = (0, import_react36.useState)(null);
4855
+ const [menuContainerRef, setMenuContainerRef] = (0, import_react36.useState)(null);
4856
+ const [overlayEl, setOverlayEl] = (0, import_react36.useState)(null);
4857
+ const [openMenu, setOpenMenu] = (0, import_react36.useState)(null);
4858
+ const frozenRef = (0, import_react36.useRef)(false);
4859
+ const menuOpenRef = (0, import_react36.useRef)(false);
4860
+ const draggingRef = (0, import_react36.useRef)(false);
4861
+ const recompute = (0, import_react36.useCallback)(() => {
3814
4862
  if (frozenRef.current) {
3815
4863
  return;
3816
4864
  }
@@ -3858,11 +4906,11 @@ function LumirTableHandlesController() {
3858
4906
  widgetContainer
3859
4907
  });
3860
4908
  }, [editor]);
3861
- (0, import_react31.useEditorContentOrSelectionChange)(recompute, editor);
3862
- (0, import_react33.useEffect)(() => {
4909
+ (0, import_react34.useEditorContentOrSelectionChange)(recompute, editor);
4910
+ (0, import_react36.useEffect)(() => {
3863
4911
  recompute();
3864
4912
  }, [recompute]);
3865
- (0, import_react33.useEffect)(() => {
4913
+ (0, import_react36.useEffect)(() => {
3866
4914
  const onUp = () => {
3867
4915
  requestAnimationFrame(() => {
3868
4916
  if (!menuOpenRef.current && !draggingRef.current && frozenRef.current) {
@@ -3874,7 +4922,7 @@ function LumirTableHandlesController() {
3874
4922
  window.addEventListener("pointerup", onUp);
3875
4923
  return () => window.removeEventListener("pointerup", onUp);
3876
4924
  }, [recompute]);
3877
- (0, import_react33.useEffect)(() => {
4925
+ (0, import_react36.useEffect)(() => {
3878
4926
  const f = focused;
3879
4927
  if (!f || !overlayEl) {
3880
4928
  return;
@@ -3899,7 +4947,13 @@ function LumirTableHandlesController() {
3899
4947
  overlayEl.style.height = `${bottom - top}px`;
3900
4948
  };
3901
4949
  update();
3902
- return (0, import_react32.autoUpdate)(f.cellEl, overlayEl, update);
4950
+ const stopAutoUpdate = (0, import_react35.autoUpdate)(f.cellEl, overlayEl, update);
4951
+ const ro = new ResizeObserver(update);
4952
+ ro.observe(f.tbodyEl);
4953
+ return () => {
4954
+ stopAutoUpdate();
4955
+ ro.disconnect();
4956
+ };
3903
4957
  }, [focused, overlayEl, openMenu]);
3904
4958
  const cellEl = focused?.cellEl ?? null;
3905
4959
  const tbodyEl = focused?.tbodyEl ?? null;
@@ -3913,21 +4967,21 @@ function LumirTableHandlesController() {
3913
4967
  show
3914
4968
  );
3915
4969
  const th = editor.tableHandles;
3916
- const coreState = (0, import_react31.useUIPluginState)(
4970
+ const coreState = (0, import_react34.useUIPluginState)(
3917
4971
  editor.tableHandles.onUpdate.bind(editor.tableHandles)
3918
4972
  );
3919
- const { addOrRemoveColumnsButton, addOrRemoveRowsButton } = (0, import_react31.useExtendButtonsPositioning)(
4973
+ const { addOrRemoveColumnsButton, addOrRemoveRowsButton } = (0, import_react34.useExtendButtonsPositioning)(
3920
4974
  coreState?.showAddOrRemoveColumnsButton || false,
3921
4975
  coreState?.showAddOrRemoveRowsButton || false,
3922
4976
  coreState?.referencePosTable || null
3923
4977
  );
3924
- const onStartExtend = (0, import_react33.useCallback)(() => {
4978
+ const onStartExtend = (0, import_react36.useCallback)(() => {
3925
4979
  editor.tableHandles?.freezeHandles();
3926
4980
  }, [editor]);
3927
- const onEndExtend = (0, import_react33.useCallback)(() => {
4981
+ const onEndExtend = (0, import_react36.useCallback)(() => {
3928
4982
  editor.tableHandles?.unfreezeHandles();
3929
4983
  }, [editor]);
3930
- const menuHandlers = (0, import_react33.useMemo)(() => {
4984
+ const menuHandlers = (0, import_react36.useMemo)(() => {
3931
4985
  const mk = (kind) => ({
3932
4986
  freeze: () => {
3933
4987
  menuOpenRef.current = true;
@@ -3945,10 +4999,10 @@ function LumirTableHandlesController() {
3945
4999
  });
3946
5000
  return { col: mk("col"), row: mk("row"), cell: mk("cell") };
3947
5001
  }, [editor, recompute]);
3948
- const onGutterPointerDown = (0, import_react33.useCallback)(() => {
5002
+ const onGutterPointerDown = (0, import_react36.useCallback)(() => {
3949
5003
  frozenRef.current = true;
3950
5004
  }, []);
3951
- const onGutterPointerEnter = (0, import_react33.useCallback)(
5005
+ const onGutterPointerEnter = (0, import_react36.useCallback)(
3952
5006
  (e) => {
3953
5007
  if (e.buttons === 0 && focused) {
3954
5008
  syncCoreHoverToFocusedCell(focused.cellEl);
@@ -3956,7 +5010,7 @@ function LumirTableHandlesController() {
3956
5010
  },
3957
5011
  [focused]
3958
5012
  );
3959
- const makeDragStart = (0, import_react33.useCallback)(
5013
+ const makeDragStart = (0, import_react36.useCallback)(
3960
5014
  (dir) => (e) => {
3961
5015
  draggingRef.current = true;
3962
5016
  frozenRef.current = true;
@@ -3968,19 +5022,19 @@ function LumirTableHandlesController() {
3968
5022
  },
3969
5023
  [editor]
3970
5024
  );
3971
- const onDragEnd = (0, import_react33.useCallback)(() => {
5025
+ const onDragEnd = (0, import_react36.useCallback)(() => {
3972
5026
  editor.tableHandles?.dragEnd();
3973
5027
  draggingRef.current = false;
3974
5028
  frozenRef.current = false;
3975
5029
  recompute();
3976
5030
  }, [editor, recompute]);
3977
- const noop = (0, import_react33.useCallback)(() => {
5031
+ const noop = (0, import_react36.useCallback)(() => {
3978
5032
  }, []);
3979
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
3980
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { ref: setMenuContainerRef }),
3981
- th && focused && menuContainerRef && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react32.FloatingPortal, { root: focused.widgetContainer, children: [
3982
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { ref: setOverlayEl, className: "lumir-tbl-cell-focus" }),
3983
- colHandle.isMounted && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5033
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5034
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { ref: setMenuContainerRef }),
5035
+ th && focused && menuContainerRef && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_react35.FloatingPortal, { root: focused.widgetContainer, children: [
5036
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { ref: setOverlayEl, className: "lumir-tbl-cell-focus" }),
5037
+ colHandle.isMounted && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
3984
5038
  "div",
3985
5039
  {
3986
5040
  ref: colHandle.ref,
@@ -3989,9 +5043,9 @@ function LumirTableHandlesController() {
3989
5043
  onPointerEnter: onGutterPointerEnter,
3990
5044
  onPointerDown: onGutterPointerDown,
3991
5045
  children: [
3992
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "lumir-tbl-gutter" }),
3993
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3994
- import_react31.TableHandle,
5046
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "lumir-tbl-gutter" }),
5047
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5048
+ import_react34.TableHandle,
3995
5049
  {
3996
5050
  editor,
3997
5051
  orientation: "column",
@@ -4009,7 +5063,7 @@ function LumirTableHandlesController() {
4009
5063
  ]
4010
5064
  }
4011
5065
  ),
4012
- rowHandle.isMounted && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5066
+ rowHandle.isMounted && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
4013
5067
  "div",
4014
5068
  {
4015
5069
  ref: rowHandle.ref,
@@ -4018,9 +5072,9 @@ function LumirTableHandlesController() {
4018
5072
  onPointerEnter: onGutterPointerEnter,
4019
5073
  onPointerDown: onGutterPointerDown,
4020
5074
  children: [
4021
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "lumir-tbl-gutter" }),
4022
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4023
- import_react31.TableHandle,
5075
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "lumir-tbl-gutter" }),
5076
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5077
+ import_react34.TableHandle,
4024
5078
  {
4025
5079
  editor,
4026
5080
  orientation: "row",
@@ -4038,7 +5092,7 @@ function LumirTableHandlesController() {
4038
5092
  ]
4039
5093
  }
4040
5094
  ),
4041
- cellHandle.isMounted && openMenu !== "col" && openMenu !== "row" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5095
+ cellHandle.isMounted && openMenu !== "col" && openMenu !== "row" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
4042
5096
  "div",
4043
5097
  {
4044
5098
  ref: cellHandle.ref,
@@ -4046,9 +5100,9 @@ function LumirTableHandlesController() {
4046
5100
  className: "lumir-tbl-gutter-wrap lumir-tbl-gutter-wrap--cell" + (openMenu === "cell" ? " lumir-tbl-gutter-wrap--active" : ""),
4047
5101
  onPointerDown: onGutterPointerDown,
4048
5102
  children: [
4049
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "lumir-tbl-gutter" }),
4050
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4051
- import_react31.TableCellButton,
5103
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "lumir-tbl-gutter" }),
5104
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5105
+ import_react34.TableCellButton,
4052
5106
  {
4053
5107
  editor,
4054
5108
  rowIndex: focused.rowIndex,
@@ -4064,9 +5118,9 @@ function LumirTableHandlesController() {
4064
5118
  }
4065
5119
  )
4066
5120
  ] }),
4067
- th && coreState?.widgetContainer && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react32.FloatingPortal, { root: coreState.widgetContainer, children: [
4068
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { ref: addOrRemoveRowsButton.ref, style: addOrRemoveRowsButton.style, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4069
- import_react31.ExtendButton,
5121
+ th && coreState?.widgetContainer && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_react35.FloatingPortal, { root: coreState.widgetContainer, children: [
5122
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { ref: addOrRemoveRowsButton.ref, style: addOrRemoveRowsButton.style, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5123
+ import_react34.ExtendButton,
4070
5124
  {
4071
5125
  editor,
4072
5126
  orientation: "addOrRemoveRows",
@@ -4075,13 +5129,13 @@ function LumirTableHandlesController() {
4075
5129
  onMouseUp: onEndExtend
4076
5130
  }
4077
5131
  ) }),
4078
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5132
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
4079
5133
  "div",
4080
5134
  {
4081
5135
  ref: addOrRemoveColumnsButton.ref,
4082
5136
  style: addOrRemoveColumnsButton.style,
4083
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4084
- import_react31.ExtendButton,
5137
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5138
+ import_react34.ExtendButton,
4085
5139
  {
4086
5140
  editor,
4087
5141
  orientation: "addOrRemoveColumns",
@@ -4097,15 +5151,17 @@ function LumirTableHandlesController() {
4097
5151
  }
4098
5152
 
4099
5153
  // src/utils/table-vertical-alignment.ts
4100
- function injectVerticalAlignment(blocks, editor) {
4101
- const tiptap = editor?._tiptapEditor;
4102
- if (!tiptap) return blocks;
4103
- const { doc } = tiptap.state;
4104
- const tableVAMap = buildTableVerticalAlignmentMap(doc);
4105
- if (tableVAMap.size === 0) return blocks;
4106
- return patchBlocks(blocks, tableVAMap);
5154
+ var CELL_ATTR_DEFAULTS = {
5155
+ verticalAlignment: "top",
5156
+ rowHeight: null
5157
+ };
5158
+ function isMeaningful2(attr, value) {
5159
+ if (value === null || value === void 0) {
5160
+ return false;
5161
+ }
5162
+ return value !== CELL_ATTR_DEFAULTS[attr];
4107
5163
  }
4108
- function buildTableVerticalAlignmentMap(doc) {
5164
+ function buildTableCellAttrMap(doc, attrs) {
4109
5165
  const result = /* @__PURE__ */ new Map();
4110
5166
  doc.descendants((node) => {
4111
5167
  if (node.type.name === "blockContainer") {
@@ -4118,9 +5174,15 @@ function buildTableVerticalAlignmentMap(doc) {
4118
5174
  if (rowNode.type.name === "tableRow") {
4119
5175
  let colIndex = 0;
4120
5176
  rowNode.forEach((cellNode) => {
4121
- const va = cellNode.attrs?.verticalAlignment;
4122
- if (va && va !== "top") {
4123
- cells.push({ row: rowIndex, col: colIndex, va });
5177
+ const props = {};
5178
+ for (const attr of attrs) {
5179
+ const value = cellNode.attrs?.[attr];
5180
+ if (isMeaningful2(attr, value)) {
5181
+ props[attr] = value;
5182
+ }
5183
+ }
5184
+ if (Object.keys(props).length > 0) {
5185
+ cells.push({ row: rowIndex, col: colIndex, props });
4124
5186
  }
4125
5187
  colIndex++;
4126
5188
  });
@@ -4136,18 +5198,21 @@ function buildTableVerticalAlignmentMap(doc) {
4136
5198
  });
4137
5199
  return result;
4138
5200
  }
4139
- function patchBlocks(blocks, tableVAMap) {
5201
+ function patchBlocks(blocks, cellAttrMap) {
4140
5202
  return blocks.map((block) => {
4141
5203
  if (block.type !== "table" || !block.id || !block.content) {
4142
5204
  if (block.children && block.children.length > 0) {
4143
5205
  return {
4144
5206
  ...block,
4145
- children: patchBlocks(block.children, tableVAMap)
5207
+ children: patchBlocks(
5208
+ block.children,
5209
+ cellAttrMap
5210
+ )
4146
5211
  };
4147
5212
  }
4148
5213
  return block;
4149
5214
  }
4150
- const cells = tableVAMap.get(block.id);
5215
+ const cells = cellAttrMap.get(block.id);
4151
5216
  if (!cells || cells.length === 0) {
4152
5217
  return block;
4153
5218
  }
@@ -4160,11 +5225,13 @@ function patchBlocks(blocks, tableVAMap) {
4160
5225
  const match = cells.find(
4161
5226
  (c) => c.row === rowIndex && c.col === colIndex
4162
5227
  );
4163
- if (!match) return cell;
5228
+ if (!match) {
5229
+ return cell;
5230
+ }
4164
5231
  if (cell && typeof cell === "object" && cell.type === "tableCell") {
4165
5232
  return {
4166
5233
  ...cell,
4167
- props: { ...cell.props, verticalAlignment: match.va }
5234
+ props: { ...cell.props, ...match.props }
4168
5235
  };
4169
5236
  }
4170
5237
  return cell;
@@ -4177,6 +5244,77 @@ function patchBlocks(blocks, tableVAMap) {
4177
5244
  };
4178
5245
  });
4179
5246
  }
5247
+ function injectTableCellAttrs(blocks, editor, attrs) {
5248
+ const tiptap = editor?._tiptapEditor;
5249
+ if (!tiptap) {
5250
+ return blocks;
5251
+ }
5252
+ const { doc } = tiptap.state;
5253
+ const cellAttrMap = buildTableCellAttrMap(doc, attrs);
5254
+ if (cellAttrMap.size === 0) {
5255
+ return blocks;
5256
+ }
5257
+ return patchBlocks(blocks, cellAttrMap);
5258
+ }
5259
+ var TABLE_BLOCK_ATTR_DEFAULTS = {
5260
+ tableAlignment: "left"
5261
+ };
5262
+ function buildTableBlockAttrMap(doc, attrs) {
5263
+ const result = /* @__PURE__ */ new Map();
5264
+ doc.descendants((node) => {
5265
+ if (node.type.name === "blockContainer") {
5266
+ const blockId = node.attrs?.id;
5267
+ const contentNode = node.firstChild;
5268
+ if (blockId && contentNode?.type.name === "table") {
5269
+ const props = {};
5270
+ for (const attr of attrs) {
5271
+ const value = contentNode.attrs?.[attr];
5272
+ if (value !== null && value !== void 0 && value !== TABLE_BLOCK_ATTR_DEFAULTS[attr]) {
5273
+ props[attr] = value;
5274
+ }
5275
+ }
5276
+ if (Object.keys(props).length > 0) {
5277
+ result.set(blockId, props);
5278
+ }
5279
+ }
5280
+ return false;
5281
+ }
5282
+ return void 0;
5283
+ });
5284
+ return result;
5285
+ }
5286
+ function patchTableBlockProps(blocks, attrMap) {
5287
+ return blocks.map((block) => {
5288
+ if (block.type === "table" && block.id && attrMap.has(block.id)) {
5289
+ return {
5290
+ ...block,
5291
+ props: { ...block.props, ...attrMap.get(block.id) }
5292
+ };
5293
+ }
5294
+ if (block.children && block.children.length > 0) {
5295
+ return {
5296
+ ...block,
5297
+ children: patchTableBlockProps(
5298
+ block.children,
5299
+ attrMap
5300
+ )
5301
+ };
5302
+ }
5303
+ return block;
5304
+ });
5305
+ }
5306
+ function injectTableBlockAttrs(blocks, editor) {
5307
+ const tiptap = editor?._tiptapEditor;
5308
+ if (!tiptap) {
5309
+ return blocks;
5310
+ }
5311
+ const { doc } = tiptap.state;
5312
+ const attrMap = buildTableBlockAttrMap(doc, ["tableAlignment"]);
5313
+ if (attrMap.size === 0) {
5314
+ return blocks;
5315
+ }
5316
+ return patchTableBlockProps(blocks, attrMap);
5317
+ }
4180
5318
 
4181
5319
  // src/utils/font-size-serialization.ts
4182
5320
  function mapPreservingRef(arr, fn) {
@@ -4491,26 +5629,8 @@ function normalizeExcelTableHtml(html) {
4491
5629
  }
4492
5630
  }
4493
5631
 
4494
- // src/constants/limits.ts
4495
- var MAX_FILE_SIZE = 10 * 1024 * 1024;
4496
- var MAX_VIDEO_FILE_SIZE = 100 * 1024 * 1024;
4497
- var BLOCKED_EXTENSIONS = [".svg", ".svgz"];
4498
- var ALLOWED_VIDEO_MIME_TYPES = /* @__PURE__ */ new Set([
4499
- "video/mp4",
4500
- "video/webm",
4501
- "video/ogg",
4502
- "video/quicktime"
4503
- // .mov
4504
- ]);
4505
- var ALLOWED_VIDEO_EXTENSIONS = [
4506
- ".mp4",
4507
- ".webm",
4508
- ".ogg",
4509
- ".mov"
4510
- ];
4511
-
4512
5632
  // src/components/LumirEditor.tsx
4513
- var import_jsx_runtime25 = require("react/jsx-runtime");
5633
+ var import_jsx_runtime27 = require("react/jsx-runtime");
4514
5634
  var DEBUG_LOG = (loc, msg, data) => {
4515
5635
  const p = fetch("http://127.0.0.1:7686/ingest/1f8ee1c5-0cf0-4ae7-91ed-5ea7ed17130a", {
4516
5636
  method: "POST",
@@ -4741,9 +5861,9 @@ var findBlockWithLink = (blocks, targetUrl) => {
4741
5861
  return null;
4742
5862
  };
4743
5863
  var ConvertToPreviewButton = ({ url }) => {
4744
- const editor = (0, import_react35.useBlockNoteEditor)();
4745
- const Components = (0, import_react35.useComponentsContext)();
4746
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5864
+ const editor = (0, import_react38.useBlockNoteEditor)();
5865
+ const Components = (0, import_react38.useComponentsContext)();
5866
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
4747
5867
  Components.LinkToolbar.Button,
4748
5868
  {
4749
5869
  className: "bn-button",
@@ -4762,29 +5882,29 @@ var ConvertToPreviewButton = ({ url }) => {
4762
5882
  console.error("Convert to link preview failed:", err);
4763
5883
  }
4764
5884
  },
4765
- icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
4766
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("rect", { x: "1", y: "3", width: "14", height: "10", rx: "2", stroke: "currentColor", strokeWidth: "1.5", fill: "none" }),
4767
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("line", { x1: "1", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "1.5" }),
4768
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("circle", { cx: "5", cy: "6.5", r: "1.5", stroke: "currentColor", strokeWidth: "1", fill: "none" })
5885
+ icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
5886
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("rect", { x: "1", y: "3", width: "14", height: "10", rx: "2", stroke: "currentColor", strokeWidth: "1.5", fill: "none" }),
5887
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("line", { x1: "1", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "1.5" }),
5888
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("circle", { cx: "5", cy: "6.5", r: "1.5", stroke: "currentColor", strokeWidth: "1", fill: "none" })
4769
5889
  ] })
4770
5890
  }
4771
5891
  );
4772
5892
  };
4773
5893
  var CustomLinkToolbar = (props) => {
4774
- const editor = (0, import_react35.useBlockNoteEditor)();
4775
- const Components = (0, import_react35.useComponentsContext)();
5894
+ const editor = (0, import_react38.useBlockNoteEditor)();
5895
+ const Components = (0, import_react38.useComponentsContext)();
4776
5896
  const hasLinkPreview = !!editor?._linkPreviewApiEndpoint;
4777
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5897
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
4778
5898
  Components.LinkToolbar.Root,
4779
5899
  {
4780
5900
  className: "bn-toolbar bn-link-toolbar",
4781
5901
  onMouseEnter: props.stopHideTimer,
4782
5902
  onMouseLeave: props.startHideTimer,
4783
5903
  children: [
4784
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react35.EditLinkButton, { url: props.url, text: props.text, editLink: props.editLink }),
4785
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react35.OpenLinkButton, { url: props.url }),
4786
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react35.DeleteLinkButton, { deleteLink: props.deleteLink }),
4787
- hasLinkPreview && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ConvertToPreviewButton, { url: props.url })
5904
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react38.EditLinkButton, { url: props.url, text: props.text, editLink: props.editLink }),
5905
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react38.OpenLinkButton, { url: props.url }),
5906
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react38.DeleteLinkButton, { deleteLink: props.deleteLink }),
5907
+ hasLinkPreview && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ConvertToPreviewButton, { url: props.url })
4788
5908
  ]
4789
5909
  }
4790
5910
  );
@@ -4828,13 +5948,13 @@ function LumirEditor({
4828
5948
  onError,
4829
5949
  onImageDelete
4830
5950
  }) {
4831
- const [isUploading, setIsUploading] = (0, import_react34.useState)(false);
4832
- const [uploadProgress, setUploadProgress] = (0, import_react34.useState)(null);
4833
- const [errorMessage, setErrorMessage] = (0, import_react34.useState)(null);
4834
- const floatingMenuFileInputRef = (0, import_react34.useRef)(null);
4835
- const floatingMenuBlockRef = (0, import_react34.useRef)(null);
4836
- const floatingMenuUploadStartTimeRef = (0, import_react34.useRef)(0);
4837
- const handleError = (0, import_react34.useCallback)(
5951
+ const [isUploading, setIsUploading] = (0, import_react37.useState)(false);
5952
+ const [uploadProgress, setUploadProgress] = (0, import_react37.useState)(null);
5953
+ const [errorMessage, setErrorMessage] = (0, import_react37.useState)(null);
5954
+ const floatingMenuFileInputRef = (0, import_react37.useRef)(null);
5955
+ const floatingMenuBlockRef = (0, import_react37.useRef)(null);
5956
+ const floatingMenuUploadStartTimeRef = (0, import_react37.useRef)(0);
5957
+ const handleError = (0, import_react37.useCallback)(
4838
5958
  (error) => {
4839
5959
  onError?.(error);
4840
5960
  setErrorMessage(error.getUserMessage());
@@ -4842,12 +5962,12 @@ function LumirEditor({
4842
5962
  },
4843
5963
  [onError]
4844
5964
  );
4845
- const validatedContent = (0, import_react34.useMemo)(() => {
5965
+ const validatedContent = (0, import_react37.useMemo)(() => {
4846
5966
  return liftFontSize(
4847
5967
  ContentUtils.validateContent(initialContent, initialEmptyBlocks)
4848
5968
  );
4849
5969
  }, [initialContent, initialEmptyBlocks]);
4850
- const tableConfig = (0, import_react34.useMemo)(() => {
5970
+ const tableConfig = (0, import_react37.useMemo)(() => {
4851
5971
  return EditorConfig.getDefaultTableConfig(tables);
4852
5972
  }, [
4853
5973
  tables?.splitCells,
@@ -4855,10 +5975,10 @@ function LumirEditor({
4855
5975
  tables?.cellTextColor,
4856
5976
  tables?.headers
4857
5977
  ]);
4858
- const headingConfig = (0, import_react34.useMemo)(() => {
5978
+ const headingConfig = (0, import_react37.useMemo)(() => {
4859
5979
  return EditorConfig.getDefaultHeadingConfig(heading);
4860
5980
  }, [heading?.levels?.join(",") ?? ""]);
4861
- const disabledExtensions = (0, import_react34.useMemo)(() => {
5981
+ const disabledExtensions = (0, import_react37.useMemo)(() => {
4862
5982
  return EditorConfig.getDisabledExtensions(
4863
5983
  disableExtensions,
4864
5984
  allowVideoUpload,
@@ -4866,18 +5986,18 @@ function LumirEditor({
4866
5986
  allowFileUpload
4867
5987
  );
4868
5988
  }, [disableExtensions, allowVideoUpload, allowAudioUpload, allowFileUpload]);
4869
- (0, import_react34.useEffect)(() => {
5989
+ (0, import_react37.useEffect)(() => {
4870
5990
  DEBUG_LOG("LumirEditor:init:disabledExtensions", "snapshot", {
4871
5991
  allowVideoUpload,
4872
5992
  hasVideoInDisabled: disabledExtensions.includes("video"),
4873
5993
  disabledList: disabledExtensions.slice(0, 15)
4874
5994
  });
4875
5995
  }, [allowVideoUpload, disabledExtensions]);
4876
- const fileNameTransformRef = (0, import_react34.useRef)(s3Upload?.fileNameTransform);
4877
- (0, import_react34.useEffect)(() => {
5996
+ const fileNameTransformRef = (0, import_react37.useRef)(s3Upload?.fileNameTransform);
5997
+ (0, import_react37.useEffect)(() => {
4878
5998
  fileNameTransformRef.current = s3Upload?.fileNameTransform;
4879
5999
  }, [s3Upload?.fileNameTransform]);
4880
- const memoizedS3Upload = (0, import_react34.useMemo)(() => {
6000
+ const memoizedS3Upload = (0, import_react37.useMemo)(() => {
4881
6001
  if (!s3Upload) return void 0;
4882
6002
  return {
4883
6003
  apiEndpoint: s3Upload.apiEndpoint,
@@ -4906,7 +6026,7 @@ function LumirEditor({
4906
6026
  s3Upload?.maxRetries,
4907
6027
  s3Upload?.onProgress
4908
6028
  ]);
4909
- const editor = (0, import_react35.useCreateBlockNote)(
6029
+ const editor = (0, import_react38.useCreateBlockNote)(
4910
6030
  {
4911
6031
  // HTML 미리보기 블록이 포함된 커스텀 스키마 사용
4912
6032
  schema,
@@ -4928,7 +6048,14 @@ function LumirEditor({
4928
6048
  // 확장 비활성: 비디오/오디오/파일 제어
4929
6049
  disableExtensions: disabledExtensions,
4930
6050
  _tiptapOptions: {
4931
- extensions: [VerticalAlignmentExtension]
6051
+ extensions: [
6052
+ VerticalAlignmentExtension,
6053
+ // 행 높이 attr 등록은 항상(저장된 높이 렌더), 드래그 리사이즈 UI는
6054
+ // tableHandles prop으로 게이트(기존 grip 컨트롤러와 동일 게이트).
6055
+ RowHeightExtension.configure({ resizable: tableHandles }),
6056
+ // 표 블록 정렬(좌/가운데/우) attr.
6057
+ TableAlignmentExtension
6058
+ ]
4932
6059
  },
4933
6060
  placeholders: placeholder ? { default: placeholder, emptyDocument: placeholder } : void 0,
4934
6061
  tabBehavior,
@@ -5104,18 +6231,29 @@ function LumirEditor({
5104
6231
  memoizedS3Upload,
5105
6232
  allowVideoUpload,
5106
6233
  linkPreview?.apiEndpoint,
5107
- placeholder
6234
+ placeholder,
6235
+ // tableHandles 변경 시 RowHeightExtension의 resizable 게이트가 반영되도록 재생성
6236
+ tableHandles
5108
6237
  ]
5109
6238
  );
5110
6239
  if (editor && linkPreview?.apiEndpoint) {
5111
6240
  editor._linkPreviewApiEndpoint = linkPreview.apiEndpoint;
5112
6241
  }
5113
- (0, import_react34.useEffect)(() => {
6242
+ if (editor) {
6243
+ try {
6244
+ const view = editor.prosemirrorView;
6245
+ if (view) {
6246
+ view.__lumirEditor = editor;
6247
+ }
6248
+ } catch {
6249
+ }
6250
+ }
6251
+ (0, import_react37.useEffect)(() => {
5114
6252
  if (editor) {
5115
6253
  editor.isEditable = editable;
5116
6254
  }
5117
6255
  }, [editor, editable]);
5118
- (0, import_react34.useEffect)(() => {
6256
+ (0, import_react37.useEffect)(() => {
5119
6257
  if (!editor || !floatingMenu) return;
5120
6258
  const ft = editor.formattingToolbar;
5121
6259
  if (!ft?.onUpdate) return;
@@ -5128,22 +6266,30 @@ function LumirEditor({
5128
6266
  });
5129
6267
  return unsubscribe;
5130
6268
  }, [editor, floatingMenu]);
5131
- (0, import_react34.useEffect)(() => {
6269
+ (0, import_react37.useEffect)(() => {
5132
6270
  if (!editor || !onContentChange) return;
5133
6271
  const handleContentChange = () => {
5134
6272
  const blocks = editor.topLevelBlocks;
5135
- const patched = lowerFontSize(injectVerticalAlignment(blocks, editor));
6273
+ const patched = lowerFontSize(
6274
+ injectTableBlockAttrs(
6275
+ injectTableCellAttrs(blocks, editor, [
6276
+ "verticalAlignment",
6277
+ "rowHeight"
6278
+ ]),
6279
+ editor
6280
+ )
6281
+ );
5136
6282
  onContentChange(patched);
5137
6283
  };
5138
6284
  return editor.onEditorContentChange(handleContentChange);
5139
6285
  }, [editor, onContentChange]);
5140
- const previousMediaUrlsRef = (0, import_react34.useRef)(/* @__PURE__ */ new Set());
5141
- (0, import_react34.useEffect)(() => {
6286
+ const previousMediaUrlsRef = (0, import_react37.useRef)(/* @__PURE__ */ new Set());
6287
+ (0, import_react37.useEffect)(() => {
5142
6288
  if (!editor) return;
5143
6289
  const initialBlocks = editor.topLevelBlocks;
5144
6290
  previousMediaUrlsRef.current = extractMediaUrls(initialBlocks);
5145
6291
  }, [editor]);
5146
- (0, import_react34.useEffect)(() => {
6292
+ (0, import_react37.useEffect)(() => {
5147
6293
  if (!editor || !onImageDelete) return;
5148
6294
  const handleMediaDeleteCheck = () => {
5149
6295
  const currentBlocks = editor.topLevelBlocks;
@@ -5157,7 +6303,7 @@ function LumirEditor({
5157
6303
  };
5158
6304
  return editor.onEditorContentChange(handleMediaDeleteCheck);
5159
6305
  }, [editor, onImageDelete]);
5160
- (0, import_react34.useEffect)(() => {
6306
+ (0, import_react37.useEffect)(() => {
5161
6307
  const el = editor?.domElement;
5162
6308
  if (!el) return;
5163
6309
  const handleDragOver = (e) => {
@@ -5288,20 +6434,20 @@ function LumirEditor({
5288
6434
  el.removeEventListener("drop", handleDrop, { capture: true });
5289
6435
  };
5290
6436
  }, [editor, allowVideoUpload]);
5291
- const computedSideMenu = (0, import_react34.useMemo)(() => {
6437
+ const computedSideMenu = (0, import_react37.useMemo)(() => {
5292
6438
  return sideMenuAddButton ? sideMenu : false;
5293
6439
  }, [sideMenuAddButton, sideMenu]);
5294
- const DragHandleOnlySideMenu = (0, import_react34.useMemo)(() => {
5295
- return (props) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react35.SideMenu, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react35.DragHandleButton, { ...props }) });
6440
+ const DragHandleOnlySideMenu = (0, import_react37.useMemo)(() => {
6441
+ return (props) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react38.SideMenu, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react38.DragHandleButton, { ...props, dragHandleMenu: LumirDragHandleMenu }) });
5296
6442
  }, []);
5297
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
6443
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
5298
6444
  "div",
5299
6445
  {
5300
6446
  className: cn("lumirEditor", className),
5301
6447
  style: { position: "relative", display: "flex", flexDirection: "column" },
5302
6448
  children: [
5303
- floatingMenu && editor && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
5304
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6449
+ floatingMenu && editor && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6450
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5305
6451
  "input",
5306
6452
  {
5307
6453
  ref: floatingMenuFileInputRef,
@@ -5372,7 +6518,7 @@ function LumirEditor({
5372
6518
  }
5373
6519
  }
5374
6520
  ),
5375
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6521
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5376
6522
  FloatingMenu,
5377
6523
  {
5378
6524
  editor,
@@ -5404,7 +6550,7 @@ function LumirEditor({
5404
6550
  }
5405
6551
  )
5406
6552
  ] }),
5407
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
6553
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
5408
6554
  import_mantine.BlockNoteView,
5409
6555
  {
5410
6556
  editor,
@@ -5419,21 +6565,21 @@ function LumirEditor({
5419
6565
  tableHandles: false,
5420
6566
  onSelectionChange,
5421
6567
  children: [
5422
- tableHandles && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LumirTableHandlesController, {}),
5423
- formattingToolbar && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5424
- import_react35.FormattingToolbarController,
6568
+ tableHandles && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(LumirTableHandlesController, {}),
6569
+ formattingToolbar && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6570
+ import_react38.FormattingToolbarController,
5425
6571
  {
5426
6572
  formattingToolbar: CustomFormattingToolbar
5427
6573
  }
5428
6574
  ),
5429
- linkToolbar && (linkPreview?.apiEndpoint ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react35.LinkToolbarController, { linkToolbar: CustomLinkToolbar }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react35.LinkToolbarController, {})),
5430
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5431
- import_react35.SuggestionMenuController,
6575
+ linkToolbar && (linkPreview?.apiEndpoint ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react38.LinkToolbarController, { linkToolbar: CustomLinkToolbar }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react38.LinkToolbarController, {})),
6576
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6577
+ import_react38.SuggestionMenuController,
5432
6578
  {
5433
6579
  triggerCharacter: "/",
5434
- getItems: (0, import_react34.useCallback)(
6580
+ getItems: (0, import_react37.useCallback)(
5435
6581
  async (query) => {
5436
- const items = (0, import_react35.getDefaultReactSlashMenuItems)(editor);
6582
+ const items = (0, import_react38.getDefaultReactSlashMenuItems)(editor);
5437
6583
  const filtered = items.filter((item) => {
5438
6584
  const key = (item?.key || "").toString().toLowerCase();
5439
6585
  const title = (item?.title || "").toString().toLowerCase();
@@ -5475,7 +6621,7 @@ function LumirEditor({
5475
6621
  },
5476
6622
  aliases: ["html", "preview", "\uC6F9", "\uC6F9\uD398\uC774\uC9C0"],
5477
6623
  group: "Embeds",
5478
- icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
6624
+ icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
5479
6625
  "svg",
5480
6626
  {
5481
6627
  width: "18",
@@ -5487,19 +6633,45 @@ function LumirEditor({
5487
6633
  strokeLinecap: "round",
5488
6634
  strokeLinejoin: "round",
5489
6635
  children: [
5490
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("polyline", { points: "16 18 22 12 16 6" }),
5491
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("polyline", { points: "8 6 2 12 8 18" })
6636
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("polyline", { points: "16 18 22 12 16 6" }),
6637
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("polyline", { points: "8 6 2 12 8 18" })
5492
6638
  ]
5493
6639
  }
5494
6640
  ),
5495
6641
  subtext: "HTML \uD30C\uC77C\uC744 \uBBF8\uB9AC\uBCF4\uAE30\uB85C \uC0BD\uC785"
5496
6642
  };
5497
- const allItems = [...filtered, htmlPreviewItem];
6643
+ const columnItem = {
6644
+ title: "2\uB2E8 \uCEEC\uB7FC",
6645
+ onItemClick: () => {
6646
+ insertTwoColumns(editor);
6647
+ },
6648
+ aliases: ["columns", "column", "2col", "\uB2E8", "\uCEEC\uB7FC", "\uB2E4\uB2E8", "\uBD84\uD560"],
6649
+ group: "Basic blocks",
6650
+ icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
6651
+ "svg",
6652
+ {
6653
+ width: "18",
6654
+ height: "18",
6655
+ viewBox: "0 0 24 24",
6656
+ fill: "none",
6657
+ stroke: "currentColor",
6658
+ strokeWidth: "2",
6659
+ strokeLinecap: "round",
6660
+ strokeLinejoin: "round",
6661
+ children: [
6662
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("rect", { x: "3", y: "4", width: "7", height: "16", rx: "1" }),
6663
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("rect", { x: "14", y: "4", width: "7", height: "16", rx: "1" })
6664
+ ]
6665
+ }
6666
+ ),
6667
+ subtext: "\uBE14\uB85D\uC744 \uC88C\uC6B0 2\uB2E8\uC73C\uB85C \uBC30\uCE58"
6668
+ };
6669
+ const allItems = [...filtered, htmlPreviewItem, columnItem];
5498
6670
  if (linkPreview?.apiEndpoint) {
5499
6671
  allItems.push({
5500
6672
  title: "Link Preview",
5501
6673
  onItemClick: () => {
5502
- (0, import_core5.insertOrUpdateBlock)(editor, {
6674
+ (0, import_core9.insertOrUpdateBlock)(editor, {
5503
6675
  type: "linkPreview",
5504
6676
  props: { url: "" }
5505
6677
  });
@@ -5513,7 +6685,7 @@ function LumirEditor({
5513
6685
  "\uD504\uB9AC\uBDF0"
5514
6686
  ],
5515
6687
  group: "Embeds",
5516
- icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
6688
+ icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
5517
6689
  "svg",
5518
6690
  {
5519
6691
  width: "18",
@@ -5525,8 +6697,8 @@ function LumirEditor({
5525
6697
  strokeLinecap: "round",
5526
6698
  strokeLinejoin: "round",
5527
6699
  children: [
5528
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
5529
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
6700
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
6701
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
5530
6702
  ]
5531
6703
  }
5532
6704
  ),
@@ -5562,21 +6734,21 @@ function LumirEditor({
5562
6734
  )
5563
6735
  }
5564
6736
  ),
5565
- !sideMenuAddButton && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react35.SideMenuController, { sideMenu: DragHandleOnlySideMenu })
6737
+ !sideMenuAddButton && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react38.SideMenuController, { sideMenu: DragHandleOnlySideMenu })
5566
6738
  ]
5567
6739
  }
5568
6740
  ),
5569
- isUploading && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "lumirEditor-upload-overlay", children: [
5570
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "lumirEditor-spinner" }),
5571
- uploadProgress !== null && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "lumirEditor-upload-progress", children: [
6741
+ isUploading && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "lumirEditor-upload-overlay", children: [
6742
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "lumirEditor-spinner" }),
6743
+ uploadProgress !== null && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "lumirEditor-upload-progress", children: [
5572
6744
  uploadProgress,
5573
6745
  "%"
5574
6746
  ] })
5575
6747
  ] }),
5576
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "lumirEditor-error-toast", children: [
5577
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "lumirEditor-error-icon", children: "\u26A0\uFE0F" }),
5578
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "lumirEditor-error-message", children: errorMessage }),
5579
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6748
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "lumirEditor-error-toast", children: [
6749
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "lumirEditor-error-icon", children: "\u26A0\uFE0F" }),
6750
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "lumirEditor-error-message", children: errorMessage }),
6751
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5580
6752
  "button",
5581
6753
  {
5582
6754
  className: "lumirEditor-error-close",