@jsenv/navi 0.27.50 → 0.27.52

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.
@@ -8869,11 +8869,11 @@ import.meta.css = [/* css */`
8869
8869
  }
8870
8870
  }
8871
8871
  /*
8872
-
8873
- It's very common to declare a display on component as follow
8872
+ To set display on component, code usually do something like:
8874
8873
  .component_class { display: component_display; }
8875
8874
 
8876
- This kill the default behavior of [hidden] attribute and we need to explicitly handle it with:
8875
+ It overrides the default behavior of [hidden] attribute!
8876
+ This needs to be explicitly handled with:
8877
8877
  .component_class[hidden] { display: none; }
8878
8878
 
8879
8879
  To avoid this extra work and potential mistakes we force the default behavior of [hidden] attribute.
@@ -22459,7 +22459,7 @@ const useUIStateController = (
22459
22459
  const currentUIState = uiStateController.uiState;
22460
22460
  const stateIsTheSame = compareTwoJsValues(newUIState, currentUIState);
22461
22461
  if (stateIsTheSame) {
22462
- if (controlType === "button") {
22462
+ if (controlType === "button" || controlType === "link") {
22463
22463
  if (!isInternalEvent(e)) {
22464
22464
  uiStateController.onUIAction(e);
22465
22465
  }
@@ -23071,6 +23071,9 @@ const useUIGroupStateController = (
23071
23071
  if (childUIStateController.controlType === "button") {
23072
23072
  return false;
23073
23073
  }
23074
+ if (childUIStateController.controlType === "link") {
23075
+ return false;
23076
+ }
23074
23077
  return true;
23075
23078
  };
23076
23079
 
@@ -23367,6 +23370,9 @@ const useUIGroupStateController = (
23367
23370
  if (childUIStateController.controlType === "button") {
23368
23371
  continue;
23369
23372
  }
23373
+ if (childUIStateController.controlType === "link") {
23374
+ continue;
23375
+ }
23370
23376
  childUIStateController.clearUIState(propagateDownClearEvent);
23371
23377
  }
23372
23378
  onChange(e, { notifyExternal: true });
@@ -23465,6 +23471,9 @@ const useUIFacadeStateController = (props, realUIStateController) => {
23465
23471
  if (childController.controlType === "button") {
23466
23472
  return false;
23467
23473
  }
23474
+ if (childController.controlType === "link") {
23475
+ return false;
23476
+ }
23468
23477
  if (childController.controlType === "facade") {
23469
23478
  return false;
23470
23479
  }
@@ -32091,8 +32100,12 @@ const getNowHoursRoundedToStep = (stepMinutes, offsetMinutes = 0) => {
32091
32100
  return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`;
32092
32101
  };
32093
32102
 
32094
- // Maps validity type names → navi input type names
32103
+ // Maps validity type names → navi input type names.
32104
+ // Numeric signal types must not fall through to the native type="number"
32105
+ // (which adds spinner buttons and has poor UX) — they map to navi_number instead.
32095
32106
  const VALIDITY_TYPE_TO_INPUT_TYPE = {
32107
+ number: "navi_number",
32108
+ integer: "navi_number",
32096
32109
  percentage: "navi_percentage",
32097
32110
  };
32098
32111
 
@@ -36318,6 +36331,10 @@ const PickerCustom = props => {
36318
36331
  Object.assign(pickerProps, {
36319
36332
  eventReactionDefinitions: {
36320
36333
  mouseDown: e => {
36334
+ const popupEl = popupRef.current;
36335
+ if (popupEl && popupEl.contains(e.target)) {
36336
+ return null;
36337
+ }
36321
36338
  if (expandedRef.current) {
36322
36339
  return {
36323
36340
  name: "mousedown to close picker",
@@ -36334,6 +36351,10 @@ const PickerCustom = props => {
36334
36351
  };
36335
36352
  },
36336
36353
  click: e => {
36354
+ const popupEl = popupRef.current;
36355
+ if (popupEl && popupEl.contains(e.target)) {
36356
+ return null;
36357
+ }
36337
36358
  // When a label is clicked it transfers focus to the select
36338
36359
  // in that case we want to open it (otherwise we have already opened on mousedown interaction)
36339
36360
  return {
@@ -36352,40 +36373,6 @@ const PickerCustom = props => {
36352
36373
  }
36353
36374
  }
36354
36375
  });
36355
- Object.assign(popupProps, {
36356
- onMouseDown: e => {
36357
- if (e.button !== 0) {
36358
- return;
36359
- }
36360
- // mousedown inside popover should not bubble to the select (would re-open it if that mousedown closes it)
36361
- debugPopup(e, `"mousedown" received on popup -> prevent bubbling to picker (e.stopPropagation())`);
36362
- e.stopPropagation();
36363
- },
36364
- onClick: e => {
36365
- if (e.button !== 0) {
36366
- return;
36367
- }
36368
- // click inside popover should not bubble to the picker (would re-open it if that click closes it)
36369
- debugPopup(e, `"click" received on popup -> prevent bubbling to picker (e.stopPropagation())`);
36370
- e.stopPropagation();
36371
- // Here we can't preventDefault because the click might be needed to check a radio for instance.
36372
- // As a result we have to let it go through which means it could trigger form submission
36373
- // but we've put type="button" on the picker to ensure it can't submit the form
36374
- // so browser won't submit eventual form for clicks inside the popover/dialog
36375
- // e.preventDefault();
36376
- },
36377
- onKeyDown: e => {
36378
- // some keys pressed inside popover should not reach the picker button
36379
- // (like enter that would try to request action of closest form otherwise for instance)
36380
- if (e.key === "Enter") {
36381
- debugPopup(e, `"enter" received on popup -> prevent bubbling to picker (e.stopPropagation())`);
36382
- e.stopPropagation();
36383
- // preventDefault prevents the browser from dispatching a "click" on the
36384
- // picker button when focus moves to it synchronously during enterEffect
36385
- e.preventDefault();
36386
- }
36387
- }
36388
- });
36389
36376
  }
36390
36377
  }
36391
36378
  if (mode === "popover") {
@@ -37257,7 +37244,7 @@ const createItemTracker = (onChange) => {
37257
37244
  const visibleItemsSignal = signal([]);
37258
37245
  const countSignal = signal(0);
37259
37246
  const visibleCountSignal = signal(0);
37260
- const matchCountSignal = signal(0);
37247
+ const noMatchCountSignal = signal(0);
37261
37248
 
37262
37249
  let notifyScheduled = false;
37263
37250
  const runNotify = () => {
@@ -37279,7 +37266,7 @@ const createItemTracker = (onChange) => {
37279
37266
  let visibleItemsChanged = false;
37280
37267
  const allItems = [];
37281
37268
  const visibleItems = [];
37282
- let newMatchCount = 0;
37269
+ let newNoMatchCount = 0;
37283
37270
  for (let i = 0; i < allOrderedKeys.length; i++) {
37284
37271
  const key = allOrderedKeys[i];
37285
37272
  const item = allRegistrations.get(key);
@@ -37288,12 +37275,12 @@ const createItemTracker = (onChange) => {
37288
37275
  if (!allItemsChanged && item !== prevAllItems[i]) {
37289
37276
  allItemsChanged = true;
37290
37277
  }
37291
- if (!item.filtered && !item.hidden) {
37278
+ if (item.match === false) {
37279
+ newNoMatchCount++;
37280
+ }
37281
+ if (!item.hidden) {
37292
37282
  const visibleIdx = visibleItems.length;
37293
37283
  visibleItems.push(item);
37294
- if (item.matchScore > 0) {
37295
- newMatchCount++;
37296
- }
37297
37284
  if (!visibleItemsChanged && item !== prevVisibleItems[visibleIdx]) {
37298
37285
  visibleItemsChanged = true;
37299
37286
  }
@@ -37315,9 +37302,9 @@ const createItemTracker = (onChange) => {
37315
37302
  visibleItemsSignal.value = visibleItems;
37316
37303
  someChange = true;
37317
37304
  }
37318
- const matchCountModified = matchCountSignal.peek() !== newMatchCount;
37319
- if (matchCountModified) {
37320
- matchCountSignal.value = newMatchCount;
37305
+ const noMatchCountModified = noMatchCountSignal.peek() !== newNoMatchCount;
37306
+ if (noMatchCountModified) {
37307
+ noMatchCountSignal.value = newNoMatchCount;
37321
37308
  someChange = true;
37322
37309
  }
37323
37310
  if (someChange) {
@@ -37516,7 +37503,7 @@ const createItemTracker = (onChange) => {
37516
37503
  visibleItemsSignal,
37517
37504
  countSignal,
37518
37505
  visibleCountSignal,
37519
- matchCountSignal,
37506
+ noMatchCountSignal,
37520
37507
  _flushSync,
37521
37508
  };
37522
37509
  };
@@ -37583,8 +37570,8 @@ installImportMetaCssBuild(import.meta);const css$n = /* css */`
37583
37570
  --list-item-outline-color: var(--navi-focus-outline-color);
37584
37571
  /* Focus outline end */
37585
37572
  --list-item-border-color: var(--navi-control-border-color);
37586
- --list-item-padding-x-default: var(--navi-control-padding-x-default);
37587
- --list-item-padding-y-default: var(--navi-control-padding-y-default);
37573
+ --list-item-padding-x-default: var(--navi-list-item-padding-x-default);
37574
+ --list-item-padding-y-default: var(--navi-list-item-padding-y-default);
37588
37575
 
37589
37576
  /* Hover (mouse) */
37590
37577
  --list-item-background-color-hover: light-dark(#f5f5f5, #2a2a2a);
@@ -37633,6 +37620,14 @@ installImportMetaCssBuild(import.meta);const css$n = /* css */`
37633
37620
  }
37634
37621
  }
37635
37622
 
37623
+ .navi_list_container[navi-selectable] {
37624
+ .navi_list_fallback,
37625
+ .navi_list_no_match_fallback {
37626
+ --list-item-padding-x-default: inherit;
37627
+ --list-item-padding-y-default: inherit;
37628
+ }
37629
+ }
37630
+
37636
37631
  .navi_list_item[navi-selectable] {
37637
37632
  --list-item-padding-x-default: inherit;
37638
37633
  --list-item-padding-y-default: inherit;
@@ -37642,6 +37637,13 @@ installImportMetaCssBuild(import.meta);const css$n = /* css */`
37642
37637
  outline-offset: var(--list-item-outline-offset);
37643
37638
  cursor: var(--x-list-item-cursor);
37644
37639
 
37640
+ .navi_checkbox {
37641
+ --margin: 0;
37642
+ }
37643
+ .navi_radio {
37644
+ --margin: 0;
37645
+ }
37646
+
37645
37647
  &[navi-selectable] {
37646
37648
  user-select: none;
37647
37649
  }
@@ -38253,6 +38255,11 @@ const applySearchHighlight = (el, highlight) => {
38253
38255
  installImportMetaCssBuild(import.meta);const ListItemTrackerContext = createContext(null);
38254
38256
  const GroupItemTrackerContext = createContext(null);
38255
38257
  const PendingScrollRefContext = createContext(null);
38258
+ // Controls how List.Item behaves when match=false (set via List searchNoMatchMode prop):
38259
+ // "remove" — remove from DOM (default)
38260
+ // "invisible_and_inert" — keep in DOM, invisible and non-interactive (preserves layout, no content visible)
38261
+ // "muted" — keep in DOM, visible but opacified and still interactive
38262
+ const SearchNoMatchModeContext = createContext("remove");
38256
38263
 
38257
38264
  // When total rendered items exceeds renderBudget, a render window [start, end)
38258
38265
  // is activated to cap the number of DOM nodes. Items outside the window return
@@ -38454,6 +38461,14 @@ const css$m = /* css */`
38454
38461
  scroll-margin-right: var(--x-list-scroll-spacing-right);
38455
38462
  scroll-margin-bottom: var(--x-list-scroll-spacing-bottom);
38456
38463
  scroll-margin-left: var(--x-list-scroll-spacing-left);
38464
+
38465
+ &[aria-hidden="true"] {
38466
+ opacity: 0;
38467
+ }
38468
+
38469
+ &[navi-muted] {
38470
+ opacity: 0.35;
38471
+ }
38457
38472
  }
38458
38473
 
38459
38474
  /* Virtual scroll fillers — must remain invisible.
@@ -38479,10 +38494,10 @@ const css$m = /* css */`
38479
38494
  Using order ensures fallbacks always appear after items regardless of DOM order.
38480
38495
  matchFallback intentionally shares the same order as fallback so it appears
38481
38496
  at the same visual position — after an input if present but before any items
38482
- still displayed (non-matching items remain in DOM with hidden prop):
38497
+ still displayed (non-matching items remain in DOM, invisible_and_inert or muted):
38483
38498
  1. Input (sticky header, order: -2)
38484
- 2. matchFallback (order: -1)
38485
- 3. hidden items (regular order, after DOM flow)
38499
+ 2. searchFallback (order: -1)
38500
+ 3. invisible/dim items (regular order, after DOM flow)
38486
38501
  4. HOT FIX OF THE DEAD for bottom filler + preact issue: order: 1
38487
38502
  5. sticky footer (order: 2)
38488
38503
  */
@@ -38496,12 +38511,39 @@ const css$m = /* css */`
38496
38511
  order: -2;
38497
38512
  }
38498
38513
  .navi_list_fallback,
38499
- .navi_list_no_match_fallback {
38514
+ .navi_list_search_fallback {
38500
38515
  order: -1;
38501
38516
  color: light-dark(#888, #aaa);
38502
38517
  &[navi-default] {
38503
38518
  display: inline;
38504
- padding: var(--list-item-padding);
38519
+ padding-top: var(
38520
+ --list-item-padding-top,
38521
+ var(
38522
+ --list-item-padding-y,
38523
+ var(--list-item-padding, var(--list-item-padding-y-default))
38524
+ )
38525
+ );
38526
+ padding-right: var(
38527
+ --list-item-padding-right,
38528
+ var(
38529
+ --list-item-padding-x,
38530
+ var(--list-item-padding, var(--list-item-padding-x-default))
38531
+ )
38532
+ );
38533
+ padding-bottom: var(
38534
+ --list-item-padding-bottom,
38535
+ var(
38536
+ --list-item-padding-y,
38537
+ var(--list-item-padding, var(--list-item-padding-y-default))
38538
+ )
38539
+ );
38540
+ padding-left: var(
38541
+ --list-item-padding-left,
38542
+ var(
38543
+ --list-item-padding-x,
38544
+ var(--list-item-padding, var(--list-item-padding-x-default))
38545
+ )
38546
+ );
38505
38547
  text-align: center;
38506
38548
  user-select: none;
38507
38549
  }
@@ -38575,37 +38617,6 @@ const css$m = /* css */`
38575
38617
  }
38576
38618
  }
38577
38619
  `;
38578
-
38579
- /**
38580
- * List — generic virtualized scroll container.
38581
- *
38582
- * Renders children inside a scrollable container with an optional render budget
38583
- * for virtual scrolling. Items must use <ListItem> to participate in tracking.
38584
- *
38585
- * Props:
38586
- * keyboardInteractions — when true, attaches arrow/enter/escape keyboard shortcuts
38587
- * that dispatch navi_list_nav / navi_list_confirm / navi_list_clear
38588
- * to the list container. Pair with uiAction for a full keyboard-
38589
- * navigable list.
38590
- * uiAction — called with the selected value on confirm. When provided
38591
- * the list becomes interactive: tracks hover and keyboard-
38592
- * pointed state, handles navi_list_nav / navi_list_clear /
38593
- * navi_list_confirm custom events via ListInteractionContext.
38594
- * popover — when true, renders as a managed popover positioned near
38595
- * an anchor element via navi_list_open / navi_list_close events.
38596
- * renderBudget — max items in DOM at once (default 100, virtual scroll when exceeded)
38597
- * virtualItemSize — fixed px size per item (width if horizontal, height otherwise) when all items have the same size.
38598
- * Enables precise virtual-scroll filler sizing without a DOM
38599
- * measurement pass. Required when renderBudget is active and
38600
- * item height is known up-front.
38601
- * fallback — content shown when no items exist at all
38602
- * matchFallback — content shown when items exist but all are hidden (e.g. no search match)
38603
- * separator — element or function(index, { previousItem, currentItem }) inserted between visible items
38604
- * lockSize — when true, captures the container's dimensions on first render
38605
- * (always in unfiltered state). Those values become min-width/
38606
- * min-height so filtering cannot collapse the layout.
38607
- * ...rest — forwarded to the outer scroll container <Box>
38608
- */
38609
38620
  const ListUI = props => {
38610
38621
  import.meta.css = [css$m, "@jsenv/navi/src/control/list/list.jsx"];
38611
38622
  const {
@@ -38614,7 +38625,7 @@ const ListUI = props => {
38614
38625
  renderBudgetSkipCheck,
38615
38626
  role,
38616
38627
  fallback,
38617
- noMatchFallback,
38628
+ searchFallback,
38618
38629
  separator,
38619
38630
  children,
38620
38631
  popover,
@@ -38625,6 +38636,7 @@ const ListUI = props => {
38625
38636
  virtualItemSize,
38626
38637
  lockSize,
38627
38638
  searchText,
38639
+ searchNoMatchMode = "remove",
38628
38640
  horizontal,
38629
38641
  spacing,
38630
38642
  ...rest
@@ -38714,8 +38726,8 @@ const ListUI = props => {
38714
38726
  children: jsx(ListContent, {
38715
38727
  role: role,
38716
38728
  fallback: fallback,
38717
- noMatchFallback: noMatchFallback,
38718
- searchText: searchText,
38729
+ searchFallback: searchFallback,
38730
+ searchNoMatchMode: searchNoMatchMode,
38719
38731
  separator: separator,
38720
38732
  expandX: expandX,
38721
38733
  expand: expand,
@@ -38739,12 +38751,39 @@ const ListFirstResolver = props => {
38739
38751
  ...props
38740
38752
  });
38741
38753
  };
38754
+
38755
+ /**
38756
+ * List — generic virtualized scroll container.
38757
+ * Items must use <List.Item> to participate in tracking.
38758
+ *
38759
+ * @type {import("ignore:preact").FunctionComponent<{
38760
+ * selectable?: boolean,
38761
+ * action?: (value: any) => void,
38762
+ * uiAction?: (value: any) => void,
38763
+ * popover?: boolean,
38764
+ * renderBudget?: number,
38765
+ * virtualItemSize?: number,
38766
+ * fallback?: import("ignore:preact").ComponentChildren,
38767
+ * searchFallback?: import("ignore:preact").ComponentChildren,
38768
+ * searchText?: string,
38769
+ * searchNoMatchMode?: "remove" | "invisible_and_inert" | "muted",
38770
+ * separator?: boolean | import("ignore:preact").ComponentChildren,
38771
+ * lockSize?: boolean,
38772
+ * horizontal?: boolean,
38773
+ * spacing?: string,
38774
+ * expandX?: boolean,
38775
+ * expand?: boolean,
38776
+ * maxHeight?: string | number,
38777
+ * children?: import("ignore:preact").ComponentChildren,
38778
+ * [key: string]: any,
38779
+ * }>}
38780
+ */
38742
38781
  const List = createComponentResolver([ListFirstResolver, ListSelectableResolver, ListUI]);
38743
38782
  const ListContent = ({
38744
38783
  role,
38745
38784
  fallback,
38746
- noMatchFallback,
38747
- searchText,
38785
+ searchFallback,
38786
+ searchNoMatchMode,
38748
38787
  separator,
38749
38788
  expandX,
38750
38789
  expand,
@@ -38762,8 +38801,8 @@ const ListContent = ({
38762
38801
  children: jsx(UnorderedList, {
38763
38802
  role: role,
38764
38803
  fallback: fallback,
38765
- noMatchFallback: noMatchFallback,
38766
- searchText: searchText,
38804
+ searchFallback: searchFallback,
38805
+ searchNoMatchMode: searchNoMatchMode,
38767
38806
  separator: separator === true ? jsx(Separator, {
38768
38807
  margin: "0"
38769
38808
  }) : separator,
@@ -39190,8 +39229,8 @@ const UnorderedList = ({
39190
39229
  renderWindow,
39191
39230
  virtualItemSizeSignal,
39192
39231
  fallback,
39193
- noMatchFallback,
39194
- searchText,
39232
+ searchFallback,
39233
+ searchNoMatchMode,
39195
39234
  separator,
39196
39235
  horizontal,
39197
39236
  spacing,
@@ -39208,20 +39247,22 @@ const UnorderedList = ({
39208
39247
  children: [jsx(BeforeFiller, {
39209
39248
  virtualItemSizeSignal: virtualItemSizeSignal,
39210
39249
  renderWindowStart: renderWindow.start
39211
- }), jsx(NoMatchFallback, {
39212
- noMatchFallback: noMatchFallback,
39213
- tracker: tracker,
39214
- searchText: searchText
39250
+ }), jsx(SearchFallback, {
39251
+ searchFallback: searchFallback,
39252
+ tracker: tracker
39215
39253
  }), jsx(Fallback, {
39216
39254
  fallback: fallback,
39217
39255
  tracker: tracker
39218
- }), jsx(RenderWindowContext.Provider, {
39219
- value: renderWindow,
39220
- children: jsx(SeparatorContext.Provider, {
39221
- value: separator ?? null,
39222
- children: jsx(ListItemTrackerContext.Provider, {
39223
- value: tracker,
39224
- children: children
39256
+ }), jsx(SearchNoMatchModeContext.Provider, {
39257
+ value: searchNoMatchMode,
39258
+ children: jsx(RenderWindowContext.Provider, {
39259
+ value: renderWindow,
39260
+ children: jsx(SeparatorContext.Provider, {
39261
+ value: separator ?? null,
39262
+ children: jsx(ListItemTrackerContext.Provider, {
39263
+ value: tracker,
39264
+ children: children
39265
+ })
39225
39266
  })
39226
39267
  })
39227
39268
  }), jsx(AfterFiller, {
@@ -39231,31 +39272,33 @@ const UnorderedList = ({
39231
39272
  })]
39232
39273
  });
39233
39274
  };
39234
- const NoMatchFallback = ({
39275
+
39276
+ // Show when all matchable items (those with a match prop) are non-matching.
39277
+ // The match prop on List.Item signals participation in a matching system
39278
+ // (search, filter, etc.). searchFallback appears when every such item has match=false.
39279
+ const SearchFallback = ({
39235
39280
  tracker,
39236
- noMatchFallback,
39237
- searchText
39281
+ searchFallback
39238
39282
  }) => {
39239
39283
  const itemCount = tracker.countSignal.value;
39240
- const visibleItemCount = tracker.visibleCountSignal.value;
39241
- const matchCount = tracker.matchCountSignal.value;
39242
- // Show when all items are filtered out (filtered prop), or when search is
39243
- // active but no visible item has a positive match score.
39244
- const allHidden = itemCount > 0 && visibleItemCount === 0;
39245
- const noneMatch = searchText && visibleItemCount > 0 && matchCount === 0;
39246
- const showMatchFallback = allHidden || noneMatch;
39247
- if (noMatchFallback === undefined) {
39248
- noMatchFallback = allHidden ? naviI18n("list.no_match") : naviI18n("list.no_match_rest_shown");
39284
+ const noMatchCount = tracker.noMatchCountSignal.value;
39285
+ const showMatchFallback = noMatchCount > 0 && noMatchCount === itemCount;
39286
+ if (searchFallback === undefined) {
39287
+ searchFallback = naviI18n("list.no_match");
39288
+ }
39289
+ if (!searchFallback) {
39290
+ // explicitely disabled by user (<List searchFallback={false|null|''}>)
39291
+ return null;
39249
39292
  }
39250
39293
  if (!showMatchFallback) {
39251
39294
  return null;
39252
39295
  }
39253
39296
  return jsx(ListItem, {
39254
39297
  role: "presentation",
39255
- className: "navi_list_item navi_list_no_match_fallback",
39298
+ className: "navi_list_item navi_list_search_fallback",
39256
39299
  hidden: !showMatchFallback,
39257
- "navi-default": typeof noMatchFallback === "string" ? "" : undefined,
39258
- children: noMatchFallback
39300
+ "navi-default": typeof searchFallback === "string" ? "" : undefined,
39301
+ children: searchFallback
39259
39302
  });
39260
39303
  };
39261
39304
  const Fallback = ({
@@ -39360,6 +39403,18 @@ const ListItemUI = props => {
39360
39403
  props.id = props.id || idDefault;
39361
39404
  const renderWindow = useContext(RenderWindowContext);
39362
39405
  const tracker = useContext(ListItemTrackerContext);
39406
+ const searchNoMatchMode = useContext(SearchNoMatchModeContext);
39407
+ // Derive filtered/hidden/nonMatching from the `match` prop + searchNoMatchMode context.
39408
+ // The `match` prop replaces the older `filtered`/`hidden` per-item props.
39409
+ if (props.match === false) {
39410
+ if (searchNoMatchMode === "remove") {
39411
+ props.filtered = true;
39412
+ } else if (searchNoMatchMode === "invisible_and_inert") {
39413
+ props.hidden = true;
39414
+ } else if (searchNoMatchMode === "muted") {
39415
+ props.muted = true;
39416
+ }
39417
+ }
39363
39418
  const item = props;
39364
39419
  const visibleIndex = tracker.useTrackItem(item);
39365
39420
  const groupTracker = useContext(GroupItemTrackerContext);
@@ -39419,6 +39474,7 @@ const ListItemReal = props => {
39419
39474
  ref,
39420
39475
  id,
39421
39476
  hidden,
39477
+ muted,
39422
39478
  highlight,
39423
39479
  children,
39424
39480
  ...rest
@@ -39451,7 +39507,15 @@ const ListItemReal = props => {
39451
39507
  index: undefined,
39452
39508
  selected: undefined,
39453
39509
  matchScore: undefined,
39454
- hidden: hidden,
39510
+ match: undefined
39511
+ // We use aria-hidden and not hidden because hidden would be forced to
39512
+ // display: none while here we want to keep it in the DOM to avoid layout shift
39513
+ // but visually hidden
39514
+ ,
39515
+
39516
+ "aria-hidden": hidden,
39517
+ inert: hidden ? true : undefined,
39518
+ "navi-muted": muted ? "" : undefined,
39455
39519
  ref: ref,
39456
39520
  children: children
39457
39521
  });