@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/jsenv_navi.js
CHANGED
|
@@ -12662,12 +12662,13 @@ const useBoundAction = (action, actionParamsSignal) => {
|
|
|
12662
12662
|
if (existingNoopAction) {
|
|
12663
12663
|
return existingNoopAction;
|
|
12664
12664
|
}
|
|
12665
|
+
// Not bound to the params signal: nothing reads what a noop runs with, and
|
|
12666
|
+
// a proxy following the signal would retarget (a new child action for each
|
|
12667
|
+
// new value) at every change — for every button of a form, at every change
|
|
12668
|
+
// of any of its fields.
|
|
12665
12669
|
const noopAction = createAction(() => {}, { params: undefined });
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
: noopAction;
|
|
12669
|
-
noopActionRef.current = noopActionBound;
|
|
12670
|
-
return noopActionBound;
|
|
12670
|
+
noopActionRef.current = noopAction;
|
|
12671
|
+
return noopAction;
|
|
12671
12672
|
}
|
|
12672
12673
|
const isFunction = typeof action === "function";
|
|
12673
12674
|
if (!isFunction) {
|
|
@@ -80989,7 +80990,6 @@ const useWheelInteractions = ({
|
|
|
80989
80990
|
attemptInteraction,
|
|
80990
80991
|
cancelAnim,
|
|
80991
80992
|
setPos,
|
|
80992
|
-
releaseScrub,
|
|
80993
80993
|
snapPosToRow,
|
|
80994
80994
|
getItemSize,
|
|
80995
80995
|
viewportMain,
|
|
@@ -81397,8 +81397,6 @@ const useWheelInteractions = ({
|
|
|
81397
81397
|
clearTimeout(settleTimer);
|
|
81398
81398
|
stopClaimingGesture();
|
|
81399
81399
|
cancelAnim();
|
|
81400
|
-
// Nothing is left to settle the scrub in progress.
|
|
81401
|
-
releaseScrub();
|
|
81402
81400
|
document.removeEventListener("pointerdown", onDocumentPointerDown, {
|
|
81403
81401
|
capture: true
|
|
81404
81402
|
});
|
|
@@ -81564,11 +81562,11 @@ function WheelUI(props) {
|
|
|
81564
81562
|
...props,
|
|
81565
81563
|
ref: inputRef,
|
|
81566
81564
|
type: "navi_js",
|
|
81567
|
-
//
|
|
81568
|
-
//
|
|
81569
|
-
// stops setUIState from auto-firing the action on every value change
|
|
81570
|
-
//
|
|
81571
|
-
// override actionEvent.
|
|
81565
|
+
// uiAction fires live (every center-crossing, via setPos live reports);
|
|
81566
|
+
// the committed action must fire only when the wheel stabilizes. "custom"
|
|
81567
|
+
// stops setUIState from auto-firing the action on every value change, so
|
|
81568
|
+
// the live reports are uiAction-only; commitSelection then dispatches the
|
|
81569
|
+
// action explicitly on settle. A caller can still override actionEvent.
|
|
81572
81570
|
actionEvent: props.actionEvent ?? "custom"
|
|
81573
81571
|
}, {
|
|
81574
81572
|
controlType: "input"
|
|
@@ -81664,11 +81662,6 @@ function WheelUI(props) {
|
|
|
81664
81662
|
// while our own scroll-driven selection does not scroll a second time. Holds the
|
|
81665
81663
|
// TARGET so rapid inputs step from it and accumulate. null = nothing pending.
|
|
81666
81664
|
const centeredIndexRef = useRef(null);
|
|
81667
|
-
// A user scrub moved the wheel onto a row that is not the value yet: set at
|
|
81668
|
-
// the first row it crosses, cleared when it settles (commitSelection), when
|
|
81669
|
-
// an arrow or a tap sets a value at once (glideToIndex), or when it is
|
|
81670
|
-
// dropped (releaseScrub). See setPos.
|
|
81671
|
-
const scrubHoldsRowRef = useRef(false);
|
|
81672
81665
|
// The wheel does NOT use native scroll. `posRef` is our own virtual scroll
|
|
81673
81666
|
// position (px, main axis); the list track is translated by -pos. This is the
|
|
81674
81667
|
// single source of truth, wrapped modulo the real-list extent in loop mode, so
|
|
@@ -81857,14 +81850,12 @@ function WheelUI(props) {
|
|
|
81857
81850
|
posRef.current = clampNumber(posRef.current, 0, (count - 1) * size);
|
|
81858
81851
|
};
|
|
81859
81852
|
|
|
81860
|
-
// `live`
|
|
81861
|
-
//
|
|
81862
|
-
//
|
|
81863
|
-
//
|
|
81864
|
-
//
|
|
81865
|
-
//
|
|
81866
|
-
// (navigation.md, "A value written per frame"). A programmatic move
|
|
81867
|
-
// (centerOnIndex) omits `live`: it places the value the wheel already has.
|
|
81853
|
+
// `live` (user scrubs: drag, momentum, wheel scroll) reports the value as each
|
|
81854
|
+
// item crosses the center, so uiAction tracks the wheel in real time — like
|
|
81855
|
+
// every other control. The committed action still fires only once it settles
|
|
81856
|
+
// (commitSelection). A programmatic move (centerOnIndex on an external value
|
|
81857
|
+
// sync) omits it, so scrolling the wheel into place doesn't echo the value
|
|
81858
|
+
// back out.
|
|
81868
81859
|
const setPos = (vp, pos, {
|
|
81869
81860
|
live = false
|
|
81870
81861
|
} = {}) => {
|
|
@@ -81875,25 +81866,18 @@ function WheelUI(props) {
|
|
|
81875
81866
|
renderPos(vp);
|
|
81876
81867
|
if (live && interactive) {
|
|
81877
81868
|
const index = centeredIndex(vp);
|
|
81878
|
-
if (index !== centeredIndexRef.current
|
|
81879
|
-
|
|
81880
|
-
|
|
81881
|
-
|
|
81882
|
-
|
|
81869
|
+
if (index !== centeredIndexRef.current) {
|
|
81870
|
+
const item = trackedItemsRef.current[index];
|
|
81871
|
+
if (item) {
|
|
81872
|
+
// Keep centeredIndexRef in step so the every-render
|
|
81873
|
+
// syncCenterToSelection doesn't read this as an external change and
|
|
81874
|
+
// fight the in-progress motion.
|
|
81875
|
+
centeredIndexRef.current = index;
|
|
81876
|
+
requestSelectValue(item.value, new CustomEvent("navi_wheel_scrub"));
|
|
81877
|
+
}
|
|
81883
81878
|
}
|
|
81884
81879
|
}
|
|
81885
81880
|
};
|
|
81886
|
-
// The scrub was dropped before it settled (the wheel stopped being
|
|
81887
|
-
// interactive, or its input bindings were torn down): the row it held never
|
|
81888
|
-
// became the value. Forgetting it lets the next sync put the wheel back on
|
|
81889
|
-
// the value.
|
|
81890
|
-
const releaseScrub = () => {
|
|
81891
|
-
if (!scrubHoldsRowRef.current) {
|
|
81892
|
-
return;
|
|
81893
|
-
}
|
|
81894
|
-
scrubHoldsRowRef.current = false;
|
|
81895
|
-
centeredIndexRef.current = null;
|
|
81896
|
-
};
|
|
81897
81881
|
|
|
81898
81882
|
// Returns whether it actually interrupted a motion in flight — lets the caller
|
|
81899
81883
|
// tell a fresh gesture from one that "caught" a spinning/gliding wheel.
|
|
@@ -81929,7 +81913,6 @@ function WheelUI(props) {
|
|
|
81929
81913
|
renderPos(vp);
|
|
81930
81914
|
}
|
|
81931
81915
|
centeredIndexRef.current = index;
|
|
81932
|
-
scrubHoldsRowRef.current = false;
|
|
81933
81916
|
if (!interactive || glideFromOutsideRef.current) {
|
|
81934
81917
|
return;
|
|
81935
81918
|
}
|
|
@@ -82127,7 +82110,6 @@ function WheelUI(props) {
|
|
|
82127
82110
|
// inputs accumulate.
|
|
82128
82111
|
const glideToIndex = (vp, index, event) => {
|
|
82129
82112
|
centeredIndexRef.current = index;
|
|
82130
|
-
scrubHoldsRowRef.current = false;
|
|
82131
82113
|
requestSelectValue(trackedItemsRef.current[index].value, event);
|
|
82132
82114
|
glideTo(vp, glideTargetFor(vp, index));
|
|
82133
82115
|
};
|
|
@@ -82158,12 +82140,12 @@ function WheelUI(props) {
|
|
|
82158
82140
|
// Sync the center with the current value — used on first display and whenever
|
|
82159
82141
|
// the controlled value changes from outside.
|
|
82160
82142
|
const syncCenterToSelection = (viewportEl, behavior) => {
|
|
82161
|
-
// A fling in flight
|
|
82162
|
-
//
|
|
82163
|
-
//
|
|
82164
|
-
// below (glideTo never restarts the
|
|
82165
|
-
// mid-glide is where the wheel ends up.
|
|
82166
|
-
if (momentumRef.current !== null
|
|
82143
|
+
// A fling in flight reports its own value at every row crossing and commits
|
|
82144
|
+
// on settle: the finger that threw it owns the wheel until then, and a value
|
|
82145
|
+
// arriving meanwhile is re-stated by the next crossing anyway. A glide is
|
|
82146
|
+
// different: its target is re-aimed below (glideTo never restarts the
|
|
82147
|
+
// loop), so a value set from outside mid-glide is where the wheel ends up.
|
|
82148
|
+
if (momentumRef.current !== null) {
|
|
82167
82149
|
return;
|
|
82168
82150
|
}
|
|
82169
82151
|
if (trackedItemsRef.current.length === 0) {
|
|
@@ -82246,7 +82228,6 @@ function WheelUI(props) {
|
|
|
82246
82228
|
attemptInteraction,
|
|
82247
82229
|
cancelAnim,
|
|
82248
82230
|
setPos,
|
|
82249
|
-
releaseScrub,
|
|
82250
82231
|
snapPosToRow,
|
|
82251
82232
|
getItemSize,
|
|
82252
82233
|
viewportMain,
|