@jsenv/navi 0.29.299 → 0.29.300

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.
@@ -157,7 +157,8 @@ to start when unsure which export solves a problem.
157
157
 
158
158
  - `popup_open.md` — a popup owns its open state; `command` + `commandfor`;
159
159
  `triggerNaviCommand` as the last resort, with the event forwarded and never
160
- invented; opening ON something; a press that opens and acts is a `Picker`;
160
+ invented; opening ON something; a press that opens and acts is a `Picker`,
161
+ and its trigger wears the wait and the error (a card that lifts, `openOn`);
161
162
  Escape cancels; the close cross; a popup that loads data. Read before passing
162
163
  `open`, calling `triggerNaviCommand`, or writing a close button.
163
164
  - `popup_backdrop.md` — three independent questions: a wall or not
@@ -403,6 +403,83 @@ dialog hides: a popup written once, far from every press that opens it, has to
403
403
  be told what it is about and has to answer somebody — and neither question
404
404
  exists once the popup is written where it is used.
405
405
 
406
+ ### The trigger wears the wait
407
+
408
+ The picker's `action` runs on the trigger, not in the popup: it is dispatched
409
+ on the close that keeps, and the popup goes while it runs. So what is still on
410
+ screen answers for the write — `aria-busy` and the loading outline on the
411
+ trigger while the request is out, the error callout on it if the server
412
+ refuses, and the value rolled back to the last accepted one (`resetOnError`,
413
+ on by default for a picker: nobody is left mid-edit behind a closed popup). A
414
+ card that IS the trigger (`variant="bare"`, the card as `ui`) therefore waits
415
+ as a card and is refused as a card, wherever in the tree the sheet was written.
416
+
417
+ ```jsx
418
+ <Picker
419
+ variant="bare"
420
+ type="object"
421
+ mode="dialog"
422
+ ui={<MatchCard match={match} />}
423
+ value={match}
424
+ action={(next) => MATCH.PATCH({ id: match.id, ...next })}
425
+ // the draft is what the person typed, and the sheet is the only place it
426
+ // can be found again: keep it when the server says no
427
+ resetOnError={false}
428
+ >
429
+ <ControlGroup>
430
+ <MatchCard match={match} editable />
431
+ <Button command="--navi-cancel">Cancel</Button>
432
+ <Button command="--navi-send">Save</Button>
433
+ </ControlGroup>
434
+ </Picker>
435
+ ```
436
+
437
+ What the picker measures as "changed since open" is what its mirrored group
438
+ holds. A piece of the answer living outside the controls — a seating
439
+ rearranged by drag, kept in component state — has to be held by a control in
440
+ the group too (a named control bound to that state), or a close over it reads
441
+ as nothing changed and nothing runs.
442
+
443
+ Two props finish the construct. `openOn="longpress"` (or
444
+ `["longpress", "contextmenu"]`) makes the hold what opens it, so a tap on the
445
+ card stays a tap — what a card in a list needs. `animation="growing"` with
446
+ `dialogSizeFromAnchor`, `dialogMaxWidth="var(--anchor-width)"`,
447
+ `popupBackgroundColor="transparent"` and `popupBoxShadow="none"` lifts the
448
+ card out of its place and puts it back (`data-grow` on the card inside the
449
+ sheet; see Dialog's own `animation`). `12_picker_card_demo.html` shows all of
450
+ it, against a backend that answers when told to.
451
+
452
+ This is not `optimistic`. `optimistic` on a control is "draw no wait at all";
453
+ here the wait is drawn, on the trigger, and the popup was never what held it.
454
+ An optimistic picker is for a write not worth showing — the card then reads
455
+ the store and says nothing until the answer lands.
456
+
457
+ The same shape with nothing to write is a **door**: a drawing that grows to be
458
+ looked at — a weather scene, a plan — and comes back. `picksNothing`, no
459
+ `action`, no `dialogSizeFromAnchor` (it opens precisely to get bigger):
460
+
461
+ ```jsx
462
+ <Picker
463
+ picksNothing
464
+ variant="bare"
465
+ mode="dialog"
466
+ ui={scene}
467
+ aria-label="Zoom"
468
+ animation="growing"
469
+ popupBackgroundColor="transparent"
470
+ popupBoxShadow="none"
471
+ >
472
+ <Box data-grow>{scene}</Box>
473
+ </Picker>
474
+ ```
475
+
476
+ A `Button` opening a `Dialog` with an `anchor` does the same and is not wrong;
477
+ what the picker removes is the id plumbing (the trigger is the anchor, the
478
+ popup is its own), and what it keeps is the day the drawing becomes editable —
479
+ it is already the thing that wears the wait. The button + shared dialog stays
480
+ the answer for [the two cases where a popup must be
481
+ shared](#when-a-shared-popup-is-still-the-right-answer).
482
+
406
483
  ### A trigger that is only an icon
407
484
 
408
485
  `variant="icon"` draws no value, and therefore no slot beside one either: the
@@ -536,8 +613,12 @@ to be hand-written to work around it: `command` next to `action` is that
536
613
  workaround, done at the one moment where the action has settled and the button
537
614
  is no longer busy.
538
615
 
539
- To close on the press instead — the answer taken as soon as it is given, the
540
- save running on its own behind a closed popup — say so on the control:
616
+ When what opened the popup is still on screen and should answer for the write
617
+ — its wait, its refusal — the popup was a picker's all along: see [the trigger
618
+ wears the wait](#the-trigger-wears-the-wait). What follows is for the other
619
+ case, a popup nobody stands in for. To close on the press — the answer taken as
620
+ soon as it is given, the save running on its own behind a closed popup — say so
621
+ on the control:
541
622
 
542
623
  ```jsx
543
624
  <Form command="--navi-close" action={saveScore} optimistic resetOnError>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.29.299",
3
+ "version": "0.29.300",
4
4
  "type": "module",
5
5
  "description": "Library of components including navigation to create frontend applications",
6
6
  "repository": {