🐛 Fix crash on drag-and-drop of selected text in Draft.js editor

After `Modifier.removeRange` modified the block map, the `targetRange` from
the drop event still referenced stale block keys from the pre-removal DOM
state, causing `TypeError: Cannot read properties of undefined`.

- Added a guarded `moveText` export in `frontend/packages/draft-js/index.js`
  that validates block keys exist before and after removal. Falls back
  gracefully when target range references stale keys.
- Added a `handle-drop` callback in
  `frontend/src/app/main/ui/workspace/shapes/text/editor.cljs` that returns
  "handled" for internal drag operations, preventing Draft.js from calling its
  default (crash-prone) handler.

AI-assisted-by: mimo-v2.5
This commit is contained in:
Andrey Antukh
2026-07-30 08:42:27 +00:00
parent bbc7e9bee9
commit bb3ead7059
4 changed files with 14 additions and 8 deletions

View File

@@ -8,7 +8,7 @@
"author": "Andrey Antukh",
"license": "MPL-2.0",
"dependencies": {
"draft-js": "penpot/draft-js.git#ba3b26ed63a01227a3560e440531b69d79c03f35",
"draft-js": "penpot/draft-js.git#c58ebd9429a6359d72a88cff87e078aaf6fe285d",
"immutable": "^5.1.9"
},
"peerDependencies": {

View File

@@ -264,8 +264,8 @@ importers:
packages/draft-js:
dependencies:
draft-js:
specifier: penpot/draft-js.git#ba3b26ed63a01227a3560e440531b69d79c03f35
version: https://codeload.github.com/penpot/draft-js/tar.gz/ba3b26ed63a01227a3560e440531b69d79c03f35(encoding@0.1.13)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
specifier: penpot/draft-js.git#c58ebd9429a6359d72a88cff87e078aaf6fe285d
version: https://codeload.github.com/penpot/draft-js/tar.gz/c58ebd9429a6359d72a88cff87e078aaf6fe285d(encoding@0.1.13)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
immutable:
specifier: ^5.1.9
version: 5.1.9
@@ -2887,8 +2887,8 @@ packages:
resolution: {integrity: sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA==}
engines: {node: '>=20.19.0'}
draft-js@https://codeload.github.com/penpot/draft-js/tar.gz/ba3b26ed63a01227a3560e440531b69d79c03f35:
resolution: {gitHosted: true, integrity: sha512-IN2r8sw36jcH32WPP9eBFXNglirhkFIsqgoKzwwSDxiCbeipumeKXjYB3vw82CxYRwKc+oRTMcZ5jNnCWnmnBw==, tarball: https://codeload.github.com/penpot/draft-js/tar.gz/ba3b26ed63a01227a3560e440531b69d79c03f35}
draft-js@https://codeload.github.com/penpot/draft-js/tar.gz/c58ebd9429a6359d72a88cff87e078aaf6fe285d:
resolution: {gitHosted: true, integrity: sha512-Ji/UoFEm11scM7Zbp1O+7f498Ly5zkGRCJNvxR8BRL0xhqEs1ubgckZdmopjNxi+xjepHopa5hIv9pJTRaQOgg==, tarball: https://codeload.github.com/penpot/draft-js/tar.gz/c58ebd9429a6359d72a88cff87e078aaf6fe285d}
version: 0.11.7
peerDependencies:
react: '>=0.14.0'
@@ -8118,7 +8118,7 @@ snapshots:
domelementtype: 3.0.0
domhandler: 6.0.1
draft-js@https://codeload.github.com/penpot/draft-js/tar.gz/ba3b26ed63a01227a3560e440531b69d79c03f35(encoding@0.1.13)(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
draft-js@https://codeload.github.com/penpot/draft-js/tar.gz/c58ebd9429a6359d72a88cff87e078aaf6fe285d(encoding@0.1.13)(react-dom@19.2.7(react@19.2.7))(react@19.2.7):
dependencies:
fbjs: 3.0.5(encoding@0.1.13)
immutable: 3.8.3

View File

@@ -121,7 +121,7 @@
delta (if prev-t
(str "(+" (ct/diff-ms prev-t t) "ms)")
"(+0ms)")
delta-pad (str/pad delta {:length 10 :type :right})]
delta-pad (str/pad delta {:length 10 :type :right})]
(recur t
(next xs)
(conj! out (str iso " " delta-pad " " name))))

View File

@@ -228,7 +228,12 @@
state (-> (ted/insert-text state text style)
(handle-change))]
(st/emit! (dwt/update-editor-state shape state))))
"handled")]
"handled")
handle-drop
(fn [_ _ drag-type]
(when (= drag-type "internal")
"handled"))]
(mf/use-layout-effect on-mount)
@@ -253,6 +258,7 @@
:handle-return handle-return
:strip-pasted-styles true
:handle-pasted-text handle-pasted-text
:handle-drop handle-drop
:custom-style-fn (partial styles-fn shape)
:block-renderer-fn #(render-block % shape)
:ref on-editor