@jsenv/navi 0.29.193 → 0.29.195
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev/jsenv_navi.js +210 -68
- package/dist/dev/jsenv_navi.js.map +6 -3
- package/dist/jsenv_navi.js +139 -48
- package/dist/jsenv_navi.js.map +6 -3
- package/docs/drag_to_travel.md +2 -2
- package/docs/interactions.md +137 -52
- package/package.json +2 -2
package/docs/drag_to_travel.md
CHANGED
|
@@ -227,7 +227,7 @@ outside it.
|
|
|
227
227
|
A drag reads the same press a travel does and holds the pointer from it, so the
|
|
228
228
|
two share a finger exactly as two travelling boxes do: what is picked up says
|
|
229
229
|
which axes it walks (`data-drag-source`, written from `data-drag-axis` by
|
|
230
|
-
`interactions={{ move, reorder, land, toss }}` — see `docs/interactions.md`), and
|
|
230
|
+
`interactions={{ move, reorder, land, toss, leave }}` — see `docs/interactions.md`), and
|
|
231
231
|
the box above keeps what is left. A list reordered along its own line inside a
|
|
232
232
|
row of slides swiped sideways: both gestures live, and neither had to be told
|
|
233
233
|
about the other.
|
|
@@ -565,7 +565,7 @@ outside — and will not find out until they watch a page leave under their
|
|
|
565
565
|
finger. The component knows, so the component says it.
|
|
566
566
|
|
|
567
567
|
_Currently marked: the wheel viewport, the table resize handles, the cells of a
|
|
568
|
-
table whose columns can be dragged
|
|
568
|
+
table whose columns can be dragged, a surface declaring `pan` or `zoom`._
|
|
569
569
|
|
|
570
570
|
## The two consumers that travel between screens
|
|
571
571
|
|
package/docs/interactions.md
CHANGED
|
@@ -40,9 +40,13 @@ one — `Box`, `List.Item`, `Button`, `Link`, the field components. Its keys are
|
|
|
40
40
|
/>
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
`action` is
|
|
44
|
-
change on a field
|
|
45
|
-
natural one.
|
|
43
|
+
`action` is a control's prop and is untouched by this: a control keeps its own
|
|
44
|
+
wiring — a click on a button, a change on a field — and `interactions` is the
|
|
45
|
+
other half, everything that is not that natural one. A plain `Box` has no such
|
|
46
|
+
wiring: it does nothing with `action` (dev warns), and a click on it is declared
|
|
47
|
+
like any other interaction, `interactions={{ click: onSelect }}`. The click the
|
|
48
|
+
browser fires after a drag is already suppressed, so `click` sits next to `move`
|
|
49
|
+
or `grab` without fighting them.
|
|
46
50
|
|
|
47
51
|
### The three values
|
|
48
52
|
|
|
@@ -62,8 +66,9 @@ condition: `{ swipe_right: canArchive && archive }`.
|
|
|
62
66
|
| `mousedown` `mouseup` `click` `dblclick` `contextmenu` | the browser's own events |
|
|
63
67
|
| `swipe_left` `swipe_right` `swipe_up` `swipe_down` | a press that travels |
|
|
64
68
|
| `longpress` | a press held still |
|
|
65
|
-
| `move` `reorder` `land` `toss`
|
|
69
|
+
| `move` `reorder` `land` `toss` `leave` | the element carried, and what letting go means |
|
|
66
70
|
| `grab` | the instant a drag takes hold of it |
|
|
71
|
+
| `pan` `zoom` | a surface under the hand, or under a wheel |
|
|
67
72
|
| `"keyboard:<shortcut>"` | keys, e.g. `"keyboard:ctrl+backspace"` |
|
|
68
73
|
|
|
69
74
|
A name nothing knows how to detect produces a dev warning naming the detectors
|
|
@@ -156,16 +161,19 @@ comes back once it settles — a failure leaves the row in place so it can be tr
|
|
|
156
161
|
again. What a success does to the element is yours (a list that redemands its
|
|
157
162
|
rows, a row that leaves): navi does not make it disappear.
|
|
158
163
|
|
|
159
|
-
## Carrying something: `move`, `reorder`, `land`, `toss`
|
|
164
|
+
## Carrying something: `move`, `reorder`, `land`, `toss`, `leave`
|
|
160
165
|
|
|
161
|
-
All
|
|
166
|
+
All five are the same gesture — the element is picked up and carried — and what
|
|
162
167
|
differs is the release. One detector reads them all, because it is one press.
|
|
163
168
|
|
|
164
|
-
`toss` **
|
|
165
|
-
element changes places, thrown far and fast it is gotten rid of
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
release cannot mean two of those
|
|
169
|
+
`toss` and `leave` each **combine** with `reorder` and with `land`: dropped on
|
|
170
|
+
another item the element changes places, thrown far and fast it is gotten rid of,
|
|
171
|
+
let go of away from every place it leaves. `leave` combines with `move` as well.
|
|
172
|
+
`toss` does **not** combine with `move`, and neither do `reorder` and `land` with
|
|
173
|
+
each other — one release cannot mean two of those. Declared together, the
|
|
174
|
+
copy-carrying one wins and `move` is never answered — the element itself never
|
|
175
|
+
travels, and a release that is not the other outcome means nothing at all (a dev
|
|
176
|
+
warning says so).
|
|
169
177
|
|
|
170
178
|
`move` carries the element ITSELF and leaves it where it was put; the others
|
|
171
179
|
carry a copy and put the original back. That is the same difference said in layout
|
|
@@ -187,11 +195,22 @@ be a scroll container at all (`overflow` anything but `visible`), since there is
|
|
|
187
195
|
nothing else for "inside" to mean. A `move` whose answer rejects travels back, because a
|
|
188
196
|
place the application would not accept must not stay on screen as if it had.
|
|
189
197
|
|
|
190
|
-
**
|
|
198
|
+
**Where the position is kept is the answer's.** An element drawn from state —
|
|
199
|
+
`left`/`top` computed from a position the application holds — is redrawn by the
|
|
200
|
+
handler above, and from then on its layout owns the position: navi sees the
|
|
201
|
+
element drawn elsewhere while the answer was given and lets go of its own
|
|
202
|
+
translate, so the thing does not land twice as far as the hand went. A handler
|
|
203
|
+
that draws nothing (a token on a free canvas) leaves the position to the element,
|
|
204
|
+
where it is baked in. Nothing to declare either way — but a handler whose draw
|
|
205
|
+
comes later than its answer has to return the promise of that draw.
|
|
206
|
+
|
|
207
|
+
**A copy that can be thrown frees its own area.** What is dragged is otherwise kept
|
|
191
208
|
inside its scroll area — right for a reorder, since a row belongs to its list, and
|
|
192
209
|
fatal for a throw: the copy hits the edge of the list, no distance is ever covered,
|
|
193
|
-
so no throw can happen and no sideways movement is even visible. So
|
|
194
|
-
|
|
210
|
+
so no throw can happen and no sideways movement is even visible. So `toss` lifts
|
|
211
|
+
that constraint for the copy it carries, and `leave` lifts it for whatever it is
|
|
212
|
+
declared on — a thing that can be let go of outside has to be able to get there.
|
|
213
|
+
Neither is a way to free a plain `move`, which says `data-drag-free`.
|
|
195
214
|
|
|
196
215
|
```jsx
|
|
197
216
|
<List.Item
|
|
@@ -211,7 +230,7 @@ together let it leave.
|
|
|
211
230
|
```
|
|
212
231
|
|
|
213
232
|
The gesture is `startDragTo`'s, whole: `move` carries the element itself, the
|
|
214
|
-
|
|
233
|
+
others carry a copy above the page while the original keeps its place, with a
|
|
215
234
|
drop hint, drop targets found by intersection, no-op drops filtered out, and the
|
|
216
235
|
flight of a thrown copy plus its return when the answer refuses. Only what the
|
|
217
236
|
declared outcomes need runs — no copy for a move, no hint for something
|
|
@@ -244,36 +263,28 @@ name what moves.
|
|
|
244
263
|
| `data-drag-delay` `data-drag-slop` `data-drag-threshold` | when the press becomes a grab |
|
|
245
264
|
| `data-drag-on-contact` | a finger may drag by travelling too |
|
|
246
265
|
| `data-toss-distance` `data-toss-speed` | how far and how fast counts as a throw |
|
|
247
|
-
| `data-toss-by="throw"\|"release-outside"` | how a toss is made here |
|
|
248
266
|
| `data-drop-container` | where the places are looked for |
|
|
249
267
|
|
|
250
|
-
###
|
|
251
|
-
|
|
252
|
-
`toss` names the outcome — the thing is gotten rid of — and a hand has two ways of
|
|
253
|
-
saying it, each right where the other is wrong:
|
|
254
|
-
|
|
255
|
-
- **`throw`** (the default): far **and** fast — that pair is what a flick is, and
|
|
256
|
-
it is asked for together because one without the other is moving something while
|
|
257
|
-
hesitating. A list's gesture. It is judged before any landing: a row sent across
|
|
258
|
-
the screen has not asked to swap places with whatever it flew over.
|
|
259
|
-
- **`release-outside`**: let go with no place under it. Dragging a marker off the plan it
|
|
260
|
-
sits on and letting go is slow and deliberate — a surface's gesture, and the only
|
|
261
|
-
one it wants, because on a plan a fast drag that ends ON it has not asked for the
|
|
262
|
-
thing to go.
|
|
268
|
+
### Let go of away from every place: `leave`
|
|
263
269
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
270
|
+
A throw is a **gesture**: far and fast, the flick that gets rid of a row, judged
|
|
271
|
+
before any landing. A release outside is a **place**: the hand let go with nothing
|
|
272
|
+
under the thing, judged after a landing was looked for. They share the outcome an
|
|
273
|
+
application usually attaches to them and nothing else — so `toss` is the throw,
|
|
274
|
+
`leave` is the release outside, and neither reads the other's rules. There is no
|
|
275
|
+
speed to a release; a fast drag across a plan that ends ON it has not asked for the
|
|
276
|
+
thing to go, and a row pulled sideways out of its list and let go is a row put
|
|
277
|
+
back, not a row deleted — a list declares `toss`, a surface declares `leave`.
|
|
267
278
|
|
|
268
279
|
```jsx
|
|
269
280
|
<div data-drop-container>
|
|
270
|
-
<Plan id="plan" data-droppable
|
|
281
|
+
<Plan id="plan" data-droppable>
|
|
271
282
|
{markers.map((marker) => (
|
|
272
283
|
<Marker
|
|
273
284
|
id={marker.id}
|
|
274
285
|
interactions={{
|
|
275
286
|
land: (event) => moveTo(marker.id, event.detail),
|
|
276
|
-
|
|
287
|
+
leave: () => remove(marker.id),
|
|
277
288
|
}}
|
|
278
289
|
/>
|
|
279
290
|
))}
|
|
@@ -281,11 +292,36 @@ return if the answer rejects. Both at once is
|
|
|
281
292
|
</div>
|
|
282
293
|
```
|
|
283
294
|
|
|
284
|
-
`
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
warning says
|
|
295
|
+
`leave` combines with every other outcome. Beside `land` or `reorder`, "outside" is
|
|
296
|
+
away from every place. Beside `move` — the element itself travels, and nothing is a
|
|
297
|
+
place — it is outside the surface the element stands in: the nearest
|
|
298
|
+
`data-droppable` ancestor, or, without one, what can be seen of the scroll
|
|
299
|
+
container (a dev warning says which). Either way it is judged on the element's
|
|
300
|
+
box no longer overlapping it, not on the pointer, which is still well inside the
|
|
301
|
+
frame when a small marker has just left it.
|
|
302
|
+
|
|
303
|
+
```jsx
|
|
304
|
+
<Plan data-droppable>
|
|
305
|
+
<Marker
|
|
306
|
+
interactions={{
|
|
307
|
+
move: (event) => remember(event.detail.x, event.detail.y),
|
|
308
|
+
leave: () => remove(marker.id),
|
|
309
|
+
}}
|
|
310
|
+
/>
|
|
311
|
+
</Plan>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Its detail is `toss`'s — `{ id, x, y }`, the distance travelled being what an exit
|
|
315
|
+
is animated with. Picked up and put straight back down stays a cancel: it has to
|
|
316
|
+
have gone somewhere to be away from anything.
|
|
317
|
+
|
|
318
|
+
What the thing does while the answer is asked follows what was carried. A copy
|
|
319
|
+
fades where it was let go of; the element itself stays where the hand put it. A
|
|
320
|
+
resolve takes the copy away and lets go of the element's position — the
|
|
321
|
+
application has removed the thing, or drawn it where it goes back to (the address
|
|
322
|
+
point returns to where the geocoder put it) — and a reject brings either back, as
|
|
323
|
+
a refused `move` does. A surface that clips its overflow clips the element on its
|
|
324
|
+
way out; the copy a `land` carries lives in the top layer and does not.
|
|
289
325
|
|
|
290
326
|
### A finger that does not have to wait: `data-drag-on-contact`
|
|
291
327
|
|
|
@@ -355,7 +391,8 @@ carried does not stand among the places — a palette BESIDE the surface it fill
|
|
|
355
391
|
marker drawn INSIDE the surface it can be put back on — say what holds both with
|
|
356
392
|
`data-drop-container`. It holds the places rather than being one, so it goes on an
|
|
357
393
|
ancestor of them: a surface that is itself the place is never found from inside
|
|
358
|
-
itself.
|
|
394
|
+
itself. Missed, nothing lands and nothing says why — so the first press on a
|
|
395
|
+
`land` with no place in reach warns, and names the surface it is standing on.
|
|
359
396
|
|
|
360
397
|
```jsx
|
|
361
398
|
<div data-drop-container>
|
|
@@ -512,7 +549,7 @@ thing it copies, and dressed by where that thing stands.
|
|
|
512
549
|
|
|
513
550
|
### Saying the grab is acquired: `grab`
|
|
514
551
|
|
|
515
|
-
The
|
|
552
|
+
The interactions above answer the **release**. Between the press and the release there is
|
|
516
553
|
one instant that counts for the hand: the one where the object stops being pressed
|
|
517
554
|
and starts being held. `grab` is that instant — the same one whichever way the drag
|
|
518
555
|
was entered, a finger held still or a mouse travelled a few pixels.
|
|
@@ -536,8 +573,8 @@ Nothing here is about vibration: a sound, a class, a measure are the same moment
|
|
|
536
573
|
|
|
537
574
|
`grab` **reports, it does not ask**: what it returns is not waited on, and
|
|
538
575
|
preventing its event does not call the gesture off. And it is not an interaction on
|
|
539
|
-
its own — declared without
|
|
540
|
-
|
|
576
|
+
its own — declared without one of the five above there is no gesture for it to be
|
|
577
|
+
the beginning of, and a dev warning says so. Its detail carries `pointerType` and
|
|
541
578
|
the `gestureInfo`.
|
|
542
579
|
|
|
543
580
|
A `longpress` needs none of this: it already happens at the moment the hold is
|
|
@@ -620,7 +657,8 @@ back to it.
|
|
|
620
657
|
`data-drag-axis` says which axes the drag walks, and its default is not the same
|
|
621
658
|
for every outcome: `reorder` alone walks the list (`y`, or `x` for a list that runs
|
|
622
659
|
sideways), while a `move` goes wherever it is put, a `land` wherever the board has
|
|
623
|
-
places
|
|
660
|
+
places, a `toss` wherever it was thrown and a `leave` out by whichever edge (`xy`).
|
|
661
|
+
`data-drag-delay`,
|
|
624
662
|
`data-drag-slop`, `data-drag-threshold` tune when the press becomes a grab.
|
|
625
663
|
|
|
626
664
|
### An affordance inside somebody else's box: `selfInteractions`
|
|
@@ -873,19 +911,63 @@ container above it does not take the gesture:
|
|
|
873
911
|
`docs/drag_to_travel.md`). navi's own swipes do the equivalent with
|
|
874
912
|
`data-travel-by-drag`.
|
|
875
913
|
|
|
914
|
+
## A surface under the hand: `pan`, `zoom`
|
|
915
|
+
|
|
916
|
+
A plan drawn over an aerial photo, a map, a floor: one box the hand drags to look
|
|
917
|
+
elsewhere on, pinches or rolls a wheel over to look closer at, with things carried
|
|
918
|
+
across it that must not drag the surface along.
|
|
919
|
+
|
|
920
|
+
```jsx
|
|
921
|
+
<Box
|
|
922
|
+
interactions={{
|
|
923
|
+
pan: (event) => moveCenterBy(event.detail), // { x, y } since the last one
|
|
924
|
+
zoom: (event) => zoomBy(event.detail), // { factor, x, y }
|
|
925
|
+
}}
|
|
926
|
+
>
|
|
927
|
+
{markers.map((marker) => (
|
|
928
|
+
<Marker interactions={{ move: (event) => place(marker, event.detail) }} />
|
|
929
|
+
))}
|
|
930
|
+
</Box>
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
Both are a **stream**, reported on every frame: `pan` says how far the hand has
|
|
934
|
+
moved since the previous `pan`, in px; `zoom` by what factor (above 1 is in) and
|
|
935
|
+
around which point of the surface, measured inside its border — the point between
|
|
936
|
+
the fingers, or under the wheel. Two fingers are one gesture, the point between
|
|
937
|
+
them panning and the distance between them zooming, and a finger lifting
|
|
938
|
+
re-anchors on what is left. What a pixel of pan means in your coordinates, and
|
|
939
|
+
whether the zoom is continuous or stepped, is yours: the numbers are the numbers.
|
|
940
|
+
|
|
941
|
+
What navi holds is what has to be settled **before** the press: `touch-action` on
|
|
942
|
+
the surface, said from a stylesheet because a browser decides what a touch may do
|
|
943
|
+
when it lands; the pan stepping back for what is carried across the surface (a
|
|
944
|
+
`move`, a handle, a field, a popover — the same list a travelling box steps back
|
|
945
|
+
for); the pinch not beginning as a pan under its first finger; the wheel and the
|
|
946
|
+
pinch writing one `zoom`; the capture, the pointer the browser drops, the click
|
|
947
|
+
the release leaves behind. A pointer pans only once it has travelled a few px
|
|
948
|
+
(`data-drag-threshold`), so a tap stays a tap and a `longpress` declared beside
|
|
949
|
+
`pan` still gets its hold.
|
|
950
|
+
|
|
951
|
+
Declared alone, `zoom` takes two fingers and the wheel and leaves one pointer to
|
|
952
|
+
whatever else reads it; `pan` alone leaves the wheel to the page.
|
|
953
|
+
|
|
876
954
|
## A gesture whose product is a value
|
|
877
955
|
|
|
878
|
-
`move`, `reorder`, `land` and `
|
|
879
|
-
element end up — because all
|
|
956
|
+
`move`, `reorder`, `land`, `toss` and `leave` answer the same question — where did
|
|
957
|
+
the element end up — because all five carry it. A rotation does not: what comes out of
|
|
880
958
|
it is an angle, and the handle that produced it stays exactly where it is. Same for
|
|
881
|
-
a scale, a
|
|
959
|
+
a scale, or a sun dragged around a plan to set the hour.
|
|
882
960
|
|
|
883
961
|
navi names none of those, and it is not an oversight: an interaction names an
|
|
884
962
|
**outcome** — something that happened once, that can be told, refused, awaited.
|
|
885
963
|
There is no outcome here, only a number read while the hand is still moving, and
|
|
886
964
|
what to do with it (snap it to the neighbouring court, draw it, keep it in a
|
|
887
|
-
signal) is knowledge navi does not have.
|
|
888
|
-
and
|
|
965
|
+
signal) is knowledge navi does not have. `pan` and `zoom` above are the one
|
|
966
|
+
exception, and not for the number: a surface has an arbitration to settle before
|
|
967
|
+
the press — what it yields to, what a touch on it may do — and arbitration is
|
|
968
|
+
what `interactions` is for. A handle has none; it is the whole surface of its own
|
|
969
|
+
gesture. So for those navi hands over the machinery instead and leaves the paint
|
|
970
|
+
alone:
|
|
889
971
|
|
|
890
972
|
```js
|
|
891
973
|
import { createDragGestureController, dragAfterIntent } from "@jsenv/navi";
|
|
@@ -988,7 +1070,9 @@ travels above it: `data-no-drag-travel` (see `docs/drag_to_travel.md`).
|
|
|
988
1070
|
- `src/control/interaction/interaction_press.js` — swipes and holds, and what a
|
|
989
1071
|
swipe writes on the element.
|
|
990
1072
|
- `src/control/interaction/interaction_drag.js` — `move`, `reorder`, `land`,
|
|
991
|
-
`toss` and the `grab` moment.
|
|
1073
|
+
`toss`, `leave` and the `grab` moment.
|
|
1074
|
+
- `src/control/interaction/interaction_surface.js` — `pan` and `zoom`, on
|
|
1075
|
+
`installPanZoom` from `@jsenv/dom`.
|
|
992
1076
|
- `src/control/interaction/interaction_keyboard.js`,
|
|
993
1077
|
`interaction_native.js` — the other two detectors.
|
|
994
1078
|
- `@jsenv/dom` — `src/interaction/drag/drag_gesture.js` (the loop, its options and
|
|
@@ -996,7 +1080,8 @@ travels above it: `data-no-drag-travel` (see `docs/drag_to_travel.md`).
|
|
|
996
1080
|
press becomes a drag, and what a source says in the stylesheet).
|
|
997
1081
|
- `src/control/demos/38_interactions_demo.html` — every case above, plus a
|
|
998
1082
|
mailbox, a board whose places are zones and the same board whose places are the
|
|
999
|
-
pieces, and a custom gesture registered from the
|
|
1083
|
+
pieces, a surface panned and zoomed, and a custom gesture registered from the
|
|
1084
|
+
page.
|
|
1000
1085
|
- `src/control/demos/integration/5_plan_editor_demo.html` — a place that is a
|
|
1001
1086
|
surface: shapes dragged out of a bank onto a plan, moved on it, and dragged off
|
|
1002
|
-
it to go.
|
|
1087
|
+
it to go; and an address point that travels itself (`move` + `leave`).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/navi",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.195",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Library of components including navigation to create frontend applications",
|
|
6
6
|
"repository": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"preact": "^11.0.0-beta.2"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@jsenv/dom": "0.17.
|
|
37
|
+
"@jsenv/dom": "0.17.48",
|
|
38
38
|
"@jsenv/humanize": "1.8.1",
|
|
39
39
|
"@jsenv/validity": "0.4.3"
|
|
40
40
|
},
|