@dloizides/ui-nav 1.16.0 → 1.17.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,12 +1,93 @@
1
- import React3, { useState, useCallback, useMemo, useEffect, useRef } from 'react';
2
- import { StyleSheet, Platform, Text, TouchableOpacity, View, TextInput, Pressable, useWindowDimensions, ActivityIndicator, ScrollView } from 'react-native';
1
+ import React, { useState, useCallback, useMemo, useEffect, useRef } from 'react';
2
+ import { Platform, StyleSheet, Pressable, Text, View, TextInput, useWindowDimensions, ActivityIndicator, ScrollView } from 'react-native';
3
3
  import { useUi, UiProvider } from '@dloizides/ui-feedback';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
5
  import { Collapse } from '@dloizides/ui-motion';
5
- import { jsx, jsxs } from 'react/jsx-runtime';
6
6
  import { ModalDropdown } from '@dloizides/ui-layout';
7
7
  import { resolveAccessibleRoutes } from '@dloizides/auth-web';
8
8
 
9
9
  // src/Sidebar.tsx
10
+ var IS_WEB = Platform.OS === "web";
11
+ var FOCUS_RING_WIDTH = 2;
12
+ var FOCUS_RING_OFFSET = 2;
13
+ var HOVER_TRANSITION_MS = 150;
14
+ var TINT_TRANSITION_MS = 160;
15
+ function focusRingStyle(focused, ringColor) {
16
+ if (!IS_WEB || !focused) return void 0;
17
+ const ring = {
18
+ outlineWidth: FOCUS_RING_WIDTH,
19
+ outlineStyle: "solid",
20
+ outlineColor: ringColor,
21
+ outlineOffset: FOCUS_RING_OFFSET
22
+ };
23
+ return ring;
24
+ }
25
+ function webTransition(properties, durationMs, reducedMotion) {
26
+ if (!IS_WEB) return void 0;
27
+ const transition = {
28
+ transitionProperty: properties,
29
+ transitionDuration: reducedMotion ? "0ms" : `${durationMs}ms`
30
+ };
31
+ return transition;
32
+ }
33
+ function hoverTransitionStyle(reducedMotion) {
34
+ return webTransition("color, background-color", HOVER_TRANSITION_MS, reducedMotion);
35
+ }
36
+ function tintTransitionStyle(reducedMotion) {
37
+ return webTransition("opacity", TINT_TRANSITION_MS, reducedMotion);
38
+ }
39
+ function rotateTransitionStyle(reducedMotion) {
40
+ return webTransition("transform", TINT_TRANSITION_MS, reducedMotion);
41
+ }
42
+ var MIN_TARGET = 36;
43
+ var styles = StyleSheet.create({
44
+ trigger: {
45
+ flexDirection: "row",
46
+ alignItems: "center",
47
+ justifyContent: "space-between",
48
+ columnGap: 8,
49
+ paddingHorizontal: 12,
50
+ minHeight: MIN_TARGET,
51
+ borderWidth: 1,
52
+ borderRadius: 8
53
+ },
54
+ label: { fontSize: 14 },
55
+ badge: { paddingHorizontal: 6, paddingVertical: 2, borderRadius: 4, borderWidth: 1 },
56
+ badgeText: { fontSize: 11, fontWeight: "700" }
57
+ });
58
+ var CommandPaletteTrigger = ({
59
+ label,
60
+ hint,
61
+ shortcut,
62
+ onPress,
63
+ testID
64
+ }) => {
65
+ const { theme } = useUi();
66
+ const colors = theme.colors;
67
+ const primary = theme.palette.primary["500"];
68
+ const [focused, setFocused] = React.useState(false);
69
+ return /* @__PURE__ */ jsxs(
70
+ Pressable,
71
+ {
72
+ accessibilityHint: hint,
73
+ accessibilityLabel: label,
74
+ accessibilityRole: "button",
75
+ style: [
76
+ styles.trigger,
77
+ { backgroundColor: colors.surface, borderColor: colors.border },
78
+ focusRingStyle(focused, primary)
79
+ ],
80
+ testID,
81
+ onBlur: () => setFocused(false),
82
+ onFocus: () => setFocused(true),
83
+ onPress,
84
+ children: [
85
+ /* @__PURE__ */ jsx(Text, { style: [styles.label, { color: colors.textSecondary }], children: label }),
86
+ /* @__PURE__ */ jsx(View, { style: [styles.badge, { borderColor: colors.border }], children: /* @__PURE__ */ jsx(Text, { style: [styles.badgeText, { color: colors.textSecondary }], children: shortcut }) })
87
+ ]
88
+ }
89
+ );
90
+ };
10
91
 
11
92
  // src/sidebarFilter.ts
12
93
  function searchTokens(query) {
@@ -50,6 +131,10 @@ var ACTIVE_ACCENT_WIDTH = 3;
50
131
  var NAV_ROW_RADIUS = 8;
51
132
  var ACTIVE_TINT_OPACITY = 0.14;
52
133
  var HOVER_TINT_OPACITY = 0.06;
134
+ function rowTintOpacity(isActive, hovered) {
135
+ if (isActive) return ACTIVE_TINT_OPACITY;
136
+ return hovered ? HOVER_TINT_OPACITY : 0;
137
+ }
53
138
  var NAV_LINK_GAP = 4;
54
139
  var navStyles = StyleSheet.create({
55
140
  // --- Sidebar ---
@@ -75,6 +160,12 @@ var navStyles = StyleSheet.create({
75
160
  sidebarSpacer: {
76
161
  flex: 1
77
162
  },
163
+ // Bottom rhythm under the ⌘K palette trigger (the narrow-viewport search
164
+ // affordance), matching the inline field's own `marginBottom` so swapping
165
+ // affordances by width keeps the same gap above the nav list.
166
+ sidebarTriggerSlot: {
167
+ marginBottom: 12
168
+ },
78
169
  // Inline-search no-match text — sits where the nav list would, muted + padded.
79
170
  sidebarEmpty: {
80
171
  fontSize: 13,
@@ -337,38 +428,6 @@ var expandableStyles = StyleSheet.create({
337
428
  var BASE_INDENT = 12;
338
429
  var NAV_ICON_SIZE = 14;
339
430
  var CHEVRON_ICON_SIZE = 12;
340
- var IS_WEB = Platform.OS === "web";
341
- var FOCUS_RING_WIDTH = 2;
342
- var FOCUS_RING_OFFSET = 2;
343
- var HOVER_TRANSITION_MS = 150;
344
- var TINT_TRANSITION_MS = 160;
345
- function focusRingStyle(focused, ringColor) {
346
- if (!IS_WEB || !focused) return void 0;
347
- const ring = {
348
- outlineWidth: FOCUS_RING_WIDTH,
349
- outlineStyle: "solid",
350
- outlineColor: ringColor,
351
- outlineOffset: FOCUS_RING_OFFSET
352
- };
353
- return ring;
354
- }
355
- function webTransition(properties, durationMs, reducedMotion) {
356
- if (!IS_WEB) return void 0;
357
- const transition = {
358
- transitionProperty: properties,
359
- transitionDuration: reducedMotion ? "0ms" : `${durationMs}ms`
360
- };
361
- return transition;
362
- }
363
- function hoverTransitionStyle(reducedMotion) {
364
- return webTransition("color, background-color", HOVER_TRANSITION_MS, reducedMotion);
365
- }
366
- function tintTransitionStyle(reducedMotion) {
367
- return webTransition("opacity", TINT_TRANSITION_MS, reducedMotion);
368
- }
369
- function rotateTransitionStyle(reducedMotion) {
370
- return webTransition("transform", TINT_TRANSITION_MS, reducedMotion);
371
- }
372
431
  var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
373
432
  function getReducedMotionQuery() {
374
433
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return void 0;
@@ -422,9 +481,19 @@ function hasActiveDescendant(item, pathname) {
422
481
  if (isRouteActive(pathname, item.route)) return true;
423
482
  return (item.children ?? []).some((child) => hasActiveDescendant(child, pathname));
424
483
  }
425
- function TintOverlay({ opacity, color }) {
484
+ function TintOverlay({
485
+ opacity,
486
+ color,
487
+ testID
488
+ }) {
426
489
  const reducedMotion = useReducedMotion();
427
- return /* @__PURE__ */ jsx(View, { style: [expandableStyles.tintOverlay, { backgroundColor: color, opacity }, tintTransitionStyle(reducedMotion)] });
490
+ return /* @__PURE__ */ jsx(
491
+ View,
492
+ {
493
+ style: [expandableStyles.tintOverlay, { backgroundColor: color, opacity }, tintTransitionStyle(reducedMotion)],
494
+ testID
495
+ }
496
+ );
428
497
  }
429
498
  var NavExpandableItem = ({
430
499
  item,
@@ -455,11 +524,12 @@ var NavExpandableItem = ({
455
524
  );
456
525
  const paddingStyle = useMemo(() => ({ paddingLeft: indent + BASE_INDENT }), [indent]);
457
526
  const headerPaddingStyle = useMemo(() => ({ paddingLeft: indent }), [indent]);
458
- const leafTintOpacity = isActive ? ACTIVE_TINT_OPACITY : hovered ? HOVER_TINT_OPACITY : 0;
459
- const headerTintOpacity = hovered ? HOVER_TINT_OPACITY : 0;
527
+ const leafTintOpacity = rowTintOpacity(isActive, hovered);
528
+ const headerTintOpacity = rowTintOpacity(false, hovered);
529
+ const rowTestID = item.testID ?? item.key;
460
530
  if (!hasChildren)
461
531
  return /* @__PURE__ */ jsxs(
462
- TouchableOpacity,
532
+ Pressable,
463
533
  {
464
534
  accessibilityHint: navigateHint(item.label),
465
535
  accessibilityLabel: item.label,
@@ -471,14 +541,14 @@ var NavExpandableItem = ({
471
541
  isActive ? activeAccentStyle : void 0,
472
542
  focusRingStyle(focused, primaryColor)
473
543
  ],
474
- testID: item.testID ?? item.key,
544
+ testID: rowTestID,
475
545
  onBlur: () => setFocused(false),
476
546
  onFocus: () => setFocused(true),
477
547
  onPress: () => onNavigate(item.route),
478
548
  ...hoverHandlerProps(onHoverIn, onHoverOut),
479
549
  ...ariaCurrentProps(isActive),
480
550
  children: [
481
- /* @__PURE__ */ jsx(TintOverlay, { color: primaryColor, opacity: leafTintOpacity }),
551
+ /* @__PURE__ */ jsx(TintOverlay, { color: primaryColor, opacity: leafTintOpacity, testID: `${rowTestID}-tint` }),
482
552
  typeof item.renderIcon === "function" ? /* @__PURE__ */ jsx(View, { style: expandableStyles.iconWrapper, children: item.renderIcon(colors.textSecondary, NAV_ICON_SIZE) }) : null,
483
553
  /* @__PURE__ */ jsx(
484
554
  Text,
@@ -496,7 +566,7 @@ var NavExpandableItem = ({
496
566
  const chevronColor = colors.textSecondary;
497
567
  return /* @__PURE__ */ jsxs(View, { children: [
498
568
  /* @__PURE__ */ jsxs(
499
- TouchableOpacity,
569
+ Pressable,
500
570
  {
501
571
  accessibilityHint: expanded ? collapseHint : expandHint,
502
572
  accessibilityLabel: item.label,
@@ -508,14 +578,14 @@ var NavExpandableItem = ({
508
578
  headerPaddingStyle,
509
579
  focusRingStyle(focused, primaryColor)
510
580
  ],
511
- testID: item.testID ?? item.key,
581
+ testID: rowTestID,
512
582
  onBlur: () => setFocused(false),
513
583
  onFocus: () => setFocused(true),
514
584
  onPress: toggle,
515
585
  ...hoverHandlerProps(onHoverIn, onHoverOut),
516
586
  ...ariaExpandedProps(expanded),
517
587
  children: [
518
- /* @__PURE__ */ jsx(TintOverlay, { color: primaryColor, opacity: headerTintOpacity }),
588
+ /* @__PURE__ */ jsx(TintOverlay, { color: primaryColor, opacity: headerTintOpacity, testID: `${rowTestID}-tint` }),
519
589
  typeof item.renderIcon === "function" ? /* @__PURE__ */ jsx(View, { style: expandableStyles.iconWrapper, children: item.renderIcon(isSectionHeader ? colors.textSecondary : colors.text, NAV_ICON_SIZE) }) : null,
520
590
  /* @__PURE__ */ jsx(
521
591
  Text,
@@ -547,10 +617,16 @@ var NavExpandableItem = ({
547
617
  )) }) })
548
618
  ] });
549
619
  };
620
+
621
+ // src/searchAffordance.ts
622
+ var DEFAULT_SEARCH_BREAKPOINT = 768;
623
+ function resolveSearchAffordance(viewport, breakpoint = DEFAULT_SEARCH_BREAKPOINT) {
624
+ return viewport >= breakpoint ? "inline" : "palette";
625
+ }
550
626
  var FIELD_MIN_HEIGHT = 38;
551
627
  var CLEAR_GLYPH = "\u2715";
552
628
  var CLEAR_MIN_TARGET = 28;
553
- var styles = StyleSheet.create({
629
+ var styles2 = StyleSheet.create({
554
630
  wrap: {
555
631
  flexDirection: "row",
556
632
  alignItems: "center",
@@ -591,7 +667,7 @@ var SidebarSearch = ({
591
667
  View,
592
668
  {
593
669
  style: [
594
- styles.wrap,
670
+ styles2.wrap,
595
671
  { backgroundColor: colors.surface, borderColor: focused ? primary : colors.border },
596
672
  focusRingStyle(focused, primary)
597
673
  ],
@@ -603,7 +679,7 @@ var SidebarSearch = ({
603
679
  accessibilityLabel: labels.placeholder,
604
680
  placeholder: labels.placeholder,
605
681
  placeholderTextColor: colors.textSecondary,
606
- style: [styles.input, { color: colors.text }],
682
+ style: [styles2.input, { color: colors.text }],
607
683
  testID,
608
684
  value,
609
685
  onBlur: () => setFocused(false),
@@ -617,10 +693,10 @@ var SidebarSearch = ({
617
693
  accessibilityHint: labels.clearHint,
618
694
  accessibilityLabel: labels.clearLabel,
619
695
  accessibilityRole: "button",
620
- style: styles.clear,
696
+ style: styles2.clear,
621
697
  testID: `${testID}-clear`,
622
698
  onPress: onClear,
623
- children: /* @__PURE__ */ jsx(Text, { style: [styles.clearGlyph, { color: colors.textSecondary }], children: CLEAR_GLYPH })
699
+ children: /* @__PURE__ */ jsx(Text, { style: [styles2.clearGlyph, { color: colors.textSecondary }], children: CLEAR_GLYPH })
624
700
  }
625
701
  ) : null
626
702
  ]
@@ -633,11 +709,12 @@ function isBareText(node) {
633
709
  function renderTextSlot(node, style) {
634
710
  if (node === void 0 || node === null) return node;
635
711
  if (isBareText(node)) return /* @__PURE__ */ jsx(Text, { style, children: node });
636
- return React3.Children.map(
712
+ return React.Children.map(
637
713
  node,
638
714
  (child) => isBareText(child) ? /* @__PURE__ */ jsx(Text, { style, children: child }) : child
639
715
  );
640
716
  }
717
+ var DEFAULT_TRIGGER_TEST_ID = "sidebar-command-palette-trigger";
641
718
  var Sidebar = ({
642
719
  items,
643
720
  pathname,
@@ -650,6 +727,7 @@ var Sidebar = ({
650
727
  renderChevron,
651
728
  enableInlineSearch = false,
652
729
  search,
730
+ paletteTrigger,
653
731
  searchQuery,
654
732
  onSearchChange,
655
733
  header,
@@ -658,6 +736,7 @@ var Sidebar = ({
658
736
  }) => {
659
737
  const { theme } = useUi();
660
738
  const colors = theme.colors;
739
+ const { width } = useWindowDimensions();
661
740
  const [internalQuery, setInternalQuery] = useState("");
662
741
  const controlled = searchQuery !== void 0;
663
742
  const query = controlled ? searchQuery : internalQuery;
@@ -669,9 +748,12 @@ var Sidebar = ({
669
748
  [controlled, onSearchChange]
670
749
  );
671
750
  const clearQuery = useCallback(() => setQuery(""), [setQuery]);
672
- const searchOn = enableInlineSearch && search !== void 0;
673
- const visibleItems = searchOn ? filterNavItems(items, query) : items;
674
- const showEmpty = searchOn && isFilterActive(query) && visibleItems.length === 0;
751
+ const affordance = resolveSearchAffordance(width);
752
+ const isInlineAffordance = affordance === "inline";
753
+ const showInlineSearch = enableInlineSearch && search !== void 0 && isInlineAffordance;
754
+ const showPaletteTrigger = paletteTrigger !== void 0 && !isInlineAffordance;
755
+ const visibleItems = showInlineSearch ? filterNavItems(items, query) : items;
756
+ const showEmpty = showInlineSearch && isFilterActive(query) && visibleItems.length === 0;
675
757
  return /* @__PURE__ */ jsxs(
676
758
  View,
677
759
  {
@@ -685,7 +767,7 @@ var Sidebar = ({
685
767
  ],
686
768
  children: [
687
769
  /* @__PURE__ */ jsx(Text, { accessibilityRole: "header", style: [navStyles.sidebarTitle, { color: colors.text }], children: title }),
688
- searchOn && search !== void 0 ? /* @__PURE__ */ jsx(
770
+ showInlineSearch && search !== void 0 ? /* @__PURE__ */ jsx(
689
771
  SidebarSearch,
690
772
  {
691
773
  labels: search,
@@ -695,6 +777,16 @@ var Sidebar = ({
695
777
  onClear: clearQuery
696
778
  }
697
779
  ) : null,
780
+ showPaletteTrigger && paletteTrigger !== void 0 ? /* @__PURE__ */ jsx(View, { style: navStyles.sidebarTriggerSlot, children: /* @__PURE__ */ jsx(
781
+ CommandPaletteTrigger,
782
+ {
783
+ hint: paletteTrigger.hint,
784
+ label: paletteTrigger.label,
785
+ shortcut: paletteTrigger.shortcut,
786
+ testID: paletteTrigger.testID ?? DEFAULT_TRIGGER_TEST_ID,
787
+ onPress: paletteTrigger.onOpen
788
+ }
789
+ ) }) : null,
698
790
  renderTextSlot(header, { color: colors.text }),
699
791
  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(
700
792
  NavExpandableItem,
@@ -716,12 +808,6 @@ var Sidebar = ({
716
808
  );
717
809
  };
718
810
 
719
- // src/searchAffordance.ts
720
- var DEFAULT_SEARCH_BREAKPOINT = 768;
721
- function resolveSearchAffordance(viewport, breakpoint = DEFAULT_SEARCH_BREAKPOINT) {
722
- return viewport >= breakpoint ? "inline" : "palette";
723
- }
724
-
725
811
  // src/constants.ts
726
812
  var NAV_TEST_IDS = {
727
813
  /** displayName line in the rich account header (tappable when `onAccount` set). */
@@ -1157,7 +1243,7 @@ var NavBarInner = ({
1157
1243
  }
1158
1244
  );
1159
1245
  if (collapsed) {
1160
- return /* @__PURE__ */ jsx(View, { nativeID: LINKS_REGION_ID, style: navBarStyles.linksStacked, testID: NAV_TEST_IDS.navBarLinks, children: items.map((item) => /* @__PURE__ */ jsx(React3.Fragment, { children: renderLink(item) }, item.key)) });
1246
+ return /* @__PURE__ */ jsx(View, { nativeID: LINKS_REGION_ID, style: navBarStyles.linksStacked, testID: NAV_TEST_IDS.navBarLinks, children: items.map((item) => /* @__PURE__ */ jsx(React.Fragment, { children: renderLink(item) }, item.key)) });
1161
1247
  }
1162
1248
  const visibleItems = items.slice(0, visibleCount);
1163
1249
  const overflowItems = items.slice(visibleCount);
@@ -1223,7 +1309,7 @@ var CARD_BORDER_WIDTH = 1;
1223
1309
  var CARD_TITLE_FONT_SIZE = 16;
1224
1310
  var CARD_MESSAGE_FONT_SIZE = 14;
1225
1311
  var CARD_TITLE_MARGIN_BOTTOM = 8;
1226
- var styles2 = StyleSheet.create({
1312
+ var styles3 = StyleSheet.create({
1227
1313
  centerFill: { flex: 1, justifyContent: "center", alignItems: "center" },
1228
1314
  card: {
1229
1315
  padding: CARD_PADDING,
@@ -1240,9 +1326,9 @@ function MessageCard({
1240
1326
  }) {
1241
1327
  const { theme } = useUi();
1242
1328
  const colors = theme.colors;
1243
- return /* @__PURE__ */ jsxs(View, { style: [styles2.card, { backgroundColor: colors.surface, borderColor: accentColor }], testID, children: [
1244
- /* @__PURE__ */ jsx(Text, { style: [styles2.cardTitle, { color: accentColor }], children: message.titleText }),
1245
- /* @__PURE__ */ jsx(Text, { style: [styles2.cardMessage, { color: colors.textSecondary }], children: message.messageText })
1329
+ return /* @__PURE__ */ jsxs(View, { style: [styles3.card, { backgroundColor: colors.surface, borderColor: accentColor }], testID, children: [
1330
+ /* @__PURE__ */ jsx(Text, { style: [styles3.cardTitle, { color: accentColor }], children: message.titleText }),
1331
+ /* @__PURE__ */ jsx(Text, { style: [styles3.cardMessage, { color: colors.textSecondary }], children: message.messageText })
1246
1332
  ] });
1247
1333
  }
1248
1334
  function useContentBody(state, children, testID) {
@@ -1254,7 +1340,7 @@ function useContentBody(state, children, testID) {
1254
1340
  if (state?.error)
1255
1341
  return /* @__PURE__ */ jsx(MessageCard, { accentColor: errorColor, message: state.error, testID: `${testID}${APP_SHELL_SUFFIX.error}` });
1256
1342
  if (state?.loading === true)
1257
- return /* @__PURE__ */ jsx(View, { style: styles2.centerFill, testID: `${testID}${APP_SHELL_SUFFIX.loading}`, children: /* @__PURE__ */ jsx(ActivityIndicator, { color: primary, size: "large" }) });
1343
+ return /* @__PURE__ */ jsx(View, { style: styles3.centerFill, testID: `${testID}${APP_SHELL_SUFFIX.loading}`, children: /* @__PURE__ */ jsx(ActivityIndicator, { color: primary, size: "large" }) });
1258
1344
  return children;
1259
1345
  }
1260
1346
  var SCRIM_COLOR = "rgba(0, 0, 0, 0.5)";
@@ -1278,7 +1364,7 @@ var DEFAULT_DRAWER_LABELS = {
1278
1364
  closeLabel: "Close menu",
1279
1365
  closeHint: "Close the navigation menu"
1280
1366
  };
1281
- var styles3 = StyleSheet.create({
1367
+ var styles4 = StyleSheet.create({
1282
1368
  overlay: { ...StyleSheet.absoluteFillObject, zIndex: DRAWER_Z_INDEX },
1283
1369
  // The scrim's tap-to-close hit area is anchored to the RIGHT of the panel
1284
1370
  // (`left: DRAWER_WIDTH`), so it NEVER overlaps the panel: nav-item taps always
@@ -1313,10 +1399,10 @@ var MenuToggle = ({ label, hint, onOpen, testID }) => {
1313
1399
  accessibilityHint: hint,
1314
1400
  accessibilityLabel: label,
1315
1401
  ringColor: theme.palette.primary["500"],
1316
- style: styles3.menuToggle,
1402
+ style: styles4.menuToggle,
1317
1403
  testID,
1318
1404
  onPress: onOpen,
1319
- children: /* @__PURE__ */ jsx(Text, { style: [styles3.menuToggleGlyph, { color: theme.colors.text }], children: MENU_GLYPH2 })
1405
+ children: /* @__PURE__ */ jsx(Text, { style: [styles4.menuToggleGlyph, { color: theme.colors.text }], children: MENU_GLYPH2 })
1320
1406
  }
1321
1407
  );
1322
1408
  };
@@ -1342,14 +1428,14 @@ var MobileDrawer = ({
1342
1428
  node.addEventListener("click", handleClick);
1343
1429
  return () => node.removeEventListener("click", handleClick);
1344
1430
  }, [onClose]);
1345
- return /* @__PURE__ */ jsxs(View, { style: styles3.overlay, children: [
1431
+ return /* @__PURE__ */ jsxs(View, { style: styles4.overlay, children: [
1346
1432
  /* @__PURE__ */ jsx(
1347
1433
  Pressable,
1348
1434
  {
1349
1435
  accessibilityHint: labels.closeHint,
1350
1436
  accessibilityLabel: labels.closeLabel,
1351
1437
  accessibilityRole: "button",
1352
- style: styles3.scrim,
1438
+ style: styles4.scrim,
1353
1439
  testID: scrimTestID,
1354
1440
  onPress: onClose
1355
1441
  }
@@ -1360,7 +1446,7 @@ var MobileDrawer = ({
1360
1446
  ref: panelRef,
1361
1447
  "aria-modal": true,
1362
1448
  role: "dialog",
1363
- style: [styles3.panel, { backgroundColor: theme.colors.surface }],
1449
+ style: [styles4.panel, { backgroundColor: theme.colors.surface }],
1364
1450
  testID: drawerTestID,
1365
1451
  children: renderTextSlot(sidebar, { color: theme.colors.text })
1366
1452
  }
@@ -1391,7 +1477,7 @@ function useContentMaxWidth(width) {
1391
1477
  return resolveContentMaxWidth(width, viewport);
1392
1478
  }
1393
1479
  var DEFAULT_CONTENT_PADDING = 24;
1394
- var styles4 = StyleSheet.create({
1480
+ var styles5 = StyleSheet.create({
1395
1481
  root: { flex: 1 },
1396
1482
  centerFill: { flex: 1, justifyContent: "center", alignItems: "center" },
1397
1483
  scroll: { flex: 1 },
@@ -1448,20 +1534,20 @@ var AppShell = ({
1448
1534
  if (isUnauthenticated && gate !== void 0) gate.onRedirect();
1449
1535
  }, [isUnauthenticated, gate]);
1450
1536
  if (gate?.pending === true)
1451
- return /* @__PURE__ */ jsx(View, { style: [styles4.root, styles4.centerFill, { backgroundColor: theme.colors.background }], testID: `${testID}${APP_SHELL_SUFFIX.pending}`, children: /* @__PURE__ */ jsx(ActivityIndicator, { color: primary, size: "large" }) });
1537
+ return /* @__PURE__ */ jsx(View, { style: [styles5.root, styles5.centerFill, { backgroundColor: theme.colors.background }], testID: `${testID}${APP_SHELL_SUFFIX.pending}`, children: /* @__PURE__ */ jsx(ActivityIndicator, { color: primary, size: "large" }) });
1452
1538
  if (isUnauthenticated) return null;
1453
- const columnStyle = maxWidth === "full" ? styles4.columnFull : [styles4.columnCapped, { maxWidth }];
1454
- const navInnerStyle = chromeAlignment === "content" && maxWidth !== "full" ? [styles4.chromeCapped, { maxWidth, paddingHorizontal: contentPadding }] : void 0;
1539
+ const columnStyle = maxWidth === "full" ? styles5.columnFull : [styles5.columnCapped, { maxWidth }];
1540
+ const navInnerStyle = chromeAlignment === "content" && maxWidth !== "full" ? [styles5.chromeCapped, { maxWidth, paddingHorizontal: contentPadding }] : void 0;
1455
1541
  const scroller = /* @__PURE__ */ jsx(
1456
1542
  ScrollView,
1457
1543
  {
1458
- contentContainerStyle: [styles4.scrollContent, { padding: contentPadding }],
1459
- style: styles4.scroll,
1544
+ contentContainerStyle: [styles5.scrollContent, { padding: contentPadding }],
1545
+ style: styles5.scroll,
1460
1546
  testID: `${testID}${APP_SHELL_SUFFIX.content}`,
1461
1547
  children: /* @__PURE__ */ jsx(View, { style: columnStyle, children: body })
1462
1548
  }
1463
1549
  );
1464
- const headerRegion = useDrawer ? /* @__PURE__ */ jsxs(View, { style: styles4.headerRow, testID: `${testID}${APP_SHELL_SUFFIX.header}`, children: [
1550
+ const headerRegion = useDrawer ? /* @__PURE__ */ jsxs(View, { style: styles5.headerRow, testID: `${testID}${APP_SHELL_SUFFIX.header}`, children: [
1465
1551
  /* @__PURE__ */ jsx(
1466
1552
  MenuToggle,
1467
1553
  {
@@ -1471,14 +1557,14 @@ var AppShell = ({
1471
1557
  onOpen: openDrawer
1472
1558
  }
1473
1559
  ),
1474
- /* @__PURE__ */ jsx(View, { style: styles4.headerFill, children: renderTextSlot(header, { color: theme.colors.text }) })
1560
+ /* @__PURE__ */ jsx(View, { style: styles5.headerFill, children: renderTextSlot(header, { color: theme.colors.text }) })
1475
1561
  ] }) : /* @__PURE__ */ jsx(View, { testID: `${testID}${APP_SHELL_SUFFIX.header}`, children: renderTextSlot(header, { color: theme.colors.text }) });
1476
1562
  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;
1477
- return /* @__PURE__ */ jsxs(View, { style: [styles4.root, { backgroundColor: theme.colors.background }], testID, children: [
1563
+ return /* @__PURE__ */ jsxs(View, { style: [styles5.root, { backgroundColor: theme.colors.background }], testID, children: [
1478
1564
  headerRegion,
1479
1565
  nav !== void 0 ? /* @__PURE__ */ jsx(View, { testID: `${testID}${APP_SHELL_SUFFIX.nav}`, children: navInnerStyle !== void 0 ? /* @__PURE__ */ jsx(View, { style: navInnerStyle, children: renderTextSlot(nav, { color: theme.colors.text }) }) : renderTextSlot(nav, { color: theme.colors.text }) }) : null,
1480
1566
  banner !== void 0 ? /* @__PURE__ */ jsx(View, { testID: `${testID}${APP_SHELL_SUFFIX.banner}`, children: renderTextSlot(banner, { color: theme.colors.text }) }) : null,
1481
- railRegion !== null ? /* @__PURE__ */ jsxs(View, { style: styles4.bodyRow, children: [
1567
+ railRegion !== null ? /* @__PURE__ */ jsxs(View, { style: styles5.bodyRow, children: [
1482
1568
  railRegion,
1483
1569
  scroller
1484
1570
  ] }) : scroller,
@@ -1595,16 +1681,21 @@ var NavShell = ({
1595
1681
  {
1596
1682
  collapseHint: sideRail.collapseHint,
1597
1683
  containerStyle: sideRail.containerStyle,
1684
+ enableInlineSearch: sideRail.enableInlineSearch,
1598
1685
  expandHint: sideRail.expandHint,
1599
1686
  footer: sideRail.footer,
1600
1687
  header: sideRail.header,
1601
1688
  items: sideRail.items,
1602
1689
  navigateHint,
1690
+ paletteTrigger: sideRail.paletteTrigger,
1603
1691
  pathname,
1604
1692
  regionLabel,
1605
1693
  renderChevron: sideRail.renderChevron,
1694
+ search: sideRail.search,
1695
+ searchQuery: sideRail.searchQuery,
1606
1696
  title: sideRail.title,
1607
- onNavigate
1697
+ onNavigate,
1698
+ onSearchChange: sideRail.onSearchChange
1608
1699
  }
1609
1700
  ) : void 0;
1610
1701
  const collapsedCfg = showSideRail ? sideRail?.collapsed : void 0;
@@ -1772,7 +1863,7 @@ var KEY_DOWN = "ArrowDown";
1772
1863
  var KEY_UP = "ArrowUp";
1773
1864
  var KEY_ENTER = "Enter";
1774
1865
  var KEY_ESCAPE = "Escape";
1775
- var styles5 = StyleSheet.create({
1866
+ var styles6 = StyleSheet.create({
1776
1867
  overlay: { ...StyleSheet.absoluteFillObject, zIndex: OVERLAY_Z_INDEX, alignItems: "center" },
1777
1868
  scrim: { ...StyleSheet.absoluteFillObject, backgroundColor: SCRIM_COLOR2 },
1778
1869
  panel: {
@@ -1801,14 +1892,14 @@ var PaletteRow = ({ item, selected, onChoose }) => {
1801
1892
  accessibilityLabel: item.label,
1802
1893
  accessibilityRole: "button",
1803
1894
  accessibilityState: { selected },
1804
- style: [styles5.row, selected ? { backgroundColor: colors.border } : void 0],
1895
+ style: [styles6.row, selected ? { backgroundColor: colors.border } : void 0],
1805
1896
  testID: item.testID ?? item.key,
1806
1897
  onPress: () => onChoose(item),
1807
1898
  children: [
1808
1899
  typeof item.renderIcon === "function" ? item.renderIcon(colors.textSecondary, NAV_ICON_SIZE) : null,
1809
- /* @__PURE__ */ jsxs(View, { style: styles5.rowText, children: [
1810
- /* @__PURE__ */ jsx(Text, { style: [styles5.rowLabel, { color: colors.text }], children: item.label }),
1811
- item.hint ? /* @__PURE__ */ jsx(Text, { style: [styles5.rowHint, { color: colors.textSecondary }], children: item.hint }) : null
1900
+ /* @__PURE__ */ jsxs(View, { style: styles6.rowText, children: [
1901
+ /* @__PURE__ */ jsx(Text, { style: [styles6.rowLabel, { color: colors.text }], children: item.label }),
1902
+ item.hint ? /* @__PURE__ */ jsx(Text, { style: [styles6.rowHint, { color: colors.textSecondary }], children: item.hint }) : null
1812
1903
  ] })
1813
1904
  ]
1814
1905
  }
@@ -1848,14 +1939,14 @@ var CommandPalette = ({ open, items, onClose, labels, testID }) => {
1848
1939
  [results, selected, choose, onClose]
1849
1940
  );
1850
1941
  if (!open) return null;
1851
- return /* @__PURE__ */ jsxs(View, { style: styles5.overlay, children: [
1942
+ return /* @__PURE__ */ jsxs(View, { style: styles6.overlay, children: [
1852
1943
  /* @__PURE__ */ jsx(
1853
1944
  Pressable,
1854
1945
  {
1855
1946
  accessibilityHint: labels.closeHint,
1856
1947
  accessibilityLabel: labels.closeLabel,
1857
1948
  accessibilityRole: "button",
1858
- style: styles5.scrim,
1949
+ style: styles6.scrim,
1859
1950
  testID: `${testID ?? "command-palette"}-scrim`,
1860
1951
  onPress: onClose
1861
1952
  }
@@ -1866,7 +1957,7 @@ var CommandPalette = ({ open, items, onClose, labels, testID }) => {
1866
1957
  "aria-modal": true,
1867
1958
  "aria-label": labels.regionLabel,
1868
1959
  role: "dialog",
1869
- style: [styles5.panel, { backgroundColor: colors.surface, borderColor: colors.border }],
1960
+ style: [styles6.panel, { backgroundColor: colors.surface, borderColor: colors.border }],
1870
1961
  testID: testID ?? "command-palette",
1871
1962
  children: [
1872
1963
  /* @__PURE__ */ jsx(
@@ -1876,68 +1967,19 @@ var CommandPalette = ({ open, items, onClose, labels, testID }) => {
1876
1967
  accessibilityLabel: labels.placeholder,
1877
1968
  placeholder: labels.placeholder,
1878
1969
  placeholderTextColor: colors.textSecondary,
1879
- style: [styles5.input, { color: colors.text, borderBottomColor: colors.border }],
1970
+ style: [styles6.input, { color: colors.text, borderBottomColor: colors.border }],
1880
1971
  testID: `${testID ?? "command-palette"}-input`,
1881
1972
  value: query,
1882
1973
  onChangeText: setQuery,
1883
1974
  onKeyPress
1884
1975
  }
1885
1976
  ),
1886
- results.length === 0 ? /* @__PURE__ */ jsx(Text, { style: [styles5.empty, { color: colors.textSecondary }], children: labels.emptyText }) : /* @__PURE__ */ jsx(ScrollView, { keyboardShouldPersistTaps: "handled", style: styles5.list, children: results.map((item, index) => /* @__PURE__ */ jsx(PaletteRow, { item, selected: index === selected, onChoose: choose }, item.key)) })
1977
+ results.length === 0 ? /* @__PURE__ */ jsx(Text, { style: [styles6.empty, { color: colors.textSecondary }], children: labels.emptyText }) : /* @__PURE__ */ jsx(ScrollView, { keyboardShouldPersistTaps: "handled", style: styles6.list, children: results.map((item, index) => /* @__PURE__ */ jsx(PaletteRow, { item, selected: index === selected, onChoose: choose }, item.key)) })
1887
1978
  ]
1888
1979
  }
1889
1980
  )
1890
1981
  ] });
1891
1982
  };
1892
- var MIN_TARGET = 36;
1893
- var styles6 = StyleSheet.create({
1894
- trigger: {
1895
- flexDirection: "row",
1896
- alignItems: "center",
1897
- justifyContent: "space-between",
1898
- columnGap: 8,
1899
- paddingHorizontal: 12,
1900
- minHeight: MIN_TARGET,
1901
- borderWidth: 1,
1902
- borderRadius: 8
1903
- },
1904
- label: { fontSize: 14 },
1905
- badge: { paddingHorizontal: 6, paddingVertical: 2, borderRadius: 4, borderWidth: 1 },
1906
- badgeText: { fontSize: 11, fontWeight: "700" }
1907
- });
1908
- var CommandPaletteTrigger = ({
1909
- label,
1910
- hint,
1911
- shortcut,
1912
- onPress,
1913
- testID
1914
- }) => {
1915
- const { theme } = useUi();
1916
- const colors = theme.colors;
1917
- const primary = theme.palette.primary["500"];
1918
- const [focused, setFocused] = React3.useState(false);
1919
- return /* @__PURE__ */ jsxs(
1920
- Pressable,
1921
- {
1922
- accessibilityHint: hint,
1923
- accessibilityLabel: label,
1924
- accessibilityRole: "button",
1925
- style: [
1926
- styles6.trigger,
1927
- { backgroundColor: colors.surface, borderColor: colors.border },
1928
- focusRingStyle(focused, primary)
1929
- ],
1930
- testID,
1931
- onBlur: () => setFocused(false),
1932
- onFocus: () => setFocused(true),
1933
- onPress,
1934
- children: [
1935
- /* @__PURE__ */ jsx(Text, { style: [styles6.label, { color: colors.textSecondary }], children: label }),
1936
- /* @__PURE__ */ jsx(View, { style: [styles6.badge, { borderColor: colors.border }], children: /* @__PURE__ */ jsx(Text, { style: [styles6.badgeText, { color: colors.textSecondary }], children: shortcut }) })
1937
- ]
1938
- }
1939
- );
1940
- };
1941
1983
  var LAUNCH_KEY = "k";
1942
1984
  function useCommandPaletteHotkey(onOpen, enabled = true) {
1943
1985
  useEffect(() => {