@lumir-company/editor 0.4.16 → 0.4.18
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/README.md +22 -0
- package/dist/index.d.mts +24 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +1724 -403
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1690 -355
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +95 -0
- package/package.json +6 -2
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
|
|
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
|
|
15
|
-
useComponentsContext as
|
|
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
|
|
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",
|
|
1646
|
+
document.removeEventListener("mousemove", handleMouseMove2);
|
|
1342
1647
|
document.removeEventListener("mouseup", handleMouseUp);
|
|
1343
1648
|
};
|
|
1344
|
-
document.addEventListener("mousemove",
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
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/
|
|
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/
|
|
3059
|
-
import {
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
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 (
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
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
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
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
|
-
}
|
|
3109
|
-
const
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
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
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
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
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
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/
|
|
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__ */
|
|
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 =
|
|
3278
|
-
const editor =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
3315
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4307
|
+
icon: /* @__PURE__ */ jsx22(FontSizeIcon, { size: currentSize })
|
|
3323
4308
|
}
|
|
3324
4309
|
) }),
|
|
3325
|
-
/* @__PURE__ */
|
|
3326
|
-
/* @__PURE__ */
|
|
3327
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
3359
|
-
useComponentsContext as
|
|
4343
|
+
useBlockNoteEditor as useBlockNoteEditor5,
|
|
4344
|
+
useComponentsContext as useComponentsContext5,
|
|
3360
4345
|
useDictionary,
|
|
3361
4346
|
useEditorContentOrSelectionChange as useEditorContentOrSelectionChange2,
|
|
3362
|
-
useSelectedBlocks as
|
|
4347
|
+
useSelectedBlocks as useSelectedBlocks5
|
|
3363
4348
|
} from "@blocknote/react";
|
|
3364
|
-
import { useCallback as
|
|
3365
|
-
import { Fragment as Fragment5, jsx as
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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 =
|
|
4400
|
+
const Components = useComponentsContext5();
|
|
3416
4401
|
const dict = useDictionary();
|
|
3417
|
-
return /* @__PURE__ */
|
|
3418
|
-
props.text ? /* @__PURE__ */
|
|
3419
|
-
/* @__PURE__ */
|
|
3420
|
-
COLORS.map((color) => /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3436
|
-
/* @__PURE__ */
|
|
3437
|
-
COLORS.map((color) => /* @__PURE__ */
|
|
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__ */
|
|
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 =
|
|
3456
|
-
const editor =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
3509
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4511
|
+
/* @__PURE__ */ jsx23(
|
|
3527
4512
|
Components.Generic.Menu.Dropdown,
|
|
3528
4513
|
{
|
|
3529
4514
|
className: "bn-menu-dropdown bn-color-picker-dropdown",
|
|
3530
|
-
children: /* @__PURE__ */
|
|
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 =
|
|
3545
|
-
const editor =
|
|
3546
|
-
const selectedBlocks =
|
|
3547
|
-
const isMultiCell =
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
4569
|
+
icon: /* @__PURE__ */ jsx23(CellFillIcon, { size: 18 })
|
|
3585
4570
|
}
|
|
3586
4571
|
) }),
|
|
3587
|
-
/* @__PURE__ */
|
|
4572
|
+
/* @__PURE__ */ jsx23(
|
|
3588
4573
|
Components.Generic.Menu.Dropdown,
|
|
3589
4574
|
{
|
|
3590
4575
|
className: "bn-menu-dropdown bn-color-picker-dropdown",
|
|
3591
|
-
children: /* @__PURE__ */
|
|
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 =
|
|
3606
|
-
const editor =
|
|
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__ */
|
|
3628
|
-
/* @__PURE__ */
|
|
3629
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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 =
|
|
3656
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
3661
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
4668
|
+
import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
3684
4669
|
var CustomFormattingToolbar = () => {
|
|
3685
|
-
return /* @__PURE__ */
|
|
3686
|
-
/* @__PURE__ */
|
|
3687
|
-
/* @__PURE__ */
|
|
3688
|
-
/* @__PURE__ */
|
|
3689
|
-
/* @__PURE__ */
|
|
3690
|
-
/* @__PURE__ */
|
|
3691
|
-
/* @__PURE__ */
|
|
3692
|
-
/* @__PURE__ */
|
|
3693
|
-
/* @__PURE__ */
|
|
3694
|
-
/* @__PURE__ */
|
|
3695
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4687
|
+
/* @__PURE__ */ jsx24(
|
|
3703
4688
|
BasicTextStyleButton,
|
|
3704
4689
|
{
|
|
3705
4690
|
basicTextStyle: "underline"
|
|
3706
4691
|
},
|
|
3707
4692
|
"underlineStyleButton"
|
|
3708
4693
|
),
|
|
3709
|
-
/* @__PURE__ */
|
|
4694
|
+
/* @__PURE__ */ jsx24(
|
|
3710
4695
|
BasicTextStyleButton,
|
|
3711
4696
|
{
|
|
3712
4697
|
basicTextStyle: "strike"
|
|
3713
4698
|
},
|
|
3714
4699
|
"strikeStyleButton"
|
|
3715
4700
|
),
|
|
3716
|
-
/* @__PURE__ */
|
|
3717
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3725
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4717
|
+
/* @__PURE__ */ jsx24(
|
|
3733
4718
|
VerticalAlignButton,
|
|
3734
4719
|
{
|
|
3735
4720
|
verticalAlignment: "middle"
|
|
3736
4721
|
},
|
|
3737
4722
|
"verticalAlignMiddle"
|
|
3738
4723
|
),
|
|
3739
|
-
/* @__PURE__ */
|
|
4724
|
+
/* @__PURE__ */ jsx24(
|
|
3740
4725
|
VerticalAlignButton,
|
|
3741
4726
|
{
|
|
3742
4727
|
verticalAlignment: "bottom"
|
|
3743
4728
|
},
|
|
3744
4729
|
"verticalAlignBottom"
|
|
3745
4730
|
),
|
|
3746
|
-
/* @__PURE__ */
|
|
3747
|
-
/* @__PURE__ */
|
|
3748
|
-
/* @__PURE__ */
|
|
3749
|
-
/* @__PURE__ */
|
|
3750
|
-
/* @__PURE__ */
|
|
3751
|
-
/* @__PURE__ */
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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,10 @@ function LumirTableHandlesController() {
|
|
|
3839
4901
|
const frozenRef = useRef11(false);
|
|
3840
4902
|
const menuOpenRef = useRef11(false);
|
|
3841
4903
|
const draggingRef = useRef11(false);
|
|
3842
|
-
|
|
4904
|
+
useEffect10(() => {
|
|
4905
|
+
editor.__lumirActiveTableId = focused?.block?.id ?? null;
|
|
4906
|
+
}, [editor, focused]);
|
|
4907
|
+
const recompute = useCallback20(() => {
|
|
3843
4908
|
if (frozenRef.current) {
|
|
3844
4909
|
return;
|
|
3845
4910
|
}
|
|
@@ -3928,7 +4993,13 @@ function LumirTableHandlesController() {
|
|
|
3928
4993
|
overlayEl.style.height = `${bottom - top}px`;
|
|
3929
4994
|
};
|
|
3930
4995
|
update();
|
|
3931
|
-
|
|
4996
|
+
const stopAutoUpdate = autoUpdate2(f.cellEl, overlayEl, update);
|
|
4997
|
+
const ro = new ResizeObserver(update);
|
|
4998
|
+
ro.observe(f.tbodyEl);
|
|
4999
|
+
return () => {
|
|
5000
|
+
stopAutoUpdate();
|
|
5001
|
+
ro.disconnect();
|
|
5002
|
+
};
|
|
3932
5003
|
}, [focused, overlayEl, openMenu]);
|
|
3933
5004
|
const cellEl = focused?.cellEl ?? null;
|
|
3934
5005
|
const tbodyEl = focused?.tbodyEl ?? null;
|
|
@@ -3950,13 +5021,13 @@ function LumirTableHandlesController() {
|
|
|
3950
5021
|
coreState?.showAddOrRemoveRowsButton || false,
|
|
3951
5022
|
coreState?.referencePosTable || null
|
|
3952
5023
|
);
|
|
3953
|
-
const onStartExtend =
|
|
5024
|
+
const onStartExtend = useCallback20(() => {
|
|
3954
5025
|
editor.tableHandles?.freezeHandles();
|
|
3955
5026
|
}, [editor]);
|
|
3956
|
-
const onEndExtend =
|
|
5027
|
+
const onEndExtend = useCallback20(() => {
|
|
3957
5028
|
editor.tableHandles?.unfreezeHandles();
|
|
3958
5029
|
}, [editor]);
|
|
3959
|
-
const menuHandlers =
|
|
5030
|
+
const menuHandlers = useMemo7(() => {
|
|
3960
5031
|
const mk = (kind) => ({
|
|
3961
5032
|
freeze: () => {
|
|
3962
5033
|
menuOpenRef.current = true;
|
|
@@ -3974,10 +5045,10 @@ function LumirTableHandlesController() {
|
|
|
3974
5045
|
});
|
|
3975
5046
|
return { col: mk("col"), row: mk("row"), cell: mk("cell") };
|
|
3976
5047
|
}, [editor, recompute]);
|
|
3977
|
-
const onGutterPointerDown =
|
|
5048
|
+
const onGutterPointerDown = useCallback20(() => {
|
|
3978
5049
|
frozenRef.current = true;
|
|
3979
5050
|
}, []);
|
|
3980
|
-
const onGutterPointerEnter =
|
|
5051
|
+
const onGutterPointerEnter = useCallback20(
|
|
3981
5052
|
(e) => {
|
|
3982
5053
|
if (e.buttons === 0 && focused) {
|
|
3983
5054
|
syncCoreHoverToFocusedCell(focused.cellEl);
|
|
@@ -3985,7 +5056,7 @@ function LumirTableHandlesController() {
|
|
|
3985
5056
|
},
|
|
3986
5057
|
[focused]
|
|
3987
5058
|
);
|
|
3988
|
-
const makeDragStart =
|
|
5059
|
+
const makeDragStart = useCallback20(
|
|
3989
5060
|
(dir) => (e) => {
|
|
3990
5061
|
draggingRef.current = true;
|
|
3991
5062
|
frozenRef.current = true;
|
|
@@ -3997,19 +5068,19 @@ function LumirTableHandlesController() {
|
|
|
3997
5068
|
},
|
|
3998
5069
|
[editor]
|
|
3999
5070
|
);
|
|
4000
|
-
const onDragEnd =
|
|
5071
|
+
const onDragEnd = useCallback20(() => {
|
|
4001
5072
|
editor.tableHandles?.dragEnd();
|
|
4002
5073
|
draggingRef.current = false;
|
|
4003
5074
|
frozenRef.current = false;
|
|
4004
5075
|
recompute();
|
|
4005
5076
|
}, [editor, recompute]);
|
|
4006
|
-
const noop =
|
|
5077
|
+
const noop = useCallback20(() => {
|
|
4007
5078
|
}, []);
|
|
4008
|
-
return /* @__PURE__ */
|
|
4009
|
-
/* @__PURE__ */
|
|
4010
|
-
th && focused && menuContainerRef && /* @__PURE__ */
|
|
4011
|
-
/* @__PURE__ */
|
|
4012
|
-
colHandle.isMounted && /* @__PURE__ */
|
|
5079
|
+
return /* @__PURE__ */ jsxs18(Fragment7, { children: [
|
|
5080
|
+
/* @__PURE__ */ jsx26("div", { ref: setMenuContainerRef }),
|
|
5081
|
+
th && focused && menuContainerRef && /* @__PURE__ */ jsxs18(FloatingPortal, { root: focused.widgetContainer, children: [
|
|
5082
|
+
/* @__PURE__ */ jsx26("div", { ref: setOverlayEl, className: "lumir-tbl-cell-focus" }),
|
|
5083
|
+
colHandle.isMounted && /* @__PURE__ */ jsxs18(
|
|
4013
5084
|
"div",
|
|
4014
5085
|
{
|
|
4015
5086
|
ref: colHandle.ref,
|
|
@@ -4018,8 +5089,8 @@ function LumirTableHandlesController() {
|
|
|
4018
5089
|
onPointerEnter: onGutterPointerEnter,
|
|
4019
5090
|
onPointerDown: onGutterPointerDown,
|
|
4020
5091
|
children: [
|
|
4021
|
-
/* @__PURE__ */
|
|
4022
|
-
/* @__PURE__ */
|
|
5092
|
+
/* @__PURE__ */ jsx26("span", { className: "lumir-tbl-gutter" }),
|
|
5093
|
+
/* @__PURE__ */ jsx26("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ jsx26(
|
|
4023
5094
|
TableHandle,
|
|
4024
5095
|
{
|
|
4025
5096
|
editor,
|
|
@@ -4038,7 +5109,7 @@ function LumirTableHandlesController() {
|
|
|
4038
5109
|
]
|
|
4039
5110
|
}
|
|
4040
5111
|
),
|
|
4041
|
-
rowHandle.isMounted && /* @__PURE__ */
|
|
5112
|
+
rowHandle.isMounted && /* @__PURE__ */ jsxs18(
|
|
4042
5113
|
"div",
|
|
4043
5114
|
{
|
|
4044
5115
|
ref: rowHandle.ref,
|
|
@@ -4047,8 +5118,8 @@ function LumirTableHandlesController() {
|
|
|
4047
5118
|
onPointerEnter: onGutterPointerEnter,
|
|
4048
5119
|
onPointerDown: onGutterPointerDown,
|
|
4049
5120
|
children: [
|
|
4050
|
-
/* @__PURE__ */
|
|
4051
|
-
/* @__PURE__ */
|
|
5121
|
+
/* @__PURE__ */ jsx26("span", { className: "lumir-tbl-gutter" }),
|
|
5122
|
+
/* @__PURE__ */ jsx26("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ jsx26(
|
|
4052
5123
|
TableHandle,
|
|
4053
5124
|
{
|
|
4054
5125
|
editor,
|
|
@@ -4067,7 +5138,7 @@ function LumirTableHandlesController() {
|
|
|
4067
5138
|
]
|
|
4068
5139
|
}
|
|
4069
5140
|
),
|
|
4070
|
-
cellHandle.isMounted && openMenu !== "col" && openMenu !== "row" && /* @__PURE__ */
|
|
5141
|
+
cellHandle.isMounted && openMenu !== "col" && openMenu !== "row" && /* @__PURE__ */ jsxs18(
|
|
4071
5142
|
"div",
|
|
4072
5143
|
{
|
|
4073
5144
|
ref: cellHandle.ref,
|
|
@@ -4075,8 +5146,8 @@ function LumirTableHandlesController() {
|
|
|
4075
5146
|
className: "lumir-tbl-gutter-wrap lumir-tbl-gutter-wrap--cell" + (openMenu === "cell" ? " lumir-tbl-gutter-wrap--active" : ""),
|
|
4076
5147
|
onPointerDown: onGutterPointerDown,
|
|
4077
5148
|
children: [
|
|
4078
|
-
/* @__PURE__ */
|
|
4079
|
-
/* @__PURE__ */
|
|
5149
|
+
/* @__PURE__ */ jsx26("span", { className: "lumir-tbl-gutter" }),
|
|
5150
|
+
/* @__PURE__ */ jsx26("div", { className: "lumir-tbl-grip", children: /* @__PURE__ */ jsx26(
|
|
4080
5151
|
TableCellButton,
|
|
4081
5152
|
{
|
|
4082
5153
|
editor,
|
|
@@ -4093,8 +5164,8 @@ function LumirTableHandlesController() {
|
|
|
4093
5164
|
}
|
|
4094
5165
|
)
|
|
4095
5166
|
] }),
|
|
4096
|
-
th && coreState?.widgetContainer && /* @__PURE__ */
|
|
4097
|
-
/* @__PURE__ */
|
|
5167
|
+
th && coreState?.widgetContainer && /* @__PURE__ */ jsxs18(FloatingPortal, { root: coreState.widgetContainer, children: [
|
|
5168
|
+
/* @__PURE__ */ jsx26("div", { ref: addOrRemoveRowsButton.ref, style: addOrRemoveRowsButton.style, children: /* @__PURE__ */ jsx26(
|
|
4098
5169
|
ExtendButton,
|
|
4099
5170
|
{
|
|
4100
5171
|
editor,
|
|
@@ -4104,12 +5175,12 @@ function LumirTableHandlesController() {
|
|
|
4104
5175
|
onMouseUp: onEndExtend
|
|
4105
5176
|
}
|
|
4106
5177
|
) }),
|
|
4107
|
-
/* @__PURE__ */
|
|
5178
|
+
/* @__PURE__ */ jsx26(
|
|
4108
5179
|
"div",
|
|
4109
5180
|
{
|
|
4110
5181
|
ref: addOrRemoveColumnsButton.ref,
|
|
4111
5182
|
style: addOrRemoveColumnsButton.style,
|
|
4112
|
-
children: /* @__PURE__ */
|
|
5183
|
+
children: /* @__PURE__ */ jsx26(
|
|
4113
5184
|
ExtendButton,
|
|
4114
5185
|
{
|
|
4115
5186
|
editor,
|
|
@@ -4126,15 +5197,17 @@ function LumirTableHandlesController() {
|
|
|
4126
5197
|
}
|
|
4127
5198
|
|
|
4128
5199
|
// src/utils/table-vertical-alignment.ts
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
if (
|
|
4135
|
-
|
|
5200
|
+
var CELL_ATTR_DEFAULTS = {
|
|
5201
|
+
verticalAlignment: "top",
|
|
5202
|
+
rowHeight: null
|
|
5203
|
+
};
|
|
5204
|
+
function isMeaningful2(attr, value) {
|
|
5205
|
+
if (value === null || value === void 0) {
|
|
5206
|
+
return false;
|
|
5207
|
+
}
|
|
5208
|
+
return value !== CELL_ATTR_DEFAULTS[attr];
|
|
4136
5209
|
}
|
|
4137
|
-
function
|
|
5210
|
+
function buildTableCellAttrMap(doc, attrs) {
|
|
4138
5211
|
const result = /* @__PURE__ */ new Map();
|
|
4139
5212
|
doc.descendants((node) => {
|
|
4140
5213
|
if (node.type.name === "blockContainer") {
|
|
@@ -4147,9 +5220,15 @@ function buildTableVerticalAlignmentMap(doc) {
|
|
|
4147
5220
|
if (rowNode.type.name === "tableRow") {
|
|
4148
5221
|
let colIndex = 0;
|
|
4149
5222
|
rowNode.forEach((cellNode) => {
|
|
4150
|
-
const
|
|
4151
|
-
|
|
4152
|
-
|
|
5223
|
+
const props = {};
|
|
5224
|
+
for (const attr of attrs) {
|
|
5225
|
+
const value = cellNode.attrs?.[attr];
|
|
5226
|
+
if (isMeaningful2(attr, value)) {
|
|
5227
|
+
props[attr] = value;
|
|
5228
|
+
}
|
|
5229
|
+
}
|
|
5230
|
+
if (Object.keys(props).length > 0) {
|
|
5231
|
+
cells.push({ row: rowIndex, col: colIndex, props });
|
|
4153
5232
|
}
|
|
4154
5233
|
colIndex++;
|
|
4155
5234
|
});
|
|
@@ -4165,18 +5244,21 @@ function buildTableVerticalAlignmentMap(doc) {
|
|
|
4165
5244
|
});
|
|
4166
5245
|
return result;
|
|
4167
5246
|
}
|
|
4168
|
-
function patchBlocks(blocks,
|
|
5247
|
+
function patchBlocks(blocks, cellAttrMap) {
|
|
4169
5248
|
return blocks.map((block) => {
|
|
4170
5249
|
if (block.type !== "table" || !block.id || !block.content) {
|
|
4171
5250
|
if (block.children && block.children.length > 0) {
|
|
4172
5251
|
return {
|
|
4173
5252
|
...block,
|
|
4174
|
-
children: patchBlocks(
|
|
5253
|
+
children: patchBlocks(
|
|
5254
|
+
block.children,
|
|
5255
|
+
cellAttrMap
|
|
5256
|
+
)
|
|
4175
5257
|
};
|
|
4176
5258
|
}
|
|
4177
5259
|
return block;
|
|
4178
5260
|
}
|
|
4179
|
-
const cells =
|
|
5261
|
+
const cells = cellAttrMap.get(block.id);
|
|
4180
5262
|
if (!cells || cells.length === 0) {
|
|
4181
5263
|
return block;
|
|
4182
5264
|
}
|
|
@@ -4189,11 +5271,13 @@ function patchBlocks(blocks, tableVAMap) {
|
|
|
4189
5271
|
const match = cells.find(
|
|
4190
5272
|
(c) => c.row === rowIndex && c.col === colIndex
|
|
4191
5273
|
);
|
|
4192
|
-
if (!match)
|
|
5274
|
+
if (!match) {
|
|
5275
|
+
return cell;
|
|
5276
|
+
}
|
|
4193
5277
|
if (cell && typeof cell === "object" && cell.type === "tableCell") {
|
|
4194
5278
|
return {
|
|
4195
5279
|
...cell,
|
|
4196
|
-
props: { ...cell.props,
|
|
5280
|
+
props: { ...cell.props, ...match.props }
|
|
4197
5281
|
};
|
|
4198
5282
|
}
|
|
4199
5283
|
return cell;
|
|
@@ -4206,6 +5290,77 @@ function patchBlocks(blocks, tableVAMap) {
|
|
|
4206
5290
|
};
|
|
4207
5291
|
});
|
|
4208
5292
|
}
|
|
5293
|
+
function injectTableCellAttrs(blocks, editor, attrs) {
|
|
5294
|
+
const tiptap = editor?._tiptapEditor;
|
|
5295
|
+
if (!tiptap) {
|
|
5296
|
+
return blocks;
|
|
5297
|
+
}
|
|
5298
|
+
const { doc } = tiptap.state;
|
|
5299
|
+
const cellAttrMap = buildTableCellAttrMap(doc, attrs);
|
|
5300
|
+
if (cellAttrMap.size === 0) {
|
|
5301
|
+
return blocks;
|
|
5302
|
+
}
|
|
5303
|
+
return patchBlocks(blocks, cellAttrMap);
|
|
5304
|
+
}
|
|
5305
|
+
var TABLE_BLOCK_ATTR_DEFAULTS = {
|
|
5306
|
+
tableAlignment: "left"
|
|
5307
|
+
};
|
|
5308
|
+
function buildTableBlockAttrMap(doc, attrs) {
|
|
5309
|
+
const result = /* @__PURE__ */ new Map();
|
|
5310
|
+
doc.descendants((node) => {
|
|
5311
|
+
if (node.type.name === "blockContainer") {
|
|
5312
|
+
const blockId = node.attrs?.id;
|
|
5313
|
+
const contentNode = node.firstChild;
|
|
5314
|
+
if (blockId && contentNode?.type.name === "table") {
|
|
5315
|
+
const props = {};
|
|
5316
|
+
for (const attr of attrs) {
|
|
5317
|
+
const value = contentNode.attrs?.[attr];
|
|
5318
|
+
if (value !== null && value !== void 0 && value !== TABLE_BLOCK_ATTR_DEFAULTS[attr]) {
|
|
5319
|
+
props[attr] = value;
|
|
5320
|
+
}
|
|
5321
|
+
}
|
|
5322
|
+
if (Object.keys(props).length > 0) {
|
|
5323
|
+
result.set(blockId, props);
|
|
5324
|
+
}
|
|
5325
|
+
}
|
|
5326
|
+
return false;
|
|
5327
|
+
}
|
|
5328
|
+
return void 0;
|
|
5329
|
+
});
|
|
5330
|
+
return result;
|
|
5331
|
+
}
|
|
5332
|
+
function patchTableBlockProps(blocks, attrMap) {
|
|
5333
|
+
return blocks.map((block) => {
|
|
5334
|
+
if (block.type === "table" && block.id && attrMap.has(block.id)) {
|
|
5335
|
+
return {
|
|
5336
|
+
...block,
|
|
5337
|
+
props: { ...block.props, ...attrMap.get(block.id) }
|
|
5338
|
+
};
|
|
5339
|
+
}
|
|
5340
|
+
if (block.children && block.children.length > 0) {
|
|
5341
|
+
return {
|
|
5342
|
+
...block,
|
|
5343
|
+
children: patchTableBlockProps(
|
|
5344
|
+
block.children,
|
|
5345
|
+
attrMap
|
|
5346
|
+
)
|
|
5347
|
+
};
|
|
5348
|
+
}
|
|
5349
|
+
return block;
|
|
5350
|
+
});
|
|
5351
|
+
}
|
|
5352
|
+
function injectTableBlockAttrs(blocks, editor) {
|
|
5353
|
+
const tiptap = editor?._tiptapEditor;
|
|
5354
|
+
if (!tiptap) {
|
|
5355
|
+
return blocks;
|
|
5356
|
+
}
|
|
5357
|
+
const { doc } = tiptap.state;
|
|
5358
|
+
const attrMap = buildTableBlockAttrMap(doc, ["tableAlignment"]);
|
|
5359
|
+
if (attrMap.size === 0) {
|
|
5360
|
+
return blocks;
|
|
5361
|
+
}
|
|
5362
|
+
return patchTableBlockProps(blocks, attrMap);
|
|
5363
|
+
}
|
|
4209
5364
|
|
|
4210
5365
|
// src/utils/font-size-serialization.ts
|
|
4211
5366
|
function mapPreservingRef(arr, fn) {
|
|
@@ -4291,6 +5446,140 @@ function liftFontSize(blocks) {
|
|
|
4291
5446
|
return mapPreservingRef(blocks, (b) => mapBlock(b, "lift"));
|
|
4292
5447
|
}
|
|
4293
5448
|
|
|
5449
|
+
// src/utils/table-delete.ts
|
|
5450
|
+
import { CellSelection, TableMap as TableMap2, deleteRow } from "prosemirror-tables";
|
|
5451
|
+
function measureRowHeights(view, tablePos) {
|
|
5452
|
+
try {
|
|
5453
|
+
const at = view?.domAtPos?.(tablePos + 1);
|
|
5454
|
+
let el = at?.node;
|
|
5455
|
+
if (el && el.nodeType === 3) el = el.parentElement;
|
|
5456
|
+
const tableEl = el?.closest?.("table") ?? null;
|
|
5457
|
+
const body = tableEl?.tBodies?.[0];
|
|
5458
|
+
if (!body) return null;
|
|
5459
|
+
return Array.from(body.rows).map(
|
|
5460
|
+
(tr) => Math.round(tr.getBoundingClientRect().height)
|
|
5461
|
+
);
|
|
5462
|
+
} catch {
|
|
5463
|
+
return null;
|
|
5464
|
+
}
|
|
5465
|
+
}
|
|
5466
|
+
function buildDeleteColumnTr(state, tablePos, col, rowPx) {
|
|
5467
|
+
const table = state.doc.nodeAt(tablePos);
|
|
5468
|
+
if (!table || table.type.name !== "table") return null;
|
|
5469
|
+
const map = TableMap2.get(table);
|
|
5470
|
+
const W = map.width;
|
|
5471
|
+
const H = map.height;
|
|
5472
|
+
if (col < 0 || col >= W || W <= 1) return null;
|
|
5473
|
+
const cells = [];
|
|
5474
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5475
|
+
for (let r = 0; r < H; r++) {
|
|
5476
|
+
for (let c = 0; c < W; c++) {
|
|
5477
|
+
const pos = map.map[r * W + c];
|
|
5478
|
+
if (seen.has(pos)) continue;
|
|
5479
|
+
seen.add(pos);
|
|
5480
|
+
const node = table.nodeAt(pos);
|
|
5481
|
+
if (!node) continue;
|
|
5482
|
+
cells.push({
|
|
5483
|
+
node,
|
|
5484
|
+
top: r,
|
|
5485
|
+
left: c,
|
|
5486
|
+
rowspan: node.attrs.rowspan ?? 1,
|
|
5487
|
+
colspan: node.attrs.colspan ?? 1
|
|
5488
|
+
});
|
|
5489
|
+
}
|
|
5490
|
+
}
|
|
5491
|
+
const spansCol = (c) => c.left <= col && col < c.left + c.colspan;
|
|
5492
|
+
const isDropped = (c) => spansCol(c) && c.colspan === 1;
|
|
5493
|
+
const survivingByRow = new Array(H).fill(0);
|
|
5494
|
+
for (const c of cells) if (!isDropped(c)) survivingByRow[c.top]++;
|
|
5495
|
+
const rowDies = survivingByRow.map((n) => n === 0);
|
|
5496
|
+
const newRowIndex = [];
|
|
5497
|
+
let ni = 0;
|
|
5498
|
+
for (let r = 0; r < H; r++) newRowIndex[r] = rowDies[r] ? -1 : ni++;
|
|
5499
|
+
const newH = ni;
|
|
5500
|
+
if (newH === 0) return null;
|
|
5501
|
+
const newRows = Array.from({ length: newH }, () => []);
|
|
5502
|
+
for (const c of cells) {
|
|
5503
|
+
if (isDropped(c)) continue;
|
|
5504
|
+
const newColspan = c.colspan - (spansCol(c) ? 1 : 0);
|
|
5505
|
+
let dyingWithin = 0;
|
|
5506
|
+
for (let r = c.top; r < c.top + c.rowspan; r++) if (rowDies[r]) dyingWithin++;
|
|
5507
|
+
const newRowspan = Math.max(1, c.rowspan - dyingWithin);
|
|
5508
|
+
const attrs = { ...c.node.attrs, colspan: newColspan, rowspan: newRowspan };
|
|
5509
|
+
if (spansCol(c) && Array.isArray(attrs.colwidth) && attrs.colwidth.length) {
|
|
5510
|
+
const cw = attrs.colwidth.slice();
|
|
5511
|
+
cw.splice(col - c.left, 1);
|
|
5512
|
+
attrs.colwidth = cw.some((w) => w > 0) ? cw : null;
|
|
5513
|
+
}
|
|
5514
|
+
if (dyingWithin > 0 && rowPx) {
|
|
5515
|
+
let sum = 0;
|
|
5516
|
+
let ok = true;
|
|
5517
|
+
for (let r = c.top; r < c.top + c.rowspan; r++) {
|
|
5518
|
+
if (typeof rowPx[r] !== "number") {
|
|
5519
|
+
ok = false;
|
|
5520
|
+
break;
|
|
5521
|
+
}
|
|
5522
|
+
sum += rowPx[r];
|
|
5523
|
+
}
|
|
5524
|
+
if (ok && sum > 0) attrs.rowHeight = Math.round(sum);
|
|
5525
|
+
}
|
|
5526
|
+
const target = newRowIndex[c.top];
|
|
5527
|
+
if (target >= 0) newRows[target].push(c.node.type.create(attrs, c.node.content));
|
|
5528
|
+
}
|
|
5529
|
+
const rowType = table.child(0)?.type;
|
|
5530
|
+
if (!rowType) return null;
|
|
5531
|
+
const rowNodes = newRows.map((rowCells) => rowType.create(null, rowCells));
|
|
5532
|
+
const newTable = table.type.create(table.attrs, rowNodes);
|
|
5533
|
+
const tr = state.tr;
|
|
5534
|
+
tr.replaceWith(tablePos, tablePos + table.nodeSize, newTable);
|
|
5535
|
+
return tr.docChanged ? tr : null;
|
|
5536
|
+
}
|
|
5537
|
+
function removeFocusedRowOrColumn(editor, index, direction) {
|
|
5538
|
+
const tiptap = editor?._tiptapEditor;
|
|
5539
|
+
if (!tiptap) return false;
|
|
5540
|
+
const { state } = tiptap;
|
|
5541
|
+
let tablePos = -1;
|
|
5542
|
+
const activeId = editor?.__lumirActiveTableId;
|
|
5543
|
+
if (activeId) {
|
|
5544
|
+
const p = findTableNodePos(tiptap, activeId);
|
|
5545
|
+
if (p >= 0 && state.doc.nodeAt(p)?.type.name === "table") tablePos = p;
|
|
5546
|
+
}
|
|
5547
|
+
if (tablePos < 0) {
|
|
5548
|
+
const $from = state.selection.$from;
|
|
5549
|
+
for (let d = $from.depth; d > 0; d--) {
|
|
5550
|
+
if ($from.node(d).type.name === "table") {
|
|
5551
|
+
tablePos = $from.before(d);
|
|
5552
|
+
break;
|
|
5553
|
+
}
|
|
5554
|
+
}
|
|
5555
|
+
}
|
|
5556
|
+
if (tablePos < 0) {
|
|
5557
|
+
const vp = editor?.tableHandles?.view?.tablePos;
|
|
5558
|
+
if (typeof vp === "number" && state.doc.nodeAt(vp)?.type.name === "table") {
|
|
5559
|
+
tablePos = vp;
|
|
5560
|
+
}
|
|
5561
|
+
}
|
|
5562
|
+
if (tablePos < 0) return false;
|
|
5563
|
+
try {
|
|
5564
|
+
if (direction === "column") {
|
|
5565
|
+
const rowPx = measureRowHeights(tiptap.view, tablePos);
|
|
5566
|
+
const tr = buildDeleteColumnTr(state, tablePos, index, rowPx);
|
|
5567
|
+
if (!tr) return false;
|
|
5568
|
+
tiptap.view.dispatch(tr);
|
|
5569
|
+
return true;
|
|
5570
|
+
}
|
|
5571
|
+
const tableInside = state.doc.resolve(tablePos + 1);
|
|
5572
|
+
const rowStart = state.doc.resolve(tableInside.posAtIndex(index) + 1);
|
|
5573
|
+
const cellPos = state.doc.resolve(rowStart.posAtIndex(0));
|
|
5574
|
+
const selState = state.apply(
|
|
5575
|
+
state.tr.setSelection(new CellSelection(cellPos))
|
|
5576
|
+
);
|
|
5577
|
+
return deleteRow(selState, (tr) => tiptap.view.dispatch(tr));
|
|
5578
|
+
} catch {
|
|
5579
|
+
return false;
|
|
5580
|
+
}
|
|
5581
|
+
}
|
|
5582
|
+
|
|
4294
5583
|
// src/utils/excel-paste.ts
|
|
4295
5584
|
var NAMED_COLORS = {
|
|
4296
5585
|
black: "#000000",
|
|
@@ -4520,26 +5809,8 @@ function normalizeExcelTableHtml(html) {
|
|
|
4520
5809
|
}
|
|
4521
5810
|
}
|
|
4522
5811
|
|
|
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
5812
|
// src/components/LumirEditor.tsx
|
|
4542
|
-
import { Fragment as
|
|
5813
|
+
import { Fragment as Fragment8, jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
4543
5814
|
var DEBUG_LOG = (loc, msg, data) => {
|
|
4544
5815
|
const p = fetch("http://127.0.0.1:7686/ingest/1f8ee1c5-0cf0-4ae7-91ed-5ea7ed17130a", {
|
|
4545
5816
|
method: "POST",
|
|
@@ -4770,9 +6041,9 @@ var findBlockWithLink = (blocks, targetUrl) => {
|
|
|
4770
6041
|
return null;
|
|
4771
6042
|
};
|
|
4772
6043
|
var ConvertToPreviewButton = ({ url }) => {
|
|
4773
|
-
const editor =
|
|
4774
|
-
const Components =
|
|
4775
|
-
return /* @__PURE__ */
|
|
6044
|
+
const editor = useBlockNoteEditor8();
|
|
6045
|
+
const Components = useComponentsContext7();
|
|
6046
|
+
return /* @__PURE__ */ jsx27(
|
|
4776
6047
|
Components.LinkToolbar.Button,
|
|
4777
6048
|
{
|
|
4778
6049
|
className: "bn-button",
|
|
@@ -4791,29 +6062,29 @@ var ConvertToPreviewButton = ({ url }) => {
|
|
|
4791
6062
|
console.error("Convert to link preview failed:", err);
|
|
4792
6063
|
}
|
|
4793
6064
|
},
|
|
4794
|
-
icon: /* @__PURE__ */
|
|
4795
|
-
/* @__PURE__ */
|
|
4796
|
-
/* @__PURE__ */
|
|
4797
|
-
/* @__PURE__ */
|
|
6065
|
+
icon: /* @__PURE__ */ jsxs19("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
6066
|
+
/* @__PURE__ */ jsx27("rect", { x: "1", y: "3", width: "14", height: "10", rx: "2", stroke: "currentColor", strokeWidth: "1.5", fill: "none" }),
|
|
6067
|
+
/* @__PURE__ */ jsx27("line", { x1: "1", y1: "9", x2: "15", y2: "9", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
6068
|
+
/* @__PURE__ */ jsx27("circle", { cx: "5", cy: "6.5", r: "1.5", stroke: "currentColor", strokeWidth: "1", fill: "none" })
|
|
4798
6069
|
] })
|
|
4799
6070
|
}
|
|
4800
6071
|
);
|
|
4801
6072
|
};
|
|
4802
6073
|
var CustomLinkToolbar = (props) => {
|
|
4803
|
-
const editor =
|
|
4804
|
-
const Components =
|
|
6074
|
+
const editor = useBlockNoteEditor8();
|
|
6075
|
+
const Components = useComponentsContext7();
|
|
4805
6076
|
const hasLinkPreview = !!editor?._linkPreviewApiEndpoint;
|
|
4806
|
-
return /* @__PURE__ */
|
|
6077
|
+
return /* @__PURE__ */ jsxs19(
|
|
4807
6078
|
Components.LinkToolbar.Root,
|
|
4808
6079
|
{
|
|
4809
6080
|
className: "bn-toolbar bn-link-toolbar",
|
|
4810
6081
|
onMouseEnter: props.stopHideTimer,
|
|
4811
6082
|
onMouseLeave: props.startHideTimer,
|
|
4812
6083
|
children: [
|
|
4813
|
-
/* @__PURE__ */
|
|
4814
|
-
/* @__PURE__ */
|
|
4815
|
-
/* @__PURE__ */
|
|
4816
|
-
hasLinkPreview && /* @__PURE__ */
|
|
6084
|
+
/* @__PURE__ */ jsx27(EditLinkButton, { url: props.url, text: props.text, editLink: props.editLink }),
|
|
6085
|
+
/* @__PURE__ */ jsx27(OpenLinkButton, { url: props.url }),
|
|
6086
|
+
/* @__PURE__ */ jsx27(DeleteLinkButton, { deleteLink: props.deleteLink }),
|
|
6087
|
+
hasLinkPreview && /* @__PURE__ */ jsx27(ConvertToPreviewButton, { url: props.url })
|
|
4817
6088
|
]
|
|
4818
6089
|
}
|
|
4819
6090
|
);
|
|
@@ -4863,7 +6134,7 @@ function LumirEditor({
|
|
|
4863
6134
|
const floatingMenuFileInputRef = useRef12(null);
|
|
4864
6135
|
const floatingMenuBlockRef = useRef12(null);
|
|
4865
6136
|
const floatingMenuUploadStartTimeRef = useRef12(0);
|
|
4866
|
-
const handleError =
|
|
6137
|
+
const handleError = useCallback21(
|
|
4867
6138
|
(error) => {
|
|
4868
6139
|
onError?.(error);
|
|
4869
6140
|
setErrorMessage(error.getUserMessage());
|
|
@@ -4871,12 +6142,12 @@ function LumirEditor({
|
|
|
4871
6142
|
},
|
|
4872
6143
|
[onError]
|
|
4873
6144
|
);
|
|
4874
|
-
const validatedContent =
|
|
6145
|
+
const validatedContent = useMemo8(() => {
|
|
4875
6146
|
return liftFontSize(
|
|
4876
6147
|
ContentUtils.validateContent(initialContent, initialEmptyBlocks)
|
|
4877
6148
|
);
|
|
4878
6149
|
}, [initialContent, initialEmptyBlocks]);
|
|
4879
|
-
const tableConfig =
|
|
6150
|
+
const tableConfig = useMemo8(() => {
|
|
4880
6151
|
return EditorConfig.getDefaultTableConfig(tables);
|
|
4881
6152
|
}, [
|
|
4882
6153
|
tables?.splitCells,
|
|
@@ -4884,10 +6155,10 @@ function LumirEditor({
|
|
|
4884
6155
|
tables?.cellTextColor,
|
|
4885
6156
|
tables?.headers
|
|
4886
6157
|
]);
|
|
4887
|
-
const headingConfig =
|
|
6158
|
+
const headingConfig = useMemo8(() => {
|
|
4888
6159
|
return EditorConfig.getDefaultHeadingConfig(heading);
|
|
4889
6160
|
}, [heading?.levels?.join(",") ?? ""]);
|
|
4890
|
-
const disabledExtensions =
|
|
6161
|
+
const disabledExtensions = useMemo8(() => {
|
|
4891
6162
|
return EditorConfig.getDisabledExtensions(
|
|
4892
6163
|
disableExtensions,
|
|
4893
6164
|
allowVideoUpload,
|
|
@@ -4906,7 +6177,7 @@ function LumirEditor({
|
|
|
4906
6177
|
useEffect11(() => {
|
|
4907
6178
|
fileNameTransformRef.current = s3Upload?.fileNameTransform;
|
|
4908
6179
|
}, [s3Upload?.fileNameTransform]);
|
|
4909
|
-
const memoizedS3Upload =
|
|
6180
|
+
const memoizedS3Upload = useMemo8(() => {
|
|
4910
6181
|
if (!s3Upload) return void 0;
|
|
4911
6182
|
return {
|
|
4912
6183
|
apiEndpoint: s3Upload.apiEndpoint,
|
|
@@ -4957,7 +6228,14 @@ function LumirEditor({
|
|
|
4957
6228
|
// 확장 비활성: 비디오/오디오/파일 제어
|
|
4958
6229
|
disableExtensions: disabledExtensions,
|
|
4959
6230
|
_tiptapOptions: {
|
|
4960
|
-
extensions: [
|
|
6231
|
+
extensions: [
|
|
6232
|
+
VerticalAlignmentExtension,
|
|
6233
|
+
// 행 높이 attr 등록은 항상(저장된 높이 렌더), 드래그 리사이즈 UI는
|
|
6234
|
+
// tableHandles prop으로 게이트(기존 grip 컨트롤러와 동일 게이트).
|
|
6235
|
+
RowHeightExtension.configure({ resizable: tableHandles }),
|
|
6236
|
+
// 표 블록 정렬(좌/가운데/우) attr.
|
|
6237
|
+
TableAlignmentExtension
|
|
6238
|
+
]
|
|
4961
6239
|
},
|
|
4962
6240
|
placeholders: placeholder ? { default: placeholder, emptyDocument: placeholder } : void 0,
|
|
4963
6241
|
tabBehavior,
|
|
@@ -5133,17 +6411,40 @@ function LumirEditor({
|
|
|
5133
6411
|
memoizedS3Upload,
|
|
5134
6412
|
allowVideoUpload,
|
|
5135
6413
|
linkPreview?.apiEndpoint,
|
|
5136
|
-
placeholder
|
|
6414
|
+
placeholder,
|
|
6415
|
+
// tableHandles 변경 시 RowHeightExtension의 resizable 게이트가 반영되도록 재생성
|
|
6416
|
+
tableHandles
|
|
5137
6417
|
]
|
|
5138
6418
|
);
|
|
5139
6419
|
if (editor && linkPreview?.apiEndpoint) {
|
|
5140
6420
|
editor._linkPreviewApiEndpoint = linkPreview.apiEndpoint;
|
|
5141
6421
|
}
|
|
6422
|
+
if (editor) {
|
|
6423
|
+
try {
|
|
6424
|
+
const view = editor.prosemirrorView;
|
|
6425
|
+
if (view) {
|
|
6426
|
+
view.__lumirEditor = editor;
|
|
6427
|
+
}
|
|
6428
|
+
} catch {
|
|
6429
|
+
}
|
|
6430
|
+
}
|
|
5142
6431
|
useEffect11(() => {
|
|
5143
6432
|
if (editor) {
|
|
5144
6433
|
editor.isEditable = editable;
|
|
5145
6434
|
}
|
|
5146
6435
|
}, [editor, editable]);
|
|
6436
|
+
useEffect11(() => {
|
|
6437
|
+
if (!editor) return;
|
|
6438
|
+
const th = editor.tableHandles;
|
|
6439
|
+
if (!th || th.__lumirColDelPatched || typeof th.removeRowOrColumn !== "function")
|
|
6440
|
+
return;
|
|
6441
|
+
const orig = th.removeRowOrColumn.bind(th);
|
|
6442
|
+
th.removeRowOrColumn = (index, dir) => {
|
|
6443
|
+
if (removeFocusedRowOrColumn(editor, index, dir)) return;
|
|
6444
|
+
return orig(index, dir);
|
|
6445
|
+
};
|
|
6446
|
+
th.__lumirColDelPatched = true;
|
|
6447
|
+
}, [editor]);
|
|
5147
6448
|
useEffect11(() => {
|
|
5148
6449
|
if (!editor || !floatingMenu) return;
|
|
5149
6450
|
const ft = editor.formattingToolbar;
|
|
@@ -5161,7 +6462,15 @@ function LumirEditor({
|
|
|
5161
6462
|
if (!editor || !onContentChange) return;
|
|
5162
6463
|
const handleContentChange = () => {
|
|
5163
6464
|
const blocks = editor.topLevelBlocks;
|
|
5164
|
-
const patched = lowerFontSize(
|
|
6465
|
+
const patched = lowerFontSize(
|
|
6466
|
+
injectTableBlockAttrs(
|
|
6467
|
+
injectTableCellAttrs(blocks, editor, [
|
|
6468
|
+
"verticalAlignment",
|
|
6469
|
+
"rowHeight"
|
|
6470
|
+
]),
|
|
6471
|
+
editor
|
|
6472
|
+
)
|
|
6473
|
+
);
|
|
5165
6474
|
onContentChange(patched);
|
|
5166
6475
|
};
|
|
5167
6476
|
return editor.onEditorContentChange(handleContentChange);
|
|
@@ -5317,20 +6626,20 @@ function LumirEditor({
|
|
|
5317
6626
|
el.removeEventListener("drop", handleDrop, { capture: true });
|
|
5318
6627
|
};
|
|
5319
6628
|
}, [editor, allowVideoUpload]);
|
|
5320
|
-
const computedSideMenu =
|
|
6629
|
+
const computedSideMenu = useMemo8(() => {
|
|
5321
6630
|
return sideMenuAddButton ? sideMenu : false;
|
|
5322
6631
|
}, [sideMenuAddButton, sideMenu]);
|
|
5323
|
-
const DragHandleOnlySideMenu =
|
|
5324
|
-
return (props) => /* @__PURE__ */
|
|
6632
|
+
const DragHandleOnlySideMenu = useMemo8(() => {
|
|
6633
|
+
return (props) => /* @__PURE__ */ jsx27(BlockSideMenu, { ...props, children: /* @__PURE__ */ jsx27(DragHandleButton, { ...props, dragHandleMenu: LumirDragHandleMenu }) });
|
|
5325
6634
|
}, []);
|
|
5326
|
-
return /* @__PURE__ */
|
|
6635
|
+
return /* @__PURE__ */ jsxs19(
|
|
5327
6636
|
"div",
|
|
5328
6637
|
{
|
|
5329
6638
|
className: cn("lumirEditor", className),
|
|
5330
6639
|
style: { position: "relative", display: "flex", flexDirection: "column" },
|
|
5331
6640
|
children: [
|
|
5332
|
-
floatingMenu && editor && /* @__PURE__ */
|
|
5333
|
-
/* @__PURE__ */
|
|
6641
|
+
floatingMenu && editor && /* @__PURE__ */ jsxs19(Fragment8, { children: [
|
|
6642
|
+
/* @__PURE__ */ jsx27(
|
|
5334
6643
|
"input",
|
|
5335
6644
|
{
|
|
5336
6645
|
ref: floatingMenuFileInputRef,
|
|
@@ -5401,7 +6710,7 @@ function LumirEditor({
|
|
|
5401
6710
|
}
|
|
5402
6711
|
}
|
|
5403
6712
|
),
|
|
5404
|
-
/* @__PURE__ */
|
|
6713
|
+
/* @__PURE__ */ jsx27(
|
|
5405
6714
|
FloatingMenu,
|
|
5406
6715
|
{
|
|
5407
6716
|
editor,
|
|
@@ -5433,7 +6742,7 @@ function LumirEditor({
|
|
|
5433
6742
|
}
|
|
5434
6743
|
)
|
|
5435
6744
|
] }),
|
|
5436
|
-
/* @__PURE__ */
|
|
6745
|
+
/* @__PURE__ */ jsxs19(
|
|
5437
6746
|
BlockNoteView,
|
|
5438
6747
|
{
|
|
5439
6748
|
editor,
|
|
@@ -5448,19 +6757,19 @@ function LumirEditor({
|
|
|
5448
6757
|
tableHandles: false,
|
|
5449
6758
|
onSelectionChange,
|
|
5450
6759
|
children: [
|
|
5451
|
-
tableHandles && /* @__PURE__ */
|
|
5452
|
-
formattingToolbar && /* @__PURE__ */
|
|
6760
|
+
tableHandles && /* @__PURE__ */ jsx27(LumirTableHandlesController, {}),
|
|
6761
|
+
formattingToolbar && /* @__PURE__ */ jsx27(
|
|
5453
6762
|
FormattingToolbarController,
|
|
5454
6763
|
{
|
|
5455
6764
|
formattingToolbar: CustomFormattingToolbar
|
|
5456
6765
|
}
|
|
5457
6766
|
),
|
|
5458
|
-
linkToolbar && (linkPreview?.apiEndpoint ? /* @__PURE__ */
|
|
5459
|
-
/* @__PURE__ */
|
|
6767
|
+
linkToolbar && (linkPreview?.apiEndpoint ? /* @__PURE__ */ jsx27(LinkToolbarController, { linkToolbar: CustomLinkToolbar }) : /* @__PURE__ */ jsx27(LinkToolbarController, {})),
|
|
6768
|
+
/* @__PURE__ */ jsx27(
|
|
5460
6769
|
SuggestionMenuController,
|
|
5461
6770
|
{
|
|
5462
6771
|
triggerCharacter: "/",
|
|
5463
|
-
getItems:
|
|
6772
|
+
getItems: useCallback21(
|
|
5464
6773
|
async (query) => {
|
|
5465
6774
|
const items = getDefaultReactSlashMenuItems(editor);
|
|
5466
6775
|
const filtered = items.filter((item) => {
|
|
@@ -5504,7 +6813,7 @@ function LumirEditor({
|
|
|
5504
6813
|
},
|
|
5505
6814
|
aliases: ["html", "preview", "\uC6F9", "\uC6F9\uD398\uC774\uC9C0"],
|
|
5506
6815
|
group: "Embeds",
|
|
5507
|
-
icon: /* @__PURE__ */
|
|
6816
|
+
icon: /* @__PURE__ */ jsxs19(
|
|
5508
6817
|
"svg",
|
|
5509
6818
|
{
|
|
5510
6819
|
width: "18",
|
|
@@ -5516,14 +6825,40 @@ function LumirEditor({
|
|
|
5516
6825
|
strokeLinecap: "round",
|
|
5517
6826
|
strokeLinejoin: "round",
|
|
5518
6827
|
children: [
|
|
5519
|
-
/* @__PURE__ */
|
|
5520
|
-
/* @__PURE__ */
|
|
6828
|
+
/* @__PURE__ */ jsx27("polyline", { points: "16 18 22 12 16 6" }),
|
|
6829
|
+
/* @__PURE__ */ jsx27("polyline", { points: "8 6 2 12 8 18" })
|
|
5521
6830
|
]
|
|
5522
6831
|
}
|
|
5523
6832
|
),
|
|
5524
6833
|
subtext: "HTML \uD30C\uC77C\uC744 \uBBF8\uB9AC\uBCF4\uAE30\uB85C \uC0BD\uC785"
|
|
5525
6834
|
};
|
|
5526
|
-
const
|
|
6835
|
+
const columnItem = {
|
|
6836
|
+
title: "2\uB2E8 \uCEEC\uB7FC",
|
|
6837
|
+
onItemClick: () => {
|
|
6838
|
+
insertTwoColumns(editor);
|
|
6839
|
+
},
|
|
6840
|
+
aliases: ["columns", "column", "2col", "\uB2E8", "\uCEEC\uB7FC", "\uB2E4\uB2E8", "\uBD84\uD560"],
|
|
6841
|
+
group: "Basic blocks",
|
|
6842
|
+
icon: /* @__PURE__ */ jsxs19(
|
|
6843
|
+
"svg",
|
|
6844
|
+
{
|
|
6845
|
+
width: "18",
|
|
6846
|
+
height: "18",
|
|
6847
|
+
viewBox: "0 0 24 24",
|
|
6848
|
+
fill: "none",
|
|
6849
|
+
stroke: "currentColor",
|
|
6850
|
+
strokeWidth: "2",
|
|
6851
|
+
strokeLinecap: "round",
|
|
6852
|
+
strokeLinejoin: "round",
|
|
6853
|
+
children: [
|
|
6854
|
+
/* @__PURE__ */ jsx27("rect", { x: "3", y: "4", width: "7", height: "16", rx: "1" }),
|
|
6855
|
+
/* @__PURE__ */ jsx27("rect", { x: "14", y: "4", width: "7", height: "16", rx: "1" })
|
|
6856
|
+
]
|
|
6857
|
+
}
|
|
6858
|
+
),
|
|
6859
|
+
subtext: "\uBE14\uB85D\uC744 \uC88C\uC6B0 2\uB2E8\uC73C\uB85C \uBC30\uCE58"
|
|
6860
|
+
};
|
|
6861
|
+
const allItems = [...filtered, htmlPreviewItem, columnItem];
|
|
5527
6862
|
if (linkPreview?.apiEndpoint) {
|
|
5528
6863
|
allItems.push({
|
|
5529
6864
|
title: "Link Preview",
|
|
@@ -5542,7 +6877,7 @@ function LumirEditor({
|
|
|
5542
6877
|
"\uD504\uB9AC\uBDF0"
|
|
5543
6878
|
],
|
|
5544
6879
|
group: "Embeds",
|
|
5545
|
-
icon: /* @__PURE__ */
|
|
6880
|
+
icon: /* @__PURE__ */ jsxs19(
|
|
5546
6881
|
"svg",
|
|
5547
6882
|
{
|
|
5548
6883
|
width: "18",
|
|
@@ -5554,8 +6889,8 @@ function LumirEditor({
|
|
|
5554
6889
|
strokeLinecap: "round",
|
|
5555
6890
|
strokeLinejoin: "round",
|
|
5556
6891
|
children: [
|
|
5557
|
-
/* @__PURE__ */
|
|
5558
|
-
/* @__PURE__ */
|
|
6892
|
+
/* @__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" }),
|
|
6893
|
+
/* @__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
6894
|
]
|
|
5560
6895
|
}
|
|
5561
6896
|
),
|
|
@@ -5591,21 +6926,21 @@ function LumirEditor({
|
|
|
5591
6926
|
)
|
|
5592
6927
|
}
|
|
5593
6928
|
),
|
|
5594
|
-
!sideMenuAddButton && /* @__PURE__ */
|
|
6929
|
+
!sideMenuAddButton && /* @__PURE__ */ jsx27(SideMenuController, { sideMenu: DragHandleOnlySideMenu })
|
|
5595
6930
|
]
|
|
5596
6931
|
}
|
|
5597
6932
|
),
|
|
5598
|
-
isUploading && /* @__PURE__ */
|
|
5599
|
-
/* @__PURE__ */
|
|
5600
|
-
uploadProgress !== null && /* @__PURE__ */
|
|
6933
|
+
isUploading && /* @__PURE__ */ jsxs19("div", { className: "lumirEditor-upload-overlay", children: [
|
|
6934
|
+
/* @__PURE__ */ jsx27("div", { className: "lumirEditor-spinner" }),
|
|
6935
|
+
uploadProgress !== null && /* @__PURE__ */ jsxs19("span", { className: "lumirEditor-upload-progress", children: [
|
|
5601
6936
|
uploadProgress,
|
|
5602
6937
|
"%"
|
|
5603
6938
|
] })
|
|
5604
6939
|
] }),
|
|
5605
|
-
errorMessage && /* @__PURE__ */
|
|
5606
|
-
/* @__PURE__ */
|
|
5607
|
-
/* @__PURE__ */
|
|
5608
|
-
/* @__PURE__ */
|
|
6940
|
+
errorMessage && /* @__PURE__ */ jsxs19("div", { className: "lumirEditor-error-toast", children: [
|
|
6941
|
+
/* @__PURE__ */ jsx27("span", { className: "lumirEditor-error-icon", children: "\u26A0\uFE0F" }),
|
|
6942
|
+
/* @__PURE__ */ jsx27("span", { className: "lumirEditor-error-message", children: errorMessage }),
|
|
6943
|
+
/* @__PURE__ */ jsx27(
|
|
5609
6944
|
"button",
|
|
5610
6945
|
{
|
|
5611
6946
|
className: "lumirEditor-error-close",
|