@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.js CHANGED
@@ -28,7 +28,6 @@ var NAV_LINK_GAP = 4;
28
28
  var navStyles = reactNative.StyleSheet.create({
29
29
  // --- Sidebar ---
30
30
  sidebarContainer: {
31
- width: 220,
32
31
  paddingTop: 24,
33
32
  paddingHorizontal: 12,
34
33
  borderRightWidth: 1,
@@ -486,6 +485,18 @@ function resolveActiveRoute(items, pathname) {
486
485
  }
487
486
  return winner;
488
487
  }
488
+ var NavAccordionContext = React.createContext(false);
489
+ function hasActiveDescendant(item, pathname) {
490
+ if (isRouteActive(pathname, item.route)) return true;
491
+ return (item.children ?? []).some((child) => hasActiveDescendant(child, pathname));
492
+ }
493
+ function initialOpenGroup(items, pathname) {
494
+ const hasChildren = (item) => (item.children ?? []).length > 0;
495
+ return items.find((item) => hasChildren(item) && hasActiveDescendant(item, pathname))?.key;
496
+ }
497
+ function nextOpenGroup(current, pressed) {
498
+ return current === pressed ? void 0 : pressed;
499
+ }
489
500
  var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
490
501
  function getReducedMotionQuery() {
491
502
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return void 0;
@@ -535,10 +546,6 @@ function ariaExpandedProps(expanded) {
535
546
  function hoverHandlerProps(onIn, onOut) {
536
547
  return IS_WEB ? { onHoverIn: onIn, onHoverOut: onOut } : {};
537
548
  }
538
- function hasActiveDescendant(item, pathname) {
539
- if (isRouteActive(pathname, item.route)) return true;
540
- return (item.children ?? []).some((child) => hasActiveDescendant(child, pathname));
541
- }
542
549
  function TintOverlay({
543
550
  opacity,
544
551
  color,
@@ -562,15 +569,21 @@ var NavExpandableItem = ({
562
569
  collapseHint,
563
570
  renderChevron,
564
571
  activeRoute,
565
- depth = 0
572
+ depth = 0,
573
+ expanded: expandedProp,
574
+ onToggle
566
575
  }) => {
567
- const [expanded, setExpanded] = React.useState(() => hasActiveDescendant(item, pathname));
576
+ const [internalExpanded, setExpanded] = React.useState(() => hasActiveDescendant(item, pathname));
577
+ const expanded = expandedProp ?? internalExpanded;
568
578
  const [focused, setFocused] = React.useState(false);
569
579
  const [hovered, setHovered] = React.useState(false);
570
580
  const { theme } = uiFeedback.useUi();
571
581
  const colors = theme.colors;
572
582
  const primaryColor = theme.palette.primary["500"];
573
- const toggle = React.useCallback(() => setExpanded((v) => !v), []);
583
+ const toggle = React.useCallback(() => {
584
+ if (onToggle !== void 0) onToggle(item.key);
585
+ else setExpanded((v) => !v);
586
+ }, [onToggle, item.key]);
574
587
  const onHoverIn = React.useCallback(() => setHovered(true), []);
575
588
  const onHoverOut = React.useCallback(() => setHovered(false), []);
576
589
  const indent = depth * BASE_INDENT;
@@ -681,9 +694,72 @@ var DEFAULT_SEARCH_BREAKPOINT = uiLayout.LAYOUT_COLLAPSE_BREAKPOINT;
681
694
  function resolveSearchAffordance(viewport, breakpoint = DEFAULT_SEARCH_BREAKPOINT) {
682
695
  return viewport >= breakpoint ? "inline" : "palette";
683
696
  }
697
+
698
+ // src/sidebarEdgeFade.ts
699
+ var EDGE_TOLERANCE = 1;
700
+ function resolveEdgeFades({ offsetY, viewportHeight, contentHeight }) {
701
+ const hiddenBelow = contentHeight - (offsetY + viewportHeight);
702
+ return { top: offsetY > EDGE_TOLERANCE, bottom: hiddenBelow > EDGE_TOLERANCE };
703
+ }
704
+ var FADE_BAND_HEIGHT = 6;
705
+ var FADE_BAND_OPACITIES = [0.9, 0.65, 0.4, 0.15];
706
+ var SCROLL_EVENT_THROTTLE_MS = 16;
707
+ var styles2 = reactNative.StyleSheet.create({
708
+ area: { flex: 1, minHeight: 0 },
709
+ fade: { position: "absolute", left: 0, right: 0 },
710
+ fadeTop: { top: 0 },
711
+ fadeBottom: { bottom: 0, flexDirection: "column-reverse" },
712
+ band: { height: FADE_BAND_HEIGHT }
713
+ });
714
+ function EdgeFade({ edge, color }) {
715
+ return /* @__PURE__ */ jsxRuntime.jsx(
716
+ reactNative.View,
717
+ {
718
+ pointerEvents: "none",
719
+ style: [styles2.fade, edge === "top" ? styles2.fadeTop : styles2.fadeBottom],
720
+ testID: `sidebar-fade-${edge}`,
721
+ children: FADE_BAND_OPACITIES.map((opacity) => /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles2.band, { backgroundColor: color, opacity }] }, opacity))
722
+ }
723
+ );
724
+ }
725
+ var SidebarScrollArea = ({ children }) => {
726
+ const { theme } = uiFeedback.useUi();
727
+ const metrics = React.useRef({ offsetY: 0, viewportHeight: 0, contentHeight: 0 });
728
+ const [fades, setFades] = React.useState({ top: false, bottom: false });
729
+ const update = React.useCallback((next) => {
730
+ metrics.current = { ...metrics.current, ...next };
731
+ const resolved = resolveEdgeFades(metrics.current);
732
+ setFades((prev) => prev.top === resolved.top && prev.bottom === resolved.bottom ? prev : resolved);
733
+ }, []);
734
+ const onLayout = React.useCallback(
735
+ (e) => update({ viewportHeight: e.nativeEvent.layout.height }),
736
+ [update]
737
+ );
738
+ const onContentSizeChange = React.useCallback((_w, h) => update({ contentHeight: h }), [update]);
739
+ const onScroll = React.useCallback(
740
+ (e) => update({ offsetY: e.nativeEvent.contentOffset.y }),
741
+ [update]
742
+ );
743
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles2.area, children: [
744
+ /* @__PURE__ */ jsxRuntime.jsx(
745
+ reactNative.ScrollView,
746
+ {
747
+ scrollEventThrottle: SCROLL_EVENT_THROTTLE_MS,
748
+ style: styles2.area,
749
+ testID: "sidebar-scroll",
750
+ onContentSizeChange,
751
+ onLayout,
752
+ onScroll,
753
+ children
754
+ }
755
+ ),
756
+ fades.top ? /* @__PURE__ */ jsxRuntime.jsx(EdgeFade, { color: theme.colors.surface, edge: "top" }) : null,
757
+ fades.bottom ? /* @__PURE__ */ jsxRuntime.jsx(EdgeFade, { color: theme.colors.surface, edge: "bottom" }) : null
758
+ ] });
759
+ };
684
760
  var FIELD_MIN_HEIGHT = 38;
685
761
  var CLEAR_GLYPH = "\u2715";
686
- var styles2 = reactNative.StyleSheet.create({
762
+ var styles3 = reactNative.StyleSheet.create({
687
763
  wrap: {
688
764
  flexDirection: "row",
689
765
  alignItems: "center",
@@ -724,7 +800,7 @@ var SidebarSearch = ({
724
800
  reactNative.View,
725
801
  {
726
802
  style: [
727
- styles2.wrap,
803
+ styles3.wrap,
728
804
  { backgroundColor: colors.surface, borderColor: focused ? primary : colors.border },
729
805
  focusRingStyle(focused, primary)
730
806
  ],
@@ -736,7 +812,7 @@ var SidebarSearch = ({
736
812
  accessibilityLabel: labels.placeholder,
737
813
  placeholder: labels.placeholder,
738
814
  placeholderTextColor: colors.textSecondary,
739
- style: [styles2.input, { color: colors.text }],
815
+ style: [styles3.input, { color: colors.text }],
740
816
  testID,
741
817
  value,
742
818
  onBlur: () => setFocused(false),
@@ -750,16 +826,30 @@ var SidebarSearch = ({
750
826
  accessibilityHint: labels.clearHint,
751
827
  accessibilityLabel: labels.clearLabel,
752
828
  accessibilityRole: "button",
753
- style: styles2.clear,
829
+ style: styles3.clear,
754
830
  testID: `${testID}-clear`,
755
831
  onPress: onClear,
756
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles2.clearGlyph, { color: colors.textSecondary }], children: CLEAR_GLYPH })
832
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles3.clearGlyph, { color: colors.textSecondary }], children: CLEAR_GLYPH })
757
833
  }
758
834
  ) : null
759
835
  ]
760
836
  }
761
837
  );
762
838
  };
839
+
840
+ // src/types.ts
841
+ var SIDEBAR_WIDTH_PX = {
842
+ default: 220,
843
+ sm: 240,
844
+ md: 264,
845
+ lg: 288
846
+ };
847
+ var NAV_BRAND_DEFAULTS = {
848
+ brandPlacement: "sidebar",
849
+ sidebarWidth: "default",
850
+ drawerHeader: "none",
851
+ drawerWidth: "default"
852
+ };
763
853
  function isBareText(node) {
764
854
  return typeof node === "string" || typeof node === "number";
765
855
  }
@@ -777,6 +867,7 @@ var Sidebar = ({
777
867
  pathname,
778
868
  onNavigate,
779
869
  title,
870
+ width: railWidth = "default",
780
871
  regionLabel,
781
872
  navigateHint = (label) => label,
782
873
  expandHint = "",
@@ -812,6 +903,10 @@ var Sidebar = ({
812
903
  const visibleItems = showInlineSearch ? filterNavItems(items, query) : items;
813
904
  const showEmpty = showInlineSearch && isFilterActive(query) && visibleItems.length === 0;
814
905
  const activeRoute = resolveActiveRoute(items, pathname);
906
+ const accordion = React.useContext(NavAccordionContext);
907
+ const [openGroup, setOpenGroup] = React.useState(() => initialOpenGroup(items, pathname));
908
+ const toggleGroup = React.useCallback((key) => setOpenGroup((current) => nextOpenGroup(current, key)), []);
909
+ const accordionProps = (item) => accordion && (item.children ?? []).length > 0 ? { expanded: openGroup === item.key, onToggle: toggleGroup } : {};
815
910
  return /* @__PURE__ */ jsxRuntime.jsxs(
816
911
  reactNative.View,
817
912
  {
@@ -820,11 +915,12 @@ var Sidebar = ({
820
915
  role: "navigation",
821
916
  style: [
822
917
  navStyles.sidebarContainer,
918
+ { width: SIDEBAR_WIDTH_PX[railWidth] },
823
919
  { backgroundColor: colors.surface, borderRightColor: colors.border },
824
920
  containerStyle
825
921
  ],
826
922
  children: [
827
- typeof title === "string" ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: [navStyles.sidebarTitle, { color: colors.text }], children: title }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: navStyles.sidebarBrand, children: title }),
923
+ title === null ? null : typeof title === "string" ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityRole: "header", style: [navStyles.sidebarTitle, { color: colors.text }], children: title }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: navStyles.sidebarBrand, children: title }),
828
924
  showInlineSearch && search !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
829
925
  SidebarSearch,
830
926
  {
@@ -845,22 +941,24 @@ var Sidebar = ({
845
941
  onPress: paletteTrigger.onOpen
846
942
  }
847
943
  ) }) : null,
848
- renderTextSlot(header, { color: colors.text }),
849
- showEmpty && search !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [navStyles.sidebarEmpty, { color: colors.textSecondary }], testID: "sidebar-search-empty", children: search.emptyText }) : visibleItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
850
- NavExpandableItem,
851
- {
852
- activeRoute,
853
- collapseHint,
854
- expandHint,
855
- item,
856
- navigateHint,
857
- pathname,
858
- renderChevron,
859
- onNavigate
860
- },
861
- item.key
862
- )),
863
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: navStyles.sidebarSpacer }),
944
+ /* @__PURE__ */ jsxRuntime.jsxs(SidebarScrollArea, { children: [
945
+ renderTextSlot(header, { color: colors.text }),
946
+ showEmpty && search !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [navStyles.sidebarEmpty, { color: colors.textSecondary }], testID: "sidebar-search-empty", children: search.emptyText }) : visibleItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
947
+ NavExpandableItem,
948
+ {
949
+ activeRoute,
950
+ collapseHint,
951
+ expandHint,
952
+ item,
953
+ navigateHint,
954
+ pathname,
955
+ renderChevron,
956
+ onNavigate,
957
+ ...accordionProps(item)
958
+ },
959
+ item.key
960
+ ))
961
+ ] }),
864
962
  renderTextSlot(footer, { color: colors.text })
865
963
  ]
866
964
  }
@@ -1582,7 +1680,7 @@ var NavBar = ({ barTheme, ...props }) => {
1582
1680
  if (barTheme === void 0) return /* @__PURE__ */ jsxRuntime.jsx(NavBarInner, { ...props });
1583
1681
  return /* @__PURE__ */ jsxRuntime.jsx(uiFeedback.UiProvider, { navigate, t, theme: barTheme, children: /* @__PURE__ */ jsxRuntime.jsx(NavBarInner, { ...props }) });
1584
1682
  };
1585
- var styles3 = reactNative.StyleSheet.create({
1683
+ var styles4 = reactNative.StyleSheet.create({
1586
1684
  hitBox: { minHeight: MIN_TOUCH_TARGET, minWidth: MIN_TOUCH_TARGET, justifyContent: "center" }
1587
1685
  });
1588
1686
  function anchorProps(route) {
@@ -1605,7 +1703,7 @@ var BrandHomeLink = ({ route, label, onNavigate, children }) => {
1605
1703
  {
1606
1704
  accessibilityLabel: label,
1607
1705
  accessibilityRole: "link",
1608
- style: [styles3.hitBox, focusRingStyle(focused, theme.palette.primary["500"])],
1706
+ style: [styles4.hitBox, focusRingStyle(focused, theme.palette.primary["500"])],
1609
1707
  testID: NAV_TEST_IDS.brandHome,
1610
1708
  onBlur: () => setFocused(false),
1611
1709
  onFocus: () => setFocused(true),
@@ -1618,7 +1716,7 @@ var BrandHomeLink = ({ route, label, onNavigate, children }) => {
1618
1716
  var DEFAULT_ICON_SIZE = 32;
1619
1717
  var NAME_FONT_SIZE = 16;
1620
1718
  var NAME_GAP = 8;
1621
- var styles4 = reactNative.StyleSheet.create({
1719
+ var styles5 = reactNative.StyleSheet.create({
1622
1720
  name: { flexShrink: 1, fontSize: NAME_FONT_SIZE, fontWeight: "700" },
1623
1721
  row: { alignItems: "center", flexDirection: "row", gap: NAME_GAP }
1624
1722
  });
@@ -1632,7 +1730,7 @@ var BrandMark = ({
1632
1730
  iconOnly = false
1633
1731
  }) => {
1634
1732
  const { theme } = uiFeedback.useUi();
1635
- return /* @__PURE__ */ jsxRuntime.jsx(BrandHomeLink, { label, route, onNavigate, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.row, children: [
1733
+ return /* @__PURE__ */ jsxRuntime.jsx(BrandHomeLink, { label, route, onNavigate, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles5.row, children: [
1636
1734
  /* @__PURE__ */ jsxRuntime.jsx(
1637
1735
  reactNative.Image,
1638
1736
  {
@@ -1646,7 +1744,7 @@ var BrandMark = ({
1646
1744
  reactNative.Text,
1647
1745
  {
1648
1746
  numberOfLines: 1,
1649
- style: [styles4.name, { color: theme.colors.text }],
1747
+ style: [styles5.name, { color: theme.colors.text }],
1650
1748
  testID: NAV_TEST_IDS.brandMarkName,
1651
1749
  children: name
1652
1750
  }
@@ -1659,7 +1757,7 @@ var Nav = (props) => {
1659
1757
  }
1660
1758
  return /* @__PURE__ */ jsxRuntime.jsx(NavBar, { ...props });
1661
1759
  };
1662
- var styles5 = reactNative.StyleSheet.create({
1760
+ var styles6 = reactNative.StyleSheet.create({
1663
1761
  band: { left: 0, position: "absolute", right: 0, top: 0 }
1664
1762
  });
1665
1763
  function readBackdrop(theme) {
@@ -1682,7 +1780,7 @@ function resolveShellBackdrop(theme, viewport, contentPadding, testID) {
1682
1780
  reactNative.View,
1683
1781
  {
1684
1782
  pointerEvents: "none",
1685
- style: [styles5.band, { backgroundColor: band.color, height: contentPadding + overlap }],
1783
+ style: [styles6.band, { backgroundColor: band.color, height: contentPadding + overlap }],
1686
1784
  testID: `${testID}${APP_SHELL_SUFFIX.band}`
1687
1785
  }
1688
1786
  );
@@ -1694,7 +1792,7 @@ var CARD_BORDER_WIDTH = 1;
1694
1792
  var CARD_TITLE_FONT_SIZE = 16;
1695
1793
  var CARD_MESSAGE_FONT_SIZE = 14;
1696
1794
  var CARD_TITLE_MARGIN_BOTTOM = 8;
1697
- var styles6 = reactNative.StyleSheet.create({
1795
+ var styles7 = reactNative.StyleSheet.create({
1698
1796
  // Loading is a TRANSITIONAL state: the spinner is an absolute overlay ON TOP of
1699
1797
  // stably-mounted children, never a replacement for them. Replacing children here
1700
1798
  // would unmount whatever they host (e.g. a navigator), and on remount React
@@ -1726,9 +1824,9 @@ function MessageCard({
1726
1824
  }) {
1727
1825
  const { theme } = uiFeedback.useUi();
1728
1826
  const colors = theme.colors;
1729
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles6.card, { backgroundColor: colors.surface, borderColor: accentColor }], testID, children: [
1730
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles6.cardTitle, { color: accentColor }], children: message.titleText }),
1731
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles6.cardMessage, { color: colors.textSecondary }], children: message.messageText })
1827
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles7.card, { backgroundColor: colors.surface, borderColor: accentColor }], testID, children: [
1828
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles7.cardTitle, { color: accentColor }], children: message.titleText }),
1829
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles7.cardMessage, { color: colors.textSecondary }], children: message.messageText })
1732
1830
  ] });
1733
1831
  }
1734
1832
  function useContentBody(state, children, testID) {
@@ -1740,18 +1838,45 @@ function useContentBody(state, children, testID) {
1740
1838
  return /* @__PURE__ */ jsxRuntime.jsx(MessageCard, { accentColor: errorColor, message: state.forbidden, testID: `${testID}${APP_SHELL_SUFFIX.forbidden}` });
1741
1839
  if (state.error)
1742
1840
  return /* @__PURE__ */ jsxRuntime.jsx(MessageCard, { accentColor: errorColor, message: state.error, testID: `${testID}${APP_SHELL_SUFFIX.error}` });
1743
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles6.loadingHost, children: [
1841
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles7.loadingHost, children: [
1744
1842
  children,
1745
1843
  state.loading === true ? /* @__PURE__ */ jsxRuntime.jsx(
1746
1844
  reactNative.View,
1747
1845
  {
1748
- style: [styles6.loadingOverlay, { backgroundColor: theme.colors.background }],
1846
+ style: [styles7.loadingOverlay, { backgroundColor: theme.colors.background }],
1749
1847
  testID: `${testID}${APP_SHELL_SUFFIX.loading}`,
1750
1848
  children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: primary, size: "large" })
1751
1849
  }
1752
1850
  ) : null
1753
1851
  ] });
1754
1852
  }
1853
+ var CLOSE_GLYPH = "\u2715";
1854
+ var CLOSE_GLYPH_FONT_SIZE = 18;
1855
+ var BAR_PADDING = 12;
1856
+ var styles8 = reactNative.StyleSheet.create({
1857
+ bar: { flexDirection: "row", alignItems: "center", paddingLeft: BAR_PADDING, borderBottomWidth: 1 },
1858
+ brand: { flex: 1 },
1859
+ close: { minWidth: MIN_TOUCH_TARGET, minHeight: MIN_TOUCH_TARGET, alignItems: "center", justifyContent: "center" },
1860
+ glyph: { fontSize: CLOSE_GLYPH_FONT_SIZE, fontWeight: "700" }
1861
+ });
1862
+ var DrawerHeaderBar = ({ brand, closeLabel, closeHint, onClose, testID }) => {
1863
+ const { theme } = uiFeedback.useUi();
1864
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles8.bar, { borderBottomColor: theme.colors.border }], testID, children: [
1865
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles8.brand, children: brand }),
1866
+ /* @__PURE__ */ jsxRuntime.jsx(
1867
+ FocusableTouchable,
1868
+ {
1869
+ accessibilityHint: closeHint,
1870
+ accessibilityLabel: closeLabel,
1871
+ ringColor: theme.palette.primary["500"],
1872
+ style: styles8.close,
1873
+ testID: `${testID}-close`,
1874
+ onPress: onClose,
1875
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles8.glyph, { color: theme.colors.text }], children: CLOSE_GLYPH })
1876
+ }
1877
+ )
1878
+ ] });
1879
+ };
1755
1880
  var SCRIM_COLOR = "rgba(0, 0, 0, 0.5)";
1756
1881
  var MENU_GLYPH2 = "\u2630";
1757
1882
  var MENU_GLYPH_FONT_SIZE = 20;
@@ -1772,7 +1897,7 @@ var DEFAULT_DRAWER_LABELS = {
1772
1897
  closeLabel: "Close menu",
1773
1898
  closeHint: "Close the navigation menu"
1774
1899
  };
1775
- var styles7 = reactNative.StyleSheet.create({
1900
+ var styles9 = reactNative.StyleSheet.create({
1776
1901
  overlay: { ...reactNative.StyleSheet.absoluteFillObject, zIndex: DRAWER_Z_INDEX },
1777
1902
  // The scrim's tap-to-close hit area is anchored to the RIGHT of the panel
1778
1903
  // (`left: DRAWER_WIDTH`), so it NEVER overlaps the panel: nav-item taps always
@@ -1790,6 +1915,8 @@ var styles7 = reactNative.StyleSheet.create({
1790
1915
  // so on react-native-web it — and the nav leaves inside it — sit above the scrim
1791
1916
  // and receive presses instead of the scrim swallowing them.
1792
1917
  panel: { position: "absolute", top: 0, bottom: 0, left: 0, width: DRAWER_WIDTH, zIndex: PANEL_Z_INDEX },
1918
+ panelFull: { width: "100%" },
1919
+ panelBody: { flex: 1 },
1793
1920
  menuToggle: {
1794
1921
  minWidth: MIN_TOUCH_TARGET,
1795
1922
  minHeight: MIN_TOUCH_TARGET,
@@ -1807,10 +1934,10 @@ var MenuToggle = ({ label, hint, onOpen, testID }) => {
1807
1934
  accessibilityHint: hint,
1808
1935
  accessibilityLabel: label,
1809
1936
  ringColor: theme.palette.primary["500"],
1810
- style: styles7.menuToggle,
1937
+ style: styles9.menuToggle,
1811
1938
  testID,
1812
1939
  onPress: onOpen,
1813
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles7.menuToggleGlyph, { color: theme.colors.text }], children: MENU_GLYPH2 })
1940
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles9.menuToggleGlyph, { color: theme.colors.text }], children: MENU_GLYPH2 })
1814
1941
  }
1815
1942
  );
1816
1943
  };
@@ -1819,10 +1946,14 @@ var MobileDrawer = ({
1819
1946
  labels,
1820
1947
  onClose,
1821
1948
  drawerTestID,
1822
- scrimTestID
1949
+ scrimTestID,
1950
+ header,
1951
+ width = "default"
1823
1952
  }) => {
1824
1953
  const { theme } = uiFeedback.useUi();
1825
1954
  const panelRef = React.useRef(null);
1955
+ const isFull = width === "full";
1956
+ const showHeaderBar = header !== void 0 || isFull;
1826
1957
  React.useEffect(() => {
1827
1958
  const node = panelRef.current;
1828
1959
  if (node === null || typeof node.addEventListener !== "function") return void 0;
@@ -1836,27 +1967,39 @@ var MobileDrawer = ({
1836
1967
  node.addEventListener("click", handleClick);
1837
1968
  return () => node.removeEventListener("click", handleClick);
1838
1969
  }, [onClose]);
1839
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles7.overlay, children: [
1840
- /* @__PURE__ */ jsxRuntime.jsx(
1970
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles9.overlay, children: [
1971
+ isFull ? null : /* @__PURE__ */ jsxRuntime.jsx(
1841
1972
  reactNative.Pressable,
1842
1973
  {
1843
1974
  accessibilityHint: labels.closeHint,
1844
1975
  accessibilityLabel: labels.closeLabel,
1845
1976
  accessibilityRole: "button",
1846
- style: styles7.scrim,
1977
+ style: styles9.scrim,
1847
1978
  testID: scrimTestID,
1848
1979
  onPress: onClose
1849
1980
  }
1850
1981
  ),
1851
- /* @__PURE__ */ jsxRuntime.jsx(
1982
+ /* @__PURE__ */ jsxRuntime.jsxs(
1852
1983
  reactNative.View,
1853
1984
  {
1854
1985
  ref: panelRef,
1855
1986
  "aria-modal": true,
1856
1987
  role: "dialog",
1857
- style: [styles7.panel, { backgroundColor: theme.colors.surface }],
1988
+ style: [styles9.panel, isFull ? styles9.panelFull : null, { backgroundColor: theme.colors.surface }],
1858
1989
  testID: drawerTestID,
1859
- children: renderTextSlot(sidebar, { color: theme.colors.text })
1990
+ children: [
1991
+ showHeaderBar ? /* @__PURE__ */ jsxRuntime.jsx(
1992
+ DrawerHeaderBar,
1993
+ {
1994
+ brand: header,
1995
+ closeHint: labels.closeHint,
1996
+ closeLabel: labels.closeLabel,
1997
+ testID: `${drawerTestID}-header`,
1998
+ onClose
1999
+ }
2000
+ ) : null,
2001
+ /* @__PURE__ */ jsxRuntime.jsx(NavAccordionContext.Provider, { value: true, children: showHeaderBar ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles9.panelBody, children: renderTextSlot(sidebar, { color: theme.colors.text }) }) : renderTextSlot(sidebar, { color: theme.colors.text }) })
2002
+ ]
1860
2003
  }
1861
2004
  )
1862
2005
  ] });
@@ -1872,7 +2015,7 @@ function useContentMaxWidth(width) {
1872
2015
  return resolveContentMaxWidth(width, viewport);
1873
2016
  }
1874
2017
  var DEFAULT_CONTENT_PADDING = 24;
1875
- var styles8 = reactNative.StyleSheet.create({
2018
+ var styles10 = reactNative.StyleSheet.create({
1876
2019
  root: { flex: 1 },
1877
2020
  // Auth-pending spinner: an opaque absolute overlay over the mounted shell, so
1878
2021
  // `children` (and any navigator they host) are never unmounted while the gate
@@ -1934,13 +2077,13 @@ var AppShell = ({
1934
2077
  }, [isUnauthenticated, gate]);
1935
2078
  const gatePending = gate?.pending === true;
1936
2079
  if (isUnauthenticated) return null;
1937
- const columnStyle = maxWidth === "full" ? styles8.columnFull : [styles8.columnCapped, { maxWidth }];
1938
- const navInnerStyle = chromeAlignment === "content" && maxWidth !== "full" ? [styles8.chromeCapped, { maxWidth, paddingHorizontal: contentPadding }] : void 0;
2080
+ const columnStyle = maxWidth === "full" ? styles10.columnFull : [styles10.columnCapped, { maxWidth }];
2081
+ const navInnerStyle = chromeAlignment === "content" && maxWidth !== "full" ? [styles10.chromeCapped, { maxWidth, paddingHorizontal: contentPadding }] : void 0;
1939
2082
  const scroller = /* @__PURE__ */ jsxRuntime.jsxs(
1940
2083
  reactNative.ScrollView,
1941
2084
  {
1942
- contentContainerStyle: [styles8.scrollContent, { padding: contentPadding }],
1943
- style: styles8.scroll,
2085
+ contentContainerStyle: [styles10.scrollContent, { padding: contentPadding }],
2086
+ style: styles10.scroll,
1944
2087
  testID: `${testID}${APP_SHELL_SUFFIX.content}`,
1945
2088
  children: [
1946
2089
  look.band,
@@ -1948,7 +2091,7 @@ var AppShell = ({
1948
2091
  ]
1949
2092
  }
1950
2093
  );
1951
- const headerRegion = useDrawer ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles8.headerRow, look.chrome], testID: `${testID}${APP_SHELL_SUFFIX.header}`, children: [
2094
+ const headerRegion = useDrawer ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles10.headerRow, look.chrome], testID: `${testID}${APP_SHELL_SUFFIX.header}`, children: [
1952
2095
  /* @__PURE__ */ jsxRuntime.jsx(
1953
2096
  MenuToggle,
1954
2097
  {
@@ -1958,14 +2101,14 @@ var AppShell = ({
1958
2101
  onOpen: openDrawer
1959
2102
  }
1960
2103
  ),
1961
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles8.headerFill, children: renderTextSlot(header, { color: look.chromeText }) })
2104
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles10.headerFill, children: renderTextSlot(header, { color: look.chromeText }) })
1962
2105
  ] }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: look.chrome, testID: `${testID}${APP_SHELL_SUFFIX.header}`, children: renderTextSlot(header, { color: look.chromeText }) });
1963
2106
  const railRegion = railMode === "full" ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { testID: `${testID}${APP_SHELL_SUFFIX.sidebar}`, children: renderTextSlot(sidebar, { color: theme.colors.text }) }) : railMode === "collapsed" ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { testID: `${testID}${APP_SHELL_SUFFIX.collapsedSidebar}`, children: renderTextSlot(collapsedSidebar, { color: theme.colors.text }) }) : null;
1964
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles8.root, look.root], testID, children: [
2107
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles10.root, look.root], testID, children: [
1965
2108
  headerRegion,
1966
2109
  nav !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: look.chrome, testID: `${testID}${APP_SHELL_SUFFIX.nav}`, children: navInnerStyle !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: navInnerStyle, children: renderTextSlot(nav, { color: look.chromeText }) }) : renderTextSlot(nav, { color: look.chromeText }) }) : null,
1967
2110
  banner !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { testID: `${testID}${APP_SHELL_SUFFIX.banner}`, children: renderTextSlot(banner, { color: theme.colors.text }) }) : null,
1968
- railRegion !== null ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles8.bodyRow, children: [
2111
+ railRegion !== null ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles10.bodyRow, children: [
1969
2112
  railRegion,
1970
2113
  scroller
1971
2114
  ] }) : scroller,
@@ -1974,15 +2117,17 @@ var AppShell = ({
1974
2117
  {
1975
2118
  drawerTestID: `${testID}${APP_SHELL_SUFFIX.drawer}`,
1976
2119
  labels: drawerLabels,
2120
+ header: mobileMenu?.header,
1977
2121
  scrimTestID: `${testID}${APP_SHELL_SUFFIX.scrim}`,
1978
- sidebar,
2122
+ sidebar: mobileMenu?.sidebar ?? sidebar,
2123
+ width: mobileMenu?.width,
1979
2124
  onClose: closeDrawer
1980
2125
  }
1981
2126
  ) : null,
1982
2127
  gatePending ? /* @__PURE__ */ jsxRuntime.jsx(
1983
2128
  reactNative.View,
1984
2129
  {
1985
- style: [styles8.pendingOverlay, { backgroundColor: theme.colors.background }],
2130
+ style: [styles10.pendingOverlay, { backgroundColor: theme.colors.background }],
1986
2131
  testID: `${testID}${APP_SHELL_SUFFIX.pending}`,
1987
2132
  children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { color: primary, size: "large" })
1988
2133
  }
@@ -2043,6 +2188,45 @@ var CollapsedRail = ({
2043
2188
  }
2044
2189
  );
2045
2190
  };
2191
+ function renderShellSidebar({ sideRail, nav, width, showBrand }) {
2192
+ const brandSlot = sideRail.brand ?? sideRail.title;
2193
+ return /* @__PURE__ */ jsxRuntime.jsx(
2194
+ Sidebar,
2195
+ {
2196
+ collapseHint: sideRail.collapseHint,
2197
+ containerStyle: sideRail.containerStyle,
2198
+ enableInlineSearch: sideRail.enableInlineSearch,
2199
+ expandHint: sideRail.expandHint,
2200
+ footer: sideRail.footer,
2201
+ header: sideRail.header,
2202
+ items: sideRail.items,
2203
+ navigateHint: nav.navigateHint,
2204
+ paletteTrigger: sideRail.paletteTrigger,
2205
+ pathname: nav.pathname,
2206
+ regionLabel: nav.regionLabel,
2207
+ renderChevron: sideRail.renderChevron,
2208
+ search: sideRail.search,
2209
+ searchQuery: sideRail.searchQuery,
2210
+ title: showBrand ? brandSlot : null,
2211
+ width,
2212
+ onNavigate: nav.onNavigate,
2213
+ onSearchChange: sideRail.onSearchChange
2214
+ }
2215
+ );
2216
+ }
2217
+ var styles11 = reactNative.StyleSheet.create({
2218
+ row: { flexDirection: "row", alignItems: "center" },
2219
+ brand: { justifyContent: "center", paddingHorizontal: 12 },
2220
+ fill: { flex: 1 }
2221
+ });
2222
+ var TopbarBrandRow = ({ brand, brandWidth, testID, children }) => {
2223
+ const { width } = reactNative.useWindowDimensions();
2224
+ if (width < RAIL_FULL_BREAKPOINT) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
2225
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles11.row, testID, children: [
2226
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles11.brand, brandWidth !== void 0 ? { width: brandWidth } : null], testID: `${testID}-brand`, children: brand }),
2227
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles11.fill, children })
2228
+ ] });
2229
+ };
2046
2230
  function wantsTopBar(layout, hasHeader) {
2047
2231
  return layout === "top" || layout === "both" || hasHeader;
2048
2232
  }
@@ -2061,6 +2245,11 @@ var NavShell = ({
2061
2245
  children,
2062
2246
  collapsedSidebar: collapsedSidebarProp,
2063
2247
  collapsedRailRange: collapsedRailRangeProp,
2248
+ brandPlacement = NAV_BRAND_DEFAULTS.brandPlacement,
2249
+ sidebarWidth = NAV_BRAND_DEFAULTS.sidebarWidth,
2250
+ drawerHeader = NAV_BRAND_DEFAULTS.drawerHeader,
2251
+ drawerWidth = NAV_BRAND_DEFAULTS.drawerWidth,
2252
+ mobileMenu,
2064
2253
  ...shellProps
2065
2254
  }) => {
2066
2255
  const showTopBar = wantsTopBar(layout, header !== void 0);
@@ -2086,28 +2275,13 @@ var NavShell = ({
2086
2275
  onNavigate
2087
2276
  }
2088
2277
  ) : null;
2089
- const sidebarNode = showSideRail && sideRail !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2090
- Sidebar,
2091
- {
2092
- collapseHint: sideRail.collapseHint,
2093
- containerStyle: sideRail.containerStyle,
2094
- enableInlineSearch: sideRail.enableInlineSearch,
2095
- expandHint: sideRail.expandHint,
2096
- footer: sideRail.footer,
2097
- header: sideRail.header,
2098
- items: sideRail.items,
2099
- navigateHint,
2100
- paletteTrigger: sideRail.paletteTrigger,
2101
- pathname,
2102
- regionLabel,
2103
- renderChevron: sideRail.renderChevron,
2104
- search: sideRail.search,
2105
- searchQuery: sideRail.searchQuery,
2106
- title: sideRail.brand ?? sideRail.title,
2107
- onNavigate,
2108
- onSearchChange: sideRail.onSearchChange
2109
- }
2110
- ) : void 0;
2278
+ const nav = { pathname, onNavigate, regionLabel, navigateHint };
2279
+ const rail = showSideRail ? sideRail : void 0;
2280
+ const brandInBar = brandPlacement === "topbar" && rail?.brand !== void 0;
2281
+ const brandInDrawer = drawerHeader === "brand" ? rail?.brand : void 0;
2282
+ const sidebarNode = rail === void 0 ? void 0 : renderShellSidebar({ sideRail: rail, nav, width: sidebarWidth, showBrand: !brandInBar });
2283
+ const drawerSidebar = rail !== void 0 && brandInDrawer !== void 0 && !brandInBar ? renderShellSidebar({ sideRail: rail, nav, width: sidebarWidth, showBrand: false }) : void 0;
2284
+ const shellHeader = brandInBar ? /* @__PURE__ */ jsxRuntime.jsx(TopbarBrandRow, { brand: rail?.brand, brandWidth: SIDEBAR_WIDTH_PX[sidebarWidth], testID: `${shellProps.testID}-topbar-brand-row`, children: headerNode }) : headerNode;
2111
2285
  const collapsedCfg = showSideRail ? sideRail?.collapsed : void 0;
2112
2286
  const collapsedNode = collapsedCfg !== void 0 && sideRail !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2113
2287
  CollapsedRail,
@@ -2128,7 +2302,8 @@ var NavShell = ({
2128
2302
  ...shellProps,
2129
2303
  collapsedRailRange: collapsedRange,
2130
2304
  collapsedSidebar: collapsedNode,
2131
- header: headerNode,
2305
+ header: shellHeader,
2306
+ mobileMenu: { ...mobileMenu, header: brandInDrawer, width: drawerWidth, sidebar: drawerSidebar },
2132
2307
  sidebar: sidebarNode,
2133
2308
  children
2134
2309
  }
@@ -2351,7 +2526,7 @@ var KEY_DOWN = "ArrowDown";
2351
2526
  var KEY_UP = "ArrowUp";
2352
2527
  var KEY_ENTER = "Enter";
2353
2528
  var KEY_ESCAPE = "Escape";
2354
- var styles9 = reactNative.StyleSheet.create({
2529
+ var styles12 = reactNative.StyleSheet.create({
2355
2530
  overlay: { ...reactNative.StyleSheet.absoluteFillObject, zIndex: OVERLAY_Z_INDEX, alignItems: "center" },
2356
2531
  scrim: { ...reactNative.StyleSheet.absoluteFillObject, backgroundColor: SCRIM_COLOR2 },
2357
2532
  panel: {
@@ -2380,14 +2555,14 @@ var PaletteRow = ({ item, selected, onChoose }) => {
2380
2555
  accessibilityLabel: item.label,
2381
2556
  accessibilityRole: "button",
2382
2557
  accessibilityState: { selected },
2383
- style: [styles9.row, selected ? { backgroundColor: colors.border } : void 0],
2558
+ style: [styles12.row, selected ? { backgroundColor: colors.border } : void 0],
2384
2559
  testID: item.testID ?? item.key,
2385
2560
  onPress: () => onChoose(item),
2386
2561
  children: [
2387
2562
  typeof item.renderIcon === "function" ? item.renderIcon(colors.textSecondary, NAV_ICON_SIZE) : null,
2388
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles9.rowText, children: [
2389
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles9.rowLabel, { color: colors.text }], children: item.label }),
2390
- item.hint ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles9.rowHint, { color: colors.textSecondary }], children: item.hint }) : null
2563
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles12.rowText, children: [
2564
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles12.rowLabel, { color: colors.text }], children: item.label }),
2565
+ item.hint ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles12.rowHint, { color: colors.textSecondary }], children: item.hint }) : null
2391
2566
  ] })
2392
2567
  ]
2393
2568
  }
@@ -2427,14 +2602,14 @@ var CommandPalette = ({ open, items, onClose, labels, testID }) => {
2427
2602
  [results, selected, choose, onClose]
2428
2603
  );
2429
2604
  if (!open) return null;
2430
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles9.overlay, children: [
2605
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles12.overlay, children: [
2431
2606
  /* @__PURE__ */ jsxRuntime.jsx(
2432
2607
  reactNative.Pressable,
2433
2608
  {
2434
2609
  accessibilityHint: labels.closeHint,
2435
2610
  accessibilityLabel: labels.closeLabel,
2436
2611
  accessibilityRole: "button",
2437
- style: styles9.scrim,
2612
+ style: styles12.scrim,
2438
2613
  testID: `${testID ?? "command-palette"}-scrim`,
2439
2614
  onPress: onClose
2440
2615
  }
@@ -2445,7 +2620,7 @@ var CommandPalette = ({ open, items, onClose, labels, testID }) => {
2445
2620
  "aria-modal": true,
2446
2621
  "aria-label": labels.regionLabel,
2447
2622
  role: "dialog",
2448
- style: [styles9.panel, { backgroundColor: colors.surface, borderColor: colors.border }],
2623
+ style: [styles12.panel, { backgroundColor: colors.surface, borderColor: colors.border }],
2449
2624
  testID: testID ?? "command-palette",
2450
2625
  children: [
2451
2626
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2455,14 +2630,14 @@ var CommandPalette = ({ open, items, onClose, labels, testID }) => {
2455
2630
  accessibilityLabel: labels.placeholder,
2456
2631
  placeholder: labels.placeholder,
2457
2632
  placeholderTextColor: colors.textSecondary,
2458
- style: [styles9.input, { color: colors.text, borderBottomColor: colors.border }],
2633
+ style: [styles12.input, { color: colors.text, borderBottomColor: colors.border }],
2459
2634
  testID: `${testID ?? "command-palette"}-input`,
2460
2635
  value: query,
2461
2636
  onChangeText: setQuery,
2462
2637
  onKeyPress
2463
2638
  }
2464
2639
  ),
2465
- results.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles9.empty, { color: colors.textSecondary }], children: labels.emptyText }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.ScrollView, { keyboardShouldPersistTaps: "handled", style: styles9.list, children: results.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(PaletteRow, { item, selected: index === selected, onChoose: choose }, item.key)) })
2640
+ results.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles12.empty, { color: colors.textSecondary }], children: labels.emptyText }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.ScrollView, { keyboardShouldPersistTaps: "handled", style: styles12.list, children: results.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(PaletteRow, { item, selected: index === selected, onChoose: choose }, item.key)) })
2466
2641
  ]
2467
2642
  }
2468
2643
  )
@@ -2567,7 +2742,7 @@ var TAB_MIN_HEIGHT = 56;
2567
2742
  var LABEL_SIZE = 12;
2568
2743
  var LABEL_GAP = 2;
2569
2744
  var TAB_PADDING = 4;
2570
- var styles10 = reactNative.StyleSheet.create({
2745
+ var styles13 = reactNative.StyleSheet.create({
2571
2746
  tab: {
2572
2747
  flex: 1,
2573
2748
  minHeight: TAB_MIN_HEIGHT,
@@ -2604,31 +2779,31 @@ var BottomTab = ({
2604
2779
  accessibilityLabel: item.label,
2605
2780
  accessibilityRole: "link",
2606
2781
  accessibilityState: { selected: isActive },
2607
- style: [styles10.tab, { opacity: feedback.opacity }],
2782
+ style: [styles13.tab, { opacity: feedback.opacity }],
2608
2783
  testID: item.testID ?? item.key,
2609
2784
  onPress: () => onPress(item.route),
2610
2785
  onPressIn: () => setPressed(true),
2611
2786
  onPressOut: () => setPressed(false),
2612
2787
  ...ariaCurrentProps3(isActive),
2613
2788
  children: [
2614
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Animated.View, { style: [styles10.iconWrap, { transform: [{ scale }] }], children: [
2789
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Animated.View, { style: [styles13.iconWrap, { transform: [{ scale }] }], children: [
2615
2790
  feedback.pillScale === null ? null : /* @__PURE__ */ jsxRuntime.jsx(
2616
2791
  reactNative.View,
2617
2792
  {
2618
2793
  pointerEvents: "none",
2619
- style: [styles10.pill, { backgroundColor: colors.pill, transform: [{ scale: feedback.pillScale }] }, motion]
2794
+ style: [styles13.pill, { backgroundColor: colors.pill, transform: [{ scale: feedback.pillScale }] }, motion]
2620
2795
  }
2621
2796
  ),
2622
2797
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [{ transform: feedback.iconTransform }, motion], children: item.renderIcon?.(color, ICON_SIZE) })
2623
2798
  ] }),
2624
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles10.label, { color }], children: item.label })
2799
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles13.label, { color }], children: item.label })
2625
2800
  ]
2626
2801
  }
2627
2802
  );
2628
2803
  };
2629
2804
  var DEFAULT_TEST_ID = "bottom-tab-bar";
2630
2805
  var SLIDER_HEIGHT = 3;
2631
- var styles11 = reactNative.StyleSheet.create({
2806
+ var styles14 = reactNative.StyleSheet.create({
2632
2807
  bar: { flexDirection: "row", borderTopWidth: reactNative.StyleSheet.hairlineWidth },
2633
2808
  slider: { position: "absolute", top: 0, height: SLIDER_HEIGHT }
2634
2809
  });
@@ -2655,14 +2830,14 @@ var BottomTabBar = ({
2655
2830
  {
2656
2831
  "aria-label": regionLabel,
2657
2832
  role: "navigation",
2658
- style: [styles11.bar, { backgroundColor: theme.colors.surface, borderTopColor: theme.colors.border }, containerStyle],
2833
+ style: [styles14.bar, { backgroundColor: theme.colors.surface, borderTopColor: theme.colors.border }, containerStyle],
2659
2834
  testID,
2660
2835
  children: [
2661
2836
  bar === null ? null : /* @__PURE__ */ jsxRuntime.jsx(
2662
2837
  reactNative.View,
2663
2838
  {
2664
2839
  pointerEvents: "none",
2665
- style: [styles11.slider, { left: bar.left, width: bar.width, backgroundColor: primary }, webTransition("left", barMs, reducedMotion)]
2840
+ style: [styles14.slider, { left: bar.left, width: bar.width, backgroundColor: primary }, webTransition("left", barMs, reducedMotion)]
2666
2841
  }
2667
2842
  ),
2668
2843
  items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -2699,6 +2874,7 @@ exports.DEFAULT_COLLAPSED_RAIL_MAX = DEFAULT_COLLAPSED_RAIL_MAX;
2699
2874
  exports.DEFAULT_SEARCH_BREAKPOINT = DEFAULT_SEARCH_BREAKPOINT;
2700
2875
  exports.DarkModeControl = DarkModeControl;
2701
2876
  exports.HOVER_TINT_OPACITY = HOVER_TINT_OPACITY;
2877
+ exports.NAV_BRAND_DEFAULTS = NAV_BRAND_DEFAULTS;
2702
2878
  exports.NAV_ICON_SIZE = NAV_ICON_SIZE;
2703
2879
  exports.NAV_LINK_GAP = NAV_LINK_GAP;
2704
2880
  exports.NAV_ROW_RADIUS = NAV_ROW_RADIUS;
@@ -2712,6 +2888,7 @@ exports.NavShell = NavShell;
2712
2888
  exports.PillNav = PillNav;
2713
2889
  exports.PillNavVariant = PillNavVariant;
2714
2890
  exports.RAIL_FULL_BREAKPOINT = RAIL_FULL_BREAKPOINT;
2891
+ exports.SIDEBAR_WIDTH_PX = SIDEBAR_WIDTH_PX;
2715
2892
  exports.Sidebar = Sidebar;
2716
2893
  exports.SidebarChevron = SidebarChevron;
2717
2894
  exports.SidebarSearch = SidebarSearch;