@dloizides/ui-nav 1.34.0 → 1.37.0

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.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import React, { useState, useCallback, useMemo, useEffect, useRef } from 'react';
1
+ import React, { createContext, useState, useCallback, useMemo, useContext, useEffect, useRef } from 'react';
2
2
  import { StyleSheet, Platform, Pressable, Text, View, TextInput, useWindowDimensions, Image, ScrollView, ActivityIndicator, Animated } from 'react-native';
3
3
  import { useUi, UiProvider } from '@dloizides/ui-feedback';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -22,7 +22,6 @@ var NAV_LINK_GAP = 4;
22
22
  var navStyles = StyleSheet.create({
23
23
  // --- Sidebar ---
24
24
  sidebarContainer: {
25
- width: 220,
26
25
  paddingTop: 24,
27
26
  paddingHorizontal: 12,
28
27
  borderRightWidth: 1,
@@ -480,6 +479,18 @@ function resolveActiveRoute(items, pathname) {
480
479
  }
481
480
  return winner;
482
481
  }
482
+ var NavAccordionContext = createContext(false);
483
+ function hasActiveDescendant(item, pathname) {
484
+ if (isRouteActive(pathname, item.route)) return true;
485
+ return (item.children ?? []).some((child) => hasActiveDescendant(child, pathname));
486
+ }
487
+ function initialOpenGroup(items, pathname) {
488
+ const hasChildren = (item) => (item.children ?? []).length > 0;
489
+ return items.find((item) => hasChildren(item) && hasActiveDescendant(item, pathname))?.key;
490
+ }
491
+ function nextOpenGroup(current, pressed) {
492
+ return current === pressed ? void 0 : pressed;
493
+ }
483
494
  var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
484
495
  function getReducedMotionQuery() {
485
496
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return void 0;
@@ -529,10 +540,6 @@ function ariaExpandedProps(expanded) {
529
540
  function hoverHandlerProps(onIn, onOut) {
530
541
  return IS_WEB ? { onHoverIn: onIn, onHoverOut: onOut } : {};
531
542
  }
532
- function hasActiveDescendant(item, pathname) {
533
- if (isRouteActive(pathname, item.route)) return true;
534
- return (item.children ?? []).some((child) => hasActiveDescendant(child, pathname));
535
- }
536
543
  function TintOverlay({
537
544
  opacity,
538
545
  color,
@@ -556,15 +563,21 @@ var NavExpandableItem = ({
556
563
  collapseHint,
557
564
  renderChevron,
558
565
  activeRoute,
559
- depth = 0
566
+ depth = 0,
567
+ expanded: expandedProp,
568
+ onToggle
560
569
  }) => {
561
- const [expanded, setExpanded] = useState(() => hasActiveDescendant(item, pathname));
570
+ const [internalExpanded, setExpanded] = useState(() => hasActiveDescendant(item, pathname));
571
+ const expanded = expandedProp ?? internalExpanded;
562
572
  const [focused, setFocused] = useState(false);
563
573
  const [hovered, setHovered] = useState(false);
564
574
  const { theme } = useUi();
565
575
  const colors = theme.colors;
566
576
  const primaryColor = theme.palette.primary["500"];
567
- const toggle = useCallback(() => setExpanded((v) => !v), []);
577
+ const toggle = useCallback(() => {
578
+ if (onToggle !== void 0) onToggle(item.key);
579
+ else setExpanded((v) => !v);
580
+ }, [onToggle, item.key]);
568
581
  const onHoverIn = useCallback(() => setHovered(true), []);
569
582
  const onHoverOut = useCallback(() => setHovered(false), []);
570
583
  const indent = depth * BASE_INDENT;
@@ -675,9 +688,72 @@ var DEFAULT_SEARCH_BREAKPOINT = LAYOUT_COLLAPSE_BREAKPOINT;
675
688
  function resolveSearchAffordance(viewport, breakpoint = DEFAULT_SEARCH_BREAKPOINT) {
676
689
  return viewport >= breakpoint ? "inline" : "palette";
677
690
  }
691
+
692
+ // src/sidebarEdgeFade.ts
693
+ var EDGE_TOLERANCE = 1;
694
+ function resolveEdgeFades({ offsetY, viewportHeight, contentHeight }) {
695
+ const hiddenBelow = contentHeight - (offsetY + viewportHeight);
696
+ return { top: offsetY > EDGE_TOLERANCE, bottom: hiddenBelow > EDGE_TOLERANCE };
697
+ }
698
+ var FADE_BAND_HEIGHT = 6;
699
+ var FADE_BAND_OPACITIES = [0.9, 0.65, 0.4, 0.15];
700
+ var SCROLL_EVENT_THROTTLE_MS = 16;
701
+ var styles2 = StyleSheet.create({
702
+ area: { flex: 1, minHeight: 0 },
703
+ fade: { position: "absolute", left: 0, right: 0 },
704
+ fadeTop: { top: 0 },
705
+ fadeBottom: { bottom: 0, flexDirection: "column-reverse" },
706
+ band: { height: FADE_BAND_HEIGHT }
707
+ });
708
+ function EdgeFade({ edge, color }) {
709
+ return /* @__PURE__ */ jsx(
710
+ View,
711
+ {
712
+ pointerEvents: "none",
713
+ style: [styles2.fade, edge === "top" ? styles2.fadeTop : styles2.fadeBottom],
714
+ testID: `sidebar-fade-${edge}`,
715
+ children: FADE_BAND_OPACITIES.map((opacity) => /* @__PURE__ */ jsx(View, { style: [styles2.band, { backgroundColor: color, opacity }] }, opacity))
716
+ }
717
+ );
718
+ }
719
+ var SidebarScrollArea = ({ children }) => {
720
+ const { theme } = useUi();
721
+ const metrics = useRef({ offsetY: 0, viewportHeight: 0, contentHeight: 0 });
722
+ const [fades, setFades] = useState({ top: false, bottom: false });
723
+ const update = useCallback((next) => {
724
+ metrics.current = { ...metrics.current, ...next };
725
+ const resolved = resolveEdgeFades(metrics.current);
726
+ setFades((prev) => prev.top === resolved.top && prev.bottom === resolved.bottom ? prev : resolved);
727
+ }, []);
728
+ const onLayout = useCallback(
729
+ (e) => update({ viewportHeight: e.nativeEvent.layout.height }),
730
+ [update]
731
+ );
732
+ const onContentSizeChange = useCallback((_w, h) => update({ contentHeight: h }), [update]);
733
+ const onScroll = useCallback(
734
+ (e) => update({ offsetY: e.nativeEvent.contentOffset.y }),
735
+ [update]
736
+ );
737
+ return /* @__PURE__ */ jsxs(View, { style: styles2.area, children: [
738
+ /* @__PURE__ */ jsx(
739
+ ScrollView,
740
+ {
741
+ scrollEventThrottle: SCROLL_EVENT_THROTTLE_MS,
742
+ style: styles2.area,
743
+ testID: "sidebar-scroll",
744
+ onContentSizeChange,
745
+ onLayout,
746
+ onScroll,
747
+ children
748
+ }
749
+ ),
750
+ fades.top ? /* @__PURE__ */ jsx(EdgeFade, { color: theme.colors.surface, edge: "top" }) : null,
751
+ fades.bottom ? /* @__PURE__ */ jsx(EdgeFade, { color: theme.colors.surface, edge: "bottom" }) : null
752
+ ] });
753
+ };
678
754
  var FIELD_MIN_HEIGHT = 38;
679
755
  var CLEAR_GLYPH = "\u2715";
680
- var styles2 = StyleSheet.create({
756
+ var styles3 = StyleSheet.create({
681
757
  wrap: {
682
758
  flexDirection: "row",
683
759
  alignItems: "center",
@@ -718,7 +794,7 @@ var SidebarSearch = ({
718
794
  View,
719
795
  {
720
796
  style: [
721
- styles2.wrap,
797
+ styles3.wrap,
722
798
  { backgroundColor: colors.surface, borderColor: focused ? primary : colors.border },
723
799
  focusRingStyle(focused, primary)
724
800
  ],
@@ -730,7 +806,7 @@ var SidebarSearch = ({
730
806
  accessibilityLabel: labels.placeholder,
731
807
  placeholder: labels.placeholder,
732
808
  placeholderTextColor: colors.textSecondary,
733
- style: [styles2.input, { color: colors.text }],
809
+ style: [styles3.input, { color: colors.text }],
734
810
  testID,
735
811
  value,
736
812
  onBlur: () => setFocused(false),
@@ -744,16 +820,30 @@ var SidebarSearch = ({
744
820
  accessibilityHint: labels.clearHint,
745
821
  accessibilityLabel: labels.clearLabel,
746
822
  accessibilityRole: "button",
747
- style: styles2.clear,
823
+ style: styles3.clear,
748
824
  testID: `${testID}-clear`,
749
825
  onPress: onClear,
750
- children: /* @__PURE__ */ jsx(Text, { style: [styles2.clearGlyph, { color: colors.textSecondary }], children: CLEAR_GLYPH })
826
+ children: /* @__PURE__ */ jsx(Text, { style: [styles3.clearGlyph, { color: colors.textSecondary }], children: CLEAR_GLYPH })
751
827
  }
752
828
  ) : null
753
829
  ]
754
830
  }
755
831
  );
756
832
  };
833
+
834
+ // src/types.ts
835
+ var SIDEBAR_WIDTH_PX = {
836
+ default: 220,
837
+ sm: 240,
838
+ md: 264,
839
+ lg: 288
840
+ };
841
+ var NAV_BRAND_DEFAULTS = {
842
+ brandPlacement: "sidebar",
843
+ sidebarWidth: "default",
844
+ drawerHeader: "none",
845
+ drawerWidth: "default"
846
+ };
757
847
  function isBareText(node) {
758
848
  return typeof node === "string" || typeof node === "number";
759
849
  }
@@ -771,6 +861,7 @@ var Sidebar = ({
771
861
  pathname,
772
862
  onNavigate,
773
863
  title,
864
+ width: railWidth = "default",
774
865
  regionLabel,
775
866
  navigateHint = (label) => label,
776
867
  expandHint = "",
@@ -806,6 +897,10 @@ var Sidebar = ({
806
897
  const visibleItems = showInlineSearch ? filterNavItems(items, query) : items;
807
898
  const showEmpty = showInlineSearch && isFilterActive(query) && visibleItems.length === 0;
808
899
  const activeRoute = resolveActiveRoute(items, pathname);
900
+ const accordion = useContext(NavAccordionContext);
901
+ const [openGroup, setOpenGroup] = useState(() => initialOpenGroup(items, pathname));
902
+ const toggleGroup = useCallback((key) => setOpenGroup((current) => nextOpenGroup(current, key)), []);
903
+ const accordionProps = (item) => accordion && (item.children ?? []).length > 0 ? { expanded: openGroup === item.key, onToggle: toggleGroup } : {};
809
904
  return /* @__PURE__ */ jsxs(
810
905
  View,
811
906
  {
@@ -814,11 +909,12 @@ var Sidebar = ({
814
909
  role: "navigation",
815
910
  style: [
816
911
  navStyles.sidebarContainer,
912
+ { width: SIDEBAR_WIDTH_PX[railWidth] },
817
913
  { backgroundColor: colors.surface, borderRightColor: colors.border },
818
914
  containerStyle
819
915
  ],
820
916
  children: [
821
- typeof title === "string" ? /* @__PURE__ */ jsx(Text, { accessibilityRole: "header", style: [navStyles.sidebarTitle, { color: colors.text }], children: title }) : /* @__PURE__ */ jsx(View, { style: navStyles.sidebarBrand, children: title }),
917
+ title === null ? null : typeof title === "string" ? /* @__PURE__ */ jsx(Text, { accessibilityRole: "header", style: [navStyles.sidebarTitle, { color: colors.text }], children: title }) : /* @__PURE__ */ jsx(View, { style: navStyles.sidebarBrand, children: title }),
822
918
  showInlineSearch && search !== void 0 ? /* @__PURE__ */ jsx(
823
919
  SidebarSearch,
824
920
  {
@@ -839,22 +935,24 @@ var Sidebar = ({
839
935
  onPress: paletteTrigger.onOpen
840
936
  }
841
937
  ) }) : null,
842
- renderTextSlot(header, { color: colors.text }),
843
- showEmpty && search !== void 0 ? /* @__PURE__ */ jsx(Text, { style: [navStyles.sidebarEmpty, { color: colors.textSecondary }], testID: "sidebar-search-empty", children: search.emptyText }) : visibleItems.map((item) => /* @__PURE__ */ jsx(
844
- NavExpandableItem,
845
- {
846
- activeRoute,
847
- collapseHint,
848
- expandHint,
849
- item,
850
- navigateHint,
851
- pathname,
852
- renderChevron,
853
- onNavigate
854
- },
855
- item.key
856
- )),
857
- /* @__PURE__ */ jsx(View, { style: navStyles.sidebarSpacer }),
938
+ /* @__PURE__ */ jsxs(SidebarScrollArea, { children: [
939
+ renderTextSlot(header, { color: colors.text }),
940
+ showEmpty && search !== void 0 ? /* @__PURE__ */ jsx(Text, { style: [navStyles.sidebarEmpty, { color: colors.textSecondary }], testID: "sidebar-search-empty", children: search.emptyText }) : visibleItems.map((item) => /* @__PURE__ */ jsx(
941
+ NavExpandableItem,
942
+ {
943
+ activeRoute,
944
+ collapseHint,
945
+ expandHint,
946
+ item,
947
+ navigateHint,
948
+ pathname,
949
+ renderChevron,
950
+ onNavigate,
951
+ ...accordionProps(item)
952
+ },
953
+ item.key
954
+ ))
955
+ ] }),
858
956
  renderTextSlot(footer, { color: colors.text })
859
957
  ]
860
958
  }
@@ -1576,7 +1674,7 @@ var NavBar = ({ barTheme, ...props }) => {
1576
1674
  if (barTheme === void 0) return /* @__PURE__ */ jsx(NavBarInner, { ...props });
1577
1675
  return /* @__PURE__ */ jsx(UiProvider, { navigate, t, theme: barTheme, children: /* @__PURE__ */ jsx(NavBarInner, { ...props }) });
1578
1676
  };
1579
- var styles3 = StyleSheet.create({
1677
+ var styles4 = StyleSheet.create({
1580
1678
  hitBox: { minHeight: MIN_TOUCH_TARGET, minWidth: MIN_TOUCH_TARGET, justifyContent: "center" }
1581
1679
  });
1582
1680
  function anchorProps(route) {
@@ -1599,7 +1697,7 @@ var BrandHomeLink = ({ route, label, onNavigate, children }) => {
1599
1697
  {
1600
1698
  accessibilityLabel: label,
1601
1699
  accessibilityRole: "link",
1602
- style: [styles3.hitBox, focusRingStyle(focused, theme.palette.primary["500"])],
1700
+ style: [styles4.hitBox, focusRingStyle(focused, theme.palette.primary["500"])],
1603
1701
  testID: NAV_TEST_IDS.brandHome,
1604
1702
  onBlur: () => setFocused(false),
1605
1703
  onFocus: () => setFocused(true),
@@ -1612,7 +1710,7 @@ var BrandHomeLink = ({ route, label, onNavigate, children }) => {
1612
1710
  var DEFAULT_ICON_SIZE = 32;
1613
1711
  var NAME_FONT_SIZE = 16;
1614
1712
  var NAME_GAP = 8;
1615
- var styles4 = StyleSheet.create({
1713
+ var styles5 = StyleSheet.create({
1616
1714
  name: { flexShrink: 1, fontSize: NAME_FONT_SIZE, fontWeight: "700" },
1617
1715
  row: { alignItems: "center", flexDirection: "row", gap: NAME_GAP }
1618
1716
  });
@@ -1626,7 +1724,7 @@ var BrandMark = ({
1626
1724
  iconOnly = false
1627
1725
  }) => {
1628
1726
  const { theme } = useUi();
1629
- return /* @__PURE__ */ jsx(BrandHomeLink, { label, route, onNavigate, children: /* @__PURE__ */ jsxs(View, { style: styles4.row, children: [
1727
+ return /* @__PURE__ */ jsx(BrandHomeLink, { label, route, onNavigate, children: /* @__PURE__ */ jsxs(View, { style: styles5.row, children: [
1630
1728
  /* @__PURE__ */ jsx(
1631
1729
  Image,
1632
1730
  {
@@ -1640,7 +1738,7 @@ var BrandMark = ({
1640
1738
  Text,
1641
1739
  {
1642
1740
  numberOfLines: 1,
1643
- style: [styles4.name, { color: theme.colors.text }],
1741
+ style: [styles5.name, { color: theme.colors.text }],
1644
1742
  testID: NAV_TEST_IDS.brandMarkName,
1645
1743
  children: name
1646
1744
  }
@@ -1653,7 +1751,7 @@ var Nav = (props) => {
1653
1751
  }
1654
1752
  return /* @__PURE__ */ jsx(NavBar, { ...props });
1655
1753
  };
1656
- var styles5 = StyleSheet.create({
1754
+ var styles6 = StyleSheet.create({
1657
1755
  band: { left: 0, position: "absolute", right: 0, top: 0 }
1658
1756
  });
1659
1757
  function readBackdrop(theme) {
@@ -1676,7 +1774,7 @@ function resolveShellBackdrop(theme, viewport, contentPadding, testID) {
1676
1774
  View,
1677
1775
  {
1678
1776
  pointerEvents: "none",
1679
- style: [styles5.band, { backgroundColor: band.color, height: contentPadding + overlap }],
1777
+ style: [styles6.band, { backgroundColor: band.color, height: contentPadding + overlap }],
1680
1778
  testID: `${testID}${APP_SHELL_SUFFIX.band}`
1681
1779
  }
1682
1780
  );
@@ -1688,7 +1786,7 @@ var CARD_BORDER_WIDTH = 1;
1688
1786
  var CARD_TITLE_FONT_SIZE = 16;
1689
1787
  var CARD_MESSAGE_FONT_SIZE = 14;
1690
1788
  var CARD_TITLE_MARGIN_BOTTOM = 8;
1691
- var styles6 = StyleSheet.create({
1789
+ var styles7 = StyleSheet.create({
1692
1790
  // Loading is a TRANSITIONAL state: the spinner is an absolute overlay ON TOP of
1693
1791
  // stably-mounted children, never a replacement for them. Replacing children here
1694
1792
  // would unmount whatever they host (e.g. a navigator), and on remount React
@@ -1720,9 +1818,9 @@ function MessageCard({
1720
1818
  }) {
1721
1819
  const { theme } = useUi();
1722
1820
  const colors = theme.colors;
1723
- return /* @__PURE__ */ jsxs(View, { style: [styles6.card, { backgroundColor: colors.surface, borderColor: accentColor }], testID, children: [
1724
- /* @__PURE__ */ jsx(Text, { style: [styles6.cardTitle, { color: accentColor }], children: message.titleText }),
1725
- /* @__PURE__ */ jsx(Text, { style: [styles6.cardMessage, { color: colors.textSecondary }], children: message.messageText })
1821
+ return /* @__PURE__ */ jsxs(View, { style: [styles7.card, { backgroundColor: colors.surface, borderColor: accentColor }], testID, children: [
1822
+ /* @__PURE__ */ jsx(Text, { style: [styles7.cardTitle, { color: accentColor }], children: message.titleText }),
1823
+ /* @__PURE__ */ jsx(Text, { style: [styles7.cardMessage, { color: colors.textSecondary }], children: message.messageText })
1726
1824
  ] });
1727
1825
  }
1728
1826
  function useContentBody(state, children, testID) {
@@ -1734,18 +1832,45 @@ function useContentBody(state, children, testID) {
1734
1832
  return /* @__PURE__ */ jsx(MessageCard, { accentColor: errorColor, message: state.forbidden, testID: `${testID}${APP_SHELL_SUFFIX.forbidden}` });
1735
1833
  if (state.error)
1736
1834
  return /* @__PURE__ */ jsx(MessageCard, { accentColor: errorColor, message: state.error, testID: `${testID}${APP_SHELL_SUFFIX.error}` });
1737
- return /* @__PURE__ */ jsxs(View, { style: styles6.loadingHost, children: [
1835
+ return /* @__PURE__ */ jsxs(View, { style: styles7.loadingHost, children: [
1738
1836
  children,
1739
1837
  state.loading === true ? /* @__PURE__ */ jsx(
1740
1838
  View,
1741
1839
  {
1742
- style: [styles6.loadingOverlay, { backgroundColor: theme.colors.background }],
1840
+ style: [styles7.loadingOverlay, { backgroundColor: theme.colors.background }],
1743
1841
  testID: `${testID}${APP_SHELL_SUFFIX.loading}`,
1744
1842
  children: /* @__PURE__ */ jsx(ActivityIndicator, { color: primary, size: "large" })
1745
1843
  }
1746
1844
  ) : null
1747
1845
  ] });
1748
1846
  }
1847
+ var CLOSE_GLYPH = "\u2715";
1848
+ var CLOSE_GLYPH_FONT_SIZE = 18;
1849
+ var BAR_PADDING = 12;
1850
+ var styles8 = StyleSheet.create({
1851
+ bar: { flexDirection: "row", alignItems: "center", paddingLeft: BAR_PADDING, borderBottomWidth: 1 },
1852
+ brand: { flex: 1 },
1853
+ close: { minWidth: MIN_TOUCH_TARGET, minHeight: MIN_TOUCH_TARGET, alignItems: "center", justifyContent: "center" },
1854
+ glyph: { fontSize: CLOSE_GLYPH_FONT_SIZE, fontWeight: "700" }
1855
+ });
1856
+ var DrawerHeaderBar = ({ brand, closeLabel, closeHint, onClose, testID }) => {
1857
+ const { theme } = useUi();
1858
+ return /* @__PURE__ */ jsxs(View, { style: [styles8.bar, { borderBottomColor: theme.colors.border }], testID, children: [
1859
+ /* @__PURE__ */ jsx(View, { style: styles8.brand, children: brand }),
1860
+ /* @__PURE__ */ jsx(
1861
+ FocusableTouchable,
1862
+ {
1863
+ accessibilityHint: closeHint,
1864
+ accessibilityLabel: closeLabel,
1865
+ ringColor: theme.palette.primary["500"],
1866
+ style: styles8.close,
1867
+ testID: `${testID}-close`,
1868
+ onPress: onClose,
1869
+ children: /* @__PURE__ */ jsx(Text, { style: [styles8.glyph, { color: theme.colors.text }], children: CLOSE_GLYPH })
1870
+ }
1871
+ )
1872
+ ] });
1873
+ };
1749
1874
  var SCRIM_COLOR = "rgba(0, 0, 0, 0.5)";
1750
1875
  var MENU_GLYPH2 = "\u2630";
1751
1876
  var MENU_GLYPH_FONT_SIZE = 20;
@@ -1766,7 +1891,7 @@ var DEFAULT_DRAWER_LABELS = {
1766
1891
  closeLabel: "Close menu",
1767
1892
  closeHint: "Close the navigation menu"
1768
1893
  };
1769
- var styles7 = StyleSheet.create({
1894
+ var styles9 = StyleSheet.create({
1770
1895
  overlay: { ...StyleSheet.absoluteFillObject, zIndex: DRAWER_Z_INDEX },
1771
1896
  // The scrim's tap-to-close hit area is anchored to the RIGHT of the panel
1772
1897
  // (`left: DRAWER_WIDTH`), so it NEVER overlaps the panel: nav-item taps always
@@ -1784,6 +1909,8 @@ var styles7 = StyleSheet.create({
1784
1909
  // so on react-native-web it — and the nav leaves inside it — sit above the scrim
1785
1910
  // and receive presses instead of the scrim swallowing them.
1786
1911
  panel: { position: "absolute", top: 0, bottom: 0, left: 0, width: DRAWER_WIDTH, zIndex: PANEL_Z_INDEX },
1912
+ panelFull: { width: "100%" },
1913
+ panelBody: { flex: 1 },
1787
1914
  menuToggle: {
1788
1915
  minWidth: MIN_TOUCH_TARGET,
1789
1916
  minHeight: MIN_TOUCH_TARGET,
@@ -1801,10 +1928,10 @@ var MenuToggle = ({ label, hint, onOpen, testID }) => {
1801
1928
  accessibilityHint: hint,
1802
1929
  accessibilityLabel: label,
1803
1930
  ringColor: theme.palette.primary["500"],
1804
- style: styles7.menuToggle,
1931
+ style: styles9.menuToggle,
1805
1932
  testID,
1806
1933
  onPress: onOpen,
1807
- children: /* @__PURE__ */ jsx(Text, { style: [styles7.menuToggleGlyph, { color: theme.colors.text }], children: MENU_GLYPH2 })
1934
+ children: /* @__PURE__ */ jsx(Text, { style: [styles9.menuToggleGlyph, { color: theme.colors.text }], children: MENU_GLYPH2 })
1808
1935
  }
1809
1936
  );
1810
1937
  };
@@ -1813,10 +1940,14 @@ var MobileDrawer = ({
1813
1940
  labels,
1814
1941
  onClose,
1815
1942
  drawerTestID,
1816
- scrimTestID
1943
+ scrimTestID,
1944
+ header,
1945
+ width = "default"
1817
1946
  }) => {
1818
1947
  const { theme } = useUi();
1819
1948
  const panelRef = useRef(null);
1949
+ const isFull = width === "full";
1950
+ const showHeaderBar = header !== void 0 || isFull;
1820
1951
  useEffect(() => {
1821
1952
  const node = panelRef.current;
1822
1953
  if (node === null || typeof node.addEventListener !== "function") return void 0;
@@ -1830,27 +1961,39 @@ var MobileDrawer = ({
1830
1961
  node.addEventListener("click", handleClick);
1831
1962
  return () => node.removeEventListener("click", handleClick);
1832
1963
  }, [onClose]);
1833
- return /* @__PURE__ */ jsxs(View, { style: styles7.overlay, children: [
1834
- /* @__PURE__ */ jsx(
1964
+ return /* @__PURE__ */ jsxs(View, { style: styles9.overlay, children: [
1965
+ isFull ? null : /* @__PURE__ */ jsx(
1835
1966
  Pressable,
1836
1967
  {
1837
1968
  accessibilityHint: labels.closeHint,
1838
1969
  accessibilityLabel: labels.closeLabel,
1839
1970
  accessibilityRole: "button",
1840
- style: styles7.scrim,
1971
+ style: styles9.scrim,
1841
1972
  testID: scrimTestID,
1842
1973
  onPress: onClose
1843
1974
  }
1844
1975
  ),
1845
- /* @__PURE__ */ jsx(
1976
+ /* @__PURE__ */ jsxs(
1846
1977
  View,
1847
1978
  {
1848
1979
  ref: panelRef,
1849
1980
  "aria-modal": true,
1850
1981
  role: "dialog",
1851
- style: [styles7.panel, { backgroundColor: theme.colors.surface }],
1982
+ style: [styles9.panel, isFull ? styles9.panelFull : null, { backgroundColor: theme.colors.surface }],
1852
1983
  testID: drawerTestID,
1853
- children: renderTextSlot(sidebar, { color: theme.colors.text })
1984
+ children: [
1985
+ showHeaderBar ? /* @__PURE__ */ jsx(
1986
+ DrawerHeaderBar,
1987
+ {
1988
+ brand: header,
1989
+ closeHint: labels.closeHint,
1990
+ closeLabel: labels.closeLabel,
1991
+ testID: `${drawerTestID}-header`,
1992
+ onClose
1993
+ }
1994
+ ) : null,
1995
+ /* @__PURE__ */ jsx(NavAccordionContext.Provider, { value: true, children: showHeaderBar ? /* @__PURE__ */ jsx(View, { style: styles9.panelBody, children: renderTextSlot(sidebar, { color: theme.colors.text }) }) : renderTextSlot(sidebar, { color: theme.colors.text }) })
1996
+ ]
1854
1997
  }
1855
1998
  )
1856
1999
  ] });
@@ -1866,7 +2009,7 @@ function useContentMaxWidth(width) {
1866
2009
  return resolveContentMaxWidth(width, viewport);
1867
2010
  }
1868
2011
  var DEFAULT_CONTENT_PADDING = 24;
1869
- var styles8 = StyleSheet.create({
2012
+ var styles10 = StyleSheet.create({
1870
2013
  root: { flex: 1 },
1871
2014
  // Auth-pending spinner: an opaque absolute overlay over the mounted shell, so
1872
2015
  // `children` (and any navigator they host) are never unmounted while the gate
@@ -1928,13 +2071,13 @@ var AppShell = ({
1928
2071
  }, [isUnauthenticated, gate]);
1929
2072
  const gatePending = gate?.pending === true;
1930
2073
  if (isUnauthenticated) return null;
1931
- const columnStyle = maxWidth === "full" ? styles8.columnFull : [styles8.columnCapped, { maxWidth }];
1932
- const navInnerStyle = chromeAlignment === "content" && maxWidth !== "full" ? [styles8.chromeCapped, { maxWidth, paddingHorizontal: contentPadding }] : void 0;
2074
+ const columnStyle = maxWidth === "full" ? styles10.columnFull : [styles10.columnCapped, { maxWidth }];
2075
+ const navInnerStyle = chromeAlignment === "content" && maxWidth !== "full" ? [styles10.chromeCapped, { maxWidth, paddingHorizontal: contentPadding }] : void 0;
1933
2076
  const scroller = /* @__PURE__ */ jsxs(
1934
2077
  ScrollView,
1935
2078
  {
1936
- contentContainerStyle: [styles8.scrollContent, { padding: contentPadding }],
1937
- style: styles8.scroll,
2079
+ contentContainerStyle: [styles10.scrollContent, { padding: contentPadding }],
2080
+ style: styles10.scroll,
1938
2081
  testID: `${testID}${APP_SHELL_SUFFIX.content}`,
1939
2082
  children: [
1940
2083
  look.band,
@@ -1942,7 +2085,7 @@ var AppShell = ({
1942
2085
  ]
1943
2086
  }
1944
2087
  );
1945
- const headerRegion = useDrawer ? /* @__PURE__ */ jsxs(View, { style: [styles8.headerRow, look.chrome], testID: `${testID}${APP_SHELL_SUFFIX.header}`, children: [
2088
+ const headerRegion = useDrawer ? /* @__PURE__ */ jsxs(View, { style: [styles10.headerRow, look.chrome], testID: `${testID}${APP_SHELL_SUFFIX.header}`, children: [
1946
2089
  /* @__PURE__ */ jsx(
1947
2090
  MenuToggle,
1948
2091
  {
@@ -1952,14 +2095,14 @@ var AppShell = ({
1952
2095
  onOpen: openDrawer
1953
2096
  }
1954
2097
  ),
1955
- /* @__PURE__ */ jsx(View, { style: styles8.headerFill, children: renderTextSlot(header, { color: look.chromeText }) })
2098
+ /* @__PURE__ */ jsx(View, { style: styles10.headerFill, children: renderTextSlot(header, { color: look.chromeText }) })
1956
2099
  ] }) : /* @__PURE__ */ jsx(View, { style: look.chrome, testID: `${testID}${APP_SHELL_SUFFIX.header}`, children: renderTextSlot(header, { color: look.chromeText }) });
1957
2100
  const railRegion = railMode === "full" ? /* @__PURE__ */ jsx(View, { testID: `${testID}${APP_SHELL_SUFFIX.sidebar}`, children: renderTextSlot(sidebar, { color: theme.colors.text }) }) : railMode === "collapsed" ? /* @__PURE__ */ jsx(View, { testID: `${testID}${APP_SHELL_SUFFIX.collapsedSidebar}`, children: renderTextSlot(collapsedSidebar, { color: theme.colors.text }) }) : null;
1958
- return /* @__PURE__ */ jsxs(View, { style: [styles8.root, look.root], testID, children: [
2101
+ return /* @__PURE__ */ jsxs(View, { style: [styles10.root, look.root], testID, children: [
1959
2102
  headerRegion,
1960
2103
  nav !== void 0 ? /* @__PURE__ */ jsx(View, { style: look.chrome, testID: `${testID}${APP_SHELL_SUFFIX.nav}`, children: navInnerStyle !== void 0 ? /* @__PURE__ */ jsx(View, { style: navInnerStyle, children: renderTextSlot(nav, { color: look.chromeText }) }) : renderTextSlot(nav, { color: look.chromeText }) }) : null,
1961
2104
  banner !== void 0 ? /* @__PURE__ */ jsx(View, { testID: `${testID}${APP_SHELL_SUFFIX.banner}`, children: renderTextSlot(banner, { color: theme.colors.text }) }) : null,
1962
- railRegion !== null ? /* @__PURE__ */ jsxs(View, { style: styles8.bodyRow, children: [
2105
+ railRegion !== null ? /* @__PURE__ */ jsxs(View, { style: styles10.bodyRow, children: [
1963
2106
  railRegion,
1964
2107
  scroller
1965
2108
  ] }) : scroller,
@@ -1968,15 +2111,17 @@ var AppShell = ({
1968
2111
  {
1969
2112
  drawerTestID: `${testID}${APP_SHELL_SUFFIX.drawer}`,
1970
2113
  labels: drawerLabels,
2114
+ header: mobileMenu?.header,
1971
2115
  scrimTestID: `${testID}${APP_SHELL_SUFFIX.scrim}`,
1972
- sidebar,
2116
+ sidebar: mobileMenu?.sidebar ?? sidebar,
2117
+ width: mobileMenu?.width,
1973
2118
  onClose: closeDrawer
1974
2119
  }
1975
2120
  ) : null,
1976
2121
  gatePending ? /* @__PURE__ */ jsx(
1977
2122
  View,
1978
2123
  {
1979
- style: [styles8.pendingOverlay, { backgroundColor: theme.colors.background }],
2124
+ style: [styles10.pendingOverlay, { backgroundColor: theme.colors.background }],
1980
2125
  testID: `${testID}${APP_SHELL_SUFFIX.pending}`,
1981
2126
  children: /* @__PURE__ */ jsx(ActivityIndicator, { color: primary, size: "large" })
1982
2127
  }
@@ -2037,6 +2182,45 @@ var CollapsedRail = ({
2037
2182
  }
2038
2183
  );
2039
2184
  };
2185
+ function renderShellSidebar({ sideRail, nav, width, showBrand }) {
2186
+ const brandSlot = sideRail.brand ?? sideRail.title;
2187
+ return /* @__PURE__ */ jsx(
2188
+ Sidebar,
2189
+ {
2190
+ collapseHint: sideRail.collapseHint,
2191
+ containerStyle: sideRail.containerStyle,
2192
+ enableInlineSearch: sideRail.enableInlineSearch,
2193
+ expandHint: sideRail.expandHint,
2194
+ footer: sideRail.footer,
2195
+ header: sideRail.header,
2196
+ items: sideRail.items,
2197
+ navigateHint: nav.navigateHint,
2198
+ paletteTrigger: sideRail.paletteTrigger,
2199
+ pathname: nav.pathname,
2200
+ regionLabel: nav.regionLabel,
2201
+ renderChevron: sideRail.renderChevron,
2202
+ search: sideRail.search,
2203
+ searchQuery: sideRail.searchQuery,
2204
+ title: showBrand ? brandSlot : null,
2205
+ width,
2206
+ onNavigate: nav.onNavigate,
2207
+ onSearchChange: sideRail.onSearchChange
2208
+ }
2209
+ );
2210
+ }
2211
+ var styles11 = StyleSheet.create({
2212
+ row: { flexDirection: "row", alignItems: "center" },
2213
+ brand: { justifyContent: "center", paddingHorizontal: 12 },
2214
+ fill: { flex: 1 }
2215
+ });
2216
+ var TopbarBrandRow = ({ brand, brandWidth, testID, children }) => {
2217
+ const { width } = useWindowDimensions();
2218
+ if (width < RAIL_FULL_BREAKPOINT) return /* @__PURE__ */ jsx(Fragment, { children });
2219
+ return /* @__PURE__ */ jsxs(View, { style: styles11.row, testID, children: [
2220
+ /* @__PURE__ */ jsx(View, { style: [styles11.brand, brandWidth !== void 0 ? { width: brandWidth } : null], testID: `${testID}-brand`, children: brand }),
2221
+ /* @__PURE__ */ jsx(View, { style: styles11.fill, children })
2222
+ ] });
2223
+ };
2040
2224
  function wantsTopBar(layout, hasHeader) {
2041
2225
  return layout === "top" || layout === "both" || hasHeader;
2042
2226
  }
@@ -2055,6 +2239,11 @@ var NavShell = ({
2055
2239
  children,
2056
2240
  collapsedSidebar: collapsedSidebarProp,
2057
2241
  collapsedRailRange: collapsedRailRangeProp,
2242
+ brandPlacement = NAV_BRAND_DEFAULTS.brandPlacement,
2243
+ sidebarWidth = NAV_BRAND_DEFAULTS.sidebarWidth,
2244
+ drawerHeader = NAV_BRAND_DEFAULTS.drawerHeader,
2245
+ drawerWidth = NAV_BRAND_DEFAULTS.drawerWidth,
2246
+ mobileMenu,
2058
2247
  ...shellProps
2059
2248
  }) => {
2060
2249
  const showTopBar = wantsTopBar(layout, header !== void 0);
@@ -2080,28 +2269,13 @@ var NavShell = ({
2080
2269
  onNavigate
2081
2270
  }
2082
2271
  ) : null;
2083
- const sidebarNode = showSideRail && sideRail !== void 0 ? /* @__PURE__ */ jsx(
2084
- Sidebar,
2085
- {
2086
- collapseHint: sideRail.collapseHint,
2087
- containerStyle: sideRail.containerStyle,
2088
- enableInlineSearch: sideRail.enableInlineSearch,
2089
- expandHint: sideRail.expandHint,
2090
- footer: sideRail.footer,
2091
- header: sideRail.header,
2092
- items: sideRail.items,
2093
- navigateHint,
2094
- paletteTrigger: sideRail.paletteTrigger,
2095
- pathname,
2096
- regionLabel,
2097
- renderChevron: sideRail.renderChevron,
2098
- search: sideRail.search,
2099
- searchQuery: sideRail.searchQuery,
2100
- title: sideRail.brand ?? sideRail.title,
2101
- onNavigate,
2102
- onSearchChange: sideRail.onSearchChange
2103
- }
2104
- ) : void 0;
2272
+ const nav = { pathname, onNavigate, regionLabel, navigateHint };
2273
+ const rail = showSideRail ? sideRail : void 0;
2274
+ const brandInBar = brandPlacement === "topbar" && rail?.brand !== void 0;
2275
+ const brandInDrawer = drawerHeader === "brand" ? rail?.brand : void 0;
2276
+ const sidebarNode = rail === void 0 ? void 0 : renderShellSidebar({ sideRail: rail, nav, width: sidebarWidth, showBrand: !brandInBar });
2277
+ const drawerSidebar = rail !== void 0 && brandInDrawer !== void 0 && !brandInBar ? renderShellSidebar({ sideRail: rail, nav, width: sidebarWidth, showBrand: false }) : void 0;
2278
+ const shellHeader = brandInBar ? /* @__PURE__ */ jsx(TopbarBrandRow, { brand: rail?.brand, brandWidth: SIDEBAR_WIDTH_PX[sidebarWidth], testID: `${shellProps.testID}-topbar-brand-row`, children: headerNode }) : headerNode;
2105
2279
  const collapsedCfg = showSideRail ? sideRail?.collapsed : void 0;
2106
2280
  const collapsedNode = collapsedCfg !== void 0 && sideRail !== void 0 ? /* @__PURE__ */ jsx(
2107
2281
  CollapsedRail,
@@ -2122,7 +2296,8 @@ var NavShell = ({
2122
2296
  ...shellProps,
2123
2297
  collapsedRailRange: collapsedRange,
2124
2298
  collapsedSidebar: collapsedNode,
2125
- header: headerNode,
2299
+ header: shellHeader,
2300
+ mobileMenu: { ...mobileMenu, header: brandInDrawer, width: drawerWidth, sidebar: drawerSidebar },
2126
2301
  sidebar: sidebarNode,
2127
2302
  children
2128
2303
  }
@@ -2345,7 +2520,7 @@ var KEY_DOWN = "ArrowDown";
2345
2520
  var KEY_UP = "ArrowUp";
2346
2521
  var KEY_ENTER = "Enter";
2347
2522
  var KEY_ESCAPE = "Escape";
2348
- var styles9 = StyleSheet.create({
2523
+ var styles12 = StyleSheet.create({
2349
2524
  overlay: { ...StyleSheet.absoluteFillObject, zIndex: OVERLAY_Z_INDEX, alignItems: "center" },
2350
2525
  scrim: { ...StyleSheet.absoluteFillObject, backgroundColor: SCRIM_COLOR2 },
2351
2526
  panel: {
@@ -2374,14 +2549,14 @@ var PaletteRow = ({ item, selected, onChoose }) => {
2374
2549
  accessibilityLabel: item.label,
2375
2550
  accessibilityRole: "button",
2376
2551
  accessibilityState: { selected },
2377
- style: [styles9.row, selected ? { backgroundColor: colors.border } : void 0],
2552
+ style: [styles12.row, selected ? { backgroundColor: colors.border } : void 0],
2378
2553
  testID: item.testID ?? item.key,
2379
2554
  onPress: () => onChoose(item),
2380
2555
  children: [
2381
2556
  typeof item.renderIcon === "function" ? item.renderIcon(colors.textSecondary, NAV_ICON_SIZE) : null,
2382
- /* @__PURE__ */ jsxs(View, { style: styles9.rowText, children: [
2383
- /* @__PURE__ */ jsx(Text, { style: [styles9.rowLabel, { color: colors.text }], children: item.label }),
2384
- item.hint ? /* @__PURE__ */ jsx(Text, { style: [styles9.rowHint, { color: colors.textSecondary }], children: item.hint }) : null
2557
+ /* @__PURE__ */ jsxs(View, { style: styles12.rowText, children: [
2558
+ /* @__PURE__ */ jsx(Text, { style: [styles12.rowLabel, { color: colors.text }], children: item.label }),
2559
+ item.hint ? /* @__PURE__ */ jsx(Text, { style: [styles12.rowHint, { color: colors.textSecondary }], children: item.hint }) : null
2385
2560
  ] })
2386
2561
  ]
2387
2562
  }
@@ -2421,14 +2596,14 @@ var CommandPalette = ({ open, items, onClose, labels, testID }) => {
2421
2596
  [results, selected, choose, onClose]
2422
2597
  );
2423
2598
  if (!open) return null;
2424
- return /* @__PURE__ */ jsxs(View, { style: styles9.overlay, children: [
2599
+ return /* @__PURE__ */ jsxs(View, { style: styles12.overlay, children: [
2425
2600
  /* @__PURE__ */ jsx(
2426
2601
  Pressable,
2427
2602
  {
2428
2603
  accessibilityHint: labels.closeHint,
2429
2604
  accessibilityLabel: labels.closeLabel,
2430
2605
  accessibilityRole: "button",
2431
- style: styles9.scrim,
2606
+ style: styles12.scrim,
2432
2607
  testID: `${testID ?? "command-palette"}-scrim`,
2433
2608
  onPress: onClose
2434
2609
  }
@@ -2439,7 +2614,7 @@ var CommandPalette = ({ open, items, onClose, labels, testID }) => {
2439
2614
  "aria-modal": true,
2440
2615
  "aria-label": labels.regionLabel,
2441
2616
  role: "dialog",
2442
- style: [styles9.panel, { backgroundColor: colors.surface, borderColor: colors.border }],
2617
+ style: [styles12.panel, { backgroundColor: colors.surface, borderColor: colors.border }],
2443
2618
  testID: testID ?? "command-palette",
2444
2619
  children: [
2445
2620
  /* @__PURE__ */ jsx(
@@ -2449,14 +2624,14 @@ var CommandPalette = ({ open, items, onClose, labels, testID }) => {
2449
2624
  accessibilityLabel: labels.placeholder,
2450
2625
  placeholder: labels.placeholder,
2451
2626
  placeholderTextColor: colors.textSecondary,
2452
- style: [styles9.input, { color: colors.text, borderBottomColor: colors.border }],
2627
+ style: [styles12.input, { color: colors.text, borderBottomColor: colors.border }],
2453
2628
  testID: `${testID ?? "command-palette"}-input`,
2454
2629
  value: query,
2455
2630
  onChangeText: setQuery,
2456
2631
  onKeyPress
2457
2632
  }
2458
2633
  ),
2459
- results.length === 0 ? /* @__PURE__ */ jsx(Text, { style: [styles9.empty, { color: colors.textSecondary }], children: labels.emptyText }) : /* @__PURE__ */ jsx(ScrollView, { keyboardShouldPersistTaps: "handled", style: styles9.list, children: results.map((item, index) => /* @__PURE__ */ jsx(PaletteRow, { item, selected: index === selected, onChoose: choose }, item.key)) })
2634
+ results.length === 0 ? /* @__PURE__ */ jsx(Text, { style: [styles12.empty, { color: colors.textSecondary }], children: labels.emptyText }) : /* @__PURE__ */ jsx(ScrollView, { keyboardShouldPersistTaps: "handled", style: styles12.list, children: results.map((item, index) => /* @__PURE__ */ jsx(PaletteRow, { item, selected: index === selected, onChoose: choose }, item.key)) })
2460
2635
  ]
2461
2636
  }
2462
2637
  )
@@ -2561,7 +2736,7 @@ var TAB_MIN_HEIGHT = 56;
2561
2736
  var LABEL_SIZE = 12;
2562
2737
  var LABEL_GAP = 2;
2563
2738
  var TAB_PADDING = 4;
2564
- var styles10 = StyleSheet.create({
2739
+ var styles13 = StyleSheet.create({
2565
2740
  tab: {
2566
2741
  flex: 1,
2567
2742
  minHeight: TAB_MIN_HEIGHT,
@@ -2598,31 +2773,31 @@ var BottomTab = ({
2598
2773
  accessibilityLabel: item.label,
2599
2774
  accessibilityRole: "link",
2600
2775
  accessibilityState: { selected: isActive },
2601
- style: [styles10.tab, { opacity: feedback.opacity }],
2776
+ style: [styles13.tab, { opacity: feedback.opacity }],
2602
2777
  testID: item.testID ?? item.key,
2603
2778
  onPress: () => onPress(item.route),
2604
2779
  onPressIn: () => setPressed(true),
2605
2780
  onPressOut: () => setPressed(false),
2606
2781
  ...ariaCurrentProps3(isActive),
2607
2782
  children: [
2608
- /* @__PURE__ */ jsxs(Animated.View, { style: [styles10.iconWrap, { transform: [{ scale }] }], children: [
2783
+ /* @__PURE__ */ jsxs(Animated.View, { style: [styles13.iconWrap, { transform: [{ scale }] }], children: [
2609
2784
  feedback.pillScale === null ? null : /* @__PURE__ */ jsx(
2610
2785
  View,
2611
2786
  {
2612
2787
  pointerEvents: "none",
2613
- style: [styles10.pill, { backgroundColor: colors.pill, transform: [{ scale: feedback.pillScale }] }, motion]
2788
+ style: [styles13.pill, { backgroundColor: colors.pill, transform: [{ scale: feedback.pillScale }] }, motion]
2614
2789
  }
2615
2790
  ),
2616
2791
  /* @__PURE__ */ jsx(View, { style: [{ transform: feedback.iconTransform }, motion], children: item.renderIcon?.(color, ICON_SIZE) })
2617
2792
  ] }),
2618
- /* @__PURE__ */ jsx(Text, { style: [styles10.label, { color }], children: item.label })
2793
+ /* @__PURE__ */ jsx(Text, { style: [styles13.label, { color }], children: item.label })
2619
2794
  ]
2620
2795
  }
2621
2796
  );
2622
2797
  };
2623
2798
  var DEFAULT_TEST_ID = "bottom-tab-bar";
2624
2799
  var SLIDER_HEIGHT = 3;
2625
- var styles11 = StyleSheet.create({
2800
+ var styles14 = StyleSheet.create({
2626
2801
  bar: { flexDirection: "row", borderTopWidth: StyleSheet.hairlineWidth },
2627
2802
  slider: { position: "absolute", top: 0, height: SLIDER_HEIGHT }
2628
2803
  });
@@ -2649,14 +2824,14 @@ var BottomTabBar = ({
2649
2824
  {
2650
2825
  "aria-label": regionLabel,
2651
2826
  role: "navigation",
2652
- style: [styles11.bar, { backgroundColor: theme.colors.surface, borderTopColor: theme.colors.border }, containerStyle],
2827
+ style: [styles14.bar, { backgroundColor: theme.colors.surface, borderTopColor: theme.colors.border }, containerStyle],
2653
2828
  testID,
2654
2829
  children: [
2655
2830
  bar === null ? null : /* @__PURE__ */ jsx(
2656
2831
  View,
2657
2832
  {
2658
2833
  pointerEvents: "none",
2659
- style: [styles11.slider, { left: bar.left, width: bar.width, backgroundColor: primary }, webTransition("left", barMs, reducedMotion)]
2834
+ style: [styles14.slider, { left: bar.left, width: bar.width, backgroundColor: primary }, webTransition("left", barMs, reducedMotion)]
2660
2835
  }
2661
2836
  ),
2662
2837
  items.map((item) => /* @__PURE__ */ jsx(
@@ -2677,6 +2852,6 @@ var BottomTabBar = ({
2677
2852
  );
2678
2853
  };
2679
2854
 
2680
- export { ACTIVE_BORDER_RADIUS, ACTIVE_TINT_OPACITY, APP_SHELL_SUFFIX, AppShell, BASE_INDENT, BottomTabBar, BrandHomeLink, BrandMark, CHEVRON_ICON_SIZE, CollapsedRail, CommandPalette, CommandPaletteTrigger, DEFAULT_COLLAPSED_RAIL_MAX, DEFAULT_SEARCH_BREAKPOINT, DarkModeControl, HOVER_TINT_OPACITY, NAV_ICON_SIZE, NAV_LINK_GAP, NAV_ROW_RADIUS, NAV_TEST_IDS, Nav, NavBar, NavExpandableItem, NavHoverFeedback, NavOverflowMenu, NavShell, PillNav, PillNavVariant, RAIL_FULL_BREAKPOINT, Sidebar, SidebarChevron, SidebarSearch, TabFeedback, Topbar, accessibleNavItems, collapsedRailStyles, darkModeStyles, expandableStyles, filterCommands, filterNavItems, isFilterActive, isRouteActive, navStyles, pillNavStyles, resolveActiveRoute, resolveContentMaxWidth, resolvePillMenuLabel, resolveRailMode, resolveSearchAffordance, roleRoutesToNavItems, searchTokens, useCommandPaletteHotkey, useContentMaxWidth };
2855
+ export { ACTIVE_BORDER_RADIUS, ACTIVE_TINT_OPACITY, APP_SHELL_SUFFIX, AppShell, BASE_INDENT, BottomTabBar, BrandHomeLink, BrandMark, CHEVRON_ICON_SIZE, CollapsedRail, CommandPalette, CommandPaletteTrigger, DEFAULT_COLLAPSED_RAIL_MAX, DEFAULT_SEARCH_BREAKPOINT, DarkModeControl, HOVER_TINT_OPACITY, NAV_BRAND_DEFAULTS, NAV_ICON_SIZE, NAV_LINK_GAP, NAV_ROW_RADIUS, NAV_TEST_IDS, Nav, NavBar, NavExpandableItem, NavHoverFeedback, NavOverflowMenu, NavShell, PillNav, PillNavVariant, RAIL_FULL_BREAKPOINT, SIDEBAR_WIDTH_PX, Sidebar, SidebarChevron, SidebarSearch, TabFeedback, Topbar, accessibleNavItems, collapsedRailStyles, darkModeStyles, expandableStyles, filterCommands, filterNavItems, isFilterActive, isRouteActive, navStyles, pillNavStyles, resolveActiveRoute, resolveContentMaxWidth, resolvePillMenuLabel, resolveRailMode, resolveSearchAffordance, roleRoutesToNavItems, searchTokens, useCommandPaletteHotkey, useContentMaxWidth };
2681
2856
  //# sourceMappingURL=index.mjs.map
2682
2857
  //# sourceMappingURL=index.mjs.map