@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.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  // src/components/LumirEditor.tsx
4
- import { useEffect as useEffect11, useMemo as useMemo7, useCallback as useCallback20, useState as useState12, useRef as useRef12 } from "react";
4
+ import { useEffect as useEffect11, useMemo as useMemo8, useCallback as useCallback21, useState as useState12, useRef as useRef12 } from "react";
5
5
  import {
6
6
  useCreateBlockNote,
7
7
  SideMenu as BlockSideMenu,
@@ -11,8 +11,8 @@ import {
11
11
  getDefaultReactSlashMenuItems,
12
12
  LinkToolbarController,
13
13
  FormattingToolbarController,
14
- useBlockNoteEditor as useBlockNoteEditor6,
15
- useComponentsContext as useComponentsContext5,
14
+ useBlockNoteEditor as useBlockNoteEditor8,
15
+ useComponentsContext as useComponentsContext7,
16
16
  EditLinkButton,
17
17
  OpenLinkButton,
18
18
  DeleteLinkButton
@@ -260,7 +260,8 @@ import {
260
260
  defaultBlockSpecs,
261
261
  BlockNoteSchema,
262
262
  defaultInlineContentSpecs,
263
- defaultStyleSpecs
263
+ defaultStyleSpecs,
264
+ createBlockSpecFromStronglyTypedTiptapNode
264
265
  } from "@blocknote/core";
265
266
 
266
267
  // src/blocks/LinkPreview.tsx
@@ -1221,6 +1222,310 @@ var VideoBlock = createReactBlockSpec2(
1221
1222
  }
1222
1223
  );
1223
1224
 
1225
+ // src/blocks/columns/ColumnList.ts
1226
+ import { createStronglyTypedTiptapNode } from "@blocknote/core";
1227
+
1228
+ // src/blocks/columns/columnNormalization.ts
1229
+ import { Plugin, PluginKey } from "prosemirror-state";
1230
+ var columnNormalizationKey = new PluginKey("lumirColumnNormalization");
1231
+ function columnNormalization() {
1232
+ return new Plugin({
1233
+ key: columnNormalizationKey,
1234
+ appendTransaction(transactions, _oldState, newState) {
1235
+ if (!transactions.some((tr2) => tr2.docChanged)) {
1236
+ return null;
1237
+ }
1238
+ const lists = [];
1239
+ newState.doc.descendants((node, pos) => {
1240
+ if (node.type.name === "columnList") {
1241
+ lists.push({ pos, node });
1242
+ return false;
1243
+ }
1244
+ return void 0;
1245
+ });
1246
+ if (lists.length === 0) {
1247
+ return null;
1248
+ }
1249
+ const tr = newState.tr;
1250
+ let modified = false;
1251
+ for (let i = lists.length - 1; i >= 0; i--) {
1252
+ const { pos, node } = lists[i];
1253
+ const nonEmptyColumns = [];
1254
+ node.forEach((col) => {
1255
+ if (col.type.name === "column" && col.childCount > 0) {
1256
+ nonEmptyColumns.push(col);
1257
+ }
1258
+ });
1259
+ if (nonEmptyColumns.length >= 2) {
1260
+ continue;
1261
+ }
1262
+ const from = tr.mapping.map(pos);
1263
+ const to = tr.mapping.map(pos + node.nodeSize);
1264
+ const blocks = [];
1265
+ nonEmptyColumns.forEach((col) => {
1266
+ col.forEach((bc) => blocks.push(bc));
1267
+ });
1268
+ if (blocks.length > 0) {
1269
+ tr.replaceWith(from, to, blocks);
1270
+ } else {
1271
+ tr.delete(from, to);
1272
+ }
1273
+ modified = true;
1274
+ }
1275
+ return modified ? tr : null;
1276
+ }
1277
+ });
1278
+ }
1279
+
1280
+ // src/blocks/columns/columnDnd.ts
1281
+ import { Plugin as Plugin2, PluginKey as PluginKey2 } from "prosemirror-state";
1282
+ import { Decoration, DecorationSet } from "prosemirror-view";
1283
+
1284
+ // src/blocks/columns/mergeColumns.ts
1285
+ function mergeBlocksIntoColumns(editor, draggedId, targetId, side) {
1286
+ if (!editor || !draggedId || !targetId || draggedId === targetId) {
1287
+ return false;
1288
+ }
1289
+ const dragged = editor.getBlock?.(draggedId);
1290
+ const target = editor.getBlock?.(targetId);
1291
+ if (!dragged || !target) {
1292
+ return false;
1293
+ }
1294
+ if (dragged.type === "columnList" || dragged.type === "column" || target.type === "columnList" || target.type === "column") {
1295
+ return false;
1296
+ }
1297
+ const columnList = {
1298
+ type: "columnList",
1299
+ children: side === "left" ? [
1300
+ { type: "column", children: [dragged] },
1301
+ { type: "column", children: [target] }
1302
+ ] : [
1303
+ { type: "column", children: [target] },
1304
+ { type: "column", children: [dragged] }
1305
+ ]
1306
+ };
1307
+ try {
1308
+ const run = () => {
1309
+ editor.removeBlocks([draggedId]);
1310
+ editor.replaceBlocks([targetId], [columnList]);
1311
+ };
1312
+ if (typeof editor.transact === "function") {
1313
+ editor.transact(run);
1314
+ } else {
1315
+ run();
1316
+ }
1317
+ return true;
1318
+ } catch {
1319
+ return false;
1320
+ }
1321
+ }
1322
+
1323
+ // src/blocks/columns/columnDnd.ts
1324
+ var columnDndKey = new PluginKey2("lumirColumnDnd");
1325
+ function edgeThreshold(width) {
1326
+ return Math.min(80, width * 0.3);
1327
+ }
1328
+ function topLevelBlockAtCoords(view, x, y) {
1329
+ const found = view.posAtCoords({ left: x, top: y });
1330
+ if (!found) {
1331
+ return null;
1332
+ }
1333
+ const $pos = view.state.doc.resolve(found.pos);
1334
+ for (let d = $pos.depth; d > 0; d--) {
1335
+ if ($pos.node(d).type.name === "blockContainer") {
1336
+ if (d !== 2 || $pos.node(d - 1).type.name !== "blockGroup") {
1337
+ return null;
1338
+ }
1339
+ const pos = $pos.before(d);
1340
+ const node = $pos.node(d);
1341
+ const dom = view.nodeDOM(pos);
1342
+ if (!dom || !node.attrs?.id) {
1343
+ return null;
1344
+ }
1345
+ return { pos, nodeSize: node.nodeSize, id: node.attrs.id, dom };
1346
+ }
1347
+ }
1348
+ return null;
1349
+ }
1350
+ function draggedBlockId(view) {
1351
+ const sel = view.state.selection;
1352
+ return sel?.node?.attrs?.id ?? null;
1353
+ }
1354
+ function setDnd(view, next) {
1355
+ const cur = columnDndKey.getState(view.state);
1356
+ if (cur && cur.targetPos === next.targetPos && cur.side === next.side) {
1357
+ return;
1358
+ }
1359
+ view.dispatch(view.state.tr.setMeta(columnDndKey, next));
1360
+ }
1361
+ var CLEARED = { targetPos: null, side: null };
1362
+ function columnDnd() {
1363
+ return new Plugin2({
1364
+ key: columnDndKey,
1365
+ state: {
1366
+ init: () => CLEARED,
1367
+ apply(tr, prev) {
1368
+ const meta = tr.getMeta(columnDndKey);
1369
+ if (meta) {
1370
+ return meta;
1371
+ }
1372
+ if (tr.docChanged && prev.targetPos !== null) {
1373
+ return CLEARED;
1374
+ }
1375
+ return prev;
1376
+ }
1377
+ },
1378
+ props: {
1379
+ handleDOMEvents: {
1380
+ dragover: (view, event) => {
1381
+ if (!view.dragging) {
1382
+ return false;
1383
+ }
1384
+ const target = topLevelBlockAtCoords(
1385
+ view,
1386
+ event.clientX,
1387
+ event.clientY
1388
+ );
1389
+ const draggedId = draggedBlockId(view);
1390
+ if (!target || !draggedId || target.id === draggedId) {
1391
+ setDnd(view, CLEARED);
1392
+ view.dom.classList.remove("lumir-col-dnd-active");
1393
+ return false;
1394
+ }
1395
+ const rect = target.dom.getBoundingClientRect();
1396
+ const th = edgeThreshold(rect.width);
1397
+ let side = null;
1398
+ if (event.clientX - rect.left <= th) {
1399
+ side = "left";
1400
+ } else if (rect.right - event.clientX <= th) {
1401
+ side = "right";
1402
+ }
1403
+ if (side) {
1404
+ setDnd(view, { targetPos: target.pos, side });
1405
+ view.dom.classList.add("lumir-col-dnd-active");
1406
+ } else {
1407
+ setDnd(view, CLEARED);
1408
+ view.dom.classList.remove("lumir-col-dnd-active");
1409
+ }
1410
+ return false;
1411
+ },
1412
+ dragend: (view) => {
1413
+ setDnd(view, CLEARED);
1414
+ view.dom.classList.remove("lumir-col-dnd-active");
1415
+ return false;
1416
+ },
1417
+ dragleave: (view, event) => {
1418
+ if (!event.relatedTarget) {
1419
+ setDnd(view, CLEARED);
1420
+ view.dom.classList.remove("lumir-col-dnd-active");
1421
+ }
1422
+ return false;
1423
+ }
1424
+ },
1425
+ handleDrop: (view, _event, _slice, _moved) => {
1426
+ const st = columnDndKey.getState(view.state);
1427
+ view.dom.classList.remove("lumir-col-dnd-active");
1428
+ if (!st || st.side === null || st.targetPos === null) {
1429
+ return false;
1430
+ }
1431
+ const draggedId = draggedBlockId(view);
1432
+ const targetNode = view.state.doc.nodeAt(st.targetPos);
1433
+ const targetId = targetNode?.attrs?.id;
1434
+ view.dispatch(view.state.tr.setMeta(columnDndKey, CLEARED));
1435
+ if (!draggedId || !targetId) {
1436
+ return false;
1437
+ }
1438
+ const editor = view.__lumirEditor;
1439
+ if (!editor) {
1440
+ return false;
1441
+ }
1442
+ const ok = mergeBlocksIntoColumns(editor, draggedId, targetId, st.side);
1443
+ return ok;
1444
+ },
1445
+ decorations: (state) => {
1446
+ const st = columnDndKey.getState(state);
1447
+ if (!st || st.side === null || st.targetPos === null) {
1448
+ return null;
1449
+ }
1450
+ const node = state.doc.nodeAt(st.targetPos);
1451
+ if (!node) {
1452
+ return null;
1453
+ }
1454
+ return DecorationSet.create(state.doc, [
1455
+ Decoration.node(st.targetPos, st.targetPos + node.nodeSize, {
1456
+ class: st.side === "left" ? "lumir-col-drop-left" : "lumir-col-drop-right"
1457
+ })
1458
+ ]);
1459
+ }
1460
+ }
1461
+ });
1462
+ }
1463
+
1464
+ // src/blocks/columns/ColumnList.ts
1465
+ var ColumnList = createStronglyTypedTiptapNode({
1466
+ name: "columnList",
1467
+ group: "childContainer bnBlock blockGroupChild",
1468
+ content: "column column+",
1469
+ parseHTML() {
1470
+ return [{ tag: 'div[data-node-type="columnList"]' }];
1471
+ },
1472
+ renderHTML({ HTMLAttributes }) {
1473
+ const dom = document.createElement("div");
1474
+ dom.className = "bn-column-list";
1475
+ dom.setAttribute("data-node-type", "columnList");
1476
+ for (const [attribute, value] of Object.entries(HTMLAttributes)) {
1477
+ if (attribute !== "class") {
1478
+ dom.setAttribute(attribute, value);
1479
+ }
1480
+ }
1481
+ return { dom, contentDOM: dom };
1482
+ },
1483
+ // columnNormalization: 빈 컬럼/1단 columnList 자동 복구(unwrap).
1484
+ // columnDnd: 블록을 다른 블록 좌/우로 드롭하면 2단 컬럼 생성.
1485
+ addProseMirrorPlugins() {
1486
+ return [columnNormalization(), columnDnd()];
1487
+ }
1488
+ });
1489
+
1490
+ // src/blocks/columns/Column.ts
1491
+ import { createStronglyTypedTiptapNode as createStronglyTypedTiptapNode2 } from "@blocknote/core";
1492
+ var Column = createStronglyTypedTiptapNode2({
1493
+ name: "column",
1494
+ group: "bnBlock childContainer",
1495
+ content: "blockContainer+",
1496
+ addAttributes() {
1497
+ return {
1498
+ width: {
1499
+ default: 1,
1500
+ parseHTML: (element) => {
1501
+ const w = parseFloat(element.getAttribute("data-column-width") || "");
1502
+ return Number.isFinite(w) && w > 0 ? w : 1;
1503
+ },
1504
+ renderHTML: (attributes) => {
1505
+ if (!attributes.width || attributes.width === 1) {
1506
+ return {};
1507
+ }
1508
+ return { "data-column-width": String(attributes.width) };
1509
+ }
1510
+ }
1511
+ };
1512
+ },
1513
+ parseHTML() {
1514
+ return [{ tag: 'div[data-node-type="column"]' }];
1515
+ },
1516
+ renderHTML({ HTMLAttributes }) {
1517
+ const dom = document.createElement("div");
1518
+ dom.className = "bn-column";
1519
+ dom.setAttribute("data-node-type", "column");
1520
+ for (const [attribute, value] of Object.entries(HTMLAttributes)) {
1521
+ if (attribute !== "class") {
1522
+ dom.setAttribute(attribute, value);
1523
+ }
1524
+ }
1525
+ return { dom, contentDOM: dom };
1526
+ }
1527
+ });
1528
+
1224
1529
  // src/styles/FontSizeStyle.tsx
1225
1530
  import { createReactStyleSpec } from "@blocknote/react";
1226
1531
  import { jsx as jsx3 } from "react/jsx-runtime";
@@ -1326,7 +1631,7 @@ var HtmlPreviewBlock = createReactBlockSpec3(
1326
1631
  setIsResizing(true);
1327
1632
  const startY = e.clientY;
1328
1633
  const startHeight = currentHeight;
1329
- const handleMouseMove = (moveEvent) => {
1634
+ const handleMouseMove2 = (moveEvent) => {
1330
1635
  const deltaY = moveEvent.clientY - startY;
1331
1636
  const newHeight = Math.min(
1332
1637
  MAX_HEIGHT,
@@ -1338,10 +1643,10 @@ var HtmlPreviewBlock = createReactBlockSpec3(
1338
1643
  };
1339
1644
  const handleMouseUp = () => {
1340
1645
  setIsResizing(false);
1341
- document.removeEventListener("mousemove", handleMouseMove);
1646
+ document.removeEventListener("mousemove", handleMouseMove2);
1342
1647
  document.removeEventListener("mouseup", handleMouseUp);
1343
1648
  };
1344
- document.addEventListener("mousemove", handleMouseMove);
1649
+ document.addEventListener("mousemove", handleMouseMove2);
1345
1650
  document.addEventListener("mouseup", handleMouseUp);
1346
1651
  },
1347
1652
  [currentHeight, props.editor, props.block]
@@ -1607,12 +1912,19 @@ var HtmlPreviewBlock = createReactBlockSpec3(
1607
1912
  }
1608
1913
  }
1609
1914
  );
1915
+ var ColumnListBlock = createBlockSpecFromStronglyTypedTiptapNode(
1916
+ ColumnList,
1917
+ {}
1918
+ );
1919
+ var ColumnBlock = createBlockSpecFromStronglyTypedTiptapNode(Column, {});
1610
1920
  var schema = BlockNoteSchema.create({
1611
1921
  blockSpecs: {
1612
1922
  ...defaultBlockSpecs,
1613
1923
  htmlPreview: HtmlPreviewBlock,
1614
1924
  linkPreview: LinkPreviewBlock,
1615
- video: VideoBlock
1925
+ video: VideoBlock,
1926
+ columnList: ColumnListBlock,
1927
+ column: ColumnBlock
1616
1928
  },
1617
1929
  inlineContentSpecs: defaultInlineContentSpecs,
1618
1930
  styleSpecs: {
@@ -1760,7 +2072,7 @@ var UndoRedoButtons = ({ editor }) => {
1760
2072
  console.error("Redo failed:", err);
1761
2073
  }
1762
2074
  }, [editor]);
1763
- const handleMouseDown = useCallback4((e) => {
2075
+ const handleMouseDown2 = useCallback4((e) => {
1764
2076
  e.preventDefault();
1765
2077
  }, []);
1766
2078
  return /* @__PURE__ */ jsxs5("div", { className: "lumir-toolbar-group", children: [
@@ -1769,7 +2081,7 @@ var UndoRedoButtons = ({ editor }) => {
1769
2081
  {
1770
2082
  className: "lumir-toolbar-btn",
1771
2083
  onClick: handleUndo,
1772
- onMouseDown: handleMouseDown,
2084
+ onMouseDown: handleMouseDown2,
1773
2085
  title: "\uC2E4\uD589 \uCDE8\uC18C",
1774
2086
  type: "button",
1775
2087
  children: Icons.undo
@@ -1780,7 +2092,7 @@ var UndoRedoButtons = ({ editor }) => {
1780
2092
  {
1781
2093
  className: "lumir-toolbar-btn",
1782
2094
  onClick: handleRedo,
1783
- onMouseDown: handleMouseDown,
2095
+ onMouseDown: handleMouseDown2,
1784
2096
  title: "\uB2E4\uC2DC \uC2E4\uD589",
1785
2097
  type: "button",
1786
2098
  children: Icons.redo
@@ -1824,7 +2136,7 @@ var TextStyleButton = ({
1824
2136
  console.error(`Toggle ${style} failed:`, err);
1825
2137
  }
1826
2138
  }, [editor, style]);
1827
- const handleMouseDown = useCallback5((e) => {
2139
+ const handleMouseDown2 = useCallback5((e) => {
1828
2140
  e.preventDefault();
1829
2141
  }, []);
1830
2142
  return /* @__PURE__ */ jsx8(
@@ -1832,7 +2144,7 @@ var TextStyleButton = ({
1832
2144
  {
1833
2145
  className: cn("lumir-toolbar-btn", isActive && "is-active"),
1834
2146
  onClick: handleClick,
1835
- onMouseDown: handleMouseDown,
2147
+ onMouseDown: handleMouseDown2,
1836
2148
  title: titleMap[style],
1837
2149
  type: "button",
1838
2150
  children: iconMap[style]
@@ -1900,6 +2212,41 @@ function getFirstSelectedCellAttr(editor, attr) {
1900
2212
  const node = tiptap.state.doc.nodeAt(positions[0]);
1901
2213
  return node?.attrs?.[attr];
1902
2214
  }
2215
+ function findTableNodePos(tiptap, blockId) {
2216
+ let tablePos = -1;
2217
+ tiptap.state.doc.descendants((node, pos) => {
2218
+ if (tablePos !== -1) return false;
2219
+ if (node.type.name === "blockContainer" && node.attrs?.id === blockId && node.firstChild?.type.name === "table") {
2220
+ tablePos = pos + 1;
2221
+ return false;
2222
+ }
2223
+ return void 0;
2224
+ });
2225
+ return tablePos;
2226
+ }
2227
+ function setTableAlignment(editor, blockId, alignment) {
2228
+ const tiptap = editor?._tiptapEditor;
2229
+ if (!tiptap || !blockId) return false;
2230
+ const tablePos = findTableNodePos(tiptap, blockId);
2231
+ if (tablePos < 0) return false;
2232
+ const node = tiptap.state.doc.nodeAt(tablePos);
2233
+ if (!node || node.type.name !== "table") return false;
2234
+ tiptap.view?.dispatch(
2235
+ tiptap.state.tr.setNodeMarkup(tablePos, void 0, {
2236
+ ...node.attrs,
2237
+ tableAlignment: alignment
2238
+ })
2239
+ );
2240
+ return true;
2241
+ }
2242
+ function getTableAlignment(editor, blockId) {
2243
+ const tiptap = editor?._tiptapEditor;
2244
+ if (!tiptap || !blockId) return "left";
2245
+ const tablePos = findTableNodePos(tiptap, blockId);
2246
+ if (tablePos < 0) return "left";
2247
+ const node = tiptap.state.doc.nodeAt(tablePos);
2248
+ return node?.attrs?.tableAlignment || "left";
2249
+ }
1903
2250
 
1904
2251
  // src/components/FloatingMenu/components/AlignButton.tsx
1905
2252
  import { jsx as jsx9 } from "react/jsx-runtime";
@@ -1942,7 +2289,7 @@ var AlignButton = ({
1942
2289
  console.error(`Set alignment ${alignment} failed:`, err);
1943
2290
  }
1944
2291
  }, [editor, alignment]);
1945
- const handleMouseDown = useCallback6((e) => {
2292
+ const handleMouseDown2 = useCallback6((e) => {
1946
2293
  e.preventDefault();
1947
2294
  }, []);
1948
2295
  return /* @__PURE__ */ jsx9(
@@ -1950,7 +2297,7 @@ var AlignButton = ({
1950
2297
  {
1951
2298
  className: cn("lumir-toolbar-btn", isActive && "is-active"),
1952
2299
  onClick: handleClick,
1953
- onMouseDown: handleMouseDown,
2300
+ onMouseDown: handleMouseDown2,
1954
2301
  title: titleMap2[alignment],
1955
2302
  type: "button",
1956
2303
  children: iconMap2[alignment]
@@ -1992,7 +2339,7 @@ var ListButton = ({ editor, type }) => {
1992
2339
  console.error(`List toggle failed:`, err);
1993
2340
  }
1994
2341
  }, [editor, type]);
1995
- const handleMouseDown = useCallback7((e) => {
2342
+ const handleMouseDown2 = useCallback7((e) => {
1996
2343
  e.preventDefault();
1997
2344
  }, []);
1998
2345
  return /* @__PURE__ */ jsx10(
@@ -2000,7 +2347,7 @@ var ListButton = ({ editor, type }) => {
2000
2347
  {
2001
2348
  className: cn("lumir-toolbar-btn", isActive && "is-active"),
2002
2349
  onClick: handleClick,
2003
- onMouseDown: handleMouseDown,
2350
+ onMouseDown: handleMouseDown2,
2004
2351
  title: titleMap3[type],
2005
2352
  type: "button",
2006
2353
  children: iconMap3[type]
@@ -2040,7 +2387,7 @@ var ImageButton = ({
2040
2387
  input.click();
2041
2388
  }
2042
2389
  }, [editor, onImageUpload]);
2043
- const handleMouseDown = useCallback8((e) => {
2390
+ const handleMouseDown2 = useCallback8((e) => {
2044
2391
  e.preventDefault();
2045
2392
  }, []);
2046
2393
  return /* @__PURE__ */ jsx11(
@@ -2048,7 +2395,7 @@ var ImageButton = ({
2048
2395
  {
2049
2396
  className: "lumir-toolbar-btn",
2050
2397
  onClick: handleClick,
2051
- onMouseDown: handleMouseDown,
2398
+ onMouseDown: handleMouseDown2,
2052
2399
  title: "\uC774\uBBF8\uC9C0 \uC0BD\uC785",
2053
2400
  type: "button",
2054
2401
  children: Icons.image
@@ -2147,7 +2494,7 @@ var ColorButton = ({ editor, type }) => {
2147
2494
  },
2148
2495
  [editor, type]
2149
2496
  );
2150
- const handleMouseDown = useCallback9((e) => {
2497
+ const handleMouseDown2 = useCallback9((e) => {
2151
2498
  e.preventDefault();
2152
2499
  }, []);
2153
2500
  return /* @__PURE__ */ jsxs6("div", { className: "lumir-dropdown-wrapper", ref: dropdownRef, children: [
@@ -2156,7 +2503,7 @@ var ColorButton = ({ editor, type }) => {
2156
2503
  {
2157
2504
  className: "lumir-toolbar-btn lumir-color-btn",
2158
2505
  onClick: () => setIsOpen(!isOpen),
2159
- onMouseDown: handleMouseDown,
2506
+ onMouseDown: handleMouseDown2,
2160
2507
  title: type === "text" ? "\uD14D\uC2A4\uD2B8 \uC0C9\uC0C1" : "\uBC30\uACBD \uC0C9\uC0C1",
2161
2508
  type: "button",
2162
2509
  children: [
@@ -2181,7 +2528,7 @@ var ColorButton = ({ editor, type }) => {
2181
2528
  currentColor === color.value && "is-active"
2182
2529
  ),
2183
2530
  onClick: () => handleColorSelect(color.value),
2184
- onMouseDown: handleMouseDown,
2531
+ onMouseDown: handleMouseDown2,
2185
2532
  title: color.name,
2186
2533
  style: { backgroundColor: color.hex },
2187
2534
  type: "button"
@@ -2233,7 +2580,7 @@ var FontSizeButton = ({ editor }) => {
2233
2580
  },
2234
2581
  [editor]
2235
2582
  );
2236
- const handleMouseDown = useCallback10((e) => {
2583
+ const handleMouseDown2 = useCallback10((e) => {
2237
2584
  e.preventDefault();
2238
2585
  }, []);
2239
2586
  return /* @__PURE__ */ jsxs7("div", { className: "lumir-dropdown-wrapper", ref: dropdownRef, children: [
@@ -2242,7 +2589,7 @@ var FontSizeButton = ({ editor }) => {
2242
2589
  {
2243
2590
  className: "lumir-dropdown-btn lumir-font-size-btn",
2244
2591
  onClick: () => setIsOpen(!isOpen),
2245
- onMouseDown: handleMouseDown,
2592
+ onMouseDown: handleMouseDown2,
2246
2593
  title: "\uAE00\uC790 \uD06C\uAE30",
2247
2594
  type: "button",
2248
2595
  children: [
@@ -2260,7 +2607,7 @@ var FontSizeButton = ({ editor }) => {
2260
2607
  currentSize === "" && "is-active"
2261
2608
  ),
2262
2609
  onClick: () => handleSizeSelect(""),
2263
- onMouseDown: handleMouseDown,
2610
+ onMouseDown: handleMouseDown2,
2264
2611
  type: "button",
2265
2612
  children: DEFAULT_LABEL
2266
2613
  }
@@ -2273,7 +2620,7 @@ var FontSizeButton = ({ editor }) => {
2273
2620
  currentSize === size && "is-active"
2274
2621
  ),
2275
2622
  onClick: () => handleSizeSelect(size),
2276
- onMouseDown: handleMouseDown,
2623
+ onMouseDown: handleMouseDown2,
2277
2624
  type: "button",
2278
2625
  children: toLabel(size)
2279
2626
  },
@@ -2371,7 +2718,7 @@ var LinkButton = ({ editor }) => {
2371
2718
  setLinkUrl("");
2372
2719
  setErrorMsg(null);
2373
2720
  }, []);
2374
- const handleMouseDown = useCallback11((e) => {
2721
+ const handleMouseDown2 = useCallback11((e) => {
2375
2722
  e.preventDefault();
2376
2723
  }, []);
2377
2724
  const handleKeyDown = useCallback11(
@@ -2390,7 +2737,7 @@ var LinkButton = ({ editor }) => {
2390
2737
  {
2391
2738
  className: "lumir-toolbar-btn",
2392
2739
  onClick: () => setIsOpen(!isOpen),
2393
- onMouseDown: handleMouseDown,
2740
+ onMouseDown: handleMouseDown2,
2394
2741
  title: "\uB9C1\uD06C \uC0BD\uC785",
2395
2742
  type: "button",
2396
2743
  children: Icons.link
@@ -2410,7 +2757,7 @@ var LinkButton = ({ editor }) => {
2410
2757
  setErrorMsg(null);
2411
2758
  },
2412
2759
  onKeyDown: handleKeyDown,
2413
- onMouseDown: handleMouseDown
2760
+ onMouseDown: handleMouseDown2
2414
2761
  }
2415
2762
  ),
2416
2763
  errorMsg && /* @__PURE__ */ jsx14(
@@ -2432,7 +2779,7 @@ var LinkButton = ({ editor }) => {
2432
2779
  type: "button",
2433
2780
  className: "lumir-link-btn lumir-link-cancel",
2434
2781
  onClick: handleCancel,
2435
- onMouseDown: handleMouseDown,
2782
+ onMouseDown: handleMouseDown2,
2436
2783
  children: "\uCDE8\uC18C"
2437
2784
  }
2438
2785
  ),
@@ -2441,7 +2788,7 @@ var LinkButton = ({ editor }) => {
2441
2788
  {
2442
2789
  type: "submit",
2443
2790
  className: "lumir-link-btn lumir-link-submit",
2444
- onMouseDown: handleMouseDown,
2791
+ onMouseDown: handleMouseDown2,
2445
2792
  disabled: !linkUrl.trim(),
2446
2793
  children: "\uD655\uC778"
2447
2794
  }
@@ -2477,7 +2824,7 @@ var TableButton = ({ editor }) => {
2477
2824
  console.error("Table insert failed:", err);
2478
2825
  }
2479
2826
  }, [editor]);
2480
- const handleMouseDown = useCallback12((e) => {
2827
+ const handleMouseDown2 = useCallback12((e) => {
2481
2828
  e.preventDefault();
2482
2829
  }, []);
2483
2830
  return /* @__PURE__ */ jsx15(
@@ -2485,7 +2832,7 @@ var TableButton = ({ editor }) => {
2485
2832
  {
2486
2833
  className: "lumir-toolbar-btn",
2487
2834
  onClick: handleClick,
2488
- onMouseDown: handleMouseDown,
2835
+ onMouseDown: handleMouseDown2,
2489
2836
  title: "\uD14C\uC774\uBE14 \uC0BD\uC785",
2490
2837
  type: "button",
2491
2838
  children: Icons.table
@@ -2539,7 +2886,7 @@ var HTMLImportButton = ({
2539
2886
  const handleClick = useCallback13(() => {
2540
2887
  fileInputRef.current?.click();
2541
2888
  }, []);
2542
- const handleMouseDown = useCallback13((e) => {
2889
+ const handleMouseDown2 = useCallback13((e) => {
2543
2890
  e.preventDefault();
2544
2891
  }, []);
2545
2892
  return /* @__PURE__ */ jsxs9(Fragment3, { children: [
@@ -2558,7 +2905,7 @@ var HTMLImportButton = ({
2558
2905
  {
2559
2906
  className: "lumir-toolbar-btn",
2560
2907
  onClick: handleClick,
2561
- onMouseDown: handleMouseDown,
2908
+ onMouseDown: handleMouseDown2,
2562
2909
  title: "HTML Import",
2563
2910
  type: "button",
2564
2911
  children: Icons.htmlFile
@@ -2641,7 +2988,7 @@ var BlockTypeSelect = ({ editor }) => {
2641
2988
  console.error("Block type change failed:", err);
2642
2989
  }
2643
2990
  };
2644
- const handleMouseDown = useCallback14((e) => {
2991
+ const handleMouseDown2 = useCallback14((e) => {
2645
2992
  e.preventDefault();
2646
2993
  }, []);
2647
2994
  const getCurrentLabel = () => {
@@ -2678,7 +3025,7 @@ var BlockTypeSelect = ({ editor }) => {
2678
3025
  {
2679
3026
  className: "lumir-dropdown-btn lumir-block-type-btn",
2680
3027
  onClick: () => setIsOpen(!isOpen),
2681
- onMouseDown: handleMouseDown,
3028
+ onMouseDown: handleMouseDown2,
2682
3029
  type: "button",
2683
3030
  children: [
2684
3031
  /* @__PURE__ */ jsx17("span", { className: "lumir-block-icon", children: BlockTypeIcons[getCurrentIcon()] }),
@@ -2697,7 +3044,7 @@ var BlockTypeSelect = ({ editor }) => {
2697
3044
  isActiveItem(bt) && "is-active"
2698
3045
  ),
2699
3046
  onClick: () => handleTypeChange(bt.type, bt.level, bt.isToggle),
2700
- onMouseDown: handleMouseDown,
3047
+ onMouseDown: handleMouseDown2,
2701
3048
  children: [
2702
3049
  /* @__PURE__ */ jsx17("span", { className: "lumir-block-icon", children: BlockTypeIcons[bt.icon] }),
2703
3050
  /* @__PURE__ */ jsx17("span", { className: "lumir-block-item-title", children: bt.label })
@@ -3038,119 +3385,693 @@ var VerticalAlignmentExtension = Extension.create({
3038
3385
  }
3039
3386
  });
3040
3387
 
3041
- // src/components/CustomFormattingToolbar.tsx
3042
- import {
3043
- BasicTextStyleButton,
3044
- BlockTypeSelect as BlockTypeSelect2,
3045
- CreateLinkButton,
3046
- FileCaptionButton,
3047
- FileDeleteButton,
3048
- FileRenameButton,
3049
- FileReplaceButton,
3050
- FileDownloadButton,
3051
- FilePreviewButton,
3052
- FormattingToolbar,
3053
- NestBlockButton,
3054
- UnnestBlockButton,
3055
- TableCellMergeButton
3056
- } from "@blocknote/react";
3388
+ // src/extensions/RowHeightExtension.ts
3389
+ import { Extension as Extension2 } from "@tiptap/core";
3057
3390
 
3058
- // src/components/TextAlignButtonWithVA.tsx
3059
- import {
3060
- checkBlockHasDefaultProp,
3061
- checkBlockTypeHasDefaultProp,
3062
- mapTableCell
3063
- } from "@blocknote/core";
3064
- import { useCallback as useCallback15, useMemo } from "react";
3065
- import {
3066
- useComponentsContext,
3067
- useBlockNoteEditor,
3068
- useSelectedBlocks
3069
- } from "@blocknote/react";
3070
- import { jsx as jsx19 } from "react/jsx-runtime";
3071
- var icons = {
3072
- left: /* @__PURE__ */ jsx19("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsx19("path", { d: "M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z" }) }),
3073
- center: /* @__PURE__ */ jsx19("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsx19("path", { d: "M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z" }) }),
3074
- right: /* @__PURE__ */ jsx19("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsx19("path", { d: "M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z" }) }),
3075
- justify: /* @__PURE__ */ jsx19("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsx19("path", { d: "M3 21h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18V7H3v2zM3 3v2h18V3H3z" }) })
3076
- };
3077
- var tooltipMap = {
3078
- left: "\uC67C\uCABD \uC815\uB82C",
3079
- center: "\uAC00\uC6B4\uB370 \uC815\uB82C",
3080
- right: "\uC624\uB978\uCABD \uC815\uB82C",
3081
- justify: "\uC591\uCABD \uC815\uB82C"
3082
- };
3083
- var TextAlignButtonWithVA = (props) => {
3084
- const Components = useComponentsContext();
3085
- const editor = useBlockNoteEditor();
3086
- const selectedBlocks = useSelectedBlocks(editor);
3087
- const textAlignment = useMemo(() => {
3088
- const block = selectedBlocks[0];
3089
- if (checkBlockHasDefaultProp("textAlignment", block, editor)) {
3090
- return block.props.textAlignment;
3391
+ // src/extensions/rowResizing.ts
3392
+ import { Plugin as Plugin3, PluginKey as PluginKey3 } from "prosemirror-state";
3393
+ import { Decoration as Decoration2, DecorationSet as DecorationSet2 } from "prosemirror-view";
3394
+ import { TableMap, cellAround, pointsAtCell } from "prosemirror-tables";
3395
+
3396
+ // src/constants/limits.ts
3397
+ var MAX_FILE_SIZE = 10 * 1024 * 1024;
3398
+ var MAX_VIDEO_FILE_SIZE = 100 * 1024 * 1024;
3399
+ var BLOCKED_EXTENSIONS = [".svg", ".svgz"];
3400
+ var ALLOWED_VIDEO_MIME_TYPES = /* @__PURE__ */ new Set([
3401
+ "video/mp4",
3402
+ "video/webm",
3403
+ "video/ogg",
3404
+ "video/quicktime"
3405
+ // .mov
3406
+ ]);
3407
+ var ALLOWED_VIDEO_EXTENSIONS = [
3408
+ ".mp4",
3409
+ ".webm",
3410
+ ".ogg",
3411
+ ".mov"
3412
+ ];
3413
+ var ROW_RESIZE_MIN_HEIGHT = 24;
3414
+ var ROW_RESIZE_HANDLE_WIDTH = 5;
3415
+
3416
+ // src/extensions/rowResizing.ts
3417
+ var rowResizingPluginKey = new PluginKey3(
3418
+ "lumirRowResizing"
3419
+ );
3420
+ var RowResizeState = class _RowResizeState {
3421
+ constructor(activeHandle, dragging) {
3422
+ this.activeHandle = activeHandle;
3423
+ this.dragging = dragging;
3424
+ }
3425
+ apply(tr) {
3426
+ const action = tr.getMeta(rowResizingPluginKey);
3427
+ if (action && action.setHandle != null) {
3428
+ return new _RowResizeState(action.setHandle, null);
3091
3429
  }
3092
- if (block.type === "table") {
3093
- const cellSelection = editor.tableHandles?.getCellSelection();
3094
- if (!cellSelection) {
3095
- return;
3430
+ if (action && action.setDragging !== void 0) {
3431
+ return new _RowResizeState(this.activeHandle, action.setDragging);
3432
+ }
3433
+ if (this.activeHandle > -1 && tr.docChanged) {
3434
+ let handle = tr.mapping.map(this.activeHandle, -1);
3435
+ if (!pointsAtCell(tr.doc.resolve(handle))) {
3436
+ handle = -1;
3096
3437
  }
3097
- const allCellsInTable = cellSelection.cells.map(
3098
- ({ row, col }) => mapTableCell(
3099
- block.content.rows[row].cells[col]
3100
- ).props.textAlignment
3101
- );
3102
- const firstAlignment = allCellsInTable[0];
3103
- if (allCellsInTable.every((alignment) => alignment === firstAlignment)) {
3104
- return firstAlignment;
3438
+ return new _RowResizeState(handle, this.dragging);
3439
+ }
3440
+ return this;
3441
+ }
3442
+ };
3443
+ function rowResizing({
3444
+ handleWidth = ROW_RESIZE_HANDLE_WIDTH,
3445
+ minHeight = ROW_RESIZE_MIN_HEIGHT
3446
+ } = {}) {
3447
+ return new Plugin3({
3448
+ key: rowResizingPluginKey,
3449
+ state: {
3450
+ init() {
3451
+ return new RowResizeState(-1, null);
3452
+ },
3453
+ apply(tr, prev) {
3454
+ return prev.apply(tr);
3455
+ }
3456
+ },
3457
+ props: {
3458
+ attributes: (state) => {
3459
+ const pluginState = rowResizingPluginKey.getState(state);
3460
+ return pluginState && pluginState.activeHandle > -1 ? { class: "row-resize-cursor" } : {};
3461
+ },
3462
+ handleDOMEvents: {
3463
+ mousemove: (view, event) => {
3464
+ handleMouseMove(view, event, handleWidth);
3465
+ },
3466
+ mouseleave: (view) => {
3467
+ handleMouseLeave(view);
3468
+ },
3469
+ mousedown: (view, event) => {
3470
+ handleMouseDown(view, event, minHeight);
3471
+ }
3472
+ },
3473
+ decorations: (state) => {
3474
+ const pluginState = rowResizingPluginKey.getState(state);
3475
+ if (pluginState && pluginState.activeHandle > -1) {
3476
+ return handleDecorations(state, pluginState);
3477
+ }
3478
+ return void 0;
3105
3479
  }
3106
3480
  }
3481
+ });
3482
+ }
3483
+ function handleMouseMove(view, event, handleWidth) {
3484
+ if (!view.editable) {
3107
3485
  return;
3108
- }, [editor, selectedBlocks]);
3109
- const setTextAlignment = useCallback15(
3110
- (newAlignment) => {
3111
- editor.focus();
3112
- for (const block of selectedBlocks) {
3113
- if (block.type === "table") {
3114
- const tiptap = editor._tiptapEditor;
3115
- if (!tiptap) continue;
3116
- const positions = getSelectedCellPositions(editor);
3117
- if (positions.length === 0) continue;
3118
- const { state } = tiptap;
3119
- let tr = state.tr;
3120
- for (const pos of positions) {
3121
- const node = tr.doc.nodeAt(pos);
3122
- if (node) {
3123
- tr = tr.setNodeMarkup(pos, void 0, {
3124
- ...node.attrs,
3125
- textAlignment: newAlignment
3126
- });
3127
- }
3128
- }
3129
- tiptap.view?.dispatch(tr);
3130
- } else if (checkBlockTypeHasDefaultProp("textAlignment", block.type, editor)) {
3131
- editor.updateBlock(block, {
3132
- props: { textAlignment: newAlignment }
3133
- });
3134
- }
3486
+ }
3487
+ const pluginState = rowResizingPluginKey.getState(view.state);
3488
+ if (!pluginState) {
3489
+ return;
3490
+ }
3491
+ if (!pluginState.dragging) {
3492
+ const target = domCellAround(event.target);
3493
+ let cell = -1;
3494
+ if (target) {
3495
+ const { top, bottom } = target.getBoundingClientRect();
3496
+ if (event.clientY - top <= handleWidth) {
3497
+ cell = edgeCell(view, event, "top", handleWidth);
3498
+ } else if (bottom - event.clientY <= handleWidth) {
3499
+ cell = edgeCell(view, event, "bottom", handleWidth);
3135
3500
  }
3136
- },
3137
- [editor, selectedBlocks]
3138
- );
3139
- const show = useMemo(() => {
3140
- return !!selectedBlocks.find(
3141
- (block) => "textAlignment" in block.props || block.type === "table" && block.children
3142
- );
3143
- }, [selectedBlocks]);
3144
- if (!show || !editor.isEditable) {
3145
- return null;
3501
+ }
3502
+ if (cell !== pluginState.activeHandle) {
3503
+ updateHandle(view, cell);
3504
+ }
3146
3505
  }
3147
- return /* @__PURE__ */ jsx19(
3148
- Components.FormattingToolbar.Button,
3149
- {
3150
- className: "bn-button",
3151
- "data-test": `alignText${props.textAlignment.slice(0, 1).toUpperCase() + props.textAlignment.slice(1)}`,
3152
- onClick: () => setTextAlignment(props.textAlignment),
3153
- isSelected: textAlignment === props.textAlignment,
3506
+ }
3507
+ function handleMouseLeave(view) {
3508
+ if (!view.editable) {
3509
+ return;
3510
+ }
3511
+ const pluginState = rowResizingPluginKey.getState(view.state);
3512
+ if (pluginState && pluginState.activeHandle > -1 && !pluginState.dragging) {
3513
+ updateHandle(view, -1);
3514
+ }
3515
+ }
3516
+ function handleMouseDown(view, event, minHeight) {
3517
+ if (!view.editable) {
3518
+ return false;
3519
+ }
3520
+ const win = view.dom.ownerDocument.defaultView ?? window;
3521
+ const pluginState = rowResizingPluginKey.getState(view.state);
3522
+ if (!pluginState || pluginState.activeHandle === -1 || pluginState.dragging) {
3523
+ return false;
3524
+ }
3525
+ const startHeight = currentRowHeight(view, pluginState.activeHandle);
3526
+ setDragging(view, {
3527
+ startY: event.clientY,
3528
+ startHeight,
3529
+ currentHeight: startHeight
3530
+ });
3531
+ function finish(finishEvent) {
3532
+ win.removeEventListener("mouseup", finish);
3533
+ win.removeEventListener("mousemove", move);
3534
+ const ps = rowResizingPluginKey.getState(view.state);
3535
+ if (ps?.dragging) {
3536
+ const finalHeight = draggedHeight(ps.dragging, finishEvent, minHeight);
3537
+ setDragging(view, null);
3538
+ commitRowHeight(view, ps.activeHandle, finalHeight);
3539
+ }
3540
+ }
3541
+ function move(moveEvent) {
3542
+ if (moveEvent.buttons === 0 || moveEvent.buttons === void 0 && !moveEvent.which) {
3543
+ return finish(moveEvent);
3544
+ }
3545
+ const ps = rowResizingPluginKey.getState(view.state);
3546
+ if (!ps?.dragging) {
3547
+ return;
3548
+ }
3549
+ const h = draggedHeight(ps.dragging, moveEvent, minHeight);
3550
+ if (h !== ps.dragging.currentHeight) {
3551
+ setDragging(view, { ...ps.dragging, currentHeight: h });
3552
+ }
3553
+ }
3554
+ win.addEventListener("mouseup", finish);
3555
+ win.addEventListener("mousemove", move);
3556
+ event.preventDefault();
3557
+ return true;
3558
+ }
3559
+ function setDragging(view, dragging) {
3560
+ view.dispatch(
3561
+ view.state.tr.setMeta(rowResizingPluginKey, { setDragging: dragging })
3562
+ );
3563
+ }
3564
+ function currentRowHeight(view, cellPos) {
3565
+ const info = targetRowInfo(view, cellPos);
3566
+ const tr = rowTrElement(view, cellPos, info.row);
3567
+ return tr ? tr.offsetHeight : ROW_RESIZE_MIN_HEIGHT;
3568
+ }
3569
+ function commitRowHeight(view, cellPos, height) {
3570
+ const { table, map, start, row } = targetRowInfo(view, cellPos);
3571
+ const tr = view.state.tr;
3572
+ const seen = /* @__PURE__ */ new Set();
3573
+ for (let col = 0; col < map.width; col++) {
3574
+ const cellRelPos = map.map[row * map.width + col];
3575
+ if (seen.has(cellRelPos)) {
3576
+ continue;
3577
+ }
3578
+ seen.add(cellRelPos);
3579
+ const rect = map.findCell(cellRelPos);
3580
+ if (rect.bottom - 1 !== row) {
3581
+ continue;
3582
+ }
3583
+ const node = table.nodeAt(cellRelPos);
3584
+ if (!node || node.attrs.rowHeight === height) {
3585
+ continue;
3586
+ }
3587
+ tr.setNodeMarkup(start + cellRelPos, void 0, {
3588
+ ...node.attrs,
3589
+ rowHeight: height
3590
+ });
3591
+ }
3592
+ if (tr.docChanged) {
3593
+ view.dispatch(tr);
3594
+ }
3595
+ }
3596
+ function targetRowInfo(view, cellPos) {
3597
+ const $cell = view.state.doc.resolve(cellPos);
3598
+ const table = $cell.node(-1);
3599
+ const map = TableMap.get(table);
3600
+ const start = $cell.start(-1);
3601
+ const rect = map.findCell($cell.pos - start);
3602
+ return { table, map, start, row: rect.bottom - 1, $cell };
3603
+ }
3604
+ function rowTrElement(view, cellPos, row) {
3605
+ let dom = view.nodeDOM(cellPos);
3606
+ while (dom && dom.nodeName !== "TABLE") {
3607
+ dom = dom.parentNode;
3608
+ }
3609
+ if (!dom) {
3610
+ return null;
3611
+ }
3612
+ return dom.rows[row] ?? null;
3613
+ }
3614
+ function domCellAround(target) {
3615
+ let node = target;
3616
+ while (node && node.nodeName !== "TD" && node.nodeName !== "TH") {
3617
+ node = node.classList?.contains("ProseMirror") ? null : node.parentNode;
3618
+ }
3619
+ return node;
3620
+ }
3621
+ function edgeCell(view, event, side, handleWidth) {
3622
+ const offset2 = side === "bottom" ? -handleWidth : handleWidth;
3623
+ const found = view.posAtCoords({
3624
+ left: event.clientX,
3625
+ top: event.clientY + offset2
3626
+ });
3627
+ if (!found) {
3628
+ return -1;
3629
+ }
3630
+ const $cell = cellAround(view.state.doc.resolve(found.pos));
3631
+ if (!$cell) {
3632
+ return -1;
3633
+ }
3634
+ if (side === "bottom") {
3635
+ return $cell.pos;
3636
+ }
3637
+ const map = TableMap.get($cell.node(-1));
3638
+ const start = $cell.start(-1);
3639
+ const index = map.map.indexOf($cell.pos - start);
3640
+ return index < map.width ? -1 : start + map.map[index - map.width];
3641
+ }
3642
+ function updateHandle(view, value) {
3643
+ view.dispatch(
3644
+ view.state.tr.setMeta(rowResizingPluginKey, { setHandle: value })
3645
+ );
3646
+ }
3647
+ function draggedHeight(dragging, event, minHeight) {
3648
+ const offset2 = event.clientY - dragging.startY;
3649
+ return Math.max(minHeight, dragging.startHeight + offset2);
3650
+ }
3651
+ function handleDecorations(state, pluginState) {
3652
+ const decorations = [];
3653
+ const $cell = state.doc.resolve(pluginState.activeHandle);
3654
+ const table = $cell.node(-1);
3655
+ if (!table) {
3656
+ return DecorationSet2.empty;
3657
+ }
3658
+ const map = TableMap.get(table);
3659
+ const start = $cell.start(-1);
3660
+ const row = map.findCell($cell.pos - start).bottom - 1;
3661
+ const dragging = pluginState.dragging;
3662
+ const seen = /* @__PURE__ */ new Set();
3663
+ for (let col = 0; col < map.width; col++) {
3664
+ const cellRelPos = map.map[row * map.width + col];
3665
+ if (seen.has(cellRelPos)) {
3666
+ continue;
3667
+ }
3668
+ seen.add(cellRelPos);
3669
+ if (map.findCell(cellRelPos).bottom - 1 !== row) {
3670
+ continue;
3671
+ }
3672
+ const node = table.nodeAt(cellRelPos);
3673
+ if (!node) {
3674
+ continue;
3675
+ }
3676
+ const from = start + cellRelPos;
3677
+ const to = from + node.nodeSize;
3678
+ if (dragging) {
3679
+ decorations.push(
3680
+ Decoration2.node(from, to, {
3681
+ class: "row-resize-dragging",
3682
+ style: `height: ${dragging.currentHeight}px`
3683
+ })
3684
+ );
3685
+ }
3686
+ const handle = document.createElement("div");
3687
+ handle.className = "row-resize-handle";
3688
+ decorations.push(Decoration2.widget(to - 1, handle));
3689
+ }
3690
+ return DecorationSet2.create(state.doc, decorations);
3691
+ }
3692
+
3693
+ // src/extensions/tableCellAttrPreserve.ts
3694
+ import { Plugin as Plugin4, PluginKey as PluginKey4 } from "prosemirror-state";
3695
+ var tableCellAttrPreserveKey = new PluginKey4(
3696
+ "lumirTableCellAttrPreserve"
3697
+ );
3698
+ var PRESERVED_ATTRS = [
3699
+ { name: "rowHeight", default: null },
3700
+ { name: "verticalAlignment", default: "top" }
3701
+ ];
3702
+ function isMeaningful(attrName, value, def) {
3703
+ if (value === null || value === void 0) {
3704
+ return false;
3705
+ }
3706
+ return value !== def;
3707
+ }
3708
+ function meaningfulAttrs(node) {
3709
+ let out = null;
3710
+ for (const { name, default: def } of PRESERVED_ATTRS) {
3711
+ const v = node.attrs?.[name];
3712
+ if (isMeaningful(name, v, def)) {
3713
+ (out ?? (out = {}))[name] = v;
3714
+ }
3715
+ }
3716
+ return out;
3717
+ }
3718
+ function collectCellAttrs(doc) {
3719
+ const result = /* @__PURE__ */ new Map();
3720
+ doc.descendants((node) => {
3721
+ if (node.type.name !== "blockContainer") {
3722
+ return void 0;
3723
+ }
3724
+ const id = node.attrs?.id;
3725
+ const table = node.firstChild;
3726
+ if (!id || table?.type.name !== "table") {
3727
+ return void 0;
3728
+ }
3729
+ const cells = /* @__PURE__ */ new Map();
3730
+ let rowIndex = 0;
3731
+ table.forEach((rowNode) => {
3732
+ if (rowNode.type.name === "tableRow") {
3733
+ let cellIndex = 0;
3734
+ rowNode.forEach((cellNode) => {
3735
+ const attrs = meaningfulAttrs(cellNode);
3736
+ if (attrs) {
3737
+ cells.set(`${rowIndex}:${cellIndex}`, attrs);
3738
+ }
3739
+ cellIndex++;
3740
+ });
3741
+ rowIndex++;
3742
+ }
3743
+ });
3744
+ if (cells.size > 0) {
3745
+ result.set(id, cells);
3746
+ }
3747
+ return false;
3748
+ });
3749
+ return result;
3750
+ }
3751
+ function tableCellAttrPreserve() {
3752
+ return new Plugin4({
3753
+ key: tableCellAttrPreserveKey,
3754
+ appendTransaction(transactions, oldState, newState) {
3755
+ if (!transactions.some((tr2) => tr2.docChanged)) {
3756
+ return null;
3757
+ }
3758
+ const oldMap = collectCellAttrs(oldState.doc);
3759
+ if (oldMap.size === 0) {
3760
+ return null;
3761
+ }
3762
+ const tr = newState.tr;
3763
+ let changed = false;
3764
+ let curTableCells = null;
3765
+ let curRowIndex = -1;
3766
+ let curCellIndex = 0;
3767
+ newState.doc.descendants((node, pos) => {
3768
+ const name = node.type.name;
3769
+ if (name === "blockContainer") {
3770
+ const id = node.attrs?.id;
3771
+ const table = node.firstChild;
3772
+ if (id && table?.type.name === "table" && oldMap.has(id)) {
3773
+ curTableCells = oldMap.get(id);
3774
+ curRowIndex = -1;
3775
+ } else {
3776
+ curTableCells = null;
3777
+ }
3778
+ return void 0;
3779
+ }
3780
+ if (!curTableCells) {
3781
+ return void 0;
3782
+ }
3783
+ if (name === "tableRow") {
3784
+ curRowIndex++;
3785
+ curCellIndex = 0;
3786
+ return void 0;
3787
+ }
3788
+ if (name === "tableCell" || name === "tableHeader") {
3789
+ const wanted = curTableCells.get(`${curRowIndex}:${curCellIndex}`);
3790
+ curCellIndex++;
3791
+ if (wanted) {
3792
+ const patch = {};
3793
+ let needs = false;
3794
+ for (const { name: attrName, default: def } of PRESERVED_ATTRS) {
3795
+ if (!(attrName in wanted)) {
3796
+ continue;
3797
+ }
3798
+ const cur = node.attrs?.[attrName];
3799
+ if (cur === null || cur === void 0 || cur === def) {
3800
+ patch[attrName] = wanted[attrName];
3801
+ needs = true;
3802
+ }
3803
+ }
3804
+ if (needs) {
3805
+ tr.setNodeMarkup(pos, void 0, { ...node.attrs, ...patch });
3806
+ changed = true;
3807
+ }
3808
+ }
3809
+ return false;
3810
+ }
3811
+ return void 0;
3812
+ });
3813
+ return changed ? tr : null;
3814
+ }
3815
+ });
3816
+ }
3817
+
3818
+ // src/extensions/RowHeightExtension.ts
3819
+ var RowHeightExtension = Extension2.create({
3820
+ name: "rowHeight",
3821
+ addOptions() {
3822
+ return { resizable: true };
3823
+ },
3824
+ addGlobalAttributes() {
3825
+ return [
3826
+ {
3827
+ types: ["tableCell", "tableHeader"],
3828
+ attributes: {
3829
+ rowHeight: {
3830
+ default: null,
3831
+ parseHTML: (element) => {
3832
+ const fromStyle = parseInt(element.style?.height ?? "", 10);
3833
+ if (Number.isFinite(fromStyle) && fromStyle > 0) {
3834
+ return fromStyle;
3835
+ }
3836
+ const fromAttr = parseInt(
3837
+ element.getAttribute("data-row-height") ?? "",
3838
+ 10
3839
+ );
3840
+ return Number.isFinite(fromAttr) && fromAttr > 0 ? fromAttr : null;
3841
+ },
3842
+ renderHTML: (attributes) => {
3843
+ const h = attributes.rowHeight;
3844
+ if (!h || typeof h !== "number") {
3845
+ return {};
3846
+ }
3847
+ return { style: `height: ${h}px` };
3848
+ }
3849
+ }
3850
+ }
3851
+ }
3852
+ ];
3853
+ },
3854
+ addProseMirrorPlugins() {
3855
+ const plugins = [tableCellAttrPreserve()];
3856
+ if (this.options.resizable) {
3857
+ plugins.push(rowResizing());
3858
+ }
3859
+ return plugins;
3860
+ }
3861
+ });
3862
+
3863
+ // src/extensions/TableAlignmentExtension.ts
3864
+ import { Extension as Extension3 } from "@tiptap/core";
3865
+ import { Plugin as Plugin5, PluginKey as PluginKey5 } from "prosemirror-state";
3866
+ import { Decoration as Decoration3, DecorationSet as DecorationSet3 } from "prosemirror-view";
3867
+ var tableAlignmentDecoKey = new PluginKey5("lumirTableAlignmentDeco");
3868
+ function tableAlignmentDecorationPlugin() {
3869
+ return new Plugin5({
3870
+ key: tableAlignmentDecoKey,
3871
+ props: {
3872
+ decorations(state) {
3873
+ const decorations = [];
3874
+ state.doc.descendants((node, pos) => {
3875
+ if (node.type.name === "table") {
3876
+ const align = node.attrs.tableAlignment;
3877
+ if (align && align !== "left") {
3878
+ decorations.push(
3879
+ Decoration3.node(pos, pos + node.nodeSize, {
3880
+ "data-table-alignment": align
3881
+ })
3882
+ );
3883
+ }
3884
+ return false;
3885
+ }
3886
+ return void 0;
3887
+ });
3888
+ return DecorationSet3.create(state.doc, decorations);
3889
+ }
3890
+ }
3891
+ });
3892
+ }
3893
+ var TableAlignmentExtension = Extension3.create({
3894
+ name: "tableAlignment",
3895
+ addGlobalAttributes() {
3896
+ return [
3897
+ {
3898
+ types: ["table"],
3899
+ attributes: {
3900
+ tableAlignment: {
3901
+ default: "left",
3902
+ parseHTML: (element) => element.getAttribute("data-table-alignment") || "left",
3903
+ renderHTML: (attributes) => {
3904
+ if (!attributes.tableAlignment || attributes.tableAlignment === "left") {
3905
+ return {};
3906
+ }
3907
+ return { "data-table-alignment": attributes.tableAlignment };
3908
+ }
3909
+ }
3910
+ }
3911
+ }
3912
+ ];
3913
+ },
3914
+ addProseMirrorPlugins() {
3915
+ return [tableAlignmentDecorationPlugin()];
3916
+ }
3917
+ });
3918
+
3919
+ // src/blocks/columns/insertColumns.ts
3920
+ import { TextSelection } from "prosemirror-state";
3921
+ function insertTwoColumns(editor) {
3922
+ const tiptap = editor?._tiptapEditor;
3923
+ if (!tiptap) {
3924
+ return false;
3925
+ }
3926
+ const { state, schema: schema2 } = tiptap;
3927
+ const { blockContainer, paragraph, column, columnList } = schema2.nodes;
3928
+ if (!blockContainer || !paragraph || !column || !columnList) {
3929
+ return false;
3930
+ }
3931
+ const $from = state.selection.$from;
3932
+ for (let d = $from.depth; d > 0; d--) {
3933
+ const name = $from.node(d).type.name;
3934
+ if (name === "column" || name === "columnList") {
3935
+ return false;
3936
+ }
3937
+ }
3938
+ let depth = $from.depth;
3939
+ while (depth > 0 && $from.node(depth).type.name !== "blockContainer") {
3940
+ depth--;
3941
+ }
3942
+ if (depth === 0) {
3943
+ return false;
3944
+ }
3945
+ const insertPos = $from.after(depth);
3946
+ const mkBlock = () => blockContainer.create(null, paragraph.create());
3947
+ const mkColumn = () => column.create(null, mkBlock());
3948
+ const list = columnList.create(null, [mkColumn(), mkColumn()]);
3949
+ try {
3950
+ let tr = state.tr.insert(insertPos, list);
3951
+ try {
3952
+ tr = tr.setSelection(TextSelection.create(tr.doc, insertPos + 4));
3953
+ } catch {
3954
+ }
3955
+ tiptap.view.dispatch(tr.scrollIntoView());
3956
+ return true;
3957
+ } catch {
3958
+ return false;
3959
+ }
3960
+ }
3961
+
3962
+ // src/components/CustomFormattingToolbar.tsx
3963
+ import {
3964
+ BasicTextStyleButton,
3965
+ BlockTypeSelect as BlockTypeSelect2,
3966
+ CreateLinkButton,
3967
+ FileCaptionButton,
3968
+ FileDeleteButton,
3969
+ FileRenameButton,
3970
+ FileReplaceButton,
3971
+ FileDownloadButton,
3972
+ FilePreviewButton,
3973
+ FormattingToolbar,
3974
+ NestBlockButton,
3975
+ UnnestBlockButton,
3976
+ TableCellMergeButton
3977
+ } from "@blocknote/react";
3978
+
3979
+ // src/components/TextAlignButtonWithVA.tsx
3980
+ import {
3981
+ checkBlockHasDefaultProp,
3982
+ checkBlockTypeHasDefaultProp,
3983
+ mapTableCell
3984
+ } from "@blocknote/core";
3985
+ import { useCallback as useCallback15, useMemo } from "react";
3986
+ import {
3987
+ useComponentsContext,
3988
+ useBlockNoteEditor,
3989
+ useSelectedBlocks
3990
+ } from "@blocknote/react";
3991
+ import { jsx as jsx19 } from "react/jsx-runtime";
3992
+ var icons = {
3993
+ left: /* @__PURE__ */ jsx19("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsx19("path", { d: "M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z" }) }),
3994
+ center: /* @__PURE__ */ jsx19("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsx19("path", { d: "M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z" }) }),
3995
+ right: /* @__PURE__ */ jsx19("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsx19("path", { d: "M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z" }) }),
3996
+ justify: /* @__PURE__ */ jsx19("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsx19("path", { d: "M3 21h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18V7H3v2zM3 3v2h18V3H3z" }) })
3997
+ };
3998
+ var tooltipMap = {
3999
+ left: "\uC67C\uCABD \uC815\uB82C",
4000
+ center: "\uAC00\uC6B4\uB370 \uC815\uB82C",
4001
+ right: "\uC624\uB978\uCABD \uC815\uB82C",
4002
+ justify: "\uC591\uCABD \uC815\uB82C"
4003
+ };
4004
+ var TextAlignButtonWithVA = (props) => {
4005
+ const Components = useComponentsContext();
4006
+ const editor = useBlockNoteEditor();
4007
+ const selectedBlocks = useSelectedBlocks(editor);
4008
+ const textAlignment = useMemo(() => {
4009
+ const block = selectedBlocks[0];
4010
+ if (checkBlockHasDefaultProp("textAlignment", block, editor)) {
4011
+ return block.props.textAlignment;
4012
+ }
4013
+ if (block.type === "table") {
4014
+ const cellSelection = editor.tableHandles?.getCellSelection();
4015
+ if (!cellSelection) {
4016
+ return;
4017
+ }
4018
+ const allCellsInTable = cellSelection.cells.map(
4019
+ ({ row, col }) => mapTableCell(
4020
+ block.content.rows[row].cells[col]
4021
+ ).props.textAlignment
4022
+ );
4023
+ const firstAlignment = allCellsInTable[0];
4024
+ if (allCellsInTable.every((alignment) => alignment === firstAlignment)) {
4025
+ return firstAlignment;
4026
+ }
4027
+ }
4028
+ return;
4029
+ }, [editor, selectedBlocks]);
4030
+ const setTextAlignment = useCallback15(
4031
+ (newAlignment) => {
4032
+ editor.focus();
4033
+ for (const block of selectedBlocks) {
4034
+ if (block.type === "table") {
4035
+ const tiptap = editor._tiptapEditor;
4036
+ if (!tiptap) continue;
4037
+ const positions = getSelectedCellPositions(editor);
4038
+ if (positions.length === 0) continue;
4039
+ const { state } = tiptap;
4040
+ let tr = state.tr;
4041
+ for (const pos of positions) {
4042
+ const node = tr.doc.nodeAt(pos);
4043
+ if (node) {
4044
+ tr = tr.setNodeMarkup(pos, void 0, {
4045
+ ...node.attrs,
4046
+ textAlignment: newAlignment
4047
+ });
4048
+ }
4049
+ }
4050
+ tiptap.view?.dispatch(tr);
4051
+ } else if (checkBlockTypeHasDefaultProp("textAlignment", block.type, editor)) {
4052
+ editor.updateBlock(block, {
4053
+ props: { textAlignment: newAlignment }
4054
+ });
4055
+ }
4056
+ }
4057
+ },
4058
+ [editor, selectedBlocks]
4059
+ );
4060
+ const show = useMemo(() => {
4061
+ return !!selectedBlocks.find(
4062
+ (block) => "textAlignment" in block.props || block.type === "table" && block.children
4063
+ );
4064
+ }, [selectedBlocks]);
4065
+ if (!show || !editor.isEditable) {
4066
+ return null;
4067
+ }
4068
+ return /* @__PURE__ */ jsx19(
4069
+ Components.FormattingToolbar.Button,
4070
+ {
4071
+ className: "bn-button",
4072
+ "data-test": `alignText${props.textAlignment.slice(0, 1).toUpperCase() + props.textAlignment.slice(1)}`,
4073
+ onClick: () => setTextAlignment(props.textAlignment),
4074
+ isSelected: textAlignment === props.textAlignment,
3154
4075
  label: tooltipMap[props.textAlignment],
3155
4076
  mainTooltip: tooltipMap[props.textAlignment],
3156
4077
  icon: icons[props.textAlignment]
@@ -3247,19 +4168,83 @@ var VerticalAlignButton = (props) => {
3247
4168
  );
3248
4169
  };
3249
4170
 
3250
- // src/components/FontSizeButton.tsx
4171
+ // src/components/TableAlignButton.tsx
4172
+ import { useCallback as useCallback17, useMemo as useMemo3 } from "react";
3251
4173
  import {
3252
4174
  useBlockNoteEditor as useBlockNoteEditor3,
3253
4175
  useComponentsContext as useComponentsContext3,
3254
- useEditorContentOrSelectionChange,
3255
4176
  useSelectedBlocks as useSelectedBlocks3
3256
4177
  } from "@blocknote/react";
3257
- import { useCallback as useCallback17, useMemo as useMemo3, useState as useState9 } from "react";
3258
4178
  import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
4179
+ var icons3 = {
4180
+ left: /* @__PURE__ */ jsxs13("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
4181
+ /* @__PURE__ */ jsx21("rect", { x: "1.5", y: "4", width: "7", height: "8", rx: "1", fill: "currentColor", stroke: "none" }),
4182
+ /* @__PURE__ */ jsx21("line", { x1: "1.5", y1: "1.5", x2: "14.5", y2: "1.5" }),
4183
+ /* @__PURE__ */ jsx21("line", { x1: "1.5", y1: "14.5", x2: "14.5", y2: "14.5" })
4184
+ ] }),
4185
+ center: /* @__PURE__ */ jsxs13("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
4186
+ /* @__PURE__ */ jsx21("rect", { x: "4.5", y: "4", width: "7", height: "8", rx: "1", fill: "currentColor", stroke: "none" }),
4187
+ /* @__PURE__ */ jsx21("line", { x1: "1.5", y1: "1.5", x2: "14.5", y2: "1.5" }),
4188
+ /* @__PURE__ */ jsx21("line", { x1: "1.5", y1: "14.5", x2: "14.5", y2: "14.5" })
4189
+ ] }),
4190
+ right: /* @__PURE__ */ jsxs13("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
4191
+ /* @__PURE__ */ jsx21("rect", { x: "7.5", y: "4", width: "7", height: "8", rx: "1", fill: "currentColor", stroke: "none" }),
4192
+ /* @__PURE__ */ jsx21("line", { x1: "1.5", y1: "1.5", x2: "14.5", y2: "1.5" }),
4193
+ /* @__PURE__ */ jsx21("line", { x1: "1.5", y1: "14.5", x2: "14.5", y2: "14.5" })
4194
+ ] })
4195
+ };
4196
+ var tooltips2 = {
4197
+ left: "\uD45C \uC67C\uCABD \uC815\uB82C",
4198
+ center: "\uD45C \uAC00\uC6B4\uB370 \uC815\uB82C",
4199
+ right: "\uD45C \uC624\uB978\uCABD \uC815\uB82C"
4200
+ };
4201
+ var TableAlignButton = (props) => {
4202
+ const Components = useComponentsContext3();
4203
+ const editor = useBlockNoteEditor3();
4204
+ const selectedBlocks = useSelectedBlocks3(editor);
4205
+ const tableBlock = useMemo3(
4206
+ () => selectedBlocks.find((block) => block.type === "table"),
4207
+ [selectedBlocks]
4208
+ );
4209
+ const current = useMemo3(() => {
4210
+ if (!tableBlock?.id) return "left";
4211
+ return getTableAlignment(editor, tableBlock.id);
4212
+ }, [editor, tableBlock, selectedBlocks]);
4213
+ const apply = useCallback17(() => {
4214
+ if (!tableBlock?.id) return;
4215
+ editor.focus();
4216
+ setTableAlignment(editor, tableBlock.id, props.alignment);
4217
+ }, [editor, tableBlock, props.alignment]);
4218
+ if (!tableBlock || !editor.isEditable) {
4219
+ return null;
4220
+ }
4221
+ return /* @__PURE__ */ jsx21(
4222
+ Components.FormattingToolbar.Button,
4223
+ {
4224
+ className: "bn-button",
4225
+ "data-test": `tableAlign${props.alignment.charAt(0).toUpperCase() + props.alignment.slice(1)}`,
4226
+ onClick: apply,
4227
+ isSelected: current === props.alignment,
4228
+ label: tooltips2[props.alignment],
4229
+ mainTooltip: tooltips2[props.alignment],
4230
+ icon: icons3[props.alignment]
4231
+ }
4232
+ );
4233
+ };
4234
+
4235
+ // src/components/FontSizeButton.tsx
4236
+ import {
4237
+ useBlockNoteEditor as useBlockNoteEditor4,
4238
+ useComponentsContext as useComponentsContext4,
4239
+ useEditorContentOrSelectionChange,
4240
+ useSelectedBlocks as useSelectedBlocks4
4241
+ } from "@blocknote/react";
4242
+ import { useCallback as useCallback18, useMemo as useMemo4, useState as useState9 } from "react";
4243
+ import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
3259
4244
  var DEFAULT_LABEL2 = "\uAE30\uBCF8";
3260
4245
  var toLabel2 = (size) => size.replace(/px$/, "");
3261
4246
  function FontSizeIcon({ size }) {
3262
- return /* @__PURE__ */ jsx21(
4247
+ return /* @__PURE__ */ jsx22(
3263
4248
  "span",
3264
4249
  {
3265
4250
  style: {
@@ -3274,12 +4259,12 @@ function FontSizeIcon({ size }) {
3274
4259
  );
3275
4260
  }
3276
4261
  function FontSizeButton2() {
3277
- const Components = useComponentsContext3();
3278
- const editor = useBlockNoteEditor3();
4262
+ const Components = useComponentsContext4();
4263
+ const editor = useBlockNoteEditor4();
3279
4264
  const ed = editor;
3280
4265
  const styleSchema = editor.schema.styleSchema;
3281
4266
  const fontSizeInSchema = styleSchema.fontSize?.type === "fontSize" && styleSchema.fontSize?.propSchema === "string";
3282
- const selectedBlocks = useSelectedBlocks3(editor);
4267
+ const selectedBlocks = useSelectedBlocks4(editor);
3283
4268
  const [currentSize, setCurrentSize] = useState9(
3284
4269
  fontSizeInSchema ? ed.getActiveStyles().fontSize || "" : ""
3285
4270
  );
@@ -3288,7 +4273,7 @@ function FontSizeButton2() {
3288
4273
  setCurrentSize(ed.getActiveStyles().fontSize || "");
3289
4274
  }
3290
4275
  }, editor);
3291
- const setFontSize = useCallback17(
4276
+ const setFontSize = useCallback18(
3292
4277
  (size) => {
3293
4278
  size === "" ? ed.removeStyles({ fontSize: "" }) : ed.addStyles({ fontSize: size });
3294
4279
  setTimeout(() => editor.focus());
@@ -3296,7 +4281,7 @@ function FontSizeButton2() {
3296
4281
  // eslint-disable-next-line react-hooks/exhaustive-deps
3297
4282
  [editor]
3298
4283
  );
3299
- const show = useMemo3(() => {
4284
+ const show = useMemo4(() => {
3300
4285
  if (!fontSizeInSchema) {
3301
4286
  return false;
3302
4287
  }
@@ -3311,20 +4296,20 @@ function FontSizeButton2() {
3311
4296
  return null;
3312
4297
  }
3313
4298
  const tooltip = "\uAE00\uC790 \uD06C\uAE30";
3314
- return /* @__PURE__ */ jsxs13(Components.Generic.Menu.Root, { children: [
3315
- /* @__PURE__ */ jsx21(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ jsx21(
4299
+ return /* @__PURE__ */ jsxs14(Components.Generic.Menu.Root, { children: [
4300
+ /* @__PURE__ */ jsx22(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ jsx22(
3316
4301
  Components.FormattingToolbar.Button,
3317
4302
  {
3318
4303
  className: "bn-button",
3319
4304
  "data-test": "font-size",
3320
4305
  label: tooltip,
3321
4306
  mainTooltip: tooltip,
3322
- icon: /* @__PURE__ */ jsx21(FontSizeIcon, { size: currentSize })
4307
+ icon: /* @__PURE__ */ jsx22(FontSizeIcon, { size: currentSize })
3323
4308
  }
3324
4309
  ) }),
3325
- /* @__PURE__ */ jsxs13(Components.Generic.Menu.Dropdown, { className: "bn-menu-dropdown", children: [
3326
- /* @__PURE__ */ jsx21(Components.Generic.Menu.Label, { children: "\uAE00\uC790 \uD06C\uAE30" }),
3327
- /* @__PURE__ */ jsx21(
4310
+ /* @__PURE__ */ jsxs14(Components.Generic.Menu.Dropdown, { className: "bn-menu-dropdown", children: [
4311
+ /* @__PURE__ */ jsx22(Components.Generic.Menu.Label, { children: "\uAE00\uC790 \uD06C\uAE30" }),
4312
+ /* @__PURE__ */ jsx22(
3328
4313
  Components.Generic.Menu.Item,
3329
4314
  {
3330
4315
  onClick: () => setFontSize(""),
@@ -3334,7 +4319,7 @@ function FontSizeButton2() {
3334
4319
  },
3335
4320
  "font-size-default"
3336
4321
  ),
3337
- FONT_SIZE_PRESETS.map((size) => /* @__PURE__ */ jsx21(
4322
+ FONT_SIZE_PRESETS.map((size) => /* @__PURE__ */ jsx22(
3338
4323
  Components.Generic.Menu.Item,
3339
4324
  {
3340
4325
  onClick: () => setFontSize(size),
@@ -3355,14 +4340,14 @@ import {
3355
4340
  } from "@blocknote/core";
3356
4341
  import {
3357
4342
  SplitButton,
3358
- useBlockNoteEditor as useBlockNoteEditor4,
3359
- useComponentsContext as useComponentsContext4,
4343
+ useBlockNoteEditor as useBlockNoteEditor5,
4344
+ useComponentsContext as useComponentsContext5,
3360
4345
  useDictionary,
3361
4346
  useEditorContentOrSelectionChange as useEditorContentOrSelectionChange2,
3362
- useSelectedBlocks as useSelectedBlocks4
4347
+ useSelectedBlocks as useSelectedBlocks5
3363
4348
  } from "@blocknote/react";
3364
- import { useCallback as useCallback18, useMemo as useMemo4, useRef as useRef10, useState as useState10 } from "react";
3365
- import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
4349
+ import { useCallback as useCallback19, useMemo as useMemo5, useRef as useRef10, useState as useState10 } from "react";
4350
+ import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
3366
4351
  var COLORS = [
3367
4352
  "default",
3368
4353
  "gray",
@@ -3379,7 +4364,7 @@ function ColorIcon(props) {
3379
4364
  const textColor = props.textColor || "default";
3380
4365
  const backgroundColor = props.backgroundColor || "default";
3381
4366
  const size = props.size || 16;
3382
- return /* @__PURE__ */ jsx22(
4367
+ return /* @__PURE__ */ jsx23(
3383
4368
  "div",
3384
4369
  {
3385
4370
  className: "bn-color-icon",
@@ -3398,7 +4383,7 @@ function ColorIcon(props) {
3398
4383
  );
3399
4384
  }
3400
4385
  function CellFillIcon({ size = 18 }) {
3401
- return /* @__PURE__ */ jsx22(
4386
+ return /* @__PURE__ */ jsx23(
3402
4387
  "svg",
3403
4388
  {
3404
4389
  width: size,
@@ -3407,17 +4392,17 @@ function CellFillIcon({ size = 18 }) {
3407
4392
  fill: "currentColor",
3408
4393
  style: { pointerEvents: "none" },
3409
4394
  "aria-hidden": "true",
3410
- children: /* @__PURE__ */ jsx22("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" })
4395
+ children: /* @__PURE__ */ jsx23("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" })
3411
4396
  }
3412
4397
  );
3413
4398
  }
3414
4399
  function LumirColorPicker(props) {
3415
- const Components = useComponentsContext4();
4400
+ const Components = useComponentsContext5();
3416
4401
  const dict = useDictionary();
3417
- return /* @__PURE__ */ jsxs14(Fragment5, { children: [
3418
- props.text ? /* @__PURE__ */ jsxs14(Fragment5, { children: [
3419
- /* @__PURE__ */ jsx22(Components.Generic.Menu.Label, { children: props.textTitle ?? dict.color_picker.text_title }),
3420
- COLORS.map((color) => /* @__PURE__ */ jsx22(
4402
+ return /* @__PURE__ */ jsxs15(Fragment5, { children: [
4403
+ props.text ? /* @__PURE__ */ jsxs15(Fragment5, { children: [
4404
+ /* @__PURE__ */ jsx23(Components.Generic.Menu.Label, { children: props.textTitle ?? dict.color_picker.text_title }),
4405
+ COLORS.map((color) => /* @__PURE__ */ jsx23(
3421
4406
  Components.Generic.Menu.Item,
3422
4407
  {
3423
4408
  onClick: () => {
@@ -3425,16 +4410,16 @@ function LumirColorPicker(props) {
3425
4410
  props.text.setColor(color);
3426
4411
  },
3427
4412
  "data-test": "text-color-" + color,
3428
- icon: /* @__PURE__ */ jsx22(ColorIcon, { textColor: color, size: props.iconSize }),
4413
+ icon: /* @__PURE__ */ jsx23(ColorIcon, { textColor: color, size: props.iconSize }),
3429
4414
  checked: props.text.color === color,
3430
4415
  children: dict.color_picker.colors[color]
3431
4416
  },
3432
4417
  "text-color-" + color
3433
4418
  ))
3434
4419
  ] }) : null,
3435
- props.background ? /* @__PURE__ */ jsxs14(Fragment5, { children: [
3436
- /* @__PURE__ */ jsx22(Components.Generic.Menu.Label, { children: props.backgroundTitle ?? dict.color_picker.background_title }),
3437
- COLORS.map((color) => /* @__PURE__ */ jsx22(
4420
+ props.background ? /* @__PURE__ */ jsxs15(Fragment5, { children: [
4421
+ /* @__PURE__ */ jsx23(Components.Generic.Menu.Label, { children: props.backgroundTitle ?? dict.color_picker.background_title }),
4422
+ COLORS.map((color) => /* @__PURE__ */ jsx23(
3438
4423
  Components.Generic.Menu.Item,
3439
4424
  {
3440
4425
  onClick: () => {
@@ -3442,7 +4427,7 @@ function LumirColorPicker(props) {
3442
4427
  props.background.setColor(color);
3443
4428
  },
3444
4429
  "data-test": "background-color-" + color,
3445
- icon: /* @__PURE__ */ jsx22(ColorIcon, { backgroundColor: color, size: props.iconSize }),
4430
+ icon: /* @__PURE__ */ jsx23(ColorIcon, { backgroundColor: color, size: props.iconSize }),
3446
4431
  checked: props.background.color === color,
3447
4432
  children: dict.color_picker.colors[color]
3448
4433
  },
@@ -3452,13 +4437,13 @@ function LumirColorPicker(props) {
3452
4437
  ] });
3453
4438
  }
3454
4439
  function LumirColorStyleButton() {
3455
- const Components = useComponentsContext4();
3456
- const editor = useBlockNoteEditor4();
4440
+ const Components = useComponentsContext5();
4441
+ const editor = useBlockNoteEditor5();
3457
4442
  const ed = editor;
3458
4443
  const styleSchema = editor.schema.styleSchema;
3459
4444
  const textColorInSchema = styleSchema.textColor?.type === "textColor" && styleSchema.textColor?.propSchema === "string";
3460
4445
  const backgroundColorInSchema = styleSchema.backgroundColor?.type === "backgroundColor" && styleSchema.backgroundColor?.propSchema === "string";
3461
- const selectedBlocks = useSelectedBlocks4(editor);
4446
+ const selectedBlocks = useSelectedBlocks5(editor);
3462
4447
  const [currentTextColor, setCurrentTextColor] = useState10(
3463
4448
  textColorInSchema ? ed.getActiveStyles().textColor || "default" : "default"
3464
4449
  );
@@ -3474,7 +4459,7 @@ function LumirColorStyleButton() {
3474
4459
  setCurrentBackgroundColor(active.backgroundColor || "default");
3475
4460
  }
3476
4461
  }, editor);
3477
- const setTextColor = useCallback18(
4462
+ const setTextColor = useCallback19(
3478
4463
  (color) => {
3479
4464
  color === "default" ? ed.removeStyles({ textColor: color }) : ed.addStyles({ textColor: color });
3480
4465
  setTimeout(() => editor.focus());
@@ -3482,7 +4467,7 @@ function LumirColorStyleButton() {
3482
4467
  // eslint-disable-next-line react-hooks/exhaustive-deps
3483
4468
  [editor]
3484
4469
  );
3485
- const setBackgroundColor = useCallback18(
4470
+ const setBackgroundColor = useCallback19(
3486
4471
  (color) => {
3487
4472
  color === "default" ? ed.removeStyles({ backgroundColor: color }) : ed.addStyles({ backgroundColor: color });
3488
4473
  setTimeout(() => editor.focus());
@@ -3490,7 +4475,7 @@ function LumirColorStyleButton() {
3490
4475
  // eslint-disable-next-line react-hooks/exhaustive-deps
3491
4476
  [editor]
3492
4477
  );
3493
- const show = useMemo4(() => {
4478
+ const show = useMemo5(() => {
3494
4479
  if (!textColorInSchema && !backgroundColorInSchema) {
3495
4480
  return false;
3496
4481
  }
@@ -3505,15 +4490,15 @@ function LumirColorStyleButton() {
3505
4490
  return null;
3506
4491
  }
3507
4492
  const tooltip = "\uD14D\uC2A4\uD2B8 \uC0C9\xB7\uBC30\uACBD";
3508
- return /* @__PURE__ */ jsxs14(Components.Generic.Menu.Root, { children: [
3509
- /* @__PURE__ */ jsx22(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ jsx22(
4493
+ return /* @__PURE__ */ jsxs15(Components.Generic.Menu.Root, { children: [
4494
+ /* @__PURE__ */ jsx23(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ jsx23(
3510
4495
  Components.FormattingToolbar.Button,
3511
4496
  {
3512
4497
  className: "bn-button",
3513
4498
  "data-test": "colors",
3514
4499
  label: tooltip,
3515
4500
  mainTooltip: tooltip,
3516
- icon: /* @__PURE__ */ jsx22(
4501
+ icon: /* @__PURE__ */ jsx23(
3517
4502
  ColorIcon,
3518
4503
  {
3519
4504
  textColor: currentTextColor,
@@ -3523,11 +4508,11 @@ function LumirColorStyleButton() {
3523
4508
  )
3524
4509
  }
3525
4510
  ) }),
3526
- /* @__PURE__ */ jsx22(
4511
+ /* @__PURE__ */ jsx23(
3527
4512
  Components.Generic.Menu.Dropdown,
3528
4513
  {
3529
4514
  className: "bn-menu-dropdown bn-color-picker-dropdown",
3530
- children: /* @__PURE__ */ jsx22(
4515
+ children: /* @__PURE__ */ jsx23(
3531
4516
  LumirColorPicker,
3532
4517
  {
3533
4518
  textTitle: "\uD14D\uC2A4\uD2B8 \uC0C9",
@@ -3541,10 +4526,10 @@ function LumirColorStyleButton() {
3541
4526
  ] });
3542
4527
  }
3543
4528
  function LumirCellColorToolbarButton() {
3544
- const Components = useComponentsContext4();
3545
- const editor = useBlockNoteEditor4();
3546
- const selectedBlocks = useSelectedBlocks4(editor);
3547
- const isMultiCell = useMemo4(() => {
4529
+ const Components = useComponentsContext5();
4530
+ const editor = useBlockNoteEditor5();
4531
+ const selectedBlocks = useSelectedBlocks5(editor);
4532
+ const isMultiCell = useMemo5(() => {
3548
4533
  if (selectedBlocks.length !== 1 || selectedBlocks[0].type !== "table") {
3549
4534
  return false;
3550
4535
  }
@@ -3552,7 +4537,7 @@ function LumirCellColorToolbarButton() {
3552
4537
  return !!cs && cs.cells.length > 1;
3553
4538
  }, [editor, selectedBlocks]);
3554
4539
  const stashRef = useRef10([]);
3555
- const applyBackground = useCallback18(
4540
+ const applyBackground = useCallback19(
3556
4541
  (color) => {
3557
4542
  const live = getSelectedCellPositions(editor);
3558
4543
  const positions = live.length > 0 ? live : stashRef.current;
@@ -3565,7 +4550,7 @@ function LumirCellColorToolbarButton() {
3565
4550
  return null;
3566
4551
  }
3567
4552
  const tooltip = "\uC140 \uBC30\uACBD\uC0C9";
3568
- return /* @__PURE__ */ jsxs14(
4553
+ return /* @__PURE__ */ jsxs15(
3569
4554
  Components.Generic.Menu.Root,
3570
4555
  {
3571
4556
  onOpenChange: (open) => {
@@ -3574,21 +4559,21 @@ function LumirCellColorToolbarButton() {
3574
4559
  }
3575
4560
  },
3576
4561
  children: [
3577
- /* @__PURE__ */ jsx22(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ jsx22(
4562
+ /* @__PURE__ */ jsx23(Components.Generic.Menu.Trigger, { children: /* @__PURE__ */ jsx23(
3578
4563
  Components.FormattingToolbar.Button,
3579
4564
  {
3580
4565
  className: "bn-button",
3581
4566
  "data-test": "cell-colors",
3582
4567
  label: tooltip,
3583
4568
  mainTooltip: tooltip,
3584
- icon: /* @__PURE__ */ jsx22(CellFillIcon, { size: 18 })
4569
+ icon: /* @__PURE__ */ jsx23(CellFillIcon, { size: 18 })
3585
4570
  }
3586
4571
  ) }),
3587
- /* @__PURE__ */ jsx22(
4572
+ /* @__PURE__ */ jsx23(
3588
4573
  Components.Generic.Menu.Dropdown,
3589
4574
  {
3590
4575
  className: "bn-menu-dropdown bn-color-picker-dropdown",
3591
- children: /* @__PURE__ */ jsx22(
4576
+ children: /* @__PURE__ */ jsx23(
3592
4577
  LumirColorPicker,
3593
4578
  {
3594
4579
  backgroundTitle: "\uC140 \uBC30\uACBD",
@@ -3602,8 +4587,8 @@ function LumirCellColorToolbarButton() {
3602
4587
  );
3603
4588
  }
3604
4589
  function LumirCellColorPickerButton(props) {
3605
- const Components = useComponentsContext4();
3606
- const editor = useBlockNoteEditor4();
4590
+ const Components = useComponentsContext5();
4591
+ const editor = useBlockNoteEditor5();
3607
4592
  const updateColor = (color, type) => {
3608
4593
  const newTable = props.block.content.rows.map((row) => ({
3609
4594
  ...row,
@@ -3624,14 +4609,14 @@ function LumirCellColorPickerButton(props) {
3624
4609
  if (!currentCell || editor.settings.tables.cellTextColor === false && editor.settings.tables.cellBackgroundColor === false) {
3625
4610
  return null;
3626
4611
  }
3627
- return /* @__PURE__ */ jsxs14(Components.Generic.Menu.Root, { position: "right", sub: true, children: [
3628
- /* @__PURE__ */ jsx22(Components.Generic.Menu.Trigger, { sub: true, children: /* @__PURE__ */ jsx22(Components.Generic.Menu.Item, { className: "bn-menu-item", subTrigger: true, children: "\uC140 \uC0C9\xB7\uBC30\uACBD" }) }),
3629
- /* @__PURE__ */ jsx22(
4612
+ return /* @__PURE__ */ jsxs15(Components.Generic.Menu.Root, { position: "right", sub: true, children: [
4613
+ /* @__PURE__ */ jsx23(Components.Generic.Menu.Trigger, { sub: true, children: /* @__PURE__ */ jsx23(Components.Generic.Menu.Item, { className: "bn-menu-item", subTrigger: true, children: "\uC140 \uC0C9\xB7\uBC30\uACBD" }) }),
4614
+ /* @__PURE__ */ jsx23(
3630
4615
  Components.Generic.Menu.Dropdown,
3631
4616
  {
3632
4617
  sub: true,
3633
4618
  className: "bn-menu-dropdown bn-color-picker-dropdown",
3634
- children: /* @__PURE__ */ jsx22(
4619
+ children: /* @__PURE__ */ jsx23(
3635
4620
  LumirColorPicker,
3636
4621
  {
3637
4622
  iconSize: 18,
@@ -3652,13 +4637,13 @@ function LumirCellColorPickerButton(props) {
3652
4637
  ] });
3653
4638
  }
3654
4639
  function LumirTableCellMenu(props) {
3655
- const Components = useComponentsContext4();
3656
- return /* @__PURE__ */ jsx22(
4640
+ const Components = useComponentsContext5();
4641
+ return /* @__PURE__ */ jsx23(
3657
4642
  Components.Generic.Menu.Dropdown,
3658
4643
  {
3659
4644
  className: "bn-menu-dropdown bn-drag-handle-menu",
3660
- children: props.children || /* @__PURE__ */ jsxs14(Fragment5, { children: [
3661
- /* @__PURE__ */ jsx22(
4645
+ children: props.children || /* @__PURE__ */ jsxs15(Fragment5, { children: [
4646
+ /* @__PURE__ */ jsx23(
3662
4647
  SplitButton,
3663
4648
  {
3664
4649
  block: props.block,
@@ -3666,7 +4651,7 @@ function LumirTableCellMenu(props) {
3666
4651
  colIndex: props.colIndex
3667
4652
  }
3668
4653
  ),
3669
- /* @__PURE__ */ jsx22(
4654
+ /* @__PURE__ */ jsx23(
3670
4655
  LumirCellColorPickerButton,
3671
4656
  {
3672
4657
  block: props.block,
@@ -3680,75 +4665,144 @@ function LumirTableCellMenu(props) {
3680
4665
  }
3681
4666
 
3682
4667
  // src/components/CustomFormattingToolbar.tsx
3683
- import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
4668
+ import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
3684
4669
  var CustomFormattingToolbar = () => {
3685
- return /* @__PURE__ */ jsxs15(FormattingToolbar, { children: [
3686
- /* @__PURE__ */ jsx23(BlockTypeSelect2, {}, "blockTypeSelect"),
3687
- /* @__PURE__ */ jsx23(TableCellMergeButton, {}, "tableCellMergeButton"),
3688
- /* @__PURE__ */ jsx23(FileCaptionButton, {}, "fileCaptionButton"),
3689
- /* @__PURE__ */ jsx23(FileReplaceButton, {}, "replaceFileButton"),
3690
- /* @__PURE__ */ jsx23(FileRenameButton, {}, "fileRenameButton"),
3691
- /* @__PURE__ */ jsx23(FileDeleteButton, {}, "fileDeleteButton"),
3692
- /* @__PURE__ */ jsx23(FileDownloadButton, {}, "fileDownloadButton"),
3693
- /* @__PURE__ */ jsx23(FilePreviewButton, {}, "filePreviewButton"),
3694
- /* @__PURE__ */ jsx23(BasicTextStyleButton, { basicTextStyle: "bold" }, "boldStyleButton"),
3695
- /* @__PURE__ */ jsx23(
4670
+ return /* @__PURE__ */ jsxs16(FormattingToolbar, { children: [
4671
+ /* @__PURE__ */ jsx24(BlockTypeSelect2, {}, "blockTypeSelect"),
4672
+ /* @__PURE__ */ jsx24(TableCellMergeButton, {}, "tableCellMergeButton"),
4673
+ /* @__PURE__ */ jsx24(FileCaptionButton, {}, "fileCaptionButton"),
4674
+ /* @__PURE__ */ jsx24(FileReplaceButton, {}, "replaceFileButton"),
4675
+ /* @__PURE__ */ jsx24(FileRenameButton, {}, "fileRenameButton"),
4676
+ /* @__PURE__ */ jsx24(FileDeleteButton, {}, "fileDeleteButton"),
4677
+ /* @__PURE__ */ jsx24(FileDownloadButton, {}, "fileDownloadButton"),
4678
+ /* @__PURE__ */ jsx24(FilePreviewButton, {}, "filePreviewButton"),
4679
+ /* @__PURE__ */ jsx24(BasicTextStyleButton, { basicTextStyle: "bold" }, "boldStyleButton"),
4680
+ /* @__PURE__ */ jsx24(
3696
4681
  BasicTextStyleButton,
3697
4682
  {
3698
4683
  basicTextStyle: "italic"
3699
4684
  },
3700
4685
  "italicStyleButton"
3701
4686
  ),
3702
- /* @__PURE__ */ jsx23(
4687
+ /* @__PURE__ */ jsx24(
3703
4688
  BasicTextStyleButton,
3704
4689
  {
3705
4690
  basicTextStyle: "underline"
3706
4691
  },
3707
4692
  "underlineStyleButton"
3708
4693
  ),
3709
- /* @__PURE__ */ jsx23(
4694
+ /* @__PURE__ */ jsx24(
3710
4695
  BasicTextStyleButton,
3711
4696
  {
3712
4697
  basicTextStyle: "strike"
3713
4698
  },
3714
4699
  "strikeStyleButton"
3715
4700
  ),
3716
- /* @__PURE__ */ jsx23(TextAlignButtonWithVA, { textAlignment: "left" }, "textAlignLeftButton"),
3717
- /* @__PURE__ */ jsx23(
4701
+ /* @__PURE__ */ jsx24(TextAlignButtonWithVA, { textAlignment: "left" }, "textAlignLeftButton"),
4702
+ /* @__PURE__ */ jsx24(
3718
4703
  TextAlignButtonWithVA,
3719
4704
  {
3720
4705
  textAlignment: "center"
3721
4706
  },
3722
4707
  "textAlignCenterButton"
3723
4708
  ),
3724
- /* @__PURE__ */ jsx23(TextAlignButtonWithVA, { textAlignment: "right" }, "textAlignRightButton"),
3725
- /* @__PURE__ */ jsx23(
4709
+ /* @__PURE__ */ jsx24(TextAlignButtonWithVA, { textAlignment: "right" }, "textAlignRightButton"),
4710
+ /* @__PURE__ */ jsx24(
3726
4711
  VerticalAlignButton,
3727
4712
  {
3728
4713
  verticalAlignment: "top"
3729
4714
  },
3730
4715
  "verticalAlignTop"
3731
4716
  ),
3732
- /* @__PURE__ */ jsx23(
4717
+ /* @__PURE__ */ jsx24(
3733
4718
  VerticalAlignButton,
3734
4719
  {
3735
4720
  verticalAlignment: "middle"
3736
4721
  },
3737
4722
  "verticalAlignMiddle"
3738
4723
  ),
3739
- /* @__PURE__ */ jsx23(
4724
+ /* @__PURE__ */ jsx24(
3740
4725
  VerticalAlignButton,
3741
4726
  {
3742
4727
  verticalAlignment: "bottom"
3743
4728
  },
3744
4729
  "verticalAlignBottom"
3745
4730
  ),
3746
- /* @__PURE__ */ jsx23(FontSizeButton2, {}, "fontSizeButton"),
3747
- /* @__PURE__ */ jsx23(LumirColorStyleButton, {}, "colorStyleButton"),
3748
- /* @__PURE__ */ jsx23(LumirCellColorToolbarButton, {}, "cellColorButton"),
3749
- /* @__PURE__ */ jsx23(NestBlockButton, {}, "nestBlockButton"),
3750
- /* @__PURE__ */ jsx23(UnnestBlockButton, {}, "unnestBlockButton"),
3751
- /* @__PURE__ */ jsx23(CreateLinkButton, {}, "createLinkButton")
4731
+ /* @__PURE__ */ jsx24(TableAlignButton, { alignment: "left" }, "tableAlignLeft"),
4732
+ /* @__PURE__ */ jsx24(TableAlignButton, { alignment: "center" }, "tableAlignCenter"),
4733
+ /* @__PURE__ */ jsx24(TableAlignButton, { alignment: "right" }, "tableAlignRight"),
4734
+ /* @__PURE__ */ jsx24(FontSizeButton2, {}, "fontSizeButton"),
4735
+ /* @__PURE__ */ jsx24(LumirColorStyleButton, {}, "colorStyleButton"),
4736
+ /* @__PURE__ */ jsx24(LumirCellColorToolbarButton, {}, "cellColorButton"),
4737
+ /* @__PURE__ */ jsx24(NestBlockButton, {}, "nestBlockButton"),
4738
+ /* @__PURE__ */ jsx24(UnnestBlockButton, {}, "unnestBlockButton"),
4739
+ /* @__PURE__ */ jsx24(CreateLinkButton, {}, "createLinkButton")
4740
+ ] });
4741
+ };
4742
+
4743
+ // src/components/LumirDragHandleMenu.tsx
4744
+ import {
4745
+ DragHandleMenu,
4746
+ RemoveBlockItem,
4747
+ BlockColorsItem,
4748
+ TableRowHeaderItem,
4749
+ TableColumnHeaderItem,
4750
+ useComponentsContext as useComponentsContext6,
4751
+ useBlockNoteEditor as useBlockNoteEditor6,
4752
+ useDictionary as useDictionary2
4753
+ } from "@blocknote/react";
4754
+ import { Fragment as Fragment6, jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
4755
+ var TABLE_ALIGN_ICONS = {
4756
+ left: /* @__PURE__ */ jsxs17("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
4757
+ /* @__PURE__ */ jsx25("rect", { x: "1.5", y: "4", width: "7", height: "8", rx: "1", fill: "currentColor", stroke: "none" }),
4758
+ /* @__PURE__ */ jsx25("line", { x1: "1.5", y1: "1.5", x2: "14.5", y2: "1.5" }),
4759
+ /* @__PURE__ */ jsx25("line", { x1: "1.5", y1: "14.5", x2: "14.5", y2: "14.5" })
4760
+ ] }),
4761
+ center: /* @__PURE__ */ jsxs17("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
4762
+ /* @__PURE__ */ jsx25("rect", { x: "4.5", y: "4", width: "7", height: "8", rx: "1", fill: "currentColor", stroke: "none" }),
4763
+ /* @__PURE__ */ jsx25("line", { x1: "1.5", y1: "1.5", x2: "14.5", y2: "1.5" }),
4764
+ /* @__PURE__ */ jsx25("line", { x1: "1.5", y1: "14.5", x2: "14.5", y2: "14.5" })
4765
+ ] }),
4766
+ right: /* @__PURE__ */ jsxs17("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.4", children: [
4767
+ /* @__PURE__ */ jsx25("rect", { x: "7.5", y: "4", width: "7", height: "8", rx: "1", fill: "currentColor", stroke: "none" }),
4768
+ /* @__PURE__ */ jsx25("line", { x1: "1.5", y1: "1.5", x2: "14.5", y2: "1.5" }),
4769
+ /* @__PURE__ */ jsx25("line", { x1: "1.5", y1: "14.5", x2: "14.5", y2: "14.5" })
4770
+ ] })
4771
+ };
4772
+ var TABLE_ALIGN_LABELS = {
4773
+ left: "\uD45C \uC67C\uCABD \uC815\uB82C",
4774
+ center: "\uD45C \uAC00\uC6B4\uB370 \uC815\uB82C",
4775
+ right: "\uD45C \uC624\uB978\uCABD \uC815\uB82C"
4776
+ };
4777
+ function TableAlignmentItems(props) {
4778
+ const Components = useComponentsContext6();
4779
+ const editor = useBlockNoteEditor6();
4780
+ if (props.block?.type !== "table" || !props.block?.id) {
4781
+ return null;
4782
+ }
4783
+ const current = getTableAlignment(editor, props.block.id);
4784
+ return /* @__PURE__ */ jsx25(Fragment6, { children: ["left", "center", "right"].map((align) => /* @__PURE__ */ jsx25(
4785
+ Components.Generic.Menu.Item,
4786
+ {
4787
+ icon: TABLE_ALIGN_ICONS[align],
4788
+ checked: current === align,
4789
+ onClick: () => {
4790
+ setTableAlignment(editor, props.block.id, align);
4791
+ editor.setTextCursorPosition(props.block.id);
4792
+ },
4793
+ children: TABLE_ALIGN_LABELS[align]
4794
+ },
4795
+ `tableAlign-${align}`
4796
+ )) });
4797
+ }
4798
+ var LumirDragHandleMenu = (props) => {
4799
+ const dict = useDictionary2();
4800
+ return /* @__PURE__ */ jsxs17(DragHandleMenu, { ...props, children: [
4801
+ /* @__PURE__ */ jsx25(RemoveBlockItem, { ...props, children: dict.drag_handle.delete_menuitem }),
4802
+ /* @__PURE__ */ jsx25(BlockColorsItem, { ...props, children: dict.drag_handle.colors_menuitem }),
4803
+ /* @__PURE__ */ jsx25(TableRowHeaderItem, { ...props, children: dict.drag_handle.header_row_menuitem }),
4804
+ /* @__PURE__ */ jsx25(TableColumnHeaderItem, { ...props, children: dict.drag_handle.header_column_menuitem }),
4805
+ /* @__PURE__ */ jsx25(TableAlignmentItems, { block: props.block })
3752
4806
  ] });
3753
4807
  };
3754
4808
 
@@ -3757,13 +4811,13 @@ import {
3757
4811
  ExtendButton,
3758
4812
  TableCellButton,
3759
4813
  TableHandle,
3760
- useBlockNoteEditor as useBlockNoteEditor5,
4814
+ useBlockNoteEditor as useBlockNoteEditor7,
3761
4815
  useEditorContentOrSelectionChange as useEditorContentOrSelectionChange3,
3762
4816
  useExtendButtonsPositioning,
3763
4817
  useUIPluginState
3764
4818
  } from "@blocknote/react";
3765
4819
  import { autoUpdate as autoUpdate2, FloatingPortal } from "@floating-ui/react";
3766
- import { useCallback as useCallback19, useEffect as useEffect10, useMemo as useMemo6, useRef as useRef11, useState as useState11 } from "react";
4820
+ import { useCallback as useCallback20, useEffect as useEffect10, useMemo as useMemo7, useRef as useRef11, useState as useState11 } from "react";
3767
4821
 
3768
4822
  // src/components/hooks/useFocusedCellHandlePositioning.ts
3769
4823
  import {
@@ -3772,9 +4826,9 @@ import {
3772
4826
  useFloating,
3773
4827
  useTransitionStyles
3774
4828
  } from "@floating-ui/react";
3775
- import { useEffect as useEffect9, useMemo as useMemo5 } from "react";
4829
+ import { useEffect as useEffect9, useMemo as useMemo6 } from "react";
3776
4830
  function useFocusedCellHandlePositioning(cellEl, tbodyEl, orientation, show) {
3777
- const { refs, floatingStyles, context } = useFloating({
4831
+ const { refs, floatingStyles, context, update } = useFloating({
3778
4832
  open: show,
3779
4833
  placement: orientation === "row" ? "left" : orientation === "col" ? "top" : "right",
3780
4834
  // col/row: 가장자리 선(zero-size)에, cell: 셀 우측 보더에 14px hit-area 중앙 정렬(-7).
@@ -3782,6 +4836,14 @@ function useFocusedCellHandlePositioning(cellEl, tbodyEl, orientation, show) {
3782
4836
  whileElementsMounted: autoUpdate
3783
4837
  });
3784
4838
  const { isMounted, styles } = useTransitionStyles(context);
4839
+ useEffect9(() => {
4840
+ if (!show || !tbodyEl) {
4841
+ return;
4842
+ }
4843
+ const ro = new ResizeObserver(() => update());
4844
+ ro.observe(tbodyEl);
4845
+ return () => ro.disconnect();
4846
+ }, [show, tbodyEl, update]);
3785
4847
  useEffect9(() => {
3786
4848
  if (!cellEl) {
3787
4849
  refs.setReference(null);
@@ -3802,7 +4864,7 @@ function useFocusedCellHandlePositioning(cellEl, tbodyEl, orientation, show) {
3802
4864
  }
3803
4865
  });
3804
4866
  }, [cellEl, tbodyEl, orientation, refs]);
3805
- return useMemo5(
4867
+ return useMemo6(
3806
4868
  () => ({
3807
4869
  isMounted,
3808
4870
  ref: refs.setFloating,
@@ -3817,7 +4879,7 @@ function useFocusedCellHandlePositioning(cellEl, tbodyEl, orientation, show) {
3817
4879
  }
3818
4880
 
3819
4881
  // src/components/LumirTableHandlesController.tsx
3820
- import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
4882
+ import { Fragment as Fragment7, jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
3821
4883
  function syncCoreHoverToFocusedCell(cellEl) {
3822
4884
  const r = cellEl.getBoundingClientRect();
3823
4885
  cellEl.dispatchEvent(
@@ -3831,7 +4893,7 @@ function syncCoreHoverToFocusedCell(cellEl) {
3831
4893
  );
3832
4894
  }
3833
4895
  function LumirTableHandlesController() {
3834
- const editor = useBlockNoteEditor5();
4896
+ const editor = useBlockNoteEditor7();
3835
4897
  const [focused, setFocused] = useState11(null);
3836
4898
  const [menuContainerRef, setMenuContainerRef] = useState11(null);
3837
4899
  const [overlayEl, setOverlayEl] = useState11(null);
@@ -3839,7 +4901,7 @@ function LumirTableHandlesController() {
3839
4901
  const frozenRef = useRef11(false);
3840
4902
  const menuOpenRef = useRef11(false);
3841
4903
  const draggingRef = useRef11(false);
3842
- const recompute = useCallback19(() => {
4904
+ const recompute = useCallback20(() => {
3843
4905
  if (frozenRef.current) {
3844
4906
  return;
3845
4907
  }
@@ -3928,7 +4990,13 @@ function LumirTableHandlesController() {
3928
4990
  overlayEl.style.height = `${bottom - top}px`;
3929
4991
  };
3930
4992
  update();
3931
- return autoUpdate2(f.cellEl, overlayEl, update);
4993
+ const stopAutoUpdate = autoUpdate2(f.cellEl, overlayEl, update);
4994
+ const ro = new ResizeObserver(update);
4995
+ ro.observe(f.tbodyEl);
4996
+ return () => {
4997
+ stopAutoUpdate();
4998
+ ro.disconnect();
4999
+ };
3932
5000
  }, [focused, overlayEl, openMenu]);
3933
5001
  const cellEl = focused?.cellEl ?? null;
3934
5002
  const tbodyEl = focused?.tbodyEl ?? null;
@@ -3950,13 +5018,13 @@ function LumirTableHandlesController() {
3950
5018
  coreState?.showAddOrRemoveRowsButton || false,
3951
5019
  coreState?.referencePosTable || null
3952
5020
  );
3953
- const onStartExtend = useCallback19(() => {
5021
+ const onStartExtend = useCallback20(() => {
3954
5022
  editor.tableHandles?.freezeHandles();
3955
5023
  }, [editor]);
3956
- const onEndExtend = useCallback19(() => {
5024
+ const onEndExtend = useCallback20(() => {
3957
5025
  editor.tableHandles?.unfreezeHandles();
3958
5026
  }, [editor]);
3959
- const menuHandlers = useMemo6(() => {
5027
+ const menuHandlers = useMemo7(() => {
3960
5028
  const mk = (kind) => ({
3961
5029
  freeze: () => {
3962
5030
  menuOpenRef.current = true;
@@ -3974,10 +5042,10 @@ function LumirTableHandlesController() {
3974
5042
  });
3975
5043
  return { col: mk("col"), row: mk("row"), cell: mk("cell") };
3976
5044
  }, [editor, recompute]);
3977
- const onGutterPointerDown = useCallback19(() => {
5045
+ const onGutterPointerDown = useCallback20(() => {
3978
5046
  frozenRef.current = true;
3979
5047
  }, []);
3980
- const onGutterPointerEnter = useCallback19(
5048
+ const onGutterPointerEnter = useCallback20(
3981
5049
  (e) => {
3982
5050
  if (e.buttons === 0 && focused) {
3983
5051
  syncCoreHoverToFocusedCell(focused.cellEl);
@@ -3985,7 +5053,7 @@ function LumirTableHandlesController() {
3985
5053
  },
3986
5054
  [focused]
3987
5055
  );
3988
- const makeDragStart = useCallback19(
5056
+ const makeDragStart = useCallback20(
3989
5057
  (dir) => (e) => {
3990
5058
  draggingRef.current = true;
3991
5059
  frozenRef.current = true;
@@ -3997,19 +5065,19 @@ function LumirTableHandlesController() {
3997
5065
  },
3998
5066
  [editor]
3999
5067
  );
4000
- const onDragEnd = useCallback19(() => {
5068
+ const onDragEnd = useCallback20(() => {
4001
5069
  editor.tableHandles?.dragEnd();
4002
5070
  draggingRef.current = false;
4003
5071
  frozenRef.current = false;
4004
5072
  recompute();
4005
5073
  }, [editor, recompute]);
4006
- const noop = useCallback19(() => {
5074
+ const noop = useCallback20(() => {
4007
5075
  }, []);
4008
- return /* @__PURE__ */ jsxs16(Fragment6, { children: [
4009
- /* @__PURE__ */ jsx24("div", { ref: setMenuContainerRef }),
4010
- th && focused && menuContainerRef && /* @__PURE__ */ jsxs16(FloatingPortal, { root: focused.widgetContainer, children: [
4011
- /* @__PURE__ */ jsx24("div", { ref: setOverlayEl, className: "lumir-tbl-cell-focus" }),
4012
- colHandle.isMounted && /* @__PURE__ */ jsxs16(
5076
+ return /* @__PURE__ */ jsxs18(Fragment7, { children: [
5077
+ /* @__PURE__ */ jsx26("div", { ref: setMenuContainerRef }),
5078
+ th && focused && menuContainerRef && /* @__PURE__ */ jsxs18(FloatingPortal, { root: focused.widgetContainer, children: [
5079
+ /* @__PURE__ */ jsx26("div", { ref: setOverlayEl, className: "lumir-tbl-cell-focus" }),
5080
+ colHandle.isMounted && /* @__PURE__ */ jsxs18(
4013
5081
  "div",
4014
5082
  {
4015
5083
  ref: colHandle.ref,
@@ -4018,8 +5086,8 @@ function LumirTableHandlesController() {
4018
5086
  onPointerEnter: onGutterPointerEnter,
4019
5087
  onPointerDown: onGutterPointerDown,
4020
5088
  children: [
4021
- /* @__PURE__ */ jsx24("span", { className: "lumir-tbl-gutter" }),
4022
- /* @__PURE__ */ jsx24("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ jsx24(
5089
+ /* @__PURE__ */ jsx26("span", { className: "lumir-tbl-gutter" }),
5090
+ /* @__PURE__ */ jsx26("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ jsx26(
4023
5091
  TableHandle,
4024
5092
  {
4025
5093
  editor,
@@ -4038,7 +5106,7 @@ function LumirTableHandlesController() {
4038
5106
  ]
4039
5107
  }
4040
5108
  ),
4041
- rowHandle.isMounted && /* @__PURE__ */ jsxs16(
5109
+ rowHandle.isMounted && /* @__PURE__ */ jsxs18(
4042
5110
  "div",
4043
5111
  {
4044
5112
  ref: rowHandle.ref,
@@ -4047,8 +5115,8 @@ function LumirTableHandlesController() {
4047
5115
  onPointerEnter: onGutterPointerEnter,
4048
5116
  onPointerDown: onGutterPointerDown,
4049
5117
  children: [
4050
- /* @__PURE__ */ jsx24("span", { className: "lumir-tbl-gutter" }),
4051
- /* @__PURE__ */ jsx24("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ jsx24(
5118
+ /* @__PURE__ */ jsx26("span", { className: "lumir-tbl-gutter" }),
5119
+ /* @__PURE__ */ jsx26("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ jsx26(
4052
5120
  TableHandle,
4053
5121
  {
4054
5122
  editor,
@@ -4067,7 +5135,7 @@ function LumirTableHandlesController() {
4067
5135
  ]
4068
5136
  }
4069
5137
  ),
4070
- cellHandle.isMounted && openMenu !== "col" && openMenu !== "row" && /* @__PURE__ */ jsxs16(
5138
+ cellHandle.isMounted && openMenu !== "col" && openMenu !== "row" && /* @__PURE__ */ jsxs18(
4071
5139
  "div",
4072
5140
  {
4073
5141
  ref: cellHandle.ref,
@@ -4075,8 +5143,8 @@ function LumirTableHandlesController() {
4075
5143
  className: "lumir-tbl-gutter-wrap lumir-tbl-gutter-wrap--cell" + (openMenu === "cell" ? " lumir-tbl-gutter-wrap--active" : ""),
4076
5144
  onPointerDown: onGutterPointerDown,
4077
5145
  children: [
4078
- /* @__PURE__ */ jsx24("span", { className: "lumir-tbl-gutter" }),
4079
- /* @__PURE__ */ jsx24("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ jsx24(
5146
+ /* @__PURE__ */ jsx26("span", { className: "lumir-tbl-gutter" }),
5147
+ /* @__PURE__ */ jsx26("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ jsx26(
4080
5148
  TableCellButton,
4081
5149
  {
4082
5150
  editor,
@@ -4093,8 +5161,8 @@ function LumirTableHandlesController() {
4093
5161
  }
4094
5162
  )
4095
5163
  ] }),
4096
- th && coreState?.widgetContainer && /* @__PURE__ */ jsxs16(FloatingPortal, { root: coreState.widgetContainer, children: [
4097
- /* @__PURE__ */ jsx24("div", { ref: addOrRemoveRowsButton.ref, style: addOrRemoveRowsButton.style, children: /* @__PURE__ */ jsx24(
5164
+ th && coreState?.widgetContainer && /* @__PURE__ */ jsxs18(FloatingPortal, { root: coreState.widgetContainer, children: [
5165
+ /* @__PURE__ */ jsx26("div", { ref: addOrRemoveRowsButton.ref, style: addOrRemoveRowsButton.style, children: /* @__PURE__ */ jsx26(
4098
5166
  ExtendButton,
4099
5167
  {
4100
5168
  editor,
@@ -4104,12 +5172,12 @@ function LumirTableHandlesController() {
4104
5172
  onMouseUp: onEndExtend
4105
5173
  }
4106
5174
  ) }),
4107
- /* @__PURE__ */ jsx24(
5175
+ /* @__PURE__ */ jsx26(
4108
5176
  "div",
4109
5177
  {
4110
5178
  ref: addOrRemoveColumnsButton.ref,
4111
5179
  style: addOrRemoveColumnsButton.style,
4112
- children: /* @__PURE__ */ jsx24(
5180
+ children: /* @__PURE__ */ jsx26(
4113
5181
  ExtendButton,
4114
5182
  {
4115
5183
  editor,
@@ -4126,15 +5194,17 @@ function LumirTableHandlesController() {
4126
5194
  }
4127
5195
 
4128
5196
  // src/utils/table-vertical-alignment.ts
4129
- function injectVerticalAlignment(blocks, editor) {
4130
- const tiptap = editor?._tiptapEditor;
4131
- if (!tiptap) return blocks;
4132
- const { doc } = tiptap.state;
4133
- const tableVAMap = buildTableVerticalAlignmentMap(doc);
4134
- if (tableVAMap.size === 0) return blocks;
4135
- return patchBlocks(blocks, tableVAMap);
5197
+ var CELL_ATTR_DEFAULTS = {
5198
+ verticalAlignment: "top",
5199
+ rowHeight: null
5200
+ };
5201
+ function isMeaningful2(attr, value) {
5202
+ if (value === null || value === void 0) {
5203
+ return false;
5204
+ }
5205
+ return value !== CELL_ATTR_DEFAULTS[attr];
4136
5206
  }
4137
- function buildTableVerticalAlignmentMap(doc) {
5207
+ function buildTableCellAttrMap(doc, attrs) {
4138
5208
  const result = /* @__PURE__ */ new Map();
4139
5209
  doc.descendants((node) => {
4140
5210
  if (node.type.name === "blockContainer") {
@@ -4147,9 +5217,15 @@ function buildTableVerticalAlignmentMap(doc) {
4147
5217
  if (rowNode.type.name === "tableRow") {
4148
5218
  let colIndex = 0;
4149
5219
  rowNode.forEach((cellNode) => {
4150
- const va = cellNode.attrs?.verticalAlignment;
4151
- if (va && va !== "top") {
4152
- cells.push({ row: rowIndex, col: colIndex, va });
5220
+ const props = {};
5221
+ for (const attr of attrs) {
5222
+ const value = cellNode.attrs?.[attr];
5223
+ if (isMeaningful2(attr, value)) {
5224
+ props[attr] = value;
5225
+ }
5226
+ }
5227
+ if (Object.keys(props).length > 0) {
5228
+ cells.push({ row: rowIndex, col: colIndex, props });
4153
5229
  }
4154
5230
  colIndex++;
4155
5231
  });
@@ -4165,18 +5241,21 @@ function buildTableVerticalAlignmentMap(doc) {
4165
5241
  });
4166
5242
  return result;
4167
5243
  }
4168
- function patchBlocks(blocks, tableVAMap) {
5244
+ function patchBlocks(blocks, cellAttrMap) {
4169
5245
  return blocks.map((block) => {
4170
5246
  if (block.type !== "table" || !block.id || !block.content) {
4171
5247
  if (block.children && block.children.length > 0) {
4172
5248
  return {
4173
5249
  ...block,
4174
- children: patchBlocks(block.children, tableVAMap)
5250
+ children: patchBlocks(
5251
+ block.children,
5252
+ cellAttrMap
5253
+ )
4175
5254
  };
4176
5255
  }
4177
5256
  return block;
4178
5257
  }
4179
- const cells = tableVAMap.get(block.id);
5258
+ const cells = cellAttrMap.get(block.id);
4180
5259
  if (!cells || cells.length === 0) {
4181
5260
  return block;
4182
5261
  }
@@ -4189,11 +5268,13 @@ function patchBlocks(blocks, tableVAMap) {
4189
5268
  const match = cells.find(
4190
5269
  (c) => c.row === rowIndex && c.col === colIndex
4191
5270
  );
4192
- if (!match) return cell;
5271
+ if (!match) {
5272
+ return cell;
5273
+ }
4193
5274
  if (cell && typeof cell === "object" && cell.type === "tableCell") {
4194
5275
  return {
4195
5276
  ...cell,
4196
- props: { ...cell.props, verticalAlignment: match.va }
5277
+ props: { ...cell.props, ...match.props }
4197
5278
  };
4198
5279
  }
4199
5280
  return cell;
@@ -4206,6 +5287,77 @@ function patchBlocks(blocks, tableVAMap) {
4206
5287
  };
4207
5288
  });
4208
5289
  }
5290
+ function injectTableCellAttrs(blocks, editor, attrs) {
5291
+ const tiptap = editor?._tiptapEditor;
5292
+ if (!tiptap) {
5293
+ return blocks;
5294
+ }
5295
+ const { doc } = tiptap.state;
5296
+ const cellAttrMap = buildTableCellAttrMap(doc, attrs);
5297
+ if (cellAttrMap.size === 0) {
5298
+ return blocks;
5299
+ }
5300
+ return patchBlocks(blocks, cellAttrMap);
5301
+ }
5302
+ var TABLE_BLOCK_ATTR_DEFAULTS = {
5303
+ tableAlignment: "left"
5304
+ };
5305
+ function buildTableBlockAttrMap(doc, attrs) {
5306
+ const result = /* @__PURE__ */ new Map();
5307
+ doc.descendants((node) => {
5308
+ if (node.type.name === "blockContainer") {
5309
+ const blockId = node.attrs?.id;
5310
+ const contentNode = node.firstChild;
5311
+ if (blockId && contentNode?.type.name === "table") {
5312
+ const props = {};
5313
+ for (const attr of attrs) {
5314
+ const value = contentNode.attrs?.[attr];
5315
+ if (value !== null && value !== void 0 && value !== TABLE_BLOCK_ATTR_DEFAULTS[attr]) {
5316
+ props[attr] = value;
5317
+ }
5318
+ }
5319
+ if (Object.keys(props).length > 0) {
5320
+ result.set(blockId, props);
5321
+ }
5322
+ }
5323
+ return false;
5324
+ }
5325
+ return void 0;
5326
+ });
5327
+ return result;
5328
+ }
5329
+ function patchTableBlockProps(blocks, attrMap) {
5330
+ return blocks.map((block) => {
5331
+ if (block.type === "table" && block.id && attrMap.has(block.id)) {
5332
+ return {
5333
+ ...block,
5334
+ props: { ...block.props, ...attrMap.get(block.id) }
5335
+ };
5336
+ }
5337
+ if (block.children && block.children.length > 0) {
5338
+ return {
5339
+ ...block,
5340
+ children: patchTableBlockProps(
5341
+ block.children,
5342
+ attrMap
5343
+ )
5344
+ };
5345
+ }
5346
+ return block;
5347
+ });
5348
+ }
5349
+ function injectTableBlockAttrs(blocks, editor) {
5350
+ const tiptap = editor?._tiptapEditor;
5351
+ if (!tiptap) {
5352
+ return blocks;
5353
+ }
5354
+ const { doc } = tiptap.state;
5355
+ const attrMap = buildTableBlockAttrMap(doc, ["tableAlignment"]);
5356
+ if (attrMap.size === 0) {
5357
+ return blocks;
5358
+ }
5359
+ return patchTableBlockProps(blocks, attrMap);
5360
+ }
4209
5361
 
4210
5362
  // src/utils/font-size-serialization.ts
4211
5363
  function mapPreservingRef(arr, fn) {
@@ -4520,26 +5672,8 @@ function normalizeExcelTableHtml(html) {
4520
5672
  }
4521
5673
  }
4522
5674
 
4523
- // src/constants/limits.ts
4524
- var MAX_FILE_SIZE = 10 * 1024 * 1024;
4525
- var MAX_VIDEO_FILE_SIZE = 100 * 1024 * 1024;
4526
- var BLOCKED_EXTENSIONS = [".svg", ".svgz"];
4527
- var ALLOWED_VIDEO_MIME_TYPES = /* @__PURE__ */ new Set([
4528
- "video/mp4",
4529
- "video/webm",
4530
- "video/ogg",
4531
- "video/quicktime"
4532
- // .mov
4533
- ]);
4534
- var ALLOWED_VIDEO_EXTENSIONS = [
4535
- ".mp4",
4536
- ".webm",
4537
- ".ogg",
4538
- ".mov"
4539
- ];
4540
-
4541
5675
  // src/components/LumirEditor.tsx
4542
- import { Fragment as Fragment7, jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
5676
+ import { Fragment as Fragment8, jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
4543
5677
  var DEBUG_LOG = (loc, msg, data) => {
4544
5678
  const p = fetch("http://127.0.0.1:7686/ingest/1f8ee1c5-0cf0-4ae7-91ed-5ea7ed17130a", {
4545
5679
  method: "POST",
@@ -4770,9 +5904,9 @@ var findBlockWithLink = (blocks, targetUrl) => {
4770
5904
  return null;
4771
5905
  };
4772
5906
  var ConvertToPreviewButton = ({ url }) => {
4773
- const editor = useBlockNoteEditor6();
4774
- const Components = useComponentsContext5();
4775
- return /* @__PURE__ */ jsx25(
5907
+ const editor = useBlockNoteEditor8();
5908
+ const Components = useComponentsContext7();
5909
+ return /* @__PURE__ */ jsx27(
4776
5910
  Components.LinkToolbar.Button,
4777
5911
  {
4778
5912
  className: "bn-button",
@@ -4791,29 +5925,29 @@ var ConvertToPreviewButton = ({ url }) => {
4791
5925
  console.error("Convert to link preview failed:", err);
4792
5926
  }
4793
5927
  },
4794
- icon: /* @__PURE__ */ jsxs17("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
4795
- /* @__PURE__ */ jsx25("rect", { x: "1", y: "3", width: "14", height: "10", rx: "2", stroke: "currentColor", strokeWidth: "1.5", fill: "none" }),
4796
- /* @__PURE__ */ jsx25("line", { x1: "1", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "1.5" }),
4797
- /* @__PURE__ */ jsx25("circle", { cx: "5", cy: "6.5", r: "1.5", stroke: "currentColor", strokeWidth: "1", fill: "none" })
5928
+ icon: /* @__PURE__ */ jsxs19("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
5929
+ /* @__PURE__ */ jsx27("rect", { x: "1", y: "3", width: "14", height: "10", rx: "2", stroke: "currentColor", strokeWidth: "1.5", fill: "none" }),
5930
+ /* @__PURE__ */ jsx27("line", { x1: "1", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "1.5" }),
5931
+ /* @__PURE__ */ jsx27("circle", { cx: "5", cy: "6.5", r: "1.5", stroke: "currentColor", strokeWidth: "1", fill: "none" })
4798
5932
  ] })
4799
5933
  }
4800
5934
  );
4801
5935
  };
4802
5936
  var CustomLinkToolbar = (props) => {
4803
- const editor = useBlockNoteEditor6();
4804
- const Components = useComponentsContext5();
5937
+ const editor = useBlockNoteEditor8();
5938
+ const Components = useComponentsContext7();
4805
5939
  const hasLinkPreview = !!editor?._linkPreviewApiEndpoint;
4806
- return /* @__PURE__ */ jsxs17(
5940
+ return /* @__PURE__ */ jsxs19(
4807
5941
  Components.LinkToolbar.Root,
4808
5942
  {
4809
5943
  className: "bn-toolbar bn-link-toolbar",
4810
5944
  onMouseEnter: props.stopHideTimer,
4811
5945
  onMouseLeave: props.startHideTimer,
4812
5946
  children: [
4813
- /* @__PURE__ */ jsx25(EditLinkButton, { url: props.url, text: props.text, editLink: props.editLink }),
4814
- /* @__PURE__ */ jsx25(OpenLinkButton, { url: props.url }),
4815
- /* @__PURE__ */ jsx25(DeleteLinkButton, { deleteLink: props.deleteLink }),
4816
- hasLinkPreview && /* @__PURE__ */ jsx25(ConvertToPreviewButton, { url: props.url })
5947
+ /* @__PURE__ */ jsx27(EditLinkButton, { url: props.url, text: props.text, editLink: props.editLink }),
5948
+ /* @__PURE__ */ jsx27(OpenLinkButton, { url: props.url }),
5949
+ /* @__PURE__ */ jsx27(DeleteLinkButton, { deleteLink: props.deleteLink }),
5950
+ hasLinkPreview && /* @__PURE__ */ jsx27(ConvertToPreviewButton, { url: props.url })
4817
5951
  ]
4818
5952
  }
4819
5953
  );
@@ -4863,7 +5997,7 @@ function LumirEditor({
4863
5997
  const floatingMenuFileInputRef = useRef12(null);
4864
5998
  const floatingMenuBlockRef = useRef12(null);
4865
5999
  const floatingMenuUploadStartTimeRef = useRef12(0);
4866
- const handleError = useCallback20(
6000
+ const handleError = useCallback21(
4867
6001
  (error) => {
4868
6002
  onError?.(error);
4869
6003
  setErrorMessage(error.getUserMessage());
@@ -4871,12 +6005,12 @@ function LumirEditor({
4871
6005
  },
4872
6006
  [onError]
4873
6007
  );
4874
- const validatedContent = useMemo7(() => {
6008
+ const validatedContent = useMemo8(() => {
4875
6009
  return liftFontSize(
4876
6010
  ContentUtils.validateContent(initialContent, initialEmptyBlocks)
4877
6011
  );
4878
6012
  }, [initialContent, initialEmptyBlocks]);
4879
- const tableConfig = useMemo7(() => {
6013
+ const tableConfig = useMemo8(() => {
4880
6014
  return EditorConfig.getDefaultTableConfig(tables);
4881
6015
  }, [
4882
6016
  tables?.splitCells,
@@ -4884,10 +6018,10 @@ function LumirEditor({
4884
6018
  tables?.cellTextColor,
4885
6019
  tables?.headers
4886
6020
  ]);
4887
- const headingConfig = useMemo7(() => {
6021
+ const headingConfig = useMemo8(() => {
4888
6022
  return EditorConfig.getDefaultHeadingConfig(heading);
4889
6023
  }, [heading?.levels?.join(",") ?? ""]);
4890
- const disabledExtensions = useMemo7(() => {
6024
+ const disabledExtensions = useMemo8(() => {
4891
6025
  return EditorConfig.getDisabledExtensions(
4892
6026
  disableExtensions,
4893
6027
  allowVideoUpload,
@@ -4906,7 +6040,7 @@ function LumirEditor({
4906
6040
  useEffect11(() => {
4907
6041
  fileNameTransformRef.current = s3Upload?.fileNameTransform;
4908
6042
  }, [s3Upload?.fileNameTransform]);
4909
- const memoizedS3Upload = useMemo7(() => {
6043
+ const memoizedS3Upload = useMemo8(() => {
4910
6044
  if (!s3Upload) return void 0;
4911
6045
  return {
4912
6046
  apiEndpoint: s3Upload.apiEndpoint,
@@ -4957,7 +6091,14 @@ function LumirEditor({
4957
6091
  // 확장 비활성: 비디오/오디오/파일 제어
4958
6092
  disableExtensions: disabledExtensions,
4959
6093
  _tiptapOptions: {
4960
- extensions: [VerticalAlignmentExtension]
6094
+ extensions: [
6095
+ VerticalAlignmentExtension,
6096
+ // 행 높이 attr 등록은 항상(저장된 높이 렌더), 드래그 리사이즈 UI는
6097
+ // tableHandles prop으로 게이트(기존 grip 컨트롤러와 동일 게이트).
6098
+ RowHeightExtension.configure({ resizable: tableHandles }),
6099
+ // 표 블록 정렬(좌/가운데/우) attr.
6100
+ TableAlignmentExtension
6101
+ ]
4961
6102
  },
4962
6103
  placeholders: placeholder ? { default: placeholder, emptyDocument: placeholder } : void 0,
4963
6104
  tabBehavior,
@@ -5133,12 +6274,23 @@ function LumirEditor({
5133
6274
  memoizedS3Upload,
5134
6275
  allowVideoUpload,
5135
6276
  linkPreview?.apiEndpoint,
5136
- placeholder
6277
+ placeholder,
6278
+ // tableHandles 변경 시 RowHeightExtension의 resizable 게이트가 반영되도록 재생성
6279
+ tableHandles
5137
6280
  ]
5138
6281
  );
5139
6282
  if (editor && linkPreview?.apiEndpoint) {
5140
6283
  editor._linkPreviewApiEndpoint = linkPreview.apiEndpoint;
5141
6284
  }
6285
+ if (editor) {
6286
+ try {
6287
+ const view = editor.prosemirrorView;
6288
+ if (view) {
6289
+ view.__lumirEditor = editor;
6290
+ }
6291
+ } catch {
6292
+ }
6293
+ }
5142
6294
  useEffect11(() => {
5143
6295
  if (editor) {
5144
6296
  editor.isEditable = editable;
@@ -5161,7 +6313,15 @@ function LumirEditor({
5161
6313
  if (!editor || !onContentChange) return;
5162
6314
  const handleContentChange = () => {
5163
6315
  const blocks = editor.topLevelBlocks;
5164
- const patched = lowerFontSize(injectVerticalAlignment(blocks, editor));
6316
+ const patched = lowerFontSize(
6317
+ injectTableBlockAttrs(
6318
+ injectTableCellAttrs(blocks, editor, [
6319
+ "verticalAlignment",
6320
+ "rowHeight"
6321
+ ]),
6322
+ editor
6323
+ )
6324
+ );
5165
6325
  onContentChange(patched);
5166
6326
  };
5167
6327
  return editor.onEditorContentChange(handleContentChange);
@@ -5317,20 +6477,20 @@ function LumirEditor({
5317
6477
  el.removeEventListener("drop", handleDrop, { capture: true });
5318
6478
  };
5319
6479
  }, [editor, allowVideoUpload]);
5320
- const computedSideMenu = useMemo7(() => {
6480
+ const computedSideMenu = useMemo8(() => {
5321
6481
  return sideMenuAddButton ? sideMenu : false;
5322
6482
  }, [sideMenuAddButton, sideMenu]);
5323
- const DragHandleOnlySideMenu = useMemo7(() => {
5324
- return (props) => /* @__PURE__ */ jsx25(BlockSideMenu, { ...props, children: /* @__PURE__ */ jsx25(DragHandleButton, { ...props }) });
6483
+ const DragHandleOnlySideMenu = useMemo8(() => {
6484
+ return (props) => /* @__PURE__ */ jsx27(BlockSideMenu, { ...props, children: /* @__PURE__ */ jsx27(DragHandleButton, { ...props, dragHandleMenu: LumirDragHandleMenu }) });
5325
6485
  }, []);
5326
- return /* @__PURE__ */ jsxs17(
6486
+ return /* @__PURE__ */ jsxs19(
5327
6487
  "div",
5328
6488
  {
5329
6489
  className: cn("lumirEditor", className),
5330
6490
  style: { position: "relative", display: "flex", flexDirection: "column" },
5331
6491
  children: [
5332
- floatingMenu && editor && /* @__PURE__ */ jsxs17(Fragment7, { children: [
5333
- /* @__PURE__ */ jsx25(
6492
+ floatingMenu && editor && /* @__PURE__ */ jsxs19(Fragment8, { children: [
6493
+ /* @__PURE__ */ jsx27(
5334
6494
  "input",
5335
6495
  {
5336
6496
  ref: floatingMenuFileInputRef,
@@ -5401,7 +6561,7 @@ function LumirEditor({
5401
6561
  }
5402
6562
  }
5403
6563
  ),
5404
- /* @__PURE__ */ jsx25(
6564
+ /* @__PURE__ */ jsx27(
5405
6565
  FloatingMenu,
5406
6566
  {
5407
6567
  editor,
@@ -5433,7 +6593,7 @@ function LumirEditor({
5433
6593
  }
5434
6594
  )
5435
6595
  ] }),
5436
- /* @__PURE__ */ jsxs17(
6596
+ /* @__PURE__ */ jsxs19(
5437
6597
  BlockNoteView,
5438
6598
  {
5439
6599
  editor,
@@ -5448,19 +6608,19 @@ function LumirEditor({
5448
6608
  tableHandles: false,
5449
6609
  onSelectionChange,
5450
6610
  children: [
5451
- tableHandles && /* @__PURE__ */ jsx25(LumirTableHandlesController, {}),
5452
- formattingToolbar && /* @__PURE__ */ jsx25(
6611
+ tableHandles && /* @__PURE__ */ jsx27(LumirTableHandlesController, {}),
6612
+ formattingToolbar && /* @__PURE__ */ jsx27(
5453
6613
  FormattingToolbarController,
5454
6614
  {
5455
6615
  formattingToolbar: CustomFormattingToolbar
5456
6616
  }
5457
6617
  ),
5458
- linkToolbar && (linkPreview?.apiEndpoint ? /* @__PURE__ */ jsx25(LinkToolbarController, { linkToolbar: CustomLinkToolbar }) : /* @__PURE__ */ jsx25(LinkToolbarController, {})),
5459
- /* @__PURE__ */ jsx25(
6618
+ linkToolbar && (linkPreview?.apiEndpoint ? /* @__PURE__ */ jsx27(LinkToolbarController, { linkToolbar: CustomLinkToolbar }) : /* @__PURE__ */ jsx27(LinkToolbarController, {})),
6619
+ /* @__PURE__ */ jsx27(
5460
6620
  SuggestionMenuController,
5461
6621
  {
5462
6622
  triggerCharacter: "/",
5463
- getItems: useCallback20(
6623
+ getItems: useCallback21(
5464
6624
  async (query) => {
5465
6625
  const items = getDefaultReactSlashMenuItems(editor);
5466
6626
  const filtered = items.filter((item) => {
@@ -5504,7 +6664,7 @@ function LumirEditor({
5504
6664
  },
5505
6665
  aliases: ["html", "preview", "\uC6F9", "\uC6F9\uD398\uC774\uC9C0"],
5506
6666
  group: "Embeds",
5507
- icon: /* @__PURE__ */ jsxs17(
6667
+ icon: /* @__PURE__ */ jsxs19(
5508
6668
  "svg",
5509
6669
  {
5510
6670
  width: "18",
@@ -5516,14 +6676,40 @@ function LumirEditor({
5516
6676
  strokeLinecap: "round",
5517
6677
  strokeLinejoin: "round",
5518
6678
  children: [
5519
- /* @__PURE__ */ jsx25("polyline", { points: "16 18 22 12 16 6" }),
5520
- /* @__PURE__ */ jsx25("polyline", { points: "8 6 2 12 8 18" })
6679
+ /* @__PURE__ */ jsx27("polyline", { points: "16 18 22 12 16 6" }),
6680
+ /* @__PURE__ */ jsx27("polyline", { points: "8 6 2 12 8 18" })
5521
6681
  ]
5522
6682
  }
5523
6683
  ),
5524
6684
  subtext: "HTML \uD30C\uC77C\uC744 \uBBF8\uB9AC\uBCF4\uAE30\uB85C \uC0BD\uC785"
5525
6685
  };
5526
- const allItems = [...filtered, htmlPreviewItem];
6686
+ const columnItem = {
6687
+ title: "2\uB2E8 \uCEEC\uB7FC",
6688
+ onItemClick: () => {
6689
+ insertTwoColumns(editor);
6690
+ },
6691
+ aliases: ["columns", "column", "2col", "\uB2E8", "\uCEEC\uB7FC", "\uB2E4\uB2E8", "\uBD84\uD560"],
6692
+ group: "Basic blocks",
6693
+ icon: /* @__PURE__ */ jsxs19(
6694
+ "svg",
6695
+ {
6696
+ width: "18",
6697
+ height: "18",
6698
+ viewBox: "0 0 24 24",
6699
+ fill: "none",
6700
+ stroke: "currentColor",
6701
+ strokeWidth: "2",
6702
+ strokeLinecap: "round",
6703
+ strokeLinejoin: "round",
6704
+ children: [
6705
+ /* @__PURE__ */ jsx27("rect", { x: "3", y: "4", width: "7", height: "16", rx: "1" }),
6706
+ /* @__PURE__ */ jsx27("rect", { x: "14", y: "4", width: "7", height: "16", rx: "1" })
6707
+ ]
6708
+ }
6709
+ ),
6710
+ subtext: "\uBE14\uB85D\uC744 \uC88C\uC6B0 2\uB2E8\uC73C\uB85C \uBC30\uCE58"
6711
+ };
6712
+ const allItems = [...filtered, htmlPreviewItem, columnItem];
5527
6713
  if (linkPreview?.apiEndpoint) {
5528
6714
  allItems.push({
5529
6715
  title: "Link Preview",
@@ -5542,7 +6728,7 @@ function LumirEditor({
5542
6728
  "\uD504\uB9AC\uBDF0"
5543
6729
  ],
5544
6730
  group: "Embeds",
5545
- icon: /* @__PURE__ */ jsxs17(
6731
+ icon: /* @__PURE__ */ jsxs19(
5546
6732
  "svg",
5547
6733
  {
5548
6734
  width: "18",
@@ -5554,8 +6740,8 @@ function LumirEditor({
5554
6740
  strokeLinecap: "round",
5555
6741
  strokeLinejoin: "round",
5556
6742
  children: [
5557
- /* @__PURE__ */ jsx25("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
5558
- /* @__PURE__ */ jsx25("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
6743
+ /* @__PURE__ */ jsx27("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
6744
+ /* @__PURE__ */ jsx27("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
5559
6745
  ]
5560
6746
  }
5561
6747
  ),
@@ -5591,21 +6777,21 @@ function LumirEditor({
5591
6777
  )
5592
6778
  }
5593
6779
  ),
5594
- !sideMenuAddButton && /* @__PURE__ */ jsx25(SideMenuController, { sideMenu: DragHandleOnlySideMenu })
6780
+ !sideMenuAddButton && /* @__PURE__ */ jsx27(SideMenuController, { sideMenu: DragHandleOnlySideMenu })
5595
6781
  ]
5596
6782
  }
5597
6783
  ),
5598
- isUploading && /* @__PURE__ */ jsxs17("div", { className: "lumirEditor-upload-overlay", children: [
5599
- /* @__PURE__ */ jsx25("div", { className: "lumirEditor-spinner" }),
5600
- uploadProgress !== null && /* @__PURE__ */ jsxs17("span", { className: "lumirEditor-upload-progress", children: [
6784
+ isUploading && /* @__PURE__ */ jsxs19("div", { className: "lumirEditor-upload-overlay", children: [
6785
+ /* @__PURE__ */ jsx27("div", { className: "lumirEditor-spinner" }),
6786
+ uploadProgress !== null && /* @__PURE__ */ jsxs19("span", { className: "lumirEditor-upload-progress", children: [
5601
6787
  uploadProgress,
5602
6788
  "%"
5603
6789
  ] })
5604
6790
  ] }),
5605
- errorMessage && /* @__PURE__ */ jsxs17("div", { className: "lumirEditor-error-toast", children: [
5606
- /* @__PURE__ */ jsx25("span", { className: "lumirEditor-error-icon", children: "\u26A0\uFE0F" }),
5607
- /* @__PURE__ */ jsx25("span", { className: "lumirEditor-error-message", children: errorMessage }),
5608
- /* @__PURE__ */ jsx25(
6791
+ errorMessage && /* @__PURE__ */ jsxs19("div", { className: "lumirEditor-error-toast", children: [
6792
+ /* @__PURE__ */ jsx27("span", { className: "lumirEditor-error-icon", children: "\u26A0\uFE0F" }),
6793
+ /* @__PURE__ */ jsx27("span", { className: "lumirEditor-error-message", children: errorMessage }),
6794
+ /* @__PURE__ */ jsx27(
5609
6795
  "button",
5610
6796
  {
5611
6797
  className: "lumirEditor-error-close",