@aracreate/arm-ui 3.11.1 → 3.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/chunk-TD6NGM5I.js.map +1 -1
- package/dist/index.d.mts +28 -2
- package/dist/index.d.ts +28 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/preset.js.map +1 -1
- package/dist/style.css +1 -0
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/primitives.ts","../src/components/Skeleton.tsx","../src/components/Accordion.tsx","../src/components/Drawer.tsx","../src/components/AccentHeader.tsx","../src/components/ConfirmDialog.tsx","../src/components/layout-tokens.ts","../src/components/CardFooter.tsx","../src/components/PausedBadge.tsx","../src/components/icon-size.ts","../src/components/AccountCard.tsx","../src/components/MonthGrid.tsx","../src/components/heading-scale.ts","../src/components/Toast.tsx","../src/components/IconTile.tsx","../src/components/EventBlock.tsx","../src/components/DataTableRow.tsx","../src/components/MetricCard.tsx","../src/components/AppCard.tsx","../src/components/ActivityRow.tsx","../src/components/DashboardErrorCard.tsx","../src/components/Pagination.tsx","../src/components/status-colors.ts","../src/components/BrandPanel.tsx","../src/components/AuthCard.tsx","../src/components/GoogleIcon.tsx","../src/components/MicrosoftIcon.tsx","../src/components/OtpInput.tsx","../src/components/OtpVerifyStep.tsx","../src/components/ProviderIcon.tsx","../src/components/Sidebar.tsx","../src/components/Topbar.tsx","../src/components/SearchOverlay.tsx","../src/components/calendar-types.ts","../src/components/CalendarDayHeader.tsx","../src/components/CalendarPickList.tsx","../src/components/CalendarToolbar.tsx","../src/components/ConnectProviderList.tsx","../src/components/ConnectedAccountCard.tsx","../src/components/EmptyCard.tsx","../src/components/ImportCalendarsDialog.tsx","../src/components/SyncPreviewRail.tsx","../src/components/WizardStepper.tsx","../src/components/OnboardingStepDots.tsx","../src/components/MiniMonthPicker.tsx","../src/components/AccountCalendarsDialog.tsx","../src/components/BigCalendarView.tsx","../src/components/SyncDetailsDialog.tsx","../src/components/useConnectAccount.ts","../src/components/AddAccountMenu.tsx","../src/components/ConnectProviderRows.tsx","../src/components/CalendarMergedView.tsx","../src/lib/utils.ts","../src/lib/ui-provider.tsx","../src/lib/hooks/useControllableState.ts","../src/lib/hooks/useDisclosure.ts","../src/lib/hooks/useClickOutside.ts","../index.ts"],"sourcesContent":["// The basic components, re-exported from Radix Themes so a frontend imports every\n// component from this package and nothing from `@radix-ui/themes`.\n//\n// These are the identical objects, not wrappers — behaviour is Radix's. A component\n// becomes a real wrapper here only when ARM needs something Radix does not give, and\n// that edit then touches this library alone. Compound families (`Dialog.Root`,\n// `DropdownMenu.Item`, `Select.Item`, …) come through whole.\n//\n// Not exported, on purpose (primitives.test.ts holds this list and fails on any\n// Radix export that is neither re-exported nor named there):\n// Theme, useThemeContext, ThemeContext UIProvider owns the theme; frontends never mount it\n// ThemePanel, Reset dev tool / internal\n// Skeleton this library keeps its own (./Skeleton)\n// ChevronDownIcon, Thick*Icon Radix's own icon copies; the icon set (root index.ts) has ChevronDownIcon\n//\n// `Link` is exported as `TextLink`: react-router's `Link` shares files with it.\n\nexport {\n // Layout\n Box,\n Flex,\n Grid,\n Container,\n Section,\n Inset,\n AspectRatio,\n ScrollArea,\n Separator,\n // Typography\n Text,\n Heading,\n Blockquote,\n Code,\n Em,\n Kbd,\n Link as TextLink,\n Quote,\n Strong,\n // Actions and form controls\n Button,\n IconButton,\n TextField,\n TextArea,\n Checkbox,\n CheckboxGroup,\n CheckboxCards,\n Radio,\n RadioGroup,\n RadioCards,\n Select,\n Slider,\n Switch,\n SegmentedControl,\n // Overlays\n Dialog,\n AlertDialog,\n DropdownMenu,\n ContextMenu,\n Popover,\n HoverCard,\n Tooltip,\n Portal,\n // Feedback and data display\n Avatar,\n Badge,\n Callout,\n Card,\n DataList,\n Progress,\n Spinner,\n Table,\n Tabs,\n TabNav,\n // Utilities\n AccessibleIcon,\n Slot,\n Slottable,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\n\nexport type {\n AccessibleIconProps,\n AspectRatioProps,\n AvatarProps,\n BadgeProps,\n BlockquoteProps,\n BoxProps,\n ButtonProps,\n CardProps,\n CheckboxProps,\n CodeProps,\n ContainerProps,\n EmProps,\n FlexProps,\n GridProps,\n HeadingProps,\n IconButtonProps,\n InsetProps,\n KbdProps,\n LinkProps as TextLinkProps,\n PortalProps,\n ProgressProps,\n QuoteProps,\n RadioProps,\n ScrollAreaProps,\n SectionProps,\n SeparatorProps,\n SliderProps,\n SpinnerProps,\n StrongProps,\n SwitchProps,\n TextAreaProps,\n TextProps,\n TooltipProps,\n VisuallyHiddenProps,\n} from \"@radix-ui/themes\";\n","import type { CSSProperties } from \"react\";\n\n/**\n * Skeleton — loading placeholder. Generalizes the local `Skel` helper and the\n * inline `<div className=\"skeleton\" .../>` blocks used in the users, user-detail,\n * and home surfaces. Pulse animation + base color come from `.skeleton` in\n * globals.css.\n */\nexport interface SkeletonProps {\n width?: number | string;\n height?: number | string;\n /** Border radius. Ignored when `circle` is set. Defaults to var(--radius-2). */\n radius?: number | string;\n /** Render as a circle (avatars). */\n circle?: boolean;\n /** Bottom margin. */\n mb?: number | string;\n className?: string;\n style?: CSSProperties;\n}\n\nexport function Skeleton({\n width = \"100%\",\n height = \"var(--space-4)\" /* 16px == space-4 */,\n radius = \"var(--radius-2)\",\n circle = false,\n mb,\n className,\n style,\n}: SkeletonProps) {\n return (\n <div\n className={[\"skeleton\", className].filter(Boolean).join(\" \")}\n aria-hidden=\"true\"\n style={{\n width,\n height,\n borderRadius: circle ? \"50%\" : radius,\n marginBottom: mb,\n ...style,\n }}\n />\n );\n}\n\nexport default Skeleton;\n","import * as React from \"react\";\nimport * as RadixAccordion from \"@radix-ui/react-accordion\";\nimport { ChevronDownIcon } from \"@radix-ui/react-icons\";\n\n/**\n * Accordion — collapsible sections. Radix Themes has no accordion, so this is\n * built on the raw `@radix-ui/react-accordion` primitive. Styles live in\n * tokens.css (`.arm-accordion*`) — consumers' UnoCSS does not scan this\n * package. Moved here from core-fe so no frontend imports a Radix primitive.\n *\n * <Accordion type=\"single\" collapsible>\n * <AccordionItem value=\"a\">\n * <AccordionTrigger>Title</AccordionTrigger>\n * <AccordionContent>Body</AccordionContent>\n * </AccordionItem>\n * </Accordion>\n */\nexport const Accordion = React.forwardRef<\n React.ComponentRef<typeof RadixAccordion.Root>,\n React.ComponentPropsWithoutRef<typeof RadixAccordion.Root>\n>(({ className = \"\", ...props }, ref) => (\n <RadixAccordion.Root\n ref={ref}\n className={`arm-accordion ${className}`}\n {...props}\n />\n));\nAccordion.displayName = \"Accordion\";\n\nexport const AccordionItem = React.forwardRef<\n React.ComponentRef<typeof RadixAccordion.Item>,\n React.ComponentPropsWithoutRef<typeof RadixAccordion.Item>\n>(({ className = \"\", ...props }, ref) => (\n <RadixAccordion.Item ref={ref} className={`arm-accordion__item ${className}`} {...props} />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nexport const AccordionTrigger = React.forwardRef<\n React.ComponentRef<typeof RadixAccordion.Trigger>,\n React.ComponentPropsWithoutRef<typeof RadixAccordion.Trigger>\n>(({ className = \"\", children, ...props }, ref) => (\n <RadixAccordion.Header className=\"arm-accordion__header\">\n <RadixAccordion.Trigger\n ref={ref}\n className={`arm-accordion__trigger ${className}`}\n {...props}\n >\n {children}\n <ChevronDownIcon aria-hidden className=\"arm-accordion__chevron\" />\n </RadixAccordion.Trigger>\n </RadixAccordion.Header>\n));\nAccordionTrigger.displayName = \"AccordionTrigger\";\n\nexport const AccordionContent = React.forwardRef<\n React.ComponentRef<typeof RadixAccordion.Content>,\n React.ComponentPropsWithoutRef<typeof RadixAccordion.Content>\n>(({ className = \"\", children, ...props }, ref) => (\n <RadixAccordion.Content ref={ref} className={`arm-accordion__content ${className}`} {...props}>\n <div className=\"arm-accordion__body\">{children}</div>\n </RadixAccordion.Content>\n));\nAccordionContent.displayName = \"AccordionContent\";\n","import * as React from \"react\";\nimport * as RadixDialog from \"@radix-ui/react-dialog\";\nimport { Cross2Icon } from \"@radix-ui/react-icons\";\n\n/**\n * Drawer — a side sheet. Not a Radix Themes concept, so it is built on the raw\n * `@radix-ui/react-dialog` primitive (focus trap, Escape, overlay click). Styles\n * live in tokens.css (`.arm-drawer*`) — consumers' UnoCSS does not scan this\n * package. Moved here from core-fe so no frontend imports a Radix primitive.\n *\n * <Drawer open={open} onOpenChange={setOpen}>\n * <DrawerContent side=\"right\" size=\"md\">\n * <DrawerHeader><DrawerTitle>Notifications</DrawerTitle></DrawerHeader>\n * …\n * <DrawerDefaultClose />\n * </DrawerContent>\n * </Drawer>\n */\nexport const Drawer = RadixDialog.Root;\nexport const DrawerTrigger = RadixDialog.Trigger;\nexport const DrawerClose = RadixDialog.Close;\n\ntype Side = \"right\" | \"left\";\n/** sm 16rem · md 20rem · lg 480px */\ntype Size = \"sm\" | \"md\" | \"lg\";\n\nexport interface DrawerContentProps\n extends React.ComponentPropsWithoutRef<typeof RadixDialog.Content> {\n side?: Side;\n size?: Size;\n}\n\nexport const DrawerContent = React.forwardRef<\n React.ComponentRef<typeof RadixDialog.Content>,\n DrawerContentProps\n>(({ className = \"\", side = \"right\", size = \"md\", children, ...props }, ref) => (\n <RadixDialog.Portal>\n <RadixDialog.Overlay className=\"arm-drawer__overlay\" />\n <RadixDialog.Content\n ref={ref}\n data-side={side}\n data-size={size}\n className={`arm-drawer ${className}`}\n {...props}\n >\n {children}\n </RadixDialog.Content>\n </RadixDialog.Portal>\n));\nDrawerContent.displayName = \"DrawerContent\";\n\nexport const DrawerHeader: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className = \"\",\n children,\n ...props\n}) => (\n <div\n className={`arm-drawer__header ${className}`}\n {...props}\n >\n {children}\n </div>\n);\n\nexport const DrawerTitle = React.forwardRef<\n React.ComponentRef<typeof RadixDialog.Title>,\n React.ComponentPropsWithoutRef<typeof RadixDialog.Title>\n>(({ className = \"\", ...props }, ref) => (\n <RadixDialog.Title\n ref={ref}\n className={`arm-drawer__title ${className}`}\n {...props}\n />\n));\nDrawerTitle.displayName = \"DrawerTitle\";\n\nexport const DrawerDescription = React.forwardRef<\n React.ComponentRef<typeof RadixDialog.Description>,\n React.ComponentPropsWithoutRef<typeof RadixDialog.Description>\n>(({ className = \"\", ...props }, ref) => (\n <RadixDialog.Description ref={ref} className={`arm-drawer__description ${className}`} {...props} />\n));\nDrawerDescription.displayName = \"DrawerDescription\";\n\nexport const DrawerDefaultClose: React.FC = () => (\n <RadixDialog.Close\n aria-label=\"Close\"\n className=\"arm-drawer__close\"\n >\n <Cross2Icon aria-hidden className=\"arm-drawer__close-icon\" />\n </RadixDialog.Close>\n);\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { Box, Flex, Text } from \"@radix-ui/themes\";\n\n/**\n * AccentHeader — the amber two-tone title bar Figma uses on cards, dialogs,\n * and page banners (Target/Source Calendar, Preview, Upcoming Event, Confirm\n * Logout, Terms hero). Build-once pattern per the design ledger: a solid\n * `--accent-9` bar with a dark bold title, optionally with trailing controls\n * (e.g. the Month/Week/Day toggle lives inside the bar on the Preview card).\n *\n * Figma refs: ui-ux/figma/crops/month-card.png, confirm-dialog.png.\n */\nexport interface AccentHeaderProps {\n title: ReactNode;\n /** Right-aligned slot inside the bar (view toggles, actions). */\n trailing?: ReactNode;\n style?: CSSProperties;\n}\n\nexport function AccentHeader({ title, trailing, style }: AccentHeaderProps) {\n // Plain strings get the bar's standard Text treatment; element titles (e.g.\n // an AlertDialog.Title heading) render as-is so we never nest a heading\n // inside a span (invalid HTML).\n const titleNode =\n typeof title === \"string\" || typeof title === \"number\" ? (\n <Text size=\"3\" weight=\"medium\" style={{ color: \"var(--accent-contrast)\" }}>\n {title}\n </Text>\n ) : (\n title\n );\n return (\n <Flex\n align=\"center\"\n justify=\"between\"\n gap=\"3\"\n px=\"4\"\n style={{\n background: \"var(--accent-9)\",\n minHeight: \"var(--space-7)\",\n ...style,\n }}\n >\n {titleNode}\n {trailing}\n </Flex>\n );\n}\n\n/**\n * AccentCard — white panel with an AccentHeader bar and rounded corners\n * (measured r≈14 @1728 → var(--radius-5)) plus the soft card shadow seen on\n * every Figma card. The header is clipped by the card's radius.\n */\nexport interface AccentCardProps extends AccentHeaderProps {\n children: ReactNode;\n /** Radix padding scale for the body. Defaults to \"4\"; use \"0\" for flush content. */\n bodyPadding?: \"0\" | \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\";\n}\n\nexport function AccentCard({\n title,\n trailing,\n children,\n bodyPadding = \"4\",\n style,\n}: AccentCardProps) {\n return (\n <Box\n style={{\n background: \"var(--color-panel-solid)\",\n borderRadius: \"var(--radius-5)\",\n overflow: \"hidden\",\n boxShadow: \"var(--shadow-card)\",\n ...style,\n }}\n >\n <AccentHeader title={title} trailing={trailing} />\n <Box p={bodyPadding}>{children}</Box>\n </Box>\n );\n}\n\nexport default AccentHeader;\n","import type { ReactNode } from \"react\";\nimport { AlertDialog, Button } from \"@radix-ui/themes\";\nimport { layout } from \"./layout-tokens\";\nimport { CardFooter } from \"./CardFooter\";\n\n/**\n * ConfirmDialog — the confirm/cancel prompt used for destructive or\n * state-changing actions (Confirm Logout, Remove account, etc). Built on\n * Radix `AlertDialog` with a plain title/description and bottom-right\n * actions, matching the app's other dialogs (e.g. ImportCalendarsDialog):\n * neutral outline Cancel, amber-primary Confirm.\n */\nexport interface ConfirmDialogProps {\n /** Dialog title, rendered inside the AccentHeader bar. */\n title: ReactNode;\n /** Question / body copy. */\n description: ReactNode;\n /** Confirm button label. Defaults to \"Yes\". */\n confirmLabel?: ReactNode;\n /** Cancel button label. Defaults to \"Cancel\". */\n cancelLabel?: ReactNode;\n /** Called when the confirm action is activated (dialog still closes via AlertDialog.Action). */\n onConfirm?: () => void;\n /** Element that opens the dialog, rendered inside AlertDialog.Trigger. Omit for a fully controlled dialog. */\n trigger?: ReactNode;\n /** Controlled open state — omit for uncontrolled, trigger-driven usage. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\nexport function ConfirmDialog({\n title,\n description,\n confirmLabel = \"Yes\",\n cancelLabel = \"Cancel\",\n onConfirm,\n trigger,\n open,\n onOpenChange,\n}: ConfirmDialogProps) {\n return (\n <AlertDialog.Root open={open} onOpenChange={onOpenChange}>\n {trigger ? <AlertDialog.Trigger>{trigger}</AlertDialog.Trigger> : null}\n <AlertDialog.Content maxWidth={layout.dialogSm}>\n <AlertDialog.Title\n size=\"5\"\n mb=\"1\"\n style={{ fontFamily: \"var(--heading-font-family)\", fontWeight: \"var(--font-weight-medium)\" }}\n >\n {title}\n </AlertDialog.Title>\n <AlertDialog.Description size=\"2\" color=\"gray\" mb=\"5\">\n {description}\n </AlertDialog.Description>\n <CardFooter justify=\"between\" noTopMargin>\n <AlertDialog.Cancel>\n <Button size=\"2\" variant=\"outline\" color=\"gray\">\n {cancelLabel}\n </Button>\n </AlertDialog.Cancel>\n <AlertDialog.Action>\n <Button size=\"2\" className=\"btn-amber-primary\" onClick={onConfirm}>\n {confirmLabel}\n </Button>\n </AlertDialog.Action>\n </CardFooter>\n </AlertDialog.Content>\n </AlertDialog.Root>\n );\n}\n\nexport default ConfirmDialog;\n","/** Radix space-scale layout widths. Originally a subset of the app's\n * src/lib/layout-tokens.ts covering only what this package's own components\n * reference; now also exported so consumers stop hand-rolling their own\n * copies (arm-admin had none at all, and core-fe carries a 5-constant\n * fork). Values must match the app's copy — see README.md's \"Files\n * duplicated from the app\". */\nexport const layout = {\n contentMax: \"calc(15 * var(--space-9) + var(--space-5))\",\n accountCardW: \"calc(3 * var(--space-9) + var(--space-8))\",\n accountCardMinH: \"calc(2 * var(--space-9) - var(--space-2))\",\n monthTitleMinW: \"calc(3 * var(--space-9) - var(--space-1))\",\n bigCalendarH: \"calc(10 * var(--space-9))\",\n sidebarColBasis: \"calc(4 * var(--space-9) - var(--space-2))\",\n sidebarColMin: \"calc(3 * var(--space-9) + var(--space-6))\",\n syncColMin: \"calc(5 * var(--space-9))\",\n syncColWide: \"calc(7 * var(--space-9) + var(--space-6))\",\n dialogSm: \"calc(6 * var(--space-9) - var(--space-2))\",\n dialogBody: \"calc(5 * var(--space-9) + var(--space-7))\",\n authFormMax: \"calc(6 * var(--space-9) + var(--space-8))\",\n brandLogoMax: \"calc(6 * var(--space-9) + var(--space-8) - var(--space-1))\",\n connectedAccountCardH: \"calc(var(--space-9) - var(--space-1))\",\n dialogMd: \"calc(6 * var(--space-9) + var(--space-6))\",\n dialogLg: \"calc(7 * var(--space-9) - var(--space-1))\",\n emptyStateMax: \"calc(10 * var(--space-9))\",\n emptyStateCopyMax: \"calc(6 * var(--space-9))\",\n providerChooserMax: \"calc(6 * var(--space-9) + var(--space-6))\",\n /* Admin portal. The two audit columns are fixed so the header grid and\n * every row grid resolve to the same track sizes; settingsGridMin is the\n * floor that keeps a 5–6 column table legible before it starts scrolling\n * horizontally instead of crushing its columns. */\n auditColTime: \"calc(var(--space-9) + var(--space-2))\",\n auditColAction: \"calc(var(--space-9) + var(--space-5) + var(--space-1))\",\n searchFieldW: \"calc(3 * var(--space-9) + var(--space-5) + var(--space-1))\",\n settingsGridMin: \"calc(5 * var(--space-9) + var(--space-5))\",\n placeholderMd: \"calc(6 * var(--space-9) + var(--space-4))\",\n} as const;\n","import type { ReactNode } from \"react\";\nimport { Flex } from \"@radix-ui/themes\";\n\nexport interface CardFooterProps {\n children: ReactNode;\n justify?: \"end\" | \"between\";\n /** Omit the top margin when the content above already ends with its own\n * bottom margin/gap (e.g. Flex `mb`) — avoids doubled spacing. */\n noTopMargin?: boolean;\n /** Match the enclosing container's own padding so the negative-margin\n * breakout lines up flush with its edges. Defaults to Card size=\"3\"'s\n * var(--space-5); pass the container's actual padding otherwise (e.g.\n * a default-size Card's var(--space-3), StepCard's var(--space-4)). */\n pad?: string;\n /** Match the enclosing container's own corner radius so the footer's\n * bottom corners line up. Defaults to Card size=\"3\"+'s var(--radius-5);\n * default-size Card (1-2) uses var(--radius-4). */\n radius?: string;\n}\n\n/** Full-bleed gray action bar for the bottom of a Card — breaks out of the\n * Card's own padding so it reads as a distinct footer strip, same shape as\n * ImportCalendarsDialog's button row. Use for any Card/Dialog that ends in\n * one or more buttons instead of a plain Separator + Flex. */\nexport function CardFooter({\n children,\n justify = \"end\",\n noTopMargin,\n pad = \"var(--space-5)\",\n radius = \"var(--radius-5)\",\n}: CardFooterProps) {\n return (\n <Flex\n justify={justify}\n style={{\n margin: `${noTopMargin ? \"0\" : \"var(--space-5)\"} calc(-1 * ${pad}) calc(-1 * ${pad})`,\n padding: `var(--space-4) ${pad}`,\n alignItems: \"center\",\n background: \"var(--gray-2)\",\n borderTop: \"1px solid var(--gray-5)\",\n borderRadius: `0 0 ${radius} ${radius}`,\n }}\n >\n {children}\n </Flex>\n );\n}\n","import type { CSSProperties } from \"react\";\nimport { PauseIcon } from \"@radix-ui/react-icons\";\nimport { iconSize } from \"./icon-size\";\n\n/**\n * PausedBadge — small outline pill marking a paused account. Sits top-left\n * of AccountCard, immediately right of the avatar. White fill, 1px\n * `--color-paused` border + text, full radius pill, a tiny circled pause\n * glyph, then the label.\n *\n * Figma ref: ui-ux/figma/crops/account-card-menu.png. Measured 59×17 @1728\n * (≈49×14 app scale) — genuinely tiny, so this is built directly rather than\n * from Radix `Badge` (Badge's smallest size/padding can't hit an 18px\n * height). Fit level: Light customization.\n *\n * Deviation: the glyph inside the circle is rendered at 8px rather than the\n * ~10px in the base spec — at 10px it collided with the circle's stroke at\n * this scale, so it was sized down to keep the badge legible instead of\n * cluttered.\n */\nexport interface PausedBadgeProps {\n label?: string;\n style?: CSSProperties;\n}\n\nexport function PausedBadge({ label = \"Paused\", style }: PausedBadgeProps) {\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"var(--space-1)\",\n height: \"calc(var(--space-4) + var(--space-1))\",\n padding: \"var(--space-1) var(--space-2)\",\n border: \"1px solid var(--color-paused)\",\n borderRadius: 999,\n background: \"var(--color-panel-solid)\",\n color: \"var(--color-paused)\",\n fontSize: \"var(--font-size-1)\",\n fontWeight: 600,\n lineHeight: 1,\n whiteSpace: \"nowrap\",\n ...style,\n }}\n >\n <span\n aria-hidden=\"true\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"var(--space-3)\",\n height: \"var(--space-3)\",\n flexShrink: 0,\n borderRadius: \"50%\",\n border: \"1px solid var(--color-paused)\",\n }}\n >\n <PauseIcon style={iconSize(\"--space-2\")} />\n </span>\n {label}\n </span>\n );\n}\n\nexport default PausedBadge;\n","import type { CSSProperties } from \"react\";\n\n/** Square size for a Radix icon, expressed on the Radix space scale.\n *\n * Icons must be sized through `style`, never through the `width`/`height`\n * props. Those props land on the underlying `<svg>` as presentation\n * attributes, and SVG attributes do not accept CSS custom properties — the\n * browser rejects `width=\"var(--space-4)\"` outright and the icon falls back\n * to its intrinsic 300x300 default. That is not a cosmetic problem: a 300px\n * icon inside a toolbar covers the page and swallows every click behind it\n * (this is exactly what happened to Topbar's mobile hamburger).\n *\n * Going through `style` resolves the var and keeps icon sizes on the space\n * scale, so they still track the Theme's `scaling` prop.\n */\nexport function iconSize(space: `--space-${number}`): CSSProperties {\n return { width: `var(${space})`, height: `var(${space})` };\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { Avatar, Box, DropdownMenu, Flex, IconButton, Text } from \"@radix-ui/themes\";\nimport { DotsVerticalIcon, PauseIcon, PlayIcon, TrashIcon } from \"@radix-ui/react-icons\";\nimport { layout } from \"./layout-tokens\";\nimport { PausedBadge } from \"./PausedBadge\";\n\n/**\n * AccountCard — the account tile used on the accounts grid: avatar + name +\n * email, an optional PausedBadge, and a kebab menu (Pause/Resume, Delete).\n *\n * Figma refs: ui-ux/figma/crops/account-grid-clean.png (clean 4×2 grid),\n * ui-ux/figma/crops/account-card-menu.png (paused card, kebab menu open).\n * Fit level: Direct/Light — Card composition + DropdownMenu with a native\n * red item (no custom menu styling needed).\n */\nexport interface AccountCardProps {\n name: string;\n email: string;\n avatarSrc?: string;\n /** Shows PausedBadge next to the avatar and swaps the kebab's first item to \"Resume\". */\n paused?: boolean;\n onPause?: () => void;\n onResume?: () => void;\n onDelete?: () => void;\n /** Makes the card clickable (kebab menu excluded) — e.g. open the account's sync setup. */\n onClick?: () => void;\n /** Small overlay badge on the avatar's corner — e.g. a provider logo. */\n badge?: ReactNode;\n /** Tints the avatar with the account's color token (e.g. \"var(--blue-9)\"). */\n accentColor?: string;\n style?: CSSProperties;\n}\n\nexport function AccountCard({\n name,\n email,\n avatarSrc,\n paused = false,\n onPause,\n onResume,\n onDelete,\n onClick,\n badge,\n accentColor,\n style,\n}: AccountCardProps) {\n const nameText = (\n <Text as={onClick ? \"span\" : \"p\"} size=\"3\" weight=\"medium\" truncate style={{ color: \"var(--gray-12)\", minWidth: 0 }}>\n {name}\n </Text>\n );\n\n return (\n /* The card takes the mouse click, but it is not role=\"button\": the kebab\n * inside it would then be a control nested in a control, which keyboard and\n * screen-reader users cannot reach. The name is the keyboard control. */\n <Box\n onClick={onClick}\n style={{\n width: layout.accountCardW,\n minHeight: layout.accountCardMinH,\n padding: \"var(--space-3)\",\n background: \"var(--color-panel-solid)\",\n borderRadius: \"var(--radius-4)\",\n boxShadow: \"var(--shadow-card)\",\n cursor: onClick ? \"pointer\" : undefined,\n ...style,\n }}\n >\n <Flex align=\"center\" justify=\"between\" gap=\"2\" mb=\"3\">\n <Flex align=\"center\" gap=\"2\" style={{ minWidth: 0 }}>\n <div style={{ position: \"relative\", flexShrink: 0 }}>\n <Avatar\n size=\"3\"\n radius=\"full\"\n src={avatarSrc}\n fallback={name.charAt(0).toUpperCase() || \"?\"}\n style={\n accentColor\n ? { background: accentColor, color: \"white\" }\n : undefined\n }\n />\n {badge && (\n <span\n style={{\n position: \"absolute\",\n right: \"calc(-1 * var(--space-1))\",\n bottom: \"calc(-1 * var(--space-1))\",\n width: \"var(--space-4)\",\n height: \"var(--space-4)\",\n borderRadius: \"50%\",\n background: \"var(--color-panel-solid)\",\n border: \"1px solid var(--gray-4)\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transform: \"scale(0.72)\",\n }}\n >\n {badge}\n </span>\n )}\n </div>\n {paused && <PausedBadge />}\n </Flex>\n\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconButton\n variant=\"ghost\"\n color=\"gray\"\n aria-label=\"Account actions\"\n style={{ flexShrink: 0 }}\n onClick={(e) => e.stopPropagation()}\n >\n <DotsVerticalIcon />\n </IconButton>\n </DropdownMenu.Trigger>\n {/* Portal content still bubbles through the React tree — keep menu\n clicks from triggering the card's onClick */}\n <DropdownMenu.Content align=\"end\" onClick={(e) => e.stopPropagation()}>\n {paused ? (\n <DropdownMenu.Item onSelect={onResume}>\n <PlayIcon /> Resume\n </DropdownMenu.Item>\n ) : (\n <DropdownMenu.Item onSelect={onPause}>\n <PauseIcon /> Pause\n </DropdownMenu.Item>\n )}\n <DropdownMenu.Item color=\"red\" onSelect={onDelete}>\n <TrashIcon /> Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </Flex>\n\n <Box style={{ minWidth: 0 }}>\n {onClick ? (\n <button\n type=\"button\"\n className=\"card-title-button\"\n onClick={(e) => {\n e.stopPropagation();\n onClick();\n }}\n >\n {nameText}\n </button>\n ) : (\n nameText\n )}\n <Text as=\"p\" size=\"1\" color=\"gray\" truncate>\n {email}\n </Text>\n </Box>\n </Box>\n );\n}\n\nexport default AccountCard;\n","import type { CSSProperties } from \"react\";\nimport { Box, Flex, Heading, IconButton, Text } from \"@radix-ui/themes\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"@radix-ui/react-icons\";\nimport { layout } from \"./layout-tokens\";\nimport { iconSize } from \"./icon-size\";\nimport { headingSize } from \"./heading-scale\";\n\n/**\n * MonthGrid — the month calendar grid from the Preview card (Target/Source\n * Calendar → Preview flow). Pure Date math, no date library: weeks start\n * Monday (Figma starts its week on Mon), and only the leading/trailing\n * adjacent-month days needed to complete the first and last week are\n * rendered (not a fixed 6 rows).\n *\n * Fit level: Truly custom (only genuine no-Radix-equivalent gap — layout via\n * CSS grid, no date lib).\n * Figma refs: ui-ux/figma/crops/preview-month.png, ui-ux/figma/crops/month-card.png.\n */\nexport interface MonthGridProps {\n /** Any date within the month to display. */\n month: Date;\n /** Called with the first-of-month date when the prev/next chevrons are used. */\n onMonthChange?: (date: Date) => void;\n /** Days that should render an event dot (matched by calendar day, time ignored). */\n events?: Date[];\n /** Per-day colored dots keyed by `date.toDateString()` → CSS color tokens (max 3 shown).\n * Takes precedence over `events` when a day has an entry. */\n dayDots?: Map<string, string[]>;\n /** Defaults to `new Date()`. Pass a fixed date for stable/deterministic visuals. */\n today?: Date;\n /** Makes day cells clickable buttons; receives the clicked date. */\n onSelectDay?: (date: Date) => void;\n style?: CSSProperties;\n}\n\nconst WEEKDAY_LABELS = [\"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\", \"Sun\"];\nconst CELL_WIDTH = \"var(--space-9)\";\nconst CELL_HEIGHT = \"var(--space-8)\";\nconst GRID_GAP = \"var(--space-2)\";\n\nconst MONTH_YEAR_FORMAT = new Intl.DateTimeFormat(\"en-US\", { month: \"long\", year: \"numeric\" });\nconst FULL_DATE_FORMAT = new Intl.DateTimeFormat(\"en-US\", {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n});\n\nfunction isSameDay(a: Date, b: Date): boolean {\n return (\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n );\n}\n\n/** JS `getDay()` is 0=Sunday..6=Saturday; remap to 0=Monday..6=Sunday. */\nfunction mondayIndex(jsDay: number): number {\n return (jsDay + 6) % 7;\n}\n\ninterface GridDay {\n date: Date;\n inCurrentMonth: boolean;\n}\n\n/** Builds exactly the weeks needed to cover `month`, Monday-first, padding\n * only the leading/trailing days required to complete the first/last row. */\nfunction buildGridDays(month: Date): GridDay[] {\n const monthIndex = month.getMonth();\n const year = month.getFullYear();\n\n const firstOfMonth = new Date(year, monthIndex, 1);\n const lastOfMonth = new Date(year, monthIndex + 1, 0);\n\n const leadingCount = mondayIndex(firstOfMonth.getDay());\n const trailingCount = 6 - mondayIndex(lastOfMonth.getDay());\n\n const gridStart = new Date(year, monthIndex, 1 - leadingCount);\n const totalDays = leadingCount + lastOfMonth.getDate() + trailingCount;\n\n return Array.from({ length: totalDays }, (_, i) => {\n const date = new Date(gridStart.getFullYear(), gridStart.getMonth(), gridStart.getDate() + i);\n return { date, inCurrentMonth: date.getMonth() === monthIndex };\n });\n}\n\nfunction addMonths(date: Date, delta: number): Date {\n return new Date(date.getFullYear(), date.getMonth() + delta, 1);\n}\n\nexport function MonthGrid({\n month,\n onMonthChange,\n events = [],\n dayDots,\n today,\n onSelectDay,\n style,\n}: MonthGridProps) {\n const resolvedToday = today ?? new Date();\n const days = buildGridDays(month);\n const eventDayKeys = new Set(events.map((d) => d.toDateString()));\n\n return (\n <Flex direction=\"column\" align=\"center\" gap=\"4\" style={style}>\n {/* Header: ‹ March 2022 › */}\n <Flex align=\"center\" gap=\"2\">\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n color=\"gray\"\n aria-label=\"Previous month\"\n onClick={() => onMonthChange?.(addMonths(month, -1))}\n >\n <ChevronLeftIcon style={iconSize(\"--space-4\")} />\n </IconButton>\n <Heading\n as=\"h2\"\n size={headingSize.h2}\n weight=\"medium\"\n style={{ minWidth: layout.monthTitleMinW, textAlign: \"center\" }}\n >\n {MONTH_YEAR_FORMAT.format(month)}\n </Heading>\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n color=\"gray\"\n aria-label=\"Next month\"\n onClick={() => onMonthChange?.(addMonths(month, 1))}\n >\n <ChevronRightIcon style={iconSize(\"--space-4\")} />\n </IconButton>\n </Flex>\n\n {/* Weekday row */}\n <Box\n style={{\n display: \"grid\",\n gridTemplateColumns: `repeat(7, ${CELL_WIDTH})`,\n gap: GRID_GAP,\n }}\n >\n {WEEKDAY_LABELS.map((label) => (\n <Text\n key={label}\n size=\"2\"\n align=\"center\"\n style={{ color: \"var(--gray-11)\" }}\n >\n {label}\n </Text>\n ))}\n </Box>\n\n {/* Date grid */}\n <Box\n style={{\n display: \"grid\",\n gridTemplateColumns: `repeat(7, ${CELL_WIDTH})`,\n gap: GRID_GAP,\n }}\n >\n {days.map(({ date, inCurrentMonth }) => {\n const isToday = isSameDay(date, resolvedToday);\n const dots = dayDots?.get(date.toDateString());\n const hasEvent = eventDayKeys.has(date.toDateString());\n\n const cellStyle: CSSProperties = {\n position: \"relative\",\n width: CELL_WIDTH,\n height: CELL_HEIGHT,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxSizing: \"border-box\",\n background: !inCurrentMonth\n ? \"var(--gray-2)\"\n : isToday\n ? \"var(--color-panel-solid)\"\n : \"transparent\",\n border: isToday ? \"1.5px solid var(--accent-9)\" : \"none\",\n borderRadius: isToday ? \"var(--radius-3)\" : !inCurrentMonth ? \"var(--radius-2)\" : undefined,\n padding: 0,\n font: \"inherit\",\n cursor: onSelectDay ? \"pointer\" : undefined,\n };\n\n const dayNumber = (\n <>\n {dots && dots.length > 0 ? (\n <span\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n bottom: \"var(--space-1)\",\n left: 0,\n right: 0,\n display: \"flex\",\n justifyContent: \"center\",\n gap: \"2px\",\n }}\n >\n {dots.slice(0, 3).map((color, i) => (\n <span\n key={i}\n style={{\n width: \"var(--space-1)\",\n height: \"var(--space-1)\",\n borderRadius: \"50%\",\n background: color,\n }}\n />\n ))}\n </span>\n ) : (\n hasEvent && (\n <span\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n top: \"var(--space-1)\",\n right: \"var(--space-2)\",\n width: \"var(--space-2)\",\n height: \"var(--space-2)\",\n borderRadius: \"50%\",\n background: \"var(--accent-9)\",\n }}\n />\n )\n )}\n <Text\n size=\"3\"\n style={{\n color: inCurrentMonth ? \"var(--gray-12)\" : \"var(--gray-11)\",\n fontWeight: isToday ? 600 : 400,\n }}\n >\n {date.getDate()}\n </Text>\n </>\n );\n\n const key = date.toISOString();\n\n if (onSelectDay) {\n return (\n <button\n key={key}\n type=\"button\"\n onClick={() => onSelectDay(date)}\n aria-label={FULL_DATE_FORMAT.format(date)}\n style={cellStyle}\n >\n {dayNumber}\n </button>\n );\n }\n\n return (\n <div key={key} style={cellStyle}>\n {dayNumber}\n </div>\n );\n })}\n </Box>\n </Flex>\n );\n}\n\nexport default MonthGrid;\n","/**\n * One heading size per level, for every `<Heading>` in the platform.\n *\n * Headings used to pick a Radix `size` per instance, so the same `<h1>`\n * rendered at 14.4px in the shell, 16.2px in a remote and 18px on Home, and\n * an `<h3>` could equal its own `<h1>` or the 12.6px body copy. The level now\n * decides the size: pass `size={headingSize[level]}` alongside `as={level}`.\n *\n * Values are Radix font-size steps, so they follow the Theme's `scaling`. At\n * the platform's 90% that is h1 21.6px, h2 18px, h3 16.2px, h4 14.4px — every\n * level one step apart and above body text (step 2, 12.6px).\n */\nexport const headingSize = {\n h1: \"6\",\n h2: \"5\",\n h3: \"4\",\n h4: \"3\",\n} as const;\n\nexport type HeadingLevel = keyof typeof headingSize;\n\n/** Radix step body copy renders at — every heading level must sit above it. */\nexport const BODY_TEXT_SIZE = \"2\";\n","import { useEffect } from \"react\";\nimport { Callout } from \"@radix-ui/themes\";\nimport { CheckCircledIcon, ExclamationTriangleIcon } from \"@radix-ui/react-icons\";\nimport { layout } from \"./layout-tokens\";\n\nexport interface ToastProps {\n msg: string;\n color?: \"green\" | \"red\";\n onDone: () => void;\n durationMs?: number;\n}\n\n/** Fixed bottom-right auto-dismissing confirmation — the shared shape for\n * \"did my save work\" feedback across the app (previously a one-off local\n * component on AdminUserDetailPage only). */\nexport function Toast({ msg, color = \"green\", onDone, durationMs = 3000 }: ToastProps) {\n useEffect(() => {\n const t = setTimeout(onDone, durationMs);\n return () => clearTimeout(t);\n }, [onDone, durationMs]);\n\n return (\n <div\n style={{\n position: \"fixed\",\n bottom: \"var(--space-5)\",\n right: \"var(--space-5)\",\n zIndex: 10000,\n maxWidth: layout.dialogBody,\n pointerEvents: \"none\",\n }}\n >\n <Callout.Root color={color} variant=\"soft\" size=\"1\">\n <Callout.Icon>\n {color === \"red\" ? <ExclamationTriangleIcon /> : <CheckCircledIcon />}\n </Callout.Icon>\n <Callout.Text>{msg}</Callout.Text>\n </Callout.Root>\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\n\n/**\n * IconTile — the app's one icon-well treatment: a bordered rounded-square\n * tile around a feature/action/logo icon. Used for app-shortcut icons,\n * provider/account logos, and empty-state icons alike, so every \"icon in a\n * box\" in the app reads as the same component instead of one-off inline\n * styles with drifting border/radius/fill choices.\n */\nexport interface IconTileProps {\n children: ReactNode;\n /** Tile size — defaults to var(--space-7), the size used across the app. */\n size?: string;\n}\n\nexport function IconTile({ children, size = \"var(--space-7)\" }: IconTileProps) {\n return (\n <div\n style={{\n width: size,\n height: size,\n borderRadius: \"var(--radius-4)\",\n background: \"var(--color-panel-solid)\",\n border: \"1px solid var(--gray-5)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n }}\n >\n {children}\n </div>\n );\n}\n\nexport default IconTile;\n","import { Box, Flex, Text } from \"@radix-ui/themes\";\nimport { LockClosedIcon } from \"@radix-ui/react-icons\";\n\nexport interface EventBlockProps {\n title: string;\n time: string;\n detail?: string;\n color: string;\n locked?: boolean;\n}\n\n/** Solid-colored calendar-event chip — a filled block in the sync's own\n * color with white text, matching OneCal's SYNC PREVIEW mockups. Used\n * anywhere a real (or sample) event needs to read as \"this calendar's\n * color\", not a thin accent bar + badge. */\nexport function EventBlock({ title, time, detail, color, locked }: EventBlockProps) {\n return (\n <Flex\n align=\"center\"\n justify=\"between\"\n style={{\n background: color,\n borderRadius: \"var(--radius-3)\",\n padding: \"var(--space-3)\",\n color: \"white\",\n }}\n >\n <Box style={{ minWidth: 0 }}>\n <Text as=\"p\" size=\"2\" weight=\"medium\" style={{ color: \"white\" }} truncate>\n {title}\n </Text>\n <Text as=\"p\" size=\"1\" style={{ color: \"rgba(255,255,255,0.85)\" }} truncate>\n {time}\n {detail ? ` · ${detail}` : \"\"}\n </Text>\n </Box>\n {locked && <LockClosedIcon style={{ flexShrink: 0, color: \"rgba(255,255,255,0.85)\" }} />}\n </Flex>\n );\n}\n","import type { KeyboardEvent, ReactNode } from \"react\";\nimport { Box } from \"@radix-ui/themes\";\n\nexport interface DataTableRowProps {\n children: ReactNode;\n /** Grid/flex layout for the row — e.g. `{ display: \"grid\", gridTemplateColumns: \"2fr 1fr 1fr\" }`.\n * Column shape varies per table, so it's always supplied by the caller rather than fixed here. */\n style?: React.CSSProperties;\n /** Draws the row separator above every row except the first — pass `idx > 0`. */\n showBorder?: boolean;\n /** Makes the row a keyboard-focusable, clickable target (role=\"button\", Enter/Space activation,\n * amber focus ring). Omit for plain display rows (most tables — see CalendarSyncsPage, which\n * keeps its per-cell action button interactive instead of the row). */\n onActivate?: () => void;\n /** Highlights the row as the current selection — only meaningful with `onActivate`. */\n selected?: boolean;\n className?: string;\n \"aria-label\"?: string;\n}\n\n/** Shared plumbing for the dense data-table-row pattern used across the admin\n * users/audit tables, calendar syncs list, and home activity feed: hover\n * wash, optional keyboard-accessible selection, and the border-top-except-\n * first-row rule. Deliberately layout-agnostic — each table's column count\n * and widths differ (see globals.css's own `.data-table-row` comment history),\n * so `style` carries the grid/flex shape and `children` carries the cells;\n * this component only owns the classes and interaction/border wiring that\n * were previously hand-copied into five separate page files. */\nexport function DataTableRow({\n children,\n style,\n showBorder = false,\n onActivate,\n selected = false,\n className,\n \"aria-label\": ariaLabel,\n}: DataTableRowProps) {\n const interactive = Boolean(onActivate);\n\n function handleKeyDown(e: KeyboardEvent<HTMLDivElement>) {\n if (!onActivate) return;\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onActivate();\n }\n }\n\n return (\n <Box\n role={interactive ? \"button\" : undefined}\n tabIndex={interactive ? 0 : undefined}\n aria-label={ariaLabel}\n onClick={onActivate}\n onKeyDown={interactive ? handleKeyDown : undefined}\n className={[\n \"data-table-row\",\n interactive && \"data-table-row--interactive\",\n interactive && selected && \"data-table-row--selected\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n style={{\n borderTop: showBorder ? \"1px solid var(--gray-3)\" : undefined,\n ...style,\n }}\n >\n {children}\n </Box>\n );\n}\n","import { useId } from \"react\";\nimport { Card, Flex, Text } from \"@radix-ui/themes\";\n\nexport interface MetricCardProps {\n label: string;\n value: string;\n delta: string;\n deltaDir: \"up\" | \"down\" | \"flat\";\n /** Which delta direction reads as \"good\" for this metric — e.g. \"up\" for\n * revenue, \"down\" for error rate. Colors the delta text green/red. */\n goodDirection: \"up\" | \"down\";\n /** Status-dot color (top-right corner) — pass a semantic token\n * (`var(--green-9)`, `var(--red-9)`, `var(--amber-9)`, `var(--gray-9)`). */\n statusColor: string;\n /** Recent-history series for the inline sparkline. */\n sparkline: number[];\n}\n\n/** Admin/platform stat tile: label + status dot, big value, delta indicator,\n * inline sparkline. Used for dashboard \"platform health\" grids. */\nexport function MetricCard({\n label,\n value,\n delta,\n deltaDir,\n goodDirection,\n statusColor,\n sparkline,\n}: MetricCardProps) {\n const deltaColor =\n deltaDir === \"flat\"\n ? \"var(--gray-11)\"\n : deltaDir === goodDirection\n ? \"var(--green-11)\"\n : \"var(--red-11)\";\n\n const deltaPrefix = deltaDir === \"up\" ? \"↑ \" : deltaDir === \"down\" ? \"↓ \" : \"\";\n\n return (\n <Card className=\"metric-card\">\n <Flex direction=\"column\" p=\"1\">\n {/* Label + status dot */}\n <Flex align=\"center\" justify=\"between\" mb=\"3\">\n <Text as=\"span\" className=\"ds-section-label\">{label}</Text>\n <div\n style={{\n width: \"var(--space-2)\",\n height: \"var(--space-2)\",\n borderRadius: \"50%\",\n background: statusColor,\n flexShrink: 0,\n }}\n />\n </Flex>\n\n {/* Metric value */}\n <Text as=\"p\" className=\"metric-card-value\">\n {value}\n </Text>\n\n {/* Delta + sparkline */}\n <Flex align=\"end\" justify=\"between\">\n <Text size=\"1\" style={{ color: deltaColor, lineHeight: 1.4 }}>\n {deltaPrefix}\n {delta}\n </Text>\n <Sparkline data={sparkline} color={statusColor} />\n </Flex>\n </Flex>\n </Card>\n );\n}\n\nfunction Sparkline({ data, color }: { data: number[]; color: string }) {\n const W = 72;\n const H = 28;\n const min = Math.min(...data);\n const max = Math.max(...data);\n const range = max - min || 1;\n\n const pts = data.map((v, i) => ({\n x: (i / (data.length - 1)) * W,\n y: H - ((v - min) / range) * H * 0.75 - H * 0.1,\n }));\n\n const line = pts\n .map((p, i) => `${i === 0 ? \"M\" : \"L\"} ${p.x.toFixed(1)} ${p.y.toFixed(1)}`)\n .join(\" \");\n\n const area = [\n `M 0 ${H}`,\n ...pts.map((p) => `L ${p.x.toFixed(1)} ${p.y.toFixed(1)}`),\n `L ${W} ${H} Z`,\n ].join(\" \");\n\n // Per-instance id — a color-derived id collides when metrics share a\n // status color, making them all reference the first card's gradient.\n // useId's colons are stripped: they break url(#…) fragment references.\n const rawId = useId();\n const gradId = `spk${rawId.replace(/[^a-zA-Z0-9_-]/g, \"\")}`;\n\n return (\n <svg\n width={W}\n height={H}\n viewBox={`0 0 ${W} ${H}`}\n aria-hidden\n style={{ overflow: \"visible\", flexShrink: 0 }}\n >\n <defs>\n <linearGradient id={gradId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={color} stopOpacity=\"0.18\" />\n <stop offset=\"100%\" stopColor={color} stopOpacity=\"0\" />\n </linearGradient>\n </defs>\n <path d={area} fill={`url(#${gradId})`} />\n <path\n d={line}\n fill=\"none\"\n stroke={color}\n strokeWidth=\"1.5\"\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { Badge, Button, Card, Flex, Text } from \"@radix-ui/themes\";\nimport { ArrowRightIcon } from \"@radix-ui/react-icons\";\nimport { IconTile } from \"./IconTile\";\nimport { CardFooter } from \"./CardFooter\";\nimport { iconSize } from \"./icon-size\";\n\nexport interface AppCardProps {\n href: string;\n icon: ReactNode;\n name: string;\n description: string;\n /** Short status shown as a pill after the name (\"BETA\"). It never shrinks,\n * so a long name truncates in front of it. */\n badge?: string;\n}\n\n/** Workspace-shortcut tile: icon + name header, description, \"Open\" CTA\n * footer. Used for the home dashboard's granted-apps grid. */\nexport function AppCard({ href, icon, name, description, badge }: AppCardProps) {\n return (\n <Card style={{ height: \"100%\", display: \"flex\", flexDirection: \"column\" }}>\n <Flex direction=\"column\" gap=\"3\" p=\"1\" flexGrow=\"1\">\n {/* Header row: icon well + name */}\n <Flex align=\"center\" gap=\"3\" minWidth=\"0\">\n <IconTile>{icon}</IconTile>\n <Text\n size=\"4\"\n weight=\"medium\"\n style={{ color: \"var(--gray-12)\", fontFamily: \"var(--font-poppins)\" }}\n truncate\n >\n {name}\n </Text>\n {badge && (\n <Badge color=\"gray\" variant=\"soft\" size=\"1\" radius=\"full\" style={{ flexShrink: 0 }}>\n {badge}\n </Badge>\n )}\n </Flex>\n\n <Text\n size=\"2\"\n style={{ color: \"var(--gray-11)\", fontFamily: \"var(--font-poppins)\", lineHeight: 1.5 }}\n >\n {description}\n </Text>\n </Flex>\n\n <CardFooter pad=\"var(--space-3)\" radius=\"var(--radius-4)\">\n <Button size=\"2\" className=\"btn-amber-primary\" asChild>\n <Link to={href}>\n Open\n <ArrowRightIcon style={iconSize(\"--space-3\")} />\n </Link>\n </Button>\n </CardFooter>\n </Card>\n );\n}\n","import { Text } from \"@radix-ui/themes\";\nimport { DataTableRow } from \"./DataTableRow\";\n\nexport interface ActivityRowProps {\n /** Short colored tag, e.g. \"AUTH\", \"ROLE\", \"PROV\" — matches an audit-log\n * action code. */\n tag: string;\n /** Tag color (semantic token, e.g. `var(--violet-9)`). */\n tagColor: string;\n msg: string;\n actor?: string;\n timeAgo?: string;\n timestamp: string;\n showBorder: boolean;\n}\n\n/** Sentry-style dense activity-feed row: colored type tag, message + actor,\n * optional relative time, and a right-aligned monospace timestamp. Built on\n * DataTableRow for the shared hover/border plumbing. */\nexport function ActivityRow({\n tag,\n tagColor,\n msg,\n actor,\n timeAgo,\n timestamp,\n showBorder,\n}: ActivityRowProps) {\n return (\n <DataTableRow\n showBorder={showBorder}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n paddingBlock: \"var(--space-2)\",\n paddingInline: \"var(--space-4)\",\n }}\n >\n {/* Type tag — monospace, colored */}\n <Text\n as=\"span\"\n size=\"1\"\n weight=\"medium\"\n className=\"data-mono\"\n style={{\n color: tagColor,\n minWidth: \"var(--space-6)\",\n letterSpacing: \"0.06em\",\n flexShrink: 0,\n }}\n >\n {tag}\n </Text>\n\n {/* Message + actor */}\n <Text\n as=\"span\"\n size=\"2\"\n style={{\n flex: 1,\n color: \"var(--gray-11)\",\n lineHeight: 1.4,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {msg}\n {actor && (\n <Text as=\"span\" size=\"1\" style={{ color: \"var(--gray-11)\", marginLeft: \"var(--space-2)\" }}>\n by {actor}\n </Text>\n )}\n </Text>\n\n {/* Time-ago (human-readable) */}\n {timeAgo && (\n <Text as=\"span\" size=\"1\" color=\"gray\" style={{ whiteSpace: \"nowrap\", flexShrink: 0 }}>\n {timeAgo}\n </Text>\n )}\n\n {/* HH:MM:SS — monospace clock */}\n <Text\n as=\"span\"\n size=\"1\"\n className=\"data-mono\"\n style={{\n color: \"var(--gray-11)\",\n whiteSpace: \"nowrap\",\n flexShrink: 0,\n minWidth: \"var(--space-7)\",\n textAlign: \"right\",\n }}\n >\n {timestamp}\n </Text>\n </DataTableRow>\n );\n}\n","import { Button, Card, Flex, Text } from \"@radix-ui/themes\";\nimport { ExclamationTriangleIcon } from \"@radix-ui/react-icons\";\nimport { IconTile } from \"./IconTile\";\nimport { iconSize } from \"./icon-size\";\n\nexport interface DashboardErrorCardProps {\n onRetry: () => void;\n /** Defaults to \"Couldn't load your dashboard.\" */\n message?: string;\n}\n\n/** Generic \"failed to load\" state: warning icon, message, Retry CTA. */\nexport function DashboardErrorCard({ onRetry, message = \"Couldn't load your dashboard.\" }: DashboardErrorCardProps) {\n return (\n <Card>\n <Flex direction=\"column\" align=\"center\" justify=\"center\" py=\"9\" gap=\"3\">\n <IconTile>\n <ExclamationTriangleIcon style={{ ...iconSize(\"--space-5\"), color: \"var(--gray-7)\" }} />\n </IconTile>\n <Text size=\"2\" color=\"gray\">\n {message}\n </Text>\n <Button size=\"2\" color=\"amber\" variant=\"solid\" className=\"btn-amber-primary\" onClick={onRetry}>\n Retry\n </Button>\n </Flex>\n </Card>\n );\n}\n","import { useMemo } from \"react\";\nimport { Button, Flex, IconButton, Text } from \"@radix-ui/themes\";\nimport {\n ChevronLeftIcon,\n ChevronRightIcon,\n DoubleArrowLeftIcon,\n DoubleArrowRightIcon,\n} from \"@radix-ui/react-icons\";\n\n/**\n * Pagination — windowed page-number nav for paginated tables.\n *\n * Neither Radix Themes nor this package covered pagination, so every app with\n * a server-paginated table grew its own. Promoted here from arm-admin so they\n * stop diverging. Composed entirely from Radix controls plus the brand\n * `btn-amber-primary` class for the current page — no utility-class colours\n * and no inline var() fallbacks.\n */\n\nconst ELLIPSIS = \"…\" as const;\n\n/** Windowed page list: always the first and last page, `siblingCount` either\n * side of the current one, and an ellipsis wherever a run is skipped. */\nfunction buildPageRange(\n currentPage: number,\n totalPages: number,\n siblingCount: number,\n): (number | typeof ELLIPSIS)[] {\n const totalVisible = siblingCount * 2 + 5;\n if (totalPages <= totalVisible) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n\n const leftSibling = Math.max(currentPage - siblingCount, 1);\n const rightSibling = Math.min(currentPage + siblingCount, totalPages);\n const showLeftEllipsis = leftSibling > 2;\n const showRightEllipsis = rightSibling < totalPages - 1;\n\n if (!showLeftEllipsis && showRightEllipsis) {\n const leftRange = Array.from({ length: 3 + siblingCount * 2 }, (_, i) => i + 1);\n return [...leftRange, ELLIPSIS, totalPages];\n }\n if (showLeftEllipsis && !showRightEllipsis) {\n const span = 3 + siblingCount * 2;\n const rightRange = Array.from({ length: span }, (_, i) => totalPages - span + i + 1);\n return [1, ELLIPSIS, ...rightRange];\n }\n const middleRange = Array.from(\n { length: rightSibling - leftSibling + 1 },\n (_, i) => leftSibling + i,\n );\n return [1, ELLIPSIS, ...middleRange, ELLIPSIS, totalPages];\n}\n\nexport interface PaginationProps {\n /** 1-based. */\n currentPage: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n /** Pages shown either side of the current one. */\n siblingCount?: number;\n /** Adds jump-to-first / jump-to-last controls. */\n showFirstLast?: boolean;\n /** Radix control size. */\n size?: \"1\" | \"2\";\n}\n\nexport function Pagination({\n currentPage,\n totalPages,\n onPageChange,\n siblingCount = 1,\n showFirstLast = false,\n size = \"2\",\n}: PaginationProps) {\n const pages = useMemo(\n () => buildPageRange(currentPage, totalPages, siblingCount),\n [currentPage, totalPages, siblingCount],\n );\n\n const atFirst = currentPage <= 1;\n const atLast = currentPage >= totalPages;\n\n return (\n <Flex asChild align=\"center\" gap=\"1\">\n <nav aria-label=\"Pagination\">\n {showFirstLast && (\n <IconButton\n size={size}\n variant=\"soft\"\n color=\"gray\"\n aria-label=\"First page\"\n disabled={atFirst}\n onClick={() => onPageChange(1)}\n >\n <DoubleArrowLeftIcon />\n </IconButton>\n )}\n <IconButton\n size={size}\n variant=\"soft\"\n color=\"gray\"\n aria-label=\"Previous page\"\n disabled={atFirst}\n onClick={() => onPageChange(currentPage - 1)}\n >\n <ChevronLeftIcon />\n </IconButton>\n\n {pages.map((page, index) =>\n page === ELLIPSIS ? (\n <Text\n key={`ellipsis-${index}`}\n size={size}\n color=\"gray\"\n aria-hidden\n style={{ paddingInline: \"var(--space-1)\" }}\n >\n {ELLIPSIS}\n </Text>\n ) : (\n <Button\n key={page}\n size={size}\n aria-label={`Page ${page}`}\n aria-current={page === currentPage ? \"page\" : undefined}\n variant={page === currentPage ? \"solid\" : \"soft\"}\n color={page === currentPage ? undefined : \"gray\"}\n className={page === currentPage ? \"btn-amber-primary\" : undefined}\n onClick={() => page !== currentPage && onPageChange(page)}\n >\n {page}\n </Button>\n ),\n )}\n\n <IconButton\n size={size}\n variant=\"soft\"\n color=\"gray\"\n aria-label=\"Next page\"\n disabled={atLast}\n onClick={() => onPageChange(currentPage + 1)}\n >\n <ChevronRightIcon />\n </IconButton>\n {showFirstLast && (\n <IconButton\n size={size}\n variant=\"soft\"\n color=\"gray\"\n aria-label=\"Last page\"\n disabled={atLast}\n onClick={() => onPageChange(totalPages)}\n >\n <DoubleArrowRightIcon />\n </IconButton>\n )}\n </nav>\n </Flex>\n );\n}\n\nexport default Pagination;\n","import type { Role } from \"./Sidebar\";\n\n/**\n * Single source of truth for status / role / activity / audit colors.\n *\n * Every consumer that renders a user's role, account status or an audit row\n * previously defined its own map inline, and those copies had already started\n * to drift — the admin portal's audit action map went stale twice while its\n * action vocabulary grew, and only `tsc` caught it. Import from here instead.\n *\n * Two color conventions live side by side, matching how Radix is consumed:\n * - Radix accent names (\"amber\" | \"blue\" | ...) passed to <Badge color={...} />.\n * - Raw CSS-var tokens (e.g. \"var(--green-9)\") used for dots, tags and rails.\n */\n\n/* ── Role ──────────────────────────────────────────────────────────────── */\n\nexport const ROLE_META: Record<Role, { label: string; color: \"amber\" | \"blue\" | \"gray\" }> = {\n admin: { label: \"Admin\", color: \"amber\" },\n operator: { label: \"Operator\", color: \"blue\" },\n user: { label: \"Platform User\", color: \"gray\" },\n};\n\nexport const ROLE_LABELS: Record<Role, string> = {\n admin: ROLE_META.admin.label,\n operator: ROLE_META.operator.label,\n user: ROLE_META.user.label,\n};\n\n/* ── Account status ────────────────────────────────────────────────────── */\n\n/** Derived, not stored. `suspended` is an admin disabling the account;\n * `inactive` is an approved account nobody has signed into lately. Approval\n * state (pending / rejected) is a separate axis and gets its own badge —\n * an account can be approved and suspended at the same time. */\nexport type UserStatus = \"active\" | \"inactive\" | \"suspended\";\n\nexport const STATUS_META: Record<UserStatus, { label: string; color: string }> = {\n active: { label: \"Active\", color: \"var(--color-success)\" },\n inactive: { label: \"Inactive\", color: \"var(--gray-11)\" },\n suspended: { label: \"Suspended\", color: \"var(--color-danger)\" },\n};\n\n/* ── Metric health ─────────────────────────────────────────────────────── */\n\nexport type MetricStatus = \"ok\" | \"warn\" | \"error\";\n\n/* Step 9 here is correct and deliberately not moved to 11 with the tag colours\n * above. MetricCard renders this as a `background` on a status dot and as the\n * Sparkline stroke — graphical objects, judged against the 3:1 non-text bar,\n * which step 9 is designed for. Darkening it to a text step would mute the\n * indicator for no accessibility gain. */\nexport const METRIC_STATUS_COLOR: Record<MetricStatus, string> = {\n ok: \"var(--green-9)\",\n warn: \"var(--orange-9)\",\n error: \"var(--red-9)\",\n};\n\n/* ── Activity feed category ────────────────────────────────────────────── */\n\nexport type ActivityType = \"auth\" | \"sync\" | \"role\" | \"provision\" | \"health\" | \"error\";\n\nexport const ACTIVITY_META: Record<ActivityType, { tag: string; color: string }> = {\n auth: { tag: \"AUTH\", color: \"var(--gray-11)\" },\n sync: { tag: \"SYNC\", color: \"var(--blue-11)\" },\n role: { tag: \"ROLE\", color: \"var(--violet-11)\" },\n provision: { tag: \"PROV\", color: \"var(--green-11)\" },\n health: { tag: \"HLTH\", color: \"var(--teal-11)\" },\n error: { tag: \"ERR!\", color: \"var(--red-11)\" },\n};\n\n/* ── Audit log action ──────────────────────────────────────────────────── */\n\n/** The admin backend's own vocabulary — these strings are written by\n * `AuditService.log` and must match it exactly. `action` is a plain varchar\n * there, not a Postgres enum, so nothing but this map and a code review stops\n * the two drifting apart. Add here whenever a new action is logged. */\nexport type AuditAction =\n | \"USER_UPDATED\"\n | \"USER_DISABLED\"\n | \"USER_ENABLED\"\n | \"USER_APPROVED\"\n | \"USER_REJECTED\"\n | \"SIGNUP_NOTIFICATIONS_ON\"\n | \"SIGNUP_NOTIFICATIONS_OFF\"\n | \"APPROVAL_EMAIL_RESENT\"\n | \"USER_DELETED\"\n | \"ADMIN_GRANTED\"\n | \"ADMIN_REVOKED\"\n | \"ADMIN_ROLE_CHANGED\"\n | \"SESSION_REVOKED\"\n | \"APP_GRANTED\"\n | \"APP_REVOKED\"\n | \"BUNDLE_GRANTED\"\n | \"BUNDLE_REVOKED\"\n | \"APP_VALIDATED\"\n | \"APP_DEPLOY_REQUESTED\"\n | \"APP_DEPLOYED\"\n | \"APP_DEPLOY_FAILED\"\n | \"APP_REVERTED\"\n | \"APP_ROLLED_BACK\"\n | \"APP_REMOVED\";\n\n/** `badge` is for <Badge color={...} />, `tag`/`color` for the compact\n * monospace tag used in per-user activity lists.\n *\n * `color` is step **11**, not step 9. Step 9 is Radix's solid-background step\n * and was never a text colour: used as one it gave the amber UPD tag 1.58:1 on\n * white, teal 3.07:1 and orange 2.97:1 — the amber one close to invisible\n * rather than merely low-contrast, at 10.8px where the requirement is\n * strictest. Step 11 is the scale's low-contrast *text* step and clears 4.5:1\n * for every scale used here (4.51-6.17 on white).\n *\n * These tags render inside a Card, so white is the surface that matters. On a\n * #F6F6F6 surface amber, teal, green and orange land at 4.17-4.36 — under AA —\n * so do not move this tag onto the page background without re-measuring.\n *\n * `badge` is untouched: it feeds Radix's own <Badge>, which pairs its own text\n * and background steps. */\nexport const AUDIT_ACTION_META: Record<\n AuditAction,\n { label: string; tag: string; badge: \"amber\" | \"gray\" | \"yellow\" | \"red\" | \"green\"; color: string }\n> = {\n USER_UPDATED: { label: \"User updated\", tag: \"UPD\", badge: \"amber\", color: \"var(--amber-11)\" },\n USER_DISABLED: { label: \"User disabled\", tag: \"DIS\", badge: \"red\", color: \"var(--red-11)\" },\n USER_ENABLED: { label: \"User enabled\", tag: \"ENA\", badge: \"green\", color: \"var(--teal-11)\" },\n USER_APPROVED: { label: \"User approved\", tag: \"APPR\", badge: \"green\", color: \"var(--green-11)\" },\n USER_REJECTED: { label: \"User rejected\", tag: \"REJ\", badge: \"red\", color: \"var(--red-11)\" },\n SIGNUP_NOTIFICATIONS_ON: { label: \"Signup notifications on\", tag: \"NOTF\", badge: \"gray\", color: \"var(--gray-11)\" },\n SIGNUP_NOTIFICATIONS_OFF: { label: \"Signup notifications off\", tag: \"NOTF\", badge: \"gray\", color: \"var(--gray-11)\" },\n APPROVAL_EMAIL_RESENT: { label: \"Approval email resent\", tag: \"MAIL\", badge: \"amber\", color: \"var(--amber-11)\" },\n USER_DELETED: { label: \"User deleted\", tag: \"DEL\", badge: \"yellow\", color: \"var(--red-11)\" },\n ADMIN_GRANTED: { label: \"Admin granted\", tag: \"ADMN\", badge: \"gray\", color: \"var(--violet-11)\" },\n ADMIN_REVOKED: { label: \"Admin revoked\", tag: \"ADMN\", badge: \"gray\", color: \"var(--orange-11)\" },\n ADMIN_ROLE_CHANGED: { label: \"Role changed\", tag: \"ROLE\", badge: \"amber\", color: \"var(--violet-11)\" },\n SESSION_REVOKED: { label: \"Session revoked\", tag: \"SESS\", badge: \"gray\", color: \"var(--gray-11)\" },\n APP_GRANTED: { label: \"App access granted\", tag: \"APP\", badge: \"green\", color: \"var(--green-11)\" },\n APP_REVOKED: { label: \"App access revoked\", tag: \"APP\", badge: \"red\", color: \"var(--orange-11)\" },\n BUNDLE_GRANTED: { label: \"Bundle access granted\", tag: \"BNDL\", badge: \"green\", color: \"var(--green-11)\" },\n BUNDLE_REVOKED: { label: \"Bundle access revoked\", tag: \"BNDL\", badge: \"red\", color: \"var(--orange-11)\" },\n APP_VALIDATED: { label: \"App repo checked\", tag: \"CHK\", badge: \"gray\", color: \"var(--gray-11)\" },\n APP_DEPLOY_REQUESTED: { label: \"App deploy requested\", tag: \"DPLY\", badge: \"amber\", color: \"var(--amber-11)\" },\n APP_DEPLOYED: { label: \"App deployed\", tag: \"LIVE\", badge: \"green\", color: \"var(--green-11)\" },\n APP_DEPLOY_FAILED: { label: \"App deploy failed\", tag: \"FAIL\", badge: \"red\", color: \"var(--red-11)\" },\n APP_REVERTED: { label: \"App deploy reverted\", tag: \"RVRT\", badge: \"red\", color: \"var(--orange-11)\" },\n APP_ROLLED_BACK: { label: \"App rolled back\", tag: \"RBCK\", badge: \"amber\", color: \"var(--orange-11)\" },\n APP_REMOVED: { label: \"App undeployed\", tag: \"UNDP\", badge: \"red\", color: \"var(--red-11)\" },\n};\n\n/** Falls back rather than throwing: the backend can log an action this build\n * has never heard of, and an unknown row must still render. */\nexport function auditActionMeta(action: string) {\n return (\n AUDIT_ACTION_META[action as AuditAction] ?? {\n label: action,\n tag: action.slice(0, 4).toUpperCase(),\n badge: \"gray\" as const,\n color: \"var(--gray-11)\",\n }\n );\n}\n","import { layout } from \"./layout-tokens\";\n\nexport function BrandPanel() {\n return (\n <div className=\"auth-art-card\">\n <img\n src=\"/arm-logo-inverted.svg\"\n alt=\"araMetrics\"\n style={{\n width: \"56%\",\n maxWidth: layout.brandLogoMax,\n display: \"block\",\n userSelect: \"none\",\n }}\n draggable={false}\n />\n </div>\n );\n}\n","import { BrandPanel } from \"./BrandPanel\";\nimport { layout } from \"./layout-tokens\";\n\n/* ── Deviates from Figma signin-01 by design request (2026-07-08): the\n * full-amber page read as \"yellow everywhere\" once every auth screen was\n * built out. Amber is now reserved for primary CTAs only — page background\n * goes to the app's standard --surface-content gray, form content sits in a\n * white --color-panel-solid card with --shadow-card, matching the\n * authenticated shell's card language instead of sitting flat on amber.\n * Left art panel keeps its amber background as the one color anchor.\n */\nexport function AuthCard({ children }: { children: React.ReactNode }) {\n return (\n <div\n style={{\n minHeight: \"100vh\",\n display: \"flex\",\n background: \"var(--surface-content)\",\n padding: \"var(--space-5)\",\n gap: \"var(--space-5)\",\n }}\n >\n {/* Left art panel — sticky so it stays put while the form scrolls */}\n <div\n className=\"auth-card-left\"\n style={{\n width: \"47%\",\n flexShrink: 0,\n position: \"sticky\",\n top: \"var(--space-5)\",\n height: \"calc(100vh - var(--space-8))\",\n }}\n >\n <BrandPanel />\n </div>\n\n {/* Right form column — white card, centered in the right half */}\n <div\n className=\"auth-card-right\"\n style={{\n flex: 1,\n /* Without this the column keeps the default `min-width: auto` and can\n never go below its content's min-content width, so a wide row\n inside the card — the SSO buttons on the login screen — becomes a\n floor for the whole page. */\n minWidth: 0,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n minHeight: \"calc(100vh - var(--space-8))\",\n padding: \"var(--space-7) var(--space-5)\",\n }}\n >\n {/* `main`, not a div: every auth screen gets its shell from here and\n none of them exposed a landmark. This component never renders inside\n the authenticated shell, which has its own `main`, so there is no\n risk of two. */}\n <main\n style={{\n maxWidth: layout.authFormMax,\n width: \"100%\",\n marginLeft: \"auto\",\n marginRight: \"auto\",\n background: \"var(--color-panel-solid)\",\n borderRadius: \"var(--radius-5)\",\n boxShadow: \"var(--shadow-card)\",\n padding: \"var(--space-7) var(--space-5)\",\n }}\n >\n {children}\n </main>\n </div>\n </div>\n );\n}\n","export function GoogleIcon() {\n return (\n <svg\n width={18}\n height={18}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden\n >\n <path d=\"M15.68 8.18c0-.57-.05-1.11-.14-1.64H8v3.1h4.3a3.68 3.68 0 0 1-1.6 2.42v2h2.58c1.51-1.39 2.4-3.44 2.4-5.88Z\" fill=\"#4285F4\" />\n <path d=\"M8 16c2.16 0 3.97-.71 5.3-1.94l-2.59-2a4.88 4.88 0 0 1-7.27-2.56H0.9v2.07A8 8 0 0 0 8 16Z\" fill=\"#34A853\" />\n <path d=\"M3.44 9.5A4.8 4.8 0 0 1 3.19 8c0-.52.09-1.03.25-1.5V4.43H.9A8 8 0 0 0 0 8c0 1.29.31 2.51.9 3.57L3.44 9.5Z\" fill=\"#FBBC05\" />\n <path d=\"M8 3.18c1.22 0 2.31.42 3.17 1.24l2.37-2.37A7.94 7.94 0 0 0 8 0 8 8 0 0 0 .9 4.43L3.44 6.5A4.77 4.77 0 0 1 8 3.18Z\" fill=\"#EA4335\" />\n </svg>\n );\n}\n","export function MicrosoftIcon() {\n return (\n <svg\n width={18}\n height={18}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden\n >\n <rect x=\"0\" y=\"0\" width=\"7.6\" height=\"7.6\" fill=\"#F25022\" />\n <rect x=\"8.4\" y=\"0\" width=\"7.6\" height=\"7.6\" fill=\"#7FBA00\" />\n <rect x=\"0\" y=\"8.4\" width=\"7.6\" height=\"7.6\" fill=\"#00A4EF\" />\n <rect x=\"8.4\" y=\"8.4\" width=\"7.6\" height=\"7.6\" fill=\"#FFB900\" />\n </svg>\n );\n}\n","import { useRef } from \"react\";\nimport { TextField } from \"@radix-ui/themes\";\n\n/* 4-digit one-time-code input — shared by sign-in and sign-up (passwordless\n * auth, 2026-07-09). Auto-advances, backspace walks left, paste fills. */\nexport function OtpInput({ value, onChange, disabled }: { value: string; onChange: (v: string) => void; disabled?: boolean }) {\n const inputs = useRef<(HTMLInputElement | null)[]>([]);\n\n function handleChange(i: number, e: React.ChangeEvent<HTMLInputElement>) {\n const ch = e.target.value.replace(/\\D/g, \"\").slice(-1);\n const digits = Array.from({ length: 4 }, (_, k) => value[k] ?? \"\");\n digits[i] = ch;\n onChange(digits.join(\"\"));\n if (ch && i < 3) inputs.current[i + 1]?.focus();\n }\n\n function handleKeyDown(i: number, e: React.KeyboardEvent<HTMLInputElement>) {\n const digits = Array.from({ length: 4 }, (_, k) => value[k] ?? \"\");\n if (e.key === \"Backspace\") {\n if (!digits[i] && i > 0) {\n digits[i - 1] = \"\";\n onChange(digits.join(\"\"));\n inputs.current[i - 1]?.focus();\n }\n } else if (e.key === \"ArrowLeft\" && i > 0) {\n inputs.current[i - 1]?.focus();\n } else if (e.key === \"ArrowRight\" && i < 3) {\n inputs.current[i + 1]?.focus();\n }\n }\n\n function handlePaste(e: React.ClipboardEvent) {\n const pasted = e.clipboardData.getData(\"text\").replace(/\\D/g, \"\").slice(0, 4);\n if (pasted) {\n e.preventDefault();\n onChange(pasted);\n inputs.current[Math.min(pasted.length, 3)]?.focus();\n }\n }\n\n const digits = Array.from({ length: 4 }, (_, k) => value[k] ?? \"\");\n\n return (\n <div\n style={{\n display: \"flex\",\n gap: \"var(--space-3)\",\n justifyContent: \"center\",\n }}\n >\n {digits.map((d, i) => (\n <TextField.Root\n key={i}\n ref={(el) => { inputs.current[i] = el; }}\n type=\"text\"\n inputMode=\"numeric\"\n maxLength={1}\n value={d}\n onChange={(e) => handleChange(i, e)}\n onKeyDown={(e) => handleKeyDown(i, e)}\n onPaste={handlePaste}\n disabled={disabled}\n className=\"otp-box\"\n aria-label={`Digit ${i + 1}`}\n autoComplete={i === 0 ? \"one-time-code\" : \"off\"}\n />\n ))}\n </div>\n );\n}\n","import { OtpInput } from \"./OtpInput\";\nimport { Button, Callout, Heading, Text } from \"@radix-ui/themes\";\nimport { ExclamationTriangleIcon } from \"@radix-ui/react-icons\";\nimport { headingSize } from \"./heading-scale\";\n\nexport interface OtpVerifyStepProps {\n email: string;\n title: React.ReactNode;\n subtitle: React.ReactNode;\n code: string;\n onCodeChange: (value: string) => void;\n otpDevHint: string | null;\n error: string | null;\n /** Optional inline recovery action shown next to `error` — for errors\n * whose message describes a fix (\"Start the signup process again\") but\n * that otherwise have no button actually doing it. */\n errorAction?: { label: string; onClick: () => void };\n busy: boolean;\n otpExpiresAt: number | null;\n otpSecondsLeft: number;\n resendCooldown: number;\n onResend: () => void;\n onUseDifferentEmail: () => void;\n}\n\nexport function OtpVerifyStep({\n email,\n title,\n subtitle,\n code,\n onCodeChange,\n otpDevHint,\n error,\n errorAction,\n busy,\n otpExpiresAt,\n otpSecondsLeft,\n resendCooldown,\n onResend,\n onUseDifferentEmail,\n}: OtpVerifyStepProps) {\n return (\n <>\n <div style={{ marginBottom: \"var(--space-6)\", textAlign: \"center\" }}>\n <Heading as=\"h1\" size={headingSize.h1} style={{ color: \"var(--ink-strong)\", marginBottom: \"var(--space-3)\" }}>\n {title}\n </Heading>\n <Text as=\"p\" size=\"2\" style={{ color: \"var(--ink-mid)\", lineHeight: 1.55 }}>\n {subtitle}{\" \"}\n <span style={{ fontWeight: 600, color: \"var(--ink-strong)\" }}>{email}</span>.\n </Text>\n </div>\n\n {otpDevHint && (\n <Callout.Root color=\"gray\" variant=\"surface\" size=\"1\" style={{ marginBottom: \"var(--space-5)\" }}>\n <Callout.Text style={{ fontFamily: \"var(--font-poppins)\" }}>\n Dev hint — code is <strong>{otpDevHint}</strong>\n </Callout.Text>\n </Callout.Root>\n )}\n\n {error && (\n <Callout.Root color=\"red\" variant=\"surface\" size=\"2\" style={{ marginBottom: \"var(--space-5)\" }}>\n <Callout.Icon><ExclamationTriangleIcon /></Callout.Icon>\n <Callout.Text style={{ fontFamily: \"var(--font-poppins)\" }}>\n {error}\n {errorAction && (\n <>\n {\" \"}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"1\"\n onClick={errorAction.onClick}\n style={{ fontWeight: 600, textDecoration: \"underline\", height: \"auto\", padding: 0 }}\n >\n {errorAction.label}\n </Button>\n </>\n )}\n </Callout.Text>\n </Callout.Root>\n )}\n\n <div>\n <OtpInput value={code} onChange={onCodeChange} disabled={busy || otpSecondsLeft <= 0} />\n {busy ? (\n <Text as=\"p\" size=\"1\" style={{ color: \"var(--ink-mid)\", marginTop: \"var(--space-3)\", textAlign: \"center\" }}>\n Checking code…\n </Text>\n ) : otpExpiresAt && otpSecondsLeft <= 0 ? (\n <Text as=\"p\" size=\"1\" style={{ color: \"var(--red-11)\", marginTop: \"var(--space-3)\", textAlign: \"center\" }}>\n Code expired — resend to get a new one.\n </Text>\n ) : null}\n </div>\n\n <div style={{ marginTop: \"var(--space-5)\", display: \"flex\", flexDirection: \"column\", alignItems: \"center\", gap: \"var(--space-3)\" }}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"2\"\n disabled={resendCooldown > 0 || busy}\n onClick={onResend}\n style={{\n fontWeight: 500,\n color: resendCooldown > 0 ? \"rgba(85, 85, 85, 0.4)\" : \"var(--ink-strong)\",\n textDecoration: resendCooldown > 0 ? \"none\" : \"underline\",\n }}\n >\n {resendCooldown > 0 ? `Resend email (${resendCooldown}s)` : \"Resend email\"}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"2\"\n className=\"auth-underline-link\"\n disabled={busy}\n onClick={onUseDifferentEmail}\n style={{ fontWeight: 500, color: \"var(--ink-strong)\" }}\n >\n Use a Different Email\n </Button>\n </div>\n </>\n );\n}\n","import { GoogleIcon } from \"./GoogleIcon\";\nimport { MicrosoftIcon } from \"./MicrosoftIcon\";\n\n/** Duplicated from the app's src/lib/mock.ts (not imported) so this package\n * has no dependency back into the app. Keep in sync if the app's type changes. */\nexport type CalendarProvider = \"google\" | \"microsoft\";\n\n/** Renders the correct provider logo for a calendar account. Used in the\n * provider chooser, consent screen, and per-account badges so a Google account\n * and a Microsoft account are always distinguishable at a glance (color tells\n * you WHICH account; this icon tells you WHICH provider). */\nexport function ProviderIcon({ provider }: { provider: CalendarProvider }) {\n return provider === \"microsoft\" ? <MicrosoftIcon /> : <GoogleIcon />;\n}\n\n/** Human-readable provider names for consent copy and the chooser. */\nexport const PROVIDER_LABEL: Record<CalendarProvider, string> = {\n google: \"Google\",\n microsoft: \"Microsoft\",\n};\n","import { useEffect, useRef, useState } from \"react\";\nimport { Link, useLocation } from \"react-router-dom\";\nimport { Avatar, Badge, DropdownMenu, IconButton, Text, Tooltip } from \"@radix-ui/themes\";\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n Cross1Icon,\n DotFilledIcon,\n DotsVerticalIcon,\n ExitIcon,\n GearIcon,\n QuestionMarkCircledIcon,\n} from \"@radix-ui/react-icons\";\nimport { ConfirmDialog } from \"./ConfirmDialog\";\nimport { iconSize } from \"./icon-size\";\n\n/** Duplicated from the app's src/lib/mock.ts Role type (not imported) so\n * this package has no dependency back into the app. Keep in sync if the\n * app's role set changes. */\nexport type Role = \"admin\" | \"operator\" | \"user\";\n\n/* ── Shell sidebar layout (Radix token scale) ──────────────────────────────\n * Shared header height with Topbar via SHELL_HEADER_H.\n * Active nav: solid amber pill + left accent bar + bold ink label.\n */\n\n/* ── Shared height constant — Sidebar header and Topbar MUST use this value ── */\nexport const SHELL_HEADER_H = \"var(--space-9)\";\n\n/* ── Nav definition ──────────────────────────────────────────────────────── */\n\nexport interface NavItem {\n label: string;\n href: string;\n Icon: React.ComponentType<{ width?: number; height?: number; style?: React.CSSProperties }>;\n roles?: Role[];\n /* Drillable section — clicking swaps the whole sidebar to show these child\n * rows plus a Back row. Children inherit the parent's Icon in the sub-menu. */\n children?: NavItem[];\n /* Exact-match highlighting only (like NavLink `end`). Needed when a child's\n * href is a prefix of its siblings' — e.g. the calendar view child\n * `end: true` = NavLink exact match (sibling routes don't keep this active). */\n end?: boolean;\n /* Section path prefix for drill-in / active matching when `href` is a\n * landing route that isn't the root (Calendar lands on /calendar/syncs,\n * but every /calendar/* page belongs to the section). */\n root?: string;\n /* Short status shown as a pill after the label (\"Soon\"). It never shrinks,\n * so it stays readable while a long label truncates in front of it. */\n badge?: string;\n /* A bundle of apps rather than an app: `href` is its landing page and\n * `children` are apps, which may drill in again to their own pages. Its\n * apps read as app rows (capitals), it holds the current path whenever one\n * of its apps does, and a bundle left with no visible apps is dropped. */\n bundle?: boolean;\n}\n\n/* A bundle of top-level rows under a heading the user can fold away. Groups\n * don't nest, and their rows never pin into the utility nav. */\nexport interface NavGroup {\n id: string;\n label: string;\n items: NavItem[];\n /* Folded on first visit. A choice stored under `persistKey` wins. */\n defaultCollapsed?: boolean;\n}\n\nexport type NavEntry = NavItem | NavGroup;\n\nconst isNavGroup = (entry: NavEntry): entry is NavGroup => \"items\" in entry;\n\n/* Full row text for tooltips and the accessible name — the label alone would\n * drop the badge, which is the one thing that tells the rows apart. */\nconst fullLabel = (item: NavItem) => (item.badge ? `${item.label} · ${item.badge}` : item.label);\n\n/* Folded state per group id. Storage can be missing or throw (private mode,\n * blocked site data), and a bad value must not take the sidebar down, so\n * every access falls back to \"nothing stored\". */\nfunction readFoldState(key: string | undefined): Record<string, boolean> {\n if (!key) return {};\n try {\n const parsed: unknown = JSON.parse(localStorage.getItem(key) ?? \"{}\");\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) return {};\n return Object.fromEntries(\n Object.entries(parsed).filter((pair): pair is [string, boolean] => typeof pair[1] === \"boolean\")\n );\n } catch {\n return {};\n }\n}\n\nfunction writeFoldState(key: string | undefined, state: Record<string, boolean>) {\n if (!key) return;\n try {\n localStorage.setItem(key, JSON.stringify(state));\n } catch {\n /* Unsaved is fine — the toggle still works for this page view. */\n }\n}\n\n/* ── Layout tokens (Radix space scale) ───────────────────────────────────── */\n\nconst WIDTH_EXPANDED = \"calc(4 * var(--space-9))\";\nconst WIDTH_COLLAPSED = \"calc(var(--space-9) + var(--space-6))\";\nconst WIDTH_DRAWER = \"calc(4 * var(--space-9) + var(--space-5))\";\n\nconst ROW_H = \"var(--space-8)\";\nconst PILL_L = \"var(--space-5)\";\nconst PILL_R = \"var(--space-5)\";\nconst ICON_X = \"calc(var(--space-5) + var(--space-3))\";\n/* space-3, not space-5: the widest row, \"Requirements\" plus its \"Soon\" badge\n * at the active weight, needs 147 px after the icon, and space-5 left 130. */\nconst LABEL_GAP = \"var(--space-3)\";\n\n/* ── Transition helpers ──────────────────────────────────────────────────── */\n/*\n * Choreography:\n * Collapse: labels/text fade OUT immediately (90ms), width then finishes (200ms).\n * Expand: width starts, labels/text fade IN with 80ms delay so they appear\n * as the sidebar opens rather than before there's room for them.\n */\nconst labelTransition = (expanded: boolean) =>\n expanded ? \"opacity 130ms ease 80ms\" : \"opacity 90ms ease\";\n\n/* Logo crossfade: symmetric, no delay offset — both marks fade in lockstep\n * so neither dips to near-zero opacity while the other hasn't started\n * (that stagger is what reads as a flicker). Slower than the label fade\n * since the logo has more visual weight and a bigger geometry swap. */\nconst LOGO_TRANSITION = \"opacity 200ms ease\";\n\n/* ── Props ───────────────────────────────────────────────────────────────── */\n\nexport interface SidebarUser {\n name: string;\n role: Role;\n /** Profile photo URL. Omitted or unloadable falls back to the derived\n * initials, so a consumer with no photo on the profile payload passes\n * nothing and keeps the previous appearance. */\n avatarSrc?: string;\n}\n\nexport interface SidebarDevRole {\n role: Role;\n email: string;\n label: string;\n}\n\nexport interface SidebarProps {\n collapsed: boolean;\n onToggle?: () => void;\n onClose?: () => void;\n /** Nav items to render — the app owns its own route table (NAV_ITEMS).\n * A `NavGroup` renders its rows under a heading that folds them away. */\n items: NavEntry[];\n /** localStorage key that remembers which groups are folded, per browser.\n * Omit it and the folded state lasts only for the page view. */\n persistKey?: string;\n /** Utility/meta hrefs (Settings, Admin Portal) that pin above the identity\n * block instead of the main scrollable list. */\n utilityHrefs: string[];\n /** Currently signed-in user, or null/undefined if not authenticated. */\n user?: SidebarUser | null;\n onSignOut: () => void;\n /** Calendar section only drills in once the app has at least one connected\n * account — pass false to keep the global menu (e.g. no accounts yet). */\n hasCalendarAccounts?: boolean;\n brandLogoExpandedSrc?: string;\n brandLogoCollapsedSrc?: string;\n /** Where the account menu's Help entry opens, in a new tab. Omit to leave\n * the entry out — there is no default, because a baked-in URL ships to every\n * consumer whether or not that address is real. */\n helpHref?: string;\n /** Dev-only role switcher shown in the account menu — omit to hide it\n * entirely (e.g. in a production build or a context with no such concept). */\n devRoles?: SidebarDevRole[];\n onDevRoleSelect?: (email: string) => void;\n showDevRoles?: boolean;\n}\n\n/* ── Sidebar ─────────────────────────────────────────────────────────────── */\n\nexport function Sidebar({\n collapsed,\n onToggle,\n onClose,\n items,\n persistKey,\n utilityHrefs: utilityHrefsProp,\n user,\n onSignOut,\n hasCalendarAccounts = false,\n brandLogoExpandedSrc = \"/expand.svg\",\n brandLogoCollapsedSrc = \"/shrink.svg\",\n helpHref,\n devRoles,\n onDevRoleSelect,\n showDevRoles = false,\n}: SidebarProps) {\n const pathname = useLocation().pathname;\n const [confirmLogoutOpen, setConfirmLogoutOpen] = useState(false);\n\n /* Drill-in Back is a sidebar-level step, not a route jump: pressing Back\n * shows the level above while you stay on the current page. The override is\n * pinned to the pathname it was set on (stored alongside it), so any\n * navigation makes it stale and the URL again drives the level on reload /\n * deep-link — no reset effect needed. Clicking a drillable row clears it to\n * drill straight back in. */\n const [backTo, setBackTo] = useState<{ path: string; depth: number } | null>(null);\n const clearBack = () => setBackTo(null);\n\n /* Drilling in or out swaps the rows, which unmounts the one that had focus\n * and drops a keyboard user on <body>. Each step records where focus should\n * land once the new level renders: Back after drilling in, the row that was\n * drilled into after Back. Only these clicks set it, so navigation from\n * elsewhere never moves focus. */\n const rootRef = useRef<HTMLElement>(null);\n const focusAfterStep = useRef<{ back: true } | { row: string } | null>(null);\n const drillIn = () => {\n focusAfterStep.current = { back: true };\n clearBack();\n };\n\n const isDrawer = !!onClose;\n const expanded = !collapsed || isDrawer;\n const width = isDrawer ? WIDTH_DRAWER : collapsed ? WIDTH_COLLAPSED : WIDTH_EXPANDED;\n\n /* Permission fence: filter by role; Admin Portal absent from DOM for Platform User.\n * Applies inside groups and bundles too, and one left with no rows is dropped. */\n const allowed = (item: NavItem) => !item.roles || (!!user && item.roles.includes(user.role));\n const prune = (item: NavItem): NavItem[] => {\n if (!allowed(item)) return [];\n if (!item.bundle || !item.children) return [item];\n const children = item.children.flatMap(prune);\n return children.length > 0 ? [{ ...item, children }] : [];\n };\n const visibleEntries = items.flatMap<NavEntry>((entry) => {\n if (!isNavGroup(entry)) return prune(entry);\n const groupItems = entry.items.flatMap(prune);\n return groupItems.length > 0 ? [{ ...entry, items: groupItems }] : [];\n });\n const topLevelItems = visibleEntries.filter((entry): entry is NavItem => !isNavGroup(entry));\n /* Every row, grouped or not — drill-in sections can live inside a group. */\n const visibleItems = visibleEntries.flatMap((entry) => (isNavGroup(entry) ? entry.items : [entry]));\n\n const [foldState, setFoldState] = useState(() => readFoldState(persistKey));\n const isFolded = (group: NavGroup) => foldState[group.id] ?? !!group.defaultCollapsed;\n function toggleGroup(group: NavGroup) {\n const next = { ...foldState, [group.id]: !isFolded(group) };\n setFoldState(next);\n writeFoldState(persistKey, next);\n }\n\n /* Utility/meta rows (Settings, Admin Portal) render pinned above the\n * identity block instead of the main scrollable list — matches Vercel's\n * Usage/Support/Settings placement. Membership is by href, not by which\n * `items` array a caller passes in, so Storybook overrides still split\n * correctly as long as they reuse these hrefs. Settings collapses further,\n * to a small icon beside the account menu (it's a single link, no\n * sub-pages to browse); Admin Portal keeps a full row since it drills\n * into real sub-pages. */\n const utilityHrefs = new Set(utilityHrefsProp);\n const primaryEntries = visibleEntries.filter((entry) => isNavGroup(entry) || !utilityHrefs.has(entry.href));\n const settingsItem = topLevelItems.find((item) => item.href === \"/settings\");\n const utilityItems = topLevelItems.filter((item) => utilityHrefs.has(item.href) && item.href !== \"/settings\");\n\n /* Drill-in: if the current path is inside a drillable section, the sidebar\n * swaps entirely to that section's sub-menu (Back row + children) instead of\n * the global app rows. Sections nest — a bundle holds apps, an app holds\n * pages — and the URL picks the deepest one, so reload / deep-link lands\n * drilled all the way in. Back (`backTo`) shows a shallower level while\n * keeping you on the page. */\n function sectionRoot(item: NavItem) {\n return item.root ?? item.href;\n }\n\n function drillable(item: NavItem) {\n return !!item.children?.length && (sectionRoot(item) !== \"/calendar\" || hasCalendarAccounts);\n }\n\n /* A bundle has no pages of its own below its landing page, so it holds the\n * current path when any of its apps does. */\n function inSection(item: NavItem): boolean {\n const root = sectionRoot(item);\n if (pathname === root || pathname === item.href || pathname.startsWith(root + \"/\")) return true;\n return !!item.bundle && !!item.children?.some(inSection);\n }\n\n const urlPath: NavItem[] = [];\n for (let level = visibleItems; ; ) {\n const section = level.find((item) => drillable(item) && inSection(item));\n if (!section) break;\n urlPath.push(section);\n level = section.children!;\n }\n const depth = backTo?.path === pathname ? Math.min(backTo.depth, urlPath.length) : urlPath.length;\n const activeSection = depth > 0 ? urlPath[depth - 1] : undefined;\n const stepBack = () => {\n if (activeSection) focusAfterStep.current = { row: activeSection.href };\n setBackTo({ path: pathname, depth: depth - 1 });\n };\n\n useEffect(() => {\n const target = focusAfterStep.current;\n const root = rootRef.current;\n if (!target || !root) return;\n focusAfterStep.current = null;\n const el = \"back\" in target\n ? root.querySelector<HTMLElement>(\"[data-nav-back]\")\n : Array.from(root.querySelectorAll<HTMLElement>(\"[data-nav-href]\"))\n .find((node) => node.dataset.navHref === target.row);\n el?.focus();\n }, [activeSection?.href]);\n\n function isActive(href: string, end?: boolean) {\n return href === \"/home\" || end\n ? pathname === href\n : pathname === href || pathname.startsWith(href + \"/\");\n }\n\n function renderTopRow(item: NavItem) {\n return renderRow(item, true);\n }\n\n /* One row at any level. `uppercase` is for app-level rows: the global menu,\n * and a bundle's apps — not an app's pages. */\n function renderRow(item: NavItem, uppercase: boolean) {\n const active = item.bundle ? inSection(item) : isActive(sectionRoot(item), item.end);\n const drills = drillable(item);\n const row = (\n <NavRow\n key={item.href}\n item={item}\n active={active}\n expanded={expanded}\n uppercase={uppercase}\n showChevron={drills}\n onClick={drills ? drillIn : undefined}\n />\n );\n /* Wrap with tooltip only in icon-only rail */\n return expanded ? row : (\n <Tooltip key={item.href} content={fullLabel(item)} side=\"right\" delayDuration={300}>\n {row}\n </Tooltip>\n );\n }\n\n /* Expanded: a heading that folds its rows away. The icon rail has no room\n * for a heading, so there it is a divider and every icon stays reachable\n * whatever the folded state. */\n function renderGroup(group: NavGroup) {\n const listId = `nav-group-${group.id}`;\n if (!expanded) {\n return (\n <div key={listId} role=\"group\" aria-label={group.label}>\n <div aria-hidden=\"true\" style={{ height: 1, background: \"var(--gray-4)\", margin: `var(--space-2) ${PILL_L}` }} />\n {group.items.map(renderTopRow)}\n </div>\n );\n }\n const folded = isFolded(group);\n return (\n <div key={listId} style={{ display: \"flex\", flexDirection: \"column\", marginTop: \"var(--space-3)\" }}>\n <GroupHeading\n label={group.label}\n folded={folded}\n holdsActive={folded && group.items.some((item) => isActive(sectionRoot(item)))}\n controls={listId}\n onToggle={() => toggleGroup(group)}\n />\n <div id={listId} role=\"group\" aria-label={group.label} hidden={folded}>\n {group.items.map(renderTopRow)}\n </div>\n </div>\n );\n }\n\n const isAdminContext =\n pathname.startsWith(\"/admin\") &&\n (user?.role === \"admin\" || user?.role === \"operator\");\n\n /* `?.` guards a null user but not a user whose `name` is empty or missing —\n * consumers build SidebarUser from API payloads where the name fields are\n * optional, and `undefined.split` here took down the whole app shell. Fall\n * back to \"?\" for any name that yields no initials. */\n const initials =\n user?.name\n ?.split(\" \")\n .map((n) => n[0])\n .join(\"\")\n .slice(0, 2) || \"?\";\n\n return (\n /* <aside>, not <div>. The two <nav> elements inside are landmarks, but the\n account chip below them was not inside either — so axe `region` flagged\n it on every page. A complementary landmark on the root covers everything\n the sidebar holds, navigation and chip alike, and is the right semantic\n for a sidebar regardless. Block-level either way, so nothing moves. */\n <aside\n ref={rootRef}\n style={{\n position: \"relative\", /* anchors the edge-straddling toggle */\n width,\n height: \"100%\",\n minHeight: \"100vh\",\n background: \"var(--shell-surface)\",\n borderRight: \"1px solid var(--gray-6)\",\n flexShrink: 0,\n transition: isDrawer ? \"none\" : \"width 200ms ease\",\n zIndex: 2, /* toggle button overhangs the content column */\n }}\n >\n {/* Inner wrapper owns the clipping so the toggle can overhang the edge */}\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n minHeight: \"100vh\", /* pins Settings/Logout to the bottom even when\n the parent's height comes from min-height */\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n }}\n >\n {/* ── Brand header ─────────────────────────────────────────────────\n Height locked to SHELL_HEADER_H — same value used in Topbar.\n Bottom border uses the same --border-hairline token as the Topbar\n so the two hairlines form one straight line across the shell.\n Full wordmark and collapsed icon crossfade in place, both fixed\n at the same 40px glyph height, so the collapse feels seamless\n instead of visibly shrinking.\n ──────────────────────────────────────────────────────────────────── */}\n <div\n style={{\n height: SHELL_HEADER_H,\n flexShrink: 0,\n position: \"relative\", /* anchors absolutely-positioned children */\n overflow: \"hidden\",\n borderBottom: \"1px solid var(--border-hairline)\",\n }}\n >\n <img\n src={brandLogoExpandedSrc}\n alt=\"\"\n height={40}\n style={{\n display: \"block\",\n position: \"absolute\",\n left: \"50%\",\n top: \"50%\",\n transform: \"translate(-50%, -50%)\",\n transition: LOGO_TRANSITION,\n opacity: expanded ? 1 : 0,\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n />\n <img\n src={brandLogoCollapsedSrc}\n alt=\"\"\n height={40}\n style={{\n display: \"block\",\n position: \"absolute\",\n left: \"50%\",\n top: \"50%\",\n transform: \"translate(-50%, -50%)\",\n transition: LOGO_TRANSITION,\n opacity: expanded ? 0 : 1,\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n />\n\n {/* Drawer close — inside the header (the floating toggle is desktop-only) */}\n {isDrawer && (\n <IconButton\n variant=\"ghost\"\n color=\"gray\"\n size=\"1\"\n onClick={onClose}\n aria-label=\"Close menu\"\n style={{ position: \"absolute\", right: \"var(--space-2)\", top: \"50%\", transform: \"translateY(-50%)\" }}\n >\n <Cross1Icon style={iconSize(\"--space-3\")} />\n </IconButton>\n )}\n </div>\n\n {/* ── Navigation — scrollable, flex:1 ──────────────────────────── */}\n <nav\n aria-label=\"Main navigation\"\n style={{\n flex: 1,\n overflowY: \"auto\",\n overflowX: \"hidden\",\n paddingTop: \"var(--space-5)\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {activeSection ? (\n /* ── Section sub-menu: Back row (shows the section title, not the\n literal word \"Back\" — matches Vercel's `< Observability`\n drill-in header) + this section's children ────────────────── */\n <>\n {(() => {\n const backRow = (\n <NavRow\n item={{ label: activeSection.label, href: \"#\", Icon: ChevronLeftIcon }}\n active={false}\n expanded={expanded}\n uppercase\n asButton\n onClick={stepBack}\n />\n );\n return expanded ? backRow : (\n <Tooltip content={activeSection.label} side=\"right\" delayDuration={300}>\n {backRow}\n </Tooltip>\n );\n })()}\n\n {activeSection.children!.map((child) => renderRow(child, !!activeSection.bundle))}\n </>\n ) : (\n /* ── Global menu: primary work-area rows only ─────────────────── */\n primaryEntries.map((entry) => (isNavGroup(entry) ? renderGroup(entry) : renderTopRow(entry)))\n )}\n </nav>\n\n {/* ── Utility rows (Settings, Admin Portal) — pinned above the\n identity block, not mixed into the main scrollable list. Hidden\n while drilled into a section so the drill-in view (which reuses\n the nav area above) isn't duplicated below it. ────────────────── */}\n {!activeSection && utilityItems.length > 0 && (\n <nav\n aria-label=\"Utility navigation\"\n style={{\n flexShrink: 0,\n borderTop: \"1px solid var(--gray-4)\",\n paddingTop: \"var(--space-2)\",\n paddingBottom: \"var(--space-2)\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {utilityItems.map((item) => {\n const active = isActive(item.href);\n const row = (\n <NavRow\n key={item.href}\n item={item}\n active={active}\n expanded={expanded}\n uppercase\n showChevron={!!item.children}\n onClick={item.children ? drillIn : undefined}\n />\n );\n return expanded ? row : (\n <Tooltip key={item.href} content={fullLabel(item)} side=\"right\" delayDuration={300}>\n {row}\n </Tooltip>\n );\n })}\n </nav>\n )}\n\n {/* ── Identity block — admin badge, compact avatar/name row, and a\n single menu (Settings, Theme, Help, Log Out). Moved here from the\n Topbar so the Topbar only carries the page title, search, and\n notifications. One line (name only, no email); a divider always\n separates it from the nav above (utility rows already have their\n own borderTop, but Settings/Admin absence — e.g. non-admin users\n with no Admin Portal row — must not leave the split missing). ── */}\n <div\n style={{\n borderTop: utilityItems.length > 0 ? \"none\" : \"1px solid var(--gray-4)\",\n padding: expanded ? \"var(--space-2) var(--space-4)\" : \"var(--space-2) 0\",\n flexShrink: 0,\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"var(--space-2)\",\n }}\n >\n {expanded && isAdminContext && (\n <Badge color=\"gray\" variant=\"soft\" highContrast size=\"1\" radius=\"full\" style={{ alignSelf: \"flex-start\" }}>\n <DotFilledIcon style={iconSize(\"--space-2\")} />\n Administering platform\n </Badge>\n )}\n\n <div\n style={{\n display: \"flex\",\n flexDirection: expanded ? \"row\" : \"column\",\n alignItems: \"center\",\n justifyContent: expanded ? \"space-between\" : \"center\",\n gap: \"var(--space-2)\",\n }}\n >\n {/* Profile row — avatar + name (expanded), avatar only (collapsed) */}\n {expanded ? (\n <div\n className=\"shell-profile-chip\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-2)\",\n minWidth: 0,\n flex: 1,\n padding: \"var(--space-1)\",\n borderRadius: \"var(--radius-3)\",\n }}\n >\n <Avatar size=\"2\" radius=\"full\" src={user?.avatarSrc} fallback={initials} color=\"gray\" variant=\"soft\" style={{ flexShrink: 0 }} />\n {/* Fixed chrome ink, not --gray-12: the rail's surface is\n pinned to --shell-surface independently of the page's gray\n scale, so chrome text has to come from the matching\n --shell-ink-* token or the pair can drift out of contrast. */}\n <Text as=\"p\" size=\"2\" weight=\"medium\" truncate style={{ color: \"var(--shell-ink-strong)\" }}>\n {user?.name}\n </Text>\n </div>\n ) : (\n <Tooltip content={user?.name ?? \"Account\"} side=\"right\" delayDuration={300}>\n <Avatar size=\"3\" radius=\"full\" src={user?.avatarSrc} fallback={initials} color=\"gray\" variant=\"soft\" />\n </Tooltip>\n )}\n\n {/* Single account menu — previously Settings had its own icon\n sitting right next to a separate three-dot menu (Theme/Help/\n Log Out), two triggers for what's conceptually one \"account\"\n area. Now everything account-related lives behind one\n trigger, Settings included as the first item. */}\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconButton\n variant=\"ghost\"\n color=\"gray\"\n aria-label=\"Account menu\"\n className=\"sidebar-icon-btn\"\n style={{ flexShrink: 0 }}\n >\n <DotsVerticalIcon style={iconSize(\"--space-4\")} />\n </IconButton>\n </DropdownMenu.Trigger>\n\n <DropdownMenu.Content align={expanded ? \"end\" : \"start\"} side={expanded ? \"top\" : \"right\"} style={{ minWidth: 200 }}>\n {settingsItem && (\n <DropdownMenu.Item asChild>\n <Link to={settingsItem.href} onClick={clearBack}>\n <GearIcon />\n Settings\n </Link>\n </DropdownMenu.Item>\n )}\n {helpHref && (\n <DropdownMenu.Item onClick={() => window.open(helpHref, \"_blank\", \"noopener,noreferrer\")}>\n <QuestionMarkCircledIcon />\n Help\n </DropdownMenu.Item>\n )}\n\n <DropdownMenu.Separator />\n\n <DropdownMenu.Item color=\"red\" onClick={() => setConfirmLogoutOpen(true)}>\n <ExitIcon />\n Log Out\n </DropdownMenu.Item>\n\n {/* Dev role switcher — app decides whether to pass devRoles/\n showDevRoles at all (e.g. gated on import.meta.env.DEV in\n the app's own build). */}\n {showDevRoles && devRoles && devRoles.length > 0 && (\n <>\n <DropdownMenu.Separator />\n <div style={{ padding: \"var(--space-1) var(--space-3)\" }}>\n <Text\n size=\"1\"\n style={{\n fontFamily: \"monospace\",\n color: \"var(--gray-11)\",\n letterSpacing: \"0.04em\",\n textTransform: \"uppercase\",\n }}\n >\n Dev · switch role\n </Text>\n </div>\n\n {devRoles.map((r) => (\n <DropdownMenu.Item\n key={r.role}\n onClick={() => onDevRoleSelect?.(r.email)}\n disabled={user?.role === r.role}\n >\n <GearIcon />\n {r.label}\n <Text size=\"1\" color=\"gray\" style={{ marginLeft: \"auto\" }}>\n {r.role}@\n </Text>\n </DropdownMenu.Item>\n ))}\n </>\n )}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </div>\n </div>\n </div>\n\n {/* ── Collapse toggle — white square straddling the right edge at the\n header line, exactly as in the Figma demo. Desktop only. ────────── */}\n {!isDrawer && (\n <button\n onClick={onToggle}\n aria-label={collapsed ? \"Expand sidebar\" : \"Collapse sidebar\"}\n className=\"sidebar-collapse-btn\"\n style={{ top: \"calc(var(--space-9) / 2)\", transform: \"translateY(-50%)\", right: \"calc(-1 * var(--space-3))\" }}\n >\n <PanelToggleIcon flipped={collapsed} />\n </button>\n )}\n\n {/* Confirm Logout — controlled so it can be triggered from the account menu. */}\n <ConfirmDialog\n open={confirmLogoutOpen}\n onOpenChange={setConfirmLogoutOpen}\n title=\"Confirm Logout\"\n description=\"Are you sure you want to log out?\"\n onConfirm={onSignOut}\n />\n </aside>\n );\n}\n\n/* ── Nav row ─────────────────────────────────────────────────────────────── */\n/*\n * Full-bleed nav row. Active: solid amber pill + left accent bar + bold label.\n * Inactive: transparent pill (hover = gray wash via .nav-pill in globals.css).\n * Labels always rendered; opacity drives show/hide during width transition.\n */\nfunction NavRow({\n item,\n active,\n expanded,\n onClick,\n asButton,\n showChevron,\n uppercase,\n}: {\n item: NavItem;\n active: boolean;\n expanded: boolean;\n /** App-level rows read in capitals; pages inside a drill-in keep their case.\n * Display-only — the accessible name and tooltip keep the label as given. */\n uppercase?: boolean;\n /** Click handler. Runs on select; combined with `asButton` for Back (no nav). */\n onClick?: () => void;\n /** Render as a <button> (no href/navigation) — used by the Back row. */\n asButton?: boolean;\n /** Trailing right-chevron marking a drillable section (global menu only). */\n showChevron?: boolean;\n}) {\n /* Shared row styling — a Link normally, a button when onClick is provided so\n * Back can flip the sidebar without changing the URL. */\n const rowStyle: React.CSSProperties = {\n position: \"relative\",\n textDecoration: \"none\",\n display: \"flex\",\n alignItems: \"center\",\n height: ROW_H,\n flexShrink: 0,\n paddingLeft: ICON_X,\n /* Ends the content inside the pill, so a label that runs long truncates\n at the pill's edge instead of past it. */\n paddingRight: expanded ? `calc(${PILL_R} + var(--space-1))` : 0,\n gap: expanded ? LABEL_GAP : 0,\n /* The active row's pill darkens to --accent-10 on hover, where mid ink\n reads 4.10:1; strong ink holds 6.96:1 on it. */\n color: active ? \"var(--shell-ink-strong)\" : \"var(--shell-ink-mid)\",\n cursor: \"pointer\",\n };\n\n const body = (\n <>\n {/* Left-edge accent bar — active only */}\n {active && (\n <span\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n width: \"var(--space-1)\",\n height: \"100%\",\n background: \"var(--accent-9)\",\n borderRadius: \"0 var(--radius-1) var(--radius-1) 0\",\n }}\n />\n )}\n\n {/* Pill surface — amber when active, hover wash target when not */}\n <span\n aria-hidden=\"true\"\n className=\"nav-pill\"\n style={{\n position: \"absolute\",\n top: 0,\n bottom: 0,\n left: PILL_L,\n right: expanded ? PILL_R : PILL_L,\n borderRadius: \"var(--radius-3)\",\n background: active ? \"var(--accent-9)\" : \"transparent\",\n transition: \"background 80ms ease\",\n }}\n />\n\n <item.Icon\n width={20}\n height={20}\n style={{ position: \"relative\", flexShrink: 0 }}\n />\n\n {/* Label + badge — always in DOM; opacity drives visibility during width\n transition. The label shrinks with an ellipsis; the badge does not. */}\n <span\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-1)\",\n minWidth: 0,\n overflow: \"hidden\",\n maxWidth: expanded ? undefined : 0,\n opacity: expanded ? 1 : 0,\n transition: labelTransition(expanded),\n }}\n >\n <Text\n as=\"span\"\n size=\"3\"\n weight={active ? \"medium\" : \"regular\"}\n style={{\n lineHeight: 1.3,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n minWidth: 0,\n textTransform: uppercase ? \"uppercase\" : undefined,\n }}\n >\n {item.label}\n </Text>\n {item.badge && (\n <Badge\n color=\"gray\"\n variant={active ? \"solid\" : \"soft\"}\n highContrast={active}\n size=\"1\"\n radius=\"full\"\n /* Radix's size-1 inline padding is 1.5 × space-1; one step is\n enough for a one-word badge and gives the label the difference. */\n style={{\n flexShrink: 0,\n paddingInline: \"var(--space-1)\",\n textTransform: uppercase ? \"uppercase\" : undefined,\n }}\n >\n {item.badge}\n </Badge>\n )}\n </span>\n\n {/* Drill-in affordance — trailing chevron on drillable rows (expanded).\n On the active (amber) row it sits in a small white box so it reads\n against the yellow pill; inactive rows show a plain chevron. */}\n {showChevron && expanded && (\n active ? (\n <span\n style={{\n position: \"relative\",\n marginLeft: \"auto\",\n /* keep the box inside the amber pill — the row's right padding\n already covers PILL_R + space-1 */\n marginRight: \"var(--space-1)\",\n flexShrink: 0,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"var(--space-5)\",\n height: \"var(--space-5)\",\n background: \"var(--color-panel-solid)\",\n borderRadius: \"var(--radius-2)\",\n boxShadow: \"0 1px 2px rgba(0,0,0,0.12)\",\n }}\n >\n <ChevronRightIcon style={{ ...iconSize(\"--space-4\"), color: \"var(--gray-11)\" }} />\n </span>\n ) : (\n <ChevronRightIcon\n style={{\n ...iconSize(\"--space-4\"),\n position: \"relative\",\n marginLeft: \"auto\",\n color: \"var(--shell-ink-mid)\",\n flexShrink: 0,\n }}\n />\n )\n )}\n </>\n );\n\n /* Back renders as a button (no href/navigation); everything else is a Link\n * that still fires onClick (used by drillable rows to clear the Back override\n * even when the target URL is unchanged). */\n if (asButton) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n data-nav-back=\"\"\n className=\"shell-nav-item\"\n style={{ ...rowStyle, background: \"none\", border: \"none\", width: \"100%\", textAlign: \"left\", font: \"inherit\" }}\n >\n {body}\n </button>\n );\n }\n\n return (\n <Link\n to={item.href}\n onClick={onClick}\n className=\"shell-nav-item\"\n data-nav-href={item.href}\n data-active={active ? \"true\" : undefined}\n aria-current={active ? \"page\" : undefined}\n /* The collapsed rail has a Radix tooltip; expanded, this is what shows\n a label the ellipsis cut short. */\n title={expanded ? fullLabel(item) : undefined}\n style={rowStyle}\n >\n {body}\n </Link>\n );\n}\n\n\n/* ── Group heading ───────────────────────────────────────────────────────── */\n/*\n * Folds a group's rows away. Folded over the current page, the heading takes\n * the strong ink and an accent dot, so the open page is never untraceable.\n */\nfunction GroupHeading({\n label,\n folded,\n holdsActive,\n controls,\n onToggle,\n}: {\n label: string;\n folded: boolean;\n holdsActive: boolean;\n controls: string;\n onToggle: () => void;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n aria-expanded={!folded}\n aria-controls={controls}\n className=\"shell-nav-group\"\n data-holds-active={holdsActive ? \"true\" : undefined}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-1)\",\n height: \"var(--space-6)\",\n flexShrink: 0,\n width: \"100%\",\n paddingLeft: ICON_X,\n paddingRight: `calc(${PILL_R} + var(--space-1))`,\n background: \"none\",\n border: \"none\",\n font: \"inherit\",\n textAlign: \"left\",\n cursor: \"pointer\",\n color: holdsActive ? \"var(--shell-ink-strong)\" : \"var(--shell-ink-mid)\",\n }}\n >\n <Text\n as=\"span\"\n size=\"1\"\n weight=\"medium\"\n style={{\n textTransform: \"uppercase\",\n letterSpacing: \"0.04em\",\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n minWidth: 0,\n }}\n >\n {label}\n </Text>\n {holdsActive && <DotFilledIcon aria-hidden=\"true\" style={{ ...iconSize(\"--space-3\"), color: \"var(--accent-9)\", flexShrink: 0 }} />}\n <ChevronDownIcon\n aria-hidden=\"true\"\n style={{\n ...iconSize(\"--space-4\"),\n marginLeft: \"auto\",\n flexShrink: 0,\n transform: folded ? \"rotate(-90deg)\" : undefined,\n transition: \"transform 120ms ease\",\n }}\n />\n </button>\n );\n}\n\n/* ── Panel-collapse glyph ─────────────────────────────────────────────── */\n\nfunction PanelToggleIcon({ flipped }: { flipped: boolean }) {\n return (\n <svg\n width=\"15\"\n height=\"15\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n style={{ transform: flipped ? \"scaleX(-1)\" : undefined }}\n >\n <rect x=\"1.5\" y=\"2.5\" width=\"13\" height=\"11\" rx=\"1.5\" stroke=\"currentColor\" />\n <path d=\"M5.5 2.5v11\" stroke=\"currentColor\" />\n <path\n d=\"M11 5.5 8.5 8l2.5 2.5\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n","import { Link, useLocation } from \"react-router-dom\";\nimport { HamburgerMenuIcon, MagnifyingGlassIcon, BellIcon } from \"@radix-ui/react-icons\";\nimport { Flex, Heading, IconButton, Text, Tooltip } from \"@radix-ui/themes\";\nimport { SHELL_HEADER_H } from \"./Sidebar\";\nimport { iconSize } from \"./icon-size\";\nimport { headingSize } from \"./heading-scale\";\n\n/* Amber topbar: breadcrumb (section / page) left, search + notifications\n * right — matches Vercel's \"Firewall / Traffic\" pattern (gray parent, bold\n * current page) instead of a single flat title. The parent segment links\n * back to the section's landing route. */\n\n/* `exact` opts a row out of prefix matching, so a landing route and its child\n * routes can carry different labels — e.g. /calendar/view is the merged grid\n * while /calendar/view/:id is one sync's detail. List the exact row first and\n * a prefix row after it to label the children. Omit it (the common case) and\n * the row keeps matching by prefix, so existing 4-element tables are\n * unaffected. */\nexport type TopbarTitleRow = [\n prefix: string,\n section: string,\n sectionHref: string,\n page: string,\n exact?: boolean,\n];\nexport type TopbarAdminTitleRow = [prefix: string, page: string];\n\n/* Route → [section label, section href, page label] — arm-ui's own route\n * table, used as the default so this component works out of the box for\n * that app. Pass `titles`/`adminTitles` to reuse Topbar with a different\n * app's routes. */\nconst DEFAULT_TITLES: TopbarTitleRow[] = [\n [\"/home\", \"Home\", \"/home\", \"Home\"],\n [\"/calendar/syncs\", \"Calendar\", \"/calendar/syncs\", \"Manage Syncs\"],\n [\"/calendar/view\", \"Calendar\", \"/calendar/syncs\", \"My Calendar\"],\n [\"/calendar\", \"Calendar\", \"/calendar/syncs\", \"Manage Syncs\"],\n [\"/settings/account\", \"Settings\", \"/settings/account\", \"Account\"],\n [\"/settings/linked\", \"Settings\", \"/settings/account\", \"Linked Account\"],\n [\"/settings\", \"Settings\", \"/settings/account\", \"Settings\"],\n];\n\n/* Admin sub-pages get their own breadcrumb page label instead of a blanket\n * \"Admin Portal\" — mirrors ADMIN_CHILDREN's labels in Sidebar.tsx so the two\n * stay in sync. Longest prefix first so \"/admin/users/:id\" still matches\n * Users. */\nconst DEFAULT_ADMIN_TITLES: TopbarAdminTitleRow[] = [\n [\"/admin/overview\", \"Overview\"],\n [\"/admin/users\", \"Users\"],\n [\"/admin/monitoring\", \"Monitoring\"],\n [\"/admin/calendar-ops\", \"Calendar Ops\"],\n [\"/admin/logs\", \"Logs\"],\n [\"/admin/security\", \"Security\"],\n [\"/admin/audit\", \"Audit Log\"],\n];\n\nfunction breadcrumb(\n pathname: string,\n titles: TopbarTitleRow[],\n adminTitles: TopbarAdminTitleRow[],\n): { section: string; sectionHref: string; page: string } {\n if (pathname === \"/admin\" || pathname.startsWith(\"/admin/\")) {\n const hit = adminTitles.find(([p]) => pathname === p || pathname.startsWith(p + \"/\"));\n return { section: \"Admin Portal\", sectionHref: \"/admin/overview\", page: hit ? hit[1] : \"Admin Portal\" };\n }\n /* Sync editor is under /calendar/syncs/* — label before the Manage Syncs prefix match. */\n if (pathname === \"/calendar/syncs/new\") {\n return { section: \"Calendar\", sectionHref: \"/calendar/syncs\", page: \"New Sync\" };\n }\n if (/^\\/calendar\\/syncs\\/[^/]+$/.test(pathname)) {\n return { section: \"Calendar\", sectionHref: \"/calendar/syncs\", page: \"Edit Sync\" };\n }\n const hit = titles.find(([p, , , , exact]) =>\n exact ? pathname === p : pathname === p || pathname.startsWith(p + \"/\"),\n );\n if (!hit) return { section: \"Home\", sectionHref: \"/home\", page: \"Home\" };\n const [, section, sectionHref, page] = hit;\n return { section, sectionHref, page };\n}\n\nexport interface TopbarProps {\n onSearchOpen: () => void;\n onMenuOpen: () => void;\n showMenu: boolean;\n /** Override the breadcrumb route tables — defaults to arm-ui's own routes. */\n titles?: TopbarTitleRow[];\n adminTitles?: TopbarAdminTitleRow[];\n}\n\nexport function Topbar({\n onSearchOpen,\n onMenuOpen,\n showMenu,\n titles = DEFAULT_TITLES,\n adminTitles = DEFAULT_ADMIN_TITLES,\n}: TopbarProps) {\n const pathname = useLocation().pathname;\n\n return (\n /* <header>, not <div>: this is the page banner, and as a plain div the\n page-title h1 and the breadcrumb beside it sat outside every landmark —\n axe `region` flagged them on every page. `display: flex` is set below, so\n the element swap changes semantics only. */\n <header\n style={{\n height: SHELL_HEADER_H,\n background: \"var(--accent-9)\",\n borderBottom: \"1px solid var(--border-hairline)\",\n flexShrink: 0,\n display: \"flex\",\n alignItems: \"center\",\n padding: \"0 var(--space-6)\",\n gap: \"var(--space-4)\",\n }}\n >\n {/* Mobile hamburger — dark ink for the amber surface */}\n {showMenu && (\n <IconButton\n variant=\"ghost\"\n size=\"1\"\n onClick={onMenuOpen}\n aria-label=\"Open navigation\"\n style={{ marginRight: \"var(--space-1)\", color: \"var(--shell-ink-strong)\" }}\n >\n <HamburgerMenuIcon style={iconSize(\"--space-4\")} />\n </IconButton>\n )}\n\n {(() => {\n const { section, sectionHref, page } = breadcrumb(pathname, titles, adminTitles);\n const showSection = section !== page;\n return (\n /* The container already allowed itself to shrink, but both segments\n were `nowrap` with nothing to truncate into — so instead of\n narrowing they overflowed and the search pill was drawn over them.\n Each segment truncates, and below 500px the section and its\n separator are hidden outright (tokens.css) so the page title keeps\n the row to itself.\n That hiding is the fix for a real measurement, not tidying: both\n the section and the separator are flexShrink: 0, so every pixel of\n squeeze landed on the h1 — 53px of a 67px title at 375px, ellipsised\n on every admin page. The older reasoning here said the page label\n should truncate first \"since the section beside it is the shorter\n of the two\", which is backwards for the admin routes: \"Admin\n Portal\" is longer than \"Audit Log\". The sidebar already says which\n section you are in; the page title is the cue that has nowhere\n else to come from. */\n <Flex align=\"baseline\" gap=\"2\" style={{ minWidth: 0, overflow: \"hidden\" }}>\n {showSection && (\n <>\n <Text asChild size=\"3\" weight=\"regular\">\n <Link\n to={sectionHref}\n style={{\n color: \"var(--shell-ink-mid)\",\n whiteSpace: \"nowrap\",\n textDecoration: \"none\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n flexShrink: 0,\n }}\n className=\"topbar-breadcrumb-link\"\n >\n {section}\n </Link>\n </Text>\n <Text\n size=\"3\"\n weight=\"regular\"\n className=\"topbar-breadcrumb-sep\"\n style={{ color: \"var(--shell-ink-mid)\", flexShrink: 0 }}\n >\n /\n </Text>\n </>\n )}\n <Heading\n as=\"h1\"\n size={headingSize.h1}\n weight=\"medium\"\n style={{\n color: \"var(--shell-ink-strong)\",\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n minWidth: 0,\n }}\n >\n {page}\n </Heading>\n </Flex>\n );\n })()}\n\n {/* Spacer */}\n <div style={{ flex: 1 }} />\n\n {/* Search trigger */}\n <button\n className=\"topbar-search\"\n onClick={onSearchOpen}\n aria-label=\"Search (⌘K)\"\n >\n <MagnifyingGlassIcon\n width={16}\n height={16}\n style={{ color: \"var(--shell-ink-strong)\", flexShrink: 0 }}\n />\n <span className=\"topbar-search-placeholder\">Search for something</span>\n </button>\n\n {/* Notifications — not wired yet */}\n <Tooltip content=\"Coming soon\">\n <span>\n <button\n className=\"topbar-icon-circle\"\n aria-label=\"Notifications (coming soon)\"\n disabled\n >\n <BellIcon style={iconSize(\"--space-4\")} />\n </button>\n </span>\n </Tooltip>\n </header>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { Dialog, Flex, Spinner, Text, TextField, VisuallyHidden } from \"@radix-ui/themes\";\nimport { CalendarIcon, MagnifyingGlassIcon, PersonIcon, ReaderIcon } from \"@radix-ui/react-icons\";\n\nexport type SearchResultType = \"app\" | \"people\" | \"page\";\n\nexport interface SearchResult {\n id: string;\n title: string;\n subtitle: string;\n href: string;\n type: SearchResultType;\n}\n\ntype OverlayState = \"prompt\" | \"searching\" | \"no-match\" | \"results\";\n\n/* ── Result icon by type ─────────────────────────────────────────────────── */\n\nconst TYPE_ICON: Record<SearchResultType, React.ComponentType<{ width?: number; height?: number; style?: React.CSSProperties }>> = {\n app: CalendarIcon,\n people: PersonIcon,\n page: ReaderIcon,\n};\n\nconst TYPE_LABEL: Record<SearchResultType, string> = {\n app: \"Apps\",\n people: \"People\",\n page: \"Pages\",\n};\n\n/* ── Group helpers ───────────────────────────────────────────────────────── */\n\ninterface ResultGroup {\n type: SearchResultType;\n label: string;\n items: SearchResult[];\n startIdx: number; // flat index of first item in this group\n}\n\nfunction groupResults(results: SearchResult[]): ResultGroup[] {\n const order: SearchResultType[] = [\"app\", \"people\", \"page\"];\n const groups: ResultGroup[] = [];\n let flat = 0;\n for (const t of order) {\n const items = results.filter((r) => r.type === t);\n if (items.length > 0) {\n groups.push({ type: t, label: TYPE_LABEL[t], items, startIdx: flat });\n flat += items.length;\n }\n }\n return groups;\n}\n\n/* ── Overlay ─────────────────────────────────────────────────────────────── */\n\nexport interface SearchOverlayProps {\n open: boolean;\n onClose: () => void;\n /** The searchable pool for the current user — the app owns its own\n * content/routes and any role-based filtering before passing this in. */\n results: SearchResult[];\n onSelectResult: (result: SearchResult) => void;\n title?: string;\n placeholder?: string;\n}\n\nexport function SearchOverlay({\n open,\n onClose,\n results: resultPool,\n onSelectResult,\n title = \"Search\",\n placeholder = \"Search…\",\n}: SearchOverlayProps) {\n // The body is mounted only while open — Radix unmounts dialog content on\n // close, so each open starts from a clean slate with no reset effect needed.\n return (\n <Dialog.Root open={open} onOpenChange={(o) => !o && onClose()}>\n <Dialog.Content\n aria-describedby={undefined}\n style={{\n padding: 0,\n maxWidth: \"calc(9 * var(--space-9) + var(--space-2))\",\n overflow: \"hidden\",\n boxShadow:\n \"0 4px 8px rgba(0,0,0,0.06), 0 12px 32px rgba(0,0,0,0.10), 0 0 0 1px var(--gray-5)\",\n }}\n >\n <SearchBody\n onClose={onClose}\n resultPool={resultPool}\n onSelectResult={onSelectResult}\n title={title}\n placeholder={placeholder}\n />\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nfunction SearchBody({\n onClose,\n resultPool,\n onSelectResult,\n title,\n placeholder,\n}: {\n onClose: () => void;\n resultPool: SearchResult[];\n onSelectResult: (result: SearchResult) => void;\n title: string;\n placeholder: string;\n}) {\n const [query, setQuery] = useState(\"\");\n const [searchResults, setSearchResults] = useState<{ q: string; items: SearchResult[] } | null>(null);\n const [selectedIdx, setSelectedIdx] = useState(-1);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n\n // Derive the overlay state from the query and the last completed search, so we\n // never set state synchronously inside the debounce effect.\n const isCurrent = !!searchResults && searchResults.q === query;\n const results = isCurrent ? searchResults.items : [];\n const state: OverlayState = !query.trim()\n ? \"prompt\"\n : !isCurrent\n ? \"searching\"\n : results.length\n ? \"results\"\n : \"no-match\";\n\n /* Debounced search — state is updated only inside the timeout callback */\n useEffect(() => {\n if (!query.trim()) return;\n const t = setTimeout(() => {\n const q = query.toLowerCase();\n const found = resultPool.filter(\n (r) =>\n r.title.toLowerCase().includes(q) ||\n r.subtitle.toLowerCase().includes(q)\n );\n setSearchResults({ q: query, items: found });\n setSelectedIdx(-1);\n }, 320);\n return () => clearTimeout(t);\n }, [query, resultPool]);\n\n /* Scroll selected item into view */\n useEffect(() => {\n if (selectedIdx < 0 || !listRef.current) return;\n const el = listRef.current.querySelector<HTMLElement>(`[data-idx=\"${selectedIdx}\"]`);\n el?.scrollIntoView({ block: \"nearest\" });\n }, [selectedIdx]);\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {\n if (e.key === \"Escape\") {\n onClose();\n } else if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setSelectedIdx((i) => Math.min(i + 1, results.length - 1));\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setSelectedIdx((i) => Math.max(i - 1, 0));\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n if (selectedIdx >= 0 && results[selectedIdx]) {\n onSelectResult(results[selectedIdx]);\n onClose();\n }\n }\n }\n\n function selectResult(result: SearchResult) {\n onSelectResult(result);\n onClose();\n }\n\n const grouped = groupResults(results);\n const promptHeight = \"calc(2 * var(--space-9) + var(--space-6))\";\n\n return (\n <>\n <VisuallyHidden>\n <Dialog.Title>{title}</Dialog.Title>\n </VisuallyHidden>\n\n {/* ── Input row ──────────────────────────────────────────────── */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n padding: \"var(--space-3) var(--space-4)\",\n borderBottom: \"1px solid var(--gray-5)\",\n }}\n >\n {state === \"searching\" ? (\n <Spinner size=\"1\" style={{ flexShrink: 0 }} />\n ) : (\n <MagnifyingGlassIcon\n width={16}\n height={16}\n style={{ color: \"var(--gray-9)\", flexShrink: 0 }}\n />\n )}\n <TextField.Root\n ref={inputRef}\n autoFocus\n type=\"text\"\n placeholder={placeholder}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={handleKeyDown}\n className=\"search-overlay-input\"\n style={{\n flex: 1,\n border: \"none\",\n outline: \"none\",\n background: \"transparent\",\n boxShadow: \"none\",\n \"--text-field-selection-color\": \"unset\",\n } as React.CSSProperties}\n />\n <kbd\n style={{\n color: \"var(--gray-11)\",\n background: \"var(--gray-3)\",\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-1)\",\n padding: \"var(--space-1) var(--space-2)\",\n flexShrink: 0,\n }}\n >\n <Text size=\"1\" as=\"span\">Esc</Text>\n </kbd>\n </div>\n\n {/* ── Results body ───────────────────────────────────────────── */}\n <div\n ref={listRef}\n style={{\n minHeight: promptHeight,\n maxHeight: \"calc(6 * var(--space-9) + var(--space-7))\",\n overflowY: \"auto\",\n }}\n >\n {state === \"prompt\" && (\n <Flex\n align=\"center\"\n justify=\"center\"\n style={{ height: promptHeight }}\n >\n <Text size=\"2\" color=\"gray\">\n Type to search…\n </Text>\n </Flex>\n )}\n\n {state === \"no-match\" && (\n <Flex\n align=\"center\"\n justify=\"center\"\n style={{ height: promptHeight }}\n >\n <div style={{ textAlign: \"center\" }}>\n <Text size=\"2\" color=\"gray\" as=\"p\">\n No results for “{query}”\n </Text>\n <Text size=\"1\" color=\"gray\" as=\"p\" mt=\"1\">\n Try searching with different keywords\n </Text>\n </div>\n </Flex>\n )}\n\n {state === \"results\" && (\n <div style={{ padding: \"var(--space-2)\" }}>\n {grouped.map((group) => {\n const Icon = TYPE_ICON[group.type];\n return (\n <div\n key={group.type}\n style={{ marginBottom: \"var(--space-1)\" }}\n >\n {/* Group label */}\n <div\n style={{\n padding: \"var(--space-2) var(--space-3) var(--space-1)\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-2)\",\n }}\n >\n <Text\n size=\"1\"\n style={{\n color: \"var(--gray-11)\",\n fontWeight: 500,\n letterSpacing: \"0.04em\",\n textTransform: \"uppercase\",\n fontFamily: \"var(--font-poppins)\",\n }}\n >\n {group.label}\n </Text>\n </div>\n\n {/* Group items */}\n {group.items.map((result, i) => {\n const flatIdx = group.startIdx + i;\n const isSelected = selectedIdx === flatIdx;\n return (\n <button\n key={result.id}\n data-idx={flatIdx}\n onClick={() => selectResult(result)}\n onMouseEnter={() => setSelectedIdx(flatIdx)}\n className=\"search-result-item\"\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n padding: \"var(--space-2) var(--space-3)\",\n borderRadius: \"var(--radius-2)\",\n border: \"none\",\n cursor: \"pointer\",\n textAlign: \"left\",\n background: isSelected ? \"var(--gray-3)\" : \"transparent\",\n }}\n >\n <div\n style={{\n width: \"var(--space-6)\",\n height: \"var(--space-6)\",\n borderRadius: \"var(--radius-1)\",\n background: isSelected ? \"var(--accent-a3)\" : \"var(--gray-3)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n transition: \"background 100ms ease\",\n }}\n >\n <Icon\n width={12}\n height={12}\n style={{ color: isSelected ? \"var(--accent-11)\" : \"var(--gray-9)\" }}\n />\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n <Text\n as=\"p\"\n size=\"2\"\n weight=\"medium\"\n style={{\n color: isSelected ? \"var(--gray-12)\" : \"var(--gray-11)\",\n lineHeight: 1.3,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {result.title}\n </Text>\n <Text\n as=\"p\"\n size=\"1\"\n style={{\n color: \"var(--gray-11)\",\n lineHeight: 1.3,\n marginTop: \"1px\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {result.subtitle}\n </Text>\n </div>\n {isSelected && (\n <kbd\n style={{\n color: \"var(--gray-9)\",\n background: \"var(--gray-4)\",\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-1)\",\n padding: \"var(--space-1)\",\n flexShrink: 0,\n }}\n >\n <Text size=\"1\" as=\"span\" className=\"data-mono\">↵</Text>\n </kbd>\n )}\n </button>\n );\n })}\n </div>\n );\n })}\n </div>\n )}\n </div>\n\n {/* ── Footer hint ────────────────────────────────────────────── */}\n {state !== \"prompt\" && (\n <div\n style={{\n borderTop: \"1px solid var(--gray-4)\",\n padding: \"var(--space-2) var(--space-4)\",\n display: \"flex\",\n gap: \"var(--space-4)\",\n }}\n >\n <Text as=\"span\" size=\"1\" color=\"gray\">\n <kbd className=\"data-mono\">↑↓</kbd> navigate\n </Text>\n <Text as=\"span\" size=\"1\" color=\"gray\">\n <kbd className=\"data-mono\">↵</kbd> open\n </Text>\n <Text as=\"span\" size=\"1\" color=\"gray\">\n <kbd className=\"data-mono\">Esc</kbd> close\n </Text>\n </div>\n )}\n </>\n );\n}\n","export type { CalendarProvider } from \"./ProviderIcon\";\nimport type { CalendarProvider } from \"./ProviderIcon\";\n\n/** Duplicated from the app's src/lib/calendar-mock.ts (not imported) so this\n * package has no dependency back into the app. Keep in sync if the app's\n * calendar data model changes. */\n\nexport interface CalendarAccountCalendar {\n id: string;\n accountId: string;\n name: string;\n isPrimary: boolean;\n /** Drives the import dialog's color dot, the legend, and month/week dots. */\n colorToken: string;\n}\n\nexport interface CalendarAccount {\n id: string;\n provider: CalendarProvider;\n email: string;\n displayName: string;\n initials: string;\n authStatus: \"active\" | \"reauth\" | \"failed\";\n calendars: CalendarAccountCalendar[];\n}\n\nexport function findCalendar(\n accounts: CalendarAccount[],\n calendarId: string\n): { account: CalendarAccount; calendar: CalendarAccountCalendar } | undefined {\n for (const account of accounts) {\n const calendar = account.calendars.find((c) => c.id === calendarId);\n if (calendar) return { account, calendar };\n }\n return undefined;\n}\n\nexport interface AvailabilityBlock {\n id: string;\n calendarId: string;\n accountId: string;\n /** 0 = Monday … 6 = Sunday (week-relative) */\n day: number;\n startHour: number;\n startMinute: number;\n endHour: number;\n endMinute: number;\n title: string;\n description?: string;\n location?: string;\n /** Marked private at the source — always renders as the sync's tag alone,\n * regardless of that sync's field toggles. */\n isPrivate: boolean;\n}\n\nexport interface DatedAvailabilityBlock extends AvailabilityBlock {\n date: Date;\n}\n\nexport interface ResolvedBlock extends DatedAvailabilityBlock {\n /** True when this occurrence is showing on a calendar it wasn't natively\n * created on (i.e. merged in via a sync), as opposed to its home calendar. */\n isMerged: boolean;\n}\n\nexport type SyncStatus = \"synced\" | \"syncing\" | \"error\";\n\nexport interface CalendarSync {\n id: string;\n name: string;\n targetCalendarId: string;\n sourceCalendarIds: string[];\n status: SyncStatus;\n lastSyncedLabel?: string;\n showTitle: boolean;\n showDescription: boolean;\n showLocation: boolean;\n /** The sync's tag — the label its events carry on the target calendar.\n * Optional so existing callers keep compiling; treat an absent value as the\n * default, \"Busy\". */\n tagLabel?: string;\n}\n","import dayjs from \"dayjs\";\nimport { Flex, Text } from \"@radix-ui/themes\";\nimport type { HeaderProps } from \"react-big-calendar\";\n\nexport interface CalendarDayHeaderProps extends HeaderProps {\n /** \"Today\" reference for the filled-circle marker. Defaults to the real\n * current date — pass a fixed date for demo/mock consistency. */\n today?: Date;\n}\n\n/** Week-view column header — replaces RBC's plain \"22 Mon\" label with a\n * weekday caption + a filled amber circle on today's date number, matching\n * the OneCal reference's today marker instead of the near-invisible\n * `.rbc-today` background wash. */\nexport function CalendarDayHeader({ date, today = new Date() }: CalendarDayHeaderProps) {\n const isToday = dayjs(date).isSame(today, \"day\");\n return (\n <Flex direction=\"column\" align=\"center\" gap=\"1\" py=\"1\">\n <Text size=\"1\" weight=\"medium\" color=\"gray\" style={{ letterSpacing: \"0.04em\" }}>\n {dayjs(date).format(\"ddd\").toUpperCase()}\n </Text>\n <Flex\n align=\"center\"\n justify=\"center\"\n style={{\n width: \"var(--space-6)\",\n height: \"var(--space-6)\",\n borderRadius: \"50%\",\n background: isToday ? \"var(--accent-9)\" : \"transparent\",\n lineHeight: 1,\n }}\n >\n <Text\n size=\"3\"\n weight={isToday ? \"medium\" : \"regular\"}\n style={{ color: isToday ? \"var(--accent-contrast)\" : \"var(--gray-12)\", lineHeight: 1 }}\n >\n {dayjs(date).format(\"D\")}\n </Text>\n </Flex>\n </Flex>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { Box, Checkbox, Flex, RadioGroup, Text } from \"@radix-ui/themes\";\nimport { ProviderIcon } from \"./ProviderIcon\";\nimport type { CalendarAccount } from \"./calendar-types\";\n\ntype Row = {\n calendarId: string;\n calendarName: string;\n email: string;\n provider: CalendarAccount[\"provider\"];\n};\n\nfunction rowsFromAccounts(accounts: CalendarAccount[]): Row[] {\n return accounts.flatMap((account) =>\n account.calendars.map((cal) => ({\n calendarId: cal.id,\n calendarName: cal.name,\n email: account.email,\n provider: account.provider,\n }))\n );\n}\n\n/** Bare provider mark — no IconTile chrome (OneCal list rows). */\nfunction ProviderMark({ provider }: { provider: CalendarAccount[\"provider\"] }) {\n return (\n <span\n aria-hidden\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"var(--space-5)\",\n height: \"var(--space-5)\",\n flexShrink: 0,\n }}\n >\n <ProviderIcon provider={provider} />\n </span>\n );\n}\n\nfunction CalendarRow({\n row,\n control,\n selected,\n disabled,\n disabledLabel,\n}: {\n row: Row;\n control: ReactNode;\n selected: boolean;\n disabled: boolean;\n disabledLabel?: string;\n}) {\n return (\n <Text\n as=\"label\"\n size=\"2\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n width: \"100%\",\n paddingBlock: \"var(--space-3)\",\n paddingInline: \"var(--space-4)\",\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n opacity: disabled ? 0.45 : 1,\n background: selected ? \"var(--accent-2)\" : \"transparent\",\n color: \"var(--gray-12)\",\n }}\n >\n <ProviderMark provider={row.provider} />\n <Flex direction=\"column\" gap=\"0\" style={{ minWidth: 0, flex: 1 }}>\n <Text size=\"2\" weight=\"medium\" truncate style={{ color: \"var(--gray-12)\" }}>\n {row.calendarName}\n </Text>\n <Text size=\"1\" color=\"gray\" truncate>\n {row.email}\n </Text>\n </Flex>\n {disabledLabel ? (\n <Text size=\"1\" color=\"gray\" style={{ flexShrink: 0 }}>\n {disabledLabel}\n </Text>\n ) : null}\n <Box style={{ flexShrink: 0, display: \"flex\", alignItems: \"center\" }}>{control}</Box>\n </Text>\n );\n}\n\n/** OneCal-style flat calendar list (logo + name/email + control). */\nexport function CalendarPickList({\n accounts,\n mode,\n sourceCalendarIds,\n targetCalendarId,\n takenSourceIds,\n onToggleSource,\n onSelectTarget,\n fill = false,\n}: {\n accounts: CalendarAccount[];\n mode: \"sources\" | \"target\";\n sourceCalendarIds: string[];\n targetCalendarId: string | null;\n takenSourceIds: Set<string>;\n onToggleSource: (calendarId: string) => void;\n onSelectTarget: (calendarId: string) => void;\n /** Fill parent and scroll internally (step 2 dual lists). */\n fill?: boolean;\n}) {\n const rows = rowsFromAccounts(accounts);\n\n // Every row can end up disabled (all calendars already used as a source\n // elsewhere, or the only one left is the chosen target) — previously this\n // just showed a fully greyed-out list with a tiny per-row \"In use\" label\n // and no page-level explanation, easy to mistake for a bug.\n const allSourcesDisabled =\n mode === \"sources\" &&\n rows.length > 0 &&\n rows.every((row) => row.calendarId === targetCalendarId || takenSourceIds.has(row.calendarId));\n\n const list = allSourcesDisabled ? (\n <Box\n style={{\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-3)\",\n background: \"var(--color-panel-solid)\",\n padding: \"var(--space-4)\",\n ...(fill ? { flex: 1, minHeight: 0 } : {}),\n }}\n >\n <Text as=\"p\" size=\"2\" color=\"gray\" align=\"center\">\n All your calendars are already used as sources in other syncs, or set as this sync's\n target. Remove a calendar from another sync to make it available here.\n </Text>\n </Box>\n ) : (\n <Box\n style={{\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-3)\",\n background: \"var(--color-panel-solid)\",\n ...(fill\n ? { flex: 1, minHeight: 0, overflowY: \"auto\" }\n : { overflow: \"hidden\" }),\n }}\n >\n {rows.map((row, idx) => {\n if (mode === \"sources\") {\n const isTarget = row.calendarId === targetCalendarId;\n const takenElsewhere = takenSourceIds.has(row.calendarId);\n const disabled = isTarget || takenElsewhere;\n const selected = sourceCalendarIds.includes(row.calendarId);\n return (\n <Box\n key={row.calendarId}\n style={{ borderTop: idx > 0 ? \"1px solid var(--gray-4)\" : undefined }}\n >\n <CalendarRow\n row={row}\n selected={selected}\n disabled={disabled}\n disabledLabel={isTarget ? \"Target\" : takenElsewhere ? \"In use\" : undefined}\n control={\n <Checkbox\n checked={selected}\n disabled={disabled}\n onCheckedChange={() => {\n if (!disabled) onToggleSource(row.calendarId);\n }}\n />\n }\n />\n </Box>\n );\n }\n\n const isSource = sourceCalendarIds.includes(row.calendarId);\n const selected = row.calendarId === targetCalendarId;\n return (\n <Box\n key={row.calendarId}\n style={{ borderTop: idx > 0 ? \"1px solid var(--gray-4)\" : undefined }}\n >\n <CalendarRow\n row={row}\n selected={selected}\n disabled={isSource}\n disabledLabel={isSource ? \"Source\" : undefined}\n control={<RadioGroup.Item value={row.calendarId} disabled={isSource} />}\n />\n </Box>\n );\n })}\n </Box>\n );\n\n if (mode === \"target\") {\n return (\n <RadioGroup.Root\n value={targetCalendarId ?? \"\"}\n onValueChange={(v) => {\n if (v) onSelectTarget(v);\n }}\n style={\n fill\n ? { flex: 1, minHeight: 0, display: \"flex\", flexDirection: \"column\" }\n : undefined\n }\n >\n {list}\n </RadioGroup.Root>\n );\n }\n\n return list;\n}\n","import { Button, Flex, Heading, IconButton } from \"@radix-ui/themes\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"@radix-ui/react-icons\";\nimport { Navigate, type ToolbarProps } from \"react-big-calendar\";\nimport type { View } from \"./BigCalendarView\";\nimport { headingSize } from \"./heading-scale\";\n\n/** DS-native replacement for react-big-calendar's default toolbar — pill nav\n * arrows + Today button (left), label (center), Week/Month switch (right).\n * All logic stays RBC's; this only swaps the rendered chrome.\n * Props typed loosely (any event/resource) since RBC's Components<TEvent>\n * requires the toolbar to accept ToolbarProps<TEvent>, not our own event type. */\nexport function CalendarToolbar({\n label,\n view,\n onNavigate,\n onView,\n}: ToolbarProps<object, object>) {\n return (\n <Flex align=\"center\" justify=\"between\" gap=\"3\" wrap=\"wrap\" className=\"calendar-toolbar\">\n <Flex align=\"center\" gap=\"2\">\n <IconButton\n size=\"2\"\n variant=\"soft\"\n color=\"gray\"\n radius=\"full\"\n aria-label=\"Previous\"\n onClick={() => onNavigate(Navigate.PREVIOUS)}\n >\n <ChevronLeftIcon />\n </IconButton>\n <Button size=\"2\" variant=\"soft\" color=\"gray\" onClick={() => onNavigate(Navigate.TODAY)}>\n Today\n </Button>\n <IconButton\n size=\"2\"\n variant=\"soft\"\n color=\"gray\"\n radius=\"full\"\n aria-label=\"Next\"\n onClick={() => onNavigate(Navigate.NEXT)}\n >\n <ChevronRightIcon />\n </IconButton>\n </Flex>\n\n <Heading as=\"h2\" size={headingSize.h2} weight=\"medium\" style={{ color: \"var(--gray-12)\" }}>\n {label}\n </Heading>\n\n <Flex\n gap=\"1\"\n style={{\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-3)\",\n padding: \"var(--space-1)\",\n background: \"var(--gray-2)\",\n }}\n >\n {([\"week\", \"month\"] as View[]).map((v) => (\n <Button\n key={v}\n size=\"2\"\n variant={view === v ? \"solid\" : \"soft\"}\n className={view === v ? \"btn-amber-primary\" : undefined}\n color={view === v ? undefined : \"gray\"}\n onClick={() => onView(v)}\n style={view === v ? undefined : { background: \"transparent\" }}\n >\n {v === \"week\" ? \"Week\" : \"Month\"}\n </Button>\n ))}\n </Flex>\n </Flex>\n );\n}\n","import { Button, Flex, Spinner, Text } from \"@radix-ui/themes\";\nimport { ChevronRightIcon, ExclamationTriangleIcon } from \"@radix-ui/react-icons\";\nimport { ProviderIcon } from \"./ProviderIcon\";\nimport { IconTile } from \"./IconTile\";\nimport type { CalendarProvider } from \"./ProviderIcon\";\nimport { iconSize } from \"./icon-size\";\n\nexport const PROVIDER_META: Record<CalendarProvider, { label: string; description: string }> = {\n google: { label: \"Google Calendar\", description: \"Connect a Google account calendar\" },\n microsoft: { label: \"Outlook Calendar\", description: \"Connect an Outlook account calendar\" },\n};\n\nconst PROVIDERS: CalendarProvider[] = [\"google\", \"microsoft\"];\n\n/** Provider connect buttons — bordered, spaced action rows with hover / press /\n * focus / connecting states (`.provider-choice` in globals.css). */\nexport function ConnectProviderList({\n connectingProvider,\n failedProvider,\n exhausted = false,\n onConnect,\n}: {\n connectingProvider: CalendarProvider | null;\n failedProvider: CalendarProvider | null;\n /** True when the failure is \"no more mock accounts for this provider\" —\n * not a real error, so Retry can't help and the copy should say so. */\n exhausted?: boolean;\n onConnect: (provider: CalendarProvider) => void;\n}) {\n return (\n <Flex direction=\"column\" gap=\"3\" style={{ width: \"100%\", textAlign: \"left\" }}>\n {PROVIDERS.map((provider) => {\n const meta = PROVIDER_META[provider];\n const connecting = connectingProvider === provider;\n const busy = connectingProvider !== null;\n return (\n <div key={provider}>\n <button\n type=\"button\"\n className=\"provider-choice\"\n onClick={() => onConnect(provider)}\n disabled={busy}\n data-connecting={connecting ? \"true\" : undefined}\n aria-busy={connecting || undefined}\n aria-label={`Connect ${meta.label}`}\n >\n <IconTile>\n <ProviderIcon provider={provider} />\n </IconTile>\n <Flex direction=\"column\" className=\"provider-choice__copy\" gap=\"1\">\n <Text size=\"3\" weight=\"medium\" truncate style={{ color: \"var(--gray-12)\" }}>\n {meta.label}\n </Text>\n <Text size=\"2\" color=\"gray\" truncate>\n {meta.description}\n </Text>\n </Flex>\n <span className=\"provider-choice__chevron\" aria-hidden>\n {connecting ? (\n <Spinner size=\"2\" />\n ) : (\n <ChevronRightIcon style={iconSize(\"--space-5\")} />\n )}\n </span>\n </button>\n {failedProvider === provider && (\n <Flex align=\"center\" justify=\"between\" gap=\"3\" mt=\"2\" px=\"1\">\n <Flex align=\"center\" gap=\"2\">\n <ExclamationTriangleIcon\n style={{ ...iconSize(\"--space-4\"), color: \"var(--red-9)\", flexShrink: 0 }}\n />\n <Text size=\"2\" style={{ color: \"var(--red-11)\" }}>\n {exhausted\n ? `No more ${meta.label} accounts available to connect.`\n : `Couldn't connect ${meta.label}. Please try again.`}\n </Text>\n </Flex>\n {!exhausted && (\n <Button variant=\"ghost\" size=\"1\" onClick={() => onConnect(provider)}>\n Retry\n </Button>\n )}\n </Flex>\n )}\n </div>\n );\n })}\n </Flex>\n );\n}\n","import { Badge, Box, DropdownMenu, Flex, IconButton, Text } from \"@radix-ui/themes\";\nimport { DotsVerticalIcon, ReloadIcon, TrashIcon } from \"@radix-ui/react-icons\";\nimport { ProviderIcon } from \"./ProviderIcon\";\nimport { IconTile } from \"./IconTile\";\nimport type { CalendarAccount } from \"./calendar-types\";\nimport { layout } from \"./layout-tokens\";\n\n/** Compact horizontal connected-account card — fills its grid cell (max 4 / row). */\nexport function ConnectedAccountCard({\n account,\n onRemove,\n onReconnect,\n onClick,\n}: {\n account: CalendarAccount;\n onRemove: () => void;\n onReconnect?: () => void;\n /** Opens account detail (calendars) — kebab clicks do not fire this. */\n onClick?: () => void;\n}) {\n const needsReauth = account.authStatus === \"reauth\";\n const hasFailed = account.authStatus === \"failed\";\n\n const name = (\n <Text size=\"2\" weight=\"medium\" truncate style={{ color: \"var(--gray-12)\" }}>\n {account.displayName}\n </Text>\n );\n\n return (\n /* The card takes the mouse click, but it is not role=\"button\": the kebab\n * inside it would then be a control nested in a control, which keyboard and\n * screen-reader users cannot reach. The name is the keyboard control. */\n <Box\n onClick={onClick}\n style={{\n width: \"100%\",\n minWidth: 0,\n height: layout.connectedAccountCardH,\n boxSizing: \"border-box\",\n padding: \"var(--space-3)\",\n background: \"var(--color-panel-solid)\",\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-3)\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n cursor: onClick ? \"pointer\" : undefined,\n }}\n >\n <IconTile size=\"var(--space-6)\">\n <ProviderIcon provider={account.provider} />\n </IconTile>\n\n <Flex direction=\"column\" style={{ flex: 1, minWidth: 0 }}>\n <Flex align=\"center\" gap=\"2\" style={{ minWidth: 0 }}>\n {onClick ? (\n <button\n type=\"button\"\n className=\"card-title-button\"\n onClick={(e) => {\n e.stopPropagation();\n onClick();\n }}\n >\n {name}\n </button>\n ) : (\n name\n )}\n {needsReauth && (\n <Badge color=\"amber\" variant=\"soft\" size=\"1\" radius=\"full\" style={{ flexShrink: 0 }}>\n Needs reconnect\n </Badge>\n )}\n {hasFailed && (\n <Badge color=\"red\" variant=\"soft\" size=\"1\" radius=\"full\" style={{ flexShrink: 0 }}>\n Connection failed\n </Badge>\n )}\n </Flex>\n <Text size=\"1\" color=\"gray\" truncate>\n {account.email}\n </Text>\n </Flex>\n\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconButton\n variant=\"ghost\"\n color=\"gray\"\n size=\"1\"\n aria-label={`${account.displayName} actions`}\n onClick={(e) => e.stopPropagation()}\n >\n <DotsVerticalIcon />\n </IconButton>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\" onClick={(e) => e.stopPropagation()}>\n {(needsReauth || hasFailed) && onReconnect && (\n <DropdownMenu.Item onSelect={onReconnect}>\n <ReloadIcon /> Reconnect\n </DropdownMenu.Item>\n )}\n <DropdownMenu.Item color=\"red\" onSelect={onRemove}>\n <TrashIcon /> Remove account\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </Box>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { Flex, Text, Heading } from \"@radix-ui/themes\";\nimport { layout } from \"./layout-tokens\";\nimport { IconTile } from \"./IconTile\";\nimport { headingSize } from \"./heading-scale\";\n\nexport interface EmptyCardProps {\n icon: ReactNode;\n title: string;\n description?: string;\n action?: ReactNode;\n /**\n * Heading level for `title`. Defaults to `h2`.\n *\n * Radix's `Heading` renders an `h1` when given no `as`, which is what this\n * component did — so every empty state emitted a second top-level heading\n * underneath the shell's own page-title `h1`. A screen-reader user\n * navigating by heading heard \"Security\", then \"Nobody is suspended\", as two\n * peers. `h2` is right for the common case, because the shell owns the `h1`\n * on every page this renders inside.\n *\n * It stays configurable because this also renders as a generic centered\n * message — a 403, an unbuilt section — where the surrounding outline may\n * differ.\n */\n headingAs?: \"h1\" | \"h2\" | \"h3\" | \"h4\";\n}\n\n/** Cardless centered empty state — icon, heading, copy, action, no border/\n * background/shadow, matching Vercel's flat \"Continue to X\" / \"Connect a\n * calendar\" pattern (see ConnectProviderRows, which uses the same shape)\n * instead of a bordered box floating in the page. */\nexport function EmptyCard({\n icon,\n title,\n description,\n action,\n headingAs = \"h2\",\n}: EmptyCardProps) {\n return (\n <Flex\n direction=\"column\"\n align=\"center\"\n gap=\"3\"\n style={{ width: \"100%\", paddingTop: \"var(--space-9)\", textAlign: \"center\" }}\n >\n <IconTile size=\"var(--space-8)\">{icon}</IconTile>\n <Heading as={headingAs} size={headingSize[headingAs]} weight=\"medium\" align=\"center\">\n {title}\n </Heading>\n {description && (\n <Text size=\"2\" color=\"gray\" align=\"center\" style={{ maxWidth: layout.emptyStateCopyMax }}>\n {description}\n </Text>\n )}\n {action}\n </Flex>\n );\n}\n","import { useState } from \"react\";\nimport { Dialog, Flex, Text, Checkbox, Button } from \"@radix-ui/themes\";\nimport type { CalendarAccount } from \"./calendar-types\";\nimport { layout } from \"./layout-tokens\";\nimport { CardFooter } from \"./CardFooter\";\n\nexport interface ImportCalendarsDialogProps {\n /** Account catalog whose calendars are offered. Null closes the dialog. */\n account: CalendarAccount | null;\n onOpenChange: (open: boolean) => void;\n /** Called with checked calendar ids when the user confirms. */\n onImport: (selectedCalendarIds: string[]) => void;\n /** Pre-checked calendar ids (manage mode). Defaults to all calendars on `account`. */\n initiallySelectedIds?: string[];\n /**\n * Calendars whose checkbox cannot be changed — the caller has a rule that\n * forbids it, such as a sync depending on the calendar.\n *\n * The row keeps its current state and still counts toward the result — it\n * simply cannot be changed. Without this a caller can only disable every row\n * or none, so a row looks freely tickable right up to the moment the user is\n * told no.\n *\n * Rendered as `data-disabled=\"true\"`, which the package's own\n * `.calendar-picker-row` rules already style.\n */\n disabledIds?: string[];\n /** Shown beside each disabled row, saying why it can't be changed. */\n disabledReason?: string;\n title?: string;\n description?: string;\n confirmLabel?: string;\n}\n\n/** Choose / change which calendars belong to a connected account — OneCal\n * import step; also reused from the account detail popup to edit selection. */\nexport function ImportCalendarsDialog({\n account,\n onOpenChange,\n onImport,\n initiallySelectedIds,\n disabledIds,\n disabledReason,\n title = \"Calendars\",\n description = \"Choose which calendars you want to import.\",\n confirmLabel = \"Import Calendars\",\n}: ImportCalendarsDialogProps) {\n const formKey = account\n ? `${account.id}:${(initiallySelectedIds ?? account.calendars.map((c) => c.id)).join(\",\")}`\n : \"closed\";\n\n return (\n <Dialog.Root open={!!account} onOpenChange={onOpenChange}>\n <Dialog.Content\n maxWidth={layout.dialogMd}\n /* Callers treat dismissal as a deliberate answer rather than an idle\n * close, so a stray click on the backdrop must not stand in for one.\n * Escape and Cancel remain the two intentional ways out. */\n onInteractOutside={(event) => event.preventDefault()}\n >\n {account && (\n <ImportCalendarsForm\n key={formKey}\n account={account}\n initiallySelectedIds={initiallySelectedIds}\n disabledIds={disabledIds}\n disabledReason={disabledReason}\n title={title}\n description={description}\n confirmLabel={confirmLabel}\n onImport={onImport}\n />\n )}\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nfunction ImportCalendarsForm({\n account,\n initiallySelectedIds,\n disabledIds,\n disabledReason,\n title,\n description,\n confirmLabel,\n onImport,\n}: {\n account: CalendarAccount;\n initiallySelectedIds?: string[];\n disabledIds?: string[];\n disabledReason?: string;\n title: string;\n description: string;\n confirmLabel: string;\n onImport: (selectedCalendarIds: string[]) => void;\n}) {\n const [selected, setSelected] = useState<Set<string>>(\n () => new Set(initiallySelectedIds ?? account.calendars.map((c) => c.id))\n );\n\n const disabled = new Set(disabledIds ?? []);\n\n function toggle(id: string) {\n if (disabled.has(id)) return;\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n }\n\n return (\n <>\n <Dialog.Title size=\"5\" weight=\"medium\" mb=\"1\">\n {title}\n </Dialog.Title>\n <Dialog.Description size=\"2\" color=\"gray\" mb=\"2\">\n {description}\n </Dialog.Description>\n <Text as=\"p\" size=\"2\" weight=\"medium\" mb=\"5\" style={{ color: \"var(--gray-12)\" }}>\n {account.email}\n </Text>\n\n <Flex direction=\"column\" gap=\"3\" mb=\"5\">\n {account.calendars.map((cal) => {\n const checked = selected.has(cal.id);\n const isDisabled = disabled.has(cal.id);\n return (\n <Text\n as=\"label\"\n key={cal.id}\n size=\"3\"\n className=\"calendar-picker-row\"\n data-selected={checked || undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n padding: \"var(--space-4)\",\n cursor: isDisabled ? \"default\" : \"pointer\",\n }}\n >\n <Checkbox\n checked={checked}\n disabled={isDisabled}\n onCheckedChange={() => toggle(cal.id)}\n />\n <Text weight=\"medium\" truncate style={{ flex: 1, minWidth: 0, color: \"var(--gray-12)\" }}>\n {cal.name}\n </Text>\n {isDisabled && disabledReason && (\n <Text size=\"1\" color=\"gray\" style={{ flexShrink: 0 }}>\n {disabledReason}\n </Text>\n )}\n </Text>\n );\n })}\n </Flex>\n\n <CardFooter justify=\"between\" noTopMargin pad=\"var(--space-5)\" radius=\"var(--radius-4)\">\n <Dialog.Close>\n <Button size=\"2\" variant=\"outline\" color=\"gray\">\n Cancel\n </Button>\n </Dialog.Close>\n <Button\n size=\"2\"\n className=\"btn-amber-primary\"\n disabled={selected.size === 0}\n onClick={() => onImport(Array.from(selected))}\n >\n {confirmLabel}\n </Button>\n </CardFooter>\n </>\n );\n}\n","import { Box, Flex, Text } from \"@radix-ui/themes\";\n\n/**\n * Black or white, whichever stays legible on `hex`.\n *\n * The chip used to hardcode white text because its background was always the\n * same amber. Once a caller can colour it, that assumption breaks: white on a\n * pale swatch (a yellow, say) is unreadable. Uses the sRGB relative-luminance\n * threshold from WCAG, which is the standard way to make this choice.\n */\nfunction readableTextOn(hex: string): string {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim());\n // Anything that is not a plain 6-digit hex (a CSS var, a named colour) keeps\n // the original white — the caller is then responsible for the contrast.\n if (!m) return \"white\";\n const int = parseInt(m[1]!, 16);\n const channel = (c: number) => {\n const v = c / 255;\n return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);\n };\n const luminance =\n 0.2126 * channel((int >> 16) & 255) +\n 0.7152 * channel((int >> 8) & 255) +\n 0.0722 * channel(int & 255);\n return luminance > 0.45 ? \"black\" : \"white\";\n}\n\nfunction EventChip({\n tone,\n title,\n meta,\n accentColor,\n}: {\n tone: \"source\" | \"synced\";\n title: string;\n meta: string;\n accentColor?: string;\n}) {\n const background =\n tone === \"synced\" ? accentColor || \"var(--accent-9)\" : \"var(--blue-11)\";\n const foreground =\n tone === \"synced\"\n ? accentColor\n ? readableTextOn(accentColor)\n : \"var(--accent-contrast)\"\n : \"white\";\n return (\n <Box\n style={{\n background,\n borderRadius: \"var(--radius-2)\",\n padding: \"var(--space-2) var(--space-3)\",\n }}\n >\n <Text as=\"p\" size=\"2\" weight=\"medium\" style={{ color: foreground }}>\n {title}\n </Text>\n {meta ? (\n <Text as=\"p\" size=\"1\" style={{ color: foreground }}>\n {meta}\n </Text>\n ) : null}\n </Box>\n );\n}\n\n/** The stand-in event the preview transforms. Not the user's data — see\n * `SyncPreviewRailProps.sampleEvent`. */\nexport interface SyncPreviewSampleEvent {\n title: string;\n time: string;\n location: string;\n description: string;\n}\n\n/* Mirrors the platform's own fallback for a sync that carries no tag of its\n * own. The rail is illustrative, so it duplicates the format rather than\n * importing it — a UI library cannot depend on a backend. */\nconst DEFAULT_TAG_LABEL = \"Busy\";\n\nconst DEFAULT_SAMPLE: SyncPreviewSampleEvent = {\n title: \"Gym\",\n time: \"10:00 AM\",\n location: \"Flex Gym on 16th Ave\",\n description: \"Workout notes\",\n};\n\nexport interface SyncPreviewRailProps {\n hasSources: boolean;\n hasTarget: boolean;\n sourceLabel?: string;\n targetLabel?: string;\n showTitle: boolean;\n showDescription: boolean;\n showLocation: boolean;\n /**\n * The sync's tag — the label its blocker events carry on the target calendar.\n * Shown on its own when titles are hidden, and appended to the title when\n * they are shown. Defaults to \"Busy\" for a caller that has no tag to pass.\n */\n tagLabel?: string;\n /**\n * CSS colour the posted block is painted, matching whatever colour the sync\n * writes its events in on the target calendar. Omitted keeps the rail's own\n * amber, which is what a sync that has chosen no colour actually gets — the\n * calendar's default.\n *\n * A colour, not a provider's colour *id*: this library cannot map Google's\n * palette (or anyone's) without depending on a backend, so the caller\n * resolves the id and passes the result.\n */\n accentColor?: string;\n /**\n * The stand-in event the preview transforms. It is illustrative, never the\n * user's real data — override it to match your product's vocabulary.\n *\n * The rail always labels it as an example: an unannounced fabricated event\n * reads as stray fixture data in a real app, which is exactly how this was\n * first reported.\n */\n sampleEvent?: SyncPreviewSampleEvent;\n}\n\n/**\n * Competitor-style SYNC PREVIEW (OneCal):\n * - Source always shows the original event (never rewritten by field toggles).\n * - Target shows the single block we post — title/location/description follow\n * sync settings, and its title always carries the sync's tag (the tag alone\n * when titles are off, `Gym - (Busy)` when they are on).\n */\nexport function SyncPreviewRail({\n hasSources,\n hasTarget,\n sourceLabel,\n targetLabel,\n showTitle,\n showDescription,\n showLocation,\n tagLabel,\n accentColor,\n sampleEvent = DEFAULT_SAMPLE,\n}: SyncPreviewRailProps) {\n // Source = original calendar event (unchanged by sync field toggles).\n const sourceTitle = sampleEvent.title;\n const sourceMeta = [sampleEvent.time, sampleEvent.location].filter(Boolean).join(\" · \");\n\n // Target = the one block we write/post onto the destination calendar.\n /* Blank or whitespace-only counts as unset, matching the platform: a blocker\n * with no title at all would post as \"(no title)\". */\n const tag = tagLabel?.trim() || DEFAULT_TAG_LABEL;\n const postedTitle = showTitle ? `${sampleEvent.title} - (${tag})` : tag;\n const postedMetaParts = [sampleEvent.time].filter(Boolean);\n if (showLocation && sampleEvent.location) postedMetaParts.push(sampleEvent.location);\n if (showDescription && sampleEvent.description) postedMetaParts.push(sampleEvent.description);\n const postedMeta = postedMetaParts.join(\" · \");\n\n return (\n <Flex direction=\"column\" gap=\"4\" style={{ padding: \"var(--space-4)\" }}>\n <Text as=\"p\" className=\"ds-section-label\" style={{ textAlign: \"center\" }}>\n Sync Preview\n </Text>\n\n {/* Without this the fabricated event reads as the user's own data, or as\n stray fixture data left in the build. */}\n <Text as=\"p\" size=\"1\" color=\"gray\" style={{ textAlign: \"center\", marginTop: \"calc(-1 * var(--space-2))\" }}>\n Example event — not from your calendars.\n </Text>\n\n <Box>\n <Text as=\"p\" size=\"1\" color=\"gray\" mb=\"1\">\n Sources\n </Text>\n <Text as=\"p\" size=\"1\" weight=\"medium\" mb=\"2\" truncate style={{ color: \"var(--gray-12)\" }}>\n {hasSources ? sourceLabel || \"Selected sources\" : \"—\"}\n </Text>\n <Box\n style={{\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-2)\",\n padding: \"var(--space-2)\",\n background: \"var(--gray-2)\",\n }}\n >\n <EventChip tone=\"source\" title={sourceTitle} meta={sourceMeta} />\n </Box>\n </Box>\n\n <Box>\n <Text as=\"p\" size=\"1\" color=\"gray\" mb=\"1\">\n Target\n </Text>\n <Text as=\"p\" size=\"1\" weight=\"medium\" mb=\"2\" truncate style={{ color: \"var(--gray-12)\" }}>\n {hasTarget ? targetLabel || \"Selected target\" : \"—\"}\n </Text>\n <Box\n style={{\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-2)\",\n padding: \"var(--space-2)\",\n background: \"var(--gray-2)\",\n }}\n >\n {hasTarget ? (\n <EventChip\n tone=\"synced\"\n title={postedTitle}\n meta={postedMeta}\n {...(accentColor ? { accentColor } : {})}\n />\n ) : (\n <Text as=\"p\" size=\"2\" color=\"gray\">\n Pick one target calendar\n </Text>\n )}\n </Box>\n </Box>\n\n {!hasSources || !hasTarget ? (\n <Text as=\"p\" size=\"1\" color=\"gray\" style={{ textAlign: \"center\" }}>\n Select one or more sources, then one target\n </Text>\n ) : (\n <Text as=\"p\" size=\"1\" color=\"gray\" style={{ textAlign: \"center\" }}>\n Only the highlighted block is posted to the target\n </Text>\n )}\n </Flex>\n );\n}\n","import { Flex, Text } from \"@radix-ui/themes\";\nimport { CheckIcon } from \"@radix-ui/react-icons\";\nimport { iconSize } from \"./icon-size\";\n\nexport interface WizardStepMeta {\n n: string;\n title: string;\n description: string;\n}\n\n/**\n * Full-width OneCal-style stepper.\n * Layout per segment: [circle] title / description — generous padding so\n * labels never collapse into the badge or each other.\n */\nexport function WizardStepper({\n steps,\n current,\n}: {\n steps: readonly WizardStepMeta[];\n current: number;\n}) {\n return (\n <div\n role=\"list\"\n aria-label=\"Wizard progress\"\n style={{\n display: \"flex\",\n /* Three segments abreast stop working long before a phone: at 390px\n each got ~116px, and after the padding and the number badge the\n label had ~50px, so \"Sync Configuration\" broke to one word-fragment\n per line. They wrap to a column instead once they cannot fit. */\n flexWrap: \"wrap\",\n width: \"100%\",\n flexShrink: 0,\n marginBottom: 0,\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-4)\",\n background: \"var(--color-panel-solid)\",\n overflow: \"hidden\",\n }}\n >\n {steps.map((step, i) => {\n const index = i + 1;\n const active = index === current;\n const done = index < current;\n return (\n <Flex\n key={step.n}\n align=\"start\"\n gap=\"3\"\n role=\"listitem\"\n aria-current={active ? \"step\" : undefined}\n style={{\n /* A floor, so the row can actually reach the point where it\n wraps. With `1 1 0` and no minimum the segments just kept\n shrinking and never wrapped at all. */\n flex: \"1 1 calc(3 * var(--space-9) + var(--space-6))\",\n minWidth: \"calc(3 * var(--space-9) + var(--space-6))\",\n paddingTop: \"var(--space-4)\",\n paddingBottom: \"var(--space-4)\",\n paddingLeft: \"var(--space-4)\",\n paddingRight: \"var(--space-4)\",\n marginBottom: \"-1px\",\n borderBottom: active\n ? \"2px solid var(--accent-9)\"\n : \"2px solid transparent\",\n /* The divider lives in tokens.css so it can become a bottom rule\n once the segments stack — an inline right border would stay on\n the right of a full-width row. */\n }}\n >\n <Flex\n align=\"center\"\n justify=\"center\"\n style={{\n width: \"var(--space-6)\",\n height: \"var(--space-6)\",\n borderRadius: \"50%\",\n flexShrink: 0,\n marginTop: \"var(--space-1)\",\n background: done\n ? \"var(--green-9)\"\n : active\n ? \"var(--accent-9)\"\n : \"var(--gray-3)\",\n color: done ? \"white\" : active ? \"var(--accent-contrast)\" : \"var(--gray-11)\",\n }}\n >\n {done ? (\n <CheckIcon style={iconSize(\"--space-3\")} />\n ) : (\n <Text size=\"1\" weight=\"medium\">\n {step.n}\n </Text>\n )}\n </Flex>\n\n <Flex\n direction=\"column\"\n gap=\"1\"\n style={{ minWidth: 0, flex: 1, paddingTop: \"var(--space-1)\" }}\n >\n <Text\n size=\"2\"\n weight=\"medium\"\n style={{\n color: active || done ? \"var(--gray-12)\" : \"var(--gray-10)\",\n lineHeight: \"var(--line-height-2)\",\n }}\n >\n {step.title}\n </Text>\n <Text\n size=\"1\"\n color=\"gray\"\n style={{ lineHeight: \"var(--line-height-1)\" }}\n >\n {step.description}\n </Text>\n </Flex>\n </Flex>\n );\n })}\n </div>\n );\n}\n","import { WizardStepper } from \"./WizardStepper\";\n\nconst FIRST_RUN_STEPS = [\n { n: \"01\", title: \"Connect\", description: \"Connect your calendar account\" },\n { n: \"02\", title: \"Calendars\", description: \"Import at least 2 calendars\" },\n { n: \"03\", title: \"Sync\", description: \"Set up your first sync\" },\n] as const;\n\n/** Guided first-run stepper on /calendar — OneCal numbered steps, our DS. */\nexport function OnboardingStepper({ current }: { current: number }) {\n return <WizardStepper steps={FIRST_RUN_STEPS} current={current} />;\n}\n\n/** @deprecated Prefer OnboardingStepper. */\nexport function OnboardingStepDots({ current, total = 3 }: { current: number; total?: number }) {\n void total;\n return <OnboardingStepper current={current} />;\n}\n\nexport default OnboardingStepper;\n","import dayjs from \"dayjs\";\nimport { Flex, Grid, IconButton, Text } from \"@radix-ui/themes\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"@radix-ui/react-icons\";\n\nconst WEEKDAY_LABELS = [\"S\", \"M\", \"T\", \"W\", \"T\", \"F\", \"S\"];\n\nexport interface MiniMonthPickerProps {\n cursor: Date;\n onSelect: (d: Date) => void;\n /** \"Today\" reference for the amber-ring marker. Defaults to the real\n * current date — pass a fixed date for demo/mock consistency. */\n today?: Date;\n}\n\n/** Compact date-jump picker for the calendar sidebar — OneCal-style layout\n * (month nav + 7-col day grid, selected day filled), rebuilt on our own\n * tokens/colors (amber selection, not blue). Clicking a day jumps the main\n * grid's cursor to that date. */\nexport function MiniMonthPicker({ cursor, onSelect, today = new Date() }: MiniMonthPickerProps) {\n const monthStart = dayjs(cursor).startOf(\"month\");\n const gridStart = monthStart.startOf(\"week\");\n const days = Array.from({ length: 42 }, (_, i) => gridStart.add(i, \"day\"));\n\n return (\n <div>\n <Flex align=\"center\" justify=\"between\" mb=\"2\">\n <Text size=\"2\" weight=\"medium\" style={{ color: \"var(--gray-12)\" }}>\n {monthStart.format(\"MMMM YYYY\")}\n </Text>\n <Flex gap=\"1\">\n <IconButton\n size=\"1\"\n variant=\"ghost\"\n color=\"gray\"\n aria-label=\"Previous month\"\n onClick={() => onSelect(dayjs(cursor).subtract(1, \"month\").toDate())}\n >\n <ChevronLeftIcon />\n </IconButton>\n <IconButton\n size=\"1\"\n variant=\"ghost\"\n color=\"gray\"\n aria-label=\"Next month\"\n onClick={() => onSelect(dayjs(cursor).add(1, \"month\").toDate())}\n >\n <ChevronRightIcon />\n </IconButton>\n </Flex>\n </Flex>\n <Grid columns=\"7\" gap=\"1\" mb=\"1\">\n {WEEKDAY_LABELS.map((w, i) => (\n <Text key={i} size=\"1\" color=\"gray\" align=\"center\">\n {w}\n </Text>\n ))}\n </Grid>\n <Grid columns=\"7\" gap=\"1\" justify=\"center\" align=\"center\" style={{ justifyItems: \"center\" }}>\n {days.map((d) => {\n const isToday = d.isSame(today, \"day\");\n const isSelected = d.isSame(cursor, \"day\");\n const isOffMonth = !d.isSame(monthStart, \"month\");\n return (\n <button\n key={d.format(\"YYYY-MM-DD\")}\n type=\"button\"\n onClick={() => onSelect(d.toDate())}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"var(--space-5)\",\n height: \"var(--space-5)\",\n boxSizing: \"border-box\",\n flexShrink: 0,\n padding: 0,\n borderRadius: \"50%\",\n border: isToday && !isSelected ? \"1.5px solid var(--accent-9)\" : \"none\",\n cursor: \"pointer\",\n background: isSelected ? \"var(--accent-9)\" : \"transparent\",\n color: isSelected\n ? \"var(--accent-contrast)\"\n : isOffMonth\n ? \"var(--gray-11)\"\n : isToday\n ? \"var(--accent-11)\"\n : \"var(--gray-12)\",\n fontWeight: isToday || isSelected ? 500 : 400,\n fontSize: \"var(--font-size-1)\",\n fontFamily: \"var(--font-poppins)\",\n }}\n >\n {d.format(\"D\")}\n </button>\n );\n })}\n </Grid>\n </div>\n );\n}\n","import { useState } from \"react\";\nimport { Dialog, Flex, Text, Button, IconButton, Badge, Separator, Box } from \"@radix-ui/themes\";\nimport { Cross2Icon, PlusIcon, ReloadIcon } from \"@radix-ui/react-icons\";\nimport { ProviderIcon } from \"./ProviderIcon\";\nimport { CardFooter } from \"./CardFooter\";\nimport { IconTile } from \"./IconTile\";\nimport { ImportCalendarsDialog } from \"./ImportCalendarsDialog\";\nimport type { CalendarAccount, CalendarAccountCalendar } from \"./calendar-types\";\nimport { layout } from \"./layout-tokens\";\nimport { iconSize } from \"./icon-size\";\n\nexport interface AccountCalendarsDialogProps {\n /** The account to show, resolved by the app — null closes the dialog. */\n account: CalendarAccount | null;\n /** The account's full available-calendars catalog (may include calendars\n * not currently imported) — used by \"Change calendars\". */\n catalog: CalendarAccount | null;\n onOpenChange: (open: boolean) => void;\n onRemoveCalendar: (account: CalendarAccount, calendar: CalendarAccountCalendar) => void;\n onSaveCalendars: (account: CalendarAccount, selectedCalendars: CalendarAccountCalendar[]) => void;\n onReconnect?: (accountId: string) => void;\n}\n\n/** Account detail popup — view calendars, remove one, or change which are imported. */\nexport function AccountCalendarsDialog({\n account,\n catalog,\n onOpenChange,\n onRemoveCalendar,\n onSaveCalendars,\n onReconnect,\n}: AccountCalendarsDialogProps) {\n const [managing, setManaging] = useState(false);\n const needsReauth = account?.authStatus === \"reauth\";\n const hasFailed = account?.authStatus === \"failed\";\n\n function handleManageSave(selectedCalendarIds: string[]) {\n if (!account || !catalog) return;\n const selected = new Set(selectedCalendarIds);\n onSaveCalendars(\n account,\n catalog.calendars.filter((c) => selected.has(c.id))\n );\n setManaging(false);\n }\n\n return (\n <>\n <Dialog.Root\n open={!!account && !managing}\n onOpenChange={(open) => {\n if (!open) onOpenChange(false);\n }}\n >\n <Dialog.Content maxWidth={layout.dialogMd}>\n {account && (\n <>\n <Flex align=\"center\" gap=\"3\" mb=\"1\">\n <IconTile size=\"var(--space-6)\">\n <ProviderIcon provider={account.provider} />\n </IconTile>\n <Box style={{ minWidth: 0, flex: 1 }}>\n <Flex align=\"center\" gap=\"2\" mb=\"1\" style={{ minWidth: 0 }}>\n <Dialog.Title size=\"4\" weight=\"medium\" mb=\"0\" truncate style={{ minWidth: 0 }}>\n {account.displayName}\n </Dialog.Title>\n {needsReauth && (\n <Badge color=\"amber\" variant=\"soft\" size=\"1\" radius=\"full\" style={{ flexShrink: 0 }}>\n Needs reconnect\n </Badge>\n )}\n {hasFailed && (\n <Badge color=\"red\" variant=\"soft\" size=\"1\" radius=\"full\" style={{ flexShrink: 0 }}>\n Connection failed\n </Badge>\n )}\n </Flex>\n <Dialog.Description size=\"2\" color=\"gray\" mb=\"0\">\n {account.email}\n </Dialog.Description>\n </Box>\n </Flex>\n\n {(needsReauth || hasFailed) && onReconnect && (\n <Button\n size=\"2\"\n variant=\"soft\"\n color={hasFailed ? \"red\" : \"amber\"}\n mt=\"3\"\n onClick={() => onReconnect(account.id)}\n >\n <ReloadIcon />\n Reconnect\n </Button>\n )}\n\n <Separator size=\"4\" my=\"4\" />\n\n <Flex align=\"center\" justify=\"between\" gap=\"3\" mb=\"3\">\n <Text as=\"p\" className=\"ds-section-label\" mb=\"0\">\n Calendars\n </Text>\n {catalog && catalog.calendars.length > 0 && (\n <Button size=\"1\" variant=\"soft\" color=\"gray\" onClick={() => setManaging(true)}>\n <PlusIcon style={iconSize(\"--space-3\")} />\n Change calendars\n </Button>\n )}\n </Flex>\n\n <Flex\n direction=\"column\"\n style={{\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-3)\",\n overflow: \"hidden\",\n background: \"var(--color-panel-solid)\",\n }}\n >\n {account.calendars.length === 0 ? (\n <Text size=\"2\" color=\"gray\" style={{ padding: \"var(--space-4)\" }}>\n No calendars imported.\n </Text>\n ) : (\n account.calendars.map((cal, idx) => (\n <Flex\n key={cal.id}\n align=\"center\"\n gap=\"3\"\n className=\"data-table-row\"\n style={{\n padding: \"var(--space-3) var(--space-4)\",\n minHeight: \"var(--space-7)\",\n borderTop: idx > 0 ? \"1px solid var(--gray-4)\" : undefined,\n }}\n >\n <Box\n aria-hidden\n style={{\n width: \"var(--space-2)\",\n height: \"var(--space-2)\",\n borderRadius: \"50%\",\n background: cal.colorToken,\n flexShrink: 0,\n }}\n />\n <Text size=\"2\" truncate style={{ flex: 1, minWidth: 0, color: \"var(--gray-12)\" }}>\n {cal.name}\n {cal.isPrimary && (\n <Text size=\"1\" color=\"gray\">\n {\" \"}\n · Primary\n </Text>\n )}\n </Text>\n <IconButton\n variant=\"ghost\"\n color=\"gray\"\n size=\"1\"\n aria-label={`Remove ${cal.name}`}\n onClick={() => onRemoveCalendar(account, cal)}\n >\n <Cross2Icon />\n </IconButton>\n </Flex>\n ))\n )}\n </Flex>\n\n <CardFooter justify=\"end\">\n <Dialog.Close>\n <Button size=\"2\" variant=\"soft\" color=\"gray\">\n Close\n </Button>\n </Dialog.Close>\n </CardFooter>\n </>\n )}\n </Dialog.Content>\n </Dialog.Root>\n\n <ImportCalendarsDialog\n account={managing && catalog ? catalog : null}\n initiallySelectedIds={account?.calendars.map((c) => c.id)}\n title=\"Change calendars\"\n description=\"Choose which calendars to keep on this account.\"\n confirmLabel=\"Save calendars\"\n onOpenChange={(open) => {\n if (!open) setManaging(false);\n }}\n onImport={handleManageSave}\n />\n </>\n );\n}\n","import { useMemo } from \"react\";\nimport dayjs from \"dayjs\";\nimport { Calendar, dayjsLocalizer, Views, type ToolbarProps, type View } from \"react-big-calendar\";\nimport \"react-big-calendar/lib/css/react-big-calendar.css\";\nimport \"./big-calendar-overrides.css\";\nimport { Text } from \"@radix-ui/themes\";\nimport { findCalendar, type CalendarAccount, type ResolvedBlock } from \"./calendar-types\";\nimport { CalendarToolbar } from \"./CalendarToolbar\";\nimport { CalendarDayHeader } from \"./CalendarDayHeader\";\n\nconst localizer = dayjsLocalizer(dayjs);\n\n/** Default scroll position for week view — opens on working hours instead\n * of midnight, so the grid isn't mostly dead space on load. */\nconst SCROLL_TO_TIME = new Date(1970, 0, 1, 8, 0, 0);\n\ninterface CalendarEvent {\n id: string;\n title: string;\n start: Date;\n end: Date;\n resource: ResolvedBlock;\n}\n\nexport interface BigCalendarViewProps {\n blocks: ResolvedBlock[];\n view: \"week\" | \"month\";\n onViewChange: (v: \"week\" | \"month\") => void;\n date: Date;\n onNavigate: (d: Date) => void;\n /** Connected accounts — used to resolve each block's calendar color. */\n accounts: CalendarAccount[];\n /** \"Today\" reference for RBC's own now-marker and CalendarDayHeader's\n * circle. Defaults to the real current date — pass a fixed date for\n * demo/mock consistency (RBC's own today and this component's header\n * must agree, or two conflicting \"today\" indicators appear). */\n today?: Date;\n}\n\n/** Real hour-grid week/month calendar via react-big-calendar (React 19\n * compatible), restyled with our Radix tokens instead of its default CSS —\n * see big-calendar-overrides.css. Renders our own event card (title, time\n * range, location) via `components.event`, colored per calendar via\n * `eventPropGetter`. */\nexport function BigCalendarView({\n blocks,\n view,\n onViewChange,\n date,\n onNavigate,\n accounts,\n today = new Date(),\n}: BigCalendarViewProps) {\n const events = useMemo<CalendarEvent[]>(\n () =>\n blocks.map((b) => {\n const start = new Date(b.date);\n start.setHours(b.startHour, b.startMinute, 0, 0);\n const end = new Date(b.date);\n end.setHours(b.endHour, b.endMinute, 0, 0);\n return { id: b.id, title: b.title, start, end, resource: b };\n }),\n [blocks]\n );\n\n return (\n <div className=\"rbc-radix-scope\" style={{ height: \"100%\", containerType: \"inline-size\" }}>\n <Calendar\n localizer={localizer}\n events={events}\n view={view === \"week\" ? Views.WEEK : Views.MONTH}\n onView={(v) => onViewChange(v === Views.MONTH ? \"month\" : \"week\")}\n date={date}\n onNavigate={onNavigate}\n views={[Views.WEEK, Views.MONTH]}\n toolbar\n popup\n scrollToTime={SCROLL_TO_TIME}\n enableAutoScroll\n getNow={() => today}\n // Suppress RBC's native browser tooltip (title attribute) — our\n // event card already shows time/title/location, so the tooltip\n // just duplicates it in an ugly overlapping OS-native popup.\n tooltipAccessor={null}\n eventPropGetter={(event: CalendarEvent) => {\n const found = findCalendar(accounts, event.resource.calendarId);\n const color = found?.calendar.colorToken ?? \"var(--gray-8)\";\n // Month view uses a dot + plain text row (see components.month.event\n // below), not a solid-fill block — no background/border there.\n if (view === \"month\") {\n return { style: { background: \"transparent\", border: \"none\", boxShadow: \"none\" } };\n }\n return {\n style: {\n backgroundColor: color,\n border: \"none\",\n },\n };\n }}\n components={{\n // Cast: our toolbar/header don't depend on the event's concrete\n // shape, but RBC's Components<TEvent> is invariant in TEvent.\n toolbar: CalendarToolbar as React.ComponentType<ToolbarProps<CalendarEvent, object>>,\n week: {\n header: (headerProps) => <CalendarDayHeader {...headerProps} today={today} />,\n // Week view has real vertical room per slot — a richer card\n // (title + time range + location) fits.\n event: ({ event }: { event: CalendarEvent }) => {\n const durationMin = (event.end.getTime() - event.start.getTime()) / 60000;\n const showLocation = durationMin >= 60;\n const showTimeRange = durationMin >= 30;\n return (\n <div>\n <Text size=\"1\" weight=\"medium\" style={{ color: \"white\", display: \"block\" }} truncate>\n {event.title}\n </Text>\n {showTimeRange && (\n <Text size=\"1\" style={{ color: \"rgba(255,255,255,0.85)\", display: \"block\" }} truncate>\n {dayjs(event.start).format(\"h:mm A\")} – {dayjs(event.end).format(\"h:mm A\")}\n </Text>\n )}\n {showLocation && event.resource.location && (\n <Text size=\"1\" style={{ color: \"rgba(255,255,255,0.85)\", display: \"block\" }} truncate>\n {event.resource.location}\n </Text>\n )}\n </div>\n );\n },\n },\n // Month view rows are short by design (multiple weeks must fit on\n // screen) — the week view's multi-line colored-block card\n // overflowed every cell regardless of duration. Each event is a\n // small tinted chip (dot + compact time + title) rather than a\n // bare text row, so events stay visually distinct while still\n // dense enough to fit several per day.\n month: {\n event: ({ event }: { event: CalendarEvent }) => {\n const found = findCalendar(accounts, event.resource.calendarId);\n const color = found?.calendar.colorToken ?? \"var(--gray-8)\";\n return (\n <Text\n size=\"1\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-1)\",\n color: \"var(--gray-12)\",\n background: `color-mix(in srgb, ${color} 28%, transparent)`,\n borderRadius: \"var(--radius-2)\",\n padding: \"var(--space-1) var(--space-2)\",\n }}\n truncate\n >\n <span\n aria-hidden\n style={{\n width: \"var(--space-2)\",\n height: \"var(--space-2)\",\n borderRadius: \"50%\",\n background: color,\n flexShrink: 0,\n }}\n />\n <span style={{ overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>\n {dayjs(event.start).format(\"H:mm\")} {event.title}\n </span>\n </Text>\n );\n },\n },\n }}\n />\n </div>\n );\n}\n\nexport type { View };\n","import { Dialog, Flex, Text, Button, Separator, Badge } from \"@radix-ui/themes\";\nimport { findCalendar, type CalendarAccount, type CalendarSync, type SyncStatus } from \"./calendar-types\";\nimport { layout } from \"./layout-tokens\";\nimport { CardFooter } from \"./CardFooter\";\n\nconst STATUS_META: Record<SyncStatus, { label: string; color: \"green\" | \"amber\" | \"red\" }> = {\n synced: { label: \"Synced\", color: \"green\" },\n syncing: { label: \"Syncing…\", color: \"amber\" },\n error: { label: \"Error\", color: \"red\" },\n};\n\nexport interface SyncDetailsDialogProps {\n sync: CalendarSync | null;\n /** Connected accounts — used to resolve source/target calendar names. */\n accounts: CalendarAccount[];\n onOpenChange: (open: boolean) => void;\n onEdit: (syncId: string) => void;\n}\n\n/** OneCal-style View Details — flat label/value summary of sync config. */\nexport function SyncDetailsDialog({ sync, accounts, onOpenChange, onEdit }: SyncDetailsDialogProps) {\n const calendarsSummary = sync\n ? (() => {\n const sources = sync.sourceCalendarIds\n .map((cid) => findCalendar(accounts, cid)?.calendar.name)\n .filter((n): n is string => Boolean(n));\n const target = findCalendar(accounts, sync.targetCalendarId)?.calendar.name ?? \"—\";\n return `${sources.join(\", \") || \"—\"} → ${target}`;\n })()\n : \"\";\n\n return (\n <Dialog.Root open={!!sync} onOpenChange={onOpenChange}>\n <Dialog.Content maxWidth={layout.dialogMd}>\n {sync && (\n <>\n <Flex align=\"center\" justify=\"between\" mb=\"1\">\n <Dialog.Title size=\"4\" mb=\"0\">\n {sync.name}\n </Dialog.Title>\n <Badge color={STATUS_META[sync.status].color} variant=\"soft\" size=\"1\" radius=\"full\">\n {STATUS_META[sync.status].label}\n </Badge>\n </Flex>\n <Dialog.Description size=\"2\" color=\"gray\" mb=\"4\">\n Sync configuration\n </Dialog.Description>\n\n <Flex direction=\"column\" gap=\"3\">\n <DetailRow label=\"Calendars\">{calendarsSummary}</DetailRow>\n <DetailRow label=\"Sources\">\n <Flex direction=\"column\" gap=\"1\" align=\"end\">\n {sync.sourceCalendarIds.map((cid) => {\n const found = findCalendar(accounts, cid);\n if (!found) return null;\n return (\n <Flex key={cid} direction=\"column\" align=\"end\">\n <Text size=\"2\" weight=\"medium\" style={{ color: \"var(--gray-12)\" }}>\n {found.calendar.name}\n </Text>\n <Text size=\"1\" color=\"gray\">{found.account.email}</Text>\n </Flex>\n );\n }) || \"—\"}\n </Flex>\n </DetailRow>\n <DetailRow label=\"Target\">\n {(() => {\n const found = findCalendar(accounts, sync.targetCalendarId);\n if (!found) return \"—\";\n return (\n <Flex direction=\"column\" align=\"end\">\n <Text size=\"2\" weight=\"medium\" style={{ color: \"var(--gray-12)\" }}>\n {found.calendar.name}\n </Text>\n <Text size=\"1\" color=\"gray\">{found.account.email}</Text>\n </Flex>\n );\n })()}\n </DetailRow>\n <DetailRow label=\"Last synced\">{sync.lastSyncedLabel ?? \"—\"}</DetailRow>\n </Flex>\n\n <Separator size=\"4\" my=\"4\" />\n\n <Text as=\"p\" size=\"1\" weight=\"medium\" color=\"gray\" mb=\"3\" style={{ letterSpacing: \"0.04em\" }}>\n WHAT TO SHOW\n </Text>\n <Flex direction=\"column\" gap=\"3\">\n <DetailRow label=\"Tag\">{sync.tagLabel?.trim() || \"Busy\"}</DetailRow>\n <DetailRow label=\"Event titles\">{sync.showTitle ? \"Shown\" : \"Hidden\"}</DetailRow>\n <DetailRow label=\"Event description\">{sync.showDescription ? \"Shown\" : \"Hidden\"}</DetailRow>\n <DetailRow label=\"Event location\">{sync.showLocation ? \"Shown\" : \"Hidden\"}</DetailRow>\n </Flex>\n\n <CardFooter justify=\"between\">\n <Dialog.Close>\n <Button size=\"2\" variant=\"soft\" color=\"gray\">\n Close\n </Button>\n </Dialog.Close>\n <Button size=\"2\" className=\"btn-amber-primary\" onClick={() => onEdit(sync.id)}>\n Edit sync\n </Button>\n </CardFooter>\n </>\n )}\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nfunction DetailRow({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <Flex align=\"baseline\" justify=\"between\" gap=\"4\">\n <Text size=\"2\" color=\"gray\" style={{ flexShrink: 0 }}>\n {label}\n </Text>\n <Text size=\"2\" weight=\"medium\" align=\"right\" style={{ color: \"var(--gray-12)\" }}>\n {children}\n </Text>\n </Flex>\n );\n}\n","import { useState } from \"react\";\nimport type { CalendarAccount, CalendarProvider } from \"./calendar-types\";\n\nexport interface UseConnectAccountOptions {\n /** Currently connected accounts — passed to `connectProvider` so it can\n * discover an account not already connected. */\n accounts: CalendarAccount[];\n /** Performs the actual \"discover an account for this provider\" round\n * trip (real OAuth flow in a real app; the app's own mock/API layer\n * today). Resolves null when no more accounts are available for that\n * provider — not an error, `exhausted` distinguishes the two. */\n connectProvider: (provider: CalendarProvider, connectedAccountIds: string[]) => Promise<CalendarAccount | null>;\n /** Called once the user confirms which calendars to import for the\n * newly-discovered account. */\n onAccountAdded: (account: CalendarAccount) => void;\n /** Called after `onAccountAdded` — e.g. navigate to the accounts list. */\n onImported?: () => void;\n}\n\n/** Shared \"discover account → import calendars\" flow behind connecting a\n * provider. Click a provider → brief spinner (no separate consent page) →\n * ImportCalendarsDialog opens with that account's calendars → confirming\n * adds the account and calls `onImported`. */\nexport function useConnectAccount({ accounts, connectProvider, onAccountAdded, onImported }: UseConnectAccountOptions) {\n const [connectingProvider, setConnectingProvider] = useState<CalendarProvider | null>(null);\n const [pendingAccount, setPendingAccount] = useState<CalendarAccount | null>(null);\n const [failedProvider, setFailedProvider] = useState<CalendarProvider | null>(null);\n // Distinguishes \"every mock account for this provider is already\n // connected\" (not a real failure, retry can't help) from an actual\n // connection error (retry might work) — the two need different copy.\n const [exhausted, setExhausted] = useState(false);\n\n function connect(provider: CalendarProvider) {\n if (connectingProvider) return;\n setFailedProvider(null);\n setExhausted(false);\n setConnectingProvider(provider);\n // Pick an account for this provider not already connected, so\n // connecting twice discovers a second account rather than a no-op.\n const connectedIds = accounts.map((a) => a.id);\n connectProvider(provider, connectedIds)\n .then((account) => {\n setConnectingProvider(null);\n // No account came back — every mock account for this provider is\n // already connected. Surface a message instead of silently doing\n // nothing (previously the spinner would just stop with zero\n // feedback).\n if (account) {\n setPendingAccount(account);\n } else {\n setFailedProvider(provider);\n setExhausted(true);\n }\n })\n .catch(() => {\n setConnectingProvider(null);\n setFailedProvider(provider);\n setExhausted(false);\n });\n }\n\n function confirmImport(selectedCalendarIds: string[]) {\n if (!pendingAccount) return;\n const selected = new Set(selectedCalendarIds);\n onAccountAdded({\n ...pendingAccount,\n calendars: pendingAccount.calendars.filter((c) => selected.has(c.id)),\n });\n setPendingAccount(null);\n onImported?.();\n }\n\n return {\n connectingProvider,\n pendingAccount,\n failedProvider,\n exhausted,\n connect,\n confirmImport,\n cancelImport: () => setPendingAccount(null),\n dismissError: () => setFailedProvider(null),\n };\n}\n","import type { ReactNode } from \"react\";\nimport { Box, DropdownMenu, Button, Flex, Text } from \"@radix-ui/themes\";\nimport { PlusIcon } from \"@radix-ui/react-icons\";\nimport { ProviderIcon } from \"./ProviderIcon\";\nimport { IconTile } from \"./IconTile\";\nimport { Toast } from \"./Toast\";\nimport { PROVIDER_META } from \"./ConnectProviderList\";\nimport { ImportCalendarsDialog } from \"./ImportCalendarsDialog\";\nimport { useConnectAccount, type UseConnectAccountOptions } from \"./useConnectAccount\";\nimport type { CalendarProvider } from \"./calendar-types\";\nimport { iconSize } from \"./icon-size\";\n\nexport interface AddAccountMenuProps extends UseConnectAccountOptions {\n variant?: \"button\" | \"tile\";\n /** Optional custom trigger; overrides `variant`. Must be a single element. */\n trigger?: ReactNode;\n}\n\n/** \"+ Connect Account\" — button or dashed tile; opens provider picker then\n * ImportCalendarsDialog. Trigger must be a single React element (Radix\n * Themes DropdownMenu.Trigger always uses asChild). */\nexport function AddAccountMenu({\n variant = \"button\",\n trigger,\n accounts,\n connectProvider,\n onAccountAdded,\n onImported,\n}: AddAccountMenuProps) {\n const { pendingAccount, failedProvider, exhausted, connect, confirmImport, cancelImport, dismissError } =\n useConnectAccount({ accounts, connectProvider, onAccountAdded, onImported });\n const providers: CalendarProvider[] = [\"google\", \"microsoft\"];\n\n const defaultTrigger =\n variant === \"tile\" ? (\n <button\n type=\"button\"\n className=\"connect-account-tile\"\n aria-label=\"Connect Account\"\n >\n <PlusIcon style={iconSize(\"--space-4\")} />\n Connect Account\n </button>\n ) : (\n <Button size=\"2\" className=\"btn-amber-primary\">\n <PlusIcon style={iconSize(\"--space-4\")} />\n Connect Account\n </Button>\n );\n\n const menu = (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>{trigger ?? defaultTrigger}</DropdownMenu.Trigger>\n <DropdownMenu.Content\n align=\"start\"\n // Fit the provider rows — don't stretch to the wide connect tile or a dialog width.\n style={{ width: \"max-content\", minWidth: \"max-content\" }}\n >\n {providers.map((provider) => {\n const meta = PROVIDER_META[provider];\n return (\n <DropdownMenu.Item\n key={provider}\n onSelect={() => connect(provider)}\n // Themes menu items default to a single-line fixed height; that\n // clips icon + title + description into a broken stack.\n style={{\n height: \"auto\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n padding: \"var(--space-2) var(--space-3)\",\n }}\n >\n <IconTile size=\"var(--space-6)\">\n <ProviderIcon provider={provider} />\n </IconTile>\n <Flex direction=\"column\" gap=\"1\" style={{ flexShrink: 0 }}>\n <Text size=\"2\" weight=\"medium\" style={{ color: \"var(--gray-12)\" }}>\n {meta.label}\n </Text>\n <Text size=\"1\" color=\"gray\">\n {meta.description}\n </Text>\n </Flex>\n </DropdownMenu.Item>\n );\n })}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n\n return (\n <>\n {variant === \"tile\" && !trigger ? (\n <Box style={{ width: \"100%\", minWidth: 0 }}>\n {menu}\n </Box>\n ) : (\n menu\n )}\n\n <ImportCalendarsDialog\n account={pendingAccount}\n onOpenChange={(open) => !open && cancelImport()}\n onImport={confirmImport}\n />\n\n {failedProvider && (\n <Toast\n msg={\n exhausted\n ? `No more ${PROVIDER_META[failedProvider].label} accounts available to connect.`\n : `Couldn't connect ${PROVIDER_META[failedProvider].label}. Please try again.`\n }\n color=\"red\"\n onDone={dismissError}\n />\n )}\n </>\n );\n}\n","import { Card, Flex, Text, Heading } from \"@radix-ui/themes\";\nimport { CalendarIcon } from \"@radix-ui/react-icons\";\nimport { ImportCalendarsDialog } from \"./ImportCalendarsDialog\";\nimport { ConnectProviderList } from \"./ConnectProviderList\";\nimport { useConnectAccount, type UseConnectAccountOptions } from \"./useConnectAccount\";\nimport { layout } from \"./layout-tokens\";\nimport { IconTile } from \"./IconTile\";\nimport { iconSize } from \"./icon-size\";\nimport { headingSize } from \"./heading-scale\";\n\nexport type ConnectProviderRowsProps = UseConnectAccountOptions;\n\n/** Connect-first UI — used on Manage Syncs (section home) and Accounts when\n * no accounts are connected yet. Fills the content slot and centers as one\n * composition; inner spacing matches Home empty cards (`py=\"6\"`, `gap=\"3\"`). */\nexport function ConnectProviderRows({ accounts, connectProvider, onAccountAdded, onImported }: ConnectProviderRowsProps) {\n const { connectingProvider, pendingAccount, failedProvider, exhausted, connect, confirmImport, cancelImport } =\n useConnectAccount({ accounts, connectProvider, onAccountAdded, onImported });\n\n return (\n <Flex\n direction=\"column\"\n align=\"center\"\n justify=\"center\"\n style={{ width: \"100%\", flex: 1, minHeight: 0 }}\n >\n <Card style={{ width: \"100%\", maxWidth: layout.providerChooserMax }}>\n <Flex\n direction=\"column\"\n align=\"center\"\n justify=\"center\"\n gap=\"3\"\n py=\"6\"\n px=\"3\"\n style={{ width: \"100%\", textAlign: \"center\" }}\n >\n <IconTile>\n <CalendarIcon\n style={{ ...iconSize(\"--space-5\"), color: \"var(--gray-7)\" }}\n />\n </IconTile>\n\n <Heading as=\"h2\" size={headingSize.h2} weight=\"medium\">\n {accounts.length > 0 ? \"Connect another account\" : \"Connect your first account\"}\n </Heading>\n <Text as=\"p\" size=\"2\" color=\"gray\">\n {accounts.length > 0\n ? \"Add another Google or Microsoft account, then choose which calendars to import.\"\n : \"Connect a Google or Microsoft account to import calendars for sync.\"}\n </Text>\n\n <Flex direction=\"column\" style={{ width: \"100%\" }} mt=\"3\">\n <ConnectProviderList\n connectingProvider={connectingProvider}\n failedProvider={failedProvider}\n exhausted={exhausted}\n onConnect={connect}\n />\n </Flex>\n </Flex>\n </Card>\n\n <ImportCalendarsDialog\n account={pendingAccount}\n onOpenChange={(open) => !open && cancelImport()}\n onImport={confirmImport}\n />\n </Flex>\n );\n}\n","import { useEffect, useMemo, useState } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { Box, Checkbox, Flex, Separator, Text } from \"@radix-ui/themes\";\nimport { ChevronDownIcon, GearIcon, HamburgerMenuIcon } from \"@radix-ui/react-icons\";\nimport { findCalendar, type CalendarAccount, type ResolvedBlock } from \"./calendar-types\";\nimport { layout } from \"./layout-tokens\";\nimport { ProviderIcon } from \"./ProviderIcon\";\nimport { MiniMonthPicker } from \"./MiniMonthPicker\";\nimport { BigCalendarView } from \"./BigCalendarView\";\nimport { iconSize } from \"./icon-size\";\n\nexport interface CalendarMergedViewProps {\n accounts: CalendarAccount[];\n view: \"week\" | \"month\";\n setView: (v: \"week\" | \"month\") => void;\n hideClones: boolean;\n setHideClones: (v: boolean) => void;\n /** Union of source calendar ids across all syncs, excluding paused accounts. */\n mergedCalendarIds: Set<string>;\n /** mergedCalendarIds minus the user's legend hide toggles. */\n visibleCalendarIds: Set<string>;\n toggleCalendarVisible: (calendarId: string) => void;\n getVisibleBlocksInRange: (start: Date, end: Date) => ResolvedBlock[];\n /** \"Manage accounts\" link at the bottom of the legend rail. */\n manageAccountsHref: string;\n /** \"Today\" reference — defaults to the real current date; pass a fixed\n * date for demo/mock consistency (also forwarded to BigCalendarView so\n * the two don't disagree on what \"today\" is). */\n today?: Date;\n}\n\n/** OneCal Calendar View chrome for a read-only merged grid — left rail\n * (mini month picker + account-grouped visibility legend + hide synced +\n * manage) + week/month hour grid. All calendar data and app navigation are\n * supplied by the caller; this component owns only its own UI state\n * (cursor date, collapsed account groups, narrow-viewport sidebar toggle). */\nexport function CalendarMergedView({\n accounts,\n view,\n setView,\n hideClones,\n setHideClones,\n mergedCalendarIds,\n visibleCalendarIds,\n toggleCalendarVisible,\n getVisibleBlocksInRange,\n manageAccountsHref,\n today = new Date(),\n}: CalendarMergedViewProps) {\n const [cursor, setCursor] = useState<Date>(today);\n const [collapsedAccounts, setCollapsedAccounts] = useState<Set<string>>(new Set());\n const [isNarrow, setIsNarrow] = useState(() => typeof window !== \"undefined\" && window.innerWidth < 900);\n const [sidebarOpen, setSidebarOpen] = useState(false);\n\n useEffect(() => {\n function onResize() {\n setIsNarrow(window.innerWidth < 900);\n }\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n const rangeStart = useMemo(() => {\n const d = new Date(cursor);\n d.setDate(d.getDate() - 42);\n return d;\n }, [cursor]);\n const rangeEnd = useMemo(() => {\n const d = new Date(cursor);\n d.setDate(d.getDate() + 42);\n return d;\n }, [cursor]);\n\n const blocks = getVisibleBlocksInRange(rangeStart, rangeEnd);\n\n /* Group merged calendars by their owning account, preserving account order. */\n const accountGroups = useMemo(() => {\n const groups: { accountId: string; calendarIds: string[] }[] = [];\n const index = new Map<string, number>();\n for (const calId of mergedCalendarIds) {\n const found = findCalendar(accounts, calId);\n if (!found) continue;\n let i = index.get(found.account.id);\n if (i === undefined) {\n i = groups.length;\n index.set(found.account.id, i);\n groups.push({ accountId: found.account.id, calendarIds: [] });\n }\n groups[i].calendarIds.push(calId);\n }\n return groups;\n }, [mergedCalendarIds, accounts]);\n\n function toggleAccountCollapsed(accountId: string) {\n setCollapsedAccounts((prev) => {\n const next = new Set(prev);\n if (next.has(accountId)) next.delete(accountId);\n else next.add(accountId);\n return next;\n });\n }\n\n return (\n <Flex\n gap=\"5\"\n align=\"start\"\n direction={isNarrow ? \"column\" : \"row\"}\n flexGrow=\"1\"\n minHeight=\"0\"\n height=\"100%\"\n >\n {/* Left rail — mini month picker + OneCal calendar sidebar density.\n Below 900px it's a toggleable panel rather than a fixed column, so\n the calendar grid stays primary instead of being pushed below a\n full legend on narrow viewports. */}\n {(!isNarrow || sidebarOpen) && (\n <Box\n minWidth={isNarrow ? undefined : layout.sidebarColMin}\n p=\"4\"\n maxHeight=\"100%\"\n style={{\n flex: isNarrow ? \"1 1 100%\" : `0 0 ${layout.sidebarColBasis}`,\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-4)\",\n background: \"var(--color-panel-solid)\",\n boxShadow: \"var(--shadow-card)\",\n overflow: \"auto\",\n }}\n >\n <MiniMonthPicker cursor={cursor} onSelect={setCursor} today={today} />\n\n <Separator size=\"4\" my=\"3\" />\n\n <Text\n as=\"p\"\n size=\"1\"\n weight=\"medium\"\n color=\"gray\"\n mb=\"3\"\n style={{ letterSpacing: \"0.04em\" }}\n >\n CALENDARS\n </Text>\n <Flex direction=\"column\" gap=\"1\" mb=\"4\">\n {accountGroups.map(({ accountId, calendarIds }, groupIdx) => {\n const account = accounts.find((a) => a.id === accountId);\n if (!account) return null;\n const collapsed = collapsedAccounts.has(accountId);\n return (\n <div\n key={accountId}\n style={{\n paddingTop: groupIdx > 0 ? \"var(--space-2)\" : undefined,\n borderTop: groupIdx > 0 ? \"1px solid var(--gray-3)\" : undefined,\n }}\n >\n <Flex\n align=\"center\"\n gap=\"2\"\n mb=\"2\"\n py=\"1\"\n className=\"calendar-legend-account-row\"\n style={{ cursor: \"pointer\", borderRadius: \"var(--radius-2)\" }}\n onClick={() => toggleAccountCollapsed(accountId)}\n >\n <ChevronDownIcon\n style={{\n ...iconSize(\"--space-3\"),\n color: \"var(--gray-9)\",\n transform: collapsed ? \"rotate(-90deg)\" : undefined,\n transition: \"transform 120ms ease\",\n flexShrink: 0,\n }}\n />\n <ProviderIcon provider={account.provider} />\n <Text\n size=\"2\"\n weight=\"medium\"\n truncate\n title={account.email}\n style={{ color: \"var(--gray-12)\", minWidth: 0 }}\n >\n {account.email}\n </Text>\n </Flex>\n {!collapsed && (\n <Flex direction=\"column\" gap=\"1\" pl=\"5\">\n {calendarIds.map((calId) => {\n const found = findCalendar(accounts, calId);\n if (!found) return null;\n return (\n <Text\n key={calId}\n as=\"label\"\n size=\"2\"\n className=\"calendar-legend-row\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-2)\",\n cursor: \"pointer\",\n borderRadius: \"var(--radius-2)\",\n padding: \"var(--space-1) var(--space-2)\",\n marginLeft: \"calc(var(--space-2) * -1)\",\n }}\n >\n <Flex align=\"center\" gap=\"1\">\n <Checkbox\n checked={visibleCalendarIds.has(calId)}\n onCheckedChange={() => toggleCalendarVisible(calId)}\n />\n <span\n aria-hidden\n style={{\n width: \"var(--space-3)\",\n height: \"var(--space-3)\",\n borderRadius: \"50%\",\n background: found.calendar.colorToken,\n flexShrink: 0,\n }}\n />\n </Flex>\n <Text size=\"2\" truncate style={{ color: \"var(--gray-12)\" }} title={found.calendar.name}>\n {found.calendar.name}\n </Text>\n </Text>\n );\n })}\n </Flex>\n )}\n </div>\n );\n })}\n </Flex>\n\n <Separator size=\"4\" mb=\"3\" />\n\n <Text\n as=\"label\"\n size=\"2\"\n style={{ display: \"flex\", alignItems: \"center\", gap: \"var(--space-2)\", cursor: \"pointer\" }}\n mb=\"3\"\n >\n <Checkbox checked={hideClones} onCheckedChange={(checked) => setHideClones(!!checked)} />\n Hide synced events\n </Text>\n\n <Separator size=\"4\" mb=\"3\" />\n\n <Link\n to={manageAccountsHref}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-2)\",\n color: \"var(--gray-11)\",\n textDecoration: \"none\",\n }}\n >\n <GearIcon style={iconSize(\"--space-3\")} />\n <Text size=\"2\">Manage accounts</Text>\n </Link>\n\n <Text as=\"p\" size=\"1\" color=\"gray\" mt=\"4\">\n On your target calendars, others see only what each sync is set to share. Full detail\n stays in araMetrics.\n </Text>\n </Box>\n )}\n\n <Box\n width={isNarrow ? \"100%\" : undefined}\n minHeight={layout.bigCalendarH}\n height=\"100%\"\n style={{\n flex: isNarrow ? \"1 1 100%\" : `1 1 ${layout.syncColWide}`,\n minWidth: isNarrow ? 0 : layout.syncColMin,\n display: \"flex\",\n flexDirection: \"column\",\n alignSelf: \"stretch\",\n }}\n >\n {isNarrow && (\n <button\n type=\"button\"\n className=\"sidebar-icon-btn\"\n aria-label={sidebarOpen ? \"Hide calendars\" : \"Show calendars\"}\n style={{ alignSelf: \"flex-start\", marginBottom: \"var(--space-3)\" }}\n onClick={() => setSidebarOpen((o) => !o)}\n >\n <HamburgerMenuIcon style={iconSize(\"--space-4\")} />\n </button>\n )}\n <Box flexGrow=\"1\" minHeight=\"0\" height=\"100%\">\n <BigCalendarView\n blocks={blocks}\n view={view}\n onViewChange={setView}\n date={cursor}\n onNavigate={setCursor}\n accounts={accounts}\n today={today}\n />\n </Box>\n </Box>\n </Flex>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\nimport {\n theme,\n type ThemeSize,\n type ThemeVariant,\n type ThemeVariantStyle,\n type ThemeColor,\n type ThemeColorShade,\n type ThemeRadius,\n type ThemeSpacing,\n getColor,\n} from \"./theme\";\nimport type { ResponsiveValue } from \"../types/common\";\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n\nexport function getVariantStyles(\n variant: ThemeVariant,\n style: ThemeVariantStyle = \"solid\"\n): string {\n return theme.variants[variant]?.[style] || theme.variants.primary[style];\n}\n\nexport function getSizeStyles(size: ThemeSize): string {\n const sizeConfig = theme.sizes[size] || theme.sizes.md;\n return `${sizeConfig.text} ${sizeConfig.padding} ${sizeConfig.height}`;\n}\n\nexport function getBaseStyles(): string {\n return cn(\n theme.base.transition,\n theme.base.focus,\n theme.base.disabled,\n theme.accessibility.reducedMotion\n );\n}\n\nexport function getInteractiveStyles(): string {\n return cn(theme.base.interactive, theme.accessibility.focusTrap, theme.accessibility.touchTarget);\n}\n\nexport function getAccessibilityStyles(\n options: {\n focusVisible?: boolean;\n highContrast?: boolean;\n reducedMotion?: boolean;\n } = {}\n): string {\n return cn(\n options.focusVisible && theme.accessibility.focusTrap,\n options.highContrast && theme.accessibility.highContrast,\n options.reducedMotion && theme.accessibility.reducedMotion\n );\n}\n\nexport function getResponsiveClasses<T extends string>(\n value: ResponsiveValue<T>,\n prefix: string = \"\"\n): string {\n if (typeof value === \"string\") {\n return `${prefix}${value}`;\n }\n\n if (typeof value === \"object\" && value !== null) {\n return Object.entries(value)\n .map(([breakpoint, val]) => {\n if (val === undefined) return \"\";\n const bp = breakpoint === \"xs\" ? \"\" : `${breakpoint}:`;\n return `${bp}${prefix}${val}`;\n })\n .filter(Boolean)\n .join(\" \");\n }\n\n return \"\";\n}\n\nexport function getSpacingClass(\n spacing: ThemeSpacing,\n type: \"gap\" | \"margin\" | \"padding\" = \"gap\"\n): string {\n const spacingValue = theme.spacing[spacing] || theme.spacing.md;\n\n switch (type) {\n case \"margin\":\n return spacingValue.replace(\"gap-\", \"m-\");\n case \"padding\":\n return spacingValue.replace(\"gap-\", \"p-\");\n default:\n return spacingValue;\n }\n}\n\nexport function getRadiusClass(radius: ThemeRadius): string {\n return theme.radius[radius] || theme.radius.md;\n}\n\nexport function getTypographyClass(typography: keyof typeof theme.typography): string {\n return theme.typography[typography] || theme.typography.base;\n}\n\nexport function getThemeColor(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return getColor(colorName, shade);\n}\n\nexport function getCSSVariableClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `[color:var(--color-${colorName}-${shade})]`;\n}\n\nexport function getBgClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `bg-${colorName}-${shade}`;\n}\n\nexport function getTextClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `text-${colorName}-${shade}`;\n}\n\nexport function getBorderClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `border-${colorName}-${shade}`;\n}\n\nexport function getHoverBgClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `hover:bg-${colorName}-${shade}`;\n}\n\nexport function getHoverTextClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `hover:text-${colorName}-${shade}`;\n}\n\nexport function getFocusRingClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `focus:ring-${colorName}-${shade}`;\n}\n\nexport function getAnimationClass(animation: keyof typeof theme.animations): string {\n const animationValue = theme.animations[animation];\n return typeof animationValue === \"string\" ? animationValue : \"\";\n}\n\nexport function validateProps<T extends Record<string, unknown>>(\n props: T,\n requiredProps: (keyof T)[],\n componentName?: string\n): void {\n const missing = requiredProps.filter((prop) => props[prop] === undefined);\n if (missing.length > 0) {\n const component = componentName ? ` in ${componentName}` : \"\";\n console.warn(`Missing required props${component}: ${missing.join(\", \")}`);\n }\n}\n\nexport function validateVariant<T extends string>(\n variant: T,\n validVariants: readonly T[],\n componentName?: string\n): boolean {\n if (!validVariants.includes(variant)) {\n const component = componentName ? ` in ${componentName}` : \"\";\n console.warn(\n `Invalid variant \"${variant}\"${component}. Valid variants: ${validVariants.join(\", \")}`\n );\n return false;\n }\n return true;\n}\n\nexport function createVariants<T extends Record<string, unknown>>(variants: T): T {\n return variants;\n}\n\nexport function createCompoundVariants<T>(\n base: string,\n variants: Record<string, Record<string, string>>,\n compoundVariants?: Array<{\n conditions: Record<string, string>;\n className: string;\n }>\n): (props: T) => string {\n return (props: T) => {\n let className = base;\n\n Object.entries(variants).forEach(([key, variantMap]) => {\n const value = (props as Record<string, unknown>)[key];\n if (value && variantMap[value as string]) {\n className += ` ${variantMap[value as string]}`;\n }\n });\n\n compoundVariants?.forEach(({ conditions, className: compoundClass }) => {\n const matches = Object.entries(conditions).every(\n ([key, value]) => (props as Record<string, unknown>)[key] === value\n );\n if (matches) {\n className += ` ${compoundClass}`;\n }\n });\n\n return cn(className);\n };\n}\n\nexport interface VariantConfig<T extends Record<string, Record<string, string>>> {\n base?: string;\n variants?: T;\n compoundVariants?: Array<{\n conditions: Partial<{ [K in keyof T]: keyof T[K] }>;\n className: string;\n }>;\n defaultVariants?: Partial<{ [K in keyof T]: keyof T[K] }>;\n}\n\nexport function createVariantGenerator<T extends Record<string, Record<string, string>>>(\n config: VariantConfig<T>\n) {\n return function generateVariantClasses(\n props: Partial<{ [K in keyof T]: keyof T[K] }> & { className?: string }\n ): string {\n const { className: customClassName, ...variantProps } = props;\n\n const mergedProps = { ...config.defaultVariants, ...variantProps };\n\n let classes = config.base || \"\";\n\n if (config.variants) {\n Object.entries(config.variants).forEach(([variantKey, variantMap]) => {\n const value = mergedProps[variantKey as keyof typeof mergedProps];\n if (value && variantMap[value as string]) {\n classes += ` ${variantMap[value as string]}`;\n }\n });\n }\n\n config.compoundVariants?.forEach(({ conditions, className: compoundClass }) => {\n const matches = Object.entries(conditions).every(\n ([key, value]) => mergedProps[key as keyof typeof mergedProps] === value\n );\n if (matches) {\n classes += ` ${compoundClass}`;\n }\n });\n\n return cn(classes, customClassName);\n };\n}\n\n// Utility for merging component props with defaults\nexport function mergeProps<T extends Record<string, unknown>>(\n defaultProps: Partial<T>,\n userProps: T\n): T {\n const merged = { ...defaultProps } as T;\n\n Object.keys(userProps).forEach((key) => {\n const userValue = userProps[key];\n const defaultValue = (defaultProps as Record<string, unknown>)[key];\n\n if (key === \"className\") {\n (merged as Record<string, unknown>)[key] = cn(\n defaultValue as string | undefined,\n userValue as string | undefined\n );\n } else if (\n typeof userValue === \"object\" &&\n typeof defaultValue === \"object\" &&\n userValue !== null &&\n defaultValue !== null &&\n !Array.isArray(userValue) &&\n !Array.isArray(defaultValue)\n ) {\n (merged as Record<string, unknown>)[key] = {\n ...(defaultValue as object),\n ...(userValue as object),\n };\n } else {\n (merged as Record<string, unknown>)[key] = userValue;\n }\n });\n\n return merged;\n}\n\n// Utility for conditional classes\nexport function conditionalClass(\n condition: boolean | undefined | null,\n trueClass: string,\n falseClass?: string\n): string {\n if (condition) return trueClass;\n if (falseClass && condition === false) return falseClass;\n return \"\";\n}\n\n// Utility for focus management\nexport function getFocusableElements(container: HTMLElement): HTMLElement[] {\n const focusableSelectors = [\n \"button:not([disabled])\",\n \"input:not([disabled])\",\n \"select:not([disabled])\",\n \"textarea:not([disabled])\",\n \"a[href]\",\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]',\n ].join(\", \");\n\n return Array.from(container.querySelectorAll(focusableSelectors));\n}\n\n// Utility for keyboard navigation\nexport function handleArrowNavigation(\n event: KeyboardEvent,\n elements: HTMLElement[],\n currentIndex: number,\n options: {\n loop?: boolean;\n orientation?: \"horizontal\" | \"vertical\" | \"both\";\n } = {}\n): number {\n const { loop = true, orientation = \"both\" } = options;\n let newIndex = currentIndex;\n\n switch (event.key) {\n case \"ArrowDown\":\n if (orientation === \"vertical\" || orientation === \"both\") {\n newIndex = currentIndex + 1;\n if (newIndex >= elements.length) {\n newIndex = loop ? 0 : elements.length - 1;\n }\n }\n break;\n case \"ArrowUp\":\n if (orientation === \"vertical\" || orientation === \"both\") {\n newIndex = currentIndex - 1;\n if (newIndex < 0) {\n newIndex = loop ? elements.length - 1 : 0;\n }\n }\n break;\n case \"ArrowRight\":\n if (orientation === \"horizontal\" || orientation === \"both\") {\n newIndex = currentIndex + 1;\n if (newIndex >= elements.length) {\n newIndex = loop ? 0 : elements.length - 1;\n }\n }\n break;\n case \"ArrowLeft\":\n if (orientation === \"horizontal\" || orientation === \"both\") {\n newIndex = currentIndex - 1;\n if (newIndex < 0) {\n newIndex = loop ? elements.length - 1 : 0;\n }\n }\n break;\n case \"Home\":\n newIndex = 0;\n break;\n case \"End\":\n newIndex = elements.length - 1;\n break;\n }\n\n if (newIndex !== currentIndex) {\n event.preventDefault();\n elements[newIndex]?.focus();\n }\n\n return newIndex;\n}\n","import React from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Theme } from \"@radix-ui/themes\";\nimport type { ThemeProps } from \"@radix-ui/themes\";\nimport \"@radix-ui/themes/styles.css\";\nimport \"../styles/radix-brand-tokens.css\";\n\nexport interface UIProviderProps extends Omit<Partial<ThemeProps>, \"children\"> {\n children: ReactNode;\n}\n\nexport function UIProvider({\n children,\n appearance = \"light\",\n radius = \"none\",\n scaling = \"100%\",\n accentColor = \"amber\",\n grayColor = \"gray\",\n panelBackground = \"solid\",\n className = \"\",\n}: UIProviderProps) {\n return (\n <Theme\n accentColor={accentColor}\n grayColor={grayColor}\n radius={radius}\n scaling={scaling}\n panelBackground={panelBackground}\n appearance={appearance}\n className={className}\n >\n {children}\n </Theme>\n );\n}\n\nexport default UIProvider;\n","import * as React from \"react\";\n\nexport function useControllableState<T>({\n value,\n defaultValue,\n onChange,\n}: {\n value?: T;\n defaultValue?: T;\n onChange?: (value: T) => void;\n}) {\n const [internalValue, setInternalValue] = React.useState<T | undefined>(defaultValue);\n\n const isControlled = value !== undefined;\n const currentValue = isControlled ? value : internalValue;\n\n const setValue = React.useCallback(\n (newValue: T | ((prev: T | undefined) => T)) => {\n const resolvedValue =\n typeof newValue === \"function\"\n ? (newValue as (prev: T | undefined) => T)(currentValue)\n : newValue;\n\n if (!isControlled) {\n setInternalValue(resolvedValue);\n }\n\n onChange?.(resolvedValue);\n },\n [isControlled, currentValue, onChange]\n );\n\n return [currentValue, setValue] as const;\n}\n","import * as React from \"react\";\n\nexport function useDisclosure(defaultOpen = false) {\n const [isOpen, setIsOpen] = React.useState(defaultOpen);\n\n const open = React.useCallback(() => setIsOpen(true), []);\n const close = React.useCallback(() => setIsOpen(false), []);\n const toggle = React.useCallback(() => setIsOpen((prev) => !prev), []);\n\n return {\n isOpen,\n open,\n close,\n toggle,\n onOpen: open,\n onClose: close,\n onToggle: toggle,\n };\n}\n","import * as React from \"react\";\n\nexport function useClickOutside<T extends HTMLElement = HTMLElement>(\n handler: () => void,\n enabled = true\n) {\n const ref = React.useRef<T>(null);\n\n React.useEffect(() => {\n if (!enabled) return;\n\n const handleClickOutside = (event: MouseEvent) => {\n if (ref.current && !ref.current.contains(event.target as Node)) {\n handler();\n }\n };\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\n }, [handler, enabled]);\n\n return ref;\n}\n","export * from \"./src\";\n// The icon set is re-exported here, at the build entry, and not only from\n// src/components/icons.ts: esbuild keeps `export * from \"<external>\"` as a real\n// ESM re-export only in an entry file. Nested one level down it becomes a runtime\n// property copy, and `import { Cross2Icon } from \"@aracreate/arm-ui\"` then fails in\n// a bundler even though the types say it exists (3.8.0 shipped that way).\nexport * from \"@radix-ui/react-icons\";\n"],"mappings":"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","names":["Box","Flex","Grid","Container","Section","Inset","AspectRatio","ScrollArea","Separator","Text","Heading","Blockquote","Code","Em","Kbd","Link","Quote","Strong","Button","IconButton","TextField","TextArea","Checkbox","CheckboxGroup","CheckboxCards","Radio","RadioGroup","RadioCards","Select","Slider","Switch","SegmentedControl","Dialog","AlertDialog","DropdownMenu","ContextMenu","Popover","HoverCard","Tooltip","Portal","Avatar","Badge","Callout","Card","DataList","Progress","Spinner","Table","Tabs","TabNav","AccessibleIcon","Slot","Slottable","VisuallyHidden","jsx","Skeleton","width","height","radius","circle","mb","className","style","React","RadixAccordion","ChevronDownIcon","jsx","jsxs","Accordion","className","props","ref","AccordionItem","AccordionTrigger","children","AccordionContent","React","RadixDialog","Cross2Icon","jsx","jsxs","Drawer","DrawerTrigger","DrawerClose","DrawerContent","className","side","size","children","props","ref","DrawerHeader","DrawerTitle","DrawerDescription","DrawerDefaultClose","Box","Flex","Text","jsx","jsxs","AccentHeader","title","trailing","style","titleNode","AccentCard","children","bodyPadding","AlertDialog","Button","layout","Flex","jsx","CardFooter","children","justify","noTopMargin","pad","radius","jsx","jsxs","ConfirmDialog","title","description","confirmLabel","cancelLabel","onConfirm","trigger","open","onOpenChange","AlertDialog","layout","CardFooter","Button","PauseIcon","iconSize","space","jsx","jsxs","PausedBadge","label","style","PauseIcon","iconSize","Avatar","Box","DropdownMenu","Flex","IconButton","Text","DotsVerticalIcon","PauseIcon","PlayIcon","TrashIcon","jsx","jsxs","AccountCard","name","email","avatarSrc","paused","onPause","onResume","onDelete","onClick","badge","accentColor","style","nameText","Text","Box","layout","Flex","Avatar","PausedBadge","DropdownMenu","IconButton","e","DotsVerticalIcon","PlayIcon","PauseIcon","TrashIcon","Box","Flex","Heading","IconButton","Text","ChevronLeftIcon","ChevronRightIcon","headingSize","Fragment","jsx","jsxs","WEEKDAY_LABELS","CELL_WIDTH","CELL_HEIGHT","GRID_GAP","MONTH_YEAR_FORMAT","FULL_DATE_FORMAT","isSameDay","a","b","mondayIndex","jsDay","buildGridDays","month","monthIndex","year","firstOfMonth","lastOfMonth","leadingCount","trailingCount","gridStart","totalDays","_","i","date","addMonths","delta","MonthGrid","onMonthChange","events","dayDots","today","onSelectDay","style","resolvedToday","days","eventDayKeys","d","Flex","IconButton","ChevronLeftIcon","iconSize","Heading","headingSize","layout","ChevronRightIcon","Box","label","Text","inCurrentMonth","isToday","dots","hasEvent","cellStyle","dayNumber","color","key","useEffect","Callout","CheckCircledIcon","ExclamationTriangleIcon","jsx","jsxs","Toast","msg","color","onDone","durationMs","useEffect","t","layout","Callout","ExclamationTriangleIcon","CheckCircledIcon","jsx","IconTile","children","size","Box","Flex","Text","LockClosedIcon","jsx","jsxs","EventBlock","title","time","detail","color","locked","Box","jsx","DataTableRow","children","style","showBorder","onActivate","selected","className","ariaLabel","interactive","handleKeyDown","e","useId","Card","Flex","Text","jsx","jsxs","MetricCard","label","value","delta","deltaDir","goodDirection","statusColor","sparkline","Sparkline","data","color","min","range","pts","v","i","line","p","area","gradId","Link","Badge","Button","Card","Flex","Text","ArrowRightIcon","jsx","jsxs","AppCard","href","icon","name","description","badge","Card","Flex","IconTile","Text","Badge","CardFooter","Button","Link","ArrowRightIcon","iconSize","Text","jsx","jsxs","ActivityRow","tag","tagColor","msg","actor","timeAgo","timestamp","showBorder","DataTableRow","Text","Button","Card","Flex","Text","ExclamationTriangleIcon","jsx","jsxs","DashboardErrorCard","onRetry","message","Card","Flex","IconTile","ExclamationTriangleIcon","iconSize","Text","Button","useMemo","Button","Flex","IconButton","Text","ChevronLeftIcon","ChevronRightIcon","DoubleArrowLeftIcon","DoubleArrowRightIcon","jsx","jsxs","ELLIPSIS","buildPageRange","currentPage","totalPages","siblingCount","totalVisible","_","i","leftSibling","rightSibling","showLeftEllipsis","showRightEllipsis","span","rightRange","middleRange","Pagination","onPageChange","showFirstLast","size","pages","atFirst","atLast","page","index","ROLE_META","ROLE_LABELS","STATUS_META","METRIC_STATUS_COLOR","ACTIVITY_META","AUDIT_ACTION_META","auditActionMeta","action","jsx","BrandPanel","layout","jsx","jsxs","AuthCard","children","BrandPanel","layout","jsx","jsxs","GoogleIcon","jsx","jsxs","MicrosoftIcon","useRef","TextField","jsx","OtpInput","value","onChange","disabled","inputs","handleChange","i","e","ch","digits","_","k","handleKeyDown","handlePaste","pasted","d","el","Button","Callout","Heading","Text","ExclamationTriangleIcon","Fragment","jsx","jsxs","OtpVerifyStep","email","title","subtitle","code","onCodeChange","otpDevHint","error","errorAction","busy","otpExpiresAt","otpSecondsLeft","resendCooldown","onResend","onUseDifferentEmail","Heading","headingSize","Text","Callout","ExclamationTriangleIcon","Button","OtpInput","jsx","ProviderIcon","provider","MicrosoftIcon","GoogleIcon","PROVIDER_LABEL","useEffect","useRef","useState","Link","useLocation","Avatar","Badge","DropdownMenu","IconButton","Text","Tooltip","ChevronDownIcon","ChevronLeftIcon","ChevronRightIcon","Cross1Icon","DotFilledIcon","DotsVerticalIcon","ExitIcon","GearIcon","QuestionMarkCircledIcon","Fragment","jsx","jsxs","SHELL_HEADER_H","isNavGroup","entry","fullLabel","item","readFoldState","key","parsed","pair","writeFoldState","state","WIDTH_EXPANDED","WIDTH_COLLAPSED","WIDTH_DRAWER","ROW_H","PILL_L","PILL_R","ICON_X","LABEL_GAP","labelTransition","expanded","LOGO_TRANSITION","Sidebar","collapsed","onToggle","onClose","items","persistKey","utilityHrefsProp","user","onSignOut","hasCalendarAccounts","brandLogoExpandedSrc","brandLogoCollapsedSrc","helpHref","devRoles","onDevRoleSelect","showDevRoles","pathname","useLocation","confirmLogoutOpen","setConfirmLogoutOpen","useState","backTo","setBackTo","clearBack","rootRef","useRef","focusAfterStep","drillIn","isDrawer","width","allowed","prune","children","visibleEntries","groupItems","topLevelItems","visibleItems","foldState","setFoldState","isFolded","group","toggleGroup","next","utilityHrefs","primaryEntries","settingsItem","utilityItems","sectionRoot","drillable","inSection","root","urlPath","level","section","depth","activeSection","stepBack","useEffect","target","node","isActive","href","end","renderTopRow","renderRow","uppercase","active","drills","row","NavRow","Tooltip","renderGroup","listId","folded","GroupHeading","isAdminContext","initials","n","IconButton","Cross1Icon","iconSize","backRow","ChevronLeftIcon","child","Badge","DotFilledIcon","Avatar","Text","DropdownMenu","DotsVerticalIcon","Link","GearIcon","QuestionMarkCircledIcon","ExitIcon","r","PanelToggleIcon","ConfirmDialog","onClick","asButton","showChevron","rowStyle","body","ChevronRightIcon","label","holdsActive","controls","ChevronDownIcon","flipped","Link","useLocation","HamburgerMenuIcon","MagnifyingGlassIcon","BellIcon","Flex","Heading","IconButton","Text","Tooltip","Fragment","jsx","jsxs","DEFAULT_TITLES","DEFAULT_ADMIN_TITLES","breadcrumb","pathname","titles","adminTitles","hit","p","exact","section","sectionHref","page","Topbar","onSearchOpen","onMenuOpen","showMenu","useLocation","SHELL_HEADER_H","IconButton","HamburgerMenuIcon","iconSize","Flex","Text","Link","Heading","headingSize","MagnifyingGlassIcon","Tooltip","BellIcon","useEffect","useRef","useState","Dialog","Flex","Spinner","Text","TextField","VisuallyHidden","CalendarIcon","MagnifyingGlassIcon","PersonIcon","ReaderIcon","Fragment","jsx","jsxs","TYPE_ICON","TYPE_LABEL","groupResults","results","order","groups","flat","t","items","r","SearchOverlay","open","onClose","resultPool","onSelectResult","title","placeholder","o","SearchBody","query","setQuery","searchResults","setSearchResults","selectedIdx","setSelectedIdx","inputRef","listRef","isCurrent","state","q","found","handleKeyDown","e","i","selectResult","result","grouped","promptHeight","group","Icon","flatIdx","isSelected","findCalendar","accounts","calendarId","account","calendar","c","dayjs","Flex","Text","jsx","jsxs","CalendarDayHeader","date","today","isToday","Box","Checkbox","Flex","RadioGroup","Text","jsx","jsxs","rowsFromAccounts","accounts","account","cal","ProviderMark","provider","ProviderIcon","CalendarRow","row","control","selected","disabled","disabledLabel","Text","Flex","Box","CalendarPickList","mode","sourceCalendarIds","targetCalendarId","takenSourceIds","onToggleSource","onSelectTarget","fill","rows","list","idx","isTarget","takenElsewhere","Checkbox","isSource","RadioGroup","v","Button","Flex","Heading","IconButton","ChevronLeftIcon","ChevronRightIcon","Navigate","jsx","jsxs","CalendarToolbar","label","view","onNavigate","onView","Flex","IconButton","Navigate","ChevronLeftIcon","Button","ChevronRightIcon","Heading","headingSize","v","Button","Flex","Spinner","Text","ChevronRightIcon","ExclamationTriangleIcon","jsx","jsxs","PROVIDER_META","PROVIDERS","ConnectProviderList","connectingProvider","failedProvider","exhausted","onConnect","Flex","provider","meta","connecting","IconTile","ProviderIcon","Text","Spinner","ChevronRightIcon","iconSize","ExclamationTriangleIcon","Button","Badge","Box","DropdownMenu","Flex","IconButton","Text","DotsVerticalIcon","ReloadIcon","TrashIcon","jsx","jsxs","ConnectedAccountCard","account","onRemove","onReconnect","onClick","needsReauth","hasFailed","name","Text","Box","layout","IconTile","ProviderIcon","Flex","e","Badge","DropdownMenu","IconButton","DotsVerticalIcon","ReloadIcon","TrashIcon","Flex","Text","Heading","jsx","jsxs","EmptyCard","icon","title","description","action","headingAs","Flex","IconTile","Heading","headingSize","Text","layout","useState","Dialog","Flex","Text","Checkbox","Button","Fragment","jsx","jsxs","ImportCalendarsDialog","account","onOpenChange","onImport","initiallySelectedIds","disabledIds","disabledReason","title","description","confirmLabel","formKey","c","Dialog","layout","event","ImportCalendarsForm","selected","setSelected","useState","disabled","toggle","id","prev","next","Text","Flex","cal","checked","isDisabled","Checkbox","CardFooter","Button","Box","Flex","Text","jsx","jsxs","readableTextOn","hex","m","int","channel","c","v","EventChip","tone","title","meta","accentColor","background","foreground","DEFAULT_TAG_LABEL","DEFAULT_SAMPLE","SyncPreviewRail","hasSources","hasTarget","sourceLabel","targetLabel","showTitle","showDescription","showLocation","tagLabel","sampleEvent","sourceTitle","sourceMeta","tag","postedTitle","postedMetaParts","postedMeta","Flex","Text","CheckIcon","jsx","jsxs","WizardStepper","steps","current","step","i","index","active","done","Flex","CheckIcon","iconSize","Text","jsx","FIRST_RUN_STEPS","OnboardingStepper","current","WizardStepper","OnboardingStepDots","total","dayjs","Flex","Grid","IconButton","Text","ChevronLeftIcon","ChevronRightIcon","jsx","jsxs","WEEKDAY_LABELS","MiniMonthPicker","cursor","onSelect","today","monthStart","gridStart","days","_","i","w","d","isToday","isSelected","isOffMonth","useState","Dialog","Flex","Text","Button","IconButton","Badge","Separator","Box","Cross2Icon","PlusIcon","ReloadIcon","Fragment","jsx","jsxs","AccountCalendarsDialog","account","catalog","onOpenChange","onRemoveCalendar","onSaveCalendars","onReconnect","managing","setManaging","useState","needsReauth","hasFailed","handleManageSave","selectedCalendarIds","selected","c","Dialog","open","layout","Flex","IconTile","ProviderIcon","Box","Badge","Button","ReloadIcon","Separator","Text","PlusIcon","iconSize","cal","idx","IconButton","Cross2Icon","CardFooter","ImportCalendarsDialog","useMemo","dayjs","Calendar","dayjsLocalizer","Views","Text","jsx","jsxs","localizer","dayjsLocalizer","dayjs","SCROLL_TO_TIME","BigCalendarView","blocks","view","onViewChange","date","onNavigate","accounts","today","events","useMemo","b","start","end","Calendar","Views","v","event","color","findCalendar","CalendarToolbar","headerProps","CalendarDayHeader","durationMin","showLocation","showTimeRange","Text","Dialog","Flex","Text","Button","Separator","Badge","Fragment","jsx","jsxs","STATUS_META","SyncDetailsDialog","sync","accounts","onOpenChange","onEdit","calendarsSummary","sources","cid","findCalendar","n","target","Dialog","layout","Flex","Badge","DetailRow","found","Text","Separator","CardFooter","Button","label","children","useState","useConnectAccount","accounts","connectProvider","onAccountAdded","onImported","connectingProvider","setConnectingProvider","pendingAccount","setPendingAccount","failedProvider","setFailedProvider","exhausted","setExhausted","connect","provider","connectedIds","a","account","confirmImport","selectedCalendarIds","selected","c","Box","DropdownMenu","Button","Flex","Text","PlusIcon","Fragment","jsx","jsxs","AddAccountMenu","variant","trigger","accounts","connectProvider","onAccountAdded","onImported","pendingAccount","failedProvider","exhausted","connect","confirmImport","cancelImport","dismissError","useConnectAccount","providers","defaultTrigger","PlusIcon","iconSize","Button","menu","DropdownMenu","provider","meta","PROVIDER_META","IconTile","ProviderIcon","Flex","Text","Box","ImportCalendarsDialog","open","Toast","Card","Flex","Text","Heading","CalendarIcon","jsx","jsxs","ConnectProviderRows","accounts","connectProvider","onAccountAdded","onImported","connectingProvider","pendingAccount","failedProvider","exhausted","connect","confirmImport","cancelImport","useConnectAccount","Flex","Card","layout","IconTile","CalendarIcon","iconSize","Heading","headingSize","Text","ConnectProviderList","ImportCalendarsDialog","open","useEffect","useMemo","useState","Link","Box","Checkbox","Flex","Separator","Text","ChevronDownIcon","GearIcon","HamburgerMenuIcon","jsx","jsxs","CalendarMergedView","accounts","view","setView","hideClones","setHideClones","mergedCalendarIds","visibleCalendarIds","toggleCalendarVisible","getVisibleBlocksInRange","manageAccountsHref","today","cursor","setCursor","useState","collapsedAccounts","setCollapsedAccounts","isNarrow","setIsNarrow","sidebarOpen","setSidebarOpen","useEffect","onResize","rangeStart","useMemo","d","rangeEnd","blocks","accountGroups","groups","index","calId","found","findCalendar","i","toggleAccountCollapsed","accountId","prev","next","Flex","Box","layout","MiniMonthPicker","Separator","Text","calendarIds","groupIdx","account","a","collapsed","ChevronDownIcon","iconSize","ProviderIcon","Checkbox","checked","Link","GearIcon","o","HamburgerMenuIcon","BigCalendarView","clsx","twMerge","cn","inputs","twMerge","clsx","getVariantStyles","variant","style","theme","getSizeStyles","size","sizeConfig","getBaseStyles","getInteractiveStyles","getAccessibilityStyles","options","getResponsiveClasses","value","prefix","breakpoint","val","getSpacingClass","spacing","type","spacingValue","getRadiusClass","radius","getTypographyClass","typography","getBgClass","colorName","shade","getTextClass","getBorderClass","getHoverBgClass","getHoverTextClass","getFocusRingClass","getAnimationClass","animation","animationValue","theme","createCompoundVariants","base","variants","compoundVariants","props","className","key","variantMap","value","conditions","compoundClass","cn","createVariantGenerator","config","customClassName","variantProps","mergedProps","classes","variantKey","mergeProps","defaultProps","userProps","merged","userValue","defaultValue","conditionalClass","condition","trueClass","falseClass","getFocusableElements","container","focusableSelectors","handleArrowNavigation","event","elements","currentIndex","options","loop","orientation","newIndex","Theme","jsx","UIProvider","children","appearance","radius","scaling","accentColor","grayColor","panelBackground","className","Theme","React","useControllableState","value","defaultValue","onChange","internalValue","setInternalValue","isControlled","currentValue","setValue","newValue","resolvedValue","React","useDisclosure","defaultOpen","isOpen","setIsOpen","open","close","toggle","prev","React","useClickOutside","handler","enabled","ref","handleClickOutside","event"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/primitives.ts","../src/components/Skeleton.tsx","../src/components/Accordion.tsx","../src/components/Drawer.tsx","../src/components/AccentHeader.tsx","../src/components/ConfirmDialog.tsx","../src/components/layout-tokens.ts","../src/components/CardFooter.tsx","../src/components/PausedBadge.tsx","../src/components/icon-size.ts","../src/components/AccountCard.tsx","../src/components/MonthGrid.tsx","../src/components/heading-scale.ts","../src/components/Toast.tsx","../src/components/IconTile.tsx","../src/components/EventBlock.tsx","../src/components/DataTableRow.tsx","../src/components/MetricCard.tsx","../src/components/AppCard.tsx","../src/components/ActivityRow.tsx","../src/components/DashboardErrorCard.tsx","../src/components/Pagination.tsx","../src/components/status-colors.ts","../src/components/BrandPanel.tsx","../src/components/AuthCard.tsx","../src/components/GoogleIcon.tsx","../src/components/MicrosoftIcon.tsx","../src/components/OtpInput.tsx","../src/components/OtpVerifyStep.tsx","../src/components/ProviderIcon.tsx","../src/components/Sidebar.tsx","../src/components/Topbar.tsx","../src/components/SearchOverlay.tsx","../src/components/calendar-types.ts","../src/components/CalendarDayHeader.tsx","../src/components/CalendarPickList.tsx","../src/components/CalendarToolbar.tsx","../src/components/ConnectProviderList.tsx","../src/components/ConnectedAccountCard.tsx","../src/components/EmptyCard.tsx","../src/components/ImportCalendarsDialog.tsx","../src/components/SyncPreviewRail.tsx","../src/components/WizardStepper.tsx","../src/components/OnboardingStepDots.tsx","../src/components/MiniMonthPicker.tsx","../src/components/AccountCalendarsDialog.tsx","../src/components/BigCalendarView.tsx","../src/components/SyncDetailsDialog.tsx","../src/components/useConnectAccount.ts","../src/components/AddAccountMenu.tsx","../src/components/ConnectProviderRows.tsx","../src/components/CalendarMergedView.tsx","../src/lib/utils.ts","../src/lib/ui-provider.tsx","../src/lib/shell-bridge.ts","../src/lib/hooks/useControllableState.ts","../src/lib/hooks/useDisclosure.ts","../src/lib/hooks/useClickOutside.ts","../index.ts"],"sourcesContent":["// The basic components, re-exported from Radix Themes so a frontend imports every\n// component from this package and nothing from `@radix-ui/themes`.\n//\n// These are the identical objects, not wrappers — behaviour is Radix's. A component\n// becomes a real wrapper here only when ARM needs something Radix does not give, and\n// that edit then touches this library alone. Compound families (`Dialog.Root`,\n// `DropdownMenu.Item`, `Select.Item`, …) come through whole.\n//\n// Not exported, on purpose (primitives.test.ts holds this list and fails on any\n// Radix export that is neither re-exported nor named there):\n// Theme, useThemeContext, ThemeContext UIProvider owns the theme; frontends never mount it\n// ThemePanel, Reset dev tool / internal\n// Skeleton this library keeps its own (./Skeleton)\n// ChevronDownIcon, Thick*Icon Radix's own icon copies; the icon set (root index.ts) has ChevronDownIcon\n//\n// `Link` is exported as `TextLink`: react-router's `Link` shares files with it.\n\nexport {\n // Layout\n Box,\n Flex,\n Grid,\n Container,\n Section,\n Inset,\n AspectRatio,\n ScrollArea,\n Separator,\n // Typography\n Text,\n Heading,\n Blockquote,\n Code,\n Em,\n Kbd,\n Link as TextLink,\n Quote,\n Strong,\n // Actions and form controls\n Button,\n IconButton,\n TextField,\n TextArea,\n Checkbox,\n CheckboxGroup,\n CheckboxCards,\n Radio,\n RadioGroup,\n RadioCards,\n Select,\n Slider,\n Switch,\n SegmentedControl,\n // Overlays\n Dialog,\n AlertDialog,\n DropdownMenu,\n ContextMenu,\n Popover,\n HoverCard,\n Tooltip,\n Portal,\n // Feedback and data display\n Avatar,\n Badge,\n Callout,\n Card,\n DataList,\n Progress,\n Spinner,\n Table,\n Tabs,\n TabNav,\n // Utilities\n AccessibleIcon,\n Slot,\n Slottable,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\n\nexport type {\n AccessibleIconProps,\n AspectRatioProps,\n AvatarProps,\n BadgeProps,\n BlockquoteProps,\n BoxProps,\n ButtonProps,\n CardProps,\n CheckboxProps,\n CodeProps,\n ContainerProps,\n EmProps,\n FlexProps,\n GridProps,\n HeadingProps,\n IconButtonProps,\n InsetProps,\n KbdProps,\n LinkProps as TextLinkProps,\n PortalProps,\n ProgressProps,\n QuoteProps,\n RadioProps,\n ScrollAreaProps,\n SectionProps,\n SeparatorProps,\n SliderProps,\n SpinnerProps,\n StrongProps,\n SwitchProps,\n TextAreaProps,\n TextProps,\n TooltipProps,\n VisuallyHiddenProps,\n} from \"@radix-ui/themes\";\n","import type { CSSProperties } from \"react\";\n\n/**\n * Skeleton — loading placeholder. Generalizes the local `Skel` helper and the\n * inline `<div className=\"skeleton\" .../>` blocks used in the users, user-detail,\n * and home surfaces. Pulse animation + base color come from `.skeleton` in\n * globals.css.\n */\nexport interface SkeletonProps {\n width?: number | string;\n height?: number | string;\n /** Border radius. Ignored when `circle` is set. Defaults to var(--radius-2). */\n radius?: number | string;\n /** Render as a circle (avatars). */\n circle?: boolean;\n /** Bottom margin. */\n mb?: number | string;\n className?: string;\n style?: CSSProperties;\n}\n\nexport function Skeleton({\n width = \"100%\",\n height = \"var(--space-4)\" /* 16px == space-4 */,\n radius = \"var(--radius-2)\",\n circle = false,\n mb,\n className,\n style,\n}: SkeletonProps) {\n return (\n <div\n className={[\"skeleton\", className].filter(Boolean).join(\" \")}\n aria-hidden=\"true\"\n style={{\n width,\n height,\n borderRadius: circle ? \"50%\" : radius,\n marginBottom: mb,\n ...style,\n }}\n />\n );\n}\n\nexport default Skeleton;\n","import * as React from \"react\";\nimport * as RadixAccordion from \"@radix-ui/react-accordion\";\nimport { ChevronDownIcon } from \"@radix-ui/react-icons\";\n\n/**\n * Accordion — collapsible sections. Radix Themes has no accordion, so this is\n * built on the raw `@radix-ui/react-accordion` primitive. Styles live in\n * tokens.css (`.arm-accordion*`) — consumers' UnoCSS does not scan this\n * package. Moved here from core-fe so no frontend imports a Radix primitive.\n *\n * <Accordion type=\"single\" collapsible>\n * <AccordionItem value=\"a\">\n * <AccordionTrigger>Title</AccordionTrigger>\n * <AccordionContent>Body</AccordionContent>\n * </AccordionItem>\n * </Accordion>\n */\nexport const Accordion = React.forwardRef<\n React.ComponentRef<typeof RadixAccordion.Root>,\n React.ComponentPropsWithoutRef<typeof RadixAccordion.Root>\n>(({ className = \"\", ...props }, ref) => (\n <RadixAccordion.Root\n ref={ref}\n className={`arm-accordion ${className}`}\n {...props}\n />\n));\nAccordion.displayName = \"Accordion\";\n\nexport const AccordionItem = React.forwardRef<\n React.ComponentRef<typeof RadixAccordion.Item>,\n React.ComponentPropsWithoutRef<typeof RadixAccordion.Item>\n>(({ className = \"\", ...props }, ref) => (\n <RadixAccordion.Item ref={ref} className={`arm-accordion__item ${className}`} {...props} />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nexport const AccordionTrigger = React.forwardRef<\n React.ComponentRef<typeof RadixAccordion.Trigger>,\n React.ComponentPropsWithoutRef<typeof RadixAccordion.Trigger>\n>(({ className = \"\", children, ...props }, ref) => (\n <RadixAccordion.Header className=\"arm-accordion__header\">\n <RadixAccordion.Trigger\n ref={ref}\n className={`arm-accordion__trigger ${className}`}\n {...props}\n >\n {children}\n <ChevronDownIcon aria-hidden className=\"arm-accordion__chevron\" />\n </RadixAccordion.Trigger>\n </RadixAccordion.Header>\n));\nAccordionTrigger.displayName = \"AccordionTrigger\";\n\nexport const AccordionContent = React.forwardRef<\n React.ComponentRef<typeof RadixAccordion.Content>,\n React.ComponentPropsWithoutRef<typeof RadixAccordion.Content>\n>(({ className = \"\", children, ...props }, ref) => (\n <RadixAccordion.Content ref={ref} className={`arm-accordion__content ${className}`} {...props}>\n <div className=\"arm-accordion__body\">{children}</div>\n </RadixAccordion.Content>\n));\nAccordionContent.displayName = \"AccordionContent\";\n","import * as React from \"react\";\nimport * as RadixDialog from \"@radix-ui/react-dialog\";\nimport { Cross2Icon } from \"@radix-ui/react-icons\";\n\n/**\n * Drawer — a side sheet. Not a Radix Themes concept, so it is built on the raw\n * `@radix-ui/react-dialog` primitive (focus trap, Escape, overlay click). Styles\n * live in tokens.css (`.arm-drawer*`) — consumers' UnoCSS does not scan this\n * package. Moved here from core-fe so no frontend imports a Radix primitive.\n *\n * <Drawer open={open} onOpenChange={setOpen}>\n * <DrawerContent side=\"right\" size=\"md\">\n * <DrawerHeader><DrawerTitle>Notifications</DrawerTitle></DrawerHeader>\n * …\n * <DrawerDefaultClose />\n * </DrawerContent>\n * </Drawer>\n */\nexport const Drawer = RadixDialog.Root;\nexport const DrawerTrigger = RadixDialog.Trigger;\nexport const DrawerClose = RadixDialog.Close;\n\ntype Side = \"right\" | \"left\";\n/** sm 16rem · md 20rem · lg 480px */\ntype Size = \"sm\" | \"md\" | \"lg\";\n\nexport interface DrawerContentProps\n extends React.ComponentPropsWithoutRef<typeof RadixDialog.Content> {\n side?: Side;\n size?: Size;\n}\n\nexport const DrawerContent = React.forwardRef<\n React.ComponentRef<typeof RadixDialog.Content>,\n DrawerContentProps\n>(({ className = \"\", side = \"right\", size = \"md\", children, ...props }, ref) => (\n <RadixDialog.Portal>\n <RadixDialog.Overlay className=\"arm-drawer__overlay\" />\n <RadixDialog.Content\n ref={ref}\n data-side={side}\n data-size={size}\n className={`arm-drawer ${className}`}\n {...props}\n >\n {children}\n </RadixDialog.Content>\n </RadixDialog.Portal>\n));\nDrawerContent.displayName = \"DrawerContent\";\n\nexport const DrawerHeader: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className = \"\",\n children,\n ...props\n}) => (\n <div\n className={`arm-drawer__header ${className}`}\n {...props}\n >\n {children}\n </div>\n);\n\nexport const DrawerTitle = React.forwardRef<\n React.ComponentRef<typeof RadixDialog.Title>,\n React.ComponentPropsWithoutRef<typeof RadixDialog.Title>\n>(({ className = \"\", ...props }, ref) => (\n <RadixDialog.Title\n ref={ref}\n className={`arm-drawer__title ${className}`}\n {...props}\n />\n));\nDrawerTitle.displayName = \"DrawerTitle\";\n\nexport const DrawerDescription = React.forwardRef<\n React.ComponentRef<typeof RadixDialog.Description>,\n React.ComponentPropsWithoutRef<typeof RadixDialog.Description>\n>(({ className = \"\", ...props }, ref) => (\n <RadixDialog.Description ref={ref} className={`arm-drawer__description ${className}`} {...props} />\n));\nDrawerDescription.displayName = \"DrawerDescription\";\n\nexport const DrawerDefaultClose: React.FC = () => (\n <RadixDialog.Close\n aria-label=\"Close\"\n className=\"arm-drawer__close\"\n >\n <Cross2Icon aria-hidden className=\"arm-drawer__close-icon\" />\n </RadixDialog.Close>\n);\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { Box, Flex, Text } from \"@radix-ui/themes\";\n\n/**\n * AccentHeader — the amber two-tone title bar Figma uses on cards, dialogs,\n * and page banners (Target/Source Calendar, Preview, Upcoming Event, Confirm\n * Logout, Terms hero). Build-once pattern per the design ledger: a solid\n * `--accent-9` bar with a dark bold title, optionally with trailing controls\n * (e.g. the Month/Week/Day toggle lives inside the bar on the Preview card).\n *\n * Figma refs: ui-ux/figma/crops/month-card.png, confirm-dialog.png.\n */\nexport interface AccentHeaderProps {\n title: ReactNode;\n /** Right-aligned slot inside the bar (view toggles, actions). */\n trailing?: ReactNode;\n style?: CSSProperties;\n}\n\nexport function AccentHeader({ title, trailing, style }: AccentHeaderProps) {\n // Plain strings get the bar's standard Text treatment; element titles (e.g.\n // an AlertDialog.Title heading) render as-is so we never nest a heading\n // inside a span (invalid HTML).\n const titleNode =\n typeof title === \"string\" || typeof title === \"number\" ? (\n <Text size=\"3\" weight=\"medium\" style={{ color: \"var(--accent-contrast)\" }}>\n {title}\n </Text>\n ) : (\n title\n );\n return (\n <Flex\n align=\"center\"\n justify=\"between\"\n gap=\"3\"\n px=\"4\"\n style={{\n background: \"var(--accent-9)\",\n minHeight: \"var(--space-7)\",\n ...style,\n }}\n >\n {titleNode}\n {trailing}\n </Flex>\n );\n}\n\n/**\n * AccentCard — white panel with an AccentHeader bar and rounded corners\n * (measured r≈14 @1728 → var(--radius-5)) plus the soft card shadow seen on\n * every Figma card. The header is clipped by the card's radius.\n */\nexport interface AccentCardProps extends AccentHeaderProps {\n children: ReactNode;\n /** Radix padding scale for the body. Defaults to \"4\"; use \"0\" for flush content. */\n bodyPadding?: \"0\" | \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\";\n}\n\nexport function AccentCard({\n title,\n trailing,\n children,\n bodyPadding = \"4\",\n style,\n}: AccentCardProps) {\n return (\n <Box\n style={{\n background: \"var(--color-panel-solid)\",\n borderRadius: \"var(--radius-5)\",\n overflow: \"hidden\",\n boxShadow: \"var(--shadow-card)\",\n ...style,\n }}\n >\n <AccentHeader title={title} trailing={trailing} />\n <Box p={bodyPadding}>{children}</Box>\n </Box>\n );\n}\n\nexport default AccentHeader;\n","import type { ReactNode } from \"react\";\nimport { AlertDialog, Button } from \"@radix-ui/themes\";\nimport { layout } from \"./layout-tokens\";\nimport { CardFooter } from \"./CardFooter\";\n\n/**\n * ConfirmDialog — the confirm/cancel prompt used for destructive or\n * state-changing actions (Confirm Logout, Remove account, etc). Built on\n * Radix `AlertDialog` with a plain title/description and bottom-right\n * actions, matching the app's other dialogs (e.g. ImportCalendarsDialog):\n * neutral outline Cancel, amber-primary Confirm.\n */\nexport interface ConfirmDialogProps {\n /** Dialog title, rendered inside the AccentHeader bar. */\n title: ReactNode;\n /** Question / body copy. */\n description: ReactNode;\n /** Confirm button label. Defaults to \"Yes\". */\n confirmLabel?: ReactNode;\n /** Cancel button label. Defaults to \"Cancel\". */\n cancelLabel?: ReactNode;\n /** Called when the confirm action is activated (dialog still closes via AlertDialog.Action). */\n onConfirm?: () => void;\n /** Element that opens the dialog, rendered inside AlertDialog.Trigger. Omit for a fully controlled dialog. */\n trigger?: ReactNode;\n /** Controlled open state — omit for uncontrolled, trigger-driven usage. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\nexport function ConfirmDialog({\n title,\n description,\n confirmLabel = \"Yes\",\n cancelLabel = \"Cancel\",\n onConfirm,\n trigger,\n open,\n onOpenChange,\n}: ConfirmDialogProps) {\n return (\n <AlertDialog.Root open={open} onOpenChange={onOpenChange}>\n {trigger ? <AlertDialog.Trigger>{trigger}</AlertDialog.Trigger> : null}\n <AlertDialog.Content maxWidth={layout.dialogSm}>\n <AlertDialog.Title\n size=\"5\"\n mb=\"1\"\n style={{ fontFamily: \"var(--heading-font-family)\", fontWeight: \"var(--font-weight-medium)\" }}\n >\n {title}\n </AlertDialog.Title>\n <AlertDialog.Description size=\"2\" color=\"gray\" mb=\"5\">\n {description}\n </AlertDialog.Description>\n <CardFooter justify=\"between\" noTopMargin>\n <AlertDialog.Cancel>\n <Button size=\"2\" variant=\"outline\" color=\"gray\">\n {cancelLabel}\n </Button>\n </AlertDialog.Cancel>\n <AlertDialog.Action>\n <Button size=\"2\" className=\"btn-amber-primary\" onClick={onConfirm}>\n {confirmLabel}\n </Button>\n </AlertDialog.Action>\n </CardFooter>\n </AlertDialog.Content>\n </AlertDialog.Root>\n );\n}\n\nexport default ConfirmDialog;\n","/** Radix space-scale layout widths. Originally a subset of the app's\n * src/lib/layout-tokens.ts covering only what this package's own components\n * reference; now also exported so consumers stop hand-rolling their own\n * copies (arm-admin had none at all, and core-fe carries a 5-constant\n * fork). Values must match the app's copy — see README.md's \"Files\n * duplicated from the app\". */\nexport const layout = {\n contentMax: \"calc(15 * var(--space-9) + var(--space-5))\",\n accountCardW: \"calc(3 * var(--space-9) + var(--space-8))\",\n accountCardMinH: \"calc(2 * var(--space-9) - var(--space-2))\",\n monthTitleMinW: \"calc(3 * var(--space-9) - var(--space-1))\",\n bigCalendarH: \"calc(10 * var(--space-9))\",\n sidebarColBasis: \"calc(4 * var(--space-9) - var(--space-2))\",\n sidebarColMin: \"calc(3 * var(--space-9) + var(--space-6))\",\n syncColMin: \"calc(5 * var(--space-9))\",\n syncColWide: \"calc(7 * var(--space-9) + var(--space-6))\",\n dialogSm: \"calc(6 * var(--space-9) - var(--space-2))\",\n dialogBody: \"calc(5 * var(--space-9) + var(--space-7))\",\n authFormMax: \"calc(6 * var(--space-9) + var(--space-8))\",\n brandLogoMax: \"calc(6 * var(--space-9) + var(--space-8) - var(--space-1))\",\n connectedAccountCardH: \"calc(var(--space-9) - var(--space-1))\",\n dialogMd: \"calc(6 * var(--space-9) + var(--space-6))\",\n dialogLg: \"calc(7 * var(--space-9) - var(--space-1))\",\n emptyStateMax: \"calc(10 * var(--space-9))\",\n emptyStateCopyMax: \"calc(6 * var(--space-9))\",\n providerChooserMax: \"calc(6 * var(--space-9) + var(--space-6))\",\n /* Admin portal. The two audit columns are fixed so the header grid and\n * every row grid resolve to the same track sizes; settingsGridMin is the\n * floor that keeps a 5–6 column table legible before it starts scrolling\n * horizontally instead of crushing its columns. */\n auditColTime: \"calc(var(--space-9) + var(--space-2))\",\n auditColAction: \"calc(var(--space-9) + var(--space-5) + var(--space-1))\",\n searchFieldW: \"calc(3 * var(--space-9) + var(--space-5) + var(--space-1))\",\n settingsGridMin: \"calc(5 * var(--space-9) + var(--space-5))\",\n placeholderMd: \"calc(6 * var(--space-9) + var(--space-4))\",\n} as const;\n","import type { ReactNode } from \"react\";\nimport { Flex } from \"@radix-ui/themes\";\n\nexport interface CardFooterProps {\n children: ReactNode;\n justify?: \"end\" | \"between\";\n /** Omit the top margin when the content above already ends with its own\n * bottom margin/gap (e.g. Flex `mb`) — avoids doubled spacing. */\n noTopMargin?: boolean;\n /** Match the enclosing container's own padding so the negative-margin\n * breakout lines up flush with its edges. Defaults to Card size=\"3\"'s\n * var(--space-5); pass the container's actual padding otherwise (e.g.\n * a default-size Card's var(--space-3), StepCard's var(--space-4)). */\n pad?: string;\n /** Match the enclosing container's own corner radius so the footer's\n * bottom corners line up. Defaults to Card size=\"3\"+'s var(--radius-5);\n * default-size Card (1-2) uses var(--radius-4). */\n radius?: string;\n}\n\n/** Full-bleed gray action bar for the bottom of a Card — breaks out of the\n * Card's own padding so it reads as a distinct footer strip, same shape as\n * ImportCalendarsDialog's button row. Use for any Card/Dialog that ends in\n * one or more buttons instead of a plain Separator + Flex. */\nexport function CardFooter({\n children,\n justify = \"end\",\n noTopMargin,\n pad = \"var(--space-5)\",\n radius = \"var(--radius-5)\",\n}: CardFooterProps) {\n return (\n <Flex\n justify={justify}\n style={{\n margin: `${noTopMargin ? \"0\" : \"var(--space-5)\"} calc(-1 * ${pad}) calc(-1 * ${pad})`,\n padding: `var(--space-4) ${pad}`,\n alignItems: \"center\",\n background: \"var(--gray-2)\",\n borderTop: \"1px solid var(--gray-5)\",\n borderRadius: `0 0 ${radius} ${radius}`,\n }}\n >\n {children}\n </Flex>\n );\n}\n","import type { CSSProperties } from \"react\";\nimport { PauseIcon } from \"@radix-ui/react-icons\";\nimport { iconSize } from \"./icon-size\";\n\n/**\n * PausedBadge — small outline pill marking a paused account. Sits top-left\n * of AccountCard, immediately right of the avatar. White fill, 1px\n * `--color-paused` border + text, full radius pill, a tiny circled pause\n * glyph, then the label.\n *\n * Figma ref: ui-ux/figma/crops/account-card-menu.png. Measured 59×17 @1728\n * (≈49×14 app scale) — genuinely tiny, so this is built directly rather than\n * from Radix `Badge` (Badge's smallest size/padding can't hit an 18px\n * height). Fit level: Light customization.\n *\n * Deviation: the glyph inside the circle is rendered at 8px rather than the\n * ~10px in the base spec — at 10px it collided with the circle's stroke at\n * this scale, so it was sized down to keep the badge legible instead of\n * cluttered.\n */\nexport interface PausedBadgeProps {\n label?: string;\n style?: CSSProperties;\n}\n\nexport function PausedBadge({ label = \"Paused\", style }: PausedBadgeProps) {\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"var(--space-1)\",\n height: \"calc(var(--space-4) + var(--space-1))\",\n padding: \"var(--space-1) var(--space-2)\",\n border: \"1px solid var(--color-paused)\",\n borderRadius: 999,\n background: \"var(--color-panel-solid)\",\n color: \"var(--color-paused)\",\n fontSize: \"var(--font-size-1)\",\n fontWeight: 600,\n lineHeight: 1,\n whiteSpace: \"nowrap\",\n ...style,\n }}\n >\n <span\n aria-hidden=\"true\"\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"var(--space-3)\",\n height: \"var(--space-3)\",\n flexShrink: 0,\n borderRadius: \"50%\",\n border: \"1px solid var(--color-paused)\",\n }}\n >\n <PauseIcon style={iconSize(\"--space-2\")} />\n </span>\n {label}\n </span>\n );\n}\n\nexport default PausedBadge;\n","import type { CSSProperties } from \"react\";\n\n/** Square size for a Radix icon, expressed on the Radix space scale.\n *\n * Icons must be sized through `style`, never through the `width`/`height`\n * props. Those props land on the underlying `<svg>` as presentation\n * attributes, and SVG attributes do not accept CSS custom properties — the\n * browser rejects `width=\"var(--space-4)\"` outright and the icon falls back\n * to its intrinsic 300x300 default. That is not a cosmetic problem: a 300px\n * icon inside a toolbar covers the page and swallows every click behind it\n * (this is exactly what happened to Topbar's mobile hamburger).\n *\n * Going through `style` resolves the var and keeps icon sizes on the space\n * scale, so they still track the Theme's `scaling` prop.\n */\nexport function iconSize(space: `--space-${number}`): CSSProperties {\n return { width: `var(${space})`, height: `var(${space})` };\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { Avatar, Box, DropdownMenu, Flex, IconButton, Text } from \"@radix-ui/themes\";\nimport { DotsVerticalIcon, PauseIcon, PlayIcon, TrashIcon } from \"@radix-ui/react-icons\";\nimport { layout } from \"./layout-tokens\";\nimport { PausedBadge } from \"./PausedBadge\";\n\n/**\n * AccountCard — the account tile used on the accounts grid: avatar + name +\n * email, an optional PausedBadge, and a kebab menu (Pause/Resume, Delete).\n *\n * Figma refs: ui-ux/figma/crops/account-grid-clean.png (clean 4×2 grid),\n * ui-ux/figma/crops/account-card-menu.png (paused card, kebab menu open).\n * Fit level: Direct/Light — Card composition + DropdownMenu with a native\n * red item (no custom menu styling needed).\n */\nexport interface AccountCardProps {\n name: string;\n email: string;\n avatarSrc?: string;\n /** Shows PausedBadge next to the avatar and swaps the kebab's first item to \"Resume\". */\n paused?: boolean;\n onPause?: () => void;\n onResume?: () => void;\n onDelete?: () => void;\n /** Makes the card clickable (kebab menu excluded) — e.g. open the account's sync setup. */\n onClick?: () => void;\n /** Small overlay badge on the avatar's corner — e.g. a provider logo. */\n badge?: ReactNode;\n /** Tints the avatar with the account's color token (e.g. \"var(--blue-9)\"). */\n accentColor?: string;\n style?: CSSProperties;\n}\n\nexport function AccountCard({\n name,\n email,\n avatarSrc,\n paused = false,\n onPause,\n onResume,\n onDelete,\n onClick,\n badge,\n accentColor,\n style,\n}: AccountCardProps) {\n const nameText = (\n <Text as={onClick ? \"span\" : \"p\"} size=\"3\" weight=\"medium\" truncate style={{ color: \"var(--gray-12)\", minWidth: 0 }}>\n {name}\n </Text>\n );\n\n return (\n /* The card takes the mouse click, but it is not role=\"button\": the kebab\n * inside it would then be a control nested in a control, which keyboard and\n * screen-reader users cannot reach. The name is the keyboard control. */\n <Box\n onClick={onClick}\n style={{\n width: layout.accountCardW,\n minHeight: layout.accountCardMinH,\n padding: \"var(--space-3)\",\n background: \"var(--color-panel-solid)\",\n borderRadius: \"var(--radius-4)\",\n boxShadow: \"var(--shadow-card)\",\n cursor: onClick ? \"pointer\" : undefined,\n ...style,\n }}\n >\n <Flex align=\"center\" justify=\"between\" gap=\"2\" mb=\"3\">\n <Flex align=\"center\" gap=\"2\" style={{ minWidth: 0 }}>\n <div style={{ position: \"relative\", flexShrink: 0 }}>\n <Avatar\n size=\"3\"\n radius=\"full\"\n src={avatarSrc}\n fallback={name.charAt(0).toUpperCase() || \"?\"}\n style={\n accentColor\n ? { background: accentColor, color: \"white\" }\n : undefined\n }\n />\n {badge && (\n <span\n style={{\n position: \"absolute\",\n right: \"calc(-1 * var(--space-1))\",\n bottom: \"calc(-1 * var(--space-1))\",\n width: \"var(--space-4)\",\n height: \"var(--space-4)\",\n borderRadius: \"50%\",\n background: \"var(--color-panel-solid)\",\n border: \"1px solid var(--gray-4)\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transform: \"scale(0.72)\",\n }}\n >\n {badge}\n </span>\n )}\n </div>\n {paused && <PausedBadge />}\n </Flex>\n\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconButton\n variant=\"ghost\"\n color=\"gray\"\n aria-label=\"Account actions\"\n style={{ flexShrink: 0 }}\n onClick={(e) => e.stopPropagation()}\n >\n <DotsVerticalIcon />\n </IconButton>\n </DropdownMenu.Trigger>\n {/* Portal content still bubbles through the React tree — keep menu\n clicks from triggering the card's onClick */}\n <DropdownMenu.Content align=\"end\" onClick={(e) => e.stopPropagation()}>\n {paused ? (\n <DropdownMenu.Item onSelect={onResume}>\n <PlayIcon /> Resume\n </DropdownMenu.Item>\n ) : (\n <DropdownMenu.Item onSelect={onPause}>\n <PauseIcon /> Pause\n </DropdownMenu.Item>\n )}\n <DropdownMenu.Item color=\"red\" onSelect={onDelete}>\n <TrashIcon /> Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </Flex>\n\n <Box style={{ minWidth: 0 }}>\n {onClick ? (\n <button\n type=\"button\"\n className=\"card-title-button\"\n onClick={(e) => {\n e.stopPropagation();\n onClick();\n }}\n >\n {nameText}\n </button>\n ) : (\n nameText\n )}\n <Text as=\"p\" size=\"1\" color=\"gray\" truncate>\n {email}\n </Text>\n </Box>\n </Box>\n );\n}\n\nexport default AccountCard;\n","import type { CSSProperties } from \"react\";\nimport { Box, Flex, Heading, IconButton, Text } from \"@radix-ui/themes\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"@radix-ui/react-icons\";\nimport { layout } from \"./layout-tokens\";\nimport { iconSize } from \"./icon-size\";\nimport { headingSize } from \"./heading-scale\";\n\n/**\n * MonthGrid — the month calendar grid from the Preview card (Target/Source\n * Calendar → Preview flow). Pure Date math, no date library: weeks start\n * Monday (Figma starts its week on Mon), and only the leading/trailing\n * adjacent-month days needed to complete the first and last week are\n * rendered (not a fixed 6 rows).\n *\n * Fit level: Truly custom (only genuine no-Radix-equivalent gap — layout via\n * CSS grid, no date lib).\n * Figma refs: ui-ux/figma/crops/preview-month.png, ui-ux/figma/crops/month-card.png.\n */\nexport interface MonthGridProps {\n /** Any date within the month to display. */\n month: Date;\n /** Called with the first-of-month date when the prev/next chevrons are used. */\n onMonthChange?: (date: Date) => void;\n /** Days that should render an event dot (matched by calendar day, time ignored). */\n events?: Date[];\n /** Per-day colored dots keyed by `date.toDateString()` → CSS color tokens (max 3 shown).\n * Takes precedence over `events` when a day has an entry. */\n dayDots?: Map<string, string[]>;\n /** Defaults to `new Date()`. Pass a fixed date for stable/deterministic visuals. */\n today?: Date;\n /** Makes day cells clickable buttons; receives the clicked date. */\n onSelectDay?: (date: Date) => void;\n style?: CSSProperties;\n}\n\nconst WEEKDAY_LABELS = [\"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\", \"Sun\"];\nconst CELL_WIDTH = \"var(--space-9)\";\nconst CELL_HEIGHT = \"var(--space-8)\";\nconst GRID_GAP = \"var(--space-2)\";\n\nconst MONTH_YEAR_FORMAT = new Intl.DateTimeFormat(\"en-US\", { month: \"long\", year: \"numeric\" });\nconst FULL_DATE_FORMAT = new Intl.DateTimeFormat(\"en-US\", {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n});\n\nfunction isSameDay(a: Date, b: Date): boolean {\n return (\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n );\n}\n\n/** JS `getDay()` is 0=Sunday..6=Saturday; remap to 0=Monday..6=Sunday. */\nfunction mondayIndex(jsDay: number): number {\n return (jsDay + 6) % 7;\n}\n\ninterface GridDay {\n date: Date;\n inCurrentMonth: boolean;\n}\n\n/** Builds exactly the weeks needed to cover `month`, Monday-first, padding\n * only the leading/trailing days required to complete the first/last row. */\nfunction buildGridDays(month: Date): GridDay[] {\n const monthIndex = month.getMonth();\n const year = month.getFullYear();\n\n const firstOfMonth = new Date(year, monthIndex, 1);\n const lastOfMonth = new Date(year, monthIndex + 1, 0);\n\n const leadingCount = mondayIndex(firstOfMonth.getDay());\n const trailingCount = 6 - mondayIndex(lastOfMonth.getDay());\n\n const gridStart = new Date(year, monthIndex, 1 - leadingCount);\n const totalDays = leadingCount + lastOfMonth.getDate() + trailingCount;\n\n return Array.from({ length: totalDays }, (_, i) => {\n const date = new Date(gridStart.getFullYear(), gridStart.getMonth(), gridStart.getDate() + i);\n return { date, inCurrentMonth: date.getMonth() === monthIndex };\n });\n}\n\nfunction addMonths(date: Date, delta: number): Date {\n return new Date(date.getFullYear(), date.getMonth() + delta, 1);\n}\n\nexport function MonthGrid({\n month,\n onMonthChange,\n events = [],\n dayDots,\n today,\n onSelectDay,\n style,\n}: MonthGridProps) {\n const resolvedToday = today ?? new Date();\n const days = buildGridDays(month);\n const eventDayKeys = new Set(events.map((d) => d.toDateString()));\n\n return (\n <Flex direction=\"column\" align=\"center\" gap=\"4\" style={style}>\n {/* Header: ‹ March 2022 › */}\n <Flex align=\"center\" gap=\"2\">\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n color=\"gray\"\n aria-label=\"Previous month\"\n onClick={() => onMonthChange?.(addMonths(month, -1))}\n >\n <ChevronLeftIcon style={iconSize(\"--space-4\")} />\n </IconButton>\n <Heading\n as=\"h2\"\n size={headingSize.h2}\n weight=\"medium\"\n style={{ minWidth: layout.monthTitleMinW, textAlign: \"center\" }}\n >\n {MONTH_YEAR_FORMAT.format(month)}\n </Heading>\n <IconButton\n type=\"button\"\n variant=\"ghost\"\n color=\"gray\"\n aria-label=\"Next month\"\n onClick={() => onMonthChange?.(addMonths(month, 1))}\n >\n <ChevronRightIcon style={iconSize(\"--space-4\")} />\n </IconButton>\n </Flex>\n\n {/* Weekday row */}\n <Box\n style={{\n display: \"grid\",\n gridTemplateColumns: `repeat(7, ${CELL_WIDTH})`,\n gap: GRID_GAP,\n }}\n >\n {WEEKDAY_LABELS.map((label) => (\n <Text\n key={label}\n size=\"2\"\n align=\"center\"\n style={{ color: \"var(--gray-11)\" }}\n >\n {label}\n </Text>\n ))}\n </Box>\n\n {/* Date grid */}\n <Box\n style={{\n display: \"grid\",\n gridTemplateColumns: `repeat(7, ${CELL_WIDTH})`,\n gap: GRID_GAP,\n }}\n >\n {days.map(({ date, inCurrentMonth }) => {\n const isToday = isSameDay(date, resolvedToday);\n const dots = dayDots?.get(date.toDateString());\n const hasEvent = eventDayKeys.has(date.toDateString());\n\n const cellStyle: CSSProperties = {\n position: \"relative\",\n width: CELL_WIDTH,\n height: CELL_HEIGHT,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxSizing: \"border-box\",\n background: !inCurrentMonth\n ? \"var(--gray-2)\"\n : isToday\n ? \"var(--color-panel-solid)\"\n : \"transparent\",\n border: isToday ? \"1.5px solid var(--accent-9)\" : \"none\",\n borderRadius: isToday ? \"var(--radius-3)\" : !inCurrentMonth ? \"var(--radius-2)\" : undefined,\n padding: 0,\n font: \"inherit\",\n cursor: onSelectDay ? \"pointer\" : undefined,\n };\n\n const dayNumber = (\n <>\n {dots && dots.length > 0 ? (\n <span\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n bottom: \"var(--space-1)\",\n left: 0,\n right: 0,\n display: \"flex\",\n justifyContent: \"center\",\n gap: \"2px\",\n }}\n >\n {dots.slice(0, 3).map((color, i) => (\n <span\n key={i}\n style={{\n width: \"var(--space-1)\",\n height: \"var(--space-1)\",\n borderRadius: \"50%\",\n background: color,\n }}\n />\n ))}\n </span>\n ) : (\n hasEvent && (\n <span\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n top: \"var(--space-1)\",\n right: \"var(--space-2)\",\n width: \"var(--space-2)\",\n height: \"var(--space-2)\",\n borderRadius: \"50%\",\n background: \"var(--accent-9)\",\n }}\n />\n )\n )}\n <Text\n size=\"3\"\n style={{\n color: inCurrentMonth ? \"var(--gray-12)\" : \"var(--gray-11)\",\n fontWeight: isToday ? 600 : 400,\n }}\n >\n {date.getDate()}\n </Text>\n </>\n );\n\n const key = date.toISOString();\n\n if (onSelectDay) {\n return (\n <button\n key={key}\n type=\"button\"\n onClick={() => onSelectDay(date)}\n aria-label={FULL_DATE_FORMAT.format(date)}\n style={cellStyle}\n >\n {dayNumber}\n </button>\n );\n }\n\n return (\n <div key={key} style={cellStyle}>\n {dayNumber}\n </div>\n );\n })}\n </Box>\n </Flex>\n );\n}\n\nexport default MonthGrid;\n","/**\n * One heading size per level, for every `<Heading>` in the platform.\n *\n * Headings used to pick a Radix `size` per instance, so the same `<h1>`\n * rendered at 14.4px in the shell, 16.2px in a remote and 18px on Home, and\n * an `<h3>` could equal its own `<h1>` or the 12.6px body copy. The level now\n * decides the size: pass `size={headingSize[level]}` alongside `as={level}`.\n *\n * Values are Radix font-size steps, so they follow the Theme's `scaling`. At\n * the platform's 90% that is h1 21.6px, h2 18px, h3 16.2px, h4 14.4px — every\n * level one step apart and above body text (step 2, 12.6px).\n */\nexport const headingSize = {\n h1: \"6\",\n h2: \"5\",\n h3: \"4\",\n h4: \"3\",\n} as const;\n\nexport type HeadingLevel = keyof typeof headingSize;\n\n/** Radix step body copy renders at — every heading level must sit above it. */\nexport const BODY_TEXT_SIZE = \"2\";\n","import { useEffect } from \"react\";\nimport { Callout } from \"@radix-ui/themes\";\nimport { CheckCircledIcon, ExclamationTriangleIcon } from \"@radix-ui/react-icons\";\nimport { layout } from \"./layout-tokens\";\n\nexport interface ToastProps {\n msg: string;\n color?: \"green\" | \"red\";\n onDone: () => void;\n durationMs?: number;\n}\n\n/** Fixed bottom-right auto-dismissing confirmation — the shared shape for\n * \"did my save work\" feedback across the app (previously a one-off local\n * component on AdminUserDetailPage only). */\nexport function Toast({ msg, color = \"green\", onDone, durationMs = 3000 }: ToastProps) {\n useEffect(() => {\n const t = setTimeout(onDone, durationMs);\n return () => clearTimeout(t);\n }, [onDone, durationMs]);\n\n return (\n <div\n style={{\n position: \"fixed\",\n bottom: \"var(--space-5)\",\n right: \"var(--space-5)\",\n zIndex: 10000,\n maxWidth: layout.dialogBody,\n pointerEvents: \"none\",\n }}\n >\n <Callout.Root color={color} variant=\"soft\" size=\"1\">\n <Callout.Icon>\n {color === \"red\" ? <ExclamationTriangleIcon /> : <CheckCircledIcon />}\n </Callout.Icon>\n <Callout.Text>{msg}</Callout.Text>\n </Callout.Root>\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\n\n/**\n * IconTile — the app's one icon-well treatment: a bordered rounded-square\n * tile around a feature/action/logo icon. Used for app-shortcut icons,\n * provider/account logos, and empty-state icons alike, so every \"icon in a\n * box\" in the app reads as the same component instead of one-off inline\n * styles with drifting border/radius/fill choices.\n */\nexport interface IconTileProps {\n children: ReactNode;\n /** Tile size — defaults to var(--space-7), the size used across the app. */\n size?: string;\n}\n\nexport function IconTile({ children, size = \"var(--space-7)\" }: IconTileProps) {\n return (\n <div\n style={{\n width: size,\n height: size,\n borderRadius: \"var(--radius-4)\",\n background: \"var(--color-panel-solid)\",\n border: \"1px solid var(--gray-5)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n }}\n >\n {children}\n </div>\n );\n}\n\nexport default IconTile;\n","import { Box, Flex, Text } from \"@radix-ui/themes\";\nimport { LockClosedIcon } from \"@radix-ui/react-icons\";\n\nexport interface EventBlockProps {\n title: string;\n time: string;\n detail?: string;\n color: string;\n locked?: boolean;\n}\n\n/** Solid-colored calendar-event chip — a filled block in the sync's own\n * color with white text, matching OneCal's SYNC PREVIEW mockups. Used\n * anywhere a real (or sample) event needs to read as \"this calendar's\n * color\", not a thin accent bar + badge. */\nexport function EventBlock({ title, time, detail, color, locked }: EventBlockProps) {\n return (\n <Flex\n align=\"center\"\n justify=\"between\"\n style={{\n background: color,\n borderRadius: \"var(--radius-3)\",\n padding: \"var(--space-3)\",\n color: \"white\",\n }}\n >\n <Box style={{ minWidth: 0 }}>\n <Text as=\"p\" size=\"2\" weight=\"medium\" style={{ color: \"white\" }} truncate>\n {title}\n </Text>\n <Text as=\"p\" size=\"1\" style={{ color: \"rgba(255,255,255,0.85)\" }} truncate>\n {time}\n {detail ? ` · ${detail}` : \"\"}\n </Text>\n </Box>\n {locked && <LockClosedIcon style={{ flexShrink: 0, color: \"rgba(255,255,255,0.85)\" }} />}\n </Flex>\n );\n}\n","import type { KeyboardEvent, ReactNode } from \"react\";\nimport { Box } from \"@radix-ui/themes\";\n\nexport interface DataTableRowProps {\n children: ReactNode;\n /** Grid/flex layout for the row — e.g. `{ display: \"grid\", gridTemplateColumns: \"2fr 1fr 1fr\" }`.\n * Column shape varies per table, so it's always supplied by the caller rather than fixed here. */\n style?: React.CSSProperties;\n /** Draws the row separator above every row except the first — pass `idx > 0`. */\n showBorder?: boolean;\n /** Makes the row a keyboard-focusable, clickable target (role=\"button\", Enter/Space activation,\n * amber focus ring). Omit for plain display rows (most tables — see CalendarSyncsPage, which\n * keeps its per-cell action button interactive instead of the row). */\n onActivate?: () => void;\n /** Highlights the row as the current selection — only meaningful with `onActivate`. */\n selected?: boolean;\n className?: string;\n \"aria-label\"?: string;\n}\n\n/** Shared plumbing for the dense data-table-row pattern used across the admin\n * users/audit tables, calendar syncs list, and home activity feed: hover\n * wash, optional keyboard-accessible selection, and the border-top-except-\n * first-row rule. Deliberately layout-agnostic — each table's column count\n * and widths differ (see globals.css's own `.data-table-row` comment history),\n * so `style` carries the grid/flex shape and `children` carries the cells;\n * this component only owns the classes and interaction/border wiring that\n * were previously hand-copied into five separate page files. */\nexport function DataTableRow({\n children,\n style,\n showBorder = false,\n onActivate,\n selected = false,\n className,\n \"aria-label\": ariaLabel,\n}: DataTableRowProps) {\n const interactive = Boolean(onActivate);\n\n function handleKeyDown(e: KeyboardEvent<HTMLDivElement>) {\n if (!onActivate) return;\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onActivate();\n }\n }\n\n return (\n <Box\n role={interactive ? \"button\" : undefined}\n tabIndex={interactive ? 0 : undefined}\n aria-label={ariaLabel}\n onClick={onActivate}\n onKeyDown={interactive ? handleKeyDown : undefined}\n className={[\n \"data-table-row\",\n interactive && \"data-table-row--interactive\",\n interactive && selected && \"data-table-row--selected\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n style={{\n borderTop: showBorder ? \"1px solid var(--gray-3)\" : undefined,\n ...style,\n }}\n >\n {children}\n </Box>\n );\n}\n","import { useId } from \"react\";\nimport { Card, Flex, Text } from \"@radix-ui/themes\";\n\nexport interface MetricCardProps {\n label: string;\n value: string;\n delta: string;\n deltaDir: \"up\" | \"down\" | \"flat\";\n /** Which delta direction reads as \"good\" for this metric — e.g. \"up\" for\n * revenue, \"down\" for error rate. Colors the delta text green/red. */\n goodDirection: \"up\" | \"down\";\n /** Status-dot color (top-right corner) — pass a semantic token\n * (`var(--green-9)`, `var(--red-9)`, `var(--amber-9)`, `var(--gray-9)`). */\n statusColor: string;\n /** Recent-history series for the inline sparkline. */\n sparkline: number[];\n}\n\n/** Admin/platform stat tile: label + status dot, big value, delta indicator,\n * inline sparkline. Used for dashboard \"platform health\" grids. */\nexport function MetricCard({\n label,\n value,\n delta,\n deltaDir,\n goodDirection,\n statusColor,\n sparkline,\n}: MetricCardProps) {\n const deltaColor =\n deltaDir === \"flat\"\n ? \"var(--gray-11)\"\n : deltaDir === goodDirection\n ? \"var(--green-11)\"\n : \"var(--red-11)\";\n\n const deltaPrefix = deltaDir === \"up\" ? \"↑ \" : deltaDir === \"down\" ? \"↓ \" : \"\";\n\n return (\n <Card className=\"metric-card\">\n <Flex direction=\"column\" p=\"1\">\n {/* Label + status dot */}\n <Flex align=\"center\" justify=\"between\" mb=\"3\">\n <Text as=\"span\" className=\"ds-section-label\">{label}</Text>\n <div\n style={{\n width: \"var(--space-2)\",\n height: \"var(--space-2)\",\n borderRadius: \"50%\",\n background: statusColor,\n flexShrink: 0,\n }}\n />\n </Flex>\n\n {/* Metric value */}\n <Text as=\"p\" className=\"metric-card-value\">\n {value}\n </Text>\n\n {/* Delta + sparkline */}\n <Flex align=\"end\" justify=\"between\">\n <Text size=\"1\" style={{ color: deltaColor, lineHeight: 1.4 }}>\n {deltaPrefix}\n {delta}\n </Text>\n <Sparkline data={sparkline} color={statusColor} />\n </Flex>\n </Flex>\n </Card>\n );\n}\n\nfunction Sparkline({ data, color }: { data: number[]; color: string }) {\n const W = 72;\n const H = 28;\n const min = Math.min(...data);\n const max = Math.max(...data);\n const range = max - min || 1;\n\n const pts = data.map((v, i) => ({\n x: (i / (data.length - 1)) * W,\n y: H - ((v - min) / range) * H * 0.75 - H * 0.1,\n }));\n\n const line = pts\n .map((p, i) => `${i === 0 ? \"M\" : \"L\"} ${p.x.toFixed(1)} ${p.y.toFixed(1)}`)\n .join(\" \");\n\n const area = [\n `M 0 ${H}`,\n ...pts.map((p) => `L ${p.x.toFixed(1)} ${p.y.toFixed(1)}`),\n `L ${W} ${H} Z`,\n ].join(\" \");\n\n // Per-instance id — a color-derived id collides when metrics share a\n // status color, making them all reference the first card's gradient.\n // useId's colons are stripped: they break url(#…) fragment references.\n const rawId = useId();\n const gradId = `spk${rawId.replace(/[^a-zA-Z0-9_-]/g, \"\")}`;\n\n return (\n <svg\n width={W}\n height={H}\n viewBox={`0 0 ${W} ${H}`}\n aria-hidden\n style={{ overflow: \"visible\", flexShrink: 0 }}\n >\n <defs>\n <linearGradient id={gradId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor={color} stopOpacity=\"0.18\" />\n <stop offset=\"100%\" stopColor={color} stopOpacity=\"0\" />\n </linearGradient>\n </defs>\n <path d={area} fill={`url(#${gradId})`} />\n <path\n d={line}\n fill=\"none\"\n stroke={color}\n strokeWidth=\"1.5\"\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { Badge, Button, Card, Flex, Text } from \"@radix-ui/themes\";\nimport { ArrowRightIcon } from \"@radix-ui/react-icons\";\nimport { IconTile } from \"./IconTile\";\nimport { CardFooter } from \"./CardFooter\";\nimport { iconSize } from \"./icon-size\";\n\nexport interface AppCardProps {\n href: string;\n icon: ReactNode;\n name: string;\n description: string;\n /** Short status shown as a pill after the name (\"BETA\"). It never shrinks,\n * so a long name truncates in front of it. */\n badge?: string;\n}\n\n/** Workspace-shortcut tile: icon + name header, description, \"Open\" CTA\n * footer. Used for the home dashboard's granted-apps grid. */\nexport function AppCard({ href, icon, name, description, badge }: AppCardProps) {\n return (\n <Card style={{ height: \"100%\", display: \"flex\", flexDirection: \"column\" }}>\n <Flex direction=\"column\" gap=\"3\" p=\"1\" flexGrow=\"1\">\n {/* Header row: icon well + name */}\n <Flex align=\"center\" gap=\"3\" minWidth=\"0\">\n <IconTile>{icon}</IconTile>\n <Text\n size=\"4\"\n weight=\"medium\"\n style={{ color: \"var(--gray-12)\", fontFamily: \"var(--font-poppins)\" }}\n truncate\n >\n {name}\n </Text>\n {badge && (\n <Badge color=\"gray\" variant=\"soft\" size=\"1\" radius=\"full\" style={{ flexShrink: 0 }}>\n {badge}\n </Badge>\n )}\n </Flex>\n\n <Text\n size=\"2\"\n style={{ color: \"var(--gray-11)\", fontFamily: \"var(--font-poppins)\", lineHeight: 1.5 }}\n >\n {description}\n </Text>\n </Flex>\n\n <CardFooter pad=\"var(--space-3)\" radius=\"var(--radius-4)\">\n <Button size=\"2\" className=\"btn-amber-primary\" asChild>\n <Link to={href}>\n Open\n <ArrowRightIcon style={iconSize(\"--space-3\")} />\n </Link>\n </Button>\n </CardFooter>\n </Card>\n );\n}\n","import { Text } from \"@radix-ui/themes\";\nimport { DataTableRow } from \"./DataTableRow\";\n\nexport interface ActivityRowProps {\n /** Short colored tag, e.g. \"AUTH\", \"ROLE\", \"PROV\" — matches an audit-log\n * action code. */\n tag: string;\n /** Tag color (semantic token, e.g. `var(--violet-9)`). */\n tagColor: string;\n msg: string;\n actor?: string;\n timeAgo?: string;\n timestamp: string;\n showBorder: boolean;\n}\n\n/** Sentry-style dense activity-feed row: colored type tag, message + actor,\n * optional relative time, and a right-aligned monospace timestamp. Built on\n * DataTableRow for the shared hover/border plumbing. */\nexport function ActivityRow({\n tag,\n tagColor,\n msg,\n actor,\n timeAgo,\n timestamp,\n showBorder,\n}: ActivityRowProps) {\n return (\n <DataTableRow\n showBorder={showBorder}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n paddingBlock: \"var(--space-2)\",\n paddingInline: \"var(--space-4)\",\n }}\n >\n {/* Type tag — monospace, colored */}\n <Text\n as=\"span\"\n size=\"1\"\n weight=\"medium\"\n className=\"data-mono\"\n style={{\n color: tagColor,\n minWidth: \"var(--space-6)\",\n letterSpacing: \"0.06em\",\n flexShrink: 0,\n }}\n >\n {tag}\n </Text>\n\n {/* Message + actor */}\n <Text\n as=\"span\"\n size=\"2\"\n style={{\n flex: 1,\n color: \"var(--gray-11)\",\n lineHeight: 1.4,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {msg}\n {actor && (\n <Text as=\"span\" size=\"1\" style={{ color: \"var(--gray-11)\", marginLeft: \"var(--space-2)\" }}>\n by {actor}\n </Text>\n )}\n </Text>\n\n {/* Time-ago (human-readable) */}\n {timeAgo && (\n <Text as=\"span\" size=\"1\" color=\"gray\" style={{ whiteSpace: \"nowrap\", flexShrink: 0 }}>\n {timeAgo}\n </Text>\n )}\n\n {/* HH:MM:SS — monospace clock */}\n <Text\n as=\"span\"\n size=\"1\"\n className=\"data-mono\"\n style={{\n color: \"var(--gray-11)\",\n whiteSpace: \"nowrap\",\n flexShrink: 0,\n minWidth: \"var(--space-7)\",\n textAlign: \"right\",\n }}\n >\n {timestamp}\n </Text>\n </DataTableRow>\n );\n}\n","import { Button, Card, Flex, Text } from \"@radix-ui/themes\";\nimport { ExclamationTriangleIcon } from \"@radix-ui/react-icons\";\nimport { IconTile } from \"./IconTile\";\nimport { iconSize } from \"./icon-size\";\n\nexport interface DashboardErrorCardProps {\n onRetry: () => void;\n /** Defaults to \"Couldn't load your dashboard.\" */\n message?: string;\n}\n\n/** Generic \"failed to load\" state: warning icon, message, Retry CTA. */\nexport function DashboardErrorCard({ onRetry, message = \"Couldn't load your dashboard.\" }: DashboardErrorCardProps) {\n return (\n <Card>\n <Flex direction=\"column\" align=\"center\" justify=\"center\" py=\"9\" gap=\"3\">\n <IconTile>\n <ExclamationTriangleIcon style={{ ...iconSize(\"--space-5\"), color: \"var(--gray-7)\" }} />\n </IconTile>\n <Text size=\"2\" color=\"gray\">\n {message}\n </Text>\n <Button size=\"2\" color=\"amber\" variant=\"solid\" className=\"btn-amber-primary\" onClick={onRetry}>\n Retry\n </Button>\n </Flex>\n </Card>\n );\n}\n","import { useMemo } from \"react\";\nimport { Button, Flex, IconButton, Text } from \"@radix-ui/themes\";\nimport {\n ChevronLeftIcon,\n ChevronRightIcon,\n DoubleArrowLeftIcon,\n DoubleArrowRightIcon,\n} from \"@radix-ui/react-icons\";\n\n/**\n * Pagination — windowed page-number nav for paginated tables.\n *\n * Neither Radix Themes nor this package covered pagination, so every app with\n * a server-paginated table grew its own. Promoted here from arm-admin so they\n * stop diverging. Composed entirely from Radix controls plus the brand\n * `btn-amber-primary` class for the current page — no utility-class colours\n * and no inline var() fallbacks.\n */\n\nconst ELLIPSIS = \"…\" as const;\n\n/** Windowed page list: always the first and last page, `siblingCount` either\n * side of the current one, and an ellipsis wherever a run is skipped. */\nfunction buildPageRange(\n currentPage: number,\n totalPages: number,\n siblingCount: number,\n): (number | typeof ELLIPSIS)[] {\n const totalVisible = siblingCount * 2 + 5;\n if (totalPages <= totalVisible) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n\n const leftSibling = Math.max(currentPage - siblingCount, 1);\n const rightSibling = Math.min(currentPage + siblingCount, totalPages);\n const showLeftEllipsis = leftSibling > 2;\n const showRightEllipsis = rightSibling < totalPages - 1;\n\n if (!showLeftEllipsis && showRightEllipsis) {\n const leftRange = Array.from({ length: 3 + siblingCount * 2 }, (_, i) => i + 1);\n return [...leftRange, ELLIPSIS, totalPages];\n }\n if (showLeftEllipsis && !showRightEllipsis) {\n const span = 3 + siblingCount * 2;\n const rightRange = Array.from({ length: span }, (_, i) => totalPages - span + i + 1);\n return [1, ELLIPSIS, ...rightRange];\n }\n const middleRange = Array.from(\n { length: rightSibling - leftSibling + 1 },\n (_, i) => leftSibling + i,\n );\n return [1, ELLIPSIS, ...middleRange, ELLIPSIS, totalPages];\n}\n\nexport interface PaginationProps {\n /** 1-based. */\n currentPage: number;\n totalPages: number;\n onPageChange: (page: number) => void;\n /** Pages shown either side of the current one. */\n siblingCount?: number;\n /** Adds jump-to-first / jump-to-last controls. */\n showFirstLast?: boolean;\n /** Radix control size. */\n size?: \"1\" | \"2\";\n}\n\nexport function Pagination({\n currentPage,\n totalPages,\n onPageChange,\n siblingCount = 1,\n showFirstLast = false,\n size = \"2\",\n}: PaginationProps) {\n const pages = useMemo(\n () => buildPageRange(currentPage, totalPages, siblingCount),\n [currentPage, totalPages, siblingCount],\n );\n\n const atFirst = currentPage <= 1;\n const atLast = currentPage >= totalPages;\n\n return (\n <Flex asChild align=\"center\" gap=\"1\">\n <nav aria-label=\"Pagination\">\n {showFirstLast && (\n <IconButton\n size={size}\n variant=\"soft\"\n color=\"gray\"\n aria-label=\"First page\"\n disabled={atFirst}\n onClick={() => onPageChange(1)}\n >\n <DoubleArrowLeftIcon />\n </IconButton>\n )}\n <IconButton\n size={size}\n variant=\"soft\"\n color=\"gray\"\n aria-label=\"Previous page\"\n disabled={atFirst}\n onClick={() => onPageChange(currentPage - 1)}\n >\n <ChevronLeftIcon />\n </IconButton>\n\n {pages.map((page, index) =>\n page === ELLIPSIS ? (\n <Text\n key={`ellipsis-${index}`}\n size={size}\n color=\"gray\"\n aria-hidden\n style={{ paddingInline: \"var(--space-1)\" }}\n >\n {ELLIPSIS}\n </Text>\n ) : (\n <Button\n key={page}\n size={size}\n aria-label={`Page ${page}`}\n aria-current={page === currentPage ? \"page\" : undefined}\n variant={page === currentPage ? \"solid\" : \"soft\"}\n color={page === currentPage ? undefined : \"gray\"}\n className={page === currentPage ? \"btn-amber-primary\" : undefined}\n onClick={() => page !== currentPage && onPageChange(page)}\n >\n {page}\n </Button>\n ),\n )}\n\n <IconButton\n size={size}\n variant=\"soft\"\n color=\"gray\"\n aria-label=\"Next page\"\n disabled={atLast}\n onClick={() => onPageChange(currentPage + 1)}\n >\n <ChevronRightIcon />\n </IconButton>\n {showFirstLast && (\n <IconButton\n size={size}\n variant=\"soft\"\n color=\"gray\"\n aria-label=\"Last page\"\n disabled={atLast}\n onClick={() => onPageChange(totalPages)}\n >\n <DoubleArrowRightIcon />\n </IconButton>\n )}\n </nav>\n </Flex>\n );\n}\n\nexport default Pagination;\n","import type { Role } from \"./Sidebar\";\n\n/**\n * Single source of truth for status / role / activity / audit colors.\n *\n * Every consumer that renders a user's role, account status or an audit row\n * previously defined its own map inline, and those copies had already started\n * to drift — the admin portal's audit action map went stale twice while its\n * action vocabulary grew, and only `tsc` caught it. Import from here instead.\n *\n * Two color conventions live side by side, matching how Radix is consumed:\n * - Radix accent names (\"amber\" | \"blue\" | ...) passed to <Badge color={...} />.\n * - Raw CSS-var tokens (e.g. \"var(--green-9)\") used for dots, tags and rails.\n */\n\n/* ── Role ──────────────────────────────────────────────────────────────── */\n\nexport const ROLE_META: Record<Role, { label: string; color: \"amber\" | \"blue\" | \"gray\" }> = {\n admin: { label: \"Admin\", color: \"amber\" },\n operator: { label: \"Operator\", color: \"blue\" },\n user: { label: \"Platform User\", color: \"gray\" },\n};\n\nexport const ROLE_LABELS: Record<Role, string> = {\n admin: ROLE_META.admin.label,\n operator: ROLE_META.operator.label,\n user: ROLE_META.user.label,\n};\n\n/* ── Account status ────────────────────────────────────────────────────── */\n\n/** Derived, not stored. `suspended` is an admin disabling the account;\n * `inactive` is an approved account nobody has signed into lately. Approval\n * state (pending / rejected) is a separate axis and gets its own badge —\n * an account can be approved and suspended at the same time. */\nexport type UserStatus = \"active\" | \"inactive\" | \"suspended\";\n\nexport const STATUS_META: Record<UserStatus, { label: string; color: string }> = {\n active: { label: \"Active\", color: \"var(--color-success)\" },\n inactive: { label: \"Inactive\", color: \"var(--gray-11)\" },\n suspended: { label: \"Suspended\", color: \"var(--color-danger)\" },\n};\n\n/* ── Metric health ─────────────────────────────────────────────────────── */\n\nexport type MetricStatus = \"ok\" | \"warn\" | \"error\";\n\n/* Step 9 here is correct and deliberately not moved to 11 with the tag colours\n * above. MetricCard renders this as a `background` on a status dot and as the\n * Sparkline stroke — graphical objects, judged against the 3:1 non-text bar,\n * which step 9 is designed for. Darkening it to a text step would mute the\n * indicator for no accessibility gain. */\nexport const METRIC_STATUS_COLOR: Record<MetricStatus, string> = {\n ok: \"var(--green-9)\",\n warn: \"var(--orange-9)\",\n error: \"var(--red-9)\",\n};\n\n/* ── Activity feed category ────────────────────────────────────────────── */\n\nexport type ActivityType = \"auth\" | \"sync\" | \"role\" | \"provision\" | \"health\" | \"error\";\n\nexport const ACTIVITY_META: Record<ActivityType, { tag: string; color: string }> = {\n auth: { tag: \"AUTH\", color: \"var(--gray-11)\" },\n sync: { tag: \"SYNC\", color: \"var(--blue-11)\" },\n role: { tag: \"ROLE\", color: \"var(--violet-11)\" },\n provision: { tag: \"PROV\", color: \"var(--green-11)\" },\n health: { tag: \"HLTH\", color: \"var(--teal-11)\" },\n error: { tag: \"ERR!\", color: \"var(--red-11)\" },\n};\n\n/* ── Audit log action ──────────────────────────────────────────────────── */\n\n/** The admin backend's own vocabulary — these strings are written by\n * `AuditService.log` and must match it exactly. `action` is a plain varchar\n * there, not a Postgres enum, so nothing but this map and a code review stops\n * the two drifting apart. Add here whenever a new action is logged. */\nexport type AuditAction =\n | \"USER_UPDATED\"\n | \"USER_DISABLED\"\n | \"USER_ENABLED\"\n | \"USER_APPROVED\"\n | \"USER_REJECTED\"\n | \"SIGNUP_NOTIFICATIONS_ON\"\n | \"SIGNUP_NOTIFICATIONS_OFF\"\n | \"APPROVAL_EMAIL_RESENT\"\n | \"USER_DELETED\"\n | \"ADMIN_GRANTED\"\n | \"ADMIN_REVOKED\"\n | \"ADMIN_ROLE_CHANGED\"\n | \"SESSION_REVOKED\"\n | \"APP_GRANTED\"\n | \"APP_REVOKED\"\n | \"BUNDLE_GRANTED\"\n | \"BUNDLE_REVOKED\"\n | \"APP_VALIDATED\"\n | \"APP_DEPLOY_REQUESTED\"\n | \"APP_DEPLOYED\"\n | \"APP_DEPLOY_FAILED\"\n | \"APP_REVERTED\"\n | \"APP_ROLLED_BACK\"\n | \"APP_REMOVED\"\n | \"APP_DEPLOY_GRANTS_FAILED\"\n | \"ADMIN_CHANGE_ROLLED_BACK\"\n | \"AUDIT_EXPORTED\"\n | \"SESSIONS_LISTED\";\n\n/** `badge` is for <Badge color={...} />, `tag`/`color` for the compact\n * monospace tag used in per-user activity lists.\n *\n * `color` is step **11**, not step 9. Step 9 is Radix's solid-background step\n * and was never a text colour: used as one it gave the amber UPD tag 1.58:1 on\n * white, teal 3.07:1 and orange 2.97:1 — the amber one close to invisible\n * rather than merely low-contrast, at 10.8px where the requirement is\n * strictest. Step 11 is the scale's low-contrast *text* step and clears 4.5:1\n * for every scale used here (4.51-6.17 on white).\n *\n * These tags render inside a Card, so white is the surface that matters. On a\n * #F6F6F6 surface amber, teal, green and orange land at 4.17-4.36 — under AA —\n * so do not move this tag onto the page background without re-measuring.\n *\n * `badge` is untouched: it feeds Radix's own <Badge>, which pairs its own text\n * and background steps. */\nexport const AUDIT_ACTION_META: Record<\n AuditAction,\n { label: string; tag: string; badge: \"amber\" | \"gray\" | \"yellow\" | \"red\" | \"green\"; color: string }\n> = {\n USER_UPDATED: { label: \"User updated\", tag: \"UPD\", badge: \"amber\", color: \"var(--amber-11)\" },\n USER_DISABLED: { label: \"User disabled\", tag: \"DIS\", badge: \"red\", color: \"var(--red-11)\" },\n USER_ENABLED: { label: \"User enabled\", tag: \"ENA\", badge: \"green\", color: \"var(--teal-11)\" },\n USER_APPROVED: { label: \"User approved\", tag: \"APPR\", badge: \"green\", color: \"var(--green-11)\" },\n USER_REJECTED: { label: \"User rejected\", tag: \"REJ\", badge: \"red\", color: \"var(--red-11)\" },\n SIGNUP_NOTIFICATIONS_ON: { label: \"Signup notifications on\", tag: \"NOTF\", badge: \"gray\", color: \"var(--gray-11)\" },\n SIGNUP_NOTIFICATIONS_OFF: { label: \"Signup notifications off\", tag: \"NOTF\", badge: \"gray\", color: \"var(--gray-11)\" },\n APPROVAL_EMAIL_RESENT: { label: \"Approval email resent\", tag: \"MAIL\", badge: \"amber\", color: \"var(--amber-11)\" },\n USER_DELETED: { label: \"User deleted\", tag: \"DEL\", badge: \"yellow\", color: \"var(--red-11)\" },\n ADMIN_GRANTED: { label: \"Admin granted\", tag: \"ADMN\", badge: \"gray\", color: \"var(--violet-11)\" },\n ADMIN_REVOKED: { label: \"Admin revoked\", tag: \"ADMN\", badge: \"gray\", color: \"var(--orange-11)\" },\n ADMIN_ROLE_CHANGED: { label: \"Role changed\", tag: \"ROLE\", badge: \"amber\", color: \"var(--violet-11)\" },\n SESSION_REVOKED: { label: \"Session revoked\", tag: \"SESS\", badge: \"gray\", color: \"var(--gray-11)\" },\n APP_GRANTED: { label: \"App access granted\", tag: \"APP\", badge: \"green\", color: \"var(--green-11)\" },\n APP_REVOKED: { label: \"App access revoked\", tag: \"APP\", badge: \"red\", color: \"var(--orange-11)\" },\n BUNDLE_GRANTED: { label: \"Bundle access granted\", tag: \"BNDL\", badge: \"green\", color: \"var(--green-11)\" },\n BUNDLE_REVOKED: { label: \"Bundle access revoked\", tag: \"BNDL\", badge: \"red\", color: \"var(--orange-11)\" },\n APP_VALIDATED: { label: \"App repo checked\", tag: \"CHK\", badge: \"gray\", color: \"var(--gray-11)\" },\n APP_DEPLOY_REQUESTED: { label: \"App deploy requested\", tag: \"DPLY\", badge: \"amber\", color: \"var(--amber-11)\" },\n APP_DEPLOYED: { label: \"App deployed\", tag: \"LIVE\", badge: \"green\", color: \"var(--green-11)\" },\n APP_DEPLOY_FAILED: { label: \"App deploy failed\", tag: \"FAIL\", badge: \"red\", color: \"var(--red-11)\" },\n APP_REVERTED: { label: \"App deploy reverted\", tag: \"RVRT\", badge: \"red\", color: \"var(--orange-11)\" },\n APP_ROLLED_BACK: { label: \"App rolled back\", tag: \"RBCK\", badge: \"amber\", color: \"var(--orange-11)\" },\n APP_REMOVED: { label: \"App undeployed\", tag: \"UNDP\", badge: \"red\", color: \"var(--red-11)\" },\n APP_DEPLOY_GRANTS_FAILED: { label: \"Deploy grants failed\", tag: \"GRNT\", badge: \"red\", color: \"var(--red-11)\" },\n ADMIN_CHANGE_ROLLED_BACK: { label: \"Admin change rolled back\", tag: \"UNDO\", badge: \"amber\", color: \"var(--amber-11)\" },\n AUDIT_EXPORTED: { label: \"Audit log exported\", tag: \"EXPT\", badge: \"gray\", color: \"var(--gray-11)\" },\n SESSIONS_LISTED: { label: \"Sessions viewed\", tag: \"VIEW\", badge: \"gray\", color: \"var(--gray-11)\" },\n};\n\n/** Falls back rather than throwing: the backend can log an action this build\n * has never heard of, and an unknown row must still render. */\nexport function auditActionMeta(action: string) {\n return (\n AUDIT_ACTION_META[action as AuditAction] ?? {\n label: action,\n tag: action.slice(0, 4).toUpperCase(),\n badge: \"gray\" as const,\n color: \"var(--gray-11)\",\n }\n );\n}\n","import { layout } from \"./layout-tokens\";\n\nexport function BrandPanel() {\n return (\n <div className=\"auth-art-card\">\n <img\n src=\"/arm-logo-inverted.svg\"\n alt=\"araMetrics\"\n style={{\n width: \"56%\",\n maxWidth: layout.brandLogoMax,\n display: \"block\",\n userSelect: \"none\",\n }}\n draggable={false}\n />\n </div>\n );\n}\n","import { BrandPanel } from \"./BrandPanel\";\nimport { layout } from \"./layout-tokens\";\n\n/* ── Deviates from Figma signin-01 by design request (2026-07-08): the\n * full-amber page read as \"yellow everywhere\" once every auth screen was\n * built out. Amber is now reserved for primary CTAs only — page background\n * goes to the app's standard --surface-content gray, form content sits in a\n * white --color-panel-solid card with --shadow-card, matching the\n * authenticated shell's card language instead of sitting flat on amber.\n * Left art panel keeps its amber background as the one color anchor.\n */\nexport function AuthCard({ children }: { children: React.ReactNode }) {\n return (\n <div\n style={{\n minHeight: \"100vh\",\n display: \"flex\",\n background: \"var(--surface-content)\",\n padding: \"var(--space-5)\",\n gap: \"var(--space-5)\",\n }}\n >\n {/* Left art panel — sticky so it stays put while the form scrolls */}\n <div\n className=\"auth-card-left\"\n style={{\n width: \"47%\",\n flexShrink: 0,\n position: \"sticky\",\n top: \"var(--space-5)\",\n height: \"calc(100vh - var(--space-8))\",\n }}\n >\n <BrandPanel />\n </div>\n\n {/* Right form column — white card, centered in the right half */}\n <div\n className=\"auth-card-right\"\n style={{\n flex: 1,\n /* Without this the column keeps the default `min-width: auto` and can\n never go below its content's min-content width, so a wide row\n inside the card — the SSO buttons on the login screen — becomes a\n floor for the whole page. */\n minWidth: 0,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n minHeight: \"calc(100vh - var(--space-8))\",\n padding: \"var(--space-7) var(--space-5)\",\n }}\n >\n {/* `main`, not a div: every auth screen gets its shell from here and\n none of them exposed a landmark. This component never renders inside\n the authenticated shell, which has its own `main`, so there is no\n risk of two. */}\n <main\n style={{\n maxWidth: layout.authFormMax,\n width: \"100%\",\n marginLeft: \"auto\",\n marginRight: \"auto\",\n background: \"var(--color-panel-solid)\",\n borderRadius: \"var(--radius-5)\",\n boxShadow: \"var(--shadow-card)\",\n padding: \"var(--space-7) var(--space-5)\",\n }}\n >\n {children}\n </main>\n </div>\n </div>\n );\n}\n","export function GoogleIcon() {\n return (\n <svg\n width={18}\n height={18}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden\n >\n <path d=\"M15.68 8.18c0-.57-.05-1.11-.14-1.64H8v3.1h4.3a3.68 3.68 0 0 1-1.6 2.42v2h2.58c1.51-1.39 2.4-3.44 2.4-5.88Z\" fill=\"#4285F4\" />\n <path d=\"M8 16c2.16 0 3.97-.71 5.3-1.94l-2.59-2a4.88 4.88 0 0 1-7.27-2.56H0.9v2.07A8 8 0 0 0 8 16Z\" fill=\"#34A853\" />\n <path d=\"M3.44 9.5A4.8 4.8 0 0 1 3.19 8c0-.52.09-1.03.25-1.5V4.43H.9A8 8 0 0 0 0 8c0 1.29.31 2.51.9 3.57L3.44 9.5Z\" fill=\"#FBBC05\" />\n <path d=\"M8 3.18c1.22 0 2.31.42 3.17 1.24l2.37-2.37A7.94 7.94 0 0 0 8 0 8 8 0 0 0 .9 4.43L3.44 6.5A4.77 4.77 0 0 1 8 3.18Z\" fill=\"#EA4335\" />\n </svg>\n );\n}\n","export function MicrosoftIcon() {\n return (\n <svg\n width={18}\n height={18}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden\n >\n <rect x=\"0\" y=\"0\" width=\"7.6\" height=\"7.6\" fill=\"#F25022\" />\n <rect x=\"8.4\" y=\"0\" width=\"7.6\" height=\"7.6\" fill=\"#7FBA00\" />\n <rect x=\"0\" y=\"8.4\" width=\"7.6\" height=\"7.6\" fill=\"#00A4EF\" />\n <rect x=\"8.4\" y=\"8.4\" width=\"7.6\" height=\"7.6\" fill=\"#FFB900\" />\n </svg>\n );\n}\n","import { useRef } from \"react\";\nimport { TextField } from \"@radix-ui/themes\";\n\n/* 4-digit one-time-code input — shared by sign-in and sign-up (passwordless\n * auth, 2026-07-09). Auto-advances, backspace walks left, paste fills. */\nexport function OtpInput({ value, onChange, disabled }: { value: string; onChange: (v: string) => void; disabled?: boolean }) {\n const inputs = useRef<(HTMLInputElement | null)[]>([]);\n\n function handleChange(i: number, e: React.ChangeEvent<HTMLInputElement>) {\n const ch = e.target.value.replace(/\\D/g, \"\").slice(-1);\n const digits = Array.from({ length: 4 }, (_, k) => value[k] ?? \"\");\n digits[i] = ch;\n onChange(digits.join(\"\"));\n if (ch && i < 3) inputs.current[i + 1]?.focus();\n }\n\n function handleKeyDown(i: number, e: React.KeyboardEvent<HTMLInputElement>) {\n const digits = Array.from({ length: 4 }, (_, k) => value[k] ?? \"\");\n if (e.key === \"Backspace\") {\n if (!digits[i] && i > 0) {\n digits[i - 1] = \"\";\n onChange(digits.join(\"\"));\n inputs.current[i - 1]?.focus();\n }\n } else if (e.key === \"ArrowLeft\" && i > 0) {\n inputs.current[i - 1]?.focus();\n } else if (e.key === \"ArrowRight\" && i < 3) {\n inputs.current[i + 1]?.focus();\n }\n }\n\n function handlePaste(e: React.ClipboardEvent) {\n const pasted = e.clipboardData.getData(\"text\").replace(/\\D/g, \"\").slice(0, 4);\n if (pasted) {\n e.preventDefault();\n onChange(pasted);\n inputs.current[Math.min(pasted.length, 3)]?.focus();\n }\n }\n\n const digits = Array.from({ length: 4 }, (_, k) => value[k] ?? \"\");\n\n return (\n <div\n style={{\n display: \"flex\",\n gap: \"var(--space-3)\",\n justifyContent: \"center\",\n }}\n >\n {digits.map((d, i) => (\n <TextField.Root\n key={i}\n ref={(el) => { inputs.current[i] = el; }}\n type=\"text\"\n inputMode=\"numeric\"\n maxLength={1}\n value={d}\n onChange={(e) => handleChange(i, e)}\n onKeyDown={(e) => handleKeyDown(i, e)}\n onPaste={handlePaste}\n disabled={disabled}\n className=\"otp-box\"\n aria-label={`Digit ${i + 1}`}\n autoComplete={i === 0 ? \"one-time-code\" : \"off\"}\n />\n ))}\n </div>\n );\n}\n","import { OtpInput } from \"./OtpInput\";\nimport { Button, Callout, Heading, Text } from \"@radix-ui/themes\";\nimport { ExclamationTriangleIcon } from \"@radix-ui/react-icons\";\nimport { headingSize } from \"./heading-scale\";\n\nexport interface OtpVerifyStepProps {\n email: string;\n title: React.ReactNode;\n subtitle: React.ReactNode;\n code: string;\n onCodeChange: (value: string) => void;\n otpDevHint: string | null;\n error: string | null;\n /** Optional inline recovery action shown next to `error` — for errors\n * whose message describes a fix (\"Start the signup process again\") but\n * that otherwise have no button actually doing it. */\n errorAction?: { label: string; onClick: () => void };\n busy: boolean;\n otpExpiresAt: number | null;\n otpSecondsLeft: number;\n resendCooldown: number;\n onResend: () => void;\n onUseDifferentEmail: () => void;\n}\n\nexport function OtpVerifyStep({\n email,\n title,\n subtitle,\n code,\n onCodeChange,\n otpDevHint,\n error,\n errorAction,\n busy,\n otpExpiresAt,\n otpSecondsLeft,\n resendCooldown,\n onResend,\n onUseDifferentEmail,\n}: OtpVerifyStepProps) {\n return (\n <>\n <div style={{ marginBottom: \"var(--space-6)\", textAlign: \"center\" }}>\n <Heading as=\"h1\" size={headingSize.h1} style={{ color: \"var(--ink-strong)\", marginBottom: \"var(--space-3)\" }}>\n {title}\n </Heading>\n <Text as=\"p\" size=\"2\" style={{ color: \"var(--ink-mid)\", lineHeight: 1.55 }}>\n {subtitle}{\" \"}\n <span style={{ fontWeight: 600, color: \"var(--ink-strong)\" }}>{email}</span>.\n </Text>\n </div>\n\n {otpDevHint && (\n <Callout.Root color=\"gray\" variant=\"surface\" size=\"1\" style={{ marginBottom: \"var(--space-5)\" }}>\n <Callout.Text style={{ fontFamily: \"var(--font-poppins)\" }}>\n Dev hint — code is <strong>{otpDevHint}</strong>\n </Callout.Text>\n </Callout.Root>\n )}\n\n {error && (\n <Callout.Root color=\"red\" variant=\"surface\" size=\"2\" style={{ marginBottom: \"var(--space-5)\" }}>\n <Callout.Icon><ExclamationTriangleIcon /></Callout.Icon>\n <Callout.Text style={{ fontFamily: \"var(--font-poppins)\" }}>\n {error}\n {errorAction && (\n <>\n {\" \"}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"1\"\n onClick={errorAction.onClick}\n style={{ fontWeight: 600, textDecoration: \"underline\", height: \"auto\", padding: 0 }}\n >\n {errorAction.label}\n </Button>\n </>\n )}\n </Callout.Text>\n </Callout.Root>\n )}\n\n <div>\n <OtpInput value={code} onChange={onCodeChange} disabled={busy || otpSecondsLeft <= 0} />\n {busy ? (\n <Text as=\"p\" size=\"1\" style={{ color: \"var(--ink-mid)\", marginTop: \"var(--space-3)\", textAlign: \"center\" }}>\n Checking code…\n </Text>\n ) : otpExpiresAt && otpSecondsLeft <= 0 ? (\n <Text as=\"p\" size=\"1\" style={{ color: \"var(--red-11)\", marginTop: \"var(--space-3)\", textAlign: \"center\" }}>\n Code expired — resend to get a new one.\n </Text>\n ) : null}\n </div>\n\n <div style={{ marginTop: \"var(--space-5)\", display: \"flex\", flexDirection: \"column\", alignItems: \"center\", gap: \"var(--space-3)\" }}>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"2\"\n disabled={resendCooldown > 0 || busy}\n onClick={onResend}\n style={{\n fontWeight: 500,\n color: resendCooldown > 0 ? \"rgba(85, 85, 85, 0.4)\" : \"var(--ink-strong)\",\n textDecoration: resendCooldown > 0 ? \"none\" : \"underline\",\n }}\n >\n {resendCooldown > 0 ? `Resend email (${resendCooldown}s)` : \"Resend email\"}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"2\"\n className=\"auth-underline-link\"\n disabled={busy}\n onClick={onUseDifferentEmail}\n style={{ fontWeight: 500, color: \"var(--ink-strong)\" }}\n >\n Use a Different Email\n </Button>\n </div>\n </>\n );\n}\n","import { GoogleIcon } from \"./GoogleIcon\";\nimport { MicrosoftIcon } from \"./MicrosoftIcon\";\n\n/** Duplicated from the app's src/lib/mock.ts (not imported) so this package\n * has no dependency back into the app. Keep in sync if the app's type changes. */\nexport type CalendarProvider = \"google\" | \"microsoft\";\n\n/** Renders the correct provider logo for a calendar account. Used in the\n * provider chooser, consent screen, and per-account badges so a Google account\n * and a Microsoft account are always distinguishable at a glance (color tells\n * you WHICH account; this icon tells you WHICH provider). */\nexport function ProviderIcon({ provider }: { provider: CalendarProvider }) {\n return provider === \"microsoft\" ? <MicrosoftIcon /> : <GoogleIcon />;\n}\n\n/** Human-readable provider names for consent copy and the chooser. */\nexport const PROVIDER_LABEL: Record<CalendarProvider, string> = {\n google: \"Google\",\n microsoft: \"Microsoft\",\n};\n","import { useEffect, useRef, useState } from \"react\";\nimport { Link, useLocation } from \"react-router-dom\";\nimport { Avatar, Badge, DropdownMenu, IconButton, Text, Tooltip } from \"@radix-ui/themes\";\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n Cross1Icon,\n DotFilledIcon,\n DotsVerticalIcon,\n ExitIcon,\n GearIcon,\n QuestionMarkCircledIcon,\n} from \"@radix-ui/react-icons\";\nimport { ConfirmDialog } from \"./ConfirmDialog\";\nimport { iconSize } from \"./icon-size\";\n\n/** Duplicated from the app's src/lib/mock.ts Role type (not imported) so\n * this package has no dependency back into the app. Keep in sync if the\n * app's role set changes. */\nexport type Role = \"admin\" | \"operator\" | \"user\";\n\n/* ── Shell sidebar layout (Radix token scale) ──────────────────────────────\n * Shared header height with Topbar via SHELL_HEADER_H.\n * Active nav: solid amber pill + left accent bar + bold ink label.\n */\n\n/* ── Shared height constant — Sidebar header and Topbar MUST use this value ── */\nexport const SHELL_HEADER_H = \"var(--space-9)\";\n\n/* ── Nav definition ──────────────────────────────────────────────────────── */\n\nexport interface NavItem {\n label: string;\n href: string;\n Icon: React.ComponentType<{ width?: number; height?: number; style?: React.CSSProperties }>;\n roles?: Role[];\n /* Drillable section — clicking swaps the whole sidebar to show these child\n * rows plus a Back row. Children inherit the parent's Icon in the sub-menu. */\n children?: NavItem[];\n /* Exact-match highlighting only (like NavLink `end`). Needed when a child's\n * href is a prefix of its siblings' — e.g. the calendar view child\n * `end: true` = NavLink exact match (sibling routes don't keep this active). */\n end?: boolean;\n /* Section path prefix for drill-in / active matching when `href` is a\n * landing route that isn't the root (Calendar lands on /calendar/syncs,\n * but every /calendar/* page belongs to the section). */\n root?: string;\n /* Short status shown as a pill after the label (\"Soon\"). It never shrinks,\n * so it stays readable while a long label truncates in front of it. */\n badge?: string;\n /* A bundle of apps rather than an app: `href` is its landing page and\n * `children` are apps, which may drill in again to their own pages. Its\n * apps read as app rows (capitals), it holds the current path whenever one\n * of its apps does, and a bundle left with no visible apps is dropped. */\n bundle?: boolean;\n /* Whether a row with `children` drills in. Omit it for the default: every\n * section with children drills in, except /calendar, which follows\n * `hasCalendarAccounts`. A row without children never drills in. */\n drillable?: boolean;\n}\n\n/* A bundle of top-level rows under a heading the user can fold away. Groups\n * don't nest, and their rows never pin into the utility nav. */\nexport interface NavGroup {\n id: string;\n label: string;\n items: NavItem[];\n /* Folded on first visit. A choice stored under `persistKey` wins. */\n defaultCollapsed?: boolean;\n}\n\nexport type NavEntry = NavItem | NavGroup;\n\nconst isNavGroup = (entry: NavEntry): entry is NavGroup => \"items\" in entry;\n\n/* Full row text for tooltips and the accessible name — the label alone would\n * drop the badge, which is the one thing that tells the rows apart. */\nconst fullLabel = (item: NavItem) => (item.badge ? `${item.label} · ${item.badge}` : item.label);\n\n/* Folded state per group id. Storage can be missing or throw (private mode,\n * blocked site data), and a bad value must not take the sidebar down, so\n * every access falls back to \"nothing stored\". */\nfunction readFoldState(key: string | undefined): Record<string, boolean> {\n if (!key) return {};\n try {\n const parsed: unknown = JSON.parse(localStorage.getItem(key) ?? \"{}\");\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) return {};\n return Object.fromEntries(\n Object.entries(parsed).filter((pair): pair is [string, boolean] => typeof pair[1] === \"boolean\")\n );\n } catch {\n return {};\n }\n}\n\nfunction writeFoldState(key: string | undefined, state: Record<string, boolean>) {\n if (!key) return;\n try {\n localStorage.setItem(key, JSON.stringify(state));\n } catch {\n /* Unsaved is fine — the toggle still works for this page view. */\n }\n}\n\n/* ── Layout tokens (Radix space scale) ───────────────────────────────────── */\n\nconst WIDTH_EXPANDED = \"calc(4 * var(--space-9))\";\nconst WIDTH_COLLAPSED = \"calc(var(--space-9) + var(--space-6))\";\nconst WIDTH_DRAWER = \"calc(4 * var(--space-9) + var(--space-5))\";\n\nconst ROW_H = \"var(--space-8)\";\nconst PILL_L = \"var(--space-5)\";\nconst PILL_R = \"var(--space-5)\";\nconst ICON_X = \"calc(var(--space-5) + var(--space-3))\";\n/* space-3, not space-5: the widest row, \"Requirements\" plus its \"Soon\" badge\n * at the active weight, needs 147 px after the icon, and space-5 left 130. */\nconst LABEL_GAP = \"var(--space-3)\";\n\n/* ── Transition helpers ──────────────────────────────────────────────────── */\n/*\n * Choreography:\n * Collapse: labels/text fade OUT immediately (90ms), width then finishes (200ms).\n * Expand: width starts, labels/text fade IN with 80ms delay so they appear\n * as the sidebar opens rather than before there's room for them.\n */\nconst labelTransition = (expanded: boolean) =>\n expanded ? \"opacity 130ms ease 80ms\" : \"opacity 90ms ease\";\n\n/* Logo crossfade: symmetric, no delay offset — both marks fade in lockstep\n * so neither dips to near-zero opacity while the other hasn't started\n * (that stagger is what reads as a flicker). Slower than the label fade\n * since the logo has more visual weight and a bigger geometry swap. */\nconst LOGO_TRANSITION = \"opacity 200ms ease\";\n\n/* ── Props ───────────────────────────────────────────────────────────────── */\n\nexport interface SidebarUser {\n name: string;\n role: Role;\n /** Profile photo URL. Omitted or unloadable falls back to the derived\n * initials, so a consumer with no photo on the profile payload passes\n * nothing and keeps the previous appearance. */\n avatarSrc?: string;\n}\n\nexport interface SidebarDevRole {\n role: Role;\n email: string;\n label: string;\n}\n\nexport interface SidebarProps {\n collapsed: boolean;\n onToggle?: () => void;\n onClose?: () => void;\n /** Nav items to render — the app owns its own route table (NAV_ITEMS).\n * A `NavGroup` renders its rows under a heading that folds them away. */\n items: NavEntry[];\n /** localStorage key that remembers which groups are folded, per browser.\n * Omit it and the folded state lasts only for the page view. */\n persistKey?: string;\n /** Utility/meta hrefs (Settings, Admin Portal) that pin above the identity\n * block instead of the main scrollable list. */\n utilityHrefs: string[];\n /** Currently signed-in user, or null/undefined if not authenticated. */\n user?: SidebarUser | null;\n onSignOut: () => void;\n /** Calendar section only drills in once the app has at least one connected\n * account — pass false to keep the global menu (e.g. no accounts yet). */\n hasCalendarAccounts?: boolean;\n brandLogoExpandedSrc?: string;\n brandLogoCollapsedSrc?: string;\n /** Where the account menu's Help entry opens, in a new tab. Omit to leave\n * the entry out — there is no default, because a baked-in URL ships to every\n * consumer whether or not that address is real. */\n helpHref?: string;\n /** Dev-only role switcher shown in the account menu — omit to hide it\n * entirely (e.g. in a production build or a context with no such concept). */\n devRoles?: SidebarDevRole[];\n onDevRoleSelect?: (email: string) => void;\n showDevRoles?: boolean;\n}\n\n/* ── Sidebar ─────────────────────────────────────────────────────────────── */\n\nexport function Sidebar({\n collapsed,\n onToggle,\n onClose,\n items,\n persistKey,\n utilityHrefs: utilityHrefsProp,\n user,\n onSignOut,\n hasCalendarAccounts = false,\n brandLogoExpandedSrc = \"/expand.svg\",\n brandLogoCollapsedSrc = \"/shrink.svg\",\n helpHref,\n devRoles,\n onDevRoleSelect,\n showDevRoles = false,\n}: SidebarProps) {\n const pathname = useLocation().pathname;\n const [confirmLogoutOpen, setConfirmLogoutOpen] = useState(false);\n\n /* Drill-in Back is a sidebar-level step, not a route jump: pressing Back\n * shows the level above while you stay on the current page. The override is\n * pinned to the pathname it was set on (stored alongside it), so any\n * navigation makes it stale and the URL again drives the level on reload /\n * deep-link — no reset effect needed. Clicking a drillable row clears it to\n * drill straight back in. */\n const [backTo, setBackTo] = useState<{ path: string; depth: number } | null>(null);\n const clearBack = () => setBackTo(null);\n\n /* Drilling in or out swaps the rows, which unmounts the one that had focus\n * and drops a keyboard user on <body>. Each step records where focus should\n * land once the new level renders: Back after drilling in, the row that was\n * drilled into after Back. Only these clicks set it, so navigation from\n * elsewhere never moves focus. */\n const rootRef = useRef<HTMLElement>(null);\n const focusAfterStep = useRef<{ back: true } | { row: string } | null>(null);\n const drillIn = () => {\n focusAfterStep.current = { back: true };\n clearBack();\n };\n\n const isDrawer = !!onClose;\n const expanded = !collapsed || isDrawer;\n const width = isDrawer ? WIDTH_DRAWER : collapsed ? WIDTH_COLLAPSED : WIDTH_EXPANDED;\n\n /* Permission fence: filter by role; Admin Portal absent from DOM for Platform User.\n * Applies inside groups and bundles too, and one left with no rows is dropped. */\n const allowed = (item: NavItem) => !item.roles || (!!user && item.roles.includes(user.role));\n const prune = (item: NavItem): NavItem[] => {\n if (!allowed(item)) return [];\n if (!item.bundle || !item.children) return [item];\n const children = item.children.flatMap(prune);\n return children.length > 0 ? [{ ...item, children }] : [];\n };\n const visibleEntries = items.flatMap<NavEntry>((entry) => {\n if (!isNavGroup(entry)) return prune(entry);\n const groupItems = entry.items.flatMap(prune);\n return groupItems.length > 0 ? [{ ...entry, items: groupItems }] : [];\n });\n const topLevelItems = visibleEntries.filter((entry): entry is NavItem => !isNavGroup(entry));\n /* Every row, grouped or not — drill-in sections can live inside a group. */\n const visibleItems = visibleEntries.flatMap((entry) => (isNavGroup(entry) ? entry.items : [entry]));\n\n const [foldState, setFoldState] = useState(() => readFoldState(persistKey));\n const isFolded = (group: NavGroup) => foldState[group.id] ?? !!group.defaultCollapsed;\n function toggleGroup(group: NavGroup) {\n const next = { ...foldState, [group.id]: !isFolded(group) };\n setFoldState(next);\n writeFoldState(persistKey, next);\n }\n\n /* Utility/meta rows (Settings, Admin Portal) render pinned above the\n * identity block instead of the main scrollable list — matches Vercel's\n * Usage/Support/Settings placement. Membership is by href, not by which\n * `items` array a caller passes in, so Storybook overrides still split\n * correctly as long as they reuse these hrefs. Settings collapses further,\n * to a small icon beside the account menu (it's a single link, no\n * sub-pages to browse); Admin Portal keeps a full row since it drills\n * into real sub-pages. */\n const utilityHrefs = new Set(utilityHrefsProp);\n const primaryEntries = visibleEntries.filter((entry) => isNavGroup(entry) || !utilityHrefs.has(entry.href));\n const settingsItem = topLevelItems.find((item) => item.href === \"/settings\");\n const utilityItems = topLevelItems.filter((item) => utilityHrefs.has(item.href) && item.href !== \"/settings\");\n\n /* Drill-in: if the current path is inside a drillable section, the sidebar\n * swaps entirely to that section's sub-menu (Back row + children) instead of\n * the global app rows. Sections nest — a bundle holds apps, an app holds\n * pages — and the URL picks the deepest one, so reload / deep-link lands\n * drilled all the way in. Back (`backTo`) shows a shallower level while\n * keeping you on the page. */\n function sectionRoot(item: NavItem) {\n return item.root ?? item.href;\n }\n\n function drillable(item: NavItem) {\n return (\n !!item.children?.length &&\n (item.drillable ?? (sectionRoot(item) !== \"/calendar\" || hasCalendarAccounts))\n );\n }\n\n /* A bundle has no pages of its own below its landing page, so it holds the\n * current path when any of its apps does. */\n function inSection(item: NavItem): boolean {\n const root = sectionRoot(item);\n if (pathname === root || pathname === item.href || pathname.startsWith(root + \"/\")) return true;\n return !!item.bundle && !!item.children?.some(inSection);\n }\n\n const urlPath: NavItem[] = [];\n for (let level = visibleItems; ; ) {\n const section = level.find((item) => drillable(item) && inSection(item));\n if (!section) break;\n urlPath.push(section);\n level = section.children!;\n }\n const depth = backTo?.path === pathname ? Math.min(backTo.depth, urlPath.length) : urlPath.length;\n const activeSection = depth > 0 ? urlPath[depth - 1] : undefined;\n const stepBack = () => {\n if (activeSection) focusAfterStep.current = { row: activeSection.href };\n setBackTo({ path: pathname, depth: depth - 1 });\n };\n\n useEffect(() => {\n const target = focusAfterStep.current;\n const root = rootRef.current;\n if (!target || !root) return;\n focusAfterStep.current = null;\n const el = \"back\" in target\n ? root.querySelector<HTMLElement>(\"[data-nav-back]\")\n : Array.from(root.querySelectorAll<HTMLElement>(\"[data-nav-href]\"))\n .find((node) => node.dataset.navHref === target.row);\n el?.focus();\n }, [activeSection?.href]);\n\n function isActive(href: string, end?: boolean) {\n return href === \"/home\" || end\n ? pathname === href\n : pathname === href || pathname.startsWith(href + \"/\");\n }\n\n function renderTopRow(item: NavItem) {\n return renderRow(item, true);\n }\n\n /* One row at any level. `uppercase` is for app-level rows: the global menu,\n * and a bundle's apps — not an app's pages. */\n function renderRow(item: NavItem, uppercase: boolean) {\n const active = item.bundle ? inSection(item) : isActive(sectionRoot(item), item.end);\n const drills = drillable(item);\n const row = (\n <NavRow\n key={item.href}\n item={item}\n active={active}\n expanded={expanded}\n uppercase={uppercase}\n showChevron={drills}\n onClick={drills ? drillIn : undefined}\n />\n );\n /* Wrap with tooltip only in icon-only rail */\n return expanded ? row : (\n <Tooltip key={item.href} content={fullLabel(item)} side=\"right\" delayDuration={300}>\n {row}\n </Tooltip>\n );\n }\n\n /* Expanded: a heading that folds its rows away. The icon rail has no room\n * for a heading, so there it is a divider and every icon stays reachable\n * whatever the folded state. */\n function renderGroup(group: NavGroup) {\n const listId = `nav-group-${group.id}`;\n if (!expanded) {\n return (\n <div key={listId} role=\"group\" aria-label={group.label}>\n <div aria-hidden=\"true\" style={{ height: 1, background: \"var(--gray-4)\", margin: `var(--space-2) ${PILL_L}` }} />\n {group.items.map(renderTopRow)}\n </div>\n );\n }\n const folded = isFolded(group);\n return (\n <div key={listId} style={{ display: \"flex\", flexDirection: \"column\", marginTop: \"var(--space-3)\" }}>\n <GroupHeading\n label={group.label}\n folded={folded}\n holdsActive={folded && group.items.some((item) => isActive(sectionRoot(item)))}\n controls={listId}\n onToggle={() => toggleGroup(group)}\n />\n <div id={listId} role=\"group\" aria-label={group.label} hidden={folded}>\n {group.items.map(renderTopRow)}\n </div>\n </div>\n );\n }\n\n const isAdminContext =\n pathname.startsWith(\"/admin\") &&\n (user?.role === \"admin\" || user?.role === \"operator\");\n\n /* `?.` guards a null user but not a user whose `name` is empty or missing —\n * consumers build SidebarUser from API payloads where the name fields are\n * optional, and `undefined.split` here took down the whole app shell. Fall\n * back to \"?\" for any name that yields no initials. */\n const initials =\n user?.name\n ?.split(\" \")\n .map((n) => n[0])\n .join(\"\")\n .slice(0, 2) || \"?\";\n\n return (\n /* <aside>, not <div>. The two <nav> elements inside are landmarks, but the\n account chip below them was not inside either — so axe `region` flagged\n it on every page. A complementary landmark on the root covers everything\n the sidebar holds, navigation and chip alike, and is the right semantic\n for a sidebar regardless. Block-level either way, so nothing moves. */\n <aside\n ref={rootRef}\n style={{\n position: \"relative\", /* anchors the edge-straddling toggle */\n width,\n height: \"100%\",\n minHeight: \"100vh\",\n background: \"var(--shell-surface)\",\n borderRight: \"1px solid var(--gray-6)\",\n flexShrink: 0,\n transition: isDrawer ? \"none\" : \"width 200ms ease\",\n zIndex: 2, /* toggle button overhangs the content column */\n }}\n >\n {/* Inner wrapper owns the clipping so the toggle can overhang the edge */}\n <div\n style={{\n width: \"100%\",\n height: \"100%\",\n minHeight: \"100vh\", /* pins Settings/Logout to the bottom even when\n the parent's height comes from min-height */\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n }}\n >\n {/* ── Brand header ─────────────────────────────────────────────────\n Height locked to SHELL_HEADER_H — same value used in Topbar.\n Bottom border uses the same --border-hairline token as the Topbar\n so the two hairlines form one straight line across the shell.\n Full wordmark and collapsed icon crossfade in place, both fixed\n at the same 40px glyph height, so the collapse feels seamless\n instead of visibly shrinking.\n ──────────────────────────────────────────────────────────────────── */}\n <div\n style={{\n height: SHELL_HEADER_H,\n flexShrink: 0,\n position: \"relative\", /* anchors absolutely-positioned children */\n overflow: \"hidden\",\n borderBottom: \"1px solid var(--border-hairline)\",\n }}\n >\n <img\n src={brandLogoExpandedSrc}\n alt=\"\"\n height={40}\n style={{\n display: \"block\",\n position: \"absolute\",\n left: \"50%\",\n top: \"50%\",\n transform: \"translate(-50%, -50%)\",\n transition: LOGO_TRANSITION,\n opacity: expanded ? 1 : 0,\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n />\n <img\n src={brandLogoCollapsedSrc}\n alt=\"\"\n height={40}\n style={{\n display: \"block\",\n position: \"absolute\",\n left: \"50%\",\n top: \"50%\",\n transform: \"translate(-50%, -50%)\",\n transition: LOGO_TRANSITION,\n opacity: expanded ? 0 : 1,\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n />\n\n {/* Drawer close — inside the header (the floating toggle is desktop-only) */}\n {isDrawer && (\n <IconButton\n variant=\"ghost\"\n color=\"gray\"\n size=\"1\"\n onClick={onClose}\n aria-label=\"Close menu\"\n style={{ position: \"absolute\", right: \"var(--space-2)\", top: \"50%\", transform: \"translateY(-50%)\" }}\n >\n <Cross1Icon style={iconSize(\"--space-3\")} />\n </IconButton>\n )}\n </div>\n\n {/* ── Navigation — scrollable, flex:1 ──────────────────────────── */}\n <nav\n aria-label=\"Main navigation\"\n style={{\n flex: 1,\n overflowY: \"auto\",\n overflowX: \"hidden\",\n paddingTop: \"var(--space-5)\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {activeSection ? (\n /* ── Section sub-menu: Back row (shows the section title, not the\n literal word \"Back\" — matches Vercel's `< Observability`\n drill-in header) + this section's children ────────────────── */\n <>\n {(() => {\n const backRow = (\n <NavRow\n item={{ label: activeSection.label, href: \"#\", Icon: ChevronLeftIcon }}\n active={false}\n expanded={expanded}\n uppercase\n asButton\n onClick={stepBack}\n />\n );\n return expanded ? backRow : (\n <Tooltip content={activeSection.label} side=\"right\" delayDuration={300}>\n {backRow}\n </Tooltip>\n );\n })()}\n\n {activeSection.children!.map((child) => renderRow(child, !!activeSection.bundle))}\n </>\n ) : (\n /* ── Global menu: primary work-area rows only ─────────────────── */\n primaryEntries.map((entry) => (isNavGroup(entry) ? renderGroup(entry) : renderTopRow(entry)))\n )}\n </nav>\n\n {/* ── Utility rows (Settings, Admin Portal) — pinned above the\n identity block, not mixed into the main scrollable list. Hidden\n while drilled into a section so the drill-in view (which reuses\n the nav area above) isn't duplicated below it. ────────────────── */}\n {!activeSection && utilityItems.length > 0 && (\n <nav\n aria-label=\"Utility navigation\"\n style={{\n flexShrink: 0,\n borderTop: \"1px solid var(--gray-4)\",\n paddingTop: \"var(--space-2)\",\n paddingBottom: \"var(--space-2)\",\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {utilityItems.map((item) => {\n const active = isActive(item.href);\n const row = (\n <NavRow\n key={item.href}\n item={item}\n active={active}\n expanded={expanded}\n uppercase\n showChevron={!!item.children}\n onClick={item.children ? drillIn : undefined}\n />\n );\n return expanded ? row : (\n <Tooltip key={item.href} content={fullLabel(item)} side=\"right\" delayDuration={300}>\n {row}\n </Tooltip>\n );\n })}\n </nav>\n )}\n\n {/* ── Identity block — admin badge, compact avatar/name row, and a\n single menu (Settings, Theme, Help, Log Out). Moved here from the\n Topbar so the Topbar only carries the page title, search, and\n notifications. One line (name only, no email); a divider always\n separates it from the nav above (utility rows already have their\n own borderTop, but Settings/Admin absence — e.g. non-admin users\n with no Admin Portal row — must not leave the split missing). ── */}\n <div\n style={{\n borderTop: utilityItems.length > 0 ? \"none\" : \"1px solid var(--gray-4)\",\n padding: expanded ? \"var(--space-2) var(--space-4)\" : \"var(--space-2) 0\",\n flexShrink: 0,\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"var(--space-2)\",\n }}\n >\n {expanded && isAdminContext && (\n <Badge color=\"gray\" variant=\"soft\" highContrast size=\"1\" radius=\"full\" style={{ alignSelf: \"flex-start\" }}>\n <DotFilledIcon style={iconSize(\"--space-2\")} />\n Administering platform\n </Badge>\n )}\n\n <div\n style={{\n display: \"flex\",\n flexDirection: expanded ? \"row\" : \"column\",\n alignItems: \"center\",\n justifyContent: expanded ? \"space-between\" : \"center\",\n gap: \"var(--space-2)\",\n }}\n >\n {/* Profile row — avatar + name (expanded), avatar only (collapsed) */}\n {expanded ? (\n <div\n className=\"shell-profile-chip\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-2)\",\n minWidth: 0,\n flex: 1,\n padding: \"var(--space-1)\",\n borderRadius: \"var(--radius-3)\",\n }}\n >\n <Avatar size=\"2\" radius=\"full\" src={user?.avatarSrc} fallback={initials} color=\"gray\" variant=\"soft\" style={{ flexShrink: 0 }} />\n {/* Fixed chrome ink, not --gray-12: the rail's surface is\n pinned to --shell-surface independently of the page's gray\n scale, so chrome text has to come from the matching\n --shell-ink-* token or the pair can drift out of contrast. */}\n <Text as=\"p\" size=\"2\" weight=\"medium\" truncate style={{ color: \"var(--shell-ink-strong)\" }}>\n {user?.name}\n </Text>\n </div>\n ) : (\n <Tooltip content={user?.name ?? \"Account\"} side=\"right\" delayDuration={300}>\n <Avatar size=\"3\" radius=\"full\" src={user?.avatarSrc} fallback={initials} color=\"gray\" variant=\"soft\" />\n </Tooltip>\n )}\n\n {/* Single account menu — previously Settings had its own icon\n sitting right next to a separate three-dot menu (Theme/Help/\n Log Out), two triggers for what's conceptually one \"account\"\n area. Now everything account-related lives behind one\n trigger, Settings included as the first item. */}\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconButton\n variant=\"ghost\"\n color=\"gray\"\n aria-label=\"Account menu\"\n className=\"sidebar-icon-btn\"\n style={{ flexShrink: 0 }}\n >\n <DotsVerticalIcon style={iconSize(\"--space-4\")} />\n </IconButton>\n </DropdownMenu.Trigger>\n\n <DropdownMenu.Content align={expanded ? \"end\" : \"start\"} side={expanded ? \"top\" : \"right\"} style={{ minWidth: 200 }}>\n {settingsItem && (\n <DropdownMenu.Item asChild>\n <Link to={settingsItem.href} onClick={clearBack}>\n <GearIcon />\n Settings\n </Link>\n </DropdownMenu.Item>\n )}\n {helpHref && (\n <DropdownMenu.Item onClick={() => window.open(helpHref, \"_blank\", \"noopener,noreferrer\")}>\n <QuestionMarkCircledIcon />\n Help\n </DropdownMenu.Item>\n )}\n\n <DropdownMenu.Separator />\n\n <DropdownMenu.Item color=\"red\" onClick={() => setConfirmLogoutOpen(true)}>\n <ExitIcon />\n Log Out\n </DropdownMenu.Item>\n\n {/* Dev role switcher — app decides whether to pass devRoles/\n showDevRoles at all (e.g. gated on import.meta.env.DEV in\n the app's own build). */}\n {showDevRoles && devRoles && devRoles.length > 0 && (\n <>\n <DropdownMenu.Separator />\n <div style={{ padding: \"var(--space-1) var(--space-3)\" }}>\n <Text\n size=\"1\"\n style={{\n fontFamily: \"monospace\",\n color: \"var(--gray-11)\",\n letterSpacing: \"0.04em\",\n textTransform: \"uppercase\",\n }}\n >\n Dev · switch role\n </Text>\n </div>\n\n {devRoles.map((r) => (\n <DropdownMenu.Item\n key={r.role}\n onClick={() => onDevRoleSelect?.(r.email)}\n disabled={user?.role === r.role}\n >\n <GearIcon />\n {r.label}\n <Text size=\"1\" color=\"gray\" style={{ marginLeft: \"auto\" }}>\n {r.role}@\n </Text>\n </DropdownMenu.Item>\n ))}\n </>\n )}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </div>\n </div>\n </div>\n\n {/* ── Collapse toggle — white square straddling the right edge at the\n header line, exactly as in the Figma demo. Desktop only. ────────── */}\n {!isDrawer && (\n <button\n onClick={onToggle}\n aria-label={collapsed ? \"Expand sidebar\" : \"Collapse sidebar\"}\n className=\"sidebar-collapse-btn\"\n style={{ top: \"calc(var(--space-9) / 2)\", transform: \"translateY(-50%)\", right: \"calc(-1 * var(--space-3))\" }}\n >\n <PanelToggleIcon flipped={collapsed} />\n </button>\n )}\n\n {/* Confirm Logout — controlled so it can be triggered from the account menu. */}\n <ConfirmDialog\n open={confirmLogoutOpen}\n onOpenChange={setConfirmLogoutOpen}\n title=\"Confirm Logout\"\n description=\"Are you sure you want to log out?\"\n onConfirm={onSignOut}\n />\n </aside>\n );\n}\n\n/* ── Nav row ─────────────────────────────────────────────────────────────── */\n/*\n * Full-bleed nav row. Active: solid amber pill + left accent bar + bold label.\n * Inactive: transparent pill (hover = gray wash via .nav-pill in globals.css).\n * Labels always rendered; opacity drives show/hide during width transition.\n */\nfunction NavRow({\n item,\n active,\n expanded,\n onClick,\n asButton,\n showChevron,\n uppercase,\n}: {\n item: NavItem;\n active: boolean;\n expanded: boolean;\n /** App-level rows read in capitals; pages inside a drill-in keep their case.\n * Display-only — the accessible name and tooltip keep the label as given. */\n uppercase?: boolean;\n /** Click handler. Runs on select; combined with `asButton` for Back (no nav). */\n onClick?: () => void;\n /** Render as a <button> (no href/navigation) — used by the Back row. */\n asButton?: boolean;\n /** Trailing right-chevron marking a drillable section (global menu only). */\n showChevron?: boolean;\n}) {\n /* Shared row styling — a Link normally, a button when onClick is provided so\n * Back can flip the sidebar without changing the URL. */\n const rowStyle: React.CSSProperties = {\n position: \"relative\",\n textDecoration: \"none\",\n display: \"flex\",\n alignItems: \"center\",\n height: ROW_H,\n flexShrink: 0,\n paddingLeft: ICON_X,\n /* Ends the content inside the pill, so a label that runs long truncates\n at the pill's edge instead of past it. */\n paddingRight: expanded ? `calc(${PILL_R} + var(--space-1))` : 0,\n gap: expanded ? LABEL_GAP : 0,\n /* The active row's pill darkens to --accent-10 on hover, where mid ink\n reads 4.10:1; strong ink holds 6.96:1 on it. */\n color: active ? \"var(--shell-ink-strong)\" : \"var(--shell-ink-mid)\",\n cursor: \"pointer\",\n };\n\n const body = (\n <>\n {/* Left-edge accent bar — active only */}\n {active && (\n <span\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n left: 0,\n top: 0,\n width: \"var(--space-1)\",\n height: \"100%\",\n background: \"var(--accent-9)\",\n borderRadius: \"0 var(--radius-1) var(--radius-1) 0\",\n }}\n />\n )}\n\n {/* Pill surface — amber when active, hover wash target when not */}\n <span\n aria-hidden=\"true\"\n className=\"nav-pill\"\n style={{\n position: \"absolute\",\n top: 0,\n bottom: 0,\n left: PILL_L,\n right: expanded ? PILL_R : PILL_L,\n borderRadius: \"var(--radius-3)\",\n background: active ? \"var(--accent-9)\" : \"transparent\",\n transition: \"background 80ms ease\",\n }}\n />\n\n <item.Icon\n width={20}\n height={20}\n style={{ position: \"relative\", flexShrink: 0 }}\n />\n\n {/* Label + badge — always in DOM; opacity drives visibility during width\n transition. The label shrinks with an ellipsis; the badge does not. */}\n <span\n style={{\n position: \"relative\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-1)\",\n minWidth: 0,\n overflow: \"hidden\",\n maxWidth: expanded ? undefined : 0,\n opacity: expanded ? 1 : 0,\n transition: labelTransition(expanded),\n }}\n >\n <Text\n as=\"span\"\n size=\"3\"\n weight={active ? \"medium\" : \"regular\"}\n style={{\n lineHeight: 1.3,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n minWidth: 0,\n textTransform: uppercase ? \"uppercase\" : undefined,\n }}\n >\n {item.label}\n </Text>\n {item.badge && (\n <Badge\n color=\"gray\"\n variant={active ? \"solid\" : \"soft\"}\n highContrast={active}\n size=\"1\"\n radius=\"full\"\n /* Radix's size-1 inline padding is 1.5 × space-1; one step is\n enough for a one-word badge and gives the label the difference. */\n style={{\n flexShrink: 0,\n paddingInline: \"var(--space-1)\",\n textTransform: uppercase ? \"uppercase\" : undefined,\n }}\n >\n {item.badge}\n </Badge>\n )}\n </span>\n\n {/* Drill-in affordance — trailing chevron on drillable rows (expanded).\n On the active (amber) row it sits in a small white box so it reads\n against the yellow pill; inactive rows show a plain chevron. */}\n {showChevron && expanded && (\n active ? (\n <span\n style={{\n position: \"relative\",\n marginLeft: \"auto\",\n /* keep the box inside the amber pill — the row's right padding\n already covers PILL_R + space-1 */\n marginRight: \"var(--space-1)\",\n flexShrink: 0,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"var(--space-5)\",\n height: \"var(--space-5)\",\n background: \"var(--color-panel-solid)\",\n borderRadius: \"var(--radius-2)\",\n boxShadow: \"0 1px 2px rgba(0,0,0,0.12)\",\n }}\n >\n <ChevronRightIcon style={{ ...iconSize(\"--space-4\"), color: \"var(--gray-11)\" }} />\n </span>\n ) : (\n <ChevronRightIcon\n style={{\n ...iconSize(\"--space-4\"),\n position: \"relative\",\n marginLeft: \"auto\",\n color: \"var(--shell-ink-mid)\",\n flexShrink: 0,\n }}\n />\n )\n )}\n </>\n );\n\n /* Back renders as a button (no href/navigation); everything else is a Link\n * that still fires onClick (used by drillable rows to clear the Back override\n * even when the target URL is unchanged). */\n if (asButton) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n data-nav-back=\"\"\n className=\"shell-nav-item\"\n style={{ ...rowStyle, background: \"none\", border: \"none\", width: \"100%\", textAlign: \"left\", font: \"inherit\" }}\n >\n {body}\n </button>\n );\n }\n\n return (\n <Link\n to={item.href}\n onClick={onClick}\n className=\"shell-nav-item\"\n data-nav-href={item.href}\n data-active={active ? \"true\" : undefined}\n aria-current={active ? \"page\" : undefined}\n /* The collapsed rail has a Radix tooltip; expanded, this is what shows\n a label the ellipsis cut short. */\n title={expanded ? fullLabel(item) : undefined}\n style={rowStyle}\n >\n {body}\n </Link>\n );\n}\n\n\n/* ── Group heading ───────────────────────────────────────────────────────── */\n/*\n * Folds a group's rows away. Folded over the current page, the heading takes\n * the strong ink and an accent dot, so the open page is never untraceable.\n */\nfunction GroupHeading({\n label,\n folded,\n holdsActive,\n controls,\n onToggle,\n}: {\n label: string;\n folded: boolean;\n holdsActive: boolean;\n controls: string;\n onToggle: () => void;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n aria-expanded={!folded}\n aria-controls={controls}\n className=\"shell-nav-group\"\n data-holds-active={holdsActive ? \"true\" : undefined}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-1)\",\n height: \"var(--space-6)\",\n flexShrink: 0,\n width: \"100%\",\n paddingLeft: ICON_X,\n paddingRight: `calc(${PILL_R} + var(--space-1))`,\n background: \"none\",\n border: \"none\",\n font: \"inherit\",\n textAlign: \"left\",\n cursor: \"pointer\",\n color: holdsActive ? \"var(--shell-ink-strong)\" : \"var(--shell-ink-mid)\",\n }}\n >\n <Text\n as=\"span\"\n size=\"1\"\n weight=\"medium\"\n style={{\n textTransform: \"uppercase\",\n letterSpacing: \"0.04em\",\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n minWidth: 0,\n }}\n >\n {label}\n </Text>\n {holdsActive && <DotFilledIcon aria-hidden=\"true\" style={{ ...iconSize(\"--space-3\"), color: \"var(--accent-9)\", flexShrink: 0 }} />}\n <ChevronDownIcon\n aria-hidden=\"true\"\n style={{\n ...iconSize(\"--space-4\"),\n marginLeft: \"auto\",\n flexShrink: 0,\n transform: folded ? \"rotate(-90deg)\" : undefined,\n transition: \"transform 120ms ease\",\n }}\n />\n </button>\n );\n}\n\n/* ── Panel-collapse glyph ─────────────────────────────────────────────── */\n\nfunction PanelToggleIcon({ flipped }: { flipped: boolean }) {\n return (\n <svg\n width=\"15\"\n height=\"15\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n style={{ transform: flipped ? \"scaleX(-1)\" : undefined }}\n >\n <rect x=\"1.5\" y=\"2.5\" width=\"13\" height=\"11\" rx=\"1.5\" stroke=\"currentColor\" />\n <path d=\"M5.5 2.5v11\" stroke=\"currentColor\" />\n <path\n d=\"M11 5.5 8.5 8l2.5 2.5\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n","import { Link, useLocation } from \"react-router-dom\";\nimport { HamburgerMenuIcon, MagnifyingGlassIcon, BellIcon } from \"@radix-ui/react-icons\";\nimport { Flex, Heading, IconButton, Text, Tooltip } from \"@radix-ui/themes\";\nimport { SHELL_HEADER_H } from \"./Sidebar\";\nimport { iconSize } from \"./icon-size\";\nimport { headingSize } from \"./heading-scale\";\n\n/* Amber topbar: breadcrumb (section / page) left, search + notifications\n * right — matches Vercel's \"Firewall / Traffic\" pattern (gray parent, bold\n * current page) instead of a single flat title. The parent segment links\n * back to the section's landing route. */\n\n/* `exact` opts a row out of prefix matching, so a landing route and its child\n * routes can carry different labels — e.g. /calendar/view is the merged grid\n * while /calendar/view/:id is one sync's detail. List the exact row first and\n * a prefix row after it to label the children. Omit it (the common case) and\n * the row keeps matching by prefix, so existing 4-element tables are\n * unaffected.\n * A `:name` segment in the prefix matches any one non-empty path segment, so\n * [\"/calendar/syncs/:id\", …, \"Edit Sync\", true] labels every sync's editor.\n * Rows are tried in order and the first match wins. */\nexport type TopbarTitleRow = [\n prefix: string,\n section: string,\n sectionHref: string,\n page: string,\n exact?: boolean,\n];\nexport type TopbarAdminTitleRow = [prefix: string, page: string];\n\n/* Route → [section label, section href, page label] — arm-ui's own route\n * table, used as the default so this component works out of the box for\n * that app. Pass `titles`/`adminTitles` to reuse Topbar with a different\n * app's routes. */\nconst DEFAULT_TITLES: TopbarTitleRow[] = [\n [\"/home\", \"Home\", \"/home\", \"Home\"],\n [\"/calendar/syncs\", \"Calendar\", \"/calendar/syncs\", \"Manage Syncs\"],\n [\"/calendar/view\", \"Calendar\", \"/calendar/syncs\", \"My Calendar\"],\n [\"/calendar\", \"Calendar\", \"/calendar/syncs\", \"Manage Syncs\"],\n [\"/settings/account\", \"Settings\", \"/settings/account\", \"Account\"],\n [\"/settings/linked\", \"Settings\", \"/settings/account\", \"Linked Account\"],\n [\"/settings\", \"Settings\", \"/settings/account\", \"Settings\"],\n];\n\n/* Admin sub-pages get their own breadcrumb page label instead of a blanket\n * \"Admin Portal\" — mirrors ADMIN_CHILDREN's labels in Sidebar.tsx so the two\n * stay in sync. Longest prefix first so \"/admin/users/:id\" still matches\n * Users. */\nconst DEFAULT_ADMIN_TITLES: TopbarAdminTitleRow[] = [\n [\"/admin/overview\", \"Overview\"],\n [\"/admin/users\", \"Users\"],\n [\"/admin/monitoring\", \"Monitoring\"],\n [\"/admin/calendar-ops\", \"Calendar Ops\"],\n [\"/admin/logs\", \"Logs\"],\n [\"/admin/security\", \"Security\"],\n [\"/admin/audit\", \"Audit Log\"],\n];\n\nfunction matchesRow(pathname: string, prefix: string, exact?: boolean): boolean {\n const want = prefix.split(\"/\");\n const got = pathname.split(\"/\");\n if (exact ? got.length !== want.length : got.length < want.length) return false;\n return want.every((segment, i) => (segment.startsWith(\":\") ? got[i] !== \"\" : segment === got[i]));\n}\n\nfunction breadcrumb(\n pathname: string,\n titles: TopbarTitleRow[],\n adminTitles: TopbarAdminTitleRow[],\n): { section: string; sectionHref: string; page: string } {\n /* Sync editor is under /calendar/syncs/* — label before the Manage Syncs prefix match. */\n if (pathname === \"/calendar/syncs/new\") {\n return { section: \"Calendar\", sectionHref: \"/calendar/syncs\", page: \"New Sync\" };\n }\n if (/^\\/calendar\\/syncs\\/[^/]+$/.test(pathname)) {\n return { section: \"Calendar\", sectionHref: \"/calendar/syncs\", page: \"Edit Sync\" };\n }\n /* `titles` before the admin table, so a consumer can label /admin routes itself. */\n const hit = titles.find(([p, , , , exact]) => matchesRow(pathname, p, exact));\n if (hit) {\n const [, section, sectionHref, page] = hit;\n return { section, sectionHref, page };\n }\n if (pathname === \"/admin\" || pathname.startsWith(\"/admin/\")) {\n const adminHit = adminTitles.find(([p]) => pathname === p || pathname.startsWith(p + \"/\"));\n return { section: \"Admin Portal\", sectionHref: \"/admin/overview\", page: adminHit ? adminHit[1] : \"Admin Portal\" };\n }\n return { section: \"Home\", sectionHref: \"/home\", page: \"Home\" };\n}\n\nexport interface TopbarProps {\n onSearchOpen: () => void;\n onMenuOpen: () => void;\n showMenu: boolean;\n /** Override the breadcrumb route tables — defaults to arm-ui's own routes. */\n titles?: TopbarTitleRow[];\n adminTitles?: TopbarAdminTitleRow[];\n}\n\nexport function Topbar({\n onSearchOpen,\n onMenuOpen,\n showMenu,\n titles = DEFAULT_TITLES,\n adminTitles = DEFAULT_ADMIN_TITLES,\n}: TopbarProps) {\n const pathname = useLocation().pathname;\n\n return (\n /* <header>, not <div>: this is the page banner, and as a plain div the\n page-title h1 and the breadcrumb beside it sat outside every landmark —\n axe `region` flagged them on every page. `display: flex` is set below, so\n the element swap changes semantics only. */\n <header\n style={{\n height: SHELL_HEADER_H,\n background: \"var(--accent-9)\",\n borderBottom: \"1px solid var(--border-hairline)\",\n flexShrink: 0,\n display: \"flex\",\n alignItems: \"center\",\n padding: \"0 var(--space-6)\",\n gap: \"var(--space-4)\",\n }}\n >\n {/* Mobile hamburger — dark ink for the amber surface */}\n {showMenu && (\n <IconButton\n variant=\"ghost\"\n size=\"1\"\n onClick={onMenuOpen}\n aria-label=\"Open navigation\"\n style={{ marginRight: \"var(--space-1)\", color: \"var(--shell-ink-strong)\" }}\n >\n <HamburgerMenuIcon style={iconSize(\"--space-4\")} />\n </IconButton>\n )}\n\n {(() => {\n const { section, sectionHref, page } = breadcrumb(pathname, titles, adminTitles);\n const showSection = section !== page;\n return (\n /* The container already allowed itself to shrink, but both segments\n were `nowrap` with nothing to truncate into — so instead of\n narrowing they overflowed and the search pill was drawn over them.\n Each segment truncates, and below 500px the section and its\n separator are hidden outright (tokens.css) so the page title keeps\n the row to itself.\n That hiding is the fix for a real measurement, not tidying: both\n the section and the separator are flexShrink: 0, so every pixel of\n squeeze landed on the h1 — 53px of a 67px title at 375px, ellipsised\n on every admin page. The older reasoning here said the page label\n should truncate first \"since the section beside it is the shorter\n of the two\", which is backwards for the admin routes: \"Admin\n Portal\" is longer than \"Audit Log\". The sidebar already says which\n section you are in; the page title is the cue that has nowhere\n else to come from. */\n <Flex align=\"baseline\" gap=\"2\" style={{ minWidth: 0, overflow: \"hidden\" }}>\n {showSection && (\n <>\n <Text asChild size=\"3\" weight=\"regular\">\n <Link\n to={sectionHref}\n style={{\n color: \"var(--shell-ink-mid)\",\n whiteSpace: \"nowrap\",\n textDecoration: \"none\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n flexShrink: 0,\n }}\n className=\"topbar-breadcrumb-link\"\n >\n {section}\n </Link>\n </Text>\n <Text\n size=\"3\"\n weight=\"regular\"\n className=\"topbar-breadcrumb-sep\"\n style={{ color: \"var(--shell-ink-mid)\", flexShrink: 0 }}\n >\n /\n </Text>\n </>\n )}\n <Heading\n as=\"h1\"\n size={headingSize.h1}\n weight=\"medium\"\n style={{\n color: \"var(--shell-ink-strong)\",\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n minWidth: 0,\n }}\n >\n {page}\n </Heading>\n </Flex>\n );\n })()}\n\n {/* Spacer */}\n <div style={{ flex: 1 }} />\n\n {/* Search trigger */}\n <button\n className=\"topbar-search\"\n onClick={onSearchOpen}\n aria-label=\"Search (⌘K)\"\n >\n <MagnifyingGlassIcon\n width={16}\n height={16}\n style={{ color: \"var(--shell-ink-strong)\", flexShrink: 0 }}\n />\n <span className=\"topbar-search-placeholder\">Search for something</span>\n </button>\n\n {/* Notifications — not wired yet */}\n <Tooltip content=\"Coming soon\">\n <span>\n <button\n className=\"topbar-icon-circle\"\n aria-label=\"Notifications (coming soon)\"\n disabled\n >\n <BellIcon style={iconSize(\"--space-4\")} />\n </button>\n </span>\n </Tooltip>\n </header>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { Dialog, Flex, Spinner, Text, TextField, VisuallyHidden } from \"@radix-ui/themes\";\nimport { CalendarIcon, MagnifyingGlassIcon, PersonIcon, ReaderIcon } from \"@radix-ui/react-icons\";\n\nexport type SearchResultType = \"app\" | \"people\" | \"page\";\n\nexport interface SearchResult {\n id: string;\n title: string;\n subtitle: string;\n href: string;\n type: SearchResultType;\n}\n\ntype OverlayState = \"prompt\" | \"searching\" | \"no-match\" | \"results\";\n\n/* ── Result icon by type ─────────────────────────────────────────────────── */\n\nconst TYPE_ICON: Record<SearchResultType, React.ComponentType<{ width?: number; height?: number; style?: React.CSSProperties }>> = {\n app: CalendarIcon,\n people: PersonIcon,\n page: ReaderIcon,\n};\n\nconst TYPE_LABEL: Record<SearchResultType, string> = {\n app: \"Apps\",\n people: \"People\",\n page: \"Pages\",\n};\n\n/* ── Group helpers ───────────────────────────────────────────────────────── */\n\ninterface ResultGroup {\n type: SearchResultType;\n label: string;\n items: SearchResult[];\n startIdx: number; // flat index of first item in this group\n}\n\nfunction groupResults(results: SearchResult[]): ResultGroup[] {\n const order: SearchResultType[] = [\"app\", \"people\", \"page\"];\n const groups: ResultGroup[] = [];\n let flat = 0;\n for (const t of order) {\n const items = results.filter((r) => r.type === t);\n if (items.length > 0) {\n groups.push({ type: t, label: TYPE_LABEL[t], items, startIdx: flat });\n flat += items.length;\n }\n }\n return groups;\n}\n\n/* ── Overlay ─────────────────────────────────────────────────────────────── */\n\nexport interface SearchOverlayProps {\n open: boolean;\n onClose: () => void;\n /** The searchable pool for the current user — the app owns its own\n * content/routes and any role-based filtering before passing this in. */\n results: SearchResult[];\n onSelectResult: (result: SearchResult) => void;\n title?: string;\n placeholder?: string;\n}\n\nexport function SearchOverlay({\n open,\n onClose,\n results: resultPool,\n onSelectResult,\n title = \"Search\",\n placeholder = \"Search…\",\n}: SearchOverlayProps) {\n // The body is mounted only while open — Radix unmounts dialog content on\n // close, so each open starts from a clean slate with no reset effect needed.\n return (\n <Dialog.Root open={open} onOpenChange={(o) => !o && onClose()}>\n <Dialog.Content\n aria-describedby={undefined}\n style={{\n padding: 0,\n maxWidth: \"calc(9 * var(--space-9) + var(--space-2))\",\n overflow: \"hidden\",\n boxShadow:\n \"0 4px 8px rgba(0,0,0,0.06), 0 12px 32px rgba(0,0,0,0.10), 0 0 0 1px var(--gray-5)\",\n }}\n >\n <SearchBody\n onClose={onClose}\n resultPool={resultPool}\n onSelectResult={onSelectResult}\n title={title}\n placeholder={placeholder}\n />\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nfunction SearchBody({\n onClose,\n resultPool,\n onSelectResult,\n title,\n placeholder,\n}: {\n onClose: () => void;\n resultPool: SearchResult[];\n onSelectResult: (result: SearchResult) => void;\n title: string;\n placeholder: string;\n}) {\n const [query, setQuery] = useState(\"\");\n const [searchResults, setSearchResults] = useState<{ q: string; items: SearchResult[] } | null>(null);\n const [selectedIdx, setSelectedIdx] = useState(-1);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n\n // Derive the overlay state from the query and the last completed search, so we\n // never set state synchronously inside the debounce effect.\n const isCurrent = !!searchResults && searchResults.q === query;\n const results = isCurrent ? searchResults.items : [];\n const state: OverlayState = !query.trim()\n ? \"prompt\"\n : !isCurrent\n ? \"searching\"\n : results.length\n ? \"results\"\n : \"no-match\";\n\n /* Debounced search — state is updated only inside the timeout callback */\n useEffect(() => {\n if (!query.trim()) return;\n const t = setTimeout(() => {\n const q = query.toLowerCase();\n const found = resultPool.filter(\n (r) =>\n r.title.toLowerCase().includes(q) ||\n r.subtitle.toLowerCase().includes(q)\n );\n setSearchResults({ q: query, items: found });\n setSelectedIdx(-1);\n }, 320);\n return () => clearTimeout(t);\n }, [query, resultPool]);\n\n /* Scroll selected item into view */\n useEffect(() => {\n if (selectedIdx < 0 || !listRef.current) return;\n const el = listRef.current.querySelector<HTMLElement>(`[data-idx=\"${selectedIdx}\"]`);\n el?.scrollIntoView({ block: \"nearest\" });\n }, [selectedIdx]);\n\n function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {\n if (e.key === \"Escape\") {\n onClose();\n } else if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setSelectedIdx((i) => Math.min(i + 1, results.length - 1));\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setSelectedIdx((i) => Math.max(i - 1, 0));\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n if (selectedIdx >= 0 && results[selectedIdx]) {\n onSelectResult(results[selectedIdx]);\n onClose();\n }\n }\n }\n\n function selectResult(result: SearchResult) {\n onSelectResult(result);\n onClose();\n }\n\n const grouped = groupResults(results);\n const promptHeight = \"calc(2 * var(--space-9) + var(--space-6))\";\n\n return (\n <>\n <VisuallyHidden>\n <Dialog.Title>{title}</Dialog.Title>\n </VisuallyHidden>\n\n {/* ── Input row ──────────────────────────────────────────────── */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n padding: \"var(--space-3) var(--space-4)\",\n borderBottom: \"1px solid var(--gray-5)\",\n }}\n >\n {state === \"searching\" ? (\n <Spinner size=\"1\" style={{ flexShrink: 0 }} />\n ) : (\n <MagnifyingGlassIcon\n width={16}\n height={16}\n style={{ color: \"var(--gray-9)\", flexShrink: 0 }}\n />\n )}\n <TextField.Root\n ref={inputRef}\n autoFocus\n type=\"text\"\n placeholder={placeholder}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={handleKeyDown}\n className=\"search-overlay-input\"\n style={{\n flex: 1,\n border: \"none\",\n outline: \"none\",\n background: \"transparent\",\n boxShadow: \"none\",\n \"--text-field-selection-color\": \"unset\",\n } as React.CSSProperties}\n />\n <kbd\n style={{\n color: \"var(--gray-11)\",\n background: \"var(--gray-3)\",\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-1)\",\n padding: \"var(--space-1) var(--space-2)\",\n flexShrink: 0,\n }}\n >\n <Text size=\"1\" as=\"span\">Esc</Text>\n </kbd>\n </div>\n\n {/* ── Results body ───────────────────────────────────────────── */}\n <div\n ref={listRef}\n style={{\n minHeight: promptHeight,\n maxHeight: \"calc(6 * var(--space-9) + var(--space-7))\",\n overflowY: \"auto\",\n }}\n >\n {state === \"prompt\" && (\n <Flex\n align=\"center\"\n justify=\"center\"\n style={{ height: promptHeight }}\n >\n <Text size=\"2\" color=\"gray\">\n Type to search…\n </Text>\n </Flex>\n )}\n\n {state === \"no-match\" && (\n <Flex\n align=\"center\"\n justify=\"center\"\n style={{ height: promptHeight }}\n >\n <div style={{ textAlign: \"center\" }}>\n <Text size=\"2\" color=\"gray\" as=\"p\">\n No results for “{query}”\n </Text>\n <Text size=\"1\" color=\"gray\" as=\"p\" mt=\"1\">\n Try searching with different keywords\n </Text>\n </div>\n </Flex>\n )}\n\n {state === \"results\" && (\n <div style={{ padding: \"var(--space-2)\" }}>\n {grouped.map((group) => {\n const Icon = TYPE_ICON[group.type];\n return (\n <div\n key={group.type}\n style={{ marginBottom: \"var(--space-1)\" }}\n >\n {/* Group label */}\n <div\n style={{\n padding: \"var(--space-2) var(--space-3) var(--space-1)\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-2)\",\n }}\n >\n <Text\n size=\"1\"\n style={{\n color: \"var(--gray-11)\",\n fontWeight: 500,\n letterSpacing: \"0.04em\",\n textTransform: \"uppercase\",\n fontFamily: \"var(--font-poppins)\",\n }}\n >\n {group.label}\n </Text>\n </div>\n\n {/* Group items */}\n {group.items.map((result, i) => {\n const flatIdx = group.startIdx + i;\n const isSelected = selectedIdx === flatIdx;\n return (\n <button\n key={result.id}\n data-idx={flatIdx}\n onClick={() => selectResult(result)}\n onMouseEnter={() => setSelectedIdx(flatIdx)}\n className=\"search-result-item\"\n style={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n padding: \"var(--space-2) var(--space-3)\",\n borderRadius: \"var(--radius-2)\",\n border: \"none\",\n cursor: \"pointer\",\n textAlign: \"left\",\n background: isSelected ? \"var(--gray-3)\" : \"transparent\",\n }}\n >\n <div\n style={{\n width: \"var(--space-6)\",\n height: \"var(--space-6)\",\n borderRadius: \"var(--radius-1)\",\n background: isSelected ? \"var(--accent-a3)\" : \"var(--gray-3)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n transition: \"background 100ms ease\",\n }}\n >\n <Icon\n width={12}\n height={12}\n style={{ color: isSelected ? \"var(--accent-11)\" : \"var(--gray-9)\" }}\n />\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n <Text\n as=\"p\"\n size=\"2\"\n weight=\"medium\"\n style={{\n color: isSelected ? \"var(--gray-12)\" : \"var(--gray-11)\",\n lineHeight: 1.3,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {result.title}\n </Text>\n <Text\n as=\"p\"\n size=\"1\"\n style={{\n color: \"var(--gray-11)\",\n lineHeight: 1.3,\n marginTop: \"1px\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {result.subtitle}\n </Text>\n </div>\n {isSelected && (\n <kbd\n style={{\n color: \"var(--gray-9)\",\n background: \"var(--gray-4)\",\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-1)\",\n padding: \"var(--space-1)\",\n flexShrink: 0,\n }}\n >\n <Text size=\"1\" as=\"span\" className=\"data-mono\">↵</Text>\n </kbd>\n )}\n </button>\n );\n })}\n </div>\n );\n })}\n </div>\n )}\n </div>\n\n {/* ── Footer hint ────────────────────────────────────────────── */}\n {state !== \"prompt\" && (\n <div\n style={{\n borderTop: \"1px solid var(--gray-4)\",\n padding: \"var(--space-2) var(--space-4)\",\n display: \"flex\",\n gap: \"var(--space-4)\",\n }}\n >\n <Text as=\"span\" size=\"1\" color=\"gray\">\n <kbd className=\"data-mono\">↑↓</kbd> navigate\n </Text>\n <Text as=\"span\" size=\"1\" color=\"gray\">\n <kbd className=\"data-mono\">↵</kbd> open\n </Text>\n <Text as=\"span\" size=\"1\" color=\"gray\">\n <kbd className=\"data-mono\">Esc</kbd> close\n </Text>\n </div>\n )}\n </>\n );\n}\n","export type { CalendarProvider } from \"./ProviderIcon\";\nimport type { CalendarProvider } from \"./ProviderIcon\";\n\n/** Duplicated from the app's src/lib/calendar-mock.ts (not imported) so this\n * package has no dependency back into the app. Keep in sync if the app's\n * calendar data model changes. */\n\nexport interface CalendarAccountCalendar {\n id: string;\n accountId: string;\n name: string;\n isPrimary: boolean;\n /** Drives the import dialog's color dot, the legend, and month/week dots. */\n colorToken: string;\n}\n\nexport interface CalendarAccount {\n id: string;\n provider: CalendarProvider;\n email: string;\n displayName: string;\n initials: string;\n authStatus: \"active\" | \"reauth\" | \"failed\";\n calendars: CalendarAccountCalendar[];\n}\n\nexport function findCalendar(\n accounts: CalendarAccount[],\n calendarId: string\n): { account: CalendarAccount; calendar: CalendarAccountCalendar } | undefined {\n for (const account of accounts) {\n const calendar = account.calendars.find((c) => c.id === calendarId);\n if (calendar) return { account, calendar };\n }\n return undefined;\n}\n\nexport interface AvailabilityBlock {\n id: string;\n calendarId: string;\n accountId: string;\n /** 0 = Monday … 6 = Sunday (week-relative) */\n day: number;\n startHour: number;\n startMinute: number;\n endHour: number;\n endMinute: number;\n title: string;\n description?: string;\n location?: string;\n /** Marked private at the source — always renders as the sync's tag alone,\n * regardless of that sync's field toggles. */\n isPrivate: boolean;\n}\n\nexport interface DatedAvailabilityBlock extends AvailabilityBlock {\n date: Date;\n}\n\nexport interface ResolvedBlock extends DatedAvailabilityBlock {\n /** True when this occurrence is showing on a calendar it wasn't natively\n * created on (i.e. merged in via a sync), as opposed to its home calendar. */\n isMerged: boolean;\n}\n\nexport type SyncStatus = \"synced\" | \"syncing\" | \"error\";\n\nexport interface CalendarSync {\n id: string;\n name: string;\n targetCalendarId: string;\n sourceCalendarIds: string[];\n status: SyncStatus;\n lastSyncedLabel?: string;\n showTitle: boolean;\n showDescription: boolean;\n showLocation: boolean;\n /** The sync's tag — the label its events carry on the target calendar.\n * Optional so existing callers keep compiling; treat an absent value as the\n * default, \"Busy\". */\n tagLabel?: string;\n}\n","import dayjs from \"dayjs\";\nimport { Flex, Text } from \"@radix-ui/themes\";\nimport type { HeaderProps } from \"react-big-calendar\";\n\nexport interface CalendarDayHeaderProps extends HeaderProps {\n /** \"Today\" reference for the filled-circle marker. Defaults to the real\n * current date — pass a fixed date for demo/mock consistency. */\n today?: Date;\n}\n\n/** Week-view column header — replaces RBC's plain \"22 Mon\" label with a\n * weekday caption + a filled amber circle on today's date number, matching\n * the OneCal reference's today marker instead of the near-invisible\n * `.rbc-today` background wash. */\nexport function CalendarDayHeader({ date, today = new Date() }: CalendarDayHeaderProps) {\n const isToday = dayjs(date).isSame(today, \"day\");\n return (\n <Flex direction=\"column\" align=\"center\" gap=\"1\" py=\"1\">\n <Text size=\"1\" weight=\"medium\" color=\"gray\" style={{ letterSpacing: \"0.04em\" }}>\n {dayjs(date).format(\"ddd\").toUpperCase()}\n </Text>\n <Flex\n align=\"center\"\n justify=\"center\"\n style={{\n width: \"var(--space-6)\",\n height: \"var(--space-6)\",\n borderRadius: \"50%\",\n background: isToday ? \"var(--accent-9)\" : \"transparent\",\n lineHeight: 1,\n }}\n >\n <Text\n size=\"3\"\n weight={isToday ? \"medium\" : \"regular\"}\n style={{ color: isToday ? \"var(--accent-contrast)\" : \"var(--gray-12)\", lineHeight: 1 }}\n >\n {dayjs(date).format(\"D\")}\n </Text>\n </Flex>\n </Flex>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { Box, Checkbox, Flex, RadioGroup, Text } from \"@radix-ui/themes\";\nimport { ProviderIcon } from \"./ProviderIcon\";\nimport type { CalendarAccount } from \"./calendar-types\";\n\ntype Row = {\n calendarId: string;\n calendarName: string;\n email: string;\n provider: CalendarAccount[\"provider\"];\n};\n\nfunction rowsFromAccounts(accounts: CalendarAccount[]): Row[] {\n return accounts.flatMap((account) =>\n account.calendars.map((cal) => ({\n calendarId: cal.id,\n calendarName: cal.name,\n email: account.email,\n provider: account.provider,\n }))\n );\n}\n\n/** Bare provider mark — no IconTile chrome (OneCal list rows). */\nfunction ProviderMark({ provider }: { provider: CalendarAccount[\"provider\"] }) {\n return (\n <span\n aria-hidden\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"var(--space-5)\",\n height: \"var(--space-5)\",\n flexShrink: 0,\n }}\n >\n <ProviderIcon provider={provider} />\n </span>\n );\n}\n\nfunction CalendarRow({\n row,\n control,\n selected,\n disabled,\n disabledLabel,\n}: {\n row: Row;\n control: ReactNode;\n selected: boolean;\n disabled: boolean;\n disabledLabel?: string;\n}) {\n return (\n <Text\n as=\"label\"\n size=\"2\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n width: \"100%\",\n paddingBlock: \"var(--space-3)\",\n paddingInline: \"var(--space-4)\",\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n opacity: disabled ? 0.45 : 1,\n background: selected ? \"var(--accent-2)\" : \"transparent\",\n color: \"var(--gray-12)\",\n }}\n >\n <ProviderMark provider={row.provider} />\n <Flex direction=\"column\" gap=\"0\" style={{ minWidth: 0, flex: 1 }}>\n <Text size=\"2\" weight=\"medium\" truncate style={{ color: \"var(--gray-12)\" }}>\n {row.calendarName}\n </Text>\n <Text size=\"1\" color=\"gray\" truncate>\n {row.email}\n </Text>\n </Flex>\n {disabledLabel ? (\n <Text size=\"1\" color=\"gray\" style={{ flexShrink: 0 }}>\n {disabledLabel}\n </Text>\n ) : null}\n <Box style={{ flexShrink: 0, display: \"flex\", alignItems: \"center\" }}>{control}</Box>\n </Text>\n );\n}\n\n/** OneCal-style flat calendar list (logo + name/email + control). */\nexport function CalendarPickList({\n accounts,\n mode,\n sourceCalendarIds,\n targetCalendarId,\n takenSourceIds,\n onToggleSource,\n onSelectTarget,\n fill = false,\n}: {\n accounts: CalendarAccount[];\n mode: \"sources\" | \"target\";\n sourceCalendarIds: string[];\n targetCalendarId: string | null;\n takenSourceIds: Set<string>;\n onToggleSource: (calendarId: string) => void;\n onSelectTarget: (calendarId: string) => void;\n /** Fill parent and scroll internally (step 2 dual lists). */\n fill?: boolean;\n}) {\n const rows = rowsFromAccounts(accounts);\n\n // Every row can end up disabled (all calendars already used as a source\n // elsewhere, or the only one left is the chosen target) — previously this\n // just showed a fully greyed-out list with a tiny per-row \"In use\" label\n // and no page-level explanation, easy to mistake for a bug.\n const allSourcesDisabled =\n mode === \"sources\" &&\n rows.length > 0 &&\n rows.every((row) => row.calendarId === targetCalendarId || takenSourceIds.has(row.calendarId));\n\n const list = allSourcesDisabled ? (\n <Box\n style={{\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-3)\",\n background: \"var(--color-panel-solid)\",\n padding: \"var(--space-4)\",\n ...(fill ? { flex: 1, minHeight: 0 } : {}),\n }}\n >\n <Text as=\"p\" size=\"2\" color=\"gray\" align=\"center\">\n All your calendars are already used as sources in other syncs, or set as this sync's\n target. Remove a calendar from another sync to make it available here.\n </Text>\n </Box>\n ) : (\n <Box\n style={{\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-3)\",\n background: \"var(--color-panel-solid)\",\n ...(fill\n ? { flex: 1, minHeight: 0, overflowY: \"auto\" }\n : { overflow: \"hidden\" }),\n }}\n >\n {rows.map((row, idx) => {\n if (mode === \"sources\") {\n const isTarget = row.calendarId === targetCalendarId;\n const takenElsewhere = takenSourceIds.has(row.calendarId);\n const disabled = isTarget || takenElsewhere;\n const selected = sourceCalendarIds.includes(row.calendarId);\n return (\n <Box\n key={row.calendarId}\n style={{ borderTop: idx > 0 ? \"1px solid var(--gray-4)\" : undefined }}\n >\n <CalendarRow\n row={row}\n selected={selected}\n disabled={disabled}\n disabledLabel={isTarget ? \"Target\" : takenElsewhere ? \"In use\" : undefined}\n control={\n <Checkbox\n checked={selected}\n disabled={disabled}\n onCheckedChange={() => {\n if (!disabled) onToggleSource(row.calendarId);\n }}\n />\n }\n />\n </Box>\n );\n }\n\n const isSource = sourceCalendarIds.includes(row.calendarId);\n const selected = row.calendarId === targetCalendarId;\n return (\n <Box\n key={row.calendarId}\n style={{ borderTop: idx > 0 ? \"1px solid var(--gray-4)\" : undefined }}\n >\n <CalendarRow\n row={row}\n selected={selected}\n disabled={isSource}\n disabledLabel={isSource ? \"Source\" : undefined}\n control={<RadioGroup.Item value={row.calendarId} disabled={isSource} />}\n />\n </Box>\n );\n })}\n </Box>\n );\n\n if (mode === \"target\") {\n return (\n <RadioGroup.Root\n value={targetCalendarId ?? \"\"}\n onValueChange={(v) => {\n if (v) onSelectTarget(v);\n }}\n style={\n fill\n ? { flex: 1, minHeight: 0, display: \"flex\", flexDirection: \"column\" }\n : undefined\n }\n >\n {list}\n </RadioGroup.Root>\n );\n }\n\n return list;\n}\n","import { Button, Flex, Heading, IconButton } from \"@radix-ui/themes\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"@radix-ui/react-icons\";\nimport { Navigate, type ToolbarProps } from \"react-big-calendar\";\nimport type { View } from \"./BigCalendarView\";\nimport { headingSize } from \"./heading-scale\";\n\n/** DS-native replacement for react-big-calendar's default toolbar — pill nav\n * arrows + Today button (left), label (center), Week/Month switch (right).\n * All logic stays RBC's; this only swaps the rendered chrome.\n * Props typed loosely (any event/resource) since RBC's Components<TEvent>\n * requires the toolbar to accept ToolbarProps<TEvent>, not our own event type. */\nexport function CalendarToolbar({\n label,\n view,\n onNavigate,\n onView,\n}: ToolbarProps<object, object>) {\n return (\n <Flex align=\"center\" justify=\"between\" gap=\"3\" wrap=\"wrap\" className=\"calendar-toolbar\">\n <Flex align=\"center\" gap=\"2\">\n <IconButton\n size=\"2\"\n variant=\"soft\"\n color=\"gray\"\n radius=\"full\"\n aria-label=\"Previous\"\n onClick={() => onNavigate(Navigate.PREVIOUS)}\n >\n <ChevronLeftIcon />\n </IconButton>\n <Button size=\"2\" variant=\"soft\" color=\"gray\" onClick={() => onNavigate(Navigate.TODAY)}>\n Today\n </Button>\n <IconButton\n size=\"2\"\n variant=\"soft\"\n color=\"gray\"\n radius=\"full\"\n aria-label=\"Next\"\n onClick={() => onNavigate(Navigate.NEXT)}\n >\n <ChevronRightIcon />\n </IconButton>\n </Flex>\n\n <Heading as=\"h2\" size={headingSize.h2} weight=\"medium\" style={{ color: \"var(--gray-12)\" }}>\n {label}\n </Heading>\n\n <Flex\n gap=\"1\"\n style={{\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-3)\",\n padding: \"var(--space-1)\",\n background: \"var(--gray-2)\",\n }}\n >\n {([\"week\", \"month\"] as View[]).map((v) => (\n <Button\n key={v}\n size=\"2\"\n variant={view === v ? \"solid\" : \"soft\"}\n className={view === v ? \"btn-amber-primary\" : undefined}\n color={view === v ? undefined : \"gray\"}\n onClick={() => onView(v)}\n style={view === v ? undefined : { background: \"transparent\" }}\n >\n {v === \"week\" ? \"Week\" : \"Month\"}\n </Button>\n ))}\n </Flex>\n </Flex>\n );\n}\n","import { Button, Flex, Spinner, Text } from \"@radix-ui/themes\";\nimport { ChevronRightIcon, ExclamationTriangleIcon } from \"@radix-ui/react-icons\";\nimport { ProviderIcon } from \"./ProviderIcon\";\nimport { IconTile } from \"./IconTile\";\nimport type { CalendarProvider } from \"./ProviderIcon\";\nimport { iconSize } from \"./icon-size\";\n\nexport const PROVIDER_META: Record<CalendarProvider, { label: string; description: string }> = {\n google: { label: \"Google Calendar\", description: \"Connect a Google account calendar\" },\n microsoft: { label: \"Outlook Calendar\", description: \"Connect an Outlook account calendar\" },\n};\n\nconst PROVIDERS: CalendarProvider[] = [\"google\", \"microsoft\"];\n\n/** Provider connect buttons — bordered, spaced action rows with hover / press /\n * focus / connecting states (`.provider-choice` in globals.css). */\nexport function ConnectProviderList({\n connectingProvider,\n failedProvider,\n exhausted = false,\n onConnect,\n}: {\n connectingProvider: CalendarProvider | null;\n failedProvider: CalendarProvider | null;\n /** True when the failure is \"no more mock accounts for this provider\" —\n * not a real error, so Retry can't help and the copy should say so. */\n exhausted?: boolean;\n onConnect: (provider: CalendarProvider) => void;\n}) {\n return (\n <Flex direction=\"column\" gap=\"3\" style={{ width: \"100%\", textAlign: \"left\" }}>\n {PROVIDERS.map((provider) => {\n const meta = PROVIDER_META[provider];\n const connecting = connectingProvider === provider;\n const busy = connectingProvider !== null;\n return (\n <div key={provider}>\n <button\n type=\"button\"\n className=\"provider-choice\"\n onClick={() => onConnect(provider)}\n disabled={busy}\n data-connecting={connecting ? \"true\" : undefined}\n aria-busy={connecting || undefined}\n aria-label={`Connect ${meta.label}`}\n >\n <IconTile>\n <ProviderIcon provider={provider} />\n </IconTile>\n <Flex direction=\"column\" className=\"provider-choice__copy\" gap=\"1\">\n <Text size=\"3\" weight=\"medium\" truncate style={{ color: \"var(--gray-12)\" }}>\n {meta.label}\n </Text>\n <Text size=\"2\" color=\"gray\" truncate>\n {meta.description}\n </Text>\n </Flex>\n <span className=\"provider-choice__chevron\" aria-hidden>\n {connecting ? (\n <Spinner size=\"2\" />\n ) : (\n <ChevronRightIcon style={iconSize(\"--space-5\")} />\n )}\n </span>\n </button>\n {failedProvider === provider && (\n <Flex align=\"center\" justify=\"between\" gap=\"3\" mt=\"2\" px=\"1\">\n <Flex align=\"center\" gap=\"2\">\n <ExclamationTriangleIcon\n style={{ ...iconSize(\"--space-4\"), color: \"var(--red-9)\", flexShrink: 0 }}\n />\n <Text size=\"2\" style={{ color: \"var(--red-11)\" }}>\n {exhausted\n ? `No more ${meta.label} accounts available to connect.`\n : `Couldn't connect ${meta.label}. Please try again.`}\n </Text>\n </Flex>\n {!exhausted && (\n <Button variant=\"ghost\" size=\"1\" onClick={() => onConnect(provider)}>\n Retry\n </Button>\n )}\n </Flex>\n )}\n </div>\n );\n })}\n </Flex>\n );\n}\n","import { Badge, Box, DropdownMenu, Flex, IconButton, Text } from \"@radix-ui/themes\";\nimport { DotsVerticalIcon, ReloadIcon, TrashIcon } from \"@radix-ui/react-icons\";\nimport { ProviderIcon } from \"./ProviderIcon\";\nimport { IconTile } from \"./IconTile\";\nimport type { CalendarAccount } from \"./calendar-types\";\nimport { layout } from \"./layout-tokens\";\n\n/** Compact horizontal connected-account card — fills its grid cell (max 4 / row). */\nexport function ConnectedAccountCard({\n account,\n onRemove,\n onReconnect,\n onClick,\n}: {\n account: CalendarAccount;\n onRemove: () => void;\n onReconnect?: () => void;\n /** Opens account detail (calendars) — kebab clicks do not fire this. */\n onClick?: () => void;\n}) {\n const needsReauth = account.authStatus === \"reauth\";\n const hasFailed = account.authStatus === \"failed\";\n\n const name = (\n <Text size=\"2\" weight=\"medium\" truncate style={{ color: \"var(--gray-12)\" }}>\n {account.displayName}\n </Text>\n );\n\n return (\n /* The card takes the mouse click, but it is not role=\"button\": the kebab\n * inside it would then be a control nested in a control, which keyboard and\n * screen-reader users cannot reach. The name is the keyboard control. */\n <Box\n onClick={onClick}\n style={{\n width: \"100%\",\n minWidth: 0,\n height: layout.connectedAccountCardH,\n boxSizing: \"border-box\",\n padding: \"var(--space-3)\",\n background: \"var(--color-panel-solid)\",\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-3)\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n cursor: onClick ? \"pointer\" : undefined,\n }}\n >\n <IconTile size=\"var(--space-6)\">\n <ProviderIcon provider={account.provider} />\n </IconTile>\n\n <Flex direction=\"column\" style={{ flex: 1, minWidth: 0 }}>\n <Flex align=\"center\" gap=\"2\" style={{ minWidth: 0 }}>\n {onClick ? (\n <button\n type=\"button\"\n className=\"card-title-button\"\n onClick={(e) => {\n e.stopPropagation();\n onClick();\n }}\n >\n {name}\n </button>\n ) : (\n name\n )}\n {needsReauth && (\n <Badge color=\"amber\" variant=\"soft\" size=\"1\" radius=\"full\" style={{ flexShrink: 0 }}>\n Needs reconnect\n </Badge>\n )}\n {hasFailed && (\n <Badge color=\"red\" variant=\"soft\" size=\"1\" radius=\"full\" style={{ flexShrink: 0 }}>\n Connection failed\n </Badge>\n )}\n </Flex>\n <Text size=\"1\" color=\"gray\" truncate>\n {account.email}\n </Text>\n </Flex>\n\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconButton\n variant=\"ghost\"\n color=\"gray\"\n size=\"1\"\n aria-label={`${account.displayName} actions`}\n onClick={(e) => e.stopPropagation()}\n >\n <DotsVerticalIcon />\n </IconButton>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\" onClick={(e) => e.stopPropagation()}>\n {(needsReauth || hasFailed) && onReconnect && (\n <DropdownMenu.Item onSelect={onReconnect}>\n <ReloadIcon /> Reconnect\n </DropdownMenu.Item>\n )}\n <DropdownMenu.Item color=\"red\" onSelect={onRemove}>\n <TrashIcon /> Remove account\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </Box>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { Flex, Text, Heading } from \"@radix-ui/themes\";\nimport { layout } from \"./layout-tokens\";\nimport { IconTile } from \"./IconTile\";\nimport { headingSize } from \"./heading-scale\";\n\nexport interface EmptyCardProps {\n icon: ReactNode;\n title: string;\n description?: string;\n action?: ReactNode;\n /**\n * Heading level for `title`. Defaults to `h2`.\n *\n * Radix's `Heading` renders an `h1` when given no `as`, which is what this\n * component did — so every empty state emitted a second top-level heading\n * underneath the shell's own page-title `h1`. A screen-reader user\n * navigating by heading heard \"Security\", then \"Nobody is suspended\", as two\n * peers. `h2` is right for the common case, because the shell owns the `h1`\n * on every page this renders inside.\n *\n * It stays configurable because this also renders as a generic centered\n * message — a 403, an unbuilt section — where the surrounding outline may\n * differ.\n */\n headingAs?: \"h1\" | \"h2\" | \"h3\" | \"h4\";\n}\n\n/** Cardless centered empty state — icon, heading, copy, action, no border/\n * background/shadow, matching Vercel's flat \"Continue to X\" / \"Connect a\n * calendar\" pattern (see ConnectProviderRows, which uses the same shape)\n * instead of a bordered box floating in the page. */\nexport function EmptyCard({\n icon,\n title,\n description,\n action,\n headingAs = \"h2\",\n}: EmptyCardProps) {\n return (\n <Flex\n direction=\"column\"\n align=\"center\"\n gap=\"3\"\n style={{ width: \"100%\", paddingTop: \"var(--space-9)\", textAlign: \"center\" }}\n >\n <IconTile size=\"var(--space-8)\">{icon}</IconTile>\n <Heading as={headingAs} size={headingSize[headingAs]} weight=\"medium\" align=\"center\">\n {title}\n </Heading>\n {description && (\n <Text size=\"2\" color=\"gray\" align=\"center\" style={{ maxWidth: layout.emptyStateCopyMax }}>\n {description}\n </Text>\n )}\n {action}\n </Flex>\n );\n}\n","import { useState } from \"react\";\nimport { Dialog, Flex, Text, Checkbox, Button } from \"@radix-ui/themes\";\nimport type { CalendarAccount } from \"./calendar-types\";\nimport { layout } from \"./layout-tokens\";\nimport { CardFooter } from \"./CardFooter\";\n\nexport interface ImportCalendarsDialogProps {\n /** Account catalog whose calendars are offered. Null closes the dialog. */\n account: CalendarAccount | null;\n onOpenChange: (open: boolean) => void;\n /** Called with checked calendar ids when the user confirms. */\n onImport: (selectedCalendarIds: string[]) => void;\n /** Pre-checked calendar ids (manage mode). Defaults to all calendars on `account`. */\n initiallySelectedIds?: string[];\n /**\n * Calendars whose checkbox cannot be changed — the caller has a rule that\n * forbids it, such as a sync depending on the calendar.\n *\n * The row keeps its current state and still counts toward the result — it\n * simply cannot be changed. Without this a caller can only disable every row\n * or none, so a row looks freely tickable right up to the moment the user is\n * told no.\n *\n * Rendered as `data-disabled=\"true\"`, which the package's own\n * `.calendar-picker-row` rules already style.\n */\n disabledIds?: string[];\n /** Shown beside each disabled row, saying why it can't be changed. */\n disabledReason?: string;\n title?: string;\n description?: string;\n confirmLabel?: string;\n}\n\n/** Choose / change which calendars belong to a connected account — OneCal\n * import step; also reused from the account detail popup to edit selection. */\nexport function ImportCalendarsDialog({\n account,\n onOpenChange,\n onImport,\n initiallySelectedIds,\n disabledIds,\n disabledReason,\n title = \"Calendars\",\n description = \"Choose which calendars you want to import.\",\n confirmLabel = \"Import Calendars\",\n}: ImportCalendarsDialogProps) {\n const formKey = account\n ? `${account.id}:${(initiallySelectedIds ?? account.calendars.map((c) => c.id)).join(\",\")}`\n : \"closed\";\n\n return (\n <Dialog.Root open={!!account} onOpenChange={onOpenChange}>\n <Dialog.Content\n maxWidth={layout.dialogMd}\n /* Callers treat dismissal as a deliberate answer rather than an idle\n * close, so a stray click on the backdrop must not stand in for one.\n * Escape and Cancel remain the two intentional ways out. */\n onInteractOutside={(event) => event.preventDefault()}\n >\n {account && (\n <ImportCalendarsForm\n key={formKey}\n account={account}\n initiallySelectedIds={initiallySelectedIds}\n disabledIds={disabledIds}\n disabledReason={disabledReason}\n title={title}\n description={description}\n confirmLabel={confirmLabel}\n onImport={onImport}\n />\n )}\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nfunction ImportCalendarsForm({\n account,\n initiallySelectedIds,\n disabledIds,\n disabledReason,\n title,\n description,\n confirmLabel,\n onImport,\n}: {\n account: CalendarAccount;\n initiallySelectedIds?: string[];\n disabledIds?: string[];\n disabledReason?: string;\n title: string;\n description: string;\n confirmLabel: string;\n onImport: (selectedCalendarIds: string[]) => void;\n}) {\n const [selected, setSelected] = useState<Set<string>>(\n () => new Set(initiallySelectedIds ?? account.calendars.map((c) => c.id))\n );\n\n const disabled = new Set(disabledIds ?? []);\n\n function toggle(id: string) {\n if (disabled.has(id)) return;\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n }\n\n return (\n <>\n <Dialog.Title size=\"5\" weight=\"medium\" mb=\"1\">\n {title}\n </Dialog.Title>\n <Dialog.Description size=\"2\" color=\"gray\" mb=\"2\">\n {description}\n </Dialog.Description>\n <Text as=\"p\" size=\"2\" weight=\"medium\" mb=\"5\" style={{ color: \"var(--gray-12)\" }}>\n {account.email}\n </Text>\n\n <Flex direction=\"column\" gap=\"3\" mb=\"5\">\n {account.calendars.map((cal) => {\n const checked = selected.has(cal.id);\n const isDisabled = disabled.has(cal.id);\n return (\n <Text\n as=\"label\"\n key={cal.id}\n size=\"3\"\n className=\"calendar-picker-row\"\n data-selected={checked || undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n padding: \"var(--space-4)\",\n cursor: isDisabled ? \"default\" : \"pointer\",\n }}\n >\n <Checkbox\n checked={checked}\n disabled={isDisabled}\n onCheckedChange={() => toggle(cal.id)}\n />\n <Text weight=\"medium\" truncate style={{ flex: 1, minWidth: 0, color: \"var(--gray-12)\" }}>\n {cal.name}\n </Text>\n {isDisabled && disabledReason && (\n <Text size=\"1\" color=\"gray\" style={{ flexShrink: 0 }}>\n {disabledReason}\n </Text>\n )}\n </Text>\n );\n })}\n </Flex>\n\n <CardFooter justify=\"between\" noTopMargin pad=\"var(--space-5)\" radius=\"var(--radius-4)\">\n <Dialog.Close>\n <Button size=\"2\" variant=\"outline\" color=\"gray\">\n Cancel\n </Button>\n </Dialog.Close>\n <Button\n size=\"2\"\n className=\"btn-amber-primary\"\n disabled={selected.size === 0}\n onClick={() => onImport(Array.from(selected))}\n >\n {confirmLabel}\n </Button>\n </CardFooter>\n </>\n );\n}\n","import { Box, Flex, Text } from \"@radix-ui/themes\";\n\n/**\n * Black or white, whichever stays legible on `hex`.\n *\n * The chip used to hardcode white text because its background was always the\n * same amber. Once a caller can colour it, that assumption breaks: white on a\n * pale swatch (a yellow, say) is unreadable. Uses the sRGB relative-luminance\n * threshold from WCAG, which is the standard way to make this choice.\n */\nfunction readableTextOn(hex: string): string {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim());\n // Anything that is not a plain 6-digit hex (a CSS var, a named colour) keeps\n // the original white — the caller is then responsible for the contrast.\n if (!m) return \"white\";\n const int = parseInt(m[1]!, 16);\n const channel = (c: number) => {\n const v = c / 255;\n return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);\n };\n const luminance =\n 0.2126 * channel((int >> 16) & 255) +\n 0.7152 * channel((int >> 8) & 255) +\n 0.0722 * channel(int & 255);\n return luminance > 0.45 ? \"black\" : \"white\";\n}\n\nfunction EventChip({\n tone,\n title,\n meta,\n accentColor,\n}: {\n tone: \"source\" | \"synced\";\n title: string;\n meta: string;\n accentColor?: string;\n}) {\n const background =\n tone === \"synced\" ? accentColor || \"var(--accent-9)\" : \"var(--blue-11)\";\n const foreground =\n tone === \"synced\"\n ? accentColor\n ? readableTextOn(accentColor)\n : \"var(--accent-contrast)\"\n : \"white\";\n return (\n <Box\n style={{\n background,\n borderRadius: \"var(--radius-2)\",\n padding: \"var(--space-2) var(--space-3)\",\n }}\n >\n <Text as=\"p\" size=\"2\" weight=\"medium\" style={{ color: foreground }}>\n {title}\n </Text>\n {meta ? (\n <Text as=\"p\" size=\"1\" style={{ color: foreground }}>\n {meta}\n </Text>\n ) : null}\n </Box>\n );\n}\n\n/** The stand-in event the preview transforms. Not the user's data — see\n * `SyncPreviewRailProps.sampleEvent`. */\nexport interface SyncPreviewSampleEvent {\n title: string;\n time: string;\n location: string;\n description: string;\n}\n\n/* Mirrors the platform's own fallback for a sync that carries no tag of its\n * own. The rail is illustrative, so it duplicates the format rather than\n * importing it — a UI library cannot depend on a backend. */\nconst DEFAULT_TAG_LABEL = \"Busy\";\n\nconst DEFAULT_SAMPLE: SyncPreviewSampleEvent = {\n title: \"Gym\",\n time: \"10:00 AM\",\n location: \"Flex Gym on 16th Ave\",\n description: \"Workout notes\",\n};\n\nexport interface SyncPreviewRailProps {\n hasSources: boolean;\n hasTarget: boolean;\n sourceLabel?: string;\n targetLabel?: string;\n showTitle: boolean;\n showDescription: boolean;\n showLocation: boolean;\n /**\n * The sync's tag — the label its blocker events carry on the target calendar.\n * Shown on its own when titles are hidden, and appended to the title when\n * they are shown. Defaults to \"Busy\" for a caller that has no tag to pass.\n */\n tagLabel?: string;\n /**\n * CSS colour the posted block is painted, matching whatever colour the sync\n * writes its events in on the target calendar. Omitted keeps the rail's own\n * amber, which is what a sync that has chosen no colour actually gets — the\n * calendar's default.\n *\n * A colour, not a provider's colour *id*: this library cannot map Google's\n * palette (or anyone's) without depending on a backend, so the caller\n * resolves the id and passes the result.\n */\n accentColor?: string;\n /**\n * The stand-in event the preview transforms. It is illustrative, never the\n * user's real data — override it to match your product's vocabulary.\n *\n * The rail always labels it as an example: an unannounced fabricated event\n * reads as stray fixture data in a real app, which is exactly how this was\n * first reported.\n */\n sampleEvent?: SyncPreviewSampleEvent;\n}\n\n/**\n * Competitor-style SYNC PREVIEW (OneCal):\n * - Source always shows the original event (never rewritten by field toggles).\n * - Target shows the single block we post — title/location/description follow\n * sync settings, and its title always carries the sync's tag (the tag alone\n * when titles are off, `Gym - (Busy)` when they are on).\n */\nexport function SyncPreviewRail({\n hasSources,\n hasTarget,\n sourceLabel,\n targetLabel,\n showTitle,\n showDescription,\n showLocation,\n tagLabel,\n accentColor,\n sampleEvent = DEFAULT_SAMPLE,\n}: SyncPreviewRailProps) {\n // Source = original calendar event (unchanged by sync field toggles).\n const sourceTitle = sampleEvent.title;\n const sourceMeta = [sampleEvent.time, sampleEvent.location].filter(Boolean).join(\" · \");\n\n // Target = the one block we write/post onto the destination calendar.\n /* Blank or whitespace-only counts as unset, matching the platform: a blocker\n * with no title at all would post as \"(no title)\". */\n const tag = tagLabel?.trim() || DEFAULT_TAG_LABEL;\n const postedTitle = showTitle ? `${sampleEvent.title} - (${tag})` : tag;\n const postedMetaParts = [sampleEvent.time].filter(Boolean);\n if (showLocation && sampleEvent.location) postedMetaParts.push(sampleEvent.location);\n if (showDescription && sampleEvent.description) postedMetaParts.push(sampleEvent.description);\n const postedMeta = postedMetaParts.join(\" · \");\n\n return (\n <Flex direction=\"column\" gap=\"4\" style={{ padding: \"var(--space-4)\" }}>\n <Text as=\"p\" className=\"ds-section-label\" style={{ textAlign: \"center\" }}>\n Sync Preview\n </Text>\n\n {/* Without this the fabricated event reads as the user's own data, or as\n stray fixture data left in the build. */}\n <Text as=\"p\" size=\"1\" color=\"gray\" style={{ textAlign: \"center\", marginTop: \"calc(-1 * var(--space-2))\" }}>\n Example event — not from your calendars.\n </Text>\n\n <Box>\n <Text as=\"p\" size=\"1\" color=\"gray\" mb=\"1\">\n Sources\n </Text>\n <Text as=\"p\" size=\"1\" weight=\"medium\" mb=\"2\" truncate style={{ color: \"var(--gray-12)\" }}>\n {hasSources ? sourceLabel || \"Selected sources\" : \"—\"}\n </Text>\n <Box\n style={{\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-2)\",\n padding: \"var(--space-2)\",\n background: \"var(--gray-2)\",\n }}\n >\n <EventChip tone=\"source\" title={sourceTitle} meta={sourceMeta} />\n </Box>\n </Box>\n\n <Box>\n <Text as=\"p\" size=\"1\" color=\"gray\" mb=\"1\">\n Target\n </Text>\n <Text as=\"p\" size=\"1\" weight=\"medium\" mb=\"2\" truncate style={{ color: \"var(--gray-12)\" }}>\n {hasTarget ? targetLabel || \"Selected target\" : \"—\"}\n </Text>\n <Box\n style={{\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-2)\",\n padding: \"var(--space-2)\",\n background: \"var(--gray-2)\",\n }}\n >\n {hasTarget ? (\n <EventChip\n tone=\"synced\"\n title={postedTitle}\n meta={postedMeta}\n {...(accentColor ? { accentColor } : {})}\n />\n ) : (\n <Text as=\"p\" size=\"2\" color=\"gray\">\n Pick one target calendar\n </Text>\n )}\n </Box>\n </Box>\n\n {!hasSources || !hasTarget ? (\n <Text as=\"p\" size=\"1\" color=\"gray\" style={{ textAlign: \"center\" }}>\n Select one or more sources, then one target\n </Text>\n ) : (\n <Text as=\"p\" size=\"1\" color=\"gray\" style={{ textAlign: \"center\" }}>\n Only the highlighted block is posted to the target\n </Text>\n )}\n </Flex>\n );\n}\n","import { Flex, Text } from \"@radix-ui/themes\";\nimport { CheckIcon } from \"@radix-ui/react-icons\";\nimport { iconSize } from \"./icon-size\";\n\nexport interface WizardStepMeta {\n n: string;\n title: string;\n description: string;\n}\n\n/**\n * Full-width OneCal-style stepper.\n * Layout per segment: [circle] title / description — generous padding so\n * labels never collapse into the badge or each other.\n */\nexport function WizardStepper({\n steps,\n current,\n}: {\n steps: readonly WizardStepMeta[];\n current: number;\n}) {\n return (\n <div\n role=\"list\"\n aria-label=\"Wizard progress\"\n style={{\n display: \"flex\",\n /* Three segments abreast stop working long before a phone: at 390px\n each got ~116px, and after the padding and the number badge the\n label had ~50px, so \"Sync Configuration\" broke to one word-fragment\n per line. They wrap to a column instead once they cannot fit. */\n flexWrap: \"wrap\",\n width: \"100%\",\n flexShrink: 0,\n marginBottom: 0,\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-4)\",\n background: \"var(--color-panel-solid)\",\n overflow: \"hidden\",\n }}\n >\n {steps.map((step, i) => {\n const index = i + 1;\n const active = index === current;\n const done = index < current;\n return (\n <Flex\n key={step.n}\n align=\"start\"\n gap=\"3\"\n role=\"listitem\"\n aria-current={active ? \"step\" : undefined}\n style={{\n /* A floor, so the row can actually reach the point where it\n wraps. With `1 1 0` and no minimum the segments just kept\n shrinking and never wrapped at all. */\n flex: \"1 1 calc(3 * var(--space-9) + var(--space-6))\",\n minWidth: \"calc(3 * var(--space-9) + var(--space-6))\",\n paddingTop: \"var(--space-4)\",\n paddingBottom: \"var(--space-4)\",\n paddingLeft: \"var(--space-4)\",\n paddingRight: \"var(--space-4)\",\n marginBottom: \"-1px\",\n borderBottom: active\n ? \"2px solid var(--accent-9)\"\n : \"2px solid transparent\",\n /* The divider lives in tokens.css so it can become a bottom rule\n once the segments stack — an inline right border would stay on\n the right of a full-width row. */\n }}\n >\n <Flex\n align=\"center\"\n justify=\"center\"\n style={{\n width: \"var(--space-6)\",\n height: \"var(--space-6)\",\n borderRadius: \"50%\",\n flexShrink: 0,\n marginTop: \"var(--space-1)\",\n background: done\n ? \"var(--green-9)\"\n : active\n ? \"var(--accent-9)\"\n : \"var(--gray-3)\",\n color: done ? \"white\" : active ? \"var(--accent-contrast)\" : \"var(--gray-11)\",\n }}\n >\n {done ? (\n <CheckIcon style={iconSize(\"--space-3\")} />\n ) : (\n <Text size=\"1\" weight=\"medium\">\n {step.n}\n </Text>\n )}\n </Flex>\n\n <Flex\n direction=\"column\"\n gap=\"1\"\n style={{ minWidth: 0, flex: 1, paddingTop: \"var(--space-1)\" }}\n >\n <Text\n size=\"2\"\n weight=\"medium\"\n style={{\n color: active || done ? \"var(--gray-12)\" : \"var(--gray-10)\",\n lineHeight: \"var(--line-height-2)\",\n }}\n >\n {step.title}\n </Text>\n <Text\n size=\"1\"\n color=\"gray\"\n style={{ lineHeight: \"var(--line-height-1)\" }}\n >\n {step.description}\n </Text>\n </Flex>\n </Flex>\n );\n })}\n </div>\n );\n}\n","import { WizardStepper } from \"./WizardStepper\";\n\nconst FIRST_RUN_STEPS = [\n { n: \"01\", title: \"Connect\", description: \"Connect your calendar account\" },\n { n: \"02\", title: \"Calendars\", description: \"Import at least 2 calendars\" },\n { n: \"03\", title: \"Sync\", description: \"Set up your first sync\" },\n] as const;\n\n/** Guided first-run stepper on /calendar — OneCal numbered steps, our DS. */\nexport function OnboardingStepper({ current }: { current: number }) {\n return <WizardStepper steps={FIRST_RUN_STEPS} current={current} />;\n}\n\n/** @deprecated Prefer OnboardingStepper. */\nexport function OnboardingStepDots({ current, total = 3 }: { current: number; total?: number }) {\n void total;\n return <OnboardingStepper current={current} />;\n}\n\nexport default OnboardingStepper;\n","import dayjs from \"dayjs\";\nimport { Flex, Grid, IconButton, Text } from \"@radix-ui/themes\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"@radix-ui/react-icons\";\n\nconst WEEKDAY_LABELS = [\"S\", \"M\", \"T\", \"W\", \"T\", \"F\", \"S\"];\n\nexport interface MiniMonthPickerProps {\n cursor: Date;\n onSelect: (d: Date) => void;\n /** \"Today\" reference for the amber-ring marker. Defaults to the real\n * current date — pass a fixed date for demo/mock consistency. */\n today?: Date;\n}\n\n/** Compact date-jump picker for the calendar sidebar — OneCal-style layout\n * (month nav + 7-col day grid, selected day filled), rebuilt on our own\n * tokens/colors (amber selection, not blue). Clicking a day jumps the main\n * grid's cursor to that date. */\nexport function MiniMonthPicker({ cursor, onSelect, today = new Date() }: MiniMonthPickerProps) {\n const monthStart = dayjs(cursor).startOf(\"month\");\n const gridStart = monthStart.startOf(\"week\");\n const days = Array.from({ length: 42 }, (_, i) => gridStart.add(i, \"day\"));\n\n return (\n <div>\n <Flex align=\"center\" justify=\"between\" mb=\"2\">\n <Text size=\"2\" weight=\"medium\" style={{ color: \"var(--gray-12)\" }}>\n {monthStart.format(\"MMMM YYYY\")}\n </Text>\n <Flex gap=\"1\">\n <IconButton\n size=\"1\"\n variant=\"ghost\"\n color=\"gray\"\n aria-label=\"Previous month\"\n onClick={() => onSelect(dayjs(cursor).subtract(1, \"month\").toDate())}\n >\n <ChevronLeftIcon />\n </IconButton>\n <IconButton\n size=\"1\"\n variant=\"ghost\"\n color=\"gray\"\n aria-label=\"Next month\"\n onClick={() => onSelect(dayjs(cursor).add(1, \"month\").toDate())}\n >\n <ChevronRightIcon />\n </IconButton>\n </Flex>\n </Flex>\n <Grid columns=\"7\" gap=\"1\" mb=\"1\">\n {WEEKDAY_LABELS.map((w, i) => (\n <Text key={i} size=\"1\" color=\"gray\" align=\"center\">\n {w}\n </Text>\n ))}\n </Grid>\n <Grid columns=\"7\" gap=\"1\" justify=\"center\" align=\"center\" style={{ justifyItems: \"center\" }}>\n {days.map((d) => {\n const isToday = d.isSame(today, \"day\");\n const isSelected = d.isSame(cursor, \"day\");\n const isOffMonth = !d.isSame(monthStart, \"month\");\n return (\n <button\n key={d.format(\"YYYY-MM-DD\")}\n type=\"button\"\n onClick={() => onSelect(d.toDate())}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"var(--space-5)\",\n height: \"var(--space-5)\",\n boxSizing: \"border-box\",\n flexShrink: 0,\n padding: 0,\n borderRadius: \"50%\",\n border: isToday && !isSelected ? \"1.5px solid var(--accent-9)\" : \"none\",\n cursor: \"pointer\",\n background: isSelected ? \"var(--accent-9)\" : \"transparent\",\n color: isSelected\n ? \"var(--accent-contrast)\"\n : isOffMonth\n ? \"var(--gray-11)\"\n : isToday\n ? \"var(--accent-11)\"\n : \"var(--gray-12)\",\n fontWeight: isToday || isSelected ? 500 : 400,\n fontSize: \"var(--font-size-1)\",\n fontFamily: \"var(--font-poppins)\",\n }}\n >\n {d.format(\"D\")}\n </button>\n );\n })}\n </Grid>\n </div>\n );\n}\n","import { useState } from \"react\";\nimport { Dialog, Flex, Text, Button, IconButton, Badge, Separator, Box } from \"@radix-ui/themes\";\nimport { Cross2Icon, PlusIcon, ReloadIcon } from \"@radix-ui/react-icons\";\nimport { ProviderIcon } from \"./ProviderIcon\";\nimport { CardFooter } from \"./CardFooter\";\nimport { IconTile } from \"./IconTile\";\nimport { ImportCalendarsDialog } from \"./ImportCalendarsDialog\";\nimport type { CalendarAccount, CalendarAccountCalendar } from \"./calendar-types\";\nimport { layout } from \"./layout-tokens\";\nimport { iconSize } from \"./icon-size\";\n\nexport interface AccountCalendarsDialogProps {\n /** The account to show, resolved by the app — null closes the dialog. */\n account: CalendarAccount | null;\n /** The account's full available-calendars catalog (may include calendars\n * not currently imported) — used by \"Change calendars\". */\n catalog: CalendarAccount | null;\n onOpenChange: (open: boolean) => void;\n onRemoveCalendar: (account: CalendarAccount, calendar: CalendarAccountCalendar) => void;\n onSaveCalendars: (account: CalendarAccount, selectedCalendars: CalendarAccountCalendar[]) => void;\n onReconnect?: (accountId: string) => void;\n}\n\n/** Account detail popup — view calendars, remove one, or change which are imported. */\nexport function AccountCalendarsDialog({\n account,\n catalog,\n onOpenChange,\n onRemoveCalendar,\n onSaveCalendars,\n onReconnect,\n}: AccountCalendarsDialogProps) {\n const [managing, setManaging] = useState(false);\n const needsReauth = account?.authStatus === \"reauth\";\n const hasFailed = account?.authStatus === \"failed\";\n\n function handleManageSave(selectedCalendarIds: string[]) {\n if (!account || !catalog) return;\n const selected = new Set(selectedCalendarIds);\n onSaveCalendars(\n account,\n catalog.calendars.filter((c) => selected.has(c.id))\n );\n setManaging(false);\n }\n\n return (\n <>\n <Dialog.Root\n open={!!account && !managing}\n onOpenChange={(open) => {\n if (!open) onOpenChange(false);\n }}\n >\n <Dialog.Content maxWidth={layout.dialogMd}>\n {account && (\n <>\n <Flex align=\"center\" gap=\"3\" mb=\"1\">\n <IconTile size=\"var(--space-6)\">\n <ProviderIcon provider={account.provider} />\n </IconTile>\n <Box style={{ minWidth: 0, flex: 1 }}>\n <Flex align=\"center\" gap=\"2\" mb=\"1\" style={{ minWidth: 0 }}>\n <Dialog.Title size=\"4\" weight=\"medium\" mb=\"0\" truncate style={{ minWidth: 0 }}>\n {account.displayName}\n </Dialog.Title>\n {needsReauth && (\n <Badge color=\"amber\" variant=\"soft\" size=\"1\" radius=\"full\" style={{ flexShrink: 0 }}>\n Needs reconnect\n </Badge>\n )}\n {hasFailed && (\n <Badge color=\"red\" variant=\"soft\" size=\"1\" radius=\"full\" style={{ flexShrink: 0 }}>\n Connection failed\n </Badge>\n )}\n </Flex>\n <Dialog.Description size=\"2\" color=\"gray\" mb=\"0\">\n {account.email}\n </Dialog.Description>\n </Box>\n </Flex>\n\n {(needsReauth || hasFailed) && onReconnect && (\n <Button\n size=\"2\"\n variant=\"soft\"\n color={hasFailed ? \"red\" : \"amber\"}\n mt=\"3\"\n onClick={() => onReconnect(account.id)}\n >\n <ReloadIcon />\n Reconnect\n </Button>\n )}\n\n <Separator size=\"4\" my=\"4\" />\n\n <Flex align=\"center\" justify=\"between\" gap=\"3\" mb=\"3\">\n <Text as=\"p\" className=\"ds-section-label\" mb=\"0\">\n Calendars\n </Text>\n {catalog && catalog.calendars.length > 0 && (\n <Button size=\"1\" variant=\"soft\" color=\"gray\" onClick={() => setManaging(true)}>\n <PlusIcon style={iconSize(\"--space-3\")} />\n Change calendars\n </Button>\n )}\n </Flex>\n\n <Flex\n direction=\"column\"\n style={{\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-3)\",\n overflow: \"hidden\",\n background: \"var(--color-panel-solid)\",\n }}\n >\n {account.calendars.length === 0 ? (\n <Text size=\"2\" color=\"gray\" style={{ padding: \"var(--space-4)\" }}>\n No calendars imported.\n </Text>\n ) : (\n account.calendars.map((cal, idx) => (\n <Flex\n key={cal.id}\n align=\"center\"\n gap=\"3\"\n className=\"data-table-row\"\n style={{\n padding: \"var(--space-3) var(--space-4)\",\n minHeight: \"var(--space-7)\",\n borderTop: idx > 0 ? \"1px solid var(--gray-4)\" : undefined,\n }}\n >\n <Box\n aria-hidden\n style={{\n width: \"var(--space-2)\",\n height: \"var(--space-2)\",\n borderRadius: \"50%\",\n background: cal.colorToken,\n flexShrink: 0,\n }}\n />\n <Text size=\"2\" truncate style={{ flex: 1, minWidth: 0, color: \"var(--gray-12)\" }}>\n {cal.name}\n {cal.isPrimary && (\n <Text size=\"1\" color=\"gray\">\n {\" \"}\n · Primary\n </Text>\n )}\n </Text>\n <IconButton\n variant=\"ghost\"\n color=\"gray\"\n size=\"1\"\n aria-label={`Remove ${cal.name}`}\n onClick={() => onRemoveCalendar(account, cal)}\n >\n <Cross2Icon />\n </IconButton>\n </Flex>\n ))\n )}\n </Flex>\n\n <CardFooter justify=\"end\">\n <Dialog.Close>\n <Button size=\"2\" variant=\"soft\" color=\"gray\">\n Close\n </Button>\n </Dialog.Close>\n </CardFooter>\n </>\n )}\n </Dialog.Content>\n </Dialog.Root>\n\n <ImportCalendarsDialog\n account={managing && catalog ? catalog : null}\n initiallySelectedIds={account?.calendars.map((c) => c.id)}\n title=\"Change calendars\"\n description=\"Choose which calendars to keep on this account.\"\n confirmLabel=\"Save calendars\"\n onOpenChange={(open) => {\n if (!open) setManaging(false);\n }}\n onImport={handleManageSave}\n />\n </>\n );\n}\n","import { useMemo } from \"react\";\nimport dayjs from \"dayjs\";\nimport { Calendar, dayjsLocalizer, Views, type ToolbarProps, type View } from \"react-big-calendar\";\nimport \"react-big-calendar/lib/css/react-big-calendar.css\";\nimport \"./big-calendar-overrides.css\";\nimport { Text } from \"@radix-ui/themes\";\nimport { findCalendar, type CalendarAccount, type ResolvedBlock } from \"./calendar-types\";\nimport { CalendarToolbar } from \"./CalendarToolbar\";\nimport { CalendarDayHeader } from \"./CalendarDayHeader\";\n\nconst localizer = dayjsLocalizer(dayjs);\n\n/** Default scroll position for week view — opens on working hours instead\n * of midnight, so the grid isn't mostly dead space on load. */\nconst SCROLL_TO_TIME = new Date(1970, 0, 1, 8, 0, 0);\n\ninterface CalendarEvent {\n id: string;\n title: string;\n start: Date;\n end: Date;\n resource: ResolvedBlock;\n}\n\nexport interface BigCalendarViewProps {\n blocks: ResolvedBlock[];\n view: \"week\" | \"month\";\n onViewChange: (v: \"week\" | \"month\") => void;\n date: Date;\n onNavigate: (d: Date) => void;\n /** Connected accounts — used to resolve each block's calendar color. */\n accounts: CalendarAccount[];\n /** \"Today\" reference for RBC's own now-marker and CalendarDayHeader's\n * circle. Defaults to the real current date — pass a fixed date for\n * demo/mock consistency (RBC's own today and this component's header\n * must agree, or two conflicting \"today\" indicators appear). */\n today?: Date;\n}\n\n/** Real hour-grid week/month calendar via react-big-calendar (React 19\n * compatible), restyled with our Radix tokens instead of its default CSS —\n * see big-calendar-overrides.css. Renders our own event card (title, time\n * range, location) via `components.event`, colored per calendar via\n * `eventPropGetter`. */\nexport function BigCalendarView({\n blocks,\n view,\n onViewChange,\n date,\n onNavigate,\n accounts,\n today = new Date(),\n}: BigCalendarViewProps) {\n const events = useMemo<CalendarEvent[]>(\n () =>\n blocks.map((b) => {\n const start = new Date(b.date);\n start.setHours(b.startHour, b.startMinute, 0, 0);\n const end = new Date(b.date);\n end.setHours(b.endHour, b.endMinute, 0, 0);\n return { id: b.id, title: b.title, start, end, resource: b };\n }),\n [blocks]\n );\n\n return (\n <div className=\"rbc-radix-scope\" style={{ height: \"100%\", containerType: \"inline-size\" }}>\n <Calendar\n localizer={localizer}\n events={events}\n view={view === \"week\" ? Views.WEEK : Views.MONTH}\n onView={(v) => onViewChange(v === Views.MONTH ? \"month\" : \"week\")}\n date={date}\n onNavigate={onNavigate}\n views={[Views.WEEK, Views.MONTH]}\n toolbar\n popup\n scrollToTime={SCROLL_TO_TIME}\n enableAutoScroll\n getNow={() => today}\n // Suppress RBC's native browser tooltip (title attribute) — our\n // event card already shows time/title/location, so the tooltip\n // just duplicates it in an ugly overlapping OS-native popup.\n tooltipAccessor={null}\n eventPropGetter={(event: CalendarEvent) => {\n const found = findCalendar(accounts, event.resource.calendarId);\n const color = found?.calendar.colorToken ?? \"var(--gray-8)\";\n // Month view uses a dot + plain text row (see components.month.event\n // below), not a solid-fill block — no background/border there.\n if (view === \"month\") {\n return { style: { background: \"transparent\", border: \"none\", boxShadow: \"none\" } };\n }\n return {\n style: {\n backgroundColor: color,\n border: \"none\",\n },\n };\n }}\n components={{\n // Cast: our toolbar/header don't depend on the event's concrete\n // shape, but RBC's Components<TEvent> is invariant in TEvent.\n toolbar: CalendarToolbar as React.ComponentType<ToolbarProps<CalendarEvent, object>>,\n week: {\n header: (headerProps) => <CalendarDayHeader {...headerProps} today={today} />,\n // Week view has real vertical room per slot — a richer card\n // (title + time range + location) fits.\n event: ({ event }: { event: CalendarEvent }) => {\n const durationMin = (event.end.getTime() - event.start.getTime()) / 60000;\n const showLocation = durationMin >= 60;\n const showTimeRange = durationMin >= 30;\n return (\n <div>\n <Text size=\"1\" weight=\"medium\" style={{ color: \"white\", display: \"block\" }} truncate>\n {event.title}\n </Text>\n {showTimeRange && (\n <Text size=\"1\" style={{ color: \"rgba(255,255,255,0.85)\", display: \"block\" }} truncate>\n {dayjs(event.start).format(\"h:mm A\")} – {dayjs(event.end).format(\"h:mm A\")}\n </Text>\n )}\n {showLocation && event.resource.location && (\n <Text size=\"1\" style={{ color: \"rgba(255,255,255,0.85)\", display: \"block\" }} truncate>\n {event.resource.location}\n </Text>\n )}\n </div>\n );\n },\n },\n // Month view rows are short by design (multiple weeks must fit on\n // screen) — the week view's multi-line colored-block card\n // overflowed every cell regardless of duration. Each event is a\n // small tinted chip (dot + compact time + title) rather than a\n // bare text row, so events stay visually distinct while still\n // dense enough to fit several per day.\n month: {\n event: ({ event }: { event: CalendarEvent }) => {\n const found = findCalendar(accounts, event.resource.calendarId);\n const color = found?.calendar.colorToken ?? \"var(--gray-8)\";\n return (\n <Text\n size=\"1\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-1)\",\n color: \"var(--gray-12)\",\n background: `color-mix(in srgb, ${color} 28%, transparent)`,\n borderRadius: \"var(--radius-2)\",\n padding: \"var(--space-1) var(--space-2)\",\n }}\n truncate\n >\n <span\n aria-hidden\n style={{\n width: \"var(--space-2)\",\n height: \"var(--space-2)\",\n borderRadius: \"50%\",\n background: color,\n flexShrink: 0,\n }}\n />\n <span style={{ overflow: \"hidden\", textOverflow: \"ellipsis\", whiteSpace: \"nowrap\" }}>\n {dayjs(event.start).format(\"H:mm\")} {event.title}\n </span>\n </Text>\n );\n },\n },\n }}\n />\n </div>\n );\n}\n\nexport type { View };\n","import { Dialog, Flex, Text, Button, Separator, Badge } from \"@radix-ui/themes\";\nimport { findCalendar, type CalendarAccount, type CalendarSync, type SyncStatus } from \"./calendar-types\";\nimport { layout } from \"./layout-tokens\";\nimport { CardFooter } from \"./CardFooter\";\n\nconst STATUS_META: Record<SyncStatus, { label: string; color: \"green\" | \"amber\" | \"red\" }> = {\n synced: { label: \"Synced\", color: \"green\" },\n syncing: { label: \"Syncing…\", color: \"amber\" },\n error: { label: \"Error\", color: \"red\" },\n};\n\nexport interface SyncDetailsDialogProps {\n sync: CalendarSync | null;\n /** Connected accounts — used to resolve source/target calendar names. */\n accounts: CalendarAccount[];\n onOpenChange: (open: boolean) => void;\n onEdit: (syncId: string) => void;\n}\n\n/** OneCal-style View Details — flat label/value summary of sync config. */\nexport function SyncDetailsDialog({ sync, accounts, onOpenChange, onEdit }: SyncDetailsDialogProps) {\n const calendarsSummary = sync\n ? (() => {\n const sources = sync.sourceCalendarIds\n .map((cid) => findCalendar(accounts, cid)?.calendar.name)\n .filter((n): n is string => Boolean(n));\n const target = findCalendar(accounts, sync.targetCalendarId)?.calendar.name ?? \"—\";\n return `${sources.join(\", \") || \"—\"} → ${target}`;\n })()\n : \"\";\n\n return (\n <Dialog.Root open={!!sync} onOpenChange={onOpenChange}>\n <Dialog.Content maxWidth={layout.dialogMd}>\n {sync && (\n <>\n <Flex align=\"center\" justify=\"between\" mb=\"1\">\n <Dialog.Title size=\"4\" mb=\"0\">\n {sync.name}\n </Dialog.Title>\n <Badge color={STATUS_META[sync.status].color} variant=\"soft\" size=\"1\" radius=\"full\">\n {STATUS_META[sync.status].label}\n </Badge>\n </Flex>\n <Dialog.Description size=\"2\" color=\"gray\" mb=\"4\">\n Sync configuration\n </Dialog.Description>\n\n <Flex direction=\"column\" gap=\"3\">\n <DetailRow label=\"Calendars\">{calendarsSummary}</DetailRow>\n <DetailRow label=\"Sources\">\n <Flex direction=\"column\" gap=\"1\" align=\"end\">\n {sync.sourceCalendarIds.map((cid) => {\n const found = findCalendar(accounts, cid);\n if (!found) return null;\n return (\n <Flex key={cid} direction=\"column\" align=\"end\">\n <Text size=\"2\" weight=\"medium\" style={{ color: \"var(--gray-12)\" }}>\n {found.calendar.name}\n </Text>\n <Text size=\"1\" color=\"gray\">{found.account.email}</Text>\n </Flex>\n );\n }) || \"—\"}\n </Flex>\n </DetailRow>\n <DetailRow label=\"Target\">\n {(() => {\n const found = findCalendar(accounts, sync.targetCalendarId);\n if (!found) return \"—\";\n return (\n <Flex direction=\"column\" align=\"end\">\n <Text size=\"2\" weight=\"medium\" style={{ color: \"var(--gray-12)\" }}>\n {found.calendar.name}\n </Text>\n <Text size=\"1\" color=\"gray\">{found.account.email}</Text>\n </Flex>\n );\n })()}\n </DetailRow>\n <DetailRow label=\"Last synced\">{sync.lastSyncedLabel ?? \"—\"}</DetailRow>\n </Flex>\n\n <Separator size=\"4\" my=\"4\" />\n\n <Text as=\"p\" size=\"1\" weight=\"medium\" color=\"gray\" mb=\"3\" style={{ letterSpacing: \"0.04em\" }}>\n WHAT TO SHOW\n </Text>\n <Flex direction=\"column\" gap=\"3\">\n <DetailRow label=\"Tag\">{sync.tagLabel?.trim() || \"Busy\"}</DetailRow>\n <DetailRow label=\"Event titles\">{sync.showTitle ? \"Shown\" : \"Hidden\"}</DetailRow>\n <DetailRow label=\"Event description\">{sync.showDescription ? \"Shown\" : \"Hidden\"}</DetailRow>\n <DetailRow label=\"Event location\">{sync.showLocation ? \"Shown\" : \"Hidden\"}</DetailRow>\n </Flex>\n\n <CardFooter justify=\"between\">\n <Dialog.Close>\n <Button size=\"2\" variant=\"soft\" color=\"gray\">\n Close\n </Button>\n </Dialog.Close>\n <Button size=\"2\" className=\"btn-amber-primary\" onClick={() => onEdit(sync.id)}>\n Edit sync\n </Button>\n </CardFooter>\n </>\n )}\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nfunction DetailRow({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <Flex align=\"baseline\" justify=\"between\" gap=\"4\">\n <Text size=\"2\" color=\"gray\" style={{ flexShrink: 0 }}>\n {label}\n </Text>\n <Text size=\"2\" weight=\"medium\" align=\"right\" style={{ color: \"var(--gray-12)\" }}>\n {children}\n </Text>\n </Flex>\n );\n}\n","import { useState } from \"react\";\nimport type { CalendarAccount, CalendarProvider } from \"./calendar-types\";\n\nexport interface UseConnectAccountOptions {\n /** Currently connected accounts — passed to `connectProvider` so it can\n * discover an account not already connected. */\n accounts: CalendarAccount[];\n /** Performs the actual \"discover an account for this provider\" round\n * trip (real OAuth flow in a real app; the app's own mock/API layer\n * today). Resolves null when no more accounts are available for that\n * provider — not an error, `exhausted` distinguishes the two. */\n connectProvider: (provider: CalendarProvider, connectedAccountIds: string[]) => Promise<CalendarAccount | null>;\n /** Called once the user confirms which calendars to import for the\n * newly-discovered account. */\n onAccountAdded: (account: CalendarAccount) => void;\n /** Called after `onAccountAdded` — e.g. navigate to the accounts list. */\n onImported?: () => void;\n}\n\n/** Shared \"discover account → import calendars\" flow behind connecting a\n * provider. Click a provider → brief spinner (no separate consent page) →\n * ImportCalendarsDialog opens with that account's calendars → confirming\n * adds the account and calls `onImported`. */\nexport function useConnectAccount({ accounts, connectProvider, onAccountAdded, onImported }: UseConnectAccountOptions) {\n const [connectingProvider, setConnectingProvider] = useState<CalendarProvider | null>(null);\n const [pendingAccount, setPendingAccount] = useState<CalendarAccount | null>(null);\n const [failedProvider, setFailedProvider] = useState<CalendarProvider | null>(null);\n // Distinguishes \"every mock account for this provider is already\n // connected\" (not a real failure, retry can't help) from an actual\n // connection error (retry might work) — the two need different copy.\n const [exhausted, setExhausted] = useState(false);\n\n function connect(provider: CalendarProvider) {\n if (connectingProvider) return;\n setFailedProvider(null);\n setExhausted(false);\n setConnectingProvider(provider);\n // Pick an account for this provider not already connected, so\n // connecting twice discovers a second account rather than a no-op.\n const connectedIds = accounts.map((a) => a.id);\n connectProvider(provider, connectedIds)\n .then((account) => {\n setConnectingProvider(null);\n // No account came back — every mock account for this provider is\n // already connected. Surface a message instead of silently doing\n // nothing (previously the spinner would just stop with zero\n // feedback).\n if (account) {\n setPendingAccount(account);\n } else {\n setFailedProvider(provider);\n setExhausted(true);\n }\n })\n .catch(() => {\n setConnectingProvider(null);\n setFailedProvider(provider);\n setExhausted(false);\n });\n }\n\n function confirmImport(selectedCalendarIds: string[]) {\n if (!pendingAccount) return;\n const selected = new Set(selectedCalendarIds);\n onAccountAdded({\n ...pendingAccount,\n calendars: pendingAccount.calendars.filter((c) => selected.has(c.id)),\n });\n setPendingAccount(null);\n onImported?.();\n }\n\n return {\n connectingProvider,\n pendingAccount,\n failedProvider,\n exhausted,\n connect,\n confirmImport,\n cancelImport: () => setPendingAccount(null),\n dismissError: () => setFailedProvider(null),\n };\n}\n","import type { ReactNode } from \"react\";\nimport { Box, DropdownMenu, Button, Flex, Text } from \"@radix-ui/themes\";\nimport { PlusIcon } from \"@radix-ui/react-icons\";\nimport { ProviderIcon } from \"./ProviderIcon\";\nimport { IconTile } from \"./IconTile\";\nimport { Toast } from \"./Toast\";\nimport { PROVIDER_META } from \"./ConnectProviderList\";\nimport { ImportCalendarsDialog } from \"./ImportCalendarsDialog\";\nimport { useConnectAccount, type UseConnectAccountOptions } from \"./useConnectAccount\";\nimport type { CalendarProvider } from \"./calendar-types\";\nimport { iconSize } from \"./icon-size\";\n\nexport interface AddAccountMenuProps extends UseConnectAccountOptions {\n variant?: \"button\" | \"tile\";\n /** Optional custom trigger; overrides `variant`. Must be a single element. */\n trigger?: ReactNode;\n}\n\n/** \"+ Connect Account\" — button or dashed tile; opens provider picker then\n * ImportCalendarsDialog. Trigger must be a single React element (Radix\n * Themes DropdownMenu.Trigger always uses asChild). */\nexport function AddAccountMenu({\n variant = \"button\",\n trigger,\n accounts,\n connectProvider,\n onAccountAdded,\n onImported,\n}: AddAccountMenuProps) {\n const { pendingAccount, failedProvider, exhausted, connect, confirmImport, cancelImport, dismissError } =\n useConnectAccount({ accounts, connectProvider, onAccountAdded, onImported });\n const providers: CalendarProvider[] = [\"google\", \"microsoft\"];\n\n const defaultTrigger =\n variant === \"tile\" ? (\n <button\n type=\"button\"\n className=\"connect-account-tile\"\n aria-label=\"Connect Account\"\n >\n <PlusIcon style={iconSize(\"--space-4\")} />\n Connect Account\n </button>\n ) : (\n <Button size=\"2\" className=\"btn-amber-primary\">\n <PlusIcon style={iconSize(\"--space-4\")} />\n Connect Account\n </Button>\n );\n\n const menu = (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>{trigger ?? defaultTrigger}</DropdownMenu.Trigger>\n <DropdownMenu.Content\n align=\"start\"\n // Fit the provider rows — don't stretch to the wide connect tile or a dialog width.\n style={{ width: \"max-content\", minWidth: \"max-content\" }}\n >\n {providers.map((provider) => {\n const meta = PROVIDER_META[provider];\n return (\n <DropdownMenu.Item\n key={provider}\n onSelect={() => connect(provider)}\n // Themes menu items default to a single-line fixed height; that\n // clips icon + title + description into a broken stack.\n style={{\n height: \"auto\",\n alignItems: \"center\",\n gap: \"var(--space-3)\",\n padding: \"var(--space-2) var(--space-3)\",\n }}\n >\n <IconTile size=\"var(--space-6)\">\n <ProviderIcon provider={provider} />\n </IconTile>\n <Flex direction=\"column\" gap=\"1\" style={{ flexShrink: 0 }}>\n <Text size=\"2\" weight=\"medium\" style={{ color: \"var(--gray-12)\" }}>\n {meta.label}\n </Text>\n <Text size=\"1\" color=\"gray\">\n {meta.description}\n </Text>\n </Flex>\n </DropdownMenu.Item>\n );\n })}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n\n return (\n <>\n {variant === \"tile\" && !trigger ? (\n <Box style={{ width: \"100%\", minWidth: 0 }}>\n {menu}\n </Box>\n ) : (\n menu\n )}\n\n <ImportCalendarsDialog\n account={pendingAccount}\n onOpenChange={(open) => !open && cancelImport()}\n onImport={confirmImport}\n />\n\n {failedProvider && (\n <Toast\n msg={\n exhausted\n ? `No more ${PROVIDER_META[failedProvider].label} accounts available to connect.`\n : `Couldn't connect ${PROVIDER_META[failedProvider].label}. Please try again.`\n }\n color=\"red\"\n onDone={dismissError}\n />\n )}\n </>\n );\n}\n","import { Card, Flex, Text, Heading } from \"@radix-ui/themes\";\nimport { CalendarIcon } from \"@radix-ui/react-icons\";\nimport { ImportCalendarsDialog } from \"./ImportCalendarsDialog\";\nimport { ConnectProviderList } from \"./ConnectProviderList\";\nimport { useConnectAccount, type UseConnectAccountOptions } from \"./useConnectAccount\";\nimport { layout } from \"./layout-tokens\";\nimport { IconTile } from \"./IconTile\";\nimport { iconSize } from \"./icon-size\";\nimport { headingSize } from \"./heading-scale\";\n\nexport type ConnectProviderRowsProps = UseConnectAccountOptions;\n\n/** Connect-first UI — used on Manage Syncs (section home) and Accounts when\n * no accounts are connected yet. Fills the content slot and centers as one\n * composition; inner spacing matches Home empty cards (`py=\"6\"`, `gap=\"3\"`). */\nexport function ConnectProviderRows({ accounts, connectProvider, onAccountAdded, onImported }: ConnectProviderRowsProps) {\n const { connectingProvider, pendingAccount, failedProvider, exhausted, connect, confirmImport, cancelImport } =\n useConnectAccount({ accounts, connectProvider, onAccountAdded, onImported });\n\n return (\n <Flex\n direction=\"column\"\n align=\"center\"\n justify=\"center\"\n style={{ width: \"100%\", flex: 1, minHeight: 0 }}\n >\n <Card style={{ width: \"100%\", maxWidth: layout.providerChooserMax }}>\n <Flex\n direction=\"column\"\n align=\"center\"\n justify=\"center\"\n gap=\"3\"\n py=\"6\"\n px=\"3\"\n style={{ width: \"100%\", textAlign: \"center\" }}\n >\n <IconTile>\n <CalendarIcon\n style={{ ...iconSize(\"--space-5\"), color: \"var(--gray-7)\" }}\n />\n </IconTile>\n\n <Heading as=\"h2\" size={headingSize.h2} weight=\"medium\">\n {accounts.length > 0 ? \"Connect another account\" : \"Connect your first account\"}\n </Heading>\n <Text as=\"p\" size=\"2\" color=\"gray\">\n {accounts.length > 0\n ? \"Add another Google or Microsoft account, then choose which calendars to import.\"\n : \"Connect a Google or Microsoft account to import calendars for sync.\"}\n </Text>\n\n <Flex direction=\"column\" style={{ width: \"100%\" }} mt=\"3\">\n <ConnectProviderList\n connectingProvider={connectingProvider}\n failedProvider={failedProvider}\n exhausted={exhausted}\n onConnect={connect}\n />\n </Flex>\n </Flex>\n </Card>\n\n <ImportCalendarsDialog\n account={pendingAccount}\n onOpenChange={(open) => !open && cancelImport()}\n onImport={confirmImport}\n />\n </Flex>\n );\n}\n","import { useEffect, useMemo, useState } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { Box, Checkbox, Flex, Separator, Text } from \"@radix-ui/themes\";\nimport { ChevronDownIcon, GearIcon, HamburgerMenuIcon } from \"@radix-ui/react-icons\";\nimport { findCalendar, type CalendarAccount, type ResolvedBlock } from \"./calendar-types\";\nimport { layout } from \"./layout-tokens\";\nimport { ProviderIcon } from \"./ProviderIcon\";\nimport { MiniMonthPicker } from \"./MiniMonthPicker\";\nimport { BigCalendarView } from \"./BigCalendarView\";\nimport { iconSize } from \"./icon-size\";\n\nexport interface CalendarMergedViewProps {\n accounts: CalendarAccount[];\n view: \"week\" | \"month\";\n setView: (v: \"week\" | \"month\") => void;\n hideClones: boolean;\n setHideClones: (v: boolean) => void;\n /** Union of source calendar ids across all syncs, excluding paused accounts. */\n mergedCalendarIds: Set<string>;\n /** mergedCalendarIds minus the user's legend hide toggles. */\n visibleCalendarIds: Set<string>;\n toggleCalendarVisible: (calendarId: string) => void;\n getVisibleBlocksInRange: (start: Date, end: Date) => ResolvedBlock[];\n /** \"Manage accounts\" link at the bottom of the legend rail. */\n manageAccountsHref: string;\n /** \"Today\" reference — defaults to the real current date; pass a fixed\n * date for demo/mock consistency (also forwarded to BigCalendarView so\n * the two don't disagree on what \"today\" is). */\n today?: Date;\n}\n\n/** OneCal Calendar View chrome for a read-only merged grid — left rail\n * (mini month picker + account-grouped visibility legend + hide synced +\n * manage) + week/month hour grid. All calendar data and app navigation are\n * supplied by the caller; this component owns only its own UI state\n * (cursor date, collapsed account groups, narrow-viewport sidebar toggle). */\nexport function CalendarMergedView({\n accounts,\n view,\n setView,\n hideClones,\n setHideClones,\n mergedCalendarIds,\n visibleCalendarIds,\n toggleCalendarVisible,\n getVisibleBlocksInRange,\n manageAccountsHref,\n today = new Date(),\n}: CalendarMergedViewProps) {\n const [cursor, setCursor] = useState<Date>(today);\n const [collapsedAccounts, setCollapsedAccounts] = useState<Set<string>>(new Set());\n const [isNarrow, setIsNarrow] = useState(() => typeof window !== \"undefined\" && window.innerWidth < 900);\n const [sidebarOpen, setSidebarOpen] = useState(false);\n\n useEffect(() => {\n function onResize() {\n setIsNarrow(window.innerWidth < 900);\n }\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, []);\n\n const rangeStart = useMemo(() => {\n const d = new Date(cursor);\n d.setDate(d.getDate() - 42);\n return d;\n }, [cursor]);\n const rangeEnd = useMemo(() => {\n const d = new Date(cursor);\n d.setDate(d.getDate() + 42);\n return d;\n }, [cursor]);\n\n const blocks = getVisibleBlocksInRange(rangeStart, rangeEnd);\n\n /* Group merged calendars by their owning account, preserving account order. */\n const accountGroups = useMemo(() => {\n const groups: { accountId: string; calendarIds: string[] }[] = [];\n const index = new Map<string, number>();\n for (const calId of mergedCalendarIds) {\n const found = findCalendar(accounts, calId);\n if (!found) continue;\n let i = index.get(found.account.id);\n if (i === undefined) {\n i = groups.length;\n index.set(found.account.id, i);\n groups.push({ accountId: found.account.id, calendarIds: [] });\n }\n groups[i].calendarIds.push(calId);\n }\n return groups;\n }, [mergedCalendarIds, accounts]);\n\n function toggleAccountCollapsed(accountId: string) {\n setCollapsedAccounts((prev) => {\n const next = new Set(prev);\n if (next.has(accountId)) next.delete(accountId);\n else next.add(accountId);\n return next;\n });\n }\n\n return (\n <Flex\n gap=\"5\"\n align=\"start\"\n direction={isNarrow ? \"column\" : \"row\"}\n flexGrow=\"1\"\n minHeight=\"0\"\n height=\"100%\"\n >\n {/* Left rail — mini month picker + OneCal calendar sidebar density.\n Below 900px it's a toggleable panel rather than a fixed column, so\n the calendar grid stays primary instead of being pushed below a\n full legend on narrow viewports. */}\n {(!isNarrow || sidebarOpen) && (\n <Box\n minWidth={isNarrow ? undefined : layout.sidebarColMin}\n p=\"4\"\n maxHeight=\"100%\"\n style={{\n flex: isNarrow ? \"1 1 100%\" : `0 0 ${layout.sidebarColBasis}`,\n border: \"1px solid var(--gray-5)\",\n borderRadius: \"var(--radius-4)\",\n background: \"var(--color-panel-solid)\",\n boxShadow: \"var(--shadow-card)\",\n overflow: \"auto\",\n }}\n >\n <MiniMonthPicker cursor={cursor} onSelect={setCursor} today={today} />\n\n <Separator size=\"4\" my=\"3\" />\n\n <Text\n as=\"p\"\n size=\"1\"\n weight=\"medium\"\n color=\"gray\"\n mb=\"3\"\n style={{ letterSpacing: \"0.04em\" }}\n >\n CALENDARS\n </Text>\n <Flex direction=\"column\" gap=\"1\" mb=\"4\">\n {accountGroups.map(({ accountId, calendarIds }, groupIdx) => {\n const account = accounts.find((a) => a.id === accountId);\n if (!account) return null;\n const collapsed = collapsedAccounts.has(accountId);\n return (\n <div\n key={accountId}\n style={{\n paddingTop: groupIdx > 0 ? \"var(--space-2)\" : undefined,\n borderTop: groupIdx > 0 ? \"1px solid var(--gray-3)\" : undefined,\n }}\n >\n <Flex\n align=\"center\"\n gap=\"2\"\n mb=\"2\"\n py=\"1\"\n className=\"calendar-legend-account-row\"\n style={{ cursor: \"pointer\", borderRadius: \"var(--radius-2)\" }}\n onClick={() => toggleAccountCollapsed(accountId)}\n >\n <ChevronDownIcon\n style={{\n ...iconSize(\"--space-3\"),\n color: \"var(--gray-9)\",\n transform: collapsed ? \"rotate(-90deg)\" : undefined,\n transition: \"transform 120ms ease\",\n flexShrink: 0,\n }}\n />\n <ProviderIcon provider={account.provider} />\n <Text\n size=\"2\"\n weight=\"medium\"\n truncate\n title={account.email}\n style={{ color: \"var(--gray-12)\", minWidth: 0 }}\n >\n {account.email}\n </Text>\n </Flex>\n {!collapsed && (\n <Flex direction=\"column\" gap=\"1\" pl=\"5\">\n {calendarIds.map((calId) => {\n const found = findCalendar(accounts, calId);\n if (!found) return null;\n return (\n <Text\n key={calId}\n as=\"label\"\n size=\"2\"\n className=\"calendar-legend-row\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-2)\",\n cursor: \"pointer\",\n borderRadius: \"var(--radius-2)\",\n padding: \"var(--space-1) var(--space-2)\",\n marginLeft: \"calc(var(--space-2) * -1)\",\n }}\n >\n <Flex align=\"center\" gap=\"1\">\n <Checkbox\n checked={visibleCalendarIds.has(calId)}\n onCheckedChange={() => toggleCalendarVisible(calId)}\n />\n <span\n aria-hidden\n style={{\n width: \"var(--space-3)\",\n height: \"var(--space-3)\",\n borderRadius: \"50%\",\n background: found.calendar.colorToken,\n flexShrink: 0,\n }}\n />\n </Flex>\n <Text size=\"2\" truncate style={{ color: \"var(--gray-12)\" }} title={found.calendar.name}>\n {found.calendar.name}\n </Text>\n </Text>\n );\n })}\n </Flex>\n )}\n </div>\n );\n })}\n </Flex>\n\n <Separator size=\"4\" mb=\"3\" />\n\n <Text\n as=\"label\"\n size=\"2\"\n style={{ display: \"flex\", alignItems: \"center\", gap: \"var(--space-2)\", cursor: \"pointer\" }}\n mb=\"3\"\n >\n <Checkbox checked={hideClones} onCheckedChange={(checked) => setHideClones(!!checked)} />\n Hide synced events\n </Text>\n\n <Separator size=\"4\" mb=\"3\" />\n\n <Link\n to={manageAccountsHref}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: \"var(--space-2)\",\n color: \"var(--gray-11)\",\n textDecoration: \"none\",\n }}\n >\n <GearIcon style={iconSize(\"--space-3\")} />\n <Text size=\"2\">Manage accounts</Text>\n </Link>\n\n <Text as=\"p\" size=\"1\" color=\"gray\" mt=\"4\">\n On your target calendars, others see only what each sync is set to share. Full detail\n stays in araMetrics.\n </Text>\n </Box>\n )}\n\n <Box\n width={isNarrow ? \"100%\" : undefined}\n minHeight={layout.bigCalendarH}\n height=\"100%\"\n style={{\n flex: isNarrow ? \"1 1 100%\" : `1 1 ${layout.syncColWide}`,\n minWidth: isNarrow ? 0 : layout.syncColMin,\n display: \"flex\",\n flexDirection: \"column\",\n alignSelf: \"stretch\",\n }}\n >\n {isNarrow && (\n <button\n type=\"button\"\n className=\"sidebar-icon-btn\"\n aria-label={sidebarOpen ? \"Hide calendars\" : \"Show calendars\"}\n style={{ alignSelf: \"flex-start\", marginBottom: \"var(--space-3)\" }}\n onClick={() => setSidebarOpen((o) => !o)}\n >\n <HamburgerMenuIcon style={iconSize(\"--space-4\")} />\n </button>\n )}\n <Box flexGrow=\"1\" minHeight=\"0\" height=\"100%\">\n <BigCalendarView\n blocks={blocks}\n view={view}\n onViewChange={setView}\n date={cursor}\n onNavigate={setCursor}\n accounts={accounts}\n today={today}\n />\n </Box>\n </Box>\n </Flex>\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\nimport {\n theme,\n type ThemeSize,\n type ThemeVariant,\n type ThemeVariantStyle,\n type ThemeColor,\n type ThemeColorShade,\n type ThemeRadius,\n type ThemeSpacing,\n getColor,\n} from \"./theme\";\nimport type { ResponsiveValue } from \"../types/common\";\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n\nexport function getVariantStyles(\n variant: ThemeVariant,\n style: ThemeVariantStyle = \"solid\"\n): string {\n return theme.variants[variant]?.[style] || theme.variants.primary[style];\n}\n\nexport function getSizeStyles(size: ThemeSize): string {\n const sizeConfig = theme.sizes[size] || theme.sizes.md;\n return `${sizeConfig.text} ${sizeConfig.padding} ${sizeConfig.height}`;\n}\n\nexport function getBaseStyles(): string {\n return cn(\n theme.base.transition,\n theme.base.focus,\n theme.base.disabled,\n theme.accessibility.reducedMotion\n );\n}\n\nexport function getInteractiveStyles(): string {\n return cn(theme.base.interactive, theme.accessibility.focusTrap, theme.accessibility.touchTarget);\n}\n\nexport function getAccessibilityStyles(\n options: {\n focusVisible?: boolean;\n highContrast?: boolean;\n reducedMotion?: boolean;\n } = {}\n): string {\n return cn(\n options.focusVisible && theme.accessibility.focusTrap,\n options.highContrast && theme.accessibility.highContrast,\n options.reducedMotion && theme.accessibility.reducedMotion\n );\n}\n\nexport function getResponsiveClasses<T extends string>(\n value: ResponsiveValue<T>,\n prefix: string = \"\"\n): string {\n if (typeof value === \"string\") {\n return `${prefix}${value}`;\n }\n\n if (typeof value === \"object\" && value !== null) {\n return Object.entries(value)\n .map(([breakpoint, val]) => {\n if (val === undefined) return \"\";\n const bp = breakpoint === \"xs\" ? \"\" : `${breakpoint}:`;\n return `${bp}${prefix}${val}`;\n })\n .filter(Boolean)\n .join(\" \");\n }\n\n return \"\";\n}\n\nexport function getSpacingClass(\n spacing: ThemeSpacing,\n type: \"gap\" | \"margin\" | \"padding\" = \"gap\"\n): string {\n const spacingValue = theme.spacing[spacing] || theme.spacing.md;\n\n switch (type) {\n case \"margin\":\n return spacingValue.replace(\"gap-\", \"m-\");\n case \"padding\":\n return spacingValue.replace(\"gap-\", \"p-\");\n default:\n return spacingValue;\n }\n}\n\nexport function getRadiusClass(radius: ThemeRadius): string {\n return theme.radius[radius] || theme.radius.md;\n}\n\nexport function getTypographyClass(typography: keyof typeof theme.typography): string {\n return theme.typography[typography] || theme.typography.base;\n}\n\nexport function getThemeColor(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return getColor(colorName, shade);\n}\n\nexport function getCSSVariableClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `[color:var(--color-${colorName}-${shade})]`;\n}\n\nexport function getBgClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `bg-${colorName}-${shade}`;\n}\n\nexport function getTextClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `text-${colorName}-${shade}`;\n}\n\nexport function getBorderClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `border-${colorName}-${shade}`;\n}\n\nexport function getHoverBgClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `hover:bg-${colorName}-${shade}`;\n}\n\nexport function getHoverTextClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `hover:text-${colorName}-${shade}`;\n}\n\nexport function getFocusRingClass(colorName: ThemeColor, shade: ThemeColorShade = 500): string {\n return `focus:ring-${colorName}-${shade}`;\n}\n\nexport function getAnimationClass(animation: keyof typeof theme.animations): string {\n const animationValue = theme.animations[animation];\n return typeof animationValue === \"string\" ? animationValue : \"\";\n}\n\nexport function validateProps<T extends Record<string, unknown>>(\n props: T,\n requiredProps: (keyof T)[],\n componentName?: string\n): void {\n const missing = requiredProps.filter((prop) => props[prop] === undefined);\n if (missing.length > 0) {\n const component = componentName ? ` in ${componentName}` : \"\";\n console.warn(`Missing required props${component}: ${missing.join(\", \")}`);\n }\n}\n\nexport function validateVariant<T extends string>(\n variant: T,\n validVariants: readonly T[],\n componentName?: string\n): boolean {\n if (!validVariants.includes(variant)) {\n const component = componentName ? ` in ${componentName}` : \"\";\n console.warn(\n `Invalid variant \"${variant}\"${component}. Valid variants: ${validVariants.join(\", \")}`\n );\n return false;\n }\n return true;\n}\n\nexport function createVariants<T extends Record<string, unknown>>(variants: T): T {\n return variants;\n}\n\nexport function createCompoundVariants<T>(\n base: string,\n variants: Record<string, Record<string, string>>,\n compoundVariants?: Array<{\n conditions: Record<string, string>;\n className: string;\n }>\n): (props: T) => string {\n return (props: T) => {\n let className = base;\n\n Object.entries(variants).forEach(([key, variantMap]) => {\n const value = (props as Record<string, unknown>)[key];\n if (value && variantMap[value as string]) {\n className += ` ${variantMap[value as string]}`;\n }\n });\n\n compoundVariants?.forEach(({ conditions, className: compoundClass }) => {\n const matches = Object.entries(conditions).every(\n ([key, value]) => (props as Record<string, unknown>)[key] === value\n );\n if (matches) {\n className += ` ${compoundClass}`;\n }\n });\n\n return cn(className);\n };\n}\n\nexport interface VariantConfig<T extends Record<string, Record<string, string>>> {\n base?: string;\n variants?: T;\n compoundVariants?: Array<{\n conditions: Partial<{ [K in keyof T]: keyof T[K] }>;\n className: string;\n }>;\n defaultVariants?: Partial<{ [K in keyof T]: keyof T[K] }>;\n}\n\nexport function createVariantGenerator<T extends Record<string, Record<string, string>>>(\n config: VariantConfig<T>\n) {\n return function generateVariantClasses(\n props: Partial<{ [K in keyof T]: keyof T[K] }> & { className?: string }\n ): string {\n const { className: customClassName, ...variantProps } = props;\n\n const mergedProps = { ...config.defaultVariants, ...variantProps };\n\n let classes = config.base || \"\";\n\n if (config.variants) {\n Object.entries(config.variants).forEach(([variantKey, variantMap]) => {\n const value = mergedProps[variantKey as keyof typeof mergedProps];\n if (value && variantMap[value as string]) {\n classes += ` ${variantMap[value as string]}`;\n }\n });\n }\n\n config.compoundVariants?.forEach(({ conditions, className: compoundClass }) => {\n const matches = Object.entries(conditions).every(\n ([key, value]) => mergedProps[key as keyof typeof mergedProps] === value\n );\n if (matches) {\n classes += ` ${compoundClass}`;\n }\n });\n\n return cn(classes, customClassName);\n };\n}\n\n// Utility for merging component props with defaults\nexport function mergeProps<T extends Record<string, unknown>>(\n defaultProps: Partial<T>,\n userProps: T\n): T {\n const merged = { ...defaultProps } as T;\n\n Object.keys(userProps).forEach((key) => {\n const userValue = userProps[key];\n const defaultValue = (defaultProps as Record<string, unknown>)[key];\n\n if (key === \"className\") {\n (merged as Record<string, unknown>)[key] = cn(\n defaultValue as string | undefined,\n userValue as string | undefined\n );\n } else if (\n typeof userValue === \"object\" &&\n typeof defaultValue === \"object\" &&\n userValue !== null &&\n defaultValue !== null &&\n !Array.isArray(userValue) &&\n !Array.isArray(defaultValue)\n ) {\n (merged as Record<string, unknown>)[key] = {\n ...(defaultValue as object),\n ...(userValue as object),\n };\n } else {\n (merged as Record<string, unknown>)[key] = userValue;\n }\n });\n\n return merged;\n}\n\n// Utility for conditional classes\nexport function conditionalClass(\n condition: boolean | undefined | null,\n trueClass: string,\n falseClass?: string\n): string {\n if (condition) return trueClass;\n if (falseClass && condition === false) return falseClass;\n return \"\";\n}\n\n// Utility for focus management\nexport function getFocusableElements(container: HTMLElement): HTMLElement[] {\n const focusableSelectors = [\n \"button:not([disabled])\",\n \"input:not([disabled])\",\n \"select:not([disabled])\",\n \"textarea:not([disabled])\",\n \"a[href]\",\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]',\n ].join(\", \");\n\n return Array.from(container.querySelectorAll(focusableSelectors));\n}\n\n// Utility for keyboard navigation\nexport function handleArrowNavigation(\n event: KeyboardEvent,\n elements: HTMLElement[],\n currentIndex: number,\n options: {\n loop?: boolean;\n orientation?: \"horizontal\" | \"vertical\" | \"both\";\n } = {}\n): number {\n const { loop = true, orientation = \"both\" } = options;\n let newIndex = currentIndex;\n\n switch (event.key) {\n case \"ArrowDown\":\n if (orientation === \"vertical\" || orientation === \"both\") {\n newIndex = currentIndex + 1;\n if (newIndex >= elements.length) {\n newIndex = loop ? 0 : elements.length - 1;\n }\n }\n break;\n case \"ArrowUp\":\n if (orientation === \"vertical\" || orientation === \"both\") {\n newIndex = currentIndex - 1;\n if (newIndex < 0) {\n newIndex = loop ? elements.length - 1 : 0;\n }\n }\n break;\n case \"ArrowRight\":\n if (orientation === \"horizontal\" || orientation === \"both\") {\n newIndex = currentIndex + 1;\n if (newIndex >= elements.length) {\n newIndex = loop ? 0 : elements.length - 1;\n }\n }\n break;\n case \"ArrowLeft\":\n if (orientation === \"horizontal\" || orientation === \"both\") {\n newIndex = currentIndex - 1;\n if (newIndex < 0) {\n newIndex = loop ? elements.length - 1 : 0;\n }\n }\n break;\n case \"Home\":\n newIndex = 0;\n break;\n case \"End\":\n newIndex = elements.length - 1;\n break;\n }\n\n if (newIndex !== currentIndex) {\n event.preventDefault();\n elements[newIndex]?.focus();\n }\n\n return newIndex;\n}\n","import React from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Theme } from \"@radix-ui/themes\";\nimport type { ThemeProps } from \"@radix-ui/themes\";\nimport \"@radix-ui/themes/styles.css\";\nimport \"../styles/radix-brand-tokens.css\";\n\nexport interface UIProviderProps extends Omit<Partial<ThemeProps>, \"children\"> {\n children: ReactNode;\n}\n\nexport function UIProvider({\n children,\n appearance = \"light\",\n radius = \"none\",\n scaling = \"100%\",\n accentColor = \"amber\",\n grayColor = \"gray\",\n panelBackground = \"solid\",\n className = \"\",\n}: UIProviderProps) {\n return (\n <Theme\n accentColor={accentColor}\n grayColor={grayColor}\n radius={radius}\n scaling={scaling}\n panelBackground={panelBackground}\n appearance={appearance}\n className={className}\n >\n {children}\n </Theme>\n );\n}\n\nexport default UIProvider;\n","/* Shell event bridge — typed events between the shell, its remotes and their\n * popup windows on the same origin.\n *\n * One BroadcastChannel (\"arm.shell.v1\") carries every event to the other\n * documents as an envelope {v: 1, id, type, payload}. A BroadcastChannel never\n * delivers to the instance that posted, so listeners in the emitting document\n * are called directly, synchronously, inside emit(). Each bridge calls its\n * listeners once per envelope id. Without BroadcastChannel only the emitting\n * document hears an event.\n *\n * Event types are named \"<app>.<event>\" — lowercase segments joined by dots,\n * e.g. \"calendar.oauth.completed\". Payloads are plain JSON (null, booleans,\n * finite numbers, strings, arrays and plain objects of those) and carry what\n * changed, never tokens or ids. emit() throws a TypeError for a malformed type\n * or a payload that is not plain JSON; envelopes received in another shape are\n * ignored. */\n\n/** Event type → payload type. Empty here: each app adds its own events by\n * declaration merging —\n *\n * declare module \"@aracreate/arm-ui\" {\n * interface ShellEventMap {\n * \"calendar.accounts.changed\": null;\n * }\n * }\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface ShellEventMap {}\n\nexport type ShellEventType = Extract<keyof ShellEventMap, string>;\n\nexport interface ShellEvents {\n /** Deliver `payload` to every listener for `type`, in this document and in\n * every other same-origin document. Throws a TypeError when the type is not\n * \"<app>.<event>\" or the payload is not plain JSON. */\n emit<K extends ShellEventType>(type: K, payload: ShellEventMap[K]): void;\n /** Listen for `type`; returns a function that stops listening. */\n on<K extends ShellEventType>(type: K, fn: (payload: ShellEventMap[K]) => void): () => void;\n}\n\nexport const SHELL_CHANNEL = \"arm.shell.v1\";\n\nconst EVENT_TYPE = /^[a-z][a-z0-9-]{0,31}(\\.[a-z][a-z0-9-]{0,31})+$/;\nconst SEEN_LIMIT = 256;\n\ninterface Envelope {\n v: 1;\n id: string;\n type: string;\n payload: unknown;\n}\n\nfunction isPlainJson(value: unknown, ancestors: object[] = []): boolean {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return true;\n if (typeof value === \"number\") return Number.isFinite(value);\n if (typeof value !== \"object\" || ancestors.includes(value)) return false;\n const inner = [...ancestors, value];\n if (Array.isArray(value)) return value.every((item) => isPlainJson(item, inner));\n const proto = Object.getPrototypeOf(value);\n if (proto !== Object.prototype && proto !== null) return false;\n return Object.values(value).every((item) => isPlainJson(item, inner));\n}\n\nfunction isEnvelope(data: unknown): data is Envelope {\n if (typeof data !== \"object\" || data === null) return false;\n const { v, id, type, payload } = data as Record<string, unknown>;\n return (\n v === 1 &&\n typeof id === \"string\" &&\n id !== \"\" &&\n typeof type === \"string\" &&\n EVENT_TYPE.test(type) &&\n isPlainJson(payload)\n );\n}\n\nfunction newId(): string {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\")\n return crypto.randomUUID();\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\n}\n\n/** A bridge of its own — `shell.events` is the one to use; this exists for tests. */\nexport function createShellEvents(): ShellEvents {\n const listeners = new Map<string, Set<(payload: unknown) => void>>();\n const seen = new Set<string>();\n let channel: BroadcastChannel | null | undefined;\n\n function deliver(envelope: Envelope) {\n if (seen.has(envelope.id)) return;\n seen.add(envelope.id);\n if (seen.size > SEEN_LIMIT) seen.delete(seen.values().next().value as string);\n for (const fn of [...(listeners.get(envelope.type) ?? [])]) fn(envelope.payload);\n }\n\n /* Opened on first use, so importing the library opens nothing. */\n function getChannel(): BroadcastChannel | null {\n if (channel === undefined) {\n channel =\n typeof BroadcastChannel === \"undefined\" ? null : new BroadcastChannel(SHELL_CHANNEL);\n channel?.addEventListener(\"message\", (event: MessageEvent) => {\n if (isEnvelope(event.data)) deliver(event.data);\n });\n }\n return channel;\n }\n\n return {\n emit(type, payload) {\n if (!EVENT_TYPE.test(type))\n throw new TypeError(`shell.events: \"${type}\" is not an \"<app>.<event>\" type`);\n if (!isPlainJson(payload))\n throw new TypeError(`shell.events: the payload of \"${type}\" is not plain JSON`);\n const envelope: Envelope = { v: 1, id: newId(), type, payload };\n getChannel()?.postMessage(envelope);\n deliver(envelope);\n },\n on(type, fn) {\n getChannel();\n const set = listeners.get(type) ?? new Set();\n listeners.set(type, set);\n const listener = fn as (payload: unknown) => void;\n set.add(listener);\n return () => {\n set.delete(listener);\n };\n },\n };\n}\n\nexport const shell: { events: ShellEvents } = { events: /* @__PURE__ */ createShellEvents() };\n","import * as React from \"react\";\n\nexport function useControllableState<T>({\n value,\n defaultValue,\n onChange,\n}: {\n value?: T;\n defaultValue?: T;\n onChange?: (value: T) => void;\n}) {\n const [internalValue, setInternalValue] = React.useState<T | undefined>(defaultValue);\n\n const isControlled = value !== undefined;\n const currentValue = isControlled ? value : internalValue;\n\n const setValue = React.useCallback(\n (newValue: T | ((prev: T | undefined) => T)) => {\n const resolvedValue =\n typeof newValue === \"function\"\n ? (newValue as (prev: T | undefined) => T)(currentValue)\n : newValue;\n\n if (!isControlled) {\n setInternalValue(resolvedValue);\n }\n\n onChange?.(resolvedValue);\n },\n [isControlled, currentValue, onChange]\n );\n\n return [currentValue, setValue] as const;\n}\n","import * as React from \"react\";\n\nexport function useDisclosure(defaultOpen = false) {\n const [isOpen, setIsOpen] = React.useState(defaultOpen);\n\n const open = React.useCallback(() => setIsOpen(true), []);\n const close = React.useCallback(() => setIsOpen(false), []);\n const toggle = React.useCallback(() => setIsOpen((prev) => !prev), []);\n\n return {\n isOpen,\n open,\n close,\n toggle,\n onOpen: open,\n onClose: close,\n onToggle: toggle,\n };\n}\n","import * as React from \"react\";\n\nexport function useClickOutside<T extends HTMLElement = HTMLElement>(\n handler: () => void,\n enabled = true\n) {\n const ref = React.useRef<T>(null);\n\n React.useEffect(() => {\n if (!enabled) return;\n\n const handleClickOutside = (event: MouseEvent) => {\n if (ref.current && !ref.current.contains(event.target as Node)) {\n handler();\n }\n };\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\n }, [handler, enabled]);\n\n return ref;\n}\n","export * from \"./src\";\n// The icon set is re-exported here, at the build entry, and not only from\n// src/components/icons.ts: esbuild keeps `export * from \"<external>\"` as a real\n// ESM re-export only in an entry file. Nested one level down it becomes a runtime\n// property copy, and `import { Cross2Icon } from \"@aracreate/arm-ui\"` then fails in\n// a bundler even though the types say it exists (3.8.0 shipped that way).\nexport * from \"@radix-ui/react-icons\";\n"],"mappings":"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","names":["Box","Flex","Grid","Container","Section","Inset","AspectRatio","ScrollArea","Separator","Text","Heading","Blockquote","Code","Em","Kbd","Link","Quote","Strong","Button","IconButton","TextField","TextArea","Checkbox","CheckboxGroup","CheckboxCards","Radio","RadioGroup","RadioCards","Select","Slider","Switch","SegmentedControl","Dialog","AlertDialog","DropdownMenu","ContextMenu","Popover","HoverCard","Tooltip","Portal","Avatar","Badge","Callout","Card","DataList","Progress","Spinner","Table","Tabs","TabNav","AccessibleIcon","Slot","Slottable","VisuallyHidden","jsx","Skeleton","width","height","radius","circle","mb","className","style","React","RadixAccordion","ChevronDownIcon","jsx","jsxs","Accordion","className","props","ref","AccordionItem","AccordionTrigger","children","AccordionContent","React","RadixDialog","Cross2Icon","jsx","jsxs","Drawer","DrawerTrigger","DrawerClose","DrawerContent","className","side","size","children","props","ref","DrawerHeader","DrawerTitle","DrawerDescription","DrawerDefaultClose","Box","Flex","Text","jsx","jsxs","AccentHeader","title","trailing","style","titleNode","AccentCard","children","bodyPadding","AlertDialog","Button","layout","Flex","jsx","CardFooter","children","justify","noTopMargin","pad","radius","jsx","jsxs","ConfirmDialog","title","description","confirmLabel","cancelLabel","onConfirm","trigger","open","onOpenChange","AlertDialog","layout","CardFooter","Button","PauseIcon","iconSize","space","jsx","jsxs","PausedBadge","label","style","PauseIcon","iconSize","Avatar","Box","DropdownMenu","Flex","IconButton","Text","DotsVerticalIcon","PauseIcon","PlayIcon","TrashIcon","jsx","jsxs","AccountCard","name","email","avatarSrc","paused","onPause","onResume","onDelete","onClick","badge","accentColor","style","nameText","Text","Box","layout","Flex","Avatar","PausedBadge","DropdownMenu","IconButton","e","DotsVerticalIcon","PlayIcon","PauseIcon","TrashIcon","Box","Flex","Heading","IconButton","Text","ChevronLeftIcon","ChevronRightIcon","headingSize","Fragment","jsx","jsxs","WEEKDAY_LABELS","CELL_WIDTH","CELL_HEIGHT","GRID_GAP","MONTH_YEAR_FORMAT","FULL_DATE_FORMAT","isSameDay","a","b","mondayIndex","jsDay","buildGridDays","month","monthIndex","year","firstOfMonth","lastOfMonth","leadingCount","trailingCount","gridStart","totalDays","_","i","date","addMonths","delta","MonthGrid","onMonthChange","events","dayDots","today","onSelectDay","style","resolvedToday","days","eventDayKeys","d","Flex","IconButton","ChevronLeftIcon","iconSize","Heading","headingSize","layout","ChevronRightIcon","Box","label","Text","inCurrentMonth","isToday","dots","hasEvent","cellStyle","dayNumber","color","key","useEffect","Callout","CheckCircledIcon","ExclamationTriangleIcon","jsx","jsxs","Toast","msg","color","onDone","durationMs","useEffect","t","layout","Callout","ExclamationTriangleIcon","CheckCircledIcon","jsx","IconTile","children","size","Box","Flex","Text","LockClosedIcon","jsx","jsxs","EventBlock","title","time","detail","color","locked","Box","jsx","DataTableRow","children","style","showBorder","onActivate","selected","className","ariaLabel","interactive","handleKeyDown","e","useId","Card","Flex","Text","jsx","jsxs","MetricCard","label","value","delta","deltaDir","goodDirection","statusColor","sparkline","Sparkline","data","color","min","range","pts","v","i","line","p","area","gradId","Link","Badge","Button","Card","Flex","Text","ArrowRightIcon","jsx","jsxs","AppCard","href","icon","name","description","badge","Card","Flex","IconTile","Text","Badge","CardFooter","Button","Link","ArrowRightIcon","iconSize","Text","jsx","jsxs","ActivityRow","tag","tagColor","msg","actor","timeAgo","timestamp","showBorder","DataTableRow","Text","Button","Card","Flex","Text","ExclamationTriangleIcon","jsx","jsxs","DashboardErrorCard","onRetry","message","Card","Flex","IconTile","ExclamationTriangleIcon","iconSize","Text","Button","useMemo","Button","Flex","IconButton","Text","ChevronLeftIcon","ChevronRightIcon","DoubleArrowLeftIcon","DoubleArrowRightIcon","jsx","jsxs","ELLIPSIS","buildPageRange","currentPage","totalPages","siblingCount","totalVisible","_","i","leftSibling","rightSibling","showLeftEllipsis","showRightEllipsis","span","rightRange","middleRange","Pagination","onPageChange","showFirstLast","size","pages","atFirst","atLast","page","index","ROLE_META","ROLE_LABELS","STATUS_META","METRIC_STATUS_COLOR","ACTIVITY_META","AUDIT_ACTION_META","auditActionMeta","action","jsx","BrandPanel","layout","jsx","jsxs","AuthCard","children","BrandPanel","layout","jsx","jsxs","GoogleIcon","jsx","jsxs","MicrosoftIcon","useRef","TextField","jsx","OtpInput","value","onChange","disabled","inputs","handleChange","i","e","ch","digits","_","k","handleKeyDown","handlePaste","pasted","d","el","Button","Callout","Heading","Text","ExclamationTriangleIcon","Fragment","jsx","jsxs","OtpVerifyStep","email","title","subtitle","code","onCodeChange","otpDevHint","error","errorAction","busy","otpExpiresAt","otpSecondsLeft","resendCooldown","onResend","onUseDifferentEmail","Heading","headingSize","Text","Callout","ExclamationTriangleIcon","Button","OtpInput","jsx","ProviderIcon","provider","MicrosoftIcon","GoogleIcon","PROVIDER_LABEL","useEffect","useRef","useState","Link","useLocation","Avatar","Badge","DropdownMenu","IconButton","Text","Tooltip","ChevronDownIcon","ChevronLeftIcon","ChevronRightIcon","Cross1Icon","DotFilledIcon","DotsVerticalIcon","ExitIcon","GearIcon","QuestionMarkCircledIcon","Fragment","jsx","jsxs","SHELL_HEADER_H","isNavGroup","entry","fullLabel","item","readFoldState","key","parsed","pair","writeFoldState","state","WIDTH_EXPANDED","WIDTH_COLLAPSED","WIDTH_DRAWER","ROW_H","PILL_L","PILL_R","ICON_X","LABEL_GAP","labelTransition","expanded","LOGO_TRANSITION","Sidebar","collapsed","onToggle","onClose","items","persistKey","utilityHrefsProp","user","onSignOut","hasCalendarAccounts","brandLogoExpandedSrc","brandLogoCollapsedSrc","helpHref","devRoles","onDevRoleSelect","showDevRoles","pathname","useLocation","confirmLogoutOpen","setConfirmLogoutOpen","useState","backTo","setBackTo","clearBack","rootRef","useRef","focusAfterStep","drillIn","isDrawer","width","allowed","prune","children","visibleEntries","groupItems","topLevelItems","visibleItems","foldState","setFoldState","isFolded","group","toggleGroup","next","utilityHrefs","primaryEntries","settingsItem","utilityItems","sectionRoot","drillable","inSection","root","urlPath","level","section","depth","activeSection","stepBack","useEffect","target","node","isActive","href","end","renderTopRow","renderRow","uppercase","active","drills","row","NavRow","Tooltip","renderGroup","listId","folded","GroupHeading","isAdminContext","initials","n","IconButton","Cross1Icon","iconSize","backRow","ChevronLeftIcon","child","Badge","DotFilledIcon","Avatar","Text","DropdownMenu","DotsVerticalIcon","Link","GearIcon","QuestionMarkCircledIcon","ExitIcon","r","PanelToggleIcon","ConfirmDialog","onClick","asButton","showChevron","rowStyle","body","ChevronRightIcon","label","holdsActive","controls","ChevronDownIcon","flipped","Link","useLocation","HamburgerMenuIcon","MagnifyingGlassIcon","BellIcon","Flex","Heading","IconButton","Text","Tooltip","Fragment","jsx","jsxs","DEFAULT_TITLES","DEFAULT_ADMIN_TITLES","matchesRow","pathname","prefix","exact","want","got","segment","breadcrumb","titles","adminTitles","hit","p","section","sectionHref","page","adminHit","Topbar","onSearchOpen","onMenuOpen","showMenu","useLocation","SHELL_HEADER_H","IconButton","HamburgerMenuIcon","iconSize","Flex","Text","Link","Heading","headingSize","MagnifyingGlassIcon","Tooltip","BellIcon","useEffect","useRef","useState","Dialog","Flex","Spinner","Text","TextField","VisuallyHidden","CalendarIcon","MagnifyingGlassIcon","PersonIcon","ReaderIcon","Fragment","jsx","jsxs","TYPE_ICON","TYPE_LABEL","groupResults","results","order","groups","flat","t","items","r","SearchOverlay","open","onClose","resultPool","onSelectResult","title","placeholder","o","SearchBody","query","setQuery","searchResults","setSearchResults","selectedIdx","setSelectedIdx","inputRef","listRef","isCurrent","state","q","found","handleKeyDown","e","i","selectResult","result","grouped","promptHeight","group","Icon","flatIdx","isSelected","findCalendar","accounts","calendarId","account","calendar","c","dayjs","Flex","Text","jsx","jsxs","CalendarDayHeader","date","today","isToday","Box","Checkbox","Flex","RadioGroup","Text","jsx","jsxs","rowsFromAccounts","accounts","account","cal","ProviderMark","provider","ProviderIcon","CalendarRow","row","control","selected","disabled","disabledLabel","Text","Flex","Box","CalendarPickList","mode","sourceCalendarIds","targetCalendarId","takenSourceIds","onToggleSource","onSelectTarget","fill","rows","list","idx","isTarget","takenElsewhere","Checkbox","isSource","RadioGroup","v","Button","Flex","Heading","IconButton","ChevronLeftIcon","ChevronRightIcon","Navigate","jsx","jsxs","CalendarToolbar","label","view","onNavigate","onView","Flex","IconButton","Navigate","ChevronLeftIcon","Button","ChevronRightIcon","Heading","headingSize","v","Button","Flex","Spinner","Text","ChevronRightIcon","ExclamationTriangleIcon","jsx","jsxs","PROVIDER_META","PROVIDERS","ConnectProviderList","connectingProvider","failedProvider","exhausted","onConnect","Flex","provider","meta","connecting","IconTile","ProviderIcon","Text","Spinner","ChevronRightIcon","iconSize","ExclamationTriangleIcon","Button","Badge","Box","DropdownMenu","Flex","IconButton","Text","DotsVerticalIcon","ReloadIcon","TrashIcon","jsx","jsxs","ConnectedAccountCard","account","onRemove","onReconnect","onClick","needsReauth","hasFailed","name","Text","Box","layout","IconTile","ProviderIcon","Flex","e","Badge","DropdownMenu","IconButton","DotsVerticalIcon","ReloadIcon","TrashIcon","Flex","Text","Heading","jsx","jsxs","EmptyCard","icon","title","description","action","headingAs","Flex","IconTile","Heading","headingSize","Text","layout","useState","Dialog","Flex","Text","Checkbox","Button","Fragment","jsx","jsxs","ImportCalendarsDialog","account","onOpenChange","onImport","initiallySelectedIds","disabledIds","disabledReason","title","description","confirmLabel","formKey","c","Dialog","layout","event","ImportCalendarsForm","selected","setSelected","useState","disabled","toggle","id","prev","next","Text","Flex","cal","checked","isDisabled","Checkbox","CardFooter","Button","Box","Flex","Text","jsx","jsxs","readableTextOn","hex","m","int","channel","c","v","EventChip","tone","title","meta","accentColor","background","foreground","DEFAULT_TAG_LABEL","DEFAULT_SAMPLE","SyncPreviewRail","hasSources","hasTarget","sourceLabel","targetLabel","showTitle","showDescription","showLocation","tagLabel","sampleEvent","sourceTitle","sourceMeta","tag","postedTitle","postedMetaParts","postedMeta","Flex","Text","CheckIcon","jsx","jsxs","WizardStepper","steps","current","step","i","index","active","done","Flex","CheckIcon","iconSize","Text","jsx","FIRST_RUN_STEPS","OnboardingStepper","current","WizardStepper","OnboardingStepDots","total","dayjs","Flex","Grid","IconButton","Text","ChevronLeftIcon","ChevronRightIcon","jsx","jsxs","WEEKDAY_LABELS","MiniMonthPicker","cursor","onSelect","today","monthStart","gridStart","days","_","i","w","d","isToday","isSelected","isOffMonth","useState","Dialog","Flex","Text","Button","IconButton","Badge","Separator","Box","Cross2Icon","PlusIcon","ReloadIcon","Fragment","jsx","jsxs","AccountCalendarsDialog","account","catalog","onOpenChange","onRemoveCalendar","onSaveCalendars","onReconnect","managing","setManaging","useState","needsReauth","hasFailed","handleManageSave","selectedCalendarIds","selected","c","Dialog","open","layout","Flex","IconTile","ProviderIcon","Box","Badge","Button","ReloadIcon","Separator","Text","PlusIcon","iconSize","cal","idx","IconButton","Cross2Icon","CardFooter","ImportCalendarsDialog","useMemo","dayjs","Calendar","dayjsLocalizer","Views","Text","jsx","jsxs","localizer","dayjsLocalizer","dayjs","SCROLL_TO_TIME","BigCalendarView","blocks","view","onViewChange","date","onNavigate","accounts","today","events","useMemo","b","start","end","Calendar","Views","v","event","color","findCalendar","CalendarToolbar","headerProps","CalendarDayHeader","durationMin","showLocation","showTimeRange","Text","Dialog","Flex","Text","Button","Separator","Badge","Fragment","jsx","jsxs","STATUS_META","SyncDetailsDialog","sync","accounts","onOpenChange","onEdit","calendarsSummary","sources","cid","findCalendar","n","target","Dialog","layout","Flex","Badge","DetailRow","found","Text","Separator","CardFooter","Button","label","children","useState","useConnectAccount","accounts","connectProvider","onAccountAdded","onImported","connectingProvider","setConnectingProvider","pendingAccount","setPendingAccount","failedProvider","setFailedProvider","exhausted","setExhausted","connect","provider","connectedIds","a","account","confirmImport","selectedCalendarIds","selected","c","Box","DropdownMenu","Button","Flex","Text","PlusIcon","Fragment","jsx","jsxs","AddAccountMenu","variant","trigger","accounts","connectProvider","onAccountAdded","onImported","pendingAccount","failedProvider","exhausted","connect","confirmImport","cancelImport","dismissError","useConnectAccount","providers","defaultTrigger","PlusIcon","iconSize","Button","menu","DropdownMenu","provider","meta","PROVIDER_META","IconTile","ProviderIcon","Flex","Text","Box","ImportCalendarsDialog","open","Toast","Card","Flex","Text","Heading","CalendarIcon","jsx","jsxs","ConnectProviderRows","accounts","connectProvider","onAccountAdded","onImported","connectingProvider","pendingAccount","failedProvider","exhausted","connect","confirmImport","cancelImport","useConnectAccount","Flex","Card","layout","IconTile","CalendarIcon","iconSize","Heading","headingSize","Text","ConnectProviderList","ImportCalendarsDialog","open","useEffect","useMemo","useState","Link","Box","Checkbox","Flex","Separator","Text","ChevronDownIcon","GearIcon","HamburgerMenuIcon","jsx","jsxs","CalendarMergedView","accounts","view","setView","hideClones","setHideClones","mergedCalendarIds","visibleCalendarIds","toggleCalendarVisible","getVisibleBlocksInRange","manageAccountsHref","today","cursor","setCursor","useState","collapsedAccounts","setCollapsedAccounts","isNarrow","setIsNarrow","sidebarOpen","setSidebarOpen","useEffect","onResize","rangeStart","useMemo","d","rangeEnd","blocks","accountGroups","groups","index","calId","found","findCalendar","i","toggleAccountCollapsed","accountId","prev","next","Flex","Box","layout","MiniMonthPicker","Separator","Text","calendarIds","groupIdx","account","a","collapsed","ChevronDownIcon","iconSize","ProviderIcon","Checkbox","checked","Link","GearIcon","o","HamburgerMenuIcon","BigCalendarView","clsx","twMerge","cn","inputs","twMerge","clsx","getVariantStyles","variant","style","theme","getSizeStyles","size","sizeConfig","getBaseStyles","getInteractiveStyles","getAccessibilityStyles","options","getResponsiveClasses","value","prefix","breakpoint","val","getSpacingClass","spacing","type","spacingValue","getRadiusClass","radius","getTypographyClass","typography","getBgClass","colorName","shade","getTextClass","getBorderClass","getHoverBgClass","getHoverTextClass","getFocusRingClass","getAnimationClass","animation","animationValue","theme","createCompoundVariants","base","variants","compoundVariants","props","className","key","variantMap","value","conditions","compoundClass","cn","createVariantGenerator","config","customClassName","variantProps","mergedProps","classes","variantKey","mergeProps","defaultProps","userProps","merged","userValue","defaultValue","conditionalClass","condition","trueClass","falseClass","getFocusableElements","container","focusableSelectors","handleArrowNavigation","event","elements","currentIndex","options","loop","orientation","newIndex","Theme","jsx","UIProvider","children","appearance","radius","scaling","accentColor","grayColor","panelBackground","className","Theme","SHELL_CHANNEL","EVENT_TYPE","isPlainJson","value","ancestors","inner","item","proto","isEnvelope","data","v","id","type","payload","EVENT_TYPE","newId","createShellEvents","listeners","seen","channel","deliver","envelope","fn","getChannel","SHELL_CHANNEL","event","set","listener","shell","React","useControllableState","value","defaultValue","onChange","internalValue","setInternalValue","isControlled","currentValue","setValue","newValue","resolvedValue","React","useDisclosure","defaultOpen","isOpen","setIsOpen","open","close","toggle","prev","React","useClickOutside","handler","enabled","ref","handleClickOutside","event"]}
|