@jsenv/navi 0.29.308 → 0.29.310

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.
@@ -2866,7 +2866,17 @@ const updateActions = ({
2866
2866
  * - willRunSet: actions that will be run
2867
2867
  * - willPromoteSet: prerun actions that become run-requested
2868
2868
  * - stays*Set: actions that remain in their current state
2869
+ *
2870
+ * A proxy in any of the sets stands for the action it currently targets,
2871
+ * exactly as proxy.run()/rerun()/reset() do: what enters activationWeakSet
2872
+ * is always the target. A proxy kept in there would retarget on its own —
2873
+ * to a never-run child once its params go falsy — and getActivationInfo
2874
+ * would then meet an IDLE member on every later update of the document.
2869
2875
  */
2876
+ prerunSet = resolveActionProxies(prerunSet);
2877
+ runSet = resolveActionProxies(runSet);
2878
+ rerunSet = resolveActionProxies(rerunSet);
2879
+ resetSet = resolveActionProxies(resetSet);
2870
2880
 
2871
2881
  const { runningSet, settledSet } = getActivationInfo();
2872
2882
 
@@ -3088,13 +3098,6 @@ ${lines.join("\n")}`);
3088
3098
  // Step 5: Execute preruns and runs
3089
3099
  {
3090
3100
  const onActionToRunOrPrerun = (actionToPrerunOrRun, isPrerun) => {
3091
- if (actionToPrerunOrRun.isProxy) {
3092
- // maybe remove this check once the API is stable because
3093
- // nothing in the API should allow this to happen
3094
- throw new Error(
3095
- `Proxy should not be reach this point, use the underlying action instead`,
3096
- );
3097
- }
3098
3101
  const actionSpecificSignal = abortSignalMap.get(actionToPrerunOrRun);
3099
3102
  const effectiveSignal = actionSpecificSignal || abortSignal;
3100
3103
 
@@ -3222,6 +3225,14 @@ ${lines.join("\n")}`);
3222
3225
  };
3223
3226
  };
3224
3227
 
3228
+ const resolveActionProxies = (actionSet) => {
3229
+ const resolvedSet = new Set();
3230
+ for (const action of actionSet) {
3231
+ resolvedSet.add(action.isProxy ? action.getCurrentAction() : action);
3232
+ }
3233
+ return resolvedSet;
3234
+ };
3235
+
3225
3236
  const NO_PARAMS = { __no_params__: true };
3226
3237
  const mergeActionParams = (currentParams, newParams) => {
3227
3238
  // The order of these two checks is load-bearing. Checking `undefined` first
@@ -10451,6 +10462,42 @@ const readNumberFromDom = (element, attribute, defaultValue) => {
10451
10462
  return value;
10452
10463
  };
10453
10464
 
10465
+ /**
10466
+ * Where a press really landed, for an element reading a gesture out of it.
10467
+ *
10468
+ * A popup is painted OVER the page and stays a DOM descendant of whatever it
10469
+ * was written in — a dialog inside the card that opens it, a callout beside the
10470
+ * button it belongs to. Its pointer events therefore bubble through boxes it
10471
+ * covers, and a box reading a gesture off one of them answers for something
10472
+ * nobody aimed at it: a finger held in a sheet opening the card underneath the
10473
+ * sheet, a card the sheet is drawn from and that the finger cannot even reach.
10474
+ *
10475
+ * The same list, read for the same reason, as the drag sources in @jsenv/dom
10476
+ * (see DRAG_IGNORED_SELECTOR in drag_to.js) and as the selection rule in
10477
+ * interaction_press.js: a layer over the element (`[popover]`, `dialog`), and
10478
+ * something saying its press is its own business (`data-drag-ignore`, which is
10479
+ * what a popup outside the top layer says for itself).
10480
+ */
10481
+
10482
+ const LAYER_OVER_SELECTOR = "[data-drag-ignore],[popover],dialog";
10483
+
10484
+ /**
10485
+ * The nearest word wins: a layer INSIDE the element takes the press away from
10486
+ * it, one AROUND it does not — an element that IS the dialog, or that sits in
10487
+ * one, goes on answering its own presses.
10488
+ *
10489
+ * @param {EventTarget} target Where the event says the press landed.
10490
+ * @param {Element} element The element reading a gesture out of that press.
10491
+ * @returns {boolean}
10492
+ */
10493
+ const isPressOnLayerOver = (target, element) => {
10494
+ if (!target || typeof target.closest !== "function") {
10495
+ return false;
10496
+ }
10497
+ const layer = target.closest(LAYER_OVER_SELECTOR);
10498
+ return Boolean(layer) && !layer.contains(element);
10499
+ };
10500
+
10454
10501
  /**
10455
10502
  * The interactions the browser already has an event for.
10456
10503
  *
@@ -10469,6 +10516,11 @@ const readNumberFromDom = (element, attribute, defaultValue) => {
10469
10516
  * refuses what is already `defaultPrevented`. Cancelling first would therefore
10470
10517
  * make the interaction refuse itself, and no right click could ever get through.
10471
10518
  * So: ask, and only cover the browser's menu once something answered.
10519
+ *
10520
+ * They are read off the element and not off whatever bubbles to it: a popup is
10521
+ * a DOM descendant of what it was opened from, so a right click in a sheet
10522
+ * reaches the card the sheet was drawn from, and answering it there answers a
10523
+ * request nobody made (see isPressOnLayerOver).
10472
10524
  */
10473
10525
 
10474
10526
 
@@ -10485,6 +10537,9 @@ defineInteractionDetector({
10485
10537
  setup: (element, trigger, { types }) => {
10486
10538
  const listeners = types.map((type) => {
10487
10539
  const listener = (nativeEvent) => {
10540
+ if (isPressOnLayerOver(nativeEvent.target, element)) {
10541
+ return;
10542
+ }
10488
10543
  const performed = trigger(type, nativeEvent);
10489
10544
  if (type === "contextmenu" && performed) {
10490
10545
  // Something answered the request, so the browser's own menu would only
@@ -10777,6 +10832,11 @@ defineInteractionDetector({
10777
10832
  if (pointerDownEvent.button !== 0) {
10778
10833
  return;
10779
10834
  }
10835
+ // A press aimed at a layer over this element, merely bubbling through it
10836
+ // — the same layers the stylesheet above hands the selection back to.
10837
+ if (isPressOnLayerOver(pointerDownEvent.target, element)) {
10838
+ return;
10839
+ }
10780
10840
  let swipe = null;
10781
10841
  let press = null;
10782
10842
  // Set below, with the hold; a no-op until then so the swipe can call it.