Skip to content

Commit 8c9602d

Browse files
committed
refactor(editor): decompose updateSelection into named rendering methods
Split the 156-line #updateSelection into a decision tree + 2 renderers: - #updateSelection: guard chain + dispatch to caret or range path - #renderCaretOverlayIfNeeded: collapsed selection (caret) rendering - #renderRangeSelectionOverlay: range selection rects rendering #updateSelection now reads as: check guards → sync SDT styles → handle cell selection → dispatch to caret or range renderer. Reduces PresentationEditor from 4757 to 4749 lines (-8 net, but #updateSelection itself drops from 156 to 95 lines).
1 parent f793562 commit 8c9602d

1 file changed

Lines changed: 26 additions & 34 deletions

File tree

packages/super-editor/src/core/presentation-editor/PresentationEditor.ts

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3485,53 +3485,46 @@ export class PresentationEditor extends EventEmitter {
34853485
}
34863486

34873487
if (from === to) {
3488-
const caretLayout = this.#computeCaretLayoutRect(from);
3489-
if (!caretLayout) {
3490-
// Keep existing cursor visible rather than clearing it
3491-
return;
3492-
}
3493-
// Only clear old cursor after successfully computing new position
3494-
try {
3495-
this.#localSelectionLayer.innerHTML = '';
3496-
renderCaretOverlay({
3497-
localSelectionLayer: this.#localSelectionLayer,
3498-
caretLayout,
3499-
convertPageLocalToOverlayCoords: (pageIndex, x, y) => this.#convertPageLocalToOverlayCoords(pageIndex, x, y),
3500-
});
3501-
} catch (error) {
3502-
// DOM manipulation can fail if element is detached or in invalid state
3503-
if (process.env.NODE_ENV === 'development') {
3504-
console.warn('[PresentationEditor] Failed to render caret overlay:', error);
3505-
}
3506-
}
3488+
this.#renderCaretOverlayIfNeeded(from);
35073489
return;
35083490
}
35093491

3492+
this.#renderRangeSelectionOverlay(selection, from, to);
3493+
}
3494+
3495+
#renderCaretOverlayIfNeeded(pos: number): void {
3496+
const caretLayout = this.#computeCaretLayoutRect(pos);
3497+
if (!caretLayout) return;
3498+
try {
3499+
this.#localSelectionLayer.innerHTML = '';
3500+
renderCaretOverlay({
3501+
localSelectionLayer: this.#localSelectionLayer,
3502+
caretLayout,
3503+
convertPageLocalToOverlayCoords: (pageIndex, x, y) => this.#convertPageLocalToOverlayCoords(pageIndex, x, y),
3504+
});
3505+
} catch (error) {
3506+
if (process.env.NODE_ENV === 'development') {
3507+
console.warn('[PresentationEditor] Failed to render caret overlay:', error);
3508+
}
3509+
}
3510+
}
3511+
3512+
#renderRangeSelectionOverlay(selection: import('prosemirror-state').Selection, from: number, to: number): void {
35103513
const domRects = this.#computeSelectionRectsFromDom(from, to);
35113514
if (domRects == null) {
3512-
// DOM-derived selection failed; keep last known-good overlay instead of drifting.
35133515
debugLog('warn', 'Local selection: DOM rect computation failed', { from, to });
35143516
return;
35153517
}
35163518

3517-
// When dragging across mark boundaries, the selection can briefly land in the
3518-
// 2-position structural gap between adjacent runs, producing zero DOM rects for
3519-
// one frame. Preserve the last overlay only during active drag to prevent flicker.
3520-
// Outside drag (scroll, programmatic changes), zero rects means the DOM is stale
3521-
// or virtualized — clearing the overlay is the safer default.
3522-
if (domRects.length === 0 && from !== to && this.#editorInputManager?.isDragging) {
3523-
debugLog('warn', '[drawSelection] zero rects for non-collapsed selection — preserving last overlay', {
3524-
from,
3525-
to,
3526-
});
3519+
// Preserve last overlay during active drag when rects are empty (mark boundary gap)
3520+
if (domRects.length === 0 && this.#editorInputManager?.isDragging) {
35273521
return;
35283522
}
35293523

35303524
try {
35313525
this.#localSelectionLayer.innerHTML = '';
3532-
const isFieldAnnotationSelection =
3533-
selection instanceof NodeSelection && selection.node?.type?.name === 'fieldAnnotation';
3534-
if (domRects.length > 0 && !isFieldAnnotationSelection) {
3526+
const isFieldAnnotation = selection instanceof NodeSelection && selection.node?.type?.name === 'fieldAnnotation';
3527+
if (domRects.length > 0 && !isFieldAnnotation) {
35353528
renderSelectionRects({
35363529
localSelectionLayer: this.#localSelectionLayer,
35373530
rects: domRects,
@@ -3541,7 +3534,6 @@ export class PresentationEditor extends EventEmitter {
35413534
});
35423535
}
35433536
} catch (error) {
3544-
// DOM manipulation can fail if element is detached or in invalid state
35453537
if (process.env.NODE_ENV === 'development') {
35463538
console.warn('[PresentationEditor] Failed to render selection rects:', error);
35473539
}

0 commit comments

Comments
 (0)