@12-apps/ui 6.50.1 → 6.51.1

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.
Files changed (61) hide show
  1. package/components-catalog.md +2 -2
  2. package/dist/_internal/components/index.js +7 -7
  3. package/dist/_internal/components/navigation/SectionNav/SectionNav.bar.js +6 -5
  4. package/dist/_internal/components/navigation/SectionNav/SectionNav.helpers.js +5 -1
  5. package/dist/_internal/components/navigation/SectionNav/SectionNav.js +8 -7
  6. package/dist/_internal/components/navigation/SectionNav/SectionNav.parts.js +8 -2
  7. package/dist/_internal/components/navigation/SectionNav/SectionNav.primary.js +3 -3
  8. package/dist/_internal/components/navigation/SectionNav/SectionNav.rail.js +3 -3
  9. package/dist/_internal/components/navigation/SectionNav/SectionNav.sheet.js +3 -3
  10. package/dist/_internal/components/navigation/SectionNav/__stories__/fixtures.js +12 -0
  11. package/dist/_internal/components/navigation/SectionNav/__stories__/fixtures.js.map +1 -1
  12. package/dist/_internal/components/navigation/index.js +8 -7
  13. package/dist/{chunk-SA2ERYVV.js → chunk-5GQYTB3K.js} +3 -3
  14. package/dist/{chunk-GLKQT2DS.js → chunk-A436VORP.js} +33 -4
  15. package/dist/chunk-A436VORP.js.map +1 -0
  16. package/dist/{chunk-RX7J6VRI.js → chunk-HKEBTPKY.js} +119 -42
  17. package/dist/chunk-HKEBTPKY.js.map +1 -0
  18. package/dist/{chunk-VHVI3D4R.js → chunk-P3GBXE73.js} +11 -2
  19. package/dist/chunk-P3GBXE73.js.map +1 -0
  20. package/dist/{chunk-32JMSHEA.js → chunk-S4ZUZ6DS.js} +10 -6
  21. package/dist/chunk-S4ZUZ6DS.js.map +1 -0
  22. package/dist/chunk-WNKRFMSI.js +113 -0
  23. package/dist/chunk-WNKRFMSI.js.map +1 -0
  24. package/dist/chunk-WNZBUR76.js +294 -0
  25. package/dist/chunk-WNZBUR76.js.map +1 -0
  26. package/dist/navigation/SectionNav.js +8 -7
  27. package/dist/types/components/navigation/SectionNav/SectionNav.bar.d.ts.map +1 -1
  28. package/dist/types/components/navigation/SectionNav/SectionNav.helpers.d.ts +12 -1
  29. package/dist/types/components/navigation/SectionNav/SectionNav.helpers.d.ts.map +1 -1
  30. package/dist/types/components/navigation/SectionNav/SectionNav.parts.d.ts +36 -2
  31. package/dist/types/components/navigation/SectionNav/SectionNav.parts.d.ts.map +1 -1
  32. package/dist/types/components/navigation/SectionNav/SectionNav.primary.d.ts +22 -4
  33. package/dist/types/components/navigation/SectionNav/SectionNav.primary.d.ts.map +1 -1
  34. package/dist/types/components/navigation/SectionNav/SectionNav.rail.d.ts.map +1 -1
  35. package/dist/types/components/navigation/SectionNav/SectionNav.sheet.d.ts.map +1 -1
  36. package/dist/types/components/navigation/SectionNav/SectionNav.types.d.ts +81 -5
  37. package/dist/types/components/navigation/SectionNav/SectionNav.types.d.ts.map +1 -1
  38. package/dist/types/components/navigation/SectionNav/__stories__/fixtures.d.ts +11 -1
  39. package/dist/types/components/navigation/SectionNav/__stories__/fixtures.d.ts.map +1 -1
  40. package/dist/types/components/navigation/SectionNav/index.d.ts +1 -1
  41. package/dist/types/components/navigation/SectionNav/index.d.ts.map +1 -1
  42. package/package.json +1 -1
  43. package/src/components/navigation/SectionNav/SectionNav.bar.tsx +166 -90
  44. package/src/components/navigation/SectionNav/SectionNav.helpers.ts +16 -1
  45. package/src/components/navigation/SectionNav/SectionNav.md +40 -4
  46. package/src/components/navigation/SectionNav/SectionNav.parts.tsx +59 -1
  47. package/src/components/navigation/SectionNav/SectionNav.primary.tsx +107 -30
  48. package/src/components/navigation/SectionNav/SectionNav.rail.tsx +154 -41
  49. package/src/components/navigation/SectionNav/SectionNav.sheet.tsx +6 -2
  50. package/src/components/navigation/SectionNav/SectionNav.types.ts +82 -5
  51. package/src/components/navigation/SectionNav/__stories__/fixtures.tsx +21 -1
  52. package/src/components/navigation/SectionNav/index.ts +1 -0
  53. package/dist/chunk-32JMSHEA.js.map +0 -1
  54. package/dist/chunk-43Q6CVPB.js +0 -240
  55. package/dist/chunk-43Q6CVPB.js.map +0 -1
  56. package/dist/chunk-GLKQT2DS.js.map +0 -1
  57. package/dist/chunk-RX7J6VRI.js.map +0 -1
  58. package/dist/chunk-RZ4SBSLP.js +0 -62
  59. package/dist/chunk-RZ4SBSLP.js.map +0 -1
  60. package/dist/chunk-VHVI3D4R.js.map +0 -1
  61. /package/dist/{chunk-SA2ERYVV.js.map → chunk-5GQYTB3K.js.map} +0 -0
@@ -16,11 +16,20 @@ function barSlots(destinations, hasMore, hasPrimary) {
16
16
  if (hasPrimary) slots.splice(Math.floor(slots.length / 2), 0, { kind: "primary" });
17
17
  return slots;
18
18
  }
19
+ function isMenu(primary) {
20
+ return primary !== void 0 && "groups" in primary;
21
+ }
22
+ function destinationState(destination) {
23
+ const active = destination.active === true;
24
+ return { current: active && destination.href !== void 0, lit: active && destination.dimmed !== true };
25
+ }
19
26
 
20
27
  export {
21
28
  shownCount,
22
29
  menuCount,
23
30
  menuActive,
24
- barSlots
31
+ barSlots,
32
+ isMenu,
33
+ destinationState
25
34
  };
26
- //# sourceMappingURL=chunk-VHVI3D4R.js.map
35
+ //# sourceMappingURL=chunk-P3GBXE73.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/navigation/SectionNav/SectionNav.helpers.ts"],"sourcesContent":["import type { SectionNavAction, SectionNavDestination, SectionNavMenu } from './SectionNav.types';\n\n/** A count worth drawing: positive and finite. Zero and \"unknown\" draw nothing. */\nexport function shownCount(count: number | undefined): number | undefined {\n return count !== undefined && Number.isFinite(count) && count > 0 ? count : undefined;\n}\n\n/**\n * The \"more\" slot's badge: its entries' counts, rolled up.\n *\n * The same reason a folded sidebar parent shows its children's counts — the\n * sheet starts closed, so a count only visible once it is opened is one nobody\n * sees.\n */\nexport function menuCount(menu: SectionNavMenu | undefined): number | undefined {\n if (!menu) return undefined;\n const total = menu.groups\n .flatMap((group) => group.entries)\n .reduce((sum, entry) => sum + (shownCount(entry.badge) ?? 0), 0);\n return shownCount(total);\n}\n\n/** Is the viewer on one of this menu's entries? Then its slot reads as current. */\nexport function menuActive(menu: SectionNavMenu | undefined): boolean {\n return menu?.groups.some((group) => group.entries.some((entry) => entry.active === true)) ?? false;\n}\n\n/** What one bar slot holds, in left-to-right order. */\nexport type BarSlot =\n | { kind: 'destination'; destination: SectionNavDestination }\n | { kind: 'more' }\n | { kind: 'primary' };\n\n/**\n * The bar's slots: the destinations, then `more`, with `primary` in the MIDDLE.\n *\n * The middle is where a thumb rests and where a raised button reads as the\n * one thing this bar is for. With four slots it lands between the second and\n * the third; with an odd count it takes the lower middle, so the heavier side\n * is the right one, under the thumb of a right-handed phone.\n */\nexport function barSlots(\n destinations: readonly SectionNavDestination[],\n hasMore: boolean,\n hasPrimary: boolean,\n): BarSlot[] {\n const slots: BarSlot[] = destinations.map((destination) => ({ kind: 'destination', destination }));\n if (hasMore) slots.push({ kind: 'more' });\n if (hasPrimary) slots.splice(Math.floor(slots.length / 2), 0, { kind: 'primary' });\n return slots;\n}\n\n/** A primary that opens a sheet, as opposed to one that acts on tap. */\nexport function isMenu(primary: SectionNavMenu | SectionNavAction | undefined): primary is SectionNavMenu {\n return primary !== undefined && 'groups' in primary;\n}\n\n/**\n * How a destination reads. `current` is `aria-current=\"page\"` and belongs to a\n * LINK only — an action slot that is ON reports `aria-pressed` instead. `lit`\n * is the look, and a `dimmed` slot is never lit: it says \"not now\".\n */\nexport function destinationState(destination: SectionNavDestination): { current: boolean; lit: boolean } {\n const active = destination.active === true;\n return { current: active && destination.href !== undefined, lit: active && destination.dimmed !== true };\n}\n"],"mappings":";AAGO,SAAS,WAAW,OAA+C;AACxE,SAAO,UAAU,UAAa,OAAO,SAAS,KAAK,KAAK,QAAQ,IAAI,QAAQ;AAC9E;AASO,SAAS,UAAU,MAAsD;AAC9E,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,QAAQ,KAAK,OAChB,QAAQ,CAAC,UAAU,MAAM,OAAO,EAChC,OAAO,CAAC,KAAK,UAAU,OAAO,WAAW,MAAM,KAAK,KAAK,IAAI,CAAC;AACjE,SAAO,WAAW,KAAK;AACzB;AAGO,SAAS,WAAW,MAA2C;AACpE,SAAO,MAAM,OAAO,KAAK,CAAC,UAAU,MAAM,QAAQ,KAAK,CAAC,UAAU,MAAM,WAAW,IAAI,CAAC,KAAK;AAC/F;AAgBO,SAAS,SACd,cACA,SACA,YACW;AACX,QAAM,QAAmB,aAAa,IAAI,CAAC,iBAAiB,EAAE,MAAM,eAAe,YAAY,EAAE;AACjG,MAAI,QAAS,OAAM,KAAK,EAAE,MAAM,OAAO,CAAC;AACxC,MAAI,WAAY,OAAM,OAAO,KAAK,MAAM,MAAM,SAAS,CAAC,GAAG,GAAG,EAAE,MAAM,UAAU,CAAC;AACjF,SAAO;AACT;AAGO,SAAS,OAAO,SAAmF;AACxG,SAAO,YAAY,UAAa,YAAY;AAC9C;AAOO,SAAS,iBAAiB,aAAwE;AACvG,QAAM,SAAS,YAAY,WAAW;AACtC,SAAO,EAAE,SAAS,UAAU,YAAY,SAAS,QAAW,KAAK,UAAU,YAAY,WAAW,KAAK;AACzG;","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  CountedIcon,
5
5
  controlProps,
6
6
  focusRing
7
- } from "./chunk-GLKQT2DS.js";
7
+ } from "./chunk-A436VORP.js";
8
8
  import {
9
9
  Drawer,
10
10
  DrawerContent,
@@ -26,13 +26,14 @@ function GridEntry({ entry, linkComponent, copy, testId, onDone }) {
26
26
  ...controlProps({
27
27
  href: entry.href,
28
28
  linkComponent,
29
+ inert: entry.disabled === true,
29
30
  onClick: () => {
30
31
  entry.onSelect?.();
31
32
  onDone();
32
33
  }
33
34
  }),
34
35
  "aria-current": entry.active ? "page" : void 0,
35
- "data-testid": `${testId}-entry-${entry.id}`,
36
+ "data-testid": entry.dataTestId ?? `${testId}-entry-${entry.id}`,
36
37
  sx: {
37
38
  ...CONTROL_RESET,
38
39
  ...focusRing(theme),
@@ -48,7 +49,8 @@ function GridEntry({ entry, linkComponent, copy, testId, onDone }) {
48
49
  textAlign: "center",
49
50
  bgcolor: entry.active ? "action.selected" : "action.hover",
50
51
  color: entry.active ? "primary.main" : "text.primary",
51
- "& svg": { color: "primary.main" }
52
+ "& svg": { color: "primary.main" },
53
+ "&:disabled": { color: "text.disabled", "& svg": { color: "text.disabled" } }
52
54
  },
53
55
  children: [
54
56
  /* @__PURE__ */ jsx(CountedIcon, { icon: entry.icon, count: entry.badge, label: copy.badge, testId: `${testId}-badge-${entry.id}` }),
@@ -65,13 +67,14 @@ function ListEntry({ entry, linkComponent, copy, testId, onDone }) {
65
67
  ...controlProps({
66
68
  href: entry.href,
67
69
  linkComponent,
70
+ inert: entry.disabled === true,
68
71
  onClick: () => {
69
72
  entry.onSelect?.();
70
73
  onDone();
71
74
  }
72
75
  }),
73
76
  "aria-current": entry.active ? "page" : void 0,
74
- "data-testid": `${testId}-entry-${entry.id}`,
77
+ "data-testid": entry.dataTestId ?? `${testId}-entry-${entry.id}`,
75
78
  sx: {
76
79
  ...CONTROL_RESET,
77
80
  ...focusRing(theme),
@@ -85,7 +88,8 @@ function ListEntry({ entry, linkComponent, copy, testId, onDone }) {
85
88
  borderRadius: 1.5,
86
89
  textAlign: "start",
87
90
  bgcolor: entry.active ? "action.selected" : "action.hover",
88
- "& svg": { color: "primary.main" }
91
+ "& svg": { color: "primary.main" },
92
+ "&:disabled": { color: "text.disabled", "& svg": { color: "text.disabled" } }
89
93
  },
90
94
  children: [
91
95
  /* @__PURE__ */ jsx(CountedIcon, { icon: entry.icon, count: entry.badge, label: copy.badge, testId: `${testId}-badge-${entry.id}` }),
@@ -171,4 +175,4 @@ function SectionNavSheet({
171
175
  export {
172
176
  SectionNavSheet
173
177
  };
174
- //# sourceMappingURL=chunk-32JMSHEA.js.map
178
+ //# sourceMappingURL=chunk-S4ZUZ6DS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/navigation/SectionNav/SectionNav.sheet.tsx"],"sourcesContent":["import Typography from '@mui/material/Typography/index.js';\nimport { useTheme } from '@mui/material/styles/index.js';\nimport type { ElementType } from 'react';\n\nimport { rem } from '../../../tokens/scales';\nimport { Drawer, DrawerContent, DrawerHeader } from '../../layout/Drawer';\n\nimport { Box, CONTROL_RESET, CountedIcon, controlProps, focusRing } from './SectionNav.parts';\nimport type { SectionNavEntry, SectionNavGroup, SectionNavMenu } from './SectionNav.types';\nimport type { SectionNavCopy } from '../../../copy';\n\ninterface EntryProps {\n entry: SectionNavEntry;\n linkComponent: ElementType | undefined;\n copy: SectionNavCopy;\n testId: string;\n onDone: () => void;\n}\n\n/** A tile in a `grid` group: icon over a short label. */\nfunction GridEntry({ entry, linkComponent, copy, testId, onDone }: EntryProps): React.JSX.Element {\n const theme = useTheme();\n return (\n <Box\n {...controlProps({\n href: entry.href,\n linkComponent,\n inert: entry.disabled === true,\n onClick: () => {\n entry.onSelect?.();\n onDone();\n },\n })}\n aria-current={entry.active ? 'page' : undefined}\n data-testid={entry.dataTestId ?? `${testId}-entry-${entry.id}`}\n sx={{\n ...CONTROL_RESET,\n ...focusRing(theme),\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 0.75,\n minHeight: rem(theme, 76),\n px: 0.5,\n py: 1,\n borderRadius: 1.5,\n textAlign: 'center',\n bgcolor: entry.active ? 'action.selected' : 'action.hover',\n color: entry.active ? 'primary.main' : 'text.primary',\n '& svg': { color: 'primary.main' },\n '&:disabled': { color: 'text.disabled', '& svg': { color: 'text.disabled' } },\n }}\n >\n <CountedIcon icon={entry.icon} count={entry.badge} label={copy.badge} testId={`${testId}-badge-${entry.id}`} />\n <Typography component=\"span\" variant=\"caption\" sx={{ lineHeight: 1.2, fontWeight: entry.active ? 700 : 500 }}>\n {entry.label}\n </Typography>\n </Box>\n );\n}\n\n/** A row in a `list` group: icon, label, and the description under it. */\nfunction ListEntry({ entry, linkComponent, copy, testId, onDone }: EntryProps): React.JSX.Element {\n const theme = useTheme();\n return (\n <Box\n {...controlProps({\n href: entry.href,\n linkComponent,\n inert: entry.disabled === true,\n onClick: () => {\n entry.onSelect?.();\n onDone();\n },\n })}\n aria-current={entry.active ? 'page' : undefined}\n data-testid={entry.dataTestId ?? `${testId}-entry-${entry.id}`}\n sx={{\n ...CONTROL_RESET,\n ...focusRing(theme),\n display: 'flex',\n alignItems: 'center',\n gap: 1.5,\n width: '100%',\n minHeight: rem(theme, 52),\n px: 1.5,\n py: 1,\n borderRadius: 1.5,\n textAlign: 'start',\n bgcolor: entry.active ? 'action.selected' : 'action.hover',\n '& svg': { color: 'primary.main' },\n '&:disabled': { color: 'text.disabled', '& svg': { color: 'text.disabled' } },\n }}\n >\n <CountedIcon icon={entry.icon} count={entry.badge} label={copy.badge} testId={`${testId}-badge-${entry.id}`} />\n <Box component=\"span\" sx={{ display: 'flex', flexDirection: 'column', minWidth: 0 }}>\n <Typography component=\"span\" variant=\"body2\" sx={{ fontWeight: 600 }}>\n {entry.label}\n </Typography>\n {entry.description ? (\n <Typography component=\"span\" variant=\"caption\" color=\"text.secondary\">\n {entry.description}\n </Typography>\n ) : null}\n </Box>\n </Box>\n );\n}\n\n/** One titled run of entries, as tiles or rows. */\nfunction SheetGroup({\n group,\n linkComponent,\n copy,\n testId,\n onDone,\n}: Omit<EntryProps, 'entry'> & { group: SectionNavGroup }): React.JSX.Element {\n const grid = group.layout === 'grid';\n const Entry = grid ? GridEntry : ListEntry;\n return (\n <Box component=\"section\" data-testid={`${testId}-group-${group.id}`} sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>\n {group.title ? (\n <Typography variant=\"overline\" color=\"text.secondary\" sx={{ lineHeight: 1.6 }}>\n {group.title}\n </Typography>\n ) : null}\n <Box\n sx={\n grid\n ? { display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 1 }\n : { display: 'flex', flexDirection: 'column', gap: 0.75 }\n }\n >\n {group.entries.map((entry) => (\n <Entry key={entry.id} entry={entry} linkComponent={linkComponent} copy={copy} testId={testId} onDone={onDone} />\n ))}\n </Box>\n </Box>\n );\n}\n\n/**\n * A menu opened from the bar: a bottom sheet over the page.\n *\n * Choosing an entry closes it — a link has somewhere to go and an action has\n * something to do, and neither wants the sheet still covering the screen.\n */\nexport function SectionNavSheet({\n menu,\n open,\n onClose,\n linkComponent,\n copy,\n testId,\n bottomOffset,\n}: {\n menu: SectionNavMenu;\n open: boolean;\n onClose: () => void;\n linkComponent: ElementType | undefined;\n copy: SectionNavCopy;\n testId: string;\n /** How far above the viewport's foot the sheet stops — the bar's own height, so the bar stays visible. */\n bottomOffset: string;\n}): React.JSX.Element {\n const theme = useTheme();\n return (\n <Drawer\n open={open}\n onClose={onClose}\n anchor=\"bottom\"\n height=\"auto\"\n dataTestId={testId}\n paperSx={{\n borderTopLeftRadius: rem(theme, Number(theme.shape.borderRadius) * 3),\n borderTopRightRadius: rem(theme, Number(theme.shape.borderRadius) * 3),\n maxHeight: `calc(85dvh - ${bottomOffset})`,\n bottom: bottomOffset,\n }}\n >\n {/* The library Drawer names nothing: the dialog role and its name live\n here, around everything the focus trap holds. */}\n <Box\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={menu.title}\n sx={{ display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0 }}\n >\n <DrawerHeader onClose={onClose} closeLabel={copy.close} dataTestId={`${testId}-header`}>\n {menu.title}\n </DrawerHeader>\n <DrawerContent>\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n {menu.groups.map((group) => (\n <SheetGroup\n key={group.id}\n group={group}\n linkComponent={linkComponent}\n copy={copy}\n testId={testId}\n onDone={onClose}\n />\n ))}\n </Box>\n </DrawerContent>\n </Box>\n </Drawer>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,113 @@
1
+ import {
2
+ Box,
3
+ CONTROL_RESET,
4
+ NOT_LIVE,
5
+ SlotIcon,
6
+ focusRing
7
+ } from "./chunk-A436VORP.js";
8
+ import {
9
+ rem
10
+ } from "./chunk-YKCAJ2TN.js";
11
+
12
+ // src/components/navigation/SectionNav/SectionNav.primary.tsx
13
+ import Typography from "@mui/material/Typography/index.js";
14
+ import { useTheme } from "@mui/material/styles/index.js";
15
+ import { jsx, jsxs } from "react/jsx-runtime";
16
+ function RaisedActionButton({
17
+ label,
18
+ icon,
19
+ onClick,
20
+ open,
21
+ closeLabel,
22
+ captioned = false,
23
+ disabled = false,
24
+ loading = false,
25
+ dataTestId = "raised-action"
26
+ }) {
27
+ const theme = useTheme();
28
+ const expanded = open === true;
29
+ return /* @__PURE__ */ jsxs(
30
+ Box,
31
+ {
32
+ sx: {
33
+ flex: "none",
34
+ display: "flex",
35
+ flexDirection: "column",
36
+ alignItems: "center",
37
+ justifyContent: "flex-start",
38
+ px: 0.5
39
+ },
40
+ children: [
41
+ /* @__PURE__ */ jsx(
42
+ Box,
43
+ {
44
+ component: "button",
45
+ type: "button",
46
+ ...raisedState({ onClick, disabled, loading }),
47
+ "aria-label": expanded && closeLabel ? closeLabel : label,
48
+ "aria-expanded": open,
49
+ "data-testid": dataTestId,
50
+ sx: raisedSx(theme, expanded),
51
+ children: /* @__PURE__ */ jsx(SlotIcon, { icon, loading })
52
+ }
53
+ ),
54
+ captioned ? /* @__PURE__ */ jsx(RaisedCaption, { label, inert: disabled || loading }) : null
55
+ ]
56
+ }
57
+ );
58
+ }
59
+ function raisedState({
60
+ onClick,
61
+ disabled,
62
+ loading
63
+ }) {
64
+ const busy = loading && !disabled;
65
+ return {
66
+ onClick: busy ? void 0 : onClick,
67
+ disabled,
68
+ "aria-disabled": busy ? "true" : void 0,
69
+ "aria-busy": loading || void 0
70
+ };
71
+ }
72
+ function RaisedCaption({ label, inert }) {
73
+ return /* @__PURE__ */ jsx(
74
+ Typography,
75
+ {
76
+ component: "span",
77
+ variant: "caption",
78
+ "aria-hidden": true,
79
+ sx: { lineHeight: 1.3, mt: 0.25, whiteSpace: "nowrap", color: inert ? "text.disabled" : "text.primary" },
80
+ children: label
81
+ }
82
+ );
83
+ }
84
+ function raisedSx(theme, expanded) {
85
+ const size = rem(theme, 52);
86
+ return {
87
+ ...CONTROL_RESET,
88
+ ...focusRing(theme),
89
+ width: size,
90
+ height: size,
91
+ // Lifted half out of the bar: the one control that is not a place.
92
+ marginTop: rem(theme, -18),
93
+ borderRadius: "50%",
94
+ display: "flex",
95
+ alignItems: "center",
96
+ justifyContent: "center",
97
+ bgcolor: "primary.main",
98
+ color: "primary.contrastText",
99
+ boxShadow: theme.shadows[6],
100
+ [NOT_LIVE]: { cursor: "default", bgcolor: "action.disabledBackground", color: "text.disabled", boxShadow: "none" },
101
+ "& svg": {
102
+ fontSize: rem(theme, 26),
103
+ transition: theme.transitions.create("transform", { duration: theme.transitions.duration.shorter }),
104
+ transform: expanded ? "rotate(45deg)" : "none"
105
+ },
106
+ "@media (prefers-reduced-motion: reduce)": { "& svg": { transition: "none" } }
107
+ };
108
+ }
109
+
110
+ export {
111
+ RaisedActionButton
112
+ };
113
+ //# sourceMappingURL=chunk-WNKRFMSI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/navigation/SectionNav/SectionNav.primary.tsx"],"sourcesContent":["import Typography from '@mui/material/Typography/index.js';\nimport { useTheme, type SxProps, type Theme } from '@mui/material/styles/index.js';\nimport type { ReactNode } from 'react';\n\nimport { rem } from '../../../tokens/scales';\n\nimport { Box, CONTROL_RESET, NOT_LIVE, SlotIcon, focusRing } from './SectionNav.parts';\n\nexport interface RaisedActionButtonProps {\n /**\n * The button's accessible name. Drawn under the button only when\n * `captioned`; the caption is hidden from assistive tech, so the name is\n * read once either way.\n */\n label: string;\n icon: ReactNode;\n onClick: () => void;\n /**\n * Whether what the button opens is open. Omit for a button that opens\n * nothing (a plain action): it then carries no `aria-expanded` and its icon\n * never turns.\n */\n open?: boolean;\n /** The name it takes while `open` — the same control closes what it opened. REQUIRED with `open`. */\n closeLabel?: string;\n /**\n * Draw `label` under the button. A bar of VERBS names the act it is for; a\n * bar of places can leave its one action to the icon.\n */\n captioned?: boolean;\n /** Dimmed and not operable: a native `disabled` button. */\n disabled?: boolean;\n /**\n * A write it started is in flight: a spinner replaces the icon, it reports\n * `aria-busy` and `aria-disabled`, and a tap is ignored. It stays focusable,\n * so the keyboard does not lose its place while the write answers.\n */\n loading?: boolean;\n dataTestId?: string;\n}\n\n/**\n * The raised round button in the middle of a bottom bar — the one control in\n * the row that is an ACTION rather than a place.\n *\n * Lifted half out of the bar so it reads as different in kind from the tabs\n * beside it. Uncaptioned it costs the row less width than a tab: that width is\n * what lets a bar keep four labelled tabs AND this button at 320px. A bar of\n * verbs captions it, naming the act under the button.\n *\n * `SectionNav` draws it for its `primary` menu. It is exported on its own for\n * a bar the host already draws — drop it between two tabs, in a flex row.\n */\nexport function RaisedActionButton({\n label,\n icon,\n onClick,\n open,\n closeLabel,\n captioned = false,\n disabled = false,\n loading = false,\n dataTestId = 'raised-action',\n}: RaisedActionButtonProps): React.JSX.Element {\n const theme = useTheme();\n const expanded = open === true;\n return (\n <Box\n sx={{\n flex: 'none',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'flex-start',\n px: 0.5,\n }}\n >\n <Box\n component=\"button\"\n type=\"button\"\n {...raisedState({ onClick, disabled, loading })}\n aria-label={expanded && closeLabel ? closeLabel : label}\n aria-expanded={open}\n data-testid={dataTestId}\n sx={raisedSx(theme, expanded)}\n >\n <SlotIcon icon={icon} loading={loading} />\n </Box>\n {captioned ? <RaisedCaption label={label} inert={disabled || loading} /> : null}\n </Box>\n );\n}\n\n/**\n * The button's operability. Only `disabled` is native: an in-flight button\n * keeps its focus, reports `aria-busy` and `aria-disabled`, and drops the click.\n */\nfunction raisedState({\n onClick,\n disabled,\n loading,\n}: {\n onClick: () => void;\n disabled: boolean;\n loading: boolean;\n}): Record<string, unknown> {\n const busy = loading && !disabled;\n return {\n onClick: busy ? undefined : onClick,\n disabled,\n 'aria-disabled': busy ? 'true' : undefined,\n 'aria-busy': loading || undefined,\n };\n}\n\n/**\n * The label under a captioned button. Hidden from assistive tech: the button\n * already carries the same words as its name, and reading them twice is noise.\n */\nfunction RaisedCaption({ label, inert }: { label: string; inert: boolean }): React.JSX.Element {\n return (\n <Typography\n component=\"span\"\n variant=\"caption\"\n aria-hidden\n sx={{ lineHeight: 1.3, mt: 0.25, whiteSpace: 'nowrap', color: inert ? 'text.disabled' : 'text.primary' }}\n >\n {label}\n </Typography>\n );\n}\n\n/** The round button: lifted half out of the bar, its icon turning while what it opened is open. */\nfunction raisedSx(theme: Theme, expanded: boolean): SxProps<Theme> {\n const size = rem(theme, 52);\n return {\n ...CONTROL_RESET,\n ...focusRing(theme),\n width: size,\n height: size,\n // Lifted half out of the bar: the one control that is not a place.\n marginTop: rem(theme, -18),\n borderRadius: '50%',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n bgcolor: 'primary.main',\n color: 'primary.contrastText',\n boxShadow: theme.shadows[6],\n [NOT_LIVE]: { cursor: 'default', bgcolor: 'action.disabledBackground', color: 'text.disabled', boxShadow: 'none' },\n '& svg': {\n fontSize: rem(theme, 26),\n transition: theme.transitions.create('transform', { duration: theme.transitions.duration.shorter }),\n transform: expanded ? 'rotate(45deg)' : 'none',\n },\n '@media (prefers-reduced-motion: reduce)': { '& svg': { transition: 'none' } },\n } as SxProps<Theme>;\n}\n"],"mappings":";;;;;;;;;;;;AAAA,OAAO,gBAAgB;AACvB,SAAS,gBAA0C;AAkE/C,SAmBI,KAnBJ;AAdG,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,UAAU;AAAA,EACV,aAAa;AACf,GAA+C;AAC7C,QAAM,QAAQ,SAAS;AACvB,QAAM,WAAW,SAAS;AAC1B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,IAAI;AAAA,QACF,MAAM;AAAA,QACN,SAAS;AAAA,QACT,eAAe;AAAA,QACf,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,IAAI;AAAA,MACN;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAK;AAAA,YACJ,GAAG,YAAY,EAAE,SAAS,UAAU,QAAQ,CAAC;AAAA,YAC9C,cAAY,YAAY,aAAa,aAAa;AAAA,YAClD,iBAAe;AAAA,YACf,eAAa;AAAA,YACb,IAAI,SAAS,OAAO,QAAQ;AAAA,YAE5B,8BAAC,YAAS,MAAY,SAAkB;AAAA;AAAA,QAC1C;AAAA,QACC,YAAY,oBAAC,iBAAc,OAAc,OAAO,YAAY,SAAS,IAAK;AAAA;AAAA;AAAA,EAC7E;AAEJ;AAMA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF,GAI4B;AAC1B,QAAM,OAAO,WAAW,CAAC;AACzB,SAAO;AAAA,IACL,SAAS,OAAO,SAAY;AAAA,IAC5B;AAAA,IACA,iBAAiB,OAAO,SAAS;AAAA,IACjC,aAAa,WAAW;AAAA,EAC1B;AACF;AAMA,SAAS,cAAc,EAAE,OAAO,MAAM,GAAyD;AAC7F,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,SAAQ;AAAA,MACR,eAAW;AAAA,MACX,IAAI,EAAE,YAAY,KAAK,IAAI,MAAM,YAAY,UAAU,OAAO,QAAQ,kBAAkB,eAAe;AAAA,MAEtG;AAAA;AAAA,EACH;AAEJ;AAGA,SAAS,SAAS,OAAc,UAAmC;AACjE,QAAM,OAAO,IAAI,OAAO,EAAE;AAC1B,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG,UAAU,KAAK;AAAA,IAClB,OAAO;AAAA,IACP,QAAQ;AAAA;AAAA,IAER,WAAW,IAAI,OAAO,GAAG;AAAA,IACzB,cAAc;AAAA,IACd,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,SAAS;AAAA,IACT,OAAO;AAAA,IACP,WAAW,MAAM,QAAQ,CAAC;AAAA,IAC1B,CAAC,QAAQ,GAAG,EAAE,QAAQ,WAAW,SAAS,6BAA6B,OAAO,iBAAiB,WAAW,OAAO;AAAA,IACjH,SAAS;AAAA,MACP,UAAU,IAAI,OAAO,EAAE;AAAA,MACvB,YAAY,MAAM,YAAY,OAAO,aAAa,EAAE,UAAU,MAAM,YAAY,SAAS,QAAQ,CAAC;AAAA,MAClG,WAAW,WAAW,kBAAkB;AAAA,IAC1C;AAAA,IACA,2CAA2C,EAAE,SAAS,EAAE,YAAY,OAAO,EAAE;AAAA,EAC/E;AACF;","names":[]}
@@ -0,0 +1,294 @@
1
+ import {
2
+ SectionNavSheet
3
+ } from "./chunk-S4ZUZ6DS.js";
4
+ import {
5
+ RaisedActionButton
6
+ } from "./chunk-WNKRFMSI.js";
7
+ import {
8
+ Box,
9
+ CONTROL_RESET,
10
+ CountedIcon,
11
+ NOT_LIVE,
12
+ SlotIcon,
13
+ controlProps,
14
+ destinationControl,
15
+ focusRing
16
+ } from "./chunk-A436VORP.js";
17
+ import {
18
+ barSlots,
19
+ destinationState,
20
+ isMenu,
21
+ menuActive,
22
+ menuCount
23
+ } from "./chunk-P3GBXE73.js";
24
+ import {
25
+ rem
26
+ } from "./chunk-YKCAJ2TN.js";
27
+ import {
28
+ stackedOverlayZIndex
29
+ } from "./chunk-MFU4Y25U.js";
30
+
31
+ // src/components/navigation/SectionNav/SectionNav.bar.tsx
32
+ import Typography from "@mui/material/Typography/index.js";
33
+ import { useTheme } from "@mui/material/styles/index.js";
34
+ import { useState } from "react";
35
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
36
+ var barHeight = (theme) => rem(theme, 60);
37
+ function sectionNavBarInset(theme) {
38
+ return `calc(${barHeight(theme)} + env(safe-area-inset-bottom))`;
39
+ }
40
+ function Slot({
41
+ label,
42
+ icon,
43
+ count,
44
+ current,
45
+ lit,
46
+ copy,
47
+ testId,
48
+ control,
49
+ expanded,
50
+ loading = false
51
+ }) {
52
+ const theme = useTheme();
53
+ return /* @__PURE__ */ jsxs(
54
+ Box,
55
+ {
56
+ ...control,
57
+ "aria-current": current ? "page" : void 0,
58
+ "aria-expanded": expanded,
59
+ "aria-busy": loading || void 0,
60
+ "data-lit": lit ? "true" : void 0,
61
+ "data-testid": testId,
62
+ sx: slotSx(theme, lit),
63
+ children: [
64
+ /* @__PURE__ */ jsx(
65
+ CountedIcon,
66
+ {
67
+ icon: /* @__PURE__ */ jsx(SlotIcon, { icon, loading }),
68
+ count,
69
+ label: copy.badge,
70
+ testId: `${testId}-badge`
71
+ }
72
+ ),
73
+ /* @__PURE__ */ jsx(
74
+ Typography,
75
+ {
76
+ component: "span",
77
+ variant: "caption",
78
+ sx: {
79
+ maxWidth: "100%",
80
+ overflow: "hidden",
81
+ textOverflow: "ellipsis",
82
+ whiteSpace: "nowrap",
83
+ lineHeight: 1.3,
84
+ fontWeight: lit ? 700 : 400
85
+ },
86
+ children: label
87
+ }
88
+ )
89
+ ]
90
+ }
91
+ );
92
+ }
93
+ function slotSx(theme, lit) {
94
+ return {
95
+ ...CONTROL_RESET,
96
+ ...focusRing(theme),
97
+ flex: 1,
98
+ minWidth: 0,
99
+ display: "flex",
100
+ flexDirection: "column",
101
+ alignItems: "center",
102
+ justifyContent: "center",
103
+ gap: 0.25,
104
+ position: "relative",
105
+ color: lit ? "primary.main" : "text.secondary",
106
+ // The current slot is marked by more than its colour: a short rule on
107
+ // its top edge, so the state survives a colour-blind reading.
108
+ '&[data-lit="true"]::before': {
109
+ content: '""',
110
+ position: "absolute",
111
+ top: 0,
112
+ insetInline: "22%",
113
+ height: rem(theme, 3),
114
+ borderBottomLeftRadius: rem(theme, 3),
115
+ borderBottomRightRadius: rem(theme, 3),
116
+ bgcolor: "primary.main"
117
+ },
118
+ "& svg": { fontSize: rem(theme, 22) },
119
+ [NOT_LIVE]: { color: "text.disabled" }
120
+ };
121
+ }
122
+ function PrimarySlot({
123
+ primary,
124
+ context
125
+ }) {
126
+ const testId = primary.dataTestId ?? `${context.dataTestId}-primary`;
127
+ if (!isMenu(primary)) {
128
+ return /* @__PURE__ */ jsx(
129
+ RaisedActionButton,
130
+ {
131
+ label: primary.label,
132
+ icon: primary.icon,
133
+ captioned: true,
134
+ disabled: primary.disabled,
135
+ loading: primary.loading,
136
+ dataTestId: testId,
137
+ onClick: () => {
138
+ context.close();
139
+ primary.onSelect();
140
+ }
141
+ }
142
+ );
143
+ }
144
+ return /* @__PURE__ */ jsx(
145
+ RaisedActionButton,
146
+ {
147
+ label: primary.label,
148
+ icon: primary.icon,
149
+ open: context.open === "primary",
150
+ closeLabel: context.copy.close,
151
+ disabled: primary.disabled,
152
+ dataTestId: testId,
153
+ onClick: () => context.toggle("primary")
154
+ }
155
+ );
156
+ }
157
+ function MoreSlot({ more, context }) {
158
+ const { open } = context;
159
+ return /* @__PURE__ */ jsx(
160
+ Slot,
161
+ {
162
+ label: more.label,
163
+ icon: more.icon,
164
+ count: menuCount(more),
165
+ current: false,
166
+ lit: open === "more" || open === null && menuActive(more),
167
+ expanded: open === "more",
168
+ copy: context.copy,
169
+ testId: more.dataTestId ?? `${context.dataTestId}-more`,
170
+ control: controlProps({
171
+ href: void 0,
172
+ linkComponent: context.linkComponent,
173
+ inert: more.disabled === true,
174
+ onClick: () => context.toggle("more")
175
+ })
176
+ }
177
+ );
178
+ }
179
+ function DestinationSlot({
180
+ destination,
181
+ context
182
+ }) {
183
+ const { current, lit } = destinationState(destination);
184
+ return /* @__PURE__ */ jsx(
185
+ Slot,
186
+ {
187
+ label: destination.label,
188
+ icon: destination.icon,
189
+ count: destination.badge,
190
+ current,
191
+ lit: context.open === null && lit,
192
+ copy: context.copy,
193
+ testId: destination.dataTestId ?? `${context.dataTestId}-dest-${destination.id}`,
194
+ loading: destination.loading === true,
195
+ control: destinationControl(destination, context.linkComponent, () => {
196
+ context.close();
197
+ destination.onSelect?.();
198
+ })
199
+ }
200
+ );
201
+ }
202
+ function BarSlotView({
203
+ slot,
204
+ primary,
205
+ more,
206
+ context
207
+ }) {
208
+ if (slot.kind === "primary") return primary ? /* @__PURE__ */ jsx(PrimarySlot, { primary, context }) : null;
209
+ if (slot.kind === "more") return more ? /* @__PURE__ */ jsx(MoreSlot, { more, context }) : null;
210
+ return /* @__PURE__ */ jsx(DestinationSlot, { destination: slot.destination, context });
211
+ }
212
+ function SectionNavBar({
213
+ label,
214
+ destinations,
215
+ primary,
216
+ more,
217
+ linkComponent,
218
+ copy,
219
+ dataTestId
220
+ }) {
221
+ const sheetMenu = isMenu(primary) ? primary : void 0;
222
+ const theme = useTheme();
223
+ const [open, setOpen] = useState(null);
224
+ const toggle = (menu) => setOpen((current) => current === menu ? null : menu);
225
+ const close = () => setOpen(null);
226
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
227
+ /* @__PURE__ */ jsx(
228
+ Box,
229
+ {
230
+ component: "nav",
231
+ "aria-label": label,
232
+ "data-testid": dataTestId,
233
+ sx: {
234
+ flex: "none",
235
+ display: "flex",
236
+ alignItems: "stretch",
237
+ boxSizing: "border-box",
238
+ height: sectionNavBarInset(theme),
239
+ paddingBottom: "env(safe-area-inset-bottom)",
240
+ borderTop: `1px solid ${theme.palette.divider}`,
241
+ bgcolor: "background.paper",
242
+ // Above the backdrop ONLY while one of its own sheets is open, so the
243
+ // primary button can close what it opened. Raised all the time it
244
+ // would sit over every dialog the page opens, and on a small phone a
245
+ // dialog's own footer is exactly where the bar is. `stackedOverlayZIndex`,
246
+ // not `zIndex.modal + 1`: a host lifting a bottom Drawer clear of a
247
+ // stacked sheet catches this bar's OWN sheets too.
248
+ position: "relative",
249
+ zIndex: open === null ? "auto" : stackedOverlayZIndex(theme) + 1
250
+ },
251
+ children: barSlots(destinations, more !== void 0, primary !== void 0).map((slot) => /* @__PURE__ */ jsx(
252
+ BarSlotView,
253
+ {
254
+ slot,
255
+ primary,
256
+ more,
257
+ context: { open, toggle, close, linkComponent, copy, dataTestId }
258
+ },
259
+ slot.kind === "destination" ? `dest-${slot.destination.id}` : `menu-${slot.kind}`
260
+ ))
261
+ }
262
+ ),
263
+ sheetMenu ? /* @__PURE__ */ jsx(
264
+ SectionNavSheet,
265
+ {
266
+ menu: sheetMenu,
267
+ open: open === "primary",
268
+ onClose: close,
269
+ linkComponent,
270
+ copy,
271
+ testId: `${dataTestId}-primary-sheet`,
272
+ bottomOffset: sectionNavBarInset(theme)
273
+ }
274
+ ) : null,
275
+ more ? /* @__PURE__ */ jsx(
276
+ SectionNavSheet,
277
+ {
278
+ menu: more,
279
+ open: open === "more",
280
+ onClose: close,
281
+ linkComponent,
282
+ copy,
283
+ testId: `${dataTestId}-more-sheet`,
284
+ bottomOffset: sectionNavBarInset(theme)
285
+ }
286
+ ) : null
287
+ ] });
288
+ }
289
+
290
+ export {
291
+ sectionNavBarInset,
292
+ SectionNavBar
293
+ };
294
+ //# sourceMappingURL=chunk-WNZBUR76.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/navigation/SectionNav/SectionNav.bar.tsx"],"sourcesContent":["import Typography from '@mui/material/Typography/index.js';\nimport { useTheme, type SxProps, type Theme } from '@mui/material/styles/index.js';\nimport { useState, type ElementType, type ReactNode } from 'react';\n\nimport type { SectionNavCopy } from '../../../copy';\nimport { stackedOverlayZIndex } from '../../../tokens/layers';\nimport { rem } from '../../../tokens/scales';\n\nimport { barSlots, destinationState, isMenu, menuActive, menuCount, type BarSlot } from './SectionNav.helpers';\nimport {\n Box,\n CONTROL_RESET,\n CountedIcon,\n NOT_LIVE,\n SlotIcon,\n controlProps,\n destinationControl,\n focusRing,\n} from './SectionNav.parts';\nimport { RaisedActionButton } from './SectionNav.primary';\nimport { SectionNavSheet } from './SectionNav.sheet';\nimport type { SectionNavAction, SectionNavDestination, SectionNavMenu, SectionNavProps } from './SectionNav.types';\n\n/** Which of the bar's two menus is open, if any. */\ntype OpenMenu = 'primary' | 'more' | null;\n\n/** The bar's height above the safe area — tall enough for an icon over a label. */\nconst barHeight = (theme: Parameters<typeof rem>[0]): string => rem(theme, 60);\n\n/**\n * The bar's full height on screen, the safe area included — where its sheets\n * stop, and what a host reserves at the foot of its content so nothing it\n * floats (a toast, a receipt) lands under the bar.\n */\nexport function sectionNavBarInset(theme: Parameters<typeof rem>[0]): string {\n return `calc(${barHeight(theme)} + env(safe-area-inset-bottom))`;\n}\n\n/**\n * One slot: icon over label, a count on the icon.\n *\n * `current` is the page the viewer is on and is what `aria-current` reports —\n * a link's claim only; an action slot that is ON says so with `aria-pressed`,\n * which arrives in `control`. `lit` is only how the slot looks, and goes out\n * while a sheet is open so the bar shows where the thumb is. Opening a sheet\n * is `aria-expanded`'s to say.\n *\n * A destination is a link or an action; the \"more\" slot is a button that\n * opens its sheet. Either way the whole slot is the target, so a thumb landing\n * on the label lands on the control. A `disabled` slot is a disabled button,\n * dimmed — the act is still where the hand expects it. A `loading` or\n * `dimmed` slot is drawn the same and stays focusable (`aria-disabled`).\n */\nfunction Slot({\n label,\n icon,\n count,\n current,\n lit,\n copy,\n testId,\n control,\n expanded,\n loading = false,\n}: {\n label: string;\n icon: ReactNode;\n count: number | undefined;\n current: boolean;\n lit: boolean;\n copy: SectionNavCopy;\n testId: string;\n control: Record<string, unknown>;\n expanded?: boolean;\n loading?: boolean;\n}): React.JSX.Element {\n const theme = useTheme();\n return (\n <Box\n {...control}\n aria-current={current ? 'page' : undefined}\n aria-expanded={expanded}\n aria-busy={loading || undefined}\n data-lit={lit ? 'true' : undefined}\n data-testid={testId}\n sx={slotSx(theme, lit)}\n >\n <CountedIcon\n icon={<SlotIcon icon={icon} loading={loading} />}\n count={count}\n label={copy.badge}\n testId={`${testId}-badge`}\n />\n <Typography\n component=\"span\"\n variant=\"caption\"\n sx={{\n maxWidth: '100%',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n lineHeight: 1.3,\n fontWeight: lit ? 700 : 400,\n }}\n >\n {label}\n </Typography>\n </Box>\n );\n}\n\n/** A slot's look: icon over label, the lit rule on its top edge, dimmed when disabled. */\nfunction slotSx(theme: Theme, lit: boolean): SxProps<Theme> {\n return {\n ...CONTROL_RESET,\n ...focusRing(theme),\n flex: 1,\n minWidth: 0,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 0.25,\n position: 'relative',\n color: lit ? 'primary.main' : 'text.secondary',\n // The current slot is marked by more than its colour: a short rule on\n // its top edge, so the state survives a colour-blind reading.\n '&[data-lit=\"true\"]::before': {\n content: '\"\"',\n position: 'absolute',\n top: 0,\n insetInline: '22%',\n height: rem(theme, 3),\n borderBottomLeftRadius: rem(theme, 3),\n borderBottomRightRadius: rem(theme, 3),\n bgcolor: 'primary.main',\n },\n '& svg': { fontSize: rem(theme, 22) },\n [NOT_LIVE]: { color: 'text.disabled' },\n } as SxProps<Theme>;\n}\n\n/** What every slot kind is handed: the bar's open state and how to change it. */\ninterface SlotContext {\n open: OpenMenu;\n toggle: (menu: Exclude<OpenMenu, null>) => void;\n close: () => void;\n linkComponent: ElementType | undefined;\n copy: SectionNavCopy;\n dataTestId: string;\n}\n\n/** The raised button: an action runs on tap; a menu opens its sheet. */\nfunction PrimarySlot({\n primary,\n context,\n}: {\n primary: SectionNavMenu | SectionNavAction;\n context: SlotContext;\n}): React.JSX.Element {\n const testId = primary.dataTestId ?? `${context.dataTestId}-primary`;\n if (!isMenu(primary)) {\n return (\n <RaisedActionButton\n label={primary.label}\n icon={primary.icon}\n captioned\n disabled={primary.disabled}\n loading={primary.loading}\n dataTestId={testId}\n onClick={() => {\n context.close();\n primary.onSelect();\n }}\n />\n );\n }\n return (\n <RaisedActionButton\n label={primary.label}\n icon={primary.icon}\n open={context.open === 'primary'}\n closeLabel={context.copy.close}\n disabled={primary.disabled}\n dataTestId={testId}\n onClick={() => context.toggle('primary')}\n />\n );\n}\n\n/** The \"more\" slot: a button that opens its sheet, carrying its entries' counts. */\nfunction MoreSlot({ more, context }: { more: SectionNavMenu; context: SlotContext }): React.JSX.Element {\n const { open } = context;\n return (\n <Slot\n label={more.label}\n icon={more.icon}\n count={menuCount(more)}\n current={false}\n lit={open === 'more' || (open === null && menuActive(more))}\n expanded={open === 'more'}\n copy={context.copy}\n testId={more.dataTestId ?? `${context.dataTestId}-more`}\n control={controlProps({\n href: undefined,\n linkComponent: context.linkComponent,\n inert: more.disabled === true,\n onClick: () => context.toggle('more'),\n })}\n />\n );\n}\n\n/** A destination: a link, or an action slot (a toggle when it carries `active`). */\nfunction DestinationSlot({\n destination,\n context,\n}: {\n destination: SectionNavDestination;\n context: SlotContext;\n}): React.JSX.Element {\n const { current, lit } = destinationState(destination);\n return (\n <Slot\n label={destination.label}\n icon={destination.icon}\n count={destination.badge}\n current={current}\n lit={context.open === null && lit}\n copy={context.copy}\n testId={destination.dataTestId ?? `${context.dataTestId}-dest-${destination.id}`}\n loading={destination.loading === true}\n control={destinationControl(destination, context.linkComponent, () => {\n context.close();\n destination.onSelect?.();\n })}\n />\n );\n}\n\n/** One slot of the bar, whichever kind it is. */\nfunction BarSlotView({\n slot,\n primary,\n more,\n context,\n}: {\n slot: BarSlot;\n primary: SectionNavMenu | SectionNavAction | undefined;\n more: SectionNavMenu | undefined;\n context: SlotContext;\n}): React.JSX.Element | null {\n if (slot.kind === 'primary') return primary ? <PrimarySlot primary={primary} context={context} /> : null;\n if (slot.kind === 'more') return more ? <MoreSlot more={more} context={context} /> : null;\n return <DestinationSlot destination={slot.destination} context={context} />;\n}\n\n/** The phone layout: a bottom bar, with its menus as bottom sheets. */\nexport function SectionNavBar({\n label,\n destinations,\n primary,\n more,\n linkComponent,\n copy,\n dataTestId,\n}: Required<Pick<SectionNavProps, 'label' | 'destinations' | 'copy' | 'dataTestId'>> &\n Pick<SectionNavProps, 'primary' | 'more'> & { linkComponent: ElementType | undefined }): React.JSX.Element {\n const sheetMenu = isMenu(primary) ? primary : undefined;\n const theme = useTheme();\n const [open, setOpen] = useState<OpenMenu>(null);\n const toggle = (menu: Exclude<OpenMenu, null>): void => setOpen((current) => (current === menu ? null : menu));\n const close = (): void => setOpen(null);\n\n return (\n <>\n <Box\n component=\"nav\"\n aria-label={label}\n data-testid={dataTestId}\n sx={{\n flex: 'none',\n display: 'flex',\n alignItems: 'stretch',\n boxSizing: 'border-box',\n height: sectionNavBarInset(theme),\n paddingBottom: 'env(safe-area-inset-bottom)',\n borderTop: `1px solid ${theme.palette.divider}`,\n bgcolor: 'background.paper',\n // Above the backdrop ONLY while one of its own sheets is open, so the\n // primary button can close what it opened. Raised all the time it\n // would sit over every dialog the page opens, and on a small phone a\n // dialog's own footer is exactly where the bar is. `stackedOverlayZIndex`,\n // not `zIndex.modal + 1`: a host lifting a bottom Drawer clear of a\n // stacked sheet catches this bar's OWN sheets too.\n position: 'relative',\n zIndex: open === null ? 'auto' : stackedOverlayZIndex(theme) + 1,\n }}\n >\n {barSlots(destinations, more !== undefined, primary !== undefined).map((slot) => (\n <BarSlotView\n key={slot.kind === 'destination' ? `dest-${slot.destination.id}` : `menu-${slot.kind}`}\n slot={slot}\n primary={primary}\n more={more}\n context={{ open, toggle, close, linkComponent, copy, dataTestId }}\n />\n ))}\n </Box>\n {sheetMenu ? (\n <SectionNavSheet\n menu={sheetMenu}\n open={open === 'primary'}\n onClose={close}\n linkComponent={linkComponent}\n copy={copy}\n testId={`${dataTestId}-primary-sheet`}\n bottomOffset={sectionNavBarInset(theme)}\n />\n ) : null}\n {more ? (\n <SectionNavSheet\n menu={more}\n open={open === 'more'}\n onClose={close}\n linkComponent={linkComponent}\n copy={copy}\n testId={`${dataTestId}-more-sheet`}\n bottomOffset={sectionNavBarInset(theme)}\n />\n ) : null}\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,gBAAgB;AACvB,SAAS,gBAA0C;AACnD,SAAS,gBAAkD;AA4EvD,SAqMA,UA3LU,KAVV;AAnDJ,IAAM,YAAY,CAAC,UAA6C,IAAI,OAAO,EAAE;AAOtE,SAAS,mBAAmB,OAA0C;AAC3E,SAAO,QAAQ,UAAU,KAAK,CAAC;AACjC;AAiBA,SAAS,KAAK;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AACZ,GAWsB;AACpB,QAAM,QAAQ,SAAS;AACvB,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,gBAAc,UAAU,SAAS;AAAA,MACjC,iBAAe;AAAA,MACf,aAAW,WAAW;AAAA,MACtB,YAAU,MAAM,SAAS;AAAA,MACzB,eAAa;AAAA,MACb,IAAI,OAAO,OAAO,GAAG;AAAA,MAErB;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,oBAAC,YAAS,MAAY,SAAkB;AAAA,YAC9C;AAAA,YACA,OAAO,KAAK;AAAA,YACZ,QAAQ,GAAG,MAAM;AAAA;AAAA,QACnB;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,SAAQ;AAAA,YACR,IAAI;AAAA,cACF,UAAU;AAAA,cACV,UAAU;AAAA,cACV,cAAc;AAAA,cACd,YAAY;AAAA,cACZ,YAAY;AAAA,cACZ,YAAY,MAAM,MAAM;AAAA,YAC1B;AAAA,YAEC;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;AAEJ;AAGA,SAAS,OAAO,OAAc,KAA8B;AAC1D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG,UAAU,KAAK;AAAA,IAClB,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,KAAK;AAAA,IACL,UAAU;AAAA,IACV,OAAO,MAAM,iBAAiB;AAAA;AAAA;AAAA,IAG9B,8BAA8B;AAAA,MAC5B,SAAS;AAAA,MACT,UAAU;AAAA,MACV,KAAK;AAAA,MACL,aAAa;AAAA,MACb,QAAQ,IAAI,OAAO,CAAC;AAAA,MACpB,wBAAwB,IAAI,OAAO,CAAC;AAAA,MACpC,yBAAyB,IAAI,OAAO,CAAC;AAAA,MACrC,SAAS;AAAA,IACX;AAAA,IACA,SAAS,EAAE,UAAU,IAAI,OAAO,EAAE,EAAE;AAAA,IACpC,CAAC,QAAQ,GAAG,EAAE,OAAO,gBAAgB;AAAA,EACvC;AACF;AAaA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AACF,GAGsB;AACpB,QAAM,SAAS,QAAQ,cAAc,GAAG,QAAQ,UAAU;AAC1D,MAAI,CAAC,OAAO,OAAO,GAAG;AACpB,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,QAAQ;AAAA,QACf,MAAM,QAAQ;AAAA,QACd,WAAS;AAAA,QACT,UAAU,QAAQ;AAAA,QAClB,SAAS,QAAQ;AAAA,QACjB,YAAY;AAAA,QACZ,SAAS,MAAM;AACb,kBAAQ,MAAM;AACd,kBAAQ,SAAS;AAAA,QACnB;AAAA;AAAA,IACF;AAAA,EAEJ;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ,SAAS;AAAA,MACvB,YAAY,QAAQ,KAAK;AAAA,MACzB,UAAU,QAAQ;AAAA,MAClB,YAAY;AAAA,MACZ,SAAS,MAAM,QAAQ,OAAO,SAAS;AAAA;AAAA,EACzC;AAEJ;AAGA,SAAS,SAAS,EAAE,MAAM,QAAQ,GAAsE;AACtG,QAAM,EAAE,KAAK,IAAI;AACjB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,KAAK;AAAA,MACZ,MAAM,KAAK;AAAA,MACX,OAAO,UAAU,IAAI;AAAA,MACrB,SAAS;AAAA,MACT,KAAK,SAAS,UAAW,SAAS,QAAQ,WAAW,IAAI;AAAA,MACzD,UAAU,SAAS;AAAA,MACnB,MAAM,QAAQ;AAAA,MACd,QAAQ,KAAK,cAAc,GAAG,QAAQ,UAAU;AAAA,MAChD,SAAS,aAAa;AAAA,QACpB,MAAM;AAAA,QACN,eAAe,QAAQ;AAAA,QACvB,OAAO,KAAK,aAAa;AAAA,QACzB,SAAS,MAAM,QAAQ,OAAO,MAAM;AAAA,MACtC,CAAC;AAAA;AAAA,EACH;AAEJ;AAGA,SAAS,gBAAgB;AAAA,EACvB;AAAA,EACA;AACF,GAGsB;AACpB,QAAM,EAAE,SAAS,IAAI,IAAI,iBAAiB,WAAW;AACrD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,YAAY;AAAA,MACnB,MAAM,YAAY;AAAA,MAClB,OAAO,YAAY;AAAA,MACnB;AAAA,MACA,KAAK,QAAQ,SAAS,QAAQ;AAAA,MAC9B,MAAM,QAAQ;AAAA,MACd,QAAQ,YAAY,cAAc,GAAG,QAAQ,UAAU,SAAS,YAAY,EAAE;AAAA,MAC9E,SAAS,YAAY,YAAY;AAAA,MACjC,SAAS,mBAAmB,aAAa,QAAQ,eAAe,MAAM;AACpE,gBAAQ,MAAM;AACd,oBAAY,WAAW;AAAA,MACzB,CAAC;AAAA;AAAA,EACH;AAEJ;AAGA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAK6B;AAC3B,MAAI,KAAK,SAAS,UAAW,QAAO,UAAU,oBAAC,eAAY,SAAkB,SAAkB,IAAK;AACpG,MAAI,KAAK,SAAS,OAAQ,QAAO,OAAO,oBAAC,YAAS,MAAY,SAAkB,IAAK;AACrF,SAAO,oBAAC,mBAAgB,aAAa,KAAK,aAAa,SAAkB;AAC3E;AAGO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAC6G;AAC3G,QAAM,YAAY,OAAO,OAAO,IAAI,UAAU;AAC9C,QAAM,QAAQ,SAAS;AACvB,QAAM,CAAC,MAAM,OAAO,IAAI,SAAmB,IAAI;AAC/C,QAAM,SAAS,CAAC,SAAwC,QAAQ,CAAC,YAAa,YAAY,OAAO,OAAO,IAAK;AAC7G,QAAM,QAAQ,MAAY,QAAQ,IAAI;AAEtC,SACE,iCACE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,cAAY;AAAA,QACZ,eAAa;AAAA,QACb,IAAI;AAAA,UACF,MAAM;AAAA,UACN,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,QAAQ,mBAAmB,KAAK;AAAA,UAChC,eAAe;AAAA,UACf,WAAW,aAAa,MAAM,QAAQ,OAAO;AAAA,UAC7C,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAOT,UAAU;AAAA,UACV,QAAQ,SAAS,OAAO,SAAS,qBAAqB,KAAK,IAAI;AAAA,QACjE;AAAA,QAEC,mBAAS,cAAc,SAAS,QAAW,YAAY,MAAS,EAAE,IAAI,CAAC,SACtE;AAAA,UAAC;AAAA;AAAA,YAEC;AAAA,YACA;AAAA,YACA;AAAA,YACA,SAAS,EAAE,MAAM,QAAQ,OAAO,eAAe,MAAM,WAAW;AAAA;AAAA,UAJ3D,KAAK,SAAS,gBAAgB,QAAQ,KAAK,YAAY,EAAE,KAAK,QAAQ,KAAK,IAAI;AAAA,QAKtF,CACD;AAAA;AAAA,IACH;AAAA,IACC,YACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,MAAM,SAAS;AAAA,QACf,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,QAAQ,GAAG,UAAU;AAAA,QACrB,cAAc,mBAAmB,KAAK;AAAA;AAAA,IACxC,IACE;AAAA,IACH,OACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,MAAM,SAAS;AAAA,QACf,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,QAAQ,GAAG,UAAU;AAAA,QACrB,cAAc,mBAAmB,KAAK;AAAA;AAAA,IACxC,IACE;AAAA,KACN;AAEJ;","names":[]}
@@ -1,17 +1,17 @@
1
1
  import "../chunk-R26KYJHK.js";
2
2
  import {
3
3
  SectionNav
4
- } from "../chunk-SA2ERYVV.js";
4
+ } from "../chunk-5GQYTB3K.js";
5
5
  import {
6
6
  sectionNavBarInset
7
- } from "../chunk-43Q6CVPB.js";
8
- import "../chunk-32JMSHEA.js";
9
- import "../chunk-RX7J6VRI.js";
7
+ } from "../chunk-WNZBUR76.js";
8
+ import "../chunk-S4ZUZ6DS.js";
9
+ import "../chunk-HKEBTPKY.js";
10
10
  import {
11
11
  RaisedActionButton
12
- } from "../chunk-RZ4SBSLP.js";
13
- import "../chunk-GLKQT2DS.js";
14
- import "../chunk-VHVI3D4R.js";
12
+ } from "../chunk-WNKRFMSI.js";
13
+ import "../chunk-A436VORP.js";
14
+ import "../chunk-P3GBXE73.js";
15
15
  import "../chunk-TMSWLFL4.js";
16
16
  import "../chunk-KIHGTL2D.js";
17
17
  import "../chunk-5AK2EZG5.js";
@@ -45,6 +45,7 @@ import "../chunk-FQ6UW7IY.js";
45
45
  import "../chunk-6JAIFIPW.js";
46
46
  import "../chunk-N3GAFIXG.js";
47
47
  import "../chunk-YKCAJ2TN.js";
48
+ import "../chunk-MFU4Y25U.js";
48
49
  import "../chunk-PZ5AY32C.js";
49
50
  export {
50
51
  RaisedActionButton,
@@ -1 +1 @@
1
- {"version":3,"file":"SectionNav.bar.d.ts","sourceRoot":"","sources":["../../../../../src/components/navigation/SectionNav/SectionNav.bar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,WAAW,EAAkB,MAAM,OAAO,CAAC;AAGnE,OAAO,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAM7C,OAAO,KAAK,EAAkB,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAQ1E;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAE3E;AAyJD,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,YAAY,EACZ,OAAO,EACP,IAAI,EACJ,aAAa,EACb,IAAI,EACJ,UAAU,GACX,EAAE,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,cAAc,GAAG,MAAM,GAAG,YAAY,CAAC,CAAC,GAClF,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,MAAM,CAAC,GAAG;IAAE,aAAa,EAAE,WAAW,GAAG,SAAS,CAAA;CAAE,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAoE3G"}
1
+ {"version":3,"file":"SectionNav.bar.d.ts","sourceRoot":"","sources":["../../../../../src/components/navigation/SectionNav/SectionNav.bar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,WAAW,EAAkB,MAAM,OAAO,CAAC;AAInE,OAAO,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAe7C,OAAO,KAAK,EAA2D,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAQnH;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAE3E;AA6ND,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,YAAY,EACZ,OAAO,EACP,IAAI,EACJ,aAAa,EACb,IAAI,EACJ,UAAU,GACX,EAAE,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,cAAc,GAAG,MAAM,GAAG,YAAY,CAAC,CAAC,GAClF,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,MAAM,CAAC,GAAG;IAAE,aAAa,EAAE,WAAW,GAAG,SAAS,CAAA;CAAE,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAkE3G"}
@@ -1,4 +1,4 @@
1
- import type { SectionNavDestination, SectionNavMenu } from './SectionNav.types';
1
+ import type { SectionNavAction, SectionNavDestination, SectionNavMenu } from './SectionNav.types';
2
2
  /** A count worth drawing: positive and finite. Zero and "unknown" draw nothing. */
3
3
  export declare function shownCount(count: number | undefined): number | undefined;
4
4
  /**
@@ -29,4 +29,15 @@ export type BarSlot = {
29
29
  * is the right one, under the thumb of a right-handed phone.
30
30
  */
31
31
  export declare function barSlots(destinations: readonly SectionNavDestination[], hasMore: boolean, hasPrimary: boolean): BarSlot[];
32
+ /** A primary that opens a sheet, as opposed to one that acts on tap. */
33
+ export declare function isMenu(primary: SectionNavMenu | SectionNavAction | undefined): primary is SectionNavMenu;
34
+ /**
35
+ * How a destination reads. `current` is `aria-current="page"` and belongs to a
36
+ * LINK only — an action slot that is ON reports `aria-pressed` instead. `lit`
37
+ * is the look, and a `dimmed` slot is never lit: it says "not now".
38
+ */
39
+ export declare function destinationState(destination: SectionNavDestination): {
40
+ current: boolean;
41
+ lit: boolean;
42
+ };
32
43
  //# sourceMappingURL=SectionNav.helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SectionNav.helpers.d.ts","sourceRoot":"","sources":["../../../../../src/components/navigation/SectionNav/SectionNav.helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEhF,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAExE;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAM9E;AAED,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,GAAG,OAAO,CAEpE;AAED,uDAAuD;AACvD,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,WAAW,EAAE,qBAAqB,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CACtB,YAAY,EAAE,SAAS,qBAAqB,EAAE,EAC9C,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,OAAO,GAClB,OAAO,EAAE,CAKX"}
1
+ {"version":3,"file":"SectionNav.helpers.d.ts","sourceRoot":"","sources":["../../../../../src/components/navigation/SectionNav/SectionNav.helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAElG,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAExE;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAM9E;AAED,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,GAAG,OAAO,CAEpE;AAED,uDAAuD;AACvD,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,WAAW,EAAE,qBAAqB,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CACtB,YAAY,EAAE,SAAS,qBAAqB,EAAE,EAC9C,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,OAAO,GAClB,OAAO,EAAE,CAKX;AAED,wEAAwE;AACxE,wBAAgB,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,gBAAgB,GAAG,SAAS,GAAG,OAAO,IAAI,cAAc,CAExG;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,qBAAqB,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CAGvG"}