@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
@@ -1 +0,0 @@
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 onClick: () => {\n entry.onSelect?.();\n onDone();\n },\n })}\n aria-current={entry.active ? 'page' : undefined}\n data-testid={`${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 }}\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 onClick: () => {\n entry.onSelect?.();\n onDone();\n },\n })}\n aria-current={entry.active ? 'page' : undefined}\n data-testid={`${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 }}\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":[]}
@@ -1,240 +0,0 @@
1
- import {
2
- SectionNavSheet
3
- } from "./chunk-32JMSHEA.js";
4
- import {
5
- RaisedActionButton
6
- } from "./chunk-RZ4SBSLP.js";
7
- import {
8
- Box,
9
- CONTROL_RESET,
10
- CountedIcon,
11
- controlProps,
12
- focusRing
13
- } from "./chunk-GLKQT2DS.js";
14
- import {
15
- barSlots,
16
- menuActive,
17
- menuCount
18
- } from "./chunk-VHVI3D4R.js";
19
- import {
20
- rem
21
- } from "./chunk-YKCAJ2TN.js";
22
-
23
- // src/components/navigation/SectionNav/SectionNav.bar.tsx
24
- import Typography from "@mui/material/Typography/index.js";
25
- import { useTheme } from "@mui/material/styles/index.js";
26
- import { useState } from "react";
27
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
28
- var barHeight = (theme) => rem(theme, 60);
29
- function sectionNavBarInset(theme) {
30
- return `calc(${barHeight(theme)} + env(safe-area-inset-bottom))`;
31
- }
32
- function Slot({
33
- label,
34
- icon,
35
- count,
36
- current,
37
- lit,
38
- copy,
39
- testId,
40
- control,
41
- expanded
42
- }) {
43
- const theme = useTheme();
44
- return /* @__PURE__ */ jsxs(
45
- Box,
46
- {
47
- ...control,
48
- "aria-current": current ? "page" : void 0,
49
- "aria-expanded": expanded,
50
- "data-lit": lit ? "true" : void 0,
51
- "data-testid": testId,
52
- sx: {
53
- ...CONTROL_RESET,
54
- ...focusRing(theme),
55
- flex: 1,
56
- minWidth: 0,
57
- display: "flex",
58
- flexDirection: "column",
59
- alignItems: "center",
60
- justifyContent: "center",
61
- gap: 0.25,
62
- position: "relative",
63
- color: lit ? "primary.main" : "text.secondary",
64
- // The current slot is marked by more than its colour: a short rule on
65
- // its top edge, so the state survives a colour-blind reading.
66
- '&[data-lit="true"]::before': {
67
- content: '""',
68
- position: "absolute",
69
- top: 0,
70
- insetInline: "22%",
71
- height: rem(theme, 3),
72
- borderBottomLeftRadius: rem(theme, 3),
73
- borderBottomRightRadius: rem(theme, 3),
74
- bgcolor: "primary.main"
75
- },
76
- "& svg": { fontSize: rem(theme, 22) }
77
- },
78
- children: [
79
- /* @__PURE__ */ jsx(CountedIcon, { icon, count, label: copy.badge, testId: `${testId}-badge` }),
80
- /* @__PURE__ */ jsx(
81
- Typography,
82
- {
83
- component: "span",
84
- variant: "caption",
85
- sx: {
86
- maxWidth: "100%",
87
- overflow: "hidden",
88
- textOverflow: "ellipsis",
89
- whiteSpace: "nowrap",
90
- lineHeight: 1.3,
91
- fontWeight: lit ? 700 : 400
92
- },
93
- children: label
94
- }
95
- )
96
- ]
97
- }
98
- );
99
- }
100
- function BarSlotView({
101
- slot,
102
- primary,
103
- more,
104
- open,
105
- toggle,
106
- close,
107
- linkComponent,
108
- copy,
109
- dataTestId
110
- }) {
111
- if (slot.kind === "primary" && primary) {
112
- return /* @__PURE__ */ jsx(
113
- RaisedActionButton,
114
- {
115
- label: primary.label,
116
- icon: primary.icon,
117
- open: open === "primary",
118
- closeLabel: copy.close,
119
- dataTestId: `${dataTestId}-primary`,
120
- onClick: () => toggle("primary")
121
- }
122
- );
123
- }
124
- if (slot.kind === "more" && more) {
125
- return /* @__PURE__ */ jsx(
126
- Slot,
127
- {
128
- label: more.label,
129
- icon: more.icon,
130
- count: menuCount(more),
131
- current: false,
132
- lit: open === "more" || open === null && menuActive(more),
133
- expanded: open === "more",
134
- copy,
135
- testId: `${dataTestId}-more`,
136
- control: controlProps({ href: void 0, linkComponent, onClick: () => toggle("more") })
137
- }
138
- );
139
- }
140
- if (slot.kind !== "destination") return null;
141
- const { destination } = slot;
142
- return /* @__PURE__ */ jsx(
143
- Slot,
144
- {
145
- label: destination.label,
146
- icon: destination.icon,
147
- count: destination.badge,
148
- current: destination.active === true,
149
- lit: open === null && destination.active === true,
150
- copy,
151
- testId: `${dataTestId}-dest-${destination.id}`,
152
- control: controlProps({ href: destination.href, linkComponent, onClick: close })
153
- }
154
- );
155
- }
156
- function SectionNavBar({
157
- label,
158
- destinations,
159
- primary,
160
- more,
161
- linkComponent,
162
- copy,
163
- dataTestId
164
- }) {
165
- const theme = useTheme();
166
- const [open, setOpen] = useState(null);
167
- const toggle = (menu) => setOpen((current) => current === menu ? null : menu);
168
- const close = () => setOpen(null);
169
- return /* @__PURE__ */ jsxs(Fragment, { children: [
170
- /* @__PURE__ */ jsx(
171
- Box,
172
- {
173
- component: "nav",
174
- "aria-label": label,
175
- "data-testid": dataTestId,
176
- sx: {
177
- flex: "none",
178
- display: "flex",
179
- alignItems: "stretch",
180
- boxSizing: "border-box",
181
- height: sectionNavBarInset(theme),
182
- paddingBottom: "env(safe-area-inset-bottom)",
183
- borderTop: `1px solid ${theme.palette.divider}`,
184
- bgcolor: "background.paper",
185
- // Above the backdrop ONLY while one of its own sheets is open, so the
186
- // primary button can close what it opened. Raised all the time it
187
- // would sit over every dialog the page opens, and on a small phone a
188
- // dialog's own footer is exactly where the bar is.
189
- position: "relative",
190
- zIndex: open === null ? "auto" : theme.zIndex.modal + 1
191
- },
192
- children: barSlots(destinations, more !== void 0, primary !== void 0).map((slot) => /* @__PURE__ */ jsx(
193
- BarSlotView,
194
- {
195
- slot,
196
- primary,
197
- more,
198
- open,
199
- toggle,
200
- close,
201
- linkComponent,
202
- copy,
203
- dataTestId
204
- },
205
- slot.kind === "destination" ? `dest-${slot.destination.id}` : `menu-${slot.kind}`
206
- ))
207
- }
208
- ),
209
- primary ? /* @__PURE__ */ jsx(
210
- SectionNavSheet,
211
- {
212
- menu: primary,
213
- open: open === "primary",
214
- onClose: close,
215
- linkComponent,
216
- copy,
217
- testId: `${dataTestId}-primary-sheet`,
218
- bottomOffset: sectionNavBarInset(theme)
219
- }
220
- ) : null,
221
- more ? /* @__PURE__ */ jsx(
222
- SectionNavSheet,
223
- {
224
- menu: more,
225
- open: open === "more",
226
- onClose: close,
227
- linkComponent,
228
- copy,
229
- testId: `${dataTestId}-more-sheet`,
230
- bottomOffset: sectionNavBarInset(theme)
231
- }
232
- ) : null
233
- ] });
234
- }
235
-
236
- export {
237
- sectionNavBarInset,
238
- SectionNavBar
239
- };
240
- //# sourceMappingURL=chunk-43Q6CVPB.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/navigation/SectionNav/SectionNav.bar.tsx"],"sourcesContent":["import Typography from '@mui/material/Typography/index.js';\nimport { useTheme } from '@mui/material/styles/index.js';\nimport { useState, type ElementType, type ReactNode } from 'react';\n\nimport type { SectionNavCopy } from '../../../copy';\nimport { rem } from '../../../tokens/scales';\n\nimport { barSlots, menuActive, menuCount, type BarSlot } from './SectionNav.helpers';\nimport { Box, CONTROL_RESET, CountedIcon, controlProps, focusRing } from './SectionNav.parts';\nimport { RaisedActionButton } from './SectionNav.primary';\nimport { SectionNavSheet } from './SectionNav.sheet';\nimport type { 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 * `lit` is only how the slot looks, and goes out while a sheet is open so the\n * bar shows where the thumb is. Opening a sheet is `aria-expanded`'s to say.\n *\n * A destination is a link; the \"more\" slot is a button that opens its sheet.\n * Either way the whole slot is the target, so a thumb landing on the label\n * lands on the control.\n */\nfunction Slot({\n label,\n icon,\n count,\n current,\n lit,\n copy,\n testId,\n control,\n expanded,\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}): React.JSX.Element {\n const theme = useTheme();\n return (\n <Box\n {...control}\n aria-current={current ? 'page' : undefined}\n aria-expanded={expanded}\n data-lit={lit ? 'true' : undefined}\n data-testid={testId}\n sx={{\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 }}\n >\n <CountedIcon icon={icon} count={count} label={copy.badge} testId={`${testId}-badge`} />\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/** One slot of the bar, whichever kind it is. */\nfunction BarSlotView({\n slot,\n primary,\n more,\n open,\n toggle,\n close,\n linkComponent,\n copy,\n dataTestId,\n}: {\n slot: BarSlot;\n primary: SectionNavMenu | undefined;\n more: SectionNavMenu | undefined;\n open: OpenMenu;\n toggle: (menu: Exclude<OpenMenu, null>) => void;\n close: () => void;\n linkComponent: ElementType | undefined;\n copy: SectionNavCopy;\n dataTestId: string;\n}): React.JSX.Element | null {\n if (slot.kind === 'primary' && primary) {\n return (\n <RaisedActionButton\n label={primary.label}\n icon={primary.icon}\n open={open === 'primary'}\n closeLabel={copy.close}\n dataTestId={`${dataTestId}-primary`}\n onClick={() => toggle('primary')}\n />\n );\n }\n if (slot.kind === 'more' && more) {\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={copy}\n testId={`${dataTestId}-more`}\n control={controlProps({ href: undefined, linkComponent, onClick: () => toggle('more') })}\n />\n );\n }\n if (slot.kind !== 'destination') return null;\n const { destination } = slot;\n return (\n <Slot\n label={destination.label}\n icon={destination.icon}\n count={destination.badge}\n current={destination.active === true}\n lit={open === null && destination.active === true}\n copy={copy}\n testId={`${dataTestId}-dest-${destination.id}`}\n control={controlProps({ href: destination.href, linkComponent, onClick: close })}\n />\n );\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 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.\n position: 'relative',\n zIndex: open === null ? 'auto' : theme.zIndex.modal + 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 open={open}\n toggle={toggle}\n close={close}\n linkComponent={linkComponent}\n copy={copy}\n dataTestId={dataTestId}\n />\n ))}\n </Box>\n {primary ? (\n <SectionNavSheet\n menu={primary}\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":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/navigation/SectionNav/SectionNav.parts.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport type { SxProps, Theme } from '@mui/material/styles/index.js';\nimport type { ElementType, ReactNode } from 'react';\n\nimport { rem } from '../../../tokens/scales';\nimport { Badge } from '../../data-display/Badge';\n\nimport { shownCount } from './SectionNav.helpers';\n\n/**\n * An icon with its count on the shoulder.\n *\n * Quiet to assistive tech on change: the count moves on a poll, and a control\n * that announces itself every minute is noise. Its NAME carries the number,\n * so it is read when the control is.\n */\nexport function CountedIcon({\n icon,\n count,\n label,\n testId,\n}: {\n icon: ReactNode;\n count: number | undefined;\n label: (count: number) => string;\n testId: string;\n}): React.JSX.Element {\n const shown = shownCount(count);\n if (shown === undefined) return <>{icon}</>;\n return (\n // The library's corner count, in the warning role the sidebar's pill is\n // drawn from.\n <Badge\n content={shown}\n variant=\"count\"\n color=\"warning\"\n max={99}\n aria-label={label(shown)}\n aria-live=\"off\"\n data-testid={testId}\n >\n {icon}\n </Badge>\n );\n}\n\n/** The keyboard ring every control in the nav draws, in the theme's own colour. */\nexport function focusRing(theme: Theme): SxProps<Theme> {\n return {\n '&:focus-visible': {\n outline: `${rem(theme, 2)} solid ${theme.palette.primary.main}`,\n outlineOffset: rem(theme, -2),\n },\n };\n}\n\n/**\n * The element an entry or destination renders as: the host's link for an\n * `href`, a button for an `onSelect`.\n *\n * Returned as props for a `Box`, so the control stays ONE interactive\n * element — never a button wrapped around a link.\n */\nexport function controlProps({\n href,\n onClick,\n linkComponent,\n}: {\n href: string | undefined;\n onClick?: () => void;\n linkComponent: ElementType | undefined;\n}): Record<string, unknown> {\n if (href !== undefined) return { component: linkComponent ?? 'a', href, onClick };\n return { component: 'button', type: 'button', onClick };\n}\n\n/** The base reset every clickable in the nav shares: no underline, no button chrome. */\nexport const CONTROL_RESET = {\n border: 0,\n background: 'none',\n font: 'inherit',\n color: 'inherit',\n textDecoration: 'none',\n cursor: 'pointer',\n margin: 0,\n} as const;\n\nexport { Box };\n"],"mappings":";;;;;;;;;;;AAAA,OAAO,SAAS;AA4BkB;AAZ3B,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKsB;AACpB,QAAM,QAAQ,WAAW,KAAK;AAC9B,MAAI,UAAU,OAAW,QAAO,gCAAG,gBAAK;AACxC;AAAA;AAAA;AAAA,IAGE;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,SAAQ;AAAA,QACR,OAAM;AAAA,QACN,KAAK;AAAA,QACL,cAAY,MAAM,KAAK;AAAA,QACvB,aAAU;AAAA,QACV,eAAa;AAAA,QAEZ;AAAA;AAAA,IACH;AAAA;AAEJ;AAGO,SAAS,UAAU,OAA8B;AACtD,SAAO;AAAA,IACL,mBAAmB;AAAA,MACjB,SAAS,GAAG,IAAI,OAAO,CAAC,CAAC,UAAU,MAAM,QAAQ,QAAQ,IAAI;AAAA,MAC7D,eAAe,IAAI,OAAO,EAAE;AAAA,IAC9B;AAAA,EACF;AACF;AASO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,GAI4B;AAC1B,MAAI,SAAS,OAAW,QAAO,EAAE,WAAW,iBAAiB,KAAK,MAAM,QAAQ;AAChF,SAAO,EAAE,WAAW,UAAU,MAAM,UAAU,QAAQ;AACxD;AAGO,IAAM,gBAAgB;AAAA,EAC3B,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,OAAO;AAAA,EACP,gBAAgB;AAAA,EAChB,QAAQ;AAAA,EACR,QAAQ;AACV;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/navigation/SectionNav/SectionNav.rail.tsx"],"sourcesContent":["import Typography from '@mui/material/Typography/index.js';\nimport { useTheme } from '@mui/material/styles/index.js';\nimport type { ElementType, ReactNode } from 'react';\n\nimport type { SectionNavCopy } from '../../../copy';\nimport { rem } from '../../../tokens/scales';\n\nimport { Box, CONTROL_RESET, CountedIcon, controlProps, focusRing } from './SectionNav.parts';\nimport type { SectionNavMenu, SectionNavProps } from './SectionNav.types';\n\n/**\n * One rail row: icon, label, and the count at the far end.\n *\n * Destinations and menu entries draw the same row — in the rail there is room\n * for everything, so the difference between \"a place\" and \"an action\" is the\n * section it sits in, not its shape.\n */\nfunction RailRow({\n label,\n description,\n icon,\n count,\n active,\n copy,\n testId,\n control,\n}: {\n label: string;\n description?: string;\n icon: ReactNode;\n count: number | undefined;\n active: boolean;\n copy: SectionNavCopy;\n testId: string;\n control: Record<string, unknown>;\n}): React.JSX.Element {\n const theme = useTheme();\n return (\n <Box\n {...control}\n aria-current={active ? 'page' : undefined}\n data-testid={testId}\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, 40),\n px: 1.25,\n py: 0.75,\n borderRadius: 1,\n textAlign: 'start',\n color: active ? 'primary.main' : 'text.primary',\n bgcolor: active ? 'action.selected' : 'transparent',\n '&:hover': { bgcolor: active ? 'action.selected' : 'action.hover' },\n '& svg': { color: 'primary.main', fontSize: rem(theme, 20) },\n }}\n >\n <CountedIcon icon={icon} count={count} label={copy.badge} testId={`${testId}-badge`} />\n <Box component=\"span\" sx={{ display: 'flex', flexDirection: 'column', minWidth: 0 }}>\n <Typography component=\"span\" variant=\"body2\" sx={{ fontWeight: active ? 700 : 500 }}>\n {label}\n </Typography>\n {description ? (\n <Typography component=\"span\" variant=\"caption\" color=\"text.secondary\">\n {description}\n </Typography>\n ) : null}\n </Box>\n </Box>\n );\n}\n\n/** A heading between the rail's sections, in the sidebar's small-caps voice. */\nfunction RailHeading({ children }: { children: ReactNode }): React.JSX.Element {\n return (\n <Typography variant=\"overline\" color=\"text.secondary\" sx={{ px: 1.25, pt: 1.5, lineHeight: 1.6 }}>\n {children}\n </Typography>\n );\n}\n\n/** A menu's groups, listed under its title — nothing folded away on a wide screen. */\nfunction RailMenu({\n menu,\n linkComponent,\n copy,\n testId,\n}: {\n menu: SectionNavMenu;\n linkComponent: ElementType | undefined;\n copy: SectionNavCopy;\n testId: string;\n}): React.JSX.Element {\n return (\n <Box component=\"section\" data-testid={testId} sx={{ display: 'flex', flexDirection: 'column', gap: 0.25 }}>\n <RailHeading>{menu.title}</RailHeading>\n {menu.groups.map((group) => (\n <Box key={group.id} sx={{ display: 'flex', flexDirection: 'column', gap: 0.25 }}>\n {group.title ? (\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ px: 1.25, pt: 0.5 }}>\n {group.title}\n </Typography>\n ) : null}\n {group.entries.map((entry) => (\n <RailRow\n key={entry.id}\n label={entry.label}\n description={entry.description}\n icon={entry.icon}\n count={entry.badge}\n active={entry.active === true}\n copy={copy}\n testId={`${testId}-entry-${entry.id}`}\n control={controlProps({ href: entry.href, linkComponent, onClick: () => entry.onSelect?.() })}\n />\n ))}\n </Box>\n ))}\n </Box>\n );\n}\n\n/**\n * The wide-screen layout: a vertical rail — the way back, the destinations,\n * then every menu's entries.\n *\n * It fills the column the host gives it and scrolls on its own, like the\n * sidebar it stands in for.\n */\nexport function SectionNavRail({\n label,\n destinations,\n primary,\n more,\n back,\n heading,\n linkComponent,\n copy,\n dataTestId,\n}: Required<Pick<SectionNavProps, 'label' | 'destinations' | 'copy' | 'dataTestId'>> &\n Pick<SectionNavProps, 'primary' | 'more' | 'back' | 'heading'> & {\n linkComponent: ElementType | undefined;\n }): React.JSX.Element {\n const theme = useTheme();\n return (\n <Box\n component=\"nav\"\n aria-label={label}\n data-testid={dataTestId}\n sx={{\n display: 'flex',\n flexDirection: 'column',\n gap: 0.25,\n height: '100%',\n overflowY: 'auto',\n px: 1,\n py: 1.5,\n bgcolor: 'background.paper',\n }}\n >\n {back ? (\n <Box\n {...controlProps({ href: back.href, linkComponent })}\n data-testid={`${dataTestId}-back`}\n sx={{\n ...CONTROL_RESET,\n ...focusRing(theme),\n display: 'flex',\n alignItems: 'center',\n gap: 1,\n px: 1.25,\n py: 0.75,\n mb: 0.5,\n borderRadius: 1,\n color: 'text.secondary',\n '&:hover': { bgcolor: 'action.hover', color: 'text.primary' },\n '& svg': { fontSize: rem(theme, 20) },\n }}\n >\n {back.icon}\n <Typography component=\"span\" variant=\"body2\" sx={{ fontWeight: 600 }}>\n {back.label}\n </Typography>\n </Box>\n ) : null}\n {heading ? <RailHeading>{heading}</RailHeading> : null}\n {destinations.map((destination) => (\n <RailRow\n key={destination.id}\n label={destination.label}\n icon={destination.icon}\n count={destination.badge}\n active={destination.active === true}\n copy={copy}\n testId={`${dataTestId}-dest-${destination.id}`}\n control={controlProps({ href: destination.href, linkComponent })}\n />\n ))}\n {primary ? (\n <RailMenu menu={primary} linkComponent={linkComponent} copy={copy} testId={`${dataTestId}-primary`} />\n ) : null}\n {more ? <RailMenu menu={more} linkComponent={linkComponent} copy={copy} testId={`${dataTestId}-more`} /> : null}\n </Box>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAAA,OAAO,gBAAgB;AACvB,SAAS,gBAAgB;AA2DnB,cACA,YADA;AA3CN,SAAS,QAAQ;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GASsB;AACpB,QAAM,QAAQ,SAAS;AACvB,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,gBAAc,SAAS,SAAS;AAAA,MAChC,eAAa;AAAA,MACb,IAAI;AAAA,QACF,GAAG;AAAA,QACH,GAAG,UAAU,KAAK;AAAA,QAClB,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,KAAK;AAAA,QACL,OAAO;AAAA,QACP,WAAW,IAAI,OAAO,EAAE;AAAA,QACxB,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,cAAc;AAAA,QACd,WAAW;AAAA,QACX,OAAO,SAAS,iBAAiB;AAAA,QACjC,SAAS,SAAS,oBAAoB;AAAA,QACtC,WAAW,EAAE,SAAS,SAAS,oBAAoB,eAAe;AAAA,QAClE,SAAS,EAAE,OAAO,gBAAgB,UAAU,IAAI,OAAO,EAAE,EAAE;AAAA,MAC7D;AAAA,MAEA;AAAA,4BAAC,eAAY,MAAY,OAAc,OAAO,KAAK,OAAO,QAAQ,GAAG,MAAM,UAAU;AAAA,QACrF,qBAAC,OAAI,WAAU,QAAO,IAAI,EAAE,SAAS,QAAQ,eAAe,UAAU,UAAU,EAAE,GAChF;AAAA,8BAAC,cAAW,WAAU,QAAO,SAAQ,SAAQ,IAAI,EAAE,YAAY,SAAS,MAAM,IAAI,GAC/E,iBACH;AAAA,UACC,cACC,oBAAC,cAAW,WAAU,QAAO,SAAQ,WAAU,OAAM,kBAClD,uBACH,IACE;AAAA,WACN;AAAA;AAAA;AAAA,EACF;AAEJ;AAGA,SAAS,YAAY,EAAE,SAAS,GAA+C;AAC7E,SACE,oBAAC,cAAW,SAAQ,YAAW,OAAM,kBAAiB,IAAI,EAAE,IAAI,MAAM,IAAI,KAAK,YAAY,IAAI,GAC5F,UACH;AAEJ;AAGA,SAAS,SAAS;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKsB;AACpB,SACE,qBAAC,OAAI,WAAU,WAAU,eAAa,QAAQ,IAAI,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,KAAK,GACtG;AAAA,wBAAC,eAAa,eAAK,OAAM;AAAA,IACxB,KAAK,OAAO,IAAI,CAAC,UAChB,qBAAC,OAAmB,IAAI,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,KAAK,GAC3E;AAAA,YAAM,QACL,oBAAC,cAAW,SAAQ,WAAU,OAAM,kBAAiB,IAAI,EAAE,IAAI,MAAM,IAAI,IAAI,GAC1E,gBAAM,OACT,IACE;AAAA,MACH,MAAM,QAAQ,IAAI,CAAC,UAClB;AAAA,QAAC;AAAA;AAAA,UAEC,OAAO,MAAM;AAAA,UACb,aAAa,MAAM;AAAA,UACnB,MAAM,MAAM;AAAA,UACZ,OAAO,MAAM;AAAA,UACb,QAAQ,MAAM,WAAW;AAAA,UACzB;AAAA,UACA,QAAQ,GAAG,MAAM,UAAU,MAAM,EAAE;AAAA,UACnC,SAAS,aAAa,EAAE,MAAM,MAAM,MAAM,eAAe,SAAS,MAAM,MAAM,WAAW,EAAE,CAAC;AAAA;AAAA,QARvF,MAAM;AAAA,MASb,CACD;AAAA,SAlBO,MAAM,EAmBhB,CACD;AAAA,KACH;AAEJ;AASO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAGwB;AACtB,QAAM,QAAQ,SAAS;AACvB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,cAAY;AAAA,MACZ,eAAa;AAAA,MACb,IAAI;AAAA,QACF,SAAS;AAAA,QACT,eAAe;AAAA,QACf,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,SAAS;AAAA,MACX;AAAA,MAEC;AAAA,eACC;AAAA,UAAC;AAAA;AAAA,YACE,GAAG,aAAa,EAAE,MAAM,KAAK,MAAM,cAAc,CAAC;AAAA,YACnD,eAAa,GAAG,UAAU;AAAA,YAC1B,IAAI;AAAA,cACF,GAAG;AAAA,cACH,GAAG,UAAU,KAAK;AAAA,cAClB,SAAS;AAAA,cACT,YAAY;AAAA,cACZ,KAAK;AAAA,cACL,IAAI;AAAA,cACJ,IAAI;AAAA,cACJ,IAAI;AAAA,cACJ,cAAc;AAAA,cACd,OAAO;AAAA,cACP,WAAW,EAAE,SAAS,gBAAgB,OAAO,eAAe;AAAA,cAC5D,SAAS,EAAE,UAAU,IAAI,OAAO,EAAE,EAAE;AAAA,YACtC;AAAA,YAEC;AAAA,mBAAK;AAAA,cACN,oBAAC,cAAW,WAAU,QAAO,SAAQ,SAAQ,IAAI,EAAE,YAAY,IAAI,GAChE,eAAK,OACR;AAAA;AAAA;AAAA,QACF,IACE;AAAA,QACH,UAAU,oBAAC,eAAa,mBAAQ,IAAiB;AAAA,QACjD,aAAa,IAAI,CAAC,gBACjB;AAAA,UAAC;AAAA;AAAA,YAEC,OAAO,YAAY;AAAA,YACnB,MAAM,YAAY;AAAA,YAClB,OAAO,YAAY;AAAA,YACnB,QAAQ,YAAY,WAAW;AAAA,YAC/B;AAAA,YACA,QAAQ,GAAG,UAAU,SAAS,YAAY,EAAE;AAAA,YAC5C,SAAS,aAAa,EAAE,MAAM,YAAY,MAAM,cAAc,CAAC;AAAA;AAAA,UAP1D,YAAY;AAAA,QAQnB,CACD;AAAA,QACA,UACC,oBAAC,YAAS,MAAM,SAAS,eAA8B,MAAY,QAAQ,GAAG,UAAU,YAAY,IAClG;AAAA,QACH,OAAO,oBAAC,YAAS,MAAM,MAAM,eAA8B,MAAY,QAAQ,GAAG,UAAU,SAAS,IAAK;AAAA;AAAA;AAAA,EAC7G;AAEJ;","names":[]}
@@ -1,62 +0,0 @@
1
- import {
2
- Box,
3
- CONTROL_RESET,
4
- focusRing
5
- } from "./chunk-GLKQT2DS.js";
6
- import {
7
- rem
8
- } from "./chunk-YKCAJ2TN.js";
9
-
10
- // src/components/navigation/SectionNav/SectionNav.primary.tsx
11
- import { useTheme } from "@mui/material/styles/index.js";
12
- import { jsx } from "react/jsx-runtime";
13
- function RaisedActionButton({
14
- label,
15
- icon,
16
- onClick,
17
- open,
18
- closeLabel,
19
- dataTestId = "raised-action"
20
- }) {
21
- const theme = useTheme();
22
- const size = rem(theme, 52);
23
- const expanded = open === true;
24
- return /* @__PURE__ */ jsx(Box, { sx: { flex: "none", display: "flex", alignItems: "flex-start", justifyContent: "center", px: 0.5 }, children: /* @__PURE__ */ jsx(
25
- Box,
26
- {
27
- component: "button",
28
- type: "button",
29
- onClick,
30
- "aria-label": expanded && closeLabel ? closeLabel : label,
31
- "aria-expanded": open,
32
- "data-testid": dataTestId,
33
- sx: {
34
- ...CONTROL_RESET,
35
- ...focusRing(theme),
36
- width: size,
37
- height: size,
38
- // Lifted half out of the bar: the one control that is not a place.
39
- marginTop: rem(theme, -18),
40
- borderRadius: "50%",
41
- display: "flex",
42
- alignItems: "center",
43
- justifyContent: "center",
44
- bgcolor: "primary.main",
45
- color: "primary.contrastText",
46
- boxShadow: theme.shadows[6],
47
- "& svg": {
48
- fontSize: rem(theme, 26),
49
- transition: theme.transitions.create("transform", { duration: theme.transitions.duration.shorter }),
50
- transform: expanded ? "rotate(45deg)" : "none"
51
- },
52
- "@media (prefers-reduced-motion: reduce)": { "& svg": { transition: "none" } }
53
- },
54
- children: icon
55
- }
56
- ) });
57
- }
58
-
59
- export {
60
- RaisedActionButton
61
- };
62
- //# sourceMappingURL=chunk-RZ4SBSLP.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/navigation/SectionNav/SectionNav.primary.tsx"],"sourcesContent":["import { useTheme } from '@mui/material/styles/index.js';\nimport type { ReactNode } from 'react';\n\nimport { rem } from '../../../tokens/scales';\n\nimport { Box, CONTROL_RESET, focusRing } from './SectionNav.parts';\n\nexport interface RaisedActionButtonProps {\n /** The button's accessible name — it has no visible label. */\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 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, and unlabelled so it costs the row less width than a tab: that\n * width is what lets a bar keep four labelled tabs AND this button at 320px.\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 dataTestId = 'raised-action',\n}: RaisedActionButtonProps): React.JSX.Element {\n const theme = useTheme();\n const size = rem(theme, 52);\n const expanded = open === true;\n return (\n <Box sx={{ flex: 'none', display: 'flex', alignItems: 'flex-start', justifyContent: 'center', px: 0.5 }}>\n <Box\n component=\"button\"\n type=\"button\"\n onClick={onClick}\n aria-label={expanded && closeLabel ? closeLabel : label}\n aria-expanded={open}\n data-testid={dataTestId}\n sx={{\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 '& 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 }}\n >\n {icon}\n </Box>\n </Box>\n );\n}\n"],"mappings":";;;;;;;;;;AAAA,SAAS,gBAAgB;AA+CnB;AAbC,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AACf,GAA+C;AAC7C,QAAM,QAAQ,SAAS;AACvB,QAAM,OAAO,IAAI,OAAO,EAAE;AAC1B,QAAM,WAAW,SAAS;AAC1B,SACE,oBAAC,OAAI,IAAI,EAAE,MAAM,QAAQ,SAAS,QAAQ,YAAY,cAAc,gBAAgB,UAAU,IAAI,IAAI,GACpG;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,MAAK;AAAA,MACL;AAAA,MACA,cAAY,YAAY,aAAa,aAAa;AAAA,MAClD,iBAAe;AAAA,MACf,eAAa;AAAA,MACb,IAAI;AAAA,QACF,GAAG;AAAA,QACH,GAAG,UAAU,KAAK;AAAA,QAClB,OAAO;AAAA,QACP,QAAQ;AAAA;AAAA,QAER,WAAW,IAAI,OAAO,GAAG;AAAA,QACzB,cAAc;AAAA,QACd,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,SAAS;AAAA,QACT,OAAO;AAAA,QACP,WAAW,MAAM,QAAQ,CAAC;AAAA,QAC1B,SAAS;AAAA,UACP,UAAU,IAAI,OAAO,EAAE;AAAA,UACvB,YAAY,MAAM,YAAY,OAAO,aAAa,EAAE,UAAU,MAAM,YAAY,SAAS,QAAQ,CAAC;AAAA,UAClG,WAAW,WAAW,kBAAkB;AAAA,QAC1C;AAAA,QACA,2CAA2C,EAAE,SAAS,EAAE,YAAY,OAAO,EAAE;AAAA,MAC/E;AAAA,MAEC;AAAA;AAAA,EACH,GACF;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/navigation/SectionNav/SectionNav.helpers.ts"],"sourcesContent":["import type { 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"],"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;","names":[]}