trc-ui 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/utils/cx.ts","../src/components/typography.tsx","../src/components/pill.tsx","../src/utils/icons.tsx","../src/components/surfaces.tsx","../src/components/field.tsx","../src/components/toggle.tsx","../src/components/site-header.tsx","../src/hooks/use-modal.ts","../src/components/site-footer.tsx","../src/components/hero.tsx","../src/components/back-to-top.tsx"],"sourcesContent":["export { cx } from \"./utils/cx\";\n\nexport { AccentText, plainText, Heading, Text, StepNumber } from \"./components/typography\";\nexport type { HeadingProps, HeadingSize, TextProps } from \"./components/typography\";\n\nexport { PillButton, PillLink } from \"./components/pill\";\nexport type { PillButtonProps, PillLinkProps } from \"./components/pill\";\n\nexport { ArrowLeft, ArrowRight, ArrowUp, Check, ChevronDown, Close, Menu } from \"./utils/icons\";\n\nexport { Card, Container, Section } from \"./components/surfaces\";\nexport type { CardProps, ContainerProps, SectionProps } from \"./components/surfaces\";\n\nexport { Field, Input, Select, Textarea } from \"./components/field\";\nexport type { FieldProps, InputProps, SelectProps, TextareaProps } from \"./components/field\";\nexport { Checkbox, Switch } from \"./components/toggle\";\nexport type { CheckboxProps, SwitchProps } from \"./components/toggle\";\n\nexport { SiteHeader } from \"./components/site-header\";\nexport type { NavItem, NavLink, NavMenu, SiteHeaderProps } from \"./components/site-header\";\nexport { SiteFooter } from \"./components/site-footer\";\nexport type { FooterLink, SiteFooterProps } from \"./components/site-footer\";\n\nexport { HeroVideo, PageHero } from \"./components/hero\";\nexport type { HeroClip, HeroVideoProps, PageHeroProps } from \"./components/hero\";\nexport { BackToTop } from \"./components/back-to-top\";\nexport type { BackToTopProps } from \"./components/back-to-top\";\n","/** Joins CSS class names, skipping empty values. */\nexport function cx(...classes: (string | false | null | undefined)[]): string {\n return classes.filter(Boolean).join(\" \");\n}\n","import type { ComponentPropsWithoutRef, ElementType, ReactNode } from \"react\";\nimport { cx } from \"../utils/cx\";\n\n/**\n * Colors the words between asterisks with the accent: \"How it *works*\".\n * Without asterisks, `accentLast` colors the last words (titles coming from a CMS).\n */\nexport function AccentText({ text, accentLast = 0 }: { text: string; accentLast?: number }) {\n if (text.includes(\"*\")) {\n return (\n <>\n {text.split(\"*\").map((part, i) =>\n i % 2 === 1 ? (\n <span key={i} className=\"trc-accent\">\n {part}\n </span>\n ) : (\n part\n ),\n )}\n </>\n );\n }\n const words = text.split(\" \");\n if (!accentLast || words.length < 2) return <>{text}</>;\n const n = Math.min(accentLast, words.length - 1);\n return (\n <>\n {words.slice(0, -n).join(\" \")} <span className=\"trc-accent\">{words.slice(-n).join(\" \")}</span>\n </>\n );\n}\n\n/** Plain text of a marked-up title, for attributes (`alt`, `title`, metadata). */\nexport const plainText = (text: string) => text.replaceAll(\"*\", \"\");\n\nexport type HeadingSize = \"display\" | \"xl\" | \"lg\" | \"md\" | \"sm\";\n\nexport type HeadingProps = Omit<ComponentPropsWithoutRef<\"h2\">, \"children\"> & {\n /** Rendered tag; the visual size is set separately with `size`. */\n as?: \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"p\" | \"span\";\n size?: HeadingSize;\n /** When `children` is a string without asterisks, number of trailing words in the accent color. */\n accentLast?: number;\n children: ReactNode;\n};\n\n/** Thin Montserrat 400 heading; a string may contain an *accent word* between asterisks. */\nexport function Heading({ as: Tag = \"h2\", size = \"xl\", accentLast, className, children, ...props }: HeadingProps) {\n return (\n <Tag className={cx(\"trc-display\", `trc-heading--${size}`, className)} {...props}>\n {typeof children === \"string\" ? <AccentText text={children} accentLast={accentLast} /> : children}\n </Tag>\n );\n}\n\nexport type TextProps<C extends ElementType = \"p\"> = {\n as?: C;\n size?: \"lg\" | \"md\" | \"sm\";\n tone?: \"default\" | \"muted\" | \"subtle\";\n} & Omit<ComponentPropsWithoutRef<C>, \"as\" | \"size\">;\n\n/** Body text; `tone=\"muted\"` (default) so that it does not compete with headings. */\nexport function Text<C extends ElementType = \"p\">({ as, size = \"md\", tone = \"muted\", className, ...props }: TextProps<C>) {\n const Tag: ElementType = as ?? \"p\";\n return <Tag className={cx(\"trc-text\", `trc-text--${size}`, `trc-text--${tone}`, className)} {...props} />;\n}\n\n/** Large thin number in the accent color (\"01\", \"02\"…), reserved for steps in a real order. */\nexport function StepNumber({ n, size = \"md\", className }: { n: number; size?: \"md\" | \"sm\"; className?: string }) {\n return (\n <span aria-hidden className={cx(\"trc-step-number\", size === \"sm\" && \"trc-step-number--sm\", className)}>\n {String(n).padStart(2, \"0\")}\n </span>\n );\n}\n","import {\n forwardRef,\n type ComponentPropsWithoutRef,\n type ElementType,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { cx } from \"../utils/cx\";\nimport { ArrowRight, Spinner } from \"../utils/icons\";\n\ntype PillStyle = {\n /** White background: the main action of a screen. */\n solid?: boolean;\n /** Compact version (header, toolbars). */\n size?: \"md\" | \"sm\";\n /** Replaces the dot's arrow (for instance a left arrow for \"Back\"). */\n icon?: ReactNode;\n};\n\nconst pillClass = ({ solid, size }: PillStyle, className?: string) =>\n cx(\"trc-pill\", size === \"sm\" && \"trc-pill--sm\", solid && \"trc-pill--solid\", className);\n\n/** The dot and the fill are one shape: it stretches on hover without a visible circle. */\nfunction PillInner({ icon, children }: { icon?: ReactNode; children: ReactNode }) {\n return (\n <>\n <span aria-hidden className=\"trc-pill__fill\" />\n <span aria-hidden className=\"trc-pill__icon\">\n {icon ?? <ArrowRight />}\n </span>\n <span className=\"trc-pill__label\">{children}</span>\n </>\n );\n}\n\nexport type PillButtonProps = ComponentPropsWithoutRef<\"button\"> &\n PillStyle & {\n /** Replaces the icon with a spinner and disables the button. */\n loading?: boolean;\n };\n\n/** Pill button: thin border, accent dot with an arrow that stretches on hover. */\nexport const PillButton = forwardRef<HTMLButtonElement, PillButtonProps>(function PillButton(\n { solid, size = \"md\", icon, loading = false, disabled, type = \"button\", className, children, ...props },\n ref,\n) {\n return (\n <button\n ref={ref}\n type={type}\n disabled={disabled || loading}\n aria-busy={loading || undefined}\n className={pillClass({ solid, size }, className)}\n {...props}\n >\n <PillInner icon={loading ? <Spinner className=\"trc-spin\" /> : icon}>{children}</PillInner>\n </button>\n );\n});\n\nexport type PillLinkProps<C extends ElementType = \"a\"> = PillStyle & {\n /** Router link component (Next.js or React Router `Link`…); `<a>` by default. */\n as?: C;\n} & Omit<ComponentPropsWithoutRef<C>, \"as\" | keyof PillStyle>;\n\n/** Same pill as a link. With a router: `<PillLink as={Link} href=\"/\">`. */\nexport const PillLink = forwardRef(function PillLink(\n { as, solid, size = \"md\", icon, className, children, ...props }: PillLinkProps<ElementType>,\n ref: Ref<HTMLAnchorElement>,\n) {\n const Tag: ElementType = as ?? \"a\";\n return (\n <Tag ref={ref} className={pillClass({ solid, size }, className)} {...props}>\n <PillInner icon={icon}>{children}</PillInner>\n </Tag>\n );\n}) as <C extends ElementType = \"a\">(props: PillLinkProps<C> & { ref?: Ref<HTMLAnchorElement> }) => ReactNode;\n","import type { SVGProps } from \"react\";\n\ntype IconProps = SVGProps<SVGSVGElement>;\n\nconst base = {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n \"aria-hidden\": true,\n} as const;\n\nexport const ArrowRight = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M5 12h14M13 6l6 6-6 6\" />\n </svg>\n);\n\nexport const ArrowLeft = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M19 12H5M11 18l-6-6 6-6\" />\n </svg>\n);\n\nexport const Spinner = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M21 12a9 9 0 1 1-6.22-8.56\" />\n </svg>\n);\n\nexport const ChevronDown = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n);\n\nexport const Check = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n);\n\nexport const Menu = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M4 7h16M4 12h16M4 17h16\" />\n </svg>\n);\n\nexport const Close = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n);\n\nexport const ArrowUp = (props: IconProps) => (\n <svg {...base} {...props}>\n <path d=\"M12 19V5M6 11l6-6 6 6\" />\n </svg>\n);\n","import type { ComponentPropsWithoutRef, ElementType, ReactNode } from \"react\";\nimport { cx } from \"../utils/cx\";\n\ntype Polymorphic<C extends ElementType, P> = P & { as?: C } & Omit<ComponentPropsWithoutRef<C>, \"as\" | keyof P>;\n\nexport type ContainerProps<C extends ElementType = \"div\"> = Polymorphic<\n C,\n {\n /** `default`: 1280 px, for text and grids; `wide`: 1600 px, for full-width cards; `narrow`: 768 px. */\n size?: \"default\" | \"wide\" | \"narrow\";\n }\n>;\n\n/** Centered max width, with side gutters that grow with the screen. */\nexport function Container<C extends ElementType = \"div\">({ as, size = \"default\", className, ...props }: ContainerProps<C>) {\n const Tag: ElementType = as ?? \"div\";\n return <Tag className={cx(\"trc-container\", size !== \"default\" && `trc-container--${size}`, className)} {...props} />;\n}\n\nexport type SectionProps<C extends ElementType = \"section\"> = Polymorphic<\n C,\n {\n /** Vertical spacing. */\n spacing?: \"sm\" | \"md\" | \"lg\" | \"none\";\n /**\n * Card inset from the screen edges (\"magazine\" effect): graphite background and rounded corners,\n * for banners, calls to action and heroes.\n */\n inset?: boolean;\n }\n>;\n\n/** Vertical block of a page. With `inset`, it becomes a large rounded card a few pixels from the edges. */\nexport function Section<C extends ElementType = \"section\">({\n as,\n spacing = \"md\",\n inset = false,\n className,\n children,\n ...props\n}: SectionProps<C>) {\n const Tag: ElementType = as ?? \"section\";\n if (inset) {\n return (\n <Tag className={cx(\"trc-section-inset\", className)} {...props}>\n <div className={cx(\"trc-section-inset__card\", spacing !== \"none\" && `trc-section--${spacing}`)}>{children}</div>\n </Tag>\n );\n }\n return (\n <Tag className={cx(spacing !== \"none\" && `trc-section--${spacing}`, className)} {...props}>\n {children}\n </Tag>\n );\n}\n\nexport type CardProps<C extends ElementType = \"div\"> = Polymorphic<\n C,\n {\n /** `alt`: a slightly lighter grey, to tell two side-by-side blocks apart. */\n tone?: \"default\" | \"alt\";\n padding?: \"none\" | \"sm\" | \"md\" | \"lg\";\n /** Lightens on hover (clickable cards: links, buttons). */\n interactive?: boolean;\n /** Decorative watermark icon: very large, thin stroke, half out of the corner; wakes up on hover. */\n watermark?: ReactNode;\n }\n>;\n\n/** Graphite card, rounded corners, no shadow: depth comes from shades of grey. */\nexport function Card<C extends ElementType = \"div\">({\n as,\n tone = \"default\",\n padding = \"md\",\n interactive = false,\n watermark,\n className,\n children,\n ...props\n}: CardProps<C>) {\n const Tag: ElementType = as ?? \"div\";\n return (\n <Tag\n className={cx(\n \"trc-card\",\n tone === \"alt\" && \"trc-card--alt\",\n padding !== \"none\" && `trc-card--pad-${padding}`,\n interactive && \"trc-card--interactive\",\n !!watermark && \"trc-card--watermark\",\n className,\n )}\n {...props}\n >\n {!!watermark && (\n <span aria-hidden className=\"trc-card__watermark\">\n {watermark}\n </span>\n )}\n {children}\n </Tag>\n );\n}\n","\"use client\";\n\nimport { createContext, forwardRef, useContext, useId, type ComponentPropsWithoutRef, type ReactNode } from \"react\";\nimport { cx } from \"../utils/cx\";\nimport { ChevronDown } from \"../utils/icons\";\n\ntype FieldContextValue = { id: string; describedBy?: string; invalid: boolean; required: boolean };\n\nconst FieldContext = createContext<FieldContextValue | null>(null);\n\nexport type FieldProps = {\n label: ReactNode;\n /** Hint shown under the control. */\n hint?: ReactNode;\n /** Error message: replaces the hint and marks the control as invalid. */\n error?: ReactNode;\n required?: boolean;\n /** Control id; generated when omitted. */\n id?: string;\n className?: string;\n children: ReactNode;\n};\n\n/**\n * Label, hint and error of a form control. The control placed inside (`Input`, `Textarea`, `Select`)\n * automatically receives its `id`, `aria-describedby` and `aria-invalid`.\n */\nexport function Field({ label, hint, error, required = false, id, className, children }: FieldProps) {\n const generated = useId();\n const fieldId = id ?? generated;\n const messageId = `${fieldId}-message`;\n const message = error ?? hint;\n return (\n <FieldContext.Provider\n value={{ id: fieldId, describedBy: message ? messageId : undefined, invalid: error != null, required }}\n >\n <div className={cx(\"trc-field\", className)}>\n <label htmlFor={fieldId} className=\"trc-field__label\">\n {label}\n {required && (\n <span aria-hidden className=\"trc-field__required\">\n {\" \"}\n *\n </span>\n )}\n </label>\n {children}\n {message != null && (\n <p id={messageId} className={cx(\"trc-field__message\", error != null && \"trc-field__message--error\")}>\n {message}\n </p>\n )}\n </div>\n </FieldContext.Provider>\n );\n}\n\n/** Accessibility attributes from the parent `Field`, without overriding those passed to the control. */\nfunction useFieldProps(props: { id?: string; required?: boolean; invalid?: boolean; \"aria-describedby\"?: string }) {\n const field = useContext(FieldContext);\n const invalid = props.invalid ?? field?.invalid ?? false;\n return {\n id: props.id ?? field?.id,\n required: props.required ?? field?.required,\n \"aria-describedby\": cx(field?.describedBy, props[\"aria-describedby\"]) || undefined,\n \"aria-invalid\": invalid || undefined,\n };\n}\n\ntype ControlProps = { invalid?: boolean };\n\nexport type InputProps = ComponentPropsWithoutRef<\"input\"> & ControlProps;\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input({ invalid, className, ...props }, ref) {\n const a11y = useFieldProps({ ...props, invalid });\n return <input ref={ref} className={cx(\"trc-control\", className)} {...props} {...a11y} />;\n});\n\nexport type TextareaProps = ComponentPropsWithoutRef<\"textarea\"> & ControlProps;\n\nexport const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(function Textarea(\n { invalid, rows = 4, className, ...props },\n ref,\n) {\n const a11y = useFieldProps({ ...props, invalid });\n return (\n <textarea\n ref={ref}\n rows={rows}\n className={cx(\"trc-control\", \"trc-control--textarea\", className)}\n {...props}\n {...a11y}\n />\n );\n});\n\nexport type SelectProps = ComponentPropsWithoutRef<\"select\"> &\n ControlProps & {\n /** Empty option shown until something is chosen. */\n placeholder?: string;\n };\n\n/** Native select (accessible and mobile friendly), dressed with a thin chevron. */\nexport const Select = forwardRef<HTMLSelectElement, SelectProps>(function Select(\n { invalid, placeholder, defaultValue, className, children, ...props },\n ref,\n) {\n const a11y = useFieldProps({ ...props, invalid });\n // Without a given value, keep the empty option shown (otherwise the browser picks the first enabled option).\n const initial = defaultValue ?? (props.value === undefined && placeholder != null ? \"\" : undefined);\n return (\n <span className={cx(\"trc-select\", className)}>\n <select ref={ref} className=\"trc-control trc-control--select\" defaultValue={initial} {...props} {...a11y}>\n {placeholder != null && (\n <option value=\"\" disabled>\n {placeholder}\n </option>\n )}\n {children}\n </select>\n <ChevronDown className=\"trc-select__chevron\" />\n </span>\n );\n});\n","import { forwardRef, type ComponentPropsWithoutRef, type ReactNode } from \"react\";\nimport { cx } from \"../utils/cx\";\nimport { Check } from \"../utils/icons\";\n\ntype ToggleProps = Omit<ComponentPropsWithoutRef<\"input\">, \"type\"> & {\n label: ReactNode;\n /** Extra detail under the label. */\n description?: ReactNode;\n};\n\n/** The label wraps the control: the whole block is clickable. */\nfunction ToggleLabel({\n kind,\n label,\n description,\n className,\n children,\n}: {\n kind: \"checkbox\" | \"switch\";\n label: ReactNode;\n description?: ReactNode;\n className?: string;\n children: ReactNode;\n}) {\n return (\n <label className={cx(\"trc-toggle\", `trc-toggle--${kind}`, className)}>\n {children}\n <span className=\"trc-toggle__text\">\n <span className=\"trc-toggle__label\">{label}</span>\n {description != null && <span className=\"trc-toggle__description\">{description}</span>}\n </span>\n </label>\n );\n}\n\nexport type CheckboxProps = ToggleProps;\n\n/** Native checkbox, filled with the accent color once checked. */\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(\n { label, description, className, ...props },\n ref,\n) {\n return (\n <ToggleLabel kind=\"checkbox\" label={label} description={description} className={className}>\n <span className=\"trc-checkbox\">\n <input ref={ref} type=\"checkbox\" className=\"trc-checkbox__input\" {...props} />\n <Check className=\"trc-checkbox__check\" />\n </span>\n </ToggleLabel>\n );\n});\n\nexport type SwitchProps = ToggleProps;\n\n/** Switch: a native checkbox announced as a `switch` to screen readers. */\nexport const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch(\n { label, description, className, ...props },\n ref,\n) {\n return (\n <ToggleLabel kind=\"switch\" label={label} description={description} className={className}>\n <span className=\"trc-switch\">\n <input ref={ref} type=\"checkbox\" role=\"switch\" className=\"trc-switch__input\" {...props} />\n <span aria-hidden className=\"trc-switch__thumb\" />\n </span>\n </ToggleLabel>\n );\n});\n","\"use client\";\n\nimport { useEffect, useId, useRef, useState, type ElementType, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useModal } from \"../hooks/use-modal\";\nimport { cx } from \"../utils/cx\";\nimport { ChevronDown, Close, Menu } from \"../utils/icons\";\nimport { PillLink } from \"./pill\";\n\nexport type NavLink = {\n label: ReactNode;\n href: string;\n /** Current page: marked with an accent dot. */\n active?: boolean;\n};\n\nexport type NavMenu = {\n label: ReactNode;\n /** Dropdown items, with an optional short description (no numbers). */\n items: (NavLink & { description?: ReactNode })[];\n};\n\nexport type NavItem = NavLink | NavMenu;\n\nexport type SiteHeaderProps = {\n /** Logo (white), wrapped in a link to `homeHref`. */\n logo: ReactNode;\n /** Accessible name of the logo link, usually the brand name. */\n logoLabel: string;\n homeHref?: string;\n nav?: NavItem[];\n /** Main action, shown as a compact pill (and a large one in the mobile menu). */\n cta?: { label: ReactNode; href: string };\n /** Extra elements on the right on large screens (language switcher…). */\n actions?: ReactNode;\n /** Content added at the bottom of the mobile menu. */\n mobileFooter?: ReactNode;\n /** Router link component (Next.js `Link`…); `<a>` by default. */\n linkAs?: ElementType;\n /** Scroll offset (px) from which the bar becomes blurred graphite. */\n scrollThreshold?: number;\n menuLabel?: string;\n closeLabel?: string;\n className?: string;\n};\n\nconst isMenu = (item: NavItem): item is NavMenu => \"items\" in item;\n\n/**\n * Floating header: transparent over the hero at the top of the page, it becomes a blurred\n * graphite bar as soon as the page scrolls. Dropdowns on large screens, side panel on mobile.\n */\nexport function SiteHeader({\n logo,\n logoLabel,\n homeHref = \"/\",\n nav = [],\n cta,\n actions,\n mobileFooter,\n linkAs: LinkTag = \"a\",\n scrollThreshold = 24,\n menuLabel = \"Menu\",\n closeLabel = \"Close\",\n className,\n}: SiteHeaderProps) {\n const [scrolled, setScrolled] = useState(false);\n const [open, setOpen] = useState(false);\n\n // Read after hydration: same render on the server and on the client.\n useEffect(() => {\n const update = () => setScrolled(window.scrollY > scrollThreshold);\n update();\n window.addEventListener(\"scroll\", update, { passive: true });\n return () => window.removeEventListener(\"scroll\", update);\n }, [scrollThreshold]);\n\n return (\n <header className={cx(\"trc-header\", className)}>\n <div className={cx(\"trc-header__bar\", scrolled && \"trc-header__bar--scrolled\")}>\n <LinkTag href={homeHref} aria-label={logoLabel} className=\"trc-header__logo\">\n {logo}\n </LinkTag>\n\n {nav.length > 0 && (\n <nav className=\"trc-header__nav\">\n {nav.map((item, i) =>\n isMenu(item) ? (\n <NavDropdown key={i} menu={item} linkAs={LinkTag} />\n ) : (\n <LinkTag\n key={i}\n href={item.href}\n aria-current={item.active ? \"page\" : undefined}\n className={cx(\"trc-header__link\", item.active && \"trc-header__link--active\")}\n >\n {item.label}\n </LinkTag>\n ),\n )}\n </nav>\n )}\n\n <div className=\"trc-header__end\">\n {actions && <div className=\"trc-header__actions\">{actions}</div>}\n {cta && (\n <PillLink as={LinkTag} href={cta.href} size=\"sm\" className=\"trc-header__cta\">\n {cta.label}\n </PillLink>\n )}\n {(nav.length > 0 || cta || mobileFooter) && (\n <button\n type=\"button\"\n className=\"trc-header__burger\"\n aria-label={menuLabel}\n aria-expanded={open}\n onClick={() => setOpen(true)}\n >\n <Menu />\n </button>\n )}\n </div>\n </div>\n\n <MobileMenu\n open={open}\n onClose={() => setOpen(false)}\n nav={nav}\n cta={cta}\n footer={mobileFooter}\n linkAs={LinkTag}\n title={menuLabel}\n closeLabel={closeLabel}\n />\n </header>\n );\n}\n\n/**\n * Dropdown menu (large screens): opens on hover or click, closes on leave, with Escape,\n * when keyboard focus leaves the menu, or after a choice.\n */\nfunction NavDropdown({ menu, linkAs: LinkTag }: { menu: NavMenu; linkAs: ElementType }) {\n const id = useId();\n const [open, setOpen] = useState(false);\n const closeTimer = useRef<number | undefined>(undefined);\n const button = useRef<HTMLButtonElement>(null);\n\n const show = () => {\n window.clearTimeout(closeTimer.current);\n setOpen(true);\n };\n // Short delay: the pointer may cross the gap between the button and the panel.\n const hide = () => {\n closeTimer.current = window.setTimeout(() => setOpen(false), 120);\n };\n useEffect(() => () => window.clearTimeout(closeTimer.current), []);\n\n return (\n <div\n className=\"trc-dropdown\"\n onMouseEnter={show}\n onMouseLeave={hide}\n onKeyDown={(e) => {\n if (e.key === \"Escape\" && open) {\n setOpen(false);\n button.current?.focus();\n }\n }}\n onBlur={(e) => !e.currentTarget.contains(e.relatedTarget) && setOpen(false)}\n >\n <button\n ref={button}\n type=\"button\"\n aria-expanded={open}\n aria-controls={id}\n onClick={() => setOpen((o) => !o)}\n className={cx(\"trc-header__link\", \"trc-dropdown__trigger\", open && \"trc-dropdown__trigger--open\")}\n >\n {menu.label}\n <ChevronDown className=\"trc-dropdown__chevron\" />\n </button>\n <div id={id} className={cx(\"trc-dropdown__panel\", open && \"trc-dropdown__panel--open\")}>\n <ul className=\"trc-dropdown__list\">\n {menu.items.map((item, i) => (\n <li key={i}>\n <LinkTag\n href={item.href}\n aria-current={item.active ? \"page\" : undefined}\n onClick={() => setOpen(false)}\n className=\"trc-dropdown__item\"\n >\n <span className=\"trc-dropdown__label\">{item.label}</span>\n {item.description != null && <span className=\"trc-dropdown__description\">{item.description}</span>}\n </LinkTag>\n </li>\n ))}\n </ul>\n </div>\n </div>\n );\n}\n\n/**\n * Side panel of the mobile menu, rendered into `document.body`: otherwise the header's blurred bar\n * (`backdrop-filter`) would trap a `fixed` element within its own bounds.\n */\nfunction MobileMenu({\n open,\n onClose,\n nav,\n cta,\n footer,\n linkAs: LinkTag,\n title,\n closeLabel,\n}: {\n open: boolean;\n onClose: () => void;\n nav: NavItem[];\n cta?: SiteHeaderProps[\"cta\"];\n footer?: ReactNode;\n linkAs: ElementType;\n title: string;\n closeLabel: string;\n}) {\n const titleId = useId();\n const panel = useRef<HTMLDivElement>(null);\n const [mounted, setMounted] = useState(false);\n useEffect(() => setMounted(true), []);\n useModal(open, panel, onClose);\n\n if (!mounted) return null;\n return createPortal(\n <div className={cx(\"trc-drawer\", open && \"trc-drawer--open\")} aria-hidden={!open}>\n <div className=\"trc-drawer__overlay\" onClick={onClose} />\n <div\n ref={panel}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n tabIndex={-1}\n className=\"trc-drawer__panel\"\n >\n <div className=\"trc-drawer__head\">\n <p id={titleId} className=\"trc-drawer__title\">\n {title}\n </p>\n <button type=\"button\" className=\"trc-drawer__close\" aria-label={closeLabel} onClick={onClose}>\n <Close />\n </button>\n </div>\n <nav className=\"trc-mobile-nav\">\n {nav.map((item, i) =>\n isMenu(item) ? (\n <div key={i} className=\"trc-mobile-nav__group\">\n <p className=\"trc-mobile-nav__heading\">{item.label}</p>\n <ul className=\"trc-mobile-nav__sub\">\n {item.items.map((sub, j) => (\n <li key={j}>\n <LinkTag\n href={sub.href}\n aria-current={sub.active ? \"page\" : undefined}\n onClick={onClose}\n className=\"trc-mobile-nav__sublink\"\n >\n {sub.label}\n </LinkTag>\n </li>\n ))}\n </ul>\n </div>\n ) : (\n <LinkTag\n key={i}\n href={item.href}\n aria-current={item.active ? \"page\" : undefined}\n onClick={onClose}\n className={cx(\"trc-mobile-nav__link\", item.active && \"trc-mobile-nav__link--active\")}\n >\n {item.label}\n </LinkTag>\n ),\n )}\n </nav>\n {cta && (\n <PillLink as={LinkTag} href={cta.href} onClick={onClose} className=\"trc-drawer__cta\">\n {cta.label}\n </PillLink>\n )}\n {footer != null && <div className=\"trc-drawer__footer\">{footer}</div>}\n </div>\n </div>,\n document.body,\n );\n}\n","import { useEffect, useRef, type RefObject } from \"react\";\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\n/**\n * Behavior of an open modal panel: focus moved inside and kept there (Tab / Shift+Tab),\n * closes with Escape, page scroll locked, focus returned to the original element on close.\n */\nexport function useModal(open: boolean, panelRef: RefObject<HTMLElement | null>, onClose: () => void) {\n // Latest close callback, without re-running the effect on every render.\n const close = useRef(onClose);\n close.current = onClose;\n\n useEffect(() => {\n const panel = panelRef.current;\n if (!open || !panel) return;\n\n const previous = document.activeElement as HTMLElement | null;\n const overflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n (\n panel.querySelector<HTMLElement>(\"[data-autofocus]\") ??\n panel.querySelector<HTMLElement>(FOCUSABLE) ??\n panel\n ).focus();\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.stopPropagation();\n close.current();\n return;\n }\n if (e.key !== \"Tab\") return;\n const items = [...panel.querySelectorAll<HTMLElement>(FOCUSABLE)].filter((el) => el.offsetParent !== null);\n const first = items[0];\n const last = items[items.length - 1];\n if (!first || !last) {\n e.preventDefault();\n return;\n }\n if (e.shiftKey && document.activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && document.activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n };\n document.addEventListener(\"keydown\", onKeyDown);\n\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n document.body.style.overflow = overflow;\n previous?.focus();\n };\n }, [open, panelRef]);\n}\n","import type { ElementType, ReactNode } from \"react\";\nimport { cx } from \"../utils/cx\";\n\nexport type FooterLink = { label: ReactNode; href: string };\n\nexport type SiteFooterProps = {\n /** Logo (white), wrapped in a link to `homeHref`. */\n logo?: ReactNode;\n logoLabel?: string;\n homeHref?: string;\n /** Short sentence under the logo. */\n tagline?: ReactNode;\n /** Under the sentence: a pill, a contact… */\n children?: ReactNode;\n /** Site map in columns, each with a spaced small-caps title. */\n columns?: { title: ReactNode; links: FooterLink[] }[];\n /** Accessible name of the site map. */\n columnsLabel?: string;\n /** Bottom line (copyright, credits…). */\n copyright?: ReactNode;\n /** Legal links, aligned right on large screens. */\n legal?: FooterLink[];\n legalLabel?: string;\n /** Router link component (Next.js `Link`…); `<a>` by default. */\n linkAs?: ElementType;\n className?: string;\n};\n\n/** Graphite card footer: brand and call to action, site map in columns, legal links. */\nexport function SiteFooter({\n logo,\n logoLabel,\n homeHref = \"/\",\n tagline,\n children,\n columns = [],\n columnsLabel = \"Site map\",\n copyright,\n legal = [],\n legalLabel = \"Legal\",\n linkAs: LinkTag = \"a\",\n className,\n}: SiteFooterProps) {\n return (\n <footer className={cx(\"trc-footer\", className)}>\n <div className=\"trc-footer__card\">\n <div className=\"trc-footer__main\">\n <div className=\"trc-footer__brand\">\n {logo != null && (\n <LinkTag href={homeHref} aria-label={logoLabel} className=\"trc-footer__logo\">\n {logo}\n </LinkTag>\n )}\n {tagline != null && <p className=\"trc-footer__tagline\">{tagline}</p>}\n {children != null && <div className=\"trc-footer__extra\">{children}</div>}\n </div>\n\n {columns.length > 0 && (\n <nav className=\"trc-footer__columns\" aria-label={columnsLabel}>\n {columns.map((col, i) => (\n <div key={i}>\n <p className=\"trc-footer__heading\">{col.title}</p>\n <ul className=\"trc-footer__list\">\n {col.links.map((link, j) => (\n <li key={j}>\n <LinkTag href={link.href} className=\"trc-footer__link\">\n {link.label}\n </LinkTag>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </nav>\n )}\n </div>\n\n {(copyright != null || legal.length > 0) && (\n <div className=\"trc-footer__bottom\">\n {copyright != null && <p className=\"trc-footer__copyright\">{copyright}</p>}\n {legal.length > 0 && (\n <nav aria-label={legalLabel} className=\"trc-footer__legal\">\n {legal.map((link, i) => (\n <LinkTag key={i} href={link.href} className=\"trc-footer__legal-link\">\n {link.label}\n </LinkTag>\n ))}\n </nav>\n )}\n </div>\n )}\n </div>\n </footer>\n );\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState, type CSSProperties, type ReactNode } from \"react\";\nimport { cx } from \"../utils/cx\";\nimport { AccentText } from \"./typography\";\n\n/** Delay of an entrance (`.trc-enter`) in milliseconds. */\nconst delay = (ms: number) => ({ \"--trc-delay\": `${ms}ms` }) as CSSProperties;\n\nexport type PageHeroProps = {\n /** Title; the words between *asterisks* take the accent, otherwise the last words (`accentLast`). */\n title: string;\n /** Number of trailing words in the accent color when the title has no asterisks (2 for a long title, 1 otherwise). */\n accentLast?: number;\n description?: ReactNode;\n /** Discreet line under the description (last updated date, breadcrumb…). */\n meta?: ReactNode;\n /**\n * Background photo, heavily darkened: a URL, or a ready-made element (Next.js `<Image fill />`…).\n * Without a photo, a subtle accent glow on a graphite background.\n */\n image?: string | ReactNode;\n /** Photo position (`object-position`). */\n imagePosition?: string;\n /** Content under the text (pills…). */\n children?: ReactNode;\n className?: string;\n};\n\n/**\n * Header of inner pages: rounded card inset from the edges, darkened background photo,\n * thin title whose last words take the accent. Leaves room for the floating header above.\n */\nexport function PageHero({\n title,\n accentLast,\n description,\n meta,\n image,\n imagePosition = \"50% 50%\",\n children,\n className,\n}: PageHeroProps) {\n const words = title.split(\" \").length;\n return (\n <section className={cx(\"trc-hero-inset\", className)}>\n <div className=\"trc-page-hero\">\n <div aria-hidden className=\"trc-hero__media\">\n {typeof image === \"string\" ? (\n <img src={image} alt=\"\" className=\"trc-hero__image\" style={{ objectPosition: imagePosition }} />\n ) : image != null ? (\n image\n ) : (\n <div className=\"trc-page-hero__glow\" />\n )}\n </div>\n <div aria-hidden className=\"trc-page-hero__veil\" />\n <div className=\"trc-page-hero__content\">\n <h1 className=\"trc-display trc-page-hero__title trc-enter\" style={delay(150)}>\n <AccentText text={title} accentLast={accentLast ?? (words > 3 ? 2 : 1)} />\n </h1>\n {description != null && (\n <p className=\"trc-page-hero__description trc-enter\" style={delay(250)}>\n {description}\n </p>\n )}\n {meta != null && (\n <div className=\"trc-page-hero__meta trc-enter\" style={delay(350)}>\n {meta}\n </div>\n )}\n {children != null && (\n <div className=\"trc-page-hero__actions trc-enter\" style={delay(450)}>\n {children}\n </div>\n )}\n </div>\n </div>\n </section>\n );\n}\n\nexport type HeroClip = {\n /** Muted video, 1280 px, without an audio track. Provide WebM and/or MP4. */\n webm?: string;\n mp4?: string;\n /** Image shown before playback, and alone when the user prefers reduced motion. */\n poster?: string;\n};\n\nexport type HeroVideoProps = {\n /** Videos played one after another with a crossfade; the first one is picked at random. */\n clips: HeroClip[];\n /** Hero text (title, description, pills), pinned to the bottom left. */\n children: ReactNode;\n /** Optional block pinned to the bottom right on large screens. */\n aside?: ReactNode;\n /** Crossfade duration, in seconds. */\n fade?: number;\n /** Soft parallax: the video moves down slower than the page. */\n parallax?: boolean;\n className?: string;\n};\n\nconst prefersReducedMotion = () => window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n/**\n * Home page hero: rounded card inset from the edges, muted background videos that alternate with\n * a crossfade, dark veils for legibility. No video in the server render: the pick happens\n * after hydration, then the video fades in. Reduced motion: the still image only.\n */\nexport function HeroVideo({ clips, children, aside, fade = 1.2, parallax = true, className }: HeroVideoProps) {\n const videos = useRef<(HTMLVideoElement | null)[]>([]);\n const section = useRef<HTMLElement>(null);\n const media = useRef<HTMLDivElement>(null);\n // -1 until the pick is made: same render on the server and on the client.\n const [active, setActive] = useState(-1);\n\n useEffect(() => {\n if (clips.length === 0) return;\n const start = Math.floor(Math.random() * clips.length);\n // Element captured here: in strict mode, React detaches refs before the cleanup runs.\n const video = videos.current[start];\n if (!prefersReducedMotion()) void video?.play().catch(() => {});\n const frame = requestAnimationFrame(() => setActive(start));\n return () => {\n cancelAnimationFrame(frame);\n video?.pause();\n };\n }, [clips.length]);\n\n useEffect(() => {\n const el = section.current;\n const layer = media.current;\n if (!parallax || !el || !layer || prefersReducedMotion()) return;\n let frame = 0;\n const update = () => {\n frame = 0;\n const rect = el.getBoundingClientRect();\n const progress = Math.min(Math.max(-rect.top / rect.height, 0), 1);\n layer.style.transform = `translate3d(0, ${progress * 120}px, 0)`;\n };\n const onScroll = () => {\n if (!frame) frame = requestAnimationFrame(update);\n };\n update();\n window.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => {\n window.removeEventListener(\"scroll\", onScroll);\n cancelAnimationFrame(frame);\n };\n }, [parallax]);\n\n const playNext = (i: number) => {\n const next = videos.current[(i + 1) % clips.length];\n if (!next) return;\n next.currentTime = 0;\n void next.play().catch(() => {});\n setActive((i + 1) % clips.length);\n };\n\n return (\n <section ref={section} className={cx(\"trc-hero-inset\", className)}>\n <div className=\"trc-hero-video\">\n <div ref={media} aria-hidden className=\"trc-hero__media trc-hero-video__media\">\n {clips.map((clip, i) => (\n <video\n key={i}\n ref={(el) => {\n videos.current[i] = el;\n }}\n className={cx(\"trc-hero__image\", \"trc-hero-video__clip\", i === active && \"trc-hero-video__clip--active\")}\n style={{ transitionDuration: `${fade}s` }}\n muted\n playsInline\n preload=\"metadata\"\n poster={clip.poster}\n // Shortly before the active video ends, the next one restarts and comes to the front.\n onTimeUpdate={(e) => {\n const v = e.currentTarget;\n if (i === active && v.duration && v.duration - v.currentTime <= fade) playNext(i);\n }}\n // Safety net when `timeupdate` did not trigger the switch (background tab…).\n onEnded={() => i === active && playNext(i)}\n >\n {clip.webm && <source src={clip.webm} type=\"video/webm\" />}\n {clip.mp4 && <source src={clip.mp4} type=\"video/mp4\" />}\n </video>\n ))}\n </div>\n <div aria-hidden className=\"trc-hero-video__veil\" />\n <div className=\"trc-hero-video__content\">\n <div className=\"trc-hero-video__main\">{children}</div>\n {aside != null && <div className=\"trc-hero-video__aside\">{aside}</div>}\n </div>\n </div>\n </section>\n );\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { cx } from \"../utils/cx\";\nimport { ArrowUp } from \"../utils/icons\";\n\nexport type BackToTopProps = {\n label?: string;\n /** Scroll offset, in viewport heights, from which the button appears. */\n threshold?: number;\n className?: string;\n};\n\n/** Floating accent \"Back to top\" button: appears once the first screen is scrolled past. */\nexport function BackToTop({ label = \"Back to top\", threshold = 0.8, className }: BackToTopProps) {\n const [visible, setVisible] = useState(false);\n\n useEffect(() => {\n const update = () => setVisible(window.scrollY > window.innerHeight * threshold);\n update();\n window.addEventListener(\"scroll\", update, { passive: true });\n return () => window.removeEventListener(\"scroll\", update);\n }, [threshold]);\n\n return (\n <button\n type=\"button\"\n onClick={() =>\n window.scrollTo({\n top: 0,\n behavior: window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches ? \"auto\" : \"smooth\",\n })\n }\n aria-label={label}\n aria-hidden={!visible}\n tabIndex={visible ? 0 : -1}\n className={cx(\"trc-back-to-top\", visible && \"trc-back-to-top--visible\", className)}\n >\n <ArrowUp />\n </button>\n );\n}\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","PillButton","PillLink","import_jsx_runtime","import_react","import_jsx_runtime","Input","Textarea","Select","import_react","import_jsx_runtime","Checkbox","Switch","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime"]}
@@ -0,0 +1,300 @@
1
+ import * as react from 'react';
2
+ import { ComponentPropsWithoutRef, ReactNode, ElementType, Ref, SVGProps } from 'react';
3
+
4
+ /** Joins CSS class names, skipping empty values. */
5
+ declare function cx(...classes: (string | false | null | undefined)[]): string;
6
+
7
+ /**
8
+ * Colors the words between asterisks with the accent: "How it *works*".
9
+ * Without asterisks, `accentLast` colors the last words (titles coming from a CMS).
10
+ */
11
+ declare function AccentText({ text, accentLast }: {
12
+ text: string;
13
+ accentLast?: number;
14
+ }): react.JSX.Element;
15
+ /** Plain text of a marked-up title, for attributes (`alt`, `title`, metadata). */
16
+ declare const plainText: (text: string) => string;
17
+ type HeadingSize = "display" | "xl" | "lg" | "md" | "sm";
18
+ type HeadingProps = Omit<ComponentPropsWithoutRef<"h2">, "children"> & {
19
+ /** Rendered tag; the visual size is set separately with `size`. */
20
+ as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span";
21
+ size?: HeadingSize;
22
+ /** When `children` is a string without asterisks, number of trailing words in the accent color. */
23
+ accentLast?: number;
24
+ children: ReactNode;
25
+ };
26
+ /** Thin Montserrat 400 heading; a string may contain an *accent word* between asterisks. */
27
+ declare function Heading({ as: Tag, size, accentLast, className, children, ...props }: HeadingProps): react.JSX.Element;
28
+ type TextProps<C extends ElementType = "p"> = {
29
+ as?: C;
30
+ size?: "lg" | "md" | "sm";
31
+ tone?: "default" | "muted" | "subtle";
32
+ } & Omit<ComponentPropsWithoutRef<C>, "as" | "size">;
33
+ /** Body text; `tone="muted"` (default) so that it does not compete with headings. */
34
+ declare function Text<C extends ElementType = "p">({ as, size, tone, className, ...props }: TextProps<C>): react.JSX.Element;
35
+ /** Large thin number in the accent color ("01", "02"…), reserved for steps in a real order. */
36
+ declare function StepNumber({ n, size, className }: {
37
+ n: number;
38
+ size?: "md" | "sm";
39
+ className?: string;
40
+ }): react.JSX.Element;
41
+
42
+ type PillStyle = {
43
+ /** White background: the main action of a screen. */
44
+ solid?: boolean;
45
+ /** Compact version (header, toolbars). */
46
+ size?: "md" | "sm";
47
+ /** Replaces the dot's arrow (for instance a left arrow for "Back"). */
48
+ icon?: ReactNode;
49
+ };
50
+ type PillButtonProps = ComponentPropsWithoutRef<"button"> & PillStyle & {
51
+ /** Replaces the icon with a spinner and disables the button. */
52
+ loading?: boolean;
53
+ };
54
+ /** Pill button: thin border, accent dot with an arrow that stretches on hover. */
55
+ declare const PillButton: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & PillStyle & {
56
+ /** Replaces the icon with a spinner and disables the button. */
57
+ loading?: boolean;
58
+ } & react.RefAttributes<HTMLButtonElement>>;
59
+ type PillLinkProps<C extends ElementType = "a"> = PillStyle & {
60
+ /** Router link component (Next.js or React Router `Link`…); `<a>` by default. */
61
+ as?: C;
62
+ } & Omit<ComponentPropsWithoutRef<C>, "as" | keyof PillStyle>;
63
+ /** Same pill as a link. With a router: `<PillLink as={Link} href="/">`. */
64
+ declare const PillLink: <C extends ElementType = "a">(props: PillLinkProps<C> & {
65
+ ref?: Ref<HTMLAnchorElement>;
66
+ }) => ReactNode;
67
+
68
+ type IconProps = SVGProps<SVGSVGElement>;
69
+ declare const ArrowRight: (props: IconProps) => react.JSX.Element;
70
+ declare const ArrowLeft: (props: IconProps) => react.JSX.Element;
71
+ declare const ChevronDown: (props: IconProps) => react.JSX.Element;
72
+ declare const Check: (props: IconProps) => react.JSX.Element;
73
+ declare const Menu: (props: IconProps) => react.JSX.Element;
74
+ declare const Close: (props: IconProps) => react.JSX.Element;
75
+ declare const ArrowUp: (props: IconProps) => react.JSX.Element;
76
+
77
+ type Polymorphic<C extends ElementType, P> = P & {
78
+ as?: C;
79
+ } & Omit<ComponentPropsWithoutRef<C>, "as" | keyof P>;
80
+ type ContainerProps<C extends ElementType = "div"> = Polymorphic<C, {
81
+ /** `default`: 1280 px, for text and grids; `wide`: 1600 px, for full-width cards; `narrow`: 768 px. */
82
+ size?: "default" | "wide" | "narrow";
83
+ }>;
84
+ /** Centered max width, with side gutters that grow with the screen. */
85
+ declare function Container<C extends ElementType = "div">({ as, size, className, ...props }: ContainerProps<C>): react.JSX.Element;
86
+ type SectionProps<C extends ElementType = "section"> = Polymorphic<C, {
87
+ /** Vertical spacing. */
88
+ spacing?: "sm" | "md" | "lg" | "none";
89
+ /**
90
+ * Card inset from the screen edges ("magazine" effect): graphite background and rounded corners,
91
+ * for banners, calls to action and heroes.
92
+ */
93
+ inset?: boolean;
94
+ }>;
95
+ /** Vertical block of a page. With `inset`, it becomes a large rounded card a few pixels from the edges. */
96
+ declare function Section<C extends ElementType = "section">({ as, spacing, inset, className, children, ...props }: SectionProps<C>): react.JSX.Element;
97
+ type CardProps<C extends ElementType = "div"> = Polymorphic<C, {
98
+ /** `alt`: a slightly lighter grey, to tell two side-by-side blocks apart. */
99
+ tone?: "default" | "alt";
100
+ padding?: "none" | "sm" | "md" | "lg";
101
+ /** Lightens on hover (clickable cards: links, buttons). */
102
+ interactive?: boolean;
103
+ /** Decorative watermark icon: very large, thin stroke, half out of the corner; wakes up on hover. */
104
+ watermark?: ReactNode;
105
+ }>;
106
+ /** Graphite card, rounded corners, no shadow: depth comes from shades of grey. */
107
+ declare function Card<C extends ElementType = "div">({ as, tone, padding, interactive, watermark, className, children, ...props }: CardProps<C>): react.JSX.Element;
108
+
109
+ type FieldProps = {
110
+ label: ReactNode;
111
+ /** Hint shown under the control. */
112
+ hint?: ReactNode;
113
+ /** Error message: replaces the hint and marks the control as invalid. */
114
+ error?: ReactNode;
115
+ required?: boolean;
116
+ /** Control id; generated when omitted. */
117
+ id?: string;
118
+ className?: string;
119
+ children: ReactNode;
120
+ };
121
+ /**
122
+ * Label, hint and error of a form control. The control placed inside (`Input`, `Textarea`, `Select`)
123
+ * automatically receives its `id`, `aria-describedby` and `aria-invalid`.
124
+ */
125
+ declare function Field({ label, hint, error, required, id, className, children }: FieldProps): react.JSX.Element;
126
+ type ControlProps = {
127
+ invalid?: boolean;
128
+ };
129
+ type InputProps = ComponentPropsWithoutRef<"input"> & ControlProps;
130
+ declare const Input: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & ControlProps & react.RefAttributes<HTMLInputElement>>;
131
+ type TextareaProps = ComponentPropsWithoutRef<"textarea"> & ControlProps;
132
+ declare const Textarea: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>, "ref"> & ControlProps & react.RefAttributes<HTMLTextAreaElement>>;
133
+ type SelectProps = ComponentPropsWithoutRef<"select"> & ControlProps & {
134
+ /** Empty option shown until something is chosen. */
135
+ placeholder?: string;
136
+ };
137
+ /** Native select (accessible and mobile friendly), dressed with a thin chevron. */
138
+ declare const Select: react.ForwardRefExoticComponent<Omit<react.DetailedHTMLProps<react.SelectHTMLAttributes<HTMLSelectElement>, HTMLSelectElement>, "ref"> & ControlProps & {
139
+ /** Empty option shown until something is chosen. */
140
+ placeholder?: string;
141
+ } & react.RefAttributes<HTMLSelectElement>>;
142
+
143
+ type ToggleProps = Omit<ComponentPropsWithoutRef<"input">, "type"> & {
144
+ label: ReactNode;
145
+ /** Extra detail under the label. */
146
+ description?: ReactNode;
147
+ };
148
+ type CheckboxProps = ToggleProps;
149
+ /** Native checkbox, filled with the accent color once checked. */
150
+ declare const Checkbox: react.ForwardRefExoticComponent<Omit<Omit<react.DetailedHTMLProps<react.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "type"> & {
151
+ label: ReactNode;
152
+ /** Extra detail under the label. */
153
+ description?: ReactNode;
154
+ } & react.RefAttributes<HTMLInputElement>>;
155
+ type SwitchProps = ToggleProps;
156
+ /** Switch: a native checkbox announced as a `switch` to screen readers. */
157
+ declare const Switch: react.ForwardRefExoticComponent<Omit<Omit<react.DetailedHTMLProps<react.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "type"> & {
158
+ label: ReactNode;
159
+ /** Extra detail under the label. */
160
+ description?: ReactNode;
161
+ } & react.RefAttributes<HTMLInputElement>>;
162
+
163
+ type NavLink = {
164
+ label: ReactNode;
165
+ href: string;
166
+ /** Current page: marked with an accent dot. */
167
+ active?: boolean;
168
+ };
169
+ type NavMenu = {
170
+ label: ReactNode;
171
+ /** Dropdown items, with an optional short description (no numbers). */
172
+ items: (NavLink & {
173
+ description?: ReactNode;
174
+ })[];
175
+ };
176
+ type NavItem = NavLink | NavMenu;
177
+ type SiteHeaderProps = {
178
+ /** Logo (white), wrapped in a link to `homeHref`. */
179
+ logo: ReactNode;
180
+ /** Accessible name of the logo link, usually the brand name. */
181
+ logoLabel: string;
182
+ homeHref?: string;
183
+ nav?: NavItem[];
184
+ /** Main action, shown as a compact pill (and a large one in the mobile menu). */
185
+ cta?: {
186
+ label: ReactNode;
187
+ href: string;
188
+ };
189
+ /** Extra elements on the right on large screens (language switcher…). */
190
+ actions?: ReactNode;
191
+ /** Content added at the bottom of the mobile menu. */
192
+ mobileFooter?: ReactNode;
193
+ /** Router link component (Next.js `Link`…); `<a>` by default. */
194
+ linkAs?: ElementType;
195
+ /** Scroll offset (px) from which the bar becomes blurred graphite. */
196
+ scrollThreshold?: number;
197
+ menuLabel?: string;
198
+ closeLabel?: string;
199
+ className?: string;
200
+ };
201
+ /**
202
+ * Floating header: transparent over the hero at the top of the page, it becomes a blurred
203
+ * graphite bar as soon as the page scrolls. Dropdowns on large screens, side panel on mobile.
204
+ */
205
+ declare function SiteHeader({ logo, logoLabel, homeHref, nav, cta, actions, mobileFooter, linkAs: LinkTag, scrollThreshold, menuLabel, closeLabel, className, }: SiteHeaderProps): react.JSX.Element;
206
+
207
+ type FooterLink = {
208
+ label: ReactNode;
209
+ href: string;
210
+ };
211
+ type SiteFooterProps = {
212
+ /** Logo (white), wrapped in a link to `homeHref`. */
213
+ logo?: ReactNode;
214
+ logoLabel?: string;
215
+ homeHref?: string;
216
+ /** Short sentence under the logo. */
217
+ tagline?: ReactNode;
218
+ /** Under the sentence: a pill, a contact… */
219
+ children?: ReactNode;
220
+ /** Site map in columns, each with a spaced small-caps title. */
221
+ columns?: {
222
+ title: ReactNode;
223
+ links: FooterLink[];
224
+ }[];
225
+ /** Accessible name of the site map. */
226
+ columnsLabel?: string;
227
+ /** Bottom line (copyright, credits…). */
228
+ copyright?: ReactNode;
229
+ /** Legal links, aligned right on large screens. */
230
+ legal?: FooterLink[];
231
+ legalLabel?: string;
232
+ /** Router link component (Next.js `Link`…); `<a>` by default. */
233
+ linkAs?: ElementType;
234
+ className?: string;
235
+ };
236
+ /** Graphite card footer: brand and call to action, site map in columns, legal links. */
237
+ declare function SiteFooter({ logo, logoLabel, homeHref, tagline, children, columns, columnsLabel, copyright, legal, legalLabel, linkAs: LinkTag, className, }: SiteFooterProps): react.JSX.Element;
238
+
239
+ type PageHeroProps = {
240
+ /** Title; the words between *asterisks* take the accent, otherwise the last words (`accentLast`). */
241
+ title: string;
242
+ /** Number of trailing words in the accent color when the title has no asterisks (2 for a long title, 1 otherwise). */
243
+ accentLast?: number;
244
+ description?: ReactNode;
245
+ /** Discreet line under the description (last updated date, breadcrumb…). */
246
+ meta?: ReactNode;
247
+ /**
248
+ * Background photo, heavily darkened: a URL, or a ready-made element (Next.js `<Image fill />`…).
249
+ * Without a photo, a subtle accent glow on a graphite background.
250
+ */
251
+ image?: string | ReactNode;
252
+ /** Photo position (`object-position`). */
253
+ imagePosition?: string;
254
+ /** Content under the text (pills…). */
255
+ children?: ReactNode;
256
+ className?: string;
257
+ };
258
+ /**
259
+ * Header of inner pages: rounded card inset from the edges, darkened background photo,
260
+ * thin title whose last words take the accent. Leaves room for the floating header above.
261
+ */
262
+ declare function PageHero({ title, accentLast, description, meta, image, imagePosition, children, className, }: PageHeroProps): react.JSX.Element;
263
+ type HeroClip = {
264
+ /** Muted video, 1280 px, without an audio track. Provide WebM and/or MP4. */
265
+ webm?: string;
266
+ mp4?: string;
267
+ /** Image shown before playback, and alone when the user prefers reduced motion. */
268
+ poster?: string;
269
+ };
270
+ type HeroVideoProps = {
271
+ /** Videos played one after another with a crossfade; the first one is picked at random. */
272
+ clips: HeroClip[];
273
+ /** Hero text (title, description, pills), pinned to the bottom left. */
274
+ children: ReactNode;
275
+ /** Optional block pinned to the bottom right on large screens. */
276
+ aside?: ReactNode;
277
+ /** Crossfade duration, in seconds. */
278
+ fade?: number;
279
+ /** Soft parallax: the video moves down slower than the page. */
280
+ parallax?: boolean;
281
+ className?: string;
282
+ };
283
+ /**
284
+ * Home page hero: rounded card inset from the edges, muted background videos that alternate with
285
+ * a crossfade, dark veils for legibility. No video in the server render: the pick happens
286
+ * after hydration, then the video fades in. Reduced motion: the still image only.
287
+ */
288
+ declare function HeroVideo({ clips, children, aside, fade, parallax, className }: HeroVideoProps): react.JSX.Element;
289
+
290
+ type BackToTopProps = {
291
+ label?: string;
292
+ /** Scroll offset, in viewport heights, from which the button appears. */
293
+ threshold?: number;
294
+ className?: string;
295
+ };
296
+ /** Floating accent "Back to top" button: appears once the first screen is scrolled past. */
297
+ declare function BackToTop({ label, threshold, className }: BackToTopProps): react.JSX.Element;
298
+
299
+ export { AccentText, ArrowLeft, ArrowRight, ArrowUp, BackToTop, Card, Check, Checkbox, ChevronDown, Close, Container, Field, Heading, HeroVideo, Input, Menu, PageHero, PillButton, PillLink, Section, Select, SiteFooter, SiteHeader, StepNumber, Switch, Text, Textarea, cx, plainText };
300
+ export type { BackToTopProps, CardProps, CheckboxProps, ContainerProps, FieldProps, FooterLink, HeadingProps, HeadingSize, HeroClip, HeroVideoProps, InputProps, NavItem, NavLink, NavMenu, PageHeroProps, PillButtonProps, PillLinkProps, SectionProps, SelectProps, SiteFooterProps, SiteHeaderProps, SwitchProps, TextProps, TextareaProps };