@jsenv/navi 0.26.19 → 0.26.21

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.
@@ -1,5 +1,5 @@
1
1
  import { installImportMetaCssBuild } from "./jsenv_navi_side_effects.js";
2
- import { isValidElement, createContext, h, options, toChildArray, render, cloneElement } from "preact";
2
+ import { isValidElement, createContext, h, toChildArray, render, cloneElement } from "preact";
3
3
  import { useErrorBoundary, useLayoutEffect, useEffect, useContext, useMemo, useRef, useState, useCallback, useImperativeHandle, useId } from "preact/hooks";
4
4
  import { jsxs, jsx, Fragment } from "preact/jsx-runtime";
5
5
  import { signal, effect, computed, batch, useSignal } from "@preact/signals";
@@ -6612,6 +6612,7 @@ const VISUAL_PROPS = {
6612
6612
  overflowWrap: "normal",
6613
6613
  };
6614
6614
  },
6615
+ objectFit: PASS_THROUGH,
6615
6616
  accentColor: PASS_THROUGH,
6616
6617
  };
6617
6618
  const CONTENT_PROPS = {
@@ -8041,72 +8042,42 @@ const updateStyle = (element, style, preventInitialTransition) => {
8041
8042
  styleKeySetWeakMap.set(element, styleKeySet);
8042
8043
  };
8043
8044
 
8044
- // Implementation notes:
8045
- //
8046
- // options.__r fires before each component render — we capture the current
8047
- // component instance (vnode.__c) so useEarlyDOMEffect can register itself.
8048
- //
8049
- // options.__c (commitRoot) fires after refs are assigned and before any
8050
- // useLayoutEffect runs. We flush all pending effects there.
8051
- // The DOM node is read from component.__v.__e (vnode → root DOM node),
8052
- // which Preact sets during diffing, before options.__c fires.
8053
- //
8054
- // stateMap (WeakMap) stores { cleanup, deps } per component instance.
8055
- // It's auto-GC'd when a component is destroyed; options.unmount also
8056
- // deletes entries eagerly to release cleanup functions sooner.
8057
- //
8058
- // pendingMap (Map) holds effects registered during the current render pass.
8059
- // It is always fully cleared in options.__c — bounded to one commit, no leak.
8060
-
8061
8045
  /**
8062
- * Like useLayoutEffect, but runs before any layout effect in the commit —
8063
- * including those of descendant components.
8064
- *
8065
- * Use this when a parent needs to mutate the DOM (e.g. apply styles) so that
8066
- * children can read those mutations in their own useLayoutEffect.
8067
- *
8068
- * The DOM node of the component is passed as the first argument to fn.
8069
- * The effect is skipped if no DOM node is found (e.g. on a fragment root).
8070
- *
8071
- * Supports deps and cleanup return, same as useLayoutEffect.
8046
+ * Keeps a DOM element in sync with `syncElement(el)` whenever deps change.
8047
+ * - If element is already mounted: runs syncElement immediately during render.
8048
+ * - If not yet mounted: runs syncElement in the ref callback when element arrives.
8049
+ * - Calls cleanup (if returned by syncElement) before each re-run and on unmount.
8050
+ *
8051
+ * @param {function|object|null} externalRef - Optional ref to forward to
8052
+ * @param {function} syncElement - Called with the DOM element when deps change
8053
+ * @param {Array} deps - syncElement is re-called only when deps change
8072
8054
  */
8073
- const useEarlyDOMEffect = (fn, deps, { needDOMNode = true } = {}) => {
8074
- const component = _currentComponent;
8075
- if (component) {
8076
- pendingMap.set(component, { fn, deps, needDOMNode });
8077
- }
8078
- };
8079
-
8080
- // Populated during render, consumed + cleared in options.__c each commit.
8081
- const pendingMap = new Map(); // component → { fn, deps, ref }
8055
+ const useElementRefEffect = (externalRef, syncElement, deps) => {
8056
+ const cleanupRef = useRef(null);
8057
+ const elRef = useRef(null);
8058
+ const prevDepsRef = useRef(undefined);
8059
+ const refCallbackRef = useRef(null);
8082
8060
 
8083
- // Persists across commits. WeakMap → no leak when component is destroyed.
8084
- const stateMap = new WeakMap(); // component → { cleanup, deps }
8085
-
8086
- let _currentComponent = null;
8087
- const _prevBeforeRender = options.__r;
8088
- options.__r = (vnode) => {
8089
- _currentComponent = vnode.__c;
8090
- if (_prevBeforeRender) {
8091
- _prevBeforeRender(vnode);
8092
- }
8093
- };
8094
-
8095
- const _prevCommit = options.__c;
8096
- options.__c = (root, commitQueue) => {
8097
- for (const [component, { fn, deps, needDOMNode }] of pendingMap) {
8098
- // component.__v is the component's vnode; __e is its root DOM node.
8099
- // Both are set during diff, before options.__c fires.
8100
- const element = component.__v && component.__v.__e;
8101
- if (needDOMNode && !element) {
8102
- continue;
8061
+ const runSync = (el) => {
8062
+ if (cleanupRef.current) {
8063
+ cleanupRef.current();
8064
+ cleanupRef.current = null;
8065
+ }
8066
+ prevDepsRef.current = deps;
8067
+ const cleanup = syncElement(el);
8068
+ if (typeof cleanup === "function") {
8069
+ cleanupRef.current = cleanup;
8103
8070
  }
8104
- const prev = stateMap.get(component);
8105
- const prevDeps = prev ? prev.deps : undefined;
8071
+ };
8072
+
8073
+ // If element already mounted, check deps and sync during render.
8074
+ if (elRef.current) {
8075
+ const prevDeps = prevDepsRef.current;
8106
8076
  let depsChanged;
8107
- if (!prevDeps || !deps || prevDeps.length !== deps.length) {
8077
+ if (!prevDeps || prevDeps.length !== deps.length) {
8108
8078
  depsChanged = true;
8109
8079
  } else {
8080
+ depsChanged = false;
8110
8081
  for (let i = 0; i < deps.length; i++) {
8111
8082
  if (!Object.is(deps[i], prevDeps[i])) {
8112
8083
  depsChanged = true;
@@ -8115,35 +8086,35 @@ options.__c = (root, commitQueue) => {
8115
8086
  }
8116
8087
  }
8117
8088
  if (depsChanged) {
8118
- if (prev && prev.cleanup) {
8119
- prev.cleanup();
8120
- }
8121
- const result = fn(element);
8122
- const cleanup = typeof result === "function" ? result : undefined;
8123
- stateMap.set(component, { cleanup, deps });
8089
+ runSync(elRef.current);
8124
8090
  }
8125
8091
  }
8126
- pendingMap.clear();
8127
- if (_prevCommit) {
8128
- _prevCommit(root, commitQueue);
8129
- }
8130
- };
8131
8092
 
8132
- const _prevUnmount = options.unmount;
8133
- options.unmount = (vnode) => {
8134
- const component = vnode.__c;
8135
- if (component) {
8136
- const state = stateMap.get(component);
8137
- if (state && state.cleanup) {
8138
- state.cleanup();
8139
- }
8140
- // stateMap is a WeakMap so the entry is GC'd automatically,
8141
- // but deleting explicitly releases the cleanup fn sooner.
8142
- stateMap.delete(component);
8143
- }
8144
- if (_prevUnmount) {
8145
- _prevUnmount(vnode);
8093
+ if (!refCallbackRef.current) {
8094
+ refCallbackRef.current = (el) => {
8095
+ elRef.current = el;
8096
+ if (externalRef) {
8097
+ if (typeof externalRef === "function") {
8098
+ externalRef(el);
8099
+ } else {
8100
+ externalRef.current = el;
8101
+ }
8102
+ }
8103
+ if (el) {
8104
+ runSync(el);
8105
+ } else {
8106
+ if (cleanupRef.current) {
8107
+ cleanupRef.current();
8108
+ cleanupRef.current = null;
8109
+ }
8110
+ prevDepsRef.current = undefined;
8111
+ }
8112
+ };
8146
8113
  }
8114
+
8115
+ const refCallback = refCallbackRef.current;
8116
+ refCallback.current = elRef.current;
8117
+ return refCallback;
8147
8118
  };
8148
8119
 
8149
8120
  installImportMetaCssBuild(import.meta);/**
@@ -8323,8 +8294,7 @@ const Box = props => {
8323
8294
  separator,
8324
8295
  ...rest
8325
8296
  } = props;
8326
- const defaultRef = useRef();
8327
- const ref = props.ref || defaultRef;
8297
+ let ref;
8328
8298
  const TagName = as;
8329
8299
  const defaultDisplay = getDefaultDisplay(TagName);
8330
8300
  // Read the parent flow early so we can use it when display="inherit" is requested.
@@ -8677,9 +8647,7 @@ const Box = props => {
8677
8647
  styleDeps.push(...pseudoClasses);
8678
8648
  }
8679
8649
  }
8680
- // TODO: just use ref function, it will be called same time as early dom effect + give the dom node + be standard
8681
- // we need to implent our styleDeps tracking but that's likely very easy
8682
- useEarlyDOMEffect(boxEl => {
8650
+ ref = useElementRefEffect(props.ref, boxEl => {
8683
8651
  const pseudoStateEl = pseudoStateSelector ? boxEl.querySelector(pseudoStateSelector) : boxEl;
8684
8652
  const visualEl = visualSelector ? boxEl.querySelector(visualSelector) : null;
8685
8653
  return initPseudoStyles(pseudoStateEl, {
@@ -16336,7 +16304,7 @@ installImportMetaCssBuild(import.meta);
16336
16304
  * - Centers in viewport when no anchor element provided or anchor is too big
16337
16305
  */
16338
16306
 
16339
- const css$B = /* css */`
16307
+ const css$E = /* css */`
16340
16308
  @layer navi {
16341
16309
  .navi_callout {
16342
16310
  --callout-success-color: #4caf50;
@@ -16510,7 +16478,7 @@ const openCallout = (message, {
16510
16478
  showErrorStack,
16511
16479
  debug = false
16512
16480
  } = {}) => {
16513
- import.meta.css = [css$B, "@jsenv/navi/src/field/validation/callout/callout.js"];
16481
+ import.meta.css = [css$E, "@jsenv/navi/src/field/validation/callout/callout.js"];
16514
16482
  const callout = {
16515
16483
  opened: true,
16516
16484
  close: null,
@@ -19636,53 +19604,55 @@ const setupNetworkMonitoring = () => {
19636
19604
  };
19637
19605
  setupNetworkMonitoring();
19638
19606
 
19639
- installImportMetaCssBuild(import.meta);/**
19640
- * RectangleLoading Component
19641
- *
19642
- * A responsive loading indicator that dynamically adjusts to fit its container.
19643
- * Displays an animated outline with a traveling dot that follows the container's shape.
19644
- *
19645
- * Features:
19646
- * - Adapts to any container dimensions using ResizeObserver
19647
- * - Scales stroke width, margins and corner radius proportionally
19648
- * - Animates using native SVG animations for smooth performance
19649
- * - High-quality SVG rendering with proper path calculations
19650
- *
19651
- * @param {Object} props - Component props
19652
- * @param {string} [props.color="#383a36"] - Color of the loading indicator
19653
- * @param {number} [props.radius=0] - Corner radius of the rectangle (px)
19654
- */
19655
- import.meta.css = [/* css */`
19656
- .navi_rectangle_loading {
19607
+ installImportMetaCssBuild(import.meta);const css$D = /* css */`
19608
+ .navi_loading_indicator_fluid_container {
19657
19609
  position: relative;
19658
19610
  display: flex;
19659
19611
  width: 100%;
19660
19612
  height: 100%;
19661
- opacity: 0;
19662
- }
19663
-
19664
- .navi_rectangle_loading[data-visible] {
19613
+ border-radius: inherit;
19665
19614
  opacity: 1;
19615
+
19616
+ &[hidden] {
19617
+ display: flex;
19618
+ opacity: 0;
19619
+ }
19666
19620
  }
19667
- `, "@jsenv/navi/src/graphic/loader/rectangle_loading.jsx"];
19668
- const RectangleLoading = ({
19669
- shouldShowSpinner,
19621
+ `;
19622
+
19623
+ /**
19624
+ * A loading indicator that fills its container, adapting to its shape like water.
19625
+ * Reads border-radius from the container (or accepts an explicit `radius` prop).
19626
+ *
19627
+ * @param {string} [props.color="currentColor"] - Stroke color
19628
+ * @param {number|"inherit"} [props.radius] - Corner radius in px. When omitted, reads border-radius from the container.
19629
+ * @param {number} [props.size=2] - Stroke width in px
19630
+ */
19631
+ const LoadingIndicatorFluid = ({
19670
19632
  color = "currentColor",
19671
- radius = 0,
19672
- size = 2
19633
+ size = 2,
19634
+ radius,
19635
+ ...rest
19673
19636
  }) => {
19674
- const containerRef = useRef(null);
19637
+ import.meta.css = [css$D, "@jsenv/navi/src/graphic/loading/loading_indicator_fluid.jsx"];
19638
+ const ref = useRef(null);
19639
+ // The container dimensions can be deduced from the ref itself as the indicator is absolute inset 0
19675
19640
  const [containerWidth, setContainerWidth] = useState(0);
19676
19641
  const [containerHeight, setContainerHeight] = useState(0);
19642
+ const [containerRadius, setContainerRadius] = useState(0);
19677
19643
  useLayoutEffect(() => {
19678
- const container = containerRef.current;
19679
- if (!container) {
19644
+ const indicatorEl = ref.current;
19645
+ if (!indicatorEl) {
19680
19646
  return null;
19681
19647
  }
19648
+ if (radius === undefined || radius === "inherit") {
19649
+ const radius = getComputedStyle(indicatorEl).borderRadius;
19650
+ setContainerRadius(radius);
19651
+ }
19682
19652
  const {
19683
19653
  width,
19684
19654
  height
19685
- } = container.getBoundingClientRect();
19655
+ } = indicatorEl.getBoundingClientRect();
19686
19656
  setContainerWidth(width);
19687
19657
  setContainerHeight(height);
19688
19658
  let animationFrameId = null;
@@ -19702,7 +19672,7 @@ const RectangleLoading = ({
19702
19672
  setContainerHeight(height);
19703
19673
  });
19704
19674
  });
19705
- resizeObserver.observe(container);
19675
+ resizeObserver.observe(indicatorEl);
19706
19676
  return () => {
19707
19677
  if (animationFrameId) {
19708
19678
  cancelAnimationFrame(animationFrameId);
@@ -19711,19 +19681,19 @@ const RectangleLoading = ({
19711
19681
  };
19712
19682
  }, []);
19713
19683
  return jsx("span", {
19714
- ref: containerRef,
19715
- className: "navi_rectangle_loading",
19716
- "data-visible": shouldShowSpinner ? "" : undefined,
19717
- children: containerWidth > 0 && containerHeight > 0 && jsx(RectangleLoadingSvg, {
19718
- radius: radius,
19684
+ ...rest,
19685
+ ref: ref,
19686
+ className: "navi_loading_indicator_fluid_container",
19687
+ children: containerWidth > 0 && containerHeight > 0 && jsx(LoadingRectangleSvg, {
19719
19688
  color: color,
19689
+ radius: containerRadius,
19720
19690
  width: containerWidth,
19721
19691
  height: containerHeight,
19722
19692
  strokeWidth: size
19723
19693
  })
19724
19694
  });
19725
19695
  };
19726
- const RectangleLoadingSvg = ({
19696
+ const LoadingRectangleSvg = ({
19727
19697
  width,
19728
19698
  height,
19729
19699
  color,
@@ -19851,178 +19821,149 @@ const RectangleLoadingSvg = ({
19851
19821
  });
19852
19822
  };
19853
19823
 
19854
- installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
19855
- .navi_loading_rectangle_wrapper {
19824
+ installImportMetaCssBuild(import.meta);const css$C = /* css */`
19825
+ .navi_loading_outline_wrapper {
19856
19826
  position: absolute;
19857
- top: var(--rectangle-top, 0);
19858
- right: var(--rectangle-right, 0);
19859
- bottom: var(--rectangle-bottom, 0);
19860
- left: var(--rectangle-left, 0);
19827
+ top: var(--loading-rectangle-top, 0);
19828
+ right: var(--loading-rectangle-right, 0);
19829
+ bottom: var(--loading-rectangle-bottom, 0);
19830
+ left: var(--loading-rectangle-left, 0);
19861
19831
  z-index: 1;
19862
- opacity: 0;
19832
+ border-radius: inherit;
19863
19833
  pointer-events: none;
19864
19834
 
19865
- &[data-visible] {
19866
- opacity: 1;
19835
+ &[hidden] {
19836
+ display: block;
19837
+ opacity: 0;
19867
19838
  }
19868
19839
  }
19869
- `, "@jsenv/navi/src/graphic/loader/loader_background.jsx"];
19870
- const LoaderBackground = ({
19871
- loading,
19872
- containerRef,
19873
- targetSelector,
19874
- color,
19875
- inset = 0,
19876
- borderRadius = 0,
19877
- spacingTop = 0,
19878
- spacingLeft = 0,
19879
- spacingBottom = 0,
19880
- spacingRight = 0,
19881
- children
19882
- }) => {
19883
- if (containerRef) {
19884
- const container = containerRef.current;
19840
+ `;
19841
+ const LoadingOutline = props => {
19842
+ import.meta.css = [css$C, "@jsenv/navi/src/graphic/loading/loading_outline.jsx"];
19843
+ if (props.containerRef) {
19844
+ const container = props.containerRef.current;
19885
19845
  if (!container) {
19886
- return children;
19846
+ return props.children;
19887
19847
  }
19888
- return createPortal(jsx(LoaderBackgroundWithPortal, {
19848
+ return createPortal(jsx(LoadingOutlineWithPortal, {
19889
19849
  container: container,
19890
- loading: loading,
19891
- color: color,
19892
- inset: inset,
19893
- spacingTop: spacingTop,
19894
- spacingLeft: spacingLeft,
19895
- spacingBottom: spacingBottom,
19896
- spacingRight: spacingRight,
19897
- children: children
19850
+ ...props,
19851
+ containerRef: undefined
19898
19852
  }), container);
19899
19853
  }
19900
- return jsx(LoaderBackgroundBasic, {
19901
- targetSelector: targetSelector,
19902
- loading: loading,
19903
- color: color,
19904
- inset: inset,
19905
- borderRadius: borderRadius,
19906
- spacingTop: spacingTop,
19907
- spacingLeft: spacingLeft,
19908
- spacingBottom: spacingBottom,
19909
- spacingRight: spacingRight,
19910
- children: children
19911
- });
19912
- };
19913
- const LoaderBackgroundWithPortal = ({
19914
- container,
19915
- loading,
19916
- color,
19917
- inset,
19918
- borderRadius,
19919
- spacingTop,
19920
- spacingLeft,
19921
- spacingBottom,
19922
- spacingRight,
19923
- children
19924
- }) => {
19925
- const shouldShowSpinner = useDebounceTrue(loading, 300);
19926
- if (!shouldShowSpinner) {
19927
- return children;
19928
- }
19929
- container.style.position = "relative";
19930
- let paddingTop = 0;
19931
- if (container.nodeName === "DETAILS") {
19932
- paddingTop = container.querySelector("summary").offsetHeight;
19933
- }
19934
- return jsxs(Fragment, {
19935
- children: [jsx("div", {
19936
- style: {
19937
- position: "absolute",
19938
- top: `${inset + paddingTop + spacingTop}px`,
19939
- bottom: `${inset + spacingBottom}px`,
19940
- left: `${inset + spacingLeft}px`,
19941
- right: `${inset + spacingRight}px`
19942
- },
19943
- children: shouldShowSpinner && jsx(RectangleLoading, {
19944
- color: color,
19945
- radius: borderRadius
19946
- })
19947
- }), children]
19854
+ return jsx(LoadingOutlineUI, {
19855
+ ...props
19948
19856
  });
19949
19857
  };
19950
- const LoaderBackgroundBasic = ({
19951
- loading,
19952
- targetSelector,
19953
- color,
19954
- borderWidth = 0,
19955
- borderRadius = 0,
19956
- spacingTop,
19957
- spacingLeft,
19958
- spacingBottom,
19959
- spacingRight,
19960
- marginTop = 0,
19961
- marginLeft = 0,
19962
- marginBottom = 0,
19963
- marginRight = 0,
19964
- paddingTop = 0,
19965
- paddingLeft = 0,
19966
- paddingBottom = 0,
19967
- paddingRight = 0,
19968
- inset,
19969
- children
19970
- }) => {
19858
+ const LoadingOutlineUI = props => {
19859
+ const {
19860
+ loading,
19861
+ targetSelector,
19862
+ color,
19863
+ borderWidth = 0,
19864
+ radius,
19865
+ spacingTop = 0,
19866
+ spacingRight = 0,
19867
+ spacingBottom = 0,
19868
+ spacingLeft = 0,
19869
+ marginTop = 0,
19870
+ marginRight = 0,
19871
+ marginBottom = 0,
19872
+ marginLeft = 0,
19873
+ paddingTop = 0,
19874
+ paddingRight = 0,
19875
+ paddingBottom = 0,
19876
+ paddingLeft = 0,
19877
+ inset = 0,
19878
+ children
19879
+ } = props;
19971
19880
  const shouldShowSpinner = useDebounceTrue(loading, 300);
19972
19881
  const rectangleRef = useRef(null);
19973
- spacingTop += inset;
19974
- // spacingTop += outlineOffset;
19975
- // spacingTop -= borderTopWidth;
19976
- spacingTop += marginTop;
19977
- spacingLeft += inset;
19978
- // spacingLeft += outlineOffset;
19979
- // spacingLeft -= borderLeftWidth;
19980
- spacingLeft += marginLeft;
19981
- spacingRight += inset;
19982
- // spacingRight += outlineOffset;
19983
- // spacingRight -= borderRightWidth;
19984
- spacingRight += marginRight;
19985
- spacingBottom += inset;
19986
- // spacingBottom += outlineOffset;
19987
- // spacingBottom -= borderBottomWidth;
19988
- spacingBottom += marginBottom;
19882
+ let insetTop = inset + spacingTop + marginTop;
19883
+ let insetRight = inset + spacingRight + marginRight;
19884
+ let insetBottom = inset + spacingBottom + marginBottom;
19885
+ let insetLeft = inset + spacingLeft + marginLeft;
19989
19886
  if (targetSelector) {
19990
19887
  // oversimplification that actually works
19991
19888
  // (simplified because it assumes the targeted element is a direct child of the contained element which may have padding)
19992
- spacingTop += paddingTop;
19993
- spacingLeft += paddingLeft;
19994
- spacingRight += paddingRight;
19995
- spacingBottom += paddingBottom;
19889
+ insetTop += paddingTop;
19890
+ insetRight += paddingBottom;
19891
+ insetBottom += paddingRight;
19892
+ insetLeft += paddingLeft;
19996
19893
  }
19997
19894
  const maxBorderWidth = Math.max(borderWidth);
19998
19895
  const halfMaxBorderSize = maxBorderWidth / 2;
19999
19896
  const size = halfMaxBorderSize < 2 ? 2 : halfMaxBorderSize;
20000
19897
  const lineHalfSize = size / 2;
20001
- spacingTop -= lineHalfSize;
20002
- spacingLeft -= lineHalfSize;
20003
- spacingRight -= lineHalfSize;
20004
- spacingBottom -= lineHalfSize;
19898
+ insetTop -= lineHalfSize;
19899
+ insetRight -= lineHalfSize;
19900
+ insetBottom -= lineHalfSize;
19901
+ insetLeft -= lineHalfSize;
20005
19902
  return jsxs(Fragment, {
20006
19903
  children: [jsx("span", {
20007
19904
  ref: rectangleRef,
20008
- className: "navi_loading_rectangle_wrapper",
20009
- "data-visible": shouldShowSpinner ? "" : undefined,
19905
+ className: "navi_loading_outline_wrapper",
19906
+ hidden: !shouldShowSpinner,
20010
19907
  style: {
20011
- "--rectangle-top": `${spacingTop}px`,
20012
- "--rectangle-left": `${spacingLeft}px`,
20013
- "--rectangle-bottom": `${spacingBottom}px`,
20014
- "--rectangle-right": `${spacingRight}px`
19908
+ "--loading-rectangle-top": `${insetTop}px`,
19909
+ "--loading-rectangle-right": `${insetRight}px`,
19910
+ "--loading-rectangle-bottom": `${insetBottom}px`,
19911
+ "--loading-rectangle-left": `${insetLeft}px`
20015
19912
  },
20016
- children: loading && jsx(RectangleLoading, {
20017
- shouldShowSpinner: shouldShowSpinner,
19913
+ children: loading && jsx(LoadingIndicatorFluid, {
19914
+ hidden: !shouldShowSpinner,
19915
+ radius: radius,
20018
19916
  color: color,
20019
- radius: borderRadius,
20020
19917
  size: size
20021
19918
  })
20022
19919
  }), children]
20023
19920
  });
20024
19921
  };
20025
19922
 
19923
+ // Not actually used anymore.
19924
+ // Now all UI have a common wrapper that can be used to display the loading indicator without needing a container portal.
19925
+ const LoadingOutlineWithPortal = props => {
19926
+ const {
19927
+ container,
19928
+ loading,
19929
+ color,
19930
+ inset = 0,
19931
+ radius,
19932
+ spacingTop = 0,
19933
+ spacingRight = 0,
19934
+ spacingBottom = 0,
19935
+ spacingLeft = 0,
19936
+ children
19937
+ } = props;
19938
+ const shouldShowSpinner = useDebounceTrue(loading, 300);
19939
+ if (!shouldShowSpinner) {
19940
+ return children;
19941
+ }
19942
+ container.style.position = "relative";
19943
+ let insetTop = inset + spacingTop;
19944
+ let insetRight = inset + spacingRight;
19945
+ let insetBottom = inset + spacingBottom;
19946
+ let insetLeft = inset + spacingLeft;
19947
+ if (container.nodeName === "DETAILS") {
19948
+ insetTop += container.querySelector("summary").offsetHeight;
19949
+ }
19950
+ return jsxs(Fragment, {
19951
+ children: [jsx("div", {
19952
+ className: "navi_loading_outline_wrapper",
19953
+ style: {
19954
+ "--loading-rectangle-top": `${insetTop}px`,
19955
+ "--loading-rectangle-right": `${insetRight}px`,
19956
+ "--loading-rectangle-bottom": `${insetBottom}px`,
19957
+ "--loading-rectangle-left": `${insetLeft}px`
19958
+ },
19959
+ children: shouldShowSpinner && jsx(LoadingIndicatorFluid, {
19960
+ color: color,
19961
+ radius: radius
19962
+ })
19963
+ }), children]
19964
+ });
19965
+ };
19966
+
20026
19967
  // used by form elements such as <input>, <select>, <textarea> to have their own action bound to a single parameter
20027
19968
  // when inside a <form> the form params are updated when the form element single param is updated
20028
19969
  const useActionBoundToOneParam = (action, externalValue) => {
@@ -20844,7 +20785,7 @@ const selectByTextStrings = (element, range, startText, endText) => {
20844
20785
  };
20845
20786
 
20846
20787
  installImportMetaCssBuild(import.meta);// https://jsfiddle.net/v5xzJ/4/
20847
- const css$A = /* css */`
20788
+ const css$B = /* css */`
20848
20789
  @layer navi {
20849
20790
  .navi_text {
20850
20791
  &[data-skeleton] {
@@ -21243,7 +21184,7 @@ const TextDispatcher = props => {
21243
21184
  });
21244
21185
  };
21245
21186
  const TextUI = props => {
21246
- import.meta.css = [css$A, "@jsenv/navi/src/text/text.jsx"];
21187
+ import.meta.css = [css$B, "@jsenv/navi/src/text/text.jsx"];
21247
21188
  let {
21248
21189
  ref,
21249
21190
  spacing,
@@ -21415,7 +21356,7 @@ const TextWithSelectRange = ({
21415
21356
  });
21416
21357
  };
21417
21358
 
21418
- installImportMetaCssBuild(import.meta);const css$z = /* css */`
21359
+ installImportMetaCssBuild(import.meta);const css$A = /* css */`
21419
21360
  .navi_text_anchor {
21420
21361
  vertical-align: baseline;
21421
21362
  user-select: none;
@@ -21450,7 +21391,7 @@ const TextAnchor = ({
21450
21391
  textSize,
21451
21392
  lineLayout
21452
21393
  }) => {
21453
- import.meta.css = [css$z, "@jsenv/navi/src/text/text_anchor.jsx"];
21394
+ import.meta.css = [css$A, "@jsenv/navi/src/text/text_anchor.jsx"];
21454
21395
  const anchorRef = useRef();
21455
21396
  const setTopOffset = (childEl, topOffset) => {
21456
21397
  // position:relative + top shifts the element visually.
@@ -21552,7 +21493,7 @@ const computeTopOffset = ({
21552
21493
  };
21553
21494
  const charTopCanvas = document.createElement("canvas");
21554
21495
 
21555
- installImportMetaCssBuild(import.meta);const css$y = /* css */`
21496
+ installImportMetaCssBuild(import.meta);const css$z = /* css */`
21556
21497
  @layer navi {
21557
21498
  /* Ensure data attributes from box.jsx can win to update display */
21558
21499
  .navi_icon {
@@ -21625,7 +21566,7 @@ const Icon = ({
21625
21566
  lineLayout,
21626
21567
  ...props
21627
21568
  }) => {
21628
- import.meta.css = [css$y, "@jsenv/navi/src/text/icon.jsx"];
21569
+ import.meta.css = [css$z, "@jsenv/navi/src/text/icon.jsx"];
21629
21570
  const innerChildren = href ? jsx("svg", {
21630
21571
  width: "100%",
21631
21572
  height: "100%",
@@ -22577,7 +22518,7 @@ const useUIState = (uiStateController) => {
22577
22518
  return trackedUIState;
22578
22519
  };
22579
22520
 
22580
- installImportMetaCssBuild(import.meta);const css$x = /* css */`
22521
+ installImportMetaCssBuild(import.meta);const css$y = /* css */`
22581
22522
  @layer navi {
22582
22523
  .navi_button {
22583
22524
  --button-border-radius: 2px;
@@ -22863,7 +22804,7 @@ const ButtonDispatcher = props => {
22863
22804
  });
22864
22805
  };
22865
22806
  const ButtonUI = props => {
22866
- import.meta.css = [css$x, "@jsenv/navi/src/field/button.jsx"];
22807
+ import.meta.css = [css$y, "@jsenv/navi/src/field/button.jsx"];
22867
22808
  const {
22868
22809
  ref,
22869
22810
  readOnly,
@@ -22963,7 +22904,7 @@ const ButtonUI = props => {
22963
22904
  },
22964
22905
  visualSelector: visualSelector,
22965
22906
  hasChildFunction: true,
22966
- children: [jsx(LoaderBackground, {
22907
+ children: [jsx(LoadingOutline, {
22967
22908
  loading: innerLoading,
22968
22909
  inset: -1,
22969
22910
  color: "var(--button-loader-color)"
@@ -23188,7 +23129,7 @@ const WarningSvg = () => {
23188
23129
  });
23189
23130
  };
23190
23131
 
23191
- installImportMetaCssBuild(import.meta);const css$w = /* css */`
23132
+ installImportMetaCssBuild(import.meta);const css$x = /* css */`
23192
23133
  @layer navi {
23193
23134
  .navi_message_box {
23194
23135
  --background-color-info: var(--navi-info-color-light);
@@ -23241,7 +23182,7 @@ const MessageBox = ({
23241
23182
  onClose,
23242
23183
  ...rest
23243
23184
  }) => {
23244
- import.meta.css = [css$w, "@jsenv/navi/src/text/message_box.jsx"];
23185
+ import.meta.css = [css$x, "@jsenv/navi/src/text/message_box.jsx"];
23245
23186
  const [hasTitleChild, setHasTitleChild] = useState(false);
23246
23187
  const innerLeftStripe = leftStripe === undefined ? hasTitleChild : leftStripe;
23247
23188
  if (icon === true) {
@@ -23300,7 +23241,7 @@ const MessageBoxPseudoClasses = [":-navi-status-info", ":-navi-status-success",
23300
23241
  const MessageBoxStatusContext = createContext();
23301
23242
  const MessageBoxReportTitleChildContext = createContext();
23302
23243
 
23303
- installImportMetaCssBuild(import.meta);const css$v = /* css */`
23244
+ installImportMetaCssBuild(import.meta);const css$w = /* css */`
23304
23245
  .navi_message_box {
23305
23246
  .navi_title {
23306
23247
  margin-top: 0;
@@ -23310,7 +23251,7 @@ installImportMetaCssBuild(import.meta);const css$v = /* css */`
23310
23251
  }
23311
23252
  `;
23312
23253
  const Title = props => {
23313
- import.meta.css = [css$v, "@jsenv/navi/src/text/title.jsx"];
23254
+ import.meta.css = [css$w, "@jsenv/navi/src/text/title.jsx"];
23314
23255
  const messageBoxStatus = useContext(MessageBoxStatusContext);
23315
23256
  const innerAs = props.as || (messageBoxStatus ? "h4" : "h1");
23316
23257
  const titleLevel = parseInt(innerAs.slice(1));
@@ -23388,7 +23329,7 @@ const useDimColorWhen = (elementRef, shouldDim) => {
23388
23329
  });
23389
23330
  };
23390
23331
 
23391
- installImportMetaCssBuild(import.meta);const css$u = /* css */`
23332
+ installImportMetaCssBuild(import.meta);const css$v = /* css */`
23392
23333
  @layer navi {
23393
23334
  .navi_link {
23394
23335
  --link-border-radius: unset;
@@ -23740,7 +23681,7 @@ Object.assign(PSEUDO_CLASSES, {
23740
23681
  }
23741
23682
  });
23742
23683
  const Link = props => {
23743
- import.meta.css = [css$u, "@jsenv/navi/src/nav/link/link.jsx"];
23684
+ import.meta.css = [css$v, "@jsenv/navi/src/nav/link/link.jsx"];
23744
23685
  return renderActionableComponent(props, {
23745
23686
  Basic: LinkBasic,
23746
23687
  WithAction: LinkWithAction
@@ -23941,7 +23882,7 @@ const LinkPlain = props => {
23941
23882
  onKeyDown?.(e);
23942
23883
  },
23943
23884
  childrenOutsideFlow: jsxs(Fragment, {
23944
- children: [jsx(LoaderBackground, {
23885
+ children: [jsx(LoadingOutline, {
23945
23886
  loading: loading,
23946
23887
  inset: 1,
23947
23888
  color: "var(--link-loader-color)"
@@ -24006,7 +23947,7 @@ installImportMetaCssBuild(import.meta);/**
24006
23947
  * TabList component with support for horizontal and vertical layouts
24007
23948
  * https://dribbble.com/search/tabs
24008
23949
  */
24009
- const css$t = /* css */`
23950
+ const css$u = /* css */`
24010
23951
  @layer navi {
24011
23952
  .navi_nav {
24012
23953
  --nav-border: none;
@@ -24142,7 +24083,7 @@ const Nav = ({
24142
24083
  panelBorderConnection,
24143
24084
  ...props
24144
24085
  }) => {
24145
- import.meta.css = [css$t, "@jsenv/navi/src/nav/link/nav.jsx"];
24086
+ import.meta.css = [css$u, "@jsenv/navi/src/nav/link/nav.jsx"];
24146
24087
  children = toChildArray(children);
24147
24088
  return jsx(Box, {
24148
24089
  as: "nav",
@@ -24190,7 +24131,7 @@ const useFocusGroup = (
24190
24131
 
24191
24132
  installImportMetaCssBuild(import.meta);const rightArrowPath = "M680-480L360-160l-80-80 240-240-240-240 80-80 320 320z";
24192
24133
  const downArrowPath = "M480-280L160-600l80-80 240 240 240-240 80 80-320 320z";
24193
- const css$s = /* css */`
24134
+ const css$t = /* css */`
24194
24135
  .navi_summary_marker {
24195
24136
  width: 1em;
24196
24137
  height: 1em;
@@ -24275,7 +24216,7 @@ const SummaryMarker = ({
24275
24216
  open,
24276
24217
  loading
24277
24218
  }) => {
24278
- import.meta.css = [css$s, "@jsenv/navi/src/field/details/summary_marker.jsx"];
24219
+ import.meta.css = [css$t, "@jsenv/navi/src/field/details/summary_marker.jsx"];
24279
24220
  const showLoading = useDebounceTrue(loading, 300);
24280
24221
  const mountedRef = useRef(false);
24281
24222
  const prevOpenRef = useRef(open);
@@ -24329,7 +24270,7 @@ const SummaryMarker = ({
24329
24270
  });
24330
24271
  };
24331
24272
 
24332
- installImportMetaCssBuild(import.meta);const css$r = /* css */`
24273
+ installImportMetaCssBuild(import.meta);const css$s = /* css */`
24333
24274
  .navi_details {
24334
24275
  position: relative;
24335
24276
  z-index: 1;
@@ -24366,7 +24307,7 @@ installImportMetaCssBuild(import.meta);const css$r = /* css */`
24366
24307
  }
24367
24308
  `;
24368
24309
  const Details = props => {
24369
- import.meta.css = [css$r, "@jsenv/navi/src/field/details/details.jsx"];
24310
+ import.meta.css = [css$s, "@jsenv/navi/src/field/details/details.jsx"];
24370
24311
  const {
24371
24312
  value = "on",
24372
24313
  persists
@@ -24681,7 +24622,7 @@ const fieldPropSet = new Set([
24681
24622
  "data-testid",
24682
24623
  ]);
24683
24624
 
24684
- installImportMetaCssBuild(import.meta);const css$q = /* css */`
24625
+ installImportMetaCssBuild(import.meta);const css$r = /* css */`
24685
24626
  @layer navi {
24686
24627
  label {
24687
24628
  &[data-interactive] {
@@ -24699,7 +24640,7 @@ installImportMetaCssBuild(import.meta);const css$q = /* css */`
24699
24640
  }
24700
24641
  `;
24701
24642
  const Label = props => {
24702
- import.meta.css = [css$q, "@jsenv/navi/src/field/label.jsx"];
24643
+ import.meta.css = [css$r, "@jsenv/navi/src/field/label.jsx"];
24703
24644
  const {
24704
24645
  readOnly,
24705
24646
  disabled,
@@ -24749,7 +24690,7 @@ const reportDisabledToLabel = value => {
24749
24690
  reportDisabled?.(value);
24750
24691
  };
24751
24692
 
24752
- installImportMetaCssBuild(import.meta);const css$p = /* css */`
24693
+ installImportMetaCssBuild(import.meta);const css$q = /* css */`
24753
24694
  @layer navi {
24754
24695
  .navi_checkbox {
24755
24696
  --margin: 3px 3px 3px 4px;
@@ -25141,7 +25082,7 @@ const InputCheckboxDispatcher = props => {
25141
25082
  });
25142
25083
  };
25143
25084
  const InputCheckboxUI = props => {
25144
- import.meta.css = [css$p, "@jsenv/navi/src/field/input_checkbox.jsx"];
25085
+ import.meta.css = [css$q, "@jsenv/navi/src/field/input_checkbox.jsx"];
25145
25086
  const {
25146
25087
  ref,
25147
25088
  /* eslint-disable no-unused-vars */
@@ -25286,11 +25227,10 @@ const InputCheckboxUI = props => {
25286
25227
  children: [jsx("span", {
25287
25228
  className: "navi_checkbox_accent_probe",
25288
25229
  "aria-hidden": "true"
25289
- }), jsx(LoaderBackground, {
25230
+ }), jsx(LoadingOutline, {
25290
25231
  loading: innerLoading,
25291
25232
  inset: -1,
25292
- color: "var(--loader-color)",
25293
- targetSelector: ".navi_checkbox_field"
25233
+ color: "var(--loader-color)"
25294
25234
  }), visualVnode, renderCheckboxMemoized]
25295
25235
  });
25296
25236
  };
@@ -25543,7 +25483,7 @@ forwardRef((props, ref) => {
25543
25483
  });
25544
25484
  });
25545
25485
 
25546
- installImportMetaCssBuild(import.meta);const css$o = /* css */`
25486
+ installImportMetaCssBuild(import.meta);const css$p = /* css */`
25547
25487
  @layer navi {
25548
25488
  .navi_radio {
25549
25489
  --margin: 3px 3px 0 5px;
@@ -25897,7 +25837,7 @@ const InputRadioDispatcher = props => {
25897
25837
  });
25898
25838
  };
25899
25839
  const InputRadioUI = props => {
25900
- import.meta.css = [css$o, "@jsenv/navi/src/field/input_radio.jsx"];
25840
+ import.meta.css = [css$p, "@jsenv/navi/src/field/input_radio.jsx"];
25901
25841
  const {
25902
25842
  ref,
25903
25843
  /* eslint-disable no-unused-vars */
@@ -26062,12 +26002,10 @@ const InputRadioUI = props => {
26062
26002
  children: [jsx("span", {
26063
26003
  className: "navi_radio_accent_probe",
26064
26004
  "aria-hidden": "true"
26065
- }), jsx(LoaderBackground, {
26005
+ }), jsx(LoadingOutline, {
26066
26006
  loading: innerLoading,
26067
26007
  inset: -1,
26068
- targetSelector: ".navi_radio_field",
26069
- color: "var(--loader-color)",
26070
- borderRadius: appearance === "radio" ? "50%" : "inherit"
26008
+ color: "var(--loader-color)"
26071
26009
  }), visualVNode, renderRadioMemoized]
26072
26010
  });
26073
26011
  };
@@ -26129,7 +26067,7 @@ const InputRadioWithAction = () => {
26129
26067
  throw new Error(`<Input type="radio" /> with an action make no sense. Use <RadioList action={something} /> instead`);
26130
26068
  };
26131
26069
 
26132
- installImportMetaCssBuild(import.meta);const css$n = /* css */`
26070
+ installImportMetaCssBuild(import.meta);const css$o = /* css */`
26133
26071
  @layer navi {
26134
26072
  .navi_input_range {
26135
26073
  --border-radius: 6px;
@@ -26391,7 +26329,7 @@ const InputRangeDispatcher = props => {
26391
26329
  });
26392
26330
  };
26393
26331
  const InputRangeUI = props => {
26394
- import.meta.css = [css$n, "@jsenv/navi/src/field/input_range.jsx"];
26332
+ import.meta.css = [css$o, "@jsenv/navi/src/field/input_range.jsx"];
26395
26333
  const {
26396
26334
  ref,
26397
26335
  onInput,
@@ -26528,7 +26466,7 @@ const InputRangeUI = props => {
26528
26466
  children: [jsx("span", {
26529
26467
  className: "navi_input_range_accent_probe",
26530
26468
  "aria-hidden": "true"
26531
- }), jsx(LoaderBackground, {
26469
+ }), jsx(LoadingOutline, {
26532
26470
  loading: innerLoading,
26533
26471
  color: "var(--loader-color)",
26534
26472
  inset: -1
@@ -26668,7 +26606,7 @@ const SearchSvg = () => jsx("svg", {
26668
26606
  })
26669
26607
  });
26670
26608
 
26671
- installImportMetaCssBuild(import.meta);const css$m = /* css */`
26609
+ installImportMetaCssBuild(import.meta);const css$n = /* css */`
26672
26610
  @layer navi {
26673
26611
  .navi_separator {
26674
26612
  --size: 1px;
@@ -26708,7 +26646,7 @@ const Separator = ({
26708
26646
  vertical,
26709
26647
  ...props
26710
26648
  }) => {
26711
- import.meta.css = [css$m, "@jsenv/navi/src/layout/separator.jsx"];
26649
+ import.meta.css = [css$n, "@jsenv/navi/src/layout/separator.jsx"];
26712
26650
  return jsx(Box, {
26713
26651
  as: vertical ? "span" : "hr",
26714
26652
  ...props,
@@ -27120,7 +27058,7 @@ const RenderWindowContext = createContext(null);
27120
27058
  // Carries the separator element/function down to each ListItem so separators
27121
27059
  // are only rendered between items that actually mount (post-filter, post-window).
27122
27060
  const SeparatorContext = createContext(null);
27123
- const css$l = /* css */`
27061
+ const css$m = /* css */`
27124
27062
  @layer navi {
27125
27063
  .navi_list_container {
27126
27064
  --list-outline-width: 1px;
@@ -27547,7 +27485,7 @@ const ListDispatcher = props => {
27547
27485
  });
27548
27486
  };
27549
27487
  const ListUI = props => {
27550
- import.meta.css = [css$l, "@jsenv/navi/src/field/list/list.jsx"];
27488
+ import.meta.css = [css$m, "@jsenv/navi/src/field/list/list.jsx"];
27551
27489
  const {
27552
27490
  ref,
27553
27491
  renderBudget = RENDER_BUDGET_DEFAULT,
@@ -29026,7 +28964,7 @@ installImportMetaCssBuild(import.meta);/**
29026
28964
  * - <InputCheckbox /> for type="checkbox"
29027
28965
  * - <InputRadio /> for type="radio"
29028
28966
  */
29029
- const css$k = /* css */`
28967
+ const css$l = /* css */`
29030
28968
  @layer navi {
29031
28969
  .navi_input {
29032
28970
  --border-radius: 2px;
@@ -29280,7 +29218,7 @@ const InputTextualDispatcher = props => {
29280
29218
  };
29281
29219
  const InputNativeContext = createContext(null);
29282
29220
  const InputTextualUI = props => {
29283
- import.meta.css = [css$k, "@jsenv/navi/src/field/input_textual.jsx"];
29221
+ import.meta.css = [css$l, "@jsenv/navi/src/field/input_textual.jsx"];
29284
29222
  const {
29285
29223
  ref,
29286
29224
  type,
@@ -29425,7 +29363,7 @@ const InputTextualUI = props => {
29425
29363
  autoFocus: undefined // See use_auto_focus.js
29426
29364
  ,
29427
29365
 
29428
- children: [jsx(LoaderBackground, {
29366
+ children: [jsx(LoadingOutline, {
29429
29367
  loading: innerLoading,
29430
29368
  color: "var(--loader-color)",
29431
29369
  inset: -1
@@ -29901,7 +29839,7 @@ installImportMetaCssBuild(import.meta);/**
29901
29839
  * This means an editable thing MUST have a parent with position relative that wraps the content and the eventual editable input
29902
29840
  *
29903
29841
  */
29904
- const css$j = /* css */`
29842
+ const css$k = /* css */`
29905
29843
  .navi_editable_wrapper {
29906
29844
  --inset-top: 0px;
29907
29845
  --inset-right: 0px;
@@ -29950,7 +29888,7 @@ const useEditionController = () => {
29950
29888
  };
29951
29889
  };
29952
29890
  const Editable = props => {
29953
- import.meta.css = [css$j, "@jsenv/navi/src/field/edition/editable.jsx"];
29891
+ import.meta.css = [css$k, "@jsenv/navi/src/field/edition/editable.jsx"];
29954
29892
  let {
29955
29893
  children,
29956
29894
  action,
@@ -30364,7 +30302,7 @@ const FormWithAction = props => {
30364
30302
  // form.dispatchEvent(customEvent);
30365
30303
  // };
30366
30304
 
30367
- installImportMetaCssBuild(import.meta);const css$i = /* css */`
30305
+ installImportMetaCssBuild(import.meta);const css$j = /* css */`
30368
30306
  .navi_group {
30369
30307
  --border-width: 1px;
30370
30308
 
@@ -30461,7 +30399,7 @@ const Group = ({
30461
30399
  vertical = row,
30462
30400
  ...props
30463
30401
  }) => {
30464
- import.meta.css = [css$i, "@jsenv/navi/src/field/group.jsx"];
30402
+ import.meta.css = [css$j, "@jsenv/navi/src/field/group.jsx"];
30465
30403
  if (typeof borderWidth === "string") {
30466
30404
  borderWidth = parseFloat(borderWidth);
30467
30405
  }
@@ -30652,7 +30590,7 @@ const useCleanup = () => {
30652
30590
  return cleanupMethods;
30653
30591
  };
30654
30592
 
30655
- installImportMetaCssBuild(import.meta);const css$h = /* css */`
30593
+ installImportMetaCssBuild(import.meta);const css$i = /* css */`
30656
30594
  .navi_dialog {
30657
30595
  &[open] {
30658
30596
  display: flex;
@@ -30665,7 +30603,7 @@ installImportMetaCssBuild(import.meta);const css$h = /* css */`
30665
30603
  }
30666
30604
  `;
30667
30605
  const Dialog = props => {
30668
- import.meta.css = [css$h, "@jsenv/navi/src/popup/dialog.jsx"];
30606
+ import.meta.css = [css$i, "@jsenv/navi/src/popup/dialog.jsx"];
30669
30607
  const {
30670
30608
  children,
30671
30609
  scrollTrap,
@@ -30776,7 +30714,7 @@ const requestDialogClose = (popoverElement, {
30776
30714
  });
30777
30715
  };
30778
30716
 
30779
- installImportMetaCssBuild(import.meta);const css$g = /* css */`
30717
+ installImportMetaCssBuild(import.meta);const css$h = /* css */`
30780
30718
  .navi_popover_backdrop {
30781
30719
  position: fixed;
30782
30720
  inset: 0;
@@ -30792,7 +30730,7 @@ installImportMetaCssBuild(import.meta);const css$g = /* css */`
30792
30730
  }
30793
30731
  `;
30794
30732
  const Popover = props => {
30795
- import.meta.css = [css$g, "@jsenv/navi/src/popup/popover.jsx"];
30733
+ import.meta.css = [css$h, "@jsenv/navi/src/popup/popover.jsx"];
30796
30734
  const {
30797
30735
  scrollTrap,
30798
30736
  pointerTrap,
@@ -30994,7 +30932,7 @@ const requestPopoverClose = (popoverElement, {
30994
30932
  });
30995
30933
  };
30996
30934
 
30997
- installImportMetaCssBuild(import.meta);const css$f = /* css */`
30935
+ installImportMetaCssBuild(import.meta);const css$g = /* css */`
30998
30936
  @layer navi {
30999
30937
  .navi_select {
31000
30938
  --select-border-radius: 2px;
@@ -31342,7 +31280,7 @@ const SelectDispatcher = props => {
31342
31280
  });
31343
31281
  };
31344
31282
  const SelectUI = props => {
31345
- import.meta.css = [css$f, "@jsenv/navi/src/field/select.jsx"];
31283
+ import.meta.css = [css$g, "@jsenv/navi/src/field/select.jsx"];
31346
31284
  const {
31347
31285
  placeholder = "Select…",
31348
31286
  trigger,
@@ -31392,7 +31330,7 @@ const SelectUI = props => {
31392
31330
  },
31393
31331
  pseudoClasses: SelectPseudoClasses,
31394
31332
  pseudoElements: SelectPseudoElements,
31395
- children: [jsx(LoaderBackground, {
31333
+ children: [jsx(LoadingOutline, {
31396
31334
  loading: innerLoading,
31397
31335
  color: "var(--loader-color)",
31398
31336
  inset: -1
@@ -32534,7 +32472,7 @@ const Z_INDEX_DROP_PREVIEW = Z_INDEX_STICKY_CORNER + 1;
32534
32472
 
32535
32473
  const Z_INDEX_TABLE_UI = Z_INDEX_STICKY_CORNER + 1;
32536
32474
 
32537
- installImportMetaCssBuild(import.meta);const css$e = /* css */`
32475
+ installImportMetaCssBuild(import.meta);const css$f = /* css */`
32538
32476
  .navi_table_drag_clone_container {
32539
32477
  position: absolute;
32540
32478
  top: var(--table-visual-top);
@@ -32714,7 +32652,7 @@ const moveItem = (array, indexA, indexB) => {
32714
32652
  return newArray;
32715
32653
  };
32716
32654
  const TableDragCloneContainer = forwardRef((props, ref) => {
32717
- import.meta.css = [css$e, "@jsenv/navi/src/field/table/drag/table_drag.jsx"];
32655
+ import.meta.css = [css$f, "@jsenv/navi/src/field/table/drag/table_drag.jsx"];
32718
32656
  const {
32719
32657
  tableId
32720
32658
  } = props;
@@ -33012,7 +32950,7 @@ installImportMetaCssBuild(import.meta);const ROW_MIN_HEIGHT = 30;
33012
32950
  const ROW_MAX_HEIGHT = 100;
33013
32951
  const COLUMN_MIN_WIDTH = 50;
33014
32952
  const COLUMN_MAX_WIDTH = 500;
33015
- const css$d = /* css */`
32953
+ const css$e = /* css */`
33016
32954
  @layer navi {
33017
32955
  .navi_table {
33018
32956
  --table-resizer-handle-color: #063b7c;
@@ -33172,7 +33110,7 @@ const css$d = /* css */`
33172
33110
 
33173
33111
  // Column resize components
33174
33112
  const TableColumnResizer = props => {
33175
- import.meta.css = [css$d, "@jsenv/navi/src/field/table/resize/table_resize.jsx"];
33113
+ import.meta.css = [css$e, "@jsenv/navi/src/field/table/resize/table_resize.jsx"];
33176
33114
  const defaultRef = useRef();
33177
33115
  const ref = props.ref || defaultRef;
33178
33116
  return jsxs("div", {
@@ -33639,7 +33577,7 @@ const findPreviousTableRow = currentRow => {
33639
33577
  return currentIndex > 0 ? allRows[currentIndex - 1] : null;
33640
33578
  };
33641
33579
 
33642
- installImportMetaCssBuild(import.meta);const css$c = /* css */`
33580
+ installImportMetaCssBuild(import.meta);const css$d = /* css */`
33643
33581
  @layer navi {
33644
33582
  .navi_table {
33645
33583
  --selection-border-color: var(--navi-selection-border-color, #0078d4);
@@ -33741,7 +33679,7 @@ const useTableSelectionController = ({
33741
33679
  onSelectionChange,
33742
33680
  selectionColor
33743
33681
  }) => {
33744
- import.meta.css = [css$c, "@jsenv/navi/src/field/table/selection/table_selection.jsx"];
33682
+ import.meta.css = [css$d, "@jsenv/navi/src/field/table/selection/table_selection.jsx"];
33745
33683
  const selectionController = useSelectionController({
33746
33684
  elementRef: tableRef,
33747
33685
  layout: "grid",
@@ -34212,7 +34150,7 @@ const useTableStickyContextValue = ({
34212
34150
  };
34213
34151
 
34214
34152
  installImportMetaCssBuild(import.meta);// TODO: sticky left/top frontier should likely use "followPosition"
34215
- const css$b = /* css */`
34153
+ const css$c = /* css */`
34216
34154
  @layer navi {
34217
34155
  .navi_table {
34218
34156
  --sticky-frontier-color: #c0c0c0;
@@ -34455,7 +34393,7 @@ const css$b = /* css */`
34455
34393
  const TableStickyFrontier = ({
34456
34394
  tableRef
34457
34395
  }) => {
34458
- import.meta.css = [css$b, "@jsenv/navi/src/field/table/sticky/table_sticky.jsx"];
34396
+ import.meta.css = [css$c, "@jsenv/navi/src/field/table/sticky/table_sticky.jsx"];
34459
34397
  const stickyLeftFrontierGhostRef = useRef();
34460
34398
  const stickyLeftFrontierPreviewRef = useRef();
34461
34399
  const stickyTopFrontierGhostRef = useRef();
@@ -34684,7 +34622,7 @@ const initMoveStickyFrontierViaPointer = (pointerdownEvent, {
34684
34622
  * inset 0 -1px 0 0 color; // Bottom border
34685
34623
  */
34686
34624
 
34687
- const css$a = /* css */ `
34625
+ const css$b = /* css */ `
34688
34626
  .navi_table_root {
34689
34627
  position: relative;
34690
34628
  max-width: var(--table-max-width, none);
@@ -34887,7 +34825,7 @@ const css$a = /* css */ `
34887
34825
  }
34888
34826
  `;
34889
34827
 
34890
- installImportMetaCssBuild(import.meta);const css$9 = /* css */`
34828
+ installImportMetaCssBuild(import.meta);const css$a = /* css */`
34891
34829
  .navi_table_ui {
34892
34830
  position: fixed;
34893
34831
  inset: 0;
@@ -34898,7 +34836,7 @@ installImportMetaCssBuild(import.meta);const css$9 = /* css */`
34898
34836
  }
34899
34837
  `;
34900
34838
  const TableUI = forwardRef((props, ref) => {
34901
- import.meta.css = [css$9, "@jsenv/navi/src/field/table/table_ui.jsx"];
34839
+ import.meta.css = [css$a, "@jsenv/navi/src/field/table/table_ui.jsx"];
34902
34840
  const {
34903
34841
  tableRef,
34904
34842
  tableId,
@@ -35004,7 +34942,7 @@ const RowIndexContext = createContext();
35004
34942
  const TableSectionContext = createContext();
35005
34943
  const useIsInTableHead = () => useContext(TableSectionContext) === "head";
35006
34944
  const Table = props => {
35007
- import.meta.css = [css$a, "@jsenv/navi/src/field/table/table.jsx"];
34945
+ import.meta.css = [css$b, "@jsenv/navi/src/field/table/table.jsx"];
35008
34946
  const tableDefaultRef = useRef();
35009
34947
  const tableDefaultId = `table-${useId()}`;
35010
34948
  const {
@@ -35901,7 +35839,7 @@ const KeyboardShortcutAriaElement = ({
35901
35839
  });
35902
35840
  };
35903
35841
 
35904
- installImportMetaCssBuild(import.meta);const css$8 = /* css */`
35842
+ installImportMetaCssBuild(import.meta);const css$9 = /* css */`
35905
35843
  @layer navi {
35906
35844
  .navi_clipboard_container {
35907
35845
  --height: 1.5em;
@@ -35933,7 +35871,7 @@ const ButtonCopyToClipboard = ({
35933
35871
  children,
35934
35872
  ...props
35935
35873
  }) => {
35936
- import.meta.css = [css$8, "@jsenv/navi/src/field/button_copy_to_clipboard.jsx"];
35874
+ import.meta.css = [css$9, "@jsenv/navi/src/field/button_copy_to_clipboard.jsx"];
35937
35875
  const [copied, setCopied] = useState(false);
35938
35876
  const renderedRef = useRef();
35939
35877
  useEffect(() => {
@@ -36014,7 +35952,7 @@ const Address = ({
36014
35952
  });
36015
35953
  };
36016
35954
 
36017
- installImportMetaCssBuild(import.meta);const css$7 = /* css */`
35955
+ installImportMetaCssBuild(import.meta);const css$8 = /* css */`
36018
35956
  @layer navi {
36019
35957
  }
36020
35958
  .navi_badge {
@@ -36048,7 +35986,7 @@ const Badge = ({
36048
35986
  className,
36049
35987
  ...props
36050
35988
  }) => {
36051
- import.meta.css = [css$7, "@jsenv/navi/src/text/badge.jsx"];
35989
+ import.meta.css = [css$8, "@jsenv/navi/src/text/badge.jsx"];
36052
35990
  const defaultRef = useRef();
36053
35991
  const ref = props.ref || defaultRef;
36054
35992
  useAccentColorAttributes(ref, null);
@@ -36073,7 +36011,7 @@ const BadgeStyleCSSVars$1 = {
36073
36011
  fontSize: "--font-size"
36074
36012
  };
36075
36013
 
36076
- const LoadingDots = () => {
36014
+ const LoadingDotsSvg = () => {
36077
36015
  return jsxs("svg", {
36078
36016
  viewBox: "0 0 200 200",
36079
36017
  width: "100%",
@@ -36138,7 +36076,7 @@ const formatNumber = (value, { lang } = {}) => {
36138
36076
  return new Intl.NumberFormat(lang).format(value);
36139
36077
  };
36140
36078
 
36141
- installImportMetaCssBuild(import.meta);const css$6 = /* css */`
36079
+ installImportMetaCssBuild(import.meta);const css$7 = /* css */`
36142
36080
  @layer navi {
36143
36081
  }
36144
36082
  .navi_text.navi_badge_count {
@@ -36251,7 +36189,7 @@ const BadgeCount = ({
36251
36189
  lineLayout,
36252
36190
  ...props
36253
36191
  }) => {
36254
- import.meta.css = [css$6, "@jsenv/navi/src/text/badge_count.jsx"];
36192
+ import.meta.css = [css$7, "@jsenv/navi/src/text/badge_count.jsx"];
36255
36193
  const defaultRef = useRef();
36256
36194
  const ref = props.ref || defaultRef;
36257
36195
  useAccentColorAttributes(ref, null);
@@ -36354,7 +36292,7 @@ const BadgeCountEllipse = ({
36354
36292
  styleCSSVars: BadgeStyleCSSVars,
36355
36293
  spacing: "pre",
36356
36294
  children: loading ? jsx(Icon, {
36357
- children: jsx(LoadingDots, {})
36295
+ children: jsx(LoadingDotsSvg, {})
36358
36296
  }) : children
36359
36297
  });
36360
36298
  };
@@ -36382,7 +36320,7 @@ const BadgeCountCircle = ({
36382
36320
  styleCSSVars: BadgeStyleCSSVars,
36383
36321
  spacing: "pre",
36384
36322
  children: loading ? jsx(Icon, {
36385
- children: jsx(LoadingDots, {})
36323
+ children: jsx(LoadingDotsSvg, {})
36386
36324
  }) : jsx("span", {
36387
36325
  className: "navi_badge_count_text",
36388
36326
  children: children
@@ -36390,7 +36328,7 @@ const BadgeCountCircle = ({
36390
36328
  });
36391
36329
  };
36392
36330
 
36393
- installImportMetaCssBuild(import.meta);const css$5 = /* css */`
36331
+ installImportMetaCssBuild(import.meta);const css$6 = /* css */`
36394
36332
  @layer navi {
36395
36333
  .navi_caption {
36396
36334
  --color: #6b7280;
@@ -36411,7 +36349,7 @@ const Caption = ({
36411
36349
  className,
36412
36350
  ...rest
36413
36351
  }) => {
36414
- import.meta.css = [css$5, "@jsenv/navi/src/text/caption.jsx"];
36352
+ import.meta.css = [css$6, "@jsenv/navi/src/text/caption.jsx"];
36415
36353
  return jsx(Text, {
36416
36354
  as: "small",
36417
36355
  size: "0.8em" // We use em to be relative to the parent (we want to be smaller than the surrounding text)
@@ -36888,7 +36826,7 @@ const interpolate = (template, values) => {
36888
36826
  });
36889
36827
  };
36890
36828
 
36891
- installImportMetaCssBuild(import.meta);const css$4 = /* css */`
36829
+ installImportMetaCssBuild(import.meta);const css$5 = /* css */`
36892
36830
  @layer navi {
36893
36831
  .navi_quantity {
36894
36832
  --unit-color: color-mix(in srgb, currentColor 50%, white);
@@ -36993,7 +36931,7 @@ const Quantity = ({
36993
36931
  bold = true,
36994
36932
  ...props
36995
36933
  }) => {
36996
- import.meta.css = [css$4, "@jsenv/navi/src/text/quantity.jsx"];
36934
+ import.meta.css = [css$5, "@jsenv/navi/src/text/quantity.jsx"];
36997
36935
  const value = parseQuantityValue(children);
36998
36936
  const valueRounded = integer && typeof value === "number" ? Math.round(value) : value;
36999
36937
  const valueFormatted = typeof valueRounded === "number" ? formatNumber(valueRounded, {
@@ -37023,8 +36961,8 @@ const Quantity = ({
37023
36961
  children: [jsx("span", {
37024
36962
  className: "navi_quantity_value",
37025
36963
  children: loading ? jsx(Icon, {
37026
- flowInline: true,
37027
- children: jsx(LoadingDots, {})
36964
+ inline: true,
36965
+ children: jsx(LoadingDotsSvg, {})
37028
36966
  }) : valueFormatted
37029
36967
  }), unit && jsx(Unit, {
37030
36968
  value: value,
@@ -37082,7 +37020,7 @@ const parseQuantityValue = children => {
37082
37020
  return Number.isNaN(parsed) ? children : parsed;
37083
37021
  };
37084
37022
 
37085
- installImportMetaCssBuild(import.meta);const css$3 = /* css */`
37023
+ installImportMetaCssBuild(import.meta);const css$4 = /* css */`
37086
37024
  @layer navi {
37087
37025
  .navi_meter {
37088
37026
  --loader-color: var(--navi-loader-color);
@@ -37162,8 +37100,8 @@ installImportMetaCssBuild(import.meta);const css$3 = /* css */`
37162
37100
  }
37163
37101
 
37164
37102
  &[data-accent-needs-dark-fg] {
37165
- --x-color: white;
37166
- --x-shadow-color: black;
37103
+ --x-color: black;
37104
+ --x-shadow-color: white;
37167
37105
  }
37168
37106
 
37169
37107
  /* When caption is shown, the track takes the full height */
@@ -37220,7 +37158,7 @@ const Meter = ({
37220
37158
  style,
37221
37159
  ...rest
37222
37160
  }) => {
37223
- import.meta.css = [css$3, "@jsenv/navi/src/text/meter.jsx"];
37161
+ import.meta.css = [css$4, "@jsenv/navi/src/text/meter.jsx"];
37224
37162
  const defaultRef = useRef();
37225
37163
  const ref = rest.ref || defaultRef;
37226
37164
  value = Number(value);
@@ -37283,7 +37221,7 @@ const Meter = ({
37283
37221
  ...rest,
37284
37222
  children: jsxs("span", {
37285
37223
  className: "navi_meter_track_container",
37286
- children: [jsx(LoaderBackground, {
37224
+ children: [jsx(LoadingOutline, {
37287
37225
  loading: loading,
37288
37226
  color: "var(--loader-color)",
37289
37227
  inset: -1
@@ -37347,10 +37285,100 @@ const Paragraph = props => {
37347
37285
  });
37348
37286
  };
37349
37287
 
37350
- const Image = props => {
37288
+ installImportMetaCssBuild(import.meta);const css$3 = /* css */`
37289
+ @keyframes navi_image_shimmer {
37290
+ 0% {
37291
+ background-position: -200% 0;
37292
+ }
37293
+ 100% {
37294
+ background-position: 200% 0;
37295
+ }
37296
+ }
37297
+ .navi_image {
37298
+ &[navi-placeholder] {
37299
+ background-image:
37300
+ linear-gradient(
37301
+ 105deg,
37302
+ transparent 30%,
37303
+ color-mix(
37304
+ in srgb,
37305
+ var(--placeholder-color) 0%,
37306
+ var(--placeholder-shimmer-color) 14%
37307
+ )
37308
+ 50%,
37309
+ transparent 70%
37310
+ ),
37311
+ radial-gradient(
37312
+ ellipse at 40% 40%,
37313
+ color-mix(
37314
+ in srgb,
37315
+ var(--placeholder-color) 70%,
37316
+ var(--placeholder-shimmer-color) 30%
37317
+ )
37318
+ 0%,
37319
+ var(--placeholder-color) 70%
37320
+ );
37321
+ background-size:
37322
+ 200% 100%,
37323
+ 100% 100%;
37324
+ animation: navi_image_shimmer 2s linear infinite;
37325
+ }
37326
+ }
37327
+ `;
37328
+ const DEFAULT_PLACEHOLDER_LIGHT = "#d4d8dd";
37329
+ const DEFAULT_PLACEHOLDER_DARK = "#374151";
37330
+
37331
+ /**
37332
+ * @param {string|false} [props.placeholderColor] - Background color shown while the image loads.
37333
+ * Defaults to a light gray. Pass `false` to disable.
37334
+ * @param {boolean} [props.placeholderDark] - Use a dark default placeholder color,
37335
+ * suited for images displayed on a dark background. Also switches the shimmer
37336
+ * highlight to mix with black instead of white.
37337
+ */
37338
+ const Image = ({
37339
+ placeholderColor,
37340
+ placeholderDark = false,
37341
+ ...rest
37342
+ }) => {
37343
+ import.meta.css = [css$3, "@jsenv/navi/src/graphic/image.jsx"];
37344
+ const loadedRef = useRef();
37345
+ let resolvedPlaceholder = placeholderColor;
37346
+ if (resolvedPlaceholder === undefined) {
37347
+ resolvedPlaceholder = placeholderDark ? DEFAULT_PLACEHOLDER_DARK : DEFAULT_PLACEHOLDER_LIGHT;
37348
+ }
37351
37349
  return jsx(Box, {
37350
+ ...rest,
37351
+ as: "img",
37352
+ baseClassName: "navi_image",
37353
+ "navi-placeholder": loadedRef.current ? undefined : "",
37354
+ style: {
37355
+ "--placeholder-color": resolvedPlaceholder || undefined,
37356
+ "--placeholder-shimmer-color": placeholderDark ? "black" : "white",
37357
+ ...rest.style
37358
+ },
37359
+ onLoad: e => {
37360
+ const imageEl = e.currentTarget;
37361
+ imageEl.removeAttribute("navi-placeholder");
37362
+ imageEl.setAttribute("navi-loaded", "");
37363
+ rest.onLoad?.(e);
37364
+ }
37365
+ });
37366
+ };
37367
+
37368
+ const LoadingIndicator = ({
37369
+ variant = "circle",
37370
+ ...props
37371
+ }) => {
37372
+ if (variant === "dots") {
37373
+ return jsx(Icon, {
37374
+ ...props,
37375
+ children: jsx(LoadingDotsSvg, {})
37376
+ });
37377
+ }
37378
+ return jsx(Icon, {
37379
+ circle: true,
37352
37380
  ...props,
37353
- as: "img"
37381
+ children: jsx(LoadingIndicatorFluid, {})
37354
37382
  });
37355
37383
  };
37356
37384
 
@@ -37944,5 +37972,5 @@ const UserSvg = () => jsx("svg", {
37944
37972
  })
37945
37973
  });
37946
37974
 
37947
- export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, Box, Button, ButtonCopyToClipboard, Caption, CheckSvg, Checkbox, CheckboxList, CloseSvg, Code, Col, Colgroup, ConstructionSvg, Details, Dialog, DialogLayout, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemFooter, ListItemGroup, ListItemHeader, Loading, MessageBox, Meter, Nav, NaviDebug, Paragraph, Popover, Quantity, QuantityIntl, Radio, RadioList, Route, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectionContext, Separator, SettingsSvg, SidePanel, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, Thead, Title, Tr, UITransition, UserSvg, ViewportLayout, actionIntegratedVia, actionRunEffect, addCustomMessage, anyMatchingRouteSignal, applySearch, arraySignalMembership, compareTwoJsValues, createAction, createAvailableConstraint, createIntl, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, enableDebugActions, enableDebugOnDocumentLoading, filterTableSelection, forwardActionRequested, installCustomConstraintValidation, isCellSelected, isColumnSelected, isRowSelected, localStorageSignal, navBack, navForward, navTo, openCallout, rawUrlPart, reload, removeCustomMessage, requestAction, requestListClose, requestListOpen, rerunActions, resource, route, routeAction, setBaseUrl, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, syncOwnedResourceToSignals, syncResourceToSignals, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, useRouteStatus, useRunOnMount, useSearchText, useSelectRequestClose, useSelectableElement, useSelectionController, useSidePanelClose, useSignalSync, useStateArray, useTitleLevel, useUrlSearchParam, valueInLocalStorage, windowWidthSignal };
37975
+ export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, Box, Button, ButtonCopyToClipboard, Caption, CheckSvg, Checkbox, CheckboxList, CloseSvg, Code, Col, Colgroup, ConstructionSvg, Details, Dialog, DialogLayout, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemFooter, ListItemGroup, ListItemHeader, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, MessageBox, Meter, Nav, NaviDebug, Paragraph, Popover, Quantity, QuantityIntl, Radio, RadioList, Route, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectionContext, Separator, SettingsSvg, SidePanel, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, Thead, Title, Tr, UITransition, UserSvg, ViewportLayout, actionIntegratedVia, actionRunEffect, addCustomMessage, anyMatchingRouteSignal, applySearch, arraySignalMembership, compareTwoJsValues, createAction, createAvailableConstraint, createIntl, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, enableDebugActions, enableDebugOnDocumentLoading, filterTableSelection, forwardActionRequested, installCustomConstraintValidation, isCellSelected, isColumnSelected, isRowSelected, localStorageSignal, navBack, navForward, navTo, openCallout, rawUrlPart, reload, removeCustomMessage, requestAction, requestListClose, requestListOpen, rerunActions, resource, route, routeAction, setBaseUrl, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, syncOwnedResourceToSignals, syncResourceToSignals, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, useRouteStatus, useRunOnMount, useSearchText, useSelectRequestClose, useSelectableElement, useSelectionController, useSidePanelClose, useSignalSync, useStateArray, useTitleLevel, useUrlSearchParam, valueInLocalStorage, windowWidthSignal };
37948
37976
  //# sourceMappingURL=jsenv_navi.js.map