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