@dloizides/ui-nav 1.23.2 → 1.24.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/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.24.0
4
+
5
+ - `Topbar` gets an optional `center` slot between `left` and the actions (testID `topbar-center`); callers that do not pass it render as before (KEFI-EDITOR-HEADER-1 "Compact the landing editor header").
6
+ - `PillNav` gets `variant={PillNavVariant.Menu}`: one compact "Current ▾" trigger (44px pill) opening a menu of the same items through the shared `ModalDropdown` (role menu, arrow keys / Home / End / Enter / Escape, highlight starts on the current item). New optional props `menuHint`, `menuTestID`, `dropdownVariant`; new exports `PillNavVariant`, `resolvePillMenuLabel`. Default stays `Pills`.
7
+
3
8
  ## 1.23.2
4
9
 
5
10
  - Topbar account-name button and language toggle get a 44x44 minimum hit box (KEFI-HEADER-HITBOX-1 "kefi-web header account control reaches 44x44").
package/dist/index.d.mts CHANGED
@@ -333,6 +333,8 @@ interface AccountState {
333
333
  interface TopbarProps {
334
334
  /** Left slot — typically the tenant logo. */
335
335
  left?: React.ReactNode;
336
+ /** Optional middle slot between `left` and the actions (e.g. a compact dashboard switch). */
337
+ center?: React.ReactNode;
336
338
  /**
337
339
  * Optional language toggle. `testID` is optional but the repo standard wants
338
340
  * one — before 1.10.0 this inline type declared none, so a testID was
@@ -359,7 +361,7 @@ interface TopbarProps {
359
361
  /** Extra container style overrides. */
360
362
  containerStyle?: ViewStyle | ViewStyle[];
361
363
  }
362
- declare const Topbar: ({ left, language, notificationSlot, user, account, logout, containerStyle, }: TopbarProps) => React.ReactElement;
364
+ declare const Topbar: ({ left, center, language, notificationSlot, user, account, logout, containerStyle, }: TopbarProps) => React.ReactElement;
363
365
 
364
366
  /**
365
367
  * NavBar — the config-driven HORIZONTAL top navigation bar. It is the top-bar
@@ -893,6 +895,12 @@ interface CollapsedRailProps {
893
895
  }
894
896
  declare const CollapsedRail: ({ items, pathname, onNavigate, regionLabel, navigateHint, header, footer, containerStyle, }: CollapsedRailProps) => React.ReactElement;
895
897
 
898
+ /** How `PillNav` lays out its items: a wrapping pill row, or one compact "Current ▾" menu button. */
899
+ declare enum PillNavVariant {
900
+ Pills = "pills",
901
+ Menu = "menu"
902
+ }
903
+
896
904
  /**
897
905
  * PillNav — a horizontal row of fully-rounded "pills", the cross-navigation
898
906
  * switcher promoted from kefi's coral dashboard nav. It renders the same
@@ -929,10 +937,21 @@ interface PillNavProps {
929
937
  * (show when non-empty); kefi passes 2 (a lone dashboard needs no switcher).
930
938
  */
931
939
  minItems?: number;
940
+ /** `Pills` (default) renders the wrapping row; `Menu` renders one compact "Current ▾" menu button. */
941
+ variant?: PillNavVariant;
942
+ /** a11y hint for the `Menu` trigger. Defaults to `regionLabel`. */
943
+ menuHint?: string;
944
+ /** testID for the `Menu` trigger. Defaults to `NAV_TEST_IDS.pillNavMenu`. */
945
+ menuTestID?: string;
946
+ /** Forces the `Menu` dropdown variant (default: responsive). */
947
+ dropdownVariant?: DropdownVariant;
932
948
  /** Extra container style overrides. */
933
949
  containerStyle?: ViewStyle | ViewStyle[];
934
950
  }
935
- declare const PillNav: ({ items, pathname, onNavigate, regionLabel, navigateHint, minItems, containerStyle, }: PillNavProps) => React.ReactElement | null;
951
+ declare const PillNav: ({ items, pathname, onNavigate, regionLabel, navigateHint, minItems, variant, menuHint, menuTestID, dropdownVariant, containerStyle, }: PillNavProps) => React.ReactElement | null;
952
+
953
+ /** The label the compact menu trigger shows: the active item's label, else `fallback`. */
954
+ declare function resolvePillMenuLabel(items: NavItem[], pathname: string, fallback: string): string;
936
955
 
937
956
  /**
938
957
  * DarkModeControl — the shared colour-scheme control promoted from erevna /
@@ -1077,6 +1096,10 @@ declare const NAV_TEST_IDS: {
1077
1096
  readonly navBarLinks: "navbar-links";
1078
1097
  /** the "More ▾" priority+ overflow trigger in the horizontal NavBar (shown when items spill). */
1079
1098
  readonly navBarOverflow: "navbar-overflow";
1099
+ /** the compact "Current ▾" trigger of `PillNav` with `variant={PillNavVariant.Menu}`. */
1100
+ readonly pillNavMenu: "pill-nav-menu";
1101
+ /** the optional middle slot of `Topbar` (rendered only when `center` is passed). */
1102
+ readonly topbarCenter: "topbar-center";
1080
1103
  };
1081
1104
  /** Suffixes appended to an `AppShell`'s required `testID` to name its regions. */
1082
1105
  declare const APP_SHELL_SUFFIX: {
@@ -1333,6 +1356,13 @@ declare const navStyles: {
1333
1356
  topbarLeft: {
1334
1357
  flex: number;
1335
1358
  };
1359
+ topbarCenter: {
1360
+ flexShrink: number;
1361
+ minWidth: number;
1362
+ flexDirection: "row";
1363
+ alignItems: "center";
1364
+ marginHorizontal: number;
1365
+ };
1336
1366
  topbarRight: {
1337
1367
  flexDirection: "row";
1338
1368
  alignItems: "center";
@@ -1413,6 +1443,9 @@ declare const pillNavStyles: {
1413
1443
  fontSize: number;
1414
1444
  fontWeight: "600";
1415
1445
  };
1446
+ menuTriggerText: {
1447
+ flexShrink: number;
1448
+ };
1416
1449
  };
1417
1450
  declare const darkModeStyles: {
1418
1451
  segmentRow: {
@@ -1552,4 +1585,4 @@ declare const NAV_ICON_SIZE = 14;
1552
1585
  /** Chevron icon size for expandable sections. */
1553
1586
  declare const CHEVRON_ICON_SIZE = 12;
1554
1587
 
1555
- export { ACTIVE_BORDER_RADIUS, ACTIVE_TINT_OPACITY, APP_SHELL_SUFFIX, type AccountPlan, type AccountState, AppShell, type AppShellProps, type AppShellWidth, BASE_INDENT, CHEVRON_ICON_SIZE, CollapsedRail, type CollapsedRailProps, type CollapsedRailRange, type CommandItem, CommandPalette, type CommandPaletteLabels, type CommandPaletteProps, CommandPaletteTrigger, type CommandPaletteTriggerProps, DEFAULT_COLLAPSED_RAIL_MAX, DEFAULT_SEARCH_BREAKPOINT, DarkModeControl, type DarkModeControlProps, type DarkModeOption, type DarkModeVariant, HOVER_TINT_OPACITY, NAV_ICON_SIZE, NAV_LINK_GAP, NAV_ROW_RADIUS, NAV_TEST_IDS, Nav, NavBar, type NavBarProps, NavExpandableItem, type NavExpandableItemProps, type NavItem, type NavOrientation, NavOverflowMenu, type NavOverflowMenuProps, type NavProps, NavShell, type NavShellCollapsedRail, type NavShellLayout, type NavShellProps, type NavShellSideRail, type NavShellTopBar, type NavUser, PillNav, type PillNavProps, RAIL_FULL_BREAKPOINT, type RailMode, type ResolveRailModeArgs, type SearchAffordance, type ShellMessage, Sidebar, SidebarChevron, type SidebarChevronProps, type SidebarPaletteTriggerConfig, type SidebarProps, SidebarSearch, type SidebarSearchConfig, type SidebarSearchLabels, type SidebarSearchProps, Topbar, type TopbarAction, type TopbarProps, type TopbarUser, accessibleNavItems, collapsedRailStyles, darkModeStyles, expandableStyles, filterCommands, filterNavItems, isFilterActive, isRouteActive, navStyles, pillNavStyles, resolveActiveRoute, resolveContentMaxWidth, resolveRailMode, resolveSearchAffordance, roleRoutesToNavItems, searchTokens, useCommandPaletteHotkey, useContentMaxWidth };
1588
+ export { ACTIVE_BORDER_RADIUS, ACTIVE_TINT_OPACITY, APP_SHELL_SUFFIX, type AccountPlan, type AccountState, AppShell, type AppShellProps, type AppShellWidth, BASE_INDENT, CHEVRON_ICON_SIZE, CollapsedRail, type CollapsedRailProps, type CollapsedRailRange, type CommandItem, CommandPalette, type CommandPaletteLabels, type CommandPaletteProps, CommandPaletteTrigger, type CommandPaletteTriggerProps, DEFAULT_COLLAPSED_RAIL_MAX, DEFAULT_SEARCH_BREAKPOINT, DarkModeControl, type DarkModeControlProps, type DarkModeOption, type DarkModeVariant, HOVER_TINT_OPACITY, NAV_ICON_SIZE, NAV_LINK_GAP, NAV_ROW_RADIUS, NAV_TEST_IDS, Nav, NavBar, type NavBarProps, NavExpandableItem, type NavExpandableItemProps, type NavItem, type NavOrientation, NavOverflowMenu, type NavOverflowMenuProps, type NavProps, NavShell, type NavShellCollapsedRail, type NavShellLayout, type NavShellProps, type NavShellSideRail, type NavShellTopBar, type NavUser, PillNav, type PillNavProps, PillNavVariant, RAIL_FULL_BREAKPOINT, type RailMode, type ResolveRailModeArgs, type SearchAffordance, type ShellMessage, Sidebar, SidebarChevron, type SidebarChevronProps, type SidebarPaletteTriggerConfig, type SidebarProps, SidebarSearch, type SidebarSearchConfig, type SidebarSearchLabels, type SidebarSearchProps, Topbar, type TopbarAction, type TopbarProps, type TopbarUser, accessibleNavItems, collapsedRailStyles, darkModeStyles, expandableStyles, filterCommands, filterNavItems, isFilterActive, isRouteActive, navStyles, pillNavStyles, resolveActiveRoute, resolveContentMaxWidth, resolvePillMenuLabel, resolveRailMode, resolveSearchAffordance, roleRoutesToNavItems, searchTokens, useCommandPaletteHotkey, useContentMaxWidth };
package/dist/index.d.ts CHANGED
@@ -333,6 +333,8 @@ interface AccountState {
333
333
  interface TopbarProps {
334
334
  /** Left slot — typically the tenant logo. */
335
335
  left?: React.ReactNode;
336
+ /** Optional middle slot between `left` and the actions (e.g. a compact dashboard switch). */
337
+ center?: React.ReactNode;
336
338
  /**
337
339
  * Optional language toggle. `testID` is optional but the repo standard wants
338
340
  * one — before 1.10.0 this inline type declared none, so a testID was
@@ -359,7 +361,7 @@ interface TopbarProps {
359
361
  /** Extra container style overrides. */
360
362
  containerStyle?: ViewStyle | ViewStyle[];
361
363
  }
362
- declare const Topbar: ({ left, language, notificationSlot, user, account, logout, containerStyle, }: TopbarProps) => React.ReactElement;
364
+ declare const Topbar: ({ left, center, language, notificationSlot, user, account, logout, containerStyle, }: TopbarProps) => React.ReactElement;
363
365
 
364
366
  /**
365
367
  * NavBar — the config-driven HORIZONTAL top navigation bar. It is the top-bar
@@ -893,6 +895,12 @@ interface CollapsedRailProps {
893
895
  }
894
896
  declare const CollapsedRail: ({ items, pathname, onNavigate, regionLabel, navigateHint, header, footer, containerStyle, }: CollapsedRailProps) => React.ReactElement;
895
897
 
898
+ /** How `PillNav` lays out its items: a wrapping pill row, or one compact "Current ▾" menu button. */
899
+ declare enum PillNavVariant {
900
+ Pills = "pills",
901
+ Menu = "menu"
902
+ }
903
+
896
904
  /**
897
905
  * PillNav — a horizontal row of fully-rounded "pills", the cross-navigation
898
906
  * switcher promoted from kefi's coral dashboard nav. It renders the same
@@ -929,10 +937,21 @@ interface PillNavProps {
929
937
  * (show when non-empty); kefi passes 2 (a lone dashboard needs no switcher).
930
938
  */
931
939
  minItems?: number;
940
+ /** `Pills` (default) renders the wrapping row; `Menu` renders one compact "Current ▾" menu button. */
941
+ variant?: PillNavVariant;
942
+ /** a11y hint for the `Menu` trigger. Defaults to `regionLabel`. */
943
+ menuHint?: string;
944
+ /** testID for the `Menu` trigger. Defaults to `NAV_TEST_IDS.pillNavMenu`. */
945
+ menuTestID?: string;
946
+ /** Forces the `Menu` dropdown variant (default: responsive). */
947
+ dropdownVariant?: DropdownVariant;
932
948
  /** Extra container style overrides. */
933
949
  containerStyle?: ViewStyle | ViewStyle[];
934
950
  }
935
- declare const PillNav: ({ items, pathname, onNavigate, regionLabel, navigateHint, minItems, containerStyle, }: PillNavProps) => React.ReactElement | null;
951
+ declare const PillNav: ({ items, pathname, onNavigate, regionLabel, navigateHint, minItems, variant, menuHint, menuTestID, dropdownVariant, containerStyle, }: PillNavProps) => React.ReactElement | null;
952
+
953
+ /** The label the compact menu trigger shows: the active item's label, else `fallback`. */
954
+ declare function resolvePillMenuLabel(items: NavItem[], pathname: string, fallback: string): string;
936
955
 
937
956
  /**
938
957
  * DarkModeControl — the shared colour-scheme control promoted from erevna /
@@ -1077,6 +1096,10 @@ declare const NAV_TEST_IDS: {
1077
1096
  readonly navBarLinks: "navbar-links";
1078
1097
  /** the "More ▾" priority+ overflow trigger in the horizontal NavBar (shown when items spill). */
1079
1098
  readonly navBarOverflow: "navbar-overflow";
1099
+ /** the compact "Current ▾" trigger of `PillNav` with `variant={PillNavVariant.Menu}`. */
1100
+ readonly pillNavMenu: "pill-nav-menu";
1101
+ /** the optional middle slot of `Topbar` (rendered only when `center` is passed). */
1102
+ readonly topbarCenter: "topbar-center";
1080
1103
  };
1081
1104
  /** Suffixes appended to an `AppShell`'s required `testID` to name its regions. */
1082
1105
  declare const APP_SHELL_SUFFIX: {
@@ -1333,6 +1356,13 @@ declare const navStyles: {
1333
1356
  topbarLeft: {
1334
1357
  flex: number;
1335
1358
  };
1359
+ topbarCenter: {
1360
+ flexShrink: number;
1361
+ minWidth: number;
1362
+ flexDirection: "row";
1363
+ alignItems: "center";
1364
+ marginHorizontal: number;
1365
+ };
1336
1366
  topbarRight: {
1337
1367
  flexDirection: "row";
1338
1368
  alignItems: "center";
@@ -1413,6 +1443,9 @@ declare const pillNavStyles: {
1413
1443
  fontSize: number;
1414
1444
  fontWeight: "600";
1415
1445
  };
1446
+ menuTriggerText: {
1447
+ flexShrink: number;
1448
+ };
1416
1449
  };
1417
1450
  declare const darkModeStyles: {
1418
1451
  segmentRow: {
@@ -1552,4 +1585,4 @@ declare const NAV_ICON_SIZE = 14;
1552
1585
  /** Chevron icon size for expandable sections. */
1553
1586
  declare const CHEVRON_ICON_SIZE = 12;
1554
1587
 
1555
- export { ACTIVE_BORDER_RADIUS, ACTIVE_TINT_OPACITY, APP_SHELL_SUFFIX, type AccountPlan, type AccountState, AppShell, type AppShellProps, type AppShellWidth, BASE_INDENT, CHEVRON_ICON_SIZE, CollapsedRail, type CollapsedRailProps, type CollapsedRailRange, type CommandItem, CommandPalette, type CommandPaletteLabels, type CommandPaletteProps, CommandPaletteTrigger, type CommandPaletteTriggerProps, DEFAULT_COLLAPSED_RAIL_MAX, DEFAULT_SEARCH_BREAKPOINT, DarkModeControl, type DarkModeControlProps, type DarkModeOption, type DarkModeVariant, HOVER_TINT_OPACITY, NAV_ICON_SIZE, NAV_LINK_GAP, NAV_ROW_RADIUS, NAV_TEST_IDS, Nav, NavBar, type NavBarProps, NavExpandableItem, type NavExpandableItemProps, type NavItem, type NavOrientation, NavOverflowMenu, type NavOverflowMenuProps, type NavProps, NavShell, type NavShellCollapsedRail, type NavShellLayout, type NavShellProps, type NavShellSideRail, type NavShellTopBar, type NavUser, PillNav, type PillNavProps, RAIL_FULL_BREAKPOINT, type RailMode, type ResolveRailModeArgs, type SearchAffordance, type ShellMessage, Sidebar, SidebarChevron, type SidebarChevronProps, type SidebarPaletteTriggerConfig, type SidebarProps, SidebarSearch, type SidebarSearchConfig, type SidebarSearchLabels, type SidebarSearchProps, Topbar, type TopbarAction, type TopbarProps, type TopbarUser, accessibleNavItems, collapsedRailStyles, darkModeStyles, expandableStyles, filterCommands, filterNavItems, isFilterActive, isRouteActive, navStyles, pillNavStyles, resolveActiveRoute, resolveContentMaxWidth, resolveRailMode, resolveSearchAffordance, roleRoutesToNavItems, searchTokens, useCommandPaletteHotkey, useContentMaxWidth };
1588
+ export { ACTIVE_BORDER_RADIUS, ACTIVE_TINT_OPACITY, APP_SHELL_SUFFIX, type AccountPlan, type AccountState, AppShell, type AppShellProps, type AppShellWidth, BASE_INDENT, CHEVRON_ICON_SIZE, CollapsedRail, type CollapsedRailProps, type CollapsedRailRange, type CommandItem, CommandPalette, type CommandPaletteLabels, type CommandPaletteProps, CommandPaletteTrigger, type CommandPaletteTriggerProps, DEFAULT_COLLAPSED_RAIL_MAX, DEFAULT_SEARCH_BREAKPOINT, DarkModeControl, type DarkModeControlProps, type DarkModeOption, type DarkModeVariant, HOVER_TINT_OPACITY, NAV_ICON_SIZE, NAV_LINK_GAP, NAV_ROW_RADIUS, NAV_TEST_IDS, Nav, NavBar, type NavBarProps, NavExpandableItem, type NavExpandableItemProps, type NavItem, type NavOrientation, NavOverflowMenu, type NavOverflowMenuProps, type NavProps, NavShell, type NavShellCollapsedRail, type NavShellLayout, type NavShellProps, type NavShellSideRail, type NavShellTopBar, type NavUser, PillNav, type PillNavProps, PillNavVariant, RAIL_FULL_BREAKPOINT, type RailMode, type ResolveRailModeArgs, type SearchAffordance, type ShellMessage, Sidebar, SidebarChevron, type SidebarChevronProps, type SidebarPaletteTriggerConfig, type SidebarProps, SidebarSearch, type SidebarSearchConfig, type SidebarSearchLabels, type SidebarSearchProps, Topbar, type TopbarAction, type TopbarProps, type TopbarUser, accessibleNavItems, collapsedRailStyles, darkModeStyles, expandableStyles, filterCommands, filterNavItems, isFilterActive, isRouteActive, navStyles, pillNavStyles, resolveActiveRoute, resolveContentMaxWidth, resolvePillMenuLabel, resolveRailMode, resolveSearchAffordance, roleRoutesToNavItems, searchTokens, useCommandPaletteHotkey, useContentMaxWidth };
package/dist/index.js CHANGED
@@ -71,6 +71,7 @@ var navStyles = reactNative.StyleSheet.create({
71
71
  justifyContent: "space-between"
72
72
  },
73
73
  topbarLeft: { flex: 1 },
74
+ topbarCenter: { flexShrink: 1, minWidth: 0, flexDirection: "row", alignItems: "center", marginHorizontal: 8 },
74
75
  topbarRight: { flexDirection: "row", alignItems: "center" },
75
76
  topbarRowItem: {
76
77
  marginHorizontal: 8,
@@ -224,7 +225,8 @@ var pillNavStyles = reactNative.StyleSheet.create({
224
225
  columnGap: 6,
225
226
  justifyContent: "center"
226
227
  },
227
- pillText: { fontSize: 14, fontWeight: "600" }
228
+ pillText: { fontSize: 14, fontWeight: "600" },
229
+ menuTriggerText: { flexShrink: 1 }
228
230
  });
229
231
  var darkModeStyles = reactNative.StyleSheet.create({
230
232
  // Segmented Light / Dark / System control.
@@ -881,7 +883,11 @@ var NAV_TEST_IDS = {
881
883
  /** links container in the horizontal NavBar. */
882
884
  navBarLinks: "navbar-links",
883
885
  /** the "More ▾" priority+ overflow trigger in the horizontal NavBar (shown when items spill). */
884
- navBarOverflow: "navbar-overflow"
886
+ navBarOverflow: "navbar-overflow",
887
+ /** the compact "Current ▾" trigger of `PillNav` with `variant={PillNavVariant.Menu}`. */
888
+ pillNavMenu: "pill-nav-menu",
889
+ /** the optional middle slot of `Topbar` (rendered only when `center` is passed). */
890
+ topbarCenter: "topbar-center"
885
891
  };
886
892
  var APP_SHELL_SUFFIX = {
887
893
  content: "-content",
@@ -941,6 +947,7 @@ function planToneColor(theme, tone) {
941
947
  }
942
948
  var Topbar = ({
943
949
  left,
950
+ center,
944
951
  language,
945
952
  notificationSlot,
946
953
  user,
@@ -964,6 +971,7 @@ var Topbar = ({
964
971
  ],
965
972
  children: [
966
973
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: navStyles.topbarLeft, children: renderTextSlot(left, { color: colors.text }) }),
974
+ center !== void 0 && center !== null ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: navStyles.topbarCenter, testID: NAV_TEST_IDS.topbarCenter, children: renderTextSlot(center, { color: colors.text }) }) : null,
967
975
  /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: navStyles.topbarRight, children: [
968
976
  language ? /* @__PURE__ */ jsxRuntime.jsx(
969
977
  FocusableTouchable,
@@ -1859,7 +1867,61 @@ var NavShell = ({
1859
1867
  }
1860
1868
  );
1861
1869
  };
1870
+
1871
+ // src/pillMenuLabel.ts
1872
+ function resolvePillMenuLabel(items, pathname, fallback) {
1873
+ const activeRoute = resolveActiveRoute(items, pathname);
1874
+ const active = items.find((item) => item.route === activeRoute);
1875
+ return active?.label ?? fallback;
1876
+ }
1862
1877
  var TEXT_ON_PRIMARY4 = "#ffffff";
1878
+ var NO_ACTIVE_ROUTE2 = "";
1879
+ var PILL_MENU_MIN_WIDTH = 200;
1880
+ var PillNavMenu = ({
1881
+ items,
1882
+ pathname,
1883
+ onNavigate,
1884
+ regionLabel,
1885
+ hint,
1886
+ testID = NAV_TEST_IDS.pillNavMenu,
1887
+ dropdownVariant
1888
+ }) => {
1889
+ const { theme } = uiFeedback.useUi();
1890
+ const primaryColor = theme.palette.primary["500"];
1891
+ const options = React.useMemo(() => items.map((item) => ({ label: item.label, value: item.route })), [items]);
1892
+ const activeRoute = resolveActiveRoute(items, pathname) ?? NO_ACTIVE_ROUTE2;
1893
+ const label = resolvePillMenuLabel(items, pathname, regionLabel);
1894
+ const optionTestID = React.useMemo(() => {
1895
+ const byRoute = new Map(items.map((item) => [item.route, item.testID ?? item.key]));
1896
+ return (route) => byRoute.get(route) ?? `${testID}-option-${route}`;
1897
+ }, [items, testID]);
1898
+ return /* @__PURE__ */ jsxRuntime.jsx(
1899
+ uiLayout.ModalDropdown,
1900
+ {
1901
+ accessibilityHint: hint,
1902
+ accessibilityLabel: label,
1903
+ menuMinWidth: PILL_MENU_MIN_WIDTH,
1904
+ optionTestID,
1905
+ options,
1906
+ testID,
1907
+ value: activeRoute,
1908
+ variant: dropdownVariant,
1909
+ onChange: onNavigate,
1910
+ renderTrigger: ({ isOpen }) => /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [pillNavStyles.pill, { backgroundColor: primaryColor }], children: [
1911
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { numberOfLines: 1, style: [pillNavStyles.pillText, pillNavStyles.menuTriggerText, { color: TEXT_ON_PRIMARY4 }], children: label }),
1912
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [pillNavStyles.pillText, { color: TEXT_ON_PRIMARY4 }], children: isOpen ? "\u25B4" : "\u25BE" })
1913
+ ] })
1914
+ }
1915
+ );
1916
+ };
1917
+
1918
+ // src/PillNavVariant.ts
1919
+ var PillNavVariant = /* @__PURE__ */ ((PillNavVariant2) => {
1920
+ PillNavVariant2["Pills"] = "pills";
1921
+ PillNavVariant2["Menu"] = "menu";
1922
+ return PillNavVariant2;
1923
+ })(PillNavVariant || {});
1924
+ var TEXT_ON_PRIMARY5 = "#ffffff";
1863
1925
  var DEFAULT_MIN_ITEMS = 1;
1864
1926
  var PillNav = ({
1865
1927
  items,
@@ -1868,12 +1930,29 @@ var PillNav = ({
1868
1930
  regionLabel,
1869
1931
  navigateHint = (label) => label,
1870
1932
  minItems = DEFAULT_MIN_ITEMS,
1933
+ variant = "pills" /* Pills */,
1934
+ menuHint,
1935
+ menuTestID,
1936
+ dropdownVariant,
1871
1937
  containerStyle
1872
1938
  }) => {
1873
1939
  const { theme } = uiFeedback.useUi();
1874
1940
  const colors = theme.colors;
1875
1941
  const primaryColor = theme.palette.primary["500"];
1876
1942
  if (items.length < minItems) return null;
1943
+ if (variant === "menu" /* Menu */)
1944
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { accessibilityRole: "none", "aria-label": regionLabel, role: "navigation", style: containerStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
1945
+ PillNavMenu,
1946
+ {
1947
+ dropdownVariant,
1948
+ hint: menuHint ?? regionLabel,
1949
+ items,
1950
+ pathname,
1951
+ regionLabel,
1952
+ testID: menuTestID,
1953
+ onNavigate
1954
+ }
1955
+ ) });
1877
1956
  const activeRoute = resolveActiveRoute(items, pathname);
1878
1957
  return /* @__PURE__ */ jsxRuntime.jsx(
1879
1958
  reactNative.View,
@@ -1884,7 +1963,7 @@ var PillNav = ({
1884
1963
  style: [pillNavStyles.container, containerStyle],
1885
1964
  children: items.map((item) => {
1886
1965
  const active = item.route === activeRoute;
1887
- const textColor = active ? TEXT_ON_PRIMARY4 : colors.textSecondary;
1966
+ const textColor = active ? TEXT_ON_PRIMARY5 : colors.textSecondary;
1888
1967
  const pillStyle = active ? { backgroundColor: primaryColor } : { backgroundColor: colors.surfaceElevated };
1889
1968
  return /* @__PURE__ */ jsxRuntime.jsxs(
1890
1969
  FocusableTouchable,
@@ -1907,7 +1986,7 @@ var PillNav = ({
1907
1986
  }
1908
1987
  );
1909
1988
  };
1910
- var TEXT_ON_PRIMARY5 = "#ffffff";
1989
+ var TEXT_ON_PRIMARY6 = "#ffffff";
1911
1990
  var DARK_MODE_ICON_SIZE = 16;
1912
1991
  var DarkModeControl = ({
1913
1992
  value,
@@ -1956,7 +2035,7 @@ var DarkModeControl = ({
1956
2035
  style: [darkModeStyles.segmentRow, { borderColor: colors.border }, containerStyle],
1957
2036
  children: options.map((option) => {
1958
2037
  const active = option.value === value;
1959
- const textColor = active ? TEXT_ON_PRIMARY5 : colors.textSecondary;
2038
+ const textColor = active ? TEXT_ON_PRIMARY6 : colors.textSecondary;
1960
2039
  return /* @__PURE__ */ jsxRuntime.jsxs(
1961
2040
  FocusableTouchable,
1962
2041
  {
@@ -2164,6 +2243,7 @@ exports.NavExpandableItem = NavExpandableItem;
2164
2243
  exports.NavOverflowMenu = NavOverflowMenu;
2165
2244
  exports.NavShell = NavShell;
2166
2245
  exports.PillNav = PillNav;
2246
+ exports.PillNavVariant = PillNavVariant;
2167
2247
  exports.RAIL_FULL_BREAKPOINT = RAIL_FULL_BREAKPOINT;
2168
2248
  exports.Sidebar = Sidebar;
2169
2249
  exports.SidebarChevron = SidebarChevron;
@@ -2181,6 +2261,7 @@ exports.navStyles = navStyles;
2181
2261
  exports.pillNavStyles = pillNavStyles;
2182
2262
  exports.resolveActiveRoute = resolveActiveRoute;
2183
2263
  exports.resolveContentMaxWidth = resolveContentMaxWidth;
2264
+ exports.resolvePillMenuLabel = resolvePillMenuLabel;
2184
2265
  exports.resolveRailMode = resolveRailMode;
2185
2266
  exports.resolveSearchAffordance = resolveSearchAffordance;
2186
2267
  exports.roleRoutesToNavItems = roleRoutesToNavItems;