@jsenv/navi 0.29.408 → 0.29.409

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.
@@ -13145,12 +13145,13 @@ const useBoundAction = (action, actionParamsSignal) => {
13145
13145
  if (existingNoopAction) {
13146
13146
  return existingNoopAction;
13147
13147
  }
13148
+ // Not bound to the params signal: nothing reads what a noop runs with, and
13149
+ // a proxy following the signal would retarget (a new child action for each
13150
+ // new value) at every change — for every button of a form, at every change
13151
+ // of any of its fields.
13148
13152
  const noopAction = createAction(() => {}, { params: undefined });
13149
- const noopActionBound = actionParamsSignal
13150
- ? noopAction.bindParams(actionParamsSignal)
13151
- : noopAction;
13152
- noopActionRef.current = noopActionBound;
13153
- return noopActionBound;
13153
+ noopActionRef.current = noopAction;
13154
+ return noopAction;
13154
13155
  }
13155
13156
  const isFunction = typeof action === "function";
13156
13157
  if (!isFunction) {
@@ -83110,7 +83111,6 @@ const useWheelInteractions = ({
83110
83111
  attemptInteraction,
83111
83112
  cancelAnim,
83112
83113
  setPos,
83113
- releaseScrub,
83114
83114
  snapPosToRow,
83115
83115
  getItemSize,
83116
83116
  viewportMain,
@@ -83519,8 +83519,6 @@ const useWheelInteractions = ({
83519
83519
  clearTimeout(settleTimer);
83520
83520
  stopClaimingGesture();
83521
83521
  cancelAnim();
83522
- // Nothing is left to settle the scrub in progress.
83523
- releaseScrub();
83524
83522
  document.removeEventListener("pointerdown", onDocumentPointerDown, {
83525
83523
  capture: true
83526
83524
  });
@@ -83686,11 +83684,11 @@ function WheelUI(props) {
83686
83684
  ...props,
83687
83685
  ref: inputRef,
83688
83686
  type: "navi_js",
83689
- // An arrow or a tap changes the value at once while the row glides into
83690
- // place, and the action must wait for the wheel to come to rest. "custom"
83691
- // stops setUIState from auto-firing the action on every value change;
83692
- // commitSelection dispatches it explicitly on settle. A caller can still
83693
- // override actionEvent.
83687
+ // uiAction fires live (every center-crossing, via setPos live reports);
83688
+ // the committed action must fire only when the wheel stabilizes. "custom"
83689
+ // stops setUIState from auto-firing the action on every value change, so
83690
+ // the live reports are uiAction-only; commitSelection then dispatches the
83691
+ // action explicitly on settle. A caller can still override actionEvent.
83694
83692
  actionEvent: props.actionEvent ?? "custom"
83695
83693
  }, {
83696
83694
  controlType: "input"
@@ -83786,11 +83784,6 @@ function WheelUI(props) {
83786
83784
  // while our own scroll-driven selection does not scroll a second time. Holds the
83787
83785
  // TARGET so rapid inputs step from it and accumulate. null = nothing pending.
83788
83786
  const centeredIndexRef = useRef(null);
83789
- // A user scrub moved the wheel onto a row that is not the value yet: set at
83790
- // the first row it crosses, cleared when it settles (commitSelection), when
83791
- // an arrow or a tap sets a value at once (glideToIndex), or when it is
83792
- // dropped (releaseScrub). See setPos.
83793
- const scrubHoldsRowRef = useRef(false);
83794
83787
  // The wheel does NOT use native scroll. `posRef` is our own virtual scroll
83795
83788
  // position (px, main axis); the list track is translated by -pos. This is the
83796
83789
  // single source of truth, wrapped modulo the real-list extent in loop mode, so
@@ -83979,14 +83972,12 @@ function WheelUI(props) {
83979
83972
  posRef.current = clampNumber(posRef.current, 0, (count - 1) * size);
83980
83973
  };
83981
83974
 
83982
- // `live` marks a user scrub (drag, momentum, wheel scroll). A scrub moves the
83983
- // drawing, not the value: the row it reaches is held by the wheel, and only
83984
- // commitSelection turns it into the value, once the motion settles. Reported
83985
- // at each crossing, every notch would be a value change for all that is
83986
- // bound to the wheel — its group, its form, a signal, the address, which
83987
- // records where a value was put down, not the path the finger took
83988
- // (navigation.md, "A value written per frame"). A programmatic move
83989
- // (centerOnIndex) omits `live`: it places the value the wheel already has.
83975
+ // `live` (user scrubs: drag, momentum, wheel scroll) reports the value as each
83976
+ // item crosses the center, so uiAction tracks the wheel in real time — like
83977
+ // every other control. The committed action still fires only once it settles
83978
+ // (commitSelection). A programmatic move (centerOnIndex on an external value
83979
+ // sync) omits it, so scrolling the wheel into place doesn't echo the value
83980
+ // back out.
83990
83981
  const setPos = (vp, pos, {
83991
83982
  live = false
83992
83983
  } = {}) => {
@@ -83997,25 +83988,18 @@ function WheelUI(props) {
83997
83988
  renderPos(vp);
83998
83989
  if (live && interactive) {
83999
83990
  const index = centeredIndex(vp);
84000
- if (index !== centeredIndexRef.current && trackedItemsRef.current[index]) {
84001
- // In step with the scrub so the next arrow or tap steps from the row
84002
- // the wheel is on (see currentTargetIndex).
84003
- centeredIndexRef.current = index;
84004
- scrubHoldsRowRef.current = true;
83991
+ if (index !== centeredIndexRef.current) {
83992
+ const item = trackedItemsRef.current[index];
83993
+ if (item) {
83994
+ // Keep centeredIndexRef in step so the every-render
83995
+ // syncCenterToSelection doesn't read this as an external change and
83996
+ // fight the in-progress motion.
83997
+ centeredIndexRef.current = index;
83998
+ requestSelectValue(item.value, new CustomEvent("navi_wheel_scrub"));
83999
+ }
84005
84000
  }
84006
84001
  }
84007
84002
  };
84008
- // The scrub was dropped before it settled (the wheel stopped being
84009
- // interactive, or its input bindings were torn down): the row it held never
84010
- // became the value. Forgetting it lets the next sync put the wheel back on
84011
- // the value.
84012
- const releaseScrub = () => {
84013
- if (!scrubHoldsRowRef.current) {
84014
- return;
84015
- }
84016
- scrubHoldsRowRef.current = false;
84017
- centeredIndexRef.current = null;
84018
- };
84019
84003
 
84020
84004
  // Returns whether it actually interrupted a motion in flight — lets the caller
84021
84005
  // tell a fresh gesture from one that "caught" a spinning/gliding wheel.
@@ -84051,7 +84035,6 @@ function WheelUI(props) {
84051
84035
  renderPos(vp);
84052
84036
  }
84053
84037
  centeredIndexRef.current = index;
84054
- scrubHoldsRowRef.current = false;
84055
84038
  if (!interactive || glideFromOutsideRef.current) {
84056
84039
  return;
84057
84040
  }
@@ -84256,7 +84239,6 @@ function WheelUI(props) {
84256
84239
  // inputs accumulate.
84257
84240
  const glideToIndex = (vp, index, event) => {
84258
84241
  centeredIndexRef.current = index;
84259
- scrubHoldsRowRef.current = false;
84260
84242
  requestSelectValue(trackedItemsRef.current[index].value, event);
84261
84243
  glideTo(vp, glideTargetFor(vp, index));
84262
84244
  };
@@ -84287,12 +84269,12 @@ function WheelUI(props) {
84287
84269
  // Sync the center with the current value — used on first display and whenever
84288
84270
  // the controlled value changes from outside.
84289
84271
  const syncCenterToSelection = (viewportEl, behavior) => {
84290
- // A fling in flight, or a scrub holding a row, commits on settle: the finger
84291
- // owns the wheel until then, and the row it leaves the wheel on overrules a
84292
- // value arriving meanwhile. A glide is different: its target is re-aimed
84293
- // below (glideTo never restarts the loop), so a value set from outside
84294
- // mid-glide is where the wheel ends up.
84295
- if (momentumRef.current !== null || scrubHoldsRowRef.current) {
84272
+ // A fling in flight reports its own value at every row crossing and commits
84273
+ // on settle: the finger that threw it owns the wheel until then, and a value
84274
+ // arriving meanwhile is re-stated by the next crossing anyway. A glide is
84275
+ // different: its target is re-aimed below (glideTo never restarts the
84276
+ // loop), so a value set from outside mid-glide is where the wheel ends up.
84277
+ if (momentumRef.current !== null) {
84296
84278
  return;
84297
84279
  }
84298
84280
  if (trackedItemsRef.current.length === 0) {
@@ -84375,7 +84357,6 @@ function WheelUI(props) {
84375
84357
  attemptInteraction,
84376
84358
  cancelAnim,
84377
84359
  setPos,
84378
- releaseScrub,
84379
84360
  snapPosToRow,
84380
84361
  getItemSize,
84381
84362
  viewportMain,