@inkorange/space-ui 1.12.0 → 1.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/components/propShared.ts","../src/components/Text.tsx","../src/components/Heading.tsx","../src/components/Link.tsx","../src/components/Flex.tsx","../src/components/Box.tsx","../src/components/Grid.tsx","../src/components/Badge.tsx","../src/components/Separator.tsx","../src/components/Card.tsx","../src/internal/seededRandom.ts","../src/components/Button.tsx","../src/components/icons.tsx","../src/components/Carousel.tsx","../src/styles/spaceControls.ts","../src/components/Pagination.tsx","../src/components/Loader.tsx","../src/internal/showMeasured.ts","../src/components/Tooltip.tsx","../src/components/IconToggle.tsx","../src/components/Select.tsx","../src/components/TextField.tsx","../src/components/TextArea.tsx","../src/components/Autocomplete.tsx","../src/components/Slider.tsx","../src/internal/chartScale.ts","../src/components/Chart.tsx","../src/components/BarList.tsx","../src/components/PieChart.tsx","../src/components/Checkbox.tsx","../src/components/RadioGroup.tsx","../src/components/Progress.tsx","../src/components/Message.tsx","../src/components/Dialog.tsx","../src/components/AlertDialog.tsx","../src/components/DropdownMenu.tsx","../src/components/Tabs.tsx","../src/components/Popover.tsx"],"sourcesContent":["// Shared prop plumbing for the design-system primitives. The spacing map is\n// the single place Radix's numeric steps meet our t-shirt tokens; \"3\" (12px)\n// rounds UP to md per the spec's when-in-doubt-go-up rule.\nimport type { CSSProperties } from \"react\";\n\nexport type SpaceStep = \"0\" | \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\";\n\nexport interface SpacingProps {\n m?: SpaceStep;\n mt?: SpaceStep;\n mb?: SpaceStep;\n p?: SpaceStep;\n pb?: SpaceStep;\n}\n\nconst SPACE: Record<SpaceStep, string> = {\n \"0\": \"0\",\n \"1\": \"var(--spacing-xs)\",\n \"2\": \"var(--spacing-sm)\",\n \"3\": \"var(--spacing-md)\",\n \"4\": \"var(--spacing-md)\",\n \"5\": \"var(--spacing-lg)\",\n \"6\": \"var(--spacing-xl)\",\n};\n\nexport function spacingStyle(\n { m, mt, mb, p, pb }: SpacingProps,\n style?: CSSProperties,\n): CSSProperties | undefined {\n const out: CSSProperties = {\n ...(m !== undefined && { margin: SPACE[m] }),\n ...(mt !== undefined && { marginTop: SPACE[mt] }),\n ...(mb !== undefined && { marginBottom: SPACE[mb] }),\n ...(p !== undefined && { padding: SPACE[p] }),\n ...(pb !== undefined && { paddingBottom: SPACE[pb] }),\n ...style,\n };\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nexport function cx(...parts: Array<string | false | undefined>): string {\n return parts.filter(Boolean).join(\" \");\n}\n","import type * as React from \"react\";\nimport { createElement, forwardRef, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Text.module.scss\";\n\nexport interface TextProps\n extends SpacingProps,\n Omit<React.HTMLAttributes<HTMLElement>, \"color\"> {\n /** Element to render. Default `span`. Use `p` for prose and `label`\n * (with `htmlFor`) for form labels — size is presentational, so the\n * element stays free to be the semantically correct one. */\n as?: \"span\" | \"div\" | \"p\" | \"label\";\n /** Font size step: 1=12px, 2=14px, 3=16px, 4=18px, 5=20px, 6=24px.\n * Line height and letter spacing move with it. Omit to inherit. */\n size?: \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\";\n /** 500 or 700. Omit for the inherited weight. */\n weight?: \"medium\" | \"bold\";\n /** Semantic colour role. `gray` is the standard secondary-text token;\n * the rest carry meaning, so avoid them for emphasis alone. Omit for\n * primary text. */\n /** Semantic colour role. `muted` is the standard secondary-text token;\n * the rest carry meaning, so avoid them for emphasis alone. Omit for\n * primary text. */\n color?: \"muted\" | \"danger\" | \"success\" | \"warning\";\n /** Id of the control this labels. Only meaningful with `as=\"label\"`. */\n htmlFor?: string;\n /** The text. */\n children?: ReactNode;\n}\n\n/**\n * Body copy. Size, weight and colour are presentational and independent of\n * the element, so `as` stays free to be whatever the document actually needs\n * — a `p` for prose, a `label` for a field, a `span` inline.\n *\n * Colour is a role, not a hue: use `muted` for secondary copy and reserve the\n * status roles for text that genuinely carries that meaning.\n */\nexport const Text = forwardRef<HTMLElement, TextProps>(function Text(\n { as = \"span\", size, weight, color, className, style, m, mt, mb, p, pb, ...rest },\n ref,\n) {\n return createElement(as, {\n ...rest,\n ref,\n className: cx(\n styles.text,\n size && styles[`size${size}`],\n weight && styles[weight],\n color && styles[`color${color[0].toUpperCase()}${color.slice(1)}`],\n className,\n ),\n style: spacingStyle({ m, mt, mb, p, pb }, style),\n });\n});\n","import type * as React from \"react\";\nimport { createElement, forwardRef, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Heading.module.scss\";\n\nexport interface HeadingProps\n extends SpacingProps,\n Omit<React.HTMLAttributes<HTMLHeadingElement>, \"color\"> {\n /** Heading level to render. Default `h2`. Independent of `size`, so\n * document outline stays correct without dictating appearance. */\n as?: \"h1\" | \"h2\" | \"h3\" | \"h4\";\n /** Font size step: 4=18px, 5=20px, 6=24px, 7=28px, 8=35px, 9=60px.\n * Shares steps 4–6 with Text, so a Heading and Text can sit on the\n * same line and match. */\n size?: \"4\" | \"5\" | \"6\" | \"7\" | \"8\" | \"9\";\n /** Semantic colour role. Omit for primary heading colour. */\n color?: \"muted\" | \"danger\";\n /** Centres the text. There is no `left`/`right` — headings are\n * start-aligned unless deliberately centred. */\n align?: \"center\";\n /** The heading text. */\n children?: ReactNode;\n}\n\n/**\n * A section heading. `as` sets the heading level and `size` sets the\n * appearance, deliberately apart — so a visually small heading can still be\n * an h2 where the document structure calls for one.\n *\n * Shares size steps 4-6 with Text, so a heading and body copy on the same\n * line align.\n */\nexport const Heading = forwardRef<HTMLHeadingElement, HeadingProps>(function Heading(\n { as = \"h2\", size, color, align, className, style, m, mt, mb, p, pb, ...rest },\n ref,\n) {\n return createElement(as, {\n ...rest,\n ref,\n className: cx(\n styles.heading,\n size && styles[`size${size}`],\n color === \"muted\" && styles.colorMuted,\n color === \"danger\" && styles.colorDanger,\n align === \"center\" && styles.alignCenter,\n className,\n ),\n style: spacingStyle({ m, mt, mb, p, pb }, style),\n });\n});\n","import type * as React from \"react\";\nimport { cloneElement, forwardRef, isValidElement, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Link.module.scss\";\n\nexport interface LinkProps\n extends SpacingProps,\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, \"color\"> {\n /** Render the single child element instead of an `<a>`, merging link\n * styling onto it. For wrapping a router's own Link component without\n * nesting two anchors. */\n asChild?: boolean;\n /** Font size step: 1=12px, 2=14px, 3=16px. Matches Text's first three\n * steps so inline links sit flush with surrounding copy. */\n size?: \"1\" | \"2\" | \"3\";\n /** Link text. With `asChild`, the single element to style as a link. */\n children?: ReactNode;\n}\n\n/**\n * An inline anchor, styled to sit inside running text without disturbing its\n * rhythm. Sizes match Text's first three steps.\n *\n * Use `asChild` to wrap a router's own link component rather than nesting two\n * anchors, which is invalid and breaks keyboard navigation.\n */\nexport const Link = forwardRef<HTMLAnchorElement, LinkProps>(function Link(\n { asChild, size, className, style, m, mt, mb, p, pb, children, ...rest },\n ref,\n) {\n const cls = cx(styles.link, size && styles[`size${size}`], className);\n const merged = spacingStyle({ m, mt, mb, p, pb }, style);\n if (asChild && isValidElement(children)) {\n const child = children as React.ReactElement<{ className?: string; style?: React.CSSProperties }>;\n return cloneElement(child, {\n ...rest,\n className: cx(cls, child.props.className),\n style: { ...merged, ...child.props.style },\n });\n }\n return (\n <a {...rest} ref={ref} className={cls} style={merged}>\n {children}\n </a>\n );\n});\n","import type * as React from \"react\";\nimport { cloneElement, forwardRef, isValidElement, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Flex.module.scss\";\n\nexport interface FlexProps extends SpacingProps, React.HTMLAttributes<HTMLDivElement> {\n /** Render the single child element instead of a wrapper div, merging\n * the flex styling onto it. Avoids a redundant layer in the DOM. */\n asChild?: boolean;\n /** Gap step: 1=4px, 2=8px, 3=12px, 4=16px, 5=24px, 6=32px. Note step 3\n * is 12px — off the 8pt grid, kept for parity with the shipped app. */\n gap?: \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\";\n /** Main axis. Default `row`. */\n direction?: \"row\" | \"column\";\n /** Cross-axis alignment (`align-items`). */\n align?: \"start\" | \"center\" | \"end\" | \"baseline\" | \"stretch\";\n /** Main-axis distribution (`justify-content`). */\n justify?: \"start\" | \"center\" | \"end\" | \"between\";\n /** Wrapping behaviour. Default is the browser's `nowrap`. */\n wrap?: \"wrap\" | \"nowrap\";\n /** The items to lay out. */\n children?: ReactNode;\n}\n\nconst cap = (s: string) => s[0].toUpperCase() + s.slice(1);\n\n/**\n * A flex row or column whose gap comes from the spacing scale, so layouts\n * inherit the 8pt grid instead of restating it in pixels.\n *\n * `asChild` merges the layout onto its only child rather than adding a\n * wrapper, for when an extra div would break a grid or a selector.\n */\nexport const Flex = forwardRef<HTMLDivElement, FlexProps>(function Flex(\n { asChild, gap, direction, align, justify, wrap, className, style, m, mt, mb, p, pb, children, ...rest },\n ref,\n) {\n const cls = cx(\n styles.flex,\n gap && styles[`gap${gap}`],\n direction && styles[`direction${cap(direction)}`],\n align && styles[`align${cap(align)}`],\n justify && styles[`justify${cap(justify)}`],\n wrap && styles[`wrap${cap(wrap)}`],\n className,\n );\n const merged = spacingStyle({ m, mt, mb, p, pb }, style);\n if (asChild && isValidElement(children)) {\n const child = children as React.ReactElement<{ className?: string; style?: React.CSSProperties }>;\n return cloneElement(child, {\n ...rest,\n className: cx(cls, child.props.className),\n style: { ...merged, ...child.props.style },\n });\n }\n return (\n <div {...rest} ref={ref} className={cls} style={merged}>\n {children}\n </div>\n );\n});\n","import type * as React from \"react\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { spacingStyle, type SpacingProps } from \"./propShared\";\n\nexport interface BoxProps extends SpacingProps, React.HTMLAttributes<HTMLDivElement> {\n /** Anything. Box adds no styling of its own. */\n children?: ReactNode;\n}\n\n// Radix Box at our call sites is a plain div carrying className/style/ref —\n// no layout props anywhere (verified by inventory). Keep it exactly that.\n\n/**\n * A plain div that understands the spacing scale. The escape hatch for when\n * you need margin or padding on the grid but no layout behaviour with it.\n *\n * Renders nothing of its own — no class, no styling — so it never interferes\n * with whatever you put inside.\n */\nexport const Box = forwardRef<HTMLDivElement, BoxProps>(function Box(\n { style, m, mt, mb, p, pb, ...rest },\n ref,\n) {\n return <div {...rest} ref={ref} style={spacingStyle({ m, mt, mb, p, pb }, style)} />;\n});\n","import type * as React from \"react\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Grid.module.scss\";\n\ntype Cols = \"1\" | \"2\" | \"3\";\nexport interface GridProps extends SpacingProps, React.HTMLAttributes<HTMLDivElement> {\n /** Column count, 1–3. Pass an object for responsive counts:\n * `{ initial: \"1\", sm: \"2\", md: \"3\" }` — `initial` applies below the\n * first breakpoint. */\n columns?: Cols | { initial?: Cols; sm?: Cols; md?: Cols };\n /** Gap step: 1=4px, 2=8px, 3=12px, 4=16px, 5=24px, 6=32px. Same scale\n * as Flex. */\n gap?: \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\";\n /** The cells. */\n children?: ReactNode;\n}\n\n/**\n * A simple column grid, 1-3 wide, with the same gap scale as Flex. Pass an\n * object to `columns` for responsive counts.\n *\n * Deliberately narrow: anything more elaborate is a job for CSS grid directly\n * rather than a prop API that would end up reinventing it.\n */\nexport const Grid = forwardRef<HTMLDivElement, GridProps>(function Grid(\n { columns, gap, className, style, m, mt, mb, p, pb, ...rest },\n ref,\n) {\n const colCls =\n typeof columns === \"string\"\n ? [styles[`cols${columns}`]]\n : columns\n ? [\n columns.initial && styles[`cols${columns.initial}`],\n columns.sm && styles[`smCols${columns.sm}`],\n columns.md && styles[`mdCols${columns.md}`],\n ]\n : [];\n return (\n <div\n {...rest}\n ref={ref}\n className={cx(styles.grid, ...(colCls as string[]), gap && styles[`gap${gap}`], className)}\n style={spacingStyle({ m, mt, mb, p, pb }, style)}\n />\n );\n});\n","import type * as React from \"react\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Badge.module.scss\";\n\n/**\n * Roles whose colour carries meaning — status and emphasis.\n */\nexport type BadgeSemanticColor =\n | \"muted\"\n | \"primary\"\n | \"success\"\n | \"warning\"\n | \"danger\";\n\n/**\n * Categorical hues for telling data apart — star classes, planet types — where\n * the colour distinguishes rather than signals. These deliberately keep hue\n * names: for a categorical scale the hue IS the identity, and calling one\n * \"tertiary\" would imply a ranking that does not exist.\n */\nexport type BadgeCategoricalColor =\n | \"cyan\"\n | \"purple\"\n | \"orange\"\n | \"yellow\"\n | \"accent\";\n\nexport type BadgeColor = BadgeSemanticColor | BadgeCategoricalColor;\n\nexport interface BadgeProps\n extends SpacingProps,\n Omit<React.HTMLAttributes<HTMLSpanElement>, \"color\"> {\n /** Semantic role or categorical hue. Roles carry meaning — pick one\n * that matches the state, not the look you want.\n */\n color?: BadgeColor;\n /** `soft` is a tinted wash for dense lists; `solid` is a filled chip\n * for a badge that must win attention.\n */\n variant?: \"soft\" | \"solid\";\n /** 1 is the default chip; 2 is for standalone use away from body text. */\n size?: \"1\" | \"2\";\n /** Badges are single-line by default: one that wraps stops reading as a\n * badge. Opt into wrapping for free text you do not control — anything a\n * reader named rather than you — so it cannot overflow what contains it. */\n wrap?: boolean;\n /** Label text. Keep it short — a badge that wraps stops reading as one. */\n children?: ReactNode;\n}\n\nconst cap = (s: string) => s[0].toUpperCase() + s.slice(1);\n\n// Default color is \"blue\" (not \"gray\") to match Radix's behavior: Badge's\n// `color` prop had no hardcoded default there either — it inherited the\n// surrounding Theme's `accentColor`, which this app sets to \"blue\" (see the\n// single <Theme accentColor> in the host app). A caller that wants a\n// neutral badge should pass color=\"muted\" explicitly.\n/**\n * A compact status label. Colour is the message, so choose it for meaning:\n * the semantic roles say safe, pending or destructive, while the categorical\n * hues only tell one kind of thing from another and carry no judgement.\n *\n * Single-line by default, since a badge that wraps stops reading as a badge.\n * Opt into `wrap` for free text you do not control.\n */\nexport const Badge = forwardRef<HTMLSpanElement, BadgeProps>(function Badge(\n { color = \"primary\", variant = \"soft\", size = \"1\", wrap, className, style, m, mt, mb, p, pb, ...rest },\n ref,\n) {\n return (\n <span\n {...rest}\n ref={ref}\n className={cx(\n styles.badge,\n styles[`color${cap(color)}`],\n variant === \"solid\" && styles.solid,\n styles[`size${size}`],\n wrap && styles.wrap,\n className,\n )}\n style={spacingStyle({ m, mt, mb, p, pb }, style)}\n />\n );\n});\n","import type * as React from \"react\";\nimport { forwardRef } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./Separator.module.scss\";\n\nexport interface SeparatorProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Length of the rule, 1 (shortest) to 4 (full width of its container). */\n size?: \"1\" | \"2\" | \"3\" | \"4\";\n}\n\n/**\n * A hairline rule for dividing content within a surface, where a full panel\n * boundary would be too heavy. Exposed as `role=\"separator\"`, so assistive\n * technology hears the division too.\n */\nexport const Separator = forwardRef<HTMLSpanElement, SeparatorProps>(function Separator(\n { size = \"4\", className, ...rest },\n ref,\n) {\n return (\n <span\n {...rest}\n ref={ref}\n role=\"separator\"\n className={cx(styles.separator, size === \"4\" && styles.full, className)}\n />\n );\n});\n","import type * as React from \"react\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Card.module.scss\";\n\nexport interface CardProps extends SpacingProps, React.HTMLAttributes<HTMLDivElement> {\n /** A media element to sit at the top of the card, full-bleed to its edges.\n * Pass whatever your framework renders — a plain `<img>`, a `next/image`,\n * a `<video>` — and the card frames it: cropped to fill, top corners\n * matched to its own radius, and a reserved box so the layout does not\n * jump when it loads.\n *\n * The reserved box is `--sp-card-image-ratio` (default `16 / 10`). Set it\n * per card for a different crop. */\n image?: ReactNode;\n /** The card's contents. */\n children?: ReactNode;\n}\n\n/**\n * A translucent panel for grouping related content, one step above the page\n * surface. Its 12px inset is a deliberate exception to the 8pt grid, kept for\n * parity with the app this was extracted from.\n *\n * Pass `image` for a media card. The image is framed by the card rather than\n * being an ordinary child, so every card in a row reserves the same box\n * before its image loads and none of them reflow when it does.\n */\nexport const Card = forwardRef<HTMLDivElement, CardProps>(function Card(\n { className, style, image, children, m, mt, mb, p, pb, ...rest },\n ref,\n) {\n return (\n <div\n {...rest}\n ref={ref}\n className={cx(styles.card, image != null && styles.hasImage, className)}\n style={spacingStyle({ m, mt, mb, p, pb }, style)}\n >\n {image != null && <div className={styles.image}>{image}</div>}\n {children}\n </div>\n );\n});\n","/** Deterministic RNG + string hash, vendored from the source application (the only\n * consumer inside the library is SpaceButton's star speckle). Pure,\n * dependency-free, and part of no public API. */\nexport function mulberry32(a: number): () => number {\n return function () {\n a |= 0;\n a = (a + 0x6d2b79f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** FNV-1a 32-bit string hash, for turning stable strings into seeds. */\nexport function hashString(s: string): number {\n let h = 0x811c9dc5;\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return h >>> 0;\n}\n","\"use client\";\n\nimport { forwardRef, useId, useMemo } from \"react\";\nimport styles from \"./Button.module.scss\";\nimport { mulberry32, hashString } from \"../internal/seededRandom\";\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Circular, icon-only sizing (e.g. the share glyph). */\n iconOnly?: boolean;\n /** Warm red-dwarf rim for destructive-ish actions (e.g. Clear). */\n ember?: boolean;\n /** md = default. lg = hero CTAs. sm = compact dialog actions. micro = tiny steppers (no stars/glint). */\n size?: \"sm\" | \"md\" | \"lg\" | \"micro\";\n /** Stretch to the container width (sticky footers). */\n fullWidth?: boolean;\n /** Ambient motion: the orbiting rim, the glint sweep, and the twinkling\n * stars. Set false for dense UI or long lists where the movement\n * distracts. The glass look itself is not optional. Default true. */\n animated?: boolean;\n}\n\n\n/**\n * The thing a reader presses to make something happen. A glass capsule whose\n * rim glows like a planet's sunlit limb, with stars twinkling inside it and a\n * glint that sweeps across it now and then.\n *\n * It renders a plain `<button>` and forwards its ref, so it drops into\n * anything that needs to borrow a trigger — a dialog, a menu, a router link's\n * render prop — without a wrapper in between.\n */\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n function Button({ iconOnly, ember, size = \"md\", fullWidth, animated = true, className, children, ...rest }, ref) {\n const id = useId();\n\n // Unique-per-instance star field: positions and timing vary button to\n // button so the sparkles don't read as a repeated stamp.\n const starStyles = useMemo(() => {\n // Deterministic PRNG seeded from useId, so each button instance gets its\n // own star arrangement while server and client render identically (no\n // hydration mismatch, unlike Math.random in render).\n const rand = mulberry32(hashString(id));\n return Array.from({ length: 3 }, () => ({\n top: `${12 + rand() * 58}%`,\n left: `${8 + rand() * 80}%`,\n animationDelay: `${(rand() * 3.2).toFixed(2)}s`,\n animationDuration: `${(2.8 + rand() * 1.8).toFixed(2)}s`,\n }));\n }, [id]);\n\n const classes = [\n styles.spaceButton,\n iconOnly ? styles.iconOnly : \"\",\n ember ? styles.ember : \"\",\n size !== \"md\" ? styles[size] : \"\",\n fullWidth ? styles.fullWidth : \"\",\n className ?? \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <button\n ref={ref}\n className={classes}\n data-animated={animated ? undefined : \"false\"}\n {...rest}\n >\n {size !== \"micro\" && (\n <span className={styles.stars} aria-hidden>\n {starStyles.map((style, i) => (\n <i key={i} className={styles.star} style={style} />\n ))}\n </span>\n )}\n <span className={styles.label}>{children}</span>\n </button>\n );\n }\n);\n","// 23 icons, ported verbatim from @radix-ui/react-icons\n// (MIT License — Copyright (c) 2022 WorkOS; https://github.com/radix-ui/icons).\n// Uniform 15x15 viewBox, currentColor, decorative by default (aria-hidden) —\n// pass aria-label + aria-hidden={undefined} for semantic uses.\nimport type * as React from \"react\";\n\nexport type IconProps = React.SVGAttributes<SVGSVGElement>;\n\nconst base = {\n width: 15,\n height: 15,\n viewBox: \"0 0 15 15\",\n fill: \"none\",\n xmlns: \"http://www.w3.org/2000/svg\",\n \"aria-hidden\": true,\n} as const;\n\nexport function Share2Icon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M3.5 5.00006C3.22386 5.00006 3 5.22392 3 5.50006L3 11.5001C3 11.7762 3.22386 12.0001 3.5 12.0001L11.5 12.0001C11.7761 12.0001 12 11.7762 12 11.5001L12 5.50006C12 5.22392 11.7761 5.00006 11.5 5.00006L10.25 5.00006C9.97386 5.00006 9.75 4.7762 9.75 4.50006C9.75 4.22392 9.97386 4.00006 10.25 4.00006L11.5 4.00006C12.3284 4.00006 13 4.67163 13 5.50006L13 11.5001C13 12.3285 12.3284 13.0001 11.5 13.0001L3.5 13.0001C2.67157 13.0001 2 12.3285 2 11.5001L2 5.50006C2 4.67163 2.67157 4.00006 3.5 4.00006L4.75 4.00006C5.02614 4.00006 5.25 4.22392 5.25 4.50006C5.25 4.7762 5.02614 5.00006 4.75 5.00006L3.5 5.00006ZM7 1.6364L5.5682 3.0682C5.39246 3.24393 5.10754 3.24393 4.9318 3.0682C4.75607 2.89246 4.75607 2.60754 4.9318 2.4318L7.1818 0.181802C7.26619 0.09741 7.38065 0.049999 7.5 0.049999C7.61935 0.049999 7.73381 0.09741 7.8182 0.181802L10.0682 2.4318C10.2439 2.60754 10.2439 2.89246 10.0682 3.0682C9.89246 3.24393 9.60754 3.24393 9.4318 3.0682L8 1.6364L8 8.5C8 8.77614 7.77614 9 7.5 9C7.22386 9 7 8.77614 7 8.5L7 1.6364Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function ChatBubbleIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M12.5 3L2.5 3.00002C1.67157 3.00002 1 3.6716 1 4.50002V9.50003C1 10.3285 1.67157 11 2.5 11H7.50003C7.63264 11 7.75982 11.0527 7.85358 11.1465L10 13.2929V11.5C10 11.2239 10.2239 11 10.5 11H12.5C13.3284 11 14 10.3285 14 9.50003V4.5C14 3.67157 13.3284 3 12.5 3ZM2.49999 2.00002L12.5 2C13.8807 2 15 3.11929 15 4.5V9.50003C15 10.8807 13.8807 12 12.5 12H11V14.5C11 14.7022 10.8782 14.8845 10.6913 14.9619C10.5045 15.0393 10.2894 14.9965 10.1464 14.8536L7.29292 12H2.5C1.11929 12 0 10.8807 0 9.50003V4.50002C0 3.11931 1.11928 2.00003 2.49999 2.00002Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function PlusIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M8 2.75C8 2.47386 7.77614 2.25 7.5 2.25C7.22386 2.25 7 2.47386 7 2.75V7H2.75C2.47386 7 2.25 7.22386 2.25 7.5C2.25 7.77614 2.47386 8 2.75 8H7V12.25C7 12.5261 7.22386 12.75 7.5 12.75C7.77614 12.75 8 12.5261 8 12.25V8H12.25C12.5261 8 12.75 7.77614 12.75 7.5C12.75 7.22386 12.5261 7 12.25 7H8V2.75Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function Pencil1Icon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M11.8536 1.14645C11.6583 0.951184 11.3417 0.951184 11.1465 1.14645L3.71455 8.57836C3.62459 8.66832 3.55263 8.77461 3.50251 8.89155L2.04044 12.303C1.9599 12.491 2.00189 12.709 2.14646 12.8536C2.29103 12.9981 2.50905 13.0401 2.69697 12.9596L6.10847 11.4975C6.2254 11.4474 6.3317 11.3754 6.42166 11.2855L13.8536 3.85355C14.0488 3.65829 14.0488 3.34171 13.8536 3.14645L11.8536 1.14645ZM4.42166 9.28547L11.5 2.20711L12.7929 3.5L5.71455 10.5784L4.21924 11.2192L3.78081 10.7808L4.42166 9.28547Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function HeartFilledIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M1.35248 4.90532C1.35248 2.94498 2.936 1.35248 4.89346 1.35248C6.25769 1.35248 6.86058 1.92336 7.50002 2.93545C8.13946 1.92336 8.74235 1.35248 10.1066 1.35248C12.064 1.35248 13.6476 2.94498 13.6476 4.90532C13.6476 6.74041 12.6013 8.50508 11.4008 9.96927C10.2636 11.3562 8.92194 12.5508 8.00601 13.3664C7.94645 13.4194 7.88869 13.4709 7.83291 13.5206C7.64324 13.6899 7.3568 13.6899 7.16713 13.5206C7.11135 13.4709 7.05359 13.4194 6.99403 13.3664C6.0781 12.5508 4.73641 11.3562 3.59926 9.96927C2.39872 8.50508 1.35248 6.74041 1.35248 4.90532Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function ExitFullScreenIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M5.5 2C5.77614 2 6 2.22386 6 2.5V5.5C6 5.77614 5.77614 6 5.5 6H2.5C2.22386 6 2 5.77614 2 5.5C2 5.22386 2.22386 5 2.5 5H5V2.5C5 2.22386 5.22386 2 5.5 2ZM9.5 2C9.77614 2 10 2.22386 10 2.5V5H12.5C12.7761 5 13 5.22386 13 5.5C13 5.77614 12.7761 6 12.5 6H9.5C9.22386 6 9 5.77614 9 5.5V2.5C9 2.22386 9.22386 2 9.5 2ZM2 9.5C2 9.22386 2.22386 9 2.5 9H5.5C5.77614 9 6 9.22386 6 9.5V12.5C6 12.7761 5.77614 13 5.5 13C5.22386 13 5 12.7761 5 12.5V10H2.5C2.22386 10 2 9.77614 2 9.5ZM9 9.5C9 9.22386 9.22386 9 9.5 9H12.5C12.7761 9 13 9.22386 13 9.5C13 9.77614 12.7761 10 12.5 10H10V12.5C10 12.7761 9.77614 13 9.5 13C9.22386 13 9 12.7761 9 12.5V9.5Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function EnterFullScreenIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M2 2.5C2 2.22386 2.22386 2 2.5 2H5.5C5.77614 2 6 2.22386 6 2.5C6 2.77614 5.77614 3 5.5 3H3V5.5C3 5.77614 2.77614 6 2.5 6C2.22386 6 2 5.77614 2 5.5V2.5ZM9 2.5C9 2.22386 9.22386 2 9.5 2H12.5C12.7761 2 13 2.22386 13 2.5V5.5C13 5.77614 12.7761 6 12.5 6C12.2239 6 12 5.77614 12 5.5V3H9.5C9.22386 3 9 2.77614 9 2.5ZM2.5 9C2.77614 9 3 9.22386 3 9.5V12H5.5C5.77614 12 6 12.2239 6 12.5C6 12.7761 5.77614 13 5.5 13H2.5C2.22386 13 2 12.7761 2 12.5V9.5C2 9.22386 2.22386 9 2.5 9ZM12.5 9C12.7761 9 13 9.22386 13 9.5V12.5C13 12.7761 12.7761 13 12.5 13H9.5C9.22386 13 9 12.7761 9 12.5C9 12.2239 9.22386 12 9.5 12H12V9.5C12 9.22386 12.2239 9 12.5 9Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function CheckIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function TrashIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M5.5 1C5.22386 1 5 1.22386 5 1.5C5 1.77614 5.22386 2 5.5 2H9.5C9.77614 2 10 1.77614 10 1.5C10 1.22386 9.77614 1 9.5 1H5.5ZM3 3.5C3 3.22386 3.22386 3 3.5 3H5H10H11.5C11.7761 3 12 3.22386 12 3.5C12 3.77614 11.7761 4 11.5 4H11V12C11 12.5523 10.5523 13 10 13H5C4.44772 13 4 12.5523 4 12V4L3.5 4C3.22386 4 3 3.77614 3 3.5ZM5 4H10V12H5V4Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function QuestionMarkCircledIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M0.877075 7.49972C0.877075 3.84204 3.84222 0.876892 7.49991 0.876892C11.1576 0.876892 14.1227 3.84204 14.1227 7.49972C14.1227 11.1574 11.1576 14.1226 7.49991 14.1226C3.84222 14.1226 0.877075 11.1574 0.877075 7.49972ZM7.49991 1.82689C4.36689 1.82689 1.82708 4.36671 1.82708 7.49972C1.82708 10.6327 4.36689 13.1726 7.49991 13.1726C10.6329 13.1726 13.1727 10.6327 13.1727 7.49972C13.1727 4.36671 10.6329 1.82689 7.49991 1.82689ZM8.24993 10.5C8.24993 10.9142 7.91414 11.25 7.49993 11.25C7.08571 11.25 6.74993 10.9142 6.74993 10.5C6.74993 10.0858 7.08571 9.75 7.49993 9.75C7.91414 9.75 8.24993 10.0858 8.24993 10.5ZM6.05003 6.25C6.05003 5.57211 6.63511 4.925 7.50003 4.925C8.36496 4.925 8.95003 5.57211 8.95003 6.25C8.95003 6.74118 8.68002 6.99212 8.21447 7.27494C8.16251 7.30651 8.10258 7.34131 8.03847 7.37854L8.03841 7.37858C7.85521 7.48497 7.63788 7.61119 7.47449 7.73849C7.23214 7.92732 6.95003 8.23198 6.95003 8.7C6.95004 9.00376 7.19628 9.25 7.50004 9.25C7.8024 9.25 8.04778 9.00601 8.05002 8.70417L8.05056 8.7033C8.05924 8.6896 8.08493 8.65735 8.15058 8.6062C8.25207 8.52712 8.36508 8.46163 8.51567 8.37436L8.51571 8.37433C8.59422 8.32883 8.68296 8.27741 8.78559 8.21506C9.32004 7.89038 10.05 7.35382 10.05 6.25C10.05 4.92789 8.93511 3.825 7.50003 3.825C6.06496 3.825 4.95003 4.92789 4.95003 6.25C4.95003 6.55376 5.19628 6.8 5.50003 6.8C5.80379 6.8 6.05003 6.55376 6.05003 6.25Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function PersonIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M7.5 0.875C5.49797 0.875 3.875 2.49797 3.875 4.5C3.875 6.15288 4.98124 7.54738 6.49373 7.98351C5.2997 8.12901 4.27557 8.55134 3.50407 9.31167C2.52216 10.2794 2.02502 11.72 2.02502 13.5999C2.02502 13.8623 2.23769 14.0749 2.50002 14.0749C2.76236 14.0749 2.97502 13.8623 2.97502 13.5999C2.97502 11.8799 3.42786 10.7206 4.17091 9.9883C4.91536 9.25463 6.02674 8.87499 7.49995 8.87499C8.97317 8.87499 10.0846 9.25463 10.8291 9.98831C11.5721 10.7206 12.025 11.8799 12.025 13.5999C12.025 13.8623 12.2376 14.0749 12.5 14.0749C12.7623 14.075 12.975 13.8623 12.975 13.6C12.975 11.72 12.4778 10.2794 11.4959 9.31166C10.7244 8.55135 9.70025 8.12903 8.50625 7.98352C10.0187 7.5474 11.125 6.15289 11.125 4.5C11.125 2.49797 9.50203 0.875 7.5 0.875ZM4.825 4.5C4.825 3.02264 6.02264 1.825 7.5 1.825C8.97736 1.825 10.175 3.02264 10.175 4.5C10.175 5.97736 8.97736 7.175 7.5 7.175C6.02264 7.175 4.825 5.97736 4.825 4.5Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function MinusIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M2.25 7.5C2.25 7.22386 2.47386 7 2.75 7H12.25C12.5261 7 12.75 7.22386 12.75 7.5C12.75 7.77614 12.5261 8 12.25 8H2.75C2.47386 8 2.25 7.77614 2.25 7.5Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function MagnifyingGlassIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function HeartIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M4.89346 2.35248C3.49195 2.35248 2.35248 3.49359 2.35248 4.90532C2.35248 6.38164 3.20954 7.9168 4.37255 9.33522C5.39396 10.581 6.59464 11.6702 7.50002 12.4778C8.4054 11.6702 9.60608 10.581 10.6275 9.33522C11.7905 7.9168 12.6476 6.38164 12.6476 4.90532C12.6476 3.49359 11.5081 2.35248 10.1066 2.35248C9.27059 2.35248 8.81894 2.64323 8.5397 2.95843C8.27877 3.25295 8.14623 3.58566 8.02501 3.88993C8.00391 3.9429 7.98315 3.99501 7.96211 4.04591C7.88482 4.23294 7.7024 4.35494 7.50002 4.35494C7.29765 4.35494 7.11523 4.23295 7.03793 4.04592C7.01689 3.99501 6.99612 3.94289 6.97502 3.8899C6.8538 3.58564 6.72126 3.25294 6.46034 2.95843C6.18109 2.64323 5.72945 2.35248 4.89346 2.35248ZM1.35248 4.90532C1.35248 2.94498 2.936 1.35248 4.89346 1.35248C6.0084 1.35248 6.73504 1.76049 7.20884 2.2953C7.32062 2.42147 7.41686 2.55382 7.50002 2.68545C7.58318 2.55382 7.67941 2.42147 7.79119 2.2953C8.265 1.76049 8.99164 1.35248 10.1066 1.35248C12.064 1.35248 13.6476 2.94498 13.6476 4.90532C13.6476 6.74041 12.6013 8.50508 11.4008 9.96927C10.2636 11.3562 8.92194 12.5508 8.00601 13.3664C7.94645 13.4194 7.88869 13.4709 7.83291 13.5206C7.64324 13.6899 7.3568 13.6899 7.16713 13.5206C7.11135 13.4709 7.05359 13.4194 6.99403 13.3664C6.0781 12.5508 4.73641 11.3562 3.59926 9.96927C2.39872 8.50508 1.35248 6.74041 1.35248 4.90532Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function ChevronUpIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M3.13523 8.84197C3.3241 9.04343 3.64052 9.05363 3.84197 8.86477L7.5 5.43536L11.158 8.86477C11.3595 9.05363 11.6759 9.04343 11.8648 8.84197C12.0536 8.64051 12.0434 8.32409 11.842 8.13523L7.84197 4.38523C7.64964 4.20492 7.35036 4.20492 7.15803 4.38523L3.15803 8.13523C2.95657 8.32409 2.94637 8.64051 3.13523 8.84197Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function ChevronDownIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** The house directional chevrons (Radix geometry, matching Up/Down above).\n * These replaced the typographic arrows: a text glyph's shape is whatever the\n * viewer's font decides, and the owner called the result poorly shaped. Used\n * by every \"onward\" CTA and \"back\" button. */\nexport function ChevronRightIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M6.1584 3.13508C5.95694 3.32394 5.94673 3.64036 6.13559 3.84182L9.56499 7.49991L6.13559 11.158C5.94673 11.3595 5.95694 11.6759 6.1584 11.8647C6.35986 12.0536 6.67628 12.0434 6.86514 11.8419L10.6151 7.84182C10.7954 7.64946 10.7954 7.35036 10.6151 7.158L6.86514 3.15801C6.67628 2.95655 6.35986 2.94634 6.1584 3.13508Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function ChevronLeftIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M8.84182 3.13508C9.04328 3.32394 9.05348 3.64036 8.86462 3.84182L5.43523 7.49991L8.86462 11.158C9.05348 11.3595 9.04328 11.6759 8.84182 11.8647C8.64036 12.0536 8.32394 12.0434 8.13508 11.8419L4.38508 7.84182C4.20477 7.64946 4.20477 7.35036 4.38508 7.158L8.13508 3.15801C8.32394 2.95655 8.64036 2.94634 8.84182 3.13508Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function BookmarkIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M3 2.5C3 2.22386 3.22386 2 3.5 2H11.5C11.7761 2 12 2.22386 12 2.5V13.5C12 13.6818 11.9014 13.8492 11.7424 13.9373C11.5834 14.0254 11.3891 14.0203 11.235 13.924L7.5 11.5896L3.765 13.924C3.61087 14.0203 3.41659 14.0254 3.25762 13.9373C3.09864 13.8492 3 13.6818 3 13.5V2.5ZM4 3V12.5979L6.97 10.7416C7.29427 10.539 7.70573 10.539 8.03 10.7416L11 12.5979V3H4Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** Dialog dismiss glyph — a plain X, used by Dialog.Content's corner button. */\nexport function XIcon(props: IconProps) {\n return (\n <svg viewBox=\"0 0 15 15\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" {...props}>\n <path\n d=\"M11.8 3.2a.6.6 0 0 0-.85 0L7.5 6.65 4.05 3.2a.6.6 0 1 0-.85.85L6.65 7.5 3.2 10.95a.6.6 0 1 0 .85.85L7.5 8.35l3.45 3.45a.6.6 0 0 0 .85-.85L8.35 7.5l3.45-3.45a.6.6 0 0 0 0-.85Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n\nexport function InfoCircledIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M7.49991 0.876892C3.84222 0.876892 0.877075 3.84204 0.877075 7.49972C0.877075 11.1574 3.84222 14.1226 7.49991 14.1226C11.1576 14.1226 14.1227 11.1574 14.1227 7.49972C14.1227 3.84204 11.1576 0.876892 7.49991 0.876892ZM1.82707 7.49972C1.82707 4.36671 4.36689 1.82689 7.49991 1.82689C10.6329 1.82689 13.1727 4.36671 13.1727 7.49972C13.1727 10.6327 10.6329 13.1726 7.49991 13.1726C4.36689 13.1726 1.82707 10.6327 1.82707 7.49972ZM8.24992 4.49999C8.24992 4.9142 7.91413 5.24999 7.49992 5.24999C7.08571 5.24999 6.74992 4.9142 6.74992 4.49999C6.74992 4.08577 7.08571 3.74999 7.49992 3.74999C7.91413 3.74999 8.24992 4.08577 8.24992 4.49999ZM6.00003 5.99999H6.50003H7.50003C7.77618 5.99999 8.00003 6.22384 8.00003 6.49999V9.99999H8.50003H9.00003V11H8.50003H7.50003H6.50003H6.00003V9.99999H6.50003H7.00003V6.99999H6.50003H6.00003V5.99999Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function ExclamationTriangleIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M8.4449 0.608765C8.0183 -0.107015 6.9817 -0.107015 6.55509 0.608766L0.161178 11.3368C-0.275824 12.07 0.252503 13 1.10608 13H13.8939C14.7475 13 15.2758 12.07 14.8388 11.3368L8.4449 0.608765ZM7.4141 1.12073C7.45288 1.05566 7.54712 1.05566 7.5859 1.12073L13.9798 11.8488C14.0196 11.9154 13.9715 12 13.8939 12H1.10608C1.02849 12 0.980454 11.9154 1.02018 11.8488L7.4141 1.12073ZM6.8269 4.48611C6.81221 4.10423 7.11783 3.78663 7.5 3.78663C7.88217 3.78663 8.18778 4.10423 8.1731 4.48612L8.01921 8.48701C8.00848 8.766 7.7792 8.98664 7.5 8.98664C7.2208 8.98664 6.99151 8.766 6.98078 8.48701L6.8269 4.48611ZM8.24989 10.476C8.24989 10.8902 7.9141 11.226 7.49989 11.226C7.08567 11.226 6.74989 10.8902 6.74989 10.476C6.74989 10.0618 7.08567 9.72599 7.49989 9.72599C7.9141 9.72599 8.24989 10.0618 8.24989 10.476Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function CrossCircledIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M0.877075 7.49988C0.877075 3.84219 3.84222 0.877045 7.49991 0.877045C11.1576 0.877045 14.1227 3.84219 14.1227 7.49988C14.1227 11.1575 11.1576 14.1227 7.49991 14.1227C3.84222 14.1227 0.877075 11.1575 0.877075 7.49988ZM7.49991 1.82704C4.36689 1.82704 1.82708 4.36686 1.82708 7.49988C1.82708 10.6329 4.36689 13.1727 7.49991 13.1727C10.6329 13.1727 13.1727 10.6329 13.1727 7.49988C13.1727 4.36686 10.6329 1.82704 7.49991 1.82704ZM9.85358 5.14644C10.0488 5.3417 10.0488 5.65829 9.85358 5.85355L8.20713 7.49999L9.85358 9.14644C10.0488 9.3417 10.0488 9.65829 9.85358 9.85355C9.65832 10.0488 9.34173 10.0488 9.14647 9.85355L7.50002 8.2071L5.85358 9.85355C5.65832 10.0488 5.34173 10.0488 5.14647 9.85355C4.95121 9.65829 4.95121 9.3417 5.14647 9.14644L6.79292 7.49999L5.14647 5.85355C4.95121 5.65829 4.95121 5.3417 5.14647 5.14644C5.34173 4.95118 5.65832 4.95118 5.85358 5.14644L7.50002 6.79289L9.14647 5.14644C9.34173 4.95118 9.65832 4.95118 9.85358 5.14644Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport {\n Children, useCallback, useEffect, useId, useLayoutEffect, useRef, useState, type ReactNode,\n} from \"react\";\nimport { cx } from \"./propShared\";\nimport { Button } from \"./Button\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"./icons\";\nimport styles from \"./Carousel.module.scss\";\n\nexport interface CarouselProps extends Omit<React.HTMLAttributes<HTMLElement>, \"children\"> {\n /** The slides, one child each. */\n children?: ReactNode;\n /** How many slides fit the viewport. Fractions show a partial slide at the\n * trailing edge — `2.5` is two whole slides and half a third, a cue that\n * there is more to swipe to. Default 1.\n *\n * This is the count wherever no stylesheet overrides it. To vary it by\n * screen width, do not switch this prop from JavaScript: set the\n * `--sp-carousel-view-count` token in media queries instead, which always\n * wins over the prop. See \"Responsive view count\" on {@link Carousel}. */\n perView?: number;\n /** What an arrow moves by, and what a dot stands for. `item` moves one\n * slide and shows a dot per stopping point; `page` moves by the number of\n * whole slides in view, snaps only at page boundaries, and shows a dot per\n * page. Default `item`. */\n step?: \"item\" | \"page\";\n /** Show the dots beneath the slides. */\n showPagination?: boolean;\n /** Ambient motion on the arrow buttons' rims. Default true. */\n animated?: boolean;\n /** Names the carousel for assistive tech. Say what it holds — \"Featured\n * planets\" — rather than that it is a carousel, which is announced\n * already. Default \"Carousel\". */\n \"aria-label\"?: string;\n}\n\n/**\n * A row of slides that scrolls sideways, with arrows and optional dots.\n *\n * The browser does the heavy lifting. The row is a native horizontal scroller\n * with CSS scroll snapping, so a flick on a phone uses the platform's own\n * momentum and lands on a slide, and nothing runs per frame while it moves.\n * Slide widths come from a CSS calculation on the view count, so a breakpoint\n * can change how many fit without React knowing.\n *\n * A mouse can drag the row too. It follows the pointer, then glides to the\n * next stop in the direction it was dragged; a drag never clicks a link or\n * button in the slide it ends on.\n *\n * ## Responsive view count\n *\n * The number of slides in view is a design token, not state. Vary it by\n * screen width in CSS; never by swapping `perView` from a resize listener or\n * `matchMedia`, which re-renders, and can disagree with the server render.\n *\n * 1. Pass `perView` for the widest layout.\n * 2. Set `--sp-carousel-view-count` on a class (or any ancestor) in media or\n * container queries for the other widths. Fractions are fine.\n * 3. Nothing else. Widths are computed in CSS, and the arrows, dots and page\n * size are measured from the rendered row whenever it resizes.\n *\n * Precedence: `--sp-carousel-view-count` from a stylesheet, then `perView`,\n * then 1. The prop is passed as a private default (`--_view-count-default`),\n * not as the public token, precisely so a stylesheet can override it.\n *\n * Setting the token on `:root` overrides `perView` on every carousel in the\n * app; scope it to a class or section instead. `--sp-carousel-gap-size` can be\n * varied the same way.\n *\n * @example\n * ```tsx\n * <Carousel aria-label=\"Featured planets\" perView={4} className=\"featured\">\n * {slides}\n * </Carousel>\n * ```\n * ```css\n * @media (max-width: 639px) {\n * .featured { --sp-carousel-view-count: 1.2; }\n * }\n * @media (min-width: 640px) and (max-width: 1079px) {\n * .featured { --sp-carousel-view-count: 2.5; }\n * }\n * // 1080px and up: nothing set, so perView={4} applies.\n * ```\n *\n * ## How the script stays small\n *\n * Script does only what CSS cannot yet do everywhere: the arrows, the dots,\n * and the mouse drag. It measures the rendered row — on mount and when it\n * resizes, never on scroll — to find where the row can stop, and on scroll it\n * only compares the scroll position with those stops, updating state when the\n * active one actually changes.\n */\nexport function Carousel({\n children,\n perView = 1,\n step = \"item\",\n showPagination = false,\n animated = true,\n className,\n \"aria-label\": ariaLabel = \"Carousel\",\n ...rest\n}: CarouselProps) {\n const slides = Children.toArray(children);\n const count = slides.length;\n const trackId = useId();\n const trackRef = useRef<HTMLDivElement | null>(null);\n\n // Before anything is measured — first paint and SSR — estimate from the\n // props, so the dots and arrows render at roughly the right count rather\n // than popping in.\n const estimatedPage = step === \"page\" ? Math.max(1, Math.floor(perView)) : 1;\n const estimatedStops =\n count <= perView\n ? 1\n : step === \"page\"\n ? Math.ceil((count - perView) / estimatedPage) + 1\n // Every whole slide start the row can scroll to, plus the end itself\n // when a fraction leaves it between two starts.\n : Math.ceil(count - perView) + 1;\n\n const [pageSize, setPageSize] = useState(estimatedPage);\n const [stopCount, setStopCount] = useState(Math.max(1, estimatedStops));\n const [active, setActive] = useState(0);\n const [atStart, setAtStart] = useState(true);\n const [atEnd, setAtEnd] = useState(count <= perView);\n // Scroll offsets the row can come to rest at. Held in a ref: they are read\n // on every scroll, and nothing needs to re-render when they are recomputed\n // unless their number changes.\n const stops = useRef<number[]>([0]);\n // How far the row could scroll when those stops were worked out. Anything\n // that changes the row's scrollable width without resizing the row itself —\n // an image arriving, a web font swapping in, a slide's content growing —\n // leaves the stops describing a row that no longer exists.\n const measuredMax = useRef(0);\n // The scroll offset the row rests at when it is showing its last slide —\n // the last stop, and what \"at the end\" means. See measure().\n const endStop = useRef(0);\n // measure() needs sync(), and sync() needs to be able to re-measure. A ref\n // breaks the cycle without either depending on the other.\n const remeasure = useRef<() => void>(() => {});\n\n const sync = useCallback(() => {\n const track = trackRef.current;\n if (!track) return;\n const x = track.scrollLeft;\n const max = Math.max(0, track.scrollWidth - track.clientWidth);\n\n // Stops from a different row: measure again and let that call back here.\n // Without this the dots can sit a stop behind for good — a row measured\n // while it was wider keeps a final stop nobody can scroll to, so arriving\n // at the true end still reads as the stop before it.\n if (Math.abs(max - measuredMax.current) > 1) {\n remeasure.current();\n return;\n }\n\n const atStartNow = x <= 1;\n // Against the last reachable stop, not the raw scroll width: with a slide\n // whose content overflows its column the two differ, and the row can never\n // reach the latter.\n const atEndNow = x >= endStop.current - 1;\n // The ends are known exactly, so they are never left to a nearest-value\n // comparison: at the end, the last stop is the one you are on.\n let nearest = 0;\n if (atEndNow) {\n nearest = stops.current.length - 1;\n } else if (!atStartNow) {\n stops.current.forEach((stop, i) => {\n // <= so that when two stops are equally close the later one wins,\n // matching the direction the row was moving to get there.\n if (Math.abs(stop - x) <= Math.abs(stops.current[nearest] - x)) nearest = i;\n });\n }\n\n // React skips the render when a value is unchanged, so scrolling within\n // one stop costs a comparison and nothing more.\n setActive(nearest);\n setAtStart(atStartNow);\n setAtEnd(atEndNow);\n }, []);\n\n const measure = useCallback(() => {\n const track = trackRef.current;\n if (!track) return;\n const items = Array.from(track.children) as HTMLElement[];\n if (!items.length) return;\n\n const max = Math.max(0, track.scrollWidth - track.clientWidth);\n const first = items[0];\n const gap = items.length > 1 ? items[1].offsetLeft - first.offsetLeft - first.offsetWidth : 0;\n // How many slides are really in view, whatever set it: the prop, or a\n // stylesheet overriding the view count at this width.\n const inView = (track.clientWidth + gap) / (first.offsetWidth + gap);\n const size = step === \"page\" ? Math.max(1, Math.floor(inView + 0.01)) : 1;\n\n // Where the row comes to rest at the end: the last slide's trailing edge\n // against the viewport's, which is what its `scroll-snap-align: end` means.\n // Not the raw scroll width — a slide whose content is wider than its\n // column leaves scrollable room past that snap position, room mandatory\n // snapping never lets the row rest in. Counting that as a stop gave a\n // final dot nobody could reach, and left the dot before it lit at the end.\n const last = items[items.length - 1];\n const end = Math.round(\n Math.max(0, Math.min(max, last.offsetLeft - first.offsetLeft + last.offsetWidth - track.clientWidth)),\n );\n\n const next: number[] = [];\n items.forEach((item, i) => {\n if (i % size !== 0) return;\n const stop = Math.round(Math.min(item.offsetLeft - first.offsetLeft, end));\n if (next[next.length - 1] !== stop) next.push(stop);\n });\n // The end is always somewhere you can arrive, even when no slide or page\n // starts exactly there.\n if (end > 0 && next[next.length - 1] < end - 1) next.push(end);\n\n stops.current = next;\n measuredMax.current = Math.round(max);\n endStop.current = end;\n setPageSize(size);\n setStopCount(next.length);\n sync();\n }, [step, sync]);\n\n useLayoutEffect(() => {\n remeasure.current = measure;\n measure();\n }, [measure, count]);\n\n useEffect(() => {\n const track = trackRef.current;\n if (!track) return;\n // Remeasure when the row's size changes — a container resize — and when a\n // SLIDE's size changes, which is what a breakpoint does: setting\n // --sp-carousel-view-count re-divides the row without altering the row's\n // own box at all, so watching only the row left the arrows and dots\n // describing the old count. Scrolling never triggers either.\n const resize = new ResizeObserver(() => measure());\n resize.observe(track);\n const first = track.firstElementChild;\n if (first) resize.observe(first);\n\n let frame = 0;\n const onScroll = () => {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(sync);\n };\n track.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => {\n resize.disconnect();\n cancelAnimationFrame(frame);\n track.removeEventListener(\"scroll\", onScroll);\n };\n // count: a slide added or removed changes which element is the first one.\n }, [measure, sync, count]);\n\n // Dragging with a mouse. Touch and pen already scroll the row natively, with\n // the platform's momentum; a mouse gets no such gesture, so it is added here\n // and only for a mouse.\n useEffect(() => {\n const track = trackRef.current;\n if (!track) return;\n\n // Movement under this is a click, not a drag, so links and buttons inside\n // a slide still work.\n const THRESHOLD = 4;\n let pointer: number | null = null;\n let startX = 0;\n let startScroll = 0;\n let dragging = false;\n let settle = 0;\n\n const endSettling = () => {\n clearTimeout(settle);\n delete track.dataset.settling;\n };\n\n const onPointerDown = (e: PointerEvent) => {\n if (e.pointerType !== \"mouse\" || e.button !== 0) return;\n if (track.scrollWidth <= track.clientWidth) return;\n endSettling();\n pointer = e.pointerId;\n startX = e.clientX;\n startScroll = track.scrollLeft;\n dragging = false;\n };\n\n const onPointerMove = (e: PointerEvent) => {\n if (e.pointerId !== pointer) return;\n const dx = e.clientX - startX;\n if (!dragging) {\n if (Math.abs(dx) < THRESHOLD) return;\n dragging = true;\n track.setPointerCapture(e.pointerId);\n // Snapping off and scrolling instant while held, or the row would\n // fight the pointer: snap back to a slide, or ease behind it.\n track.dataset.dragging = \"\";\n }\n track.scrollLeft = startScroll - dx;\n };\n\n const onPointerUp = (e: PointerEvent) => {\n if (e.pointerId !== pointer) return;\n pointer = null;\n if (!dragging) return;\n delete track.dataset.dragging;\n\n // Land on the nearest stop, but never back where the drag began: any\n // deliberate drag moves at least one stop in its direction.\n const x = track.scrollLeft;\n const all = stops.current;\n let target = all.reduce((best, stop) => (Math.abs(stop - x) < Math.abs(best - x) ? stop : best), all[0]);\n if (x > startScroll + 1 && target <= startScroll + 1) {\n target = all.find((stop) => stop > startScroll + 1) ?? target;\n } else if (x < startScroll - 1 && target >= startScroll - 1) {\n target = [...all].reverse().find((stop) => stop < startScroll - 1) ?? target;\n }\n\n // Snapping stays off until the row arrives. Turned back on mid-glide,\n // the browser would jump straight to a snap point.\n track.dataset.settling = \"\";\n const reduced = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n track.scrollTo({ left: target, behavior: reduced ? \"auto\" : \"smooth\" });\n // scrollend where supported; the timer covers browsers without it and a\n // row that was already exactly on target, which scrolls nowhere.\n track.addEventListener(\"scrollend\", endSettling, { once: true });\n settle = window.setTimeout(endSettling, 700);\n };\n\n // A drag that ends over a link or button inside a slide must not click it.\n const onClick = (e: MouseEvent) => {\n if (!dragging) return;\n dragging = false;\n e.preventDefault();\n e.stopPropagation();\n };\n\n // Images and links are natively draggable, which would hijack the gesture.\n const onDragStart = (e: DragEvent) => e.preventDefault();\n\n track.addEventListener(\"pointerdown\", onPointerDown);\n track.addEventListener(\"pointermove\", onPointerMove);\n track.addEventListener(\"pointerup\", onPointerUp);\n track.addEventListener(\"pointercancel\", onPointerUp);\n track.addEventListener(\"click\", onClick, true);\n track.addEventListener(\"dragstart\", onDragStart);\n return () => {\n endSettling();\n track.removeEventListener(\"pointerdown\", onPointerDown);\n track.removeEventListener(\"pointermove\", onPointerMove);\n track.removeEventListener(\"pointerup\", onPointerUp);\n track.removeEventListener(\"pointercancel\", onPointerUp);\n track.removeEventListener(\"click\", onClick, true);\n track.removeEventListener(\"dragstart\", onDragStart);\n };\n }, []);\n\n // No behaviour passed, so the stylesheet's scroll-behavior decides: smooth,\n // or instant under reduced motion.\n const scrollTo = (left: number) => trackRef.current?.scrollTo({ left });\n\n const go = (direction: 1 | -1) => {\n const track = trackRef.current;\n if (!track) return;\n const x = track.scrollLeft;\n const target = direction > 0\n ? stops.current.find((stop) => stop > x + 1)\n : [...stops.current].reverse().find((stop) => stop < x - 1);\n if (target !== undefined) scrollTo(target);\n };\n\n const scrollable = stopCount > 1;\n\n return (\n <section\n {...rest}\n aria-roledescription=\"carousel\"\n aria-label={ariaLabel}\n className={cx(styles.root, className)}\n data-scrollable={scrollable ? \"\" : undefined}\n >\n <div className={styles.viewport}>\n <div\n ref={trackRef}\n id={trackId}\n className={styles.track}\n // Focusable, so arrow keys scroll it natively once it has focus.\n tabIndex={0}\n style={{ \"--_view-count-default\": perView } as React.CSSProperties}\n >\n {slides.map((slide, i) => (\n <div\n key={(slide as React.ReactElement).key ?? i}\n className={styles.slide}\n role=\"group\"\n aria-roledescription=\"slide\"\n aria-label={`${i + 1} of ${count}`}\n data-snap={i % pageSize === 0 ? \"\" : undefined}\n >\n {slide}\n </div>\n ))}\n </div>\n\n <span className={cx(styles.arrow, styles.prev)}>\n <Button\n iconOnly\n className={styles.arrowButton}\n animated={animated}\n aria-label=\"Previous\"\n aria-controls={trackId}\n disabled={atStart}\n onClick={() => go(-1)}\n >\n <ChevronLeftIcon aria-hidden=\"true\" />\n </Button>\n </span>\n <span className={cx(styles.arrow, styles.next)}>\n <Button\n iconOnly\n className={styles.arrowButton}\n animated={animated}\n aria-label=\"Next\"\n aria-controls={trackId}\n disabled={atEnd}\n onClick={() => go(1)}\n >\n <ChevronRightIcon aria-hidden=\"true\" />\n </Button>\n </span>\n </div>\n\n {showPagination && scrollable && (\n <div className={styles.dots}>\n {Array.from({ length: stopCount }, (_, i) => (\n <button\n // eslint-disable-next-line react/no-array-index-key\n key={i}\n type=\"button\"\n className={styles.dot}\n aria-label={step === \"page\" ? `Page ${i + 1} of ${stopCount}` : `Position ${i + 1} of ${stopCount}`}\n aria-controls={trackId}\n aria-current={i === active ? \"true\" : undefined}\n onClick={() => scrollTo(stops.current[i] ?? 0)}\n />\n ))}\n </div>\n )}\n </section>\n );\n}\n","// The shared control-chrome class map — INTERNAL. Components apply this skin\n// themselves, so a consumer never composes it; it was a public subpath until\n// the skin became unconditional, which made every call site a no-op.\n//\n// Kept as a typed module rather than importing the SCSS directly, so a typo in\n// ctl.spaceInput is a compile error here rather than undefined at runtime.\nimport ctlModule from \"./spaceControls.module.scss\";\n\n/** Declared explicitly rather than inferred from the SCSS module, so the\n * emitted .d.ts stands alone: the .module.scss is not published, and a\n * consumer importing this subpath must not need it. Naming the keys also\n * means a typo at a call site is a type error instead of `undefined`. */\nexport interface SpaceControlClasses {\n spaceControl: string;\n spaceInput: string;\n spacePanel: string;\n spaceSlider: string;\n spaceTextArea: string;\n rimRotate: string;\n}\n\n// Through `unknown` because Vite types a CSS module as CSSModuleClasses —\n// an index signature, which TypeScript will not narrow straight to a named\n// interface. The names are checked against the SCSS by a test instead.\nconst ctl = ctlModule as unknown as SpaceControlClasses;\nexport default ctl;\n","\"use client\";\nimport type * as React from \"react\";\nimport { cx } from \"./propShared\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"./icons\";\nimport styles from \"./Pagination.module.scss\";\nimport ctl from \"../styles/spaceControls\";\n\n/**\n * The data Pagination needs, in the shape most APIs return beside a page of\n * results. Pass it as `pagination`. When `onPageClick` reports a page, hand\n * back a copy with only `page` changed — the component works out everything\n * else, including how many pages there are, from these three numbers. With\n * `totalItems` at or below `pageSize` there is only one page, and the\n * component renders nothing.\n */\nexport interface PaginationState {\n /** The page being shown, counting from 1. If your API counts from 0, add\n * one before passing it in. A page past either end is clamped to the first\n * or last rather than rejected. */\n page: number;\n /** How many items one page holds — the size you requested, not how many\n * came back on the final page. Must be above zero. */\n pageSize: number;\n /** How many items exist across every page: the full result count, not the\n * length of the page you are showing. Usually the `total` or `count` field\n * of the response. */\n totalItems: number;\n}\n\n/** How many pages a pagination object describes — never fewer than one. */\nexport function pageCount({ pageSize, totalItems }: PaginationState): number {\n if (pageSize <= 0) return 1;\n return Math.max(1, Math.ceil(totalItems / pageSize));\n}\n\n/**\n * The page numbers to offer, with `null` marking a gap to draw as an ellipsis.\n *\n * Always the same length once there are enough pages to need gaps — first,\n * last, `siblings` either side of the current page, and two slots that are\n * either a gap or the single page a gap would have hidden. A window that grew\n * and shrank as you paged would change the control's width under the cursor,\n * so the next click would land on a different number than the last one did.\n *\n * Exported so a caller rendering its own markup can reuse the arithmetic.\n */\nexport function pageWindow(page: number, total: number, siblings = 1): (number | null)[] {\n const range = (from: number, to: number) =>\n Array.from({ length: Math.max(0, to - from + 1) }, (_, i) => from + i);\n\n // first + last + current + siblings either side + two gap slots\n const slots = siblings * 2 + 5;\n if (total <= slots) return range(1, total);\n\n const current = Math.min(Math.max(page, 1), total);\n const left = Math.max(current - siblings, 1);\n const right = Math.min(current + siblings, total);\n // A gap only earns its ellipsis when it hides two or more pages. Hiding one\n // page behind \"…\" costs the same space as just showing it.\n const gapLeft = left > 3;\n const gapRight = right < total - 2;\n const edge = siblings * 2 + 3;\n\n if (!gapLeft) return [...range(1, edge), null, total];\n if (!gapRight) return [1, null, ...range(total - edge + 1, total)];\n return [1, null, ...range(left, right), null, total];\n}\n\nexport interface PaginationProps\n extends Omit<React.HTMLAttributes<HTMLElement>, \"children\"> {\n /** Where the list stands: the current page, the page size, and the total\n * item count. Pass the object your API returns; the page count is derived\n * from it. With one page or fewer nothing renders. */\n pagination: PaginationState;\n /** Called with the page the reader chose — a number, Previous or Next.\n * Not called for the page already showing. Fetch or slice, then hand back\n * an updated `pagination`. */\n onPageClick: (page: number) => void;\n /** Page numbers shown either side of the current one. Default 1. */\n siblings?: number;\n /** Ambient motion: the lit arc orbiting the current page's rim. The glass\n * skin is always applied — only its motion is optional. Default true. */\n animated?: boolean;\n}\n\n/**\n * Page-by-page navigation for a long list.\n *\n * Holds no state: give it the pagination object you already have and it\n * reports which page was clicked.\n *\n * Every control is the same limb-lit glass as Select and Button, but only the\n * current page's rim orbits. Nine arcs turning in one row would be noise; one\n * turning is where you are. Previous and Next stay in place when they\n * cannot be used, so the numbers never slide sideways on the first and last\n * page.\n */\nexport function Pagination({\n pagination,\n onPageClick,\n siblings = 1,\n animated = true,\n className,\n \"aria-label\": ariaLabel = \"Pagination\",\n ...rest\n}: PaginationProps) {\n const total = pageCount(pagination);\n if (total <= 1) return null;\n\n const current = Math.min(Math.max(pagination.page, 1), total);\n\n const go = (target: number) => {\n if (target !== current && target >= 1 && target <= total) onPageClick(target);\n };\n\n return (\n <nav {...rest} aria-label={ariaLabel} className={cx(styles.nav, className)}>\n <button\n type=\"button\"\n className={cx(ctl.spaceControl, styles.item, styles.step)}\n disabled={current <= 1}\n aria-label=\"Previous page\"\n onClick={() => go(current - 1)}\n >\n <ChevronLeftIcon aria-hidden=\"true\" />\n <span className={styles.stepText}>Previous</span>\n </button>\n\n <ol className={styles.pages}>\n {pageWindow(current, total, siblings).map((p, i) =>\n p === null ? (\n // Presentational: \"ellipsis\" read aloud between page numbers tells\n // nobody anything.\n // eslint-disable-next-line react/no-array-index-key\n <li key={`gap-${i}`} className={styles.gap} aria-hidden=\"true\">\n …\n </li>\n ) : (\n <li key={p}>\n <button\n type=\"button\"\n className={cx(\n ctl.spaceControl,\n styles.item,\n styles.page,\n p === current && styles.current,\n )}\n data-animated={p === current && !animated ? \"false\" : undefined}\n aria-label={`Page ${p}`}\n aria-current={p === current ? \"page\" : undefined}\n onClick={() => go(p)}\n >\n {p}\n </button>\n </li>\n ),\n )}\n </ol>\n\n <button\n type=\"button\"\n className={cx(ctl.spaceControl, styles.item, styles.step)}\n disabled={current >= total}\n aria-label=\"Next page\"\n onClick={() => go(current + 1)}\n >\n <span className={styles.stepText}>Next</span>\n <ChevronRightIcon aria-hidden=\"true\" />\n </button>\n </nav>\n );\n}\n","\"use client\";\n\nimport { cx } from \"./propShared\";\nimport styles from \"./Loader.module.scss\";\n\nexport interface LoaderProps {\n /** sm = inline/compact spots. md = default. lg = full-panel takeovers. */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Visible caption under the spinner; also doubles as the accessible name. */\n label?: string;\n /** Merged onto the wrapper. */\n className?: string;\n}\n\n/**\n * An orbital spinner, for work whose length you cannot measure: a small\n * pulsing planet at the centre of a static ring, with a moon travelling it.\n * Where you CAN measure the work, use `Progress` instead — a spinner that\n * could have been a bar tells the reader less than it knows.\n *\n * The motion is pure CSS and runs on the compositor, so it keeps turning\n * smoothly while the main thread is busy doing the thing it is waiting on —\n * which is exactly when a loader is on screen.\n */\nexport function Loader({ size = \"md\", label, className }: LoaderProps) {\n return (\n <div\n className={cx(styles.wrap, styles[size], className)}\n role=\"status\"\n aria-live=\"polite\"\n aria-label={label ?? \"Loading\"}\n >\n <span className={styles.orbit}>\n <span className={styles.planet} />\n <span className={styles.moon} />\n </span>\n {label && <span className={styles.label}>{label}</span>}\n </div>\n );\n}\n","/**\n * Shows a popover-API element after it has been placed, so its reveal starts\n * from the right side.\n *\n * The reveal's starting offset is captured the instant the element first\n * renders, and which way it should travel depends on where it lands — which\n * can flip when there is no room — which needs its size, which needs it\n * rendered. Showing first and measuring after locks a flipped surface into\n * travelling towards its own trigger.\n *\n * So `place` runs while the element is laid out but invisible, with every\n * transition off, and must write the side it chose to `data-side`. The\n * element then returns to unrendered and that state is committed before it is\n * shown, so the real reveal begins fresh from its starting style. Transitions\n * stay off until then: leaving the measurement with them on counts as a\n * dismissal, which keeps the element rendered animating its offset, and the\n * reveal would start from that live value instead.\n *\n * Pairs with the `reveal` mixin, which supplies the `data-measuring` and\n * `data-instant` states this relies on.\n */\nexport function showMeasured(element: HTMLElement, place: () => void): void {\n if (element.matches(\":popover-open\")) return;\n element.dataset.instant = \"\";\n element.dataset.measuring = \"\";\n place();\n delete element.dataset.measuring;\n void element.offsetWidth;\n delete element.dataset.instant;\n void element.offsetWidth;\n element.showPopover();\n}\n","\"use client\";\n\n// Generic hover/focus tooltip for icon-only controls. Built on the same\n// native popover=\"auto\" top-layer pattern as ElementTooltip (and\n// DropdownMenu) rather than a library: Radix is gone from this app, and the\n// platform gives Escape/click-outside dismissal and top-layer stacking for\n// free — which matters here because these triggers sit over WebGL canvases\n// and inside their own stacking contexts.\n//\n// Deliberately NOT the native `title` attribute, which these controls used\n// before: the browser's own tooltip waits about a second, cannot be styled\n// to match the app, and never appears for keyboard users at all.\n\nimport {\n cloneElement, isValidElement, useEffect, useId, useLayoutEffect, useRef, useState,\n} from \"react\";\nimport styles from \"./Tooltip.module.scss\";\nimport { showMeasured } from \"../internal/showMeasured\";\n\ninterface TooltipProps {\n /** The text to show. Nothing renders when this is empty. */\n label: string;\n /** Preferred side; flips to the opposite one when there isn't room.\n * `left`/`right` are for a control in a vertical stack, where a tooltip\n * above or below would land on the neighbouring item. */\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n /** The element the tooltip describes. Receives the hover and focus\n * handlers, so it must accept a ref. */\n children: React.ReactElement;\n}\n\nconst SHOW_DELAY = 350;\nconst HIDE_DELAY = 80;\nconst SIDE_OFFSET = 8;\nconst COLLISION_PADDING = 8;\n\n// The clone lives in its own component so this scope never dereferences\n// triggerRef itself — the React Compiler flags a ref that is BOTH passed\n// into cloneElement's props and read in the same scope. Same split, and the\n// same reason, as ElementTooltip's TooltipTrigger.\ninterface TriggerProps {\n triggerRef: React.RefObject<HTMLElement | null>;\n tooltipId: string;\n show: (immediate?: boolean) => void;\n hide: () => void;\n children: React.ReactElement<Record<string, unknown>>;\n}\nfunction TooltipTrigger({ triggerRef, tooltipId, show, hide, children }: TriggerProps) {\n const p = children.props;\n return cloneElement(children, {\n ref: triggerRef,\n // Always present, so the id it points at never dangles: the content\n // element stays mounted and only toggles its popover state.\n \"aria-describedby\": tooltipId,\n onPointerEnter: (e: React.PointerEvent) => {\n (p.onPointerEnter as ((e: React.PointerEvent) => void) | undefined)?.(e);\n // Mouse only. A touch \"hover\" fires on tap, which would pop a tooltip\n // over the very control the user just pressed.\n if (e.pointerType === \"mouse\") show();\n },\n onPointerLeave: (e: React.PointerEvent) => {\n (p.onPointerLeave as ((e: React.PointerEvent) => void) | undefined)?.(e);\n hide();\n },\n // Keyboard focus shows it immediately — no hover delay to wait out.\n onFocus: (e: React.FocusEvent) => {\n (p.onFocus as ((e: React.FocusEvent) => void) | undefined)?.(e);\n show(true);\n },\n onBlur: (e: React.FocusEvent) => {\n (p.onBlur as ((e: React.FocusEvent) => void) | undefined)?.(e);\n hide();\n },\n // A tooltip must never outlive the action it describes: clicking the\n // control (expand, switch view) leaves it stranded over the new layout.\n onClick: (e: React.MouseEvent) => {\n (p.onClick as ((e: React.MouseEvent) => void) | undefined)?.(e);\n hide();\n },\n });\n}\n\n/**\n * A short label revealed on hover or focus, for naming a control whose icon\n * is not self-evident.\n *\n * Never put information here that a reader needs: a tooltip is unreachable on\n * touch and easy to miss. If it must be read, put it on the page.\n */\nexport function Tooltip({ label, side = \"bottom\", children }: TooltipProps) {\n const tooltipId = useId();\n const [open, setOpen] = useState(false);\n const [pos, setPos] = useState<{ top: number; left: number } | null>(null);\n const triggerRef = useRef<HTMLElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n const showTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearTimers = () => {\n if (showTimer.current) { clearTimeout(showTimer.current); showTimer.current = null; }\n if (hideTimer.current) { clearTimeout(hideTimer.current); hideTimer.current = null; }\n };\n const show = (immediate = false) => {\n clearTimers();\n if (immediate) { setOpen(true); return; }\n showTimer.current = setTimeout(() => setOpen(true), SHOW_DELAY);\n };\n const hide = () => {\n clearTimers();\n hideTimer.current = setTimeout(() => setOpen(false), HIDE_DELAY);\n };\n\n useEffect(() => clearTimers, []);\n\n useLayoutEffect(() => {\n const content = contentRef.current;\n if (!content) return;\n if (!open) {\n if (content.matches(\":popover-open\")) content.hidePopover();\n return;\n }\n const trigger = triggerRef.current;\n if (!trigger) return;\n\n // Measured while laid out — its size reads 0 while display:none — and\n // records the side it lands on, so the reveal can travel away from the\n // trigger. Run once before it is shown (see showMeasured) and again on a\n // label change while already open.\n const place = () => {\n const r = trigger.getBoundingClientRect();\n const w = content.offsetWidth;\n const h = content.offsetHeight;\n\n // Centre on the trigger along the free axis, clamped inside the viewport.\n const centre = (start: number, size: number, extent: number, viewport: number) =>\n Math.min(\n Math.max(start + size / 2 - extent / 2, COLLISION_PADDING),\n Math.max(viewport - extent - COLLISION_PADDING, COLLISION_PADDING),\n );\n\n // Flip to the opposite side when the preferred one has no room — these\n // controls sit in the top row, the bottom action bar, and a rail down\n // the edge, so any of the four can be the side without space.\n const fits = (near: number, far: number, size: number, viewport: number) => ({\n fitsNear: near >= COLLISION_PADDING,\n fitsFar: far + size <= viewport - COLLISION_PADDING,\n });\n\n if (side === \"left\" || side === \"right\") {\n const after = r.right + SIDE_OFFSET;\n const before = r.left - w - SIDE_OFFSET;\n const { fitsNear: fitsBefore, fitsFar: fitsAfter } =\n fits(before, after, w, window.innerWidth);\n const left = side === \"right\"\n ? (fitsAfter || !fitsBefore ? after : before)\n : (fitsBefore || !fitsAfter ? before : after);\n content.dataset.side = left === after ? \"right\" : \"left\";\n setPos({ top: centre(r.top, r.height, h, window.innerHeight), left });\n return;\n }\n\n const below = r.bottom + SIDE_OFFSET;\n const above = r.top - h - SIDE_OFFSET;\n const { fitsNear: fitsAbove, fitsFar: fitsBelow } =\n fits(above, below, h, window.innerHeight);\n const top = side === \"bottom\"\n ? (fitsBelow || !fitsAbove ? below : above)\n : (fitsAbove || !fitsBelow ? above : below);\n content.dataset.side = top === below ? \"bottom\" : \"top\";\n setPos({ top, left: centre(r.left, r.width, w, window.innerWidth) });\n };\n\n if (content.matches(\":popover-open\")) place();\n else showMeasured(content, place);\n }, [open, side, label]);\n\n if (!label || !isValidElement(children)) return <>{children}</>;\n\n return (\n <>\n <TooltipTrigger\n triggerRef={triggerRef}\n tooltipId={tooltipId}\n show={show}\n hide={hide}\n >\n {children as React.ReactElement<Record<string, unknown>>}\n </TooltipTrigger>\n <div\n ref={contentRef}\n id={tooltipId}\n popover=\"auto\"\n role=\"tooltip\"\n className={styles.content}\n style={pos ? { top: pos.top, left: pos.left } : undefined}\n onToggle={(e: React.SyntheticEvent<HTMLDivElement>) => {\n if ((e.nativeEvent as ToggleEvent).newState === \"closed\" && open) setOpen(false);\n }}\n >\n {label}\n </div>\n </>\n );\n}\n","\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { Tooltip } from \"./Tooltip\";\nimport styles from \"./IconToggle.module.scss\";\n\nexport interface IconToggleOption<V extends string> {\n value: V;\n icon: ReactNode;\n /** Used for aria-label and the hover tooltip. */\n label: string;\n}\n\n/**\n * A segmented icon toggle: every option visible at once in a single pill, the\n * selected one reading as active, and a click on any of them selecting it.\n *\n * Reach for it to switch between modes or views of the same thing, where the\n * options are few and each has an obvious glyph. The alternative pattern — one\n * button that shows the mode you are NOT in and swaps its own icon on click —\n * is deliberately not what this does: the control's meaning changes under the\n * cursor, and nobody can tell whether the icon means \"you are here\" or \"go\n * here\". Generic over the option set, so the values stay your own union type.\n */\nexport function IconToggle<V extends string>({\n options,\n value,\n onValueChange,\n orientation = \"horizontal\",\n className = \"\",\n}: {\n /** The segments, in display order. Every option is always visible —\n * this is a segmented control, not a menu.\n */\n options: IconToggleOption<V>[];\n /** The selected option's value. Fully controlled.\n *\n * NoInfer so V is derived from `options` alone. Without it a value that is\n * not among the options simply widened V to include itself, which made the\n * generic silently accept the one mistake it looks like it should catch. */\n value: NoInfer<V>;\n /** Called with the newly selected value. Not called when the already\n * selected option is clicked. */\n onValueChange(next: V): void;\n /** Which way the pill runs. `vertical` for a rail down the edge of a\n * viewport, where a horizontal strip would eat the width. Default\n * `horizontal`. */\n orientation?: \"horizontal\" | \"vertical\";\n /** Merged onto the group wrapper. */\n className?: string;\n}) {\n const vertical = orientation === \"vertical\";\n return (\n <div\n className={`${styles.group} ${vertical ? styles.vertical : \"\"} ${className}`}\n role=\"group\"\n >\n {options.map((opt) => (\n // A horizontal pill sits at the top of the scene, so its tooltips hang\n // below it. A vertical one has a segment directly below every segment,\n // so they go to the side instead — otherwise each tooltip covers the\n // next option along.\n <Tooltip key={opt.value} label={opt.label} side={vertical ? \"right\" : \"bottom\"}>\n <button\n type=\"button\"\n className={`${styles.segment} ${opt.value === value ? styles.active : \"\"}`}\n aria-label={opt.label}\n aria-pressed={opt.value === value}\n onClick={() => {\n if (opt.value !== value) onValueChange(opt.value);\n }}\n >\n {opt.icon}\n </button>\n </Tooltip>\n ))}\n </div>\n );\n}\n","// A single-choice menu. One component and one child type:\n//\n// <Select value={v} onValueChange={setV}>\n// <Select.Item value=\"a\">A</Select.Item>\n// </Select>\n//\n// It used to be Root/Trigger/Content/Item, mirroring the JSX shape of the\n// library this was migrated from. Three of those four were ceremony: the\n// trigger was mandatory and identical at every call site, and Content only\n// ever wrapped Items. They are now built in, which is why `Select` is the\n// component itself rather than a namespace.\n//\n// Native engine: a <button> trigger plus an always-mounted listbox that rides\n// the browser's own popover layer. It stays where it is in the DOM — so the\n// component is still one subtree, and a click inside it is still a click\n// inside the Select — while rendering in the top layer, above every ancestor.\n// That is what lets a Select inside a Dialog, or any container that clips or\n// contains its children, drop its panel over the lot. No React portal: a\n// portal would move the node, and with it the event paths and the focus order\n// this relies on.\n\"use client\";\nimport type * as React from \"react\";\nimport {\n Children, createContext, isValidElement, useCallback, useContext,\n useEffect, useId, useLayoutEffect, useMemo, useRef, useState, type ReactNode,\n} from \"react\";\nimport { cx } from \"./propShared\";\nimport { showMeasured } from \"../internal/showMeasured\";\nimport styles from \"./Select.module.scss\";\nimport ctl from \"../styles/spaceControls\";\n\ninterface RootCtx {\n value: string;\n onValueChange: (v: string) => void;\n disabled?: boolean;\n open: boolean;\n setOpen: (o: boolean) => void;\n highlighted: string | null;\n setHighlighted: (v: string | null) => void;\n listboxId: string;\n values: string[];\n labelFor: (v: string) => ReactNode;\n /** Previously carried in its own context, because with Trigger and Content\n * as separate components a ref sitting beside plain state made every read\n * of the OTHER fields look like a render-time ref access to\n * react-hooks/refs. Only Item reads it now, and only inside an event\n * handler, so the split bought nothing. Keep it that way: read `.current`\n * in handlers and effects, never during render. */\n triggerRef: React.RefObject<HTMLButtonElement | null>;\n}\nconst Ctx = createContext<RootCtx | null>(null);\nconst useSelect = () => {\n const ctx = useContext(Ctx);\n if (!ctx) throw new Error(\"Select.Item must be inside a Select\");\n return ctx;\n};\n\n// Shared id contract between the listbox's aria-activedescendant and each\n// Item's id. encodeURIComponent guards against values containing spaces or\n// other characters that aren't legal in an HTML id.\nconst optionId = (listboxId: string, value: string) => `${listboxId}-${encodeURIComponent(value)}`;\n\n/** Gap between trigger and panel, and the least room to leave at a viewport\n * edge — the same values Popover places by. */\nconst OFFSET = 4;\nconst EDGE_PADDING = 8;\n\n/** Pure render-time walk of the children collecting Item values and labels —\n * no effects, so the trigger label is correct on first paint, under SSR, and\n * in renderToStaticMarkup tests. Recurses, so Items may be wrapped (a\n * fragment, a `.map`, a grouping element) rather than being direct children. */\nfunction collectItems(children: ReactNode): Array<{ value: string; label: ReactNode; disabled?: boolean }> {\n const out: Array<{ value: string; label: ReactNode; disabled?: boolean }> = [];\n const walk = (nodes: ReactNode) => {\n Children.forEach(nodes, (child) => {\n if (!isValidElement(child)) return;\n const props = child.props as { value?: string; children?: ReactNode; disabled?: boolean };\n if (child.type === Item && typeof props.value === \"string\") {\n out.push({ value: props.value, label: props.children, disabled: props.disabled });\n } else if (props.children) {\n walk(props.children);\n }\n });\n };\n walk(children);\n return out;\n}\n\nexport interface SelectProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"value\" | \"children\" | \"onChange\"> {\n /** The selected item's value. Fully controlled. */\n value: string;\n /** Called with the newly selected value. */\n onValueChange: (v: string) => void;\n /** Blocks the trigger and removes it from the tab order. */\n disabled?: boolean;\n /** Shown when nothing is selected. Counts toward the control's width, so\n * selecting an option never resizes it. */\n placeholder?: string;\n /** Ambient motion: the lit arc orbiting the rim. The glass skin itself is\n * always applied. Default true. */\n animated?: boolean;\n /** One or more `Select.Item`. Anything else is ignored for selection but\n * still rendered in the panel. */\n children?: ReactNode;\n}\n\n/**\n * A single-choice menu for lists too long to show inline. Fully controlled.\n *\n * The control sizes itself to its widest option, so it never changes width as\n * you select — capped by `--sp-select-trigger-max-width`, past which the label\n * ellipsizes.\n *\n * Reads its options at render time rather than through effects, so the right\n * label shows on first paint and under SSR.\n *\n * Every prop other than the ones listed lands on the trigger button, which is\n * the focusable control — so `aria-label`, `id`, `name` and `onBlur` go where\n * you would expect.\n */\nfunction SelectRoot({\n value,\n onValueChange,\n disabled,\n placeholder,\n animated = true,\n className,\n children,\n ...rest\n}: SelectProps) {\n const [open, setOpen] = useState(false);\n const [highlighted, setHighlighted] = useState<string | null>(null);\n const listboxId = useId();\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const rootRef = useRef<HTMLDivElement | null>(null);\n const listRef = useRef<HTMLDivElement | null>(null);\n const [triggerWidth, setTriggerWidth] = useState<number | null>(null);\n const [maxHeight, setMaxHeight] = useState<number | null>(null);\n // Where the panel sits in the viewport. Fixed coordinates, because a\n // top-layer element is positioned against the viewport rather than against\n // any ancestor of its own.\n const [pos, setPos] = useState<{ top: number; left: number } | null>(null);\n\n const items = useMemo(() => collectItems(children), [children]);\n const values = useMemo(() => items.filter((i) => !i.disabled).map((i) => i.value), [items]);\n const itemLabels = useMemo(() => items.map((i) => i.label), [items]);\n const labelFor = useCallback(\n (v: string) => items.find((i) => i.value === v)?.label ?? null,\n [items],\n );\n\n // Light-dismiss: click outside closes.\n useEffect(() => {\n if (!open) return;\n const onDown = (e: MouseEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener(\"mousedown\", onDown);\n return () => document.removeEventListener(\"mousedown\", onDown);\n }, [open]);\n\n // Measures the trigger to size and place the panel: its width, the room\n // below it, and the viewport coordinates to sit at. One layout read, and\n // the panel writes the side it landed on for the reveal to travel away from.\n const place = useCallback(() => {\n const trigger = triggerRef.current;\n const list = listRef.current;\n if (!trigger || !list) return;\n const rect = trigger.getBoundingClientRect();\n setTriggerWidth(trigger.offsetWidth);\n\n const below = window.innerHeight - rect.bottom - EDGE_PADDING;\n const above = rect.top - EDGE_PADDING;\n // Below unless there is markedly more room above: a menu that jumps sides\n // for a few pixels' gain reads as a glitch.\n const flip = below < Math.min(list.offsetHeight + OFFSET, 200) && above > below;\n const room = Math.max(120, Math.min(380, flip ? above - OFFSET : below - OFFSET));\n setMaxHeight(room);\n list.dataset.side = flip ? \"top\" : \"bottom\";\n\n const height = Math.min(list.offsetHeight, room);\n const top = flip ? Math.max(EDGE_PADDING, rect.top - OFFSET - height) : rect.bottom + OFFSET;\n // Kept on screen: a panel wider than its trigger near the right edge\n // slides back in rather than running off.\n const left = Math.min(\n Math.max(rect.left, EDGE_PADDING),\n Math.max(window.innerWidth - list.offsetWidth - EDGE_PADDING, EDGE_PADDING),\n );\n setPos((prev) => (prev && prev.top === top && prev.left === left ? prev : { top, left }));\n }, []);\n\n // Placed while laid out but invisible, then shown, so the reveal starts from\n // the right side. Layout effect: the corrected position lands before paint.\n useLayoutEffect(() => {\n const list = listRef.current;\n if (!list) return;\n if (open) {\n showMeasured(list, place);\n place();\n } else if (list.matches(\":popover-open\")) {\n list.hidePopover();\n }\n }, [open, place]);\n\n // Follow the trigger while open. Scroll and resize listeners are not enough:\n // anything that moves the trigger without scrolling — a dialog resizing, an\n // image loading above it — would leave the panel behind, and a top-layer\n // element cannot simply ride along with its ancestor the way an absolutely\n // positioned one does. One layout read a frame, and only while open.\n useEffect(() => {\n if (!open) return;\n let frame = 0;\n let last = \"\";\n const track = () => {\n const trigger = triggerRef.current;\n if (trigger) {\n const r = trigger.getBoundingClientRect();\n const key = `${r.top}|${r.left}|${r.width}|${window.innerWidth}|${window.innerHeight}`;\n if (key !== last) {\n last = key;\n place();\n }\n }\n frame = requestAnimationFrame(track);\n };\n frame = requestAnimationFrame(track);\n return () => cancelAnimationFrame(frame);\n }, [open, place]);\n\n // Focus the listbox on open so arrow keys work immediately.\n useEffect(() => {\n if (open) listRef.current?.focus();\n }, [open]);\n\n const openWith = (highlight: string | null) => {\n setHighlighted(highlight ?? values[0] ?? null);\n setOpen(true);\n };\n\n const move = (delta: number) => {\n const idx = highlighted ? values.indexOf(highlighted) : -1;\n const next = Math.min(Math.max(idx + delta, 0), values.length - 1);\n setHighlighted(values[next] ?? null);\n };\n\n const label = value ? labelFor(value) : null;\n\n return (\n <Ctx.Provider\n value={{\n value, onValueChange, disabled, open, setOpen, highlighted,\n setHighlighted, listboxId, values, labelFor, triggerRef,\n }}\n >\n <div ref={rootRef} className={styles.root}>\n <button\n type=\"button\"\n {...rest}\n ref={triggerRef}\n disabled={disabled}\n className={cx(styles.trigger, ctl.spaceControl, \"spSelectTrigger\", className)}\n data-animated={animated ? undefined : \"false\"}\n data-state={open ? \"open\" : \"closed\"}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-controls={listboxId}\n onClick={() => (open ? setOpen(false) : openWith(value || null))}\n onKeyDown={(e) => {\n if (e.key === \"ArrowDown\" || e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n openWith(value || null);\n }\n }}\n >\n {/* The visible label and a hidden copy of every option share one\n grid cell, so the button is as wide as its widest choice and\n never jumps width when the selection changes. Capped by\n --sp-select-trigger-max-width, past which the label ellipsizes. */}\n <span className={styles.labelWrap}>\n <span className={styles.sizer} data-sizer=\"\" aria-hidden=\"true\">\n {itemLabels.map((l, i) => (\n // eslint-disable-next-line react/no-array-index-key\n <span key={i}>{l}</span>\n ))}\n {placeholder && <span>{placeholder}</span>}\n </span>\n <span className={styles.triggerLabel}>{label ?? placeholder ?? \"\"}</span>\n </span>\n <svg className={styles.chevron} width=\"9\" height=\"9\" viewBox=\"0 0 9 9\" aria-hidden=\"true\">\n <path d=\"M0.5 3 L4.5 7 L8.5 3\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n </svg>\n </button>\n\n {/* Always mounted, so the trigger can read the item labels for sizing\n before the panel has ever been opened.\n\n popover=\"manual\", not \"auto\": auto would light-dismiss on the\n pointerdown that presses the trigger, so the click that follows\n would reopen a panel the reader meant to close. The outside-press\n listener above already closes it, and Escape is handled below. */}\n <div\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n tabIndex={-1}\n popover=\"manual\"\n data-side=\"bottom\"\n aria-activedescendant={highlighted ? optionId(listboxId, highlighted) : undefined}\n className={cx(styles.listbox, ctl.spacePanel)}\n data-animated={animated ? undefined : \"false\"}\n style={\n {\n ...(triggerWidth != null ? { \"--_select-trigger-width\": `${triggerWidth}px` } : {}),\n ...(maxHeight != null ? { maxHeight: `${maxHeight}px` } : {}),\n ...(pos ? { top: pos.top, left: pos.left } : {}),\n } as React.CSSProperties\n }\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n e.stopPropagation(); // don't let an ancestor Dialog close too\n setOpen(false);\n triggerRef.current?.focus();\n } else if (e.key === \"ArrowDown\") { e.preventDefault(); move(1); }\n else if (e.key === \"ArrowUp\") { e.preventDefault(); move(-1); }\n else if (e.key === \"Home\") { e.preventDefault(); setHighlighted(values[0] ?? null); }\n else if (e.key === \"End\") { e.preventDefault(); setHighlighted(values[values.length - 1] ?? null); }\n else if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n if (highlighted) {\n onValueChange(highlighted);\n setOpen(false);\n triggerRef.current?.focus();\n }\n } else if (e.key === \"Tab\") {\n setOpen(false);\n }\n }}\n >\n {children}\n </div>\n </div>\n </Ctx.Provider>\n );\n}\n\nexport interface SelectItemProps {\n /** Reported to onValueChange when chosen. */\n value: string;\n /** Skipped by keyboard navigation and not selectable. Still contributes its\n * width to the control's sizing. */\n disabled?: boolean;\n /** Shown in the panel and, once selected, in the closed control — so it has\n * to read correctly in both places. */\n children?: ReactNode;\n}\n\n/**\n * One option. Its children are what the closed control displays once\n * selected, so anything rendered here has to read correctly in both places.\n */\nfunction Item({ value, disabled, children }: SelectItemProps) {\n const s = useSelect();\n const selected = s.value === value;\n const highlighted = s.highlighted === value;\n return (\n <div\n id={optionId(s.listboxId, value)}\n role=\"option\"\n aria-selected={selected}\n aria-disabled={disabled || undefined}\n data-highlighted={highlighted ? \"\" : undefined}\n className={cx(styles.item, \"spSelectItem\")}\n onMouseEnter={() => !disabled && s.setHighlighted(value)}\n onClick={() => {\n if (disabled) return;\n s.onValueChange(value);\n s.setOpen(false);\n s.triggerRef.current?.focus();\n }}\n >\n {children}\n </div>\n );\n}\n\n/**\n * Choosing one value from a list, with the list kept out of the way until it\n * is wanted.\n *\n * The right control when the options are many, or dull, or both — a country, a\n * size, a sort order. Where there are few options and each one deserves to be\n * read, `RadioGroup` shows them all without a click. Where the items are\n * actions rather than values, that is `DropdownMenu`.\n *\n * The panel opens on the browser's popover layer, which is what lets it escape\n * a dialog, a transformed ancestor or a clipping overflow and sit above the\n * page at its full height. It flips above the trigger when there is no room\n * below, follows the trigger if the page scrolls, and closes on Escape with\n * focus handed back. Typing jumps to a matching option.\n *\n * Compose it from `Select.Item`.\n */\nexport const Select = Object.assign(SelectRoot, { Item });\n","\"use client\";\nimport type * as React from \"react\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./TextField.module.scss\";\nimport ctl from \"../styles/spaceControls\";\n\nexport interface TextFieldProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"className\" | \"style\"> {\n /** Merged onto the field wrapper, not the inner input. */\n className?: string;\n /** Ambient motion on the rim. The glass skin is always applied.\n * Default true. */\n animated?: boolean;\n /** Applied to the field wrapper — set width here. */\n style?: React.CSSProperties;\n /** Slots rendered inside the field, alongside the input. */\n children?: ReactNode; // Slot(s)\n}\n\n/**\n * Single-line text entry. The field surface is a wrapper around the input so\n * `TextField.Slot` can sit alongside it inside the same surface — that\n * wrapper is built in rather than being something you compose.\n *\n * Props land on the inner input, so `value`, `onChange` and the rest behave\n * as they would on a bare input. `className` and `style` land on the field\n * surface instead, which is where width belongs.\n *\n * The ref forwards to the input, not the wrapper.\n */\nconst TextFieldRoot = forwardRef<HTMLInputElement, TextFieldProps>(function TextField(\n { className, style, animated = true, children, ...inputProps },\n ref,\n) {\n return (\n <div\n className={cx(styles.root, ctl.spaceInput, \"spTextFieldRoot\", className)}\n data-animated={animated ? undefined : \"false\"}\n style={style}\n >\n {children}\n <input {...inputProps} ref={ref} className={cx(styles.input, \"spTextFieldInput\")} />\n </div>\n );\n});\n\n/**\n * A fixed element inside the field, before or after the input — an icon, a\n * unit, a short affordance. Sits within the field's surface rather than\n * beside it, and does not shrink as the input fills.\n */\nfunction Slot({\n children,\n}: {\n /** The slot's contents — an icon, a unit, a short affordance. */\n children?: ReactNode;\n}) {\n return <span className={styles.slot}>{children}</span>;\n}\n\n/**\n * A single line of text the reader types.\n *\n * A real `<input>` underneath, so `value`, `onChange`, `type`, `required`,\n * `autoComplete` and the rest of the native attributes all work as they\n * already do, and the browser's own autofill and validation come along with\n * them. For more than a line, use `TextArea`.\n *\n * Put an icon, a unit or a small button beside the text with `TextField.Slot`.\n * It sits inside the field's rim and keeps its own padding, so the text never\n * runs underneath it.\n */\nexport const TextField = Object.assign(TextFieldRoot, { Slot });\n","\"use client\";\nimport type * as React from \"react\";\nimport { forwardRef } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./TextArea.module.scss\";\nimport ctl from \"../styles/spaceControls\";\n\nexport interface TextAreaProps\n extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, \"className\" | \"style\"> {\n /** Merged onto the field wrapper, not the inner textarea. */\n className?: string;\n /** Ambient motion on the rim. The glass skin is always applied.\n * Default true. */\n animated?: boolean;\n /** Applied to the field wrapper — set width here. */\n style?: React.CSSProperties;\n}\n\n/**\n * Multi-line text entry. `rows` sets the initial height; it grows with its\n * container's width and resizes vertically only, since horizontal drag would\n * break the surrounding layout.\n */\nexport const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(function TextArea(\n { className, style, animated = true, ...rest },\n ref,\n) {\n return (\n <div\n className={cx(styles.root, ctl.spaceInput, ctl.spaceTextArea, \"spTextFieldRoot\", className)}\n data-animated={animated ? undefined : \"false\"}\n style={style}\n >\n <textarea {...rest} ref={ref} className={cx(styles.textarea, \"spTextAreaInput\")} />\n </div>\n );\n});\n","// A text field with a result list hanging under it.\n//\n// It never fetches and never ranks: the consumer hands it the candidate rows,\n// from memory or from an API, in whatever order that domain considers best.\n// What it does own is the narrowing — matching the typed text against those\n// rows — plus the popover, the keyboard model and the aria wiring. Those are\n// the parts every autocomplete needs and nobody enjoys writing twice.\n//\n// A caller whose rows were already matched server-side passes `preFiltered`\n// and the narrowing is skipped, so a fuzzy or synonym match made elsewhere is\n// not undone by a plain substring test here.\n\"use client\";\nimport type * as React from \"react\";\nimport {\n useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, type ReactNode,\n} from \"react\";\nimport { cx } from \"./propShared\";\nimport { showMeasured } from \"../internal/showMeasured\";\nimport { TextField } from \"./TextField\";\nimport styles from \"./Autocomplete.module.scss\";\nimport ctl from \"../styles/spaceControls\";\n\nexport interface AutocompleteOption {\n /** Handed back to `onSelect` when this row is chosen. */\n value: string;\n /** The row's main text. */\n label: ReactNode;\n /** Optional secondary text, set against the trailing edge — a category, a\n * score, a date. Kept out of `label` so it stays visually subordinate and\n * does not affect which row a reader scans for. */\n meta?: ReactNode;\n /** Shown, but skipped by the keyboard and unselectable. */\n disabled?: boolean;\n /** The text the typed query is matched against, when `label` is not a plain\n * string. Falls back to `label` if it is one, and to `value` otherwise —\n * and `value` is usually a slug, which is rarely what someone is typing. */\n search?: string;\n}\n\nexport interface AutocompleteProps\n extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n \"value\" | \"onChange\" | \"onSelect\" | \"className\" | \"style\"\n > {\n /** The text in the field. Fully controlled. */\n value: string;\n /** Called on every keystroke. */\n onValueChange: (value: string) => void;\n /** The candidate rows, in the order you want them shown. They are narrowed\n * against what has been typed unless `preFiltered` is set; the order you\n * give is always preserved, so ranking stays yours. Nothing is offered\n * until something has been typed. Past that, an empty array with no\n * `loading` and no `emptyMessage` still shows no panel, which is how you\n * hold it shut below a minimum query length. */\n options: AutocompleteOption[];\n /** Called when a row is chosen by click or Enter. */\n onSelect: (value: string, option: AutocompleteOption) => void;\n /** Renders a leading glyph inside the field — a magnifier, usually. */\n icon?: ReactNode;\n /** Match exactly as typed, so `trappist` no longer finds `TRAPPIST`.\n * Default off, which is what nearly every search wants. */\n caseSensitive?: boolean;\n /** The rows were already matched — by a server, a fuzzy search, a synonym\n * table — so render them as given. Without this a substring test here\n * would silently drop rows a smarter match upstream had found. */\n preFiltered?: boolean;\n /** Replaces the list with a waiting message while results are on their way. */\n loading?: boolean;\n /** What that waiting message says. Name the thing being fetched — \"Loading\n * the catalogue…\" tells a reader more than a spinner's worth of nothing.\n * Default \"Loading…\". */\n loadingMessage?: ReactNode;\n /** Shown when there are no options and nothing is loading. Leave it out to\n * show no panel at all rather than an empty one. */\n emptyMessage?: ReactNode;\n /** A line under the list, outside its scroll area — \"showing 50 of 2,700\",\n * a hint, a keyboard legend. */\n footer?: ReactNode;\n /** Ambient motion on the field's rim. The glass skin is always applied.\n * Default true. */\n animated?: boolean;\n /** Merged onto the wrapper, which is what you size. */\n className?: string;\n /** Applied to the wrapper — set width here. */\n style?: React.CSSProperties;\n}\n\n/** Gap between field and panel, and the least room to leave at a viewport\n * edge — the same values Select and Popover place by. */\nconst OFFSET = 8;\nconst EDGE_PADDING = 8;\n\n/**\n * A text field that offers matching rows as you type.\n *\n * It holds no data of its own. Give it `options` and it renders them,\n * highlights one, moves that highlight with the arrow keys, and calls\n * `onSelect` when a row is chosen — however those options were produced.\n *\n * The list is a popover rather than a block in the flow: results that appear\n * mid-keystroke and push the page down under the cursor are disorienting, and\n * whatever is being searched usually sits directly below the field.\n */\nexport function Autocomplete({\n value,\n onValueChange,\n options,\n onSelect,\n icon,\n caseSensitive = false,\n preFiltered = false,\n loading = false,\n loadingMessage = \"Loading…\",\n emptyMessage,\n footer,\n animated = true,\n className,\n style,\n ...inputProps\n}: AutocompleteProps) {\n const [open, setOpen] = useState(false);\n const [active, setActive] = useState(0);\n const wrapRef = useRef<HTMLDivElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const listRef = useRef<HTMLUListElement>(null);\n const listId = useId();\n // Viewport coordinates for the panel, which renders in the browser's top\n // layer and so is placed against the viewport rather than the field.\n const [pos, setPos] = useState<{ top: number; left: number; width: number } | null>(null);\n\n // What a row is matched on: its label when that is plain text, an explicit\n // `search` when the label is markup, and the value as a last resort.\n const haystack = (o: AutocompleteOption) =>\n typeof o.label === \"string\" ? o.label : (o.search ?? o.value);\n\n // Nothing typed, nothing offered. An empty query used to let every option\n // through, so focusing the field dropped the whole dataset open before the\n // reader had asked for anything. Whitespace counts as empty.\n const hasQuery = value.trim() !== \"\";\n\n const shown = useMemo(() => {\n if (!hasQuery) return [];\n if (preFiltered) return options;\n const needle = caseSensitive ? value : value.toLowerCase();\n return options.filter((o) => {\n const text = caseSensitive ? haystack(o) : haystack(o).toLowerCase();\n return text.includes(needle);\n });\n }, [options, value, caseSensitive, preFiltered, hasQuery]);\n\n const selectable = useMemo(() => shown.filter((o) => !o.disabled), [shown]);\n\n // Nothing to say, no panel. With no query there is never anything to say —\n // not the rows, not a loading line, and not an empty message that would\n // report \"nothing matching\" for a search nobody has typed. Past that, a\n // consumer can still keep the panel shut below a minimum length by sending\n // no options, no loading and no message.\n const hasContent = hasQuery && (shown.length > 0 || loading || emptyMessage != null);\n const showPanel = open && hasContent;\n\n // A changed result set invalidates the highlight — it pointed at a row that\n // may no longer exist, let alone be the best match.\n useEffect(() => setActive(0), [shown]);\n\n // \"nearest\" scrolls only when the row is actually out of view, so walking a\n // visible list does not jump the container under the cursor.\n useEffect(() => {\n if (!showPanel) return;\n const el = listRef.current?.querySelector<HTMLElement>(`[data-index=\"${active}\"]`);\n el?.scrollIntoView({ block: \"nearest\" });\n }, [active, showPanel]);\n\n // Under the field, as wide as it, clamped to the viewport — and flipped\n // above when there is not enough room below.\n const place = useCallback(() => {\n const wrap = wrapRef.current;\n const panel = panelRef.current;\n if (!wrap || !panel) return;\n // The control itself, not the wrapper around it: the wrapper also holds\n // the panel, so measuring it put the panel below its own height and gave\n // it the wrong width.\n const field = wrap.firstElementChild ?? wrap;\n const rect = field.getBoundingClientRect();\n const height = panel.offsetHeight;\n const below = window.innerHeight - rect.bottom - EDGE_PADDING;\n const flip = below < height && rect.top - EDGE_PADDING > below;\n panel.dataset.side = flip ? \"top\" : \"bottom\";\n const top = flip ? Math.max(EDGE_PADDING, rect.top - OFFSET - height) : rect.bottom + OFFSET;\n setPos((prev) =>\n prev && prev.top === top && prev.left === rect.left && prev.width === rect.width\n ? prev\n : { top, left: rect.left, width: rect.width },\n );\n }, []);\n\n // Placed while laid out but invisible, then shown, so the reveal starts from\n // the side it landed on. Layout effect: placed before the first paint.\n useLayoutEffect(() => {\n const panel = panelRef.current;\n if (!panel) return;\n if (showPanel) {\n showMeasured(panel, place);\n place();\n } else if (panel.matches(\":popover-open\")) {\n panel.hidePopover();\n }\n }, [showPanel, place]);\n\n // Follow the field while the panel is open. A top-layer element cannot ride\n // along with an ancestor the way an absolutely positioned one does, so\n // anything that moves the field — a scroll, a dialog resizing, the list\n // growing as results arrive — has to be tracked. One layout read a frame.\n useEffect(() => {\n if (!showPanel) return;\n let frame = 0;\n let last = \"\";\n const track = () => {\n const field = wrapRef.current;\n const panel = panelRef.current;\n if (field && panel) {\n const r = (field.firstElementChild ?? field).getBoundingClientRect();\n const key = `${r.top}|${r.left}|${r.width}|${panel.offsetHeight}|${window.innerHeight}`;\n if (key !== last) {\n last = key;\n place();\n }\n }\n frame = requestAnimationFrame(track);\n };\n frame = requestAnimationFrame(track);\n return () => cancelAnimationFrame(frame);\n }, [showPanel, place]);\n\n // pointerdown, not click: a drag that starts inside the panel and ends\n // outside it is not an outside click, and the dismissal should land before\n // whatever sits underneath can fire.\n const close = useCallback(() => setOpen(false), []);\n useEffect(() => {\n if (!showPanel) return;\n const onDown = (e: PointerEvent) => {\n const node = wrapRef.current;\n if (node && e.target instanceof Node && !node.contains(e.target)) close();\n };\n document.addEventListener(\"pointerdown\", onDown);\n return () => document.removeEventListener(\"pointerdown\", onDown);\n }, [showPanel, close]);\n\n // Whether the reader has moved the highlight with the keyboard since they\n // last typed. Space selects only then: the first row is highlighted the\n // moment results appear, so a Space that always selected would make it\n // impossible to type \"trappist-1 b\" — the space after the 1 would choose a\n // row instead.\n const navigated = useRef(false);\n\n const choose = (option: AutocompleteOption) => {\n if (option.disabled) return;\n // The chosen row's text goes into the field — the same text it was matched\n // on, not its value, which is usually a slug nobody typed.\n onValueChange(haystack(option));\n onSelect(option.value, option);\n navigated.current = false;\n setOpen(false);\n };\n\n const move = (delta: number) => {\n if (selectable.length === 0) return;\n const current = shown[active];\n const from = current && !current.disabled ? selectable.indexOf(current) : -1;\n const next = (from + delta + selectable.length) % selectable.length;\n const target = selectable[next];\n if (target) setActive(shown.indexOf(target));\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Escape\") {\n // Stop here: an ancestor Dialog must not close because a suggestion\n // list did.\n if (showPanel) e.stopPropagation();\n setOpen(false);\n return;\n }\n if (e.key === \"Tab\") {\n setOpen(false);\n return;\n }\n if (!showPanel) {\n if (e.key === \"ArrowDown\") setOpen(true);\n return;\n }\n if (e.key === \"ArrowDown\") { e.preventDefault(); navigated.current = true; move(1); }\n else if (e.key === \"ArrowUp\") { e.preventDefault(); navigated.current = true; move(-1); }\n else if (e.key === \"Home\") {\n e.preventDefault();\n navigated.current = true;\n const first = selectable[0];\n if (first) setActive(shown.indexOf(first));\n } else if (e.key === \"End\") {\n e.preventDefault();\n navigated.current = true;\n const last = selectable[selectable.length - 1];\n if (last) setActive(shown.indexOf(last));\n } else if (e.key === \"Enter\" || (e.key === \" \" && navigated.current)) {\n const chosen = shown[active];\n if (chosen && !chosen.disabled) {\n e.preventDefault();\n choose(chosen);\n }\n }\n };\n\n const activeOption = showPanel ? shown[active] : undefined;\n\n return (\n <div ref={wrapRef} className={cx(styles.wrap, className)} style={style}>\n <TextField\n {...inputProps}\n type={inputProps.type ?? \"text\"}\n role=\"combobox\"\n animated={animated}\n className={styles.field}\n autoComplete=\"off\"\n aria-expanded={showPanel}\n aria-controls={listId}\n aria-autocomplete=\"list\"\n aria-activedescendant={\n activeOption && !activeOption.disabled ? `${listId}-${active}` : undefined\n }\n value={value}\n onFocus={(e) => {\n inputProps.onFocus?.(e);\n setOpen(true);\n }}\n // Focus alone is not enough. After a selection the panel shuts but\n // focus stays in the field, so onFocus never fires again and clicking\n // back into it did nothing — a combobox you cannot reopen by clicking\n // reads as broken.\n onClick={(e) => {\n inputProps.onClick?.(e);\n setOpen(true);\n }}\n onKeyDown={(e) => {\n inputProps.onKeyDown?.(e);\n onKeyDown(e);\n }}\n onChange={(e) => {\n // Typing again hands Space back to the text.\n navigated.current = false;\n onValueChange(e.target.value);\n setOpen(true);\n }}\n >\n {icon != null && <TextField.Slot>{icon}</TextField.Slot>}\n </TextField>\n\n {/* Always mounted. aria-controls above points at the listbox by id, and\n an id that resolves to nothing is a promise the markup does not keep\n — same reason Select keeps its listbox in the tree.\n\n popover=\"manual\", like Select: it renders in the browser's top layer\n so a Dialog or any container that clips or contains it cannot trap\n it, while the outside-press handling above stays ours. */}\n <div\n ref={panelRef}\n popover=\"manual\"\n data-side=\"bottom\"\n className={cx(styles.panel, ctl.spacePanel)}\n data-animated={animated ? undefined : \"false\"}\n style={pos ? { top: pos.top, left: pos.left, width: pos.width } : undefined}\n >\n {hasQuery && loading && <p className={styles.status}>{loadingMessage}</p>}\n\n {hasQuery && !loading && shown.length === 0 && emptyMessage != null && (\n <p className={styles.status}>{emptyMessage}</p>\n )}\n\n <ul\n ref={listRef}\n id={listId}\n role=\"listbox\"\n className={styles.list}\n hidden={loading || shown.length === 0}\n >\n {shown.map((option, i) => (\n <li\n key={option.value}\n id={`${listId}-${i}`}\n data-index={i}\n role=\"option\"\n aria-selected={i === active}\n aria-disabled={option.disabled || undefined}\n className={cx(\n styles.option,\n i === active && !option.disabled && styles.active,\n \"spAutocompleteOption\",\n )}\n // One highlight for pointer and keyboard both: hovering moves the\n // active row, so there is never a mouse highlight and a keyboard\n // highlight disagreeing about what Enter would do.\n onMouseEnter={() => !option.disabled && setActive(i)}\n onPointerDown={(e) => {\n // Before blur, or the panel closes and the click lands on\n // whatever the layout collapses into its place.\n e.preventDefault();\n choose(option);\n }}\n >\n <span className={styles.label}>{option.label}</span>\n {option.meta != null && <span className={styles.meta}>{option.meta}</span>}\n </li>\n ))}\n </ul>\n\n {/* Outside the scroll area, so a count stays put while the list moves. */}\n {footer != null && <div className={styles.footer}>{footer}</div>}\n </div>\n </div>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport { forwardRef, useEffect, useRef } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./Slider.module.scss\";\nimport ctl from \"../styles/spaceControls\";\n\nexport interface SliderProps {\n /** The value, as an array. One number is one thumb; two is a range, read\n * as `[start, end]` and kept in that order — the thumbs cannot swap\n * places, so index 0 is always the lower of the two. Fully controlled. */\n value: number[];\n /** Called with the whole array as a thumb moves, in the same shape it was\n * given. */\n onValueChange: (value: number[]) => void;\n /** Lower bound. */\n min: number;\n /** Upper bound. */\n max: number;\n /** The increment a thumb moves by, and the grid every value lands on: with\n * `step={10}` over 0–100 a thumb stops at 0, 10, 20 … and nothing between,\n * whether it is dragged, pressed on the track, or walked with the arrow\n * keys. Counted from `min`, so a range of 5–105 with a step of 10 lands on\n * 5, 15, 25 … Default 1, the same as a bare `<input type=\"range\">`. */\n step?: number;\n /** How close the two thumbs may come, in the value's own units. 0 lets\n * them meet; a positive number keeps a gap, for a range that would mean\n * nothing empty — \"between 2 and 2 bedrooms\". Ignored with one thumb. */\n minDistance?: number;\n /** Blocks interaction and removes it from the tab order. */\n disabled?: boolean;\n /** Merged onto the wrapper. */\n className?: string;\n /** Accessible name. Required unless a visible label references it, since a\n * slider has no text of its own. With two thumbs each one needs its own\n * name, so this is suffixed — \"Mass minimum\", \"Mass maximum\" — unless\n * `thumbLabels` says otherwise. */\n \"aria-label\"?: string;\n /** Names for the two thumbs, when the generated ones do not fit: a price\n * range might want \"From\" and \"To\". */\n thumbLabels?: [string, string];\n}\n\nconst clamp = (value: number, low: number, high: number) =>\n Math.min(Math.max(value, low), high);\n\n/**\n * A range control: one thumb for a value, two for a span between values.\n *\n * Each thumb is a real `<input type=\"range\">`, so arrow keys, Home, End and\n * Page Up/Down all work without this component reimplementing them, and a\n * screen reader announces a slider because it is one. What is drawn — the\n * glass tube, the lit fill, the little planet of a thumb — sits on top of\n * inputs that are invisible but still doing the work.\n *\n * With two thumbs they cannot cross: each is clamped to the other, so the\n * array stays in order and a range can never read back inverted. `minDistance`\n * keeps a gap between them where a zero-width range would be meaningless.\n *\n * The pointer is the component's own business, and the inputs take none of it.\n * Two inputs each covering the whole track cannot decide between them which\n * thumb a press meant: the browser hit-tests before any of this code runs, so\n * the answer came down to which input was later in the DOM. Whenever the\n * thumbs were within a thumb's width of each other — constant over a wide\n * range, where a few units are a fraction of a pixel — a press on the lower\n * one was handed to the upper one, which then refused to travel. So a press\n * anywhere on the control is measured here, against where the thumbs actually\n * are, and the nearest one is dragged until the pointer is released.\n */\nexport const Slider = forwardRef<HTMLInputElement, SliderProps>(function Slider(\n {\n value,\n onValueChange,\n min,\n max,\n step = 1,\n minDistance = 0,\n disabled,\n className,\n \"aria-label\": ariaLabel,\n thumbLabels,\n },\n ref,\n) {\n const rootRef = useRef<HTMLSpanElement | null>(null);\n const inputs = useRef<(HTMLInputElement | null)[]>([]);\n const marks = useRef<(HTMLSpanElement | null)[]>([]);\n /** The drag in progress: which thumb it carries, and where it began. A null\n * `index` means the press was exactly on two stacked thumbs and has not yet\n * said which one it wants — see `onPointerDown`. */\n const drag = useRef<{ index: number | null; startX: number } | null>(null);\n /** Takes the window listeners back off again. */\n const release = useRef<(() => void) | null>(null);\n\n const isRange = value.length > 1;\n const span = max - min || 1;\n const lower = clamp(value[0] ?? min, min, max);\n const upper = isRange ? clamp(value[1] ?? max, min, max) : lower;\n const values = isRange ? [lower, upper] : [lower];\n\n const percent = (v: number) => ((v - min) / span) * 100;\n\n /**\n * What the component knows right now.\n *\n * A drag's listeners are attached once, when the pointer goes down, so they\n * close over that render — and the value they are moving changes under them\n * on every frame of the drag. Reading through a ref instead means the\n * clamping sees where the OTHER thumb is now, not where it was when the\n * drag began, which is the difference between two thumbs that cannot cross\n * and two that cross once and stick.\n */\n const now = useRef({ values, min, max, span, step, minDistance, isRange, onValueChange });\n now.current = { values, min, max, span, step, minDistance, isRange, onValueChange };\n\n /** The nearest value on the step grid at or below `v`, and at or above. The\n * grid is counted from `min`, and rounded before flooring because a sum of\n * floats lands a hair under the mark often enough to matter: 0.1 * 3 is\n * 0.30000000000000004, and floor would send it a whole step backwards. */\n const gridBelow = (v: number) => {\n const s = now.current;\n return s.min + Math.floor(Number(((v - s.min) / s.step).toFixed(8))) * s.step;\n };\n const gridAbove = (v: number) => {\n const s = now.current;\n return s.min + Math.ceil(Number(((v - s.min) / s.step).toFixed(8))) * s.step;\n };\n\n /** A thumb's new value, clamped so the two can never cross — and kept on\n * the step grid while doing it. A `minDistance` that is not a whole number\n * of steps would otherwise park a thumb between two steps: with a step of\n * 10 and a gap of 25, stopping against the neighbour means 75, which is\n * not a value this slider can otherwise produce. The gap is the floor, so\n * the thumb settles on the next step that still honours it. */\n const clampThumb = (index: number, next: number) => {\n const s = now.current;\n if (!s.isRange) return clamp(next, s.min, s.max);\n return index === 0\n ? clamp(next, s.min, Math.max(s.min, gridBelow(s.values[1] - s.minDistance)))\n : clamp(next, Math.min(s.max, gridAbove(s.values[0] + s.minDistance)), s.max);\n };\n\n const move = (index: number, next: number) => {\n const s = now.current;\n const settled = clampThumb(index, next);\n if (settled === s.values[index]) return;\n const updated = [...s.values];\n updated[index] = settled;\n s.onValueChange(updated);\n };\n\n /** The value a press at this point on the screen is asking for. */\n const valueAt = (clientX: number) => {\n const s = now.current;\n const box = rootRef.current?.getBoundingClientRect();\n if (!box || box.width === 0) return s.values[0];\n const ratio = clamp((clientX - box.left) / box.width, 0, 1);\n const raw = s.min + ratio * s.span;\n return clamp(s.min + Math.round((raw - s.min) / s.step) * s.step, s.min, s.max);\n };\n\n /** Where a thumb is drawn, in screen pixels, and how wide it is. */\n const markBox = (index: number) => marks.current[index]?.getBoundingClientRect();\n\n /**\n * Which thumb a press belongs to: the one drawn nearest the pointer. Asking\n * in pixels rather than in values is the point — over a wide range two very\n * different numbers are the same place on screen, and the reader is pressing\n * a place.\n */\n const nearestTo = (clientX: number): number | null => {\n if (!now.current.isRange) return 0;\n const first = markBox(0);\n const second = markBox(1);\n if (!first || !second) return 0;\n const firstCentre = first.left + first.width / 2;\n const toFirst = Math.abs(clientX - firstCentre);\n const toSecond = Math.abs(clientX - (second.left + second.width / 2));\n if (toFirst !== toSecond) return toFirst < toSecond ? 0 : 1;\n // Equally near, which with two thumbs at one value is every press on\n // them. Off to one side, the side is the answer: a press to the left of\n // the pair wants the lower thumb, because that is the one that can travel\n // that way. Dead centre, nothing in the press says which, so the question\n // is left to the first move of the drag.\n if (Math.abs(clientX - firstCentre) <= 1) return null;\n return clientX < firstCentre ? 0 : 1;\n };\n\n /** Whether the press landed on the thumb itself rather than on the track. */\n const onThumb = (index: number, clientX: number) => {\n const box = markBox(index);\n if (!box) return false;\n return Math.abs(clientX - (box.left + box.width / 2)) <= box.width / 2;\n };\n\n const stopDragging = () => {\n drag.current = null;\n rootRef.current?.removeAttribute(\"data-dragging\");\n release.current?.();\n };\n\n /**\n * Takes hold of a thumb and drags it until the pointer lets go.\n *\n * A press on the track moves the nearest thumb to it first; a press on a\n * thumb takes hold of it where it stands, so grabbing a handle never jogs\n * the value before the drag has begun.\n */\n const onPointerDown = (event: React.PointerEvent<HTMLSpanElement>) => {\n if (disabled || event.button !== 0) return;\n // A second pointer coming down mid-drag would otherwise strand the first\n // drag's listeners on the window.\n release.current?.();\n\n const index = nearestTo(event.clientX);\n drag.current = { index, startX: event.clientX };\n rootRef.current?.setAttribute(\"data-dragging\", \"\");\n\n if (index !== null) {\n if (!onThumb(index, event.clientX)) move(index, valueAt(event.clientX));\n // Focus follows the press, so the keyboard carries on from the thumb the\n // reader just moved.\n inputs.current[index]?.focus();\n }\n\n // Keeps the drag alive when the pointer leaves the control, and keeps a\n // touch drag from scrolling the page with it. Synthetic events in a test\n // have no live pointer to capture, hence the guard rather than a crash.\n try {\n rootRef.current?.setPointerCapture(event.pointerId);\n } catch {\n /* no such pointer */\n }\n\n const onPointerMove = (e: PointerEvent) => {\n const held = drag.current;\n if (!held) return;\n if (held.index === null) {\n // The press sat on two stacked thumbs. Whichever way it travels names\n // the thumb: left is the lower one, right is the upper, and those are\n // the only directions each can go from a dead heat.\n const travelled = e.clientX - held.startX;\n if (Math.abs(travelled) < 1) return;\n held.index = travelled < 0 ? 0 : 1;\n inputs.current[held.index]?.focus();\n }\n move(held.index, valueAt(e.clientX));\n };\n // On the window, not the element: a drag that runs off the end of the\n // track has to keep reporting, and the release can happen anywhere.\n window.addEventListener(\"pointermove\", onPointerMove);\n window.addEventListener(\"pointerup\", stopDragging);\n window.addEventListener(\"pointercancel\", stopDragging);\n release.current = () => {\n window.removeEventListener(\"pointermove\", onPointerMove);\n window.removeEventListener(\"pointerup\", stopDragging);\n window.removeEventListener(\"pointercancel\", stopDragging);\n release.current = null;\n };\n\n // Stops the press selecting the text around the slider as it travels.\n event.preventDefault();\n };\n\n // A slider unmounted mid-drag would otherwise leave its listeners behind.\n useEffect(() => () => release.current?.(), []);\n\n const labelFor = (index: number) => {\n if (thumbLabels) return thumbLabels[index];\n if (!isRange) return ariaLabel;\n if (!ariaLabel) return index === 0 ? \"Minimum\" : \"Maximum\";\n return `${ariaLabel} ${index === 0 ? \"minimum\" : \"maximum\"}`;\n };\n\n return (\n <span\n ref={rootRef}\n className={cx(styles.root, ctl.spaceSlider, className)}\n data-disabled={disabled || undefined}\n data-range={isRange || undefined}\n onPointerDown={onPointerDown}\n >\n <span className={cx(styles.track, \"spSliderTrack\")}>\n <span\n className={cx(styles.range, \"spSliderRange\")}\n style={{\n insetInlineStart: `${isRange ? percent(lower) : 0}%`,\n width: `${isRange ? percent(upper) - percent(lower) : percent(lower)}%`,\n }}\n />\n </span>\n\n {values.map((v, index) => (\n <span\n key={index}\n ref={(node) => {\n marks.current[index] = node;\n }}\n className={cx(styles.thumb, \"spSliderThumb\")}\n style={{ left: `${percent(v)}%` }}\n data-thumb={index}\n />\n ))}\n\n {values.map((v, index) => (\n <input\n key={index}\n ref={(node) => {\n inputs.current[index] = node;\n if (index === 0) {\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }\n }}\n type=\"range\"\n className={cx(styles.input, \"spSliderInput\")}\n value={v}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n aria-label={labelFor(index)}\n onChange={(e) => move(index, Number(e.target.value))}\n />\n ))}\n </span>\n );\n});\n","/**\n * The arithmetic every chart here shares: how many colours there are, what a\n * readable set of axis ticks is, and how a value becomes a position.\n *\n * Kept apart from the components because it is pure — given the same numbers\n * it returns the same answer — which is also what makes it testable without a\n * browser, unlike everything that has to be measured.\n */\n\n/**\n * The palette, written out rather than built from an index: a token name\n * assembled at runtime cannot be checked against the ones the library\n * promises, and the check is what keeps these honest.\n */\nconst SERIES_COLORS = [\n \"var(--sp-chart-series-1-color)\",\n \"var(--sp-chart-series-2-color)\",\n \"var(--sp-chart-series-3-color)\",\n \"var(--sp-chart-series-4-color)\",\n \"var(--sp-chart-series-5-color)\",\n \"var(--sp-chart-series-6-color)\",\n \"var(--sp-chart-series-7-color)\",\n \"var(--sp-chart-series-8-color)\",\n] as const;\n\n/** How many series the palette names. A ninth is never invented: see `seriesColor`. */\nexport const SERIES_COLOR_COUNT = SERIES_COLORS.length;\n\n/**\n * The colour for a series, by its position.\n *\n * The palette is an order, not a pool. Slot 1 is always the first series, so\n * hiding one never repaints the rest — a legend toggle that recoloured the\n * survivors would make the reader re-learn the chart.\n *\n * Past the eighth the colours repeat, which is a state worth avoiding rather\n * than papering over: group the tail into \"Other\", or split the chart. The\n * components warn once in development when a chart goes past it.\n */\nexport const seriesColor = (index: number): string =>\n SERIES_COLORS[index % SERIES_COLOR_COUNT];\n\n/** A tick step a person would have chosen: 1, 2 or 5 times a power of ten. */\nfunction niceStep(rough: number): number {\n if (rough <= 0) return 1;\n const magnitude = 10 ** Math.floor(Math.log10(rough));\n const scaled = rough / magnitude;\n const step = scaled <= 1 ? 1 : scaled <= 2 ? 2 : scaled <= 5 ? 5 : 10;\n return step * magnitude;\n}\n\nexport interface Scale {\n /** The value at the bottom of the axis — zero unless something is negative. */\n min: number;\n /** The value at the top: a whole tick at or above the largest value. */\n max: number;\n /** The values to label, bottom to top. */\n ticks: number[];\n /** Where a value sits, 0 at the axis minimum and 1 at its maximum. */\n ratio: (value: number) => number;\n}\n\n/**\n * An axis for these values: a zero baseline and ticks at readable intervals.\n *\n * The top is the first whole tick at or above the largest value, so a bar\n * whose value lands exactly on a tick reaches the top line — which is the\n * honest drawing of it, not an error.\n *\n * Bars are measured from zero, always — a bar chart that starts at 40 makes a\n * 5% difference look like a fivefold one. Lines may start elsewhere, and pass\n * `zeroBased: false` to say so.\n */\nexport function linearScale(\n values: number[],\n { tickCount = 5, zeroBased = true }: { tickCount?: number; zeroBased?: boolean } = {},\n): Scale {\n const real = values.filter((v) => Number.isFinite(v));\n const lowest = real.length ? Math.min(...real) : 0;\n const highest = real.length ? Math.max(...real) : 0;\n\n // Flat data still needs an axis with height, or every mark lands on one line.\n let low = zeroBased ? Math.min(0, lowest) : lowest;\n let high = zeroBased ? Math.max(0, highest) : highest;\n if (low === high) {\n if (low === 0) high = 1;\n else {\n low = Math.min(0, low);\n high = Math.max(0, high);\n }\n }\n\n const step = niceStep((high - low) / Math.max(1, tickCount));\n const from = Math.floor(low / step) * step;\n const to = Math.ceil(high / step) * step;\n\n const ticks: number[] = [];\n // Counted rather than accumulated: adding a float step repeatedly drifts,\n // and the labels would read 0.30000000000000004.\n const count = Math.round((to - from) / step);\n for (let i = 0; i <= count; i++) ticks.push(Number((from + i * step).toPrecision(12)));\n\n const span = to - from || 1;\n return { min: from, max: to, ticks, ratio: (value) => (value - from) / span };\n}\n\n/**\n * Where each category sits along the x axis, as a fraction of the width.\n *\n * `band` is the middle of each slot — what a bar is centred on, and where a\n * line's point sits. Bars share their slot: `inset` is how much of it is left\n * clear either side, so neighbouring bars do not touch.\n */\nexport function bandPositions(count: number, inset = 0.25): { centre: number[]; width: number } {\n if (count <= 0) return { centre: [], width: 0 };\n const slot = 1 / count;\n return {\n centre: Array.from({ length: count }, (_, i) => slot * (i + 0.5)),\n width: slot * (1 - inset * 2),\n };\n}\n\n/**\n * A bar as a path, rounded at the end the value reaches and square where it\n * meets the baseline — a bar is a length measured from the axis, and rounding\n * that end would round away the thing being measured. `up` is false for a\n * value below zero, which rounds the bottom instead.\n */\nexport function barPath(\n x: number, y: number, width: number, height: number, radius: number, up = true,\n): string {\n const r = Math.max(0, Math.min(radius, width / 2, height));\n if (r === 0) return `M${x},${y}h${width}v${height}h${-width}Z`;\n return up\n ? `M${x},${y + height}V${y + r}a${r},${r} 0 0 1 ${r},${-r}h${width - r * 2}` +\n `a${r},${r} 0 0 1 ${r},${r}V${y + height}Z`\n : `M${x},${y}V${y + height - r}a${r},${r} 0 0 0 ${r},${r}h${width - r * 2}` +\n `a${r},${r} 0 0 0 ${r},${-r}V${y}Z`;\n}\n\n/** Points along the x axis for a line: first at the left edge, last at the right. */\nexport function pointPositions(count: number): number[] {\n if (count <= 0) return [];\n if (count === 1) return [0.5];\n return Array.from({ length: count }, (_, i) => i / (count - 1));\n}\n\n/**\n * Whether this is a development build, read off the global rather than from\n * `process`: the library is bundled for browsers too, where naming `process`\n * is both untyped and, in some bundlers, a runtime error.\n */\nexport const isDevelopment = (): boolean => {\n const global = globalThis as { process?: { env?: { NODE_ENV?: string } } };\n return global.process?.env?.NODE_ENV !== \"production\";\n};\n\n/** A number as a label: thousands separated, long decimals trimmed. */\nexport const formatValue = (value: number): string =>\n Number.isInteger(value)\n ? value.toLocaleString(\"en-US\")\n : value.toLocaleString(\"en-US\", { maximumFractionDigits: 2 });\n","\"use client\";\nimport type * as React from \"react\";\nimport { useCallback, useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./Chart.module.scss\";\nimport {\n SERIES_COLOR_COUNT, bandPositions, barPath, formatValue, isDevelopment, linearScale,\n pointPositions, seriesColor,\n} from \"../internal/chartScale\";\n\nexport interface ChartSeries {\n /** Named in the legend and the tooltip, so say what the numbers are. */\n name: string;\n /** One value per category, in the same order. `null` is a gap — a month with\n * no reading — and is drawn as one rather than as zero. */\n data: (number | null)[];\n /** Overrides this series' colour. Leave it alone unless the series has a\n * meaning of its own that a reader already associates with a colour. */\n color?: string;\n}\n\nexport interface ChartPoint {\n /** The series the point belongs to. */\n series: string;\n seriesIndex: number;\n /** The category beneath it. */\n category: string;\n categoryIndex: number;\n value: number;\n}\n\nexport interface ChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onClick\"> {\n /** How to draw it. The same data can be any of the three: bars for\n * comparing amounts, a line for a trend, an area for a trend whose total\n * matters. Switching is a prop, so a chart can offer the choice. */\n type: \"bar\" | \"line\" | \"area\";\n /** The x axis, in order. Every series' `data` lines up with this by\n * position, so they must be the same length. */\n categories: string[];\n /** One entry per dataset. */\n series: ChartSeries[];\n /** How tall the plot is, in pixels. The width comes from the container.\n * Default 240. */\n height?: number;\n /** Stack the series instead of setting them side by side (bar) or overlaying\n * them (area). For parts of a whole, where the total is the point. */\n stacked?: boolean;\n /** Show the legend. Defaults to true for more than one series, which is when\n * colour alone would otherwise be carrying the identity. */\n legend?: boolean;\n /** Draw the horizontal grid lines. Default true. */\n grid?: boolean;\n /** How a value is written, in labels and the tooltip. */\n formatValue?: (value: number) => string;\n /** Roughly how many labelled ticks the y axis gets. Default 5. */\n tickCount?: number;\n /** The lit finish this library gives everything else: marks that catch the\n * light, and a first draw where bars rise from the axis and a line draws\n * itself on. Default true; a reader who asked for less motion gets the\n * finish without the movement either way. */\n animated?: boolean;\n /** The category index from which the data is still arriving — usually\n * `categories.length - 1`, today's bar, which will keep growing until the\n * day ends. Those bars are drawn hatched rather than solid, and the\n * tooltip and the table say \"so far\", so a half-counted day is never read\n * as a collapse. Bars only: a line says the same thing with its own last\n * segment, which is a separate job. */\n partialFrom?: number;\n /** Called when a bar or point is chosen, with what it stands for. Keyboard\n * activation reports the same thing a click does. */\n onPointClick?: (point: ChartPoint) => void;\n /** Says what the chart shows, for a reader who cannot see it. The figures\n * themselves are always available in the table this renders for screen\n * readers, so this wants the point, not the numbers. */\n \"aria-label\"?: string;\n}\n\n/** The reading under the pointer: which category, and where to put the card. */\ninterface Hover {\n index: number;\n x: number;\n}\n\nconst PADDING = { top: 8, right: 8, bottom: 24 };\n/** Room for the y labels. Widened per chart by the longest one. */\nconst AXIS_GUTTER = 8;\n\n/**\n * A chart of one or more datasets over a shared set of categories — as bars,\n * a line, or a filled area.\n *\n * Drawn as plain SVG from the library's own arithmetic: no charting\n * dependency, and every colour, size and radius is a token, so a chart is the\n * same material as the rest of the page.\n *\n * The series palette is an order rather than a pool. The first series is\n * always the first colour, so hiding one never repaints the others.\n *\n * What it does without being asked: a legend once there is more than one\n * series, a crosshair reading every series at the category under the pointer,\n * and a table of the same numbers for screen readers. What it refuses to do:\n * a second y axis. Two measures on different scales belong in two charts —\n * one pair of axes can be drawn to tell any story you like.\n */\nexport function Chart({\n type,\n categories,\n series,\n height = 240,\n stacked = false,\n legend,\n grid = true,\n formatValue: format = formatValue,\n tickCount = 5,\n animated = true,\n partialFrom,\n onPointClick,\n className,\n \"aria-label\": ariaLabel,\n ...rest\n}: ChartProps) {\n const titleId = useId();\n const plotRef = useRef<HTMLDivElement | null>(null);\n const [width, setWidth] = useState(0);\n const [hover, setHover] = useState<Hover | null>(null);\n\n // The plot is as wide as its container: the width has to be measured, since\n // an SVG cannot size its own coordinate system from a percentage.\n useEffect(() => {\n const node = plotRef.current;\n if (!node) return;\n const observer = new ResizeObserver(([entry]) => {\n setWidth(Math.round(entry.contentRect.width));\n });\n observer.observe(node);\n setWidth(Math.round(node.getBoundingClientRect().width));\n return () => observer.disconnect();\n }, []);\n\n useEffect(() => {\n if (!isDevelopment()) return;\n if (series.length > SERIES_COLOR_COUNT) {\n // Not an error: it still draws. But two series now share a colour, and\n // no amount of care elsewhere makes that readable.\n console.warn(\n `Chart: ${series.length} series, but the palette names ${SERIES_COLOR_COUNT}. ` +\n \"Past that the colours repeat. Group the tail into an \\\"Other\\\" series, or split the chart.\",\n );\n }\n const wrong = series.filter((s) => s.data.length !== categories.length);\n if (wrong.length) {\n console.warn(\n `Chart: ${wrong.map((s) => `\"${s.name}\"`).join(\", \")} ${wrong.length === 1 ? \"has\" : \"have\"} ` +\n `a different number of values than there are categories (${categories.length}). ` +\n \"Values line up with categories by position, so the tail will be missing.\",\n );\n }\n }, [series, categories.length]);\n\n const stackable = stacked && (type === \"bar\" || type === \"area\");\n // Only bars are hatched; a line has its own way of showing an unfinished\n // tail, and drawing one here would be two claims at once.\n const partial = type === \"bar\" && typeof partialFrom === \"number\" && partialFrom >= 0;\n const stillFilling = (index: number) => partial && index >= (partialFrom as number);\n\n // What the axis has to cover: the values themselves, or the running totals\n // when the series are stacked on top of one another.\n const scale = useMemo(() => {\n const values: number[] = [];\n if (stackable) {\n categories.forEach((_, i) => {\n let positive = 0;\n let negative = 0;\n series.forEach((s) => {\n const v = s.data[i];\n if (typeof v !== \"number\") return;\n if (v >= 0) positive += v;\n else negative += v;\n });\n values.push(positive, negative);\n });\n } else {\n series.forEach((s) => s.data.forEach((v) => { if (typeof v === \"number\") values.push(v); }));\n }\n // Bars are read as lengths from zero; a line is read as a shape, so it may\n // start where the data does — but not when something is negative, where\n // the zero line is the thing that gives the shape meaning.\n return linearScale(values, { tickCount, zeroBased: type !== \"line\" || values.some((v) => v < 0) });\n }, [series, categories, stackable, tickCount, type]);\n\n const labels = useMemo(() => scale.ticks.map(format), [scale.ticks, format]);\n // The gutter fits the longest label rather than a guess: 7px a character is\n // close enough for the digits and separators these labels are made of.\n const gutter = Math.max(...labels.map((l) => l.length * 7), 24) + AXIS_GUTTER;\n\n const plotWidth = Math.max(0, width - gutter - PADDING.right);\n const plotHeight = Math.max(0, height - PADDING.top - PADDING.bottom);\n // A line's first and last points sit on the ends of the axis, so without\n // this their category labels hang off both edges. Bars need none: they are\n // already inset inside their own slots.\n const edge = type === \"bar\" ? 0 : 16;\n const x = (ratio: number) => gutter + edge + ratio * Math.max(0, plotWidth - edge * 2);\n const y = (value: number) => PADDING.top + (1 - scale.ratio(value)) * plotHeight;\n\n const band = bandPositions(categories.length);\n const points = pointPositions(categories.length);\n const colorOf = (i: number) => series[i]?.color ?? seriesColor(i);\n const showLegend = legend ?? series.length > 1;\n\n /** Running totals, so a stacked mark knows what it sits on. */\n const baseline = useMemo(() => {\n const bases: number[][] = series.map(() => []);\n categories.forEach((_, i) => {\n let positive = 0;\n let negative = 0;\n series.forEach((s, si) => {\n const v = s.data[i];\n if (!stackable || typeof v !== \"number\") {\n bases[si][i] = 0;\n return;\n }\n if (v >= 0) { bases[si][i] = positive; positive += v; }\n else { bases[si][i] = negative; negative += v; }\n });\n });\n return bases;\n }, [series, categories, stackable]);\n\n const readingAt = useCallback(\n (clientX: number) => {\n const node = plotRef.current;\n if (!node || !categories.length || plotWidth <= 0) return null;\n const box = node.getBoundingClientRect();\n const span = type === \"bar\" ? plotWidth : Math.max(1, plotWidth - 32);\n const ratio = (clientX - box.left - gutter - (type === \"bar\" ? 0 : 16)) / span;\n const positions = type === \"bar\" ? band.centre : points;\n let nearest = 0;\n positions.forEach((p, i) => {\n if (Math.abs(p - ratio) < Math.abs(positions[nearest] - ratio)) nearest = i;\n });\n return { index: nearest, x: x(positions[nearest]) };\n },\n // x and the position arrays are derived from these; listing them keeps the\n // callback honest without re-creating it on every render.\n [categories.length, gutter, plotWidth, type, band.centre, points], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const report = (seriesIndex: number, categoryIndex: number) => {\n const value = series[seriesIndex]?.data[categoryIndex];\n if (typeof value !== \"number\" || !onPointClick) return;\n onPointClick({\n series: series[seriesIndex].name,\n seriesIndex,\n category: categories[categoryIndex],\n categoryIndex,\n value,\n });\n };\n\n const barWidth = stackable || series.length === 1\n ? band.width * plotWidth\n : (band.width * plotWidth) / series.length;\n\n return (\n <div\n {...rest}\n className={cx(styles.root, className)}\n data-type={type}\n data-animated={animated ? \"\" : undefined}\n style={{ ...rest.style }}\n >\n <div\n ref={plotRef}\n className={styles.plot}\n style={{ height }}\n onPointerMove={(e) => {\n if (e.pointerType === \"touch\") return;\n setHover(readingAt(e.clientX));\n }}\n onPointerLeave={() => setHover(null)}\n >\n {/* aria-hidden: the same numbers are in the table below, which is what\n a screen reader reads. A pile of unlabelled <rect>s is noise. */}\n <svg\n className={styles.svg}\n width={width || undefined}\n height={height}\n viewBox={width ? `0 0 ${width} ${height}` : undefined}\n role=\"img\"\n aria-labelledby={ariaLabel ? undefined : titleId}\n aria-label={ariaLabel}\n >\n <defs>\n {series.map((s2, si) => (\n <linearGradient key={`grad-${si}`} id={`${titleId}-grad-${si}`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n {/* The limb again: brightest where the light lands, falling\n away into the ground it stands on. */}\n <stop offset=\"0%\" stopColor={colorOf(si)} stopOpacity=\"1\" />\n <stop offset=\"100%\" stopColor={colorOf(si)} stopOpacity=\"0.55\" />\n </linearGradient>\n ))}\n {series.map((s2, si) => (\n <linearGradient key={`area-${si}`} id={`${titleId}-area-${si}`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n {/* An atmosphere rather than a slab: dense at the line, thinning\n to nothing before the axis. */}\n <stop offset=\"0%\" stopColor={colorOf(si)} stopOpacity=\"0.45\" />\n <stop offset=\"100%\" stopColor={colorOf(si)} stopOpacity=\"0.02\" />\n </linearGradient>\n ))}\n </defs>\n\n {/* Diagonal stripes in the series' own colour: a bar that is still\n filling reads as unfinished at a glance, and keeps its identity.\n One pattern per series, because a pattern carries its own paint. */}\n {partial && (\n <defs>\n {series.map((s2, si) => (\n <pattern\n key={`hatch-${si}`}\n id={`${titleId}-hatch-${si}`}\n width=\"8\"\n height=\"8\"\n patternUnits=\"userSpaceOnUse\"\n patternTransform=\"rotate(45)\"\n >\n <rect width=\"8\" height=\"8\" fill=\"transparent\" />\n <line className={styles.hatch} x1=\"2\" y1=\"0\" x2=\"2\" y2=\"8\" stroke={colorOf(si)} />\n <line className={styles.hatch} x1=\"6\" y1=\"0\" x2=\"6\" y2=\"8\" stroke={colorOf(si)} />\n </pattern>\n ))}\n </defs>\n )}\n\n {grid && scale.ticks.map((tick) => (\n <line\n key={`grid-${tick}`}\n className={cx(styles.grid, tick === 0 && scale.min < 0 && styles.zeroLine)}\n x1={gutter}\n x2={gutter + plotWidth}\n y1={y(tick)}\n y2={y(tick)}\n />\n ))}\n\n {scale.ticks.map((tick, i) => (\n <text key={`label-${tick}`} className={styles.axisLabel} x={gutter - AXIS_GUTTER} y={y(tick)} textAnchor=\"end\" dominantBaseline=\"middle\">\n {labels[i]}\n </text>\n ))}\n\n {categories.map((category, i) => (\n <text\n key={`cat-${category}-${i}`}\n className={styles.axisLabel}\n x={x(type === \"bar\" ? band.centre[i] : points[i])}\n y={height - PADDING.bottom / 2}\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n >\n {category}\n </text>\n ))}\n\n {type === \"bar\" && series.map((s, si) => (\n <g key={`bars-${s.name}-${si}`}>\n {categories.map((category, ci) => {\n const value = s.data[ci];\n if (typeof value !== \"number\") return null;\n const base = baseline[si][ci];\n const top = y(base + value);\n const bottom = y(base);\n const slotLeft = x(band.centre[ci]) - (band.width * plotWidth) / 2;\n const left = stackable || series.length === 1\n ? slotLeft\n : slotLeft + si * barWidth;\n // 2px of the surface between neighbouring bars, so two fills\n // never read as one.\n const drawWidth = Math.max(1, barWidth - (series.length > 1 && !stackable ? 2 : 0));\n const drawHeight = Math.max(1, Math.abs(bottom - top));\n const stillCounting = partial && ci >= (partialFrom as number);\n return (\n <path\n key={`bar-${category}-${ci}`}\n className={cx(styles.bar, onPointClick && styles.clickable)}\n d={barPath(left, Math.min(top, bottom), drawWidth, drawHeight, 4, value >= 0)}\n fill={stillCounting ? `url(#${titleId}-hatch-${si})` : `url(#${titleId}-grad-${si})`}\n // currentColor is what the glow in the stylesheet burns.\n color={colorOf(si)}\n data-dim={hover && hover.index !== ci ? \"\" : undefined}\n onClick={() => report(si, ci)}\n >\n <title>\n {`${s.name}, ${category}: ${format(value)}${stillCounting ? \" so far\" : \"\"}`}\n </title>\n </path>\n );\n })}\n </g>\n ))}\n\n {type !== \"bar\" && series.map((s, si) => {\n // A null is a gap: the line stops and starts again rather than\n // drawing a straight run through missing readings.\n const runs: { i: number; value: number; base: number }[][] = [];\n let run: { i: number; value: number; base: number }[] = [];\n s.data.forEach((value, i) => {\n if (typeof value !== \"number\") {\n if (run.length) runs.push(run);\n run = [];\n return;\n }\n run.push({ i, value, base: baseline[si][i] });\n });\n if (run.length) runs.push(run);\n\n return (\n <g key={`line-${s.name}-${si}`}>\n {runs.map((segment, ri) => {\n const line = segment\n .map((p, k) => `${k === 0 ? \"M\" : \"L\"}${x(points[p.i])},${y(p.base + p.value)}`)\n .join(\" \");\n const area = type === \"area\"\n ? `${line} L${x(points[segment[segment.length - 1].i])},${y(segment[segment.length - 1].base)} ` +\n segment.slice().reverse().map((p) => `L${x(points[p.i])},${y(p.base)}`).join(\" \") + \" Z\"\n : null;\n return (\n <g key={`run-${ri}`}>\n {area && (\n <path className={styles.area} d={area} fill={`url(#${titleId}-area-${si})`} />\n )}\n <path\n className={styles.line}\n d={line}\n stroke={colorOf(si)}\n color={colorOf(si)}\n fill=\"none\"\n pathLength={1}\n />\n </g>\n );\n })}\n {/* A marker per reading, shown at the crosshair — and always,\n when a series is a single point with no line to carry it. */}\n {s.data.map((value, ci) =>\n typeof value === \"number\" ? (\n <circle\n key={`dot-${ci}`}\n className={cx(styles.dot, onPointClick && styles.clickable)}\n cx={x(points[ci])}\n cy={y(baseline[si][ci] + value)}\n r={4}\n fill={colorOf(si)}\n color={colorOf(si)}\n data-on={hover?.index === ci ? \"\" : undefined}\n onClick={() => report(si, ci)}\n >\n <title>{`${s.name}, ${categories[ci]}: ${format(value)}`}</title>\n </circle>\n ) : null,\n )}\n </g>\n );\n })}\n\n {hover && (\n <line\n className={styles.crosshair}\n x1={hover.x}\n x2={hover.x}\n y1={PADDING.top}\n y2={PADDING.top + plotHeight}\n />\n )}\n </svg>\n\n {hover && (\n <div\n className={styles.tooltip}\n // Placed from the left when the reading is on the left half and\n // from the right when it is not, so the card never runs off.\n style={\n hover.x > gutter + plotWidth / 2\n ? { right: Math.max(0, width - hover.x + 12) }\n : { left: hover.x + 12 }\n }\n role=\"status\"\n >\n <p className={styles.tooltipHead}>{categories[hover.index]}</p>\n <ul className={styles.tooltipList}>\n {series.map((s, si) => {\n const value = s.data[hover.index];\n return (\n <li key={s.name} className={styles.tooltipRow}>\n <span className={styles.swatch} style={{ background: colorOf(si) }} aria-hidden=\"true\" />\n <span className={styles.tooltipName}>{s.name}</span>\n <span className={styles.tooltipValue}>\n {typeof value === \"number\" ? format(value) : \"—\"}\n {stillFilling(hover.index) && typeof value === \"number\" && (\n <span className={styles.partialNote}>so far</span>\n )}\n </span>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </div>\n\n {showLegend && (\n <ul className={styles.legend}>\n {series.map((s, si) => (\n <li key={s.name} className={styles.legendItem}>\n <span className={styles.swatch} style={{ background: colorOf(si) }} aria-hidden=\"true\" />\n {s.name}\n </li>\n ))}\n </ul>\n )}\n\n {/* The figures, for a reader who cannot see the picture. Visually\n hidden rather than absent: the alternative is a chart that says\n nothing at all to a screen reader. */}\n <table className={styles.data} id={titleId}>\n <caption>{ariaLabel ?? \"Chart data\"}</caption>\n <thead>\n <tr>\n <th scope=\"col\">Category</th>\n {series.map((s) => <th key={s.name} scope=\"col\">{s.name}</th>)}\n </tr>\n </thead>\n <tbody>\n {categories.map((category, ci) => (\n <tr key={category}>\n <th scope=\"row\">{category}</th>\n {series.map((s) => (\n <td key={s.name}>\n {typeof s.data[ci] === \"number\" ? format(s.data[ci] as number) : \"—\"}\n {stillFilling(ci) && typeof s.data[ci] === \"number\" ? \" so far\" : \"\"}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./BarList.module.scss\";\nimport { formatValue, seriesColor } from \"../internal/chartScale\";\n\nexport interface BarListItem {\n /** The row's name, at the left. */\n label: string;\n /** How long the bar is, against the largest value or an explicit `max`. */\n value: number;\n /** Overrides this row's colour. One colour for the set reads as a ranking;\n * a colour per row reads as categories. */\n color?: string;\n}\n\nexport interface BarListProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onSelect\"> {\n /** The rows, in the order they should appear. Sort before passing: the\n * order is the caller's statement about the data, not this component's. */\n items: BarListItem[];\n /** What a full track means. Defaults to the largest value, which makes the\n * rows relative to each other. Pass the total to make them shares of it. */\n max?: number;\n /** Show each row's share as a percentage beside its value. */\n showPercent?: boolean;\n /** How the value is written. */\n formatValue?: (value: number) => string;\n /** Give every row its own colour from the series palette, rather than one\n * colour for the set. */\n colorful?: boolean;\n /** Fill the bars on first render, one row after the next, the way results\n * arrive. Default true; a reader who asked for less motion gets the bars\n * already filled either way. */\n animated?: boolean;\n /** Called when a row is chosen. Rows become buttons when this is given, and\n * stay plain text when it is not — nothing looks clickable unless it is. */\n onItemClick?: (item: BarListItem, index: number) => void;\n /** Names the set for assistive tech: \"Poll results\", say. */\n \"aria-label\"?: string;\n}\n\n/**\n * A ranked list of values as bars: a label, a track, a filled bar, a figure.\n *\n * For results read against each other — a poll, the top ten by some measure,\n * a breakdown of a total. It is the form to reach for when the category names\n * are words rather than dates: they get a column of their own and stay\n * readable, where a vertical bar chart would turn them on their side.\n *\n * No axis and no grid, because there is nothing to measure against but the\n * other rows: every bar is drawn against the longest one, or against `max`\n * when the share of a known total is the point.\n */\nexport function BarList({\n items,\n max,\n showPercent = false,\n formatValue: format = formatValue,\n colorful = false,\n animated = true,\n onItemClick,\n className,\n \"aria-label\": ariaLabel,\n ...rest\n}: BarListProps) {\n const largest = max ?? Math.max(0, ...items.map((i) => i.value));\n const total = items.reduce((sum, i) => sum + (i.value > 0 ? i.value : 0), 0);\n\n return (\n <div\n {...rest}\n className={cx(styles.root, className)}\n role=\"list\"\n aria-label={ariaLabel}\n data-animated={animated ? \"\" : undefined}\n >\n {items.map((item, index) => {\n // A zero-length bar still shows its rounded cap, so a row with no\n // votes reads as a row with no votes rather than as a missing row.\n const ratio = largest > 0 ? Math.max(0, item.value) / largest : 0;\n const percent = total > 0 ? (item.value / total) * 100 : 0;\n const fill = item.color ?? (colorful ? seriesColor(index) : \"var(--sp-chart-series-1-color)\");\n\n const row = (\n <>\n <span className={styles.label}>{item.label}</span>\n <span className={styles.track}>\n <span\n className={styles.fill}\n style={{\n width: `${ratio * 100}%`,\n background: fill,\n // Each row starts a little after the one above, so a poll\n // reads as counting up rather than snapping into place.\n // Capped, or a long list would still be filling when the\n // reader has finished reading it.\n animationDelay: `${Math.min(index * 60, 360)}ms`,\n }}\n />\n </span>\n <span className={styles.value}>\n {format(item.value)}\n {showPercent && <span className={styles.percent}>{Math.round(percent)}%</span>}\n </span>\n </>\n );\n\n return (\n <div key={`${item.label}-${index}`} role=\"listitem\" className={styles.row}>\n {onItemClick ? (\n <button\n type=\"button\"\n className={cx(styles.line, styles.pressable)}\n onClick={() => onItemClick(item, index)}\n >\n {row}\n </button>\n ) : (\n <span className={styles.line}>{row}</span>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport { useId, useState } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./PieChart.module.scss\";\nimport { formatValue, seriesColor } from \"../internal/chartScale\";\n\nexport interface PieSlice {\n /** The slice's name — always drawn in the legend, never colour alone. */\n label: string;\n /** Its size. Negative values are dropped: a pie has no way to show one. */\n value: number;\n /** Overrides this slice's colour. */\n color?: string;\n}\n\nexport interface PieChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onSelect\"> {\n /** The slices, in order. Sort before passing — usually largest first, which\n * is what makes a pie readable at all. */\n slices: PieSlice[];\n /** Cut the middle out, making a donut. The hole gives the total somewhere\n * to live, which is usually worth more than the extra ink. */\n donut?: boolean;\n /** Shown in a donut's middle, under the total. */\n label?: React.ReactNode;\n /** How wide the circle is, in pixels. Default 180. */\n size?: number;\n /** Show the legend. Default true: a pie without one is a colour quiz. */\n legend?: boolean;\n /** The lit finish, and the sweep on its first draw. Default true. */\n animated?: boolean;\n /** How a value is written, in the legend and the middle. */\n formatValue?: (value: number) => string;\n /** Called when a slice is chosen. */\n onSliceClick?: (slice: PieSlice, index: number) => void;\n /** Says what the whole shows. */\n \"aria-label\"?: string;\n}\n\n/** Where a fraction of the circle lands, measured clockwise from the top. */\nconst pointOnCircle = (centre: number, radius: number, fraction: number) => {\n const angle = fraction * 2 * Math.PI - Math.PI / 2;\n return { x: centre + radius * Math.cos(angle), y: centre + radius * Math.sin(angle) };\n};\n\n/**\n * Parts of a whole, as a circle.\n *\n * Worth saying plainly: a pie is the weakest way to compare sizes — people\n * read angles badly — and it is the wrong chart for more than a handful of\n * slices, for values that are not parts of one total, or for change over\n * time. Where the comparison is the point, `BarList` is easier to read. Where\n * a pie is right is a whole that splits a few ways and a reader who needs to\n * see \"most of it\" at a glance.\n *\n * So this one is built to stay readable: every slice keeps a hairline of the\n * surface between it and its neighbour, the legend carries the names and the\n * figures, and a donut puts the total in the middle where it can be read\n * exactly rather than estimated.\n */\nexport function PieChart({\n slices,\n donut = false,\n label,\n size = 180,\n legend = true,\n animated = true,\n formatValue: format = formatValue,\n onSliceClick,\n className,\n \"aria-label\": ariaLabel,\n ...rest\n}: PieChartProps) {\n const [hovered, setHovered] = useState<number | null>(null);\n // Gradient ids have to be unique per instance: two pies on one page would\n // otherwise both paint with whichever defs rendered last.\n const uid = useId();\n\n const usable = slices.filter((s) => s.value > 0);\n const total = usable.reduce((sum, s) => sum + s.value, 0);\n const centre = size / 2;\n const radius = centre - 2;\n const hole = donut ? radius * 0.62 : 0;\n\n let cursor = 0;\n const arcs = usable.map((slice, index) => {\n const fraction = total > 0 ? slice.value / total : 0;\n const from = cursor;\n cursor += fraction;\n\n const outerFrom = pointOnCircle(centre, radius, from);\n const outerTo = pointOnCircle(centre, radius, cursor);\n const large = fraction > 0.5 ? 1 : 0;\n\n // A single slice is the whole circle, which an arc cannot draw: its start\n // and end points are the same, so the path collapses to nothing.\n const whole = fraction >= 0.999;\n const d = whole\n ? donut\n ? `M${centre},${centre - radius} A${radius},${radius} 0 1 1 ${centre - 0.01},${centre - radius} Z ` +\n `M${centre},${centre - hole} A${hole},${hole} 0 1 0 ${centre - 0.01},${centre - hole} Z`\n : `M${centre},${centre - radius} A${radius},${radius} 0 1 1 ${centre - 0.01},${centre - radius} Z`\n : donut\n ? `M${outerFrom.x},${outerFrom.y} A${radius},${radius} 0 ${large} 1 ${outerTo.x},${outerTo.y} ` +\n `L${pointOnCircle(centre, hole, cursor).x},${pointOnCircle(centre, hole, cursor).y} ` +\n `A${hole},${hole} 0 ${large} 0 ${pointOnCircle(centre, hole, from).x},${pointOnCircle(centre, hole, from).y} Z`\n : `M${centre},${centre} L${outerFrom.x},${outerFrom.y} ` +\n `A${radius},${radius} 0 ${large} 1 ${outerTo.x},${outerTo.y} Z`;\n\n return { slice, index, d, fraction, fillRule: whole && donut ? (\"evenodd\" as const) : undefined };\n });\n\n const originalIndex = (slice: PieSlice) => slices.indexOf(slice);\n\n return (\n <div {...rest} className={cx(styles.root, className)} data-animated={animated ? \"\" : undefined}>\n <svg\n className={styles.svg}\n width={size}\n height={size}\n viewBox={`0 0 ${size} ${size}`}\n role=\"img\"\n aria-label={ariaLabel ?? \"Pie chart\"}\n >\n {/* The slices alone are swept in; the total in the middle is not part\n of the ring and should not be revealed by it. */}\n <defs>\n {/* The same light every planet in this library is lit by: a source\n up and to the left, a limb that falls away from it, and an edge\n that darkens where the disc turns away. */}\n <radialGradient id={`${uid}-face`} cx=\"32%\" cy=\"26%\" r=\"78%\">\n <stop offset=\"0%\" stopColor=\"#fff\" stopOpacity=\"0.22\" />\n <stop offset=\"55%\" stopColor=\"#fff\" stopOpacity=\"0.04\" />\n <stop offset=\"100%\" stopColor=\"#000\" stopOpacity=\"0.28\" />\n </radialGradient>\n <radialGradient id={`${uid}-edge`} cx=\"50%\" cy=\"50%\" r=\"50%\">\n <stop offset=\"88%\" stopColor=\"#000\" stopOpacity=\"0\" />\n <stop offset=\"100%\" stopColor=\"#000\" stopOpacity=\"0.45\" />\n </radialGradient>\n </defs>\n\n <g className={styles.sweep}>\n {arcs.map(({ slice, index, d, fillRule }) => (\n <path\n key={`${slice.label}-${index}`}\n className={cx(styles.slice, onSliceClick && styles.clickable)}\n d={d}\n fill={slice.color ?? seriesColor(originalIndex(slice))}\n fillRule={fillRule}\n data-dim={hovered !== null && hovered !== index ? \"\" : undefined}\n onPointerEnter={() => setHovered(index)}\n onPointerLeave={() => setHovered(null)}\n onClick={() => onSliceClick?.(slice, originalIndex(slice))}\n >\n <title>{`${slice.label}: ${format(slice.value)}`}</title>\n </path>\n ))}\n\n {/* Laid over the slices, not under them: the light falls on the\n whole disc rather than on each slice separately, which is what\n makes it read as one solid object. Angles are untouched — the\n circle stays a circle, so a quarter still looks like a quarter.\n A tilted pie would foreshorten it and make the near slices look\n bigger than equal ones at the back. */}\n <circle className={styles.face} cx={centre} cy={centre} r={radius} fill={`url(#${uid}-face)`} />\n <circle className={styles.face} cx={centre} cy={centre} r={radius} fill={`url(#${uid}-edge)`} />\n {donut && (\n // The wall of the hole, so the middle reads as cut through the\n // disc rather than printed on it.\n <circle\n className={styles.hole}\n cx={centre}\n cy={centre}\n r={hole}\n fill=\"none\"\n stroke=\"#000\"\n strokeOpacity=\"0.45\"\n strokeWidth=\"3\"\n />\n )}\n </g>\n\n {donut && (\n <>\n <text className={styles.total} x={centre} y={centre - (label ? 6 : 0)} textAnchor=\"middle\" dominantBaseline=\"middle\">\n {format(hovered !== null ? usable[hovered].value : total)}\n </text>\n {label && (\n <text className={styles.totalLabel} x={centre} y={centre + 14} textAnchor=\"middle\" dominantBaseline=\"middle\">\n {hovered !== null ? usable[hovered].label : label}\n </text>\n )}\n </>\n )}\n </svg>\n\n {legend && (\n <ul className={styles.legend}>\n {usable.map((slice, index) => (\n <li\n key={`${slice.label}-${index}`}\n className={styles.legendItem}\n data-dim={hovered !== null && hovered !== index ? \"\" : undefined}\n >\n <span\n className={styles.swatch}\n style={{ background: slice.color ?? seriesColor(originalIndex(slice)) }}\n aria-hidden=\"true\"\n />\n <span className={styles.legendName}>{slice.label}</span>\n <span className={styles.legendValue}>\n {format(slice.value)}\n <span className={styles.legendPercent}>\n {total > 0 ? Math.round((slice.value / total) * 100) : 0}%\n </span>\n </span>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport { createContext, useContext, useEffect, useRef, type ReactNode } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./Checkbox.module.scss\";\n\ninterface GroupCtx {\n value: string[];\n onValueChange: (v: string[]) => void;\n disabled?: boolean;\n}\nconst Ctx = createContext<GroupCtx | null>(null);\n\n/** The tile, its marks, and the input that actually holds the state. */\nfunction Control({\n checked,\n indeterminate,\n disabled,\n onToggle,\n value,\n ariaLabel,\n}: {\n checked: boolean;\n indeterminate?: boolean;\n disabled?: boolean;\n onToggle: (next: boolean) => void;\n value?: string;\n ariaLabel?: string;\n}) {\n const ref = useRef<HTMLInputElement | null>(null);\n\n // Indeterminate exists only as a DOM property — there is no attribute for\n // it — and setting it is what makes the input announce as \"mixed\".\n useEffect(() => {\n if (ref.current) ref.current.indeterminate = indeterminate === true;\n }, [indeterminate]);\n\n return (\n <>\n <input\n ref={ref}\n type=\"checkbox\"\n className={styles.input}\n aria-label={ariaLabel}\n value={value}\n checked={checked}\n disabled={disabled}\n onChange={(e) => onToggle(e.currentTarget.checked)}\n />\n <span className={styles.box} aria-hidden=\"true\">\n {/* Drawn here rather than with CheckIcon: a stroked path with\n pathLength 1 lets the tick draw itself on, which a filled icon\n cannot do. */}\n <svg className={styles.tick} viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n className={styles.tickPath}\n d=\"M3.5 8.4 6.6 11.5 12.5 4.8\"\n pathLength={1}\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n <span className={styles.dash} />\n </span>\n </>\n );\n}\n\nexport interface CheckboxGroupProps {\n /** The chosen values. Fully controlled; order is the caller's to keep. */\n value: string[];\n /** Called with the new list whenever an item is ticked or unticked. */\n onValueChange: (value: string[]) => void;\n /** Disables every item at once. */\n disabled?: boolean;\n /** Names the set for assistive tech — \"Planet types\", say. Use it whenever\n * the visible heading above the group is not already tied to it. */\n \"aria-label\"?: string;\n /** Merged onto the group wrapper. */\n className?: string;\n /** One or more `CheckboxGroup.Item`. */\n children?: ReactNode;\n}\n\n/**\n * A set of options where any number can be chosen, including none.\n *\n * The group holds the chosen values as an array and reports a new array on\n * every change, so a caller stores one piece of state rather than one boolean\n * per option. For a single yes/no — accepting terms, toggling one setting —\n * use `Checkbox` on its own; for choosing exactly one of several, RadioGroup.\n */\nfunction CheckboxGroupRoot({\n value,\n onValueChange,\n disabled,\n className,\n \"aria-label\": ariaLabel,\n children,\n}: CheckboxGroupProps) {\n return (\n <Ctx.Provider value={{ value, onValueChange, disabled }}>\n {/* group, not radiogroup: these options are independent of each other. */}\n <div role=\"group\" aria-label={ariaLabel} className={cx(styles.root, className)}>\n {children}\n </div>\n </Ctx.Provider>\n );\n}\n\nexport interface CheckboxGroupItemProps {\n /** Added to, or removed from, the group's value when ticked. */\n value: string;\n /** Disables this option only. */\n disabled?: boolean;\n /** The option's label. Part of the click target, not merely beside it. */\n children?: ReactNode;\n}\n\n/**\n * One option in a group.\n *\n * With children it labels itself: a <label> wraps the input, the tile and the\n * children, so the text is part of the click target. Without children it\n * emits a bare span instead, so an OUTER label can own the association —\n * nesting one label inside another is invalid HTML.\n */\nfunction Item({ value, disabled, children }: CheckboxGroupItemProps) {\n const g = useContext(Ctx);\n if (!g) throw new Error(\"CheckboxGroup.Item must be inside a CheckboxGroup\");\n const isDisabled = disabled || g.disabled;\n const checked = g.value.includes(value);\n\n const control = (\n <Control\n checked={checked}\n disabled={isDisabled}\n value={value}\n // Ticking appends, so the order of the value array is the order things\n // were chosen in; unticking keeps the rest as they were.\n onToggle={(next) =>\n g.onValueChange(next ? [...g.value, value] : g.value.filter((v) => v !== value))\n }\n />\n );\n\n if (children === undefined || children === null) {\n return <span className={styles.item}>{control}</span>;\n }\n return (\n <label className={cx(styles.item, styles.selfLabeled)}>\n {control}\n <span className={styles.label}>{children}</span>\n </label>\n );\n}\n\n// Item hangs off the component rather than being a separate export, so the\n// whole API is reachable from the one name a consumer already imported.\nexport const CheckboxGroup = Object.assign(CheckboxGroupRoot, { Item });\n\nexport interface CheckboxProps {\n /** Whether it is ticked. Fully controlled. */\n checked: boolean;\n /** Called with the new state. */\n onCheckedChange: (checked: boolean) => void;\n /** Partly chosen: draws a dash instead of a tick and announces as \"mixed\".\n * For a \"select all\" whose children are only some chosen. The box still\n * reports `checked` when clicked, so decide there what a click means. */\n indeterminate?: boolean;\n /** Disables it. */\n disabled?: boolean;\n /** Names it for assistive tech when there are no children to do so. */\n \"aria-label\"?: string;\n /** Merged onto the label. */\n className?: string;\n /** The label. Part of the click target, not merely beside it. */\n children?: ReactNode;\n}\n\n/**\n * A single yes/no choice: accepting terms, turning one setting on.\n *\n * For a set of options where several can be chosen, wrap `CheckboxGroup`\n * around `CheckboxGroup.Item`s and hold one array instead of a boolean each.\n */\nexport function Checkbox({\n checked,\n onCheckedChange,\n indeterminate,\n disabled,\n className,\n \"aria-label\": ariaLabel,\n children,\n}: CheckboxProps) {\n const control = (\n <Control\n checked={checked}\n indeterminate={indeterminate}\n disabled={disabled}\n ariaLabel={ariaLabel}\n onToggle={onCheckedChange}\n />\n );\n\n if (children === undefined || children === null) {\n return (\n <span className={cx(styles.item, className)}>{control}</span>\n );\n }\n return (\n <label className={cx(styles.item, styles.selfLabeled, className)}>\n {control}\n <span className={styles.label}>{children}</span>\n </label>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport { createContext, useContext, useId, type ReactNode } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./RadioGroup.module.scss\";\n\ninterface GroupCtx {\n value: string;\n onValueChange: (v: string) => void;\n disabled?: boolean;\n name: string;\n}\nconst Ctx = createContext<GroupCtx | null>(null);\n\nexport interface RadioGroupProps {\n /** The selected item's value. Fully controlled. */\n value: string;\n /** Called with the newly selected value. */\n onValueChange: (v: string) => void;\n /** Disables every item at once. */\n disabled?: boolean;\n /** Merged onto the group wrapper. */\n className?: string;\n /** One or more `RadioGroup.Item`. */\n children?: ReactNode;\n}\n\n/**\n * A single-choice control for short lists, where seeing every option at once\n * matters more than saving space. Reach for Select when it does not.\n */\nfunction RadioGroupRoot({ value, onValueChange, disabled, className, children }: RadioGroupProps) {\n const name = useId();\n return (\n <Ctx.Provider value={{ value, onValueChange, disabled, name }}>\n <div role=\"radiogroup\" className={cx(styles.root, className)}>\n {children}\n </div>\n </Ctx.Provider>\n );\n}\n\nexport interface RadioGroupItemProps {\n /** Reported to the group's onValueChange when chosen. */\n value: string;\n /** Disables this option only. */\n disabled?: boolean;\n /** The option's label. Part of the click target, not merely beside it. */\n children?: ReactNode;\n}\n\n/**\n * One option.\n *\n * With children it labels itself: a <label> wraps the input, the orb and the\n * children, so the text is part of the click target. Without children it\n * emits a bare span instead, so an OUTER label can own the association —\n * nesting one label inside another is invalid HTML.\n */\nfunction Item({ value, disabled, children }: RadioGroupItemProps) {\n const g = useContext(Ctx);\n if (!g) throw new Error(\"RadioGroup.Item must be inside a RadioGroup\");\n const isDisabled = disabled || g.disabled;\n const control = (\n <>\n <input\n type=\"radio\"\n className={styles.input}\n name={g.name}\n value={value}\n checked={g.value === value}\n disabled={isDisabled}\n onChange={() => g.onValueChange(value)}\n />\n <span className={cx(styles.orb, \"spRadioOrb\")} aria-hidden=\"true\">\n {/* The orb's own ::before and ::after are the glass and the star\n core, so the ignition ring needs an element of its own. */}\n <span className={styles.burst} />\n </span>\n </>\n );\n if (children === undefined || children === null) {\n return <span className={styles.item}>{control}</span>;\n }\n return (\n <label className={cx(styles.item, styles.selfLabeled)}>\n {control}\n {children}\n </label>\n );\n}\n\n/**\n * Exactly one choice from a set you can see all of at once.\n *\n * Use it where the options matter enough to be read side by side and there are\n * few enough to show — up to about seven. Past that a `Select` keeps the page\n * calm. Where several answers can be true at the same time, that is\n * `CheckboxGroup`.\n *\n * Hold the chosen value and pass `onValueChange`. Each orb ignites when it is\n * chosen, arrow keys move between the options the way a native radio group\n * does, and a label that wraps to two lines keeps its orb beside the first\n * line rather than drifting to the middle.\n *\n * Compose it from `RadioGroup.Item`.\n */\nexport const RadioGroup = Object.assign(RadioGroupRoot, { Item });\n","\"use client\";\nimport type * as React from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./Progress.module.scss\";\n\nexport interface ProgressProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Current progress, clamped between 0 and `max`. */\n value: number;\n /** The value representing complete. */\n max?: number;\n}\n\n/**\n * A determinate bar for work you can measure — use Loader when you cannot.\n *\n * Speaks the same visual language as Slider, because a progress bar and a\n * slider track are the same object: one you watch, one you drag.\n */\nexport function Progress({ value, max = 100, className, style, ...rest }: ProgressProps) {\n const pct = max > 0 ? Math.min(Math.max((value / max) * 100, 0), 100) : 0;\n return (\n <div\n {...rest}\n role=\"progressbar\"\n aria-valuenow={value}\n aria-valuemin={0}\n aria-valuemax={max}\n className={cx(styles.progress, className)}\n style={style}\n >\n {/* Unclassed on purpose: a consumer can target `.progress > div`\n without knowing the hashed module class. */}\n <div style={{ width: `${pct}%`, height: \"100%\" }} />\n </div>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { cx } from \"./propShared\";\nimport { InfoCircledIcon, ExclamationTriangleIcon, CrossCircledIcon } from \"./icons\";\nimport styles from \"./Message.module.scss\";\n\nexport type MessageVariant = \"info\" | \"warning\" | \"alert\";\n\n/** Each variant carries its own glyph, so the message reads at a glance\n * before any of its words do. Overridable per instance via `icon`. */\nconst ICONS: Record<MessageVariant, ReactNode> = {\n info: <InfoCircledIcon />,\n warning: <ExclamationTriangleIcon />,\n alert: <CrossCircledIcon />,\n};\n\n/**\n * How loudly each variant announces itself.\n *\n * `alert` uses role=\"alert\", which is assertive: it interrupts whatever a\n * screen reader is saying. That is right for something gone wrong and wrong\n * for everything else, so info and warning are polite status regions that\n * wait their turn.\n */\nconst ROLES: Record<MessageVariant, { role: string; live?: \"polite\" }> = {\n info: { role: \"status\", live: \"polite\" },\n warning: { role: \"status\", live: \"polite\" },\n alert: { role: \"alert\" },\n};\n\nexport interface MessageProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Which message this is. `info` states something, `warning` flags a risk\n * worth acting on, `alert` reports something already wrong. Default\n * `info`. */\n variant?: MessageVariant;\n /** An optional bold line above the body. Omit for a single-line message —\n * a title that merely restates the body is noise.\n *\n * This shadows the HTML `title` attribute, which took a string and showed\n * a browser tooltip. A tooltip on a banner nobody hovers was never the\n * useful reading of the name. */\n title?: ReactNode;\n /** Replaces the variant's own glyph. Pass `null` for no icon at all. */\n icon?: ReactNode;\n /** The message. */\n children?: ReactNode;\n}\n\n/**\n * A banner that tells the reader something about the state of the page — a\n * risk, a result, a failure.\n *\n * The three variants do not merely change hue. `info` is lit like the rest of\n * the system, cool and calm; `warning` warms the rim to amber; `alert` uses\n * the ember treatment, the same warm limb the destructive Button wears. Each\n * carries its own glyph so the kind of message reads before the words do.\n *\n * For a decision the reader must make, reach for `AlertDialog` instead — a\n * message states, it does not ask.\n */\nexport const Message = forwardRef<HTMLDivElement, MessageProps>(function Message(\n { variant = \"info\", title, icon, className, children, ...rest },\n ref,\n) {\n const glyph = icon === undefined ? ICONS[variant] : icon;\n const { role, live } = ROLES[variant];\n\n return (\n <div\n {...rest}\n ref={ref}\n role={role}\n aria-live={live}\n className={cx(styles.message, styles[variant], className)}\n >\n {glyph != null && (\n <span className={styles.icon} aria-hidden=\"true\">\n {glyph}\n </span>\n )}\n <div className={styles.body}>\n {title != null && <p className={styles.title}>{title}</p>}\n {children != null && <div className={styles.text}>{children}</div>}\n </div>\n </div>\n );\n});\n","// src/components/ui/Dialog.tsx\n// Compound Dialog matching the Radix JSX shape on a native <dialog>:\n// top-layer stacking (nested/stacked dialogs work), built-in focus trap and\n// focus return, Esc via the `cancel` event. Both controlled (open/\n// onOpenChange) and Trigger-driven uncontrolled sites are supported — the\n// inventory has both. Esc handoff with the in-house Select: a capture-phase\n// keydown checks for an open listbox inside the dialog and flags the next\n// `cancel` to be swallowed, so one Esc closes the Select, the next closes\n// the dialog (matching the Radix-era behavior sites were built against).\n\"use client\";\nimport type * as React from \"react\";\nimport { XIcon } from \"./icons\";\nimport {\n cloneElement, createContext, isValidElement, useContext, useEffect,\n useId, useLayoutEffect, useRef, useState, type ReactNode,\n} from \"react\";\nimport { cx } from \"./propShared\";\nimport { Heading, type HeadingProps } from \"./Heading\";\nimport { Text, type TextProps } from \"./Text\";\nimport styles from \"./Dialog.module.scss\";\n\n// Body scroll-lock reference count, shared across every mounted Content\n// instance (module scope, not per-instance state) — Dialog and AlertDialog\n// stack on top of one another, and per-instance prev-capture couldn't tell\n// \"I'm the last one closing\" from \"another instance is still open\" when\n// unmounts land out of open-order. A plain 0→1 / 1→0 edge count is\n// order-proof: overflow is locked exactly while count > 0, regardless of\n// which instance opened or closed first.\nlet lockCount = 0;\n\nexport interface DialogCtx {\n open: boolean;\n setOpen: (o: boolean) => void;\n titleId: string;\n descId: string;\n /** alert dialogs: no backdrop light-dismiss */\n alert?: boolean;\n /** whether a Description is currently mounted (drives aria-describedby) */\n hasDesc: boolean;\n setHasDesc: (v: boolean) => void;\n}\nconst Ctx = createContext<DialogCtx | null>(null);\nexport const useDialog = () => {\n const ctx = useContext(Ctx);\n if (!ctx) throw new Error(\"Dialog parts must be inside a Dialog\");\n return ctx;\n};\n\nexport interface DialogProps {\n /** Controls the dialog. Omit both this and onOpenChange to let the dialog\n * manage its own state. */\n open?: boolean;\n /** Called whenever the dialog opens or closes, including via Escape or a\n * backdrop click. */\n onOpenChange?: (o: boolean) => void;\n /** A `Trigger` and a `Content`, in any arrangement — this renders\n * nothing itself, so they can sit anywhere beneath it. */\n children?: ReactNode;\n}\n\n/** Shared by Dialog and AlertDialog; only the alert flag differs. */\nexport function makeRoot(alert: boolean) {\n return function DialogRoot({ open, onOpenChange, children }: DialogProps) {\n const [internal, setInternal] = useState(false);\n const isControlled = open !== undefined;\n const actual = isControlled ? open : internal;\n const setOpen = (o: boolean) => {\n if (!isControlled) setInternal(o);\n onOpenChange?.(o);\n };\n const titleId = useId();\n const descId = useId();\n const [hasDesc, setHasDesc] = useState(false);\n return (\n <Ctx.Provider value={{ open: actual, setOpen, titleId, descId, alert, hasDesc, setHasDesc }}>\n {children}\n </Ctx.Provider>\n );\n };\n}\n/**\n * Owns a dialog's open state. Works controlled via `open`/`onOpenChange`, or\n * uncontrolled if you pass neither.\n *\n * Renders nothing itself — it only provides context, so Trigger and Content\n * can sit anywhere beneath it in the tree.\n */\nconst Root = makeRoot(false);\n\ntype Clickable = React.ReactElement<{ onClick?: (e: React.MouseEvent) => void }>;\nconst chainOpen = (child: ReactNode, fn: () => void): ReactNode => {\n if (!isValidElement(child)) return child;\n const c = child as Clickable;\n return cloneElement(c, {\n onClick: (e: React.MouseEvent) => { c.props.onClick?.(e); fn(); },\n });\n};\n\n/**\n * Opens the dialog. Chains onto its child's existing click handler rather\n * than replacing it, and renders no element of its own — so the child stays\n * whatever it already was, button or otherwise.\n */\nexport function Trigger({\n children,\n}: {\n /** The control that opens the dialog. Its own onClick still fires. */\n children?: ReactNode;\n}) {\n const d = useDialog();\n return <>{chainOpen(children, () => d.setOpen(true))}</>;\n}\n\n/**\n * Closes the dialog. Same shape as Trigger: wraps its child, adds a close on\n * click, and adds no markup.\n */\nexport function Close({\n children,\n}: {\n /** The control that closes the dialog. Its own onClick still fires. */\n children?: ReactNode;\n}) {\n const d = useDialog();\n return <>{chainOpen(children, () => d.setOpen(false))}</>;\n}\n\nexport interface ContentProps extends React.HTMLAttributes<HTMLDialogElement> {\n /** Padding and radius step. 4 is roomier, for dialogs carrying a form. */\n size?: \"3\" | \"4\";\n /** Caps the dialog's width, e.g. \"480px\". Without it the dialog uses its\n * own default and grows with its content. */\n maxWidth?: string;\n /** Dialog contents. Include a Title — it is the accessible name. */\n children?: ReactNode;\n}\n\n/**\n * The dialog surface. Built on the native `<dialog>` element, so the browser\n * supplies the top layer, focus trapping and Escape handling rather than the\n * library reimplementing them.\n *\n * Dismissible by Escape or a click on the backdrop; AlertDialog's Content\n * deliberately is not.\n */\nexport function Content({ size = \"3\", maxWidth, className, style, children, ...rest }: ContentProps) {\n const d = useDialog();\n const ref = useRef<HTMLDialogElement | null>(null);\n const swallowCancel = useRef(false);\n // Backdrop dismissal must require BOTH the mousedown/pointerdown AND the\n // click to land on the backdrop (the <dialog> element itself, not the\n // inner content wrapper) — otherwise a text-selection drag that starts in\n // the content and ends up released over the backdrop would close the\n // dialog on mouseup even though the gesture began inside it.\n const pointerDownOnBackdrop = useRef(false);\n\n // Imperative <dialog> API follows the declarative open prop (handles the\n // delayed first open of AccountsIntroModal's 900ms timer too).\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n if (d.open && !el.open) el.showModal();\n else if (!d.open && el.open) el.close();\n }, [d.open]);\n\n // Body scroll lock while open (Radix did this; panels behind rely on it).\n // Module-level counter (see `lockCount` above) so stacked dialogs compose:\n // only the 0→1 transition locks, only the 1→0 transition unlocks.\n useEffect(() => {\n if (!d.open) return;\n lockCount += 1;\n if (lockCount === 1) document.body.style.overflow = \"hidden\";\n return () => {\n lockCount -= 1;\n if (lockCount === 0) document.body.style.overflow = \"\";\n };\n }, [d.open]);\n\n return (\n <dialog\n {...rest}\n ref={ref}\n role={d.alert ? \"alertdialog\" : undefined}\n aria-labelledby={d.titleId}\n aria-describedby={d.hasDesc ? d.descId : undefined}\n className={cx(styles.dialog, \"spDialog\", size === \"4\" && styles.size4, className)}\n style={{ ...(maxWidth ? { maxWidth } : null), ...style }}\n onKeyDownCapture={(e) => {\n if (e.key !== \"Escape\") return;\n // A nested dialog is open inside this one (e.g. an AlertDialog\n // launched from this dialog's content) — that inner dialog owns\n // this Esc; don't let the outer one arm its own swallow logic on\n // an event that's about to close a dialog it isn't itself.\n if (ref.current?.querySelector(\"dialog[open]\")) return;\n // Esc while an in-house Select's listbox is open inside this dialog:\n // the Select closes itself; swallow the dialog's own cancel.\n if (ref.current?.querySelector('[role=\"listbox\"]:not([hidden])')) {\n swallowCancel.current = true;\n }\n }}\n onCancel={(e) => {\n e.preventDefault(); // we route ALL closes through React state\n if (swallowCancel.current) { swallowCancel.current = false; return; }\n d.setOpen(false);\n }}\n onClose={() => {\n // Belt-and-suspenders: any UA-initiated close we didn't route\n // through onCancel (a non-cancelable close request, or a future\n // method=\"dialog\" form submission inside the content) still fires\n // `close`. Resync React state so `open` doesn't get stranded true\n // while the native element is actually closed.\n if (d.open) d.setOpen(false);\n }}\n onPointerDown={(e) => {\n pointerDownOnBackdrop.current = e.target === ref.current;\n }}\n onClick={(e) => {\n // Backdrop click = clicking the <dialog> element itself (the inner\n // wrapper covers the content area). Alert dialogs don't light-dismiss.\n // Require the pointerdown that started this click to have also\n // landed on the backdrop, so a text-selection drag from the content\n // out to the backdrop doesn't close the dialog on release.\n if (!d.alert && e.target === ref.current && pointerDownOnBackdrop.current) d.setOpen(false);\n }}\n >\n <div className={styles.inner}>\n {/* Every dialog gets the same dismiss affordance in the same place.\n Alert dialogs are excluded on purpose: they ask a question that\n wants an explicit answer, and a corner X is an ambiguous one. */}\n {!d.alert && (\n <button\n type=\"button\"\n className={styles.closeX}\n aria-label=\"Close\"\n onClick={() => d.setOpen(false)}\n >\n <XIcon width={16} height={16} />\n </button>\n )}\n {children}\n </div>\n </dialog>\n );\n}\n\n/**\n * The dialog's accessible name. Wire one up for every dialog — it is what a\n * screen reader announces when the dialog opens.\n */\nexport function Title({ className, ...rest }: HeadingProps) {\n const d = useDialog();\n return <Heading as=\"h2\" size=\"5\" {...rest} id={d.titleId} className={cx(styles.title, className)} />;\n}\n\n/**\n * Supporting copy beneath the title, registered as the dialog's accessible\n * description. Optional, and only announced when present.\n */\nexport function Description(props: TextProps) {\n const d = useDialog();\n // aria-describedby on Content is conditional on a Description actually\n // being mounted (some dialogs render none), so Content can't just point\n // at descId unconditionally. Register/unregister via a layout effect —\n // runs before paint, and Description mounts synchronously with the\n // dialog's content, so there's no visible flash of a missing attribute.\n // Depend on setHasDesc alone (a stable useState setter), not the whole\n // `d` context object — that object is a fresh literal every Root render,\n // so depending on it would re-fire this effect (and its cleanup) on\n // every render instead of just mount/unmount.\n const { setHasDesc } = d;\n useLayoutEffect(() => {\n setHasDesc(true);\n return () => setHasDesc(false);\n }, [setHasDesc]);\n return <Text as=\"p\" {...props} id={d.descId} />;\n}\n\n/**\n * A modal window over the page, for a task that has to finish or be abandoned\n * before anything else happens.\n *\n * It rides the platform's own `<dialog>`, so the backdrop, the top layer, the\n * Escape key and the focus trap are the browser's rather than an\n * approximation of them. Opening moves focus inside; closing returns it to\n * whatever opened it.\n *\n * For a decision with consequences — deleting, discarding, overwriting —\n * reach for `AlertDialog`, which refuses to close by a click outside, so a\n * misplaced click cannot answer the question for the reader.\n *\n * Compose it from the parts hanging off this name: `Dialog.Trigger`,\n * `Dialog.Content`, `Dialog.Title`, `Dialog.Description` and `Dialog.Close`.\n */\nexport const Dialog = Object.assign(Root, {\n Trigger,\n Close,\n Content,\n Title,\n Description,\n});\n","// The same native-<dialog> engine as Dialog, with alertdialog semantics:\n// role=\"alertdialog\", and NO backdrop light-dismiss — an alert is a decision,\n// so it does not go away because you clicked beside it. Render Cancel before\n// Action so showModal()'s initial focus lands on the safe choice.\n\"use client\";\nimport {\n makeRoot, Trigger, Close,\n Content, Title, Description,\n type DialogProps,\n} from \"./Dialog\";\n\nexport type { DialogProps as AlertDialogProps };\n\n// Cancel and Action are the same component under two names. The name is the\n// point: it says which one is destructive at the call site, and it makes the\n// ordering rule above readable rather than positional trivia. Close chains\n// the child's own onClick before closing, so an Action's handler runs first.\nconst Cancel = Close;\nconst Action = Close;\n\n/**\n * A modal that interrupts to confirm something consequential.\n *\n * Unlike a Dialog it has no backdrop dismissal, because dismissing an alert\n * by missing it is not a decision. Put `Cancel` before `Action` so the safe\n * choice takes focus when it opens.\n */\nexport const AlertDialog = Object.assign(makeRoot(true), {\n Trigger,\n Content,\n Title,\n Description,\n Cancel,\n Action,\n});\n","// src/components/ui/DropdownMenu.tsx\n// role=\"menu\" on a popover=\"auto\" div: top-layer + click-outside dismissal\n// come from the platform. Anchor positioning is manual (align=\"end\" is the\n// only inventoried mode). Roving tabindex arrows per the spec.\n\"use client\";\nimport type * as React from \"react\";\nimport {\n createContext, createElement, isValidElement, useCallback, useContext,\n useEffect, useId, useLayoutEffect, useRef, useState, type ReactNode,\n} from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./DropdownMenu.module.scss\";\nimport { Button, type ButtonProps } from \"./Button\";\n\ninterface MenuCtx {\n open: boolean;\n setOpen: (o: boolean) => void;\n menuId: string;\n}\nconst Ctx = createContext<MenuCtx | null>(null);\nconst useMenu = () => {\n const ctx = useContext(Ctx);\n if (!ctx) throw new Error(\"DropdownMenu parts must be inside a DropdownMenu\");\n return ctx;\n};\n\n\nexport interface DropdownMenuProps extends Omit<ButtonProps, \"children\"> {\n /** The trigger's content. The trigger is always a Button, so this is what\n * goes inside it — text, or an icon with `iconOnly`. */\n label: ReactNode;\n /** Which edge of the trigger the menu lines up with. Use `end` when the\n * trigger sits near the right edge and the menu would overflow. */\n align?: \"start\" | \"end\";\n /** `DropdownMenu.Item`, `.Separator` and `.Label`, in any order. */\n children?: ReactNode;\n}\n\n/**\n * A menu of actions hung off a button.\n *\n * The trigger is built in and is always a Button — a dropdown whose trigger\n * looked like anything else was never a shape worth supporting, and making it\n * arbitrary cost a `cloneElement` that had to graft aria wiring and a click\n * handler onto someone else's element.\n *\n * The menu rides the platform's top layer via `popover`, so click-outside\n * dismissal and stacking come from the browser rather than an approximation.\n * Arrows move between items, Escape closes and returns focus to the trigger.\n */\nfunction DropdownMenuRoot({ label, align = \"start\", children, ...buttonProps }: DropdownMenuProps) {\n const [open, setOpenState] = useState(false);\n const menuId = useId();\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const menuRef = useRef<HTMLDivElement | null>(null);\n // What a pointer press on the trigger meant, decided at pointerdown — before\n // the platform has had a chance to light-dismiss. See the trigger below.\n const pressIntent = useRef<boolean | null>(null);\n // The latest open state, including one requested this tick but not yet\n // rendered. The trigger's click and the menu's toggle can report the same\n // close in one gesture; this is what makes the second report a no-op.\n const openNow = useRef(open);\n openNow.current = open;\n\n const setOpen = useCallback((next: boolean) => {\n if (openNow.current === next) return;\n openNow.current = next;\n setOpenState(next);\n }, []);\n const [pos, setPos] = useState<{ top: number; left: number | \"auto\"; right: number | \"auto\" } | null>(null);\n\n // useLayoutEffect (not useEffect) so the position is measured and applied\n // synchronously before paint — matches Select's trigger measurement and\n // avoids a one-frame flash at the wrong coordinates.\n useLayoutEffect(() => {\n const el = menuRef.current;\n if (!el) return;\n if (open) {\n // Position under the trigger before entering the top layer.\n const trigger = triggerRef.current;\n if (trigger) {\n const r = trigger.getBoundingClientRect();\n const left = align === \"end\" ? \"auto\" : r.left;\n const right = align === \"end\" ? window.innerWidth - r.right : \"auto\";\n setPos({ top: r.bottom + 6, left, right });\n }\n el.showPopover();\n // Focus the first item for keyboard users.\n el.querySelector<HTMLElement>('[role=\"menuitem\"]')?.focus();\n } else if (el.matches(\":popover-open\")) {\n el.hidePopover();\n }\n }, [open, align]);\n\n // A resize invalidates the anchored position (measured once, at open) —\n // rather than re-measuring on every tick, close the menu, as a light\n // dismiss would.\n useEffect(() => {\n if (!open) return;\n const onResize = () => setOpen(false);\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, [open]);\n\n return (\n <Ctx.Provider value={{ open, setOpen, menuId }}>\n <Button\n {...buttonProps}\n ref={triggerRef}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-controls={menuId}\n onPointerDown={(e) => {\n buttonProps.onPointerDown?.(e);\n // Decide here, not on click. Pressing the trigger while the menu is\n // open is an outside press to the platform, which closes the menu\n // during pointerdown — so by click the menu already reads as shut\n // and a plain toggle would reopen it. The toggle event cannot\n // settle it either: it fires after click. What the reader meant is\n // knowable only at the moment they pressed.\n //\n // This replaces a 300ms timer that ignored trigger clicks after any\n // close. Escape armed it too, so a click shortly after Escape was\n // silently swallowed.\n pressIntent.current = !openNow.current;\n }}\n onKeyDown={(e) => {\n buttonProps.onKeyDown?.(e);\n // A press dragged off the button never clicks, which would leave its\n // intent behind to hijack the next Enter or Space. Keys decide fresh.\n if (e.key === \"Enter\" || e.key === \" \") pressIntent.current = null;\n }}\n onClick={(e) => {\n buttonProps.onClick?.(e);\n // Keyboard activation has no pointerdown, so it falls back to a\n // straight toggle — Enter and Space never light-dismiss.\n const next = pressIntent.current ?? !openNow.current;\n pressIntent.current = null;\n setOpen(next);\n }}\n >\n {label}\n </Button>\n\n <div\n ref={menuRef}\n id={menuId}\n role=\"menu\"\n popover=\"auto\"\n className={styles.menu}\n style={\n pos\n ? {\n top: pos.top,\n left: pos.left === \"auto\" ? \"auto\" : pos.left,\n right: pos.right === \"auto\" ? \"auto\" : pos.right,\n }\n : undefined\n }\n onToggle={(e: React.SyntheticEvent<HTMLDivElement>) => {\n // A platform close — a press elsewhere or Escape — synced into\n // state. setOpen ignores a close already recorded, such as one an\n // Item or the trigger asked for.\n if ((e.nativeEvent as ToggleEvent).newState === \"closed\") setOpen(false);\n }}\n onKeyDown={(e) => {\n const items = Array.from(\n menuRef.current?.querySelectorAll<HTMLElement>('[role=\"menuitem\"]') ?? []\n );\n const idx = items.indexOf(document.activeElement as HTMLElement);\n if (e.key === \"ArrowDown\") { e.preventDefault(); items[Math.min(idx + 1, items.length - 1)]?.focus(); }\n else if (e.key === \"ArrowUp\") { e.preventDefault(); items[Math.max(idx - 1, 0)]?.focus(); }\n else if (e.key === \"Home\") { e.preventDefault(); items[0]?.focus(); }\n else if (e.key === \"End\") { e.preventDefault(); items[items.length - 1]?.focus(); }\n else if (e.key === \"Escape\") { setOpen(false); triggerRef.current?.focus(); }\n }}\n >\n {children}\n </div>\n </Ctx.Provider>\n );\n}\n\n/**\n * A non-interactive heading for a group of items. Skipped by arrow-key\n * navigation, since there is nothing to activate.\n */\nfunction Label({\n children,\n}: {\n /** Heading text for the group beneath it. Not focusable. */\n children?: ReactNode;\n}) {\n return <div className={styles.label}>{children}</div>;\n}\n\nexport interface DropdownMenuItemProps {\n /** Render the child element instead of the default item — for a link that\n * should stay an anchor rather than becoming a button. */\n asChild?: boolean;\n /** Marks a destructive action, so it reads differently before it is\n * chosen rather than after. */\n color?: \"danger\";\n /** Runs when the item is chosen; the menu closes either way. */\n onSelect?: () => void | Promise<void>;\n /** The item's label. */\n children?: ReactNode;\n}\n\n/**\n * One menu action. `onSelect` fires and the menu closes.\n *\n * Pass `color=\"danger\"` for a destructive action so it reads differently from\n * its neighbours before it is chosen, not after.\n */\nfunction Item({ asChild, color, onSelect, children }: DropdownMenuItemProps) {\n const m = useMenu();\n const cls = cx(styles.item, color === \"danger\" && styles.danger);\n const activate = () => {\n m.setOpen(false);\n void onSelect?.();\n };\n if (asChild && isValidElement(children)) {\n const child = children as React.ReactElement<Record<string, unknown>>;\n // Rebuild (rather than cloneElement) so role/tabIndex land BEFORE the\n // child's own attributes (e.g. href) in the emitted markup — cloneElement\n // always keeps pre-existing keys in their original position. Also drop\n // the child's own role/tabIndex (if any) from restProps entirely — a\n // spread landing after the forced menuitem/-1 values would otherwise\n // silently win and undo the forced semantics.\n const {\n className: childClassName, onClick: childOnClick, children: childChildren,\n role: childRole, tabIndex: childTabIndex, ...restProps\n } = child.props;\n // Discarded — pulled out of restProps only so the forced role/tabIndex\n // below can't be silently overwritten by the child's own values.\n void childRole;\n void childTabIndex;\n const originalRef = (child as unknown as { ref?: React.Ref<unknown> }).ref;\n return createElement(\n child.type as React.ElementType,\n {\n key: child.key,\n ref: originalRef,\n role: \"menuitem\",\n tabIndex: -1,\n ...restProps,\n className: cx(cls, childClassName as string | undefined),\n onClick: (e: React.MouseEvent) => {\n (childOnClick as ((e: React.MouseEvent) => void) | undefined)?.(e);\n m.setOpen(false); // real navigation proceeds; menu closes\n },\n },\n childChildren as ReactNode,\n );\n }\n return (\n <button type=\"button\" role=\"menuitem\" tabIndex={-1} className={cls} onClick={activate}>\n {children}\n </button>\n );\n}\n\n/**\n * A rule between groups of items — for separating a destructive action from\n * routine ones, so the two are not adjacent to a moving cursor.\n */\nfunction Separator() {\n return <div role=\"separator\" className={styles.separator} />;\n}\n\n/**\n * A button that opens a list of actions.\n *\n * Actions, not choices: every item does something when picked, and nothing in\n * the menu holds a value. For choosing one of a set of values, that is\n * `Select`, which looks similar and means something entirely different to a\n * screen reader.\n *\n * Arrow keys move through the items, Home and End jump to the ends, Escape\n * closes and returns focus to the button, and typing a letter jumps to the\n * next item starting with it. The panel uses the browser's popover layer, so\n * it stacks above the page without a z-index to maintain.\n *\n * Compose it from `DropdownMenu.Item`, `DropdownMenu.Label` and\n * `DropdownMenu.Separator`.\n */\nexport const DropdownMenu = Object.assign(DropdownMenuRoot, { Item, Separator, Label });\n","// ARIA tabs. Inactive Content unmounts, matching Radix's default.\n\"use client\";\nimport type * as React from \"react\";\nimport { createContext, useContext, useId, type ReactNode } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./Tabs.module.scss\";\n\ninterface TabsCtx {\n value: string;\n onValueChange: (v: string) => void;\n /** useId()-derived base, shared by Trigger/Content so a trigger's\n * aria-controls always matches its panel's id (and vice versa via\n * aria-labelledby) without either side guessing the other's id. */\n id: string;\n}\nconst Ctx = createContext<TabsCtx | null>(null);\nconst useTabs = () => {\n const ctx = useContext(Ctx);\n if (!ctx) throw new Error(\"Tabs parts must be inside a Tabs\");\n return ctx;\n};\n\nexport interface TabsProps {\n /** The selected tab's value. Fully controlled — there is no default. */\n value: string;\n /** Called with the newly selected tab's value. */\n onValueChange: (v: string) => void;\n /** Merged onto the wrapper div, which is otherwise unstyled. */\n className?: string;\n /** A `Tabs.List` and the `Tabs.Content`s it switches between. */\n children?: ReactNode;\n}\n\n/**\n * Wraps a tab set and owns which tab is showing. Fully controlled — pass\n * `value` and `onValueChange`; there is no uncontrolled mode.\n *\n * Renders a plain div, so it imposes no layout of its own. It also mints the\n * id that pairs each Trigger with its Content, which is why every part has to\n * sit inside it rather than being usable on its own.\n */\nfunction TabsRoot({ value, onValueChange, className, children }: TabsProps) {\n const id = useId();\n return (\n <Ctx.Provider value={{ value, onValueChange, id }}>\n <div className={className}>{children}</div>\n </Ctx.Provider>\n );\n}\n\n/**\n * The row of triggers, and the keyboard model for the set: arrow keys move\n * between tabs, Home and End jump to the ends, each moving focus and\n * selection together as the ARIA tabs pattern expects.\n *\n * Bottom-aligns its children, so an active tab that grows taller rises above\n * its neighbours instead of pushing the row down — the folder-tab effect.\n */\nfunction List({\n children,\n}: {\n /** The Triggers. Their order is the tab order. */\n children?: ReactNode;\n}) {\n return (\n <div\n role=\"tablist\"\n className={cx(styles.list, \"spTabsList\")}\n onKeyDown={(e) => {\n const tabs = Array.from(\n (e.currentTarget as HTMLElement).querySelectorAll<HTMLElement>('[role=\"tab\"]')\n );\n const idx = tabs.indexOf(document.activeElement as HTMLElement);\n if (idx === -1) return;\n if (e.key === \"ArrowRight\") { e.preventDefault(); const t = tabs[(idx + 1) % tabs.length]; t.focus(); t.click(); }\n else if (e.key === \"ArrowLeft\") { e.preventDefault(); const t = tabs[(idx - 1 + tabs.length) % tabs.length]; t.focus(); t.click(); }\n else if (e.key === \"Home\") { e.preventDefault(); const t = tabs[0]; t.focus(); t.click(); }\n else if (e.key === \"End\") { e.preventDefault(); const t = tabs[tabs.length - 1]; t.focus(); t.click(); }\n }}\n >\n {children}\n </div>\n );\n}\n\n/**\n * One tab. Selects its `value` on click and carries the ARIA wiring that ties\n * it to the matching Content.\n *\n * Emits `data-state=\"active\" | \"inactive\"`, which is the hook the active\n * styling keys off — useful if you are restyling tabs from outside.\n */\nfunction Trigger({ value, className, children, ...rest }: {\n /** Selects this value. Must match the Content it reveals. */\n value: string;\n /** Merged with the tab's own classes rather than replacing them. */\n className?: string;\n /** The tab's label. */\n children?: ReactNode;\n} & React.ButtonHTMLAttributes<HTMLButtonElement>) {\n const t = useTabs();\n const active = t.value === value;\n return (\n <button\n {...rest}\n type=\"button\"\n role=\"tab\"\n id={`${t.id}-tab-${value}`}\n aria-selected={active}\n aria-controls={`${t.id}-panel-${value}`}\n tabIndex={active ? 0 : -1}\n data-state={active ? \"active\" : \"inactive\"}\n className={cx(styles.trigger, \"spTabsTrigger\", className)}\n onClick={() => t.onValueChange(value)}\n >\n {children}\n </button>\n );\n}\n\n/**\n * The panel for one tab. Renders only while its `value` is the selected one —\n * inactive panels unmount rather than hide, so their contents do not run,\n * hold state, or appear to a screen reader.\n *\n * Carries no styling: the surface a tab set seats onto is the consumer's, and\n * should match `--sp-tabs-surface-color` so the active tab connects to it.\n */\nfunction Content({\n value,\n children,\n}: {\n /** Shown while this matches the Root's value. Must match a Trigger. */\n value: string;\n /** Panel contents. Unmounted while another tab is selected. */\n children?: ReactNode;\n}) {\n const t = useTabs();\n if (t.value !== value) return null;\n return (\n <div role=\"tabpanel\" id={`${t.id}-panel-${value}`} aria-labelledby={`${t.id}-tab-${value}`}>\n {children}\n </div>\n );\n}\n\n/**\n * Several panels sharing one piece of the page, one visible at a time.\n *\n * Right for views of the same subject that a reader moves between and\n * compares — overview, history, settings for one record. Wrong for steps in a\n * sequence, where the reader needs to know how far along they are, and wrong\n * for content that should be findable by search or linkable on its own: a\n * hidden panel is invisible to both.\n *\n * Arrow keys move between the tabs, Home and End jump to the ends, and only\n * the selected tab is in the tab order, so one press of Tab leaves the strip\n * for the panel instead of walking every tab in it.\n *\n * Compose it from `Tabs.List`, `Tabs.Trigger` and `Tabs.Content`.\n */\nexport const Tabs = Object.assign(TabsRoot, { List, Trigger, Content });\n","\"use client\";\nimport type * as React from \"react\";\nimport {\n useCallback, useEffect, useId, useLayoutEffect, useRef, useState, type ReactNode,\n} from \"react\";\nimport { cx } from \"./propShared\";\nimport { Button, type ButtonProps } from \"./Button\";\nimport styles from \"./Popover.module.scss\";\nimport { showMeasured } from \"../internal/showMeasured\";\nimport ctl from \"../styles/spaceControls\";\n\nconst OFFSET = 8;\nconst EDGE_PADDING = 8;\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\nexport interface PopoverProps extends Omit<ButtonProps, \"children\"> {\n /** What the trigger shows. The trigger is always a Button, so this is its\n * content — text, or an icon with `iconOnly` and an `aria-label`. */\n label: ReactNode;\n /** The panel's contents. Anything: a form, a filter set, a prompt. For a\n * list of actions reach for DropdownMenu; for a line of text, Tooltip. */\n children?: ReactNode;\n /** Controls the panel. Omit both this and `onOpenChange` to let the popover\n * manage itself. */\n open?: boolean;\n /** Called whenever the panel opens or closes, including by Escape or a\n * click elsewhere. */\n onOpenChange?: (open: boolean) => void;\n /** Open on first render when uncontrolled. Focus is left where it is, so a\n * popover shown on arrival never steals the page's focus. */\n defaultOpen?: boolean;\n /** Which side of the trigger the panel prefers. It flips to the other side\n * when there is no room. Default `bottom`. */\n side?: \"top\" | \"bottom\";\n /** Which edge of the trigger the panel lines up with. Use `end` for a\n * trigger near the right of the viewport. Default `start`. */\n align?: \"start\" | \"center\" | \"end\";\n /** Merged onto the panel. */\n panelClassName?: string;\n}\n\n/**\n * A button that opens a floating panel of anything — a small form, a set of\n * filters, a prompt — without leaving the page.\n *\n * It rides the browser's own popover layer, so the panel stacks above\n * everything without a z-index arms race and closes on Escape or a click\n * elsewhere by the platform's rules rather than an approximation of them. It\n * sits next to its trigger, flips above it when there is no room below, and\n * stays attached to it if the page scrolls or the layout around it shifts.\n *\n * Opening moves focus into the panel so a keyboard user lands on its first\n * control; closing with Escape hands focus back to the trigger. The panel is\n * labelled by the trigger, so it announces as what the button said it was.\n */\nexport function Popover({\n label,\n children,\n open: openProp,\n onOpenChange,\n defaultOpen = false,\n side = \"bottom\",\n align = \"start\",\n panelClassName,\n onClick,\n ...buttonProps\n}: PopoverProps) {\n const [internal, setInternal] = useState(defaultOpen);\n const controlled = openProp !== undefined;\n const open = controlled ? openProp : internal;\n\n const triggerId = useId();\n const panelId = useId();\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const panelRef = useRef<HTMLDivElement | null>(null);\n const [pos, setPos] = useState<{ top: number; left: number; placed: \"top\" | \"bottom\" } | null>(null);\n\n // Whether the next open came from the reader, as opposed to defaultOpen on\n // mount. Only a reader's open moves focus.\n const openedByReader = useRef(false);\n // Set by Escape inside the panel, so the close that follows returns focus.\n const closingByEscape = useRef(false);\n // What a pointer press on the trigger meant, decided at pointerdown — before\n // the platform has had a chance to light-dismiss. See the trigger below.\n const pressIntent = useRef<boolean | null>(null);\n // The latest open state, including one requested this tick but not yet\n // rendered. Both the trigger's click and the panel's toggle can report the\n // same close in one gesture; this is what stops onOpenChange hearing twice.\n const openNow = useRef(open);\n openNow.current = open;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (openNow.current === next) return;\n openNow.current = next;\n if (!controlled) setInternal(next);\n onOpenChange?.(next);\n },\n [controlled, onOpenChange],\n );\n\n const place = useCallback(() => {\n const trigger = triggerRef.current;\n const panel = panelRef.current;\n if (!trigger || !panel) return;\n const r = trigger.getBoundingClientRect();\n const w = panel.offsetWidth;\n const h = panel.offsetHeight;\n\n const below = r.bottom + OFFSET;\n const above = r.top - h - OFFSET;\n const fitsBelow = below + h <= window.innerHeight - EDGE_PADDING;\n const fitsAbove = above >= EDGE_PADDING;\n const top = side === \"bottom\"\n ? (fitsBelow || !fitsAbove ? below : above)\n : (fitsAbove || !fitsBelow ? above : below);\n // Where it actually landed after any flip, so the reveal can travel away\n // from the trigger rather than towards it. Written to the element as well\n // as to state: the reveal reads it before React has re-rendered.\n const placed = top === below ? \"bottom\" : \"top\";\n panel.dataset.side = placed;\n\n const wanted =\n align === \"start\" ? r.left : align === \"end\" ? r.right - w : r.left + r.width / 2 - w / 2;\n const left = Math.min(\n Math.max(wanted, EDGE_PADDING),\n Math.max(window.innerWidth - w - EDGE_PADDING, EDGE_PADDING),\n );\n setPos((prev) =>\n prev && prev.top === top && prev.left === left && prev.placed === placed\n ? prev\n : { top, left, placed },\n );\n }, [side, align]);\n\n // Show before measuring: while the panel is display:none its size reads 0\n // and every clamp above would be computed against nothing. Layout effect,\n // so the corrected position lands before the first frame is painted.\n useLayoutEffect(() => {\n const panel = panelRef.current;\n if (!panel) return;\n if (open) {\n // Placed before it is shown, so the reveal travels away from the trigger\n // on whichever side it lands.\n showMeasured(panel, place);\n place();\n if (openedByReader.current) {\n openedByReader.current = false;\n const first = panel.querySelector<HTMLElement>(FOCUSABLE);\n (first ?? panel).focus({ preventScroll: true });\n }\n } else if (panel.matches(\":popover-open\")) {\n panel.hidePopover();\n }\n }, [open, place]);\n\n // Follow the trigger for as long as the panel is open. Scroll and resize\n // listeners were not enough: anything that moves the trigger without\n // scrolling — an image loading above it, a font swapping in, a sibling\n // growing — left the panel where it opened, detached from its button and\n // sometimes sitting on top of it. So each frame compares where the trigger\n // is now with where it was, and re-places only on a change. One layout read\n // a frame, and only while open.\n useEffect(() => {\n if (!open) return;\n let frame = 0;\n let last = \"\";\n const track = () => {\n const trigger = triggerRef.current;\n const panel = panelRef.current;\n if (trigger && panel) {\n const r = trigger.getBoundingClientRect();\n const key = `${r.top}|${r.left}|${r.width}|${r.height}|${panel.offsetWidth}|${panel.offsetHeight}|${window.innerWidth}|${window.innerHeight}`;\n if (key !== last) {\n last = key;\n place();\n }\n }\n frame = requestAnimationFrame(track);\n };\n frame = requestAnimationFrame(track);\n return () => cancelAnimationFrame(frame);\n }, [open, place]);\n\n return (\n <>\n <Button\n {...buttonProps}\n ref={triggerRef}\n id={triggerId}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={panelId}\n onPointerDown={(e) => {\n buttonProps.onPointerDown?.(e);\n // Decide here, not on click. Pressing the trigger while the panel is\n // open is an outside press to the platform, which closes the panel\n // during pointerdown — so by the time click runs, the panel already\n // reads as shut and a plain toggle would reopen it. The platform's\n // toggle event cannot settle it either: it fires after click. What\n // the reader meant is knowable only at the moment they pressed.\n pressIntent.current = !openNow.current;\n }}\n onKeyDown={(e) => {\n buttonProps.onKeyDown?.(e);\n // A press dragged off the button never clicks, which would leave its\n // intent behind to hijack the next Enter or Space. Keys decide fresh.\n if (e.key === \"Enter\" || e.key === \" \") pressIntent.current = null;\n }}\n onClick={(e) => {\n onClick?.(e);\n // Keyboard activation has no pointerdown, so it falls back to a\n // straight toggle, which is right: Enter and Space never light-dismiss.\n const next = pressIntent.current ?? !openNow.current;\n pressIntent.current = null;\n if (next) openedByReader.current = true;\n setOpen(next);\n }}\n >\n {label}\n </Button>\n\n <div\n ref={panelRef}\n id={panelId}\n popover=\"auto\"\n role=\"dialog\"\n aria-labelledby={triggerId}\n tabIndex={-1}\n className={cx(styles.panel, ctl.spacePanel, panelClassName)}\n data-animated={buttonProps.animated === false ? \"false\" : undefined}\n data-side={pos?.placed ?? side}\n style={pos ? { top: pos.top, left: pos.left } : undefined}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n closingByEscape.current = true;\n // Only this popover. An enclosing Dialog must not close with it.\n e.stopPropagation();\n }\n }}\n onToggle={(e: React.SyntheticEvent<HTMLDivElement>) => {\n if ((e.nativeEvent as ToggleEvent).newState !== \"closed\") return;\n if (closingByEscape.current) {\n closingByEscape.current = false;\n triggerRef.current?.focus();\n }\n // The platform closed it — a press elsewhere or Escape. setOpen\n // ignores a close this component has already recorded.\n setOpen(false);\n }}\n >\n {children}\n </div>\n </>\n );\n}\n"],"names":["SPACE","spacingStyle","m","mt","mb","p","pb","style","out","cx","parts","Text","forwardRef","as","size","weight","color","className","rest","ref","createElement","styles","Heading","align","Link","asChild","children","cls","merged","isValidElement","child","cloneElement","jsx","cap","s","Flex","gap","direction","justify","wrap","Box","Grid","columns","colCls","Badge","variant","Separator","Card","image","jsxs","mulberry32","a","t","hashString","h","i","Button","iconOnly","ember","fullWidth","animated","id","useId","starStyles","useMemo","rand","classes","base","Share2Icon","props","ChatBubbleIcon","PlusIcon","Pencil1Icon","HeartFilledIcon","ExitFullScreenIcon","EnterFullScreenIcon","CheckIcon","TrashIcon","QuestionMarkCircledIcon","PersonIcon","MinusIcon","MagnifyingGlassIcon","HeartIcon","ChevronUpIcon","ChevronDownIcon","ChevronRightIcon","ChevronLeftIcon","BookmarkIcon","XIcon","InfoCircledIcon","ExclamationTriangleIcon","CrossCircledIcon","Carousel","perView","step","showPagination","ariaLabel","slides","Children","count","trackId","trackRef","useRef","estimatedPage","estimatedStops","pageSize","setPageSize","useState","stopCount","setStopCount","active","setActive","atStart","setAtStart","atEnd","setAtEnd","stops","measuredMax","endStop","remeasure","sync","useCallback","track","x","max","atStartNow","atEndNow","nearest","stop","measure","items","first","inView","last","end","next","item","useLayoutEffect","useEffect","resize","frame","onScroll","THRESHOLD","pointer","startX","startScroll","dragging","settle","endSettling","onPointerDown","e","onPointerMove","dx","onPointerUp","all","target","best","reduced","onClick","onDragStart","scrollTo","left","_a","go","scrollable","slide","_","ctl","ctlModule","pageCount","totalItems","pageWindow","page","total","siblings","range","from","to","slots","current","right","gapLeft","gapRight","edge","Pagination","pagination","onPageClick","Loader","label","showMeasured","element","place","SHOW_DELAY","HIDE_DELAY","SIDE_OFFSET","COLLISION_PADDING","TooltipTrigger","triggerRef","tooltipId","show","hide","Tooltip","side","open","setOpen","pos","setPos","contentRef","showTimer","hideTimer","clearTimers","immediate","content","trigger","r","w","centre","start","extent","viewport","fits","near","far","after","before","fitsBefore","fitsAfter","below","above","fitsAbove","fitsBelow","top","Fragment","IconToggle","options","value","onValueChange","orientation","vertical","opt","Ctx","createContext","useSelect","ctx","useContext","optionId","listboxId","OFFSET","EDGE_PADDING","collectItems","walk","nodes","Item","SelectRoot","disabled","placeholder","highlighted","setHighlighted","rootRef","listRef","triggerWidth","setTriggerWidth","maxHeight","setMaxHeight","values","itemLabels","labelFor","v","onDown","list","rect","flip","room","height","prev","key","openWith","highlight","move","delta","idx","l","_b","selected","Select","TextFieldRoot","inputProps","Slot","TextField","TextArea","Autocomplete","onSelect","icon","caseSensitive","preFiltered","loading","loadingMessage","emptyMessage","footer","wrapRef","panelRef","listId","haystack","o","hasQuery","shown","needle","selectable","hasContent","showPanel","el","panel","field","close","node","navigated","choose","option","onKeyDown","chosen","activeOption","clamp","low","high","Slider","min","minDistance","thumbLabels","inputs","marks","drag","release","isRange","span","lower","upper","percent","now","gridBelow","gridAbove","clampThumb","index","settled","updated","valueAt","clientX","box","ratio","raw","markBox","nearestTo","second","firstCentre","toFirst","toSecond","onThumb","stopDragging","event","_c","_d","held","travelled","SERIES_COLORS","SERIES_COLOR_COUNT","seriesColor","niceStep","rough","magnitude","scaled","linearScale","tickCount","zeroBased","real","lowest","highest","ticks","bandPositions","inset","slot","barPath","y","width","radius","up","pointPositions","isDevelopment","formatValue","PADDING","AXIS_GUTTER","Chart","type","categories","series","stacked","legend","grid","format","partialFrom","onPointClick","titleId","plotRef","setWidth","hover","setHover","observer","entry","wrong","stackable","partial","stillFilling","scale","positive","negative","labels","gutter","plotWidth","plotHeight","band","points","colorOf","showLegend","baseline","bases","si","readingAt","positions","report","seriesIndex","categoryIndex","barWidth","s2","tick","category","ci","bottom","slotLeft","drawWidth","drawHeight","stillCounting","runs","run","segment","ri","line","k","area","BarList","showPercent","colorful","onItemClick","largest","sum","fill","row","pointOnCircle","fraction","angle","PieChart","slices","donut","onSliceClick","hovered","setHovered","uid","usable","hole","cursor","arcs","slice","outerFrom","outerTo","large","whole","d","originalIndex","fillRule","Control","checked","indeterminate","onToggle","CheckboxGroupRoot","g","isDisabled","control","CheckboxGroup","Checkbox","onCheckedChange","RadioGroupRoot","name","RadioGroup","Progress","pct","ICONS","ROLES","Message","title","glyph","role","live","lockCount","useDialog","makeRoot","alert","onOpenChange","internal","setInternal","isControlled","actual","descId","hasDesc","setHasDesc","Root","chainOpen","fn","c","Trigger","Close","Content","maxWidth","swallowCancel","pointerDownOnBackdrop","Title","Description","Dialog","Cancel","Action","AlertDialog","useMenu","DropdownMenuRoot","buttonProps","setOpenState","menuId","menuRef","pressIntent","openNow","onResize","_e","_f","Label","activate","childClassName","childOnClick","childChildren","childRole","childTabIndex","restProps","originalRef","DropdownMenu","useTabs","TabsRoot","List","tabs","Tabs","FOCUSABLE","Popover","openProp","defaultOpen","panelClassName","controlled","triggerId","panelId","openedByReader","closingByEscape","placed","wanted"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/components/propShared.ts","../src/components/Text.tsx","../src/components/Heading.tsx","../src/components/Link.tsx","../src/components/Flex.tsx","../src/components/Box.tsx","../src/components/Grid.tsx","../src/components/Badge.tsx","../src/components/Separator.tsx","../src/components/Card.tsx","../src/internal/seededRandom.ts","../src/components/Button.tsx","../src/components/icons.tsx","../src/components/Carousel.tsx","../src/styles/spaceControls.ts","../src/components/Pagination.tsx","../src/components/Loader.tsx","../src/internal/showMeasured.ts","../src/components/Tooltip.tsx","../src/components/IconToggle.tsx","../src/components/Select.tsx","../src/components/TextField.tsx","../src/components/TextArea.tsx","../src/components/Autocomplete.tsx","../src/components/Slider.tsx","../src/internal/chartScale.ts","../src/components/Chart.tsx","../src/components/BarList.tsx","../src/components/PieChart.tsx","../src/components/Checkbox.tsx","../src/components/RadioGroup.tsx","../src/components/Progress.tsx","../src/components/Message.tsx","../src/components/Dialog.tsx","../src/components/AlertDialog.tsx","../src/components/DropdownMenu.tsx","../src/components/Tabs.tsx","../src/components/Popover.tsx"],"sourcesContent":["// Shared prop plumbing for the design-system primitives. The spacing map is\n// the single place Radix's numeric steps meet our t-shirt tokens; \"3\" (12px)\n// rounds UP to md per the spec's when-in-doubt-go-up rule.\nimport type { CSSProperties } from \"react\";\n\nexport type SpaceStep = \"0\" | \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\";\n\nexport interface SpacingProps {\n m?: SpaceStep;\n mt?: SpaceStep;\n mb?: SpaceStep;\n p?: SpaceStep;\n pb?: SpaceStep;\n}\n\nconst SPACE: Record<SpaceStep, string> = {\n \"0\": \"0\",\n \"1\": \"var(--spacing-xs)\",\n \"2\": \"var(--spacing-sm)\",\n \"3\": \"var(--spacing-md)\",\n \"4\": \"var(--spacing-md)\",\n \"5\": \"var(--spacing-lg)\",\n \"6\": \"var(--spacing-xl)\",\n};\n\nexport function spacingStyle(\n { m, mt, mb, p, pb }: SpacingProps,\n style?: CSSProperties,\n): CSSProperties | undefined {\n const out: CSSProperties = {\n ...(m !== undefined && { margin: SPACE[m] }),\n ...(mt !== undefined && { marginTop: SPACE[mt] }),\n ...(mb !== undefined && { marginBottom: SPACE[mb] }),\n ...(p !== undefined && { padding: SPACE[p] }),\n ...(pb !== undefined && { paddingBottom: SPACE[pb] }),\n ...style,\n };\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nexport function cx(...parts: Array<string | false | undefined>): string {\n return parts.filter(Boolean).join(\" \");\n}\n","import type * as React from \"react\";\nimport { createElement, forwardRef, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Text.module.scss\";\n\nexport interface TextProps\n extends SpacingProps,\n Omit<React.HTMLAttributes<HTMLElement>, \"color\"> {\n /** Element to render. Default `span`. Use `p` for prose and `label`\n * (with `htmlFor`) for form labels — size is presentational, so the\n * element stays free to be the semantically correct one. */\n as?: \"span\" | \"div\" | \"p\" | \"label\";\n /** Font size step: 1=12px, 2=14px, 3=16px, 4=18px, 5=20px, 6=24px.\n * Line height and letter spacing move with it. Omit to inherit. */\n size?: \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\";\n /** 500 or 700. Omit for the inherited weight. */\n weight?: \"medium\" | \"bold\";\n /** Semantic colour role. `gray` is the standard secondary-text token;\n * the rest carry meaning, so avoid them for emphasis alone. Omit for\n * primary text. */\n /** Semantic colour role. `muted` is the standard secondary-text token;\n * the rest carry meaning, so avoid them for emphasis alone. Omit for\n * primary text. */\n color?: \"muted\" | \"danger\" | \"success\" | \"warning\";\n /** Id of the control this labels. Only meaningful with `as=\"label\"`. */\n htmlFor?: string;\n /** The text. */\n children?: ReactNode;\n}\n\n/**\n * Body copy. Size, weight and colour are presentational and independent of\n * the element, so `as` stays free to be whatever the document actually needs\n * — a `p` for prose, a `label` for a field, a `span` inline.\n *\n * Colour is a role, not a hue: use `muted` for secondary copy and reserve the\n * status roles for text that genuinely carries that meaning.\n */\nexport const Text = forwardRef<HTMLElement, TextProps>(function Text(\n { as = \"span\", size, weight, color, className, style, m, mt, mb, p, pb, ...rest },\n ref,\n) {\n return createElement(as, {\n ...rest,\n ref,\n className: cx(\n styles.text,\n size && styles[`size${size}`],\n weight && styles[weight],\n color && styles[`color${color[0].toUpperCase()}${color.slice(1)}`],\n className,\n ),\n style: spacingStyle({ m, mt, mb, p, pb }, style),\n });\n});\n","import type * as React from \"react\";\nimport { createElement, forwardRef, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Heading.module.scss\";\n\nexport interface HeadingProps\n extends SpacingProps,\n Omit<React.HTMLAttributes<HTMLHeadingElement>, \"color\"> {\n /** Heading level to render. Default `h2`. Independent of `size`, so\n * document outline stays correct without dictating appearance. */\n as?: \"h1\" | \"h2\" | \"h3\" | \"h4\";\n /** Font size step: 4=18px, 5=20px, 6=24px, 7=28px, 8=35px, 9=60px.\n * Shares steps 4–6 with Text, so a Heading and Text can sit on the\n * same line and match. */\n size?: \"4\" | \"5\" | \"6\" | \"7\" | \"8\" | \"9\";\n /** Semantic colour role. Omit for primary heading colour. */\n color?: \"muted\" | \"danger\";\n /** Centres the text. There is no `left`/`right` — headings are\n * start-aligned unless deliberately centred. */\n align?: \"center\";\n /** The heading text. */\n children?: ReactNode;\n}\n\n/**\n * A section heading. `as` sets the heading level and `size` sets the\n * appearance, deliberately apart — so a visually small heading can still be\n * an h2 where the document structure calls for one.\n *\n * Shares size steps 4-6 with Text, so a heading and body copy on the same\n * line align.\n */\nexport const Heading = forwardRef<HTMLHeadingElement, HeadingProps>(function Heading(\n { as = \"h2\", size, color, align, className, style, m, mt, mb, p, pb, ...rest },\n ref,\n) {\n return createElement(as, {\n ...rest,\n ref,\n className: cx(\n styles.heading,\n size && styles[`size${size}`],\n color === \"muted\" && styles.colorMuted,\n color === \"danger\" && styles.colorDanger,\n align === \"center\" && styles.alignCenter,\n className,\n ),\n style: spacingStyle({ m, mt, mb, p, pb }, style),\n });\n});\n","import type * as React from \"react\";\nimport { cloneElement, forwardRef, isValidElement, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Link.module.scss\";\n\nexport interface LinkProps\n extends SpacingProps,\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, \"color\"> {\n /** Render the single child element instead of an `<a>`, merging link\n * styling onto it. For wrapping a router's own Link component without\n * nesting two anchors. */\n asChild?: boolean;\n /** Font size step: 1=12px, 2=14px, 3=16px. Matches Text's first three\n * steps so inline links sit flush with surrounding copy. */\n size?: \"1\" | \"2\" | \"3\";\n /** Link text. With `asChild`, the single element to style as a link. */\n children?: ReactNode;\n}\n\n/**\n * An inline anchor, styled to sit inside running text without disturbing its\n * rhythm. Sizes match Text's first three steps.\n *\n * Use `asChild` to wrap a router's own link component rather than nesting two\n * anchors, which is invalid and breaks keyboard navigation.\n */\nexport const Link = forwardRef<HTMLAnchorElement, LinkProps>(function Link(\n { asChild, size, className, style, m, mt, mb, p, pb, children, ...rest },\n ref,\n) {\n const cls = cx(styles.link, size && styles[`size${size}`], className);\n const merged = spacingStyle({ m, mt, mb, p, pb }, style);\n if (asChild && isValidElement(children)) {\n const child = children as React.ReactElement<{ className?: string; style?: React.CSSProperties }>;\n return cloneElement(child, {\n ...rest,\n className: cx(cls, child.props.className),\n style: { ...merged, ...child.props.style },\n });\n }\n return (\n <a {...rest} ref={ref} className={cls} style={merged}>\n {children}\n </a>\n );\n});\n","import type * as React from \"react\";\nimport { cloneElement, forwardRef, isValidElement, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Flex.module.scss\";\n\nexport interface FlexProps extends SpacingProps, React.HTMLAttributes<HTMLDivElement> {\n /** Render the single child element instead of a wrapper div, merging\n * the flex styling onto it. Avoids a redundant layer in the DOM. */\n asChild?: boolean;\n /** Gap step: 1=4px, 2=8px, 3=12px, 4=16px, 5=24px, 6=32px. Note step 3\n * is 12px — off the 8pt grid, kept for parity with the shipped app. */\n gap?: \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\";\n /** Main axis. Default `row`. */\n direction?: \"row\" | \"column\";\n /** Cross-axis alignment (`align-items`). */\n align?: \"start\" | \"center\" | \"end\" | \"baseline\" | \"stretch\";\n /** Main-axis distribution (`justify-content`). */\n justify?: \"start\" | \"center\" | \"end\" | \"between\";\n /** Wrapping behaviour. Default is the browser's `nowrap`. */\n wrap?: \"wrap\" | \"nowrap\";\n /** The items to lay out. */\n children?: ReactNode;\n}\n\nconst cap = (s: string) => s[0].toUpperCase() + s.slice(1);\n\n/**\n * A flex row or column whose gap comes from the spacing scale, so layouts\n * inherit the 8pt grid instead of restating it in pixels.\n *\n * `asChild` merges the layout onto its only child rather than adding a\n * wrapper, for when an extra div would break a grid or a selector.\n */\nexport const Flex = forwardRef<HTMLDivElement, FlexProps>(function Flex(\n { asChild, gap, direction, align, justify, wrap, className, style, m, mt, mb, p, pb, children, ...rest },\n ref,\n) {\n const cls = cx(\n styles.flex,\n gap && styles[`gap${gap}`],\n direction && styles[`direction${cap(direction)}`],\n align && styles[`align${cap(align)}`],\n justify && styles[`justify${cap(justify)}`],\n wrap && styles[`wrap${cap(wrap)}`],\n className,\n );\n const merged = spacingStyle({ m, mt, mb, p, pb }, style);\n if (asChild && isValidElement(children)) {\n const child = children as React.ReactElement<{ className?: string; style?: React.CSSProperties }>;\n return cloneElement(child, {\n ...rest,\n className: cx(cls, child.props.className),\n style: { ...merged, ...child.props.style },\n });\n }\n return (\n <div {...rest} ref={ref} className={cls} style={merged}>\n {children}\n </div>\n );\n});\n","import type * as React from \"react\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { spacingStyle, type SpacingProps } from \"./propShared\";\n\nexport interface BoxProps extends SpacingProps, React.HTMLAttributes<HTMLDivElement> {\n /** Anything. Box adds no styling of its own. */\n children?: ReactNode;\n}\n\n// Radix Box at our call sites is a plain div carrying className/style/ref —\n// no layout props anywhere (verified by inventory). Keep it exactly that.\n\n/**\n * A plain div that understands the spacing scale. The escape hatch for when\n * you need margin or padding on the grid but no layout behaviour with it.\n *\n * Renders nothing of its own — no class, no styling — so it never interferes\n * with whatever you put inside.\n */\nexport const Box = forwardRef<HTMLDivElement, BoxProps>(function Box(\n { style, m, mt, mb, p, pb, ...rest },\n ref,\n) {\n return <div {...rest} ref={ref} style={spacingStyle({ m, mt, mb, p, pb }, style)} />;\n});\n","import type * as React from \"react\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Grid.module.scss\";\n\ntype Cols = \"1\" | \"2\" | \"3\";\nexport interface GridProps extends SpacingProps, React.HTMLAttributes<HTMLDivElement> {\n /** Column count, 1–3. Pass an object for responsive counts:\n * `{ initial: \"1\", sm: \"2\", md: \"3\" }` — `initial` applies below the\n * first breakpoint. */\n columns?: Cols | { initial?: Cols; sm?: Cols; md?: Cols };\n /** Gap step: 1=4px, 2=8px, 3=12px, 4=16px, 5=24px, 6=32px. Same scale\n * as Flex. */\n gap?: \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\";\n /** The cells. */\n children?: ReactNode;\n}\n\n/**\n * A simple column grid, 1-3 wide, with the same gap scale as Flex. Pass an\n * object to `columns` for responsive counts.\n *\n * Deliberately narrow: anything more elaborate is a job for CSS grid directly\n * rather than a prop API that would end up reinventing it.\n */\nexport const Grid = forwardRef<HTMLDivElement, GridProps>(function Grid(\n { columns, gap, className, style, m, mt, mb, p, pb, ...rest },\n ref,\n) {\n const colCls =\n typeof columns === \"string\"\n ? [styles[`cols${columns}`]]\n : columns\n ? [\n columns.initial && styles[`cols${columns.initial}`],\n columns.sm && styles[`smCols${columns.sm}`],\n columns.md && styles[`mdCols${columns.md}`],\n ]\n : [];\n return (\n <div\n {...rest}\n ref={ref}\n className={cx(styles.grid, ...(colCls as string[]), gap && styles[`gap${gap}`], className)}\n style={spacingStyle({ m, mt, mb, p, pb }, style)}\n />\n );\n});\n","import type * as React from \"react\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Badge.module.scss\";\n\n/**\n * Roles whose colour carries meaning — status and emphasis.\n */\nexport type BadgeSemanticColor =\n | \"muted\"\n | \"primary\"\n | \"success\"\n | \"warning\"\n | \"danger\";\n\n/**\n * Categorical hues for telling data apart — star classes, planet types — where\n * the colour distinguishes rather than signals. These deliberately keep hue\n * names: for a categorical scale the hue IS the identity, and calling one\n * \"tertiary\" would imply a ranking that does not exist.\n */\nexport type BadgeCategoricalColor =\n | \"cyan\"\n | \"purple\"\n | \"orange\"\n | \"yellow\"\n | \"accent\";\n\nexport type BadgeColor = BadgeSemanticColor | BadgeCategoricalColor;\n\nexport interface BadgeProps\n extends SpacingProps,\n Omit<React.HTMLAttributes<HTMLSpanElement>, \"color\"> {\n /** Semantic role or categorical hue. Roles carry meaning — pick one\n * that matches the state, not the look you want.\n */\n color?: BadgeColor;\n /** `soft` is a tinted wash for dense lists; `solid` is a filled chip\n * for a badge that must win attention.\n */\n variant?: \"soft\" | \"solid\";\n /** 1 is the default chip; 2 is for standalone use away from body text. */\n size?: \"1\" | \"2\";\n /** Badges are single-line by default: one that wraps stops reading as a\n * badge. Opt into wrapping for free text you do not control — anything a\n * reader named rather than you — so it cannot overflow what contains it. */\n wrap?: boolean;\n /** Label text. Keep it short — a badge that wraps stops reading as one. */\n children?: ReactNode;\n}\n\nconst cap = (s: string) => s[0].toUpperCase() + s.slice(1);\n\n// Default color is \"blue\" (not \"gray\") to match Radix's behavior: Badge's\n// `color` prop had no hardcoded default there either — it inherited the\n// surrounding Theme's `accentColor`, which this app sets to \"blue\" (see the\n// single <Theme accentColor> in the host app). A caller that wants a\n// neutral badge should pass color=\"muted\" explicitly.\n/**\n * A compact status label. Colour is the message, so choose it for meaning:\n * the semantic roles say safe, pending or destructive, while the categorical\n * hues only tell one kind of thing from another and carry no judgement.\n *\n * Single-line by default, since a badge that wraps stops reading as a badge.\n * Opt into `wrap` for free text you do not control.\n */\nexport const Badge = forwardRef<HTMLSpanElement, BadgeProps>(function Badge(\n { color = \"primary\", variant = \"soft\", size = \"1\", wrap, className, style, m, mt, mb, p, pb, ...rest },\n ref,\n) {\n return (\n <span\n {...rest}\n ref={ref}\n className={cx(\n styles.badge,\n styles[`color${cap(color)}`],\n variant === \"solid\" && styles.solid,\n styles[`size${size}`],\n wrap && styles.wrap,\n className,\n )}\n style={spacingStyle({ m, mt, mb, p, pb }, style)}\n />\n );\n});\n","import type * as React from \"react\";\nimport { forwardRef } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./Separator.module.scss\";\n\nexport interface SeparatorProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Length of the rule, 1 (shortest) to 4 (full width of its container). */\n size?: \"1\" | \"2\" | \"3\" | \"4\";\n}\n\n/**\n * A hairline rule for dividing content within a surface, where a full panel\n * boundary would be too heavy. Exposed as `role=\"separator\"`, so assistive\n * technology hears the division too.\n */\nexport const Separator = forwardRef<HTMLSpanElement, SeparatorProps>(function Separator(\n { size = \"4\", className, ...rest },\n ref,\n) {\n return (\n <span\n {...rest}\n ref={ref}\n role=\"separator\"\n className={cx(styles.separator, size === \"4\" && styles.full, className)}\n />\n );\n});\n","import type * as React from \"react\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { cx, spacingStyle, type SpacingProps } from \"./propShared\";\nimport styles from \"./Card.module.scss\";\n\nexport interface CardProps extends SpacingProps, React.HTMLAttributes<HTMLDivElement> {\n /** A media element to sit at the top of the card, full-bleed to its edges.\n * Pass whatever your framework renders — a plain `<img>`, a `next/image`,\n * a `<video>` — and the card frames it: cropped to fill, top corners\n * matched to its own radius, and a reserved box so the layout does not\n * jump when it loads.\n *\n * The reserved box is `--sp-card-image-ratio` (default `16 / 10`). Set it\n * per card for a different crop. */\n image?: ReactNode;\n /** The card's contents. */\n children?: ReactNode;\n}\n\n/**\n * A translucent panel for grouping related content, one step above the page\n * surface. Its 12px inset is a deliberate exception to the 8pt grid, kept for\n * parity with the app this was extracted from.\n *\n * Pass `image` for a media card. The image is framed by the card rather than\n * being an ordinary child, so every card in a row reserves the same box\n * before its image loads and none of them reflow when it does.\n */\nexport const Card = forwardRef<HTMLDivElement, CardProps>(function Card(\n { className, style, image, children, m, mt, mb, p, pb, ...rest },\n ref,\n) {\n return (\n <div\n {...rest}\n ref={ref}\n className={cx(styles.card, image != null && styles.hasImage, className)}\n style={spacingStyle({ m, mt, mb, p, pb }, style)}\n >\n {image != null && <div className={styles.image}>{image}</div>}\n {children}\n </div>\n );\n});\n","/** Deterministic RNG + string hash, vendored from the source application (the only\n * consumer inside the library is SpaceButton's star speckle). Pure,\n * dependency-free, and part of no public API. */\nexport function mulberry32(a: number): () => number {\n return function () {\n a |= 0;\n a = (a + 0x6d2b79f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** FNV-1a 32-bit string hash, for turning stable strings into seeds. */\nexport function hashString(s: string): number {\n let h = 0x811c9dc5;\n for (let i = 0; i < s.length; i++) {\n h ^= s.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return h >>> 0;\n}\n","\"use client\";\n\nimport { forwardRef, useId, useMemo } from \"react\";\nimport styles from \"./Button.module.scss\";\nimport { mulberry32, hashString } from \"../internal/seededRandom\";\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Circular, icon-only sizing (e.g. the share glyph). */\n iconOnly?: boolean;\n /** Warm red-dwarf rim for destructive-ish actions (e.g. Clear). */\n ember?: boolean;\n /** md = default. lg = hero CTAs. sm = compact dialog actions. micro = tiny steppers (no stars/glint). */\n size?: \"sm\" | \"md\" | \"lg\" | \"micro\";\n /** Stretch to the container width (sticky footers). */\n fullWidth?: boolean;\n /** Ambient motion: the orbiting rim, the glint sweep, and the twinkling\n * stars. Set false for dense UI or long lists where the movement\n * distracts. The glass look itself is not optional. Default true. */\n animated?: boolean;\n}\n\n\n/**\n * The thing a reader presses to make something happen. A glass capsule whose\n * rim glows like a planet's sunlit limb, with stars twinkling inside it and a\n * glint that sweeps across it now and then.\n *\n * It renders a plain `<button>` and forwards its ref, so it drops into\n * anything that needs to borrow a trigger — a dialog, a menu, a router link's\n * render prop — without a wrapper in between.\n */\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n function Button({ iconOnly, ember, size = \"md\", fullWidth, animated = true, className, children, ...rest }, ref) {\n const id = useId();\n\n // Unique-per-instance star field: positions and timing vary button to\n // button so the sparkles don't read as a repeated stamp.\n const starStyles = useMemo(() => {\n // Deterministic PRNG seeded from useId, so each button instance gets its\n // own star arrangement while server and client render identically (no\n // hydration mismatch, unlike Math.random in render).\n const rand = mulberry32(hashString(id));\n return Array.from({ length: 3 }, () => ({\n top: `${12 + rand() * 58}%`,\n left: `${8 + rand() * 80}%`,\n animationDelay: `${(rand() * 3.2).toFixed(2)}s`,\n animationDuration: `${(2.8 + rand() * 1.8).toFixed(2)}s`,\n }));\n }, [id]);\n\n const classes = [\n styles.spaceButton,\n iconOnly ? styles.iconOnly : \"\",\n ember ? styles.ember : \"\",\n size !== \"md\" ? styles[size] : \"\",\n fullWidth ? styles.fullWidth : \"\",\n className ?? \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <button\n ref={ref}\n className={classes}\n data-animated={animated ? undefined : \"false\"}\n {...rest}\n >\n {size !== \"micro\" && (\n <span className={styles.stars} aria-hidden>\n {starStyles.map((style, i) => (\n <i key={i} className={styles.star} style={style} />\n ))}\n </span>\n )}\n <span className={styles.label}>{children}</span>\n </button>\n );\n }\n);\n","// 23 icons, ported verbatim from @radix-ui/react-icons\n// (MIT License — Copyright (c) 2022 WorkOS; https://github.com/radix-ui/icons).\n// Uniform 15x15 viewBox, currentColor, decorative by default (aria-hidden) —\n// pass aria-label + aria-hidden={undefined} for semantic uses.\nimport type * as React from \"react\";\n\nexport type IconProps = React.SVGAttributes<SVGSVGElement>;\n\nconst base = {\n width: 15,\n height: 15,\n viewBox: \"0 0 15 15\",\n fill: \"none\",\n xmlns: \"http://www.w3.org/2000/svg\",\n \"aria-hidden\": true,\n} as const;\n\nexport function Share2Icon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M3.5 5.00006C3.22386 5.00006 3 5.22392 3 5.50006L3 11.5001C3 11.7762 3.22386 12.0001 3.5 12.0001L11.5 12.0001C11.7761 12.0001 12 11.7762 12 11.5001L12 5.50006C12 5.22392 11.7761 5.00006 11.5 5.00006L10.25 5.00006C9.97386 5.00006 9.75 4.7762 9.75 4.50006C9.75 4.22392 9.97386 4.00006 10.25 4.00006L11.5 4.00006C12.3284 4.00006 13 4.67163 13 5.50006L13 11.5001C13 12.3285 12.3284 13.0001 11.5 13.0001L3.5 13.0001C2.67157 13.0001 2 12.3285 2 11.5001L2 5.50006C2 4.67163 2.67157 4.00006 3.5 4.00006L4.75 4.00006C5.02614 4.00006 5.25 4.22392 5.25 4.50006C5.25 4.7762 5.02614 5.00006 4.75 5.00006L3.5 5.00006ZM7 1.6364L5.5682 3.0682C5.39246 3.24393 5.10754 3.24393 4.9318 3.0682C4.75607 2.89246 4.75607 2.60754 4.9318 2.4318L7.1818 0.181802C7.26619 0.09741 7.38065 0.049999 7.5 0.049999C7.61935 0.049999 7.73381 0.09741 7.8182 0.181802L10.0682 2.4318C10.2439 2.60754 10.2439 2.89246 10.0682 3.0682C9.89246 3.24393 9.60754 3.24393 9.4318 3.0682L8 1.6364L8 8.5C8 8.77614 7.77614 9 7.5 9C7.22386 9 7 8.77614 7 8.5L7 1.6364Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function ChatBubbleIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M12.5 3L2.5 3.00002C1.67157 3.00002 1 3.6716 1 4.50002V9.50003C1 10.3285 1.67157 11 2.5 11H7.50003C7.63264 11 7.75982 11.0527 7.85358 11.1465L10 13.2929V11.5C10 11.2239 10.2239 11 10.5 11H12.5C13.3284 11 14 10.3285 14 9.50003V4.5C14 3.67157 13.3284 3 12.5 3ZM2.49999 2.00002L12.5 2C13.8807 2 15 3.11929 15 4.5V9.50003C15 10.8807 13.8807 12 12.5 12H11V14.5C11 14.7022 10.8782 14.8845 10.6913 14.9619C10.5045 15.0393 10.2894 14.9965 10.1464 14.8536L7.29292 12H2.5C1.11929 12 0 10.8807 0 9.50003V4.50002C0 3.11931 1.11928 2.00003 2.49999 2.00002Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function PlusIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M8 2.75C8 2.47386 7.77614 2.25 7.5 2.25C7.22386 2.25 7 2.47386 7 2.75V7H2.75C2.47386 7 2.25 7.22386 2.25 7.5C2.25 7.77614 2.47386 8 2.75 8H7V12.25C7 12.5261 7.22386 12.75 7.5 12.75C7.77614 12.75 8 12.5261 8 12.25V8H12.25C12.5261 8 12.75 7.77614 12.75 7.5C12.75 7.22386 12.5261 7 12.25 7H8V2.75Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function Pencil1Icon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M11.8536 1.14645C11.6583 0.951184 11.3417 0.951184 11.1465 1.14645L3.71455 8.57836C3.62459 8.66832 3.55263 8.77461 3.50251 8.89155L2.04044 12.303C1.9599 12.491 2.00189 12.709 2.14646 12.8536C2.29103 12.9981 2.50905 13.0401 2.69697 12.9596L6.10847 11.4975C6.2254 11.4474 6.3317 11.3754 6.42166 11.2855L13.8536 3.85355C14.0488 3.65829 14.0488 3.34171 13.8536 3.14645L11.8536 1.14645ZM4.42166 9.28547L11.5 2.20711L12.7929 3.5L5.71455 10.5784L4.21924 11.2192L3.78081 10.7808L4.42166 9.28547Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function HeartFilledIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M1.35248 4.90532C1.35248 2.94498 2.936 1.35248 4.89346 1.35248C6.25769 1.35248 6.86058 1.92336 7.50002 2.93545C8.13946 1.92336 8.74235 1.35248 10.1066 1.35248C12.064 1.35248 13.6476 2.94498 13.6476 4.90532C13.6476 6.74041 12.6013 8.50508 11.4008 9.96927C10.2636 11.3562 8.92194 12.5508 8.00601 13.3664C7.94645 13.4194 7.88869 13.4709 7.83291 13.5206C7.64324 13.6899 7.3568 13.6899 7.16713 13.5206C7.11135 13.4709 7.05359 13.4194 6.99403 13.3664C6.0781 12.5508 4.73641 11.3562 3.59926 9.96927C2.39872 8.50508 1.35248 6.74041 1.35248 4.90532Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function ExitFullScreenIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M5.5 2C5.77614 2 6 2.22386 6 2.5V5.5C6 5.77614 5.77614 6 5.5 6H2.5C2.22386 6 2 5.77614 2 5.5C2 5.22386 2.22386 5 2.5 5H5V2.5C5 2.22386 5.22386 2 5.5 2ZM9.5 2C9.77614 2 10 2.22386 10 2.5V5H12.5C12.7761 5 13 5.22386 13 5.5C13 5.77614 12.7761 6 12.5 6H9.5C9.22386 6 9 5.77614 9 5.5V2.5C9 2.22386 9.22386 2 9.5 2ZM2 9.5C2 9.22386 2.22386 9 2.5 9H5.5C5.77614 9 6 9.22386 6 9.5V12.5C6 12.7761 5.77614 13 5.5 13C5.22386 13 5 12.7761 5 12.5V10H2.5C2.22386 10 2 9.77614 2 9.5ZM9 9.5C9 9.22386 9.22386 9 9.5 9H12.5C12.7761 9 13 9.22386 13 9.5C13 9.77614 12.7761 10 12.5 10H10V12.5C10 12.7761 9.77614 13 9.5 13C9.22386 13 9 12.7761 9 12.5V9.5Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function EnterFullScreenIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M2 2.5C2 2.22386 2.22386 2 2.5 2H5.5C5.77614 2 6 2.22386 6 2.5C6 2.77614 5.77614 3 5.5 3H3V5.5C3 5.77614 2.77614 6 2.5 6C2.22386 6 2 5.77614 2 5.5V2.5ZM9 2.5C9 2.22386 9.22386 2 9.5 2H12.5C12.7761 2 13 2.22386 13 2.5V5.5C13 5.77614 12.7761 6 12.5 6C12.2239 6 12 5.77614 12 5.5V3H9.5C9.22386 3 9 2.77614 9 2.5ZM2.5 9C2.77614 9 3 9.22386 3 9.5V12H5.5C5.77614 12 6 12.2239 6 12.5C6 12.7761 5.77614 13 5.5 13H2.5C2.22386 13 2 12.7761 2 12.5V9.5C2 9.22386 2.22386 9 2.5 9ZM12.5 9C12.7761 9 13 9.22386 13 9.5V12.5C13 12.7761 12.7761 13 12.5 13H9.5C9.22386 13 9 12.7761 9 12.5C9 12.2239 9.22386 12 9.5 12H12V9.5C12 9.22386 12.2239 9 12.5 9Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function CheckIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function TrashIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M5.5 1C5.22386 1 5 1.22386 5 1.5C5 1.77614 5.22386 2 5.5 2H9.5C9.77614 2 10 1.77614 10 1.5C10 1.22386 9.77614 1 9.5 1H5.5ZM3 3.5C3 3.22386 3.22386 3 3.5 3H5H10H11.5C11.7761 3 12 3.22386 12 3.5C12 3.77614 11.7761 4 11.5 4H11V12C11 12.5523 10.5523 13 10 13H5C4.44772 13 4 12.5523 4 12V4L3.5 4C3.22386 4 3 3.77614 3 3.5ZM5 4H10V12H5V4Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function QuestionMarkCircledIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M0.877075 7.49972C0.877075 3.84204 3.84222 0.876892 7.49991 0.876892C11.1576 0.876892 14.1227 3.84204 14.1227 7.49972C14.1227 11.1574 11.1576 14.1226 7.49991 14.1226C3.84222 14.1226 0.877075 11.1574 0.877075 7.49972ZM7.49991 1.82689C4.36689 1.82689 1.82708 4.36671 1.82708 7.49972C1.82708 10.6327 4.36689 13.1726 7.49991 13.1726C10.6329 13.1726 13.1727 10.6327 13.1727 7.49972C13.1727 4.36671 10.6329 1.82689 7.49991 1.82689ZM8.24993 10.5C8.24993 10.9142 7.91414 11.25 7.49993 11.25C7.08571 11.25 6.74993 10.9142 6.74993 10.5C6.74993 10.0858 7.08571 9.75 7.49993 9.75C7.91414 9.75 8.24993 10.0858 8.24993 10.5ZM6.05003 6.25C6.05003 5.57211 6.63511 4.925 7.50003 4.925C8.36496 4.925 8.95003 5.57211 8.95003 6.25C8.95003 6.74118 8.68002 6.99212 8.21447 7.27494C8.16251 7.30651 8.10258 7.34131 8.03847 7.37854L8.03841 7.37858C7.85521 7.48497 7.63788 7.61119 7.47449 7.73849C7.23214 7.92732 6.95003 8.23198 6.95003 8.7C6.95004 9.00376 7.19628 9.25 7.50004 9.25C7.8024 9.25 8.04778 9.00601 8.05002 8.70417L8.05056 8.7033C8.05924 8.6896 8.08493 8.65735 8.15058 8.6062C8.25207 8.52712 8.36508 8.46163 8.51567 8.37436L8.51571 8.37433C8.59422 8.32883 8.68296 8.27741 8.78559 8.21506C9.32004 7.89038 10.05 7.35382 10.05 6.25C10.05 4.92789 8.93511 3.825 7.50003 3.825C6.06496 3.825 4.95003 4.92789 4.95003 6.25C4.95003 6.55376 5.19628 6.8 5.50003 6.8C5.80379 6.8 6.05003 6.55376 6.05003 6.25Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function PersonIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M7.5 0.875C5.49797 0.875 3.875 2.49797 3.875 4.5C3.875 6.15288 4.98124 7.54738 6.49373 7.98351C5.2997 8.12901 4.27557 8.55134 3.50407 9.31167C2.52216 10.2794 2.02502 11.72 2.02502 13.5999C2.02502 13.8623 2.23769 14.0749 2.50002 14.0749C2.76236 14.0749 2.97502 13.8623 2.97502 13.5999C2.97502 11.8799 3.42786 10.7206 4.17091 9.9883C4.91536 9.25463 6.02674 8.87499 7.49995 8.87499C8.97317 8.87499 10.0846 9.25463 10.8291 9.98831C11.5721 10.7206 12.025 11.8799 12.025 13.5999C12.025 13.8623 12.2376 14.0749 12.5 14.0749C12.7623 14.075 12.975 13.8623 12.975 13.6C12.975 11.72 12.4778 10.2794 11.4959 9.31166C10.7244 8.55135 9.70025 8.12903 8.50625 7.98352C10.0187 7.5474 11.125 6.15289 11.125 4.5C11.125 2.49797 9.50203 0.875 7.5 0.875ZM4.825 4.5C4.825 3.02264 6.02264 1.825 7.5 1.825C8.97736 1.825 10.175 3.02264 10.175 4.5C10.175 5.97736 8.97736 7.175 7.5 7.175C6.02264 7.175 4.825 5.97736 4.825 4.5Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function MinusIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M2.25 7.5C2.25 7.22386 2.47386 7 2.75 7H12.25C12.5261 7 12.75 7.22386 12.75 7.5C12.75 7.77614 12.5261 8 12.25 8H2.75C2.47386 8 2.25 7.77614 2.25 7.5Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function MagnifyingGlassIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M10 6.5C10 8.433 8.433 10 6.5 10C4.567 10 3 8.433 3 6.5C3 4.567 4.567 3 6.5 3C8.433 3 10 4.567 10 6.5ZM9.30884 10.0159C8.53901 10.6318 7.56251 11 6.5 11C4.01472 11 2 8.98528 2 6.5C2 4.01472 4.01472 2 6.5 2C8.98528 2 11 4.01472 11 6.5C11 7.56251 10.6318 8.53901 10.0159 9.30884L12.8536 12.1464C13.0488 12.3417 13.0488 12.6583 12.8536 12.8536C12.6583 13.0488 12.3417 13.0488 12.1464 12.8536L9.30884 10.0159Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function HeartIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M4.89346 2.35248C3.49195 2.35248 2.35248 3.49359 2.35248 4.90532C2.35248 6.38164 3.20954 7.9168 4.37255 9.33522C5.39396 10.581 6.59464 11.6702 7.50002 12.4778C8.4054 11.6702 9.60608 10.581 10.6275 9.33522C11.7905 7.9168 12.6476 6.38164 12.6476 4.90532C12.6476 3.49359 11.5081 2.35248 10.1066 2.35248C9.27059 2.35248 8.81894 2.64323 8.5397 2.95843C8.27877 3.25295 8.14623 3.58566 8.02501 3.88993C8.00391 3.9429 7.98315 3.99501 7.96211 4.04591C7.88482 4.23294 7.7024 4.35494 7.50002 4.35494C7.29765 4.35494 7.11523 4.23295 7.03793 4.04592C7.01689 3.99501 6.99612 3.94289 6.97502 3.8899C6.8538 3.58564 6.72126 3.25294 6.46034 2.95843C6.18109 2.64323 5.72945 2.35248 4.89346 2.35248ZM1.35248 4.90532C1.35248 2.94498 2.936 1.35248 4.89346 1.35248C6.0084 1.35248 6.73504 1.76049 7.20884 2.2953C7.32062 2.42147 7.41686 2.55382 7.50002 2.68545C7.58318 2.55382 7.67941 2.42147 7.79119 2.2953C8.265 1.76049 8.99164 1.35248 10.1066 1.35248C12.064 1.35248 13.6476 2.94498 13.6476 4.90532C13.6476 6.74041 12.6013 8.50508 11.4008 9.96927C10.2636 11.3562 8.92194 12.5508 8.00601 13.3664C7.94645 13.4194 7.88869 13.4709 7.83291 13.5206C7.64324 13.6899 7.3568 13.6899 7.16713 13.5206C7.11135 13.4709 7.05359 13.4194 6.99403 13.3664C6.0781 12.5508 4.73641 11.3562 3.59926 9.96927C2.39872 8.50508 1.35248 6.74041 1.35248 4.90532Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function ChevronUpIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M3.13523 8.84197C3.3241 9.04343 3.64052 9.05363 3.84197 8.86477L7.5 5.43536L11.158 8.86477C11.3595 9.05363 11.6759 9.04343 11.8648 8.84197C12.0536 8.64051 12.0434 8.32409 11.842 8.13523L7.84197 4.38523C7.64964 4.20492 7.35036 4.20492 7.15803 4.38523L3.15803 8.13523C2.95657 8.32409 2.94637 8.64051 3.13523 8.84197Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function ChevronDownIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** The house directional chevrons (Radix geometry, matching Up/Down above).\n * These replaced the typographic arrows: a text glyph's shape is whatever the\n * viewer's font decides, and the owner called the result poorly shaped. Used\n * by every \"onward\" CTA and \"back\" button. */\nexport function ChevronRightIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M6.1584 3.13508C5.95694 3.32394 5.94673 3.64036 6.13559 3.84182L9.56499 7.49991L6.13559 11.158C5.94673 11.3595 5.95694 11.6759 6.1584 11.8647C6.35986 12.0536 6.67628 12.0434 6.86514 11.8419L10.6151 7.84182C10.7954 7.64946 10.7954 7.35036 10.6151 7.158L6.86514 3.15801C6.67628 2.95655 6.35986 2.94634 6.1584 3.13508Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function ChevronLeftIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M8.84182 3.13508C9.04328 3.32394 9.05348 3.64036 8.86462 3.84182L5.43523 7.49991L8.86462 11.158C9.05348 11.3595 9.04328 11.6759 8.84182 11.8647C8.64036 12.0536 8.32394 12.0434 8.13508 11.8419L4.38508 7.84182C4.20477 7.64946 4.20477 7.35036 4.38508 7.158L8.13508 3.15801C8.32394 2.95655 8.64036 2.94634 8.84182 3.13508Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function BookmarkIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M3 2.5C3 2.22386 3.22386 2 3.5 2H11.5C11.7761 2 12 2.22386 12 2.5V13.5C12 13.6818 11.9014 13.8492 11.7424 13.9373C11.5834 14.0254 11.3891 14.0203 11.235 13.924L7.5 11.5896L3.765 13.924C3.61087 14.0203 3.41659 14.0254 3.25762 13.9373C3.09864 13.8492 3 13.6818 3 13.5V2.5ZM4 3V12.5979L6.97 10.7416C7.29427 10.539 7.70573 10.539 8.03 10.7416L11 12.5979V3H4Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\n/** Dialog dismiss glyph — a plain X, used by Dialog.Content's corner button. */\nexport function XIcon(props: IconProps) {\n return (\n <svg viewBox=\"0 0 15 15\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" {...props}>\n <path\n d=\"M11.8 3.2a.6.6 0 0 0-.85 0L7.5 6.65 4.05 3.2a.6.6 0 1 0-.85.85L6.65 7.5 3.2 10.95a.6.6 0 1 0 .85.85L7.5 8.35l3.45 3.45a.6.6 0 0 0 .85-.85L8.35 7.5l3.45-3.45a.6.6 0 0 0 0-.85Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n\nexport function InfoCircledIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M7.49991 0.876892C3.84222 0.876892 0.877075 3.84204 0.877075 7.49972C0.877075 11.1574 3.84222 14.1226 7.49991 14.1226C11.1576 14.1226 14.1227 11.1574 14.1227 7.49972C14.1227 3.84204 11.1576 0.876892 7.49991 0.876892ZM1.82707 7.49972C1.82707 4.36671 4.36689 1.82689 7.49991 1.82689C10.6329 1.82689 13.1727 4.36671 13.1727 7.49972C13.1727 10.6327 10.6329 13.1726 7.49991 13.1726C4.36689 13.1726 1.82707 10.6327 1.82707 7.49972ZM8.24992 4.49999C8.24992 4.9142 7.91413 5.24999 7.49992 5.24999C7.08571 5.24999 6.74992 4.9142 6.74992 4.49999C6.74992 4.08577 7.08571 3.74999 7.49992 3.74999C7.91413 3.74999 8.24992 4.08577 8.24992 4.49999ZM6.00003 5.99999H6.50003H7.50003C7.77618 5.99999 8.00003 6.22384 8.00003 6.49999V9.99999H8.50003H9.00003V11H8.50003H7.50003H6.50003H6.00003V9.99999H6.50003H7.00003V6.99999H6.50003H6.00003V5.99999Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function ExclamationTriangleIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M8.4449 0.608765C8.0183 -0.107015 6.9817 -0.107015 6.55509 0.608766L0.161178 11.3368C-0.275824 12.07 0.252503 13 1.10608 13H13.8939C14.7475 13 15.2758 12.07 14.8388 11.3368L8.4449 0.608765ZM7.4141 1.12073C7.45288 1.05566 7.54712 1.05566 7.5859 1.12073L13.9798 11.8488C14.0196 11.9154 13.9715 12 13.8939 12H1.10608C1.02849 12 0.980454 11.9154 1.02018 11.8488L7.4141 1.12073ZM6.8269 4.48611C6.81221 4.10423 7.11783 3.78663 7.5 3.78663C7.88217 3.78663 8.18778 4.10423 8.1731 4.48612L8.01921 8.48701C8.00848 8.766 7.7792 8.98664 7.5 8.98664C7.2208 8.98664 6.99151 8.766 6.98078 8.48701L6.8269 4.48611ZM8.24989 10.476C8.24989 10.8902 7.9141 11.226 7.49989 11.226C7.08567 11.226 6.74989 10.8902 6.74989 10.476C6.74989 10.0618 7.08567 9.72599 7.49989 9.72599C7.9141 9.72599 8.24989 10.0618 8.24989 10.476Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nexport function CrossCircledIcon(props: IconProps) {\n return (\n <svg {...base} {...props}>\n <path\n d=\"M0.877075 7.49988C0.877075 3.84219 3.84222 0.877045 7.49991 0.877045C11.1576 0.877045 14.1227 3.84219 14.1227 7.49988C14.1227 11.1575 11.1576 14.1227 7.49991 14.1227C3.84222 14.1227 0.877075 11.1575 0.877075 7.49988ZM7.49991 1.82704C4.36689 1.82704 1.82708 4.36686 1.82708 7.49988C1.82708 10.6329 4.36689 13.1727 7.49991 13.1727C10.6329 13.1727 13.1727 10.6329 13.1727 7.49988C13.1727 4.36686 10.6329 1.82704 7.49991 1.82704ZM9.85358 5.14644C10.0488 5.3417 10.0488 5.65829 9.85358 5.85355L8.20713 7.49999L9.85358 9.14644C10.0488 9.3417 10.0488 9.65829 9.85358 9.85355C9.65832 10.0488 9.34173 10.0488 9.14647 9.85355L7.50002 8.2071L5.85358 9.85355C5.65832 10.0488 5.34173 10.0488 5.14647 9.85355C4.95121 9.65829 4.95121 9.3417 5.14647 9.14644L6.79292 7.49999L5.14647 5.85355C4.95121 5.65829 4.95121 5.3417 5.14647 5.14644C5.34173 4.95118 5.65832 4.95118 5.85358 5.14644L7.50002 6.79289L9.14647 5.14644C9.34173 4.95118 9.65832 4.95118 9.85358 5.14644Z\"\n fill=\"currentColor\"\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport {\n Children, useCallback, useEffect, useId, useLayoutEffect, useRef, useState, type ReactNode,\n} from \"react\";\nimport { cx } from \"./propShared\";\nimport { Button } from \"./Button\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"./icons\";\nimport styles from \"./Carousel.module.scss\";\n\nexport interface CarouselProps extends Omit<React.HTMLAttributes<HTMLElement>, \"children\"> {\n /** The slides, one child each. */\n children?: ReactNode;\n /** How many slides fit the viewport. Fractions show a partial slide at the\n * trailing edge — `2.5` is two whole slides and half a third, a cue that\n * there is more to swipe to. Default 1.\n *\n * This is the count wherever no stylesheet overrides it. To vary it by\n * screen width, do not switch this prop from JavaScript: set the\n * `--sp-carousel-view-count` token in media queries instead, which always\n * wins over the prop. See \"Responsive view count\" on {@link Carousel}. */\n perView?: number;\n /** What an arrow moves by, and what a dot stands for. `item` moves one\n * slide and shows a dot per stopping point; `page` moves by the number of\n * whole slides in view, snaps only at page boundaries, and shows a dot per\n * page. Default `item`. */\n step?: \"item\" | \"page\";\n /** Show the dots beneath the slides. */\n showPagination?: boolean;\n /** Ambient motion on the arrow buttons' rims. Default true. */\n animated?: boolean;\n /** Names the carousel for assistive tech. Say what it holds — \"Featured\n * planets\" — rather than that it is a carousel, which is announced\n * already. Default \"Carousel\". */\n \"aria-label\"?: string;\n}\n\n/**\n * A row of slides that scrolls sideways, with arrows and optional dots.\n *\n * The browser does the heavy lifting. The row is a native horizontal scroller\n * with CSS scroll snapping, so a flick on a phone uses the platform's own\n * momentum and lands on a slide, and nothing runs per frame while it moves.\n * Slide widths come from a CSS calculation on the view count, so a breakpoint\n * can change how many fit without React knowing.\n *\n * A mouse can drag the row too. It follows the pointer, then glides to the\n * next stop in the direction it was dragged; a drag never clicks a link or\n * button in the slide it ends on.\n *\n * ## Responsive view count\n *\n * The number of slides in view is a design token, not state. Vary it by\n * screen width in CSS; never by swapping `perView` from a resize listener or\n * `matchMedia`, which re-renders, and can disagree with the server render.\n *\n * 1. Pass `perView` for the widest layout.\n * 2. Set `--sp-carousel-view-count` on a class (or any ancestor) in media or\n * container queries for the other widths. Fractions are fine.\n * 3. Nothing else. Widths are computed in CSS, and the arrows, dots and page\n * size are measured from the rendered row whenever it resizes.\n *\n * Precedence: `--sp-carousel-view-count` from a stylesheet, then `perView`,\n * then 1. The prop is passed as a private default (`--_view-count-default`),\n * not as the public token, precisely so a stylesheet can override it.\n *\n * Setting the token on `:root` overrides `perView` on every carousel in the\n * app; scope it to a class or section instead. `--sp-carousel-gap-size` can be\n * varied the same way.\n *\n * @example\n * ```tsx\n * <Carousel aria-label=\"Featured planets\" perView={4} className=\"featured\">\n * {slides}\n * </Carousel>\n * ```\n * ```css\n * @media (max-width: 639px) {\n * .featured { --sp-carousel-view-count: 1.2; }\n * }\n * @media (min-width: 640px) and (max-width: 1079px) {\n * .featured { --sp-carousel-view-count: 2.5; }\n * }\n * // 1080px and up: nothing set, so perView={4} applies.\n * ```\n *\n * ## How the script stays small\n *\n * Script does only what CSS cannot yet do everywhere: the arrows, the dots,\n * and the mouse drag. It measures the rendered row — on mount and when it\n * resizes, never on scroll — to find where the row can stop, and on scroll it\n * only compares the scroll position with those stops, updating state when the\n * active one actually changes.\n */\nexport function Carousel({\n children,\n perView = 1,\n step = \"item\",\n showPagination = false,\n animated = true,\n className,\n \"aria-label\": ariaLabel = \"Carousel\",\n ...rest\n}: CarouselProps) {\n const slides = Children.toArray(children);\n const count = slides.length;\n const trackId = useId();\n const trackRef = useRef<HTMLDivElement | null>(null);\n\n // Before anything is measured — first paint and SSR — estimate from the\n // props, so the dots and arrows render at roughly the right count rather\n // than popping in.\n const estimatedPage = step === \"page\" ? Math.max(1, Math.floor(perView)) : 1;\n const estimatedStops =\n count <= perView\n ? 1\n : step === \"page\"\n ? Math.ceil((count - perView) / estimatedPage) + 1\n // Every whole slide start the row can scroll to, plus the end itself\n // when a fraction leaves it between two starts.\n : Math.ceil(count - perView) + 1;\n\n const [pageSize, setPageSize] = useState(estimatedPage);\n const [stopCount, setStopCount] = useState(Math.max(1, estimatedStops));\n const [active, setActive] = useState(0);\n const [atStart, setAtStart] = useState(true);\n const [atEnd, setAtEnd] = useState(count <= perView);\n // Scroll offsets the row can come to rest at. Held in a ref: they are read\n // on every scroll, and nothing needs to re-render when they are recomputed\n // unless their number changes.\n const stops = useRef<number[]>([0]);\n // How far the row could scroll when those stops were worked out. Anything\n // that changes the row's scrollable width without resizing the row itself —\n // an image arriving, a web font swapping in, a slide's content growing —\n // leaves the stops describing a row that no longer exists.\n const measuredMax = useRef(0);\n // The scroll offset the row rests at when it is showing its last slide —\n // the last stop, and what \"at the end\" means. See measure().\n const endStop = useRef(0);\n // measure() needs sync(), and sync() needs to be able to re-measure. A ref\n // breaks the cycle without either depending on the other.\n const remeasure = useRef<() => void>(() => {});\n\n const sync = useCallback(() => {\n const track = trackRef.current;\n if (!track) return;\n const x = track.scrollLeft;\n const max = Math.max(0, track.scrollWidth - track.clientWidth);\n\n // Stops from a different row: measure again and let that call back here.\n // Without this the dots can sit a stop behind for good — a row measured\n // while it was wider keeps a final stop nobody can scroll to, so arriving\n // at the true end still reads as the stop before it.\n if (Math.abs(max - measuredMax.current) > 1) {\n remeasure.current();\n return;\n }\n\n const atStartNow = x <= 1;\n // Against the last reachable stop, not the raw scroll width: with a slide\n // whose content overflows its column the two differ, and the row can never\n // reach the latter.\n const atEndNow = x >= endStop.current - 1;\n // The ends are known exactly, so they are never left to a nearest-value\n // comparison: at the end, the last stop is the one you are on.\n let nearest = 0;\n if (atEndNow) {\n nearest = stops.current.length - 1;\n } else if (!atStartNow) {\n stops.current.forEach((stop, i) => {\n // <= so that when two stops are equally close the later one wins,\n // matching the direction the row was moving to get there.\n if (Math.abs(stop - x) <= Math.abs(stops.current[nearest] - x)) nearest = i;\n });\n }\n\n // React skips the render when a value is unchanged, so scrolling within\n // one stop costs a comparison and nothing more.\n setActive(nearest);\n setAtStart(atStartNow);\n setAtEnd(atEndNow);\n }, []);\n\n const measure = useCallback(() => {\n const track = trackRef.current;\n if (!track) return;\n const items = Array.from(track.children) as HTMLElement[];\n if (!items.length) return;\n\n const max = Math.max(0, track.scrollWidth - track.clientWidth);\n const first = items[0];\n const gap = items.length > 1 ? items[1].offsetLeft - first.offsetLeft - first.offsetWidth : 0;\n // How many slides are really in view, whatever set it: the prop, or a\n // stylesheet overriding the view count at this width.\n const inView = (track.clientWidth + gap) / (first.offsetWidth + gap);\n const size = step === \"page\" ? Math.max(1, Math.floor(inView + 0.01)) : 1;\n\n // Where the row comes to rest at the end: the last slide's trailing edge\n // against the viewport's, which is what its `scroll-snap-align: end` means.\n // Not the raw scroll width — a slide whose content is wider than its\n // column leaves scrollable room past that snap position, room mandatory\n // snapping never lets the row rest in. Counting that as a stop gave a\n // final dot nobody could reach, and left the dot before it lit at the end.\n const last = items[items.length - 1];\n const end = Math.round(\n Math.max(0, Math.min(max, last.offsetLeft - first.offsetLeft + last.offsetWidth - track.clientWidth)),\n );\n\n const next: number[] = [];\n items.forEach((item, i) => {\n if (i % size !== 0) return;\n const stop = Math.round(Math.min(item.offsetLeft - first.offsetLeft, end));\n if (next[next.length - 1] !== stop) next.push(stop);\n });\n // The end is always somewhere you can arrive, even when no slide or page\n // starts exactly there.\n if (end > 0 && next[next.length - 1] < end - 1) next.push(end);\n\n stops.current = next;\n measuredMax.current = Math.round(max);\n endStop.current = end;\n setPageSize(size);\n setStopCount(next.length);\n sync();\n }, [step, sync]);\n\n useLayoutEffect(() => {\n remeasure.current = measure;\n measure();\n }, [measure, count]);\n\n useEffect(() => {\n const track = trackRef.current;\n if (!track) return;\n // Remeasure when the row's size changes — a container resize — and when a\n // SLIDE's size changes, which is what a breakpoint does: setting\n // --sp-carousel-view-count re-divides the row without altering the row's\n // own box at all, so watching only the row left the arrows and dots\n // describing the old count. Scrolling never triggers either.\n const resize = new ResizeObserver(() => measure());\n resize.observe(track);\n const first = track.firstElementChild;\n if (first) resize.observe(first);\n\n let frame = 0;\n const onScroll = () => {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(sync);\n };\n track.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => {\n resize.disconnect();\n cancelAnimationFrame(frame);\n track.removeEventListener(\"scroll\", onScroll);\n };\n // count: a slide added or removed changes which element is the first one.\n }, [measure, sync, count]);\n\n // Dragging with a mouse. Touch and pen already scroll the row natively, with\n // the platform's momentum; a mouse gets no such gesture, so it is added here\n // and only for a mouse.\n useEffect(() => {\n const track = trackRef.current;\n if (!track) return;\n\n // Movement under this is a click, not a drag, so links and buttons inside\n // a slide still work.\n const THRESHOLD = 4;\n let pointer: number | null = null;\n let startX = 0;\n let startScroll = 0;\n let dragging = false;\n let settle = 0;\n\n const endSettling = () => {\n clearTimeout(settle);\n delete track.dataset.settling;\n };\n\n const onPointerDown = (e: PointerEvent) => {\n if (e.pointerType !== \"mouse\" || e.button !== 0) return;\n if (track.scrollWidth <= track.clientWidth) return;\n endSettling();\n pointer = e.pointerId;\n startX = e.clientX;\n startScroll = track.scrollLeft;\n dragging = false;\n };\n\n const onPointerMove = (e: PointerEvent) => {\n if (e.pointerId !== pointer) return;\n const dx = e.clientX - startX;\n if (!dragging) {\n if (Math.abs(dx) < THRESHOLD) return;\n dragging = true;\n track.setPointerCapture(e.pointerId);\n // Snapping off and scrolling instant while held, or the row would\n // fight the pointer: snap back to a slide, or ease behind it.\n track.dataset.dragging = \"\";\n }\n track.scrollLeft = startScroll - dx;\n };\n\n const onPointerUp = (e: PointerEvent) => {\n if (e.pointerId !== pointer) return;\n pointer = null;\n if (!dragging) return;\n delete track.dataset.dragging;\n\n // Land on the nearest stop, but never back where the drag began: any\n // deliberate drag moves at least one stop in its direction.\n const x = track.scrollLeft;\n const all = stops.current;\n let target = all.reduce((best, stop) => (Math.abs(stop - x) < Math.abs(best - x) ? stop : best), all[0]);\n if (x > startScroll + 1 && target <= startScroll + 1) {\n target = all.find((stop) => stop > startScroll + 1) ?? target;\n } else if (x < startScroll - 1 && target >= startScroll - 1) {\n target = [...all].reverse().find((stop) => stop < startScroll - 1) ?? target;\n }\n\n // Snapping stays off until the row arrives. Turned back on mid-glide,\n // the browser would jump straight to a snap point.\n track.dataset.settling = \"\";\n const reduced = window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n track.scrollTo({ left: target, behavior: reduced ? \"auto\" : \"smooth\" });\n // scrollend where supported; the timer covers browsers without it and a\n // row that was already exactly on target, which scrolls nowhere.\n track.addEventListener(\"scrollend\", endSettling, { once: true });\n settle = window.setTimeout(endSettling, 700);\n };\n\n // A drag that ends over a link or button inside a slide must not click it.\n const onClick = (e: MouseEvent) => {\n if (!dragging) return;\n dragging = false;\n e.preventDefault();\n e.stopPropagation();\n };\n\n // Images and links are natively draggable, which would hijack the gesture.\n const onDragStart = (e: DragEvent) => e.preventDefault();\n\n track.addEventListener(\"pointerdown\", onPointerDown);\n track.addEventListener(\"pointermove\", onPointerMove);\n track.addEventListener(\"pointerup\", onPointerUp);\n track.addEventListener(\"pointercancel\", onPointerUp);\n track.addEventListener(\"click\", onClick, true);\n track.addEventListener(\"dragstart\", onDragStart);\n return () => {\n endSettling();\n track.removeEventListener(\"pointerdown\", onPointerDown);\n track.removeEventListener(\"pointermove\", onPointerMove);\n track.removeEventListener(\"pointerup\", onPointerUp);\n track.removeEventListener(\"pointercancel\", onPointerUp);\n track.removeEventListener(\"click\", onClick, true);\n track.removeEventListener(\"dragstart\", onDragStart);\n };\n }, []);\n\n // No behaviour passed, so the stylesheet's scroll-behavior decides: smooth,\n // or instant under reduced motion.\n const scrollTo = (left: number) => trackRef.current?.scrollTo({ left });\n\n const go = (direction: 1 | -1) => {\n const track = trackRef.current;\n if (!track) return;\n const x = track.scrollLeft;\n const target = direction > 0\n ? stops.current.find((stop) => stop > x + 1)\n : [...stops.current].reverse().find((stop) => stop < x - 1);\n if (target !== undefined) scrollTo(target);\n };\n\n const scrollable = stopCount > 1;\n\n return (\n <section\n {...rest}\n aria-roledescription=\"carousel\"\n aria-label={ariaLabel}\n className={cx(styles.root, className)}\n data-scrollable={scrollable ? \"\" : undefined}\n >\n <div className={styles.viewport}>\n <div\n ref={trackRef}\n id={trackId}\n className={styles.track}\n // Focusable, so arrow keys scroll it natively once it has focus.\n tabIndex={0}\n style={{ \"--_view-count-default\": perView } as React.CSSProperties}\n >\n {slides.map((slide, i) => (\n <div\n key={(slide as React.ReactElement).key ?? i}\n className={styles.slide}\n role=\"group\"\n aria-roledescription=\"slide\"\n aria-label={`${i + 1} of ${count}`}\n data-snap={i % pageSize === 0 ? \"\" : undefined}\n >\n {slide}\n </div>\n ))}\n </div>\n\n <span className={cx(styles.arrow, styles.prev)}>\n <Button\n iconOnly\n className={styles.arrowButton}\n animated={animated}\n aria-label=\"Previous\"\n aria-controls={trackId}\n disabled={atStart}\n onClick={() => go(-1)}\n >\n <ChevronLeftIcon aria-hidden=\"true\" />\n </Button>\n </span>\n <span className={cx(styles.arrow, styles.next)}>\n <Button\n iconOnly\n className={styles.arrowButton}\n animated={animated}\n aria-label=\"Next\"\n aria-controls={trackId}\n disabled={atEnd}\n onClick={() => go(1)}\n >\n <ChevronRightIcon aria-hidden=\"true\" />\n </Button>\n </span>\n </div>\n\n {showPagination && scrollable && (\n <div className={styles.dots}>\n {Array.from({ length: stopCount }, (_, i) => (\n <button\n // eslint-disable-next-line react/no-array-index-key\n key={i}\n type=\"button\"\n className={styles.dot}\n aria-label={step === \"page\" ? `Page ${i + 1} of ${stopCount}` : `Position ${i + 1} of ${stopCount}`}\n aria-controls={trackId}\n aria-current={i === active ? \"true\" : undefined}\n onClick={() => scrollTo(stops.current[i] ?? 0)}\n />\n ))}\n </div>\n )}\n </section>\n );\n}\n","// The shared control-chrome class map — INTERNAL. Components apply this skin\n// themselves, so a consumer never composes it; it was a public subpath until\n// the skin became unconditional, which made every call site a no-op.\n//\n// Kept as a typed module rather than importing the SCSS directly, so a typo in\n// ctl.spaceInput is a compile error here rather than undefined at runtime.\nimport ctlModule from \"./spaceControls.module.scss\";\n\n/** Declared explicitly rather than inferred from the SCSS module, so the\n * emitted .d.ts stands alone: the .module.scss is not published, and a\n * consumer importing this subpath must not need it. Naming the keys also\n * means a typo at a call site is a type error instead of `undefined`. */\nexport interface SpaceControlClasses {\n spaceControl: string;\n spaceInput: string;\n spacePanel: string;\n spaceSlider: string;\n spaceTextArea: string;\n rimRotate: string;\n}\n\n// Through `unknown` because Vite types a CSS module as CSSModuleClasses —\n// an index signature, which TypeScript will not narrow straight to a named\n// interface. The names are checked against the SCSS by a test instead.\nconst ctl = ctlModule as unknown as SpaceControlClasses;\nexport default ctl;\n","\"use client\";\nimport type * as React from \"react\";\nimport { cx } from \"./propShared\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"./icons\";\nimport styles from \"./Pagination.module.scss\";\nimport ctl from \"../styles/spaceControls\";\n\n/**\n * The data Pagination needs, in the shape most APIs return beside a page of\n * results. Pass it as `pagination`. When `onPageClick` reports a page, hand\n * back a copy with only `page` changed — the component works out everything\n * else, including how many pages there are, from these three numbers. With\n * `totalItems` at or below `pageSize` there is only one page, and the\n * component renders nothing.\n */\nexport interface PaginationState {\n /** The page being shown, counting from 1. If your API counts from 0, add\n * one before passing it in. A page past either end is clamped to the first\n * or last rather than rejected. */\n page: number;\n /** How many items one page holds — the size you requested, not how many\n * came back on the final page. Must be above zero. */\n pageSize: number;\n /** How many items exist across every page: the full result count, not the\n * length of the page you are showing. Usually the `total` or `count` field\n * of the response. */\n totalItems: number;\n}\n\n/** How many pages a pagination object describes — never fewer than one. */\nexport function pageCount({ pageSize, totalItems }: PaginationState): number {\n if (pageSize <= 0) return 1;\n return Math.max(1, Math.ceil(totalItems / pageSize));\n}\n\n/**\n * The page numbers to offer, with `null` marking a gap to draw as an ellipsis.\n *\n * Always the same length once there are enough pages to need gaps — first,\n * last, `siblings` either side of the current page, and two slots that are\n * either a gap or the single page a gap would have hidden. A window that grew\n * and shrank as you paged would change the control's width under the cursor,\n * so the next click would land on a different number than the last one did.\n *\n * Exported so a caller rendering its own markup can reuse the arithmetic.\n */\nexport function pageWindow(page: number, total: number, siblings = 1): (number | null)[] {\n const range = (from: number, to: number) =>\n Array.from({ length: Math.max(0, to - from + 1) }, (_, i) => from + i);\n\n // first + last + current + siblings either side + two gap slots\n const slots = siblings * 2 + 5;\n if (total <= slots) return range(1, total);\n\n const current = Math.min(Math.max(page, 1), total);\n const left = Math.max(current - siblings, 1);\n const right = Math.min(current + siblings, total);\n // A gap only earns its ellipsis when it hides two or more pages. Hiding one\n // page behind \"…\" costs the same space as just showing it.\n const gapLeft = left > 3;\n const gapRight = right < total - 2;\n const edge = siblings * 2 + 3;\n\n if (!gapLeft) return [...range(1, edge), null, total];\n if (!gapRight) return [1, null, ...range(total - edge + 1, total)];\n return [1, null, ...range(left, right), null, total];\n}\n\nexport interface PaginationProps\n extends Omit<React.HTMLAttributes<HTMLElement>, \"children\"> {\n /** Where the list stands: the current page, the page size, and the total\n * item count. Pass the object your API returns; the page count is derived\n * from it. With one page or fewer nothing renders. */\n pagination: PaginationState;\n /** Called with the page the reader chose — a number, Previous or Next.\n * Not called for the page already showing. Fetch or slice, then hand back\n * an updated `pagination`. */\n onPageClick: (page: number) => void;\n /** Page numbers shown either side of the current one. Default 1. */\n siblings?: number;\n /** Ambient motion: the lit arc orbiting the current page's rim. The glass\n * skin is always applied — only its motion is optional. Default true. */\n animated?: boolean;\n}\n\n/**\n * Page-by-page navigation for a long list.\n *\n * Holds no state: give it the pagination object you already have and it\n * reports which page was clicked.\n *\n * Every control is the same limb-lit glass as Select and Button, but only the\n * current page's rim orbits. Nine arcs turning in one row would be noise; one\n * turning is where you are. Previous and Next stay in place when they\n * cannot be used, so the numbers never slide sideways on the first and last\n * page.\n */\nexport function Pagination({\n pagination,\n onPageClick,\n siblings = 1,\n animated = true,\n className,\n \"aria-label\": ariaLabel = \"Pagination\",\n ...rest\n}: PaginationProps) {\n const total = pageCount(pagination);\n if (total <= 1) return null;\n\n const current = Math.min(Math.max(pagination.page, 1), total);\n\n const go = (target: number) => {\n if (target !== current && target >= 1 && target <= total) onPageClick(target);\n };\n\n return (\n <nav {...rest} aria-label={ariaLabel} className={cx(styles.nav, className)}>\n <button\n type=\"button\"\n className={cx(ctl.spaceControl, styles.item, styles.step)}\n disabled={current <= 1}\n aria-label=\"Previous page\"\n onClick={() => go(current - 1)}\n >\n <ChevronLeftIcon aria-hidden=\"true\" />\n <span className={styles.stepText}>Previous</span>\n </button>\n\n <ol className={styles.pages}>\n {pageWindow(current, total, siblings).map((p, i) =>\n p === null ? (\n // Presentational: \"ellipsis\" read aloud between page numbers tells\n // nobody anything.\n // eslint-disable-next-line react/no-array-index-key\n <li key={`gap-${i}`} className={styles.gap} aria-hidden=\"true\">\n …\n </li>\n ) : (\n <li key={p}>\n <button\n type=\"button\"\n className={cx(\n ctl.spaceControl,\n styles.item,\n styles.page,\n p === current && styles.current,\n )}\n data-animated={p === current && !animated ? \"false\" : undefined}\n aria-label={`Page ${p}`}\n aria-current={p === current ? \"page\" : undefined}\n onClick={() => go(p)}\n >\n {p}\n </button>\n </li>\n ),\n )}\n </ol>\n\n <button\n type=\"button\"\n className={cx(ctl.spaceControl, styles.item, styles.step)}\n disabled={current >= total}\n aria-label=\"Next page\"\n onClick={() => go(current + 1)}\n >\n <span className={styles.stepText}>Next</span>\n <ChevronRightIcon aria-hidden=\"true\" />\n </button>\n </nav>\n );\n}\n","\"use client\";\n\nimport { cx } from \"./propShared\";\nimport styles from \"./Loader.module.scss\";\n\nexport interface LoaderProps {\n /** sm = inline/compact spots. md = default. lg = full-panel takeovers. */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Visible caption under the spinner; also doubles as the accessible name. */\n label?: string;\n /** Merged onto the wrapper. */\n className?: string;\n}\n\n/**\n * An orbital spinner, for work whose length you cannot measure: a small\n * pulsing planet at the centre of a static ring, with a moon travelling it.\n * Where you CAN measure the work, use `Progress` instead — a spinner that\n * could have been a bar tells the reader less than it knows.\n *\n * The motion is pure CSS and runs on the compositor, so it keeps turning\n * smoothly while the main thread is busy doing the thing it is waiting on —\n * which is exactly when a loader is on screen.\n */\nexport function Loader({ size = \"md\", label, className }: LoaderProps) {\n return (\n <div\n className={cx(styles.wrap, styles[size], className)}\n role=\"status\"\n aria-live=\"polite\"\n aria-label={label ?? \"Loading\"}\n >\n <span className={styles.orbit}>\n <span className={styles.planet} />\n <span className={styles.moon} />\n </span>\n {label && <span className={styles.label}>{label}</span>}\n </div>\n );\n}\n","/**\n * Shows a popover-API element after it has been placed, so its reveal starts\n * from the right side.\n *\n * The reveal's starting offset is captured the instant the element first\n * renders, and which way it should travel depends on where it lands — which\n * can flip when there is no room — which needs its size, which needs it\n * rendered. Showing first and measuring after locks a flipped surface into\n * travelling towards its own trigger.\n *\n * So `place` runs while the element is laid out but invisible, with every\n * transition off, and must write the side it chose to `data-side`. The\n * element then returns to unrendered and that state is committed before it is\n * shown, so the real reveal begins fresh from its starting style. Transitions\n * stay off until then: leaving the measurement with them on counts as a\n * dismissal, which keeps the element rendered animating its offset, and the\n * reveal would start from that live value instead.\n *\n * Pairs with the `reveal` mixin, which supplies the `data-measuring` and\n * `data-instant` states this relies on.\n */\nexport function showMeasured(element: HTMLElement, place: () => void): void {\n if (element.matches(\":popover-open\")) return;\n element.dataset.instant = \"\";\n element.dataset.measuring = \"\";\n place();\n delete element.dataset.measuring;\n void element.offsetWidth;\n delete element.dataset.instant;\n void element.offsetWidth;\n element.showPopover();\n}\n","\"use client\";\n\n// Generic hover/focus tooltip for icon-only controls. Built on the same\n// native popover=\"auto\" top-layer pattern as ElementTooltip (and\n// DropdownMenu) rather than a library: Radix is gone from this app, and the\n// platform gives Escape/click-outside dismissal and top-layer stacking for\n// free — which matters here because these triggers sit over WebGL canvases\n// and inside their own stacking contexts.\n//\n// Deliberately NOT the native `title` attribute, which these controls used\n// before: the browser's own tooltip waits about a second, cannot be styled\n// to match the app, and never appears for keyboard users at all.\n\nimport {\n cloneElement, isValidElement, useEffect, useId, useLayoutEffect, useRef, useState,\n} from \"react\";\nimport styles from \"./Tooltip.module.scss\";\nimport { showMeasured } from \"../internal/showMeasured\";\n\ninterface TooltipProps {\n /** The text to show. Nothing renders when this is empty. */\n label: string;\n /** Preferred side; flips to the opposite one when there isn't room.\n * `left`/`right` are for a control in a vertical stack, where a tooltip\n * above or below would land on the neighbouring item. */\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n /** The element the tooltip describes. Receives the hover and focus\n * handlers, so it must accept a ref. */\n children: React.ReactElement;\n}\n\nconst SHOW_DELAY = 350;\nconst HIDE_DELAY = 80;\nconst SIDE_OFFSET = 8;\nconst COLLISION_PADDING = 8;\n\n// The clone lives in its own component so this scope never dereferences\n// triggerRef itself — the React Compiler flags a ref that is BOTH passed\n// into cloneElement's props and read in the same scope. Same split, and the\n// same reason, as ElementTooltip's TooltipTrigger.\ninterface TriggerProps {\n triggerRef: React.RefObject<HTMLElement | null>;\n tooltipId: string;\n show: (immediate?: boolean) => void;\n hide: () => void;\n children: React.ReactElement<Record<string, unknown>>;\n}\nfunction TooltipTrigger({ triggerRef, tooltipId, show, hide, children }: TriggerProps) {\n const p = children.props;\n return cloneElement(children, {\n ref: triggerRef,\n // Always present, so the id it points at never dangles: the content\n // element stays mounted and only toggles its popover state.\n \"aria-describedby\": tooltipId,\n onPointerEnter: (e: React.PointerEvent) => {\n (p.onPointerEnter as ((e: React.PointerEvent) => void) | undefined)?.(e);\n // Mouse only. A touch \"hover\" fires on tap, which would pop a tooltip\n // over the very control the user just pressed.\n if (e.pointerType === \"mouse\") show();\n },\n onPointerLeave: (e: React.PointerEvent) => {\n (p.onPointerLeave as ((e: React.PointerEvent) => void) | undefined)?.(e);\n hide();\n },\n // Keyboard focus shows it immediately — no hover delay to wait out.\n onFocus: (e: React.FocusEvent) => {\n (p.onFocus as ((e: React.FocusEvent) => void) | undefined)?.(e);\n show(true);\n },\n onBlur: (e: React.FocusEvent) => {\n (p.onBlur as ((e: React.FocusEvent) => void) | undefined)?.(e);\n hide();\n },\n // A tooltip must never outlive the action it describes: clicking the\n // control (expand, switch view) leaves it stranded over the new layout.\n onClick: (e: React.MouseEvent) => {\n (p.onClick as ((e: React.MouseEvent) => void) | undefined)?.(e);\n hide();\n },\n });\n}\n\n/**\n * A short label revealed on hover or focus, for naming a control whose icon\n * is not self-evident.\n *\n * Never put information here that a reader needs: a tooltip is unreachable on\n * touch and easy to miss. If it must be read, put it on the page.\n */\nexport function Tooltip({ label, side = \"bottom\", children }: TooltipProps) {\n const tooltipId = useId();\n const [open, setOpen] = useState(false);\n const [pos, setPos] = useState<{ top: number; left: number } | null>(null);\n const triggerRef = useRef<HTMLElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n const showTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearTimers = () => {\n if (showTimer.current) { clearTimeout(showTimer.current); showTimer.current = null; }\n if (hideTimer.current) { clearTimeout(hideTimer.current); hideTimer.current = null; }\n };\n const show = (immediate = false) => {\n clearTimers();\n if (immediate) { setOpen(true); return; }\n showTimer.current = setTimeout(() => setOpen(true), SHOW_DELAY);\n };\n const hide = () => {\n clearTimers();\n hideTimer.current = setTimeout(() => setOpen(false), HIDE_DELAY);\n };\n\n useEffect(() => clearTimers, []);\n\n useLayoutEffect(() => {\n const content = contentRef.current;\n if (!content) return;\n if (!open) {\n if (content.matches(\":popover-open\")) content.hidePopover();\n return;\n }\n const trigger = triggerRef.current;\n if (!trigger) return;\n\n // Measured while laid out — its size reads 0 while display:none — and\n // records the side it lands on, so the reveal can travel away from the\n // trigger. Run once before it is shown (see showMeasured) and again on a\n // label change while already open.\n const place = () => {\n const r = trigger.getBoundingClientRect();\n const w = content.offsetWidth;\n const h = content.offsetHeight;\n\n // Centre on the trigger along the free axis, clamped inside the viewport.\n const centre = (start: number, size: number, extent: number, viewport: number) =>\n Math.min(\n Math.max(start + size / 2 - extent / 2, COLLISION_PADDING),\n Math.max(viewport - extent - COLLISION_PADDING, COLLISION_PADDING),\n );\n\n // Flip to the opposite side when the preferred one has no room — these\n // controls sit in the top row, the bottom action bar, and a rail down\n // the edge, so any of the four can be the side without space.\n const fits = (near: number, far: number, size: number, viewport: number) => ({\n fitsNear: near >= COLLISION_PADDING,\n fitsFar: far + size <= viewport - COLLISION_PADDING,\n });\n\n if (side === \"left\" || side === \"right\") {\n const after = r.right + SIDE_OFFSET;\n const before = r.left - w - SIDE_OFFSET;\n const { fitsNear: fitsBefore, fitsFar: fitsAfter } =\n fits(before, after, w, window.innerWidth);\n const left = side === \"right\"\n ? (fitsAfter || !fitsBefore ? after : before)\n : (fitsBefore || !fitsAfter ? before : after);\n content.dataset.side = left === after ? \"right\" : \"left\";\n setPos({ top: centre(r.top, r.height, h, window.innerHeight), left });\n return;\n }\n\n const below = r.bottom + SIDE_OFFSET;\n const above = r.top - h - SIDE_OFFSET;\n const { fitsNear: fitsAbove, fitsFar: fitsBelow } =\n fits(above, below, h, window.innerHeight);\n const top = side === \"bottom\"\n ? (fitsBelow || !fitsAbove ? below : above)\n : (fitsAbove || !fitsBelow ? above : below);\n content.dataset.side = top === below ? \"bottom\" : \"top\";\n setPos({ top, left: centre(r.left, r.width, w, window.innerWidth) });\n };\n\n if (content.matches(\":popover-open\")) place();\n else showMeasured(content, place);\n }, [open, side, label]);\n\n if (!label || !isValidElement(children)) return <>{children}</>;\n\n return (\n <>\n <TooltipTrigger\n triggerRef={triggerRef}\n tooltipId={tooltipId}\n show={show}\n hide={hide}\n >\n {children as React.ReactElement<Record<string, unknown>>}\n </TooltipTrigger>\n <div\n ref={contentRef}\n id={tooltipId}\n popover=\"auto\"\n role=\"tooltip\"\n className={styles.content}\n style={pos ? { top: pos.top, left: pos.left } : undefined}\n onToggle={(e: React.SyntheticEvent<HTMLDivElement>) => {\n if ((e.nativeEvent as ToggleEvent).newState === \"closed\" && open) setOpen(false);\n }}\n >\n {label}\n </div>\n </>\n );\n}\n","\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { Tooltip } from \"./Tooltip\";\nimport styles from \"./IconToggle.module.scss\";\n\nexport interface IconToggleOption<V extends string> {\n value: V;\n icon: ReactNode;\n /** Used for aria-label and the hover tooltip. */\n label: string;\n}\n\n/**\n * A segmented icon toggle: every option visible at once in a single pill, the\n * selected one reading as active, and a click on any of them selecting it.\n *\n * Reach for it to switch between modes or views of the same thing, where the\n * options are few and each has an obvious glyph. The alternative pattern — one\n * button that shows the mode you are NOT in and swaps its own icon on click —\n * is deliberately not what this does: the control's meaning changes under the\n * cursor, and nobody can tell whether the icon means \"you are here\" or \"go\n * here\". Generic over the option set, so the values stay your own union type.\n */\nexport function IconToggle<V extends string>({\n options,\n value,\n onValueChange,\n orientation = \"horizontal\",\n className = \"\",\n}: {\n /** The segments, in display order. Every option is always visible —\n * this is a segmented control, not a menu.\n */\n options: IconToggleOption<V>[];\n /** The selected option's value. Fully controlled.\n *\n * NoInfer so V is derived from `options` alone. Without it a value that is\n * not among the options simply widened V to include itself, which made the\n * generic silently accept the one mistake it looks like it should catch. */\n value: NoInfer<V>;\n /** Called with the newly selected value. Not called when the already\n * selected option is clicked. */\n onValueChange(next: V): void;\n /** Which way the pill runs. `vertical` for a rail down the edge of a\n * viewport, where a horizontal strip would eat the width. Default\n * `horizontal`. */\n orientation?: \"horizontal\" | \"vertical\";\n /** Merged onto the group wrapper. */\n className?: string;\n}) {\n const vertical = orientation === \"vertical\";\n return (\n <div\n className={`${styles.group} ${vertical ? styles.vertical : \"\"} ${className}`}\n role=\"group\"\n >\n {options.map((opt) => (\n // A horizontal pill sits at the top of the scene, so its tooltips hang\n // below it. A vertical one has a segment directly below every segment,\n // so they go to the side instead — otherwise each tooltip covers the\n // next option along.\n <Tooltip key={opt.value} label={opt.label} side={vertical ? \"right\" : \"bottom\"}>\n <button\n type=\"button\"\n className={`${styles.segment} ${opt.value === value ? styles.active : \"\"}`}\n aria-label={opt.label}\n aria-pressed={opt.value === value}\n onClick={() => {\n if (opt.value !== value) onValueChange(opt.value);\n }}\n >\n {opt.icon}\n </button>\n </Tooltip>\n ))}\n </div>\n );\n}\n","// A single-choice menu. One component and one child type:\n//\n// <Select value={v} onValueChange={setV}>\n// <Select.Item value=\"a\">A</Select.Item>\n// </Select>\n//\n// It used to be Root/Trigger/Content/Item, mirroring the JSX shape of the\n// library this was migrated from. Three of those four were ceremony: the\n// trigger was mandatory and identical at every call site, and Content only\n// ever wrapped Items. They are now built in, which is why `Select` is the\n// component itself rather than a namespace.\n//\n// Native engine: a <button> trigger plus an always-mounted listbox that rides\n// the browser's own popover layer. It stays where it is in the DOM — so the\n// component is still one subtree, and a click inside it is still a click\n// inside the Select — while rendering in the top layer, above every ancestor.\n// That is what lets a Select inside a Dialog, or any container that clips or\n// contains its children, drop its panel over the lot. No React portal: a\n// portal would move the node, and with it the event paths and the focus order\n// this relies on.\n\"use client\";\nimport type * as React from \"react\";\nimport {\n Children, createContext, isValidElement, useCallback, useContext,\n useEffect, useId, useLayoutEffect, useMemo, useRef, useState, type ReactNode,\n} from \"react\";\nimport { cx } from \"./propShared\";\nimport { showMeasured } from \"../internal/showMeasured\";\nimport styles from \"./Select.module.scss\";\nimport ctl from \"../styles/spaceControls\";\n\ninterface RootCtx {\n value: string;\n onValueChange: (v: string) => void;\n disabled?: boolean;\n open: boolean;\n setOpen: (o: boolean) => void;\n highlighted: string | null;\n setHighlighted: (v: string | null) => void;\n listboxId: string;\n values: string[];\n labelFor: (v: string) => ReactNode;\n /** Previously carried in its own context, because with Trigger and Content\n * as separate components a ref sitting beside plain state made every read\n * of the OTHER fields look like a render-time ref access to\n * react-hooks/refs. Only Item reads it now, and only inside an event\n * handler, so the split bought nothing. Keep it that way: read `.current`\n * in handlers and effects, never during render. */\n triggerRef: React.RefObject<HTMLButtonElement | null>;\n}\nconst Ctx = createContext<RootCtx | null>(null);\nconst useSelect = () => {\n const ctx = useContext(Ctx);\n if (!ctx) throw new Error(\"Select.Item must be inside a Select\");\n return ctx;\n};\n\n// Shared id contract between the listbox's aria-activedescendant and each\n// Item's id. encodeURIComponent guards against values containing spaces or\n// other characters that aren't legal in an HTML id.\nconst optionId = (listboxId: string, value: string) => `${listboxId}-${encodeURIComponent(value)}`;\n\n/** Gap between trigger and panel, and the least room to leave at a viewport\n * edge — the same values Popover places by. */\nconst OFFSET = 4;\nconst EDGE_PADDING = 8;\n\n/** Pure render-time walk of the children collecting Item values and labels —\n * no effects, so the trigger label is correct on first paint, under SSR, and\n * in renderToStaticMarkup tests. Recurses, so Items may be wrapped (a\n * fragment, a `.map`, a grouping element) rather than being direct children. */\nfunction collectItems(children: ReactNode): Array<{ value: string; label: ReactNode; disabled?: boolean }> {\n const out: Array<{ value: string; label: ReactNode; disabled?: boolean }> = [];\n const walk = (nodes: ReactNode) => {\n Children.forEach(nodes, (child) => {\n if (!isValidElement(child)) return;\n const props = child.props as { value?: string; children?: ReactNode; disabled?: boolean };\n if (child.type === Item && typeof props.value === \"string\") {\n out.push({ value: props.value, label: props.children, disabled: props.disabled });\n } else if (props.children) {\n walk(props.children);\n }\n });\n };\n walk(children);\n return out;\n}\n\nexport interface SelectProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"value\" | \"children\" | \"onChange\"> {\n /** The selected item's value. Fully controlled. */\n value: string;\n /** Called with the newly selected value. */\n onValueChange: (v: string) => void;\n /** Blocks the trigger and removes it from the tab order. */\n disabled?: boolean;\n /** Shown when nothing is selected. Counts toward the control's width, so\n * selecting an option never resizes it. */\n placeholder?: string;\n /** Ambient motion: the lit arc orbiting the rim. The glass skin itself is\n * always applied. Default true. */\n animated?: boolean;\n /** One or more `Select.Item`. Anything else is ignored for selection but\n * still rendered in the panel. */\n children?: ReactNode;\n}\n\n/**\n * A single-choice menu for lists too long to show inline. Fully controlled.\n *\n * The control sizes itself to its widest option, so it never changes width as\n * you select — capped by `--sp-select-trigger-max-width`, past which the label\n * ellipsizes.\n *\n * Reads its options at render time rather than through effects, so the right\n * label shows on first paint and under SSR.\n *\n * Every prop other than the ones listed lands on the trigger button, which is\n * the focusable control — so `aria-label`, `id`, `name` and `onBlur` go where\n * you would expect.\n */\nfunction SelectRoot({\n value,\n onValueChange,\n disabled,\n placeholder,\n animated = true,\n className,\n children,\n ...rest\n}: SelectProps) {\n const [open, setOpen] = useState(false);\n const [highlighted, setHighlighted] = useState<string | null>(null);\n const listboxId = useId();\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const rootRef = useRef<HTMLDivElement | null>(null);\n const listRef = useRef<HTMLDivElement | null>(null);\n const [triggerWidth, setTriggerWidth] = useState<number | null>(null);\n const [maxHeight, setMaxHeight] = useState<number | null>(null);\n // Where the panel sits in the viewport. Fixed coordinates, because a\n // top-layer element is positioned against the viewport rather than against\n // any ancestor of its own.\n const [pos, setPos] = useState<{ top: number; left: number } | null>(null);\n\n const items = useMemo(() => collectItems(children), [children]);\n const values = useMemo(() => items.filter((i) => !i.disabled).map((i) => i.value), [items]);\n const itemLabels = useMemo(() => items.map((i) => i.label), [items]);\n const labelFor = useCallback(\n (v: string) => items.find((i) => i.value === v)?.label ?? null,\n [items],\n );\n\n // Light-dismiss: click outside closes.\n useEffect(() => {\n if (!open) return;\n const onDown = (e: MouseEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener(\"mousedown\", onDown);\n return () => document.removeEventListener(\"mousedown\", onDown);\n }, [open]);\n\n // Measures the trigger to size and place the panel: its width, the room\n // below it, and the viewport coordinates to sit at. One layout read, and\n // the panel writes the side it landed on for the reveal to travel away from.\n const place = useCallback(() => {\n const trigger = triggerRef.current;\n const list = listRef.current;\n if (!trigger || !list) return;\n const rect = trigger.getBoundingClientRect();\n setTriggerWidth(trigger.offsetWidth);\n\n const below = window.innerHeight - rect.bottom - EDGE_PADDING;\n const above = rect.top - EDGE_PADDING;\n // Below unless there is markedly more room above: a menu that jumps sides\n // for a few pixels' gain reads as a glitch.\n const flip = below < Math.min(list.offsetHeight + OFFSET, 200) && above > below;\n const room = Math.max(120, Math.min(380, flip ? above - OFFSET : below - OFFSET));\n setMaxHeight(room);\n list.dataset.side = flip ? \"top\" : \"bottom\";\n\n const height = Math.min(list.offsetHeight, room);\n const top = flip ? Math.max(EDGE_PADDING, rect.top - OFFSET - height) : rect.bottom + OFFSET;\n // Kept on screen: a panel wider than its trigger near the right edge\n // slides back in rather than running off.\n const left = Math.min(\n Math.max(rect.left, EDGE_PADDING),\n Math.max(window.innerWidth - list.offsetWidth - EDGE_PADDING, EDGE_PADDING),\n );\n setPos((prev) => (prev && prev.top === top && prev.left === left ? prev : { top, left }));\n }, []);\n\n // Placed while laid out but invisible, then shown, so the reveal starts from\n // the right side. Layout effect: the corrected position lands before paint.\n useLayoutEffect(() => {\n const list = listRef.current;\n if (!list) return;\n if (open) {\n showMeasured(list, place);\n place();\n } else if (list.matches(\":popover-open\")) {\n list.hidePopover();\n }\n }, [open, place]);\n\n // Follow the trigger while open. Scroll and resize listeners are not enough:\n // anything that moves the trigger without scrolling — a dialog resizing, an\n // image loading above it — would leave the panel behind, and a top-layer\n // element cannot simply ride along with its ancestor the way an absolutely\n // positioned one does. One layout read a frame, and only while open.\n useEffect(() => {\n if (!open) return;\n let frame = 0;\n let last = \"\";\n const track = () => {\n const trigger = triggerRef.current;\n if (trigger) {\n const r = trigger.getBoundingClientRect();\n const key = `${r.top}|${r.left}|${r.width}|${window.innerWidth}|${window.innerHeight}`;\n if (key !== last) {\n last = key;\n place();\n }\n }\n frame = requestAnimationFrame(track);\n };\n frame = requestAnimationFrame(track);\n return () => cancelAnimationFrame(frame);\n }, [open, place]);\n\n // Focus the listbox on open so arrow keys work immediately.\n useEffect(() => {\n if (open) listRef.current?.focus();\n }, [open]);\n\n const openWith = (highlight: string | null) => {\n setHighlighted(highlight ?? values[0] ?? null);\n setOpen(true);\n };\n\n const move = (delta: number) => {\n const idx = highlighted ? values.indexOf(highlighted) : -1;\n const next = Math.min(Math.max(idx + delta, 0), values.length - 1);\n setHighlighted(values[next] ?? null);\n };\n\n const label = value ? labelFor(value) : null;\n\n return (\n <Ctx.Provider\n value={{\n value, onValueChange, disabled, open, setOpen, highlighted,\n setHighlighted, listboxId, values, labelFor, triggerRef,\n }}\n >\n <div ref={rootRef} className={styles.root}>\n <button\n type=\"button\"\n {...rest}\n ref={triggerRef}\n disabled={disabled}\n className={cx(styles.trigger, ctl.spaceControl, \"spSelectTrigger\", className)}\n data-animated={animated ? undefined : \"false\"}\n data-state={open ? \"open\" : \"closed\"}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-controls={listboxId}\n onClick={() => (open ? setOpen(false) : openWith(value || null))}\n onKeyDown={(e) => {\n if (e.key === \"ArrowDown\" || e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n openWith(value || null);\n }\n }}\n >\n {/* The visible label and a hidden copy of every option share one\n grid cell, so the button is as wide as its widest choice and\n never jumps width when the selection changes. Capped by\n --sp-select-trigger-max-width, past which the label ellipsizes. */}\n <span className={styles.labelWrap}>\n <span className={styles.sizer} data-sizer=\"\" aria-hidden=\"true\">\n {itemLabels.map((l, i) => (\n // eslint-disable-next-line react/no-array-index-key\n <span key={i}>{l}</span>\n ))}\n {placeholder && <span>{placeholder}</span>}\n </span>\n <span className={styles.triggerLabel}>{label ?? placeholder ?? \"\"}</span>\n </span>\n <svg className={styles.chevron} width=\"9\" height=\"9\" viewBox=\"0 0 9 9\" aria-hidden=\"true\">\n <path d=\"M0.5 3 L4.5 7 L8.5 3\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.2\" />\n </svg>\n </button>\n\n {/* Always mounted, so the trigger can read the item labels for sizing\n before the panel has ever been opened.\n\n popover=\"manual\", not \"auto\": auto would light-dismiss on the\n pointerdown that presses the trigger, so the click that follows\n would reopen a panel the reader meant to close. The outside-press\n listener above already closes it, and Escape is handled below. */}\n <div\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n tabIndex={-1}\n popover=\"manual\"\n data-side=\"bottom\"\n aria-activedescendant={highlighted ? optionId(listboxId, highlighted) : undefined}\n className={cx(styles.listbox, ctl.spacePanel)}\n data-animated={animated ? undefined : \"false\"}\n style={\n {\n ...(triggerWidth != null ? { \"--_select-trigger-width\": `${triggerWidth}px` } : {}),\n ...(maxHeight != null ? { maxHeight: `${maxHeight}px` } : {}),\n ...(pos ? { top: pos.top, left: pos.left } : {}),\n } as React.CSSProperties\n }\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n e.stopPropagation(); // don't let an ancestor Dialog close too\n setOpen(false);\n triggerRef.current?.focus();\n } else if (e.key === \"ArrowDown\") { e.preventDefault(); move(1); }\n else if (e.key === \"ArrowUp\") { e.preventDefault(); move(-1); }\n else if (e.key === \"Home\") { e.preventDefault(); setHighlighted(values[0] ?? null); }\n else if (e.key === \"End\") { e.preventDefault(); setHighlighted(values[values.length - 1] ?? null); }\n else if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n if (highlighted) {\n onValueChange(highlighted);\n setOpen(false);\n triggerRef.current?.focus();\n }\n } else if (e.key === \"Tab\") {\n setOpen(false);\n }\n }}\n >\n {children}\n </div>\n </div>\n </Ctx.Provider>\n );\n}\n\nexport interface SelectItemProps {\n /** Reported to onValueChange when chosen. */\n value: string;\n /** Skipped by keyboard navigation and not selectable. Still contributes its\n * width to the control's sizing. */\n disabled?: boolean;\n /** Shown in the panel and, once selected, in the closed control — so it has\n * to read correctly in both places. */\n children?: ReactNode;\n}\n\n/**\n * One option. Its children are what the closed control displays once\n * selected, so anything rendered here has to read correctly in both places.\n */\nfunction Item({ value, disabled, children }: SelectItemProps) {\n const s = useSelect();\n const selected = s.value === value;\n const highlighted = s.highlighted === value;\n return (\n <div\n id={optionId(s.listboxId, value)}\n role=\"option\"\n aria-selected={selected}\n aria-disabled={disabled || undefined}\n data-highlighted={highlighted ? \"\" : undefined}\n className={cx(styles.item, \"spSelectItem\")}\n onMouseEnter={() => !disabled && s.setHighlighted(value)}\n onClick={() => {\n if (disabled) return;\n s.onValueChange(value);\n s.setOpen(false);\n s.triggerRef.current?.focus();\n }}\n >\n {children}\n </div>\n );\n}\n\n/**\n * Choosing one value from a list, with the list kept out of the way until it\n * is wanted.\n *\n * The right control when the options are many, or dull, or both — a country, a\n * size, a sort order. Where there are few options and each one deserves to be\n * read, `RadioGroup` shows them all without a click. Where the items are\n * actions rather than values, that is `DropdownMenu`.\n *\n * The panel opens on the browser's popover layer, which is what lets it escape\n * a dialog, a transformed ancestor or a clipping overflow and sit above the\n * page at its full height. It flips above the trigger when there is no room\n * below, follows the trigger if the page scrolls, and closes on Escape with\n * focus handed back. Typing jumps to a matching option.\n *\n * Compose it from `Select.Item`.\n */\nexport const Select = Object.assign(SelectRoot, { Item });\n","\"use client\";\nimport type * as React from \"react\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./TextField.module.scss\";\nimport ctl from \"../styles/spaceControls\";\n\nexport interface TextFieldProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"className\" | \"style\"> {\n /** Merged onto the field wrapper, not the inner input. */\n className?: string;\n /** Ambient motion on the rim. The glass skin is always applied.\n * Default true. */\n animated?: boolean;\n /** Applied to the field wrapper — set width here. */\n style?: React.CSSProperties;\n /** Slots rendered inside the field, alongside the input. */\n children?: ReactNode; // Slot(s)\n}\n\n/**\n * Single-line text entry. The field surface is a wrapper around the input so\n * `TextField.Slot` can sit alongside it inside the same surface — that\n * wrapper is built in rather than being something you compose.\n *\n * Props land on the inner input, so `value`, `onChange` and the rest behave\n * as they would on a bare input. `className` and `style` land on the field\n * surface instead, which is where width belongs.\n *\n * The ref forwards to the input, not the wrapper.\n */\nconst TextFieldRoot = forwardRef<HTMLInputElement, TextFieldProps>(function TextField(\n { className, style, animated = true, children, ...inputProps },\n ref,\n) {\n return (\n <div\n className={cx(styles.root, ctl.spaceInput, \"spTextFieldRoot\", className)}\n data-animated={animated ? undefined : \"false\"}\n style={style}\n >\n {children}\n <input {...inputProps} ref={ref} className={cx(styles.input, \"spTextFieldInput\")} />\n </div>\n );\n});\n\n/**\n * A fixed element inside the field, before or after the input — an icon, a\n * unit, a short affordance. Sits within the field's surface rather than\n * beside it, and does not shrink as the input fills.\n */\nfunction Slot({\n children,\n}: {\n /** The slot's contents — an icon, a unit, a short affordance. */\n children?: ReactNode;\n}) {\n return <span className={styles.slot}>{children}</span>;\n}\n\n/**\n * A single line of text the reader types.\n *\n * A real `<input>` underneath, so `value`, `onChange`, `type`, `required`,\n * `autoComplete` and the rest of the native attributes all work as they\n * already do, and the browser's own autofill and validation come along with\n * them. For more than a line, use `TextArea`.\n *\n * Put an icon, a unit or a small button beside the text with `TextField.Slot`.\n * It sits inside the field's rim and keeps its own padding, so the text never\n * runs underneath it.\n */\nexport const TextField = Object.assign(TextFieldRoot, { Slot });\n","\"use client\";\nimport type * as React from \"react\";\nimport { forwardRef } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./TextArea.module.scss\";\nimport ctl from \"../styles/spaceControls\";\n\nexport interface TextAreaProps\n extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, \"className\" | \"style\"> {\n /** Merged onto the field wrapper, not the inner textarea. */\n className?: string;\n /** Ambient motion on the rim. The glass skin is always applied.\n * Default true. */\n animated?: boolean;\n /** Applied to the field wrapper — set width here. */\n style?: React.CSSProperties;\n}\n\n/**\n * Multi-line text entry. `rows` sets the initial height; it grows with its\n * container's width and resizes vertically only, since horizontal drag would\n * break the surrounding layout.\n */\nexport const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(function TextArea(\n { className, style, animated = true, ...rest },\n ref,\n) {\n return (\n <div\n className={cx(styles.root, ctl.spaceInput, ctl.spaceTextArea, \"spTextFieldRoot\", className)}\n data-animated={animated ? undefined : \"false\"}\n style={style}\n >\n <textarea {...rest} ref={ref} className={cx(styles.textarea, \"spTextAreaInput\")} />\n </div>\n );\n});\n","// A text field with a result list hanging under it.\n//\n// It never fetches and never ranks: the consumer hands it the candidate rows,\n// from memory or from an API, in whatever order that domain considers best.\n// What it does own is the narrowing — matching the typed text against those\n// rows — plus the popover, the keyboard model and the aria wiring. Those are\n// the parts every autocomplete needs and nobody enjoys writing twice.\n//\n// A caller whose rows were already matched server-side passes `preFiltered`\n// and the narrowing is skipped, so a fuzzy or synonym match made elsewhere is\n// not undone by a plain substring test here.\n\"use client\";\nimport type * as React from \"react\";\nimport {\n useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, type ReactNode,\n} from \"react\";\nimport { cx } from \"./propShared\";\nimport { showMeasured } from \"../internal/showMeasured\";\nimport { TextField } from \"./TextField\";\nimport styles from \"./Autocomplete.module.scss\";\nimport ctl from \"../styles/spaceControls\";\n\nexport interface AutocompleteOption {\n /** Handed back to `onSelect` when this row is chosen. */\n value: string;\n /** The row's main text. */\n label: ReactNode;\n /** Optional secondary text, set against the trailing edge — a category, a\n * score, a date. Kept out of `label` so it stays visually subordinate and\n * does not affect which row a reader scans for. */\n meta?: ReactNode;\n /** Shown, but skipped by the keyboard and unselectable. */\n disabled?: boolean;\n /** The text the typed query is matched against, when `label` is not a plain\n * string. Falls back to `label` if it is one, and to `value` otherwise —\n * and `value` is usually a slug, which is rarely what someone is typing. */\n search?: string;\n}\n\nexport interface AutocompleteProps\n extends Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n \"value\" | \"onChange\" | \"onSelect\" | \"className\" | \"style\"\n > {\n /** The text in the field. Fully controlled. */\n value: string;\n /** Called on every keystroke. */\n onValueChange: (value: string) => void;\n /** The candidate rows, in the order you want them shown. They are narrowed\n * against what has been typed unless `preFiltered` is set; the order you\n * give is always preserved, so ranking stays yours. Nothing is offered\n * until something has been typed. Past that, an empty array with no\n * `loading` and no `emptyMessage` still shows no panel, which is how you\n * hold it shut below a minimum query length. */\n options: AutocompleteOption[];\n /** Called when a row is chosen by click or Enter. */\n onSelect: (value: string, option: AutocompleteOption) => void;\n /** Renders a leading glyph inside the field — a magnifier, usually. */\n icon?: ReactNode;\n /** Match exactly as typed, so `trappist` no longer finds `TRAPPIST`.\n * Default off, which is what nearly every search wants. */\n caseSensitive?: boolean;\n /** The rows were already matched — by a server, a fuzzy search, a synonym\n * table — so render them as given. Without this a substring test here\n * would silently drop rows a smarter match upstream had found. */\n preFiltered?: boolean;\n /** Replaces the list with a waiting message while results are on their way. */\n loading?: boolean;\n /** What that waiting message says. Name the thing being fetched — \"Loading\n * the catalogue…\" tells a reader more than a spinner's worth of nothing.\n * Default \"Loading…\". */\n loadingMessage?: ReactNode;\n /** Shown when there are no options and nothing is loading. Leave it out to\n * show no panel at all rather than an empty one. */\n emptyMessage?: ReactNode;\n /** A line under the list, outside its scroll area — \"showing 50 of 2,700\",\n * a hint, a keyboard legend. */\n footer?: ReactNode;\n /** Ambient motion on the field's rim. The glass skin is always applied.\n * Default true. */\n animated?: boolean;\n /** Merged onto the wrapper, which is what you size. */\n className?: string;\n /** Applied to the wrapper — set width here. */\n style?: React.CSSProperties;\n}\n\n/** Gap between field and panel, and the least room to leave at a viewport\n * edge — the same values Select and Popover place by. */\nconst OFFSET = 8;\nconst EDGE_PADDING = 8;\n\n/**\n * A text field that offers matching rows as you type.\n *\n * It holds no data of its own. Give it `options` and it renders them,\n * highlights one, moves that highlight with the arrow keys, and calls\n * `onSelect` when a row is chosen — however those options were produced.\n *\n * The list is a popover rather than a block in the flow: results that appear\n * mid-keystroke and push the page down under the cursor are disorienting, and\n * whatever is being searched usually sits directly below the field.\n */\nexport function Autocomplete({\n value,\n onValueChange,\n options,\n onSelect,\n icon,\n caseSensitive = false,\n preFiltered = false,\n loading = false,\n loadingMessage = \"Loading…\",\n emptyMessage,\n footer,\n animated = true,\n className,\n style,\n ...inputProps\n}: AutocompleteProps) {\n const [open, setOpen] = useState(false);\n const [active, setActive] = useState(0);\n const wrapRef = useRef<HTMLDivElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const listRef = useRef<HTMLUListElement>(null);\n const listId = useId();\n // Viewport coordinates for the panel, which renders in the browser's top\n // layer and so is placed against the viewport rather than the field.\n const [pos, setPos] = useState<{ top: number; left: number; width: number } | null>(null);\n\n // What a row is matched on: its label when that is plain text, an explicit\n // `search` when the label is markup, and the value as a last resort.\n const haystack = (o: AutocompleteOption) =>\n typeof o.label === \"string\" ? o.label : (o.search ?? o.value);\n\n // Nothing typed, nothing offered. An empty query used to let every option\n // through, so focusing the field dropped the whole dataset open before the\n // reader had asked for anything. Whitespace counts as empty.\n const hasQuery = value.trim() !== \"\";\n\n const shown = useMemo(() => {\n if (!hasQuery) return [];\n if (preFiltered) return options;\n const needle = caseSensitive ? value : value.toLowerCase();\n return options.filter((o) => {\n const text = caseSensitive ? haystack(o) : haystack(o).toLowerCase();\n return text.includes(needle);\n });\n }, [options, value, caseSensitive, preFiltered, hasQuery]);\n\n const selectable = useMemo(() => shown.filter((o) => !o.disabled), [shown]);\n\n // Nothing to say, no panel. With no query there is never anything to say —\n // not the rows, not a loading line, and not an empty message that would\n // report \"nothing matching\" for a search nobody has typed. Past that, a\n // consumer can still keep the panel shut below a minimum length by sending\n // no options, no loading and no message.\n const hasContent = hasQuery && (shown.length > 0 || loading || emptyMessage != null);\n const showPanel = open && hasContent;\n\n // A changed result set invalidates the highlight — it pointed at a row that\n // may no longer exist, let alone be the best match.\n useEffect(() => setActive(0), [shown]);\n\n // \"nearest\" scrolls only when the row is actually out of view, so walking a\n // visible list does not jump the container under the cursor.\n useEffect(() => {\n if (!showPanel) return;\n const el = listRef.current?.querySelector<HTMLElement>(`[data-index=\"${active}\"]`);\n el?.scrollIntoView({ block: \"nearest\" });\n }, [active, showPanel]);\n\n // Under the field, as wide as it, clamped to the viewport — and flipped\n // above when there is not enough room below.\n const place = useCallback(() => {\n const wrap = wrapRef.current;\n const panel = panelRef.current;\n if (!wrap || !panel) return;\n // The control itself, not the wrapper around it: the wrapper also holds\n // the panel, so measuring it put the panel below its own height and gave\n // it the wrong width.\n const field = wrap.firstElementChild ?? wrap;\n const rect = field.getBoundingClientRect();\n const height = panel.offsetHeight;\n const below = window.innerHeight - rect.bottom - EDGE_PADDING;\n const flip = below < height && rect.top - EDGE_PADDING > below;\n panel.dataset.side = flip ? \"top\" : \"bottom\";\n const top = flip ? Math.max(EDGE_PADDING, rect.top - OFFSET - height) : rect.bottom + OFFSET;\n setPos((prev) =>\n prev && prev.top === top && prev.left === rect.left && prev.width === rect.width\n ? prev\n : { top, left: rect.left, width: rect.width },\n );\n }, []);\n\n // Placed while laid out but invisible, then shown, so the reveal starts from\n // the side it landed on. Layout effect: placed before the first paint.\n useLayoutEffect(() => {\n const panel = panelRef.current;\n if (!panel) return;\n if (showPanel) {\n showMeasured(panel, place);\n place();\n } else if (panel.matches(\":popover-open\")) {\n panel.hidePopover();\n }\n }, [showPanel, place]);\n\n // Follow the field while the panel is open. A top-layer element cannot ride\n // along with an ancestor the way an absolutely positioned one does, so\n // anything that moves the field — a scroll, a dialog resizing, the list\n // growing as results arrive — has to be tracked. One layout read a frame.\n useEffect(() => {\n if (!showPanel) return;\n let frame = 0;\n let last = \"\";\n const track = () => {\n const field = wrapRef.current;\n const panel = panelRef.current;\n if (field && panel) {\n const r = (field.firstElementChild ?? field).getBoundingClientRect();\n const key = `${r.top}|${r.left}|${r.width}|${panel.offsetHeight}|${window.innerHeight}`;\n if (key !== last) {\n last = key;\n place();\n }\n }\n frame = requestAnimationFrame(track);\n };\n frame = requestAnimationFrame(track);\n return () => cancelAnimationFrame(frame);\n }, [showPanel, place]);\n\n // pointerdown, not click: a drag that starts inside the panel and ends\n // outside it is not an outside click, and the dismissal should land before\n // whatever sits underneath can fire.\n const close = useCallback(() => setOpen(false), []);\n useEffect(() => {\n if (!showPanel) return;\n const onDown = (e: PointerEvent) => {\n const node = wrapRef.current;\n if (node && e.target instanceof Node && !node.contains(e.target)) close();\n };\n document.addEventListener(\"pointerdown\", onDown);\n return () => document.removeEventListener(\"pointerdown\", onDown);\n }, [showPanel, close]);\n\n // Whether the reader has moved the highlight with the keyboard since they\n // last typed. Space selects only then: the first row is highlighted the\n // moment results appear, so a Space that always selected would make it\n // impossible to type \"trappist-1 b\" — the space after the 1 would choose a\n // row instead.\n const navigated = useRef(false);\n\n const choose = (option: AutocompleteOption) => {\n if (option.disabled) return;\n // The chosen row's text goes into the field — the same text it was matched\n // on, not its value, which is usually a slug nobody typed.\n onValueChange(haystack(option));\n onSelect(option.value, option);\n navigated.current = false;\n setOpen(false);\n };\n\n const move = (delta: number) => {\n if (selectable.length === 0) return;\n const current = shown[active];\n const from = current && !current.disabled ? selectable.indexOf(current) : -1;\n const next = (from + delta + selectable.length) % selectable.length;\n const target = selectable[next];\n if (target) setActive(shown.indexOf(target));\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Escape\") {\n // Stop here: an ancestor Dialog must not close because a suggestion\n // list did.\n if (showPanel) e.stopPropagation();\n setOpen(false);\n return;\n }\n if (e.key === \"Tab\") {\n setOpen(false);\n return;\n }\n if (!showPanel) {\n if (e.key === \"ArrowDown\") setOpen(true);\n return;\n }\n if (e.key === \"ArrowDown\") { e.preventDefault(); navigated.current = true; move(1); }\n else if (e.key === \"ArrowUp\") { e.preventDefault(); navigated.current = true; move(-1); }\n else if (e.key === \"Home\") {\n e.preventDefault();\n navigated.current = true;\n const first = selectable[0];\n if (first) setActive(shown.indexOf(first));\n } else if (e.key === \"End\") {\n e.preventDefault();\n navigated.current = true;\n const last = selectable[selectable.length - 1];\n if (last) setActive(shown.indexOf(last));\n } else if (e.key === \"Enter\" || (e.key === \" \" && navigated.current)) {\n const chosen = shown[active];\n if (chosen && !chosen.disabled) {\n e.preventDefault();\n choose(chosen);\n }\n }\n };\n\n const activeOption = showPanel ? shown[active] : undefined;\n\n return (\n <div ref={wrapRef} className={cx(styles.wrap, className)} style={style}>\n <TextField\n {...inputProps}\n type={inputProps.type ?? \"text\"}\n role=\"combobox\"\n animated={animated}\n className={styles.field}\n autoComplete=\"off\"\n aria-expanded={showPanel}\n aria-controls={listId}\n aria-autocomplete=\"list\"\n aria-activedescendant={\n activeOption && !activeOption.disabled ? `${listId}-${active}` : undefined\n }\n value={value}\n onFocus={(e) => {\n inputProps.onFocus?.(e);\n setOpen(true);\n }}\n // Focus alone is not enough. After a selection the panel shuts but\n // focus stays in the field, so onFocus never fires again and clicking\n // back into it did nothing — a combobox you cannot reopen by clicking\n // reads as broken.\n onClick={(e) => {\n inputProps.onClick?.(e);\n setOpen(true);\n }}\n onKeyDown={(e) => {\n inputProps.onKeyDown?.(e);\n onKeyDown(e);\n }}\n onChange={(e) => {\n // Typing again hands Space back to the text.\n navigated.current = false;\n onValueChange(e.target.value);\n setOpen(true);\n }}\n >\n {icon != null && <TextField.Slot>{icon}</TextField.Slot>}\n </TextField>\n\n {/* Always mounted. aria-controls above points at the listbox by id, and\n an id that resolves to nothing is a promise the markup does not keep\n — same reason Select keeps its listbox in the tree.\n\n popover=\"manual\", like Select: it renders in the browser's top layer\n so a Dialog or any container that clips or contains it cannot trap\n it, while the outside-press handling above stays ours. */}\n <div\n ref={panelRef}\n popover=\"manual\"\n data-side=\"bottom\"\n className={cx(styles.panel, ctl.spacePanel)}\n data-animated={animated ? undefined : \"false\"}\n style={pos ? { top: pos.top, left: pos.left, width: pos.width } : undefined}\n >\n {hasQuery && loading && <p className={styles.status}>{loadingMessage}</p>}\n\n {hasQuery && !loading && shown.length === 0 && emptyMessage != null && (\n <p className={styles.status}>{emptyMessage}</p>\n )}\n\n <ul\n ref={listRef}\n id={listId}\n role=\"listbox\"\n className={styles.list}\n hidden={loading || shown.length === 0}\n >\n {shown.map((option, i) => (\n <li\n key={option.value}\n id={`${listId}-${i}`}\n data-index={i}\n role=\"option\"\n aria-selected={i === active}\n aria-disabled={option.disabled || undefined}\n className={cx(\n styles.option,\n i === active && !option.disabled && styles.active,\n \"spAutocompleteOption\",\n )}\n // One highlight for pointer and keyboard both: hovering moves the\n // active row, so there is never a mouse highlight and a keyboard\n // highlight disagreeing about what Enter would do.\n onMouseEnter={() => !option.disabled && setActive(i)}\n onPointerDown={(e) => {\n // Before blur, or the panel closes and the click lands on\n // whatever the layout collapses into its place.\n e.preventDefault();\n choose(option);\n }}\n >\n <span className={styles.label}>{option.label}</span>\n {option.meta != null && <span className={styles.meta}>{option.meta}</span>}\n </li>\n ))}\n </ul>\n\n {/* Outside the scroll area, so a count stays put while the list moves. */}\n {footer != null && <div className={styles.footer}>{footer}</div>}\n </div>\n </div>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport { forwardRef, useEffect, useRef } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./Slider.module.scss\";\nimport ctl from \"../styles/spaceControls\";\n\nexport interface SliderProps {\n /** The value, as an array. One number is one thumb; two is a range, read\n * as `[start, end]` and kept in that order — the thumbs cannot swap\n * places, so index 0 is always the lower of the two. Fully controlled. */\n value: number[];\n /** Called with the whole array as a thumb moves, in the same shape it was\n * given. */\n onValueChange: (value: number[]) => void;\n /** Lower bound. */\n min: number;\n /** Upper bound. */\n max: number;\n /** The increment a thumb moves by, and the grid every value lands on: with\n * `step={10}` over 0–100 a thumb stops at 0, 10, 20 … and nothing between,\n * whether it is dragged, pressed on the track, or walked with the arrow\n * keys. Counted from `min`, so a range of 5–105 with a step of 10 lands on\n * 5, 15, 25 … Default 1, the same as a bare `<input type=\"range\">`. */\n step?: number;\n /** How close the two thumbs may come, in the value's own units. 0 lets\n * them meet; a positive number keeps a gap, for a range that would mean\n * nothing empty — \"between 2 and 2 bedrooms\". Ignored with one thumb. */\n minDistance?: number;\n /** Blocks interaction and removes it from the tab order. */\n disabled?: boolean;\n /** Merged onto the wrapper. */\n className?: string;\n /** Accessible name. Required unless a visible label references it, since a\n * slider has no text of its own. With two thumbs each one needs its own\n * name, so this is suffixed — \"Mass minimum\", \"Mass maximum\" — unless\n * `thumbLabels` says otherwise. */\n \"aria-label\"?: string;\n /** Names for the two thumbs, when the generated ones do not fit: a price\n * range might want \"From\" and \"To\". */\n thumbLabels?: [string, string];\n}\n\nconst clamp = (value: number, low: number, high: number) =>\n Math.min(Math.max(value, low), high);\n\n/**\n * A range control: one thumb for a value, two for a span between values.\n *\n * Each thumb is a real `<input type=\"range\">`, so arrow keys, Home, End and\n * Page Up/Down all work without this component reimplementing them, and a\n * screen reader announces a slider because it is one. What is drawn — the\n * glass tube, the lit fill, the little planet of a thumb — sits on top of\n * inputs that are invisible but still doing the work.\n *\n * With two thumbs they cannot cross: each is clamped to the other, so the\n * array stays in order and a range can never read back inverted. `minDistance`\n * keeps a gap between them where a zero-width range would be meaningless.\n *\n * The pointer is the component's own business, and the inputs take none of it.\n * Two inputs each covering the whole track cannot decide between them which\n * thumb a press meant: the browser hit-tests before any of this code runs, so\n * the answer came down to which input was later in the DOM. Whenever the\n * thumbs were within a thumb's width of each other — constant over a wide\n * range, where a few units are a fraction of a pixel — a press on the lower\n * one was handed to the upper one, which then refused to travel. So a press\n * anywhere on the control is measured here, against where the thumbs actually\n * are, and the nearest one is dragged until the pointer is released.\n */\nexport const Slider = forwardRef<HTMLInputElement, SliderProps>(function Slider(\n {\n value,\n onValueChange,\n min,\n max,\n step = 1,\n minDistance = 0,\n disabled,\n className,\n \"aria-label\": ariaLabel,\n thumbLabels,\n },\n ref,\n) {\n const rootRef = useRef<HTMLSpanElement | null>(null);\n const inputs = useRef<(HTMLInputElement | null)[]>([]);\n const marks = useRef<(HTMLSpanElement | null)[]>([]);\n /** The drag in progress: which thumb it carries, and where it began. A null\n * `index` means the press was exactly on two stacked thumbs and has not yet\n * said which one it wants — see `onPointerDown`. */\n const drag = useRef<{ index: number | null; startX: number } | null>(null);\n /** Takes the window listeners back off again. */\n const release = useRef<(() => void) | null>(null);\n\n const isRange = value.length > 1;\n const span = max - min || 1;\n const lower = clamp(value[0] ?? min, min, max);\n const upper = isRange ? clamp(value[1] ?? max, min, max) : lower;\n const values = isRange ? [lower, upper] : [lower];\n\n const percent = (v: number) => ((v - min) / span) * 100;\n\n /**\n * What the component knows right now.\n *\n * A drag's listeners are attached once, when the pointer goes down, so they\n * close over that render — and the value they are moving changes under them\n * on every frame of the drag. Reading through a ref instead means the\n * clamping sees where the OTHER thumb is now, not where it was when the\n * drag began, which is the difference between two thumbs that cannot cross\n * and two that cross once and stick.\n */\n const now = useRef({ values, min, max, span, step, minDistance, isRange, onValueChange });\n now.current = { values, min, max, span, step, minDistance, isRange, onValueChange };\n\n /** The nearest value on the step grid at or below `v`, and at or above. The\n * grid is counted from `min`, and rounded before flooring because a sum of\n * floats lands a hair under the mark often enough to matter: 0.1 * 3 is\n * 0.30000000000000004, and floor would send it a whole step backwards. */\n const gridBelow = (v: number) => {\n const s = now.current;\n return s.min + Math.floor(Number(((v - s.min) / s.step).toFixed(8))) * s.step;\n };\n const gridAbove = (v: number) => {\n const s = now.current;\n return s.min + Math.ceil(Number(((v - s.min) / s.step).toFixed(8))) * s.step;\n };\n\n /** A thumb's new value, clamped so the two can never cross — and kept on\n * the step grid while doing it. A `minDistance` that is not a whole number\n * of steps would otherwise park a thumb between two steps: with a step of\n * 10 and a gap of 25, stopping against the neighbour means 75, which is\n * not a value this slider can otherwise produce. The gap is the floor, so\n * the thumb settles on the next step that still honours it. */\n const clampThumb = (index: number, next: number) => {\n const s = now.current;\n if (!s.isRange) return clamp(next, s.min, s.max);\n return index === 0\n ? clamp(next, s.min, Math.max(s.min, gridBelow(s.values[1] - s.minDistance)))\n : clamp(next, Math.min(s.max, gridAbove(s.values[0] + s.minDistance)), s.max);\n };\n\n const move = (index: number, next: number) => {\n const s = now.current;\n const settled = clampThumb(index, next);\n if (settled === s.values[index]) return;\n const updated = [...s.values];\n updated[index] = settled;\n s.onValueChange(updated);\n };\n\n /** The value a press at this point on the screen is asking for. */\n const valueAt = (clientX: number) => {\n const s = now.current;\n const box = rootRef.current?.getBoundingClientRect();\n if (!box || box.width === 0) return s.values[0];\n const ratio = clamp((clientX - box.left) / box.width, 0, 1);\n const raw = s.min + ratio * s.span;\n return clamp(s.min + Math.round((raw - s.min) / s.step) * s.step, s.min, s.max);\n };\n\n /** Where a thumb is drawn, in screen pixels, and how wide it is. */\n const markBox = (index: number) => marks.current[index]?.getBoundingClientRect();\n\n /**\n * Which thumb a press belongs to: the one drawn nearest the pointer. Asking\n * in pixels rather than in values is the point — over a wide range two very\n * different numbers are the same place on screen, and the reader is pressing\n * a place.\n */\n const nearestTo = (clientX: number): number | null => {\n if (!now.current.isRange) return 0;\n const first = markBox(0);\n const second = markBox(1);\n if (!first || !second) return 0;\n const firstCentre = first.left + first.width / 2;\n const toFirst = Math.abs(clientX - firstCentre);\n const toSecond = Math.abs(clientX - (second.left + second.width / 2));\n if (toFirst !== toSecond) return toFirst < toSecond ? 0 : 1;\n // Equally near, which with two thumbs at one value is every press on\n // them. Off to one side, the side is the answer: a press to the left of\n // the pair wants the lower thumb, because that is the one that can travel\n // that way. Dead centre, nothing in the press says which, so the question\n // is left to the first move of the drag.\n if (Math.abs(clientX - firstCentre) <= 1) return null;\n return clientX < firstCentre ? 0 : 1;\n };\n\n /** Whether the press landed on the thumb itself rather than on the track. */\n const onThumb = (index: number, clientX: number) => {\n const box = markBox(index);\n if (!box) return false;\n return Math.abs(clientX - (box.left + box.width / 2)) <= box.width / 2;\n };\n\n const stopDragging = () => {\n drag.current = null;\n rootRef.current?.removeAttribute(\"data-dragging\");\n release.current?.();\n };\n\n /**\n * Takes hold of a thumb and drags it until the pointer lets go.\n *\n * A press on the track moves the nearest thumb to it first; a press on a\n * thumb takes hold of it where it stands, so grabbing a handle never jogs\n * the value before the drag has begun.\n */\n const onPointerDown = (event: React.PointerEvent<HTMLSpanElement>) => {\n if (disabled || event.button !== 0) return;\n // A second pointer coming down mid-drag would otherwise strand the first\n // drag's listeners on the window.\n release.current?.();\n\n const index = nearestTo(event.clientX);\n drag.current = { index, startX: event.clientX };\n rootRef.current?.setAttribute(\"data-dragging\", \"\");\n\n if (index !== null) {\n if (!onThumb(index, event.clientX)) move(index, valueAt(event.clientX));\n // Focus follows the press, so the keyboard carries on from the thumb the\n // reader just moved.\n inputs.current[index]?.focus();\n }\n\n // Keeps the drag alive when the pointer leaves the control, and keeps a\n // touch drag from scrolling the page with it. Synthetic events in a test\n // have no live pointer to capture, hence the guard rather than a crash.\n try {\n rootRef.current?.setPointerCapture(event.pointerId);\n } catch {\n /* no such pointer */\n }\n\n const onPointerMove = (e: PointerEvent) => {\n const held = drag.current;\n if (!held) return;\n if (held.index === null) {\n // The press sat on two stacked thumbs. Whichever way it travels names\n // the thumb: left is the lower one, right is the upper, and those are\n // the only directions each can go from a dead heat.\n const travelled = e.clientX - held.startX;\n if (Math.abs(travelled) < 1) return;\n held.index = travelled < 0 ? 0 : 1;\n inputs.current[held.index]?.focus();\n }\n move(held.index, valueAt(e.clientX));\n };\n // On the window, not the element: a drag that runs off the end of the\n // track has to keep reporting, and the release can happen anywhere.\n window.addEventListener(\"pointermove\", onPointerMove);\n window.addEventListener(\"pointerup\", stopDragging);\n window.addEventListener(\"pointercancel\", stopDragging);\n release.current = () => {\n window.removeEventListener(\"pointermove\", onPointerMove);\n window.removeEventListener(\"pointerup\", stopDragging);\n window.removeEventListener(\"pointercancel\", stopDragging);\n release.current = null;\n };\n\n // Stops the press selecting the text around the slider as it travels.\n event.preventDefault();\n };\n\n // A slider unmounted mid-drag would otherwise leave its listeners behind.\n useEffect(() => () => release.current?.(), []);\n\n const labelFor = (index: number) => {\n if (thumbLabels) return thumbLabels[index];\n if (!isRange) return ariaLabel;\n if (!ariaLabel) return index === 0 ? \"Minimum\" : \"Maximum\";\n return `${ariaLabel} ${index === 0 ? \"minimum\" : \"maximum\"}`;\n };\n\n return (\n <span\n ref={rootRef}\n className={cx(styles.root, ctl.spaceSlider, className)}\n data-disabled={disabled || undefined}\n data-range={isRange || undefined}\n onPointerDown={onPointerDown}\n >\n <span className={cx(styles.track, \"spSliderTrack\")}>\n <span\n className={cx(styles.range, \"spSliderRange\")}\n style={{\n insetInlineStart: `${isRange ? percent(lower) : 0}%`,\n width: `${isRange ? percent(upper) - percent(lower) : percent(lower)}%`,\n }}\n />\n </span>\n\n {values.map((v, index) => (\n <span\n key={index}\n ref={(node) => {\n marks.current[index] = node;\n }}\n className={cx(styles.thumb, \"spSliderThumb\")}\n style={{ left: `${percent(v)}%` }}\n data-thumb={index}\n />\n ))}\n\n {values.map((v, index) => (\n <input\n key={index}\n ref={(node) => {\n inputs.current[index] = node;\n if (index === 0) {\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }\n }}\n type=\"range\"\n className={cx(styles.input, \"spSliderInput\")}\n value={v}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n aria-label={labelFor(index)}\n onChange={(e) => move(index, Number(e.target.value))}\n />\n ))}\n </span>\n );\n});\n","/**\n * The arithmetic every chart here shares: how many colours there are, what a\n * readable set of axis ticks is, and how a value becomes a position.\n *\n * Kept apart from the components because it is pure — given the same numbers\n * it returns the same answer — which is also what makes it testable without a\n * browser, unlike everything that has to be measured.\n */\n\n/**\n * The palette, written out rather than built from an index: a token name\n * assembled at runtime cannot be checked against the ones the library\n * promises, and the check is what keeps these honest.\n */\nconst SERIES_COLORS = [\n \"var(--sp-chart-series-1-color)\",\n \"var(--sp-chart-series-2-color)\",\n \"var(--sp-chart-series-3-color)\",\n \"var(--sp-chart-series-4-color)\",\n \"var(--sp-chart-series-5-color)\",\n \"var(--sp-chart-series-6-color)\",\n \"var(--sp-chart-series-7-color)\",\n \"var(--sp-chart-series-8-color)\",\n] as const;\n\n/** How many series the palette names. A ninth is never invented: see `seriesColor`. */\nexport const SERIES_COLOR_COUNT = SERIES_COLORS.length;\n\n/**\n * The colour for a series, by its position.\n *\n * The palette is an order, not a pool. Slot 1 is always the first series, so\n * hiding one never repaints the rest — a legend toggle that recoloured the\n * survivors would make the reader re-learn the chart.\n *\n * Past the eighth the colours repeat, which is a state worth avoiding rather\n * than papering over: group the tail into \"Other\", or split the chart. The\n * components warn once in development when a chart goes past it.\n */\nexport const seriesColor = (index: number): string =>\n SERIES_COLORS[index % SERIES_COLOR_COUNT];\n\n/** A tick step a person would have chosen: 1, 2 or 5 times a power of ten. */\nfunction niceStep(rough: number): number {\n if (rough <= 0) return 1;\n const magnitude = 10 ** Math.floor(Math.log10(rough));\n const scaled = rough / magnitude;\n const step = scaled <= 1 ? 1 : scaled <= 2 ? 2 : scaled <= 5 ? 5 : 10;\n return step * magnitude;\n}\n\nexport interface Scale {\n /** The value at the bottom of the axis — zero unless something is negative. */\n min: number;\n /** The value at the top: a whole tick at or above the largest value. */\n max: number;\n /** The values to label, bottom to top. */\n ticks: number[];\n /** Where a value sits, 0 at the axis minimum and 1 at its maximum. */\n ratio: (value: number) => number;\n}\n\n/**\n * An axis for these values: a zero baseline and ticks at readable intervals.\n *\n * The top is the first whole tick at or above the largest value, so a bar\n * whose value lands exactly on a tick reaches the top line — which is the\n * honest drawing of it, not an error.\n *\n * Bars are measured from zero, always — a bar chart that starts at 40 makes a\n * 5% difference look like a fivefold one. Lines may start elsewhere, and pass\n * `zeroBased: false` to say so.\n */\nexport function linearScale(\n values: number[],\n { tickCount = 5, zeroBased = true }: { tickCount?: number; zeroBased?: boolean } = {},\n): Scale {\n const real = values.filter((v) => Number.isFinite(v));\n const lowest = real.length ? Math.min(...real) : 0;\n const highest = real.length ? Math.max(...real) : 0;\n\n // Flat data still needs an axis with height, or every mark lands on one line.\n let low = zeroBased ? Math.min(0, lowest) : lowest;\n let high = zeroBased ? Math.max(0, highest) : highest;\n if (low === high) {\n if (low === 0) high = 1;\n else {\n low = Math.min(0, low);\n high = Math.max(0, high);\n }\n }\n\n const step = niceStep((high - low) / Math.max(1, tickCount));\n const from = Math.floor(low / step) * step;\n const to = Math.ceil(high / step) * step;\n\n const ticks: number[] = [];\n // Counted rather than accumulated: adding a float step repeatedly drifts,\n // and the labels would read 0.30000000000000004.\n const count = Math.round((to - from) / step);\n for (let i = 0; i <= count; i++) ticks.push(Number((from + i * step).toPrecision(12)));\n\n const span = to - from || 1;\n return { min: from, max: to, ticks, ratio: (value) => (value - from) / span };\n}\n\n/**\n * Where each category sits along the x axis, as a fraction of the width.\n *\n * `band` is the middle of each slot — what a bar is centred on, and where a\n * line's point sits. Bars share their slot: `inset` is how much of it is left\n * clear either side, so neighbouring bars do not touch.\n */\nexport function bandPositions(count: number, inset = 0.25): { centre: number[]; width: number } {\n if (count <= 0) return { centre: [], width: 0 };\n const slot = 1 / count;\n return {\n centre: Array.from({ length: count }, (_, i) => slot * (i + 0.5)),\n width: slot * (1 - inset * 2),\n };\n}\n\n/**\n * A bar as a path, rounded at the end the value reaches and square where it\n * meets the baseline — a bar is a length measured from the axis, and rounding\n * that end would round away the thing being measured. `up` is false for a\n * value below zero, which rounds the bottom instead.\n */\nexport function barPath(\n x: number, y: number, width: number, height: number, radius: number, up = true,\n): string {\n const r = Math.max(0, Math.min(radius, width / 2, height));\n if (r === 0) return `M${x},${y}h${width}v${height}h${-width}Z`;\n return up\n ? `M${x},${y + height}V${y + r}a${r},${r} 0 0 1 ${r},${-r}h${width - r * 2}` +\n `a${r},${r} 0 0 1 ${r},${r}V${y + height}Z`\n : `M${x},${y}V${y + height - r}a${r},${r} 0 0 0 ${r},${r}h${width - r * 2}` +\n `a${r},${r} 0 0 0 ${r},${-r}V${y}Z`;\n}\n\n/** Points along the x axis for a line: first at the left edge, last at the right. */\nexport function pointPositions(count: number): number[] {\n if (count <= 0) return [];\n if (count === 1) return [0.5];\n return Array.from({ length: count }, (_, i) => i / (count - 1));\n}\n\n/**\n * Whether this is a development build, read off the global rather than from\n * `process`: the library is bundled for browsers too, where naming `process`\n * is both untyped and, in some bundlers, a runtime error.\n */\nexport const isDevelopment = (): boolean => {\n const global = globalThis as { process?: { env?: { NODE_ENV?: string } } };\n return global.process?.env?.NODE_ENV !== \"production\";\n};\n\n/** A number as a label: thousands separated, long decimals trimmed. */\nexport const formatValue = (value: number): string =>\n Number.isInteger(value)\n ? value.toLocaleString(\"en-US\")\n : value.toLocaleString(\"en-US\", { maximumFractionDigits: 2 });\n","\"use client\";\nimport type * as React from \"react\";\nimport { useCallback, useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./Chart.module.scss\";\nimport {\n SERIES_COLOR_COUNT, bandPositions, barPath, formatValue, isDevelopment, linearScale,\n pointPositions, seriesColor,\n} from \"../internal/chartScale\";\n\nexport interface ChartSeries {\n /** Named in the legend and the tooltip, so say what the numbers are. */\n name: string;\n /** One value per category, in the same order. `null` is a gap — a month with\n * no reading — and is drawn as one rather than as zero. */\n data: (number | null)[];\n /** Overrides this series' colour. Leave it alone unless the series has a\n * meaning of its own that a reader already associates with a colour. */\n color?: string;\n}\n\nexport interface ChartPoint {\n /** The series the point belongs to. */\n series: string;\n seriesIndex: number;\n /** The category beneath it. */\n category: string;\n categoryIndex: number;\n value: number;\n}\n\nexport interface ChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onClick\"> {\n /** How to draw it. The same data can be any of the three: bars for\n * comparing amounts, a line for a trend, an area for a trend whose total\n * matters. Switching is a prop, so a chart can offer the choice. */\n type: \"bar\" | \"line\" | \"area\";\n /** The x axis, in order. Every series' `data` lines up with this by\n * position, so they must be the same length. */\n categories: string[];\n /** One entry per dataset. */\n series: ChartSeries[];\n /** How tall the plot is, in pixels. The width comes from the container.\n * Default 240. */\n height?: number;\n /** Stack the series instead of setting them side by side (bar) or overlaying\n * them (area). For parts of a whole, where the total is the point. */\n stacked?: boolean;\n /** Show the legend. Defaults to true for more than one series, which is when\n * colour alone would otherwise be carrying the identity. */\n legend?: boolean;\n /** Draw the horizontal grid lines. Default true. */\n grid?: boolean;\n /** How a value is written, in labels and the tooltip. */\n formatValue?: (value: number) => string;\n /** Roughly how many labelled ticks the y axis gets. Default 5. */\n tickCount?: number;\n /** The lit finish this library gives everything else: marks that catch the\n * light, and a first draw where bars rise from the axis and a line draws\n * itself on. Default true; a reader who asked for less motion gets the\n * finish without the movement either way. */\n animated?: boolean;\n /** The category index from which the data is still arriving — usually\n * `categories.length - 1`, today's bar, which will keep growing until the\n * day ends. Those bars are drawn hatched rather than solid, and the\n * tooltip and the table say \"so far\", so a half-counted day is never read\n * as a collapse. Bars only: a line says the same thing with its own last\n * segment, which is a separate job. */\n partialFrom?: number;\n /** Called when a bar or point is chosen, with what it stands for. Keyboard\n * activation reports the same thing a click does. */\n onPointClick?: (point: ChartPoint) => void;\n /** Says what the chart shows, for a reader who cannot see it. The figures\n * themselves are always available in the table this renders for screen\n * readers, so this wants the point, not the numbers. */\n \"aria-label\"?: string;\n}\n\n/** The reading under the pointer: which category, and where to put the card. */\ninterface Hover {\n index: number;\n x: number;\n}\n\nconst PADDING = { top: 8, right: 8, bottom: 24 };\n/** Room for the y labels. Widened per chart by the longest one. */\nconst AXIS_GUTTER = 8;\n\n/**\n * A chart of one or more datasets over a shared set of categories — as bars,\n * a line, or a filled area.\n *\n * Drawn as plain SVG from the library's own arithmetic: no charting\n * dependency, and every colour, size and radius is a token, so a chart is the\n * same material as the rest of the page.\n *\n * The series palette is an order rather than a pool. The first series is\n * always the first colour, so hiding one never repaints the others.\n *\n * What it does without being asked: a legend once there is more than one\n * series, a crosshair reading every series at the category under the pointer,\n * and a table of the same numbers for screen readers. What it refuses to do:\n * a second y axis. Two measures on different scales belong in two charts —\n * one pair of axes can be drawn to tell any story you like.\n */\nexport function Chart({\n type,\n categories,\n series,\n height = 240,\n stacked = false,\n legend,\n grid = true,\n formatValue: format = formatValue,\n tickCount = 5,\n animated = true,\n partialFrom,\n onPointClick,\n className,\n \"aria-label\": ariaLabel,\n ...rest\n}: ChartProps) {\n const titleId = useId();\n const plotRef = useRef<HTMLDivElement | null>(null);\n const [width, setWidth] = useState(0);\n const [hover, setHover] = useState<Hover | null>(null);\n\n // The plot is as wide as its container: the width has to be measured, since\n // an SVG cannot size its own coordinate system from a percentage.\n useEffect(() => {\n const node = plotRef.current;\n if (!node) return;\n const observer = new ResizeObserver(([entry]) => {\n setWidth(Math.round(entry.contentRect.width));\n });\n observer.observe(node);\n setWidth(Math.round(node.getBoundingClientRect().width));\n return () => observer.disconnect();\n }, []);\n\n useEffect(() => {\n if (!isDevelopment()) return;\n if (series.length > SERIES_COLOR_COUNT) {\n // Not an error: it still draws. But two series now share a colour, and\n // no amount of care elsewhere makes that readable.\n console.warn(\n `Chart: ${series.length} series, but the palette names ${SERIES_COLOR_COUNT}. ` +\n \"Past that the colours repeat. Group the tail into an \\\"Other\\\" series, or split the chart.\",\n );\n }\n const wrong = series.filter((s) => s.data.length !== categories.length);\n if (wrong.length) {\n console.warn(\n `Chart: ${wrong.map((s) => `\"${s.name}\"`).join(\", \")} ${wrong.length === 1 ? \"has\" : \"have\"} ` +\n `a different number of values than there are categories (${categories.length}). ` +\n \"Values line up with categories by position, so the tail will be missing.\",\n );\n }\n }, [series, categories.length]);\n\n const stackable = stacked && (type === \"bar\" || type === \"area\");\n // Only bars are hatched; a line has its own way of showing an unfinished\n // tail, and drawing one here would be two claims at once.\n const partial = type === \"bar\" && typeof partialFrom === \"number\" && partialFrom >= 0;\n const stillFilling = (index: number) => partial && index >= (partialFrom as number);\n\n // What the axis has to cover: the values themselves, or the running totals\n // when the series are stacked on top of one another.\n const scale = useMemo(() => {\n const values: number[] = [];\n if (stackable) {\n categories.forEach((_, i) => {\n let positive = 0;\n let negative = 0;\n series.forEach((s) => {\n const v = s.data[i];\n if (typeof v !== \"number\") return;\n if (v >= 0) positive += v;\n else negative += v;\n });\n values.push(positive, negative);\n });\n } else {\n series.forEach((s) => s.data.forEach((v) => { if (typeof v === \"number\") values.push(v); }));\n }\n // Bars are read as lengths from zero; a line is read as a shape, so it may\n // start where the data does — but not when something is negative, where\n // the zero line is the thing that gives the shape meaning.\n return linearScale(values, { tickCount, zeroBased: type !== \"line\" || values.some((v) => v < 0) });\n }, [series, categories, stackable, tickCount, type]);\n\n const labels = useMemo(() => scale.ticks.map(format), [scale.ticks, format]);\n // The gutter fits the longest label rather than a guess: 7px a character is\n // close enough for the digits and separators these labels are made of.\n const gutter = Math.max(...labels.map((l) => l.length * 7), 24) + AXIS_GUTTER;\n\n const plotWidth = Math.max(0, width - gutter - PADDING.right);\n const plotHeight = Math.max(0, height - PADDING.top - PADDING.bottom);\n // A line's first and last points sit on the ends of the axis, so without\n // this their category labels hang off both edges. Bars need none: they are\n // already inset inside their own slots.\n const edge = type === \"bar\" ? 0 : 16;\n const x = (ratio: number) => gutter + edge + ratio * Math.max(0, plotWidth - edge * 2);\n const y = (value: number) => PADDING.top + (1 - scale.ratio(value)) * plotHeight;\n\n const band = bandPositions(categories.length);\n const points = pointPositions(categories.length);\n const colorOf = (i: number) => series[i]?.color ?? seriesColor(i);\n const showLegend = legend ?? series.length > 1;\n\n /** Running totals, so a stacked mark knows what it sits on. */\n const baseline = useMemo(() => {\n const bases: number[][] = series.map(() => []);\n categories.forEach((_, i) => {\n let positive = 0;\n let negative = 0;\n series.forEach((s, si) => {\n const v = s.data[i];\n if (!stackable || typeof v !== \"number\") {\n bases[si][i] = 0;\n return;\n }\n if (v >= 0) { bases[si][i] = positive; positive += v; }\n else { bases[si][i] = negative; negative += v; }\n });\n });\n return bases;\n }, [series, categories, stackable]);\n\n const readingAt = useCallback(\n (clientX: number) => {\n const node = plotRef.current;\n if (!node || !categories.length || plotWidth <= 0) return null;\n const box = node.getBoundingClientRect();\n const span = type === \"bar\" ? plotWidth : Math.max(1, plotWidth - 32);\n const ratio = (clientX - box.left - gutter - (type === \"bar\" ? 0 : 16)) / span;\n const positions = type === \"bar\" ? band.centre : points;\n let nearest = 0;\n positions.forEach((p, i) => {\n if (Math.abs(p - ratio) < Math.abs(positions[nearest] - ratio)) nearest = i;\n });\n return { index: nearest, x: x(positions[nearest]) };\n },\n // x and the position arrays are derived from these; listing them keeps the\n // callback honest without re-creating it on every render.\n [categories.length, gutter, plotWidth, type, band.centre, points], // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const report = (seriesIndex: number, categoryIndex: number) => {\n const value = series[seriesIndex]?.data[categoryIndex];\n if (typeof value !== \"number\" || !onPointClick) return;\n onPointClick({\n series: series[seriesIndex].name,\n seriesIndex,\n category: categories[categoryIndex],\n categoryIndex,\n value,\n });\n };\n\n const barWidth = stackable || series.length === 1\n ? band.width * plotWidth\n : (band.width * plotWidth) / series.length;\n\n return (\n <div\n {...rest}\n className={cx(styles.root, className)}\n data-type={type}\n data-animated={animated ? \"\" : undefined}\n style={{ ...rest.style }}\n >\n <div\n ref={plotRef}\n className={styles.plot}\n style={{ height }}\n onPointerMove={(e) => {\n if (e.pointerType === \"touch\") return;\n setHover(readingAt(e.clientX));\n }}\n onPointerLeave={() => setHover(null)}\n >\n {/* aria-hidden: the same numbers are in the table below, which is what\n a screen reader reads. A pile of unlabelled <rect>s is noise. */}\n <svg\n className={styles.svg}\n width={width || undefined}\n height={height}\n viewBox={width ? `0 0 ${width} ${height}` : undefined}\n role=\"img\"\n aria-labelledby={ariaLabel ? undefined : titleId}\n aria-label={ariaLabel}\n >\n <defs>\n {series.map((s2, si) => (\n <linearGradient key={`grad-${si}`} id={`${titleId}-grad-${si}`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n {/* The limb again: brightest where the light lands, falling\n away into the ground it stands on. */}\n <stop offset=\"0%\" stopColor={colorOf(si)} stopOpacity=\"1\" />\n <stop offset=\"100%\" stopColor={colorOf(si)} stopOpacity=\"0.55\" />\n </linearGradient>\n ))}\n {series.map((s2, si) => (\n <linearGradient key={`area-${si}`} id={`${titleId}-area-${si}`} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n {/* An atmosphere rather than a slab: dense at the line, thinning\n to nothing before the axis. */}\n <stop offset=\"0%\" stopColor={colorOf(si)} stopOpacity=\"0.45\" />\n <stop offset=\"100%\" stopColor={colorOf(si)} stopOpacity=\"0.02\" />\n </linearGradient>\n ))}\n </defs>\n\n {/* Diagonal stripes in the series' own colour: a bar that is still\n filling reads as unfinished at a glance, and keeps its identity.\n One pattern per series, because a pattern carries its own paint. */}\n {partial && (\n <defs>\n {series.map((s2, si) => (\n <pattern\n key={`hatch-${si}`}\n id={`${titleId}-hatch-${si}`}\n width=\"8\"\n height=\"8\"\n patternUnits=\"userSpaceOnUse\"\n patternTransform=\"rotate(45)\"\n >\n <rect width=\"8\" height=\"8\" fill=\"transparent\" />\n <line className={styles.hatch} x1=\"2\" y1=\"0\" x2=\"2\" y2=\"8\" stroke={colorOf(si)} />\n <line className={styles.hatch} x1=\"6\" y1=\"0\" x2=\"6\" y2=\"8\" stroke={colorOf(si)} />\n </pattern>\n ))}\n </defs>\n )}\n\n {grid && scale.ticks.map((tick) => (\n <line\n key={`grid-${tick}`}\n className={cx(styles.grid, tick === 0 && scale.min < 0 && styles.zeroLine)}\n x1={gutter}\n x2={gutter + plotWidth}\n y1={y(tick)}\n y2={y(tick)}\n />\n ))}\n\n {scale.ticks.map((tick, i) => (\n <text key={`label-${tick}`} className={styles.axisLabel} x={gutter - AXIS_GUTTER} y={y(tick)} textAnchor=\"end\" dominantBaseline=\"middle\">\n {labels[i]}\n </text>\n ))}\n\n {categories.map((category, i) => (\n <text\n key={`cat-${category}-${i}`}\n className={styles.axisLabel}\n x={x(type === \"bar\" ? band.centre[i] : points[i])}\n y={height - PADDING.bottom / 2}\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n >\n {category}\n </text>\n ))}\n\n {type === \"bar\" && series.map((s, si) => (\n <g key={`bars-${s.name}-${si}`}>\n {categories.map((category, ci) => {\n const value = s.data[ci];\n if (typeof value !== \"number\") return null;\n const base = baseline[si][ci];\n const top = y(base + value);\n const bottom = y(base);\n const slotLeft = x(band.centre[ci]) - (band.width * plotWidth) / 2;\n const left = stackable || series.length === 1\n ? slotLeft\n : slotLeft + si * barWidth;\n // 2px of the surface between neighbouring bars, so two fills\n // never read as one.\n const drawWidth = Math.max(1, barWidth - (series.length > 1 && !stackable ? 2 : 0));\n const drawHeight = Math.max(1, Math.abs(bottom - top));\n const stillCounting = partial && ci >= (partialFrom as number);\n return (\n <path\n key={`bar-${category}-${ci}`}\n className={cx(styles.bar, onPointClick && styles.clickable)}\n d={barPath(left, Math.min(top, bottom), drawWidth, drawHeight, 4, value >= 0)}\n fill={stillCounting ? `url(#${titleId}-hatch-${si})` : `url(#${titleId}-grad-${si})`}\n // currentColor is what the glow in the stylesheet burns.\n color={colorOf(si)}\n data-dim={hover && hover.index !== ci ? \"\" : undefined}\n onClick={() => report(si, ci)}\n >\n <title>\n {`${s.name}, ${category}: ${format(value)}${stillCounting ? \" so far\" : \"\"}`}\n </title>\n </path>\n );\n })}\n </g>\n ))}\n\n {type !== \"bar\" && series.map((s, si) => {\n // A null is a gap: the line stops and starts again rather than\n // drawing a straight run through missing readings.\n const runs: { i: number; value: number; base: number }[][] = [];\n let run: { i: number; value: number; base: number }[] = [];\n s.data.forEach((value, i) => {\n if (typeof value !== \"number\") {\n if (run.length) runs.push(run);\n run = [];\n return;\n }\n run.push({ i, value, base: baseline[si][i] });\n });\n if (run.length) runs.push(run);\n\n return (\n <g key={`line-${s.name}-${si}`}>\n {runs.map((segment, ri) => {\n const line = segment\n .map((p, k) => `${k === 0 ? \"M\" : \"L\"}${x(points[p.i])},${y(p.base + p.value)}`)\n .join(\" \");\n const area = type === \"area\"\n ? `${line} L${x(points[segment[segment.length - 1].i])},${y(segment[segment.length - 1].base)} ` +\n segment.slice().reverse().map((p) => `L${x(points[p.i])},${y(p.base)}`).join(\" \") + \" Z\"\n : null;\n return (\n <g key={`run-${ri}`}>\n {area && (\n <path className={styles.area} d={area} fill={`url(#${titleId}-area-${si})`} />\n )}\n <path\n className={styles.line}\n d={line}\n stroke={colorOf(si)}\n color={colorOf(si)}\n fill=\"none\"\n pathLength={1}\n />\n </g>\n );\n })}\n {/* A marker per reading, shown at the crosshair — and always,\n when a series is a single point with no line to carry it. */}\n {s.data.map((value, ci) =>\n typeof value === \"number\" ? (\n <circle\n key={`dot-${ci}`}\n className={cx(styles.dot, onPointClick && styles.clickable)}\n cx={x(points[ci])}\n cy={y(baseline[si][ci] + value)}\n r={4}\n fill={colorOf(si)}\n color={colorOf(si)}\n data-on={hover?.index === ci ? \"\" : undefined}\n onClick={() => report(si, ci)}\n >\n <title>{`${s.name}, ${categories[ci]}: ${format(value)}`}</title>\n </circle>\n ) : null,\n )}\n </g>\n );\n })}\n\n {hover && (\n <line\n className={styles.crosshair}\n x1={hover.x}\n x2={hover.x}\n y1={PADDING.top}\n y2={PADDING.top + plotHeight}\n />\n )}\n </svg>\n\n {hover && (\n <div\n className={styles.tooltip}\n // Placed from the left when the reading is on the left half and\n // from the right when it is not, so the card never runs off.\n style={\n hover.x > gutter + plotWidth / 2\n ? { right: Math.max(0, width - hover.x + 12) }\n : { left: hover.x + 12 }\n }\n role=\"status\"\n >\n <p className={styles.tooltipHead}>{categories[hover.index]}</p>\n <ul className={styles.tooltipList}>\n {series.map((s, si) => {\n const value = s.data[hover.index];\n return (\n <li key={s.name} className={styles.tooltipRow}>\n <span className={styles.swatch} style={{ background: colorOf(si) }} aria-hidden=\"true\" />\n <span className={styles.tooltipName}>{s.name}</span>\n <span className={styles.tooltipValue}>\n {typeof value === \"number\" ? format(value) : \"—\"}\n {stillFilling(hover.index) && typeof value === \"number\" && (\n <span className={styles.partialNote}>so far</span>\n )}\n </span>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </div>\n\n {showLegend && (\n <ul className={styles.legend}>\n {series.map((s, si) => (\n <li key={s.name} className={styles.legendItem}>\n <span className={styles.swatch} style={{ background: colorOf(si) }} aria-hidden=\"true\" />\n {s.name}\n </li>\n ))}\n </ul>\n )}\n\n {/* The figures, for a reader who cannot see the picture. Visually\n hidden rather than absent: the alternative is a chart that says\n nothing at all to a screen reader. */}\n <table className={styles.data} id={titleId}>\n <caption>{ariaLabel ?? \"Chart data\"}</caption>\n <thead>\n <tr>\n <th scope=\"col\">Category</th>\n {series.map((s) => <th key={s.name} scope=\"col\">{s.name}</th>)}\n </tr>\n </thead>\n <tbody>\n {categories.map((category, ci) => (\n <tr key={category}>\n <th scope=\"row\">{category}</th>\n {series.map((s) => (\n <td key={s.name}>\n {typeof s.data[ci] === \"number\" ? format(s.data[ci] as number) : \"—\"}\n {stillFilling(ci) && typeof s.data[ci] === \"number\" ? \" so far\" : \"\"}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./BarList.module.scss\";\nimport { formatValue, seriesColor } from \"../internal/chartScale\";\n\nexport interface BarListItem {\n /** The row's name, at the left. */\n label: string;\n /** How long the bar is, against the largest value or an explicit `max`. */\n value: number;\n /** Overrides this row's colour. One colour for the set reads as a ranking;\n * a colour per row reads as categories. */\n color?: string;\n}\n\nexport interface BarListProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onSelect\"> {\n /** The rows, in the order they should appear. Sort before passing: the\n * order is the caller's statement about the data, not this component's. */\n items: BarListItem[];\n /** What a full track means. Defaults to the largest value, which makes the\n * rows relative to each other. Pass the total to make them shares of it. */\n max?: number;\n /** Show each row's share as a percentage beside its value. */\n showPercent?: boolean;\n /** How the value is written. */\n formatValue?: (value: number) => string;\n /** Give every row its own colour from the series palette, rather than one\n * colour for the set. */\n colorful?: boolean;\n /** Fill the bars on first render, one row after the next, the way results\n * arrive. Default true; a reader who asked for less motion gets the bars\n * already filled either way. */\n animated?: boolean;\n /** Called when a row is chosen. Rows become buttons when this is given, and\n * stay plain text when it is not — nothing looks clickable unless it is. */\n onItemClick?: (item: BarListItem, index: number) => void;\n /** Names the set for assistive tech: \"Poll results\", say. */\n \"aria-label\"?: string;\n}\n\n/**\n * A ranked list of values as bars: a label, a track, a filled bar, a figure.\n *\n * For results read against each other — a poll, the top ten by some measure,\n * a breakdown of a total. It is the form to reach for when the category names\n * are words rather than dates: they get a column of their own and stay\n * readable, where a vertical bar chart would turn them on their side.\n *\n * No axis and no grid, because there is nothing to measure against but the\n * other rows: every bar is drawn against the longest one, or against `max`\n * when the share of a known total is the point.\n */\nexport function BarList({\n items,\n max,\n showPercent = false,\n formatValue: format = formatValue,\n colorful = false,\n animated = true,\n onItemClick,\n className,\n \"aria-label\": ariaLabel,\n ...rest\n}: BarListProps) {\n const largest = max ?? Math.max(0, ...items.map((i) => i.value));\n const total = items.reduce((sum, i) => sum + (i.value > 0 ? i.value : 0), 0);\n\n return (\n <div\n {...rest}\n className={cx(styles.root, className)}\n role=\"list\"\n aria-label={ariaLabel}\n data-animated={animated ? \"\" : undefined}\n >\n {items.map((item, index) => {\n // A zero-length bar still shows its rounded cap, so a row with no\n // votes reads as a row with no votes rather than as a missing row.\n const ratio = largest > 0 ? Math.max(0, item.value) / largest : 0;\n const percent = total > 0 ? (item.value / total) * 100 : 0;\n const fill = item.color ?? (colorful ? seriesColor(index) : \"var(--sp-chart-series-1-color)\");\n\n const row = (\n <>\n <span className={styles.label}>{item.label}</span>\n <span className={styles.track}>\n <span\n className={styles.fill}\n style={{\n width: `${ratio * 100}%`,\n background: fill,\n // Each row starts a little after the one above, so a poll\n // reads as counting up rather than snapping into place.\n // Capped, or a long list would still be filling when the\n // reader has finished reading it.\n animationDelay: `${Math.min(index * 60, 360)}ms`,\n }}\n />\n </span>\n <span className={styles.value}>\n {format(item.value)}\n {showPercent && <span className={styles.percent}>{Math.round(percent)}%</span>}\n </span>\n </>\n );\n\n return (\n <div key={`${item.label}-${index}`} role=\"listitem\" className={styles.row}>\n {onItemClick ? (\n <button\n type=\"button\"\n className={cx(styles.line, styles.pressable)}\n onClick={() => onItemClick(item, index)}\n >\n {row}\n </button>\n ) : (\n <span className={styles.line}>{row}</span>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport { useId, useState } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./PieChart.module.scss\";\nimport { formatValue, seriesColor } from \"../internal/chartScale\";\n\nexport interface PieSlice {\n /** The slice's name — always drawn in the legend, never colour alone. */\n label: string;\n /** Its size. Negative values are dropped: a pie has no way to show one. */\n value: number;\n /** Overrides this slice's colour. */\n color?: string;\n}\n\nexport interface PieChartProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onSelect\"> {\n /** The slices, in order. Sort before passing — usually largest first, which\n * is what makes a pie readable at all. */\n slices: PieSlice[];\n /** Cut the middle out, making a donut. The hole gives the total somewhere\n * to live, which is usually worth more than the extra ink. */\n donut?: boolean;\n /** Shown in a donut's middle, under the total. */\n label?: React.ReactNode;\n /** How wide the circle is, in pixels. Default 180. */\n size?: number;\n /** Show the legend. Default true: a pie without one is a colour quiz. */\n legend?: boolean;\n /** The lit finish, and the sweep on its first draw. Default true. */\n animated?: boolean;\n /** How a value is written, in the legend and the middle. */\n formatValue?: (value: number) => string;\n /** Called when a slice is chosen. */\n onSliceClick?: (slice: PieSlice, index: number) => void;\n /** Says what the whole shows. */\n \"aria-label\"?: string;\n}\n\n/** Where a fraction of the circle lands, measured clockwise from the top. */\nconst pointOnCircle = (centre: number, radius: number, fraction: number) => {\n const angle = fraction * 2 * Math.PI - Math.PI / 2;\n return { x: centre + radius * Math.cos(angle), y: centre + radius * Math.sin(angle) };\n};\n\n/**\n * Parts of a whole, as a circle.\n *\n * Worth saying plainly: a pie is the weakest way to compare sizes — people\n * read angles badly — and it is the wrong chart for more than a handful of\n * slices, for values that are not parts of one total, or for change over\n * time. Where the comparison is the point, `BarList` is easier to read. Where\n * a pie is right is a whole that splits a few ways and a reader who needs to\n * see \"most of it\" at a glance.\n *\n * So this one is built to stay readable: every slice keeps a hairline of the\n * surface between it and its neighbour, the legend carries the names and the\n * figures, and a donut puts the total in the middle where it can be read\n * exactly rather than estimated.\n */\nexport function PieChart({\n slices,\n donut = false,\n label,\n size = 180,\n legend = true,\n animated = true,\n formatValue: format = formatValue,\n onSliceClick,\n className,\n \"aria-label\": ariaLabel,\n ...rest\n}: PieChartProps) {\n const [hovered, setHovered] = useState<number | null>(null);\n // Gradient ids have to be unique per instance: two pies on one page would\n // otherwise both paint with whichever defs rendered last.\n const uid = useId();\n\n const usable = slices.filter((s) => s.value > 0);\n const total = usable.reduce((sum, s) => sum + s.value, 0);\n const centre = size / 2;\n const radius = centre - 2;\n const hole = donut ? radius * 0.62 : 0;\n\n let cursor = 0;\n const arcs = usable.map((slice, index) => {\n const fraction = total > 0 ? slice.value / total : 0;\n const from = cursor;\n cursor += fraction;\n\n const outerFrom = pointOnCircle(centre, radius, from);\n const outerTo = pointOnCircle(centre, radius, cursor);\n const large = fraction > 0.5 ? 1 : 0;\n\n // A single slice is the whole circle, which an arc cannot draw: its start\n // and end points are the same, so the path collapses to nothing.\n // The hole runs the other way round, so its end sits just RIGHT of the\n // top: a large anticlockwise arc to a point just left of the top lies on\n // a circle centred above the start, which drew a dark disc over the\n // ring's top edge instead of cutting the hole.\n const whole = fraction >= 0.999;\n const d = whole\n ? donut\n ? `M${centre},${centre - radius} A${radius},${radius} 0 1 1 ${centre - 0.01},${centre - radius} Z ` +\n `M${centre},${centre - hole} A${hole},${hole} 0 1 0 ${centre + 0.01},${centre - hole} Z`\n : `M${centre},${centre - radius} A${radius},${radius} 0 1 1 ${centre - 0.01},${centre - radius} Z`\n : donut\n ? `M${outerFrom.x},${outerFrom.y} A${radius},${radius} 0 ${large} 1 ${outerTo.x},${outerTo.y} ` +\n `L${pointOnCircle(centre, hole, cursor).x},${pointOnCircle(centre, hole, cursor).y} ` +\n `A${hole},${hole} 0 ${large} 0 ${pointOnCircle(centre, hole, from).x},${pointOnCircle(centre, hole, from).y} Z`\n : `M${centre},${centre} L${outerFrom.x},${outerFrom.y} ` +\n `A${radius},${radius} 0 ${large} 1 ${outerTo.x},${outerTo.y} Z`;\n\n return { slice, index, d, fraction, fillRule: whole && donut ? (\"evenodd\" as const) : undefined };\n });\n\n const originalIndex = (slice: PieSlice) => slices.indexOf(slice);\n\n return (\n <div {...rest} className={cx(styles.root, className)} data-animated={animated ? \"\" : undefined}>\n <svg\n className={styles.svg}\n width={size}\n height={size}\n viewBox={`0 0 ${size} ${size}`}\n role=\"img\"\n aria-label={ariaLabel ?? \"Pie chart\"}\n >\n {/* The slices alone are swept in; the total in the middle is not part\n of the ring and should not be revealed by it. */}\n <defs>\n {/* The same light every planet in this library is lit by: a source\n up and to the left, a limb that falls away from it, and an edge\n that darkens where the disc turns away. */}\n <radialGradient id={`${uid}-face`} cx=\"32%\" cy=\"26%\" r=\"78%\">\n <stop offset=\"0%\" stopColor=\"#fff\" stopOpacity=\"0.22\" />\n <stop offset=\"55%\" stopColor=\"#fff\" stopOpacity=\"0.04\" />\n <stop offset=\"100%\" stopColor=\"#000\" stopOpacity=\"0.28\" />\n </radialGradient>\n <radialGradient id={`${uid}-edge`} cx=\"50%\" cy=\"50%\" r=\"50%\">\n <stop offset=\"88%\" stopColor=\"#000\" stopOpacity=\"0\" />\n <stop offset=\"100%\" stopColor=\"#000\" stopOpacity=\"0.45\" />\n </radialGradient>\n </defs>\n\n <g className={styles.sweep}>\n {arcs.map(({ slice, index, d, fillRule }) => (\n <path\n key={`${slice.label}-${index}`}\n className={cx(styles.slice, onSliceClick && styles.clickable)}\n d={d}\n fill={slice.color ?? seriesColor(originalIndex(slice))}\n fillRule={fillRule}\n data-dim={hovered !== null && hovered !== index ? \"\" : undefined}\n onPointerEnter={() => setHovered(index)}\n onPointerLeave={() => setHovered(null)}\n onClick={() => onSliceClick?.(slice, originalIndex(slice))}\n >\n <title>{`${slice.label}: ${format(slice.value)}`}</title>\n </path>\n ))}\n\n {/* Laid over the slices, not under them: the light falls on the\n whole disc rather than on each slice separately, which is what\n makes it read as one solid object. Angles are untouched — the\n circle stays a circle, so a quarter still looks like a quarter.\n A tilted pie would foreshorten it and make the near slices look\n bigger than equal ones at the back. */}\n <circle className={styles.face} cx={centre} cy={centre} r={radius} fill={`url(#${uid}-face)`} />\n <circle className={styles.face} cx={centre} cy={centre} r={radius} fill={`url(#${uid}-edge)`} />\n {donut && (\n // The wall of the hole, so the middle reads as cut through the\n // disc rather than printed on it.\n <circle\n className={styles.hole}\n cx={centre}\n cy={centre}\n r={hole}\n fill=\"none\"\n stroke=\"#000\"\n strokeOpacity=\"0.45\"\n strokeWidth=\"3\"\n />\n )}\n </g>\n\n {donut && (\n <>\n <text className={styles.total} x={centre} y={centre - (label ? 6 : 0)} textAnchor=\"middle\" dominantBaseline=\"middle\">\n {format(hovered !== null ? usable[hovered].value : total)}\n </text>\n {label && (\n <text className={styles.totalLabel} x={centre} y={centre + 14} textAnchor=\"middle\" dominantBaseline=\"middle\">\n {hovered !== null ? usable[hovered].label : label}\n </text>\n )}\n </>\n )}\n </svg>\n\n {legend && (\n <ul className={styles.legend}>\n {usable.map((slice, index) => (\n <li\n key={`${slice.label}-${index}`}\n className={styles.legendItem}\n data-dim={hovered !== null && hovered !== index ? \"\" : undefined}\n >\n <span\n className={styles.swatch}\n style={{ background: slice.color ?? seriesColor(originalIndex(slice)) }}\n aria-hidden=\"true\"\n />\n <span className={styles.legendName}>{slice.label}</span>\n <span className={styles.legendValue}>\n {format(slice.value)}\n <span className={styles.legendPercent}>\n {total > 0 ? Math.round((slice.value / total) * 100) : 0}%\n </span>\n </span>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport { createContext, useContext, useEffect, useRef, type ReactNode } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./Checkbox.module.scss\";\n\ninterface GroupCtx {\n value: string[];\n onValueChange: (v: string[]) => void;\n disabled?: boolean;\n}\nconst Ctx = createContext<GroupCtx | null>(null);\n\n/** The tile, its marks, and the input that actually holds the state. */\nfunction Control({\n checked,\n indeterminate,\n disabled,\n onToggle,\n value,\n ariaLabel,\n}: {\n checked: boolean;\n indeterminate?: boolean;\n disabled?: boolean;\n onToggle: (next: boolean) => void;\n value?: string;\n ariaLabel?: string;\n}) {\n const ref = useRef<HTMLInputElement | null>(null);\n\n // Indeterminate exists only as a DOM property — there is no attribute for\n // it — and setting it is what makes the input announce as \"mixed\".\n useEffect(() => {\n if (ref.current) ref.current.indeterminate = indeterminate === true;\n }, [indeterminate]);\n\n return (\n <>\n <input\n ref={ref}\n type=\"checkbox\"\n className={styles.input}\n aria-label={ariaLabel}\n value={value}\n checked={checked}\n disabled={disabled}\n onChange={(e) => onToggle(e.currentTarget.checked)}\n />\n <span className={styles.box} aria-hidden=\"true\">\n {/* Drawn here rather than with CheckIcon: a stroked path with\n pathLength 1 lets the tick draw itself on, which a filled icon\n cannot do. */}\n <svg className={styles.tick} viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n className={styles.tickPath}\n d=\"M3.5 8.4 6.6 11.5 12.5 4.8\"\n pathLength={1}\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n <span className={styles.dash} />\n </span>\n </>\n );\n}\n\nexport interface CheckboxGroupProps {\n /** The chosen values. Fully controlled; order is the caller's to keep. */\n value: string[];\n /** Called with the new list whenever an item is ticked or unticked. */\n onValueChange: (value: string[]) => void;\n /** Disables every item at once. */\n disabled?: boolean;\n /** Names the set for assistive tech — \"Planet types\", say. Use it whenever\n * the visible heading above the group is not already tied to it. */\n \"aria-label\"?: string;\n /** Merged onto the group wrapper. */\n className?: string;\n /** One or more `CheckboxGroup.Item`. */\n children?: ReactNode;\n}\n\n/**\n * A set of options where any number can be chosen, including none.\n *\n * The group holds the chosen values as an array and reports a new array on\n * every change, so a caller stores one piece of state rather than one boolean\n * per option. For a single yes/no — accepting terms, toggling one setting —\n * use `Checkbox` on its own; for choosing exactly one of several, RadioGroup.\n */\nfunction CheckboxGroupRoot({\n value,\n onValueChange,\n disabled,\n className,\n \"aria-label\": ariaLabel,\n children,\n}: CheckboxGroupProps) {\n return (\n <Ctx.Provider value={{ value, onValueChange, disabled }}>\n {/* group, not radiogroup: these options are independent of each other. */}\n <div role=\"group\" aria-label={ariaLabel} className={cx(styles.root, className)}>\n {children}\n </div>\n </Ctx.Provider>\n );\n}\n\nexport interface CheckboxGroupItemProps {\n /** Added to, or removed from, the group's value when ticked. */\n value: string;\n /** Disables this option only. */\n disabled?: boolean;\n /** The option's label. Part of the click target, not merely beside it. */\n children?: ReactNode;\n}\n\n/**\n * One option in a group.\n *\n * With children it labels itself: a <label> wraps the input, the tile and the\n * children, so the text is part of the click target. Without children it\n * emits a bare span instead, so an OUTER label can own the association —\n * nesting one label inside another is invalid HTML.\n */\nfunction Item({ value, disabled, children }: CheckboxGroupItemProps) {\n const g = useContext(Ctx);\n if (!g) throw new Error(\"CheckboxGroup.Item must be inside a CheckboxGroup\");\n const isDisabled = disabled || g.disabled;\n const checked = g.value.includes(value);\n\n const control = (\n <Control\n checked={checked}\n disabled={isDisabled}\n value={value}\n // Ticking appends, so the order of the value array is the order things\n // were chosen in; unticking keeps the rest as they were.\n onToggle={(next) =>\n g.onValueChange(next ? [...g.value, value] : g.value.filter((v) => v !== value))\n }\n />\n );\n\n if (children === undefined || children === null) {\n return <span className={styles.item}>{control}</span>;\n }\n return (\n <label className={cx(styles.item, styles.selfLabeled)}>\n {control}\n <span className={styles.label}>{children}</span>\n </label>\n );\n}\n\n// Item hangs off the component rather than being a separate export, so the\n// whole API is reachable from the one name a consumer already imported.\nexport const CheckboxGroup = Object.assign(CheckboxGroupRoot, { Item });\n\nexport interface CheckboxProps {\n /** Whether it is ticked. Fully controlled. */\n checked: boolean;\n /** Called with the new state. */\n onCheckedChange: (checked: boolean) => void;\n /** Partly chosen: draws a dash instead of a tick and announces as \"mixed\".\n * For a \"select all\" whose children are only some chosen. The box still\n * reports `checked` when clicked, so decide there what a click means. */\n indeterminate?: boolean;\n /** Disables it. */\n disabled?: boolean;\n /** Names it for assistive tech when there are no children to do so. */\n \"aria-label\"?: string;\n /** Merged onto the label. */\n className?: string;\n /** The label. Part of the click target, not merely beside it. */\n children?: ReactNode;\n}\n\n/**\n * A single yes/no choice: accepting terms, turning one setting on.\n *\n * For a set of options where several can be chosen, wrap `CheckboxGroup`\n * around `CheckboxGroup.Item`s and hold one array instead of a boolean each.\n */\nexport function Checkbox({\n checked,\n onCheckedChange,\n indeterminate,\n disabled,\n className,\n \"aria-label\": ariaLabel,\n children,\n}: CheckboxProps) {\n const control = (\n <Control\n checked={checked}\n indeterminate={indeterminate}\n disabled={disabled}\n ariaLabel={ariaLabel}\n onToggle={onCheckedChange}\n />\n );\n\n if (children === undefined || children === null) {\n return (\n <span className={cx(styles.item, className)}>{control}</span>\n );\n }\n return (\n <label className={cx(styles.item, styles.selfLabeled, className)}>\n {control}\n <span className={styles.label}>{children}</span>\n </label>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport { createContext, useContext, useId, type ReactNode } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./RadioGroup.module.scss\";\n\ninterface GroupCtx {\n value: string;\n onValueChange: (v: string) => void;\n disabled?: boolean;\n name: string;\n}\nconst Ctx = createContext<GroupCtx | null>(null);\n\nexport interface RadioGroupProps {\n /** The selected item's value. Fully controlled. */\n value: string;\n /** Called with the newly selected value. */\n onValueChange: (v: string) => void;\n /** Disables every item at once. */\n disabled?: boolean;\n /** Merged onto the group wrapper. */\n className?: string;\n /** One or more `RadioGroup.Item`. */\n children?: ReactNode;\n}\n\n/**\n * A single-choice control for short lists, where seeing every option at once\n * matters more than saving space. Reach for Select when it does not.\n */\nfunction RadioGroupRoot({ value, onValueChange, disabled, className, children }: RadioGroupProps) {\n const name = useId();\n return (\n <Ctx.Provider value={{ value, onValueChange, disabled, name }}>\n <div role=\"radiogroup\" className={cx(styles.root, className)}>\n {children}\n </div>\n </Ctx.Provider>\n );\n}\n\nexport interface RadioGroupItemProps {\n /** Reported to the group's onValueChange when chosen. */\n value: string;\n /** Disables this option only. */\n disabled?: boolean;\n /** The option's label. Part of the click target, not merely beside it. */\n children?: ReactNode;\n}\n\n/**\n * One option.\n *\n * With children it labels itself: a <label> wraps the input, the orb and the\n * children, so the text is part of the click target. Without children it\n * emits a bare span instead, so an OUTER label can own the association —\n * nesting one label inside another is invalid HTML.\n */\nfunction Item({ value, disabled, children }: RadioGroupItemProps) {\n const g = useContext(Ctx);\n if (!g) throw new Error(\"RadioGroup.Item must be inside a RadioGroup\");\n const isDisabled = disabled || g.disabled;\n const control = (\n <>\n <input\n type=\"radio\"\n className={styles.input}\n name={g.name}\n value={value}\n checked={g.value === value}\n disabled={isDisabled}\n onChange={() => g.onValueChange(value)}\n />\n <span className={cx(styles.orb, \"spRadioOrb\")} aria-hidden=\"true\">\n {/* The orb's own ::before and ::after are the glass and the star\n core, so the ignition ring needs an element of its own. */}\n <span className={styles.burst} />\n </span>\n </>\n );\n if (children === undefined || children === null) {\n return <span className={styles.item}>{control}</span>;\n }\n return (\n <label className={cx(styles.item, styles.selfLabeled)}>\n {control}\n {children}\n </label>\n );\n}\n\n/**\n * Exactly one choice from a set you can see all of at once.\n *\n * Use it where the options matter enough to be read side by side and there are\n * few enough to show — up to about seven. Past that a `Select` keeps the page\n * calm. Where several answers can be true at the same time, that is\n * `CheckboxGroup`.\n *\n * Hold the chosen value and pass `onValueChange`. Each orb ignites when it is\n * chosen, arrow keys move between the options the way a native radio group\n * does, and a label that wraps to two lines keeps its orb beside the first\n * line rather than drifting to the middle.\n *\n * Compose it from `RadioGroup.Item`.\n */\nexport const RadioGroup = Object.assign(RadioGroupRoot, { Item });\n","\"use client\";\nimport type * as React from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./Progress.module.scss\";\n\nexport interface ProgressProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Current progress, clamped between 0 and `max`. */\n value: number;\n /** The value representing complete. */\n max?: number;\n}\n\n/**\n * A determinate bar for work you can measure — use Loader when you cannot.\n *\n * Speaks the same visual language as Slider, because a progress bar and a\n * slider track are the same object: one you watch, one you drag.\n */\nexport function Progress({ value, max = 100, className, style, ...rest }: ProgressProps) {\n const pct = max > 0 ? Math.min(Math.max((value / max) * 100, 0), 100) : 0;\n return (\n <div\n {...rest}\n role=\"progressbar\"\n aria-valuenow={value}\n aria-valuemin={0}\n aria-valuemax={max}\n className={cx(styles.progress, className)}\n style={style}\n >\n {/* Unclassed on purpose: a consumer can target `.progress > div`\n without knowing the hashed module class. */}\n <div style={{ width: `${pct}%`, height: \"100%\" }} />\n </div>\n );\n}\n","\"use client\";\nimport type * as React from \"react\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { cx } from \"./propShared\";\nimport { InfoCircledIcon, ExclamationTriangleIcon, CrossCircledIcon } from \"./icons\";\nimport styles from \"./Message.module.scss\";\n\nexport type MessageVariant = \"info\" | \"warning\" | \"alert\";\n\n/** Each variant carries its own glyph, so the message reads at a glance\n * before any of its words do. Overridable per instance via `icon`. */\nconst ICONS: Record<MessageVariant, ReactNode> = {\n info: <InfoCircledIcon />,\n warning: <ExclamationTriangleIcon />,\n alert: <CrossCircledIcon />,\n};\n\n/**\n * How loudly each variant announces itself.\n *\n * `alert` uses role=\"alert\", which is assertive: it interrupts whatever a\n * screen reader is saying. That is right for something gone wrong and wrong\n * for everything else, so info and warning are polite status regions that\n * wait their turn.\n */\nconst ROLES: Record<MessageVariant, { role: string; live?: \"polite\" }> = {\n info: { role: \"status\", live: \"polite\" },\n warning: { role: \"status\", live: \"polite\" },\n alert: { role: \"alert\" },\n};\n\nexport interface MessageProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Which message this is. `info` states something, `warning` flags a risk\n * worth acting on, `alert` reports something already wrong. Default\n * `info`. */\n variant?: MessageVariant;\n /** An optional bold line above the body. Omit for a single-line message —\n * a title that merely restates the body is noise.\n *\n * This shadows the HTML `title` attribute, which took a string and showed\n * a browser tooltip. A tooltip on a banner nobody hovers was never the\n * useful reading of the name. */\n title?: ReactNode;\n /** Replaces the variant's own glyph. Pass `null` for no icon at all. */\n icon?: ReactNode;\n /** The message. */\n children?: ReactNode;\n}\n\n/**\n * A banner that tells the reader something about the state of the page — a\n * risk, a result, a failure.\n *\n * The three variants do not merely change hue. `info` is lit like the rest of\n * the system, cool and calm; `warning` warms the rim to amber; `alert` uses\n * the ember treatment, the same warm limb the destructive Button wears. Each\n * carries its own glyph so the kind of message reads before the words do.\n *\n * For a decision the reader must make, reach for `AlertDialog` instead — a\n * message states, it does not ask.\n */\nexport const Message = forwardRef<HTMLDivElement, MessageProps>(function Message(\n { variant = \"info\", title, icon, className, children, ...rest },\n ref,\n) {\n const glyph = icon === undefined ? ICONS[variant] : icon;\n const { role, live } = ROLES[variant];\n\n return (\n <div\n {...rest}\n ref={ref}\n role={role}\n aria-live={live}\n className={cx(styles.message, styles[variant], className)}\n >\n {glyph != null && (\n <span className={styles.icon} aria-hidden=\"true\">\n {glyph}\n </span>\n )}\n <div className={styles.body}>\n {title != null && <p className={styles.title}>{title}</p>}\n {children != null && <div className={styles.text}>{children}</div>}\n </div>\n </div>\n );\n});\n","// src/components/ui/Dialog.tsx\n// Compound Dialog matching the Radix JSX shape on a native <dialog>:\n// top-layer stacking (nested/stacked dialogs work), built-in focus trap and\n// focus return, Esc via the `cancel` event. Both controlled (open/\n// onOpenChange) and Trigger-driven uncontrolled sites are supported — the\n// inventory has both. Esc handoff with the in-house Select: a capture-phase\n// keydown checks for an open listbox inside the dialog and flags the next\n// `cancel` to be swallowed, so one Esc closes the Select, the next closes\n// the dialog (matching the Radix-era behavior sites were built against).\n\"use client\";\nimport type * as React from \"react\";\nimport { XIcon } from \"./icons\";\nimport {\n cloneElement, createContext, isValidElement, useContext, useEffect,\n useId, useLayoutEffect, useRef, useState, type ReactNode,\n} from \"react\";\nimport { cx } from \"./propShared\";\nimport { Heading, type HeadingProps } from \"./Heading\";\nimport { Text, type TextProps } from \"./Text\";\nimport styles from \"./Dialog.module.scss\";\n\n// Body scroll-lock reference count, shared across every mounted Content\n// instance (module scope, not per-instance state) — Dialog and AlertDialog\n// stack on top of one another, and per-instance prev-capture couldn't tell\n// \"I'm the last one closing\" from \"another instance is still open\" when\n// unmounts land out of open-order. A plain 0→1 / 1→0 edge count is\n// order-proof: overflow is locked exactly while count > 0, regardless of\n// which instance opened or closed first.\nlet lockCount = 0;\n\nexport interface DialogCtx {\n open: boolean;\n setOpen: (o: boolean) => void;\n titleId: string;\n descId: string;\n /** alert dialogs: no backdrop light-dismiss */\n alert?: boolean;\n /** whether a Description is currently mounted (drives aria-describedby) */\n hasDesc: boolean;\n setHasDesc: (v: boolean) => void;\n}\nconst Ctx = createContext<DialogCtx | null>(null);\nexport const useDialog = () => {\n const ctx = useContext(Ctx);\n if (!ctx) throw new Error(\"Dialog parts must be inside a Dialog\");\n return ctx;\n};\n\nexport interface DialogProps {\n /** Controls the dialog. Omit both this and onOpenChange to let the dialog\n * manage its own state. */\n open?: boolean;\n /** Called whenever the dialog opens or closes, including via Escape or a\n * backdrop click. */\n onOpenChange?: (o: boolean) => void;\n /** A `Trigger` and a `Content`, in any arrangement — this renders\n * nothing itself, so they can sit anywhere beneath it. */\n children?: ReactNode;\n}\n\n/** Shared by Dialog and AlertDialog; only the alert flag differs. */\nexport function makeRoot(alert: boolean) {\n return function DialogRoot({ open, onOpenChange, children }: DialogProps) {\n const [internal, setInternal] = useState(false);\n const isControlled = open !== undefined;\n const actual = isControlled ? open : internal;\n const setOpen = (o: boolean) => {\n if (!isControlled) setInternal(o);\n onOpenChange?.(o);\n };\n const titleId = useId();\n const descId = useId();\n const [hasDesc, setHasDesc] = useState(false);\n return (\n <Ctx.Provider value={{ open: actual, setOpen, titleId, descId, alert, hasDesc, setHasDesc }}>\n {children}\n </Ctx.Provider>\n );\n };\n}\n/**\n * Owns a dialog's open state. Works controlled via `open`/`onOpenChange`, or\n * uncontrolled if you pass neither.\n *\n * Renders nothing itself — it only provides context, so Trigger and Content\n * can sit anywhere beneath it in the tree.\n */\nconst Root = makeRoot(false);\n\ntype Clickable = React.ReactElement<{ onClick?: (e: React.MouseEvent) => void }>;\nconst chainOpen = (child: ReactNode, fn: () => void): ReactNode => {\n if (!isValidElement(child)) return child;\n const c = child as Clickable;\n return cloneElement(c, {\n onClick: (e: React.MouseEvent) => { c.props.onClick?.(e); fn(); },\n });\n};\n\n/**\n * Opens the dialog. Chains onto its child's existing click handler rather\n * than replacing it, and renders no element of its own — so the child stays\n * whatever it already was, button or otherwise.\n */\nexport function Trigger({\n children,\n}: {\n /** The control that opens the dialog. Its own onClick still fires. */\n children?: ReactNode;\n}) {\n const d = useDialog();\n return <>{chainOpen(children, () => d.setOpen(true))}</>;\n}\n\n/**\n * Closes the dialog. Same shape as Trigger: wraps its child, adds a close on\n * click, and adds no markup.\n */\nexport function Close({\n children,\n}: {\n /** The control that closes the dialog. Its own onClick still fires. */\n children?: ReactNode;\n}) {\n const d = useDialog();\n return <>{chainOpen(children, () => d.setOpen(false))}</>;\n}\n\nexport interface ContentProps extends React.HTMLAttributes<HTMLDialogElement> {\n /** Padding and radius step. 4 is roomier, for dialogs carrying a form. */\n size?: \"3\" | \"4\";\n /** Caps the dialog's width, e.g. \"480px\". Without it the dialog uses its\n * own default and grows with its content. */\n maxWidth?: string;\n /** Dialog contents. Include a Title — it is the accessible name. */\n children?: ReactNode;\n}\n\n/**\n * The dialog surface. Built on the native `<dialog>` element, so the browser\n * supplies the top layer, focus trapping and Escape handling rather than the\n * library reimplementing them.\n *\n * Dismissible by Escape or a click on the backdrop; AlertDialog's Content\n * deliberately is not.\n */\nexport function Content({ size = \"3\", maxWidth, className, style, children, ...rest }: ContentProps) {\n const d = useDialog();\n const ref = useRef<HTMLDialogElement | null>(null);\n const swallowCancel = useRef(false);\n // Backdrop dismissal must require BOTH the mousedown/pointerdown AND the\n // click to land on the backdrop (the <dialog> element itself, not the\n // inner content wrapper) — otherwise a text-selection drag that starts in\n // the content and ends up released over the backdrop would close the\n // dialog on mouseup even though the gesture began inside it.\n const pointerDownOnBackdrop = useRef(false);\n\n // Imperative <dialog> API follows the declarative open prop (handles the\n // delayed first open of AccountsIntroModal's 900ms timer too).\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n if (d.open && !el.open) el.showModal();\n else if (!d.open && el.open) el.close();\n }, [d.open]);\n\n // Body scroll lock while open (Radix did this; panels behind rely on it).\n // Module-level counter (see `lockCount` above) so stacked dialogs compose:\n // only the 0→1 transition locks, only the 1→0 transition unlocks.\n useEffect(() => {\n if (!d.open) return;\n lockCount += 1;\n if (lockCount === 1) document.body.style.overflow = \"hidden\";\n return () => {\n lockCount -= 1;\n if (lockCount === 0) document.body.style.overflow = \"\";\n };\n }, [d.open]);\n\n return (\n <dialog\n {...rest}\n ref={ref}\n role={d.alert ? \"alertdialog\" : undefined}\n aria-labelledby={d.titleId}\n aria-describedby={d.hasDesc ? d.descId : undefined}\n className={cx(styles.dialog, \"spDialog\", size === \"4\" && styles.size4, className)}\n style={{ ...(maxWidth ? { maxWidth } : null), ...style }}\n onKeyDownCapture={(e) => {\n if (e.key !== \"Escape\") return;\n // A nested dialog is open inside this one (e.g. an AlertDialog\n // launched from this dialog's content) — that inner dialog owns\n // this Esc; don't let the outer one arm its own swallow logic on\n // an event that's about to close a dialog it isn't itself.\n if (ref.current?.querySelector(\"dialog[open]\")) return;\n // Esc while an in-house Select's listbox is open inside this dialog:\n // the Select closes itself; swallow the dialog's own cancel.\n if (ref.current?.querySelector('[role=\"listbox\"]:not([hidden])')) {\n swallowCancel.current = true;\n }\n }}\n onCancel={(e) => {\n e.preventDefault(); // we route ALL closes through React state\n if (swallowCancel.current) { swallowCancel.current = false; return; }\n d.setOpen(false);\n }}\n onClose={() => {\n // Belt-and-suspenders: any UA-initiated close we didn't route\n // through onCancel (a non-cancelable close request, or a future\n // method=\"dialog\" form submission inside the content) still fires\n // `close`. Resync React state so `open` doesn't get stranded true\n // while the native element is actually closed.\n if (d.open) d.setOpen(false);\n }}\n onPointerDown={(e) => {\n pointerDownOnBackdrop.current = e.target === ref.current;\n }}\n onClick={(e) => {\n // Backdrop click = clicking the <dialog> element itself (the inner\n // wrapper covers the content area). Alert dialogs don't light-dismiss.\n // Require the pointerdown that started this click to have also\n // landed on the backdrop, so a text-selection drag from the content\n // out to the backdrop doesn't close the dialog on release.\n if (!d.alert && e.target === ref.current && pointerDownOnBackdrop.current) d.setOpen(false);\n }}\n >\n <div className={styles.inner}>\n {/* Every dialog gets the same dismiss affordance in the same place.\n Alert dialogs are excluded on purpose: they ask a question that\n wants an explicit answer, and a corner X is an ambiguous one. */}\n {!d.alert && (\n <button\n type=\"button\"\n className={styles.closeX}\n aria-label=\"Close\"\n onClick={() => d.setOpen(false)}\n >\n <XIcon width={16} height={16} />\n </button>\n )}\n {children}\n </div>\n </dialog>\n );\n}\n\n/**\n * The dialog's accessible name. Wire one up for every dialog — it is what a\n * screen reader announces when the dialog opens.\n */\nexport function Title({ className, ...rest }: HeadingProps) {\n const d = useDialog();\n return <Heading as=\"h2\" size=\"5\" {...rest} id={d.titleId} className={cx(styles.title, className)} />;\n}\n\n/**\n * Supporting copy beneath the title, registered as the dialog's accessible\n * description. Optional, and only announced when present.\n */\nexport function Description(props: TextProps) {\n const d = useDialog();\n // aria-describedby on Content is conditional on a Description actually\n // being mounted (some dialogs render none), so Content can't just point\n // at descId unconditionally. Register/unregister via a layout effect —\n // runs before paint, and Description mounts synchronously with the\n // dialog's content, so there's no visible flash of a missing attribute.\n // Depend on setHasDesc alone (a stable useState setter), not the whole\n // `d` context object — that object is a fresh literal every Root render,\n // so depending on it would re-fire this effect (and its cleanup) on\n // every render instead of just mount/unmount.\n const { setHasDesc } = d;\n useLayoutEffect(() => {\n setHasDesc(true);\n return () => setHasDesc(false);\n }, [setHasDesc]);\n return <Text as=\"p\" {...props} id={d.descId} />;\n}\n\n/**\n * A modal window over the page, for a task that has to finish or be abandoned\n * before anything else happens.\n *\n * It rides the platform's own `<dialog>`, so the backdrop, the top layer, the\n * Escape key and the focus trap are the browser's rather than an\n * approximation of them. Opening moves focus inside; closing returns it to\n * whatever opened it.\n *\n * For a decision with consequences — deleting, discarding, overwriting —\n * reach for `AlertDialog`, which refuses to close by a click outside, so a\n * misplaced click cannot answer the question for the reader.\n *\n * Compose it from the parts hanging off this name: `Dialog.Trigger`,\n * `Dialog.Content`, `Dialog.Title`, `Dialog.Description` and `Dialog.Close`.\n */\nexport const Dialog = Object.assign(Root, {\n Trigger,\n Close,\n Content,\n Title,\n Description,\n});\n","// The same native-<dialog> engine as Dialog, with alertdialog semantics:\n// role=\"alertdialog\", and NO backdrop light-dismiss — an alert is a decision,\n// so it does not go away because you clicked beside it. Render Cancel before\n// Action so showModal()'s initial focus lands on the safe choice.\n\"use client\";\nimport {\n makeRoot, Trigger, Close,\n Content, Title, Description,\n type DialogProps,\n} from \"./Dialog\";\n\nexport type { DialogProps as AlertDialogProps };\n\n// Cancel and Action are the same component under two names. The name is the\n// point: it says which one is destructive at the call site, and it makes the\n// ordering rule above readable rather than positional trivia. Close chains\n// the child's own onClick before closing, so an Action's handler runs first.\nconst Cancel = Close;\nconst Action = Close;\n\n/**\n * A modal that interrupts to confirm something consequential.\n *\n * Unlike a Dialog it has no backdrop dismissal, because dismissing an alert\n * by missing it is not a decision. Put `Cancel` before `Action` so the safe\n * choice takes focus when it opens.\n */\nexport const AlertDialog = Object.assign(makeRoot(true), {\n Trigger,\n Content,\n Title,\n Description,\n Cancel,\n Action,\n});\n","// src/components/ui/DropdownMenu.tsx\n// role=\"menu\" on a popover=\"auto\" div: top-layer + click-outside dismissal\n// come from the platform. Anchor positioning is manual (align=\"end\" is the\n// only inventoried mode). Roving tabindex arrows per the spec.\n\"use client\";\nimport type * as React from \"react\";\nimport {\n createContext, createElement, isValidElement, useCallback, useContext,\n useEffect, useId, useLayoutEffect, useRef, useState, type ReactNode,\n} from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./DropdownMenu.module.scss\";\nimport { Button, type ButtonProps } from \"./Button\";\n\ninterface MenuCtx {\n open: boolean;\n setOpen: (o: boolean) => void;\n menuId: string;\n}\nconst Ctx = createContext<MenuCtx | null>(null);\nconst useMenu = () => {\n const ctx = useContext(Ctx);\n if (!ctx) throw new Error(\"DropdownMenu parts must be inside a DropdownMenu\");\n return ctx;\n};\n\n\nexport interface DropdownMenuProps extends Omit<ButtonProps, \"children\"> {\n /** The trigger's content. The trigger is always a Button, so this is what\n * goes inside it — text, or an icon with `iconOnly`. */\n label: ReactNode;\n /** Which edge of the trigger the menu lines up with. Use `end` when the\n * trigger sits near the right edge and the menu would overflow. */\n align?: \"start\" | \"end\";\n /** `DropdownMenu.Item`, `.Separator` and `.Label`, in any order. */\n children?: ReactNode;\n}\n\n/**\n * A menu of actions hung off a button.\n *\n * The trigger is built in and is always a Button — a dropdown whose trigger\n * looked like anything else was never a shape worth supporting, and making it\n * arbitrary cost a `cloneElement` that had to graft aria wiring and a click\n * handler onto someone else's element.\n *\n * The menu rides the platform's top layer via `popover`, so click-outside\n * dismissal and stacking come from the browser rather than an approximation.\n * Arrows move between items, Escape closes and returns focus to the trigger.\n */\nfunction DropdownMenuRoot({ label, align = \"start\", children, ...buttonProps }: DropdownMenuProps) {\n const [open, setOpenState] = useState(false);\n const menuId = useId();\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const menuRef = useRef<HTMLDivElement | null>(null);\n // What a pointer press on the trigger meant, decided at pointerdown — before\n // the platform has had a chance to light-dismiss. See the trigger below.\n const pressIntent = useRef<boolean | null>(null);\n // The latest open state, including one requested this tick but not yet\n // rendered. The trigger's click and the menu's toggle can report the same\n // close in one gesture; this is what makes the second report a no-op.\n const openNow = useRef(open);\n openNow.current = open;\n\n const setOpen = useCallback((next: boolean) => {\n if (openNow.current === next) return;\n openNow.current = next;\n setOpenState(next);\n }, []);\n const [pos, setPos] = useState<{ top: number; left: number | \"auto\"; right: number | \"auto\" } | null>(null);\n\n // useLayoutEffect (not useEffect) so the position is measured and applied\n // synchronously before paint — matches Select's trigger measurement and\n // avoids a one-frame flash at the wrong coordinates.\n useLayoutEffect(() => {\n const el = menuRef.current;\n if (!el) return;\n if (open) {\n // Position under the trigger before entering the top layer.\n const trigger = triggerRef.current;\n if (trigger) {\n const r = trigger.getBoundingClientRect();\n const left = align === \"end\" ? \"auto\" : r.left;\n const right = align === \"end\" ? window.innerWidth - r.right : \"auto\";\n setPos({ top: r.bottom + 6, left, right });\n }\n el.showPopover();\n // Focus the first item for keyboard users.\n el.querySelector<HTMLElement>('[role=\"menuitem\"]')?.focus();\n } else if (el.matches(\":popover-open\")) {\n el.hidePopover();\n }\n }, [open, align]);\n\n // A resize invalidates the anchored position (measured once, at open) —\n // rather than re-measuring on every tick, close the menu, as a light\n // dismiss would.\n useEffect(() => {\n if (!open) return;\n const onResize = () => setOpen(false);\n window.addEventListener(\"resize\", onResize);\n return () => window.removeEventListener(\"resize\", onResize);\n }, [open]);\n\n return (\n <Ctx.Provider value={{ open, setOpen, menuId }}>\n <Button\n {...buttonProps}\n ref={triggerRef}\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-controls={menuId}\n onPointerDown={(e) => {\n buttonProps.onPointerDown?.(e);\n // Decide here, not on click. Pressing the trigger while the menu is\n // open is an outside press to the platform, which closes the menu\n // during pointerdown — so by click the menu already reads as shut\n // and a plain toggle would reopen it. The toggle event cannot\n // settle it either: it fires after click. What the reader meant is\n // knowable only at the moment they pressed.\n //\n // This replaces a 300ms timer that ignored trigger clicks after any\n // close. Escape armed it too, so a click shortly after Escape was\n // silently swallowed.\n pressIntent.current = !openNow.current;\n }}\n onKeyDown={(e) => {\n buttonProps.onKeyDown?.(e);\n // A press dragged off the button never clicks, which would leave its\n // intent behind to hijack the next Enter or Space. Keys decide fresh.\n if (e.key === \"Enter\" || e.key === \" \") pressIntent.current = null;\n }}\n onClick={(e) => {\n buttonProps.onClick?.(e);\n // Keyboard activation has no pointerdown, so it falls back to a\n // straight toggle — Enter and Space never light-dismiss.\n const next = pressIntent.current ?? !openNow.current;\n pressIntent.current = null;\n setOpen(next);\n }}\n >\n {label}\n </Button>\n\n <div\n ref={menuRef}\n id={menuId}\n role=\"menu\"\n popover=\"auto\"\n className={styles.menu}\n style={\n pos\n ? {\n top: pos.top,\n left: pos.left === \"auto\" ? \"auto\" : pos.left,\n right: pos.right === \"auto\" ? \"auto\" : pos.right,\n }\n : undefined\n }\n onToggle={(e: React.SyntheticEvent<HTMLDivElement>) => {\n // A platform close — a press elsewhere or Escape — synced into\n // state. setOpen ignores a close already recorded, such as one an\n // Item or the trigger asked for.\n if ((e.nativeEvent as ToggleEvent).newState === \"closed\") setOpen(false);\n }}\n onKeyDown={(e) => {\n const items = Array.from(\n menuRef.current?.querySelectorAll<HTMLElement>('[role=\"menuitem\"]') ?? []\n );\n const idx = items.indexOf(document.activeElement as HTMLElement);\n if (e.key === \"ArrowDown\") { e.preventDefault(); items[Math.min(idx + 1, items.length - 1)]?.focus(); }\n else if (e.key === \"ArrowUp\") { e.preventDefault(); items[Math.max(idx - 1, 0)]?.focus(); }\n else if (e.key === \"Home\") { e.preventDefault(); items[0]?.focus(); }\n else if (e.key === \"End\") { e.preventDefault(); items[items.length - 1]?.focus(); }\n else if (e.key === \"Escape\") { setOpen(false); triggerRef.current?.focus(); }\n }}\n >\n {children}\n </div>\n </Ctx.Provider>\n );\n}\n\n/**\n * A non-interactive heading for a group of items. Skipped by arrow-key\n * navigation, since there is nothing to activate.\n */\nfunction Label({\n children,\n}: {\n /** Heading text for the group beneath it. Not focusable. */\n children?: ReactNode;\n}) {\n return <div className={styles.label}>{children}</div>;\n}\n\nexport interface DropdownMenuItemProps {\n /** Render the child element instead of the default item — for a link that\n * should stay an anchor rather than becoming a button. */\n asChild?: boolean;\n /** Marks a destructive action, so it reads differently before it is\n * chosen rather than after. */\n color?: \"danger\";\n /** Runs when the item is chosen; the menu closes either way. */\n onSelect?: () => void | Promise<void>;\n /** The item's label. */\n children?: ReactNode;\n}\n\n/**\n * One menu action. `onSelect` fires and the menu closes.\n *\n * Pass `color=\"danger\"` for a destructive action so it reads differently from\n * its neighbours before it is chosen, not after.\n */\nfunction Item({ asChild, color, onSelect, children }: DropdownMenuItemProps) {\n const m = useMenu();\n const cls = cx(styles.item, color === \"danger\" && styles.danger);\n const activate = () => {\n m.setOpen(false);\n void onSelect?.();\n };\n if (asChild && isValidElement(children)) {\n const child = children as React.ReactElement<Record<string, unknown>>;\n // Rebuild (rather than cloneElement) so role/tabIndex land BEFORE the\n // child's own attributes (e.g. href) in the emitted markup — cloneElement\n // always keeps pre-existing keys in their original position. Also drop\n // the child's own role/tabIndex (if any) from restProps entirely — a\n // spread landing after the forced menuitem/-1 values would otherwise\n // silently win and undo the forced semantics.\n const {\n className: childClassName, onClick: childOnClick, children: childChildren,\n role: childRole, tabIndex: childTabIndex, ...restProps\n } = child.props;\n // Discarded — pulled out of restProps only so the forced role/tabIndex\n // below can't be silently overwritten by the child's own values.\n void childRole;\n void childTabIndex;\n const originalRef = (child as unknown as { ref?: React.Ref<unknown> }).ref;\n return createElement(\n child.type as React.ElementType,\n {\n key: child.key,\n ref: originalRef,\n role: \"menuitem\",\n tabIndex: -1,\n ...restProps,\n className: cx(cls, childClassName as string | undefined),\n onClick: (e: React.MouseEvent) => {\n (childOnClick as ((e: React.MouseEvent) => void) | undefined)?.(e);\n m.setOpen(false); // real navigation proceeds; menu closes\n },\n },\n childChildren as ReactNode,\n );\n }\n return (\n <button type=\"button\" role=\"menuitem\" tabIndex={-1} className={cls} onClick={activate}>\n {children}\n </button>\n );\n}\n\n/**\n * A rule between groups of items — for separating a destructive action from\n * routine ones, so the two are not adjacent to a moving cursor.\n */\nfunction Separator() {\n return <div role=\"separator\" className={styles.separator} />;\n}\n\n/**\n * A button that opens a list of actions.\n *\n * Actions, not choices: every item does something when picked, and nothing in\n * the menu holds a value. For choosing one of a set of values, that is\n * `Select`, which looks similar and means something entirely different to a\n * screen reader.\n *\n * Arrow keys move through the items, Home and End jump to the ends, Escape\n * closes and returns focus to the button, and typing a letter jumps to the\n * next item starting with it. The panel uses the browser's popover layer, so\n * it stacks above the page without a z-index to maintain.\n *\n * Compose it from `DropdownMenu.Item`, `DropdownMenu.Label` and\n * `DropdownMenu.Separator`.\n */\nexport const DropdownMenu = Object.assign(DropdownMenuRoot, { Item, Separator, Label });\n","// ARIA tabs. Inactive Content unmounts, matching Radix's default.\n\"use client\";\nimport type * as React from \"react\";\nimport { createContext, useContext, useId, type ReactNode } from \"react\";\nimport { cx } from \"./propShared\";\nimport styles from \"./Tabs.module.scss\";\n\ninterface TabsCtx {\n value: string;\n onValueChange: (v: string) => void;\n /** useId()-derived base, shared by Trigger/Content so a trigger's\n * aria-controls always matches its panel's id (and vice versa via\n * aria-labelledby) without either side guessing the other's id. */\n id: string;\n}\nconst Ctx = createContext<TabsCtx | null>(null);\nconst useTabs = () => {\n const ctx = useContext(Ctx);\n if (!ctx) throw new Error(\"Tabs parts must be inside a Tabs\");\n return ctx;\n};\n\nexport interface TabsProps {\n /** The selected tab's value. Fully controlled — there is no default. */\n value: string;\n /** Called with the newly selected tab's value. */\n onValueChange: (v: string) => void;\n /** Merged onto the wrapper div, which is otherwise unstyled. */\n className?: string;\n /** A `Tabs.List` and the `Tabs.Content`s it switches between. */\n children?: ReactNode;\n}\n\n/**\n * Wraps a tab set and owns which tab is showing. Fully controlled — pass\n * `value` and `onValueChange`; there is no uncontrolled mode.\n *\n * Renders a plain div, so it imposes no layout of its own. It also mints the\n * id that pairs each Trigger with its Content, which is why every part has to\n * sit inside it rather than being usable on its own.\n */\nfunction TabsRoot({ value, onValueChange, className, children }: TabsProps) {\n const id = useId();\n return (\n <Ctx.Provider value={{ value, onValueChange, id }}>\n <div className={className}>{children}</div>\n </Ctx.Provider>\n );\n}\n\n/**\n * The row of triggers, and the keyboard model for the set: arrow keys move\n * between tabs, Home and End jump to the ends, each moving focus and\n * selection together as the ARIA tabs pattern expects.\n *\n * Bottom-aligns its children, so an active tab that grows taller rises above\n * its neighbours instead of pushing the row down — the folder-tab effect.\n */\nfunction List({\n children,\n}: {\n /** The Triggers. Their order is the tab order. */\n children?: ReactNode;\n}) {\n return (\n <div\n role=\"tablist\"\n className={cx(styles.list, \"spTabsList\")}\n onKeyDown={(e) => {\n const tabs = Array.from(\n (e.currentTarget as HTMLElement).querySelectorAll<HTMLElement>('[role=\"tab\"]')\n );\n const idx = tabs.indexOf(document.activeElement as HTMLElement);\n if (idx === -1) return;\n if (e.key === \"ArrowRight\") { e.preventDefault(); const t = tabs[(idx + 1) % tabs.length]; t.focus(); t.click(); }\n else if (e.key === \"ArrowLeft\") { e.preventDefault(); const t = tabs[(idx - 1 + tabs.length) % tabs.length]; t.focus(); t.click(); }\n else if (e.key === \"Home\") { e.preventDefault(); const t = tabs[0]; t.focus(); t.click(); }\n else if (e.key === \"End\") { e.preventDefault(); const t = tabs[tabs.length - 1]; t.focus(); t.click(); }\n }}\n >\n {children}\n </div>\n );\n}\n\n/**\n * One tab. Selects its `value` on click and carries the ARIA wiring that ties\n * it to the matching Content.\n *\n * Emits `data-state=\"active\" | \"inactive\"`, which is the hook the active\n * styling keys off — useful if you are restyling tabs from outside.\n */\nfunction Trigger({ value, className, children, ...rest }: {\n /** Selects this value. Must match the Content it reveals. */\n value: string;\n /** Merged with the tab's own classes rather than replacing them. */\n className?: string;\n /** The tab's label. */\n children?: ReactNode;\n} & React.ButtonHTMLAttributes<HTMLButtonElement>) {\n const t = useTabs();\n const active = t.value === value;\n return (\n <button\n {...rest}\n type=\"button\"\n role=\"tab\"\n id={`${t.id}-tab-${value}`}\n aria-selected={active}\n aria-controls={`${t.id}-panel-${value}`}\n tabIndex={active ? 0 : -1}\n data-state={active ? \"active\" : \"inactive\"}\n className={cx(styles.trigger, \"spTabsTrigger\", className)}\n onClick={() => t.onValueChange(value)}\n >\n {children}\n </button>\n );\n}\n\n/**\n * The panel for one tab. Renders only while its `value` is the selected one —\n * inactive panels unmount rather than hide, so their contents do not run,\n * hold state, or appear to a screen reader.\n *\n * Carries no styling: the surface a tab set seats onto is the consumer's, and\n * should match `--sp-tabs-surface-color` so the active tab connects to it.\n */\nfunction Content({\n value,\n children,\n}: {\n /** Shown while this matches the Root's value. Must match a Trigger. */\n value: string;\n /** Panel contents. Unmounted while another tab is selected. */\n children?: ReactNode;\n}) {\n const t = useTabs();\n if (t.value !== value) return null;\n return (\n <div role=\"tabpanel\" id={`${t.id}-panel-${value}`} aria-labelledby={`${t.id}-tab-${value}`}>\n {children}\n </div>\n );\n}\n\n/**\n * Several panels sharing one piece of the page, one visible at a time.\n *\n * Right for views of the same subject that a reader moves between and\n * compares — overview, history, settings for one record. Wrong for steps in a\n * sequence, where the reader needs to know how far along they are, and wrong\n * for content that should be findable by search or linkable on its own: a\n * hidden panel is invisible to both.\n *\n * Arrow keys move between the tabs, Home and End jump to the ends, and only\n * the selected tab is in the tab order, so one press of Tab leaves the strip\n * for the panel instead of walking every tab in it.\n *\n * Compose it from `Tabs.List`, `Tabs.Trigger` and `Tabs.Content`.\n */\nexport const Tabs = Object.assign(TabsRoot, { List, Trigger, Content });\n","\"use client\";\nimport type * as React from \"react\";\nimport {\n useCallback, useEffect, useId, useLayoutEffect, useRef, useState, type ReactNode,\n} from \"react\";\nimport { cx } from \"./propShared\";\nimport { Button, type ButtonProps } from \"./Button\";\nimport styles from \"./Popover.module.scss\";\nimport { showMeasured } from \"../internal/showMeasured\";\nimport ctl from \"../styles/spaceControls\";\n\nconst OFFSET = 8;\nconst EDGE_PADDING = 8;\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\nexport interface PopoverProps extends Omit<ButtonProps, \"children\"> {\n /** What the trigger shows. The trigger is always a Button, so this is its\n * content — text, or an icon with `iconOnly` and an `aria-label`. */\n label: ReactNode;\n /** The panel's contents. Anything: a form, a filter set, a prompt. For a\n * list of actions reach for DropdownMenu; for a line of text, Tooltip. */\n children?: ReactNode;\n /** Controls the panel. Omit both this and `onOpenChange` to let the popover\n * manage itself. */\n open?: boolean;\n /** Called whenever the panel opens or closes, including by Escape or a\n * click elsewhere. */\n onOpenChange?: (open: boolean) => void;\n /** Open on first render when uncontrolled. Focus is left where it is, so a\n * popover shown on arrival never steals the page's focus. */\n defaultOpen?: boolean;\n /** Which side of the trigger the panel prefers. It flips to the other side\n * when there is no room. Default `bottom`. */\n side?: \"top\" | \"bottom\";\n /** Which edge of the trigger the panel lines up with. Use `end` for a\n * trigger near the right of the viewport. Default `start`. */\n align?: \"start\" | \"center\" | \"end\";\n /** Merged onto the panel. */\n panelClassName?: string;\n}\n\n/**\n * A button that opens a floating panel of anything — a small form, a set of\n * filters, a prompt — without leaving the page.\n *\n * It rides the browser's own popover layer, so the panel stacks above\n * everything without a z-index arms race and closes on Escape or a click\n * elsewhere by the platform's rules rather than an approximation of them. It\n * sits next to its trigger, flips above it when there is no room below, and\n * stays attached to it if the page scrolls or the layout around it shifts.\n *\n * Opening moves focus into the panel so a keyboard user lands on its first\n * control; closing with Escape hands focus back to the trigger. The panel is\n * labelled by the trigger, so it announces as what the button said it was.\n */\nexport function Popover({\n label,\n children,\n open: openProp,\n onOpenChange,\n defaultOpen = false,\n side = \"bottom\",\n align = \"start\",\n panelClassName,\n onClick,\n ...buttonProps\n}: PopoverProps) {\n const [internal, setInternal] = useState(defaultOpen);\n const controlled = openProp !== undefined;\n const open = controlled ? openProp : internal;\n\n const triggerId = useId();\n const panelId = useId();\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const panelRef = useRef<HTMLDivElement | null>(null);\n const [pos, setPos] = useState<{ top: number; left: number; placed: \"top\" | \"bottom\" } | null>(null);\n\n // Whether the next open came from the reader, as opposed to defaultOpen on\n // mount. Only a reader's open moves focus.\n const openedByReader = useRef(false);\n // Set by Escape inside the panel, so the close that follows returns focus.\n const closingByEscape = useRef(false);\n // What a pointer press on the trigger meant, decided at pointerdown — before\n // the platform has had a chance to light-dismiss. See the trigger below.\n const pressIntent = useRef<boolean | null>(null);\n // The latest open state, including one requested this tick but not yet\n // rendered. Both the trigger's click and the panel's toggle can report the\n // same close in one gesture; this is what stops onOpenChange hearing twice.\n const openNow = useRef(open);\n openNow.current = open;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (openNow.current === next) return;\n openNow.current = next;\n if (!controlled) setInternal(next);\n onOpenChange?.(next);\n },\n [controlled, onOpenChange],\n );\n\n const place = useCallback(() => {\n const trigger = triggerRef.current;\n const panel = panelRef.current;\n if (!trigger || !panel) return;\n const r = trigger.getBoundingClientRect();\n const w = panel.offsetWidth;\n const h = panel.offsetHeight;\n\n const below = r.bottom + OFFSET;\n const above = r.top - h - OFFSET;\n const fitsBelow = below + h <= window.innerHeight - EDGE_PADDING;\n const fitsAbove = above >= EDGE_PADDING;\n const top = side === \"bottom\"\n ? (fitsBelow || !fitsAbove ? below : above)\n : (fitsAbove || !fitsBelow ? above : below);\n // Where it actually landed after any flip, so the reveal can travel away\n // from the trigger rather than towards it. Written to the element as well\n // as to state: the reveal reads it before React has re-rendered.\n const placed = top === below ? \"bottom\" : \"top\";\n panel.dataset.side = placed;\n\n const wanted =\n align === \"start\" ? r.left : align === \"end\" ? r.right - w : r.left + r.width / 2 - w / 2;\n const left = Math.min(\n Math.max(wanted, EDGE_PADDING),\n Math.max(window.innerWidth - w - EDGE_PADDING, EDGE_PADDING),\n );\n setPos((prev) =>\n prev && prev.top === top && prev.left === left && prev.placed === placed\n ? prev\n : { top, left, placed },\n );\n }, [side, align]);\n\n // Show before measuring: while the panel is display:none its size reads 0\n // and every clamp above would be computed against nothing. Layout effect,\n // so the corrected position lands before the first frame is painted.\n useLayoutEffect(() => {\n const panel = panelRef.current;\n if (!panel) return;\n if (open) {\n // Placed before it is shown, so the reveal travels away from the trigger\n // on whichever side it lands.\n showMeasured(panel, place);\n place();\n if (openedByReader.current) {\n openedByReader.current = false;\n const first = panel.querySelector<HTMLElement>(FOCUSABLE);\n (first ?? panel).focus({ preventScroll: true });\n }\n } else if (panel.matches(\":popover-open\")) {\n panel.hidePopover();\n }\n }, [open, place]);\n\n // Follow the trigger for as long as the panel is open. Scroll and resize\n // listeners were not enough: anything that moves the trigger without\n // scrolling — an image loading above it, a font swapping in, a sibling\n // growing — left the panel where it opened, detached from its button and\n // sometimes sitting on top of it. So each frame compares where the trigger\n // is now with where it was, and re-places only on a change. One layout read\n // a frame, and only while open.\n useEffect(() => {\n if (!open) return;\n let frame = 0;\n let last = \"\";\n const track = () => {\n const trigger = triggerRef.current;\n const panel = panelRef.current;\n if (trigger && panel) {\n const r = trigger.getBoundingClientRect();\n const key = `${r.top}|${r.left}|${r.width}|${r.height}|${panel.offsetWidth}|${panel.offsetHeight}|${window.innerWidth}|${window.innerHeight}`;\n if (key !== last) {\n last = key;\n place();\n }\n }\n frame = requestAnimationFrame(track);\n };\n frame = requestAnimationFrame(track);\n return () => cancelAnimationFrame(frame);\n }, [open, place]);\n\n return (\n <>\n <Button\n {...buttonProps}\n ref={triggerRef}\n id={triggerId}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-controls={panelId}\n onPointerDown={(e) => {\n buttonProps.onPointerDown?.(e);\n // Decide here, not on click. Pressing the trigger while the panel is\n // open is an outside press to the platform, which closes the panel\n // during pointerdown — so by the time click runs, the panel already\n // reads as shut and a plain toggle would reopen it. The platform's\n // toggle event cannot settle it either: it fires after click. What\n // the reader meant is knowable only at the moment they pressed.\n pressIntent.current = !openNow.current;\n }}\n onKeyDown={(e) => {\n buttonProps.onKeyDown?.(e);\n // A press dragged off the button never clicks, which would leave its\n // intent behind to hijack the next Enter or Space. Keys decide fresh.\n if (e.key === \"Enter\" || e.key === \" \") pressIntent.current = null;\n }}\n onClick={(e) => {\n onClick?.(e);\n // Keyboard activation has no pointerdown, so it falls back to a\n // straight toggle, which is right: Enter and Space never light-dismiss.\n const next = pressIntent.current ?? !openNow.current;\n pressIntent.current = null;\n if (next) openedByReader.current = true;\n setOpen(next);\n }}\n >\n {label}\n </Button>\n\n <div\n ref={panelRef}\n id={panelId}\n popover=\"auto\"\n role=\"dialog\"\n aria-labelledby={triggerId}\n tabIndex={-1}\n className={cx(styles.panel, ctl.spacePanel, panelClassName)}\n data-animated={buttonProps.animated === false ? \"false\" : undefined}\n data-side={pos?.placed ?? side}\n style={pos ? { top: pos.top, left: pos.left } : undefined}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n closingByEscape.current = true;\n // Only this popover. An enclosing Dialog must not close with it.\n e.stopPropagation();\n }\n }}\n onToggle={(e: React.SyntheticEvent<HTMLDivElement>) => {\n if ((e.nativeEvent as ToggleEvent).newState !== \"closed\") return;\n if (closingByEscape.current) {\n closingByEscape.current = false;\n triggerRef.current?.focus();\n }\n // The platform closed it — a press elsewhere or Escape. setOpen\n // ignores a close this component has already recorded.\n setOpen(false);\n }}\n >\n {children}\n </div>\n </>\n );\n}\n"],"names":["SPACE","spacingStyle","m","mt","mb","p","pb","style","out","cx","parts","Text","forwardRef","as","size","weight","color","className","rest","ref","createElement","styles","Heading","align","Link","asChild","children","cls","merged","isValidElement","child","cloneElement","jsx","cap","s","Flex","gap","direction","justify","wrap","Box","Grid","columns","colCls","Badge","variant","Separator","Card","image","jsxs","mulberry32","a","t","hashString","h","i","Button","iconOnly","ember","fullWidth","animated","id","useId","starStyles","useMemo","rand","classes","base","Share2Icon","props","ChatBubbleIcon","PlusIcon","Pencil1Icon","HeartFilledIcon","ExitFullScreenIcon","EnterFullScreenIcon","CheckIcon","TrashIcon","QuestionMarkCircledIcon","PersonIcon","MinusIcon","MagnifyingGlassIcon","HeartIcon","ChevronUpIcon","ChevronDownIcon","ChevronRightIcon","ChevronLeftIcon","BookmarkIcon","XIcon","InfoCircledIcon","ExclamationTriangleIcon","CrossCircledIcon","Carousel","perView","step","showPagination","ariaLabel","slides","Children","count","trackId","trackRef","useRef","estimatedPage","estimatedStops","pageSize","setPageSize","useState","stopCount","setStopCount","active","setActive","atStart","setAtStart","atEnd","setAtEnd","stops","measuredMax","endStop","remeasure","sync","useCallback","track","x","max","atStartNow","atEndNow","nearest","stop","measure","items","first","inView","last","end","next","item","useLayoutEffect","useEffect","resize","frame","onScroll","THRESHOLD","pointer","startX","startScroll","dragging","settle","endSettling","onPointerDown","e","onPointerMove","dx","onPointerUp","all","target","best","reduced","onClick","onDragStart","scrollTo","left","_a","go","scrollable","slide","_","ctl","ctlModule","pageCount","totalItems","pageWindow","page","total","siblings","range","from","to","slots","current","right","gapLeft","gapRight","edge","Pagination","pagination","onPageClick","Loader","label","showMeasured","element","place","SHOW_DELAY","HIDE_DELAY","SIDE_OFFSET","COLLISION_PADDING","TooltipTrigger","triggerRef","tooltipId","show","hide","Tooltip","side","open","setOpen","pos","setPos","contentRef","showTimer","hideTimer","clearTimers","immediate","content","trigger","r","w","centre","start","extent","viewport","fits","near","far","after","before","fitsBefore","fitsAfter","below","above","fitsAbove","fitsBelow","top","Fragment","IconToggle","options","value","onValueChange","orientation","vertical","opt","Ctx","createContext","useSelect","ctx","useContext","optionId","listboxId","OFFSET","EDGE_PADDING","collectItems","walk","nodes","Item","SelectRoot","disabled","placeholder","highlighted","setHighlighted","rootRef","listRef","triggerWidth","setTriggerWidth","maxHeight","setMaxHeight","values","itemLabels","labelFor","v","onDown","list","rect","flip","room","height","prev","key","openWith","highlight","move","delta","idx","l","_b","selected","Select","TextFieldRoot","inputProps","Slot","TextField","TextArea","Autocomplete","onSelect","icon","caseSensitive","preFiltered","loading","loadingMessage","emptyMessage","footer","wrapRef","panelRef","listId","haystack","o","hasQuery","shown","needle","selectable","hasContent","showPanel","el","panel","field","close","node","navigated","choose","option","onKeyDown","chosen","activeOption","clamp","low","high","Slider","min","minDistance","thumbLabels","inputs","marks","drag","release","isRange","span","lower","upper","percent","now","gridBelow","gridAbove","clampThumb","index","settled","updated","valueAt","clientX","box","ratio","raw","markBox","nearestTo","second","firstCentre","toFirst","toSecond","onThumb","stopDragging","event","_c","_d","held","travelled","SERIES_COLORS","SERIES_COLOR_COUNT","seriesColor","niceStep","rough","magnitude","scaled","linearScale","tickCount","zeroBased","real","lowest","highest","ticks","bandPositions","inset","slot","barPath","y","width","radius","up","pointPositions","isDevelopment","formatValue","PADDING","AXIS_GUTTER","Chart","type","categories","series","stacked","legend","grid","format","partialFrom","onPointClick","titleId","plotRef","setWidth","hover","setHover","observer","entry","wrong","stackable","partial","stillFilling","scale","positive","negative","labels","gutter","plotWidth","plotHeight","band","points","colorOf","showLegend","baseline","bases","si","readingAt","positions","report","seriesIndex","categoryIndex","barWidth","s2","tick","category","ci","bottom","slotLeft","drawWidth","drawHeight","stillCounting","runs","run","segment","ri","line","k","area","BarList","showPercent","colorful","onItemClick","largest","sum","fill","row","pointOnCircle","fraction","angle","PieChart","slices","donut","onSliceClick","hovered","setHovered","uid","usable","hole","cursor","arcs","slice","outerFrom","outerTo","large","whole","d","originalIndex","fillRule","Control","checked","indeterminate","onToggle","CheckboxGroupRoot","g","isDisabled","control","CheckboxGroup","Checkbox","onCheckedChange","RadioGroupRoot","name","RadioGroup","Progress","pct","ICONS","ROLES","Message","title","glyph","role","live","lockCount","useDialog","makeRoot","alert","onOpenChange","internal","setInternal","isControlled","actual","descId","hasDesc","setHasDesc","Root","chainOpen","fn","c","Trigger","Close","Content","maxWidth","swallowCancel","pointerDownOnBackdrop","Title","Description","Dialog","Cancel","Action","AlertDialog","useMenu","DropdownMenuRoot","buttonProps","setOpenState","menuId","menuRef","pressIntent","openNow","onResize","_e","_f","Label","activate","childClassName","childOnClick","childChildren","childRole","childTabIndex","restProps","originalRef","DropdownMenu","useTabs","TabsRoot","List","tabs","Tabs","FOCUSABLE","Popover","openProp","defaultOpen","panelClassName","controlled","triggerId","panelId","openedByReader","closingByEscape","placed","wanted"],"mappings":"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"}
|