quoin-editor 2.0.5 → 2.1.0
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/CHANGELOG.md +105 -0
- package/MIGRATION.md +1 -1
- package/README.md +4 -3
- package/dist/ai.cjs +124 -94
- package/dist/ai.d.cts +7 -0
- package/dist/ai.d.ts +7 -0
- package/dist/ai.js +50 -20
- package/dist/ai.js.map +1 -1
- package/dist/catalogue.cjs +28 -26
- package/dist/catalogue.js +19 -17
- package/dist/catalogue.js.map +1 -1
- package/dist/{chunk-JGEDJYIV.cjs → chunk-2FUWXPPC.cjs} +92 -98
- package/dist/{chunk-NHNW5DK3.js → chunk-3F76QQ65.js} +6 -6
- package/dist/{chunk-NHNW5DK3.js.map → chunk-3F76QQ65.js.map} +1 -1
- package/dist/{chunk-DBOZFNWU.js → chunk-3QYFAAQR.js} +3 -3
- package/dist/{chunk-DBOZFNWU.js.map → chunk-3QYFAAQR.js.map} +1 -1
- package/dist/{chunk-I7X7B3WD.cjs → chunk-4JDRDPLC.cjs} +17 -8
- package/dist/{chunk-EBSDPHPS.cjs → chunk-4UFWFV43.cjs} +1060 -719
- package/dist/{chunk-LM3DHROX.cjs → chunk-5AUIA4B3.cjs} +2 -2
- package/dist/{chunk-3INFNIGN.cjs → chunk-5H3BB5VJ.cjs} +131 -78
- package/dist/{chunk-DJU25PFC.cjs → chunk-5L2NSIHZ.cjs} +11 -11
- package/dist/{chunk-W376L2GM.js → chunk-6Y7JAWYY.js} +8 -8
- package/dist/chunk-6Y7JAWYY.js.map +1 -0
- package/dist/{chunk-UDBLZILE.js → chunk-ATKDXQEY.js} +12 -7
- package/dist/{chunk-UDBLZILE.js.map → chunk-ATKDXQEY.js.map} +1 -1
- package/dist/{chunk-A2IQHMIH.js → chunk-BE2SYPK5.js} +49 -54
- package/dist/chunk-BE2SYPK5.js.map +1 -0
- package/dist/{chunk-PURYVDC3.cjs → chunk-CFICD2JP.cjs} +21 -16
- package/dist/{chunk-3HW3WRYC.cjs → chunk-CSIUXYRU.cjs} +2 -2
- package/dist/{chunk-N7BSFDDM.cjs → chunk-DBKL524I.cjs} +23 -23
- package/dist/{chunk-XE3IYW5B.js → chunk-DEFYFIWW.js} +90 -37
- package/dist/chunk-DEFYFIWW.js.map +1 -0
- package/dist/{chunk-7E43TURF.cjs → chunk-ECI3PSMS.cjs} +7 -7
- package/dist/{chunk-4G645EYO.js → chunk-F73QEF7E.js} +5 -5
- package/dist/{chunk-4G645EYO.js.map → chunk-F73QEF7E.js.map} +1 -1
- package/dist/{chunk-KHRVCTQQ.cjs → chunk-FUT7XLMP.cjs} +61 -74
- package/dist/{chunk-7J63427U.cjs → chunk-GQSBOBOM.cjs} +375 -320
- package/dist/{chunk-LU3T3JB4.js → chunk-HPNSQWRD.js} +15 -28
- package/dist/chunk-HPNSQWRD.js.map +1 -0
- package/dist/{chunk-7Y4B7NHO.js → chunk-I34BFOLL.js} +18 -11
- package/dist/chunk-I34BFOLL.js.map +1 -0
- package/dist/{chunk-AJT54OMZ.js → chunk-IFRXEFQH.js} +9 -15
- package/dist/chunk-IFRXEFQH.js.map +1 -0
- package/dist/{chunk-YYW33WUL.cjs → chunk-K3XWVRL4.cjs} +8 -8
- package/dist/{chunk-LSI4RMTY.js → chunk-L5L6YNLT.js} +3 -3
- package/dist/{chunk-LSI4RMTY.js.map → chunk-L5L6YNLT.js.map} +1 -1
- package/dist/{chunk-2BPXVQBP.js → chunk-MO4UMXMT.js} +238 -86
- package/dist/chunk-MO4UMXMT.js.map +1 -0
- package/dist/{chunk-2QKFRKOP.cjs → chunk-N25EH2GZ.cjs} +351 -205
- package/dist/{chunk-CSPCDVCT.js → chunk-NCV2ML25.js} +3 -3
- package/dist/{chunk-CSPCDVCT.js.map → chunk-NCV2ML25.js.map} +1 -1
- package/dist/{chunk-NUQ64S5B.cjs → chunk-OJSKSQTL.cjs} +26 -26
- package/dist/chunk-PIWMU4BV.js +9 -0
- package/dist/chunk-PIWMU4BV.js.map +1 -0
- package/dist/chunk-QFGWSFOI.cjs +10 -0
- package/dist/{chunk-GPTJYWGS.js → chunk-RNBLVGWY.js} +3 -3
- package/dist/{chunk-GPTJYWGS.js.map → chunk-RNBLVGWY.js.map} +1 -1
- package/dist/{chunk-5RBMZGKV.js → chunk-TL2MJOWM.js} +325 -57
- package/dist/chunk-TL2MJOWM.js.map +1 -0
- package/dist/{chunk-YEDPBYO5.cjs → chunk-UDQ52EEC.cjs} +4 -4
- package/dist/{chunk-EIWPJWY3.js → chunk-UE2NQPNG.js} +5 -5
- package/dist/{chunk-EIWPJWY3.js.map → chunk-UE2NQPNG.js.map} +1 -1
- package/dist/{chunk-BE2YHZXA.cjs → chunk-ULV3SCYP.cjs} +26 -15
- package/dist/{chunk-WDBFGX3U.cjs → chunk-VTTMJGWP.cjs} +72 -77
- package/dist/{chunk-556PFYES.js → chunk-WK4UGDZN.js} +290 -235
- package/dist/chunk-WK4UGDZN.js.map +1 -0
- package/dist/{chunk-JZF6UQH5.cjs → chunk-WMKA37NJ.cjs} +12 -12
- package/dist/{chunk-F2ZK6Z52.js → chunk-Y26F2X4E.js} +3 -3
- package/dist/{chunk-F2ZK6Z52.js.map → chunk-Y26F2X4E.js.map} +1 -1
- package/dist/{chunk-FK7EBZPX.cjs → chunk-Z5EEDCRI.cjs} +549 -276
- package/dist/{chunk-G6NBQYMM.js → chunk-ZGFZRVQA.js} +817 -478
- package/dist/chunk-ZGFZRVQA.js.map +1 -0
- package/dist/{chunk-QLVX7MPS.js → chunk-ZQF45LA4.js} +19 -8
- package/dist/chunk-ZQF45LA4.js.map +1 -0
- package/dist/comments.cjs +127 -65
- package/dist/comments.d.cts +35 -2
- package/dist/comments.d.ts +35 -2
- package/dist/comments.js +73 -12
- package/dist/comments.js.map +1 -1
- package/dist/{diagram-extension-22x_njXB.d.ts → diagram-extension-BMlh8GCw.d.ts} +1 -1
- package/dist/{diagram-extension-C_FSkoj9.d.cts → diagram-extension-gmndUpti.d.cts} +1 -1
- package/dist/diagram.cjs +10 -9
- package/dist/diagram.d.cts +2 -2
- package/dist/diagram.d.ts +2 -2
- package/dist/diagram.js +7 -6
- package/dist/diff.cjs +25 -25
- package/dist/diff.js +3 -3
- package/dist/docx.cjs +31 -30
- package/dist/docx.js +5 -4
- package/dist/docx.js.map +1 -1
- package/dist/embed.cjs +10 -9
- package/dist/embed.js +8 -7
- package/dist/{emoji-extension-Dk5IQLZf.d.cts → emoji-extension-DD9CQTQj.d.cts} +1 -1
- package/dist/{emoji-extension-C832oGeT.d.ts → emoji-extension-U_PWZ2fX.d.ts} +1 -1
- package/dist/emoji.cjs +10 -9
- package/dist/emoji.d.cts +2 -2
- package/dist/emoji.d.ts +2 -2
- package/dist/emoji.js +7 -6
- package/dist/engine.cjs +58 -58
- package/dist/engine.d.cts +3 -3
- package/dist/engine.d.ts +3 -3
- package/dist/engine.js +3 -3
- package/dist/{find-extension-DmK9_N81.d.ts → find-extension-BGlqooZi.d.ts} +1 -1
- package/dist/{find-extension-BfruAPLi.d.cts → find-extension-BPnAJ8bY.d.cts} +1 -1
- package/dist/find.cjs +11 -10
- package/dist/find.d.cts +1 -1
- package/dist/find.d.ts +1 -1
- package/dist/find.js +7 -6
- package/dist/headless.cjs +70 -69
- package/dist/headless.d.cts +33 -10
- package/dist/headless.d.ts +33 -10
- package/dist/headless.js +5 -4
- package/dist/highlight.cjs +7 -6
- package/dist/highlight.js +6 -5
- package/dist/highlight.js.map +1 -1
- package/dist/{index-3fYvwqUZ.d.cts → index-DN7vRKFw.d.cts} +1 -1
- package/dist/{index-CgxnzCO5.d.ts → index-DyIYI3PM.d.ts} +1 -1
- package/dist/index.cjs +82 -81
- package/dist/index.d.cts +19 -12
- package/dist/index.d.ts +19 -12
- package/dist/index.js +6 -5
- package/dist/{labels-CiCxj2jP.d.cts → labels-BJORhN93.d.ts} +10 -5
- package/dist/{labels-BhRJYo46.d.ts → labels-CVYJ2-1X.d.cts} +10 -5
- package/dist/locale-ar.cjs +10 -0
- package/dist/locale-ar.d.cts +1 -1
- package/dist/locale-ar.d.ts +1 -1
- package/dist/locale-ar.js +10 -0
- package/dist/locale-ar.js.map +1 -1
- package/dist/locale-de.cjs +4 -0
- package/dist/locale-de.d.cts +1 -1
- package/dist/locale-de.d.ts +1 -1
- package/dist/locale-de.js +4 -0
- package/dist/locale-de.js.map +1 -1
- package/dist/locale-es.cjs +4 -0
- package/dist/locale-es.d.cts +1 -1
- package/dist/locale-es.d.ts +1 -1
- package/dist/locale-es.js +4 -0
- package/dist/locale-es.js.map +1 -1
- package/dist/locale-fr.cjs +4 -0
- package/dist/locale-fr.d.cts +1 -1
- package/dist/locale-fr.d.ts +1 -1
- package/dist/locale-fr.js +4 -0
- package/dist/locale-fr.js.map +1 -1
- package/dist/locale-ja.cjs +4 -0
- package/dist/locale-ja.d.cts +1 -1
- package/dist/locale-ja.d.ts +1 -1
- package/dist/locale-ja.js +4 -0
- package/dist/locale-ja.js.map +1 -1
- package/dist/locale-pt.cjs +4 -0
- package/dist/locale-pt.d.cts +1 -1
- package/dist/locale-pt.d.ts +1 -1
- package/dist/locale-pt.js +4 -0
- package/dist/locale-pt.js.map +1 -1
- package/dist/locale-zh.cjs +4 -0
- package/dist/locale-zh.d.cts +1 -1
- package/dist/locale-zh.d.ts +1 -1
- package/dist/locale-zh.js +4 -0
- package/dist/locale-zh.js.map +1 -1
- package/dist/math.cjs +11 -10
- package/dist/math.js +9 -8
- package/dist/mention.cjs +11 -10
- package/dist/mention.js +9 -8
- package/dist/{node-reveal-DY6bimv3.d.cts → node-reveal-Be7Xa0BL.d.cts} +1 -1
- package/dist/{node-reveal-BnFcnHhz.d.ts → node-reveal-CftIEqF_.d.ts} +1 -1
- package/dist/palette-DuIFHYHc.d.cts +10 -0
- package/dist/palette-DuIFHYHc.d.ts +10 -0
- package/dist/presence.cjs +39 -38
- package/dist/presence.js +8 -7
- package/dist/presence.js.map +1 -1
- package/dist/source.cjs +10 -9
- package/dist/source.d.cts +1 -1
- package/dist/source.d.ts +1 -1
- package/dist/source.js +6 -5
- package/dist/source.js.map +1 -1
- package/dist/{stats-extension-Dmw0Ujxe.d.ts → stats-extension-Bbpr593p.d.ts} +1 -1
- package/dist/{stats-extension-D5HySF0a.d.cts → stats-extension-D7FaeydW.d.cts} +1 -1
- package/dist/stats.cjs +12 -10
- package/dist/stats.d.cts +2 -2
- package/dist/stats.d.ts +2 -2
- package/dist/stats.js +9 -7
- package/dist/styles.css +1 -1
- package/dist/{table-extension-7LkLNK6Q.d.cts → table-extension-DNijjmxV.d.cts} +1 -1
- package/dist/{table-extension-DEpV0DnP.d.ts → table-extension-Dp6FYGPh.d.ts} +1 -1
- package/dist/table.cjs +26 -25
- package/dist/table.d.cts +4 -3
- package/dist/table.d.ts +4 -3
- package/dist/table.js +7 -6
- package/dist/{toc-extension-Dvh37bWQ.d.cts → toc-extension-BGEVAmSY.d.cts} +1 -1
- package/dist/{toc-extension-SVckrFmb.d.ts → toc-extension-DZIe40eV.d.ts} +1 -1
- package/dist/toc.cjs +10 -9
- package/dist/toc.d.cts +2 -2
- package/dist/toc.d.ts +2 -2
- package/dist/toc.js +7 -6
- package/dist/{types-DMuuDBVh.d.ts → types-Byu2a9qk.d.ts} +6 -1
- package/dist/{types-Bzhq5AXj.d.cts → types-DdDlCyyZ.d.cts} +6 -1
- package/dist/view.cjs +4 -4
- package/dist/view.js +2 -2
- package/dist/yjs.cjs +121 -121
- package/dist/yjs.d.cts +2 -2
- package/dist/yjs.d.ts +2 -2
- package/dist/yjs.js +5 -5
- package/package.json +4 -3
- package/dist/chunk-2BPXVQBP.js.map +0 -1
- package/dist/chunk-556PFYES.js.map +0 -1
- package/dist/chunk-5RBMZGKV.js.map +0 -1
- package/dist/chunk-7Y4B7NHO.js.map +0 -1
- package/dist/chunk-A2IQHMIH.js.map +0 -1
- package/dist/chunk-AJT54OMZ.js.map +0 -1
- package/dist/chunk-G6NBQYMM.js.map +0 -1
- package/dist/chunk-LU3T3JB4.js.map +0 -1
- package/dist/chunk-QLVX7MPS.js.map +0 -1
- package/dist/chunk-W376L2GM.js.map +0 -1
- package/dist/chunk-XE3IYW5B.js.map +0 -1
- package/dist/palette-BrX-hEd-.d.cts +0 -4
- package/dist/palette-BrX-hEd-.d.ts +0 -4
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { Table, FOCUS_RING, interceptKeys, DropdownMenuCheckboxItem, DropdownMenuSeparator, DropdownMenuRadioGroup, DropdownMenuRadioItem, MenuIcon, keepFocus, Plus, DropdownMenu, DropdownMenuTrigger, GripVertical, GripHorizontal, DropdownMenuContent, bubblePart, returnFocusToText, AlignLeft, AlignCenter, AlignRight, DropdownMenuItem, ArrowUpToLine, ArrowDownToLine, ArrowUp, ArrowDown, Trash, ArrowLeftToLine, ArrowRightToLine, ArrowLeft, ArrowRight } from './chunk-
|
|
2
|
-
import { useEditorState, EditableRegion, useReadOnly, useIsomorphicLayoutEffect, isComposingKey,
|
|
1
|
+
import { Table, FOCUS_RING, interceptKeys, watchDirection, DropdownMenuCheckboxItem, DropdownMenuSeparator, DropdownMenuRadioGroup, DropdownMenuRadioItem, MenuIcon, keepFocus, Plus, DropdownMenu, DropdownMenuTrigger, GripVertical, GripHorizontal, DropdownMenuContent, bubblePart, returnFocusToText, AlignLeft, AlignCenter, AlignRight, DropdownMenuItem, ArrowUpToLine, ArrowDownToLine, ArrowUp, ArrowDown, Trash, ArrowLeftToLine, ArrowRightToLine, ArrowLeft, ArrowRight } from './chunk-ZGFZRVQA.js';
|
|
2
|
+
import { useEditorState, EditableRegion, useReadOnly, useIsomorphicLayoutEffect, isComposingKey, neighbourBlock, NATIVE_INTERACTION, inlineDirection, posToDom, isOnFirstLine, isOnLastLine, caretClientRect, lineEdgeRect, caretFromPoint, domToPos, arrowAsWritten } from './chunk-MO4UMXMT.js';
|
|
3
3
|
import { mergeLabels } from './chunk-DLQCTGC3.js';
|
|
4
|
-
import { createPluginKey, markCoverage, toggleMark, setMark, Transaction, textSelection, headBlockId, isParagraph, regionLength, primaryRegion, replaceBlockStep, insertBlocksStep, descendantsEnd, defineExtension,
|
|
5
|
-
import { cellKey, blockById, inlineLength, requireBlockIndex, newId, countOf, sameItems, equalInline } from './chunk-
|
|
4
|
+
import { createPluginKey, markCoverage, toggleMark, setMark, Transaction, textSelection, cellOf, cellsBetween, headBlockId, isParagraph, regionLength, primaryRegion, replaceBlockStep, insertBlocksStep, descendantsEnd, defineExtension, deleteRange, isCollapsed, insertHardBreak, sliceFromClipboard, orderedRange, replaceInlineStep, insertTextAt, isTextFlow } from './chunk-TL2MJOWM.js';
|
|
5
|
+
import { cellKey, blockById, inlineLength, requireBlockIndex, newId, countOf, createBlockCodec, validWidths, sameItems, equalInline } from './chunk-I34BFOLL.js';
|
|
6
6
|
import { memo, useCallback, useRef, useState, useEffect, useSyncExternalStore, Fragment as Fragment$1 } from 'react';
|
|
7
7
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
8
|
import { createPortal } from 'react-dom';
|
|
9
9
|
|
|
10
10
|
// src/engine/commands/table-shape.ts
|
|
11
|
-
var CELL = /^cell:(\d+):(\d+)$/;
|
|
12
11
|
var tableShape = (block) => ({
|
|
13
12
|
rows: countOf(block.attrs.rows),
|
|
14
13
|
cols: countOf(block.attrs.cols)
|
|
@@ -18,12 +17,7 @@ var columnAligns = (block, cols) => Array.from({ length: cols }, (_, col) => {
|
|
|
18
17
|
const align = Array.isArray(block.attrs.align) ? block.attrs.align[col] : null;
|
|
19
18
|
return ALIGNS.includes(align) ? align : null;
|
|
20
19
|
});
|
|
21
|
-
var validWidths = (value, cols) => Array.isArray(value) && value.length === cols && value.every((width) => typeof width === "number" && width > 0) ? value : null;
|
|
22
20
|
var storedWidths = (block, cols) => validWidths(block.attrs.widths, cols);
|
|
23
|
-
function cellOf(region) {
|
|
24
|
-
const match = CELL.exec(region);
|
|
25
|
-
return match === null ? null : [Number(match[1]), Number(match[2])];
|
|
26
|
-
}
|
|
27
21
|
function tableBlock(doc, id) {
|
|
28
22
|
const block = blockById(doc, id);
|
|
29
23
|
return block?.type === "TABLE" ? block : null;
|
|
@@ -83,85 +77,23 @@ function cellSelection(state) {
|
|
|
83
77
|
}
|
|
84
78
|
var between = (value, a, b) => value >= Math.min(a, b) && value <= Math.max(a, b);
|
|
85
79
|
var rangeHasCell = ({ anchor, head }, [row, col]) => between(row, anchor[0], head[0]) && between(col, anchor[1], head[1]);
|
|
86
|
-
|
|
87
|
-
const cells = [];
|
|
88
|
-
for (let row = Math.min(anchor[0], head[0]); row <= Math.max(anchor[0], head[0]); row++) {
|
|
89
|
-
for (let col = Math.min(anchor[1], head[1]); col <= Math.max(anchor[1], head[1]); col++) cells.push([row, col]);
|
|
90
|
-
}
|
|
91
|
-
return cells;
|
|
92
|
-
}
|
|
80
|
+
var cellsInRange = ({ anchor, head }) => cellsBetween(anchor, head);
|
|
93
81
|
function selectCells(blockId, anchor, head) {
|
|
94
82
|
return (state, dispatch) => {
|
|
95
83
|
const block = tableBlock(state.doc, blockId);
|
|
96
84
|
const { rows, cols } = block === null ? { rows: 0, cols: 0 } : tableShape(block);
|
|
97
85
|
const inside = ([row, col]) => isIndex(row, rows) && isIndex(col, cols);
|
|
98
86
|
if (block === null || !inside(anchor) || !inside(head)) return false;
|
|
99
|
-
const
|
|
87
|
+
const end = cellKey(...head);
|
|
100
88
|
const selection = textSelection(
|
|
101
89
|
{ block: blockId, region: cellKey(...anchor), offset: 0 },
|
|
102
|
-
{ block: blockId, region:
|
|
90
|
+
{ block: blockId, region: end, offset: inlineLength(block.regions[end] ?? []) }
|
|
103
91
|
);
|
|
104
92
|
dispatch?.(new Transaction(state).setSelection(selection));
|
|
105
93
|
return true;
|
|
106
94
|
};
|
|
107
95
|
}
|
|
108
96
|
|
|
109
|
-
// src/engine/commands/cell-commands.ts
|
|
110
|
-
function filledCells(doc, range) {
|
|
111
|
-
const regions = blockById(doc, range.block)?.regions ?? {};
|
|
112
|
-
return cellsInRange(range).flatMap((cell) => {
|
|
113
|
-
const region = cellKey(...cell);
|
|
114
|
-
const length = inlineLength(regions[region] ?? []);
|
|
115
|
-
return length > 0 ? [{ region, length }] : [];
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
function firstCell({ block, anchor, head }) {
|
|
119
|
-
return { block, region: cellKey(Math.min(anchor[0], head[0]), Math.min(anchor[1], head[1])), offset: 0 };
|
|
120
|
-
}
|
|
121
|
-
function emptied(state, range) {
|
|
122
|
-
const tr = new Transaction(state);
|
|
123
|
-
for (const { region, length } of filledCells(state.doc, range)) {
|
|
124
|
-
tr.step(replaceInlineStep(range.block, region, 0, length, []));
|
|
125
|
-
}
|
|
126
|
-
return tr;
|
|
127
|
-
}
|
|
128
|
-
var deleteCellContents = (state, dispatch) => {
|
|
129
|
-
const range = cellSelection(state);
|
|
130
|
-
if (range === null) return false;
|
|
131
|
-
dispatch?.(emptied(state, range).setSelection(textSelection(firstCell(range))));
|
|
132
|
-
return true;
|
|
133
|
-
};
|
|
134
|
-
function typeOverCells(text) {
|
|
135
|
-
return (state, dispatch) => {
|
|
136
|
-
const range = cellSelection(state);
|
|
137
|
-
if (range === null || text === "") return false;
|
|
138
|
-
const tr = emptied(state, range);
|
|
139
|
-
dispatch?.(tr.setSelection(textSelection(insertTextAt(tr, state.schema, firstCell(range), text))));
|
|
140
|
-
return true;
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
function setCellsMark(type, attrs) {
|
|
144
|
-
return (state, dispatch) => {
|
|
145
|
-
const range = cellSelection(state);
|
|
146
|
-
const cells = range === null ? [] : filledCells(state.doc, range);
|
|
147
|
-
const regions = range === null ? void 0 : blockById(state.doc, range.block)?.regions;
|
|
148
|
-
if (range === null || regions === void 0 || cells.length === 0) return false;
|
|
149
|
-
const carried = cells.every(({ region }) => markCoverage(regions[region], type, attrs).every);
|
|
150
|
-
const mark = carried ? toggleMark(type, attrs) : setMark(type, attrs);
|
|
151
|
-
const tr = new Transaction(state);
|
|
152
|
-
for (const { region, length } of cells) {
|
|
153
|
-
const start = { block: range.block, region, offset: 0 };
|
|
154
|
-
const whole = textSelection(start, { ...start, offset: length });
|
|
155
|
-
mark({ ...state, doc: tr.doc, selection: whole, storedMarks: null }, (cell) => {
|
|
156
|
-
for (const step of cell.steps) tr.step(step);
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
if (!tr.docChanged) return false;
|
|
160
|
-
dispatch?.(tr);
|
|
161
|
-
return true;
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
97
|
// src/extensions/table/controls-slot.ts
|
|
166
98
|
var CONTROLS_SLOT = "data-quoin-table-controls";
|
|
167
99
|
var controlsSlot = (controller, blockId) => controller.blockElement(blockId)?.querySelector(`[${CONTROLS_SLOT}]`) ?? null;
|
|
@@ -222,6 +154,60 @@ function useWidthPreview(controller, blockId) {
|
|
|
222
154
|
return useSyncExternalStore(store.subscribe, read, read);
|
|
223
155
|
}
|
|
224
156
|
|
|
157
|
+
// src/engine/commands/cell-commands.ts
|
|
158
|
+
function filledCells(doc, range) {
|
|
159
|
+
const regions = blockById(doc, range.block)?.regions ?? {};
|
|
160
|
+
return cellsInRange(range).flatMap((cell) => {
|
|
161
|
+
const region = cellKey(...cell);
|
|
162
|
+
const length = inlineLength(regions[region] ?? []);
|
|
163
|
+
return length > 0 ? [{ region, length }] : [];
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
function overCells(state, write) {
|
|
167
|
+
const { selection } = state;
|
|
168
|
+
if (cellSelection(state) === null || selection?.kind !== "text") return null;
|
|
169
|
+
const tr = new Transaction(state);
|
|
170
|
+
return tr.setSelection(textSelection(write(tr, deleteRange(tr, state.schema, selection.anchor, selection.head))));
|
|
171
|
+
}
|
|
172
|
+
var deleteCellContents = (state, dispatch) => {
|
|
173
|
+
const tr = overCells(state, (_, caret) => caret);
|
|
174
|
+
if (tr !== null) dispatch?.(tr);
|
|
175
|
+
return tr !== null;
|
|
176
|
+
};
|
|
177
|
+
function typeOverCells(content) {
|
|
178
|
+
return (state, dispatch) => {
|
|
179
|
+
if (content.length === 0) return false;
|
|
180
|
+
const tr = overCells(state, (into, caret) => {
|
|
181
|
+
if (typeof content === "string") return insertTextAt(into, state.schema, caret, content);
|
|
182
|
+
into.step(replaceInlineStep(caret.block, caret.region, caret.offset, caret.offset, content));
|
|
183
|
+
return { ...caret, offset: caret.offset + inlineLength(content) };
|
|
184
|
+
});
|
|
185
|
+
if (tr !== null) dispatch?.(tr);
|
|
186
|
+
return tr !== null;
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function setCellsMark(type, attrs) {
|
|
190
|
+
return (state, dispatch) => {
|
|
191
|
+
const range = cellSelection(state);
|
|
192
|
+
const cells = range === null ? [] : filledCells(state.doc, range);
|
|
193
|
+
const regions = range === null ? void 0 : blockById(state.doc, range.block)?.regions;
|
|
194
|
+
if (range === null || regions === void 0 || cells.length === 0) return false;
|
|
195
|
+
const carried = cells.every(({ region }) => markCoverage(regions[region], type, attrs).every);
|
|
196
|
+
const mark = carried ? toggleMark(type, attrs) : setMark(type, attrs);
|
|
197
|
+
const tr = new Transaction(state);
|
|
198
|
+
for (const { region, length } of cells) {
|
|
199
|
+
const start = { block: range.block, region, offset: 0 };
|
|
200
|
+
const whole = textSelection(start, { ...start, offset: length });
|
|
201
|
+
mark({ ...state, doc: tr.doc, selection: whole, storedMarks: null }, (cell) => {
|
|
202
|
+
for (const step of cell.steps) tr.step(step);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
if (!tr.docChanged) return false;
|
|
206
|
+
dispatch?.(tr);
|
|
207
|
+
return true;
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
225
211
|
// src/engine/commands/table-commands.ts
|
|
226
212
|
function changeTable(blockId, change, plan) {
|
|
227
213
|
return (state, dispatch) => {
|
|
@@ -440,7 +426,7 @@ var tableKeymap = {
|
|
|
440
426
|
};
|
|
441
427
|
|
|
442
428
|
// src/extensions/table/use-cell-press.ts
|
|
443
|
-
function
|
|
429
|
+
function pressedCell(element) {
|
|
444
430
|
const row = element.getAttribute("data-row");
|
|
445
431
|
const col = element.getAttribute("data-col");
|
|
446
432
|
return element.matches("td, th") && row !== null && col !== null ? [Number(row), Number(col)] : null;
|
|
@@ -450,7 +436,7 @@ function useCellPress(controller, blockId, table, editable) {
|
|
|
450
436
|
const element = table.current;
|
|
451
437
|
if (!editable || element === null) return;
|
|
452
438
|
const onPointerDown = (event) => {
|
|
453
|
-
const cell = event.button === 0 && event.pointerType !== "touch" ?
|
|
439
|
+
const cell = event.button === 0 && event.pointerType !== "touch" ? pressedCell(event.target) : null;
|
|
454
440
|
const block = cell && blockById(controller.editor.state.doc, blockId);
|
|
455
441
|
if (!cell || !block) return;
|
|
456
442
|
event.preventDefault();
|
|
@@ -479,87 +465,6 @@ function useRevealCell(controller, blockId) {
|
|
|
479
465
|
host.closest("td, th")?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
|
|
480
466
|
}, [controller, blockId, region]);
|
|
481
467
|
}
|
|
482
|
-
|
|
483
|
-
// src/extensions/table/vertical-cell-move.ts
|
|
484
|
-
var VERTICAL = { ArrowUp: -1, ArrowDown: 1 };
|
|
485
|
-
function caretAtGoal(controller, blockId, cell, direction) {
|
|
486
|
-
const region = cellKey(...cell);
|
|
487
|
-
const host = controller.registry.get(blockId, region);
|
|
488
|
-
const { goalX } = controller;
|
|
489
|
-
const line = host && lineEdgeRect(host, direction < 0);
|
|
490
|
-
if (!host || !line || goalX === null) return null;
|
|
491
|
-
const box = host.getBoundingClientRect();
|
|
492
|
-
const x = Math.min(Math.max(goalX, box.left), box.right - 1);
|
|
493
|
-
const point = caretFromPoint(host.ownerDocument, x, line.top + line.height / 2);
|
|
494
|
-
const pos = point && domToPos(controller.registry, point.node, point.offset);
|
|
495
|
-
return pos && pos.block === blockId && pos.region === region ? pos : null;
|
|
496
|
-
}
|
|
497
|
-
var plainArrow = (event) => event.altKey || event.ctrlKey || event.metaKey ? void 0 : VERTICAL[event.key];
|
|
498
|
-
function caretOnEdgeLine(controller, head, direction) {
|
|
499
|
-
const host = controller.registry.get(head.block, head.region);
|
|
500
|
-
const point = posToDom(controller.registry, head);
|
|
501
|
-
if (!host || !point || !(direction < 0 ? isOnFirstLine(host, point) : isOnLastLine(host, point))) return null;
|
|
502
|
-
return { left: caretClientRect(point)?.left ?? null };
|
|
503
|
-
}
|
|
504
|
-
function columnAt(controller, blockId, row, x) {
|
|
505
|
-
const cells = Array.from(controller.blockElement(blockId)?.querySelector("table")?.rows[row]?.cells ?? []);
|
|
506
|
-
const index = cells.findIndex((cell) => x < cell.getBoundingClientRect().right);
|
|
507
|
-
return index === -1 ? Math.max(cells.length - 1, 0) : index;
|
|
508
|
-
}
|
|
509
|
-
function enterTable(controller, blockId, event) {
|
|
510
|
-
const direction = plainArrow(event);
|
|
511
|
-
const { state } = controller.editor;
|
|
512
|
-
const { selection } = state;
|
|
513
|
-
const block = tableBlock(state.doc, blockId);
|
|
514
|
-
if (direction === void 0 || event.shiftKey || block === null || selection?.kind !== "text") return false;
|
|
515
|
-
if (!isCollapsed(selection) || neighbourBlock(state.doc, selection.head.block, direction)?.id !== blockId) return false;
|
|
516
|
-
const caret = caretOnEdgeLine(controller, selection.head, direction);
|
|
517
|
-
if (caret === null) return false;
|
|
518
|
-
controller.goalX ??= caret.left;
|
|
519
|
-
const { rows, cols } = tableShape(block);
|
|
520
|
-
const row = direction > 0 ? 0 : rows - 1;
|
|
521
|
-
const { goalX } = controller;
|
|
522
|
-
const cell = [row, goalX === null ? direction > 0 ? 0 : cols - 1 : columnAt(controller, blockId, row, goalX)];
|
|
523
|
-
const pos = caretAtGoal(controller, blockId, cell, direction) ?? cellPos(block, cell, direction < 0);
|
|
524
|
-
controller.dispatch(controller.editor.createTransaction().setSelection(textSelection(pos)));
|
|
525
|
-
return true;
|
|
526
|
-
}
|
|
527
|
-
function moveBetweenRows(controller, blockId, event) {
|
|
528
|
-
const direction = plainArrow(event);
|
|
529
|
-
const { state } = controller.editor;
|
|
530
|
-
const caret = headCell(state);
|
|
531
|
-
if (direction === void 0 || caret === null || caret.block.id !== blockId || state.selection?.kind !== "text") {
|
|
532
|
-
return false;
|
|
533
|
-
}
|
|
534
|
-
const target = [caret.cell[0] + direction, caret.cell[1]];
|
|
535
|
-
if (target[0] < 0 || target[0] >= caret.shape.rows) return false;
|
|
536
|
-
const edge = caretOnEdgeLine(controller, caret.head, direction);
|
|
537
|
-
if (edge === null) return false;
|
|
538
|
-
controller.goalX ??= edge.left;
|
|
539
|
-
const pos = caretAtGoal(controller, blockId, target, direction) ?? cellPos(caret.block, target, direction < 0);
|
|
540
|
-
const selection = event.shiftKey ? textSelection(state.selection.anchor, pos) : textSelection(pos);
|
|
541
|
-
controller.dispatch(controller.editor.createTransaction().setSelection(selection));
|
|
542
|
-
return true;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
// src/extensions/table/use-table-keys.ts
|
|
546
|
-
var printable = (event) => [...event.key].length === 1 && !event.ctrlKey && !event.metaKey;
|
|
547
|
-
function typeOver(controller, blockId, event) {
|
|
548
|
-
if (cellSelection(controller.editor.state)?.block !== blockId || !printable(event)) return false;
|
|
549
|
-
return controller.run(typeOverCells(event.key));
|
|
550
|
-
}
|
|
551
|
-
function useTableKeys(controller, blockId, editable) {
|
|
552
|
-
useEffect(() => {
|
|
553
|
-
if (!editable) return;
|
|
554
|
-
const intercept = (event) => {
|
|
555
|
-
if (isComposingKey(controller, event)) return false;
|
|
556
|
-
const handled = typeOver(controller, blockId, event) || moveBetweenRows(controller, blockId, event) || enterTable(controller, blockId, event);
|
|
557
|
-
if (handled) event.preventDefault();
|
|
558
|
-
return handled;
|
|
559
|
-
};
|
|
560
|
-
return interceptKeys(controller, intercept);
|
|
561
|
-
}, [controller, blockId, editable]);
|
|
562
|
-
}
|
|
563
468
|
var indexes = (from, to) => Array.from({ length: Math.max(to - from, 0) }, (_, i) => from + i);
|
|
564
469
|
function TableBlock({ block, controller, labels }) {
|
|
565
470
|
const readOnly = useReadOnly(controller);
|
|
@@ -569,7 +474,6 @@ function TableBlock({ block, controller, labels }) {
|
|
|
569
474
|
const aligns = columnAligns(block, cols);
|
|
570
475
|
const preview = useWidthPreview(controller, block.id);
|
|
571
476
|
const widths = preview?.length === cols ? preview : storedWidths(block, cols);
|
|
572
|
-
useTableKeys(controller, block.id, !readOnly);
|
|
573
477
|
useCellPress(controller, block.id, table, !readOnly);
|
|
574
478
|
useRevealCell(controller, block.id);
|
|
575
479
|
const row = (index) => /* @__PURE__ */ jsx("tr", { children: indexes(0, cols).map((col) => /* @__PURE__ */ jsx(
|
|
@@ -630,7 +534,7 @@ var STEP = 10;
|
|
|
630
534
|
var LARGE_STEP = 50;
|
|
631
535
|
var clampWidth = (px) => Math.min(MAX_COLUMN_WIDTH, Math.max(MIN_COLUMN_WIDTH, Math.round(px)));
|
|
632
536
|
function ColumnResizer(props) {
|
|
633
|
-
const { controller, labels, blockId, col, drawn, style, resizerRef, onHold, onBack } = props;
|
|
537
|
+
const { controller, labels, blockId, col, drawn, direction, style, resizerRef, onHold, onBack } = props;
|
|
634
538
|
const drag = useRef(null);
|
|
635
539
|
const width = Math.round(drawn[col] ?? 0);
|
|
636
540
|
const store = tableUiStore(controller);
|
|
@@ -641,8 +545,9 @@ function ColumnResizer(props) {
|
|
|
641
545
|
if (isComposingKey(controller, event.nativeEvent)) return;
|
|
642
546
|
const step = event.shiftKey ? LARGE_STEP : STEP;
|
|
643
547
|
const tab = event.key === "Tab" && !event.altKey && !event.ctrlKey && !event.metaKey;
|
|
644
|
-
|
|
645
|
-
|
|
548
|
+
const arrow = arrowAsWritten(event.key, direction);
|
|
549
|
+
if (arrow === "ArrowLeft" || arrow === "ArrowRight") {
|
|
550
|
+
const next = clampWidth(width + (arrow === "ArrowLeft" ? -step : step));
|
|
646
551
|
if (next !== width) write(next, drawn);
|
|
647
552
|
} else if (tab && event.shiftKey) onBack();
|
|
648
553
|
else if (tab || event.key === "Escape") controller.focus();
|
|
@@ -658,7 +563,8 @@ function ColumnResizer(props) {
|
|
|
658
563
|
const onPointerMove = (event) => {
|
|
659
564
|
const current = drag.current;
|
|
660
565
|
if (current === null) return;
|
|
661
|
-
|
|
566
|
+
const moved = event.clientX - current.x;
|
|
567
|
+
current.to = clampWidth(current.widths[col] + (direction === "rtl" ? -moved : moved));
|
|
662
568
|
const widths = current.widths.map((px, i) => i === col ? current.to ?? px : px);
|
|
663
569
|
store.set({ preview: { block: blockId, widths } });
|
|
664
570
|
};
|
|
@@ -675,7 +581,7 @@ function ColumnResizer(props) {
|
|
|
675
581
|
},
|
|
676
582
|
[store]
|
|
677
583
|
);
|
|
678
|
-
const
|
|
584
|
+
const end = () => {
|
|
679
585
|
const ended = stop();
|
|
680
586
|
if (ended?.to != null && ended.to !== Math.round(ended.widths[col])) write(ended.to, ended.widths);
|
|
681
587
|
};
|
|
@@ -697,7 +603,7 @@ function ColumnResizer(props) {
|
|
|
697
603
|
onKeyDown,
|
|
698
604
|
onPointerDown,
|
|
699
605
|
onPointerMove,
|
|
700
|
-
onPointerUp:
|
|
606
|
+
onPointerUp: end,
|
|
701
607
|
onPointerCancel: stop
|
|
702
608
|
}
|
|
703
609
|
);
|
|
@@ -755,6 +661,49 @@ function HandleMenu({ controller, axis, label, style, items, open, onOpenChange,
|
|
|
755
661
|
] });
|
|
756
662
|
}
|
|
757
663
|
|
|
664
|
+
// src/extensions/table/table-geometry.ts
|
|
665
|
+
function measureTable(table, origin) {
|
|
666
|
+
const box = table.getBoundingClientRect();
|
|
667
|
+
const first = table.rows[0];
|
|
668
|
+
return {
|
|
669
|
+
left: box.left - origin.left,
|
|
670
|
+
top: box.top - origin.top,
|
|
671
|
+
width: box.width,
|
|
672
|
+
height: box.height,
|
|
673
|
+
rows: Array.from(table.rows, (row) => {
|
|
674
|
+
const rect = row.getBoundingClientRect();
|
|
675
|
+
return { start: rect.top - origin.top, size: rect.height };
|
|
676
|
+
}),
|
|
677
|
+
cols: Array.from(first?.cells ?? [], (cell) => {
|
|
678
|
+
const rect = cell.getBoundingClientRect();
|
|
679
|
+
return { start: rect.left - origin.left, size: rect.width };
|
|
680
|
+
}),
|
|
681
|
+
direction: inlineDirection(table)
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
var sameSpans = (a, b) => a.length === b.length && a.every((span, i) => span.start === b[i].start && span.size === b[i].size);
|
|
685
|
+
var sameGeometry = (a, b) => a === b || a !== null && b !== null && a.left === b.left && a.top === b.top && a.width === b.width && a.height === b.height && a.direction === b.direction && sameSpans(a.rows, b.rows) && sameSpans(a.cols, b.cols);
|
|
686
|
+
var spanEnd = (span) => span.start + span.size;
|
|
687
|
+
var leadingEdge = (span, direction) => direction === "rtl" ? spanEnd(span) : span.start;
|
|
688
|
+
var trailingEdge = (span, direction) => direction === "rtl" ? span.start : spanEnd(span);
|
|
689
|
+
function spanAt(spans, at) {
|
|
690
|
+
const inside = spans.findIndex((span) => span.start <= at && at < spanEnd(span));
|
|
691
|
+
if (inside !== -1) return inside;
|
|
692
|
+
const distances = spans.map((span) => Math.min(Math.abs(span.start - at), Math.abs(spanEnd(span) - at)));
|
|
693
|
+
return distances.indexOf(Math.min(...distances));
|
|
694
|
+
}
|
|
695
|
+
function edgeNear(spans, at, reach, direction = "ltr") {
|
|
696
|
+
if (spans.length === 0) return null;
|
|
697
|
+
const last = trailingEdge(spans[spans.length - 1], direction);
|
|
698
|
+
const edges = [...spans.map((span) => leadingEdge(span, direction)), last];
|
|
699
|
+
const index = edges.findIndex((edge) => Math.abs(edge - at) <= reach);
|
|
700
|
+
return index === -1 ? null : index;
|
|
701
|
+
}
|
|
702
|
+
function edgeAt(spans, edge, direction = "ltr") {
|
|
703
|
+
if (edge === null || !Number.isInteger(edge) || edge < 0 || edge > spans.length || spans.length === 0) return null;
|
|
704
|
+
return edge === spans.length ? trailingEdge(spans[edge - 1], direction) : leadingEdge(spans[edge], direction);
|
|
705
|
+
}
|
|
706
|
+
|
|
758
707
|
// src/extensions/table/table-menu-items.ts
|
|
759
708
|
var item = (id, label, icon, command, done, options = {}) => ({ id, label, icon, command, done, ...options });
|
|
760
709
|
function rowMenuItems(labels, blockId, row, { rows }) {
|
|
@@ -791,16 +740,12 @@ var alignItems = (labels) => [
|
|
|
791
740
|
{ value: "right", label: labels.alignRight, icon: AlignRight, done: labels.alignedRight }
|
|
792
741
|
];
|
|
793
742
|
var BESIDE = 4;
|
|
794
|
-
var
|
|
795
|
-
function edgeOf(spans, edge) {
|
|
796
|
-
if (edge === null || !Number.isInteger(edge) || edge < 0 || edge > spans.length || spans.length === 0) return null;
|
|
797
|
-
return edge === spans.length ? end(spans[edge - 1]) : spans[edge].start;
|
|
798
|
-
}
|
|
743
|
+
var besideRows = ({ left, width, direction }) => direction === "rtl" ? left + width + BESIDE : left - BESIDE;
|
|
799
744
|
var middle = (span) => span.start + span.size / 2;
|
|
800
745
|
var isTab = (event) => event.key === "Tab" && !event.altKey && !event.ctrlKey && !event.metaKey;
|
|
801
746
|
function TableHandles(props) {
|
|
802
747
|
const { controller, labels, block, target, geometry, menu, onMenu, onHold, focusRequested, onFocused } = props;
|
|
803
|
-
const direction =
|
|
748
|
+
const { direction } = geometry;
|
|
804
749
|
const rowHandle = useRef(null);
|
|
805
750
|
const columnHandle = useRef(null);
|
|
806
751
|
const resizer = useRef(null);
|
|
@@ -810,8 +755,8 @@ function TableHandles(props) {
|
|
|
810
755
|
const align = columnAligns(block, shape.cols)[col];
|
|
811
756
|
const drawn = geometry.cols.map((span) => span.size);
|
|
812
757
|
const { rowEdge, colEdge } = target;
|
|
813
|
-
const rowInsertAt =
|
|
814
|
-
const columnInsertAt =
|
|
758
|
+
const rowInsertAt = edgeAt(geometry.rows, rowEdge);
|
|
759
|
+
const columnInsertAt = edgeAt(geometry.cols, colEdge, direction);
|
|
815
760
|
useIsomorphicLayoutEffect(() => {
|
|
816
761
|
if (!focusRequested) return;
|
|
817
762
|
(columnHandle.current ?? rowHandle.current)?.focus();
|
|
@@ -841,7 +786,8 @@ function TableHandles(props) {
|
|
|
841
786
|
blockId: block.id,
|
|
842
787
|
col: index,
|
|
843
788
|
drawn,
|
|
844
|
-
|
|
789
|
+
direction,
|
|
790
|
+
style: { left: trailingEdge(span, direction), top: geometry.top, height: geometry.height },
|
|
845
791
|
resizerRef: index === col ? resizer : void 0,
|
|
846
792
|
onHold,
|
|
847
793
|
onBack: () => (columnHandle.current ?? rowHandle.current)?.focus()
|
|
@@ -855,7 +801,7 @@ function TableHandles(props) {
|
|
|
855
801
|
controller,
|
|
856
802
|
axis: "row",
|
|
857
803
|
label: labels.rowOptions(row + 1),
|
|
858
|
-
style: place(geometry
|
|
804
|
+
style: place(besideRows(geometry), middle(geometry.rows[row])),
|
|
859
805
|
items: rowMenuItems(labels, block.id, row, shape),
|
|
860
806
|
open: menu === "row",
|
|
861
807
|
onOpenChange: opener("row"),
|
|
@@ -907,7 +853,7 @@ function TableHandles(props) {
|
|
|
907
853
|
"aria-label": labels.insertRowAt(rowEdge + 1),
|
|
908
854
|
"data-axis": "row",
|
|
909
855
|
className: "quoin-table-insert",
|
|
910
|
-
style: place(geometry
|
|
856
|
+
style: place(besideRows(geometry), rowInsertAt),
|
|
911
857
|
onPointerDown: keepFocus,
|
|
912
858
|
onMouseDown: keepFocus,
|
|
913
859
|
onClick: () => run(addRow(block.id, rowEdge), labels.rowInserted),
|
|
@@ -931,40 +877,6 @@ function TableHandles(props) {
|
|
|
931
877
|
)
|
|
932
878
|
] });
|
|
933
879
|
}
|
|
934
|
-
|
|
935
|
-
// src/extensions/table/table-geometry.ts
|
|
936
|
-
function measureTable(table, origin) {
|
|
937
|
-
const box = table.getBoundingClientRect();
|
|
938
|
-
const first = table.rows[0];
|
|
939
|
-
return {
|
|
940
|
-
left: box.left - origin.left,
|
|
941
|
-
top: box.top - origin.top,
|
|
942
|
-
width: box.width,
|
|
943
|
-
height: box.height,
|
|
944
|
-
rows: Array.from(table.rows, (row) => {
|
|
945
|
-
const rect = row.getBoundingClientRect();
|
|
946
|
-
return { start: rect.top - origin.top, size: rect.height };
|
|
947
|
-
}),
|
|
948
|
-
cols: Array.from(first?.cells ?? [], (cell) => {
|
|
949
|
-
const rect = cell.getBoundingClientRect();
|
|
950
|
-
return { start: rect.left - origin.left, size: rect.width };
|
|
951
|
-
})
|
|
952
|
-
};
|
|
953
|
-
}
|
|
954
|
-
var sameSpans = (a, b) => a.length === b.length && a.every((span, i) => span.start === b[i].start && span.size === b[i].size);
|
|
955
|
-
var sameGeometry = (a, b) => a === b || a !== null && b !== null && a.left === b.left && a.top === b.top && a.width === b.width && a.height === b.height && sameSpans(a.rows, b.rows) && sameSpans(a.cols, b.cols);
|
|
956
|
-
function spanAt(spans, at) {
|
|
957
|
-
const inside = spans.findIndex((span) => at < span.start + span.size);
|
|
958
|
-
return inside === -1 ? spans.length - 1 : inside;
|
|
959
|
-
}
|
|
960
|
-
function edgeNear(spans, at, reach) {
|
|
961
|
-
if (spans.length === 0) return null;
|
|
962
|
-
const edges = [spans[0].start, ...spans.map((span) => span.start + span.size)];
|
|
963
|
-
const index = edges.findIndex((edge) => Math.abs(edge - at) <= reach);
|
|
964
|
-
return index === -1 ? null : index;
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
// src/extensions/table/use-table-geometry.ts
|
|
968
880
|
function useTableGeometry(controller, blockId, slot) {
|
|
969
881
|
const [geometry, setGeometry] = useState(null);
|
|
970
882
|
useIsomorphicLayoutEffect(() => {
|
|
@@ -982,31 +894,103 @@ function useTableGeometry(controller, blockId, slot) {
|
|
|
982
894
|
frame = view.requestAnimationFrame(measure);
|
|
983
895
|
};
|
|
984
896
|
const unsubscribe = controller.editor.subscribe(later);
|
|
897
|
+
const unwatch = watchDirection(table, later);
|
|
985
898
|
const observer = new ResizeObserver(later);
|
|
986
899
|
observer.observe(table);
|
|
987
900
|
view.addEventListener("resize", later);
|
|
988
901
|
return () => {
|
|
989
902
|
view.cancelAnimationFrame(frame);
|
|
990
903
|
unsubscribe();
|
|
904
|
+
unwatch();
|
|
991
905
|
observer.disconnect();
|
|
992
906
|
view.removeEventListener("resize", later);
|
|
993
907
|
};
|
|
994
908
|
}, [controller, blockId, slot]);
|
|
995
909
|
return geometry;
|
|
996
910
|
}
|
|
997
|
-
|
|
911
|
+
|
|
912
|
+
// src/extensions/table/vertical-cell-move.ts
|
|
913
|
+
var VERTICAL = { ArrowUp: -1, ArrowDown: 1 };
|
|
914
|
+
function caretAtGoal(controller, blockId, cell, direction) {
|
|
915
|
+
const region = cellKey(...cell);
|
|
916
|
+
const host = controller.registry.get(blockId, region);
|
|
917
|
+
const { goalX } = controller;
|
|
918
|
+
const line = host && lineEdgeRect(host, direction < 0);
|
|
919
|
+
if (!host || !line || goalX === null) return null;
|
|
920
|
+
const box = host.getBoundingClientRect();
|
|
921
|
+
const x = Math.min(Math.max(goalX, box.left), box.right - 1);
|
|
922
|
+
const point = caretFromPoint(host.ownerDocument, x, line.top + line.height / 2);
|
|
923
|
+
const pos = point && domToPos(controller.registry, point.node, point.offset);
|
|
924
|
+
return pos && pos.block === blockId && pos.region === region ? pos : null;
|
|
925
|
+
}
|
|
926
|
+
var plainArrow = (event) => event.altKey || event.ctrlKey || event.metaKey ? void 0 : VERTICAL[event.key];
|
|
927
|
+
function caretOnEdgeLine(controller, head, direction) {
|
|
928
|
+
const host = controller.registry.get(head.block, head.region);
|
|
929
|
+
const point = posToDom(controller.registry, head);
|
|
930
|
+
if (!host || !point || !(direction < 0 ? isOnFirstLine(host, point) : isOnLastLine(host, point))) return null;
|
|
931
|
+
return { left: caretClientRect(point)?.left ?? null };
|
|
932
|
+
}
|
|
933
|
+
function columnAt(controller, blockId, row, x) {
|
|
934
|
+
const cells = Array.from(controller.blockElement(blockId)?.querySelector("table")?.rows[row]?.cells ?? []);
|
|
935
|
+
const spans = cells.map((cell) => {
|
|
936
|
+
const { left, width } = cell.getBoundingClientRect();
|
|
937
|
+
return { start: left, size: width };
|
|
938
|
+
});
|
|
939
|
+
return Math.max(spanAt(spans, x), 0);
|
|
940
|
+
}
|
|
941
|
+
function enterTable(controller, event) {
|
|
942
|
+
const direction = plainArrow(event);
|
|
943
|
+
const { state } = controller.editor;
|
|
944
|
+
const { selection } = state;
|
|
945
|
+
if (direction === void 0 || event.shiftKey || selection?.kind !== "text" || !isCollapsed(selection)) return false;
|
|
946
|
+
const block = neighbourBlock(state.doc, selection.head.block, direction);
|
|
947
|
+
if (block?.type !== "TABLE") return false;
|
|
948
|
+
const blockId = block.id;
|
|
949
|
+
const caret = caretOnEdgeLine(controller, selection.head, direction);
|
|
950
|
+
if (caret === null) return false;
|
|
951
|
+
controller.goalX ??= caret.left;
|
|
952
|
+
const { rows, cols } = tableShape(block);
|
|
953
|
+
const row = direction > 0 ? 0 : rows - 1;
|
|
954
|
+
const { goalX } = controller;
|
|
955
|
+
const cell = [row, goalX === null ? direction > 0 ? 0 : cols - 1 : columnAt(controller, blockId, row, goalX)];
|
|
956
|
+
const pos = caretAtGoal(controller, blockId, cell, direction) ?? cellPos(block, cell, direction < 0);
|
|
957
|
+
controller.dispatch(controller.editor.createTransaction().setSelection(textSelection(pos)));
|
|
958
|
+
return true;
|
|
959
|
+
}
|
|
960
|
+
function moveBetweenRows(controller, event) {
|
|
961
|
+
const direction = plainArrow(event);
|
|
962
|
+
const { state } = controller.editor;
|
|
963
|
+
const caret = headCell(state);
|
|
964
|
+
if (direction === void 0 || caret === null || state.selection?.kind !== "text") return false;
|
|
965
|
+
const blockId = caret.block.id;
|
|
966
|
+
const target = [caret.cell[0] + direction, caret.cell[1]];
|
|
967
|
+
if (target[0] < 0 || target[0] >= caret.shape.rows) return false;
|
|
968
|
+
const edge = caretOnEdgeLine(controller, caret.head, direction);
|
|
969
|
+
if (edge === null) return false;
|
|
970
|
+
controller.goalX ??= edge.left;
|
|
971
|
+
const pos = caretAtGoal(controller, blockId, target, direction) ?? cellPos(caret.block, target, direction < 0);
|
|
972
|
+
const selection = event.shiftKey ? textSelection(state.selection.anchor, pos) : textSelection(pos);
|
|
973
|
+
controller.dispatch(controller.editor.createTransaction().setSelection(selection));
|
|
974
|
+
return true;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// src/extensions/table/use-table-keys.ts
|
|
978
|
+
var printable = (event) => [...event.key].length === 1 && !event.ctrlKey && !event.metaKey;
|
|
979
|
+
function typeOver(controller, event) {
|
|
980
|
+
if (cellSelection(controller.editor.state) === null || !printable(event)) return false;
|
|
981
|
+
return controller.run(typeOverCells(event.key));
|
|
982
|
+
}
|
|
983
|
+
function useTableKeys(controller, editable) {
|
|
998
984
|
useEffect(() => {
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
event.
|
|
1004
|
-
|
|
1005
|
-
controller.run(deleteCellContents);
|
|
985
|
+
if (!editable) return;
|
|
986
|
+
const intercept = (event) => {
|
|
987
|
+
if (isComposingKey(controller, event)) return false;
|
|
988
|
+
const handled = typeOver(controller, event) || moveBetweenRows(controller, event) || enterTable(controller, event);
|
|
989
|
+
if (handled) event.preventDefault();
|
|
990
|
+
return handled;
|
|
1006
991
|
};
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
}, [controller]);
|
|
992
|
+
return interceptKeys(controller, intercept);
|
|
993
|
+
}, [controller, editable]);
|
|
1010
994
|
}
|
|
1011
995
|
var EDGE_ZONE = 24;
|
|
1012
996
|
var EDGE_REACH = 8;
|
|
@@ -1017,6 +1001,7 @@ function caretTarget(state) {
|
|
|
1017
1001
|
const caret = headCell(state);
|
|
1018
1002
|
return caret && { block: caret.block.id, row: caret.cell[0], col: caret.cell[1], rowEdge: null, colEdge: null };
|
|
1019
1003
|
}
|
|
1004
|
+
var nearRowStarts = ({ left, width, direction }, x) => direction === "rtl" ? x > left + width - EDGE_ZONE : x < left + EDGE_ZONE;
|
|
1020
1005
|
function pointerTarget(controller, event) {
|
|
1021
1006
|
const blockId = controller.blockAt(event.target);
|
|
1022
1007
|
const block = blockId === void 0 ? null : tableBlock(controller.editor.state.doc, blockId);
|
|
@@ -1027,8 +1012,8 @@ function pointerTarget(controller, event) {
|
|
|
1027
1012
|
const row = spanAt(geometry.rows, y);
|
|
1028
1013
|
const col = spanAt(geometry.cols, x);
|
|
1029
1014
|
if (row < 0 || col < 0) return null;
|
|
1030
|
-
const rowEdge =
|
|
1031
|
-
const colEdge = y < geometry.top + EDGE_ZONE ? edgeNear(geometry.cols, x, EDGE_REACH) : null;
|
|
1015
|
+
const rowEdge = nearRowStarts(geometry, x) ? edgeNear(geometry.rows, y, EDGE_REACH) : null;
|
|
1016
|
+
const colEdge = y < geometry.top + EDGE_ZONE ? edgeNear(geometry.cols, x, EDGE_REACH, geometry.direction) : null;
|
|
1032
1017
|
return { block: block.id, row, col, rowEdge, colEdge };
|
|
1033
1018
|
}
|
|
1034
1019
|
function shapeOf(state, blockId) {
|
|
@@ -1093,7 +1078,7 @@ function TableControls({ controller, labels }) {
|
|
|
1093
1078
|
const [focusFor, setFocusFor] = useState(null);
|
|
1094
1079
|
const [slot, setSlot] = useState(null);
|
|
1095
1080
|
const target = useTableTarget(controller, held?.target ?? null);
|
|
1096
|
-
|
|
1081
|
+
useTableKeys(controller, !readOnly);
|
|
1097
1082
|
const blockId = target?.block ?? null;
|
|
1098
1083
|
const block = useEditorState(
|
|
1099
1084
|
controller,
|
|
@@ -1130,10 +1115,12 @@ function TableControls({ controller, labels }) {
|
|
|
1130
1115
|
setHeld((current) => current?.menu === null ? null : current);
|
|
1131
1116
|
}, []);
|
|
1132
1117
|
useIsomorphicLayoutEffect(() => {
|
|
1133
|
-
const
|
|
1134
|
-
|
|
1118
|
+
const element = block === null || readOnly ? null : controlsSlot(controller, block.id);
|
|
1119
|
+
const drawn = element && block && { block: block.id, element };
|
|
1120
|
+
setSlot((current) => current?.element === drawn?.element && current?.block === drawn?.block ? current : drawn);
|
|
1135
1121
|
});
|
|
1136
|
-
|
|
1122
|
+
const placed = slot !== null && slot.block === block?.id && slot.element.isConnected ? slot.element : null;
|
|
1123
|
+
if (target === null || block === null || readOnly || placed === null) return null;
|
|
1137
1124
|
return createPortal(
|
|
1138
1125
|
/* @__PURE__ */ jsx(
|
|
1139
1126
|
PlacedHandles,
|
|
@@ -1142,7 +1129,7 @@ function TableControls({ controller, labels }) {
|
|
|
1142
1129
|
labels,
|
|
1143
1130
|
block,
|
|
1144
1131
|
target,
|
|
1145
|
-
slot,
|
|
1132
|
+
slot: placed,
|
|
1146
1133
|
menu: held?.menu ?? null,
|
|
1147
1134
|
onMenu,
|
|
1148
1135
|
onHold,
|
|
@@ -1151,7 +1138,7 @@ function TableControls({ controller, labels }) {
|
|
|
1151
1138
|
},
|
|
1152
1139
|
block.id
|
|
1153
1140
|
),
|
|
1154
|
-
|
|
1141
|
+
placed
|
|
1155
1142
|
);
|
|
1156
1143
|
}
|
|
1157
1144
|
function PlacedHandles({ slot, ...props }) {
|
|
@@ -1159,6 +1146,78 @@ function PlacedHandles({ slot, ...props }) {
|
|
|
1159
1146
|
return geometry === null ? null : /* @__PURE__ */ jsx(TableHandles, { ...props, geometry });
|
|
1160
1147
|
}
|
|
1161
1148
|
|
|
1149
|
+
// src/engine/commands/paste-cells.ts
|
|
1150
|
+
var unmoved = (cell) => cell;
|
|
1151
|
+
function grown(block, rows, cols) {
|
|
1152
|
+
const shape = tableShape(block);
|
|
1153
|
+
if (rows <= shape.rows && cols <= shape.cols) return null;
|
|
1154
|
+
const added = Math.max(cols - shape.cols, 0);
|
|
1155
|
+
const widths = storedWidths(block, shape.cols);
|
|
1156
|
+
return rebuiltTable(block, {
|
|
1157
|
+
rows: Math.max(rows, shape.rows),
|
|
1158
|
+
cols: shape.cols + added,
|
|
1159
|
+
source: (row, col) => row < shape.rows && col < shape.cols ? [row, col] : null,
|
|
1160
|
+
target: unmoved,
|
|
1161
|
+
landing: unmoved,
|
|
1162
|
+
attrs: {
|
|
1163
|
+
align: [...columnAligns(block, shape.cols), ...Array(added).fill(null)],
|
|
1164
|
+
...widths && { widths: [...widths, ...Array(added).fill(widths[shape.cols - 1])] }
|
|
1165
|
+
}
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1168
|
+
function pasteCells(source) {
|
|
1169
|
+
return (state, dispatch) => {
|
|
1170
|
+
const { doc, schema, selection } = state;
|
|
1171
|
+
const { rows, cols } = tableShape(source);
|
|
1172
|
+
if (selection?.kind !== "text" || rows === 0 || cols === 0) return false;
|
|
1173
|
+
const { anchor, head } = selection;
|
|
1174
|
+
const inCells = anchor.block === head.block && cellOf(anchor.region) !== null && cellOf(head.region) !== null;
|
|
1175
|
+
if (!inCells || tableBlock(doc, head.block) === null) return false;
|
|
1176
|
+
const tr = new Transaction(state).setOrigin("paste");
|
|
1177
|
+
const { from, to } = orderedRange(doc, anchor, head);
|
|
1178
|
+
const [top, left] = cellOf(deleteRange(tr, schema, from, to).region);
|
|
1179
|
+
const larger = grown(tableBlock(tr.doc, head.block), top + rows, left + cols);
|
|
1180
|
+
if (larger !== null) tr.step(replaceBlockStep(larger));
|
|
1181
|
+
const block = tableBlock(tr.doc, head.block);
|
|
1182
|
+
let caret = head;
|
|
1183
|
+
for (const [row, col] of cellsBetween([0, 0], [rows - 1, cols - 1])) {
|
|
1184
|
+
const region = cellKey(top + row, left + col);
|
|
1185
|
+
const content = source.regions[cellKey(row, col)] ?? [];
|
|
1186
|
+
const length = regionLength(block, region);
|
|
1187
|
+
if (length > 0 || content.length > 0) tr.step(replaceInlineStep(block.id, region, 0, length, content));
|
|
1188
|
+
caret = { block: block.id, region, offset: inlineLength(content) };
|
|
1189
|
+
}
|
|
1190
|
+
dispatch?.(tr.setSelection(textSelection(caret)));
|
|
1191
|
+
return true;
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
// src/extensions/table/paste-over-cells.ts
|
|
1196
|
+
function richBlocks(state, pasted) {
|
|
1197
|
+
const slice = pasted?.json || pasted?.html ? sliceFromClipboard({ json: pasted.json, html: pasted.html }) : null;
|
|
1198
|
+
if (slice === null) return null;
|
|
1199
|
+
const codec = createBlockCodec(state.schema);
|
|
1200
|
+
const blocks = slice.blocks.flatMap((block) => codec.toEngineBlocks(block));
|
|
1201
|
+
return { blocks, open: slice.openStart && slice.openEnd };
|
|
1202
|
+
}
|
|
1203
|
+
function lineOf(state, rich) {
|
|
1204
|
+
const [only] = rich?.blocks ?? [];
|
|
1205
|
+
if (!rich?.open || rich.blocks.length !== 1 || !isTextFlow(state.schema, only)) return void 0;
|
|
1206
|
+
return only.regions[primaryRegion(state.schema, only) ?? ""];
|
|
1207
|
+
}
|
|
1208
|
+
var pasteOverCells = {
|
|
1209
|
+
name: "table-cells",
|
|
1210
|
+
match(text, state, pasted) {
|
|
1211
|
+
const { doc, selection } = state;
|
|
1212
|
+
if (selection?.kind !== "text" || tableBlock(doc, selection.head.block) === null) return null;
|
|
1213
|
+
const rich = richBlocks(state, pasted);
|
|
1214
|
+
const [only] = rich?.blocks.length === 1 ? rich.blocks : [];
|
|
1215
|
+
if (only?.type === "TABLE") return pasteCells(only);
|
|
1216
|
+
if (cellSelection(state) === null) return null;
|
|
1217
|
+
return typeOverCells(lineOf(state, rich) ?? text.replace(/\r\n?/g, "\n"));
|
|
1218
|
+
}
|
|
1219
|
+
};
|
|
1220
|
+
|
|
1162
1221
|
// src/extensions/table/table-labels.ts
|
|
1163
1222
|
var englishTableLabels = {
|
|
1164
1223
|
table: "Table",
|
|
@@ -1212,10 +1271,6 @@ var tableSlashItem = (labels) => ({
|
|
|
1212
1271
|
command: () => insertTable(NEW_TABLE.rows, NEW_TABLE.cols)
|
|
1213
1272
|
});
|
|
1214
1273
|
var ABOVE_CORE_KEYS = 200;
|
|
1215
|
-
var pasteOverCells = {
|
|
1216
|
-
name: "table-cells",
|
|
1217
|
-
match: (text, state) => cellSelection(state) === null ? null : typeOverCells(text.replace(/\r\n?/g, "\n"))
|
|
1218
|
-
};
|
|
1219
1274
|
function tableExtension(options = {}) {
|
|
1220
1275
|
const labels = resolveTableLabels(options.labels);
|
|
1221
1276
|
const TableRenderer = (props) => /* @__PURE__ */ jsx(TableBlock, { ...props, labels });
|
|
@@ -1237,5 +1292,5 @@ function tableExtension(options = {}) {
|
|
|
1237
1292
|
}
|
|
1238
1293
|
|
|
1239
1294
|
export { addColumn, addRow, cellSelection, cellSelectionKey, cellSelectionPlugin, cellsInRange, deleteCellContents, englishTableLabels, insertTable, moveColumn, moveRow, removeColumn, removeRow, selectCells, setCellsMark, setColumnAlign, setColumnWidth, tableExtension, toggleHeaderRow };
|
|
1240
|
-
//# sourceMappingURL=chunk-
|
|
1241
|
-
//# sourceMappingURL=chunk-
|
|
1295
|
+
//# sourceMappingURL=chunk-WK4UGDZN.js.map
|
|
1296
|
+
//# sourceMappingURL=chunk-WK4UGDZN.js.map
|