@trafica/editor 1.0.20 → 1.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +301 -115
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +301 -115
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { forwardRef, useRef, useEffect, useCallback, useMemo, useImperativeHandle, useState, useLayoutEffect, useSyncExternalStore } from 'react';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
import { createPortal } from 'react-dom';
|
|
3
4
|
|
|
4
5
|
// src/editor/core/DocumentModel.ts
|
|
5
6
|
function isTextNode(node) {
|
|
@@ -5530,9 +5531,11 @@ function SpecialCharactersButton({
|
|
|
5530
5531
|
null
|
|
5531
5532
|
);
|
|
5532
5533
|
const [focusedIdx, setFocusedIdx] = useState(-1);
|
|
5533
|
-
const
|
|
5534
|
+
const buttonRef = useRef(null);
|
|
5535
|
+
const popupRef = useRef(null);
|
|
5534
5536
|
const searchRef = useRef(null);
|
|
5535
5537
|
const gridRef = useRef(null);
|
|
5538
|
+
const [popupPos, setPopupPos] = useState({ top: 0, left: 0 });
|
|
5536
5539
|
const filtered = useMemo(() => {
|
|
5537
5540
|
const q = search.toLowerCase();
|
|
5538
5541
|
return SPECIAL_CHARACTERS.filter(
|
|
@@ -5540,6 +5543,12 @@ function SpecialCharactersButton({
|
|
|
5540
5543
|
);
|
|
5541
5544
|
}, [category, search]);
|
|
5542
5545
|
const openModal = () => {
|
|
5546
|
+
if (buttonRef.current) {
|
|
5547
|
+
const rect = buttonRef.current.getBoundingClientRect();
|
|
5548
|
+
const popupWidth = 340;
|
|
5549
|
+
const left = Math.min(rect.left, window.innerWidth - popupWidth - 8);
|
|
5550
|
+
setPopupPos({ top: rect.bottom + 4, left: Math.max(8, left) });
|
|
5551
|
+
}
|
|
5543
5552
|
setOpen(true);
|
|
5544
5553
|
setSearch("");
|
|
5545
5554
|
setFocusedIdx(-1);
|
|
@@ -5552,9 +5561,11 @@ function SpecialCharactersButton({
|
|
|
5552
5561
|
useEffect(() => {
|
|
5553
5562
|
if (!open) return;
|
|
5554
5563
|
const handler = (e) => {
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5564
|
+
var _a, _b;
|
|
5565
|
+
const target = e.target;
|
|
5566
|
+
const insidePopup = (_a = popupRef.current) == null ? void 0 : _a.contains(target);
|
|
5567
|
+
const insideButton = (_b = buttonRef.current) == null ? void 0 : _b.contains(target);
|
|
5568
|
+
if (!insidePopup && !insideButton) closeModal();
|
|
5558
5569
|
};
|
|
5559
5570
|
document.addEventListener("mousedown", handler);
|
|
5560
5571
|
return () => document.removeEventListener("mousedown", handler);
|
|
@@ -5602,10 +5613,11 @@ function SpecialCharactersButton({
|
|
|
5602
5613
|
const cell = gridRef.current.children[focusedIdx];
|
|
5603
5614
|
cell == null ? void 0 : cell.focus();
|
|
5604
5615
|
}, [focusedIdx]);
|
|
5605
|
-
return /* @__PURE__ */ jsxs(
|
|
5616
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5606
5617
|
/* @__PURE__ */ jsx(
|
|
5607
5618
|
"button",
|
|
5608
5619
|
{
|
|
5620
|
+
ref: buttonRef,
|
|
5609
5621
|
type: "button",
|
|
5610
5622
|
title: "Special Characters",
|
|
5611
5623
|
"aria-label": "Insert special character",
|
|
@@ -5613,7 +5625,11 @@ function SpecialCharactersButton({
|
|
|
5613
5625
|
"aria-expanded": open,
|
|
5614
5626
|
onMouseDown: (e) => {
|
|
5615
5627
|
e.preventDefault();
|
|
5616
|
-
|
|
5628
|
+
if (open) {
|
|
5629
|
+
closeModal();
|
|
5630
|
+
} else {
|
|
5631
|
+
openModal();
|
|
5632
|
+
}
|
|
5617
5633
|
},
|
|
5618
5634
|
className: [
|
|
5619
5635
|
"flex items-center justify-center w-8 h-8 rounded text-sm font-medium transition-colors",
|
|
@@ -5622,127 +5638,131 @@ function SpecialCharactersButton({
|
|
|
5622
5638
|
children: /* @__PURE__ */ jsx(OmegaIcon, {})
|
|
5623
5639
|
}
|
|
5624
5640
|
),
|
|
5625
|
-
open &&
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
/* @__PURE__ */
|
|
5641
|
-
"
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
] }),
|
|
5651
|
-
/* @__PURE__ */ jsx(
|
|
5652
|
-
"input",
|
|
5653
|
-
{
|
|
5654
|
-
ref: searchRef,
|
|
5655
|
-
type: "search",
|
|
5656
|
-
placeholder: "Search characters\u2026",
|
|
5657
|
-
value: search,
|
|
5658
|
-
onChange: (e) => {
|
|
5659
|
-
setSearch(e.target.value);
|
|
5660
|
-
setFocusedIdx(-1);
|
|
5661
|
-
},
|
|
5662
|
-
onKeyDown: (e) => {
|
|
5663
|
-
var _a, _b;
|
|
5664
|
-
if (e.key === "Escape") closeModal();
|
|
5665
|
-
if (e.key === "ArrowDown") {
|
|
5666
|
-
e.preventDefault();
|
|
5667
|
-
setFocusedIdx(0);
|
|
5668
|
-
(_b = (_a = gridRef.current) == null ? void 0 : _a.children[0]) == null ? void 0 : _b.dispatchEvent(
|
|
5669
|
-
new Event("focus")
|
|
5670
|
-
);
|
|
5641
|
+
open && createPortal(
|
|
5642
|
+
/* @__PURE__ */ jsxs(
|
|
5643
|
+
"div",
|
|
5644
|
+
{
|
|
5645
|
+
ref: popupRef,
|
|
5646
|
+
role: "dialog",
|
|
5647
|
+
"aria-label": "Special characters",
|
|
5648
|
+
"aria-modal": "true",
|
|
5649
|
+
className: "bg-white border border-gray-200 rounded-lg shadow-2xl flex flex-col",
|
|
5650
|
+
style: { position: "fixed", top: popupPos.top, left: popupPos.left, width: 340, maxHeight: 420, zIndex: 9999 },
|
|
5651
|
+
onKeyDown: (e) => {
|
|
5652
|
+
if (e.key === "Escape") closeModal();
|
|
5653
|
+
},
|
|
5654
|
+
children: [
|
|
5655
|
+
/* @__PURE__ */ jsxs("div", { className: "px-3 pt-3 pb-2 border-b border-gray-100 ", children: [
|
|
5656
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
5657
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-gray-500 uppercase tracking-wide", children: "Special Characters" }),
|
|
5658
|
+
/* @__PURE__ */ jsx(
|
|
5659
|
+
"button",
|
|
5660
|
+
{
|
|
5661
|
+
type: "button",
|
|
5662
|
+
onClick: closeModal,
|
|
5663
|
+
"aria-label": "Close",
|
|
5664
|
+
className: "text-gray-400 hover:text-gray-600 p-0.5 rounded",
|
|
5665
|
+
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
5671
5666
|
}
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1 mt-2", children: CATEGORIES.map((cat) => /* @__PURE__ */ jsx(
|
|
5677
|
-
"button",
|
|
5678
|
-
{
|
|
5679
|
-
type: "button",
|
|
5680
|
-
onMouseDown: (e) => {
|
|
5681
|
-
e.preventDefault();
|
|
5682
|
-
setCategory(cat);
|
|
5683
|
-
setFocusedIdx(-1);
|
|
5684
|
-
},
|
|
5685
|
-
className: [
|
|
5686
|
-
"px-2 py-0.5 rounded text-xs font-medium transition-colors",
|
|
5687
|
-
category === cat ? "bg-blue-600 text-white" : "bg-gray-100 text-gray-600 hover:bg-gray-200 "
|
|
5688
|
-
].join(" "),
|
|
5689
|
-
children: cat
|
|
5690
|
-
},
|
|
5691
|
-
cat
|
|
5692
|
-
)) })
|
|
5693
|
-
] }),
|
|
5694
|
-
/* @__PURE__ */ jsx(
|
|
5695
|
-
"div",
|
|
5696
|
-
{
|
|
5697
|
-
ref: gridRef,
|
|
5698
|
-
role: "grid",
|
|
5699
|
-
"aria-label": "Character grid",
|
|
5700
|
-
className: "flex-1 overflow-y-auto p-2",
|
|
5701
|
-
style: {
|
|
5702
|
-
display: "grid",
|
|
5703
|
-
gridTemplateColumns: "repeat(8, 1fr)",
|
|
5704
|
-
gap: 2
|
|
5705
|
-
},
|
|
5706
|
-
onKeyDown: handleGridKeyDown,
|
|
5707
|
-
children: filtered.length === 0 ? /* @__PURE__ */ jsx(
|
|
5708
|
-
"div",
|
|
5667
|
+
)
|
|
5668
|
+
] }),
|
|
5669
|
+
/* @__PURE__ */ jsx(
|
|
5670
|
+
"input",
|
|
5709
5671
|
{
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5672
|
+
ref: searchRef,
|
|
5673
|
+
type: "search",
|
|
5674
|
+
placeholder: "Search characters\u2026",
|
|
5675
|
+
value: search,
|
|
5676
|
+
onChange: (e) => {
|
|
5677
|
+
setSearch(e.target.value);
|
|
5678
|
+
setFocusedIdx(-1);
|
|
5679
|
+
},
|
|
5680
|
+
onKeyDown: (e) => {
|
|
5681
|
+
var _a, _b;
|
|
5682
|
+
if (e.key === "Escape") closeModal();
|
|
5683
|
+
if (e.key === "ArrowDown") {
|
|
5684
|
+
e.preventDefault();
|
|
5685
|
+
setFocusedIdx(0);
|
|
5686
|
+
(_b = (_a = gridRef.current) == null ? void 0 : _a.children[0]) == null ? void 0 : _b.dispatchEvent(
|
|
5687
|
+
new Event("focus")
|
|
5688
|
+
);
|
|
5689
|
+
}
|
|
5690
|
+
},
|
|
5691
|
+
className: "w-full border border-gray-200 rounded px-2.5 py-1.5 text-sm bg-white text-gray-900 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
5713
5692
|
}
|
|
5714
|
-
)
|
|
5693
|
+
),
|
|
5694
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1 mt-2", children: CATEGORIES.map((cat) => /* @__PURE__ */ jsx(
|
|
5715
5695
|
"button",
|
|
5716
5696
|
{
|
|
5717
5697
|
type: "button",
|
|
5718
|
-
role: "gridcell",
|
|
5719
|
-
tabIndex: focusedIdx === idx ? 0 : -1,
|
|
5720
|
-
"aria-label": c.name,
|
|
5721
|
-
title: c.name,
|
|
5722
5698
|
onMouseDown: (e) => {
|
|
5723
5699
|
e.preventDefault();
|
|
5724
|
-
|
|
5700
|
+
setCategory(cat);
|
|
5701
|
+
setFocusedIdx(-1);
|
|
5725
5702
|
},
|
|
5726
|
-
onMouseEnter: () => setHovered({ char: c.char, name: c.name }),
|
|
5727
|
-
onMouseLeave: () => setHovered(null),
|
|
5728
|
-
onFocus: () => setHovered({ char: c.char, name: c.name }),
|
|
5729
|
-
onBlur: () => setHovered(null),
|
|
5730
5703
|
className: [
|
|
5731
|
-
"
|
|
5732
|
-
|
|
5704
|
+
"px-2 py-0.5 rounded text-xs font-medium transition-colors",
|
|
5705
|
+
category === cat ? "bg-blue-600 text-white" : "bg-gray-100 text-gray-600 hover:bg-gray-200 "
|
|
5733
5706
|
].join(" "),
|
|
5734
|
-
children:
|
|
5707
|
+
children: cat
|
|
5735
5708
|
},
|
|
5736
|
-
|
|
5737
|
-
))
|
|
5738
|
-
}
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5709
|
+
cat
|
|
5710
|
+
)) })
|
|
5711
|
+
] }),
|
|
5712
|
+
/* @__PURE__ */ jsx(
|
|
5713
|
+
"div",
|
|
5714
|
+
{
|
|
5715
|
+
ref: gridRef,
|
|
5716
|
+
role: "grid",
|
|
5717
|
+
"aria-label": "Character grid",
|
|
5718
|
+
className: "flex-1 overflow-y-auto p-2",
|
|
5719
|
+
style: {
|
|
5720
|
+
display: "grid",
|
|
5721
|
+
gridTemplateColumns: "repeat(8, 1fr)",
|
|
5722
|
+
gap: 2
|
|
5723
|
+
},
|
|
5724
|
+
onKeyDown: handleGridKeyDown,
|
|
5725
|
+
children: filtered.length === 0 ? /* @__PURE__ */ jsx(
|
|
5726
|
+
"div",
|
|
5727
|
+
{
|
|
5728
|
+
className: "col-span-8 text-center py-8 text-sm text-gray-400 ",
|
|
5729
|
+
role: "status",
|
|
5730
|
+
children: "No characters found"
|
|
5731
|
+
}
|
|
5732
|
+
) : filtered.map((c, idx) => /* @__PURE__ */ jsx(
|
|
5733
|
+
"button",
|
|
5734
|
+
{
|
|
5735
|
+
type: "button",
|
|
5736
|
+
role: "gridcell",
|
|
5737
|
+
tabIndex: focusedIdx === idx ? 0 : -1,
|
|
5738
|
+
"aria-label": c.name,
|
|
5739
|
+
title: c.name,
|
|
5740
|
+
onMouseDown: (e) => {
|
|
5741
|
+
e.preventDefault();
|
|
5742
|
+
insertChar(c.char);
|
|
5743
|
+
},
|
|
5744
|
+
onMouseEnter: () => setHovered({ char: c.char, name: c.name }),
|
|
5745
|
+
onMouseLeave: () => setHovered(null),
|
|
5746
|
+
onFocus: () => setHovered({ char: c.char, name: c.name }),
|
|
5747
|
+
onBlur: () => setHovered(null),
|
|
5748
|
+
className: [
|
|
5749
|
+
"flex items-center justify-center rounded text-base h-8 w-full transition-colors cursor-pointer select-none",
|
|
5750
|
+
focusedIdx === idx ? "bg-blue-100 text-blue-700 ring-2 ring-blue-500" : "text-gray-800 hover:bg-blue-50 hover:text-blue-700 "
|
|
5751
|
+
].join(" "),
|
|
5752
|
+
children: c.char
|
|
5753
|
+
},
|
|
5754
|
+
c.char + c.name
|
|
5755
|
+
))
|
|
5756
|
+
}
|
|
5757
|
+
),
|
|
5758
|
+
/* @__PURE__ */ jsx("div", { className: "px-3 py-2 border-t border-gray-100 flex items-center gap-3 min-h-[40px]", children: hovered ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5759
|
+
/* @__PURE__ */ jsx("span", { className: "text-2xl leading-none text-gray-800 w-8 text-center", children: hovered.char }),
|
|
5760
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-gray-500 truncate", children: hovered.name })
|
|
5761
|
+
] }) : /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400 ", children: "Hover or use arrow keys to preview" }) })
|
|
5762
|
+
]
|
|
5763
|
+
}
|
|
5764
|
+
),
|
|
5765
|
+
document.body
|
|
5746
5766
|
)
|
|
5747
5767
|
] });
|
|
5748
5768
|
}
|
|
@@ -8607,6 +8627,53 @@ function prettyPrintHTML(html) {
|
|
|
8607
8627
|
}
|
|
8608
8628
|
|
|
8609
8629
|
// src/editor/table/TablePlugin.ts
|
|
8630
|
+
function getCellDOMElement(cellPathJson) {
|
|
8631
|
+
return document.querySelector(`[data-block-path='${cellPathJson}']`);
|
|
8632
|
+
}
|
|
8633
|
+
function isCaretAtContainerStart(container) {
|
|
8634
|
+
const sel = window.getSelection();
|
|
8635
|
+
if (!sel || sel.rangeCount === 0 || !sel.isCollapsed) return false;
|
|
8636
|
+
const range = sel.getRangeAt(0);
|
|
8637
|
+
if (range.startOffset !== 0) return false;
|
|
8638
|
+
let node = range.startContainer;
|
|
8639
|
+
while (node && node !== container) {
|
|
8640
|
+
if (node.previousSibling) return false;
|
|
8641
|
+
node = node.parentNode;
|
|
8642
|
+
}
|
|
8643
|
+
return node === container;
|
|
8644
|
+
}
|
|
8645
|
+
function isCaretAtContainerEnd(container) {
|
|
8646
|
+
var _a, _b;
|
|
8647
|
+
const sel = window.getSelection();
|
|
8648
|
+
if (!sel || sel.rangeCount === 0 || !sel.isCollapsed) return false;
|
|
8649
|
+
const range = sel.getRangeAt(0);
|
|
8650
|
+
const endNode = range.endContainer;
|
|
8651
|
+
const endOffset = range.endOffset;
|
|
8652
|
+
const len = endNode.nodeType === Node.TEXT_NODE ? (_b = (_a = endNode.textContent) == null ? void 0 : _a.length) != null ? _b : 0 : endNode.childNodes.length;
|
|
8653
|
+
if (endOffset !== len) return false;
|
|
8654
|
+
let node = endNode;
|
|
8655
|
+
while (node && node !== container) {
|
|
8656
|
+
if (node.nextSibling) return false;
|
|
8657
|
+
node = node.parentNode;
|
|
8658
|
+
}
|
|
8659
|
+
return node === container;
|
|
8660
|
+
}
|
|
8661
|
+
function isCaretOnEdgeLine(container, direction) {
|
|
8662
|
+
const sel = window.getSelection();
|
|
8663
|
+
if (!sel || sel.rangeCount === 0 || !sel.isCollapsed) return false;
|
|
8664
|
+
const caretRange = sel.getRangeAt(0).cloneRange();
|
|
8665
|
+
caretRange.collapse(true);
|
|
8666
|
+
const caretRects = caretRange.getClientRects();
|
|
8667
|
+
if (!caretRects.length) return true;
|
|
8668
|
+
const caretRect = caretRects[0];
|
|
8669
|
+
const containerRect = container.getBoundingClientRect();
|
|
8670
|
+
const lineHeight = parseFloat(getComputedStyle(container).lineHeight) || 20;
|
|
8671
|
+
if (direction === "up") {
|
|
8672
|
+
return caretRect.top < containerRect.top + lineHeight;
|
|
8673
|
+
} else {
|
|
8674
|
+
return caretRect.bottom > containerRect.bottom - lineHeight;
|
|
8675
|
+
}
|
|
8676
|
+
}
|
|
8610
8677
|
var TablePlugin = {
|
|
8611
8678
|
name: "table",
|
|
8612
8679
|
keyBindings: {
|
|
@@ -8657,6 +8724,125 @@ var TablePlugin = {
|
|
|
8657
8724
|
engine.dispatch(tr);
|
|
8658
8725
|
return true;
|
|
8659
8726
|
},
|
|
8727
|
+
"ArrowRight": (engine) => {
|
|
8728
|
+
var _a;
|
|
8729
|
+
const state = engine.getState();
|
|
8730
|
+
const sel = state.selection;
|
|
8731
|
+
if (!sel) return false;
|
|
8732
|
+
const cellPos = findCellPosition(state.doc, sel.anchor.path);
|
|
8733
|
+
if (!cellPos) return false;
|
|
8734
|
+
const { tablePath, row, col } = cellPos;
|
|
8735
|
+
const cellPath = [...tablePath, row, col];
|
|
8736
|
+
const cellEl = getCellDOMElement(JSON.stringify(cellPath));
|
|
8737
|
+
if (!cellEl || !isCaretAtContainerEnd(cellEl)) return false;
|
|
8738
|
+
const table = getNodeAtPath(state.doc, tablePath);
|
|
8739
|
+
const { rows, cols } = getTableDimensions(table);
|
|
8740
|
+
let nextRow = row;
|
|
8741
|
+
let nextCol = col + 1;
|
|
8742
|
+
while (nextRow < rows) {
|
|
8743
|
+
if (nextCol >= cols) {
|
|
8744
|
+
nextCol = 0;
|
|
8745
|
+
nextRow++;
|
|
8746
|
+
continue;
|
|
8747
|
+
}
|
|
8748
|
+
const c = getNodeAtPath(state.doc, [...tablePath, nextRow, nextCol]);
|
|
8749
|
+
if (!((_a = c == null ? void 0 : c.attrs) == null ? void 0 : _a.covered)) break;
|
|
8750
|
+
nextCol++;
|
|
8751
|
+
}
|
|
8752
|
+
if (nextRow >= rows) return true;
|
|
8753
|
+
const pos = getCellFirstPosition(state.doc, tablePath, nextRow, nextCol);
|
|
8754
|
+
if (!pos) return false;
|
|
8755
|
+
const tr = createTransaction();
|
|
8756
|
+
tr.steps.push(tr_setSelection(makeCollapsedSelection(pos)));
|
|
8757
|
+
engine.dispatch(tr);
|
|
8758
|
+
return true;
|
|
8759
|
+
},
|
|
8760
|
+
"ArrowLeft": (engine) => {
|
|
8761
|
+
var _a;
|
|
8762
|
+
const state = engine.getState();
|
|
8763
|
+
const sel = state.selection;
|
|
8764
|
+
if (!sel) return false;
|
|
8765
|
+
const cellPos = findCellPosition(state.doc, sel.anchor.path);
|
|
8766
|
+
if (!cellPos) return false;
|
|
8767
|
+
const { tablePath, row, col } = cellPos;
|
|
8768
|
+
const cellPath = [...tablePath, row, col];
|
|
8769
|
+
const cellEl = getCellDOMElement(JSON.stringify(cellPath));
|
|
8770
|
+
if (!cellEl || !isCaretAtContainerStart(cellEl)) return false;
|
|
8771
|
+
const table = getNodeAtPath(state.doc, tablePath);
|
|
8772
|
+
const { cols } = getTableDimensions(table);
|
|
8773
|
+
let prevRow = row;
|
|
8774
|
+
let prevCol = col - 1;
|
|
8775
|
+
while (prevRow >= 0) {
|
|
8776
|
+
if (prevCol < 0) {
|
|
8777
|
+
prevCol = cols - 1;
|
|
8778
|
+
prevRow--;
|
|
8779
|
+
continue;
|
|
8780
|
+
}
|
|
8781
|
+
const c = getNodeAtPath(state.doc, [...tablePath, prevRow, prevCol]);
|
|
8782
|
+
if (!((_a = c == null ? void 0 : c.attrs) == null ? void 0 : _a.covered)) break;
|
|
8783
|
+
prevCol--;
|
|
8784
|
+
}
|
|
8785
|
+
if (prevRow < 0) return true;
|
|
8786
|
+
const pos = getCellLastPosition(state.doc, tablePath, prevRow, prevCol);
|
|
8787
|
+
if (!pos) return false;
|
|
8788
|
+
const tr = createTransaction();
|
|
8789
|
+
tr.steps.push(tr_setSelection(makeCollapsedSelection(pos)));
|
|
8790
|
+
engine.dispatch(tr);
|
|
8791
|
+
return true;
|
|
8792
|
+
},
|
|
8793
|
+
"ArrowDown": (engine) => {
|
|
8794
|
+
var _a;
|
|
8795
|
+
const state = engine.getState();
|
|
8796
|
+
const sel = state.selection;
|
|
8797
|
+
if (!sel) return false;
|
|
8798
|
+
const cellPos = findCellPosition(state.doc, sel.anchor.path);
|
|
8799
|
+
if (!cellPos) return false;
|
|
8800
|
+
const { tablePath, row, col } = cellPos;
|
|
8801
|
+
const cellPath = [...tablePath, row, col];
|
|
8802
|
+
const cellEl = getCellDOMElement(JSON.stringify(cellPath));
|
|
8803
|
+
if (!cellEl || !isCaretOnEdgeLine(cellEl, "down")) return false;
|
|
8804
|
+
const table = getNodeAtPath(state.doc, tablePath);
|
|
8805
|
+
const { rows, cols } = getTableDimensions(table);
|
|
8806
|
+
let nextRow = row + 1;
|
|
8807
|
+
while (nextRow < rows) {
|
|
8808
|
+
const c = getNodeAtPath(state.doc, [...tablePath, nextRow, col]);
|
|
8809
|
+
if (c && !((_a = c.attrs) == null ? void 0 : _a.covered)) break;
|
|
8810
|
+
nextRow++;
|
|
8811
|
+
}
|
|
8812
|
+
if (nextRow >= rows) return false;
|
|
8813
|
+
const pos = getCellFirstPosition(state.doc, tablePath, nextRow, col < cols ? col : 0);
|
|
8814
|
+
if (!pos) return false;
|
|
8815
|
+
const tr = createTransaction();
|
|
8816
|
+
tr.steps.push(tr_setSelection(makeCollapsedSelection(pos)));
|
|
8817
|
+
engine.dispatch(tr);
|
|
8818
|
+
return true;
|
|
8819
|
+
},
|
|
8820
|
+
"ArrowUp": (engine) => {
|
|
8821
|
+
var _a;
|
|
8822
|
+
const state = engine.getState();
|
|
8823
|
+
const sel = state.selection;
|
|
8824
|
+
if (!sel) return false;
|
|
8825
|
+
const cellPos = findCellPosition(state.doc, sel.anchor.path);
|
|
8826
|
+
if (!cellPos) return false;
|
|
8827
|
+
const { tablePath, row, col } = cellPos;
|
|
8828
|
+
const cellPath = [...tablePath, row, col];
|
|
8829
|
+
const cellEl = getCellDOMElement(JSON.stringify(cellPath));
|
|
8830
|
+
if (!cellEl || !isCaretOnEdgeLine(cellEl, "up")) return false;
|
|
8831
|
+
let prevRow = row - 1;
|
|
8832
|
+
while (prevRow >= 0) {
|
|
8833
|
+
const c = getNodeAtPath(state.doc, [...tablePath, prevRow, col]);
|
|
8834
|
+
if (c && !((_a = c.attrs) == null ? void 0 : _a.covered)) break;
|
|
8835
|
+
prevRow--;
|
|
8836
|
+
}
|
|
8837
|
+
if (prevRow < 0) return false;
|
|
8838
|
+
const { cols } = getTableDimensions(getNodeAtPath(state.doc, tablePath));
|
|
8839
|
+
const pos = getCellLastPosition(state.doc, tablePath, prevRow, col < cols ? col : 0);
|
|
8840
|
+
if (!pos) return false;
|
|
8841
|
+
const tr = createTransaction();
|
|
8842
|
+
tr.steps.push(tr_setSelection(makeCollapsedSelection(pos)));
|
|
8843
|
+
engine.dispatch(tr);
|
|
8844
|
+
return true;
|
|
8845
|
+
},
|
|
8660
8846
|
"Shift+Tab": (engine) => {
|
|
8661
8847
|
var _a;
|
|
8662
8848
|
const state = engine.getState();
|