@jsenv/navi 0.29.192 → 0.29.194

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.
@@ -10716,9 +10716,20 @@ defineInteractionDetector({
10716
10716
  return undefined;
10717
10717
  }
10718
10718
  const tellsWhenGrabbed = types.includes(GRAB);
10719
- if (canMove && (canReorder || canLand)) {
10719
+ // `startDragTo` arbitrates the same conflicts and says so too, and that voice
10720
+ // is not heard from here: @jsenv/dom publishes one build with `import.meta.dev`
10721
+ // false, so nothing of its dev code exists for whoever consumes navi. What a
10722
+ // caller wrote is `interactions`, so this is also where the warning can name it.
10723
+ if (canMove && (canReorder || canLand || canToss)) {
10724
+ // The other three all carry a copy and put the original back — there is no
10725
+ // move anywhere in that gesture, so the element itself never travels.
10726
+ const other = canLand ? LAND : canReorder ? REORDER : TOSS;
10727
+ const instead =
10728
+ other === TOSS
10729
+ ? ` Something that can be put down anywhere AND thrown away declares "${LAND}" rather than "${MOVE}": its detail says where the copy came down, which is what a surface answers with.`
10730
+ : "";
10720
10731
  console.warn(
10721
- `interactions: "move" and "${canReorder ? REORDER : LAND}" cannot both answer one release — an element either goes where it is put, or takes the place the list/board gives it. "${canReorder ? REORDER : LAND}" wins here.`,
10732
+ `interactions: "${MOVE}" and "${other}" cannot both answer one release — "${MOVE}" leaves the element where the hand put it, "${other}" carries a copy and puts the original back. "${other}" wins here, so the element never travels.${instead}`,
10722
10733
  );
10723
10734
  }
10724
10735
  if (canReorder && canLand) {
@@ -10776,7 +10787,16 @@ defineInteractionDetector({
10776
10787
  // moment, not an outcome, and the gesture must not read it as one.
10777
10788
  const effects = types.filter((type) => type !== GRAB);
10778
10789
 
10790
+ // Whether there is anywhere to land, asked at the first press rather than
10791
+ // here: the places are drawn by whatever renders them, which at setup may
10792
+ // not have happened yet.
10793
+ let placesLookedFor = false;
10794
+
10779
10795
  const onPointerDown = (pointerDownEvent) => {
10796
+ if (canLand && !placesLookedFor) {
10797
+ placesLookedFor = true;
10798
+ warnWhenNothingToLandOn(element, dropContainer, tossBy);
10799
+ }
10780
10800
  // What this element says a release can mean. The gesture then runs only what
10781
10801
  // those need — no copy for a move, no drop hint for something that can only
10782
10802
  // be thrown away.
@@ -10854,6 +10874,42 @@ defineInteractionDetector({
10854
10874
  },
10855
10875
  });
10856
10876
 
10877
+ // A place is looked for INSIDE the container and nowhere else, so the surface a
10878
+ // piece already stands on is not one of them — a search never finds what it starts
10879
+ // from. Nothing then happens at all, and where `release-outside` is on it is worse
10880
+ // than nothing: every release is away from every place, so every release gets rid
10881
+ // of the thing.
10882
+ const warnWhenNothingToLandOn = (element, dropContainer, tossBy) => {
10883
+ const container = dropContainer || element.parentElement;
10884
+ if (!container) {
10885
+ return;
10886
+ }
10887
+ for (const droppable of container.querySelectorAll(
10888
+ `[${DROPPABLE_ATTRIBUTE}]`,
10889
+ )) {
10890
+ if (droppable !== element) {
10891
+ return;
10892
+ }
10893
+ }
10894
+ const consequence = tossBy.includes("release-outside")
10895
+ ? ` Every release is then away from every place, which ${TOSS_BY_ATTRIBUTE}="release-outside" reads as a toss.`
10896
+ : " Nothing answers a release.";
10897
+ const droppableAround = element.parentElement?.closest(
10898
+ `[${DROPPABLE_ATTRIBUTE}]`,
10899
+ );
10900
+ if (droppableAround) {
10901
+ console.warn(
10902
+ `interactions: "${LAND}" has nowhere to land — this element sits INSIDE the only place there is, and places are looked for inside ${dropContainer ? `the [${DROP_CONTAINER_ATTRIBUTE}]` : `the element's parent`}, never above it.${consequence} Put ${DROP_CONTAINER_ATTRIBUTE} on an ancestor of both, so the surface is among the places rather than around them.`,
10903
+ droppableAround,
10904
+ );
10905
+ return;
10906
+ }
10907
+ console.warn(
10908
+ `interactions: "${LAND}" has nowhere to land — nothing marked ${DROPPABLE_ATTRIBUTE} is inside ${dropContainer ? `the [${DROP_CONTAINER_ATTRIBUTE}]` : `the element's parent`}, which is where the places are looked for.${consequence} Mark them, and when they are not siblings of this element put ${DROP_CONTAINER_ATTRIBUTE} on an ancestor of both.`,
10909
+ container,
10910
+ );
10911
+ };
10912
+
10857
10913
  // used by form elements such as <input>, <select>, <textarea> to have their own action bound to a single parameter
10858
10914
  // when inside a <form> the form params are updated when the form element single param is updated
10859
10915
  const useActionBoundToOneParam = (action, paramsSignal) => {