@jsenv/navi 0.29.318 → 0.29.320
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 +211 -64
- package/dist/dev/jsenv_navi.js.map +8 -8
- package/dist/jsenv_navi.js +211 -64
- package/dist/jsenv_navi.js.map +8 -8
- package/package.json +1 -1
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -27799,14 +27799,35 @@ Consider using unique IDs for each component instance.`,
|
|
|
27799
27799
|
|
|
27800
27800
|
const NO_OP = () => {};
|
|
27801
27801
|
const NO_ID_GIVEN = [undefined, NO_OP, NO_OP];
|
|
27802
|
+
// What the computed below answers for a key the document state does not hold:
|
|
27803
|
+
// key presence is the flag, and the value under a present key may be anything,
|
|
27804
|
+
// undefined included.
|
|
27805
|
+
const KEY_NOT_IN_STATE = Symbol("key_not_in_state");
|
|
27802
27806
|
const useNavStateBasic = (
|
|
27803
27807
|
id,
|
|
27804
27808
|
{ debug, type = "replace", onLeave, defaultValue } = {},
|
|
27805
27809
|
) => {
|
|
27806
27810
|
// Hooks must be called unconditionally — before the !id early return.
|
|
27807
|
-
|
|
27808
|
-
//
|
|
27809
|
-
|
|
27811
|
+
//
|
|
27812
|
+
// Subscribed to this one key, through a computed, rather than to the state
|
|
27813
|
+
// as a whole: every popup with a nav state reads here, and a document state
|
|
27814
|
+
// is written whenever any of them opens — a list of forty names each with a
|
|
27815
|
+
// tooltip would re-render forty pickers, chains included, for the sheet
|
|
27816
|
+
// around them opening. The computed only wakes this component when what
|
|
27817
|
+
// sits under its own key changes.
|
|
27818
|
+
const keyValueComputed = useMemo(
|
|
27819
|
+
() =>
|
|
27820
|
+
computed(() => {
|
|
27821
|
+
const state = documentStateSignal.value;
|
|
27822
|
+
if (id && state && Object.hasOwn(state, id)) {
|
|
27823
|
+
return state[id];
|
|
27824
|
+
}
|
|
27825
|
+
return KEY_NOT_IN_STATE;
|
|
27826
|
+
}),
|
|
27827
|
+
[id],
|
|
27828
|
+
);
|
|
27829
|
+
const keyValue = keyValueComputed.value;
|
|
27830
|
+
const keyInState = keyValue !== KEY_NOT_IN_STATE;
|
|
27810
27831
|
const onLeaveRef = useRef(onLeave);
|
|
27811
27832
|
onLeaveRef.current = onLeave;
|
|
27812
27833
|
const prevKeyInStateRef = useRef(keyInState);
|
|
@@ -27841,7 +27862,7 @@ const useNavStateBasic = (
|
|
|
27841
27862
|
effectiveType = "replace";
|
|
27842
27863
|
}
|
|
27843
27864
|
|
|
27844
|
-
const currentValue = keyInState ?
|
|
27865
|
+
const currentValue = keyInState ? keyValue : defaultValue;
|
|
27845
27866
|
|
|
27846
27867
|
if (debug) {
|
|
27847
27868
|
console.debug(`useNavState(${id}) current value is ${currentValue}`);
|
|
@@ -35465,6 +35486,18 @@ const MOUNT_DEFAULT = "from-first-open";
|
|
|
35465
35486
|
const popupsMountingContentForOpen = new Set();
|
|
35466
35487
|
const isMountingContentForOpen = (popupElement) =>
|
|
35467
35488
|
popupsMountingContentForOpen.has(popupElement);
|
|
35489
|
+
// The popup being built that holds `element` somewhere below it, or null. For
|
|
35490
|
+
// an element whose own openable ancestor is something else (a closed trigger
|
|
35491
|
+
// inside the popup): what the layout would say about it is what it says about
|
|
35492
|
+
// the whole popup — nothing is on screen there yet.
|
|
35493
|
+
const findPopupMountingContentAround = (element) => {
|
|
35494
|
+
for (const popupElement of popupsMountingContentForOpen) {
|
|
35495
|
+
if (popupElement !== element && popupElement.contains(element)) {
|
|
35496
|
+
return popupElement;
|
|
35497
|
+
}
|
|
35498
|
+
}
|
|
35499
|
+
return null;
|
|
35500
|
+
};
|
|
35468
35501
|
|
|
35469
35502
|
// requestIdleCallback is missing from Safari; a timeout is close enough there.
|
|
35470
35503
|
const requestIdle = (callback) =>
|
|
@@ -35634,6 +35667,9 @@ const useDisplayedLayoutEffect = (ref, callback, deps) => {
|
|
|
35634
35667
|
// Set by the mount effect below for an element that lives in its openable
|
|
35635
35668
|
// ancestor's façade rather than in what that ancestor opens.
|
|
35636
35669
|
const displayedWhileAncestorClosedRef = useRef(false);
|
|
35670
|
+
// The popup whose opening will answer what the mount could not — see the
|
|
35671
|
+
// mount effect below.
|
|
35672
|
+
const decisionDeferredToRef = useRef(null);
|
|
35637
35673
|
|
|
35638
35674
|
// Run on mount (or when deps change) — but only if the element is visible.
|
|
35639
35675
|
useLayoutEffect(() => {
|
|
@@ -35647,14 +35683,26 @@ const useDisplayedLayoutEffect = (ref, callback, deps) => {
|
|
|
35647
35683
|
return;
|
|
35648
35684
|
}
|
|
35649
35685
|
if (!isAncestorOpen(ancestor)) {
|
|
35650
|
-
if (
|
|
35686
|
+
if (isMountingContentForOpen(ancestor)) {
|
|
35651
35687
|
// The popup building its content for its own opening: nothing in it
|
|
35652
35688
|
// is on screen, and the open about to follow reveals all of it. Known
|
|
35653
35689
|
// without asking the layout, which a synchronous mount would have to
|
|
35654
|
-
// bring up to date once per element asking
|
|
35655
|
-
|
|
35656
|
-
|
|
35657
|
-
|
|
35690
|
+
// bring up to date once per element asking; the observer below fires
|
|
35691
|
+
// once it opens.
|
|
35692
|
+
return;
|
|
35693
|
+
}
|
|
35694
|
+
const popupMounting = findPopupMountingContentAround(el);
|
|
35695
|
+
if (popupMounting) {
|
|
35696
|
+
// Under a closed trigger — a picker's façade, an expandable's header —
|
|
35697
|
+
// inside a popup being built. Whether this element is on screen once
|
|
35698
|
+
// that popup is open is exactly what the layout cannot say while the
|
|
35699
|
+
// popup, and everything in it, is display:none: it would answer "hidden"
|
|
35700
|
+
// for a façade that the opening is about to show. Asked again when the
|
|
35701
|
+
// popup opens (see the observer effect below).
|
|
35702
|
+
decisionDeferredToRef.current = popupMounting;
|
|
35703
|
+
return;
|
|
35704
|
+
}
|
|
35705
|
+
if (!isDisplayedDespiteClosedAncestor(el, ancestor)) {
|
|
35658
35706
|
// Ancestor is closed and took this element off screen with it — skip
|
|
35659
35707
|
// now; the observeAncestorOpenState call below will fire once it
|
|
35660
35708
|
// opens.
|
|
@@ -35678,19 +35726,63 @@ const useDisplayedLayoutEffect = (ref, callback, deps) => {
|
|
|
35678
35726
|
if (!ancestor) {
|
|
35679
35727
|
return undefined;
|
|
35680
35728
|
}
|
|
35681
|
-
|
|
35682
|
-
|
|
35683
|
-
|
|
35684
|
-
|
|
35685
|
-
|
|
35686
|
-
|
|
35687
|
-
|
|
35688
|
-
|
|
35689
|
-
|
|
35690
|
-
|
|
35691
|
-
|
|
35692
|
-
|
|
35693
|
-
|
|
35729
|
+
const stopObservingAncestor = observeAncestorOpenState(
|
|
35730
|
+
ancestor,
|
|
35731
|
+
({ isOpen }) => {
|
|
35732
|
+
if (!isOpen) {
|
|
35733
|
+
return;
|
|
35734
|
+
}
|
|
35735
|
+
if (displayedWhileAncestorClosedRef.current) {
|
|
35736
|
+
// Façade content: on screen the whole time, so this opening reveals
|
|
35737
|
+
// nothing here — and `becauseAncestorOpened: true` about it would be
|
|
35738
|
+
// false in a way consumers act on (see use_auto_focus.js).
|
|
35739
|
+
return;
|
|
35740
|
+
}
|
|
35741
|
+
const lastEl = ref.current;
|
|
35742
|
+
callbackRef.current(lastEl, createDisplayedEvent(ancestor, true));
|
|
35743
|
+
},
|
|
35744
|
+
);
|
|
35745
|
+
const popupMounting = decisionDeferredToRef.current;
|
|
35746
|
+
if (!popupMounting) {
|
|
35747
|
+
return stopObservingAncestor;
|
|
35748
|
+
}
|
|
35749
|
+
// The mount deferred its decision to this popup's opening (see above):
|
|
35750
|
+
// once it is open, the layout answers for what the closed ancestor keeps
|
|
35751
|
+
// on screen. A façade element is then displayed, by that opening — which
|
|
35752
|
+
// owns it, the way it owns everything the popup reveals. An element the
|
|
35753
|
+
// closed ancestor genuinely hides stays with the observer above.
|
|
35754
|
+
const stopObservingPopup = observeAncestorOpenState(
|
|
35755
|
+
popupMounting,
|
|
35756
|
+
({ isOpen }) => {
|
|
35757
|
+
if (!isOpen) {
|
|
35758
|
+
return;
|
|
35759
|
+
}
|
|
35760
|
+
stopObservingPopup();
|
|
35761
|
+
decisionDeferredToRef.current = null;
|
|
35762
|
+
const lastEl = ref.current;
|
|
35763
|
+
if (!lastEl) {
|
|
35764
|
+
return;
|
|
35765
|
+
}
|
|
35766
|
+
if (isAncestorOpen(ancestor)) {
|
|
35767
|
+
callbackRef.current(
|
|
35768
|
+
lastEl,
|
|
35769
|
+
createDisplayedEvent(popupMounting, true),
|
|
35770
|
+
);
|
|
35771
|
+
return;
|
|
35772
|
+
}
|
|
35773
|
+
if (isDisplayedDespiteClosedAncestor(lastEl, ancestor)) {
|
|
35774
|
+
displayedWhileAncestorClosedRef.current = true;
|
|
35775
|
+
callbackRef.current(
|
|
35776
|
+
lastEl,
|
|
35777
|
+
createDisplayedEvent(popupMounting, true),
|
|
35778
|
+
);
|
|
35779
|
+
}
|
|
35780
|
+
},
|
|
35781
|
+
);
|
|
35782
|
+
return () => {
|
|
35783
|
+
stopObservingAncestor();
|
|
35784
|
+
stopObservingPopup();
|
|
35785
|
+
};
|
|
35694
35786
|
}, []);
|
|
35695
35787
|
};
|
|
35696
35788
|
|
|
@@ -61198,24 +61290,18 @@ const useDialogProps = props => {
|
|
|
61198
61290
|
// comment): this opening has its own content to be measured against, and
|
|
61199
61291
|
// measuring it inside last time's box would answer with last time's size.
|
|
61200
61292
|
unfreezeSize(dialogEl);
|
|
61201
|
-
positionDialog();
|
|
61202
|
-
if (sizing === "frozen") {
|
|
61203
|
-
// After positionDialog: the caps it writes
|
|
61204
|
-
// (--container-position-remaining-*) are part of what decides the size
|
|
61205
|
-
// being taken, so measuring before it would freeze a box the dialog
|
|
61206
|
-
// never actually had.
|
|
61207
|
-
freezeSize(dialogEl);
|
|
61208
|
-
}
|
|
61209
61293
|
|
|
61210
|
-
//
|
|
61211
|
-
//
|
|
61212
|
-
//
|
|
61294
|
+
// Placed by the effect's own first check, synchronously, on the opening
|
|
61295
|
+
// event — and repositioned on the same triggers Popover's own
|
|
61296
|
+
// visibleRectEffect reacts to generically: window resize/scroll/
|
|
61297
|
+
// visual-viewport changes for layer="top" (positionedAncestor is already
|
|
61213
61298
|
// document.documentElement there, see its own computation above;
|
|
61214
|
-
// visibleRectEffect already debounces visualViewport resize by 100ms
|
|
61215
|
-
//
|
|
61216
|
-
//
|
|
61217
|
-
//
|
|
61218
|
-
//
|
|
61299
|
+
// visibleRectEffect already debounces visualViewport resize by 100ms to
|
|
61300
|
+
// avoid the mobile tap-to-tap-input keyboard flicker, so no separate
|
|
61301
|
+
// mechanism is needed here for that), or the positioned ancestor's own
|
|
61302
|
+
// resize for layer="local" — see this file's top comment. One placement
|
|
61303
|
+
// for the opening: a positionDialog() of our own before the effect would
|
|
61304
|
+
// be a second pick, and a second layout between two reads of the viewport.
|
|
61219
61305
|
const rectEffect = visibleRectEffect(positionedAncestor, (visibleRect, {
|
|
61220
61306
|
event
|
|
61221
61307
|
}) => {
|
|
@@ -61230,6 +61316,13 @@ const useDialogProps = props => {
|
|
|
61230
61316
|
event: e,
|
|
61231
61317
|
skipElementResize: true
|
|
61232
61318
|
});
|
|
61319
|
+
if (sizing === "frozen") {
|
|
61320
|
+
// After the placement: the caps it writes
|
|
61321
|
+
// (--container-position-remaining-*) are part of what decides the size
|
|
61322
|
+
// being taken, so measuring before it would freeze a box the dialog
|
|
61323
|
+
// never actually had.
|
|
61324
|
+
freezeSize(dialogEl);
|
|
61325
|
+
}
|
|
61233
61326
|
rectEffect.observeSize(dialogEl);
|
|
61234
61327
|
// Exposed for the placement-props effect below, which needs to re-place an
|
|
61235
61328
|
// already-open dialog.
|
|
@@ -63569,6 +63662,13 @@ const PickerCustomResolver = props => {
|
|
|
63569
63662
|
if (props.calloutIcon === undefined) {
|
|
63570
63663
|
props.calloutIcon = props.variant !== "text";
|
|
63571
63664
|
}
|
|
63665
|
+
// A door's content is never where its value comes from (see `standalone`
|
|
63666
|
+
// above), so nothing needs it before the first open: built then, like a
|
|
63667
|
+
// popup's. A name in a list wrapped in a tooltip is otherwise a card in
|
|
63668
|
+
// the DOM per name, and each one asks the layout whether it is on screen.
|
|
63669
|
+
if (props.mount === undefined) {
|
|
63670
|
+
props.mount = MOUNT_DEFAULT;
|
|
63671
|
+
}
|
|
63572
63672
|
if (props.rightSlotIcon === undefined) {
|
|
63573
63673
|
props.rightSlotIcon = jsx(CalloutStatusIcon, {
|
|
63574
63674
|
status: props.calloutStatus,
|
|
@@ -64434,13 +64534,15 @@ const PICKER_CALLOUT_CONTENT_TOKEN = createOpenToken();
|
|
|
64434
64534
|
* The content is rendered into an element this component owns, handed to the
|
|
64435
64535
|
* callout as its message (a Node, appended as-is) and taken back when the
|
|
64436
64536
|
* callout closes. Between two opens it is docked, hidden, in the span below:
|
|
64437
|
-
* in the document the whole time,
|
|
64438
|
-
*
|
|
64439
|
-
*
|
|
64440
|
-
*
|
|
64441
|
-
*
|
|
64442
|
-
*
|
|
64443
|
-
*
|
|
64537
|
+
* in the document the whole time once built, so what it holds survives a
|
|
64538
|
+
* close, and what it measures of itself at mount (a computed color, a
|
|
64539
|
+
* light-dark() pair) resolves against a real ancestry. An element with no
|
|
64540
|
+
* document has no computed style, and a badge reading its own background
|
|
64541
|
+
* there would see nothing at all. When it is built is the popup's own `mount`
|
|
64542
|
+
* rule (see popup_content_mount.js) — the first open, for a callout. The
|
|
64543
|
+
* element carries data-picker-content: the callout is appended inside the
|
|
64544
|
+
* picker root, and a press in there must read as inside the popup, not on the
|
|
64545
|
+
* trigger.
|
|
64444
64546
|
*/
|
|
64445
64547
|
const PickerCalloutPopup = ({
|
|
64446
64548
|
ref,
|
|
@@ -64455,9 +64557,18 @@ const PickerCalloutPopup = ({
|
|
|
64455
64557
|
onnavi_request_open,
|
|
64456
64558
|
onnavi_request_close,
|
|
64457
64559
|
onnavi_request_confirm,
|
|
64458
|
-
|
|
64560
|
+
mount,
|
|
64561
|
+
children: childrenProp
|
|
64459
64562
|
}) => {
|
|
64460
64563
|
const hostRef = useRef(null);
|
|
64564
|
+
// The dock is what the content finds as its openable ancestor (the
|
|
64565
|
+
// aria-expanded below), which is what the mount marks as being built for
|
|
64566
|
+
// its own opening.
|
|
64567
|
+
const contentMounted = usePopupContentMount(openController, ref, {
|
|
64568
|
+
mount,
|
|
64569
|
+
anchor
|
|
64570
|
+
});
|
|
64571
|
+
const children = contentMounted ? childrenProp : null;
|
|
64461
64572
|
// Reassigned on every render, like Popover's own, so it closes over the
|
|
64462
64573
|
// latest props.
|
|
64463
64574
|
openController.getElement = () => pickerRef.current;
|
|
@@ -67338,7 +67449,8 @@ const useListScrollSync = ({
|
|
|
67338
67449
|
const debugScroll = useDebugScroll();
|
|
67339
67450
|
const virtualItemSizeSignal = useVirtualItemSizeSignal(ref, virtualItemSize, horizontal, {
|
|
67340
67451
|
virtual,
|
|
67341
|
-
renderBudget
|
|
67452
|
+
renderBudget,
|
|
67453
|
+
scrolledWanted: scrolled ?? defaultScrolled
|
|
67342
67454
|
});
|
|
67343
67455
|
const getScroller = () => getScrollerEl(ref.current, scroller, horizontal);
|
|
67344
67456
|
const getListEl = () => ref.current.querySelector(".navi_list");
|
|
@@ -68744,7 +68856,8 @@ const measureItemSize = (listEl, horizontal) => {
|
|
|
68744
68856
|
};
|
|
68745
68857
|
const useVirtualItemSizeSignal = (ref, virtualItemSizeProp = 0, horizontal, {
|
|
68746
68858
|
virtual,
|
|
68747
|
-
renderBudget
|
|
68859
|
+
renderBudget,
|
|
68860
|
+
scrolledWanted
|
|
68748
68861
|
}) => {
|
|
68749
68862
|
const virtualSizeSignalRef = useRef(null);
|
|
68750
68863
|
if (!virtualSizeSignalRef.current) {
|
|
@@ -68814,6 +68927,14 @@ const useVirtualItemSizeSignal = (ref, virtualItemSizeProp = 0, horizontal, {
|
|
|
68814
68927
|
if (virtualSizeSignal.peek() !== 0) {
|
|
68815
68928
|
return undefined;
|
|
68816
68929
|
}
|
|
68930
|
+
// Measured only for what reads the size: the fillers of rows held off
|
|
68931
|
+
// screen, and a list held somewhere (placeWhereHeld) before it knows where
|
|
68932
|
+
// that is. A list drawing every row it has, opening at its start, would
|
|
68933
|
+
// pay a layout in every commit for a number nobody reads.
|
|
68934
|
+
const sizeRead = virtual.totalSignal.peek() > renderBudget || scrolledWanted !== undefined && scrolledWanted !== "start";
|
|
68935
|
+
if (!sizeRead) {
|
|
68936
|
+
return undefined;
|
|
68937
|
+
}
|
|
68817
68938
|
const listEl = ref.current?.querySelector(".navi_list");
|
|
68818
68939
|
if (!listEl) {
|
|
68819
68940
|
return undefined;
|
|
@@ -70030,6 +70151,7 @@ const ListItems = ({
|
|
|
70030
70151
|
const virtual = useContext(ListVirtualContext);
|
|
70031
70152
|
const slotId = useContext(ListSlotContext);
|
|
70032
70153
|
const renderWindow = useContext(RenderWindowContext);
|
|
70154
|
+
const separator = useContext(SeparatorContext);
|
|
70033
70155
|
// The vnode drawn for a row, kept by item: a run rendering again (its window
|
|
70034
70156
|
// moving, its first paint's budget giving way to the full one) hands preact
|
|
70035
70157
|
// the same vnode for a row that has not changed, and preact leaves that
|
|
@@ -70038,14 +70160,14 @@ const ListItems = ({
|
|
|
70038
70160
|
// row at the same index, in the same refreshing state: everything the
|
|
70039
70161
|
// function is given.
|
|
70040
70162
|
const rowVnodesRef = useRef(null);
|
|
70041
|
-
if (!rowVnodesRef.current || rowVnodesRef.current.renderItem !== renderItem) {
|
|
70163
|
+
if (!rowVnodesRef.current || rowVnodesRef.current.renderItem !== renderItem || rowVnodesRef.current.separator !== separator) {
|
|
70042
70164
|
rowVnodesRef.current = {
|
|
70043
70165
|
renderItem,
|
|
70166
|
+
separator,
|
|
70044
70167
|
byItem: new Map()
|
|
70045
70168
|
};
|
|
70046
70169
|
}
|
|
70047
70170
|
const rowVnodesByItem = rowVnodesRef.current.byItem;
|
|
70048
|
-
const separator = useContext(SeparatorContext);
|
|
70049
70171
|
const store = useItemStore({
|
|
70050
70172
|
items,
|
|
70051
70173
|
count,
|
|
@@ -70275,17 +70397,33 @@ const ListItems = ({
|
|
|
70275
70397
|
const item = getItemAt(rowIndex);
|
|
70276
70398
|
const key = item === undefined ? `${ownerId}_skeleton_${rowIndex}` : idOf(item, rowIndex);
|
|
70277
70399
|
let rowVnode;
|
|
70400
|
+
let rowContextValue;
|
|
70401
|
+
let rowKept = null;
|
|
70278
70402
|
if (item !== undefined) {
|
|
70279
70403
|
const rowVnodeKept = rowVnodesByItem.get(item);
|
|
70280
70404
|
if (rowVnodeKept && rowVnodeKept.rowIndex === rowIndex && rowVnodeKept.refreshing === renderItemState.refreshing) {
|
|
70281
70405
|
rowVnode = rowVnodeKept.vnode;
|
|
70406
|
+
rowContextValue = rowVnodeKept.rowContextValue;
|
|
70407
|
+
rowKept = rowVnodeKept;
|
|
70282
70408
|
} else {
|
|
70283
70409
|
rowVnode = renderItem(item, rowIndex, renderItemState);
|
|
70284
|
-
|
|
70410
|
+
// Kept with the vnode, for the same reason: a context value that is a
|
|
70411
|
+
// fresh object on every render forces every consumer of it to render,
|
|
70412
|
+
// which is the row's own chain — the vnode handed back unchanged would
|
|
70413
|
+
// then buy nothing.
|
|
70414
|
+
rowContextValue = {
|
|
70415
|
+
id: key,
|
|
70416
|
+
index: rowIndex,
|
|
70417
|
+
item
|
|
70418
|
+
};
|
|
70419
|
+
rowKept = {
|
|
70285
70420
|
vnode: rowVnode,
|
|
70421
|
+
rowContextValue,
|
|
70286
70422
|
rowIndex,
|
|
70287
|
-
refreshing: renderItemState.refreshing
|
|
70288
|
-
|
|
70423
|
+
refreshing: renderItemState.refreshing,
|
|
70424
|
+
separatorVnode: null
|
|
70425
|
+
};
|
|
70426
|
+
rowVnodesByItem.set(item, rowKept);
|
|
70289
70427
|
}
|
|
70290
70428
|
} else if (renderRowSkeleton === false) {
|
|
70291
70429
|
// The row must still take its room: without it the rows below would
|
|
@@ -70309,20 +70447,25 @@ const ListItems = ({
|
|
|
70309
70447
|
// as a hairline under the label.
|
|
70310
70448
|
const drawSeparator = separator && rowIndex > 0 && !opensGroup(groupKeyOf(item, rowIndex));
|
|
70311
70449
|
if (drawSeparator) {
|
|
70312
|
-
|
|
70313
|
-
|
|
70314
|
-
|
|
70450
|
+
// Kept with the row too: a separator built again is a separator
|
|
70451
|
+
// rendered again.
|
|
70452
|
+
let separatorVnode = rowKept ? rowKept.separatorVnode : null;
|
|
70453
|
+
if (!separatorVnode) {
|
|
70454
|
+
separatorVnode = cloneElement(resolveSeparatorVnode(separator, rowIndex - 1), {
|
|
70455
|
+
key: `${key}_separator`
|
|
70456
|
+
});
|
|
70457
|
+
if (rowKept) {
|
|
70458
|
+
rowKept.separatorVnode = separatorVnode;
|
|
70459
|
+
}
|
|
70460
|
+
}
|
|
70461
|
+
pushRow(separatorVnode, item, rowIndex);
|
|
70315
70462
|
}
|
|
70316
70463
|
pushRow(jsx(ListRowContext.Provider, {
|
|
70317
70464
|
value: item === undefined ? {
|
|
70318
70465
|
id: key,
|
|
70319
70466
|
index: rowIndex,
|
|
70320
70467
|
...getSkeletonRow()
|
|
70321
|
-
} :
|
|
70322
|
-
id: key,
|
|
70323
|
-
index: rowIndex,
|
|
70324
|
-
item
|
|
70325
|
-
},
|
|
70468
|
+
} : rowContextValue,
|
|
70326
70469
|
children: rowVnode
|
|
70327
70470
|
}, key), item, rowIndex);
|
|
70328
70471
|
}
|
|
@@ -77100,9 +77243,13 @@ const useSearchText = (searchText, items, matchFn = applySearch) => {
|
|
|
77100
77243
|
return { orderedItems, matchInfoMap };
|
|
77101
77244
|
}, [items, searchText, matchFn]);
|
|
77102
77245
|
|
|
77103
|
-
|
|
77104
|
-
|
|
77105
|
-
|
|
77246
|
+
// The same function for as long as the map is the same: a `renderItem`
|
|
77247
|
+
// reading it is stable only if this is, and a run keeps the rows it drew
|
|
77248
|
+
// only for a stable `renderItem` (see List.Items).
|
|
77249
|
+
const getItemMatchInfo = useCallback(
|
|
77250
|
+
(item) => matchInfoMap.get(item),
|
|
77251
|
+
[matchInfoMap],
|
|
77252
|
+
);
|
|
77106
77253
|
|
|
77107
77254
|
return [orderedItems, getItemMatchInfo];
|
|
77108
77255
|
};
|