@dloizides/ui-nav 1.7.0 → 1.8.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 +58 -0
- package/README.md +83 -0
- package/dist/index.d.mts +533 -79
- package/dist/index.d.ts +533 -79
- package/dist/index.js +437 -69
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +430 -72
- 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,
|
|
@@ -842,13 +924,57 @@ var NavBar = ({
|
|
|
842
924
|
}
|
|
843
925
|
);
|
|
844
926
|
};
|
|
927
|
+
var NavBar = ({ barTheme, ...props }) => {
|
|
928
|
+
const { t, navigate } = useUi();
|
|
929
|
+
if (barTheme === void 0) return /* @__PURE__ */ jsx(NavBarInner, { ...props });
|
|
930
|
+
return /* @__PURE__ */ jsx(UiProvider, { navigate, t, theme: barTheme, children: /* @__PURE__ */ jsx(NavBarInner, { ...props }) });
|
|
931
|
+
};
|
|
845
932
|
var Nav = (props) => {
|
|
846
933
|
if (props.orientation === "vertical") {
|
|
847
934
|
return /* @__PURE__ */ jsx(Sidebar, { ...props });
|
|
848
935
|
}
|
|
849
936
|
return /* @__PURE__ */ jsx(NavBar, { ...props });
|
|
850
937
|
};
|
|
851
|
-
var
|
|
938
|
+
var CARD_PADDING = 20;
|
|
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 styles = StyleSheet.create({
|
|
945
|
+
centerFill: { flex: 1, justifyContent: "center", alignItems: "center" },
|
|
946
|
+
card: {
|
|
947
|
+
padding: CARD_PADDING,
|
|
948
|
+
borderRadius: CARD_BORDER_RADIUS,
|
|
949
|
+
borderWidth: CARD_BORDER_WIDTH
|
|
950
|
+
},
|
|
951
|
+
cardTitle: { fontSize: CARD_TITLE_FONT_SIZE, fontWeight: "700", marginBottom: CARD_TITLE_MARGIN_BOTTOM },
|
|
952
|
+
cardMessage: { fontSize: CARD_MESSAGE_FONT_SIZE }
|
|
953
|
+
});
|
|
954
|
+
function MessageCard({
|
|
955
|
+
message,
|
|
956
|
+
accentColor,
|
|
957
|
+
testID
|
|
958
|
+
}) {
|
|
959
|
+
const { theme } = useUi();
|
|
960
|
+
const colors = theme.colors;
|
|
961
|
+
return /* @__PURE__ */ jsxs(View, { style: [styles.card, { backgroundColor: colors.surface, borderColor: accentColor }], testID, children: [
|
|
962
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.cardTitle, { color: accentColor }], children: message.titleText }),
|
|
963
|
+
/* @__PURE__ */ jsx(Text, { style: [styles.cardMessage, { color: colors.textSecondary }], children: message.messageText })
|
|
964
|
+
] });
|
|
965
|
+
}
|
|
966
|
+
function useContentBody(state, children, testID) {
|
|
967
|
+
const { theme } = useUi();
|
|
968
|
+
const primary = theme.palette.primary["500"];
|
|
969
|
+
const errorColor = theme.semantic.error["500"];
|
|
970
|
+
if (state?.forbidden)
|
|
971
|
+
return /* @__PURE__ */ jsx(MessageCard, { accentColor: errorColor, message: state.forbidden, testID: `${testID}${APP_SHELL_SUFFIX.forbidden}` });
|
|
972
|
+
if (state?.error)
|
|
973
|
+
return /* @__PURE__ */ jsx(MessageCard, { accentColor: errorColor, message: state.error, testID: `${testID}${APP_SHELL_SUFFIX.error}` });
|
|
974
|
+
if (state?.loading === true)
|
|
975
|
+
return /* @__PURE__ */ jsx(View, { style: styles.centerFill, testID: `${testID}${APP_SHELL_SUFFIX.loading}`, children: /* @__PURE__ */ jsx(ActivityIndicator, { color: primary, size: "large" }) });
|
|
976
|
+
return children;
|
|
977
|
+
}
|
|
852
978
|
var SCRIM_COLOR = "rgba(0, 0, 0, 0.5)";
|
|
853
979
|
var MENU_GLYPH2 = "\u2630";
|
|
854
980
|
var MENU_MIN_TARGET = 44;
|
|
@@ -862,7 +988,7 @@ var DEFAULT_DRAWER_LABELS = {
|
|
|
862
988
|
closeLabel: "Close menu",
|
|
863
989
|
closeHint: "Close the navigation menu"
|
|
864
990
|
};
|
|
865
|
-
var
|
|
991
|
+
var styles2 = StyleSheet.create({
|
|
866
992
|
overlay: { ...StyleSheet.absoluteFillObject, zIndex: DRAWER_Z_INDEX },
|
|
867
993
|
scrim: { ...StyleSheet.absoluteFillObject, backgroundColor: SCRIM_COLOR },
|
|
868
994
|
panel: { position: "absolute", top: 0, bottom: 0, left: 0 },
|
|
@@ -883,10 +1009,10 @@ var MenuToggle = ({ label, hint, onOpen, testID }) => {
|
|
|
883
1009
|
accessibilityHint: hint,
|
|
884
1010
|
accessibilityLabel: label,
|
|
885
1011
|
ringColor: theme.palette.primary["500"],
|
|
886
|
-
style:
|
|
1012
|
+
style: styles2.menuToggle,
|
|
887
1013
|
testID,
|
|
888
1014
|
onPress: onOpen,
|
|
889
|
-
children: /* @__PURE__ */ jsx(Text, { style: [
|
|
1015
|
+
children: /* @__PURE__ */ jsx(Text, { style: [styles2.menuToggleGlyph, { color: theme.colors.text }], children: MENU_GLYPH2 })
|
|
890
1016
|
}
|
|
891
1017
|
);
|
|
892
1018
|
};
|
|
@@ -909,21 +1035,34 @@ var MobileDrawer = ({
|
|
|
909
1035
|
node.addEventListener("click", handleClick);
|
|
910
1036
|
return () => node.removeEventListener("click", handleClick);
|
|
911
1037
|
}, [onClose]);
|
|
912
|
-
return /* @__PURE__ */ jsxs(View, { style:
|
|
1038
|
+
return /* @__PURE__ */ jsxs(View, { style: styles2.overlay, children: [
|
|
913
1039
|
/* @__PURE__ */ jsx(
|
|
914
1040
|
Pressable,
|
|
915
1041
|
{
|
|
916
1042
|
accessibilityHint: labels.closeHint,
|
|
917
1043
|
accessibilityLabel: labels.closeLabel,
|
|
918
1044
|
accessibilityRole: "button",
|
|
919
|
-
style:
|
|
1045
|
+
style: styles2.scrim,
|
|
920
1046
|
testID: scrimTestID,
|
|
921
1047
|
onPress: onClose
|
|
922
1048
|
}
|
|
923
1049
|
),
|
|
924
|
-
/* @__PURE__ */ jsx(View, { ref: panelRef, "aria-modal": true, role: "dialog", style:
|
|
1050
|
+
/* @__PURE__ */ jsx(View, { ref: panelRef, "aria-modal": true, role: "dialog", style: styles2.panel, testID: drawerTestID, children: sidebar })
|
|
925
1051
|
] });
|
|
926
1052
|
};
|
|
1053
|
+
|
|
1054
|
+
// src/railMode.ts
|
|
1055
|
+
var RAIL_FULL_BREAKPOINT = 768;
|
|
1056
|
+
var DEFAULT_COLLAPSED_RAIL_MAX = 1024;
|
|
1057
|
+
function resolveRailMode({ viewport, hasSidebar, hasCollapsed, range }) {
|
|
1058
|
+
if (!hasSidebar) return "none";
|
|
1059
|
+
if (hasCollapsed) {
|
|
1060
|
+
if (viewport >= range.max) return "full";
|
|
1061
|
+
if (viewport >= range.min) return "collapsed";
|
|
1062
|
+
return "drawer";
|
|
1063
|
+
}
|
|
1064
|
+
return viewport >= RAIL_FULL_BREAKPOINT ? "full" : "drawer";
|
|
1065
|
+
}
|
|
927
1066
|
function resolveContentMaxWidth(width, viewport) {
|
|
928
1067
|
if (width === "full") return "full";
|
|
929
1068
|
const wideMinViewport = width.wideMinViewport ?? Number.POSITIVE_INFINITY;
|
|
@@ -935,13 +1074,7 @@ function useContentMaxWidth(width) {
|
|
|
935
1074
|
return resolveContentMaxWidth(width, viewport);
|
|
936
1075
|
}
|
|
937
1076
|
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({
|
|
1077
|
+
var styles3 = StyleSheet.create({
|
|
945
1078
|
root: { flex: 1 },
|
|
946
1079
|
centerFill: { flex: 1, justifyContent: "center", alignItems: "center" },
|
|
947
1080
|
scroll: { flex: 1 },
|
|
@@ -955,50 +1088,14 @@ var styles2 = StyleSheet.create({
|
|
|
955
1088
|
columnCapped: { flex: 1, width: "100%", alignSelf: "center" },
|
|
956
1089
|
// Non-flex variant used to cap the nav strip's inner content to the content
|
|
957
1090
|
// 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 }
|
|
1091
|
+
chromeCapped: { width: "100%", alignSelf: "center" }
|
|
966
1092
|
});
|
|
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
1093
|
var AppShell = ({
|
|
999
1094
|
header,
|
|
1000
1095
|
nav,
|
|
1001
1096
|
sidebar,
|
|
1097
|
+
collapsedSidebar,
|
|
1098
|
+
collapsedRailRange,
|
|
1002
1099
|
mobileMenu,
|
|
1003
1100
|
banner,
|
|
1004
1101
|
width = "full",
|
|
@@ -1014,34 +1111,40 @@ var AppShell = ({
|
|
|
1014
1111
|
const maxWidth = useContentMaxWidth(width);
|
|
1015
1112
|
const body = useContentBody(state, children, testID);
|
|
1016
1113
|
const { width: viewportWidth } = useWindowDimensions();
|
|
1017
|
-
const
|
|
1018
|
-
const
|
|
1114
|
+
const railRange = collapsedRailRange ?? { min: RAIL_FULL_BREAKPOINT, max: DEFAULT_COLLAPSED_RAIL_MAX };
|
|
1115
|
+
const railMode = resolveRailMode({
|
|
1116
|
+
viewport: viewportWidth,
|
|
1117
|
+
hasSidebar: sidebar !== void 0,
|
|
1118
|
+
hasCollapsed: collapsedSidebar !== void 0,
|
|
1119
|
+
range: railRange
|
|
1120
|
+
});
|
|
1121
|
+
const useDrawer = railMode === "drawer";
|
|
1019
1122
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
1020
1123
|
const openDrawer = useCallback(() => setDrawerOpen(true), []);
|
|
1021
1124
|
const closeDrawer = useCallback(() => setDrawerOpen(false), []);
|
|
1022
1125
|
useEffect(() => {
|
|
1023
|
-
if (!
|
|
1024
|
-
}, [
|
|
1126
|
+
if (!useDrawer && drawerOpen) setDrawerOpen(false);
|
|
1127
|
+
}, [useDrawer, drawerOpen]);
|
|
1025
1128
|
const drawerLabels = { ...DEFAULT_DRAWER_LABELS, ...mobileMenu };
|
|
1026
1129
|
const isUnauthenticated = gate !== void 0 && !gate.pending && !gate.authenticated;
|
|
1027
1130
|
useEffect(() => {
|
|
1028
1131
|
if (isUnauthenticated && gate !== void 0) gate.onRedirect();
|
|
1029
1132
|
}, [isUnauthenticated, gate]);
|
|
1030
1133
|
if (gate?.pending === true)
|
|
1031
|
-
return /* @__PURE__ */ jsx(View, { style: [
|
|
1134
|
+
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
1135
|
if (isUnauthenticated) return null;
|
|
1033
|
-
const columnStyle = maxWidth === "full" ?
|
|
1034
|
-
const navInnerStyle = chromeAlignment === "content" && maxWidth !== "full" ? [
|
|
1136
|
+
const columnStyle = maxWidth === "full" ? styles3.columnFull : [styles3.columnCapped, { maxWidth }];
|
|
1137
|
+
const navInnerStyle = chromeAlignment === "content" && maxWidth !== "full" ? [styles3.chromeCapped, { maxWidth, paddingHorizontal: contentPadding }] : void 0;
|
|
1035
1138
|
const scroller = /* @__PURE__ */ jsx(
|
|
1036
1139
|
ScrollView,
|
|
1037
1140
|
{
|
|
1038
|
-
contentContainerStyle: [
|
|
1039
|
-
style:
|
|
1141
|
+
contentContainerStyle: [styles3.scrollContent, { padding: contentPadding }],
|
|
1142
|
+
style: styles3.scroll,
|
|
1040
1143
|
testID: `${testID}${APP_SHELL_SUFFIX.content}`,
|
|
1041
1144
|
children: /* @__PURE__ */ jsx(View, { style: columnStyle, children: body })
|
|
1042
1145
|
}
|
|
1043
1146
|
);
|
|
1044
|
-
const headerRegion = useDrawer ? /* @__PURE__ */ jsxs(View, { style:
|
|
1147
|
+
const headerRegion = useDrawer ? /* @__PURE__ */ jsxs(View, { style: styles3.headerRow, testID: `${testID}${APP_SHELL_SUFFIX.header}`, children: [
|
|
1045
1148
|
/* @__PURE__ */ jsx(
|
|
1046
1149
|
MenuToggle,
|
|
1047
1150
|
{
|
|
@@ -1051,15 +1154,15 @@ var AppShell = ({
|
|
|
1051
1154
|
onOpen: openDrawer
|
|
1052
1155
|
}
|
|
1053
1156
|
),
|
|
1054
|
-
/* @__PURE__ */ jsx(View, { style:
|
|
1157
|
+
/* @__PURE__ */ jsx(View, { style: styles3.headerFill, children: header })
|
|
1055
1158
|
] }) : /* @__PURE__ */ jsx(View, { testID: `${testID}${APP_SHELL_SUFFIX.header}`, children: header });
|
|
1056
|
-
const
|
|
1057
|
-
return /* @__PURE__ */ jsxs(View, { style: [
|
|
1159
|
+
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;
|
|
1160
|
+
return /* @__PURE__ */ jsxs(View, { style: [styles3.root, { backgroundColor: theme.colors.background }], testID, children: [
|
|
1058
1161
|
headerRegion,
|
|
1059
1162
|
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
1163
|
banner !== void 0 ? /* @__PURE__ */ jsx(View, { testID: `${testID}${APP_SHELL_SUFFIX.banner}`, children: banner }) : null,
|
|
1061
|
-
|
|
1062
|
-
|
|
1164
|
+
railRegion !== null ? /* @__PURE__ */ jsxs(View, { style: styles3.bodyRow, children: [
|
|
1165
|
+
railRegion,
|
|
1063
1166
|
scroller
|
|
1064
1167
|
] }) : scroller,
|
|
1065
1168
|
useDrawer && drawerOpen ? /* @__PURE__ */ jsx(
|
|
@@ -1074,6 +1177,261 @@ var AppShell = ({
|
|
|
1074
1177
|
) : null
|
|
1075
1178
|
] });
|
|
1076
1179
|
};
|
|
1180
|
+
var COLLAPSED_ICON_SIZE = 22;
|
|
1181
|
+
function glyphFor(label) {
|
|
1182
|
+
return label.trim().charAt(0).toUpperCase();
|
|
1183
|
+
}
|
|
1184
|
+
var CollapsedRail = ({
|
|
1185
|
+
items,
|
|
1186
|
+
pathname,
|
|
1187
|
+
onNavigate,
|
|
1188
|
+
regionLabel,
|
|
1189
|
+
navigateHint = (label) => label,
|
|
1190
|
+
header,
|
|
1191
|
+
footer,
|
|
1192
|
+
containerStyle
|
|
1193
|
+
}) => {
|
|
1194
|
+
const { theme } = useUi();
|
|
1195
|
+
const colors = theme.colors;
|
|
1196
|
+
const primaryColor = theme.palette.primary["500"];
|
|
1197
|
+
return /* @__PURE__ */ jsxs(
|
|
1198
|
+
View,
|
|
1199
|
+
{
|
|
1200
|
+
accessibilityRole: "none",
|
|
1201
|
+
"aria-label": regionLabel,
|
|
1202
|
+
role: "navigation",
|
|
1203
|
+
style: [
|
|
1204
|
+
collapsedRailStyles.container,
|
|
1205
|
+
{ backgroundColor: colors.surface, borderRightColor: colors.border },
|
|
1206
|
+
containerStyle
|
|
1207
|
+
],
|
|
1208
|
+
children: [
|
|
1209
|
+
header !== void 0 ? /* @__PURE__ */ jsx(View, { style: collapsedRailStyles.slot, children: header }) : null,
|
|
1210
|
+
items.map((item) => {
|
|
1211
|
+
const active = isRouteActive(pathname, item.route);
|
|
1212
|
+
const iconColor = active ? primaryColor : colors.textSecondary;
|
|
1213
|
+
return /* @__PURE__ */ jsx(
|
|
1214
|
+
FocusableTouchable,
|
|
1215
|
+
{
|
|
1216
|
+
accessibilityHint: navigateHint(item.label),
|
|
1217
|
+
accessibilityLabel: item.label,
|
|
1218
|
+
ringColor: primaryColor,
|
|
1219
|
+
style: [collapsedRailStyles.item, active ? { backgroundColor: colors.border } : void 0],
|
|
1220
|
+
testID: item.testID ?? item.key,
|
|
1221
|
+
onPress: () => onNavigate(item.route),
|
|
1222
|
+
children: typeof item.renderIcon === "function" ? item.renderIcon(iconColor, COLLAPSED_ICON_SIZE) : /* @__PURE__ */ jsx(Text, { style: [collapsedRailStyles.glyph, { color: iconColor }], children: glyphFor(item.label) })
|
|
1223
|
+
},
|
|
1224
|
+
item.key
|
|
1225
|
+
);
|
|
1226
|
+
}),
|
|
1227
|
+
/* @__PURE__ */ jsx(View, { style: collapsedRailStyles.spacer }),
|
|
1228
|
+
footer !== void 0 ? /* @__PURE__ */ jsx(View, { style: collapsedRailStyles.slot, children: footer }) : null
|
|
1229
|
+
]
|
|
1230
|
+
}
|
|
1231
|
+
);
|
|
1232
|
+
};
|
|
1233
|
+
function wantsTopBar(layout, hasHeader, hasTopBar) {
|
|
1234
|
+
return layout === "top" || layout === "both" || hasHeader || layout === "side" && hasTopBar;
|
|
1235
|
+
}
|
|
1236
|
+
function wantsSideRail(layout, hasSideRail) {
|
|
1237
|
+
return (layout === "side" || layout === "both") && hasSideRail;
|
|
1238
|
+
}
|
|
1239
|
+
var NavShell = ({
|
|
1240
|
+
layout,
|
|
1241
|
+
pathname,
|
|
1242
|
+
onNavigate,
|
|
1243
|
+
regionLabel,
|
|
1244
|
+
navigateHint,
|
|
1245
|
+
topBar,
|
|
1246
|
+
header,
|
|
1247
|
+
sideRail,
|
|
1248
|
+
children,
|
|
1249
|
+
collapsedSidebar: collapsedSidebarProp,
|
|
1250
|
+
collapsedRailRange: collapsedRailRangeProp,
|
|
1251
|
+
...shellProps
|
|
1252
|
+
}) => {
|
|
1253
|
+
const showTopBar = wantsTopBar(layout, header !== void 0, topBar !== void 0);
|
|
1254
|
+
const showSideRail = wantsSideRail(layout, sideRail !== void 0);
|
|
1255
|
+
const headerNode = header !== void 0 ? header : showTopBar && topBar !== void 0 ? /* @__PURE__ */ jsx(
|
|
1256
|
+
NavBar,
|
|
1257
|
+
{
|
|
1258
|
+
barTheme: topBar.barTheme,
|
|
1259
|
+
brand: topBar.brand,
|
|
1260
|
+
collapseBelow: topBar.collapseBelow,
|
|
1261
|
+
containerStyle: topBar.containerStyle,
|
|
1262
|
+
items: topBar.items,
|
|
1263
|
+
menuHint: topBar.menuHint,
|
|
1264
|
+
menuLabel: topBar.menuLabel,
|
|
1265
|
+
navigateHint,
|
|
1266
|
+
overflowHint: topBar.overflowHint,
|
|
1267
|
+
overflowLabel: topBar.overflowLabel,
|
|
1268
|
+
pathname,
|
|
1269
|
+
regionLabel,
|
|
1270
|
+
renderMenuIcon: topBar.renderMenuIcon,
|
|
1271
|
+
right: topBar.right,
|
|
1272
|
+
onNavigate
|
|
1273
|
+
}
|
|
1274
|
+
) : null;
|
|
1275
|
+
const sidebarNode = showSideRail && sideRail !== void 0 ? /* @__PURE__ */ jsx(
|
|
1276
|
+
Sidebar,
|
|
1277
|
+
{
|
|
1278
|
+
collapseHint: sideRail.collapseHint,
|
|
1279
|
+
containerStyle: sideRail.containerStyle,
|
|
1280
|
+
expandHint: sideRail.expandHint,
|
|
1281
|
+
footer: sideRail.footer,
|
|
1282
|
+
header: sideRail.header,
|
|
1283
|
+
items: sideRail.items,
|
|
1284
|
+
navigateHint,
|
|
1285
|
+
pathname,
|
|
1286
|
+
regionLabel,
|
|
1287
|
+
renderChevron: sideRail.renderChevron,
|
|
1288
|
+
title: sideRail.title,
|
|
1289
|
+
onNavigate
|
|
1290
|
+
}
|
|
1291
|
+
) : void 0;
|
|
1292
|
+
const collapsedCfg = showSideRail ? sideRail?.collapsed : void 0;
|
|
1293
|
+
const collapsedNode = collapsedCfg !== void 0 && sideRail !== void 0 ? /* @__PURE__ */ jsx(
|
|
1294
|
+
CollapsedRail,
|
|
1295
|
+
{
|
|
1296
|
+
footer: collapsedCfg.footer,
|
|
1297
|
+
header: collapsedCfg.header,
|
|
1298
|
+
items: collapsedCfg.items ?? sideRail.items,
|
|
1299
|
+
navigateHint,
|
|
1300
|
+
pathname,
|
|
1301
|
+
regionLabel,
|
|
1302
|
+
onNavigate
|
|
1303
|
+
}
|
|
1304
|
+
) : collapsedSidebarProp;
|
|
1305
|
+
const collapsedRange = collapsedCfg?.range ?? collapsedRailRangeProp;
|
|
1306
|
+
return /* @__PURE__ */ jsx(
|
|
1307
|
+
AppShell,
|
|
1308
|
+
{
|
|
1309
|
+
...shellProps,
|
|
1310
|
+
collapsedRailRange: collapsedRange,
|
|
1311
|
+
collapsedSidebar: collapsedNode,
|
|
1312
|
+
header: headerNode,
|
|
1313
|
+
sidebar: sidebarNode,
|
|
1314
|
+
children
|
|
1315
|
+
}
|
|
1316
|
+
);
|
|
1317
|
+
};
|
|
1318
|
+
var TEXT_ON_PRIMARY4 = "#ffffff";
|
|
1319
|
+
var DEFAULT_MIN_ITEMS = 1;
|
|
1320
|
+
var PillNav = ({
|
|
1321
|
+
items,
|
|
1322
|
+
pathname,
|
|
1323
|
+
onNavigate,
|
|
1324
|
+
regionLabel,
|
|
1325
|
+
navigateHint = (label) => label,
|
|
1326
|
+
minItems = DEFAULT_MIN_ITEMS,
|
|
1327
|
+
containerStyle
|
|
1328
|
+
}) => {
|
|
1329
|
+
const { theme } = useUi();
|
|
1330
|
+
const colors = theme.colors;
|
|
1331
|
+
const primaryColor = theme.palette.primary["500"];
|
|
1332
|
+
if (items.length < minItems) return null;
|
|
1333
|
+
return /* @__PURE__ */ jsx(
|
|
1334
|
+
View,
|
|
1335
|
+
{
|
|
1336
|
+
accessibilityRole: "none",
|
|
1337
|
+
"aria-label": regionLabel,
|
|
1338
|
+
role: "navigation",
|
|
1339
|
+
style: [pillNavStyles.container, containerStyle],
|
|
1340
|
+
children: items.map((item) => {
|
|
1341
|
+
const active = isRouteActive(pathname, item.route);
|
|
1342
|
+
const textColor = active ? TEXT_ON_PRIMARY4 : colors.textSecondary;
|
|
1343
|
+
const pillStyle = active ? { backgroundColor: primaryColor } : { backgroundColor: colors.surfaceElevated };
|
|
1344
|
+
return /* @__PURE__ */ jsxs(
|
|
1345
|
+
FocusableTouchable,
|
|
1346
|
+
{
|
|
1347
|
+
accessibilityHint: navigateHint(item.label),
|
|
1348
|
+
accessibilityLabel: item.label,
|
|
1349
|
+
accessibilityRole: "link",
|
|
1350
|
+
ringColor: primaryColor,
|
|
1351
|
+
style: [pillNavStyles.pill, pillStyle],
|
|
1352
|
+
testID: item.testID ?? item.key,
|
|
1353
|
+
onPress: () => onNavigate(item.route),
|
|
1354
|
+
children: [
|
|
1355
|
+
typeof item.renderIcon === "function" ? item.renderIcon(textColor, NAV_ICON_SIZE) : null,
|
|
1356
|
+
/* @__PURE__ */ jsx(Text, { style: [pillNavStyles.pillText, { color: textColor }], children: item.label })
|
|
1357
|
+
]
|
|
1358
|
+
},
|
|
1359
|
+
item.key
|
|
1360
|
+
);
|
|
1361
|
+
})
|
|
1362
|
+
}
|
|
1363
|
+
);
|
|
1364
|
+
};
|
|
1365
|
+
var TEXT_ON_PRIMARY5 = "#ffffff";
|
|
1366
|
+
var DARK_MODE_ICON_SIZE = 16;
|
|
1367
|
+
var DarkModeControl = ({
|
|
1368
|
+
value,
|
|
1369
|
+
options,
|
|
1370
|
+
onChange,
|
|
1371
|
+
regionLabel,
|
|
1372
|
+
variant = "segmented",
|
|
1373
|
+
testID,
|
|
1374
|
+
containerStyle
|
|
1375
|
+
}) => {
|
|
1376
|
+
const { theme } = useUi();
|
|
1377
|
+
const colors = theme.colors;
|
|
1378
|
+
const primaryColor = theme.palette.primary["500"];
|
|
1379
|
+
const currentIndex = options.findIndex((option) => option.value === value);
|
|
1380
|
+
const current = currentIndex >= 0 ? options[currentIndex] : options[0];
|
|
1381
|
+
const advance = useCallback(() => {
|
|
1382
|
+
if (options.length === 0) return;
|
|
1383
|
+
const from = currentIndex >= 0 ? currentIndex : 0;
|
|
1384
|
+
const next = options[(from + 1) % options.length];
|
|
1385
|
+
if (next !== void 0) onChange(next.value);
|
|
1386
|
+
}, [options, currentIndex, onChange]);
|
|
1387
|
+
if (options.length === 0 || current === void 0) return null;
|
|
1388
|
+
if (variant === "cycle") {
|
|
1389
|
+
const iconColor = colors.text;
|
|
1390
|
+
return /* @__PURE__ */ jsx(View, { "aria-label": regionLabel, style: containerStyle, children: /* @__PURE__ */ jsxs(
|
|
1391
|
+
FocusableTouchable,
|
|
1392
|
+
{
|
|
1393
|
+
accessibilityHint: current.hint,
|
|
1394
|
+
accessibilityLabel: current.label,
|
|
1395
|
+
ringColor: primaryColor,
|
|
1396
|
+
style: [darkModeStyles.cycle, { backgroundColor: colors.surfaceElevated }],
|
|
1397
|
+
testID,
|
|
1398
|
+
onPress: advance,
|
|
1399
|
+
children: [
|
|
1400
|
+
typeof current.renderIcon === "function" ? current.renderIcon(iconColor, DARK_MODE_ICON_SIZE) : null,
|
|
1401
|
+
/* @__PURE__ */ jsx(Text, { style: [darkModeStyles.cycleText, { color: colors.text }], children: current.label })
|
|
1402
|
+
]
|
|
1403
|
+
}
|
|
1404
|
+
) });
|
|
1405
|
+
}
|
|
1406
|
+
return /* @__PURE__ */ jsx(
|
|
1407
|
+
View,
|
|
1408
|
+
{
|
|
1409
|
+
"aria-label": regionLabel,
|
|
1410
|
+
role: "group",
|
|
1411
|
+
style: [darkModeStyles.segmentRow, { borderColor: colors.border }, containerStyle],
|
|
1412
|
+
children: options.map((option) => {
|
|
1413
|
+
const active = option.value === value;
|
|
1414
|
+
const textColor = active ? TEXT_ON_PRIMARY5 : colors.textSecondary;
|
|
1415
|
+
return /* @__PURE__ */ jsxs(
|
|
1416
|
+
FocusableTouchable,
|
|
1417
|
+
{
|
|
1418
|
+
accessibilityHint: option.hint,
|
|
1419
|
+
accessibilityLabel: option.label,
|
|
1420
|
+
ringColor: primaryColor,
|
|
1421
|
+
style: [darkModeStyles.segment, active ? { backgroundColor: primaryColor } : void 0],
|
|
1422
|
+
testID: testID !== void 0 ? `${testID}-${option.value}` : void 0,
|
|
1423
|
+
onPress: () => onChange(option.value),
|
|
1424
|
+
children: [
|
|
1425
|
+
typeof option.renderIcon === "function" ? option.renderIcon(textColor, DARK_MODE_ICON_SIZE) : null,
|
|
1426
|
+
/* @__PURE__ */ jsx(Text, { style: [darkModeStyles.segmentText, { color: textColor }], children: option.label })
|
|
1427
|
+
]
|
|
1428
|
+
},
|
|
1429
|
+
option.value
|
|
1430
|
+
);
|
|
1431
|
+
})
|
|
1432
|
+
}
|
|
1433
|
+
);
|
|
1434
|
+
};
|
|
1077
1435
|
function roleRoutesToNavItems(routes, translate) {
|
|
1078
1436
|
return routes.map((entry) => ({
|
|
1079
1437
|
key: entry.role,
|
|
@@ -1085,6 +1443,6 @@ function accessibleNavItems(user, table, translate) {
|
|
|
1085
1443
|
return roleRoutesToNavItems(resolveAccessibleRoutes(user, table), translate);
|
|
1086
1444
|
}
|
|
1087
1445
|
|
|
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 };
|
|
1446
|
+
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
1447
|
//# sourceMappingURL=index.mjs.map
|
|
1090
1448
|
//# sourceMappingURL=index.mjs.map
|