@dloizides/ui-nav 1.20.0 → 1.22.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.d.mts CHANGED
@@ -1359,6 +1359,9 @@ declare const navStyles: {
1359
1359
  paddingHorizontal: number;
1360
1360
  paddingVertical: number;
1361
1361
  borderRadius: number;
1362
+ minHeight: number;
1363
+ minWidth: number;
1364
+ justifyContent: "center";
1362
1365
  };
1363
1366
  accountText: {
1364
1367
  fontWeight: "600";
@@ -1415,6 +1418,7 @@ declare const darkModeStyles: {
1415
1418
  paddingHorizontal: number;
1416
1419
  paddingVertical: number;
1417
1420
  minHeight: number;
1421
+ minWidth: number;
1418
1422
  flexDirection: "row";
1419
1423
  alignItems: "center";
1420
1424
  columnGap: number;
@@ -1476,6 +1480,7 @@ declare const expandableStyles: {
1476
1480
  flexDirection: "row";
1477
1481
  alignItems: "center";
1478
1482
  paddingVertical: number;
1483
+ minHeight: number;
1479
1484
  borderLeftWidth: number;
1480
1485
  borderLeftColor: string;
1481
1486
  };
@@ -1509,6 +1514,7 @@ declare const expandableStyles: {
1509
1514
  flexDirection: "row";
1510
1515
  alignItems: "center";
1511
1516
  paddingVertical: number;
1517
+ minHeight: number;
1512
1518
  };
1513
1519
  sectionHeader: {
1514
1520
  marginTop: number;
package/dist/index.d.ts CHANGED
@@ -1359,6 +1359,9 @@ declare const navStyles: {
1359
1359
  paddingHorizontal: number;
1360
1360
  paddingVertical: number;
1361
1361
  borderRadius: number;
1362
+ minHeight: number;
1363
+ minWidth: number;
1364
+ justifyContent: "center";
1362
1365
  };
1363
1366
  accountText: {
1364
1367
  fontWeight: "600";
@@ -1415,6 +1418,7 @@ declare const darkModeStyles: {
1415
1418
  paddingHorizontal: number;
1416
1419
  paddingVertical: number;
1417
1420
  minHeight: number;
1421
+ minWidth: number;
1418
1422
  flexDirection: "row";
1419
1423
  alignItems: "center";
1420
1424
  columnGap: number;
@@ -1476,6 +1480,7 @@ declare const expandableStyles: {
1476
1480
  flexDirection: "row";
1477
1481
  alignItems: "center";
1478
1482
  paddingVertical: number;
1483
+ minHeight: number;
1479
1484
  borderLeftWidth: number;
1480
1485
  borderLeftColor: string;
1481
1486
  };
@@ -1509,6 +1514,7 @@ declare const expandableStyles: {
1509
1514
  flexDirection: "row";
1510
1515
  alignItems: "center";
1511
1516
  paddingVertical: number;
1517
+ minHeight: number;
1512
1518
  };
1513
1519
  sectionHeader: {
1514
1520
  marginTop: number;
package/dist/index.js CHANGED
@@ -13,146 +13,7 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
13
13
  var React__default = /*#__PURE__*/_interopDefault(React);
14
14
 
15
15
  // src/Sidebar.tsx
16
- var IS_WEB = reactNative.Platform.OS === "web";
17
- var FOCUS_RING_WIDTH = 2;
18
- var FOCUS_RING_OFFSET = 2;
19
- var HOVER_TRANSITION_MS = 150;
20
- var TINT_TRANSITION_MS = 160;
21
- function focusRingStyle(focused, ringColor) {
22
- if (!IS_WEB || !focused) return void 0;
23
- const ring = {
24
- outlineWidth: FOCUS_RING_WIDTH,
25
- outlineStyle: "solid",
26
- outlineColor: ringColor,
27
- outlineOffset: FOCUS_RING_OFFSET
28
- };
29
- return ring;
30
- }
31
- function webTransition(properties, durationMs, reducedMotion) {
32
- if (!IS_WEB) return void 0;
33
- const transition = {
34
- transitionProperty: properties,
35
- transitionDuration: reducedMotion ? "0ms" : `${durationMs}ms`
36
- };
37
- return transition;
38
- }
39
- function hoverTransitionStyle(reducedMotion) {
40
- return webTransition("color, background-color", HOVER_TRANSITION_MS, reducedMotion);
41
- }
42
- function tintTransitionStyle(reducedMotion) {
43
- return webTransition("opacity", TINT_TRANSITION_MS, reducedMotion);
44
- }
45
- function rotateTransitionStyle(reducedMotion) {
46
- return webTransition("transform", TINT_TRANSITION_MS, reducedMotion);
47
- }
48
- var MIN_TARGET = 36;
49
- var styles = reactNative.StyleSheet.create({
50
- trigger: {
51
- flexDirection: "row",
52
- alignItems: "center",
53
- justifyContent: "space-between",
54
- columnGap: 8,
55
- paddingHorizontal: 12,
56
- minHeight: MIN_TARGET,
57
- borderWidth: 1,
58
- borderRadius: 8
59
- },
60
- label: { fontSize: 14 },
61
- badge: { paddingHorizontal: 6, paddingVertical: 2, borderRadius: 4, borderWidth: 1 },
62
- badgeText: { fontSize: 11, fontWeight: "700" }
63
- });
64
- var CommandPaletteTrigger = ({
65
- label,
66
- hint,
67
- shortcut,
68
- onPress,
69
- testID
70
- }) => {
71
- const { theme } = uiFeedback.useUi();
72
- const colors = theme.colors;
73
- const primary = theme.palette.primary["500"];
74
- const [focused, setFocused] = React__default.default.useState(false);
75
- return /* @__PURE__ */ jsxRuntime.jsxs(
76
- reactNative.Pressable,
77
- {
78
- accessibilityHint: hint,
79
- accessibilityLabel: label,
80
- accessibilityRole: "button",
81
- style: [
82
- styles.trigger,
83
- { backgroundColor: colors.surface, borderColor: colors.border },
84
- focusRingStyle(focused, primary)
85
- ],
86
- testID,
87
- onBlur: () => setFocused(false),
88
- onFocus: () => setFocused(true),
89
- onPress,
90
- children: [
91
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.label, { color: colors.textSecondary }], children: label }),
92
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.badge, { borderColor: colors.border }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.badgeText, { color: colors.textSecondary }], children: shortcut }) })
93
- ]
94
- }
95
- );
96
- };
97
-
98
- // src/sidebarFilter.ts
99
- function searchTokens(query) {
100
- return query.trim().toLowerCase().split(/\s+/).filter(Boolean);
101
- }
102
- function labelMatches(item, tokens) {
103
- const label = item.label.toLowerCase();
104
- return tokens.every((token) => label.includes(token));
105
- }
106
- function filterNavItems(items, query) {
107
- const tokens = searchTokens(query);
108
- if (tokens.length === 0) return [...items];
109
- return filterByTokens(items, tokens);
110
- }
111
- function filterByTokens(items, tokens) {
112
- const kept = [];
113
- for (const item of items) {
114
- const selfMatch = labelMatches(item, tokens);
115
- const children = item.children ?? [];
116
- if (selfMatch) {
117
- kept.push(item);
118
- continue;
119
- }
120
- if (children.length === 0) continue;
121
- const prunedChildren = filterByTokens(children, tokens);
122
- if (prunedChildren.length > 0) kept.push({ ...item, children: prunedChildren });
123
- }
124
- return kept;
125
- }
126
- function isFilterActive(query) {
127
- return searchTokens(query).length > 0;
128
- }
129
-
130
- // src/isRouteActive.ts
131
- function isRouteActive(pathname, route, exact = false) {
132
- if (exact) return pathname === route;
133
- if (route === "/") return pathname === "/";
134
- return pathname === route || pathname.startsWith(`${route}/`);
135
- }
136
- function leafRoutes(items) {
137
- return items.flatMap((item) => {
138
- const children = item.children ?? [];
139
- const isGroup = children.length > 0;
140
- return isGroup ? leafRoutes(children) : [{ route: item.route, exact: item.exact === true }];
141
- });
142
- }
143
- function resolveActiveRoute(items, pathname) {
144
- let winner;
145
- let winnerLength = -1;
146
- for (const leaf of leafRoutes(items)) {
147
- const matches = isRouteActive(pathname, leaf.route, leaf.exact);
148
- const isLonger = leaf.route.length > winnerLength;
149
- if (matches && isLonger) {
150
- winner = leaf.route;
151
- winnerLength = leaf.route.length;
152
- }
153
- }
154
- return winner;
155
- }
16
+ var MIN_TOUCH_TARGET = 44;
156
17
  var ACTIVE_BORDER_RADIUS = 4;
157
18
  var ACTIVE_ACCENT_WIDTH = 3;
158
19
  var NAV_ROW_RADIUS = 8;
@@ -215,7 +76,15 @@ var navStyles = reactNative.StyleSheet.create({
215
76
  userBlock: { marginHorizontal: 12, alignItems: "flex-end" },
216
77
  userName: { fontWeight: "600" },
217
78
  userEmail: { fontSize: 12 },
218
- accountBtn: { marginLeft: 8, paddingHorizontal: 10, paddingVertical: 6, borderRadius: 4 },
79
+ accountBtn: {
80
+ marginLeft: 8,
81
+ paddingHorizontal: 10,
82
+ paddingVertical: 6,
83
+ borderRadius: 4,
84
+ minHeight: MIN_TOUCH_TARGET,
85
+ minWidth: MIN_TOUCH_TARGET,
86
+ justifyContent: "center"
87
+ },
219
88
  accountText: { fontWeight: "600" },
220
89
  // --- Rich account-state header (Move 1c) ---
221
90
  accountTenant: { fontSize: 12 },
@@ -251,8 +120,8 @@ var navBarStyles = reactNative.StyleSheet.create({
251
120
  paddingVertical: 6,
252
121
  borderRadius: 4,
253
122
  // a11y: keep the hamburger a comfortable ≥44×44 touch target.
254
- minWidth: 44,
255
- minHeight: 44,
123
+ minWidth: MIN_TOUCH_TARGET,
124
+ minHeight: MIN_TOUCH_TARGET,
256
125
  alignItems: "center",
257
126
  justifyContent: "center"
258
127
  },
@@ -294,7 +163,7 @@ var navBarStyles = reactNative.StyleSheet.create({
294
163
  flexDirection: "row",
295
164
  alignItems: "center",
296
165
  // a11y: comfortable ≥44 tall touch target (rounded-pill hover/active affordance).
297
- minHeight: 44,
166
+ minHeight: MIN_TOUCH_TARGET,
298
167
  justifyContent: "center"
299
168
  },
300
169
  linkStacked: { paddingVertical: 10 },
@@ -330,7 +199,7 @@ var pillNavStyles = reactNative.StyleSheet.create({
330
199
  paddingHorizontal: 16,
331
200
  paddingVertical: 8,
332
201
  borderRadius: 999,
333
- minHeight: 36,
202
+ minHeight: MIN_TOUCH_TARGET,
334
203
  flexDirection: "row",
335
204
  alignItems: "center",
336
205
  columnGap: 6,
@@ -351,7 +220,8 @@ var darkModeStyles = reactNative.StyleSheet.create({
351
220
  segment: {
352
221
  paddingHorizontal: 12,
353
222
  paddingVertical: 8,
354
- minHeight: 36,
223
+ minHeight: MIN_TOUCH_TARGET,
224
+ minWidth: MIN_TOUCH_TARGET,
355
225
  flexDirection: "row",
356
226
  alignItems: "center",
357
227
  columnGap: 6,
@@ -362,8 +232,8 @@ var darkModeStyles = reactNative.StyleSheet.create({
362
232
  cycle: {
363
233
  paddingHorizontal: 12,
364
234
  paddingVertical: 8,
365
- minHeight: 44,
366
- minWidth: 44,
235
+ minHeight: MIN_TOUCH_TARGET,
236
+ minWidth: MIN_TOUCH_TARGET,
367
237
  borderRadius: 8,
368
238
  flexDirection: "row",
369
239
  alignItems: "center",
@@ -408,6 +278,7 @@ var expandableStyles = reactNative.StyleSheet.create({
408
278
  flexDirection: "row",
409
279
  alignItems: "center",
410
280
  paddingVertical: 9,
281
+ minHeight: MIN_TOUCH_TARGET,
411
282
  borderLeftWidth: ACTIVE_ACCENT_WIDTH,
412
283
  borderLeftColor: "transparent"
413
284
  },
@@ -435,7 +306,8 @@ var expandableStyles = reactNative.StyleSheet.create({
435
306
  borderRadius: NAV_ROW_RADIUS,
436
307
  flexDirection: "row",
437
308
  alignItems: "center",
438
- paddingVertical: 8
309
+ paddingVertical: 8,
310
+ minHeight: MIN_TOUCH_TARGET
439
311
  },
440
312
  // Depth-0 module groups render as docs-style SECTION HEADERS: extra top rhythm
441
313
  // to separate one module from the next.
@@ -455,6 +327,145 @@ var expandableStyles = reactNative.StyleSheet.create({
455
327
  var BASE_INDENT = 12;
456
328
  var NAV_ICON_SIZE = 14;
457
329
  var CHEVRON_ICON_SIZE = 12;
330
+ var IS_WEB = reactNative.Platform.OS === "web";
331
+ var FOCUS_RING_WIDTH = 2;
332
+ var FOCUS_RING_OFFSET = 2;
333
+ var HOVER_TRANSITION_MS = 150;
334
+ var TINT_TRANSITION_MS = 160;
335
+ function focusRingStyle(focused, ringColor) {
336
+ if (!IS_WEB || !focused) return void 0;
337
+ const ring = {
338
+ outlineWidth: FOCUS_RING_WIDTH,
339
+ outlineStyle: "solid",
340
+ outlineColor: ringColor,
341
+ outlineOffset: FOCUS_RING_OFFSET
342
+ };
343
+ return ring;
344
+ }
345
+ function webTransition(properties, durationMs, reducedMotion) {
346
+ if (!IS_WEB) return void 0;
347
+ const transition = {
348
+ transitionProperty: properties,
349
+ transitionDuration: reducedMotion ? "0ms" : `${durationMs}ms`
350
+ };
351
+ return transition;
352
+ }
353
+ function hoverTransitionStyle(reducedMotion) {
354
+ return webTransition("color, background-color", HOVER_TRANSITION_MS, reducedMotion);
355
+ }
356
+ function tintTransitionStyle(reducedMotion) {
357
+ return webTransition("opacity", TINT_TRANSITION_MS, reducedMotion);
358
+ }
359
+ function rotateTransitionStyle(reducedMotion) {
360
+ return webTransition("transform", TINT_TRANSITION_MS, reducedMotion);
361
+ }
362
+ var styles = reactNative.StyleSheet.create({
363
+ trigger: {
364
+ flexDirection: "row",
365
+ alignItems: "center",
366
+ justifyContent: "space-between",
367
+ columnGap: 8,
368
+ paddingHorizontal: 12,
369
+ minHeight: MIN_TOUCH_TARGET,
370
+ borderWidth: 1,
371
+ borderRadius: 8
372
+ },
373
+ label: { fontSize: 14 },
374
+ badge: { paddingHorizontal: 6, paddingVertical: 2, borderRadius: 4, borderWidth: 1 },
375
+ badgeText: { fontSize: 11, fontWeight: "700" }
376
+ });
377
+ var CommandPaletteTrigger = ({
378
+ label,
379
+ hint,
380
+ shortcut,
381
+ onPress,
382
+ testID
383
+ }) => {
384
+ const { theme } = uiFeedback.useUi();
385
+ const colors = theme.colors;
386
+ const primary = theme.palette.primary["500"];
387
+ const [focused, setFocused] = React__default.default.useState(false);
388
+ return /* @__PURE__ */ jsxRuntime.jsxs(
389
+ reactNative.Pressable,
390
+ {
391
+ accessibilityHint: hint,
392
+ accessibilityLabel: label,
393
+ accessibilityRole: "button",
394
+ style: [
395
+ styles.trigger,
396
+ { backgroundColor: colors.surface, borderColor: colors.border },
397
+ focusRingStyle(focused, primary)
398
+ ],
399
+ testID,
400
+ onBlur: () => setFocused(false),
401
+ onFocus: () => setFocused(true),
402
+ onPress,
403
+ children: [
404
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.label, { color: colors.textSecondary }], children: label }),
405
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles.badge, { borderColor: colors.border }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.badgeText, { color: colors.textSecondary }], children: shortcut }) })
406
+ ]
407
+ }
408
+ );
409
+ };
410
+
411
+ // src/sidebarFilter.ts
412
+ function searchTokens(query) {
413
+ return query.trim().toLowerCase().split(/\s+/).filter(Boolean);
414
+ }
415
+ function labelMatches(item, tokens) {
416
+ const label = item.label.toLowerCase();
417
+ return tokens.every((token) => label.includes(token));
418
+ }
419
+ function filterNavItems(items, query) {
420
+ const tokens = searchTokens(query);
421
+ if (tokens.length === 0) return [...items];
422
+ return filterByTokens(items, tokens);
423
+ }
424
+ function filterByTokens(items, tokens) {
425
+ const kept = [];
426
+ for (const item of items) {
427
+ const selfMatch = labelMatches(item, tokens);
428
+ const children = item.children ?? [];
429
+ if (selfMatch) {
430
+ kept.push(item);
431
+ continue;
432
+ }
433
+ if (children.length === 0) continue;
434
+ const prunedChildren = filterByTokens(children, tokens);
435
+ if (prunedChildren.length > 0) kept.push({ ...item, children: prunedChildren });
436
+ }
437
+ return kept;
438
+ }
439
+ function isFilterActive(query) {
440
+ return searchTokens(query).length > 0;
441
+ }
442
+
443
+ // src/isRouteActive.ts
444
+ function isRouteActive(pathname, route, exact = false) {
445
+ if (exact) return pathname === route;
446
+ if (route === "/") return pathname === "/";
447
+ return pathname === route || pathname.startsWith(`${route}/`);
448
+ }
449
+ function leafRoutes(items) {
450
+ return items.flatMap((item) => {
451
+ const children = item.children ?? [];
452
+ const isGroup = children.length > 0;
453
+ return isGroup ? leafRoutes(children) : [{ route: item.route, exact: item.exact === true }];
454
+ });
455
+ }
456
+ function resolveActiveRoute(items, pathname) {
457
+ let winner;
458
+ let winnerLength = -1;
459
+ for (const leaf of leafRoutes(items)) {
460
+ const matches = isRouteActive(pathname, leaf.route, leaf.exact);
461
+ const isLonger = leaf.route.length > winnerLength;
462
+ if (matches && isLonger) {
463
+ winner = leaf.route;
464
+ winnerLength = leaf.route.length;
465
+ }
466
+ }
467
+ return winner;
468
+ }
458
469
  var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
459
470
  function getReducedMotionQuery() {
460
471
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return void 0;
@@ -646,15 +657,12 @@ var NavExpandableItem = ({
646
657
  )) }) })
647
658
  ] });
648
659
  };
649
-
650
- // src/searchAffordance.ts
651
- var DEFAULT_SEARCH_BREAKPOINT = 768;
660
+ var DEFAULT_SEARCH_BREAKPOINT = uiLayout.LAYOUT_COLLAPSE_BREAKPOINT;
652
661
  function resolveSearchAffordance(viewport, breakpoint = DEFAULT_SEARCH_BREAKPOINT) {
653
662
  return viewport >= breakpoint ? "inline" : "palette";
654
663
  }
655
664
  var FIELD_MIN_HEIGHT = 38;
656
665
  var CLEAR_GLYPH = "\u2715";
657
- var CLEAR_MIN_TARGET = 28;
658
666
  var styles2 = reactNative.StyleSheet.create({
659
667
  wrap: {
660
668
  flexDirection: "row",
@@ -672,8 +680,8 @@ var styles2 = reactNative.StyleSheet.create({
672
680
  minHeight: FIELD_MIN_HEIGHT
673
681
  },
674
682
  clear: {
675
- minWidth: CLEAR_MIN_TARGET,
676
- minHeight: CLEAR_MIN_TARGET,
683
+ minWidth: MIN_TOUCH_TARGET,
684
+ minHeight: MIN_TOUCH_TARGET,
677
685
  alignItems: "center",
678
686
  justifyContent: "center",
679
687
  borderRadius: 6
@@ -1403,7 +1411,6 @@ function useContentBody(state, children, testID) {
1403
1411
  }
1404
1412
  var SCRIM_COLOR = "rgba(0, 0, 0, 0.5)";
1405
1413
  var MENU_GLYPH2 = "\u2630";
1406
- var MENU_MIN_TARGET = 44;
1407
1414
  var MENU_GLYPH_FONT_SIZE = 20;
1408
1415
  var MENU_TOGGLE_PADDING = 12;
1409
1416
  var DRAWER_Z_INDEX = 50;
@@ -1441,8 +1448,8 @@ var styles4 = reactNative.StyleSheet.create({
1441
1448
  // and receive presses instead of the scrim swallowing them.
1442
1449
  panel: { position: "absolute", top: 0, bottom: 0, left: 0, width: DRAWER_WIDTH, zIndex: PANEL_Z_INDEX },
1443
1450
  menuToggle: {
1444
- minWidth: MENU_MIN_TARGET,
1445
- minHeight: MENU_MIN_TARGET,
1451
+ minWidth: MIN_TOUCH_TARGET,
1452
+ minHeight: MIN_TOUCH_TARGET,
1446
1453
  alignItems: "center",
1447
1454
  justifyContent: "center",
1448
1455
  paddingHorizontal: MENU_TOGGLE_PADDING
@@ -1511,9 +1518,7 @@ var MobileDrawer = ({
1511
1518
  )
1512
1519
  ] });
1513
1520
  };
1514
-
1515
- // src/railMode.ts
1516
- var RAIL_FULL_BREAKPOINT = 768;
1521
+ var RAIL_FULL_BREAKPOINT = uiLayout.LAYOUT_COLLAPSE_BREAKPOINT;
1517
1522
  var DEFAULT_COLLAPSED_RAIL_MAX = 1024;
1518
1523
  function resolveRailMode({ viewport, hasSidebar, hasCollapsed, range }) {
1519
1524
  if (!hasSidebar) return "none";