Skip to content

feat(dnd): pluggable drop position resolver#1382

Merged
mathuo merged 2 commits into
v8-branchfrom
feat/drop-position-resolver
Jun 27, 2026
Merged

feat(dnd): pluggable drop position resolver#1382
mathuo merged 2 commits into
v8-branchfrom
feat/drop-position-resolver

Conversation

@mathuo

@mathuo mathuo commented Jun 27, 2026

Copy link
Copy Markdown
Owner

A small, free-core extensibility seam for drag-and-drop: let a consumer override how a pointer location within a drop target maps to a drop Position, replacing the built-in cursor-quadrant threshold bands — without re-implementing the overlay or commit path.

What's added

  • PositionResolver contract (dnd/droptarget.ts, exported): resolve({ x, y, width, height, zones, event }) => { position, edge? } | null. null means "no drop here".
  • Both DnD backends (Droptarget and PointerDropTarget) consult an optional, lazy getPositionResolver getter at the drag-over resolve step — matching the existing getOverrideTarget / getOverlayOutline getters, so the source can change at runtime. When unset, the default quadrant logic runs unchanged.
  • Public option DockviewOptions.dropPositionResolver, read live (swappable via updateOptions), threaded into the 5-way group/layout drop targets — group content + whole-layout edges. Tab/header reorder targets intentionally keep the default quadrant.

Why

This is a reusable building block for aim-at-a-cell drop affordances and other custom drop-resolution UIs: the consumer supplies a hit-test, the existing overlay + commit path render/commit whatever Position it returns. Shipping it as a standalone seam lets it bake before anything builds on it (same approach as transformFloatingGroupDrag).

Backward compatibility

Fully additive. With dropPositionResolver unset (the default for everyone), the drop loop is byte-for-byte unchanged — no behaviour change for existing consumers.

Tests

  • Both backends: resolver overrides the quadrant, a null result shows no drop target, and the default-when-absent path is unchanged.
  • Integration: the public dropPositionResolver option reaches the group content drop target.
  • core: 1087 tests green.

🤖 Generated with Claude Code

mathuo and others added 2 commits June 27, 2026 21:26
Add an optional `PositionResolver` to the drop-target options that overrides how
a pointer location within a target maps to a drop `Position` (or `null` for no
drop), replacing the built-in cursor-quadrant threshold bands. Both DnD backends
(`Droptarget` and `PointerDropTarget`) consult the same resolver at the drag-over
resolve step; when unset the default quadrant logic runs unchanged — the drop
loop is byte-for-byte identical for every existing consumer.

This is a free-core extensibility hook: it lets a consumer drive drop resolution
from a custom hit-test (e.g. aim-at-a-cell affordances) without re-implementing
the overlay or commit path. Exposes `PositionResolver` + its arg/result types.

Unit tests cover both backends: the resolver overriding the quadrant, a `null`
result showing no drop target, and the default-when-absent path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rop targets

Expose the drop-position-resolver seam as a public app option,
`DockviewOptions.dropPositionResolver`, and thread it (read live, like
`getOverrideTarget`) into the 5-way group/layout drop targets — the group
content (`content.ts`) and the whole-layout edges (`rootDropTargetService.ts`).
Tab / header reorder targets are intentionally left on the default quadrant.

Unset ⇒ the built-in cursor-quadrant behaviour, unchanged. With it set, an app
can drive group-dock resolution from a custom hit-test (e.g. an aim-at-a-cell
affordance) without re-implementing the overlay or commit path.

Adds an integration test that the option reaches the content drop target, plus
the PROPERTY_KEYS entry so `updateOptions` forwards it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@mathuo mathuo merged commit 893fd26 into v8-branch Jun 27, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant