@dloizides/ui-nav 1.7.0 → 1.9.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/ADOPTION.md +83 -0
- package/CHANGELOG.md +73 -0
- package/README.md +97 -0
- package/dist/index.d.mts +550 -79
- package/dist/index.d.ts +550 -79
- package/dist/index.js +445 -71
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +438 -74
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StyleSheet, Platform, TouchableOpacity, View, Text, useWindowDimensions,
|
|
2
|
-
import { useUi } from '@dloizides/ui-feedback';
|
|
1
|
+
import { StyleSheet, Platform, TouchableOpacity, View, Text, useWindowDimensions, ActivityIndicator, ScrollView, Pressable } from 'react-native';
|
|
2
|
+
import { useUi, UiProvider } from '@dloizides/ui-feedback';
|
|
3
3
|
import React5, { useState, useCallback, useMemo, useEffect, useRef } from 'react';
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
5
|
import { ModalDropdown } from '@dloizides/ui-layout';
|
|
@@ -155,6 +155,86 @@ var navBarStyles = StyleSheet.create({
|
|
|
155
155
|
columnGap: 8
|
|
156
156
|
}
|
|
157
157
|
});
|
|
158
|
+
var pillNavStyles = StyleSheet.create({
|
|
159
|
+
// Cross-nav pill row (kefi coral dashboard switcher): fully-rounded pills, wraps.
|
|
160
|
+
container: {
|
|
161
|
+
flexDirection: "row",
|
|
162
|
+
flexWrap: "wrap",
|
|
163
|
+
alignItems: "center",
|
|
164
|
+
columnGap: 8,
|
|
165
|
+
rowGap: 8,
|
|
166
|
+
paddingVertical: 8
|
|
167
|
+
},
|
|
168
|
+
pill: {
|
|
169
|
+
paddingHorizontal: 16,
|
|
170
|
+
paddingVertical: 8,
|
|
171
|
+
borderRadius: 999,
|
|
172
|
+
minHeight: 36,
|
|
173
|
+
flexDirection: "row",
|
|
174
|
+
alignItems: "center",
|
|
175
|
+
columnGap: 6,
|
|
176
|
+
justifyContent: "center"
|
|
177
|
+
},
|
|
178
|
+
pillText: { fontSize: 14, fontWeight: "600" }
|
|
179
|
+
});
|
|
180
|
+
var darkModeStyles = StyleSheet.create({
|
|
181
|
+
// Segmented Light / Dark / System control.
|
|
182
|
+
segmentRow: {
|
|
183
|
+
flexDirection: "row",
|
|
184
|
+
alignItems: "center",
|
|
185
|
+
borderWidth: 1,
|
|
186
|
+
borderRadius: 8,
|
|
187
|
+
overflow: "hidden",
|
|
188
|
+
alignSelf: "flex-start"
|
|
189
|
+
},
|
|
190
|
+
segment: {
|
|
191
|
+
paddingHorizontal: 12,
|
|
192
|
+
paddingVertical: 8,
|
|
193
|
+
minHeight: 36,
|
|
194
|
+
flexDirection: "row",
|
|
195
|
+
alignItems: "center",
|
|
196
|
+
columnGap: 6,
|
|
197
|
+
justifyContent: "center"
|
|
198
|
+
},
|
|
199
|
+
segmentText: { fontSize: 13, fontWeight: "600" },
|
|
200
|
+
// Cycle-button variant.
|
|
201
|
+
cycle: {
|
|
202
|
+
paddingHorizontal: 12,
|
|
203
|
+
paddingVertical: 8,
|
|
204
|
+
minHeight: 44,
|
|
205
|
+
minWidth: 44,
|
|
206
|
+
borderRadius: 8,
|
|
207
|
+
flexDirection: "row",
|
|
208
|
+
alignItems: "center",
|
|
209
|
+
columnGap: 6,
|
|
210
|
+
justifyContent: "center"
|
|
211
|
+
},
|
|
212
|
+
cycleText: { fontSize: 13, fontWeight: "600" }
|
|
213
|
+
});
|
|
214
|
+
var collapsedRailStyles = StyleSheet.create({
|
|
215
|
+
// Intermediate (tablet) icon-only rail: a narrow vertical strip of icon buttons.
|
|
216
|
+
container: {
|
|
217
|
+
width: 64,
|
|
218
|
+
paddingTop: 16,
|
|
219
|
+
paddingHorizontal: 8,
|
|
220
|
+
borderRightWidth: 1,
|
|
221
|
+
height: "100%",
|
|
222
|
+
alignItems: "center"
|
|
223
|
+
},
|
|
224
|
+
// Each item is a ≥44×44 centred touch target with a rounded active/hover pill.
|
|
225
|
+
item: {
|
|
226
|
+
width: 48,
|
|
227
|
+
height: 48,
|
|
228
|
+
marginVertical: 4,
|
|
229
|
+
borderRadius: 8,
|
|
230
|
+
alignItems: "center",
|
|
231
|
+
justifyContent: "center"
|
|
232
|
+
},
|
|
233
|
+
// Glyph fallback (the label's first character) when an item has no renderIcon.
|
|
234
|
+
glyph: { fontSize: 18, fontWeight: "700" },
|
|
235
|
+
spacer: { flex: 1 },
|
|
236
|
+
slot: { alignItems: "center" }
|
|
237
|
+
});
|
|
158
238
|
var expandableStyles = StyleSheet.create({
|
|
159
239
|
childItem: {
|
|
160
240
|
borderRadius: 4,
|
|
@@ -371,6 +451,8 @@ var APP_SHELL_SUFFIX = {
|
|
|
371
451
|
nav: "-nav",
|
|
372
452
|
/** The persistent left rail of the back-office layout (only when `sidebar` is supplied). */
|
|
373
453
|
sidebar: "-sidebar",
|
|
454
|
+
/** The intermediate persistent COLLAPSED (icon-only) rail (3-tier layout, tablet band). */
|
|
455
|
+
collapsedSidebar: "-collapsed-sidebar",
|
|
374
456
|
/** Mobile hamburger that opens the nav drawer (back-office layout, below the breakpoint). */
|
|
375
457
|
menuToggle: "-menu-toggle",
|
|
376
458
|
/** The mobile nav drawer panel (holds the `sidebar` slot when opened on a narrow viewport). */
|
|
@@ -704,7 +786,7 @@ var MENU_GLYPH = "\u2630";
|
|
|
704
786
|
function ariaControlsProps(id) {
|
|
705
787
|
return { "aria-controls": id };
|
|
706
788
|
}
|
|
707
|
-
var
|
|
789
|
+
var NavBarInner = ({
|
|
708
790
|
items,
|
|
709
791
|
pathname,
|
|
710
792
|
onNavigate,
|
|
@@ -718,7 +800,8 @@ var NavBar = ({
|
|
|
718
800
|
collapseBelow = DEFAULT_COLLAPSE_BELOW,
|
|
719
801
|
overflowLabel = "More",
|
|
720
802
|
overflowHint = "",
|
|
721
|
-
containerStyle
|
|
803
|
+
containerStyle,
|
|
804
|
+
contentMaxWidth
|
|
722
805
|
}) => {
|
|
723
806
|
const { theme } = useUi();
|
|
724
807
|
const colors = theme.colors;
|
|
@@ -730,6 +813,10 @@ var NavBar = ({
|
|
|
730
813
|
const { visibleCount, setAvailableWidth, setItemWidth, setMoreWidth } = useNavOverflow(items.length, NAV_LINK_GAP);
|
|
731
814
|
const collapsed = width < collapseBelow;
|
|
732
815
|
const showLinks = !collapsed || open;
|
|
816
|
+
const innerCapStyle = useMemo(
|
|
817
|
+
() => contentMaxWidth === void 0 ? null : { maxWidth: contentMaxWidth, width: "100%", alignSelf: "center" },
|
|
818
|
+
[contentMaxWidth]
|
|
819
|
+
);
|
|
733
820
|
const toggleMenu = useCallback(() => setOpen((v) => !v), []);
|
|
734
821
|
const handlePress = useCallback(
|
|
735
822
|
(route) => {
|
|
@@ -759,7 +846,7 @@ var NavBar = ({
|
|
|
759
846
|
{ backgroundColor: colors.surface, borderBottomColor: colors.border },
|
|
760
847
|
containerStyle
|
|
761
848
|
],
|
|
762
|
-
children: /* @__PURE__ */ jsxs(View, { style: [navBarStyles.inner, collapsed ? null : navBarStyles.innerNoWrap], children: [
|
|
849
|
+
children: /* @__PURE__ */ jsxs(View, { style: [navBarStyles.inner, collapsed ? null : navBarStyles.innerNoWrap, innerCapStyle], children: [
|
|
763
850
|
brand !== void 0 ? /* @__PURE__ */ jsx(View, { style: navBarStyles.brand, children: brand }) : null,
|
|
764
851
|
collapsed ? /* @__PURE__ */ jsx(
|
|
765
852
|
Pressable,
|
|
@@ -842,13 +929,57 @@ var NavBar = ({
|
|
|
842
929
|
}
|
|
843
930
|
);
|
|
844
931
|
};
|
|
932
|
+
var NavBar = ({ barTheme, ...props }) => {
|
|
933
|
+
const { t, navigate } = useUi();
|
|
934
|
+
if (barTheme === void 0) return /* @__PURE__ */ jsx(NavBarInner, { ...props });
|
|
935
|
+
return /* @__PURE__ */ jsx(UiProvider, { navigate, t, theme: barTheme, children: /* @__PURE__ */ jsx(NavBarInner, { ...props }) });
|
|
936
|
+
};
|
|
845
937
|
var Nav = (props) => {
|
|
846
938
|
if (props.orientation === "vertical") {
|
|
847
939
|
return /* @__PURE__ */ jsx(Sidebar, { ...props });
|
|
848
940
|
}
|
|
849
941
|
return /* @__PURE__ */ jsx(NavBar, { ...props });
|
|
850
942
|
};
|
|
851
|
-
var
|
|
943
|
+
var CARD_PADDING = 20;
|
|
944
|
+
var CARD_BORDER_RADIUS = 12;
|
|
945
|
+
var CARD_BORDER_WIDTH = 1;
|
|
946
|
+
var CARD_TITLE_FONT_SIZE = 16;
|
|
947
|
+
var CARD_MESSAGE_FONT_SIZE = 14;
|
|
948
|
+
var CARD_TITLE_MARGIN_BOTTOM = 8;
|
|
949
|
+
var styles = StyleSheet.create({
|
|
950
|
+
centerFill: { flex: 1, justifyContent: "center", alignItems: "center" },
|
|
951
|
+
card: {
|
|
952
|
+
padding: CARD_PADDING,
|
|
953
|
+
borderRadius: CARD_BORDER_RADIUS,
|
|
954
|
+
borderWidth: CARD_BORDER_WIDTH
|
|
955
|
+
},
|
|
956
|
+
cardTitle: { fontSize: CARD_TITLE_FONT_SIZE, fontWeight: "700", marginBottom: CARD_TITLE_MARGIN_BOTTOM },
|
|
957
|
+
cardMessage: { fontSize: CARD_MESSAGE_FONT_SIZE }
|
|
958
|
+
});
|
|
959
|
+
function MessageCard({
|
|
960
|
+
message,
|
|
961
|
+
accentColor,
|
|
962
|
+
testID
|
|
963
|
+
}) {
|
|
964
|
+
const { theme } = useUi();
|
|
965
|
+
const colors = theme.colors;
|
|
966
|
+
return /* @__PURE__ */ jsxs(View, { style: [styles.card, { backgroundColor: colors.surface, borderColor: accentColor }], testID, children: [
|
|
967
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.cardTitle, { color: accentColor }], children: message.titleText }),
|
|
968
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.cardMessage, { color: colors.textSecondary }], children: message.messageText })
|
|
969
|
+
] });
|
|
970
|
+
}
|
|
971
|
+
function useContentBody(state, children, testID) {
|
|
972
|
+
const { theme } = useUi();
|
|
973
|
+
const primary = theme.palette.primary["500"];
|
|
974
|
+
const errorColor = theme.semantic.error["500"];
|
|
975
|
+
if (state?.forbidden)
|
|
976
|
+
return /* @__PURE__ */ jsx(MessageCard, { accentColor: errorColor, message: state.forbidden, testID: `${testID}${APP_SHELL_SUFFIX.forbidden}` });
|
|
977
|
+
if (state?.error)
|
|
978
|
+
return /* @__PURE__ */ jsx(MessageCard, { accentColor: errorColor, message: state.error, testID: `${testID}${APP_SHELL_SUFFIX.error}` });
|
|
979
|
+
if (state?.loading === true)
|
|
980
|
+
return /* @__PURE__ */ jsx(View, { style: styles.centerFill, testID: `${testID}${APP_SHELL_SUFFIX.loading}`, children: /* @__PURE__ */ jsx(ActivityIndicator, { color: primary, size: "large" }) });
|
|
981
|
+
return children;
|
|
982
|
+
}
|
|
852
983
|
var SCRIM_COLOR = "rgba(0, 0, 0, 0.5)";
|
|
853
984
|
var MENU_GLYPH2 = "\u2630";
|
|
854
985
|
var MENU_MIN_TARGET = 44;
|
|
@@ -862,7 +993,7 @@ var DEFAULT_DRAWER_LABELS = {
|
|
|
862
993
|
closeLabel: "Close menu",
|
|
863
994
|
closeHint: "Close the navigation menu"
|
|
864
995
|
};
|
|
865
|
-
var
|
|
996
|
+
var styles2 = StyleSheet.create({
|
|
866
997
|
overlay: { ...StyleSheet.absoluteFillObject, zIndex: DRAWER_Z_INDEX },
|
|
867
998
|
scrim: { ...StyleSheet.absoluteFillObject, backgroundColor: SCRIM_COLOR },
|
|
868
999
|
panel: { position: "absolute", top: 0, bottom: 0, left: 0 },
|
|
@@ -883,10 +1014,10 @@ var MenuToggle = ({ label, hint, onOpen, testID }) => {
|
|
|
883
1014
|
accessibilityHint: hint,
|
|
884
1015
|
accessibilityLabel: label,
|
|
885
1016
|
ringColor: theme.palette.primary["500"],
|
|
886
|
-
style:
|
|
1017
|
+
style: styles2.menuToggle,
|
|
887
1018
|
testID,
|
|
888
1019
|
onPress: onOpen,
|
|
889
|
-
children: /* @__PURE__ */ jsx(Text, { style: [
|
|
1020
|
+
children: /* @__PURE__ */ jsx(Text, { style: [styles2.menuToggleGlyph, { color: theme.colors.text }], children: MENU_GLYPH2 })
|
|
890
1021
|
}
|
|
891
1022
|
);
|
|
892
1023
|
};
|
|
@@ -909,21 +1040,34 @@ var MobileDrawer = ({
|
|
|
909
1040
|
node.addEventListener("click", handleClick);
|
|
910
1041
|
return () => node.removeEventListener("click", handleClick);
|
|
911
1042
|
}, [onClose]);
|
|
912
|
-
return /* @__PURE__ */ jsxs(View, { style:
|
|
1043
|
+
return /* @__PURE__ */ jsxs(View, { style: styles2.overlay, children: [
|
|
913
1044
|
/* @__PURE__ */ jsx(
|
|
914
1045
|
Pressable,
|
|
915
1046
|
{
|
|
916
1047
|
accessibilityHint: labels.closeHint,
|
|
917
1048
|
accessibilityLabel: labels.closeLabel,
|
|
918
1049
|
accessibilityRole: "button",
|
|
919
|
-
style:
|
|
1050
|
+
style: styles2.scrim,
|
|
920
1051
|
testID: scrimTestID,
|
|
921
1052
|
onPress: onClose
|
|
922
1053
|
}
|
|
923
1054
|
),
|
|
924
|
-
/* @__PURE__ */ jsx(View, { ref: panelRef, "aria-modal": true, role: "dialog", style:
|
|
1055
|
+
/* @__PURE__ */ jsx(View, { ref: panelRef, "aria-modal": true, role: "dialog", style: styles2.panel, testID: drawerTestID, children: sidebar })
|
|
925
1056
|
] });
|
|
926
1057
|
};
|
|
1058
|
+
|
|
1059
|
+
// src/railMode.ts
|
|
1060
|
+
var RAIL_FULL_BREAKPOINT = 768;
|
|
1061
|
+
var DEFAULT_COLLAPSED_RAIL_MAX = 1024;
|
|
1062
|
+
function resolveRailMode({ viewport, hasSidebar, hasCollapsed, range }) {
|
|
1063
|
+
if (!hasSidebar) return "none";
|
|
1064
|
+
if (hasCollapsed) {
|
|
1065
|
+
if (viewport >= range.max) return "full";
|
|
1066
|
+
if (viewport >= range.min) return "collapsed";
|
|
1067
|
+
return "drawer";
|
|
1068
|
+
}
|
|
1069
|
+
return viewport >= RAIL_FULL_BREAKPOINT ? "full" : "drawer";
|
|
1070
|
+
}
|
|
927
1071
|
function resolveContentMaxWidth(width, viewport) {
|
|
928
1072
|
if (width === "full") return "full";
|
|
929
1073
|
const wideMinViewport = width.wideMinViewport ?? Number.POSITIVE_INFINITY;
|
|
@@ -935,13 +1079,7 @@ function useContentMaxWidth(width) {
|
|
|
935
1079
|
return resolveContentMaxWidth(width, viewport);
|
|
936
1080
|
}
|
|
937
1081
|
var DEFAULT_CONTENT_PADDING = 24;
|
|
938
|
-
var
|
|
939
|
-
var CARD_BORDER_RADIUS = 12;
|
|
940
|
-
var CARD_BORDER_WIDTH = 1;
|
|
941
|
-
var CARD_TITLE_FONT_SIZE = 16;
|
|
942
|
-
var CARD_MESSAGE_FONT_SIZE = 14;
|
|
943
|
-
var CARD_TITLE_MARGIN_BOTTOM = 8;
|
|
944
|
-
var styles2 = StyleSheet.create({
|
|
1082
|
+
var styles3 = StyleSheet.create({
|
|
945
1083
|
root: { flex: 1 },
|
|
946
1084
|
centerFill: { flex: 1, justifyContent: "center", alignItems: "center" },
|
|
947
1085
|
scroll: { flex: 1 },
|
|
@@ -955,50 +1093,14 @@ var styles2 = StyleSheet.create({
|
|
|
955
1093
|
columnCapped: { flex: 1, width: "100%", alignSelf: "center" },
|
|
956
1094
|
// Non-flex variant used to cap the nav strip's inner content to the content
|
|
957
1095
|
// column so the nav aligns with the page content instead of running full-bleed.
|
|
958
|
-
chromeCapped: { width: "100%", alignSelf: "center" }
|
|
959
|
-
card: {
|
|
960
|
-
padding: CARD_PADDING,
|
|
961
|
-
borderRadius: CARD_BORDER_RADIUS,
|
|
962
|
-
borderWidth: CARD_BORDER_WIDTH
|
|
963
|
-
},
|
|
964
|
-
cardTitle: { fontSize: CARD_TITLE_FONT_SIZE, fontWeight: "700", marginBottom: CARD_TITLE_MARGIN_BOTTOM },
|
|
965
|
-
cardMessage: { fontSize: CARD_MESSAGE_FONT_SIZE }
|
|
1096
|
+
chromeCapped: { width: "100%", alignSelf: "center" }
|
|
966
1097
|
});
|
|
967
|
-
function MessageCard({
|
|
968
|
-
message,
|
|
969
|
-
accentColor,
|
|
970
|
-
testID
|
|
971
|
-
}) {
|
|
972
|
-
const { theme } = useUi();
|
|
973
|
-
const colors = theme.colors;
|
|
974
|
-
return /* @__PURE__ */ jsxs(
|
|
975
|
-
View,
|
|
976
|
-
{
|
|
977
|
-
style: [styles2.card, { backgroundColor: colors.surface, borderColor: accentColor }],
|
|
978
|
-
testID,
|
|
979
|
-
children: [
|
|
980
|
-
/* @__PURE__ */ jsx(Text, { style: [styles2.cardTitle, { color: accentColor }], children: message.titleText }),
|
|
981
|
-
/* @__PURE__ */ jsx(Text, { style: [styles2.cardMessage, { color: colors.textSecondary }], children: message.messageText })
|
|
982
|
-
]
|
|
983
|
-
}
|
|
984
|
-
);
|
|
985
|
-
}
|
|
986
|
-
function useContentBody(state, children, testID) {
|
|
987
|
-
const { theme } = useUi();
|
|
988
|
-
const primary = theme.palette.primary["500"];
|
|
989
|
-
const errorColor = theme.semantic.error["500"];
|
|
990
|
-
if (state?.forbidden)
|
|
991
|
-
return /* @__PURE__ */ jsx(MessageCard, { accentColor: errorColor, message: state.forbidden, testID: `${testID}${APP_SHELL_SUFFIX.forbidden}` });
|
|
992
|
-
if (state?.error)
|
|
993
|
-
return /* @__PURE__ */ jsx(MessageCard, { accentColor: errorColor, message: state.error, testID: `${testID}${APP_SHELL_SUFFIX.error}` });
|
|
994
|
-
if (state?.loading === true)
|
|
995
|
-
return /* @__PURE__ */ jsx(View, { style: styles2.centerFill, testID: `${testID}${APP_SHELL_SUFFIX.loading}`, children: /* @__PURE__ */ jsx(ActivityIndicator, { color: primary, size: "large" }) });
|
|
996
|
-
return children;
|
|
997
|
-
}
|
|
998
1098
|
var AppShell = ({
|
|
999
1099
|
header,
|
|
1000
1100
|
nav,
|
|
1001
1101
|
sidebar,
|
|
1102
|
+
collapsedSidebar,
|
|
1103
|
+
collapsedRailRange,
|
|
1002
1104
|
mobileMenu,
|
|
1003
1105
|
banner,
|
|
1004
1106
|
width = "full",
|
|
@@ -1014,34 +1116,40 @@ var AppShell = ({
|
|
|
1014
1116
|
const maxWidth = useContentMaxWidth(width);
|
|
1015
1117
|
const body = useContentBody(state, children, testID);
|
|
1016
1118
|
const { width: viewportWidth } = useWindowDimensions();
|
|
1017
|
-
const
|
|
1018
|
-
const
|
|
1119
|
+
const railRange = collapsedRailRange ?? { min: RAIL_FULL_BREAKPOINT, max: DEFAULT_COLLAPSED_RAIL_MAX };
|
|
1120
|
+
const railMode = resolveRailMode({
|
|
1121
|
+
viewport: viewportWidth,
|
|
1122
|
+
hasSidebar: sidebar !== void 0,
|
|
1123
|
+
hasCollapsed: collapsedSidebar !== void 0,
|
|
1124
|
+
range: railRange
|
|
1125
|
+
});
|
|
1126
|
+
const useDrawer = railMode === "drawer";
|
|
1019
1127
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
1020
1128
|
const openDrawer = useCallback(() => setDrawerOpen(true), []);
|
|
1021
1129
|
const closeDrawer = useCallback(() => setDrawerOpen(false), []);
|
|
1022
1130
|
useEffect(() => {
|
|
1023
|
-
if (!
|
|
1024
|
-
}, [
|
|
1131
|
+
if (!useDrawer && drawerOpen) setDrawerOpen(false);
|
|
1132
|
+
}, [useDrawer, drawerOpen]);
|
|
1025
1133
|
const drawerLabels = { ...DEFAULT_DRAWER_LABELS, ...mobileMenu };
|
|
1026
1134
|
const isUnauthenticated = gate !== void 0 && !gate.pending && !gate.authenticated;
|
|
1027
1135
|
useEffect(() => {
|
|
1028
1136
|
if (isUnauthenticated && gate !== void 0) gate.onRedirect();
|
|
1029
1137
|
}, [isUnauthenticated, gate]);
|
|
1030
1138
|
if (gate?.pending === true)
|
|
1031
|
-
return /* @__PURE__ */ jsx(View, { style: [
|
|
1139
|
+
return /* @__PURE__ */ jsx(View, { style: [styles3.root, styles3.centerFill, { backgroundColor: theme.colors.background }], testID: `${testID}${APP_SHELL_SUFFIX.pending}`, children: /* @__PURE__ */ jsx(ActivityIndicator, { color: primary, size: "large" }) });
|
|
1032
1140
|
if (isUnauthenticated) return null;
|
|
1033
|
-
const columnStyle = maxWidth === "full" ?
|
|
1034
|
-
const navInnerStyle = chromeAlignment === "content" && maxWidth !== "full" ? [
|
|
1141
|
+
const columnStyle = maxWidth === "full" ? styles3.columnFull : [styles3.columnCapped, { maxWidth }];
|
|
1142
|
+
const navInnerStyle = chromeAlignment === "content" && maxWidth !== "full" ? [styles3.chromeCapped, { maxWidth, paddingHorizontal: contentPadding }] : void 0;
|
|
1035
1143
|
const scroller = /* @__PURE__ */ jsx(
|
|
1036
1144
|
ScrollView,
|
|
1037
1145
|
{
|
|
1038
|
-
contentContainerStyle: [
|
|
1039
|
-
style:
|
|
1146
|
+
contentContainerStyle: [styles3.scrollContent, { padding: contentPadding }],
|
|
1147
|
+
style: styles3.scroll,
|
|
1040
1148
|
testID: `${testID}${APP_SHELL_SUFFIX.content}`,
|
|
1041
1149
|
children: /* @__PURE__ */ jsx(View, { style: columnStyle, children: body })
|
|
1042
1150
|
}
|
|
1043
1151
|
);
|
|
1044
|
-
const headerRegion = useDrawer ? /* @__PURE__ */ jsxs(View, { style:
|
|
1152
|
+
const headerRegion = useDrawer ? /* @__PURE__ */ jsxs(View, { style: styles3.headerRow, testID: `${testID}${APP_SHELL_SUFFIX.header}`, children: [
|
|
1045
1153
|
/* @__PURE__ */ jsx(
|
|
1046
1154
|
MenuToggle,
|
|
1047
1155
|
{
|
|
@@ -1051,15 +1159,15 @@ var AppShell = ({
|
|
|
1051
1159
|
onOpen: openDrawer
|
|
1052
1160
|
}
|
|
1053
1161
|
),
|
|
1054
|
-
/* @__PURE__ */ jsx(View, { style:
|
|
1162
|
+
/* @__PURE__ */ jsx(View, { style: styles3.headerFill, children: header })
|
|
1055
1163
|
] }) : /* @__PURE__ */ jsx(View, { testID: `${testID}${APP_SHELL_SUFFIX.header}`, children: header });
|
|
1056
|
-
const
|
|
1057
|
-
return /* @__PURE__ */ jsxs(View, { style: [
|
|
1164
|
+
const railRegion = railMode === "full" ? /* @__PURE__ */ jsx(View, { testID: `${testID}${APP_SHELL_SUFFIX.sidebar}`, children: sidebar }) : railMode === "collapsed" ? /* @__PURE__ */ jsx(View, { testID: `${testID}${APP_SHELL_SUFFIX.collapsedSidebar}`, children: collapsedSidebar }) : null;
|
|
1165
|
+
return /* @__PURE__ */ jsxs(View, { style: [styles3.root, { backgroundColor: theme.colors.background }], testID, children: [
|
|
1058
1166
|
headerRegion,
|
|
1059
1167
|
nav !== void 0 ? /* @__PURE__ */ jsx(View, { testID: `${testID}${APP_SHELL_SUFFIX.nav}`, children: navInnerStyle !== void 0 ? /* @__PURE__ */ jsx(View, { style: navInnerStyle, children: nav }) : nav }) : null,
|
|
1060
1168
|
banner !== void 0 ? /* @__PURE__ */ jsx(View, { testID: `${testID}${APP_SHELL_SUFFIX.banner}`, children: banner }) : null,
|
|
1061
|
-
|
|
1062
|
-
|
|
1169
|
+
railRegion !== null ? /* @__PURE__ */ jsxs(View, { style: styles3.bodyRow, children: [
|
|
1170
|
+
railRegion,
|
|
1063
1171
|
scroller
|
|
1064
1172
|
] }) : scroller,
|
|
1065
1173
|
useDrawer && drawerOpen ? /* @__PURE__ */ jsx(
|
|
@@ -1074,6 +1182,262 @@ var AppShell = ({
|
|
|
1074
1182
|
) : null
|
|
1075
1183
|
] });
|
|
1076
1184
|
};
|
|
1185
|
+
var COLLAPSED_ICON_SIZE = 22;
|
|
1186
|
+
function glyphFor(label) {
|
|
1187
|
+
return label.trim().charAt(0).toUpperCase();
|
|
1188
|
+
}
|
|
1189
|
+
var CollapsedRail = ({
|
|
1190
|
+
items,
|
|
1191
|
+
pathname,
|
|
1192
|
+
onNavigate,
|
|
1193
|
+
regionLabel,
|
|
1194
|
+
navigateHint = (label) => label,
|
|
1195
|
+
header,
|
|
1196
|
+
footer,
|
|
1197
|
+
containerStyle
|
|
1198
|
+
}) => {
|
|
1199
|
+
const { theme } = useUi();
|
|
1200
|
+
const colors = theme.colors;
|
|
1201
|
+
const primaryColor = theme.palette.primary["500"];
|
|
1202
|
+
return /* @__PURE__ */ jsxs(
|
|
1203
|
+
View,
|
|
1204
|
+
{
|
|
1205
|
+
accessibilityRole: "none",
|
|
1206
|
+
"aria-label": regionLabel,
|
|
1207
|
+
role: "navigation",
|
|
1208
|
+
style: [
|
|
1209
|
+
collapsedRailStyles.container,
|
|
1210
|
+
{ backgroundColor: colors.surface, borderRightColor: colors.border },
|
|
1211
|
+
containerStyle
|
|
1212
|
+
],
|
|
1213
|
+
children: [
|
|
1214
|
+
header !== void 0 ? /* @__PURE__ */ jsx(View, { style: collapsedRailStyles.slot, children: header }) : null,
|
|
1215
|
+
items.map((item) => {
|
|
1216
|
+
const active = isRouteActive(pathname, item.route);
|
|
1217
|
+
const iconColor = active ? primaryColor : colors.textSecondary;
|
|
1218
|
+
return /* @__PURE__ */ jsx(
|
|
1219
|
+
FocusableTouchable,
|
|
1220
|
+
{
|
|
1221
|
+
accessibilityHint: navigateHint(item.label),
|
|
1222
|
+
accessibilityLabel: item.label,
|
|
1223
|
+
ringColor: primaryColor,
|
|
1224
|
+
style: [collapsedRailStyles.item, active ? { backgroundColor: colors.border } : void 0],
|
|
1225
|
+
testID: item.testID ?? item.key,
|
|
1226
|
+
onPress: () => onNavigate(item.route),
|
|
1227
|
+
children: typeof item.renderIcon === "function" ? item.renderIcon(iconColor, COLLAPSED_ICON_SIZE) : /* @__PURE__ */ jsx(Text, { style: [collapsedRailStyles.glyph, { color: iconColor }], children: glyphFor(item.label) })
|
|
1228
|
+
},
|
|
1229
|
+
item.key
|
|
1230
|
+
);
|
|
1231
|
+
}),
|
|
1232
|
+
/* @__PURE__ */ jsx(View, { style: collapsedRailStyles.spacer }),
|
|
1233
|
+
footer !== void 0 ? /* @__PURE__ */ jsx(View, { style: collapsedRailStyles.slot, children: footer }) : null
|
|
1234
|
+
]
|
|
1235
|
+
}
|
|
1236
|
+
);
|
|
1237
|
+
};
|
|
1238
|
+
function wantsTopBar(layout, hasHeader, hasTopBar) {
|
|
1239
|
+
return layout === "top" || layout === "both" || hasHeader || layout === "side" && hasTopBar;
|
|
1240
|
+
}
|
|
1241
|
+
function wantsSideRail(layout, hasSideRail) {
|
|
1242
|
+
return (layout === "side" || layout === "both") && hasSideRail;
|
|
1243
|
+
}
|
|
1244
|
+
var NavShell = ({
|
|
1245
|
+
layout,
|
|
1246
|
+
pathname,
|
|
1247
|
+
onNavigate,
|
|
1248
|
+
regionLabel,
|
|
1249
|
+
navigateHint,
|
|
1250
|
+
topBar,
|
|
1251
|
+
header,
|
|
1252
|
+
sideRail,
|
|
1253
|
+
children,
|
|
1254
|
+
collapsedSidebar: collapsedSidebarProp,
|
|
1255
|
+
collapsedRailRange: collapsedRailRangeProp,
|
|
1256
|
+
...shellProps
|
|
1257
|
+
}) => {
|
|
1258
|
+
const showTopBar = wantsTopBar(layout, header !== void 0, topBar !== void 0);
|
|
1259
|
+
const showSideRail = wantsSideRail(layout, sideRail !== void 0);
|
|
1260
|
+
const headerNode = header !== void 0 ? header : showTopBar && topBar !== void 0 ? /* @__PURE__ */ jsx(
|
|
1261
|
+
NavBar,
|
|
1262
|
+
{
|
|
1263
|
+
barTheme: topBar.barTheme,
|
|
1264
|
+
brand: topBar.brand,
|
|
1265
|
+
collapseBelow: topBar.collapseBelow,
|
|
1266
|
+
containerStyle: topBar.containerStyle,
|
|
1267
|
+
contentMaxWidth: topBar.contentMaxWidth,
|
|
1268
|
+
items: topBar.items,
|
|
1269
|
+
menuHint: topBar.menuHint,
|
|
1270
|
+
menuLabel: topBar.menuLabel,
|
|
1271
|
+
navigateHint,
|
|
1272
|
+
overflowHint: topBar.overflowHint,
|
|
1273
|
+
overflowLabel: topBar.overflowLabel,
|
|
1274
|
+
pathname,
|
|
1275
|
+
regionLabel,
|
|
1276
|
+
renderMenuIcon: topBar.renderMenuIcon,
|
|
1277
|
+
right: topBar.right,
|
|
1278
|
+
onNavigate
|
|
1279
|
+
}
|
|
1280
|
+
) : null;
|
|
1281
|
+
const sidebarNode = showSideRail && sideRail !== void 0 ? /* @__PURE__ */ jsx(
|
|
1282
|
+
Sidebar,
|
|
1283
|
+
{
|
|
1284
|
+
collapseHint: sideRail.collapseHint,
|
|
1285
|
+
containerStyle: sideRail.containerStyle,
|
|
1286
|
+
expandHint: sideRail.expandHint,
|
|
1287
|
+
footer: sideRail.footer,
|
|
1288
|
+
header: sideRail.header,
|
|
1289
|
+
items: sideRail.items,
|
|
1290
|
+
navigateHint,
|
|
1291
|
+
pathname,
|
|
1292
|
+
regionLabel,
|
|
1293
|
+
renderChevron: sideRail.renderChevron,
|
|
1294
|
+
title: sideRail.title,
|
|
1295
|
+
onNavigate
|
|
1296
|
+
}
|
|
1297
|
+
) : void 0;
|
|
1298
|
+
const collapsedCfg = showSideRail ? sideRail?.collapsed : void 0;
|
|
1299
|
+
const collapsedNode = collapsedCfg !== void 0 && sideRail !== void 0 ? /* @__PURE__ */ jsx(
|
|
1300
|
+
CollapsedRail,
|
|
1301
|
+
{
|
|
1302
|
+
footer: collapsedCfg.footer,
|
|
1303
|
+
header: collapsedCfg.header,
|
|
1304
|
+
items: collapsedCfg.items ?? sideRail.items,
|
|
1305
|
+
navigateHint,
|
|
1306
|
+
pathname,
|
|
1307
|
+
regionLabel,
|
|
1308
|
+
onNavigate
|
|
1309
|
+
}
|
|
1310
|
+
) : collapsedSidebarProp;
|
|
1311
|
+
const collapsedRange = collapsedCfg?.range ?? collapsedRailRangeProp;
|
|
1312
|
+
return /* @__PURE__ */ jsx(
|
|
1313
|
+
AppShell,
|
|
1314
|
+
{
|
|
1315
|
+
...shellProps,
|
|
1316
|
+
collapsedRailRange: collapsedRange,
|
|
1317
|
+
collapsedSidebar: collapsedNode,
|
|
1318
|
+
header: headerNode,
|
|
1319
|
+
sidebar: sidebarNode,
|
|
1320
|
+
children
|
|
1321
|
+
}
|
|
1322
|
+
);
|
|
1323
|
+
};
|
|
1324
|
+
var TEXT_ON_PRIMARY4 = "#ffffff";
|
|
1325
|
+
var DEFAULT_MIN_ITEMS = 1;
|
|
1326
|
+
var PillNav = ({
|
|
1327
|
+
items,
|
|
1328
|
+
pathname,
|
|
1329
|
+
onNavigate,
|
|
1330
|
+
regionLabel,
|
|
1331
|
+
navigateHint = (label) => label,
|
|
1332
|
+
minItems = DEFAULT_MIN_ITEMS,
|
|
1333
|
+
containerStyle
|
|
1334
|
+
}) => {
|
|
1335
|
+
const { theme } = useUi();
|
|
1336
|
+
const colors = theme.colors;
|
|
1337
|
+
const primaryColor = theme.palette.primary["500"];
|
|
1338
|
+
if (items.length < minItems) return null;
|
|
1339
|
+
return /* @__PURE__ */ jsx(
|
|
1340
|
+
View,
|
|
1341
|
+
{
|
|
1342
|
+
accessibilityRole: "none",
|
|
1343
|
+
"aria-label": regionLabel,
|
|
1344
|
+
role: "navigation",
|
|
1345
|
+
style: [pillNavStyles.container, containerStyle],
|
|
1346
|
+
children: items.map((item) => {
|
|
1347
|
+
const active = isRouteActive(pathname, item.route);
|
|
1348
|
+
const textColor = active ? TEXT_ON_PRIMARY4 : colors.textSecondary;
|
|
1349
|
+
const pillStyle = active ? { backgroundColor: primaryColor } : { backgroundColor: colors.surfaceElevated };
|
|
1350
|
+
return /* @__PURE__ */ jsxs(
|
|
1351
|
+
FocusableTouchable,
|
|
1352
|
+
{
|
|
1353
|
+
accessibilityHint: navigateHint(item.label),
|
|
1354
|
+
accessibilityLabel: item.label,
|
|
1355
|
+
accessibilityRole: "link",
|
|
1356
|
+
ringColor: primaryColor,
|
|
1357
|
+
style: [pillNavStyles.pill, pillStyle],
|
|
1358
|
+
testID: item.testID ?? item.key,
|
|
1359
|
+
onPress: () => onNavigate(item.route),
|
|
1360
|
+
children: [
|
|
1361
|
+
typeof item.renderIcon === "function" ? item.renderIcon(textColor, NAV_ICON_SIZE) : null,
|
|
1362
|
+
/* @__PURE__ */ jsx(Text, { style: [pillNavStyles.pillText, { color: textColor }], children: item.label })
|
|
1363
|
+
]
|
|
1364
|
+
},
|
|
1365
|
+
item.key
|
|
1366
|
+
);
|
|
1367
|
+
})
|
|
1368
|
+
}
|
|
1369
|
+
);
|
|
1370
|
+
};
|
|
1371
|
+
var TEXT_ON_PRIMARY5 = "#ffffff";
|
|
1372
|
+
var DARK_MODE_ICON_SIZE = 16;
|
|
1373
|
+
var DarkModeControl = ({
|
|
1374
|
+
value,
|
|
1375
|
+
options,
|
|
1376
|
+
onChange,
|
|
1377
|
+
regionLabel,
|
|
1378
|
+
variant = "segmented",
|
|
1379
|
+
testID,
|
|
1380
|
+
containerStyle
|
|
1381
|
+
}) => {
|
|
1382
|
+
const { theme } = useUi();
|
|
1383
|
+
const colors = theme.colors;
|
|
1384
|
+
const primaryColor = theme.palette.primary["500"];
|
|
1385
|
+
const currentIndex = options.findIndex((option) => option.value === value);
|
|
1386
|
+
const current = currentIndex >= 0 ? options[currentIndex] : options[0];
|
|
1387
|
+
const advance = useCallback(() => {
|
|
1388
|
+
if (options.length === 0) return;
|
|
1389
|
+
const from = currentIndex >= 0 ? currentIndex : 0;
|
|
1390
|
+
const next = options[(from + 1) % options.length];
|
|
1391
|
+
if (next !== void 0) onChange(next.value);
|
|
1392
|
+
}, [options, currentIndex, onChange]);
|
|
1393
|
+
if (options.length === 0 || current === void 0) return null;
|
|
1394
|
+
if (variant === "cycle") {
|
|
1395
|
+
const iconColor = colors.text;
|
|
1396
|
+
return /* @__PURE__ */ jsx(View, { "aria-label": regionLabel, style: containerStyle, children: /* @__PURE__ */ jsxs(
|
|
1397
|
+
FocusableTouchable,
|
|
1398
|
+
{
|
|
1399
|
+
accessibilityHint: current.hint,
|
|
1400
|
+
accessibilityLabel: current.label,
|
|
1401
|
+
ringColor: primaryColor,
|
|
1402
|
+
style: [darkModeStyles.cycle, { backgroundColor: colors.surfaceElevated }],
|
|
1403
|
+
testID,
|
|
1404
|
+
onPress: advance,
|
|
1405
|
+
children: [
|
|
1406
|
+
typeof current.renderIcon === "function" ? current.renderIcon(iconColor, DARK_MODE_ICON_SIZE) : null,
|
|
1407
|
+
/* @__PURE__ */ jsx(Text, { style: [darkModeStyles.cycleText, { color: colors.text }], children: current.label })
|
|
1408
|
+
]
|
|
1409
|
+
}
|
|
1410
|
+
) });
|
|
1411
|
+
}
|
|
1412
|
+
return /* @__PURE__ */ jsx(
|
|
1413
|
+
View,
|
|
1414
|
+
{
|
|
1415
|
+
"aria-label": regionLabel,
|
|
1416
|
+
role: "group",
|
|
1417
|
+
style: [darkModeStyles.segmentRow, { borderColor: colors.border }, containerStyle],
|
|
1418
|
+
children: options.map((option) => {
|
|
1419
|
+
const active = option.value === value;
|
|
1420
|
+
const textColor = active ? TEXT_ON_PRIMARY5 : colors.textSecondary;
|
|
1421
|
+
return /* @__PURE__ */ jsxs(
|
|
1422
|
+
FocusableTouchable,
|
|
1423
|
+
{
|
|
1424
|
+
accessibilityHint: option.hint,
|
|
1425
|
+
accessibilityLabel: option.label,
|
|
1426
|
+
ringColor: primaryColor,
|
|
1427
|
+
style: [darkModeStyles.segment, active ? { backgroundColor: primaryColor } : void 0],
|
|
1428
|
+
testID: testID !== void 0 ? `${testID}-${option.value}` : void 0,
|
|
1429
|
+
onPress: () => onChange(option.value),
|
|
1430
|
+
children: [
|
|
1431
|
+
typeof option.renderIcon === "function" ? option.renderIcon(textColor, DARK_MODE_ICON_SIZE) : null,
|
|
1432
|
+
/* @__PURE__ */ jsx(Text, { style: [darkModeStyles.segmentText, { color: textColor }], children: option.label })
|
|
1433
|
+
]
|
|
1434
|
+
},
|
|
1435
|
+
option.value
|
|
1436
|
+
);
|
|
1437
|
+
})
|
|
1438
|
+
}
|
|
1439
|
+
);
|
|
1440
|
+
};
|
|
1077
1441
|
function roleRoutesToNavItems(routes, translate) {
|
|
1078
1442
|
return routes.map((entry) => ({
|
|
1079
1443
|
key: entry.role,
|
|
@@ -1085,6 +1449,6 @@ function accessibleNavItems(user, table, translate) {
|
|
|
1085
1449
|
return roleRoutesToNavItems(resolveAccessibleRoutes(user, table), translate);
|
|
1086
1450
|
}
|
|
1087
1451
|
|
|
1088
|
-
export { ACTIVE_BORDER_RADIUS, APP_SHELL_SUFFIX, AppShell, BASE_INDENT, CHEVRON_ICON_SIZE, NAV_ICON_SIZE, NAV_LINK_GAP, NAV_TEST_IDS, Nav, NavBar, NavExpandableItem, NavOverflowMenu, Sidebar, Topbar, accessibleNavItems, expandableStyles, isRouteActive, navStyles, resolveContentMaxWidth, roleRoutesToNavItems, useContentMaxWidth };
|
|
1452
|
+
export { ACTIVE_BORDER_RADIUS, APP_SHELL_SUFFIX, AppShell, BASE_INDENT, CHEVRON_ICON_SIZE, CollapsedRail, DEFAULT_COLLAPSED_RAIL_MAX, DarkModeControl, NAV_ICON_SIZE, NAV_LINK_GAP, NAV_TEST_IDS, Nav, NavBar, NavExpandableItem, NavOverflowMenu, NavShell, PillNav, RAIL_FULL_BREAKPOINT, Sidebar, Topbar, accessibleNavItems, collapsedRailStyles, darkModeStyles, expandableStyles, isRouteActive, navStyles, pillNavStyles, resolveContentMaxWidth, resolveRailMode, roleRoutesToNavItems, useContentMaxWidth };
|
|
1089
1453
|
//# sourceMappingURL=index.mjs.map
|
|
1090
1454
|
//# sourceMappingURL=index.mjs.map
|