@jsenv/navi 0.29.10 → 0.29.11

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.
@@ -9742,7 +9742,7 @@ const setupNetworkMonitoring = () => {
9742
9742
  };
9743
9743
  setupNetworkMonitoring();
9744
9744
 
9745
- installImportMetaCssBuild(import.meta);const css$X = /* css */`
9745
+ installImportMetaCssBuild(import.meta);const css$Y = /* css */`
9746
9746
  .navi_loading_indicator_fluid_container {
9747
9747
  position: relative;
9748
9748
  display: flex;
@@ -9774,7 +9774,7 @@ const LoadingIndicatorFluid = ({
9774
9774
  visuallyHidden,
9775
9775
  ...rest
9776
9776
  }) => {
9777
- import.meta.css = [css$X, "@jsenv/navi/src/graphic/loading/loading_indicator_fluid.jsx"];
9777
+ import.meta.css = [css$Y, "@jsenv/navi/src/graphic/loading/loading_indicator_fluid.jsx"];
9778
9778
  const ref = useRef(null);
9779
9779
  // The container dimensions can be deduced from the ref itself as the indicator is absolute inset 0
9780
9780
  const [containerWidth, setContainerWidth] = useState(0);
@@ -9979,7 +9979,7 @@ const LoadingRectangleSvg = ({
9979
9979
  });
9980
9980
  };
9981
9981
 
9982
- installImportMetaCssBuild(import.meta);const css$W = /* css */`
9982
+ installImportMetaCssBuild(import.meta);const css$X = /* css */`
9983
9983
  .navi_loading_outline_wrapper {
9984
9984
  position: absolute;
9985
9985
  /* Controls place the outline slightly outside their box, right on top of
@@ -10016,7 +10016,7 @@ installImportMetaCssBuild(import.meta);const css$W = /* css */`
10016
10016
  }
10017
10017
  `;
10018
10018
  const LoadingOutline = props => {
10019
- import.meta.css = [css$W, "@jsenv/navi/src/graphic/loading/loading_outline.jsx"];
10019
+ import.meta.css = [css$X, "@jsenv/navi/src/graphic/loading/loading_outline.jsx"];
10020
10020
  if (props.containerRef) {
10021
10021
  const container = props.containerRef.current;
10022
10022
  if (!container) {
@@ -10341,7 +10341,7 @@ const selectByTextStrings = (element, range, startText, endText) => {
10341
10341
  };
10342
10342
 
10343
10343
  installImportMetaCssBuild(import.meta);// https://jsfiddle.net/v5xzJ/4/
10344
- const css$V = /* css */`
10344
+ const css$W = /* css */`
10345
10345
  @layer navi {
10346
10346
  .navi_text {
10347
10347
  &[data-skeleton] {
@@ -10847,7 +10847,7 @@ const TextShrinkWrap = props => {
10847
10847
  });
10848
10848
  };
10849
10849
  const TextUI = props => {
10850
- import.meta.css = [css$V, "@jsenv/navi/src/text/text.jsx"];
10850
+ import.meta.css = [css$W, "@jsenv/navi/src/text/text.jsx"];
10851
10851
  let {
10852
10852
  ref,
10853
10853
  spacing,
@@ -13561,7 +13561,7 @@ installImportMetaCssBuild(import.meta);/**
13561
13561
  * - Arrow automatically shows when pointing at a valid anchor element
13562
13562
  * - Centers in viewport when no anchor element provided or anchor is too big
13563
13563
  */
13564
- const css$U = /* css */`
13564
+ const css$V = /* css */`
13565
13565
  @layer navi {
13566
13566
  .navi_callout {
13567
13567
  /* A callout is parented to what it explains, so it inherits from it — and
@@ -13781,7 +13781,7 @@ const openCallout = (message, {
13781
13781
  skipFocus = false,
13782
13782
  debug = () => {}
13783
13783
  } = {}) => {
13784
- import.meta.css = [css$U, "@jsenv/navi/src/control/rules/callout/callout.js"];
13784
+ import.meta.css = [css$V, "@jsenv/navi/src/control/rules/callout/callout.js"];
13785
13785
  if (debug === true) {
13786
13786
  debug = (e, ...args) => console.debug(`"${e.type}" -> `, ...args);
13787
13787
  }
@@ -22859,7 +22859,7 @@ const getAssociatedLabels = element => {
22859
22859
  return [];
22860
22860
  };
22861
22861
 
22862
- installImportMetaCssBuild(import.meta);const css$T = /* css */`
22862
+ installImportMetaCssBuild(import.meta);const css$U = /* css */`
22863
22863
  @layer navi {
22864
22864
  .navi_button {
22865
22865
  --button-border-radius: var(--navi-control-border-radius);
@@ -23252,7 +23252,7 @@ installImportMetaCssBuild(import.meta);const css$T = /* css */`
23252
23252
  }
23253
23253
  `;
23254
23254
  const ButtonUI = props => {
23255
- import.meta.css = [css$T, "@jsenv/navi/src/control/input/button_ui.jsx"];
23255
+ import.meta.css = [css$U, "@jsenv/navi/src/control/input/button_ui.jsx"];
23256
23256
  const {
23257
23257
  ref,
23258
23258
  // href/link
@@ -25380,7 +25380,7 @@ installImportMetaCssBuild(import.meta);/**
25380
25380
  * reaches the real container.
25381
25381
  */
25382
25382
  let openLocalDialogCount = 0;
25383
- const css$S = /* css */`
25383
+ const css$T = /* css */`
25384
25384
  @layer navi {
25385
25385
  .navi_dialog {
25386
25386
  /* Min gap between the dialog and the edges of its container. Written
@@ -25790,7 +25790,7 @@ const css$S = /* css */`
25790
25790
  * @param {import("ignore:preact").ComponentChildren} props.children
25791
25791
  */
25792
25792
  const Dialog = props => {
25793
- import.meta.css = [css$S, "@jsenv/navi/src/layout/dialog.jsx"];
25793
+ import.meta.css = [css$T, "@jsenv/navi/src/layout/dialog.jsx"];
25794
25794
  if (props.openController) {
25795
25795
  return jsx(ControlledDialog, {
25796
25796
  ...props
@@ -26608,7 +26608,7 @@ installImportMetaCssBuild(import.meta);/**
26608
26608
  * and applied.
26609
26609
  */
26610
26610
  let openLocalPopoverCount = 0;
26611
- const css$R = /* css */`
26611
+ const css$S = /* css */`
26612
26612
  @layer navi {
26613
26613
  .navi_popover {
26614
26614
  /* soft: user-configurable preferred max-height. Kept as a *default*
@@ -26978,7 +26978,7 @@ const css$R = /* css */`
26978
26978
  * @param {import("ignore:preact").ComponentChildren} props.children
26979
26979
  */
26980
26980
  const Popover = props => {
26981
- import.meta.css = [css$R, "@jsenv/navi/src/layout/popover.jsx"];
26981
+ import.meta.css = [css$S, "@jsenv/navi/src/layout/popover.jsx"];
26982
26982
  if (props.openController) {
26983
26983
  return jsx(ControlledPopover, {
26984
26984
  ...props
@@ -27942,7 +27942,7 @@ installImportMetaCssBuild(import.meta);/**
27942
27942
  * event, and a caller replacing the body entirely then has one protocol to
27943
27943
  * follow — `--navi-confirm` for yes, anything that closes for no.
27944
27944
  */
27945
- const css$Q = /* css */`
27945
+ const css$R = /* css */`
27946
27946
  /* The width lives on the body rather than on the popup, so that custom
27947
27947
  content (which replaces this body entirely) sizes itself instead of
27948
27948
  inheriting a ceiling meant for a sentence-long question. */
@@ -28079,7 +28079,7 @@ const ConfirmPopup = ({
28079
28079
  onAnswer,
28080
28080
  onClosed
28081
28081
  }) => {
28082
- import.meta.css = [css$Q, "@jsenv/navi/src/action/confirm_popup.jsx"];
28082
+ import.meta.css = [css$R, "@jsenv/navi/src/action/confirm_popup.jsx"];
28083
28083
  const {
28084
28084
  mode,
28085
28085
  confirmLabel,
@@ -28163,7 +28163,7 @@ const defaultBody = (message, {
28163
28163
  });
28164
28164
  };
28165
28165
 
28166
- installImportMetaCssBuild(import.meta);const css$P = /* css */`
28166
+ installImportMetaCssBuild(import.meta);const css$Q = /* css */`
28167
28167
  .action_error {
28168
28168
  margin-top: 0;
28169
28169
  margin-bottom: 20px;
@@ -28188,7 +28188,7 @@ const ActionRenderer = ({
28188
28188
  children,
28189
28189
  disabled
28190
28190
  }) => {
28191
- import.meta.css = [css$P, "@jsenv/navi/src/action/action_renderer.jsx"];
28191
+ import.meta.css = [css$Q, "@jsenv/navi/src/action/action_renderer.jsx"];
28192
28192
  if (action === undefined) {
28193
28193
  throw new Error("ActionRenderer requires an action to render, but none was provided.");
28194
28194
  }
@@ -35234,7 +35234,7 @@ const PhoneSvg = () => {
35234
35234
  };
35235
35235
 
35236
35236
  installImportMetaCssBuild(import.meta);// # TextAnchor — how it works
35237
- const css$O = /* css */`
35237
+ const css$P = /* css */`
35238
35238
  .navi_text_anchor {
35239
35239
  vertical-align: baseline;
35240
35240
  user-select: none;
@@ -35269,7 +35269,7 @@ const TextAnchor = ({
35269
35269
  textSize,
35270
35270
  lineLayout
35271
35271
  }) => {
35272
- import.meta.css = [css$O, "@jsenv/navi/src/text/text_anchor.jsx"];
35272
+ import.meta.css = [css$P, "@jsenv/navi/src/text/text_anchor.jsx"];
35273
35273
  const anchorRef = useRef();
35274
35274
 
35275
35275
  // Plain useLayoutEffect would also fire while an ancestor dialog/popover
@@ -35384,7 +35384,7 @@ const computeTopOffset = ({
35384
35384
  };
35385
35385
  const charTopCanvas = document.createElement("canvas");
35386
35386
 
35387
- installImportMetaCssBuild(import.meta);const css$N = /* css */`
35387
+ installImportMetaCssBuild(import.meta);const css$O = /* css */`
35388
35388
  @layer navi {
35389
35389
  /* Ensure data attributes from box.jsx can win to update display */
35390
35390
  .navi_icon {
@@ -35542,7 +35542,7 @@ const Icon = ({
35542
35542
  fillLine,
35543
35543
  ...props
35544
35544
  }) => {
35545
- import.meta.css = [css$N, "@jsenv/navi/src/text/icon.jsx"];
35545
+ import.meta.css = [css$O, "@jsenv/navi/src/text/icon.jsx"];
35546
35546
  const innerChildren = href ? jsx("svg", {
35547
35547
  width: "100%",
35548
35548
  height: "100%",
@@ -35695,7 +35695,7 @@ const useDimColorWhen = (elementRef, shouldDim) => {
35695
35695
  });
35696
35696
  };
35697
35697
 
35698
- installImportMetaCssBuild(import.meta);const css$M = /* css */`
35698
+ installImportMetaCssBuild(import.meta);const css$N = /* css */`
35699
35699
  @layer navi {
35700
35700
  .navi_link {
35701
35701
  --link-border-radius: unset;
@@ -36134,7 +36134,7 @@ Object.assign(PSEUDO_CLASSES, {
36134
36134
  * @param {boolean} [props.readOnly]
36135
36135
  */
36136
36136
  const Link = props => {
36137
- import.meta.css = [css$M, "@jsenv/navi/src/nav/link/link.jsx"];
36137
+ import.meta.css = [css$N, "@jsenv/navi/src/nav/link/link.jsx"];
36138
36138
  if (props.route) {
36139
36139
  return jsx(LinkWithRoute, {
36140
36140
  ...props
@@ -36369,7 +36369,7 @@ installImportMetaCssBuild(import.meta);/**
36369
36369
  * TabList component with support for horizontal and vertical layouts
36370
36370
  * https://dribbble.com/search/tabs
36371
36371
  */
36372
- const css$L = /* css */`
36372
+ const css$M = /* css */`
36373
36373
  @layer navi {
36374
36374
  .navi_nav {
36375
36375
  --nav-border: none;
@@ -36544,7 +36544,7 @@ const Nav = ({
36544
36544
  // "before" or "after": which side the panel sits on, turning the nav into folder tabs
36545
36545
  ...props
36546
36546
  }) => {
36547
- import.meta.css = [css$L, "@jsenv/navi/src/nav/link/nav.jsx"];
36547
+ import.meta.css = [css$M, "@jsenv/navi/src/nav/link/nav.jsx"];
36548
36548
  children = toChildArray(children);
36549
36549
  return jsx(Box, {
36550
36550
  as: "nav",
@@ -36936,7 +36936,7 @@ installImportMetaCssBuild(import.meta);/**
36936
36936
  * Border width participates in layout (it is added to the tab and page
36937
36937
  * padding): a thick border grows the binder rather than eating into the text.
36938
36938
  */
36939
- const css$K = /* css */`
36939
+ const css$L = /* css */`
36940
36940
  @layer navi {
36941
36941
  .navi_binder {
36942
36942
  --binder-border-width: var(--navi-control-border-width);
@@ -37249,7 +37249,7 @@ const Binder = ({
37249
37249
  pagePadding,
37250
37250
  ...props
37251
37251
  }) => {
37252
- import.meta.css = [css$K, "@jsenv/navi/src/nav/binder/binder.jsx"];
37252
+ import.meta.css = [css$L, "@jsenv/navi/src/nav/binder/binder.jsx"];
37253
37253
  const items = toChildArray(children).map((child, index) => {
37254
37254
  const {
37255
37255
  value: itemValue,
@@ -37671,7 +37671,7 @@ installImportMetaCssBuild(import.meta);/**
37671
37671
  * into the size; a box-shadow draws the identical line and stays out of
37672
37672
  * layout.
37673
37673
  */
37674
- const css$J = /* css */`
37674
+ const css$K = /* css */`
37675
37675
  @layer navi {
37676
37676
  :root {
37677
37677
  --navi-fixed-bar-width: 56px;
@@ -37809,7 +37809,7 @@ const FixedBar = ({
37809
37809
  border = true,
37810
37810
  ...props
37811
37811
  }) => {
37812
- import.meta.css = [css$J, "@jsenv/navi/src/layout/fixed_bar/fixed_bar.jsx"];
37812
+ import.meta.css = [css$K, "@jsenv/navi/src/layout/fixed_bar/fixed_bar.jsx"];
37813
37813
  const defaultRef = useRef();
37814
37814
  props.ref = props.ref || defaultRef;
37815
37815
  // Whichever of width/height crosses the edge the bar sits on is what the
@@ -37846,6 +37846,178 @@ const FixedBar = ({
37846
37846
  });
37847
37847
  };
37848
37848
 
37849
+ /**
37850
+ * Finds the element that is too wide for the page and says which one it is.
37851
+ *
37852
+ * A page that overflows horizontally is a bug wherever it happens, and on
37853
+ * Chrome Android it is a catastrophic one: the layout viewport inflates to the
37854
+ * content and `position: fixed` centering goes with it (see
37855
+ * docs/MOBILE_LAYOUT_PITFALLS.md). The remedy there is a wrapper in
37856
+ * `overflow-x: clip`, and it works — at the price of making the cause
37857
+ * invisible: nothing sticks out anymore, so nothing says a fixed width, a
37858
+ * `min-width` or an unbreakable string is still oversized. This puts the
37859
+ * signal back, without giving up the net.
37860
+ *
37861
+ * What counts as "too wide" is measured against the box that clips, not
37862
+ * against the document: with `clip` there is no scrollable overflow to read
37863
+ * (`scrollWidth` reports none), so the rectangles of the descendants are what
37864
+ * tells.
37865
+ *
37866
+ * Two things are deliberately not reported, because they cannot reach the
37867
+ * document:
37868
+ * - anything inside a box that clips or scrolls on its own — a wide table in
37869
+ * its `overflow-x: auto` container is doing exactly what it should;
37870
+ * - anything out of flow in the viewport's own coordinates (`position: fixed`,
37871
+ * the top layer), which contributes nothing to the document's overflow.
37872
+ */
37873
+
37874
+
37875
+ // Subpixel layout rounds rectangles up on boxes that fit exactly.
37876
+ const OVERFLOW_TOLERANCE = 1;
37877
+
37878
+ const css$J = /* css */ `
37879
+ [data-navi-overflow-x] {
37880
+ outline: 2px dashed #e74c3c;
37881
+ outline-offset: -2px;
37882
+ }
37883
+ `;
37884
+
37885
+ /**
37886
+ * @param {object} [options]
37887
+ * @param {Element} [options.root=document.body] The box the content must fit
37888
+ * in — the wrapper carrying `overflow-x: clip`, when there is one.
37889
+ * @param {boolean} [options.highlight=true] Outline the culprits on screen.
37890
+ * @param {(overflows: Array<{element: Element, overflow: number, side: "left"|"right"}>) => void} [options.onDetect]
37891
+ * Replaces the default console warning.
37892
+ * @returns {() => void} Stops watching.
37893
+ */
37894
+ const detectHorizontalOverflow = ({
37895
+ root = document.body,
37896
+ highlight = true,
37897
+ onDetect = warnOverflows,
37898
+ } = {}) => {
37899
+ let styleEl = null;
37900
+ if (highlight) {
37901
+ styleEl = document.createElement("style");
37902
+ styleEl.textContent = css$J;
37903
+ document.head.appendChild(styleEl);
37904
+ }
37905
+
37906
+ let highlightedSet = new Set();
37907
+ const detect = () => {
37908
+ const overflows = findOverflows(root);
37909
+ if (highlight) {
37910
+ const nextHighlightedSet = new Set();
37911
+ for (const { element } of overflows) {
37912
+ element.setAttribute("data-navi-overflow-x", "");
37913
+ nextHighlightedSet.add(element);
37914
+ }
37915
+ for (const element of highlightedSet) {
37916
+ if (!nextHighlightedSet.has(element)) {
37917
+ element.removeAttribute("data-navi-overflow-x");
37918
+ }
37919
+ }
37920
+ highlightedSet = nextHighlightedSet;
37921
+ }
37922
+ if (overflows.length) {
37923
+ onDetect(overflows);
37924
+ }
37925
+ };
37926
+
37927
+ // Measuring inside a resize callback is what makes the loop; wait for the
37928
+ // frame that resize produced.
37929
+ let frame = null;
37930
+ const requestDetect = () => {
37931
+ if (frame !== null) {
37932
+ return;
37933
+ }
37934
+ frame = requestAnimationFrame(() => {
37935
+ frame = null;
37936
+ detect();
37937
+ });
37938
+ };
37939
+
37940
+ // Resize catches the window narrowing and the content growing (the root gets
37941
+ // taller); mutations catch a wide element arriving without changing the
37942
+ // root's size.
37943
+ const resizeObserver = new ResizeObserver(requestDetect);
37944
+ resizeObserver.observe(root);
37945
+ const mutationObserver = new MutationObserver(requestDetect);
37946
+ mutationObserver.observe(root, { subtree: true, childList: true });
37947
+ requestDetect();
37948
+
37949
+ return () => {
37950
+ resizeObserver.disconnect();
37951
+ mutationObserver.disconnect();
37952
+ if (frame !== null) {
37953
+ cancelAnimationFrame(frame);
37954
+ frame = null;
37955
+ }
37956
+ for (const element of highlightedSet) {
37957
+ element.removeAttribute("data-navi-overflow-x");
37958
+ }
37959
+ highlightedSet.clear();
37960
+ if (styleEl) {
37961
+ styleEl.remove();
37962
+ }
37963
+ };
37964
+ };
37965
+
37966
+ const warnOverflows = (overflows) => {
37967
+ for (const { element, overflow, side } of overflows) {
37968
+ console.warn(
37969
+ `${getElementSignature(element)} overflows the page by ${Math.round(
37970
+ overflow,
37971
+ )}px on the ${side}. Look for a width in px, a min-width, or an unbreakable string; if it is meant to be wider than the screen, give it its own "overflow-x: auto".`,
37972
+ element,
37973
+ );
37974
+ }
37975
+ };
37976
+
37977
+ const findOverflows = (root) => {
37978
+ const rootRect = root.getBoundingClientRect();
37979
+ const rootStyle = getComputedStyle(root);
37980
+ // Only the end side is watched: what sticks out there is what the document
37981
+ // grows to hold, and what inflates the layout viewport. Past the start edge
37982
+ // the content is simply unreachable, and that is where the offscreen
37983
+ // patterns (a label parked at `left: -9999px`) live.
37984
+ const side = rootStyle.direction === "rtl" ? "left" : "right";
37985
+ const overflows = [];
37986
+ const collect = (parentEl) => {
37987
+ for (const el of parentEl.children) {
37988
+ const style = getComputedStyle(el);
37989
+ if (style.display === "none" || style.position === "fixed") {
37990
+ continue;
37991
+ }
37992
+ if (el.hasAttribute("popover") || el.tagName === "DIALOG") {
37993
+ continue;
37994
+ }
37995
+ const rect = el.getBoundingClientRect();
37996
+ if (rect.width === 0 && rect.height === 0) {
37997
+ continue;
37998
+ }
37999
+ const overflow =
38000
+ side === "right"
38001
+ ? rect.right - rootRect.right
38002
+ : rootRect.left - rect.left;
38003
+ if (overflow > OVERFLOW_TOLERANCE) {
38004
+ // The outermost box that sticks out is the one to fix; its children
38005
+ // stick out because it does.
38006
+ overflows.push({ element: el, overflow, side });
38007
+ continue;
38008
+ }
38009
+ // A box holding its own horizontal overflow cannot leak into the page,
38010
+ // whatever it holds — a wide table in its own scroll box is right.
38011
+ if (style.overflowX !== "visible") {
38012
+ continue;
38013
+ }
38014
+ collect(el);
38015
+ }
38016
+ };
38017
+ collect(root);
38018
+ return overflows;
38019
+ };
38020
+
37849
38021
  const useFocusGroup = (
37850
38022
  elementRef,
37851
38023
  {
@@ -47048,7 +47220,7 @@ const css$u = /* css */`
47048
47220
  around it does. Its own scroll box must then be transparent to
47049
47221
  layout — otherwise it would cap the list at a height of its own and
47050
47222
  start a second, nested scroll inside the page's. */
47051
- &[data-scroller="parent"] {
47223
+ &[data-scroller] {
47052
47224
  max-height: none;
47053
47225
  overflow: visible;
47054
47226
 
@@ -47058,6 +47230,14 @@ const css$u = /* css */`
47058
47230
  }
47059
47231
  }
47060
47232
 
47233
+ /* Scrolling with the page means sticking to the viewport, and a FixedBar
47234
+ is in front of that viewport: without the offset a sticky label lands
47235
+ behind the bar. The bar publishes the room it takes (see
47236
+ fixed_bar_space.js) and it is 0px when there is no bar. */
47237
+ &[data-scroller="document"] {
47238
+ --x-list-group-label-top: var(--navi-fixed-bar-space-top, 0px);
47239
+ }
47240
+
47061
47241
  &[data-expand-x] {
47062
47242
  width: 100%;
47063
47243
  }
@@ -47416,7 +47596,7 @@ const css$u = /* css */`
47416
47596
 
47417
47597
  .navi_list_item_group_label {
47418
47598
  position: sticky;
47419
- top: 0;
47599
+ top: var(--list-group-label-top, var(--x-list-group-label-top, 0px));
47420
47600
  z-index: 1;
47421
47601
  display: block;
47422
47602
  background-color: var(--list-group-label-background-color);
@@ -47659,7 +47839,7 @@ const ListUI = props => {
47659
47839
  baseClassName: "navi_list_container",
47660
47840
  popover: popover,
47661
47841
  "data-horizontal": horizontal ? "" : undefined,
47662
- "data-scroller": scroller === "self" ? undefined : "parent",
47842
+ "data-scroller": getScrollerAttribute(scroller),
47663
47843
  "data-expand-x": expandX || expand ? "" : undefined,
47664
47844
  "data-expand-y": expandY || expand ? "" : undefined,
47665
47845
  expandX: expandX,
@@ -47918,6 +48098,7 @@ const useListScrollSync = ({
47918
48098
  setScrollerElResolved(current => current === scrollerElNow ? current : scrollerElNow);
47919
48099
  };
47920
48100
  useLayoutEffect(resolveScroller);
48101
+ useStickyScrollportWarning();
47921
48102
 
47922
48103
  // The row the scroll holds onto across a change of geometry, and where it
47923
48104
  // sat when that change was decided. Captured at the two moments the list
@@ -48695,6 +48876,28 @@ const getScrollerViewportRect = scrollerEl => {
48695
48876
  }
48696
48877
  return scrollerEl.getBoundingClientRect();
48697
48878
  };
48879
+ const useStickyScrollportWarning = (ref, scroller) => {
48880
+ useRef(false);
48881
+ useLayoutEffect(() => {
48882
+ {
48883
+ return;
48884
+ }
48885
+ });
48886
+ };
48887
+
48888
+ // The CSS needs to tell "the page scrolls me" from "some box around me
48889
+ // scrolls me": only the first one sticks to the viewport, where the fixed bars
48890
+ // are.
48891
+ const getScrollerAttribute = scroller => {
48892
+ if (scroller === "self") {
48893
+ return undefined;
48894
+ }
48895
+ if (scroller === "document") {
48896
+ return "document";
48897
+ }
48898
+ return "parent";
48899
+ };
48900
+
48698
48901
  // scroller="parent": the list virtualizes against the scroll box it lives in
48699
48902
  // instead of one of its own. Which box that is can only be measured, and a
48700
48903
  // measurement holds for the geometry it was taken on — see resolveScroller in
@@ -62783,5 +62986,5 @@ const UserSvg = () => jsx("svg", {
62783
62986
  })
62784
62987
  });
62785
62988
 
62786
- export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, InputDuration, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, ListItems, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, NumberSpin, Paragraph, Picker, Popover, Popup, Quantity, RadioGroup, Route, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, coarsePointerSignal, compareTwoJsValues, createAction, createAvailableConstraint, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineNaviConfirmPopupOptions, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isToday, languagesSignal, localStorageSignal, moveArrayItemByIndex, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, setBaseUrl, setPreferredLanguage, setSupportedLanguages, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutRequestClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useInputGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, usePopupMode, useRouteStatus, useRunOnMount, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideValue, useStateArray, useTitleLevel, useUrlSearchParam, valueInLocalStorage, windowWidthSignal };
62989
+ export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Binder, Box, Button, ButtonCopyToClipboard, Caption, CardLayout, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, ControlGroup, DaySpin, Details, Dialog, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Field, FixedBar, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, InputDuration, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, ListItems, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, NumberSpin, Paragraph, Picker, Popover, Popup, Quantity, RadioGroup, Route, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, Slide, SlideContainer, Spin, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Textarea, TextareaCharCount, Thead, Time, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, Wheel, WheelGroup, WheelItem, actionRunEffect, anyMatchingRouteSignal, applySearch, arraySignalMembership, coarsePointerSignal, compareTwoJsValues, createAction, createAvailableConstraint, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, createSlot, defineNaviConfirmPopupOptions, detectHorizontalOverflow, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isToday, languagesSignal, localStorageSignal, moveArrayItemByIndex, navBack, navForward, navIntegratedVia, navTo, naviI18n, openCallout, rawUrlPart, registerGlobalConstraint, reload, rerunActions, resource, route, routeAction, setBaseUrl, setPreferredLanguage, setSupportedLanguages, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutRequestClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useInputGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, usePopupMode, useRouteStatus, useRunOnMount, useSearchText, useSelectableElement, useSelectionController, useSignalSync, useSlideValue, useStateArray, useTitleLevel, useUrlSearchParam, valueInLocalStorage, windowWidthSignal };
62787
62990
  //# sourceMappingURL=jsenv_navi.js.map