@jsenv/navi 0.29.454 → 0.29.455

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.
@@ -40613,18 +40613,20 @@ const callLiftOverCallbacks = () => {
40613
40613
  *
40614
40614
  * A picker's `action` waits for its popup to close: what is done in there is
40615
40615
  * one answer, given when the person is done. A change made while the popup is
40616
- * closed — a chip's cross, a paste, a cut, a value proposed from beside it
40617
- * (`--navi-update`) — has no close coming, so nothing would ever send it: the
40618
- * value moves on screen and the record behind it stays. Each of those gestures
40619
- * calls this right after setting the value; a failing action puts the value
40620
- * back (resetOnError), as it does after a close.
40616
+ * closed — the clear cross, a chip's cross, a paste, a cut, a value proposed
40617
+ * from beside it (`--navi-update`) — has no close coming, so nothing would ever
40618
+ * send it: the value moves on screen and the record behind it stays. Each of
40619
+ * those gestures calls this right after setting the value; a failing action
40620
+ * puts the value back (resetOnError), as it does after a close.
40621
40621
  *
40622
40622
  * Called by gestures only. A value set without one — a bound signal followed, a
40623
40623
  * cancel or a failure rolled back — is the picker being told, not asked, which
40624
40624
  * is why this is not a reaction to every value set on a closed picker.
40625
40625
  *
40626
- * The clear cross does the same through `--navi-send` (see --navi-clear in
40627
- * commands.js), and so does not come through here.
40626
+ * The action is requested the way the close requests it, not through
40627
+ * `--navi-send`: a send also answers the surface around the control (a slide
40628
+ * moves on, an open dialog closes — see resolveAfterSend in commands.js), and a
40629
+ * cross pressed on a picker in a dialog is not the dialog being answered.
40628
40630
  */
40629
40631
 
40630
40632
 
@@ -40647,6 +40649,13 @@ const sendClosedPickerChange = (element, { event, name, requester }) => {
40647
40649
  if (props.picksNothing) {
40648
40650
  return;
40649
40651
  }
40652
+ // A source with an action of its own made the request already: `<Button
40653
+ // action={remove} command="--navi-clear">` runs the removal, and the command
40654
+ // that follows only brings the picker in line with it. Sending the picker's
40655
+ // action on top would ask twice.
40656
+ if (requester?.__uiStateController__?.props.action) {
40657
+ return;
40658
+ }
40650
40659
  // `requester`: the source of a command may have claimed the press to send
40651
40660
  // this very change (see isAimedAtSelfInteractionsBelow).
40652
40661
  dispatchRequestAction(controlHost, { event, name, requester });
@@ -41060,20 +41069,6 @@ registerNaviCommand("--navi-clear", (source, event) => {
41060
41069
  return undefined;
41061
41070
  }
41062
41071
  const fromInput = source.closest(`[navi-control="input"]`);
41063
- // A control that commits on an explicit send — a picker, whose list sends the
41064
- // moment a value is chosen — has nothing that would commit a clear: its
41065
- // action never runs on a ui state change. Left alone, the field goes empty
41066
- // while the caller still holds the value it gave, and renders it right back.
41067
- //
41068
- // Unless the source committed the clear itself: a clear button given its own
41069
- // action (`<Button action={remove} command="--navi-clear">`) already made the
41070
- // request — the ui state is being brought in line with what just happened, and
41071
- // sending the picker's own action on top would ask twice.
41072
- const sourceController = source.__uiStateController__;
41073
- const fromSendOnlyControl = Boolean(
41074
- source.closest?.(`[navi-control=picker]`) &&
41075
- !sourceController?.props.action,
41076
- );
41077
41072
 
41078
41073
  const performClear = (clearEvent) => {
41079
41074
  dispatchRequestInteraction(target, {
@@ -41084,46 +41079,11 @@ registerNaviCommand("--navi-clear", (source, event) => {
41084
41079
  requester: source,
41085
41080
  prevented: () => clearEvent.preventDefault(),
41086
41081
  allowed: () => {
41087
- // What the control holds, before it holds nothing: the clear is
41088
- // optimistic — the field empties now and the send that commits it may
41089
- // still fail — so what it emptied has to be kept to be put back.
41090
- const uiStateBefore = getUIStateFromElement(target);
41091
41082
  dispatchRequestClearUIState(target, clearEvent);
41092
- if (!fromSendOnlyControl) {
41093
- return;
41094
- }
41095
- // After the clear, never before: the action is bound to the ui
41096
- // state signal, so this sends the value the control now holds.
41097
- const actionHost = findControlHost(target) || target;
41098
- const completion = watchActionCompletion(actionHost, () => {
41099
- triggerNaviCommand(source, "--navi-send", clearEvent, {
41100
- optional: true,
41101
- });
41102
- });
41103
- completion.whenSettled(({ error, aborted }) => {
41104
- if (!error && !aborted) {
41105
- return;
41106
- }
41107
- // The removal did not happen, so the field must stop saying it did.
41108
- // The error itself stays where the action put it — on the control,
41109
- // which is still there, unlike the cross that has just gone with the
41110
- // value it cleared (see addErrorMessage in use_execute_action.js).
41111
- //
41112
- // Put back from the inside ("clear_rollback" is an internal event
41113
- // type, see ui_state_controller.js) rather than asked for the way a
41114
- // user would: nobody acted, the control is being returned to the
41115
- // state its caller still holds. Asked from the outside it would be
41116
- // answered with "this element is busy" — the action is still
41117
- // settling — over the very error that explains why the value is back.
41118
- const controller = actionHost.__uiStateController__;
41119
- if (!controller) {
41120
- return;
41121
- }
41122
- const rollbackEvent = new CustomEvent("clear_rollback", {
41123
- detail: {},
41124
- });
41125
- chainEvent(rollbackEvent, clearEvent);
41126
- controller.setUIState(uiStateBefore, rollbackEvent);
41083
+ sendClosedPickerChange(target, {
41084
+ event: clearEvent,
41085
+ name: "--navi-clear",
41086
+ requester: source,
41127
41087
  });
41128
41088
  },
41129
41089
  });
@@ -41863,6 +41823,7 @@ registerNaviCommand("--navi-select", (source, event) => {
41863
41823
  return dispatchCustomEvent(target, "navi_request_select", {
41864
41824
  event,
41865
41825
  id: resolveCommandValue(source, event),
41826
+ requester: source,
41866
41827
  });
41867
41828
  },
41868
41829
  };
@@ -41879,6 +41840,7 @@ registerNaviCommand("--navi-unselect", (source, event) => {
41879
41840
  return dispatchCustomEvent(target, "navi_request_unselect", {
41880
41841
  event,
41881
41842
  id: resolveCommandValue(source, event),
41843
+ requester: source,
41882
41844
  });
41883
41845
  },
41884
41846
  };
@@ -45782,12 +45744,6 @@ const INTERNAL_EVENT_SET = new Set([
45782
45744
  // on registration, and group pushing value/defaultValue to children on registerChild.
45783
45745
  // Equivalent to defaultValue initialization: no uiAction, no commands, no parent notification.
45784
45746
  "initial_state_push",
45785
- // navi undoing its own optimistic write: the clear cross emptied the control
45786
- // before the send that commits it, the send failed, and the value it emptied
45787
- // goes back where it was (see the --navi-clear command). Nothing acted — the
45788
- // control is being put back on the state the caller still holds — so this
45789
- // must not fire a uiAction, a command, or a report on the way.
45790
- "clear_rollback",
45791
45747
  // A picker's popup closed on a cancel (the no button, Escape, a click
45792
45748
  // outside): what the picker held at open goes back. Nobody acted — no
45793
45749
  // command — but the value really did move back, so uiAction and the parent
@@ -84127,7 +84083,8 @@ const requestPickerListEntry = (pickerEl, pickerInputEl, e, goal) => {
84127
84083
  return;
84128
84084
  }
84129
84085
  const {
84130
- id: entry
84086
+ id: entry,
84087
+ requester
84131
84088
  } = e.detail;
84132
84089
  const isThere = uiState.some(item => compareTwoJsValues(item, entry));
84133
84090
  if (goal === "select" ? isThere : !isThere) {
@@ -84144,7 +84101,8 @@ const requestPickerListEntry = (pickerEl, pickerInputEl, e, goal) => {
84144
84101
  });
84145
84102
  sendClosedPickerChange(pickerInputEl, {
84146
84103
  event: e,
84147
- name: goal
84104
+ name: goal,
84105
+ requester
84148
84106
  });
84149
84107
  }
84150
84108
  });
@@ -84618,7 +84576,9 @@ const PickerFirstResolver = props => {
84618
84576
  * the `<Picker type="confirm">` the cross then is, plain text or JSX. Asked
84619
84577
  * BEFORE the ui state is emptied, so answering no leaves the field exactly
84620
84578
  * as it was; answering yes clears and sends, and the picker's own action
84621
- * receives the cleared value like any other choice.
84579
+ * receives the cleared value like any other choice. A cut (Ctrl+X) on such a
84580
+ * picker copies the value and leaves it in place: no clear without the
84581
+ * question.
84622
84582
  * @param {"icon"|"headless"|"discrete"|"button"|"text"|"bare"|"picker"} [variant]
84623
84583
  * How the trigger is drawn. `"button"` is a Button's drawing — surface,
84624
84584
  * padding, a centered label, no chevron — and what a `type="confirm"` picker