@jsenv/navi 0.28.2 → 0.28.4

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.
@@ -42278,9 +42278,10 @@ const css$p = /* css */`
42278
42278
  user-select: none;
42279
42279
  }
42280
42280
  }
42281
- /* Loading placeholders (see List's loading / loadingIndicator / skeletonTemplate).
42281
+ /* Loading placeholders (see List's loading / loadingFallback / loadingSkeletonTemplate).
42282
42282
  A skeleton row reuses <Text loading> for the shimmer bar; the loader row
42283
- centers a spinner. */
42283
+ centers a spinner; a custom loadingFallback is only given a row to live in,
42284
+ its own markup does the layout. */
42284
42285
  .navi_list_item_skeleton {
42285
42286
  pointer-events: none;
42286
42287
  }
@@ -42291,6 +42292,9 @@ const css$p = /* css */`
42291
42292
  justify-content: center;
42292
42293
  color: light-dark(#888, #aaa);
42293
42294
  }
42295
+ .navi_list_loading_fallback {
42296
+ display: flex;
42297
+ }
42294
42298
  /* Error state (List error prop): an inline callout describing why the list
42295
42299
  failed to load, shown in place of the items. */
42296
42300
  .navi_list_error {
@@ -42402,9 +42406,9 @@ const ListUI = props => {
42402
42406
  searchText,
42403
42407
  searchNoMatchMode = "remove",
42404
42408
  loading,
42405
- loadingIndicator = "skeleton",
42409
+ loadingFallback = "skeleton",
42406
42410
  loadingSkeletonCount = 3,
42407
- skeletonTemplate,
42411
+ loadingSkeletonTemplate,
42408
42412
  error,
42409
42413
  horizontal,
42410
42414
  spacing,
@@ -42495,9 +42499,8 @@ const ListUI = props => {
42495
42499
  const nothingToDisplay = !loading && !error && noVisibleItems && !searchFallbackShown && !emptyFallbackShown;
42496
42500
 
42497
42501
  // Placeholder content replaces the real children: an error message when the
42498
- // load failed (takes precedence), otherwise — while loading — skeleton rows
42499
- // (default, count loadingSkeletonCount, look skeletonTemplate) or a single
42500
- // centered loader when loadingIndicator="loader".
42502
+ // load failed (takes precedence), otherwise — while loading — whatever
42503
+ // loadingFallback asks for.
42501
42504
  let content = children;
42502
42505
  if (error) {
42503
42506
  content = jsxs(ListItem, {
@@ -42511,27 +42514,43 @@ const ListUI = props => {
42511
42514
  children: error === true ? "Something went wrong." : error
42512
42515
  })]
42513
42516
  });
42514
- } else if (loading) {
42515
- if (loadingIndicator === "loader") {
42516
- content = jsx(ListItem, {
42517
- role: "presentation",
42518
- "aria-hidden": "true",
42519
- baseClassName: "navi_list_item navi_list_loader",
42520
- children: jsx(LoadingIndicator, {})
42521
- });
42522
- } else {
42523
- const template = skeletonTemplate ?? jsx(ListItem, {
42517
+ } else if (loading && loadingFallback) {
42518
+ if (loadingFallback === "skeleton") {
42519
+ // Skeleton rows draw their own separators: they never reach ListItemUI
42520
+ // (where real items get theirs from SeparatorContext), and without them
42521
+ // the list would visibly gain its dividers only once loaded.
42522
+ const template = loadingSkeletonTemplate ?? jsx(ListItem, {
42524
42523
  skeleton: true
42525
42524
  });
42526
42525
  const skeletons = [];
42527
42526
  let skeletonIndex = 0;
42528
42527
  while (skeletonIndex < loadingSkeletonCount) {
42528
+ if (separator && skeletonIndex > 0) {
42529
+ skeletons.push(cloneElement(resolveSeparatorVnode(separator, skeletonIndex - 1), {
42530
+ key: `navi-list-skeleton-separator-${skeletonIndex}`
42531
+ }));
42532
+ }
42529
42533
  skeletons.push(cloneElement(template, {
42530
42534
  key: `navi-list-skeleton-${skeletonIndex}`
42531
42535
  }));
42532
42536
  skeletonIndex++;
42533
42537
  }
42534
42538
  content = skeletons;
42539
+ } else if (loadingFallback === "loader") {
42540
+ content = jsx(ListItem, {
42541
+ role: "presentation",
42542
+ "aria-hidden": "true",
42543
+ baseClassName: "navi_list_item navi_list_loader",
42544
+ children: jsx(LoadingIndicator, {})
42545
+ });
42546
+ } else {
42547
+ // Custom content is not aria-hidden (unlike the bare spinner): it usually
42548
+ // carries a message worth announcing.
42549
+ content = jsx(ListItem, {
42550
+ role: "presentation",
42551
+ baseClassName: "navi_list_item navi_list_loading_fallback",
42552
+ children: loadingFallback
42553
+ });
42535
42554
  }
42536
42555
  }
42537
42556
  return jsx(Box, {
@@ -42614,9 +42633,9 @@ const ListFirstResolver = props => {
42614
42633
  * searchText?: string,
42615
42634
  * searchNoMatchMode?: "remove" | "invisible_and_inert" | "muted" | "below",
42616
42635
  * loading?: boolean,
42617
- * loadingIndicator?: "skeleton" | "loader",
42636
+ * loadingFallback?: "skeleton" | "loader" | import("ignore:preact").ComponentChildren,
42618
42637
  * loadingSkeletonCount?: number,
42619
- * skeletonTemplate?: import("ignore:preact").ComponentChildren,
42638
+ * loadingSkeletonTemplate?: import("ignore:preact").ComponentChildren,
42620
42639
  * error?: boolean | import("ignore:preact").ComponentChildren,
42621
42640
  * separator?: boolean | import("ignore:preact").ComponentChildren,
42622
42641
  * lockSize?: boolean,
@@ -42629,6 +42648,11 @@ const ListFirstResolver = props => {
42629
42648
  * children?: import("ignore:preact").ComponentChildren,
42630
42649
  * [key: string]: any,
42631
42650
  * }>}
42651
+ * @param {"skeleton"|"loader"|import("ignore:preact").ComponentChildren} [props.loadingFallback="skeleton"]
42652
+ * What to display in place of the items while `loading`: `"skeleton"` renders
42653
+ * `loadingSkeletonCount` placeholder rows (look: `loadingSkeletonTemplate`),
42654
+ * `"loader"` a single centered spinner, and anything else is rendered as-is
42655
+ * in a row of its own. A falsy value displays nothing.
42632
42656
  */
42633
42657
  const List = createComponentResolver([ListFirstResolver, ListSelectableResolver, ListUI]);
42634
42658
  const ListContent = ({
@@ -42661,9 +42685,7 @@ const ListContent = ({
42661
42685
  loading: loading,
42662
42686
  error: error,
42663
42687
  searchNoMatchMode: searchNoMatchMode,
42664
- separator: separator === true ? jsx(Separator, {
42665
- margin: "0"
42666
- }) : separator,
42688
+ separator: separator,
42667
42689
  expandX: expandX
42668
42690
  // Deliberately not expandY here (unlike expandX above): the outer
42669
42691
  // .navi_list_container already gets its own expandY treatment (see
@@ -43376,7 +43398,7 @@ const ListItemPresentation = props => {
43376
43398
  // A <List.Item skeleton> — a non-interactive placeholder row shown while a list
43377
43399
  // is loading. It is presentation-only (not tracked, not selectable, aria-hidden)
43378
43400
  // and reuses <Text loading> for the shimmer. Box layout props (padding, spacing…)
43379
- // pass through so a skeletonTemplate can match the real items' metrics; and when
43401
+ // pass through so a loadingSkeletonTemplate can match the real items' metrics; and when
43380
43402
  // children are provided they render as-is, so a template can reproduce a
43381
43403
  // multi-part item (e.g. title + subtitle) out of several <Text loading> bars.
43382
43404
  const ListItemSkeletonResolver = props => {
@@ -43495,7 +43517,7 @@ const ListItemUI = props => {
43495
43517
  }
43496
43518
  // separatorIndex is only used as the function-form argument (gap index)
43497
43519
  const separatorIndex = groupVisibleIndex === null ? visibleIndex : groupVisibleIndex;
43498
- const separatorVnode = typeof separator === "function" ? separator(separatorIndex - 1) : separator;
43520
+ const separatorVnode = resolveSeparatorVnode(separator, separatorIndex - 1);
43499
43521
  return jsxs(Fragment$1, {
43500
43522
  children: [separatorVnode, listItemVnode]
43501
43523
  });
@@ -43617,7 +43639,7 @@ const LIST_ITEM_PSEUDO_ELEMENTS = ["::highlight"];
43617
43639
  * depending on whether the parent List has `multiple`). Requires
43618
43640
  * `value` and typically a <SelectableInput /> child.
43619
43641
  * skeleton — render a non-interactive placeholder row (a shimmering bar)
43620
- * instead of a real item. Used as the List `skeletonTemplate`
43642
+ * instead of a real item. Used as the List `loadingSkeletonTemplate`
43621
43643
  * while `loading`; Box layout props (padding…) pass through so the
43622
43644
  * placeholder can match the real items' metrics.
43623
43645
  * value — the JS value emitted by the list's action/uiAction when this item
@@ -43707,6 +43729,21 @@ const ListItemGroup = ({
43707
43729
  });
43708
43730
  };
43709
43731
 
43732
+ // The `separator` prop accepts `true` (the default divider), a vnode, or a
43733
+ // function receiving the gap index — this turns any of them into the vnode to
43734
+ // render at that gap.
43735
+ const resolveSeparatorVnode = (separator, gapIndex) => {
43736
+ if (separator === true) {
43737
+ return jsx(Separator, {
43738
+ margin: "0"
43739
+ });
43740
+ }
43741
+ if (typeof separator === "function") {
43742
+ return separator(gapIndex);
43743
+ }
43744
+ return separator;
43745
+ };
43746
+
43710
43747
  const PickerNaviTime = props => {
43711
43748
  const Next = useNextResolver();
43712
43749
  const {