@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.
- package/dist/dev/jsenv_navi.js +32 -51
- package/dist/dev/jsenv_navi.js.map +3 -3
- package/dist/jsenv_navi.js +32 -51
- package/dist/jsenv_navi.js.map +3 -3
- package/docs/control_value.md +6 -7
- package/package.json +1 -1
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -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
|
-
|
|
13150
|
-
|
|
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
|
-
//
|
|
83690
|
-
//
|
|
83691
|
-
// stops setUIState from auto-firing the action on every value change
|
|
83692
|
-
//
|
|
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`
|
|
83983
|
-
//
|
|
83984
|
-
//
|
|
83985
|
-
//
|
|
83986
|
-
//
|
|
83987
|
-
//
|
|
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
|
|
84001
|
-
|
|
84002
|
-
|
|
84003
|
-
|
|
84004
|
-
|
|
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
|
|
84291
|
-
//
|
|
84292
|
-
//
|
|
84293
|
-
// below (glideTo never restarts the
|
|
84294
|
-
// mid-glide is where the wheel ends up.
|
|
84295
|
-
if (momentumRef.current !== null
|
|
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,
|