@stll/folio-react 0.18.0 → 0.18.2
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.
|
@@ -9,6 +9,7 @@ import { IntlProvider, useTranslations } from "use-intl";
|
|
|
9
9
|
import { FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, createFolioAIEditSnapshot, getCommentAnchorsFromDoc, getFolioDocumentOperationIssues, getTrackedChangesFromDoc } from "@stll/folio-core/ai-edits";
|
|
10
10
|
import { resolveActiveEditorStory } from "@stll/folio-core/controller/activeEditorStory";
|
|
11
11
|
import { FOLIO_DOCX_SERIALIZATION_MODE, createFolioEditor } from "@stll/folio-core/controller/folioEditor";
|
|
12
|
+
import { cloneDocumentWithParagraphPropertySources } from "@stll/folio-core/docx/document-clone";
|
|
12
13
|
import { normalizeBaseDirection } from "@stll/folio-core/docx/normalizeBaseDirection";
|
|
13
14
|
import { getCachedNumberingMap } from "@stll/folio-core/docx/numberingParser";
|
|
14
15
|
import { computeScrollPageInfo, updateScrollPageTotal } from "@stll/folio-core/paged-layout/scrollPageInfo";
|
|
@@ -54,14 +55,16 @@ import { documentFontsAreLoaded, getDocumentFontSet, waitForInitialLayoutFonts }
|
|
|
54
55
|
import { getFootnoteText } from "@stll/folio-core/docx/footnoteParser";
|
|
55
56
|
import { convertHeaderFooterPmDocToContent, convertHeaderFooterToContent } from "@stll/folio-core/layout-bridge/convert/headerFooterLayout";
|
|
56
57
|
import { templatePreviewDirtyRange } from "@stll/folio-core/layout-bridge/convert/templatePreviewFlow";
|
|
57
|
-
import { clickToPositionDom,
|
|
58
|
+
import { clickToPositionDom, getCaretPositionFromDom, getSelectionRectsFromDom } from "@stll/folio-core/layout-bridge/dom/clickToPositionDom";
|
|
59
|
+
import { measurePaintedSpanRange } from "@stll/folio-core/layout-bridge/dom/textStreamDom";
|
|
58
60
|
import { resetImeCaretAnchor, syncImeCaretAnchor } from "@stll/folio-core/layout-bridge/dom/imeCaretAnchor";
|
|
59
|
-
import {
|
|
60
|
-
import { clickToPositionInHfSlot,
|
|
61
|
+
import { findBodyPmAnchor, findBodyPmAnchors, findBodyPmSpans } from "@stll/folio-core/layout-bridge/dom/findBodyPmSpans";
|
|
62
|
+
import { clickToPositionInHfSlot, findHfSlotForTarget, findHfSlotKindForTarget } from "@stll/folio-core/layout-bridge/dom/findHfPmSpans";
|
|
61
63
|
import { findNoteStoryForTarget } from "@stll/folio-core/layout-bridge/dom/noteStoryDom";
|
|
62
64
|
import { clickToPosition } from "@stll/folio-core/layout-bridge/engine/clickToPosition";
|
|
63
65
|
import { getPageTop, hitTestFragment, hitTestTableCell } from "@stll/folio-core/layout-bridge/engine/hitTest";
|
|
64
66
|
import { clearAllCaches, resetCanvasContext } from "@stll/folio-core/layout-bridge/engine/measuring";
|
|
67
|
+
import { resolveHeaderFooterSelectionGeometry } from "@stll/folio-core/render-dom/HeaderFooterSelectionOverlay";
|
|
65
68
|
import { setEmbeddedFontFamilyMap } from "@stll/folio-core/utils/fontResolver";
|
|
66
69
|
import { resolveSectionHeaderFooterRefs } from "@stll/folio-core/layout-engine";
|
|
67
70
|
import { recordLayoutPhase } from "@stll/folio-core/layout-engine/layoutInstrumentation";
|
|
@@ -77,12 +80,13 @@ import { flashParagraphFragmentsByParaId } from "@stll/folio-core/paged-layout/p
|
|
|
77
80
|
import { DEFAULT_PAGE_HEIGHT_PX, getMargins, getPageSize, twipsToPixels as twipsToPixels$1 } from "@stll/folio-core/paged-layout/sectionGeometry";
|
|
78
81
|
import { resizeColumnPair } from "@stll/folio-core/paged-layout/tableColumnResize";
|
|
79
82
|
import { tableInsertButtonOffset } from "@stll/folio-core/paged-layout/tableInsertButtonGeometry";
|
|
80
|
-
import {
|
|
83
|
+
import { getTransactionsDirtyRange } from "@stll/folio-core/paged-layout/transactionDirtyRange";
|
|
81
84
|
import { findStartPosForParaId } from "@stll/folio-core/prosemirror/utils/findParagraphByParaId";
|
|
82
85
|
import { buildEmbeddedFontFamilyMap, extractEmbeddedFonts } from "@stll/folio-core/fonts/embeddedFonts";
|
|
83
86
|
import { panic } from "better-result";
|
|
84
87
|
import { collectRemoteSelections, createHiddenEditorManager, createHiddenEditorState } from "@stll/folio-core/controller/hiddenEditorManager";
|
|
85
88
|
import { loadCollaborationModules } from "@stll/folio-core/controller/collaborationModules";
|
|
89
|
+
import { createVisualLineState, handleVisualLineKeyDown } from "@stll/folio-core/prosemirror/utils/visualLineNavigation";
|
|
86
90
|
import { clampRangeToDocSize, resolveFolioAIBlockRange, resolveFolioAITextRange, resolvePassageRange } from "@stll/folio-core/ai-edits/blockRange";
|
|
87
91
|
import { getFolioParaIdFromBlockId } from "@stll/folio-core/types/block-id";
|
|
88
92
|
import { getPageTextFromLayout } from "@stll/folio-core/paged-layout/pageText";
|
|
@@ -1264,7 +1268,7 @@ const HiddenProseMirror = forwardRef((props, ref) => {
|
|
|
1264
1268
|
getReadOnly: () => readOnlyRef.current,
|
|
1265
1269
|
getDocumentIdentity: () => documentIdentityRef.current,
|
|
1266
1270
|
getDocumentContext: () => documentRef.current,
|
|
1267
|
-
onTransaction: (
|
|
1271
|
+
onTransaction: (update) => onTransactionRef.current?.(update),
|
|
1268
1272
|
onSelectionChange: (state) => onSelectionChangeRef.current?.(state),
|
|
1269
1273
|
onKeyDown: (view, event) => onKeyDownRef.current?.(view, event) ?? false,
|
|
1270
1274
|
onCopy: () => onCopyRef.current?.(),
|
|
@@ -2162,7 +2166,7 @@ const MAX_SPEED = 12;
|
|
|
2162
2166
|
/**
|
|
2163
2167
|
* Find the nearest scrollable ancestor.
|
|
2164
2168
|
*/
|
|
2165
|
-
function findScrollParent
|
|
2169
|
+
function findScrollParent(el) {
|
|
2166
2170
|
let parent = el.parentElement;
|
|
2167
2171
|
while (parent && parent !== document.documentElement) {
|
|
2168
2172
|
const { overflowY } = getComputedStyle(parent);
|
|
@@ -2183,7 +2187,7 @@ function useDragAutoScroll({ pagesContainerRef, onScrollExtendSelection }) {
|
|
|
2183
2187
|
if (scrollParentRef.current) return scrollParentRef.current;
|
|
2184
2188
|
const pages = pagesContainerRef.current;
|
|
2185
2189
|
if (!pages) return null;
|
|
2186
|
-
scrollParentRef.current = findScrollParent
|
|
2190
|
+
scrollParentRef.current = findScrollParent(pages);
|
|
2187
2191
|
return scrollParentRef.current;
|
|
2188
2192
|
}, [pagesContainerRef]);
|
|
2189
2193
|
const stopAutoScroll = useCallback(() => {
|
|
@@ -2236,246 +2240,30 @@ function useDragAutoScroll({ pagesContainerRef, onScrollExtendSelection }) {
|
|
|
2236
2240
|
}
|
|
2237
2241
|
//#endregion
|
|
2238
2242
|
//#region src/paged-editor/useVisualLineNavigation.ts
|
|
2239
|
-
/**
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
}
|
|
2264
|
-
return null;
|
|
2265
|
-
}
|
|
2266
|
-
/**
|
|
2267
|
-
* Scroll the nearest scrollable ancestor so that the target element is visible.
|
|
2268
|
-
* Uses manual scroll math because `scrollIntoView` misbehaves when the
|
|
2269
|
-
* content is inside a CSS `transform: scale()` viewport.
|
|
2270
|
-
*/
|
|
2271
|
-
function scrollIntoViewIfNeeded(el) {
|
|
2272
|
-
const container = findScrollParent(el);
|
|
2273
|
-
if (!container) return;
|
|
2274
|
-
const elRect = el.getBoundingClientRect();
|
|
2275
|
-
const containerRect = container.getBoundingClientRect();
|
|
2276
|
-
const margin = 40;
|
|
2277
|
-
if (elRect.bottom > containerRect.bottom - margin) container.scrollTop += elRect.bottom - containerRect.bottom + margin;
|
|
2278
|
-
else if (elRect.top < containerRect.top + margin) container.scrollTop -= containerRect.top - elRect.top + margin;
|
|
2279
|
-
}
|
|
2280
|
-
function useVisualLineNavigation({ pagesContainerRef }) {
|
|
2281
|
-
const stickyXRef = useRef(null);
|
|
2282
|
-
const lastVisualLineIndexRef = useRef(-1);
|
|
2283
|
-
/**
|
|
2284
|
-
* Get the client X coordinate of the caret at a PM position.
|
|
2285
|
-
*/
|
|
2286
|
-
const getCaretClientX = useCallback((pmPos) => {
|
|
2287
|
-
if (!pagesContainerRef.current) return null;
|
|
2288
|
-
const spans = findBodyPmSpans(pagesContainerRef.current);
|
|
2289
|
-
for (const spanEl of spans) {
|
|
2290
|
-
const pmStart = Number(spanEl.dataset["pmStart"]);
|
|
2291
|
-
const pmEnd = Number(spanEl.dataset["pmEnd"]);
|
|
2292
|
-
if (spanEl.classList.contains("layout-run-tab")) {
|
|
2293
|
-
if (pmPos >= pmStart && pmPos < pmEnd) return spanEl.getBoundingClientRect().left;
|
|
2294
|
-
continue;
|
|
2295
|
-
}
|
|
2296
|
-
if (pmPos >= pmStart && pmPos <= pmEnd && spanEl.firstChild?.nodeType === Node.TEXT_NODE) {
|
|
2297
|
-
const textNode = spanEl.firstChild;
|
|
2298
|
-
const charIndex = Math.min(pmPos - pmStart, textNode.length);
|
|
2299
|
-
const range = spanEl.ownerDocument.createRange();
|
|
2300
|
-
range.setStart(textNode, charIndex);
|
|
2301
|
-
range.setEnd(textNode, charIndex);
|
|
2302
|
-
return range.getBoundingClientRect().left;
|
|
2303
|
-
}
|
|
2304
|
-
if (pmPos >= pmStart && pmPos <= pmEnd) return spanEl.getBoundingClientRect().left;
|
|
2305
|
-
}
|
|
2306
|
-
const emptyRuns = findBodyEmptyRuns(pagesContainerRef.current);
|
|
2307
|
-
for (const emptyRun of emptyRuns) {
|
|
2308
|
-
const paragraph = closestHtmlElement(emptyRun, ".layout-paragraph");
|
|
2309
|
-
if (!paragraph) continue;
|
|
2310
|
-
const pmStart_0 = Number(paragraph.dataset["pmStart"]);
|
|
2311
|
-
const pmEnd_0 = Number(paragraph.dataset["pmEnd"]);
|
|
2312
|
-
if (pmPos >= pmStart_0 && pmPos <= pmEnd_0) return emptyRun.getBoundingClientRect().left;
|
|
2313
|
-
}
|
|
2314
|
-
return null;
|
|
2315
|
-
}, [pagesContainerRef]);
|
|
2316
|
-
/**
|
|
2317
|
-
* Find the visual line element (.layout-line) containing a PM position.
|
|
2318
|
-
*/
|
|
2319
|
-
const findLineElementAtPosition = useCallback((pmPos_0) => {
|
|
2320
|
-
if (!pagesContainerRef.current) return null;
|
|
2321
|
-
const allLines = htmlQueryAll(pagesContainerRef.current, CONTENT_LINE_SELECTOR);
|
|
2322
|
-
for (const lineEl of allLines) {
|
|
2323
|
-
const spans_0 = htmlQueryAll(lineEl, "span[data-pm-start][data-pm-end]");
|
|
2324
|
-
for (const span of spans_0) {
|
|
2325
|
-
const start = Number(span.dataset["pmStart"]);
|
|
2326
|
-
const end = Number(span.dataset["pmEnd"]);
|
|
2327
|
-
if (pmPos_0 >= start && pmPos_0 <= end) return lineEl;
|
|
2328
|
-
}
|
|
2329
|
-
}
|
|
2330
|
-
for (const lineEl_0 of allLines) {
|
|
2331
|
-
const paragraph_0 = closestHtmlElement(lineEl_0, ".layout-paragraph");
|
|
2332
|
-
if (!paragraph_0) continue;
|
|
2333
|
-
const pStart = Number(paragraph_0.dataset["pmStart"]);
|
|
2334
|
-
const pEnd = Number(paragraph_0.dataset["pmEnd"]);
|
|
2335
|
-
if (pmPos_0 >= pStart && pmPos_0 <= pEnd) {
|
|
2336
|
-
if (paragraph_0.querySelector(".layout-line") === lineEl_0) return lineEl_0;
|
|
2337
|
-
}
|
|
2338
|
-
}
|
|
2339
|
-
return null;
|
|
2340
|
-
}, [pagesContainerRef]);
|
|
2341
|
-
/**
|
|
2342
|
-
* Find the PM position on a visual line closest to a client X coordinate.
|
|
2343
|
-
*/
|
|
2344
|
-
const findPositionOnLineAtClientX = useCallback((lineEl_1, clientX) => {
|
|
2345
|
-
const spans_1 = htmlQueryAll(lineEl_1, "span[data-pm-start][data-pm-end]");
|
|
2346
|
-
const emptyRun_0 = lineEl_1.querySelector(".layout-empty-run");
|
|
2347
|
-
if (emptyRun_0) {
|
|
2348
|
-
if (emptyRun_0 instanceof HTMLElement && emptyRun_0.dataset["pmStart"]) return Number(emptyRun_0.dataset["pmStart"]);
|
|
2349
|
-
const paragraph_1 = closestHtmlElement(lineEl_1, ".layout-paragraph");
|
|
2350
|
-
if (paragraph_1?.dataset["pmStart"]) return Number(paragraph_1.dataset["pmStart"]) + 1;
|
|
2351
|
-
return null;
|
|
2352
|
-
}
|
|
2353
|
-
if (spans_1.length === 0) {
|
|
2354
|
-
const paragraph_2 = closestHtmlElement(lineEl_1, ".layout-paragraph");
|
|
2355
|
-
if (paragraph_2?.dataset["pmStart"]) return Number(paragraph_2.dataset["pmStart"]) + 1;
|
|
2356
|
-
return null;
|
|
2357
|
-
}
|
|
2358
|
-
for (const spanEl_0 of spans_1) {
|
|
2359
|
-
const rect = spanEl_0.getBoundingClientRect();
|
|
2360
|
-
const pmStart_1 = Number(spanEl_0.dataset["pmStart"]);
|
|
2361
|
-
const pmEnd_1 = Number(spanEl_0.dataset["pmEnd"]);
|
|
2362
|
-
if (spanEl_0.classList.contains("layout-run-tab")) {
|
|
2363
|
-
if (clientX >= rect.left && clientX <= rect.right) return clientX < (rect.left + rect.right) / 2 ? pmStart_1 : pmEnd_1;
|
|
2364
|
-
continue;
|
|
2365
|
-
}
|
|
2366
|
-
if (clientX >= rect.left && clientX <= rect.right) {
|
|
2367
|
-
const textNode_0 = spanEl_0.firstChild;
|
|
2368
|
-
if (!textNode_0 || textNode_0.nodeType !== Node.TEXT_NODE) return pmStart_1;
|
|
2369
|
-
const text = textNode_0;
|
|
2370
|
-
const ownerDoc_0 = spanEl_0.ownerDocument;
|
|
2371
|
-
let lo = 0;
|
|
2372
|
-
let hi = text.length;
|
|
2373
|
-
while (lo < hi) {
|
|
2374
|
-
const mid_0 = Math.floor((lo + hi) / 2);
|
|
2375
|
-
const r = ownerDoc_0.createRange();
|
|
2376
|
-
r.setStart(text, mid_0);
|
|
2377
|
-
r.setEnd(text, mid_0);
|
|
2378
|
-
if (clientX < r.getBoundingClientRect().left) hi = mid_0;
|
|
2379
|
-
else lo = mid_0 + 1;
|
|
2380
|
-
}
|
|
2381
|
-
if (lo > 0 && lo <= text.length) {
|
|
2382
|
-
const r_0 = ownerDoc_0.createRange();
|
|
2383
|
-
r_0.setStart(text, lo - 1);
|
|
2384
|
-
r_0.setEnd(text, lo - 1);
|
|
2385
|
-
const leftX = r_0.getBoundingClientRect().left;
|
|
2386
|
-
r_0.setStart(text, Math.min(lo, text.length));
|
|
2387
|
-
r_0.setEnd(text, Math.min(lo, text.length));
|
|
2388
|
-
const rightX = r_0.getBoundingClientRect().left;
|
|
2389
|
-
if (Math.abs(clientX - leftX) < Math.abs(clientX - rightX)) return pmStart_1 + (lo - 1);
|
|
2390
|
-
}
|
|
2391
|
-
return pmStart_1 + Math.min(lo, pmEnd_1 - pmStart_1);
|
|
2392
|
-
}
|
|
2393
|
-
}
|
|
2394
|
-
let closestSpan = null;
|
|
2395
|
-
let closestDist = Infinity;
|
|
2396
|
-
for (const span_0 of spans_1) {
|
|
2397
|
-
const rect_0 = span_0.getBoundingClientRect();
|
|
2398
|
-
const dist = clientX < rect_0.left ? rect_0.left - clientX : clientX - rect_0.right;
|
|
2399
|
-
if (dist < closestDist) {
|
|
2400
|
-
closestDist = dist;
|
|
2401
|
-
closestSpan = span_0;
|
|
2402
|
-
}
|
|
2403
|
-
}
|
|
2404
|
-
if (!closestSpan) return null;
|
|
2405
|
-
return clientX < closestSpan.getBoundingClientRect().left ? Number(closestSpan.dataset["pmStart"]) : Number(closestSpan.dataset["pmEnd"]);
|
|
2406
|
-
}, []);
|
|
2407
|
-
return {
|
|
2408
|
-
stickyXRef,
|
|
2409
|
-
lastVisualLineIndexRef,
|
|
2410
|
-
getCaretClientX,
|
|
2411
|
-
findLineElementAtPosition,
|
|
2412
|
-
findPositionOnLineAtClientX,
|
|
2413
|
-
handlePMKeyDown: useCallback((view, event) => {
|
|
2414
|
-
if (event.key !== "ArrowUp" && event.key !== "ArrowDown") {
|
|
2415
|
-
if ([
|
|
2416
|
-
"ArrowLeft",
|
|
2417
|
-
"ArrowRight",
|
|
2418
|
-
"Home",
|
|
2419
|
-
"End"
|
|
2420
|
-
].includes(event.key) || event.key.length === 1 && !event.ctrlKey && !event.metaKey) {
|
|
2421
|
-
stickyXRef.current = null;
|
|
2422
|
-
lastVisualLineIndexRef.current = -1;
|
|
2423
|
-
}
|
|
2424
|
-
return false;
|
|
2425
|
-
}
|
|
2426
|
-
if (event.ctrlKey || event.metaKey) {
|
|
2427
|
-
stickyXRef.current = null;
|
|
2428
|
-
lastVisualLineIndexRef.current = -1;
|
|
2429
|
-
return false;
|
|
2430
|
-
}
|
|
2431
|
-
if (!pagesContainerRef.current) return false;
|
|
2432
|
-
const allLines_0 = htmlQueryAll(pagesContainerRef.current, CONTENT_LINE_SELECTOR);
|
|
2433
|
-
if (allLines_0.length === 0) return false;
|
|
2434
|
-
const { from, anchor } = view.state.selection;
|
|
2435
|
-
if (stickyXRef.current === null) {
|
|
2436
|
-
const clientX_0 = getCaretClientX(from);
|
|
2437
|
-
if (clientX_0 === null) return false;
|
|
2438
|
-
stickyXRef.current = clientX_0;
|
|
2439
|
-
}
|
|
2440
|
-
let currentIndex;
|
|
2441
|
-
if (lastVisualLineIndexRef.current >= 0 && lastVisualLineIndexRef.current < allLines_0.length) currentIndex = lastVisualLineIndexRef.current;
|
|
2442
|
-
else {
|
|
2443
|
-
const currentLine = findLineElementAtPosition(from);
|
|
2444
|
-
if (!currentLine) return false;
|
|
2445
|
-
currentIndex = allLines_0.indexOf(currentLine);
|
|
2446
|
-
if (currentIndex === -1) return false;
|
|
2447
|
-
}
|
|
2448
|
-
const targetIndex = event.key === "ArrowUp" ? currentIndex - 1 : currentIndex + 1;
|
|
2449
|
-
if (targetIndex < 0 || targetIndex >= allLines_0.length) {
|
|
2450
|
-
lastVisualLineIndexRef.current = -1;
|
|
2451
|
-
return false;
|
|
2452
|
-
}
|
|
2453
|
-
const targetLine = allLines_0[targetIndex];
|
|
2454
|
-
if (!targetLine) return false;
|
|
2455
|
-
const newPos = findPositionOnLineAtClientX(targetLine, stickyXRef.current);
|
|
2456
|
-
if (newPos === null) return false;
|
|
2457
|
-
lastVisualLineIndexRef.current = targetIndex;
|
|
2458
|
-
const { state, dispatch } = view;
|
|
2459
|
-
const clampedPos = Math.max(0, Math.min(newPos, state.doc.content.size));
|
|
2460
|
-
const clampedAnchor = Math.max(0, Math.min(anchor, state.doc.content.size));
|
|
2461
|
-
try {
|
|
2462
|
-
const $newPos_0 = state.doc.resolve(clampedPos);
|
|
2463
|
-
const sel_0 = event.shiftKey ? TextSelection$1.between(state.doc.resolve(clampedAnchor), $newPos_0) : Selection.near($newPos_0);
|
|
2464
|
-
dispatch(state.tr.setSelection(sel_0));
|
|
2465
|
-
} catch {
|
|
2466
|
-
const $newPos = state.doc.resolve(clampedPos);
|
|
2467
|
-
const sel = event.shiftKey ? TextSelection$1.between(state.doc.resolve(clampedAnchor), $newPos) : Selection.near($newPos);
|
|
2468
|
-
dispatch(state.tr.setSelection(sel));
|
|
2469
|
-
}
|
|
2470
|
-
scrollIntoViewIfNeeded(targetLine);
|
|
2471
|
-
return true;
|
|
2472
|
-
}, [
|
|
2473
|
-
pagesContainerRef,
|
|
2474
|
-
getCaretClientX,
|
|
2475
|
-
findLineElementAtPosition,
|
|
2476
|
-
findPositionOnLineAtClientX
|
|
2477
|
-
])
|
|
2478
|
-
};
|
|
2243
|
+
/** Bind the framework-neutral visual-line navigation state to React. */
|
|
2244
|
+
function useVisualLineNavigation(t0) {
|
|
2245
|
+
const $ = c(5);
|
|
2246
|
+
const { pagesContainerRef } = t0;
|
|
2247
|
+
let t1;
|
|
2248
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
2249
|
+
t1 = createVisualLineState();
|
|
2250
|
+
$[0] = t1;
|
|
2251
|
+
} else t1 = $[0];
|
|
2252
|
+
const stateRef = useRef(t1);
|
|
2253
|
+
let t2;
|
|
2254
|
+
if ($[1] !== pagesContainerRef) {
|
|
2255
|
+
t2 = (view, event) => handleVisualLineKeyDown(stateRef.current, view, event, pagesContainerRef.current);
|
|
2256
|
+
$[1] = pagesContainerRef;
|
|
2257
|
+
$[2] = t2;
|
|
2258
|
+
} else t2 = $[2];
|
|
2259
|
+
const handlePMKeyDown = t2;
|
|
2260
|
+
let t3;
|
|
2261
|
+
if ($[3] !== handlePMKeyDown) {
|
|
2262
|
+
t3 = { handlePMKeyDown };
|
|
2263
|
+
$[3] = handlePMKeyDown;
|
|
2264
|
+
$[4] = t3;
|
|
2265
|
+
} else t3 = $[4];
|
|
2266
|
+
return t3;
|
|
2479
2267
|
}
|
|
2480
2268
|
/** Distance in px from a row/column boundary that triggers the insert button */
|
|
2481
2269
|
/** Distance in px from the table edge where boundary detection is active */
|
|
@@ -2565,15 +2353,6 @@ const getPageIndex = (el) => {
|
|
|
2565
2353
|
const raw = pageEl.dataset["pageNumber"];
|
|
2566
2354
|
return raw ? Number(raw) - 1 : 0;
|
|
2567
2355
|
};
|
|
2568
|
-
/**
|
|
2569
|
-
* Get the line height for a node by climbing to its `.layout-line`
|
|
2570
|
-
* ancestor and reading `offsetHeight`. Returns `fallback` if no
|
|
2571
|
-
* ancestor is found.
|
|
2572
|
-
*/
|
|
2573
|
-
const getLineHeight = (el, fallback = 16) => {
|
|
2574
|
-
const lineEl = closestHtmlElement(el, ".layout-line");
|
|
2575
|
-
return lineEl ? lineEl.offsetHeight : fallback;
|
|
2576
|
-
};
|
|
2577
2356
|
const containerStyles = {
|
|
2578
2357
|
position: "relative",
|
|
2579
2358
|
width: "100%",
|
|
@@ -2599,7 +2378,7 @@ const loadSelectionGeometry = () => {
|
|
|
2599
2378
|
return selectionGeometryPromise;
|
|
2600
2379
|
};
|
|
2601
2380
|
function HfCaretOverlay(t0) {
|
|
2602
|
-
const $ = c(
|
|
2381
|
+
const $ = c(27);
|
|
2603
2382
|
const { selection, pagesContainer, hiddenHost, editorView, zoom } = t0;
|
|
2604
2383
|
const [caret, setCaret] = useState(null);
|
|
2605
2384
|
let t1;
|
|
@@ -2609,62 +2388,24 @@ function HfCaretOverlay(t0) {
|
|
|
2609
2388
|
} else t1 = $[0];
|
|
2610
2389
|
const [rangeRects, setRangeRects] = useState(t1);
|
|
2611
2390
|
let t2;
|
|
2612
|
-
|
|
2613
|
-
if ($[1] !== editorView || $[2] !== hiddenHost || $[3] !== pagesContainer || $[4] !== selection.from || $[5] !== selection.kind || $[6] !== selection.pageNumber || $[7] !== selection.rId || $[8] !== selection.to || $[9] !== zoom) {
|
|
2391
|
+
if ($[1] !== editorView || $[2] !== hiddenHost || $[3] !== pagesContainer || $[4] !== selection || $[5] !== zoom) {
|
|
2614
2392
|
t2 = () => {
|
|
2615
2393
|
if (!pagesContainer) return;
|
|
2616
2394
|
const recompute = () => {
|
|
2617
2395
|
const cr = pagesContainer.getBoundingClientRect();
|
|
2618
2396
|
const zoomDivisor = zoom !== 0 ? zoom : 1;
|
|
2619
|
-
const
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
syncImeCaretAnchor({
|
|
2624
|
-
hiddenHost,
|
|
2625
|
-
editorView,
|
|
2626
|
-
visibleCaret: null
|
|
2627
|
-
});
|
|
2628
|
-
setCaret(null);
|
|
2629
|
-
setRangeRects([]);
|
|
2630
|
-
return;
|
|
2631
|
-
}
|
|
2632
|
-
const ar = hit.element.getBoundingClientRect();
|
|
2633
|
-
let absX = hit.edge === "right" ? ar.right : ar.left;
|
|
2634
|
-
let absY = ar.top;
|
|
2635
|
-
let absHeight = ar.height || 16;
|
|
2636
|
-
const pmStartStr = hit.element.dataset.pmStart;
|
|
2637
|
-
const pmEndStr = hit.element.dataset.pmEnd;
|
|
2638
|
-
const pmStart = pmStartStr ? Number.parseInt(pmStartStr, 10) : NaN;
|
|
2639
|
-
const pmEnd = pmEndStr ? Number.parseInt(pmEndStr, 10) : NaN;
|
|
2640
|
-
const textNode = hit.element.firstChild;
|
|
2641
|
-
if (textNode && textNode.nodeType === Node.TEXT_NODE && Number.isFinite(pmStart) && Number.isFinite(pmEnd)) {
|
|
2642
|
-
const textContent = textNode.textContent ?? "";
|
|
2643
|
-
const charOffset = Math.min(Math.max(0, selection.from - pmStart), textContent.length);
|
|
2644
|
-
const range = hit.element.ownerDocument.createRange();
|
|
2645
|
-
range.setStart(textNode, charOffset);
|
|
2646
|
-
range.setEnd(textNode, charOffset);
|
|
2647
|
-
const rRect = range.getBoundingClientRect();
|
|
2648
|
-
if (rRect.height > 0 || rRect.width > 0 || rRect.left > 0) {
|
|
2649
|
-
absX = rRect.left;
|
|
2650
|
-
absY = rRect.top;
|
|
2651
|
-
absHeight = rRect.height || absHeight;
|
|
2652
|
-
}
|
|
2653
|
-
}
|
|
2654
|
-
setCaret({
|
|
2655
|
-
x: (absX - cr.left) / zoomDivisor,
|
|
2656
|
-
y: (absY - cr.top) / zoomDivisor,
|
|
2657
|
-
height: absHeight / zoomDivisor
|
|
2658
|
-
});
|
|
2397
|
+
const geometry = resolveHeaderFooterSelectionGeometry(pagesContainer, selection, zoomDivisor);
|
|
2398
|
+
setCaret(geometry.caret);
|
|
2399
|
+
setRangeRects(geometry.ranges);
|
|
2400
|
+
if (geometry.caret) {
|
|
2659
2401
|
syncImeCaretAnchor({
|
|
2660
2402
|
hiddenHost,
|
|
2661
2403
|
editorView,
|
|
2662
2404
|
visibleCaret: {
|
|
2663
|
-
left:
|
|
2664
|
-
top:
|
|
2405
|
+
left: cr.left + geometry.caret.x * zoomDivisor,
|
|
2406
|
+
top: cr.top + geometry.caret.y * zoomDivisor
|
|
2665
2407
|
}
|
|
2666
2408
|
});
|
|
2667
|
-
setRangeRects([]);
|
|
2668
2409
|
return;
|
|
2669
2410
|
}
|
|
2670
2411
|
syncImeCaretAnchor({
|
|
@@ -2672,41 +2413,6 @@ function HfCaretOverlay(t0) {
|
|
|
2672
2413
|
editorView,
|
|
2673
2414
|
visibleCaret: null
|
|
2674
2415
|
});
|
|
2675
|
-
const spans = findHfPmSpans(pageScope, selection.kind, selection.rId);
|
|
2676
|
-
const rects = [];
|
|
2677
|
-
for (const span of spans) {
|
|
2678
|
-
const spanStart = Number.parseInt(span.dataset.pmStart ?? "", 10);
|
|
2679
|
-
const spanEnd = Number.parseInt(span.dataset.pmEnd ?? "", 10);
|
|
2680
|
-
if (!Number.isFinite(spanStart) || !Number.isFinite(spanEnd)) continue;
|
|
2681
|
-
if (spanEnd <= selection.from || spanStart >= selection.to) continue;
|
|
2682
|
-
const textNode_0 = span.firstChild;
|
|
2683
|
-
if (textNode_0 && textNode_0.nodeType === Node.TEXT_NODE) {
|
|
2684
|
-
const textContent_0 = textNode_0.textContent ?? "";
|
|
2685
|
-
const startChar = Math.max(0, selection.from - spanStart);
|
|
2686
|
-
const endChar = Math.min(textContent_0.length, selection.to - spanStart);
|
|
2687
|
-
if (startChar < endChar) {
|
|
2688
|
-
const range_0 = span.ownerDocument.createRange();
|
|
2689
|
-
range_0.setStart(textNode_0, startChar);
|
|
2690
|
-
range_0.setEnd(textNode_0, endChar);
|
|
2691
|
-
for (const cRect of Array.from(range_0.getClientRects())) rects.push({
|
|
2692
|
-
x: (cRect.left - cr.left) / zoomDivisor,
|
|
2693
|
-
y: (cRect.top - cr.top) / zoomDivisor,
|
|
2694
|
-
width: cRect.width / zoomDivisor,
|
|
2695
|
-
height: cRect.height / zoomDivisor
|
|
2696
|
-
});
|
|
2697
|
-
continue;
|
|
2698
|
-
}
|
|
2699
|
-
}
|
|
2700
|
-
const r = span.getBoundingClientRect();
|
|
2701
|
-
rects.push({
|
|
2702
|
-
x: (r.left - cr.left) / zoomDivisor,
|
|
2703
|
-
y: (r.top - cr.top) / zoomDivisor,
|
|
2704
|
-
width: r.width / zoomDivisor,
|
|
2705
|
-
height: r.height / zoomDivisor
|
|
2706
|
-
});
|
|
2707
|
-
}
|
|
2708
|
-
setRangeRects(rects);
|
|
2709
|
-
setCaret(null);
|
|
2710
2416
|
};
|
|
2711
2417
|
recompute();
|
|
2712
2418
|
const onPainted = () => recompute();
|
|
@@ -2731,6 +2437,15 @@ function HfCaretOverlay(t0) {
|
|
|
2731
2437
|
resetImeCaretAnchor(hiddenHost);
|
|
2732
2438
|
};
|
|
2733
2439
|
};
|
|
2440
|
+
$[1] = editorView;
|
|
2441
|
+
$[2] = hiddenHost;
|
|
2442
|
+
$[3] = pagesContainer;
|
|
2443
|
+
$[4] = selection;
|
|
2444
|
+
$[5] = zoom;
|
|
2445
|
+
$[6] = t2;
|
|
2446
|
+
} else t2 = $[6];
|
|
2447
|
+
let t3;
|
|
2448
|
+
if ($[7] !== editorView || $[8] !== hiddenHost || $[9] !== pagesContainer || $[10] !== selection.from || $[11] !== selection.kind || $[12] !== selection.pageNumber || $[13] !== selection.rId || $[14] !== selection.to || $[15] !== zoom) {
|
|
2734
2449
|
t3 = [
|
|
2735
2450
|
selection.rId,
|
|
2736
2451
|
selection.kind,
|
|
@@ -2742,31 +2457,27 @@ function HfCaretOverlay(t0) {
|
|
|
2742
2457
|
editorView,
|
|
2743
2458
|
zoom
|
|
2744
2459
|
];
|
|
2745
|
-
$[
|
|
2746
|
-
$[
|
|
2747
|
-
$[
|
|
2748
|
-
$[
|
|
2749
|
-
$[
|
|
2750
|
-
$[
|
|
2751
|
-
$[
|
|
2752
|
-
$[
|
|
2753
|
-
$[
|
|
2754
|
-
$[
|
|
2755
|
-
|
|
2756
|
-
} else {
|
|
2757
|
-
t2 = $[10];
|
|
2758
|
-
t3 = $[11];
|
|
2759
|
-
}
|
|
2460
|
+
$[7] = editorView;
|
|
2461
|
+
$[8] = hiddenHost;
|
|
2462
|
+
$[9] = pagesContainer;
|
|
2463
|
+
$[10] = selection.from;
|
|
2464
|
+
$[11] = selection.kind;
|
|
2465
|
+
$[12] = selection.pageNumber;
|
|
2466
|
+
$[13] = selection.rId;
|
|
2467
|
+
$[14] = selection.to;
|
|
2468
|
+
$[15] = zoom;
|
|
2469
|
+
$[16] = t3;
|
|
2470
|
+
} else t3 = $[16];
|
|
2760
2471
|
useEffect(t2, t3);
|
|
2761
2472
|
if (!pagesContainer) return null;
|
|
2762
2473
|
let t4;
|
|
2763
|
-
if ($[
|
|
2474
|
+
if ($[17] !== rangeRects) {
|
|
2764
2475
|
t4 = rangeRects.map(_temp$8);
|
|
2765
|
-
$[
|
|
2766
|
-
$[
|
|
2767
|
-
} else t4 = $[
|
|
2476
|
+
$[17] = rangeRects;
|
|
2477
|
+
$[18] = t4;
|
|
2478
|
+
} else t4 = $[18];
|
|
2768
2479
|
let t5;
|
|
2769
|
-
if ($[
|
|
2480
|
+
if ($[19] !== caret) {
|
|
2770
2481
|
t5 = caret && /* @__PURE__ */ jsx("div", {
|
|
2771
2482
|
"data-testid": "hf-caret",
|
|
2772
2483
|
style: {
|
|
@@ -2781,39 +2492,39 @@ function HfCaretOverlay(t0) {
|
|
|
2781
2492
|
animation: "folio-caret-blink 1060ms steps(1, end) infinite"
|
|
2782
2493
|
}
|
|
2783
2494
|
});
|
|
2784
|
-
$[
|
|
2785
|
-
$[
|
|
2786
|
-
} else t5 = $[
|
|
2495
|
+
$[19] = caret;
|
|
2496
|
+
$[20] = t5;
|
|
2497
|
+
} else t5 = $[20];
|
|
2787
2498
|
let t6;
|
|
2788
|
-
if ($[
|
|
2499
|
+
if ($[21] !== t4 || $[22] !== t5) {
|
|
2789
2500
|
t6 = /* @__PURE__ */ jsxs(Fragment, { children: [t4, t5] });
|
|
2790
|
-
$[
|
|
2791
|
-
$[
|
|
2792
|
-
$[
|
|
2793
|
-
} else t6 = $[
|
|
2501
|
+
$[21] = t4;
|
|
2502
|
+
$[22] = t5;
|
|
2503
|
+
$[23] = t6;
|
|
2504
|
+
} else t6 = $[23];
|
|
2794
2505
|
let t7;
|
|
2795
|
-
if ($[
|
|
2506
|
+
if ($[24] !== pagesContainer || $[25] !== t6) {
|
|
2796
2507
|
t7 = createPortal(t6, pagesContainer);
|
|
2797
|
-
$[
|
|
2798
|
-
$[
|
|
2799
|
-
$[
|
|
2800
|
-
} else t7 = $[
|
|
2508
|
+
$[24] = pagesContainer;
|
|
2509
|
+
$[25] = t6;
|
|
2510
|
+
$[26] = t7;
|
|
2511
|
+
} else t7 = $[26];
|
|
2801
2512
|
return t7;
|
|
2802
2513
|
}
|
|
2803
|
-
function _temp$8(
|
|
2514
|
+
function _temp$8(r, i) {
|
|
2804
2515
|
return /* @__PURE__ */ jsx("div", {
|
|
2805
2516
|
"data-testid": "hf-selection-rect",
|
|
2806
2517
|
style: {
|
|
2807
2518
|
position: "absolute",
|
|
2808
|
-
left:
|
|
2809
|
-
top:
|
|
2810
|
-
width:
|
|
2811
|
-
height:
|
|
2519
|
+
left: r.x,
|
|
2520
|
+
top: r.y,
|
|
2521
|
+
width: r.width,
|
|
2522
|
+
height: r.height,
|
|
2812
2523
|
backgroundColor: "var(--doc-selection, rgba(66, 133, 244, 0.3))",
|
|
2813
2524
|
pointerEvents: "none",
|
|
2814
2525
|
zIndex: 10
|
|
2815
2526
|
}
|
|
2816
|
-
}, `hf-sel-${i}-${
|
|
2527
|
+
}, `hf-sel-${i}-${r.x}-${r.y}-${r.width}`);
|
|
2817
2528
|
}
|
|
2818
2529
|
function renderHfFromContentOrPm(hf, rId, hfPMs, contentWidth, metrics, options) {
|
|
2819
2530
|
if (!hf) return;
|
|
@@ -3547,87 +3258,17 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
3547
3258
|
* This uses the browser's text rendering to get precise pixel positions.
|
|
3548
3259
|
*/
|
|
3549
3260
|
const getCaretFromDom = useCallback((pmPos_0, currentZoom = 1) => {
|
|
3550
|
-
|
|
3551
|
-
|
|
3261
|
+
const pagesContainer = pagesContainerRef.current;
|
|
3262
|
+
if (!pagesContainer) return null;
|
|
3263
|
+
const overlay = pagesContainer.parentElement?.querySelector("[data-testid=\"selection-overlay\"]");
|
|
3552
3264
|
if (!overlay) return null;
|
|
3553
|
-
const
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
pageIndex: getPageIndex(collapsedTarget.span)
|
|
3561
|
-
};
|
|
3562
|
-
for (const spanEl of spans) {
|
|
3563
|
-
const pmStart = Number(spanEl.dataset["pmStart"]);
|
|
3564
|
-
const pmEnd = Number(spanEl.dataset["pmEnd"]);
|
|
3565
|
-
if (spanEl.classList.contains("layout-run-tab")) {
|
|
3566
|
-
if (pmPos_0 >= pmStart && pmPos_0 < pmEnd) {
|
|
3567
|
-
const spanRect = spanEl.getBoundingClientRect();
|
|
3568
|
-
return {
|
|
3569
|
-
x: (spanRect.left - overlayRect.left) / currentZoom,
|
|
3570
|
-
y: (spanRect.top - overlayRect.top) / currentZoom,
|
|
3571
|
-
height: getLineHeight(spanEl),
|
|
3572
|
-
pageIndex: getPageIndex(spanEl)
|
|
3573
|
-
};
|
|
3574
|
-
}
|
|
3575
|
-
continue;
|
|
3576
|
-
}
|
|
3577
|
-
if (spanEl.classList.contains("layout-empty-run") && pmPos_0 >= pmStart && pmPos_0 <= pmEnd) {
|
|
3578
|
-
const spanRect_0 = spanEl.getBoundingClientRect();
|
|
3579
|
-
return {
|
|
3580
|
-
x: (spanRect_0.left - overlayRect.left) / currentZoom,
|
|
3581
|
-
y: (spanRect_0.top - overlayRect.top) / currentZoom,
|
|
3582
|
-
height: getLineHeight(spanEl, Math.max(16, spanRect_0.height)),
|
|
3583
|
-
pageIndex: getPageIndex(spanEl)
|
|
3584
|
-
};
|
|
3585
|
-
}
|
|
3586
|
-
if (pmPos_0 >= pmStart && pmPos_0 <= pmEnd && spanEl.firstChild?.nodeType === Node.TEXT_NODE) {
|
|
3587
|
-
const textNode = spanEl.firstChild;
|
|
3588
|
-
const charIndex = Math.min(pmPos_0 - pmStart, textNode.length);
|
|
3589
|
-
const range = spanEl.ownerDocument.createRange();
|
|
3590
|
-
range.setStart(textNode, charIndex);
|
|
3591
|
-
range.setEnd(textNode, charIndex);
|
|
3592
|
-
const rangeRect = range.getBoundingClientRect();
|
|
3593
|
-
const spanRect_1 = spanEl.getBoundingClientRect();
|
|
3594
|
-
const useSpanStart = charIndex === 0 || rangeRect.width === 0 && rangeRect.left < spanRect_1.left;
|
|
3595
|
-
const caretLeft = useSpanStart ? spanRect_1.left : rangeRect.left;
|
|
3596
|
-
const caretTop = rangeRect.height > 0 && !useSpanStart ? rangeRect.top : spanRect_1.top;
|
|
3597
|
-
return {
|
|
3598
|
-
x: (caretLeft - overlayRect.left) / currentZoom,
|
|
3599
|
-
y: (caretTop - overlayRect.top) / currentZoom,
|
|
3600
|
-
height: getLineHeight(spanEl),
|
|
3601
|
-
pageIndex: getPageIndex(spanEl)
|
|
3602
|
-
};
|
|
3603
|
-
}
|
|
3604
|
-
if (pmPos_0 >= pmStart && pmPos_0 <= pmEnd) {
|
|
3605
|
-
const spanRect_2 = spanEl.getBoundingClientRect();
|
|
3606
|
-
return {
|
|
3607
|
-
x: (spanRect_2.left - overlayRect.left) / currentZoom,
|
|
3608
|
-
y: (spanRect_2.top - overlayRect.top) / currentZoom,
|
|
3609
|
-
height: getLineHeight(spanEl, Math.max(16, spanRect_2.height)),
|
|
3610
|
-
pageIndex: getPageIndex(spanEl)
|
|
3611
|
-
};
|
|
3612
|
-
}
|
|
3613
|
-
}
|
|
3614
|
-
const emptyRuns = findBodyEmptyRuns(pagesContainerRef.current);
|
|
3615
|
-
for (const emptyRun of emptyRuns) {
|
|
3616
|
-
const paragraph = closestHtmlElement(emptyRun, ".layout-paragraph");
|
|
3617
|
-
if (!paragraph) continue;
|
|
3618
|
-
const pmStart_0 = Number(paragraph.dataset["pmStart"]);
|
|
3619
|
-
const pmEnd_0 = Number(paragraph.dataset["pmEnd"]);
|
|
3620
|
-
if (pmPos_0 >= pmStart_0 && pmPos_0 <= pmEnd_0) {
|
|
3621
|
-
const runRect = emptyRun.getBoundingClientRect();
|
|
3622
|
-
return {
|
|
3623
|
-
x: (runRect.left - overlayRect.left) / currentZoom,
|
|
3624
|
-
y: (runRect.top - overlayRect.top) / currentZoom,
|
|
3625
|
-
height: getLineHeight(emptyRun),
|
|
3626
|
-
pageIndex: getPageIndex(paragraph)
|
|
3627
|
-
};
|
|
3628
|
-
}
|
|
3629
|
-
}
|
|
3630
|
-
return null;
|
|
3265
|
+
const caret = getCaretPositionFromDom(pagesContainer, pmPos_0, overlay.getBoundingClientRect());
|
|
3266
|
+
return caret ? {
|
|
3267
|
+
x: caret.x / currentZoom,
|
|
3268
|
+
y: caret.y / currentZoom,
|
|
3269
|
+
height: caret.height / currentZoom,
|
|
3270
|
+
pageIndex: caret.pageIndex
|
|
3271
|
+
} : null;
|
|
3631
3272
|
}, []);
|
|
3632
3273
|
const refreshBodyImeCaretAnchor = useCallback(() => {
|
|
3633
3274
|
const view_1 = hiddenPMRef.current?.getView();
|
|
@@ -3726,12 +3367,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
3726
3367
|
setCaretPosition(null);
|
|
3727
3368
|
loadSelectionGeometry().then(({ getCaretPosition }) => {
|
|
3728
3369
|
if (!isCurrentRequest()) return;
|
|
3729
|
-
const
|
|
3730
|
-
if (
|
|
3370
|
+
const caret_0 = getCaretPosition(layout, blocks, measures, from);
|
|
3371
|
+
if (caret_0) {
|
|
3731
3372
|
const fallbackCaret = {
|
|
3732
|
-
...
|
|
3733
|
-
x:
|
|
3734
|
-
y:
|
|
3373
|
+
...caret_0,
|
|
3374
|
+
x: caret_0.x + (pageRect.left - overlayRect_2.left) / zoom,
|
|
3375
|
+
y: caret_0.y + (pageRect.top - overlayRect_2.top) / zoom
|
|
3735
3376
|
};
|
|
3736
3377
|
setCaretPosition(fallbackCaret);
|
|
3737
3378
|
syncImeCaretAnchor({
|
|
@@ -3779,45 +3420,13 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
3779
3420
|
const overlay_3 = pagesContainerRef.current?.parentElement?.querySelector("[data-testid=\"selection-overlay\"]");
|
|
3780
3421
|
if (overlay_3 && pagesContainerRef.current) {
|
|
3781
3422
|
const overlayRect_3 = overlay_3.getBoundingClientRect();
|
|
3782
|
-
const domRects =
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
domRects.push({
|
|
3790
|
-
x: (spanRect_3.left - overlayRect_3.left) / zoom,
|
|
3791
|
-
y: (spanRect_3.top - overlayRect_3.top) / zoom,
|
|
3792
|
-
width: spanRect_3.width / zoom,
|
|
3793
|
-
height: spanRect_3.height / zoom,
|
|
3794
|
-
pageIndex: getPageIndex(spanEl_0)
|
|
3795
|
-
});
|
|
3796
|
-
continue;
|
|
3797
|
-
}
|
|
3798
|
-
let textNode_0 = null;
|
|
3799
|
-
if (spanEl_0.firstChild?.nodeType === Node.TEXT_NODE) textNode_0 = spanEl_0.firstChild;
|
|
3800
|
-
else if (spanEl_0.firstChild instanceof HTMLElement && spanEl_0.firstChild.tagName === "A" && spanEl_0.firstChild.firstChild?.nodeType === Node.TEXT_NODE) textNode_0 = spanEl_0.firstChild.firstChild;
|
|
3801
|
-
if (!textNode_0) continue;
|
|
3802
|
-
const ownerDoc_0 = spanEl_0.ownerDocument;
|
|
3803
|
-
const startChar = Math.max(0, from - pmStart_1);
|
|
3804
|
-
const endChar = Math.min(textNode_0.length, to - pmStart_1);
|
|
3805
|
-
if (startChar < endChar) {
|
|
3806
|
-
const range_0 = ownerDoc_0.createRange();
|
|
3807
|
-
range_0.setStart(textNode_0, startChar);
|
|
3808
|
-
range_0.setEnd(textNode_0, endChar);
|
|
3809
|
-
const clientRects = range_0.getClientRects();
|
|
3810
|
-
const pageIndex = getPageIndex(spanEl_0);
|
|
3811
|
-
for (const rect_0 of Array.from(clientRects)) domRects.push({
|
|
3812
|
-
x: (rect_0.left - overlayRect_3.left) / zoom,
|
|
3813
|
-
y: (rect_0.top - overlayRect_3.top) / zoom,
|
|
3814
|
-
width: rect_0.width / zoom,
|
|
3815
|
-
height: rect_0.height / zoom,
|
|
3816
|
-
pageIndex
|
|
3817
|
-
});
|
|
3818
|
-
}
|
|
3819
|
-
}
|
|
3820
|
-
}
|
|
3423
|
+
const domRects = getSelectionRectsFromDom(pagesContainerRef.current, from, to, overlayRect_3).map((rect_0) => ({
|
|
3424
|
+
pageIndex: rect_0.pageIndex,
|
|
3425
|
+
x: rect_0.x / zoom,
|
|
3426
|
+
y: rect_0.y / zoom,
|
|
3427
|
+
width: rect_0.width / zoom,
|
|
3428
|
+
height: rect_0.height / zoom
|
|
3429
|
+
}));
|
|
3821
3430
|
if (domRects.length > 0) setSelectionRects(domRects);
|
|
3822
3431
|
else {
|
|
3823
3432
|
const firstPage_0 = pagesContainerRef.current.querySelector(".layout-page");
|
|
@@ -3854,6 +3463,24 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
3854
3463
|
]);
|
|
3855
3464
|
const updateSelectionOverlayRef = useRef(updateSelectionOverlay);
|
|
3856
3465
|
updateSelectionOverlayRef.current = updateSelectionOverlay;
|
|
3466
|
+
useEffect(() => {
|
|
3467
|
+
const pagesContainer_0 = pagesContainerRef.current;
|
|
3468
|
+
if (!pagesContainer_0) return void 0;
|
|
3469
|
+
let animationFrame = null;
|
|
3470
|
+
const repaintSelection = () => {
|
|
3471
|
+
if (animationFrame !== null) cancelAnimationFrame(animationFrame);
|
|
3472
|
+
animationFrame = requestAnimationFrame(() => {
|
|
3473
|
+
animationFrame = null;
|
|
3474
|
+
const state_4 = hiddenPMRef.current?.getState();
|
|
3475
|
+
if (state_4) updateSelectionOverlayRef.current(state_4);
|
|
3476
|
+
});
|
|
3477
|
+
};
|
|
3478
|
+
pagesContainer_0.addEventListener(PAINTER_PAINTED_EVENT, repaintSelection);
|
|
3479
|
+
return () => {
|
|
3480
|
+
if (animationFrame !== null) cancelAnimationFrame(animationFrame);
|
|
3481
|
+
pagesContainer_0.removeEventListener(PAINTER_PAINTED_EVENT, repaintSelection);
|
|
3482
|
+
};
|
|
3483
|
+
}, []);
|
|
3857
3484
|
const updateAnonymizationOverlay = useCallback(() => {
|
|
3858
3485
|
const isCurrentRequest_0 = anonymizationOverlayRequestGate.begin();
|
|
3859
3486
|
const matches = anonymizationMatchesRef.current;
|
|
@@ -3861,13 +3488,13 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
3861
3488
|
setAnonymizationRectGroups([]);
|
|
3862
3489
|
return;
|
|
3863
3490
|
}
|
|
3864
|
-
const
|
|
3865
|
-
if (!
|
|
3491
|
+
const pagesContainer_1 = pagesContainerRef.current;
|
|
3492
|
+
if (!pagesContainer_1) {
|
|
3866
3493
|
setAnonymizationRectGroups([]);
|
|
3867
3494
|
return;
|
|
3868
3495
|
}
|
|
3869
|
-
const overlay_4 =
|
|
3870
|
-
const firstPage_1 =
|
|
3496
|
+
const overlay_4 = pagesContainer_1.parentElement?.querySelector("[data-testid=\"selection-overlay\"]");
|
|
3497
|
+
const firstPage_1 = pagesContainer_1.querySelector(".layout-page");
|
|
3871
3498
|
if (!overlay_4 || !firstPage_1) {
|
|
3872
3499
|
setAnonymizationRectGroups([]);
|
|
3873
3500
|
return;
|
|
@@ -3876,42 +3503,21 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
3876
3503
|
const pageRect_1 = firstPage_1.getBoundingClientRect();
|
|
3877
3504
|
const pageOffsetX_0 = (pageRect_1.left - overlayRect_4.left) / zoom;
|
|
3878
3505
|
const pageOffsetY_0 = (pageRect_1.top - overlayRect_4.top) / zoom;
|
|
3879
|
-
const pmSpans = findBodyPmSpans(
|
|
3506
|
+
const pmSpans = findBodyPmSpans(pagesContainer_1);
|
|
3880
3507
|
const layoutFallbackMatches = [];
|
|
3881
3508
|
const rectsForMatch = (match, from_0, to_0) => {
|
|
3882
3509
|
const domRects_0 = [];
|
|
3883
|
-
for (const
|
|
3884
|
-
const
|
|
3885
|
-
if (
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
x: (spanRect_4.left - overlayRect_4.left) / zoom,
|
|
3890
|
-
y: (spanRect_4.top - overlayRect_4.top) / zoom,
|
|
3891
|
-
width: spanRect_4.width / zoom,
|
|
3892
|
-
height: spanRect_4.height / zoom,
|
|
3893
|
-
pageIndex: getPageIndex(spanEl_1)
|
|
3894
|
-
});
|
|
3895
|
-
continue;
|
|
3896
|
-
}
|
|
3897
|
-
let textNode_1 = null;
|
|
3898
|
-
if (spanEl_1.firstChild?.nodeType === Node.TEXT_NODE) textNode_1 = spanEl_1.firstChild;
|
|
3899
|
-
else if (spanEl_1.firstChild instanceof HTMLElement && spanEl_1.firstChild.tagName === "A" && spanEl_1.firstChild.firstChild?.nodeType === Node.TEXT_NODE) textNode_1 = spanEl_1.firstChild.firstChild;
|
|
3900
|
-
if (!textNode_1) continue;
|
|
3901
|
-
const ownerDoc_1 = spanEl_1.ownerDocument;
|
|
3902
|
-
const startChar_0 = Math.max(0, from_0 - pmStart_2);
|
|
3903
|
-
const endChar_0 = Math.min(textNode_1.length, to_0 - pmStart_2);
|
|
3904
|
-
if (startChar_0 >= endChar_0) continue;
|
|
3905
|
-
const range_1 = ownerDoc_1.createRange();
|
|
3906
|
-
range_1.setStart(textNode_1, startChar_0);
|
|
3907
|
-
range_1.setEnd(textNode_1, endChar_0);
|
|
3908
|
-
const pageIndex_0 = getPageIndex(spanEl_1);
|
|
3909
|
-
for (const rect_2 of Array.from(range_1.getClientRects())) domRects_0.push({
|
|
3510
|
+
for (const spanEl of pmSpans) {
|
|
3511
|
+
const measurement = measurePaintedSpanRange(spanEl, from_0, to_0);
|
|
3512
|
+
if (measurement.type === "outside") continue;
|
|
3513
|
+
const pageIndex = getPageIndex(spanEl);
|
|
3514
|
+
const measuredRects = measurement.type === "element" ? [measurement.rect] : measurement.rects;
|
|
3515
|
+
for (const rect_2 of measuredRects) domRects_0.push({
|
|
3910
3516
|
x: (rect_2.left - overlayRect_4.left) / zoom,
|
|
3911
3517
|
y: (rect_2.top - overlayRect_4.top) / zoom,
|
|
3912
3518
|
width: rect_2.width / zoom,
|
|
3913
3519
|
height: rect_2.height / zoom,
|
|
3914
|
-
pageIndex
|
|
3520
|
+
pageIndex
|
|
3915
3521
|
});
|
|
3916
3522
|
}
|
|
3917
3523
|
if (domRects_0.length > 0) return domRects_0;
|
|
@@ -3970,15 +3576,15 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
3970
3576
|
const anchor_0 = current.anchor;
|
|
3971
3577
|
loadSelectionGeometry().then(({ getCaretPosition: getCaretPosition_0 }) => {
|
|
3972
3578
|
if (!isCurrentRequest_1()) return;
|
|
3973
|
-
const
|
|
3579
|
+
const caret_1 = getCaretPosition_0(layout, blocks, measures, anchor_0);
|
|
3974
3580
|
if (!isCurrentRequest_1()) return;
|
|
3975
|
-
if (
|
|
3581
|
+
if (caret_1 === null) {
|
|
3976
3582
|
setAutocompleteCaret(null);
|
|
3977
3583
|
return;
|
|
3978
3584
|
}
|
|
3979
|
-
const
|
|
3980
|
-
const overlay_5 =
|
|
3981
|
-
const firstPage_2 =
|
|
3585
|
+
const pagesContainer_2 = pagesContainerRef.current;
|
|
3586
|
+
const overlay_5 = pagesContainer_2?.parentElement?.querySelector("[data-testid=\"selection-overlay\"]");
|
|
3587
|
+
const firstPage_2 = pagesContainer_2?.querySelector(".layout-page");
|
|
3982
3588
|
if (!overlay_5 || !firstPage_2) {
|
|
3983
3589
|
setAutocompleteCaret(null);
|
|
3984
3590
|
return;
|
|
@@ -3988,12 +3594,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
3988
3594
|
const pageOffsetX_1 = (pageRect_2.left - overlayRect_5.left) / zoom;
|
|
3989
3595
|
const pageOffsetY_1 = (pageRect_2.top - overlayRect_5.top) / zoom;
|
|
3990
3596
|
if (!isCurrentRequest_1()) return;
|
|
3991
|
-
const caretPage = layout.pages.at(
|
|
3992
|
-
const maxWidth = caretPage ? Math.max(AUTOCOMPLETE_GHOST_MIN_WIDTH, caretPage.size.w - caretPage.margins.right -
|
|
3597
|
+
const caretPage = layout.pages.at(caret_1.pageIndex);
|
|
3598
|
+
const maxWidth = caretPage ? Math.max(AUTOCOMPLETE_GHOST_MIN_WIDTH, caretPage.size.w - caretPage.margins.right - caret_1.x) : void 0;
|
|
3993
3599
|
setAutocompleteCaret({
|
|
3994
|
-
x:
|
|
3995
|
-
y:
|
|
3996
|
-
lineHeight:
|
|
3600
|
+
x: caret_1.x + pageOffsetX_1,
|
|
3601
|
+
y: caret_1.y + pageOffsetY_1,
|
|
3602
|
+
lineHeight: caret_1.height,
|
|
3997
3603
|
maxWidth
|
|
3998
3604
|
});
|
|
3999
3605
|
setAutocompleteText(current.text);
|
|
@@ -4009,17 +3615,17 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4009
3615
|
const updateDirectivesOverlay = useCallback(() => {
|
|
4010
3616
|
const isCurrentRequest_2 = directivesOverlayRequestGate.begin();
|
|
4011
3617
|
const previewedStarts = new Set(templatePreviewRef.current.entries.map((entry) => entry.from));
|
|
4012
|
-
const ranges = directivesRef.current.filter((
|
|
4013
|
-
const
|
|
4014
|
-
if (ranges.length === 0 || !
|
|
3618
|
+
const ranges = directivesRef.current.filter((range) => !(range.kind === "placeholder" && previewedStarts.has(range.from)));
|
|
3619
|
+
const pagesContainer_3 = pagesContainerRef.current;
|
|
3620
|
+
if (ranges.length === 0 || !pagesContainer_3) {
|
|
4015
3621
|
setDirectiveRectGroups([]);
|
|
4016
3622
|
setDirectiveGutter(null);
|
|
4017
3623
|
return;
|
|
4018
3624
|
}
|
|
4019
|
-
setDirectiveGutter(measureDirectiveGutter(
|
|
3625
|
+
setDirectiveGutter(measureDirectiveGutter(pagesContainer_3, zoom));
|
|
4020
3626
|
(async () => {
|
|
4021
3627
|
const projected = await projectRangesToRects(ranges, {
|
|
4022
|
-
pagesContainer:
|
|
3628
|
+
pagesContainer: pagesContainer_3,
|
|
4023
3629
|
zoom,
|
|
4024
3630
|
layout,
|
|
4025
3631
|
blocks,
|
|
@@ -4038,8 +3644,8 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4038
3644
|
const isCurrentRequest_3 = aiSuggestionsOverlayRequestGate.begin();
|
|
4039
3645
|
const { suggestions, focusedId } = aiSuggestionsRef.current;
|
|
4040
3646
|
const pending = suggestions.filter((suggestion) => suggestion.status === "pending" && suggestion.range.from >= 0 && suggestion.range.to > suggestion.range.from);
|
|
4041
|
-
const
|
|
4042
|
-
if (pending.length === 0 || !
|
|
3647
|
+
const pagesContainer_4 = pagesContainerRef.current;
|
|
3648
|
+
if (pending.length === 0 || !pagesContainer_4) {
|
|
4043
3649
|
setAiSuggestionRectGroups((prev) => prev.length === 0 ? prev : []);
|
|
4044
3650
|
return;
|
|
4045
3651
|
}
|
|
@@ -4049,20 +3655,20 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4049
3655
|
to: suggestion_0.range.to,
|
|
4050
3656
|
suggestion: suggestion_0
|
|
4051
3657
|
})), {
|
|
4052
|
-
pagesContainer:
|
|
3658
|
+
pagesContainer: pagesContainer_4,
|
|
4053
3659
|
zoom,
|
|
4054
3660
|
layout,
|
|
4055
3661
|
blocks,
|
|
4056
3662
|
measures
|
|
4057
3663
|
});
|
|
4058
3664
|
if (!isCurrentRequest_3()) return;
|
|
4059
|
-
const focused = projected_0.find(({ range:
|
|
4060
|
-
const fonts = collectRunFontsAtPmPositions(
|
|
4061
|
-
setAiSuggestionRectGroups(projected_0.map(({ range:
|
|
4062
|
-
suggestion:
|
|
3665
|
+
const focused = projected_0.find(({ range: range_0 }) => range_0.suggestion.id === focusedId);
|
|
3666
|
+
const fonts = collectRunFontsAtPmPositions(pagesContainer_4, focused ? [focused.range.from] : []);
|
|
3667
|
+
setAiSuggestionRectGroups(projected_0.map(({ range: range_1, rects: rects_2 }) => ({
|
|
3668
|
+
suggestion: range_1.suggestion,
|
|
4063
3669
|
rects: rects_2,
|
|
4064
|
-
focused:
|
|
4065
|
-
font:
|
|
3670
|
+
focused: range_1.suggestion.id === focusedId,
|
|
3671
|
+
font: range_1.suggestion.id === focusedId ? fonts.get(range_1.from) ?? null : null
|
|
4066
3672
|
})));
|
|
4067
3673
|
})();
|
|
4068
3674
|
}, [
|
|
@@ -4074,15 +3680,15 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4074
3680
|
]);
|
|
4075
3681
|
const updatePassageHighlightOverlay = useCallback(() => {
|
|
4076
3682
|
const isCurrentRequest_4 = passageHighlightOverlayRequestGate.begin();
|
|
4077
|
-
const
|
|
4078
|
-
const
|
|
4079
|
-
if (
|
|
3683
|
+
const range_2 = passageHighlightRangeRef.current;
|
|
3684
|
+
const pagesContainer_5 = pagesContainerRef.current;
|
|
3685
|
+
if (range_2 === null || !pagesContainer_5) {
|
|
4080
3686
|
setPassageHighlightRects((prev_0) => prev_0.length === 0 ? prev_0 : []);
|
|
4081
3687
|
return;
|
|
4082
3688
|
}
|
|
4083
3689
|
(async () => {
|
|
4084
|
-
const projected_1 = await projectRangesToRects([
|
|
4085
|
-
pagesContainer:
|
|
3690
|
+
const projected_1 = await projectRangesToRects([range_2], {
|
|
3691
|
+
pagesContainer: pagesContainer_5,
|
|
4086
3692
|
zoom,
|
|
4087
3693
|
layout,
|
|
4088
3694
|
blocks,
|
|
@@ -4098,16 +3704,16 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4098
3704
|
measures,
|
|
4099
3705
|
zoom
|
|
4100
3706
|
]);
|
|
4101
|
-
const setPassageHighlightImpl = useCallback((
|
|
4102
|
-
passageHighlightRangeRef.current =
|
|
4103
|
-
if (
|
|
3707
|
+
const setPassageHighlightImpl = useCallback((range_3) => {
|
|
3708
|
+
passageHighlightRangeRef.current = range_3;
|
|
3709
|
+
if (range_3 === null) {
|
|
4104
3710
|
passageHighlightOverlayRequestGate.invalidate();
|
|
4105
3711
|
setPassageHighlightRects((prev_1) => prev_1.length === 0 ? prev_1 : []);
|
|
4106
3712
|
return;
|
|
4107
3713
|
}
|
|
4108
3714
|
updatePassageHighlightOverlay();
|
|
4109
3715
|
}, [passageHighlightOverlayRequestGate, updatePassageHighlightOverlay]);
|
|
4110
|
-
const hideSelectionOverlayDuringInput = useCallback((
|
|
3716
|
+
const hideSelectionOverlayDuringInput = useCallback((state_5) => {
|
|
4111
3717
|
selectionOverlayRequestGate.invalidate();
|
|
4112
3718
|
suppressSelectionOverlayRef.current = true;
|
|
4113
3719
|
setCaretPosition(null);
|
|
@@ -4116,7 +3722,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4116
3722
|
revealSelectionOverlayTimerRef.current = window.setTimeout(() => {
|
|
4117
3723
|
revealSelectionOverlayTimerRef.current = null;
|
|
4118
3724
|
suppressSelectionOverlayRef.current = false;
|
|
4119
|
-
updateSelectionOverlay(hiddenPMRef.current?.getState() ??
|
|
3725
|
+
updateSelectionOverlay(hiddenPMRef.current?.getState() ?? state_5);
|
|
4120
3726
|
}, SELECTION_REVEAL_AFTER_INPUT_DELAY);
|
|
4121
3727
|
}, [selectionOverlayRequestGate, updateSelectionOverlay]);
|
|
4122
3728
|
useEffect(() => () => {
|
|
@@ -4141,7 +3747,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4141
3747
|
/**
|
|
4142
3748
|
* Handle PM transaction - re-layout on content/selection change.
|
|
4143
3749
|
*/
|
|
4144
|
-
const handleTransaction = useCallback((
|
|
3750
|
+
const handleTransaction = useCallback(({ transactions, newState, docChanged }) => {
|
|
4145
3751
|
const nextMatches = anonymizationDecorationsKey.getState(newState)?.matches ?? [];
|
|
4146
3752
|
const matchesChanged = nextMatches !== anonymizationMatchesRef.current;
|
|
4147
3753
|
anonymizationMatchesRef.current = nextMatches;
|
|
@@ -4154,7 +3760,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4154
3760
|
const nextDirectives = templateDirectivesKey.getState(newState)?.ranges ?? [];
|
|
4155
3761
|
if (nextDirectives !== directivesRef.current) {
|
|
4156
3762
|
directivesRef.current = nextDirectives;
|
|
4157
|
-
if (!
|
|
3763
|
+
if (!docChanged) updateDirectivesOverlay();
|
|
4158
3764
|
}
|
|
4159
3765
|
const nextPreviewState = templatePreviewValuesKey.getState(newState);
|
|
4160
3766
|
const nextPreviewEntries = nextPreviewState?.entries ?? EMPTY_TEMPLATE_PREVIEW_ENTRIES;
|
|
@@ -4165,7 +3771,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4165
3771
|
entries: nextPreviewEntries,
|
|
4166
3772
|
mode: nextPreviewMode
|
|
4167
3773
|
};
|
|
4168
|
-
if (!
|
|
3774
|
+
if (!docChanged) if (nextPreviewMode !== previousPreview.mode) scheduleLayout(newState, null);
|
|
4169
3775
|
else {
|
|
4170
3776
|
const previewDirty = templatePreviewDirtyRange(previousPreview.entries, nextPreviewEntries);
|
|
4171
3777
|
if (previewDirty) scheduleLayout(newState, previewDirty);
|
|
@@ -4179,9 +3785,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4179
3785
|
suggestions: nextAiSuggestions,
|
|
4180
3786
|
focusedId: nextAiFocusedId
|
|
4181
3787
|
};
|
|
4182
|
-
if (!
|
|
3788
|
+
if (!docChanged) updateAISuggestionsOverlay();
|
|
4183
3789
|
}
|
|
4184
|
-
if (
|
|
3790
|
+
if (docChanged) {
|
|
4185
3791
|
syncCoordinator.incrementStateSeq();
|
|
4186
3792
|
if (passageHighlightRangeRef.current !== null) {
|
|
4187
3793
|
passageHighlightRangeRef.current = null;
|
|
@@ -4189,11 +3795,11 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4189
3795
|
setPassageHighlightRects((prev_2) => prev_2.length === 0 ? prev_2 : []);
|
|
4190
3796
|
}
|
|
4191
3797
|
hideSelectionOverlayDuringInput(newState);
|
|
4192
|
-
scheduleLayout(newState,
|
|
3798
|
+
scheduleLayout(newState, getTransactionsDirtyRange(transactions));
|
|
4193
3799
|
scheduleDocumentChangeNotification();
|
|
4194
3800
|
}
|
|
4195
3801
|
syncCoordinator.requestRender();
|
|
4196
|
-
if (!
|
|
3802
|
+
if (!docChanged) updateSelectionOverlay(newState);
|
|
4197
3803
|
}, [
|
|
4198
3804
|
scheduleLayout,
|
|
4199
3805
|
scheduleDocumentChangeNotification,
|
|
@@ -4223,8 +3829,8 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4223
3829
|
*/
|
|
4224
3830
|
const [hfCaretSelection, setHfCaretSelection] = useState(null);
|
|
4225
3831
|
const activeHfPageNumberRef = useRef(null);
|
|
4226
|
-
const handleHfPmTransaction = useCallback((rId, kind, view_2,
|
|
4227
|
-
if (
|
|
3832
|
+
const handleHfPmTransaction = useCallback((rId, kind, view_2, docChanged_0, selectionChanged) => {
|
|
3833
|
+
if (docChanged_0) {
|
|
4228
3834
|
let bodyState = hiddenPMRef.current?.getState();
|
|
4229
3835
|
if (!bodyState && precomputedInitialStateRef.current) bodyState = precomputedInitialStateRef.current;
|
|
4230
3836
|
if (!bodyState) {
|
|
@@ -4233,7 +3839,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4233
3839
|
}
|
|
4234
3840
|
if (bodyState) scheduleLayout(bodyState, null);
|
|
4235
3841
|
}
|
|
4236
|
-
if (
|
|
3842
|
+
if (docChanged_0 || selectionChanged) {
|
|
4237
3843
|
const { from: from_1, to: to_1 } = view_2.state.selection;
|
|
4238
3844
|
const pageNumber = activeHfPageNumberRef.current;
|
|
4239
3845
|
setHfCaretSelection({
|
|
@@ -4250,12 +3856,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4250
3856
|
});
|
|
4251
3857
|
}
|
|
4252
3858
|
}, [scheduleLayout, ensureHiddenEditorView]);
|
|
4253
|
-
const handleNoteStoryTransaction = useCallback((view_3,
|
|
4254
|
-
if (
|
|
3859
|
+
const handleNoteStoryTransaction = useCallback((view_3, docChanged_1, selectionChanged_0) => {
|
|
3860
|
+
if (docChanged_1) {
|
|
4255
3861
|
const bodyState_0 = hiddenPMRef.current?.getState();
|
|
4256
3862
|
if (bodyState_0) scheduleLayout(bodyState_0, null);
|
|
4257
3863
|
}
|
|
4258
|
-
if (
|
|
3864
|
+
if (docChanged_1 || selectionChanged_0) {
|
|
4259
3865
|
const { from: from_2, to: to_2 } = view_3.state.selection;
|
|
4260
3866
|
onSelectionChangeRef.current?.(from_2, to_2);
|
|
4261
3867
|
folioEmitterRef.current.emit("selectionChange", {
|
|
@@ -4277,12 +3883,12 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4277
3883
|
/**
|
|
4278
3884
|
* Handle selection change from PM.
|
|
4279
3885
|
*/
|
|
4280
|
-
const handleSelectionChange = useCallback((
|
|
4281
|
-
const { selection: selection_2 } =
|
|
3886
|
+
const handleSelectionChange = useCallback((state_6) => {
|
|
3887
|
+
const { selection: selection_2 } = state_6;
|
|
4282
3888
|
if (selection_2 instanceof NodeSelection && selection_2.node.type.name === "image") {
|
|
4283
3889
|
setSelectionRects([]);
|
|
4284
3890
|
setCaretPosition(null);
|
|
4285
|
-
} else if (syncCoordinator.isSafeToRender()) updateSelectionOverlay(
|
|
3891
|
+
} else if (syncCoordinator.isSafeToRender()) updateSelectionOverlay(state_6);
|
|
4286
3892
|
requestAnimationFrame(() => {
|
|
4287
3893
|
const view_4 = hiddenPMRef.current?.getView();
|
|
4288
3894
|
if (!view_4) {
|
|
@@ -4404,9 +4010,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4404
4010
|
});
|
|
4405
4011
|
}, [layout, scrollToPositionImpl]);
|
|
4406
4012
|
const scrollToParaIdImpl = useCallback((paraId, options_2) => {
|
|
4407
|
-
const
|
|
4408
|
-
if (!
|
|
4409
|
-
const startPos = findStartPosForParaId(
|
|
4013
|
+
const state_7 = hiddenPMRef.current?.getState();
|
|
4014
|
+
if (!state_7) return false;
|
|
4015
|
+
const startPos = findStartPosForParaId(state_7.doc, paraId);
|
|
4410
4016
|
if (startPos == null || startPos < 0) return false;
|
|
4411
4017
|
scrollToPositionImpl(startPos);
|
|
4412
4018
|
requestAnimationFrame(() => {
|
|
@@ -4414,8 +4020,8 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4414
4020
|
const pages = pagesContainerRef.current;
|
|
4415
4021
|
if (pages) flashParagraphFragmentsByParaId(pages, paraId, options_2.highlight);
|
|
4416
4022
|
}
|
|
4417
|
-
const targetNode =
|
|
4418
|
-
const inner = targetNode?.isTextblock === true ? Math.min(startPos + 1 + targetNode.content.size,
|
|
4023
|
+
const targetNode = state_7.doc.nodeAt(startPos);
|
|
4024
|
+
const inner = targetNode?.isTextblock === true ? Math.min(startPos + 1 + targetNode.content.size, state_7.doc.content.size) : Math.min(startPos + 1, state_7.doc.content.size);
|
|
4419
4025
|
hiddenPMRef.current?.setSelection(inner);
|
|
4420
4026
|
hiddenPMRef.current?.focus();
|
|
4421
4027
|
});
|
|
@@ -4670,9 +4276,9 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4670
4276
|
if (!readOnly && imageEl) {
|
|
4671
4277
|
e.preventDefault();
|
|
4672
4278
|
e.stopPropagation();
|
|
4673
|
-
const
|
|
4674
|
-
if (
|
|
4675
|
-
const pos_1 = Number.parseInt(
|
|
4279
|
+
const pmStart = imageEl.dataset["pmStart"];
|
|
4280
|
+
if (pmStart !== void 0) {
|
|
4281
|
+
const pos_1 = Number.parseInt(pmStart, 10);
|
|
4676
4282
|
const hfSlot = hfEditMode ? findHfSlotForTarget(imageEl) : null;
|
|
4677
4283
|
const hfView_0 = hfSlot ? hfPMsRef.current?.getView(hfSlot.rId) : null;
|
|
4678
4284
|
if (hfView_0) {
|
|
@@ -4856,10 +4462,10 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4856
4462
|
const view_12 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
|
|
4857
4463
|
resizingHfSurfaceRef.current = null;
|
|
4858
4464
|
if (view_12) {
|
|
4859
|
-
const
|
|
4465
|
+
const pmStart_0 = resizeTablePmStartRef.current;
|
|
4860
4466
|
const colIdx = resizeColumnIndexRef.current;
|
|
4861
4467
|
const { left: newLeft, right: newRight } = resizeOrigWidthsRef.current;
|
|
4862
|
-
const $pos_5 = view_12.state.doc.resolve(
|
|
4468
|
+
const $pos_5 = view_12.state.doc.resolve(pmStart_0 + 1);
|
|
4863
4469
|
for (let d_3 = $pos_5.depth; d_3 >= 0; d_3--) {
|
|
4864
4470
|
const node_4 = $pos_5.node(d_3);
|
|
4865
4471
|
if (node_4.type.name === "table") {
|
|
@@ -4906,10 +4512,10 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4906
4512
|
const view_13 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
|
|
4907
4513
|
resizingHfSurfaceRef.current = null;
|
|
4908
4514
|
if (view_13) {
|
|
4909
|
-
const
|
|
4515
|
+
const pmStart_1 = resizeRowTablePmStartRef.current;
|
|
4910
4516
|
const rowIdx = resizeRowIndexRef.current;
|
|
4911
4517
|
const newHeight_0 = resizeRowOrigHeightRef.current;
|
|
4912
|
-
const $pos_6 = view_13.state.doc.resolve(
|
|
4518
|
+
const $pos_6 = view_13.state.doc.resolve(pmStart_1 + 1);
|
|
4913
4519
|
for (let d_4 = $pos_6.depth; d_4 >= 0; d_4--) {
|
|
4914
4520
|
const node_5 = $pos_6.node(d_4);
|
|
4915
4521
|
if (node_5.type.name === "table") {
|
|
@@ -4941,10 +4547,10 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
4941
4547
|
const view_14 = (resizingHfSurfaceRef.current ? hfPMsRef.current?.getView(resizingHfSurfaceRef.current.rId) : hiddenPMRef.current?.getView()) ?? null;
|
|
4942
4548
|
resizingHfSurfaceRef.current = null;
|
|
4943
4549
|
if (view_14) {
|
|
4944
|
-
const
|
|
4550
|
+
const pmStart_2 = resizeRightEdgePmStartRef.current;
|
|
4945
4551
|
const colIdx_0 = resizeRightEdgeColIndexRef.current;
|
|
4946
4552
|
const newWidth_1 = resizeRightEdgeOrigWidthRef.current;
|
|
4947
|
-
const $pos_7 = view_14.state.doc.resolve(
|
|
4553
|
+
const $pos_7 = view_14.state.doc.resolve(pmStart_2 + 1);
|
|
4948
4554
|
for (let d_5 = $pos_7.depth; d_5 >= 0; d_5--) {
|
|
4949
4555
|
const node_6 = $pos_7.node(d_5);
|
|
4950
4556
|
if (node_6.type.name === "table") {
|
|
@@ -5808,8 +5414,8 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
5808
5414
|
const container = containerRef.current;
|
|
5809
5415
|
if (!container) return;
|
|
5810
5416
|
const observer = new ResizeObserver(() => {
|
|
5811
|
-
const
|
|
5812
|
-
if (
|
|
5417
|
+
const state_8 = hiddenPMRef.current?.getState();
|
|
5418
|
+
if (state_8) updateSelectionOverlay(state_8);
|
|
5813
5419
|
});
|
|
5814
5420
|
observer.observe(container);
|
|
5815
5421
|
return () => observer.disconnect();
|
|
@@ -5817,11 +5423,11 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
5817
5423
|
useEffect(() => {
|
|
5818
5424
|
const hiddenHost = hiddenPMRef.current?.getHostElement();
|
|
5819
5425
|
if (!hiddenHost) return;
|
|
5820
|
-
let
|
|
5426
|
+
let animationFrame_0 = null;
|
|
5821
5427
|
const scheduleRefresh = () => {
|
|
5822
|
-
if (
|
|
5823
|
-
|
|
5824
|
-
|
|
5428
|
+
if (animationFrame_0 !== null) cancelAnimationFrame(animationFrame_0);
|
|
5429
|
+
animationFrame_0 = requestAnimationFrame(() => {
|
|
5430
|
+
animationFrame_0 = null;
|
|
5825
5431
|
refreshBodyImeCaretAnchor();
|
|
5826
5432
|
});
|
|
5827
5433
|
};
|
|
@@ -5830,7 +5436,7 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
5830
5436
|
hiddenHost.addEventListener("compositionend", scheduleRefresh);
|
|
5831
5437
|
window.addEventListener("scroll", scheduleRefresh, true);
|
|
5832
5438
|
return () => {
|
|
5833
|
-
if (
|
|
5439
|
+
if (animationFrame_0 !== null) cancelAnimationFrame(animationFrame_0);
|
|
5834
5440
|
hiddenHost.removeEventListener("focusin", refreshOnFocus);
|
|
5835
5441
|
hiddenHost.removeEventListener("compositionend", scheduleRefresh);
|
|
5836
5442
|
window.removeEventListener("scroll", scheduleRefresh, true);
|
|
@@ -5946,33 +5552,33 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
5946
5552
|
return bestNumber;
|
|
5947
5553
|
},
|
|
5948
5554
|
getBlockRect(blockId) {
|
|
5949
|
-
const
|
|
5950
|
-
const
|
|
5555
|
+
const state_9 = folioEditor.getState();
|
|
5556
|
+
const pagesContainer_6 = pagesContainerRef.current;
|
|
5951
5557
|
const scrollRoot = getScrollContainer();
|
|
5952
|
-
if (!
|
|
5558
|
+
if (!state_9 || !pagesContainer_6 || !scrollRoot) return null;
|
|
5953
5559
|
return readBlockRects({
|
|
5954
5560
|
blockIds: [blockId],
|
|
5955
|
-
snapshot: createFolioAIEditSnapshot$1(
|
|
5956
|
-
pagesContainer:
|
|
5561
|
+
snapshot: createFolioAIEditSnapshot$1(state_9.doc),
|
|
5562
|
+
pagesContainer: pagesContainer_6,
|
|
5957
5563
|
scrollRoot
|
|
5958
5564
|
}).get(blockId) ?? null;
|
|
5959
5565
|
},
|
|
5960
5566
|
getBlockRects(blockIds) {
|
|
5961
|
-
const
|
|
5962
|
-
const
|
|
5567
|
+
const state_10 = folioEditor.getState();
|
|
5568
|
+
const pagesContainer_7 = pagesContainerRef.current;
|
|
5963
5569
|
const scrollRoot_0 = getScrollContainer();
|
|
5964
|
-
if (!
|
|
5570
|
+
if (!state_10 || !pagesContainer_7 || !scrollRoot_0) return /* @__PURE__ */ new Map();
|
|
5965
5571
|
return readBlockRects({
|
|
5966
5572
|
blockIds,
|
|
5967
|
-
snapshot: createFolioAIEditSnapshot$1(
|
|
5968
|
-
pagesContainer:
|
|
5573
|
+
snapshot: createFolioAIEditSnapshot$1(state_10.doc),
|
|
5574
|
+
pagesContainer: pagesContainer_7,
|
|
5969
5575
|
scrollRoot: scrollRoot_0
|
|
5970
5576
|
});
|
|
5971
5577
|
},
|
|
5972
5578
|
getScrollRoot: getScrollContainer,
|
|
5973
5579
|
onLayoutChange(listener) {
|
|
5974
|
-
const
|
|
5975
|
-
return
|
|
5580
|
+
const pagesContainer_8 = pagesContainerRef.current;
|
|
5581
|
+
return pagesContainer_8 ? onPaintedLayoutChange(pagesContainer_8, listener) : () => {};
|
|
5976
5582
|
}
|
|
5977
5583
|
}), [
|
|
5978
5584
|
ensureHiddenEditorView,
|
|
@@ -5993,8 +5599,8 @@ const PagedEditor = forwardRef(function PagedEditor(props, ref) {
|
|
|
5993
5599
|
onTotalPagesChangeRef.current?.(totalPages);
|
|
5994
5600
|
}, [layout]);
|
|
5995
5601
|
useEffect(() => {
|
|
5996
|
-
const
|
|
5997
|
-
if (layout &&
|
|
5602
|
+
const state_11 = hiddenPMRef.current?.getState();
|
|
5603
|
+
if (layout && state_11) updateSelectionOverlay(state_11);
|
|
5998
5604
|
}, [layout, updateSelectionOverlay]);
|
|
5999
5605
|
const totalHeight = useMemo(() => {
|
|
6000
5606
|
if (!layout) return DEFAULT_PAGE_HEIGHT_PX + 48;
|
|
@@ -10585,6 +10191,26 @@ function useFindReplace(t0) {
|
|
|
10585
10191
|
* glue — the edit-position state, the memoised resolution, the host
|
|
10586
10192
|
* `pushDocument` routing, and reading the live hidden HF PM doc at save time.
|
|
10587
10193
|
*/
|
|
10194
|
+
const saveAndCloseHeaderFooterEdit = ({ activeRId, document, editPosition, isFirstPage, pushDocument, setEditPosition, view }) => {
|
|
10195
|
+
if (!activeRId || !view) {
|
|
10196
|
+
setEditPosition(null);
|
|
10197
|
+
return;
|
|
10198
|
+
}
|
|
10199
|
+
const source = (editPosition === "header" ? document.package.headers : document.package.footers)?.get(activeRId);
|
|
10200
|
+
if (!source) {
|
|
10201
|
+
setEditPosition(null);
|
|
10202
|
+
return;
|
|
10203
|
+
}
|
|
10204
|
+
const newDocument = saveHeaderFooterContent({
|
|
10205
|
+
document,
|
|
10206
|
+
position: editPosition,
|
|
10207
|
+
isFirstPage,
|
|
10208
|
+
activeRId,
|
|
10209
|
+
blocks: proseDocToBlocks(view.state.doc, source.content)
|
|
10210
|
+
});
|
|
10211
|
+
if (newDocument) pushDocument(newDocument);
|
|
10212
|
+
setEditPosition(null);
|
|
10213
|
+
};
|
|
10588
10214
|
const useHeaderFooterEditor = ({ history, pushDocument, getHfView }) => {
|
|
10589
10215
|
const [hfEditPosition, setHfEditPosition] = useState(null);
|
|
10590
10216
|
const [hfEditIsFirstPage, setHfEditIsFirstPage] = useState(false);
|
|
@@ -10624,17 +10250,15 @@ const useHeaderFooterEditor = ({ history, pushDocument, getHfView }) => {
|
|
|
10624
10250
|
}
|
|
10625
10251
|
const activeRId = pickActiveHeaderFooterRId(resolution, hfEditPosition, hfEditIsFirstPage);
|
|
10626
10252
|
const view = activeRId ? getHfView(activeRId) : null;
|
|
10627
|
-
|
|
10628
|
-
|
|
10629
|
-
|
|
10630
|
-
|
|
10631
|
-
|
|
10632
|
-
|
|
10633
|
-
|
|
10634
|
-
|
|
10635
|
-
|
|
10636
|
-
}
|
|
10637
|
-
setHfEditPosition(null);
|
|
10253
|
+
saveAndCloseHeaderFooterEdit({
|
|
10254
|
+
activeRId,
|
|
10255
|
+
document: history.state,
|
|
10256
|
+
editPosition: hfEditPosition,
|
|
10257
|
+
isFirstPage: hfEditIsFirstPage,
|
|
10258
|
+
pushDocument,
|
|
10259
|
+
setEditPosition: setHfEditPosition,
|
|
10260
|
+
view
|
|
10261
|
+
});
|
|
10638
10262
|
}, [
|
|
10639
10263
|
hfEditPosition,
|
|
10640
10264
|
hfEditIsFirstPage,
|
|
@@ -12680,7 +12304,7 @@ function useFolioComments({ doc, autoOpenReviewSidebar, anchorPositions, editorC
|
|
|
12680
12304
|
* - Error boundary
|
|
12681
12305
|
* - Loading states
|
|
12682
12306
|
*/
|
|
12683
|
-
const CommentsSidebar = lazy(() => import("./CommentsSidebar-
|
|
12307
|
+
const CommentsSidebar = lazy(() => import("./CommentsSidebar-Bvlu7MpL.js").then((m) => ({ default: m.CommentsSidebar })));
|
|
12684
12308
|
const TextContextMenu = lazy(() => import("./TextContextMenu-Ci7-M4oU.js").then((m) => ({ default: m.TextContextMenu })));
|
|
12685
12309
|
const loadAttemptSelectiveSave = async () => {
|
|
12686
12310
|
const { attemptSelectiveSave } = await import("@stll/folio-core/docx/selectiveSave");
|
|
@@ -12941,7 +12565,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
|
|
|
12941
12565
|
const scrollContainerRef = useRef(null);
|
|
12942
12566
|
const [formatPainterMode, setFormatPainterModeState] = useState("off");
|
|
12943
12567
|
const formatPainterModeRef = useRef("off");
|
|
12944
|
-
const capturedFormatMarksRef = useRef(
|
|
12568
|
+
const capturedFormatMarksRef = useRef(null);
|
|
12945
12569
|
const setFormatPainterMode = useCallback((next) => {
|
|
12946
12570
|
formatPainterModeRef.current = next;
|
|
12947
12571
|
setFormatPainterModeState(next);
|
|
@@ -13211,7 +12835,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
|
|
|
13211
12835
|
]);
|
|
13212
12836
|
const buildCurrentDocument = useCallback(() => {
|
|
13213
12837
|
if (!history.state) return null;
|
|
13214
|
-
let doc_0 =
|
|
12838
|
+
let doc_0 = cloneDocumentWithParagraphPropertySources(history.state);
|
|
13215
12839
|
const pmDoc = pagedEditorRef.current?.getDocument();
|
|
13216
12840
|
if (pmDoc) {
|
|
13217
12841
|
doc_0.package.document.content = pmDoc.package.document.content;
|
|
@@ -13224,7 +12848,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
|
|
|
13224
12848
|
if (!bag) return;
|
|
13225
12849
|
for (const [rId_0, hf] of bag) {
|
|
13226
12850
|
const view_5 = editor.getHfView(rId_0);
|
|
13227
|
-
if (view_5) hf.content = proseDocToBlocks(view_5.state.doc);
|
|
12851
|
+
if (view_5) hf.content = proseDocToBlocks(view_5.state.doc, hf.content);
|
|
13228
12852
|
}
|
|
13229
12853
|
};
|
|
13230
12854
|
flushBag(doc_0.package.headers);
|
|
@@ -13808,7 +13432,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
|
|
|
13808
13432
|
}, [getActiveEditorView, getCachedStyleResolver]);
|
|
13809
13433
|
const captureFormatPainter = useCallback(() => {
|
|
13810
13434
|
const view_10 = getActiveEditorView();
|
|
13811
|
-
capturedFormatMarksRef.current = view_10 ? captureFormatMarks(view_10.state) :
|
|
13435
|
+
capturedFormatMarksRef.current = view_10 ? captureFormatMarks(view_10.state) : null;
|
|
13812
13436
|
}, [getActiveEditorView]);
|
|
13813
13437
|
const paintFormatToSelection = useCallback(() => {
|
|
13814
13438
|
const view_11 = getActiveEditorView();
|
|
@@ -13819,7 +13443,7 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
|
|
|
13819
13443
|
}, [getActiveEditorView]);
|
|
13820
13444
|
const handleFormatPainter = useCallback((sticky) => {
|
|
13821
13445
|
if (formatPainterModeRef.current !== "off") {
|
|
13822
|
-
capturedFormatMarksRef.current =
|
|
13446
|
+
capturedFormatMarksRef.current = null;
|
|
13823
13447
|
setFormatPainterMode("off");
|
|
13824
13448
|
return;
|
|
13825
13449
|
}
|
|
@@ -13842,11 +13466,11 @@ const DocxEditor = forwardRef(function DocxEditor({ documentBuffer, password, do
|
|
|
13842
13466
|
const handleKeyDown = (event_0) => {
|
|
13843
13467
|
if (event_0.key === "Escape") {
|
|
13844
13468
|
const armed = formatPainterModeRef.current !== "off";
|
|
13845
|
-
const hasCopiedFormat = capturedFormatMarksRef.current
|
|
13469
|
+
const hasCopiedFormat = capturedFormatMarksRef.current !== null;
|
|
13846
13470
|
if (!armed && !hasCopiedFormat) return;
|
|
13847
13471
|
event_0.preventDefault();
|
|
13848
13472
|
event_0.stopPropagation();
|
|
13849
|
-
capturedFormatMarksRef.current =
|
|
13473
|
+
capturedFormatMarksRef.current = null;
|
|
13850
13474
|
if (armed) setFormatPainterMode("off");
|
|
13851
13475
|
return;
|
|
13852
13476
|
}
|