@jsenv/navi 0.29.360 → 0.29.361

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.
@@ -4635,9 +4635,12 @@ const findControlHost = (el) => {
4635
4635
  * `findControlHost` above answers for a control's own DOM (itself, or the native
4636
4636
  * element it wraps). This one is for something that is not part of a control but
4637
4637
  * has to reach one — an interaction declared on a box (see
4638
- * interaction/interactions.js), which may be the control, may hold it, or may sit
4639
- * inside it. Nearest wins in that order, and the answer is null when there is no
4640
- * control anywhere: not every box lives in one.
4638
+ * interaction/interactions.js), which may be the control, may sit inside it, or
4639
+ * may be a wrapper around exactly one. Nearest wins in that order, and the answer
4640
+ * is null when there is no control the box belongs to: not every box lives in
4641
+ * one, and a box laying out several controls (a row of badges, a toolbar) is
4642
+ * held by none of them — its interactions are its own, and a press on its empty
4643
+ * part is not a press on the first control it happens to contain.
4641
4644
  */
4642
4645
  const findNearestControlHost = (el) => {
4643
4646
  // Itself, then upwards — the box is inside a button, or is one.
@@ -4645,8 +4648,22 @@ const findNearestControlHost = (el) => {
4645
4648
  if (selfOrAncestor) {
4646
4649
  return selfOrAncestor;
4647
4650
  }
4648
- // …then downwards: the box holds the control rather than being held by it.
4649
- return el.querySelector("[navi-control-host]");
4651
+ // …then downwards, only when the box wraps a single control. Counted by
4652
+ // control, not by host: a picker holds the hosts of its popup content, and a
4653
+ // box around that one picker is still around one control.
4654
+ let single = null;
4655
+ for (const host of el.querySelectorAll("[navi-control-host]")) {
4656
+ const controlRoot = host.closest("[navi-control]") || host;
4657
+ const controlAbove = controlRoot.parentElement.closest("[navi-control]");
4658
+ if (controlAbove && el.contains(controlAbove)) {
4659
+ continue;
4660
+ }
4661
+ if (single && single !== controlRoot) {
4662
+ return null;
4663
+ }
4664
+ single = controlRoot;
4665
+ }
4666
+ return single ? findControlHost(single) : null;
4650
4667
  };
4651
4668
  const isControlRoot = (el) => {
4652
4669
  return el.hasAttribute("navi-control");
@@ -10957,9 +10974,10 @@ const interactionsDisputeThePress = (interactions) => {
10957
10974
  *
10958
10975
  * The control is not passed in: it is found from the element, which is what lets
10959
10976
  * `interactions` live on a Box rather than on the control itself. A Box that IS a
10960
- * control (a Button) is its own; a Box around one or inside one reaches it; a Box
10961
- * with no control anywhere near it can still answer with a callback of the
10962
- * caller's, and only "request_action" has nothing to ask.
10977
+ * control (a Button) is its own; a Box inside one, or wrapping exactly one,
10978
+ * reaches it; a Box with no control anywhere near it or laying out several,
10979
+ * which belongs to none of them still answers with a callback of the caller's,
10980
+ * and only "request_action" has nothing to ask.
10963
10981
  *
10964
10982
  * Set up once per element rather than on every render, which is what lets a
10965
10983
  * detector be a plain `setup`/teardown pair. So the interactions themselves are
@@ -11007,7 +11025,7 @@ const useInteractionsEffect = (ref, interactionsRef) => {
11007
11025
  if (!controlHost) {
11008
11026
  {
11009
11027
  console.warn(
11010
- `interactions: "${type}" asks for an action, but there is no control around it to ask. Put the interaction on a control (or on a box that holds one), or give it a callback.`,
11028
+ `interactions: "${type}" asks for an action, but there is no control around it to ask. Put the interaction on a control (or on a box that wraps exactly one), or give it a callback.`,
11011
11029
  );
11012
11030
  }
11013
11031
  return null;