@dloizides/ui-nav 1.21.0 → 1.23.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 +12 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +216 -160
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +217 -161
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState, useCallback, useMemo, useEffect, useRef } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { StyleSheet, Platform, Pressable, Text, View, TextInput, useWindowDimensions, ScrollView, ActivityIndicator } from 'react-native';
|
|
3
3
|
import { useUi, UiProvider } from '@dloizides/ui-feedback';
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
5
|
import { Collapse } from '@dloizides/ui-motion';
|
|
@@ -7,146 +7,7 @@ import { LAYOUT_COLLAPSE_BREAKPOINT, ModalDropdown } from '@dloizides/ui-layout'
|
|
|
7
7
|
import { resolveAccessibleRoutes } from '@dloizides/auth-web';
|
|
8
8
|
|
|
9
9
|
// src/Sidebar.tsx
|
|
10
|
-
var
|
|
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
|
-
};
|
|
91
|
-
|
|
92
|
-
// src/sidebarFilter.ts
|
|
93
|
-
function searchTokens(query) {
|
|
94
|
-
return query.trim().toLowerCase().split(/\s+/).filter(Boolean);
|
|
95
|
-
}
|
|
96
|
-
function labelMatches(item, tokens) {
|
|
97
|
-
const label = item.label.toLowerCase();
|
|
98
|
-
return tokens.every((token) => label.includes(token));
|
|
99
|
-
}
|
|
100
|
-
function filterNavItems(items, query) {
|
|
101
|
-
const tokens = searchTokens(query);
|
|
102
|
-
if (tokens.length === 0) return [...items];
|
|
103
|
-
return filterByTokens(items, tokens);
|
|
104
|
-
}
|
|
105
|
-
function filterByTokens(items, tokens) {
|
|
106
|
-
const kept = [];
|
|
107
|
-
for (const item of items) {
|
|
108
|
-
const selfMatch = labelMatches(item, tokens);
|
|
109
|
-
const children = item.children ?? [];
|
|
110
|
-
if (selfMatch) {
|
|
111
|
-
kept.push(item);
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
if (children.length === 0) continue;
|
|
115
|
-
const prunedChildren = filterByTokens(children, tokens);
|
|
116
|
-
if (prunedChildren.length > 0) kept.push({ ...item, children: prunedChildren });
|
|
117
|
-
}
|
|
118
|
-
return kept;
|
|
119
|
-
}
|
|
120
|
-
function isFilterActive(query) {
|
|
121
|
-
return searchTokens(query).length > 0;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// src/isRouteActive.ts
|
|
125
|
-
function isRouteActive(pathname, route, exact = false) {
|
|
126
|
-
if (exact) return pathname === route;
|
|
127
|
-
if (route === "/") return pathname === "/";
|
|
128
|
-
return pathname === route || pathname.startsWith(`${route}/`);
|
|
129
|
-
}
|
|
130
|
-
function leafRoutes(items) {
|
|
131
|
-
return items.flatMap((item) => {
|
|
132
|
-
const children = item.children ?? [];
|
|
133
|
-
const isGroup = children.length > 0;
|
|
134
|
-
return isGroup ? leafRoutes(children) : [{ route: item.route, exact: item.exact === true }];
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
function resolveActiveRoute(items, pathname) {
|
|
138
|
-
let winner;
|
|
139
|
-
let winnerLength = -1;
|
|
140
|
-
for (const leaf of leafRoutes(items)) {
|
|
141
|
-
const matches = isRouteActive(pathname, leaf.route, leaf.exact);
|
|
142
|
-
const isLonger = leaf.route.length > winnerLength;
|
|
143
|
-
if (matches && isLonger) {
|
|
144
|
-
winner = leaf.route;
|
|
145
|
-
winnerLength = leaf.route.length;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
return winner;
|
|
149
|
-
}
|
|
10
|
+
var MIN_TOUCH_TARGET = 44;
|
|
150
11
|
var ACTIVE_BORDER_RADIUS = 4;
|
|
151
12
|
var ACTIVE_ACCENT_WIDTH = 3;
|
|
152
13
|
var NAV_ROW_RADIUS = 8;
|
|
@@ -209,7 +70,15 @@ var navStyles = StyleSheet.create({
|
|
|
209
70
|
userBlock: { marginHorizontal: 12, alignItems: "flex-end" },
|
|
210
71
|
userName: { fontWeight: "600" },
|
|
211
72
|
userEmail: { fontSize: 12 },
|
|
212
|
-
accountBtn: {
|
|
73
|
+
accountBtn: {
|
|
74
|
+
marginLeft: 8,
|
|
75
|
+
paddingHorizontal: 10,
|
|
76
|
+
paddingVertical: 6,
|
|
77
|
+
borderRadius: 4,
|
|
78
|
+
minHeight: MIN_TOUCH_TARGET,
|
|
79
|
+
minWidth: MIN_TOUCH_TARGET,
|
|
80
|
+
justifyContent: "center"
|
|
81
|
+
},
|
|
213
82
|
accountText: { fontWeight: "600" },
|
|
214
83
|
// --- Rich account-state header (Move 1c) ---
|
|
215
84
|
accountTenant: { fontSize: 12 },
|
|
@@ -245,8 +114,8 @@ var navBarStyles = StyleSheet.create({
|
|
|
245
114
|
paddingVertical: 6,
|
|
246
115
|
borderRadius: 4,
|
|
247
116
|
// a11y: keep the hamburger a comfortable ≥44×44 touch target.
|
|
248
|
-
minWidth:
|
|
249
|
-
minHeight:
|
|
117
|
+
minWidth: MIN_TOUCH_TARGET,
|
|
118
|
+
minHeight: MIN_TOUCH_TARGET,
|
|
250
119
|
alignItems: "center",
|
|
251
120
|
justifyContent: "center"
|
|
252
121
|
},
|
|
@@ -273,13 +142,19 @@ var navBarStyles = StyleSheet.create({
|
|
|
273
142
|
overflowChevron: { fontSize: 12, fontWeight: "700" },
|
|
274
143
|
// Collapsed (below breakpoint): links drop onto their own full-width line,
|
|
275
144
|
// stacked vertically — mirrors the v1 `.gn-links` responsive behaviour.
|
|
145
|
+
// SHOWCASE-1: this is a ScrollView — `maxHeight` (viewport minus bar) is applied at render time,
|
|
146
|
+
// so a long menu scrolls within the viewport instead of running off a body:overflow:hidden page.
|
|
276
147
|
linksStacked: {
|
|
277
148
|
width: "100%",
|
|
278
149
|
flexBasis: "100%",
|
|
150
|
+
flexGrow: 0,
|
|
151
|
+
flexShrink: 0,
|
|
152
|
+
marginTop: 8
|
|
153
|
+
},
|
|
154
|
+
linksStackedContent: {
|
|
279
155
|
flexDirection: "column",
|
|
280
156
|
alignItems: "stretch",
|
|
281
|
-
rowGap: 2
|
|
282
|
-
marginTop: 8
|
|
157
|
+
rowGap: 2
|
|
283
158
|
},
|
|
284
159
|
link: {
|
|
285
160
|
paddingVertical: 8,
|
|
@@ -288,7 +163,7 @@ var navBarStyles = StyleSheet.create({
|
|
|
288
163
|
flexDirection: "row",
|
|
289
164
|
alignItems: "center",
|
|
290
165
|
// a11y: comfortable ≥44 tall touch target (rounded-pill hover/active affordance).
|
|
291
|
-
minHeight:
|
|
166
|
+
minHeight: MIN_TOUCH_TARGET,
|
|
292
167
|
justifyContent: "center"
|
|
293
168
|
},
|
|
294
169
|
linkStacked: { paddingVertical: 10 },
|
|
@@ -324,7 +199,7 @@ var pillNavStyles = StyleSheet.create({
|
|
|
324
199
|
paddingHorizontal: 16,
|
|
325
200
|
paddingVertical: 8,
|
|
326
201
|
borderRadius: 999,
|
|
327
|
-
minHeight:
|
|
202
|
+
minHeight: MIN_TOUCH_TARGET,
|
|
328
203
|
flexDirection: "row",
|
|
329
204
|
alignItems: "center",
|
|
330
205
|
columnGap: 6,
|
|
@@ -345,7 +220,8 @@ var darkModeStyles = StyleSheet.create({
|
|
|
345
220
|
segment: {
|
|
346
221
|
paddingHorizontal: 12,
|
|
347
222
|
paddingVertical: 8,
|
|
348
|
-
minHeight:
|
|
223
|
+
minHeight: MIN_TOUCH_TARGET,
|
|
224
|
+
minWidth: MIN_TOUCH_TARGET,
|
|
349
225
|
flexDirection: "row",
|
|
350
226
|
alignItems: "center",
|
|
351
227
|
columnGap: 6,
|
|
@@ -356,8 +232,8 @@ var darkModeStyles = StyleSheet.create({
|
|
|
356
232
|
cycle: {
|
|
357
233
|
paddingHorizontal: 12,
|
|
358
234
|
paddingVertical: 8,
|
|
359
|
-
minHeight:
|
|
360
|
-
minWidth:
|
|
235
|
+
minHeight: MIN_TOUCH_TARGET,
|
|
236
|
+
minWidth: MIN_TOUCH_TARGET,
|
|
361
237
|
borderRadius: 8,
|
|
362
238
|
flexDirection: "row",
|
|
363
239
|
alignItems: "center",
|
|
@@ -402,6 +278,7 @@ var expandableStyles = StyleSheet.create({
|
|
|
402
278
|
flexDirection: "row",
|
|
403
279
|
alignItems: "center",
|
|
404
280
|
paddingVertical: 9,
|
|
281
|
+
minHeight: MIN_TOUCH_TARGET,
|
|
405
282
|
borderLeftWidth: ACTIVE_ACCENT_WIDTH,
|
|
406
283
|
borderLeftColor: "transparent"
|
|
407
284
|
},
|
|
@@ -429,7 +306,8 @@ var expandableStyles = StyleSheet.create({
|
|
|
429
306
|
borderRadius: NAV_ROW_RADIUS,
|
|
430
307
|
flexDirection: "row",
|
|
431
308
|
alignItems: "center",
|
|
432
|
-
paddingVertical: 8
|
|
309
|
+
paddingVertical: 8,
|
|
310
|
+
minHeight: MIN_TOUCH_TARGET
|
|
433
311
|
},
|
|
434
312
|
// Depth-0 module groups render as docs-style SECTION HEADERS: extra top rhythm
|
|
435
313
|
// to separate one module from the next.
|
|
@@ -449,6 +327,145 @@ var expandableStyles = StyleSheet.create({
|
|
|
449
327
|
var BASE_INDENT = 12;
|
|
450
328
|
var NAV_ICON_SIZE = 14;
|
|
451
329
|
var CHEVRON_ICON_SIZE = 12;
|
|
330
|
+
var IS_WEB = 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 = 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 } = useUi();
|
|
385
|
+
const colors = theme.colors;
|
|
386
|
+
const primary = theme.palette.primary["500"];
|
|
387
|
+
const [focused, setFocused] = React.useState(false);
|
|
388
|
+
return /* @__PURE__ */ jsxs(
|
|
389
|
+
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__ */ jsx(Text, { style: [styles.label, { color: colors.textSecondary }], children: label }),
|
|
405
|
+
/* @__PURE__ */ jsx(View, { style: [styles.badge, { borderColor: colors.border }], children: /* @__PURE__ */ jsx(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
|
+
}
|
|
452
469
|
var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
453
470
|
function getReducedMotionQuery() {
|
|
454
471
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return void 0;
|
|
@@ -646,7 +663,6 @@ function resolveSearchAffordance(viewport, breakpoint = DEFAULT_SEARCH_BREAKPOIN
|
|
|
646
663
|
}
|
|
647
664
|
var FIELD_MIN_HEIGHT = 38;
|
|
648
665
|
var CLEAR_GLYPH = "\u2715";
|
|
649
|
-
var CLEAR_MIN_TARGET = 28;
|
|
650
666
|
var styles2 = StyleSheet.create({
|
|
651
667
|
wrap: {
|
|
652
668
|
flexDirection: "row",
|
|
@@ -664,8 +680,8 @@ var styles2 = StyleSheet.create({
|
|
|
664
680
|
minHeight: FIELD_MIN_HEIGHT
|
|
665
681
|
},
|
|
666
682
|
clear: {
|
|
667
|
-
minWidth:
|
|
668
|
-
minHeight:
|
|
683
|
+
minWidth: MIN_TOUCH_TARGET,
|
|
684
|
+
minHeight: MIN_TOUCH_TARGET,
|
|
669
685
|
alignItems: "center",
|
|
670
686
|
justifyContent: "center",
|
|
671
687
|
borderRadius: 6
|
|
@@ -1168,9 +1184,24 @@ function useNavOverflow(itemCount, gap) {
|
|
|
1168
1184
|
);
|
|
1169
1185
|
return { visibleCount, setAvailableWidth, setItemWidth, setMoreWidth };
|
|
1170
1186
|
}
|
|
1187
|
+
|
|
1188
|
+
// src/stackedMenuMaxHeight.ts
|
|
1189
|
+
var DEFAULT_BAR_HEIGHT = 64;
|
|
1190
|
+
var MIN_STACKED_MENU_HEIGHT = 3 * 44;
|
|
1191
|
+
function computeStackedMenuMaxHeight({
|
|
1192
|
+
windowHeight,
|
|
1193
|
+
barHeight,
|
|
1194
|
+
reservedBelow
|
|
1195
|
+
}) {
|
|
1196
|
+
const bar = barHeight > 0 ? barHeight : DEFAULT_BAR_HEIGHT;
|
|
1197
|
+
const reserved = Math.max(0, reservedBelow);
|
|
1198
|
+
return Math.max(MIN_STACKED_MENU_HEIGHT, windowHeight - bar - reserved);
|
|
1199
|
+
}
|
|
1171
1200
|
var LINKS_REGION_ID = "navbar-links-region";
|
|
1172
1201
|
var DEFAULT_COLLAPSE_BELOW = 760;
|
|
1173
1202
|
var MENU_GLYPH = "\u2630";
|
|
1203
|
+
var STACKED_MENU_CHROME = 12;
|
|
1204
|
+
var STACKED_RIGHT_CHROME = 8;
|
|
1174
1205
|
function ariaControlsProps(id) {
|
|
1175
1206
|
return { "aria-controls": id };
|
|
1176
1207
|
}
|
|
@@ -1194,13 +1225,22 @@ var NavBarInner = ({
|
|
|
1194
1225
|
const { theme } = useUi();
|
|
1195
1226
|
const colors = theme.colors;
|
|
1196
1227
|
const primaryColor = theme.palette.primary["500"];
|
|
1197
|
-
const { width } = useWindowDimensions();
|
|
1228
|
+
const { width, height } = useWindowDimensions();
|
|
1198
1229
|
const reducedMotion = useReducedMotion();
|
|
1199
1230
|
const [open, setOpen] = useState(false);
|
|
1200
1231
|
const [toggleFocused, setToggleFocused] = useState(false);
|
|
1201
1232
|
const { visibleCount, setAvailableWidth, setItemWidth, setMoreWidth } = useNavOverflow(items.length, NAV_LINK_GAP);
|
|
1202
1233
|
const collapsed = width < collapseBelow;
|
|
1203
1234
|
const showLinks = !collapsed || open;
|
|
1235
|
+
const [barHeight, setBarHeight] = useState(0);
|
|
1236
|
+
const [rightHeight, setRightHeight] = useState(0);
|
|
1237
|
+
const hasRight = right !== void 0;
|
|
1238
|
+
const stackedMaxHeight = computeStackedMenuMaxHeight({
|
|
1239
|
+
windowHeight: height,
|
|
1240
|
+
barHeight,
|
|
1241
|
+
reservedBelow: STACKED_MENU_CHROME + (hasRight ? STACKED_RIGHT_CHROME + rightHeight : 0)
|
|
1242
|
+
});
|
|
1243
|
+
const measureBar = collapsed && !open;
|
|
1204
1244
|
const innerCapStyle = useMemo(
|
|
1205
1245
|
() => contentMaxWidth === void 0 ? null : { maxWidth: contentMaxWidth, width: "100%", alignSelf: "center" },
|
|
1206
1246
|
[contentMaxWidth]
|
|
@@ -1235,6 +1275,7 @@ var NavBarInner = ({
|
|
|
1235
1275
|
{ backgroundColor: colors.surface, borderBottomColor: colors.border },
|
|
1236
1276
|
containerStyle
|
|
1237
1277
|
],
|
|
1278
|
+
onLayout: measureBar ? (event) => setBarHeight(event.nativeEvent.layout.height) : void 0,
|
|
1238
1279
|
children: /* @__PURE__ */ jsxs(View, { style: [navBarStyles.inner, collapsed ? null : navBarStyles.innerNoWrap, innerCapStyle], children: [
|
|
1239
1280
|
brand !== void 0 ? /* @__PURE__ */ jsx(View, { style: navBarStyles.brand, children: renderTextSlot(brand, { color: colors.text }) }) : null,
|
|
1240
1281
|
collapsed ? /* @__PURE__ */ jsx(
|
|
@@ -1269,7 +1310,16 @@ var NavBarInner = ({
|
|
|
1269
1310
|
}
|
|
1270
1311
|
);
|
|
1271
1312
|
if (collapsed) {
|
|
1272
|
-
return /* @__PURE__ */ jsx(
|
|
1313
|
+
return /* @__PURE__ */ jsx(
|
|
1314
|
+
ScrollView,
|
|
1315
|
+
{
|
|
1316
|
+
contentContainerStyle: navBarStyles.linksStackedContent,
|
|
1317
|
+
nativeID: LINKS_REGION_ID,
|
|
1318
|
+
style: [navBarStyles.linksStacked, { maxHeight: stackedMaxHeight }],
|
|
1319
|
+
testID: NAV_TEST_IDS.navBarLinks,
|
|
1320
|
+
children: items.map((item) => /* @__PURE__ */ jsx(React.Fragment, { children: renderLink(item) }, item.key))
|
|
1321
|
+
}
|
|
1322
|
+
);
|
|
1273
1323
|
}
|
|
1274
1324
|
const visibleItems = items.slice(0, visibleCount);
|
|
1275
1325
|
const overflowItems = items.slice(visibleCount);
|
|
@@ -1313,7 +1363,14 @@ var NavBarInner = ({
|
|
|
1313
1363
|
}
|
|
1314
1364
|
);
|
|
1315
1365
|
})() : null,
|
|
1316
|
-
showLinks &&
|
|
1366
|
+
showLinks && hasRight ? /* @__PURE__ */ jsx(
|
|
1367
|
+
View,
|
|
1368
|
+
{
|
|
1369
|
+
style: collapsed ? navBarStyles.rightStacked : navBarStyles.right,
|
|
1370
|
+
onLayout: collapsed ? (event) => setRightHeight(event.nativeEvent.layout.height) : void 0,
|
|
1371
|
+
children: renderTextSlot(right, { color: colors.text })
|
|
1372
|
+
}
|
|
1373
|
+
) : null
|
|
1317
1374
|
] })
|
|
1318
1375
|
}
|
|
1319
1376
|
);
|
|
@@ -1395,7 +1452,6 @@ function useContentBody(state, children, testID) {
|
|
|
1395
1452
|
}
|
|
1396
1453
|
var SCRIM_COLOR = "rgba(0, 0, 0, 0.5)";
|
|
1397
1454
|
var MENU_GLYPH2 = "\u2630";
|
|
1398
|
-
var MENU_MIN_TARGET = 44;
|
|
1399
1455
|
var MENU_GLYPH_FONT_SIZE = 20;
|
|
1400
1456
|
var MENU_TOGGLE_PADDING = 12;
|
|
1401
1457
|
var DRAWER_Z_INDEX = 50;
|
|
@@ -1433,8 +1489,8 @@ var styles4 = StyleSheet.create({
|
|
|
1433
1489
|
// and receive presses instead of the scrim swallowing them.
|
|
1434
1490
|
panel: { position: "absolute", top: 0, bottom: 0, left: 0, width: DRAWER_WIDTH, zIndex: PANEL_Z_INDEX },
|
|
1435
1491
|
menuToggle: {
|
|
1436
|
-
minWidth:
|
|
1437
|
-
minHeight:
|
|
1492
|
+
minWidth: MIN_TOUCH_TARGET,
|
|
1493
|
+
minHeight: MIN_TOUCH_TARGET,
|
|
1438
1494
|
alignItems: "center",
|
|
1439
1495
|
justifyContent: "center",
|
|
1440
1496
|
paddingHorizontal: MENU_TOGGLE_PADDING
|