fix: keep drag.dragover cheap and depth-aware#2639
Conversation
🦋 Changeset detectedLatest commit: b1aab4f The changes in this PR will be included in the next version bump. This PR includes changesets to release 11 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📦 Bundle Stats —
|
| Metric | Value | vs main (1b64415) |
|---|---|---|
| Internal (raw) | 745.6 KB | +1.4 KB, +0.2% |
| Internal (gzip) | 143.1 KB | +277 B, +0.2% |
| Bundled (raw) | 1.35 MB | +1.4 KB, +0.1% |
| Bundled (gzip) | 304.1 KB | +299 B, +0.1% |
| Import time | 98ms | -1ms, -0.7% |
@portabletext/editor/behaviors
| Metric | Value | vs main (1b64415) |
|---|---|---|
| Internal (raw) | 467 B | - |
| Internal (gzip) | 207 B | - |
| Bundled (raw) | 424 B | - |
| Bundled (gzip) | 171 B | - |
| Import time | 2ms | +0ms, +0.4% |
@portabletext/editor/plugins
| Metric | Value | vs main (1b64415) |
|---|---|---|
| Internal (raw) | 3.6 KB | - |
| Internal (gzip) | 1021 B | - |
| Bundled (raw) | 3.4 KB | - |
| Bundled (gzip) | 952 B | - |
| Import time | 8ms | -0ms, -0.5% |
@portabletext/editor/selectors
| Metric | Value | vs main (1b64415) |
|---|---|---|
| Internal (raw) | 76.2 KB | -33 B, -0.0% |
| Internal (gzip) | 14.3 KB | -24 B, -0.2% |
| Bundled (raw) | 72.4 KB | -33 B, -0.0% |
| Bundled (gzip) | 13.3 KB | -35 B, -0.3% |
| Import time | 8ms | -0ms, -0.5% |
@portabletext/editor/traversal
| Metric | Value | vs main (1b64415) |
|---|---|---|
| Internal (raw) | 9.2 KB | - |
| Internal (gzip) | 2.4 KB | - |
| Bundled (raw) | 9.3 KB | - |
| Bundled (gzip) | 2.4 KB | - |
| Import time | 5ms | +0ms, +0.8% |
@portabletext/editor/utils
| Metric | Value | vs main (1b64415) |
|---|---|---|
| Internal (raw) | 30.6 KB | - |
| Internal (gzip) | 6.5 KB | - |
| Bundled (raw) | 28.4 KB | - |
| Bundled (gzip) | 6.1 KB | - |
| Import time | 6ms | -0ms, -2.8% |
🗺️ . · ./behaviors · ./plugins · ./selectors · ./traversal · ./utils · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
|
Closing — after the fixup that restored the behavior-level preventDefault, this PR ends up doing the same guard compute twice per dragover (once in the behavior, once in the hook) without a real win. The depth-shared-key bug ( |
drag.dragoverfires at 50–100Hz during an internal drag. Today the drop-indicator computation goes through the behavior pipeline as a pair of behaviors registered viacreateDropPositionBehaviorsConfig. Thedrag.dragoverbehavior recomputesgetDragSelection,getSelectedBlocks, andisSelectingEntireBlockson every event, even though all three derive fromdragOrigin.selectionwhich is stable for the entire drag. The same-block check isdragged._key === dropFocus._key- a depth-1 comparison from the same bug class as #2638 (keys are sibling-unique, not tree-unique).The behavior shape was the wrong layer for what the code actually does. Behaviors compose synthetic events that transform the editor model. This handler reads position from a DOM event and writes to a React state setter via an
effectaction. It's a UI affordance, not a transform.This PR moves the drop-indicator computation into
useDropPositiondirectly, alongside the React state it drives. The dragged-blocks list and entire-blocks check are computed once withuseMemokeyed oninternalDrag. Per dragover does onegetEnclosingBlockfor the cursor's block plus anArray.someover the small dragged-blocks list, thensetDropPosition. Same-block discrimination usespathEqualsinstead of key compare, which closes the depth-shared-key bug class.Editablecalls the returnedupdateDropPositionfrom its existinghandleDragOvercallback, alongside the existingeditor.send({type: 'behavior event', ...})forwarding (so consumer plugins listening ondrag.dragoverkeep working).createDropPositionBehaviorsConfigand the two behaviors it returned are deleted. TheDropPositiontype moves touse-drop-position.ts.7 existing dnd browser tests pass on chromium. 5 unit tests for
resolveElementDropPosition(the per-element matcher from #2638) pass.PR #2555 (the WeakMap memo on
dragOrigin) is superseded by this - closing.