From 5ddd41905823fb77ca987517b63e46a63fe4d4ca Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 19 Mar 2025 14:40:24 -0400
Subject: fixed focus() on text boxes to scroll into view by hacking around a
 breaking prosemirror patch.

---
 .../views/nodes/formattedText/FormattedTextBox.tsx | 47 +++++++++++++---------
 1 file changed, 27 insertions(+), 20 deletions(-)

(limited to 'src/client/views/nodes/formattedText/FormattedTextBox.tsx')

diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 7b24125e7..b84575389 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1458,6 +1458,29 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
     }
     _didScroll = false;
     _scrollStopper: undefined | (() => void);
+    scrollToSelection = () => {
+        if (this.EditorView && this._ref.current) {
+            const editorView = this.EditorView;
+            const docPos = editorView.coordsAtPos(editorView.state.selection.to);
+            const viewRect = this._ref.current.getBoundingClientRect();
+            const scrollRef = this._scrollRef;
+            const topOff = docPos.top < viewRect.top ? docPos.top - viewRect.top : undefined;
+            const botOff = docPos.bottom > viewRect.bottom ? docPos.bottom - viewRect.bottom : undefined;
+            if (((topOff && Math.abs(Math.trunc(topOff)) > 0) || (botOff && Math.abs(Math.trunc(botOff)) > 0)) && scrollRef) {
+                const shift = Math.min(topOff ?? Number.MAX_VALUE, botOff ?? Number.MAX_VALUE);
+                const scrollPos = scrollRef.scrollTop + shift * this.ScreenToLocalBoxXf().Scale;
+                if (this._focusSpeed !== undefined) {
+                    setTimeout(() => {
+                        scrollPos && (this._scrollStopper = smoothScroll(this._focusSpeed || 0, scrollRef, scrollPos, 'ease', this._scrollStopper));
+                    });
+                } else {
+                    scrollRef.scrollTo({ top: scrollPos });
+                }
+                this._didScroll = true;
+            }
+        }
+        return true;
+    };
     // eslint-disable-next-line @typescript-eslint/no-explicit-any
     setupEditor(config: any, fieldKey: string) {
         const curText = Cast(this.dataDoc[this.fieldKey], RichTextField, null) || StrCast(this.dataDoc[this.fieldKey]);
@@ -1466,31 +1489,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
             this.EditorView?.destroy();
             this._editorView = new EditorView(this.ProseRef, {
                 state: rtfField?.Data ? EditorState.fromJSON(config, JSON.parse(rtfField.Data)) : EditorState.create(config),
-                handleScrollToSelection: editorView => {
-                    const docPos = editorView.coordsAtPos(editorView.state.selection.to);
-                    const viewRect = this._ref.current!.getBoundingClientRect();
-                    const scrollRef = this._scrollRef;
-                    const topOff = docPos.top < viewRect.top ? docPos.top - viewRect.top : undefined;
-                    const botOff = docPos.bottom > viewRect.bottom ? docPos.bottom - viewRect.bottom : undefined;
-                    if (((topOff && Math.abs(Math.trunc(topOff)) > 0) || (botOff && Math.abs(Math.trunc(botOff)) > 0)) && scrollRef) {
-                        const shift = Math.min(topOff ?? Number.MAX_VALUE, botOff ?? Number.MAX_VALUE);
-                        const scrollPos = scrollRef.scrollTop + shift * this.ScreenToLocalBoxXf().Scale;
-                        if (this._focusSpeed !== undefined) {
-                            setTimeout(() => {
-                                scrollPos && (this._scrollStopper = smoothScroll(this._focusSpeed || 0, scrollRef, scrollPos, 'ease', this._scrollStopper));
-                            });
-                        } else {
-                            scrollRef.scrollTo({ top: scrollPos });
-                        }
-                        this._didScroll = true;
-                    }
-                    return true;
-                },
+                handleScrollToSelection: this.scrollToSelection,
                 dispatchTransaction: this.dispatchTransaction,
                 nodeViews: FormattedTextBox._nodeViews(this),
                 clipboardTextSerializer: this.clipboardTextSerializer,
                 handlePaste: this.handlePaste,
             });
+            // bcz: major hack!   a patch to prosemirror broke scrolling to selection when the selection is not a dom selection
+            //   this replaces prosemirror's scrollToSelection function with Dash's
+            (this.EditorView as unknown as { scrollToSelection: unknown }).scrollToSelection = this.scrollToSelection;
             const { state } = this._editorView;
             if (!rtfField) {
                 const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc.proto), this.fieldKey) ? DocCast(this.layoutDoc.proto) : this.dataDoc;
-- 
cgit v1.2.3-70-g09d2

