@jsenv/navi 0.11.6 → 0.11.8

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,3 +1,4 @@
1
+ import { installImportMetaCss } from "./jsenv_navi_side_effects.js";
1
2
  import { createIterableWeakSet, createPubSub, createValueEffect, createStyleController, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, allowWheelThrough, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, activeElementSignal, canInterceptKeys, initUITransition, getElementSignature, resolveCSSSize, normalizeStyles, appendStyles, findBefore, findAfter, initFocusGroup, elementIsFocusable, pickLightOrDark, dragAfterThreshold, getScrollContainer, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement } from "@jsenv/dom";
2
3
  import { prefixFirstAndIndentRemainingLines } from "@jsenv/humanize";
3
4
  import { effect, signal, computed, batch, useSignal } from "@preact/signals";
@@ -6,42 +7,6 @@ import { createContext, createRef, toChildArray, cloneElement } from "preact";
6
7
  import { jsx, jsxs, Fragment } from "preact/jsx-runtime";
7
8
  import { forwardRef, createPortal } from "preact/compat";
8
9
 
9
- const installImportMetaCss = (importMeta) => {
10
- const stylesheet = new CSSStyleSheet({ baseUrl: importMeta.url });
11
-
12
- let called = false;
13
- // eslint-disable-next-line accessor-pairs
14
- Object.defineProperty(importMeta, "css", {
15
- configurable: true,
16
- set(value) {
17
- if (called) {
18
- throw new Error("import.meta.css setter can only be called once");
19
- }
20
- called = true;
21
- stylesheet.replaceSync(value);
22
- document.adoptedStyleSheets = [
23
- ...document.adoptedStyleSheets,
24
- stylesheet,
25
- ];
26
- },
27
- });
28
- };
29
-
30
- installImportMetaCss(import.meta);import.meta.css = /* css */ `
31
- @layer navi {
32
- :root {
33
- --navi-background-color-readonly: #d3d3d3;
34
- --navi-color-readonly: grey;
35
- --navi-background-color-disabled: #d3d3d3;
36
- --navi-color-disabled: #eeeeee;
37
-
38
- --navi-info-color: #2196f3;
39
- --navi-warning-color: #ff9800;
40
- --navi-error-color: #f44336;
41
- }
42
- }
43
- `;
44
-
45
10
  const actionPrivatePropertiesWeakMap = new WeakMap();
46
11
  const getActionPrivateProperties = (action) => {
47
12
  const actionPrivateProperties = actionPrivatePropertiesWeakMap.get(action);
@@ -7682,7 +7647,11 @@ const createRoute = (urlPatternInput) => {
7682
7647
  let relativeUrl = urlPatternInput;
7683
7648
  let hasRawUrlPartWithInvalidChars = false;
7684
7649
 
7685
- const encode = (value) => {
7650
+ // Encode parameter values for URL usage, with special handling for raw URL parts.
7651
+ // When a parameter is wrapped with rawUrlPart(), it bypasses encoding and is
7652
+ // inserted as-is into the URL. This allows including pre-encoded values or
7653
+ // special characters that should not be percent-encoded.
7654
+ const encodeParamValue = (value) => {
7686
7655
  if (value && value[rawUrlPartSymbol]) {
7687
7656
  const rawValue = value.value;
7688
7657
  // Check if raw value contains invalid URL characters
@@ -7700,7 +7669,7 @@ const createRoute = (urlPatternInput) => {
7700
7669
  // Replace named parameters (:param and {param})
7701
7670
  for (const key of keys) {
7702
7671
  const value = params[key];
7703
- const encodedValue = encode(value);
7672
+ const encodedValue = encodeParamValue(value);
7704
7673
  const beforeReplace = relativeUrl;
7705
7674
  relativeUrl = relativeUrl.replace(`:${key}`, encodedValue);
7706
7675
  relativeUrl = relativeUrl.replace(`{${key}}`, encodedValue);
@@ -7724,7 +7693,7 @@ const createRoute = (urlPatternInput) => {
7724
7693
  if (paramValue) {
7725
7694
  extraParamSet.delete(paramKey);
7726
7695
  }
7727
- const replacement = paramValue ? encode(paramValue) : "*";
7696
+ const replacement = paramValue ? encodeParamValue(paramValue) : "*";
7728
7697
  wildcardIndex++;
7729
7698
  return replacement;
7730
7699
  });
@@ -7733,15 +7702,17 @@ const createRoute = (urlPatternInput) => {
7733
7702
  // Add remaining parameters as search params
7734
7703
  if (extraParamSet.size > 0) {
7735
7704
  if (extraParamEffect === "inject_as_search_param") {
7736
- const searchParams = new URLSearchParams();
7705
+ const searchParamPairs = [];
7737
7706
  for (const key of extraParamSet) {
7738
7707
  const value = params[key];
7739
7708
  if (value !== undefined && value !== null) {
7740
- searchParams.append(key, value);
7709
+ const encodedKey = encodeURIComponent(key);
7710
+ const encodedValue = encodeParamValue(value);
7711
+ searchParamPairs.push(`${encodedKey}=${encodedValue}`);
7741
7712
  }
7742
7713
  }
7743
- const searchString = searchParams.toString();
7744
- if (searchString) {
7714
+ if (searchParamPairs.length > 0) {
7715
+ const searchString = searchParamPairs.join("&");
7745
7716
  relativeUrl += (relativeUrl.includes("?") ? "&" : "?") + searchString;
7746
7717
  }
7747
7718
  } else if (extraParamEffect === "warn") {
@@ -7757,6 +7728,25 @@ const createRoute = (urlPatternInput) => {
7757
7728
  hasRawUrlPartWithInvalidChars,
7758
7729
  };
7759
7730
  };
7731
+
7732
+ /**
7733
+ * Builds a complete URL for this route with the given parameters.
7734
+ *
7735
+ * Takes parameters and substitutes them into the route's URL pattern,
7736
+ * automatically URL-encoding values unless wrapped with rawUrlPart().
7737
+ * Extra parameters not in the pattern are added as search parameters.
7738
+ *
7739
+ * @param {Object} params - Parameters to substitute into the URL pattern
7740
+ * @returns {string} Complete URL with base URL and encoded parameters
7741
+ *
7742
+ * @example
7743
+ * // For a route with pattern "/items/:id"
7744
+ * // Normal parameter encoding
7745
+ * route.buildUrl({ id: "hello world" }) // → "https://example.com/items/hello%20world"
7746
+ * // Raw parameter (no encoding)
7747
+ * route.buildUrl({ id: rawUrlPart("hello world") }) // → "https://example.com/items/hello world"
7748
+ *
7749
+ */
7760
7750
  const buildUrl = (params = {}) => {
7761
7751
  const { relativeUrl, hasRawUrlPartWithInvalidChars } =
7762
7752
  buildRelativeUrl(params);
@@ -8117,6 +8107,62 @@ const updateDocumentUrl = (value) => {
8117
8107
  documentUrlSignal.value = value;
8118
8108
  };
8119
8109
 
8110
+ const getLinkTargetInfo = (href) => {
8111
+ href = String(href);
8112
+
8113
+ if (!href || href.trim() === "") {
8114
+ return {
8115
+ targetIsEmpty: true,
8116
+ targetIsCurrent: false,
8117
+ targetIsAnchor: false,
8118
+ targetIsSameOrigin: true,
8119
+ targetIsSameSite: true,
8120
+ };
8121
+ }
8122
+
8123
+ const currentUrl = new URL(window.location.href);
8124
+ const targetUrl = new URL(href, window.location.href);
8125
+
8126
+ let targetIsCurrent = false;
8127
+ {
8128
+ targetIsCurrent = currentUrl.href === targetUrl.href;
8129
+ }
8130
+ let targetIsAnchor = false;
8131
+ {
8132
+ if (
8133
+ currentUrl.pathname === targetUrl.pathname &&
8134
+ currentUrl.search === targetUrl.search &&
8135
+ targetUrl.hash !== ""
8136
+ ) {
8137
+ targetIsAnchor = true;
8138
+ }
8139
+ }
8140
+ let targetIsSameOrigin = false;
8141
+ {
8142
+ const currentOrigin = currentUrl.origin;
8143
+ const targetOrigin = targetUrl.origin;
8144
+ targetIsSameOrigin = currentOrigin === targetOrigin;
8145
+ }
8146
+ let targetIsSameSite = false;
8147
+ {
8148
+ const baseDomain = (hostname) => {
8149
+ const parts = hostname.split(".").slice(-2);
8150
+ return parts.join(".");
8151
+ };
8152
+ const currentDomain = baseDomain(currentUrl.hostname);
8153
+ const targetDomain = baseDomain(targetUrl.hostname);
8154
+ targetIsSameSite = currentDomain === targetDomain;
8155
+ }
8156
+
8157
+ return {
8158
+ targetIsEmpty: false,
8159
+ targetIsCurrent,
8160
+ targetIsAnchor,
8161
+ targetIsSameOrigin,
8162
+ targetIsSameSite,
8163
+ };
8164
+ };
8165
+
8120
8166
  const setupBrowserIntegrationViaHistory = ({
8121
8167
  applyActions,
8122
8168
  applyRouting,
@@ -8236,20 +8282,18 @@ const setupBrowserIntegrationViaHistory = ({
8236
8282
  if (!linkElement) {
8237
8283
  return;
8238
8284
  }
8239
- const href = linkElement.href;
8240
- if (!href || !href.startsWith(window.location.origin)) {
8241
- return;
8242
- }
8243
8285
  if (linkElement.hasAttribute("data-readonly")) {
8244
8286
  return;
8245
8287
  }
8246
- // Ignore anchor navigation (same page, different hash)
8247
- const currentUrl = new URL(window.location.href);
8248
- const targetUrl = new URL(href);
8288
+ const href = linkElement.href;
8289
+ const { targetIsEmpty, targetIsSameOrigin, targetIsAnchor } =
8290
+ getLinkTargetInfo(href);
8249
8291
  if (
8250
- currentUrl.pathname === targetUrl.pathname &&
8251
- currentUrl.search === targetUrl.search &&
8252
- targetUrl.hash !== ""
8292
+ targetIsEmpty ||
8293
+ // Let link to other origins be handled by the browser
8294
+ !targetIsSameOrigin ||
8295
+ // Ignore anchor navigation (same page, different hash)
8296
+ targetIsAnchor
8253
8297
  ) {
8254
8298
  return;
8255
8299
  }
@@ -8806,18 +8850,23 @@ const initRouteObserver = ({
8806
8850
  isComposite: true,
8807
8851
  active: false,
8808
8852
  subscribeStatus: subscribeCompositeStatus,
8809
- toString: () => `composite(${candidateSet.size} candidates)`
8853
+ toString: () => `composite(${candidateSet.size} candidates)`,
8854
+ routeFromProps: route,
8855
+ elementFromProps: element
8810
8856
  };
8811
8857
  const findActiveChildInfo = () => {
8812
8858
  let fallbackInfo = null;
8813
8859
  for (const candidate of candidateSet) {
8814
- if (candidate.route.active) {
8860
+ if (candidate.route?.active) {
8815
8861
  return {
8816
8862
  ChildActiveElement: candidate.ActiveElement,
8817
8863
  route: candidate.route
8818
8864
  };
8819
8865
  }
8820
- if (candidate.fallback) {
8866
+ // fallback without route can match when no other route matches.
8867
+ // This is useful solely for "catch all" fallback used on the <Routes>
8868
+ // otherwise a fallback would always match and make the parent route always active
8869
+ if (candidate.fallback && !candidate.route.routeFromProps) {
8821
8870
  fallbackInfo = {
8822
8871
  ChildActiveElement: candidate.ActiveElement,
8823
8872
  route: candidate.route
@@ -8852,7 +8901,8 @@ const initRouteObserver = ({
8852
8901
  const activeRouteSignal = signal();
8853
8902
  const SlotActiveElementSignal = signal();
8854
8903
  const ActiveElement = () => {
8855
- useContentKey(activeRouteSignal.value.urlPattern);
8904
+ const activeRoute = activeRouteSignal.value;
8905
+ useContentKey(activeRoute?.urlPattern);
8856
8906
  const SlotActiveElement = SlotActiveElementSignal.value;
8857
8907
  if (typeof element === "function") {
8858
8908
  const Element = element;
@@ -9807,54 +9857,57 @@ const withPropsStyle = (
9807
9857
  {
9808
9858
  marginStyles = {};
9809
9859
  if (margin !== undefined) {
9810
- marginStyles.margin = spacingSizes[margin] || margin;
9860
+ marginStyles.margin = sizeSpacingScale[margin] || margin;
9811
9861
  }
9812
9862
  if (marginLeft !== undefined) {
9813
- marginStyles.marginLeft = spacingSizes[marginLeft] || marginLeft;
9863
+ marginStyles.marginLeft = sizeSpacingScale[marginLeft] || marginLeft;
9814
9864
  } else if (marginX !== undefined) {
9815
- marginStyles.marginLeft = spacingSizes[marginX] || marginX;
9865
+ marginStyles.marginLeft = sizeSpacingScale[marginX] || marginX;
9816
9866
  }
9817
9867
  if (marginRight !== undefined) {
9818
- marginStyles.marginRight = spacingSizes[marginRight] || marginRight;
9868
+ marginStyles.marginRight = sizeSpacingScale[marginRight] || marginRight;
9819
9869
  } else if (marginX !== undefined) {
9820
- marginStyles.marginRight = spacingSizes[marginX] || marginX;
9870
+ marginStyles.marginRight = sizeSpacingScale[marginX] || marginX;
9821
9871
  }
9822
9872
  if (marginTop !== undefined) {
9823
- marginStyles.marginTop = spacingSizes[marginTop] || marginTop;
9873
+ marginStyles.marginTop = sizeSpacingScale[marginTop] || marginTop;
9824
9874
  } else if (marginY !== undefined) {
9825
- marginStyles.marginTop = spacingSizes[marginY] || marginY;
9875
+ marginStyles.marginTop = sizeSpacingScale[marginY] || marginY;
9826
9876
  }
9827
9877
  if (marginBottom !== undefined) {
9828
- marginStyles.marginBottom = spacingSizes[marginBottom] || marginBottom;
9878
+ marginStyles.marginBottom =
9879
+ sizeSpacingScale[marginBottom] || marginBottom;
9829
9880
  } else if (marginY !== undefined) {
9830
- marginStyles.marginBottom = spacingSizes[marginY] || marginY;
9881
+ marginStyles.marginBottom = sizeSpacingScale[marginY] || marginY;
9831
9882
  }
9832
9883
  }
9833
9884
  {
9834
9885
  paddingStyles = {};
9835
9886
  if (padding !== undefined) {
9836
- paddingStyles.padding = spacingSizes[padding] || padding;
9887
+ paddingStyles.padding = sizeSpacingScale[padding] || padding;
9837
9888
  }
9838
9889
  if (paddingLeft !== undefined) {
9839
- paddingStyles.paddingLeft = spacingSizes[paddingLeft] || paddingLeft;
9890
+ paddingStyles.paddingLeft =
9891
+ sizeSpacingScale[paddingLeft] || paddingLeft;
9840
9892
  } else if (paddingX !== undefined) {
9841
- paddingStyles.paddingLeft = spacingSizes[paddingX] || paddingX;
9893
+ paddingStyles.paddingLeft = sizeSpacingScale[paddingX] || paddingX;
9842
9894
  }
9843
9895
  if (paddingRight !== undefined) {
9844
- paddingStyles.paddingRight = spacingSizes[paddingRight] || paddingRight;
9896
+ paddingStyles.paddingRight =
9897
+ sizeSpacingScale[paddingRight] || paddingRight;
9845
9898
  } else if (paddingX !== undefined) {
9846
- paddingStyles.paddingRight = spacingSizes[paddingX] || paddingX;
9899
+ paddingStyles.paddingRight = sizeSpacingScale[paddingX] || paddingX;
9847
9900
  }
9848
9901
  if (paddingTop !== undefined) {
9849
- paddingStyles.paddingTop = spacingSizes[paddingTop] || paddingTop;
9902
+ paddingStyles.paddingTop = sizeSpacingScale[paddingTop] || paddingTop;
9850
9903
  } else if (paddingY !== undefined) {
9851
- paddingStyles.paddingTop = spacingSizes[paddingY] || paddingY;
9904
+ paddingStyles.paddingTop = sizeSpacingScale[paddingY] || paddingY;
9852
9905
  }
9853
9906
  if (paddingBottom !== undefined) {
9854
9907
  paddingStyles.paddingBottom =
9855
- spacingSizes[paddingBottom] || paddingBottom;
9908
+ sizeSpacingScale[paddingBottom] || paddingBottom;
9856
9909
  } else if (paddingY !== undefined) {
9857
- paddingStyles.paddingBottom = spacingSizes[paddingY] || paddingY;
9910
+ paddingStyles.paddingBottom = sizeSpacingScale[paddingY] || paddingY;
9858
9911
  }
9859
9912
  }
9860
9913
  }
@@ -9958,7 +10011,7 @@ const withPropsStyle = (
9958
10011
  if (textSize) {
9959
10012
  const fontSize =
9960
10013
  typeof textSize === "string"
9961
- ? typoSizes[textSize] || textSize
10014
+ ? sizeTypoScale[textSize] || textSize
9962
10015
  : textSize;
9963
10016
  typoStyles.fontSize = fontSize;
9964
10017
  }
@@ -10043,9 +10096,18 @@ const withPropsStyle = (
10043
10096
  };
10044
10097
 
10045
10098
  // Unified design scale using t-shirt sizes with rem units for accessibility.
10046
- // This scale is used for both typography and spacing to create visual harmony
10099
+ // This scale is used for spacing to create visual harmony
10047
10100
  // and consistent proportions throughout the design system.
10048
- const tshirtSizeToCSSValues = {
10101
+ const sizeSpacingScale = {
10102
+ xxs: "0.125rem", // 0.125 = 2px at 16px base
10103
+ xs: "0.25rem", // 0.25 = 4px at 16px base
10104
+ sm: "0.5rem", // 0.5 = 8px at 16px base
10105
+ md: "1rem", // 1 = 16px at 16px base (base font size)
10106
+ lg: "1.5rem", // 1.5 = 24px at 16px base
10107
+ xl: "2rem", // 2 = 32px at 16px base
10108
+ xxl: "3rem", // 3 = 48px at 16px base
10109
+ };
10110
+ const sizeTypoScale = {
10049
10111
  xxs: "0.625rem", // 0.625 = 10px at 16px base (smaller than before for more range)
10050
10112
  xs: "0.75rem", // 0.75 = 12px at 16px base
10051
10113
  sm: "0.875rem", // 0.875 = 14px at 16px base
@@ -10055,12 +10117,6 @@ const tshirtSizeToCSSValues = {
10055
10117
  xxl: "1.5rem", // 1.5 = 24px at 16px base
10056
10118
  };
10057
10119
 
10058
- // Typography and spacing use the same scale for consistent visual rhythm.
10059
- // When text size is "lg", using "lg" spacing creates naturally proportioned layouts.
10060
- // All values scale with user font preferences for better accessibility.
10061
- const typoSizes = tshirtSizeToCSSValues;
10062
- const spacingSizes = tshirtSizeToCSSValues;
10063
-
10064
10120
  const DEBUG = {
10065
10121
  registration: false,
10066
10122
  // Element registration/unregistration
@@ -11347,6 +11403,59 @@ const createSelectionKeyboardShortcuts = (selectionController, {
11347
11403
  }];
11348
11404
  };
11349
11405
 
11406
+ installImportMetaCss(import.meta);import.meta.css = /* css */`
11407
+ :root {
11408
+ --navi-icon-align-y: center;
11409
+ }
11410
+
11411
+ .navi_text {
11412
+ display: inline-flex;
11413
+ align-items: baseline;
11414
+ gap: 0.1em;
11415
+ }
11416
+
11417
+ .navi_icon {
11418
+ --align-y: var(--navi-icon-align-y, center);
11419
+
11420
+ display: inline-flex;
11421
+ width: 1em;
11422
+ height: 1em;
11423
+ flex-shrink: 0;
11424
+ align-self: var(--align-y);
11425
+ line-height: 1em;
11426
+ }
11427
+ `;
11428
+ const Text = ({
11429
+ children,
11430
+ ...rest
11431
+ }) => {
11432
+ const [remainingProps, innerStyle] = withPropsStyle(rest, {
11433
+ layout: true,
11434
+ typo: true
11435
+ });
11436
+ return jsx("span", {
11437
+ ...remainingProps,
11438
+ className: "navi_text",
11439
+ style: innerStyle,
11440
+ children: children
11441
+ });
11442
+ };
11443
+ const Icon = ({
11444
+ children,
11445
+ ...rest
11446
+ }) => {
11447
+ const [remainingProps, innerStyle] = withPropsStyle(rest, {
11448
+ layout: true,
11449
+ typo: true
11450
+ });
11451
+ return jsx("span", {
11452
+ ...remainingProps,
11453
+ className: "navi_icon",
11454
+ style: innerStyle,
11455
+ children: children
11456
+ });
11457
+ };
11458
+
11350
11459
  // autoFocus does not work so we focus in a useLayoutEffect,
11351
11460
  // see https://github.com/preactjs/preact/issues/1255
11352
11461
 
@@ -11443,6 +11552,9 @@ const useAutoFocus = (
11443
11552
 
11444
11553
  installImportMetaCss(import.meta);import.meta.css = /* css */`
11445
11554
  .navi_link {
11555
+ position: relative;
11556
+ display: inline-flex;
11557
+ gap: 0.1em;
11446
11558
  border-radius: 2px;
11447
11559
  }
11448
11560
  /* Focus */
@@ -11514,8 +11626,13 @@ const LinkPlain = forwardRef((props, ref) => {
11514
11626
  onClick,
11515
11627
  onKeyDown,
11516
11628
  href,
11629
+ target,
11630
+ rel,
11517
11631
  // visual
11518
11632
  className,
11633
+ blankTargetIcon,
11634
+ anchorIcon,
11635
+ icon,
11519
11636
  ...rest
11520
11637
  } = props;
11521
11638
  const innerRef = useRef();
@@ -11530,18 +11647,43 @@ const LinkPlain = forwardRef((props, ref) => {
11530
11647
  layout: true,
11531
11648
  typo: true
11532
11649
  });
11650
+ const {
11651
+ targetIsSameSite,
11652
+ targetIsAnchor,
11653
+ targetIsCurrent
11654
+ } = getLinkTargetInfo(href);
11655
+ const innerTarget = target === undefined ? targetIsSameSite ? "_self" : "_blank" : target;
11656
+ const innerRel = rel === undefined ? targetIsSameSite ? undefined : "noopener noreferrer" : rel;
11657
+ let innerIcon;
11658
+ if (icon === undefined) {
11659
+ const innerBlankTargetIcon = blankTargetIcon === undefined ? innerTarget === "_blank" : blankTargetIcon;
11660
+ const innerAnchorIcon = anchorIcon === undefined ? targetIsAnchor : anchorIcon;
11661
+ if (innerBlankTargetIcon) {
11662
+ innerIcon = innerBlankTargetIcon === true ? jsx(BlankTargetLinkSvg, {}) : innerBlankTargetIcon;
11663
+ } else if (innerAnchorIcon) {
11664
+ innerIcon = innerAnchorIcon === true ? jsx(AnchorLinkSvg, {}) : anchorIcon;
11665
+ }
11666
+ } else {
11667
+ innerIcon = icon;
11668
+ }
11533
11669
  return jsx("a", {
11534
11670
  ...remainingProps,
11535
11671
  ref: innerRef,
11536
- href: href,
11537
11672
  className: innerClassName,
11538
11673
  style: innerStyle,
11674
+ href: href,
11675
+ rel: innerRel,
11676
+ target: innerTarget === "_self" ? undefined : target,
11539
11677
  "aria-busy": loading,
11540
11678
  inert: disabled,
11541
11679
  "data-disabled": disabled ? "" : undefined,
11542
11680
  "data-readonly": readOnly ? "" : undefined,
11543
11681
  "data-active": active ? "" : undefined,
11544
11682
  "data-visited": visited || isVisited ? "" : undefined,
11683
+ "data-external": targetIsSameSite ? undefined : "",
11684
+ "data-internal": targetIsSameSite ? "" : undefined,
11685
+ "data-anchor": targetIsAnchor ? "" : undefined,
11686
+ "data-current": targetIsCurrent ? "" : undefined,
11545
11687
  onClick: e => {
11546
11688
  closeValidationMessage(e.target, "click");
11547
11689
  if (readOnly) {
@@ -11559,13 +11701,46 @@ const LinkPlain = forwardRef((props, ref) => {
11559
11701
  }
11560
11702
  onKeyDown?.(e);
11561
11703
  },
11562
- children: jsx(LoaderBackground, {
11704
+ children: jsxs(LoaderBackground, {
11563
11705
  loading: loading,
11564
11706
  color: "light-dark(#355fcc, #3b82f6)",
11565
- children: children
11707
+ children: [children, innerIcon && jsx(Icon, {
11708
+ children: innerIcon
11709
+ })]
11566
11710
  })
11567
11711
  });
11568
11712
  });
11713
+ const BlankTargetLinkSvg = () => {
11714
+ return jsx("svg", {
11715
+ viewBox: "0 0 24 24",
11716
+ width: "100%",
11717
+ height: "100%",
11718
+ xmlns: "http://www.w3.org/2000/svg",
11719
+ children: jsx("path", {
11720
+ d: "M10.0002 5H8.2002C7.08009 5 6.51962 5 6.0918 5.21799C5.71547 5.40973 5.40973 5.71547 5.21799 6.0918C5 6.51962 5 7.08009 5 8.2002V15.8002C5 16.9203 5 17.4801 5.21799 17.9079C5.40973 18.2842 5.71547 18.5905 6.0918 18.7822C6.5192 19 7.07899 19 8.19691 19H15.8031C16.921 19 17.48 19 17.9074 18.7822C18.2837 18.5905 18.5905 18.2839 18.7822 17.9076C19 17.4802 19 16.921 19 15.8031V14M20 9V4M20 4H15M20 4L13 11",
11721
+ stroke: "currentColor",
11722
+ fill: "none",
11723
+ "stroke-width": "2",
11724
+ "stroke-linecap": "round",
11725
+ "stroke-linejoin": "round"
11726
+ })
11727
+ });
11728
+ };
11729
+ const AnchorLinkSvg = () => {
11730
+ return jsxs("svg", {
11731
+ viewBox: "0 0 24 24",
11732
+ width: "100%",
11733
+ height: "100%",
11734
+ xmlns: "http://www.w3.org/2000/svg",
11735
+ children: [jsx("path", {
11736
+ d: "M13.2218 3.32234C15.3697 1.17445 18.8521 1.17445 21 3.32234C23.1479 5.47022 23.1479 8.95263 21 11.1005L17.4645 14.636C15.3166 16.7839 11.8342 16.7839 9.6863 14.636C9.48752 14.4373 9.30713 14.2271 9.14514 14.0075C8.90318 13.6796 8.97098 13.2301 9.25914 12.9419C9.73221 12.4688 10.5662 12.6561 11.0245 13.1435C11.0494 13.1699 11.0747 13.196 11.1005 13.2218C12.4673 14.5887 14.6834 14.5887 16.0503 13.2218L19.5858 9.6863C20.9526 8.31947 20.9526 6.10339 19.5858 4.73655C18.219 3.36972 16.0029 3.36972 14.636 4.73655L13.5754 5.79721C13.1849 6.18774 12.5517 6.18774 12.1612 5.79721C11.7706 5.40669 11.7706 4.77352 12.1612 4.383L13.2218 3.32234Z",
11737
+ fill: "currentColor"
11738
+ }), jsx("path", {
11739
+ d: "M6.85787 9.6863C8.90184 7.64233 12.2261 7.60094 14.3494 9.42268C14.7319 9.75083 14.7008 10.3287 14.3444 10.685C13.9253 11.1041 13.2317 11.0404 12.7416 10.707C11.398 9.79292 9.48593 9.88667 8.27209 11.1005L4.73655 14.636C3.36972 16.0029 3.36972 18.219 4.73655 19.5858C6.10339 20.9526 8.31947 20.9526 9.6863 19.5858L10.747 18.5251C11.1375 18.1346 11.7706 18.1346 12.1612 18.5251C12.5517 18.9157 12.5517 19.5488 12.1612 19.9394L11.1005 21C8.95263 23.1479 5.47022 23.1479 3.32234 21C1.17445 18.8521 1.17445 15.3697 3.32234 13.2218L6.85787 9.6863Z",
11740
+ fill: "currentColor"
11741
+ })]
11742
+ });
11743
+ };
11569
11744
  const LinkWithSelection = forwardRef((props, ref) => {
11570
11745
  const {
11571
11746
  selection,
@@ -18975,54 +19150,19 @@ const Overflow = ({
18975
19150
  });
18976
19151
  };
18977
19152
 
18978
- installImportMetaCss(import.meta);import.meta.css = /* css */`
18979
- :root {
18980
- --navi-icon-align-y: center;
18981
- }
18982
-
18983
- .navi_text {
18984
- display: inline-flex;
18985
- align-items: baseline;
18986
- gap: 0.1em;
18987
- }
18988
-
18989
- .navi_icon {
18990
- --align-y: var(--navi-icon-align-y, center);
18991
-
18992
- display: inline-flex;
18993
- width: 1em;
18994
- height: 1em;
18995
- flex-shrink: 0;
18996
- align-self: var(--align-y);
18997
- line-height: 1em;
18998
- }
18999
- `;
19000
- const Text = ({
19001
- children,
19002
- ...rest
19003
- }) => {
19004
- const [remainingProps, innerStyle] = withPropsStyle(rest, {
19005
- layout: true,
19006
- typo: true
19007
- });
19008
- return jsx("span", {
19009
- ...remainingProps,
19010
- className: "navi_text",
19011
- style: innerStyle,
19012
- children: children
19013
- });
19014
- };
19015
- const Icon = ({
19153
+ const Paragraph = ({
19016
19154
  children,
19017
19155
  ...rest
19018
19156
  }) => {
19157
+ if (rest.marginTop === undefined) {
19158
+ rest.marginTop = "md";
19159
+ }
19019
19160
  const [remainingProps, innerStyle] = withPropsStyle(rest, {
19020
19161
  layout: true,
19021
19162
  typo: true
19022
19163
  });
19023
- return jsx("span", {
19164
+ return jsx("p", {
19024
19165
  ...remainingProps,
19025
- className: "navi_icon",
19026
19166
  style: innerStyle,
19027
19167
  children: children
19028
19168
  });
@@ -19060,6 +19200,26 @@ const TextAndCount = ({
19060
19200
  });
19061
19201
  };
19062
19202
 
19203
+ const Title = ({
19204
+ children,
19205
+ as = "h1",
19206
+ ...rest
19207
+ }) => {
19208
+ if (rest.bold === undefined) {
19209
+ rest.bold = true;
19210
+ }
19211
+ const [remainingProps, innerStyle] = withPropsStyle(rest, {
19212
+ layout: true,
19213
+ typo: true
19214
+ });
19215
+ const HeadingTag = as;
19216
+ return jsx(HeadingTag, {
19217
+ ...remainingProps,
19218
+ style: innerStyle,
19219
+ children: children
19220
+ });
19221
+ };
19222
+
19063
19223
  installImportMetaCss(import.meta);import.meta.css = /* css */`
19064
19224
  .navi_flex_row {
19065
19225
  display: flex;
@@ -19117,7 +19277,7 @@ const FlexColumn = ({
19117
19277
  alignItems: alignX !== "stretch" ? alignX : undefined,
19118
19278
  // Only set justifyContent if it's not the default "start"
19119
19279
  justifyContent: alignY !== "start" ? alignY : undefined,
19120
- gap: tshirtSizeToCSSValues[gap] || gap
19280
+ gap: sizeSpacingScale[gap] || gap
19121
19281
  }
19122
19282
  });
19123
19283
  return jsx("div", {
@@ -19248,5 +19408,5 @@ const useDependenciesDiff = (inputs) => {
19248
19408
  return diffRef.current;
19249
19409
  };
19250
19410
 
19251
- export { ActionRenderer, ActiveKeyboardShortcuts, Button, Checkbox, CheckboxList, Col, Colgroup, Details, Editable, ErrorBoundaryContext, FlexColumn, FlexItem, FlexRow, FontSizedSvg, Form, Icon, IconAndText, Input, Label, Link, LinkWithIcon, Overflow, Radio, RadioList, Route, RouteLink, Routes, RowNumberCol, RowNumberTableCell, SINGLE_SPACE_CONSTRAINT, SVGMaskOverlay, Select, SelectionContext, Spacing, SummaryMarker, Tab, TabList, Table, TableCell, Tbody, Text, TextAndCount, Thead, Tr, UITransition, actionIntegratedVia, addCustomMessage, createAction, createSelectionKeyboardShortcuts, createUniqueValueConstraint, enableDebugActions, enableDebugOnDocumentLoading, forwardActionRequested, goBack, goForward, goTo, installCustomConstraintValidation, isCellSelected, isColumnSelected, isRowSelected, openCallout, rawUrlPart, reload, removeCustomMessage, rerunActions, resource, setBaseUrl, setupRoutes, stopLoad, stringifyTableSelectionValue, updateActions, useActionData, useActionStatus, useCellsAndColumns, useDependenciesDiff, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useNavState, useRouteStatus, useRunOnMount, useSelectableElement, useSelectionController, useSignalSync, useStateArray, valueInLocalStorage };
19411
+ export { ActionRenderer, ActiveKeyboardShortcuts, Button, Checkbox, CheckboxList, Col, Colgroup, Details, Editable, ErrorBoundaryContext, FlexColumn, FlexItem, FlexRow, FontSizedSvg, Form, Icon, IconAndText, Input, Label, Link, LinkWithIcon, Overflow, Paragraph, Radio, RadioList, Route, RouteLink, Routes, RowNumberCol, RowNumberTableCell, SINGLE_SPACE_CONSTRAINT, SVGMaskOverlay, Select, SelectionContext, Spacing, SummaryMarker, Tab, TabList, Table, TableCell, Tbody, Text, TextAndCount, Thead, Title, Tr, UITransition, actionIntegratedVia, addCustomMessage, createAction, createSelectionKeyboardShortcuts, createUniqueValueConstraint, enableDebugActions, enableDebugOnDocumentLoading, forwardActionRequested, goBack, goForward, goTo, installCustomConstraintValidation, isCellSelected, isColumnSelected, isRowSelected, openCallout, rawUrlPart, reload, removeCustomMessage, rerunActions, resource, setBaseUrl, setupRoutes, stopLoad, stringifyTableSelectionValue, updateActions, useActionData, useActionStatus, useCellsAndColumns, useDependenciesDiff, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useNavState, useRouteStatus, useRunOnMount, useSelectableElement, useSelectionController, useSignalSync, useStateArray, valueInLocalStorage };
19252
19412
  //# sourceMappingURL=jsenv_navi.js.map