@jsenv/navi 0.29.494 → 0.29.496
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 +82 -38
- package/dist/dev/jsenv_navi.js.map +7 -7
- package/dist/jsenv_navi.js +82 -38
- package/dist/jsenv_navi.js.map +7 -7
- package/package.json +1 -1
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -46773,17 +46773,22 @@ document.body.addEventListener(
|
|
|
46773
46773
|
* on screen. A registry keyed by id then holds the newcomer, and loses the
|
|
46774
46774
|
* first control when the newcomer leaves. navi renders on the client only, so
|
|
46775
46775
|
* a counter is all the uniqueness needs.
|
|
46776
|
+
*
|
|
46777
|
+
* Held in a ref, not in useState: @preact/signals' shouldComponentUpdate
|
|
46778
|
+
* skips the render of a component holding hook state whose props did not
|
|
46779
|
+
* change, so an id kept as state would change when its caller renders.
|
|
46776
46780
|
*/
|
|
46777
46781
|
|
|
46778
46782
|
|
|
46779
46783
|
let generatedIdCount = 0;
|
|
46780
46784
|
|
|
46781
46785
|
const useGeneratedId = () => {
|
|
46782
|
-
const
|
|
46786
|
+
const idRef = useRef(null);
|
|
46787
|
+
if (idRef.current === null) {
|
|
46783
46788
|
generatedIdCount++;
|
|
46784
|
-
|
|
46785
|
-
}
|
|
46786
|
-
return
|
|
46789
|
+
idRef.current = `navi_${generatedIdCount}`;
|
|
46790
|
+
}
|
|
46791
|
+
return idRef.current;
|
|
46787
46792
|
};
|
|
46788
46793
|
|
|
46789
46794
|
/**
|
|
@@ -80762,12 +80767,14 @@ const PickerCustomResolver = props => {
|
|
|
80762
80767
|
return renderResolver(PickerNative, props);
|
|
80763
80768
|
}
|
|
80764
80769
|
if (props.mode === "callout") {
|
|
80765
|
-
// A tooltip is an icon one presses, unless told otherwise
|
|
80766
|
-
//
|
|
80767
|
-
//
|
|
80768
|
-
//
|
|
80769
|
-
if (
|
|
80770
|
+
// A tooltip is an icon one presses, unless told otherwise; "picker" asks
|
|
80771
|
+
// for the field-like drawing back. "circle" is the icon variant with the
|
|
80772
|
+
// status icon drawn round — a word about the trigger, not a drawing of its
|
|
80773
|
+
// own.
|
|
80774
|
+
if (props.variant === undefined) {
|
|
80770
80775
|
props.variant = "icon";
|
|
80776
|
+
} else if (props.variant === "picker") {
|
|
80777
|
+
props.variant = undefined;
|
|
80771
80778
|
}
|
|
80772
80779
|
const circle = props.variant === "circle";
|
|
80773
80780
|
if (circle) {
|
|
@@ -82272,11 +82279,10 @@ const PickerConfirmResolver = props => {
|
|
|
82272
82279
|
openWhileReadOnly = false
|
|
82273
82280
|
} = props;
|
|
82274
82281
|
// A button, unless told otherwise: nothing is picked here, the popup is a
|
|
82275
|
-
// question, and a question is asked by pressing something. "picker"
|
|
82276
|
-
//
|
|
82277
|
-
//
|
|
82278
|
-
|
|
82279
|
-
const variant = Object.hasOwn(props, "variant") ? props.variant === "picker" ? undefined : props.variant : "button";
|
|
82282
|
+
// question, and a question is asked by pressing something. "picker" is how a
|
|
82283
|
+
// caller asks for the field-like drawing back — a word, not an undefined, so
|
|
82284
|
+
// a wrapper forwarding `variant={variant}` keeps the button.
|
|
82285
|
+
const variant = props.variant === undefined ? "button" : props.variant === "picker" ? undefined : props.variant;
|
|
82280
82286
|
|
|
82281
82287
|
// From the picker's own input, as its press would have been: the input is
|
|
82282
82288
|
// what carries `command`/`commandFor` in the DOM, and what a form sending
|
|
@@ -94996,9 +95002,8 @@ const PickerUI = /*#__PURE__*/Object.assign(PickerDefaultUI, {
|
|
|
94996
95002
|
* not sit in — an object on a map saying
|
|
94997
95003
|
* `triggerNaviCommand(pickerEl, "--navi-open", event, { anchor, value })` —
|
|
94998
95004
|
* therefore wants an element of its own to stretch into rather than the
|
|
94999
|
-
* nearest positioned ancestor it happens to find. `"picker"`
|
|
95000
|
-
*
|
|
95001
|
-
* drawing every other picker has.
|
|
95005
|
+
* nearest positioned ancestor it happens to find. `"picker"` asks a confirm
|
|
95006
|
+
* or callout picker for the field-like drawing every other picker has.
|
|
95002
95007
|
* @param {boolean} [cta] A call to action: filled with the accent, its border
|
|
95003
95008
|
* matching, as `cta` draws a Button — for a confirm picker that is a row's
|
|
95004
95009
|
* main action.
|
|
@@ -98829,12 +98834,18 @@ const buildMatchInfo = (searchText, items, matchFn) => {
|
|
|
98829
98834
|
* needed. `data.role === "presentation"` keeps it out entirely.
|
|
98830
98835
|
* Returns the visible rank (position among visible items), or -1 when hidden
|
|
98831
98836
|
* or filtered.
|
|
98837
|
+
* An item rendered without an index keeps the position it has, and a new one
|
|
98838
|
+
* goes last: for a host that cannot know the order at render and gives it
|
|
98839
|
+
* afterwards with setOrder.
|
|
98832
98840
|
* Signals and onChange are deferred to a microtask so multiple items updating
|
|
98833
98841
|
* in one commit cause only one notification.
|
|
98834
98842
|
*
|
|
98835
98843
|
* getTrackedItemByIndex(index): synchronous O(1) lookup of a visible item by
|
|
98836
98844
|
* its visible rank. Returns undefined when index is out of range.
|
|
98837
98845
|
*
|
|
98846
|
+
* setOrder(ids): gives each tracked item its position from its rank in
|
|
98847
|
+
* `ids`.
|
|
98848
|
+
*
|
|
98838
98849
|
* peekItems(): the items as they stand right now, without waiting for the
|
|
98839
98850
|
* deferred notification — what a sibling rendering after the items must read
|
|
98840
98851
|
* to paint them in the same commit.
|
|
@@ -99115,8 +99126,14 @@ const createItemTracker = (onChange) => {
|
|
|
99115
99126
|
// that determines this item's position among siblings.
|
|
99116
99127
|
// Returns the item's visible rank among non-hidden items, or -1 when hidden.
|
|
99117
99128
|
const useTrackItem = (data) => {
|
|
99118
|
-
const { id
|
|
99129
|
+
const { id } = data;
|
|
99119
99130
|
const key = keyForId(id);
|
|
99131
|
+
let { index } = data;
|
|
99132
|
+
if (index === undefined) {
|
|
99133
|
+
index = keyToExplicitOrder.has(key)
|
|
99134
|
+
? keyToExplicitOrder.get(key)
|
|
99135
|
+
: Infinity;
|
|
99136
|
+
}
|
|
99120
99137
|
|
|
99121
99138
|
syncItem(key, index, data);
|
|
99122
99139
|
notify();
|
|
@@ -99134,6 +99151,24 @@ const createItemTracker = (onChange) => {
|
|
|
99134
99151
|
return keyToOrderedIndex.get(key) ?? -1;
|
|
99135
99152
|
};
|
|
99136
99153
|
|
|
99154
|
+
const setOrder = (ids) => {
|
|
99155
|
+
let changed = false;
|
|
99156
|
+
for (let i = 0; i < ids.length; i++) {
|
|
99157
|
+
const key = idToKey.get(ids[i]);
|
|
99158
|
+
if (key === undefined || !allRegistrations.has(key)) {
|
|
99159
|
+
continue;
|
|
99160
|
+
}
|
|
99161
|
+
if (keyToExplicitOrder.get(key) === i) {
|
|
99162
|
+
continue;
|
|
99163
|
+
}
|
|
99164
|
+
syncItem(key, i, allRegistrations.get(key));
|
|
99165
|
+
changed = true;
|
|
99166
|
+
}
|
|
99167
|
+
if (changed) {
|
|
99168
|
+
notify();
|
|
99169
|
+
}
|
|
99170
|
+
};
|
|
99171
|
+
|
|
99137
99172
|
const getTrackedItemByIndex = (index) => {
|
|
99138
99173
|
const key = orderedKeys[index];
|
|
99139
99174
|
if (key === undefined) {
|
|
@@ -99167,6 +99202,7 @@ const createItemTracker = (onChange) => {
|
|
|
99167
99202
|
return {
|
|
99168
99203
|
useTrackItem,
|
|
99169
99204
|
getTrackedItemByIndex,
|
|
99205
|
+
setOrder,
|
|
99170
99206
|
peekItems,
|
|
99171
99207
|
itemsSignal,
|
|
99172
99208
|
visibleItemsSignal,
|
|
@@ -99564,8 +99600,8 @@ const getNumericRange = items => {
|
|
|
99564
99600
|
|
|
99565
99601
|
// Wheel.Item registers its {value, label} here so WheelUI knows the full ordered
|
|
99566
99602
|
// list of items regardless of how children are wrapped (providers, fragments…).
|
|
99567
|
-
//
|
|
99568
|
-
//
|
|
99603
|
+
// The position comes after the commit, from the marker each item leaves where it
|
|
99604
|
+
// stands (see WheelUI).
|
|
99569
99605
|
const WheelItemTrackerContext = createContext(null);
|
|
99570
99606
|
|
|
99571
99607
|
// Lets a WheelGroup push shared presentation (glass, orientation) down to every
|
|
@@ -100188,15 +100224,21 @@ function WheelUI(props) {
|
|
|
100188
100224
|
// (children may be wrapped). This ordered list is the source of truth for the
|
|
100189
100225
|
// whole wheel — the rendered rows are a small recycled window over it.
|
|
100190
100226
|
const tracker = useItemTracker();
|
|
100191
|
-
|
|
100192
|
-
|
|
100193
|
-
|
|
100194
|
-
|
|
100195
|
-
|
|
100196
|
-
|
|
100197
|
-
|
|
100198
|
-
|
|
100199
|
-
|
|
100227
|
+
// The order is read from the markers the items leave in the DOM, not from the
|
|
100228
|
+
// order they render in: an item whose props did not change may skip a render
|
|
100229
|
+
// (signals' shouldComponentUpdate), and a render count would then rank the
|
|
100230
|
+
// ones that did render first.
|
|
100231
|
+
useLayoutEffect(() => {
|
|
100232
|
+
const el = ref.current;
|
|
100233
|
+
if (!el) {
|
|
100234
|
+
return;
|
|
100235
|
+
}
|
|
100236
|
+
const ids = [];
|
|
100237
|
+
for (const marker of el.querySelectorAll("[data-navi-wheel-item]")) {
|
|
100238
|
+
ids.push(marker.getAttribute("data-navi-wheel-item"));
|
|
100239
|
+
}
|
|
100240
|
+
tracker.setOrder(ids);
|
|
100241
|
+
});
|
|
100200
100242
|
const trackedItems = tracker.itemsSignal.value;
|
|
100201
100243
|
const trackedItemsRef = useRef(trackedItems);
|
|
100202
100244
|
trackedItemsRef.current = trackedItems;
|
|
@@ -101003,7 +101045,7 @@ function WheelUI(props) {
|
|
|
101003
101045
|
className: "navi_wheel_pane",
|
|
101004
101046
|
"data-side": "start"
|
|
101005
101047
|
}), jsx(WheelItemTrackerContext.Provider, {
|
|
101006
|
-
value:
|
|
101048
|
+
value: tracker,
|
|
101007
101049
|
children: jsx(ControlFacadeChildrenWrapper, {
|
|
101008
101050
|
facadeController: facadeController,
|
|
101009
101051
|
children: children
|
|
@@ -101116,9 +101158,10 @@ const WheelWindow = ({
|
|
|
101116
101158
|
* Wheel.Item — a value in a Wheel. Must be used inside <Wheel>.
|
|
101117
101159
|
*
|
|
101118
101160
|
* Registration only: it records its {value, label, itemProps} with the wheel and
|
|
101119
|
-
* renders
|
|
101120
|
-
*
|
|
101121
|
-
*
|
|
101161
|
+
* renders no row, only a hidden marker the wheel reads its position from. The
|
|
101162
|
+
* wheel is virtualized — it renders a small recycled window of rows and fills
|
|
101163
|
+
* each from this tracked data — so the value list is the source of truth, not a
|
|
101164
|
+
* per-item DOM node. Selection lives on the wheel's value.
|
|
101122
101165
|
*
|
|
101123
101166
|
* @type {import("preact").FunctionComponent<{
|
|
101124
101167
|
* value: any,
|
|
@@ -101135,16 +101178,17 @@ const WheelItem = ({
|
|
|
101135
101178
|
const idDefault = useGeneratedId();
|
|
101136
101179
|
const resolvedId = id || idDefault;
|
|
101137
101180
|
// Wheel.Item must live inside a Wheel, so the context is always present.
|
|
101138
|
-
const
|
|
101139
|
-
|
|
101140
|
-
trackerContext.tracker.useTrackItem({
|
|
101181
|
+
const tracker = useContext(WheelItemTrackerContext);
|
|
101182
|
+
tracker.useTrackItem({
|
|
101141
101183
|
id: resolvedId,
|
|
101142
|
-
index,
|
|
101143
101184
|
value,
|
|
101144
101185
|
label: children,
|
|
101145
101186
|
itemProps: rest
|
|
101146
101187
|
});
|
|
101147
|
-
return
|
|
101188
|
+
return jsx("span", {
|
|
101189
|
+
hidden: true,
|
|
101190
|
+
"data-navi-wheel-item": resolvedId
|
|
101191
|
+
});
|
|
101148
101192
|
};
|
|
101149
101193
|
Wheel.Item = WheelItem;
|
|
101150
101194
|
|