Gap
Drag-across-to-select — press on a row, move the pointer, select everything
passed over — is not expressible in either core language.
on-drag is the only signal that a button is held while the pointer moves,
but it reports the drag SOURCE (sourceId) plus raw view-local x/y. An
app cannot turn that y into a row: layout lives in the runtime, and rows
vary in height (wrapping, inline images). There is also no press-down /
press-up pair, so there is no other way to know a button is down.
on-drag also lifts the source out of flow and draws it under the pointer.
That is right for reordering and wrong for selection: every drag looks like
the row is being dragged away.
on-hover-enter is not an answer either — containment advances on
hover-phase motion, which a button-down drag is not.
Why the obvious fix doesn't help
Reporting the widget id under the pointer is useless to an app: it has no
map from ObjectId back to its own data.
Proposed shape
Report the global key of the widget under the pointer.
Apps already set global-key="{row.id}" to their own item id, so the value
is meaningful with no new mapping. WidgetOptions.global_key is already
stored per widget (integer or string), and the runtime already hit-tests
during a drag — so the value exists at dispatch time.
Two candidate spellings, and I'd rather have direction than guess:
- A 7th field (
overKey) on the existing drag record, behind a new
reflect predicate so the current 6-field shape keeps working. Cheapest,
but widens a record the docs describe as closed.
- A separate
on-drag-over naming an arm of
{ sourceKey, overKey, phase }. More surface, but it leaves the reorder
record alone and reads as its own gesture.
(2) looks like the better citizen from outside, but you own that call.
Selection drag must also not lift the source — either a
drag-mode="select" attribute, or infer it (an element with on-drag-over
and no on-drag does not lift).
Touch list
Mirrors #318: ui_markup_reflect.zig, ui.zig,
canvas_widget_events.zig (resolve the global key under the pointer during
a drag), both engines, ui_markup_contract.zig (payload class + artifact
version), automation (widget-drag routing the over-key), tests, docs,
skill-data.
Context
Came out of building a capture inbox where multi-select is core. #318
(press modifiers) covers cmd-click and shift-click; this is the remaining
gesture. Happy to implement it once you've said which spelling you want —
and it probably wants to land after #318, since it touches adjacent code.
Gap
Drag-across-to-select — press on a row, move the pointer, select everything
passed over — is not expressible in either core language.
on-dragis the only signal that a button is held while the pointer moves,but it reports the drag SOURCE (
sourceId) plus raw view-localx/y. Anapp cannot turn that
yinto a row: layout lives in the runtime, and rowsvary in height (wrapping, inline images). There is also no press-down /
press-up pair, so there is no other way to know a button is down.
on-dragalso lifts the source out of flow and draws it under the pointer.That is right for reordering and wrong for selection: every drag looks like
the row is being dragged away.
on-hover-enteris not an answer either — containment advances onhover-phase motion, which a button-down drag is not.
Why the obvious fix doesn't help
Reporting the widget id under the pointer is useless to an app: it has no
map from
ObjectIdback to its own data.Proposed shape
Report the global key of the widget under the pointer.
Apps already set
global-key="{row.id}"to their own item id, so the valueis meaningful with no new mapping.
WidgetOptions.global_keyis alreadystored per widget (integer or string), and the runtime already hit-tests
during a drag — so the value exists at dispatch time.
Two candidate spellings, and I'd rather have direction than guess:
overKey) on the existing drag record, behind a newreflect predicate so the current 6-field shape keeps working. Cheapest,
but widens a record the docs describe as closed.
on-drag-overnaming an arm of{ sourceKey, overKey, phase }. More surface, but it leaves the reorderrecord alone and reads as its own gesture.
(2) looks like the better citizen from outside, but you own that call.
Selection drag must also not lift the source — either a
drag-mode="select"attribute, or infer it (an element withon-drag-overand no
on-dragdoes not lift).Touch list
Mirrors #318:
ui_markup_reflect.zig,ui.zig,canvas_widget_events.zig(resolve the global key under the pointer duringa drag), both engines,
ui_markup_contract.zig(payload class + artifactversion), automation (
widget-dragrouting the over-key), tests, docs,skill-data.Context
Came out of building a capture inbox where multi-select is core. #318
(press modifiers) covers cmd-click and shift-click; this is the remaining
gesture. Happy to implement it once you've said which spelling you want —
and it probably wants to land after #318, since it touches adjacent code.