@jsenv/navi 0.26.20 → 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.
@@ -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 = {
@@ -16303,7 +16304,7 @@ installImportMetaCssBuild(import.meta);
16303
16304
  * - Centers in viewport when no anchor element provided or anchor is too big
16304
16305
  */
16305
16306
 
16306
- const css$B = /* css */`
16307
+ const css$E = /* css */`
16307
16308
  @layer navi {
16308
16309
  .navi_callout {
16309
16310
  --callout-success-color: #4caf50;
@@ -16477,7 +16478,7 @@ const openCallout = (message, {
16477
16478
  showErrorStack,
16478
16479
  debug = false
16479
16480
  } = {}) => {
16480
- 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"];
16481
16482
  const callout = {
16482
16483
  opened: true,
16483
16484
  close: null,
@@ -19603,53 +19604,55 @@ const setupNetworkMonitoring = () => {
19603
19604
  };
19604
19605
  setupNetworkMonitoring();
19605
19606
 
19606
- installImportMetaCssBuild(import.meta);/**
19607
- * RectangleLoading Component
19608
- *
19609
- * A responsive loading indicator that dynamically adjusts to fit its container.
19610
- * Displays an animated outline with a traveling dot that follows the container's shape.
19611
- *
19612
- * Features:
19613
- * - Adapts to any container dimensions using ResizeObserver
19614
- * - Scales stroke width, margins and corner radius proportionally
19615
- * - Animates using native SVG animations for smooth performance
19616
- * - High-quality SVG rendering with proper path calculations
19617
- *
19618
- * @param {Object} props - Component props
19619
- * @param {string} [props.color="#383a36"] - Color of the loading indicator
19620
- * @param {number} [props.radius=0] - Corner radius of the rectangle (px)
19621
- */
19622
- import.meta.css = [/* css */`
19623
- .navi_rectangle_loading {
19607
+ installImportMetaCssBuild(import.meta);const css$D = /* css */`
19608
+ .navi_loading_indicator_fluid_container {
19624
19609
  position: relative;
19625
19610
  display: flex;
19626
19611
  width: 100%;
19627
19612
  height: 100%;
19628
- opacity: 0;
19629
- }
19630
-
19631
- .navi_rectangle_loading[data-visible] {
19613
+ border-radius: inherit;
19632
19614
  opacity: 1;
19615
+
19616
+ &[hidden] {
19617
+ display: flex;
19618
+ opacity: 0;
19619
+ }
19633
19620
  }
19634
- `, "@jsenv/navi/src/graphic/loader/rectangle_loading.jsx"];
19635
- const RectangleLoading = ({
19636
- 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 = ({
19637
19632
  color = "currentColor",
19638
- radius = 0,
19639
- size = 2
19633
+ size = 2,
19634
+ radius,
19635
+ ...rest
19640
19636
  }) => {
19641
- 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
19642
19640
  const [containerWidth, setContainerWidth] = useState(0);
19643
19641
  const [containerHeight, setContainerHeight] = useState(0);
19642
+ const [containerRadius, setContainerRadius] = useState(0);
19644
19643
  useLayoutEffect(() => {
19645
- const container = containerRef.current;
19646
- if (!container) {
19644
+ const indicatorEl = ref.current;
19645
+ if (!indicatorEl) {
19647
19646
  return null;
19648
19647
  }
19648
+ if (radius === undefined || radius === "inherit") {
19649
+ const radius = getComputedStyle(indicatorEl).borderRadius;
19650
+ setContainerRadius(radius);
19651
+ }
19649
19652
  const {
19650
19653
  width,
19651
19654
  height
19652
- } = container.getBoundingClientRect();
19655
+ } = indicatorEl.getBoundingClientRect();
19653
19656
  setContainerWidth(width);
19654
19657
  setContainerHeight(height);
19655
19658
  let animationFrameId = null;
@@ -19669,7 +19672,7 @@ const RectangleLoading = ({
19669
19672
  setContainerHeight(height);
19670
19673
  });
19671
19674
  });
19672
- resizeObserver.observe(container);
19675
+ resizeObserver.observe(indicatorEl);
19673
19676
  return () => {
19674
19677
  if (animationFrameId) {
19675
19678
  cancelAnimationFrame(animationFrameId);
@@ -19678,19 +19681,19 @@ const RectangleLoading = ({
19678
19681
  };
19679
19682
  }, []);
19680
19683
  return jsx("span", {
19681
- ref: containerRef,
19682
- className: "navi_rectangle_loading",
19683
- "data-visible": shouldShowSpinner ? "" : undefined,
19684
- children: containerWidth > 0 && containerHeight > 0 && jsx(RectangleLoadingSvg, {
19685
- radius: radius,
19684
+ ...rest,
19685
+ ref: ref,
19686
+ className: "navi_loading_indicator_fluid_container",
19687
+ children: containerWidth > 0 && containerHeight > 0 && jsx(LoadingRectangleSvg, {
19686
19688
  color: color,
19689
+ radius: containerRadius,
19687
19690
  width: containerWidth,
19688
19691
  height: containerHeight,
19689
19692
  strokeWidth: size
19690
19693
  })
19691
19694
  });
19692
19695
  };
19693
- const RectangleLoadingSvg = ({
19696
+ const LoadingRectangleSvg = ({
19694
19697
  width,
19695
19698
  height,
19696
19699
  color,
@@ -19818,178 +19821,149 @@ const RectangleLoadingSvg = ({
19818
19821
  });
19819
19822
  };
19820
19823
 
19821
- installImportMetaCssBuild(import.meta);import.meta.css = [/* css */`
19822
- .navi_loading_rectangle_wrapper {
19824
+ installImportMetaCssBuild(import.meta);const css$C = /* css */`
19825
+ .navi_loading_outline_wrapper {
19823
19826
  position: absolute;
19824
- top: var(--rectangle-top, 0);
19825
- right: var(--rectangle-right, 0);
19826
- bottom: var(--rectangle-bottom, 0);
19827
- 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);
19828
19831
  z-index: 1;
19829
- opacity: 0;
19832
+ border-radius: inherit;
19830
19833
  pointer-events: none;
19831
19834
 
19832
- &[data-visible] {
19833
- opacity: 1;
19835
+ &[hidden] {
19836
+ display: block;
19837
+ opacity: 0;
19834
19838
  }
19835
19839
  }
19836
- `, "@jsenv/navi/src/graphic/loader/loader_background.jsx"];
19837
- const LoaderBackground = ({
19838
- loading,
19839
- containerRef,
19840
- targetSelector,
19841
- color,
19842
- inset = 0,
19843
- borderRadius = 0,
19844
- spacingTop = 0,
19845
- spacingLeft = 0,
19846
- spacingBottom = 0,
19847
- spacingRight = 0,
19848
- children
19849
- }) => {
19850
- if (containerRef) {
19851
- 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;
19852
19845
  if (!container) {
19853
- return children;
19846
+ return props.children;
19854
19847
  }
19855
- return createPortal(jsx(LoaderBackgroundWithPortal, {
19848
+ return createPortal(jsx(LoadingOutlineWithPortal, {
19856
19849
  container: container,
19857
- loading: loading,
19858
- color: color,
19859
- inset: inset,
19860
- spacingTop: spacingTop,
19861
- spacingLeft: spacingLeft,
19862
- spacingBottom: spacingBottom,
19863
- spacingRight: spacingRight,
19864
- children: children
19850
+ ...props,
19851
+ containerRef: undefined
19865
19852
  }), container);
19866
19853
  }
19867
- return jsx(LoaderBackgroundBasic, {
19868
- targetSelector: targetSelector,
19869
- loading: loading,
19870
- color: color,
19871
- inset: inset,
19872
- borderRadius: borderRadius,
19873
- spacingTop: spacingTop,
19874
- spacingLeft: spacingLeft,
19875
- spacingBottom: spacingBottom,
19876
- spacingRight: spacingRight,
19877
- children: children
19878
- });
19879
- };
19880
- const LoaderBackgroundWithPortal = ({
19881
- container,
19882
- loading,
19883
- color,
19884
- inset,
19885
- borderRadius,
19886
- spacingTop,
19887
- spacingLeft,
19888
- spacingBottom,
19889
- spacingRight,
19890
- children
19891
- }) => {
19892
- const shouldShowSpinner = useDebounceTrue(loading, 300);
19893
- if (!shouldShowSpinner) {
19894
- return children;
19895
- }
19896
- container.style.position = "relative";
19897
- let paddingTop = 0;
19898
- if (container.nodeName === "DETAILS") {
19899
- paddingTop = container.querySelector("summary").offsetHeight;
19900
- }
19901
- return jsxs(Fragment, {
19902
- children: [jsx("div", {
19903
- style: {
19904
- position: "absolute",
19905
- top: `${inset + paddingTop + spacingTop}px`,
19906
- bottom: `${inset + spacingBottom}px`,
19907
- left: `${inset + spacingLeft}px`,
19908
- right: `${inset + spacingRight}px`
19909
- },
19910
- children: shouldShowSpinner && jsx(RectangleLoading, {
19911
- color: color,
19912
- radius: borderRadius
19913
- })
19914
- }), children]
19854
+ return jsx(LoadingOutlineUI, {
19855
+ ...props
19915
19856
  });
19916
19857
  };
19917
- const LoaderBackgroundBasic = ({
19918
- loading,
19919
- targetSelector,
19920
- color,
19921
- borderWidth = 0,
19922
- borderRadius = 0,
19923
- spacingTop,
19924
- spacingLeft,
19925
- spacingBottom,
19926
- spacingRight,
19927
- marginTop = 0,
19928
- marginLeft = 0,
19929
- marginBottom = 0,
19930
- marginRight = 0,
19931
- paddingTop = 0,
19932
- paddingLeft = 0,
19933
- paddingBottom = 0,
19934
- paddingRight = 0,
19935
- inset,
19936
- children
19937
- }) => {
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;
19938
19880
  const shouldShowSpinner = useDebounceTrue(loading, 300);
19939
19881
  const rectangleRef = useRef(null);
19940
- spacingTop += inset;
19941
- // spacingTop += outlineOffset;
19942
- // spacingTop -= borderTopWidth;
19943
- spacingTop += marginTop;
19944
- spacingLeft += inset;
19945
- // spacingLeft += outlineOffset;
19946
- // spacingLeft -= borderLeftWidth;
19947
- spacingLeft += marginLeft;
19948
- spacingRight += inset;
19949
- // spacingRight += outlineOffset;
19950
- // spacingRight -= borderRightWidth;
19951
- spacingRight += marginRight;
19952
- spacingBottom += inset;
19953
- // spacingBottom += outlineOffset;
19954
- // spacingBottom -= borderBottomWidth;
19955
- 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;
19956
19886
  if (targetSelector) {
19957
19887
  // oversimplification that actually works
19958
19888
  // (simplified because it assumes the targeted element is a direct child of the contained element which may have padding)
19959
- spacingTop += paddingTop;
19960
- spacingLeft += paddingLeft;
19961
- spacingRight += paddingRight;
19962
- spacingBottom += paddingBottom;
19889
+ insetTop += paddingTop;
19890
+ insetRight += paddingBottom;
19891
+ insetBottom += paddingRight;
19892
+ insetLeft += paddingLeft;
19963
19893
  }
19964
19894
  const maxBorderWidth = Math.max(borderWidth);
19965
19895
  const halfMaxBorderSize = maxBorderWidth / 2;
19966
19896
  const size = halfMaxBorderSize < 2 ? 2 : halfMaxBorderSize;
19967
19897
  const lineHalfSize = size / 2;
19968
- spacingTop -= lineHalfSize;
19969
- spacingLeft -= lineHalfSize;
19970
- spacingRight -= lineHalfSize;
19971
- spacingBottom -= lineHalfSize;
19898
+ insetTop -= lineHalfSize;
19899
+ insetRight -= lineHalfSize;
19900
+ insetBottom -= lineHalfSize;
19901
+ insetLeft -= lineHalfSize;
19972
19902
  return jsxs(Fragment, {
19973
19903
  children: [jsx("span", {
19974
19904
  ref: rectangleRef,
19975
- className: "navi_loading_rectangle_wrapper",
19976
- "data-visible": shouldShowSpinner ? "" : undefined,
19905
+ className: "navi_loading_outline_wrapper",
19906
+ hidden: !shouldShowSpinner,
19977
19907
  style: {
19978
- "--rectangle-top": `${spacingTop}px`,
19979
- "--rectangle-left": `${spacingLeft}px`,
19980
- "--rectangle-bottom": `${spacingBottom}px`,
19981
- "--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`
19982
19912
  },
19983
- children: loading && jsx(RectangleLoading, {
19984
- shouldShowSpinner: shouldShowSpinner,
19913
+ children: loading && jsx(LoadingIndicatorFluid, {
19914
+ hidden: !shouldShowSpinner,
19915
+ radius: radius,
19985
19916
  color: color,
19986
- radius: borderRadius,
19987
19917
  size: size
19988
19918
  })
19989
19919
  }), children]
19990
19920
  });
19991
19921
  };
19992
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
+
19993
19967
  // used by form elements such as <input>, <select>, <textarea> to have their own action bound to a single parameter
19994
19968
  // when inside a <form> the form params are updated when the form element single param is updated
19995
19969
  const useActionBoundToOneParam = (action, externalValue) => {
@@ -20811,7 +20785,7 @@ const selectByTextStrings = (element, range, startText, endText) => {
20811
20785
  };
20812
20786
 
20813
20787
  installImportMetaCssBuild(import.meta);// https://jsfiddle.net/v5xzJ/4/
20814
- const css$A = /* css */`
20788
+ const css$B = /* css */`
20815
20789
  @layer navi {
20816
20790
  .navi_text {
20817
20791
  &[data-skeleton] {
@@ -21210,7 +21184,7 @@ const TextDispatcher = props => {
21210
21184
  });
21211
21185
  };
21212
21186
  const TextUI = props => {
21213
- import.meta.css = [css$A, "@jsenv/navi/src/text/text.jsx"];
21187
+ import.meta.css = [css$B, "@jsenv/navi/src/text/text.jsx"];
21214
21188
  let {
21215
21189
  ref,
21216
21190
  spacing,
@@ -21382,7 +21356,7 @@ const TextWithSelectRange = ({
21382
21356
  });
21383
21357
  };
21384
21358
 
21385
- installImportMetaCssBuild(import.meta);const css$z = /* css */`
21359
+ installImportMetaCssBuild(import.meta);const css$A = /* css */`
21386
21360
  .navi_text_anchor {
21387
21361
  vertical-align: baseline;
21388
21362
  user-select: none;
@@ -21417,7 +21391,7 @@ const TextAnchor = ({
21417
21391
  textSize,
21418
21392
  lineLayout
21419
21393
  }) => {
21420
- 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"];
21421
21395
  const anchorRef = useRef();
21422
21396
  const setTopOffset = (childEl, topOffset) => {
21423
21397
  // position:relative + top shifts the element visually.
@@ -21519,7 +21493,7 @@ const computeTopOffset = ({
21519
21493
  };
21520
21494
  const charTopCanvas = document.createElement("canvas");
21521
21495
 
21522
- installImportMetaCssBuild(import.meta);const css$y = /* css */`
21496
+ installImportMetaCssBuild(import.meta);const css$z = /* css */`
21523
21497
  @layer navi {
21524
21498
  /* Ensure data attributes from box.jsx can win to update display */
21525
21499
  .navi_icon {
@@ -21592,7 +21566,7 @@ const Icon = ({
21592
21566
  lineLayout,
21593
21567
  ...props
21594
21568
  }) => {
21595
- import.meta.css = [css$y, "@jsenv/navi/src/text/icon.jsx"];
21569
+ import.meta.css = [css$z, "@jsenv/navi/src/text/icon.jsx"];
21596
21570
  const innerChildren = href ? jsx("svg", {
21597
21571
  width: "100%",
21598
21572
  height: "100%",
@@ -22544,7 +22518,7 @@ const useUIState = (uiStateController) => {
22544
22518
  return trackedUIState;
22545
22519
  };
22546
22520
 
22547
- installImportMetaCssBuild(import.meta);const css$x = /* css */`
22521
+ installImportMetaCssBuild(import.meta);const css$y = /* css */`
22548
22522
  @layer navi {
22549
22523
  .navi_button {
22550
22524
  --button-border-radius: 2px;
@@ -22830,7 +22804,7 @@ const ButtonDispatcher = props => {
22830
22804
  });
22831
22805
  };
22832
22806
  const ButtonUI = props => {
22833
- import.meta.css = [css$x, "@jsenv/navi/src/field/button.jsx"];
22807
+ import.meta.css = [css$y, "@jsenv/navi/src/field/button.jsx"];
22834
22808
  const {
22835
22809
  ref,
22836
22810
  readOnly,
@@ -22930,7 +22904,7 @@ const ButtonUI = props => {
22930
22904
  },
22931
22905
  visualSelector: visualSelector,
22932
22906
  hasChildFunction: true,
22933
- children: [jsx(LoaderBackground, {
22907
+ children: [jsx(LoadingOutline, {
22934
22908
  loading: innerLoading,
22935
22909
  inset: -1,
22936
22910
  color: "var(--button-loader-color)"
@@ -23155,7 +23129,7 @@ const WarningSvg = () => {
23155
23129
  });
23156
23130
  };
23157
23131
 
23158
- installImportMetaCssBuild(import.meta);const css$w = /* css */`
23132
+ installImportMetaCssBuild(import.meta);const css$x = /* css */`
23159
23133
  @layer navi {
23160
23134
  .navi_message_box {
23161
23135
  --background-color-info: var(--navi-info-color-light);
@@ -23208,7 +23182,7 @@ const MessageBox = ({
23208
23182
  onClose,
23209
23183
  ...rest
23210
23184
  }) => {
23211
- 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"];
23212
23186
  const [hasTitleChild, setHasTitleChild] = useState(false);
23213
23187
  const innerLeftStripe = leftStripe === undefined ? hasTitleChild : leftStripe;
23214
23188
  if (icon === true) {
@@ -23267,7 +23241,7 @@ const MessageBoxPseudoClasses = [":-navi-status-info", ":-navi-status-success",
23267
23241
  const MessageBoxStatusContext = createContext();
23268
23242
  const MessageBoxReportTitleChildContext = createContext();
23269
23243
 
23270
- installImportMetaCssBuild(import.meta);const css$v = /* css */`
23244
+ installImportMetaCssBuild(import.meta);const css$w = /* css */`
23271
23245
  .navi_message_box {
23272
23246
  .navi_title {
23273
23247
  margin-top: 0;
@@ -23277,7 +23251,7 @@ installImportMetaCssBuild(import.meta);const css$v = /* css */`
23277
23251
  }
23278
23252
  `;
23279
23253
  const Title = props => {
23280
- import.meta.css = [css$v, "@jsenv/navi/src/text/title.jsx"];
23254
+ import.meta.css = [css$w, "@jsenv/navi/src/text/title.jsx"];
23281
23255
  const messageBoxStatus = useContext(MessageBoxStatusContext);
23282
23256
  const innerAs = props.as || (messageBoxStatus ? "h4" : "h1");
23283
23257
  const titleLevel = parseInt(innerAs.slice(1));
@@ -23355,7 +23329,7 @@ const useDimColorWhen = (elementRef, shouldDim) => {
23355
23329
  });
23356
23330
  };
23357
23331
 
23358
- installImportMetaCssBuild(import.meta);const css$u = /* css */`
23332
+ installImportMetaCssBuild(import.meta);const css$v = /* css */`
23359
23333
  @layer navi {
23360
23334
  .navi_link {
23361
23335
  --link-border-radius: unset;
@@ -23707,7 +23681,7 @@ Object.assign(PSEUDO_CLASSES, {
23707
23681
  }
23708
23682
  });
23709
23683
  const Link = props => {
23710
- 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"];
23711
23685
  return renderActionableComponent(props, {
23712
23686
  Basic: LinkBasic,
23713
23687
  WithAction: LinkWithAction
@@ -23908,7 +23882,7 @@ const LinkPlain = props => {
23908
23882
  onKeyDown?.(e);
23909
23883
  },
23910
23884
  childrenOutsideFlow: jsxs(Fragment, {
23911
- children: [jsx(LoaderBackground, {
23885
+ children: [jsx(LoadingOutline, {
23912
23886
  loading: loading,
23913
23887
  inset: 1,
23914
23888
  color: "var(--link-loader-color)"
@@ -23973,7 +23947,7 @@ installImportMetaCssBuild(import.meta);/**
23973
23947
  * TabList component with support for horizontal and vertical layouts
23974
23948
  * https://dribbble.com/search/tabs
23975
23949
  */
23976
- const css$t = /* css */`
23950
+ const css$u = /* css */`
23977
23951
  @layer navi {
23978
23952
  .navi_nav {
23979
23953
  --nav-border: none;
@@ -24109,7 +24083,7 @@ const Nav = ({
24109
24083
  panelBorderConnection,
24110
24084
  ...props
24111
24085
  }) => {
24112
- 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"];
24113
24087
  children = toChildArray(children);
24114
24088
  return jsx(Box, {
24115
24089
  as: "nav",
@@ -24157,7 +24131,7 @@ const useFocusGroup = (
24157
24131
 
24158
24132
  installImportMetaCssBuild(import.meta);const rightArrowPath = "M680-480L360-160l-80-80 240-240-240-240 80-80 320 320z";
24159
24133
  const downArrowPath = "M480-280L160-600l80-80 240 240 240-240 80 80-320 320z";
24160
- const css$s = /* css */`
24134
+ const css$t = /* css */`
24161
24135
  .navi_summary_marker {
24162
24136
  width: 1em;
24163
24137
  height: 1em;
@@ -24242,7 +24216,7 @@ const SummaryMarker = ({
24242
24216
  open,
24243
24217
  loading
24244
24218
  }) => {
24245
- 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"];
24246
24220
  const showLoading = useDebounceTrue(loading, 300);
24247
24221
  const mountedRef = useRef(false);
24248
24222
  const prevOpenRef = useRef(open);
@@ -24296,7 +24270,7 @@ const SummaryMarker = ({
24296
24270
  });
24297
24271
  };
24298
24272
 
24299
- installImportMetaCssBuild(import.meta);const css$r = /* css */`
24273
+ installImportMetaCssBuild(import.meta);const css$s = /* css */`
24300
24274
  .navi_details {
24301
24275
  position: relative;
24302
24276
  z-index: 1;
@@ -24333,7 +24307,7 @@ installImportMetaCssBuild(import.meta);const css$r = /* css */`
24333
24307
  }
24334
24308
  `;
24335
24309
  const Details = props => {
24336
- 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"];
24337
24311
  const {
24338
24312
  value = "on",
24339
24313
  persists
@@ -24648,7 +24622,7 @@ const fieldPropSet = new Set([
24648
24622
  "data-testid",
24649
24623
  ]);
24650
24624
 
24651
- installImportMetaCssBuild(import.meta);const css$q = /* css */`
24625
+ installImportMetaCssBuild(import.meta);const css$r = /* css */`
24652
24626
  @layer navi {
24653
24627
  label {
24654
24628
  &[data-interactive] {
@@ -24666,7 +24640,7 @@ installImportMetaCssBuild(import.meta);const css$q = /* css */`
24666
24640
  }
24667
24641
  `;
24668
24642
  const Label = props => {
24669
- import.meta.css = [css$q, "@jsenv/navi/src/field/label.jsx"];
24643
+ import.meta.css = [css$r, "@jsenv/navi/src/field/label.jsx"];
24670
24644
  const {
24671
24645
  readOnly,
24672
24646
  disabled,
@@ -24716,7 +24690,7 @@ const reportDisabledToLabel = value => {
24716
24690
  reportDisabled?.(value);
24717
24691
  };
24718
24692
 
24719
- installImportMetaCssBuild(import.meta);const css$p = /* css */`
24693
+ installImportMetaCssBuild(import.meta);const css$q = /* css */`
24720
24694
  @layer navi {
24721
24695
  .navi_checkbox {
24722
24696
  --margin: 3px 3px 3px 4px;
@@ -25108,7 +25082,7 @@ const InputCheckboxDispatcher = props => {
25108
25082
  });
25109
25083
  };
25110
25084
  const InputCheckboxUI = props => {
25111
- 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"];
25112
25086
  const {
25113
25087
  ref,
25114
25088
  /* eslint-disable no-unused-vars */
@@ -25253,11 +25227,10 @@ const InputCheckboxUI = props => {
25253
25227
  children: [jsx("span", {
25254
25228
  className: "navi_checkbox_accent_probe",
25255
25229
  "aria-hidden": "true"
25256
- }), jsx(LoaderBackground, {
25230
+ }), jsx(LoadingOutline, {
25257
25231
  loading: innerLoading,
25258
25232
  inset: -1,
25259
- color: "var(--loader-color)",
25260
- targetSelector: ".navi_checkbox_field"
25233
+ color: "var(--loader-color)"
25261
25234
  }), visualVnode, renderCheckboxMemoized]
25262
25235
  });
25263
25236
  };
@@ -25510,7 +25483,7 @@ forwardRef((props, ref) => {
25510
25483
  });
25511
25484
  });
25512
25485
 
25513
- installImportMetaCssBuild(import.meta);const css$o = /* css */`
25486
+ installImportMetaCssBuild(import.meta);const css$p = /* css */`
25514
25487
  @layer navi {
25515
25488
  .navi_radio {
25516
25489
  --margin: 3px 3px 0 5px;
@@ -25864,7 +25837,7 @@ const InputRadioDispatcher = props => {
25864
25837
  });
25865
25838
  };
25866
25839
  const InputRadioUI = props => {
25867
- 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"];
25868
25841
  const {
25869
25842
  ref,
25870
25843
  /* eslint-disable no-unused-vars */
@@ -26029,12 +26002,10 @@ const InputRadioUI = props => {
26029
26002
  children: [jsx("span", {
26030
26003
  className: "navi_radio_accent_probe",
26031
26004
  "aria-hidden": "true"
26032
- }), jsx(LoaderBackground, {
26005
+ }), jsx(LoadingOutline, {
26033
26006
  loading: innerLoading,
26034
26007
  inset: -1,
26035
- targetSelector: ".navi_radio_field",
26036
- color: "var(--loader-color)",
26037
- borderRadius: appearance === "radio" ? "50%" : "inherit"
26008
+ color: "var(--loader-color)"
26038
26009
  }), visualVNode, renderRadioMemoized]
26039
26010
  });
26040
26011
  };
@@ -26096,7 +26067,7 @@ const InputRadioWithAction = () => {
26096
26067
  throw new Error(`<Input type="radio" /> with an action make no sense. Use <RadioList action={something} /> instead`);
26097
26068
  };
26098
26069
 
26099
- installImportMetaCssBuild(import.meta);const css$n = /* css */`
26070
+ installImportMetaCssBuild(import.meta);const css$o = /* css */`
26100
26071
  @layer navi {
26101
26072
  .navi_input_range {
26102
26073
  --border-radius: 6px;
@@ -26358,7 +26329,7 @@ const InputRangeDispatcher = props => {
26358
26329
  });
26359
26330
  };
26360
26331
  const InputRangeUI = props => {
26361
- 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"];
26362
26333
  const {
26363
26334
  ref,
26364
26335
  onInput,
@@ -26495,7 +26466,7 @@ const InputRangeUI = props => {
26495
26466
  children: [jsx("span", {
26496
26467
  className: "navi_input_range_accent_probe",
26497
26468
  "aria-hidden": "true"
26498
- }), jsx(LoaderBackground, {
26469
+ }), jsx(LoadingOutline, {
26499
26470
  loading: innerLoading,
26500
26471
  color: "var(--loader-color)",
26501
26472
  inset: -1
@@ -26635,7 +26606,7 @@ const SearchSvg = () => jsx("svg", {
26635
26606
  })
26636
26607
  });
26637
26608
 
26638
- installImportMetaCssBuild(import.meta);const css$m = /* css */`
26609
+ installImportMetaCssBuild(import.meta);const css$n = /* css */`
26639
26610
  @layer navi {
26640
26611
  .navi_separator {
26641
26612
  --size: 1px;
@@ -26675,7 +26646,7 @@ const Separator = ({
26675
26646
  vertical,
26676
26647
  ...props
26677
26648
  }) => {
26678
- import.meta.css = [css$m, "@jsenv/navi/src/layout/separator.jsx"];
26649
+ import.meta.css = [css$n, "@jsenv/navi/src/layout/separator.jsx"];
26679
26650
  return jsx(Box, {
26680
26651
  as: vertical ? "span" : "hr",
26681
26652
  ...props,
@@ -27087,7 +27058,7 @@ const RenderWindowContext = createContext(null);
27087
27058
  // Carries the separator element/function down to each ListItem so separators
27088
27059
  // are only rendered between items that actually mount (post-filter, post-window).
27089
27060
  const SeparatorContext = createContext(null);
27090
- const css$l = /* css */`
27061
+ const css$m = /* css */`
27091
27062
  @layer navi {
27092
27063
  .navi_list_container {
27093
27064
  --list-outline-width: 1px;
@@ -27514,7 +27485,7 @@ const ListDispatcher = props => {
27514
27485
  });
27515
27486
  };
27516
27487
  const ListUI = props => {
27517
- 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"];
27518
27489
  const {
27519
27490
  ref,
27520
27491
  renderBudget = RENDER_BUDGET_DEFAULT,
@@ -28993,7 +28964,7 @@ installImportMetaCssBuild(import.meta);/**
28993
28964
  * - <InputCheckbox /> for type="checkbox"
28994
28965
  * - <InputRadio /> for type="radio"
28995
28966
  */
28996
- const css$k = /* css */`
28967
+ const css$l = /* css */`
28997
28968
  @layer navi {
28998
28969
  .navi_input {
28999
28970
  --border-radius: 2px;
@@ -29247,7 +29218,7 @@ const InputTextualDispatcher = props => {
29247
29218
  };
29248
29219
  const InputNativeContext = createContext(null);
29249
29220
  const InputTextualUI = props => {
29250
- 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"];
29251
29222
  const {
29252
29223
  ref,
29253
29224
  type,
@@ -29392,7 +29363,7 @@ const InputTextualUI = props => {
29392
29363
  autoFocus: undefined // See use_auto_focus.js
29393
29364
  ,
29394
29365
 
29395
- children: [jsx(LoaderBackground, {
29366
+ children: [jsx(LoadingOutline, {
29396
29367
  loading: innerLoading,
29397
29368
  color: "var(--loader-color)",
29398
29369
  inset: -1
@@ -29868,7 +29839,7 @@ installImportMetaCssBuild(import.meta);/**
29868
29839
  * This means an editable thing MUST have a parent with position relative that wraps the content and the eventual editable input
29869
29840
  *
29870
29841
  */
29871
- const css$j = /* css */`
29842
+ const css$k = /* css */`
29872
29843
  .navi_editable_wrapper {
29873
29844
  --inset-top: 0px;
29874
29845
  --inset-right: 0px;
@@ -29917,7 +29888,7 @@ const useEditionController = () => {
29917
29888
  };
29918
29889
  };
29919
29890
  const Editable = props => {
29920
- 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"];
29921
29892
  let {
29922
29893
  children,
29923
29894
  action,
@@ -30331,7 +30302,7 @@ const FormWithAction = props => {
30331
30302
  // form.dispatchEvent(customEvent);
30332
30303
  // };
30333
30304
 
30334
- installImportMetaCssBuild(import.meta);const css$i = /* css */`
30305
+ installImportMetaCssBuild(import.meta);const css$j = /* css */`
30335
30306
  .navi_group {
30336
30307
  --border-width: 1px;
30337
30308
 
@@ -30428,7 +30399,7 @@ const Group = ({
30428
30399
  vertical = row,
30429
30400
  ...props
30430
30401
  }) => {
30431
- import.meta.css = [css$i, "@jsenv/navi/src/field/group.jsx"];
30402
+ import.meta.css = [css$j, "@jsenv/navi/src/field/group.jsx"];
30432
30403
  if (typeof borderWidth === "string") {
30433
30404
  borderWidth = parseFloat(borderWidth);
30434
30405
  }
@@ -30619,7 +30590,7 @@ const useCleanup = () => {
30619
30590
  return cleanupMethods;
30620
30591
  };
30621
30592
 
30622
- installImportMetaCssBuild(import.meta);const css$h = /* css */`
30593
+ installImportMetaCssBuild(import.meta);const css$i = /* css */`
30623
30594
  .navi_dialog {
30624
30595
  &[open] {
30625
30596
  display: flex;
@@ -30632,7 +30603,7 @@ installImportMetaCssBuild(import.meta);const css$h = /* css */`
30632
30603
  }
30633
30604
  `;
30634
30605
  const Dialog = props => {
30635
- import.meta.css = [css$h, "@jsenv/navi/src/popup/dialog.jsx"];
30606
+ import.meta.css = [css$i, "@jsenv/navi/src/popup/dialog.jsx"];
30636
30607
  const {
30637
30608
  children,
30638
30609
  scrollTrap,
@@ -30743,7 +30714,7 @@ const requestDialogClose = (popoverElement, {
30743
30714
  });
30744
30715
  };
30745
30716
 
30746
- installImportMetaCssBuild(import.meta);const css$g = /* css */`
30717
+ installImportMetaCssBuild(import.meta);const css$h = /* css */`
30747
30718
  .navi_popover_backdrop {
30748
30719
  position: fixed;
30749
30720
  inset: 0;
@@ -30759,7 +30730,7 @@ installImportMetaCssBuild(import.meta);const css$g = /* css */`
30759
30730
  }
30760
30731
  `;
30761
30732
  const Popover = props => {
30762
- import.meta.css = [css$g, "@jsenv/navi/src/popup/popover.jsx"];
30733
+ import.meta.css = [css$h, "@jsenv/navi/src/popup/popover.jsx"];
30763
30734
  const {
30764
30735
  scrollTrap,
30765
30736
  pointerTrap,
@@ -30961,7 +30932,7 @@ const requestPopoverClose = (popoverElement, {
30961
30932
  });
30962
30933
  };
30963
30934
 
30964
- installImportMetaCssBuild(import.meta);const css$f = /* css */`
30935
+ installImportMetaCssBuild(import.meta);const css$g = /* css */`
30965
30936
  @layer navi {
30966
30937
  .navi_select {
30967
30938
  --select-border-radius: 2px;
@@ -31309,7 +31280,7 @@ const SelectDispatcher = props => {
31309
31280
  });
31310
31281
  };
31311
31282
  const SelectUI = props => {
31312
- import.meta.css = [css$f, "@jsenv/navi/src/field/select.jsx"];
31283
+ import.meta.css = [css$g, "@jsenv/navi/src/field/select.jsx"];
31313
31284
  const {
31314
31285
  placeholder = "Select…",
31315
31286
  trigger,
@@ -31359,7 +31330,7 @@ const SelectUI = props => {
31359
31330
  },
31360
31331
  pseudoClasses: SelectPseudoClasses,
31361
31332
  pseudoElements: SelectPseudoElements,
31362
- children: [jsx(LoaderBackground, {
31333
+ children: [jsx(LoadingOutline, {
31363
31334
  loading: innerLoading,
31364
31335
  color: "var(--loader-color)",
31365
31336
  inset: -1
@@ -32501,7 +32472,7 @@ const Z_INDEX_DROP_PREVIEW = Z_INDEX_STICKY_CORNER + 1;
32501
32472
 
32502
32473
  const Z_INDEX_TABLE_UI = Z_INDEX_STICKY_CORNER + 1;
32503
32474
 
32504
- installImportMetaCssBuild(import.meta);const css$e = /* css */`
32475
+ installImportMetaCssBuild(import.meta);const css$f = /* css */`
32505
32476
  .navi_table_drag_clone_container {
32506
32477
  position: absolute;
32507
32478
  top: var(--table-visual-top);
@@ -32681,7 +32652,7 @@ const moveItem = (array, indexA, indexB) => {
32681
32652
  return newArray;
32682
32653
  };
32683
32654
  const TableDragCloneContainer = forwardRef((props, ref) => {
32684
- 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"];
32685
32656
  const {
32686
32657
  tableId
32687
32658
  } = props;
@@ -32979,7 +32950,7 @@ installImportMetaCssBuild(import.meta);const ROW_MIN_HEIGHT = 30;
32979
32950
  const ROW_MAX_HEIGHT = 100;
32980
32951
  const COLUMN_MIN_WIDTH = 50;
32981
32952
  const COLUMN_MAX_WIDTH = 500;
32982
- const css$d = /* css */`
32953
+ const css$e = /* css */`
32983
32954
  @layer navi {
32984
32955
  .navi_table {
32985
32956
  --table-resizer-handle-color: #063b7c;
@@ -33139,7 +33110,7 @@ const css$d = /* css */`
33139
33110
 
33140
33111
  // Column resize components
33141
33112
  const TableColumnResizer = props => {
33142
- 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"];
33143
33114
  const defaultRef = useRef();
33144
33115
  const ref = props.ref || defaultRef;
33145
33116
  return jsxs("div", {
@@ -33606,7 +33577,7 @@ const findPreviousTableRow = currentRow => {
33606
33577
  return currentIndex > 0 ? allRows[currentIndex - 1] : null;
33607
33578
  };
33608
33579
 
33609
- installImportMetaCssBuild(import.meta);const css$c = /* css */`
33580
+ installImportMetaCssBuild(import.meta);const css$d = /* css */`
33610
33581
  @layer navi {
33611
33582
  .navi_table {
33612
33583
  --selection-border-color: var(--navi-selection-border-color, #0078d4);
@@ -33708,7 +33679,7 @@ const useTableSelectionController = ({
33708
33679
  onSelectionChange,
33709
33680
  selectionColor
33710
33681
  }) => {
33711
- 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"];
33712
33683
  const selectionController = useSelectionController({
33713
33684
  elementRef: tableRef,
33714
33685
  layout: "grid",
@@ -34179,7 +34150,7 @@ const useTableStickyContextValue = ({
34179
34150
  };
34180
34151
 
34181
34152
  installImportMetaCssBuild(import.meta);// TODO: sticky left/top frontier should likely use "followPosition"
34182
- const css$b = /* css */`
34153
+ const css$c = /* css */`
34183
34154
  @layer navi {
34184
34155
  .navi_table {
34185
34156
  --sticky-frontier-color: #c0c0c0;
@@ -34422,7 +34393,7 @@ const css$b = /* css */`
34422
34393
  const TableStickyFrontier = ({
34423
34394
  tableRef
34424
34395
  }) => {
34425
- 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"];
34426
34397
  const stickyLeftFrontierGhostRef = useRef();
34427
34398
  const stickyLeftFrontierPreviewRef = useRef();
34428
34399
  const stickyTopFrontierGhostRef = useRef();
@@ -34651,7 +34622,7 @@ const initMoveStickyFrontierViaPointer = (pointerdownEvent, {
34651
34622
  * inset 0 -1px 0 0 color; // Bottom border
34652
34623
  */
34653
34624
 
34654
- const css$a = /* css */ `
34625
+ const css$b = /* css */ `
34655
34626
  .navi_table_root {
34656
34627
  position: relative;
34657
34628
  max-width: var(--table-max-width, none);
@@ -34854,7 +34825,7 @@ const css$a = /* css */ `
34854
34825
  }
34855
34826
  `;
34856
34827
 
34857
- installImportMetaCssBuild(import.meta);const css$9 = /* css */`
34828
+ installImportMetaCssBuild(import.meta);const css$a = /* css */`
34858
34829
  .navi_table_ui {
34859
34830
  position: fixed;
34860
34831
  inset: 0;
@@ -34865,7 +34836,7 @@ installImportMetaCssBuild(import.meta);const css$9 = /* css */`
34865
34836
  }
34866
34837
  `;
34867
34838
  const TableUI = forwardRef((props, ref) => {
34868
- 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"];
34869
34840
  const {
34870
34841
  tableRef,
34871
34842
  tableId,
@@ -34971,7 +34942,7 @@ const RowIndexContext = createContext();
34971
34942
  const TableSectionContext = createContext();
34972
34943
  const useIsInTableHead = () => useContext(TableSectionContext) === "head";
34973
34944
  const Table = props => {
34974
- 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"];
34975
34946
  const tableDefaultRef = useRef();
34976
34947
  const tableDefaultId = `table-${useId()}`;
34977
34948
  const {
@@ -35868,7 +35839,7 @@ const KeyboardShortcutAriaElement = ({
35868
35839
  });
35869
35840
  };
35870
35841
 
35871
- installImportMetaCssBuild(import.meta);const css$8 = /* css */`
35842
+ installImportMetaCssBuild(import.meta);const css$9 = /* css */`
35872
35843
  @layer navi {
35873
35844
  .navi_clipboard_container {
35874
35845
  --height: 1.5em;
@@ -35900,7 +35871,7 @@ const ButtonCopyToClipboard = ({
35900
35871
  children,
35901
35872
  ...props
35902
35873
  }) => {
35903
- 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"];
35904
35875
  const [copied, setCopied] = useState(false);
35905
35876
  const renderedRef = useRef();
35906
35877
  useEffect(() => {
@@ -35981,7 +35952,7 @@ const Address = ({
35981
35952
  });
35982
35953
  };
35983
35954
 
35984
- installImportMetaCssBuild(import.meta);const css$7 = /* css */`
35955
+ installImportMetaCssBuild(import.meta);const css$8 = /* css */`
35985
35956
  @layer navi {
35986
35957
  }
35987
35958
  .navi_badge {
@@ -36015,7 +35986,7 @@ const Badge = ({
36015
35986
  className,
36016
35987
  ...props
36017
35988
  }) => {
36018
- import.meta.css = [css$7, "@jsenv/navi/src/text/badge.jsx"];
35989
+ import.meta.css = [css$8, "@jsenv/navi/src/text/badge.jsx"];
36019
35990
  const defaultRef = useRef();
36020
35991
  const ref = props.ref || defaultRef;
36021
35992
  useAccentColorAttributes(ref, null);
@@ -36040,7 +36011,7 @@ const BadgeStyleCSSVars$1 = {
36040
36011
  fontSize: "--font-size"
36041
36012
  };
36042
36013
 
36043
- const LoadingDots = () => {
36014
+ const LoadingDotsSvg = () => {
36044
36015
  return jsxs("svg", {
36045
36016
  viewBox: "0 0 200 200",
36046
36017
  width: "100%",
@@ -36105,7 +36076,7 @@ const formatNumber = (value, { lang } = {}) => {
36105
36076
  return new Intl.NumberFormat(lang).format(value);
36106
36077
  };
36107
36078
 
36108
- installImportMetaCssBuild(import.meta);const css$6 = /* css */`
36079
+ installImportMetaCssBuild(import.meta);const css$7 = /* css */`
36109
36080
  @layer navi {
36110
36081
  }
36111
36082
  .navi_text.navi_badge_count {
@@ -36218,7 +36189,7 @@ const BadgeCount = ({
36218
36189
  lineLayout,
36219
36190
  ...props
36220
36191
  }) => {
36221
- 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"];
36222
36193
  const defaultRef = useRef();
36223
36194
  const ref = props.ref || defaultRef;
36224
36195
  useAccentColorAttributes(ref, null);
@@ -36321,7 +36292,7 @@ const BadgeCountEllipse = ({
36321
36292
  styleCSSVars: BadgeStyleCSSVars,
36322
36293
  spacing: "pre",
36323
36294
  children: loading ? jsx(Icon, {
36324
- children: jsx(LoadingDots, {})
36295
+ children: jsx(LoadingDotsSvg, {})
36325
36296
  }) : children
36326
36297
  });
36327
36298
  };
@@ -36349,7 +36320,7 @@ const BadgeCountCircle = ({
36349
36320
  styleCSSVars: BadgeStyleCSSVars,
36350
36321
  spacing: "pre",
36351
36322
  children: loading ? jsx(Icon, {
36352
- children: jsx(LoadingDots, {})
36323
+ children: jsx(LoadingDotsSvg, {})
36353
36324
  }) : jsx("span", {
36354
36325
  className: "navi_badge_count_text",
36355
36326
  children: children
@@ -36357,7 +36328,7 @@ const BadgeCountCircle = ({
36357
36328
  });
36358
36329
  };
36359
36330
 
36360
- installImportMetaCssBuild(import.meta);const css$5 = /* css */`
36331
+ installImportMetaCssBuild(import.meta);const css$6 = /* css */`
36361
36332
  @layer navi {
36362
36333
  .navi_caption {
36363
36334
  --color: #6b7280;
@@ -36378,7 +36349,7 @@ const Caption = ({
36378
36349
  className,
36379
36350
  ...rest
36380
36351
  }) => {
36381
- import.meta.css = [css$5, "@jsenv/navi/src/text/caption.jsx"];
36352
+ import.meta.css = [css$6, "@jsenv/navi/src/text/caption.jsx"];
36382
36353
  return jsx(Text, {
36383
36354
  as: "small",
36384
36355
  size: "0.8em" // We use em to be relative to the parent (we want to be smaller than the surrounding text)
@@ -36855,7 +36826,7 @@ const interpolate = (template, values) => {
36855
36826
  });
36856
36827
  };
36857
36828
 
36858
- installImportMetaCssBuild(import.meta);const css$4 = /* css */`
36829
+ installImportMetaCssBuild(import.meta);const css$5 = /* css */`
36859
36830
  @layer navi {
36860
36831
  .navi_quantity {
36861
36832
  --unit-color: color-mix(in srgb, currentColor 50%, white);
@@ -36960,7 +36931,7 @@ const Quantity = ({
36960
36931
  bold = true,
36961
36932
  ...props
36962
36933
  }) => {
36963
- import.meta.css = [css$4, "@jsenv/navi/src/text/quantity.jsx"];
36934
+ import.meta.css = [css$5, "@jsenv/navi/src/text/quantity.jsx"];
36964
36935
  const value = parseQuantityValue(children);
36965
36936
  const valueRounded = integer && typeof value === "number" ? Math.round(value) : value;
36966
36937
  const valueFormatted = typeof valueRounded === "number" ? formatNumber(valueRounded, {
@@ -36990,8 +36961,8 @@ const Quantity = ({
36990
36961
  children: [jsx("span", {
36991
36962
  className: "navi_quantity_value",
36992
36963
  children: loading ? jsx(Icon, {
36993
- flowInline: true,
36994
- children: jsx(LoadingDots, {})
36964
+ inline: true,
36965
+ children: jsx(LoadingDotsSvg, {})
36995
36966
  }) : valueFormatted
36996
36967
  }), unit && jsx(Unit, {
36997
36968
  value: value,
@@ -37049,7 +37020,7 @@ const parseQuantityValue = children => {
37049
37020
  return Number.isNaN(parsed) ? children : parsed;
37050
37021
  };
37051
37022
 
37052
- installImportMetaCssBuild(import.meta);const css$3 = /* css */`
37023
+ installImportMetaCssBuild(import.meta);const css$4 = /* css */`
37053
37024
  @layer navi {
37054
37025
  .navi_meter {
37055
37026
  --loader-color: var(--navi-loader-color);
@@ -37129,8 +37100,8 @@ installImportMetaCssBuild(import.meta);const css$3 = /* css */`
37129
37100
  }
37130
37101
 
37131
37102
  &[data-accent-needs-dark-fg] {
37132
- --x-color: white;
37133
- --x-shadow-color: black;
37103
+ --x-color: black;
37104
+ --x-shadow-color: white;
37134
37105
  }
37135
37106
 
37136
37107
  /* When caption is shown, the track takes the full height */
@@ -37187,7 +37158,7 @@ const Meter = ({
37187
37158
  style,
37188
37159
  ...rest
37189
37160
  }) => {
37190
- import.meta.css = [css$3, "@jsenv/navi/src/text/meter.jsx"];
37161
+ import.meta.css = [css$4, "@jsenv/navi/src/text/meter.jsx"];
37191
37162
  const defaultRef = useRef();
37192
37163
  const ref = rest.ref || defaultRef;
37193
37164
  value = Number(value);
@@ -37250,7 +37221,7 @@ const Meter = ({
37250
37221
  ...rest,
37251
37222
  children: jsxs("span", {
37252
37223
  className: "navi_meter_track_container",
37253
- children: [jsx(LoaderBackground, {
37224
+ children: [jsx(LoadingOutline, {
37254
37225
  loading: loading,
37255
37226
  color: "var(--loader-color)",
37256
37227
  inset: -1
@@ -37314,10 +37285,100 @@ const Paragraph = props => {
37314
37285
  });
37315
37286
  };
37316
37287
 
37317
- 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
+ }
37318
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,
37319
37380
  ...props,
37320
- as: "img"
37381
+ children: jsx(LoadingIndicatorFluid, {})
37321
37382
  });
37322
37383
  };
37323
37384
 
@@ -37911,5 +37972,5 @@ const UserSvg = () => jsx("svg", {
37911
37972
  })
37912
37973
  });
37913
37974
 
37914
- 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 };
37915
37976
  //# sourceMappingURL=jsenv_navi.js.map