sonahang-ui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +125 -0
- package/dist/components/Accordion/Accordion.d.ts +36 -0
- package/dist/components/Accordion/AccordionItem.d.ts +15 -0
- package/dist/components/Accordion/accordion.context.d.ts +18 -0
- package/dist/components/Accordion/index.d.ts +5 -0
- package/dist/components/Alert/Alert.d.ts +24 -0
- package/dist/components/Alert/alert.tokens.d.ts +2 -0
- package/dist/components/Alert/index.d.ts +4 -0
- package/dist/components/Avatar/Avatar.d.ts +17 -0
- package/dist/components/Avatar/AvatarGroup.d.ts +12 -0
- package/dist/components/Avatar/avatar.context.d.ts +7 -0
- package/dist/components/Avatar/avatar.tokens.d.ts +2 -0
- package/dist/components/Avatar/getInitials.d.ts +6 -0
- package/dist/components/Avatar/index.d.ts +6 -0
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +19 -0
- package/dist/components/Breadcrumb/BreadcrumbItem.d.ts +25 -0
- package/dist/components/Breadcrumb/breadcrumb.context.d.ts +10 -0
- package/dist/components/Breadcrumb/index.d.ts +4 -0
- package/dist/components/Button/Button.d.ts +20 -0
- package/dist/components/Button/button.tokens.d.ts +4 -0
- package/dist/components/Button/buttonClassNames.d.ts +17 -0
- package/dist/components/Button/index.d.ts +6 -0
- package/dist/components/Checkbox/Checkbox.d.ts +24 -0
- package/dist/components/Checkbox/CheckboxGroup.d.ts +28 -0
- package/dist/components/Checkbox/checkbox.context.d.ts +17 -0
- package/dist/components/Checkbox/index.d.ts +4 -0
- package/dist/components/Chip/Chip.d.ts +21 -0
- package/dist/components/Chip/chip.tokens.d.ts +4 -0
- package/dist/components/Chip/index.d.ts +4 -0
- package/dist/components/CodeBlock/CodeBlock.d.ts +41 -0
- package/dist/components/CodeBlock/dedentCode.d.ts +12 -0
- package/dist/components/CodeBlock/index.d.ts +3 -0
- package/dist/components/Dialog/Dialog.d.ts +70 -0
- package/dist/components/Dialog/dialog.tokens.d.ts +8 -0
- package/dist/components/Dialog/index.d.ts +4 -0
- package/dist/components/Drawer/Drawer.d.ts +72 -0
- package/dist/components/Drawer/drawer.tokens.d.ts +10 -0
- package/dist/components/Drawer/index.d.ts +4 -0
- package/dist/components/Dropdown/Dropdown.d.ts +24 -0
- package/dist/components/Dropdown/DropdownItem.d.ts +16 -0
- package/dist/components/Dropdown/DropdownMenu.d.ts +13 -0
- package/dist/components/Dropdown/DropdownSeparator.d.ts +10 -0
- package/dist/components/Dropdown/DropdownTrigger.d.ts +8 -0
- package/dist/components/Dropdown/dropdown.context.d.ts +24 -0
- package/dist/components/Dropdown/index.d.ts +11 -0
- package/dist/components/EmptyState/EmptyState.d.ts +47 -0
- package/dist/components/EmptyState/index.d.ts +2 -0
- package/dist/components/FileDrop/FileDrop.d.ts +41 -0
- package/dist/components/FileDrop/index.d.ts +3 -0
- package/dist/components/FileDrop/isFileAccepted.d.ts +11 -0
- package/dist/components/Input/Input.d.ts +20 -0
- package/dist/components/Input/index.d.ts +2 -0
- package/dist/components/InputOtp/InputOtp.d.ts +39 -0
- package/dist/components/InputOtp/index.d.ts +4 -0
- package/dist/components/InputOtp/sanitizeOtpValue.d.ts +20 -0
- package/dist/components/MinMaxSlider/MinMaxSlider.d.ts +41 -0
- package/dist/components/MinMaxSlider/index.d.ts +2 -0
- package/dist/components/Pagination/Pagination.d.ts +41 -0
- package/dist/components/Pagination/getPaginationRange.d.ts +25 -0
- package/dist/components/Pagination/index.d.ts +4 -0
- package/dist/components/ProgressBar/ProgressBar.d.ts +34 -0
- package/dist/components/ProgressBar/index.d.ts +4 -0
- package/dist/components/ProgressBar/progressBar.tokens.d.ts +2 -0
- package/dist/components/Radio/Radio.d.ts +18 -0
- package/dist/components/Radio/RadioGroup.d.ts +28 -0
- package/dist/components/Radio/index.d.ts +4 -0
- package/dist/components/Radio/radio.context.d.ts +17 -0
- package/dist/components/RangeSlider/RangeSlider.d.ts +36 -0
- package/dist/components/RangeSlider/index.d.ts +2 -0
- package/dist/components/SegmentedControl/SegmentedControl.d.ts +39 -0
- package/dist/components/SegmentedControl/index.d.ts +2 -0
- package/dist/components/Select/Select.d.ts +39 -0
- package/dist/components/Select/index.d.ts +2 -0
- package/dist/components/Skeleton/Skeleton.d.ts +24 -0
- package/dist/components/Skeleton/index.d.ts +4 -0
- package/dist/components/Skeleton/skeleton.tokens.d.ts +4 -0
- package/dist/components/Spinner/Spinner.d.ts +22 -0
- package/dist/components/Spinner/index.d.ts +4 -0
- package/dist/components/Spinner/spinner.tokens.d.ts +2 -0
- package/dist/components/Stepper/Step.d.ts +20 -0
- package/dist/components/Stepper/Stepper.d.ts +25 -0
- package/dist/components/Stepper/index.d.ts +5 -0
- package/dist/components/Stepper/stepper.context.d.ts +14 -0
- package/dist/components/Switch/Switch.d.ts +22 -0
- package/dist/components/Switch/SwitchGroup.d.ts +30 -0
- package/dist/components/Switch/index.d.ts +4 -0
- package/dist/components/Switch/switch.context.d.ts +19 -0
- package/dist/components/Tabs/Tab.d.ts +10 -0
- package/dist/components/Tabs/TabList.d.ts +20 -0
- package/dist/components/Tabs/TabPanel.d.ts +16 -0
- package/dist/components/Tabs/Tabs.d.ts +22 -0
- package/dist/components/Tabs/index.d.ts +9 -0
- package/dist/components/Tabs/tabs.context.d.ts +24 -0
- package/dist/components/Tag/Tag.d.ts +10 -0
- package/dist/components/Tag/index.d.ts +4 -0
- package/dist/components/Tag/tag.tokens.d.ts +2 -0
- package/dist/components/Text/Text.d.ts +19 -0
- package/dist/components/Text/index.d.ts +4 -0
- package/dist/components/Text/text.tokens.d.ts +8 -0
- package/dist/components/Textarea/Textarea.d.ts +19 -0
- package/dist/components/Textarea/index.d.ts +2 -0
- package/dist/components/Tooltip/Tooltip.d.ts +44 -0
- package/dist/components/Tooltip/index.d.ts +4 -0
- package/dist/components/Tooltip/resolveTooltipPlacement.d.ts +39 -0
- package/dist/index.d.ts +82 -0
- package/dist/internal/bodyScrollLock.d.ts +2 -0
- package/dist/internal/portalInto.d.ts +7 -0
- package/dist/internal/useModalSurface.d.ts +27 -0
- package/dist/sonahang-ui.cjs +7 -0
- package/dist/sonahang-ui.cjs.map +1 -0
- package/dist/sonahang-ui.css +2 -0
- package/dist/sonahang-ui.js +2578 -0
- package/dist/sonahang-ui.js.map +1 -0
- package/dist/tokens/colors.d.ts +167 -0
- package/package.json +101 -0
- package/style.css.d.ts +17 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sonahang-ui.cjs","names":[],"sources":["../src/components/Text/text.tokens.ts","../src/components/Text/Text.tsx","../src/components/Button/buttonClassNames.ts","../src/components/Button/Button.tsx","../src/components/Button/button.tokens.ts","../src/components/EmptyState/EmptyState.tsx","../src/components/Tag/Tag.tsx","../src/components/Tag/tag.tokens.ts","../src/components/Chip/Chip.tsx","../src/components/Chip/chip.tokens.ts","../src/components/Avatar/avatar.context.ts","../src/components/Avatar/getInitials.ts","../src/components/Avatar/Avatar.tsx","../src/components/Avatar/AvatarGroup.tsx","../src/components/Avatar/avatar.tokens.ts","../src/components/Input/Input.tsx","../src/components/InputOtp/sanitizeOtpValue.ts","../src/components/InputOtp/InputOtp.tsx","../src/components/Dropdown/dropdown.context.ts","../src/components/Dropdown/Dropdown.tsx","../src/components/Dropdown/DropdownTrigger.tsx","../src/components/Dropdown/DropdownMenu.tsx","../src/components/Dropdown/DropdownItem.tsx","../src/components/Dropdown/DropdownSeparator.tsx","../src/components/CodeBlock/dedentCode.ts","../src/components/CodeBlock/CodeBlock.tsx","../src/internal/portalInto.ts","../src/internal/bodyScrollLock.ts","../src/internal/useModalSurface.ts","../src/components/Dialog/Dialog.tsx","../src/components/Dialog/dialog.tokens.ts","../src/components/Drawer/Drawer.tsx","../src/components/Drawer/drawer.tokens.ts","../src/components/Tooltip/resolveTooltipPlacement.ts","../src/components/Tooltip/Tooltip.tsx","../src/components/Select/Select.tsx","../src/components/Textarea/Textarea.tsx","../src/components/Checkbox/checkbox.context.ts","../src/components/Checkbox/Checkbox.tsx","../src/components/Checkbox/CheckboxGroup.tsx","../src/components/Radio/radio.context.ts","../src/components/Radio/Radio.tsx","../src/components/Radio/RadioGroup.tsx","../src/components/Pagination/getPaginationRange.ts","../src/components/Pagination/Pagination.tsx","../src/components/Accordion/accordion.context.ts","../src/components/Accordion/Accordion.tsx","../src/components/Accordion/AccordionItem.tsx","../src/components/Stepper/stepper.context.ts","../src/components/Stepper/Stepper.tsx","../src/components/Stepper/Step.tsx","../src/components/Breadcrumb/breadcrumb.context.ts","../src/components/Breadcrumb/Breadcrumb.tsx","../src/components/Breadcrumb/BreadcrumbItem.tsx","../src/components/Tabs/tabs.context.ts","../src/components/Tabs/Tabs.tsx","../src/components/Tabs/TabList.tsx","../src/components/Tabs/Tab.tsx","../src/components/Tabs/TabPanel.tsx","../src/components/Skeleton/Skeleton.tsx","../src/components/Skeleton/skeleton.tokens.ts","../src/components/Spinner/Spinner.tsx","../src/components/Spinner/spinner.tokens.ts","../src/components/ProgressBar/ProgressBar.tsx","../src/components/ProgressBar/progressBar.tokens.ts","../src/components/Alert/Alert.tsx","../src/components/Alert/alert.tokens.ts","../src/components/FileDrop/isFileAccepted.ts","../src/components/FileDrop/FileDrop.tsx","../src/components/RangeSlider/RangeSlider.tsx","../src/components/MinMaxSlider/MinMaxSlider.tsx","../src/components/Switch/switch.context.ts","../src/components/Switch/Switch.tsx","../src/components/Switch/SwitchGroup.tsx","../src/components/SegmentedControl/SegmentedControl.tsx","../src/tokens/colors.ts"],"sourcesContent":["import type { ElementType } from 'react';\n\nexport const textVariants = [\n 'display',\n 'heading-1',\n 'heading-2',\n 'heading-3',\n 'heading-4',\n 'body-lg',\n 'body',\n 'body-sm',\n 'caption',\n] as const;\n\nexport type TextVariant = (typeof textVariants)[number];\n\nexport const textColors = ['default', 'subtle', 'inverse', 'accent'] as const;\n\nexport type TextColor = (typeof textColors)[number];\n\nexport const textWeights = ['regular', 'medium', 'semibold', 'bold'] as const;\n\nexport type TextWeight = (typeof textWeights)[number];\n\nexport const defaultElement: Record<TextVariant, ElementType> = {\n display: 'h1',\n 'heading-1': 'h1',\n 'heading-2': 'h2',\n 'heading-3': 'h3',\n 'heading-4': 'h4',\n 'body-lg': 'p',\n body: 'p',\n 'body-sm': 'p',\n caption: 'span',\n};\n","import type { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react';\n\nimport { defaultElement } from './text.tokens';\nimport type { TextColor, TextVariant, TextWeight } from './text.tokens';\nimport './Text.css';\n\ntype TextOwnProps<E extends ElementType> = {\n /** Element to render. Defaults to the semantically correct tag for `variant`. */\n as?: E;\n /** Typography scale to apply. */\n variant?: TextVariant;\n /** Semantic color token to use. */\n color?: TextColor;\n /** Overrides the variant's default font weight. */\n weight?: TextWeight;\n align?: 'left' | 'center' | 'right';\n children?: ReactNode;\n};\n\nexport type TextProps<E extends ElementType = 'p'> = TextOwnProps<E> &\n Omit<ComponentPropsWithoutRef<E>, keyof TextOwnProps<E>>;\n\n/** Typography primitive for the design system — renders any variant as any element. */\nexport function Text<E extends ElementType = 'p'>({\n as,\n variant = 'body',\n color = 'default',\n weight,\n align,\n className,\n style,\n children,\n ...props\n}: TextProps<E>) {\n const Component = as ?? defaultElement[variant];\n const classes = ['sh-text', `sh-text--${variant}`, `sh-text--color-${color}`, className]\n .filter(Boolean)\n .join(' ');\n\n return (\n <Component\n className={classes}\n style={{\n ...(weight ? { fontWeight: `var(--font-weight-${weight})` } : undefined),\n ...(align ? { textAlign: align } : undefined),\n ...style,\n }}\n {...props}\n >\n {children}\n </Component>\n );\n}\n","import type { ButtonSize, ButtonVariant } from \"./button.tokens\";\n\nexport type ButtonClassNameOptions = {\n variant?: ButtonVariant;\n size?: ButtonSize;\n fullWidth?: boolean;\n loading?: boolean;\n className?: string;\n};\n\n/**\n * The class list `Button` puts on itself.\n *\n * Exported because `<button>` can't be a link: anything that needs to look\n * like a button while navigating — an `EmptyState` call to action, a \"read the\n * docs\" link — has to be an `<a>`, and should get its appearance from here\n * rather than from a second copy of the same rules.\n */\nexport function buttonClassNames({\n variant = \"primary\",\n size = \"md\",\n fullWidth = false,\n loading = false,\n className,\n}: ButtonClassNameOptions = {}): string {\n return [\n \"sh-button\",\n `sh-button--${variant}`,\n `sh-button--${size}`,\n fullWidth && \"sh-button--full-width\",\n loading && \"sh-button--loading\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n}\n","import type { ButtonHTMLAttributes, ReactNode } from \"react\";\n\nimport { buttonClassNames } from \"./buttonClassNames\";\nimport type { ButtonSize, ButtonVariant } from \"./button.tokens\";\nimport \"./Button.css\";\n\nexport type ButtonProps = {\n /** Visual style of the button. Defaults to `primary`. Use `icon` for an icon-only, square button. */\n variant?: ButtonVariant;\n /** Size of the button. Defaults to `md`. */\n size?: ButtonSize;\n /** Stretches the button to fill its container's width. */\n fullWidth?: boolean;\n /** Icon to render alongside `children`, or on its own when `variant=\"icon\"`. Note: icon-only buttons need an `aria-label`. */\n icon?: ReactNode;\n /** Where `icon` renders relative to `children`. Ignored when `variant=\"icon\"`. Defaults to `left`. */\n iconPosition?: \"left\" | \"right\";\n /** Shows a spinner on the left and disables the button while an async action is pending. Content stays visible, so `children` can be swapped for a loading message. */\n loading?: boolean;\n children?: ReactNode;\n} & Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"children\">;\n\n/** Interactive button primitive for the design system. */\nexport function Button({\n variant = \"primary\",\n size = \"md\",\n fullWidth = false,\n icon,\n iconPosition = \"left\",\n loading = false,\n disabled,\n className,\n children,\n ...props\n}: ButtonProps) {\n const isIconOnly = variant === \"icon\";\n const classes = buttonClassNames({ variant, size, fullWidth, loading, className });\n\n return (\n <button\n className={classes}\n disabled={disabled || loading}\n aria-busy={loading || undefined}\n {...props}\n >\n <span className=\"sh-button__content\">\n {loading && <span className=\"sh-button__spinner\" aria-hidden=\"true\" />}\n {isIconOnly ? (\n !loading && <span className=\"sh-button__icon\">{icon}</span>\n ) : (\n <>\n {icon && iconPosition === \"left\" && !loading && (\n <span className=\"sh-button__icon\">{icon}</span>\n )}\n {children}\n {icon && iconPosition === \"right\" && (\n <span className=\"sh-button__icon\">{icon}</span>\n )}\n </>\n )}\n </span>\n </button>\n );\n}\n","export const buttonVariants = ['primary', 'secondary', 'outline', 'ghost', 'icon'] as const;\n\nexport type ButtonVariant = (typeof buttonVariants)[number];\n\nexport const buttonSizes = ['sm', 'md', 'lg'] as const;\n\nexport type ButtonSize = (typeof buttonSizes)[number];\n","import { createElement } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\n\nimport { Button, buttonClassNames } from \"../Button\";\nimport type { ButtonVariant } from \"../Button\";\nimport \"./EmptyState.css\";\n\n/** Fallback mark: an open, empty tray. */\nconst EmptyIcon = () => (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.5} aria-hidden=\"true\">\n <path\n d=\"M3 13.5h4l1.5 2.5h7l1.5-2.5h4M3 13.5 5.8 6.2A1.5 1.5 0 0 1 7.2 5.2h9.6a1.5 1.5 0 0 1 1.4 1L21 13.5v3.3a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 3 16.8Z\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport type EmptyStateHeadingLevel = 2 | 3 | 4 | 5 | 6;\n\n/**\n * A call to action.\n *\n * `href` makes it a link and `onClick` makes it a button — the two are the\n * same offer to the user but very different elements, and picking the wrong\n * one costs middle-click, right-click and keyboard behaviour.\n */\nexport type EmptyStateAction = {\n label: ReactNode;\n /** Renders an `<a>`. Without it the action is a `<button>`. */\n href?: string;\n onClick?: () => void;\n /** Icon rendered before the label. */\n icon?: ReactNode;\n /** Overrides the default styling — `primary` for the main action. */\n variant?: ButtonVariant;\n target?: string;\n rel?: string;\n};\n\nexport type EmptyStateProps = {\n /** What isn't here. Rendered as a heading. */\n title: ReactNode;\n /** A line under the title, usually explaining what to do about it. */\n description?: ReactNode;\n /**\n * Replaces the default mark, or removes it entirely with `false`. Sized by\n * the component, so a bare `<svg>` is fine.\n */\n icon?: ReactNode | false;\n /** The main call to action. */\n action?: EmptyStateAction;\n /** A quieter second option beside it. */\n secondaryAction?: EmptyStateAction;\n /** Heading rank for the title. Defaults to `3`. */\n headingLevel?: EmptyStateHeadingLevel;\n /** `sm` for an empty state inside a card or panel. Defaults to `md`. */\n size?: \"sm\" | \"md\";\n /** Anything extra, rendered below the actions. */\n children?: ReactNode;\n className?: string;\n} & Omit<HTMLAttributes<HTMLDivElement>, \"className\" | \"title\" | \"children\">;\n\n/** Placeholder for a space with nothing in it yet, or nothing left in it. */\nexport function EmptyState({\n title,\n description,\n icon,\n action,\n secondaryAction,\n headingLevel = 3,\n size = \"md\",\n children,\n className,\n ...props\n}: EmptyStateProps) {\n /*\n * `undefined` means \"no opinion\", so the default mark stands in. Both\n * `false` and `null` mean \"no icon\" — the wrapper carries the gap below the\n * mark, so rendering it around nothing leaves a stray band of space.\n */\n const resolvedIcon = icon === undefined ? <EmptyIcon /> : icon;\n const hasIcon = resolvedIcon !== false && resolvedIcon !== null;\n\n const renderAction = (config: EmptyStateAction, variant: ButtonVariant) => {\n const { label, href, onClick, icon: actionIcon, variant: override, target, rel } = config;\n const resolvedVariant = override ?? variant;\n\n if (href === undefined) {\n return (\n <Button variant={resolvedVariant} size={size === \"sm\" ? \"sm\" : \"md\"} icon={actionIcon} onClick={onClick}>\n {label}\n </Button>\n );\n }\n\n /*\n * A link, wearing the button's own classes rather than a second copy of\n * its rules. `rel` defaults to noreferrer only for a new tab, where the\n * opened page would otherwise get a handle on this one.\n */\n return (\n <a\n href={href}\n target={target}\n rel={rel ?? (target === \"_blank\" ? \"noopener noreferrer\" : undefined)}\n onClick={onClick}\n className={buttonClassNames({\n variant: resolvedVariant,\n size: size === \"sm\" ? \"sm\" : \"md\",\n })}\n >\n <span className=\"sh-button__content\">\n {actionIcon && <span className=\"sh-button__icon\">{actionIcon}</span>}\n {label}\n </span>\n </a>\n );\n };\n\n return (\n <div\n className={[\"sh-empty-state\", `sh-empty-state--${size}`, className].filter(Boolean).join(\" \")}\n {...props}\n >\n {hasIcon && <span className=\"sh-empty-state__icon\">{resolvedIcon}</span>}\n\n {createElement(\n `h${headingLevel}`,\n { className: \"sh-empty-state__title\" },\n title,\n )}\n\n {description && <p className=\"sh-empty-state__description\">{description}</p>}\n\n {(action || secondaryAction) && (\n <div className=\"sh-empty-state__actions\">\n {action && renderAction(action, \"primary\")}\n {secondaryAction && renderAction(secondaryAction, \"secondary\")}\n </div>\n )}\n\n {children && <div className=\"sh-empty-state__extra\">{children}</div>}\n </div>\n );\n}\n","import type { HTMLAttributes, ReactNode } from \"react\";\n\nimport type { TagVariant } from \"./tag.tokens\";\nimport \"./Tag.css\";\n\nexport type TagProps = {\n /** Visual style of the tag. Defaults to `primary`. */\n variant?: TagVariant;\n children?: ReactNode;\n} & Omit<HTMLAttributes<HTMLSpanElement>, \"children\">;\n\n/** Compact label for statuses, categories, and metadata. */\nexport function Tag({ variant = \"primary\", className, children, ...props }: TagProps) {\n const classes = [\"sh-tag\", `sh-tag--${variant}`, className].filter(Boolean).join(\" \");\n\n return (\n <span className={classes} {...props}>\n {children}\n </span>\n );\n}\n","export const tagVariants = [\"primary\", \"secondary\", \"outline\"] as const;\n\nexport type TagVariant = (typeof tagVariants)[number];\n","import type { HTMLAttributes, ReactNode } from \"react\";\n\nimport type { ChipAction, ChipVariant } from \"./chip.tokens\";\nimport \"./Chip.css\";\n\nconst actionIcons: Record<ChipAction, ReactNode> = {\n add: (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.75} aria-hidden=\"true\">\n <path d=\"M8 3.5v9M3.5 8h9\" strokeLinecap=\"round\" />\n </svg>\n ),\n remove: (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.75} aria-hidden=\"true\">\n <path d=\"M4.5 4.5l7 7M11.5 4.5l-7 7\" strokeLinecap=\"round\" />\n </svg>\n ),\n};\n\nconst actionVerbs: Record<ChipAction, string> = {\n add: \"Add\",\n remove: \"Remove\",\n};\n\nexport type ChipProps = {\n /** Visual style of the chip. Defaults to `primary`. */\n variant?: ChipVariant;\n /** Trailing icon button to render. Omit for a chip with no action. */\n action?: ChipAction;\n /** Fired when the trailing icon button is activated. */\n onAction?: () => void;\n /**\n * Accessible name for the trailing button. Defaults to the action verb\n * plus the label when `children` is a string — e.g. \"Remove Vite\".\n */\n actionLabel?: string;\n /** Disables the trailing button and mutes the chip. */\n disabled?: boolean;\n children?: ReactNode;\n} & Omit<HTMLAttributes<HTMLSpanElement>, \"children\">;\n\n/** Compact, actionable label — a `Tag` with a trailing add or remove button. */\nexport function Chip({\n variant = \"primary\",\n action,\n onAction,\n actionLabel,\n disabled = false,\n className,\n children,\n ...props\n}: ChipProps) {\n const classes = [\n \"sh-chip\",\n `sh-chip--${variant}`,\n action && \"sh-chip--with-action\",\n disabled && \"sh-chip--disabled\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n // An icon-only button needs a name; fall back to the verb alone when the\n // label isn't plain text, since we can't read it out of an arbitrary node.\n const label =\n actionLabel ??\n (action\n ? typeof children === \"string\"\n ? `${actionVerbs[action]} ${children}`\n : actionVerbs[action]\n : undefined);\n\n return (\n <span className={classes} {...props}>\n <span className=\"sh-chip__label\">{children}</span>\n {action && (\n <button\n type=\"button\"\n className=\"sh-chip__action\"\n onClick={onAction}\n disabled={disabled}\n aria-label={label}\n >\n {actionIcons[action]}\n </button>\n )}\n </span>\n );\n}\n","export const chipVariants = [\"primary\", \"secondary\", \"outline\"] as const;\n\nexport type ChipVariant = (typeof chipVariants)[number];\n\nexport const chipActions = [\"add\", \"remove\"] as const;\n\nexport type ChipAction = (typeof chipActions)[number];\n","import { createContext } from \"react\";\n\nimport type { AvatarSize } from \"./avatar.tokens\";\n\n/**\n * Lets `AvatarGroup` set the size for every avatar it contains without\n * cloning children. An explicit `size` on an individual `Avatar` still wins.\n * Kept in its own module so the component files only export components\n * (see the react-refresh rule in eslint.config.js).\n */\nexport const AvatarSizeContext = createContext<AvatarSize | undefined>(undefined);\n","/**\n * \"Ada Lovelace\" -> \"AL\", \"Ada\" -> \"A\", \"Ada B. Lovelace\" -> \"AL\".\n * Returns \"\" for names with no word characters, so callers can fall\n * through to the placeholder icon.\n */\nexport function getInitials(name: string, max = 2): string {\n const words = name.trim().split(/\\s+/).filter(Boolean);\n\n if (words.length === 0) return \"\";\n\n const picked = words.length > max ? [words[0], words[words.length - 1]] : words;\n\n return picked\n .slice(0, max)\n .map((word) => word.charAt(0).toUpperCase())\n .join(\"\");\n}\n","import { useContext, useState } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\n\nimport { AvatarSizeContext } from \"./avatar.context\";\nimport type { AvatarSize } from \"./avatar.tokens\";\nimport { getInitials } from \"./getInitials\";\nimport \"./Avatar.css\";\n\nconst PlaceholderIcon = () => (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" className=\"sh-avatar__icon\">\n <path d=\"M12 12a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Zm0 1.8c-3.6 0-7.2 1.8-7.2 4.05V21h14.4v-3.15c0-2.25-3.6-4.05-7.2-4.05Z\" />\n </svg>\n);\n\nexport type AvatarProps = {\n /** Image URL. Falls back to initials (then an icon) if it fails to load. */\n src?: string;\n /** Person's name — used for the accessible label and to derive initials. */\n name?: string;\n /** Overrides the image alt text. Defaults to `name`. */\n alt?: string;\n /** Size of the avatar. Defaults to `md`, or the size set by `AvatarGroup`. */\n size?: AvatarSize;\n /** Custom fallback, rendered instead of initials when there's no image. */\n children?: ReactNode;\n} & Omit<HTMLAttributes<HTMLSpanElement>, \"children\">;\n\n/** User avatar with an image → initials → icon fallback chain. */\nexport function Avatar({ src, name, alt, size, className, children, ...props }: AvatarProps) {\n // Track *which* src failed rather than a boolean, so swapping in a new\n // `src` automatically retries instead of staying stuck on the fallback.\n const [failedSrc, setFailedSrc] = useState<string | undefined>(undefined);\n\n const groupSize = useContext(AvatarSizeContext);\n const resolvedSize = size ?? groupSize ?? \"md\";\n\n const showImage = Boolean(src) && failedSrc !== src;\n const initials = name ? getInitials(name) : \"\";\n const label = alt ?? name;\n\n const classes = [\"sh-avatar\", `sh-avatar--${resolvedSize}`, className].filter(Boolean).join(\" \");\n\n // When showing an image the <img alt> carries the name, so the wrapper\n // stays a plain span. For the fallback the wrapper has to carry it.\n const labelProps =\n !showImage && label ? ({ role: \"img\", \"aria-label\": label } as const) : undefined;\n\n return (\n <span className={classes} {...labelProps} {...props}>\n {showImage ? (\n <img\n className=\"sh-avatar__image\"\n src={src}\n alt={label ?? \"\"}\n onError={() => setFailedSrc(src)}\n />\n ) : (\n (children ?? (\n <span className=\"sh-avatar__fallback\" aria-hidden=\"true\">\n {initials || <PlaceholderIcon />}\n </span>\n ))\n )}\n </span>\n );\n}\n","import { Children, isValidElement } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\n\nimport { AvatarSizeContext } from \"./avatar.context\";\nimport type { AvatarSize } from \"./avatar.tokens\";\nimport \"./Avatar.css\";\n\nexport type AvatarGroupProps = {\n /** Maximum avatars to show before collapsing the rest into a \"+N\" counter. */\n max?: number;\n /** Size applied to every avatar in the group. Individual `size` props win. */\n size?: AvatarSize;\n children?: ReactNode;\n} & Omit<HTMLAttributes<HTMLDivElement>, \"children\">;\n\n/** Overlapping stack of `Avatar`s, with optional overflow counter. */\nexport function AvatarGroup({\n max,\n size = \"md\",\n className,\n children,\n ...props\n}: AvatarGroupProps) {\n const items = Children.toArray(children).filter(isValidElement);\n const limit = typeof max === \"number\" && max >= 0 ? max : items.length;\n const visible = items.slice(0, limit);\n const overflow = items.length - visible.length;\n\n const classes = [\"sh-avatar-group\", className].filter(Boolean).join(\" \");\n\n return (\n <AvatarSizeContext.Provider value={size}>\n <div className={classes} {...props}>\n {visible}\n {overflow > 0 && (\n <span\n className={`sh-avatar sh-avatar--${size} sh-avatar--overflow`}\n role=\"img\"\n aria-label={`${overflow} more`}\n >\n <span className=\"sh-avatar__fallback\" aria-hidden=\"true\">\n +{overflow}\n </span>\n </span>\n )}\n </div>\n </AvatarSizeContext.Provider>\n );\n}\n","export const avatarSizes = [\"sm\", \"md\", \"lg\"] as const;\n\nexport type AvatarSize = (typeof avatarSizes)[number];\n","import { useId } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\n\nimport \"./Input.css\";\n\nexport type InputProps = {\n /** Visible label, associated with the input via `htmlFor`/`id`. */\n label?: ReactNode;\n /** Hint shown below the input. Replaced by `error` when that's set. */\n helperText?: ReactNode;\n /** Validation message. Its presence also marks the input invalid. */\n error?: ReactNode;\n /** Decorative icon rendered inside the field. See `iconPosition`. */\n icon?: ReactNode;\n /** Which side `icon` sits on. Defaults to `left`. */\n iconPosition?: \"left\" | \"right\";\n /** Class for the wrapper element. Use `inputClassName` for the input itself. */\n className?: string;\n /** Class for the underlying `<input>`. */\n inputClassName?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, \"className\">;\n\n/** Text input with an associated label, helper text, error state, and optional icon. */\nexport function Input({\n label,\n helperText,\n error,\n icon,\n iconPosition = \"left\",\n className,\n inputClassName,\n id,\n required,\n disabled,\n \"aria-describedby\": ariaDescribedBy,\n ...props\n}: InputProps) {\n // Only used when the consumer doesn't supply an id — the label needs a\n // stable target either way.\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const messageId = `${inputId}-message`;\n\n const invalid = Boolean(error);\n const message = error ?? helperText;\n\n // Keep any describedby the consumer passed; don't clobber it.\n const describedBy =\n [ariaDescribedBy, message ? messageId : undefined].filter(Boolean).join(\" \") || undefined;\n\n const classes = [\n \"sh-input\",\n invalid && \"sh-input--invalid\",\n disabled && \"sh-input--disabled\",\n icon && `sh-input--with-icon-${iconPosition}`,\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div className={classes}>\n {label && (\n <label className=\"sh-input__label\" htmlFor={inputId}>\n {label}\n {required && (\n <span className=\"sh-input__required\" aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )}\n\n <span className=\"sh-input__field\">\n {icon && (\n <span className=\"sh-input__icon\" aria-hidden=\"true\">\n {icon}\n </span>\n )}\n <input\n id={inputId}\n className={[\"sh-input__control\", inputClassName].filter(Boolean).join(\" \")}\n required={required}\n disabled={disabled}\n aria-invalid={invalid || undefined}\n aria-describedby={describedBy}\n {...props}\n />\n </span>\n\n {message && (\n <span id={messageId} className=\"sh-input__message\">\n {message}\n </span>\n )}\n </div>\n );\n}\n","export const otpTypes = [\"numeric\", \"alphanumeric\"] as const;\n\nexport type OtpType = (typeof otpTypes)[number];\n\nconst ALLOWED: Record<OtpType, RegExp> = {\n numeric: /[0-9]/,\n alphanumeric: /[a-zA-Z0-9]/,\n};\n\nexport type SanitizeOtpValueOptions = {\n /** Number of characters the code holds. */\n length: number;\n /** Which characters survive. Defaults to `numeric`. */\n type?: OtpType;\n};\n\n/**\n * Keeps only the characters an OTP field accepts, capped at its length.\n *\n * Runs over everything that reaches the field — typing, pasting, and the\n * controlled `value` — so a pasted \"123-456\", a code copied with trailing\n * whitespace, and a stray letter all land as the same clean string.\n *\n * Case is preserved for `alphanumeric`: upper-casing here would quietly\n * change what the user submits, and whether a code is case-sensitive is the\n * server's business, not this component's.\n */\nexport function sanitizeOtpValue(\n raw: string,\n { length, type = \"numeric\" }: SanitizeOtpValueOptions,\n): string {\n // No guard for a length of zero or less: the cap below already stops before\n // the first character, so an explicit check would never change the result.\n const allowed = ALLOWED[type];\n let result = \"\";\n\n // Iterating the string yields whole code points, so an emoji pasted in\n // can't be split into halves that individually pass the test.\n for (const character of raw) {\n if (result.length >= length) break;\n if (allowed.test(character)) result += character;\n }\n\n return result;\n}\n","import { Fragment, useId, useRef, useState } from \"react\";\nimport type { InputHTMLAttributes, ReactNode } from \"react\";\n\nimport { sanitizeOtpValue } from \"./sanitizeOtpValue\";\nimport type { OtpType } from \"./sanitizeOtpValue\";\nimport \"./InputOtp.css\";\n\nexport type InputOtpProps = {\n /** Number of characters in the code. Defaults to 6. */\n length?: number;\n /** The code — makes the component controlled. */\n value?: string;\n /** Starting code when uncontrolled. */\n defaultValue?: string;\n /** Fired with the whole code whenever it changes. */\n onChange?: (value: string) => void;\n /** Fired once, when the last character lands. */\n onComplete?: (value: string) => void;\n /** Which characters are accepted. Defaults to `numeric`. */\n type?: OtpType;\n /** Hides the characters behind dots, for codes that are secrets. */\n mask?: boolean;\n /** Draws a separator every N characters — 3 gives `123 456`. */\n groupSize?: number;\n /** Visible label, associated with the field via `htmlFor`/`id`. */\n label?: ReactNode;\n /** Hint shown below the field. Replaced by `error` when that's set. */\n helperText?: ReactNode;\n /** Validation message. Its presence also marks the field invalid. */\n error?: ReactNode;\n /** Class for the wrapper element. */\n className?: string;\n} & Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"className\" | \"value\" | \"defaultValue\" | \"onChange\" | \"type\" | \"maxLength\" | \"size\"\n>;\n\n/**\n * One-time-code field: a row of boxes backed by a single text input.\n *\n * The boxes are presentation. The value lives in one real `<input>` covering\n * them, which is what makes `autocomplete=\"one-time-code\"`, pasting, undo,\n * password managers and screen-reader labelling work without being rebuilt —\n * a row of six separate inputs is six unlabelled fields to assistive tech, and\n * reimplements a text field along the way.\n */\nexport function InputOtp({\n length = 6,\n value: controlledValue,\n defaultValue = \"\",\n onChange,\n onComplete,\n type = \"numeric\",\n mask = false,\n groupSize,\n label,\n helperText,\n error,\n className,\n id,\n required,\n disabled,\n \"aria-describedby\": ariaDescribedBy,\n onFocus,\n onBlur,\n onSelect,\n onClick,\n ...props\n}: InputOtpProps) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const messageId = `${inputId}-message`;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const [focused, setFocused] = useState(false);\n const [caret, setCaret] = useState(0);\n\n const [uncontrolledValue, setUncontrolledValue] = useState(() =>\n sanitizeOtpValue(defaultValue, { length, type }),\n );\n const isControlled = controlledValue !== undefined;\n // Sanitised on the way in as well as out, so a controlled parent handing\n // back \"12-34\" can't put characters in the boxes that typing couldn't.\n const value = isControlled\n ? sanitizeOtpValue(controlledValue, { length, type })\n : uncontrolledValue;\n\n const invalid = Boolean(error);\n const message = error ?? helperText;\n const describedBy =\n [ariaDescribedBy, message ? messageId : undefined].filter(Boolean).join(\" \") || undefined;\n\n /*\n * The input is invisible, so a click maps to an arbitrary offset in text\n * nobody can see. Collapsing to the end makes it predictable: focus the\n * field and the next character goes in the next empty box. Arrow keys still\n * move deliberately.\n */\n const moveCaretToEnd = () => {\n const input = inputRef.current;\n if (!input) return;\n\n const end = input.value.length;\n input.setSelectionRange(end, end);\n setCaret(end);\n };\n\n const characters = Array.from({ length }, (_, index) => value[index] ?? \"\");\n const activeIndex = focused && !disabled ? Math.min(caret, length - 1) : -1;\n\n return (\n <div\n className={[\n \"sh-input-otp\",\n invalid && \"sh-input-otp--invalid\",\n disabled && \"sh-input-otp--disabled\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {label && (\n <label className=\"sh-input-otp__label\" htmlFor={inputId}>\n {label}\n {required && (\n <span className=\"sh-input-otp__required\" aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )}\n\n <div className=\"sh-input-otp__field\">\n <input\n ref={inputRef}\n id={inputId}\n className=\"sh-input-otp__control\"\n value={value}\n /*\n * Deliberately no `maxLength`. The browser truncates a paste to fit\n * it *before* any handler runs, so \"123-456\" would arrive as\n * \"123-45\" and clean up to five digits. The length cap lives in\n * sanitizeOtpValue, which counts only the characters it keeps.\n */\n required={required}\n disabled={disabled}\n /* Numeric codes get the number pad; letters need the full keyboard. */\n inputMode={type === \"numeric\" ? \"numeric\" : \"text\"}\n autoComplete=\"one-time-code\"\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n spellCheck={false}\n aria-invalid={invalid || undefined}\n aria-describedby={describedBy}\n onChange={(event) => {\n const next = sanitizeOtpValue(event.target.value, { length, type });\n // A rejected character leaves the value untouched; React puts the\n // input's DOM value back on its own.\n if (next === value) return;\n\n if (!isControlled) setUncontrolledValue(next);\n onChange?.(next);\n\n /*\n * Every time the code becomes full, including when a complete one\n * is replaced by another — pasting a corrected code over the top\n * should still submit. Typing into a full code can't reach here at\n * all, because the value doesn't change.\n */\n if (next.length === length) onComplete?.(next);\n }}\n onFocus={(event) => {\n onFocus?.(event);\n setFocused(true);\n moveCaretToEnd();\n }}\n onBlur={(event) => {\n onBlur?.(event);\n setFocused(false);\n }}\n onClick={(event) => {\n onClick?.(event);\n moveCaretToEnd();\n }}\n onSelect={(event) => {\n onSelect?.(event);\n setCaret(event.currentTarget.selectionStart ?? value.length);\n }}\n {...props}\n />\n\n {/* Presentation only — the input above carries the value and the name. */}\n <div className=\"sh-input-otp__boxes\" aria-hidden=\"true\">\n {characters.map((character, index) => (\n <Fragment key={index}>\n {groupSize !== undefined && index > 0 && index % groupSize === 0 && (\n <span className=\"sh-input-otp__separator\" />\n )}\n\n <span\n className={[\n \"sh-input-otp__slot\",\n character && \"sh-input-otp__slot--filled\",\n index === activeIndex && \"sh-input-otp__slot--active\",\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {character && mask ? \"•\" : character}\n </span>\n </Fragment>\n ))}\n </div>\n </div>\n\n {message && (\n <span id={messageId} className=\"sh-input-otp__message\">\n {message}\n </span>\n )}\n </div>\n );\n}\n","import { createContext, useContext } from \"react\";\nimport type { RefObject } from \"react\";\n\n/** Where focus should land when the menu opens, or null to leave it alone. */\nexport type DropdownFocusTarget = \"first\" | \"last\" | null;\n\nexport type DropdownPlacement = \"bottom\" | \"top\";\nexport type DropdownAlign = \"start\" | \"end\";\n\nexport type DropdownContextValue = {\n isOpen: boolean;\n /** Opens the menu, optionally moving focus to an end of the list. */\n open: (focus?: DropdownFocusTarget) => void;\n /** Closes the menu. Returns focus to the trigger unless told not to. */\n close: (options?: { restoreFocus?: boolean }) => void;\n /** Set while the menu is opening, consumed once by the menu on mount. */\n focusOnOpen: DropdownFocusTarget;\n triggerId: string;\n menuId: string;\n triggerRef: RefObject<HTMLButtonElement | null>;\n placement: DropdownPlacement;\n align: DropdownAlign;\n};\n\nexport const DropdownContext = createContext<DropdownContextValue | undefined>(undefined);\n\n/** Reads the surrounding `Dropdown`, failing loudly rather than silently. */\nexport function useDropdownContext(component: string): DropdownContextValue {\n const context = useContext(DropdownContext);\n\n if (!context) {\n throw new Error(`<${component}> must be rendered inside <Dropdown>.`);\n }\n\n return context;\n}\n","import { useCallback, useEffect, useId, useRef, useState } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\n\nimport { DropdownContext } from \"./dropdown.context\";\nimport type { DropdownAlign, DropdownFocusTarget, DropdownPlacement } from \"./dropdown.context\";\nimport \"./Dropdown.css\";\n\nexport type DropdownProps = {\n children?: ReactNode;\n /** Open state — makes the component controlled. */\n open?: boolean;\n /** Initial open state when uncontrolled. Defaults to closed. */\n defaultOpen?: boolean;\n /** Fired whenever the menu opens or closes. */\n onOpenChange?: (open: boolean) => void;\n /** Which side of the trigger the menu sits on. Defaults to `bottom`. */\n placement?: DropdownPlacement;\n /** Which edge the menu lines up with. Defaults to `start`. */\n align?: DropdownAlign;\n className?: string;\n} & Omit<HTMLAttributes<HTMLDivElement>, \"className\">;\n\n/**\n * Root of a menu-button dropdown: a trigger and a popup of commands.\n *\n * This is the *action* menu pattern (`role=\"menu\"`), not a value picker —\n * use `Select` for choosing a value. Nothing here is a form control.\n */\nexport function Dropdown({\n children,\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n placement = \"bottom\",\n align = \"start\",\n className,\n ...props\n}: DropdownProps) {\n const baseId = useId();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const rootRef = useRef<HTMLDivElement>(null);\n\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : uncontrolledOpen;\n\n const [focusOnOpen, setFocusOnOpen] = useState<DropdownFocusTarget>(null);\n\n const open = useCallback(\n (focus: DropdownFocusTarget = null) => {\n setFocusOnOpen(focus);\n if (!isControlled) setUncontrolledOpen(true);\n onOpenChange?.(true);\n },\n [isControlled, onOpenChange],\n );\n\n const close = useCallback(\n ({ restoreFocus = true }: { restoreFocus?: boolean } = {}) => {\n setFocusOnOpen(null);\n if (!isControlled) setUncontrolledOpen(false);\n onOpenChange?.(false);\n // Focus would otherwise fall to the body when the menu unmounts.\n if (restoreFocus) triggerRef.current?.focus();\n },\n [isControlled, onOpenChange],\n );\n\n /*\n * Dismiss on an outside press. Bound to pointerdown rather than click so the\n * menu closes on press, matching platform menus, and so a press that starts\n * outside can't land on an item that moved under the cursor.\n */\n useEffect(() => {\n if (!isOpen) return;\n\n const handlePointerDown = (event: PointerEvent) => {\n if (!rootRef.current?.contains(event.target as Node)) {\n // Focus is already leaving; yanking it back to the trigger would\n // fight whatever the user just pressed.\n close({ restoreFocus: false });\n }\n };\n\n document.addEventListener(\"pointerdown\", handlePointerDown);\n return () => document.removeEventListener(\"pointerdown\", handlePointerDown);\n }, [isOpen, close]);\n\n /*\n * Escape is handled at the document rather than on the menu, because focus\n * isn't always inside it: a controlled parent can open the menu without\n * moving focus, and a menu that ignores Escape in that state is a trap.\n */\n useEffect(() => {\n if (!isOpen) return;\n\n const handleKeyDown = (event: globalThis.KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n event.preventDefault();\n close();\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, close]);\n\n return (\n <DropdownContext.Provider\n value={{\n isOpen,\n open,\n close,\n focusOnOpen,\n triggerId: `${baseId}-trigger`,\n menuId: `${baseId}-menu`,\n triggerRef,\n placement,\n align,\n }}\n >\n <div\n ref={rootRef}\n className={[\"sh-dropdown\", className].filter(Boolean).join(\" \")}\n {...props}\n >\n {children}\n </div>\n </DropdownContext.Provider>\n );\n}\n","import type { ButtonHTMLAttributes, KeyboardEvent, ReactNode } from \"react\";\n\nimport { useDropdownContext } from \"./dropdown.context\";\nimport \"./Dropdown.css\";\n\nexport type DropdownTriggerProps = {\n children?: ReactNode;\n className?: string;\n} & Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"className\">;\n\n/** Button that opens the menu. */\nexport function DropdownTrigger({\n children,\n className,\n onClick,\n onKeyDown,\n ...props\n}: DropdownTriggerProps) {\n const { isOpen, open, close, triggerId, menuId, triggerRef } =\n useDropdownContext(\"DropdownTrigger\");\n\n const handleKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented || isOpen) return;\n\n /*\n * Down opens at the top of the list, Up at the bottom — the standard\n * shortcut for reaching the last command without walking the whole menu.\n */\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n open(\"first\");\n } else if (event.key === \"ArrowUp\") {\n event.preventDefault();\n open(\"last\");\n }\n };\n\n return (\n <button\n ref={triggerRef}\n type=\"button\"\n id={triggerId}\n className={[\"sh-dropdown__trigger\", className].filter(Boolean).join(\" \")}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n // Only points at the menu while it exists in the DOM.\n aria-controls={isOpen ? menuId : undefined}\n onClick={(event) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n // Closing from the trigger shouldn't re-focus what's already focused.\n if (isOpen) close({ restoreFocus: false });\n else open(\"first\");\n }}\n onKeyDown={handleKeyDown}\n {...props}\n >\n {children}\n </button>\n );\n}\n","import { useEffect, useRef } from \"react\";\nimport type { HTMLAttributes, KeyboardEvent, ReactNode } from \"react\";\n\nimport { useDropdownContext } from \"./dropdown.context\";\nimport \"./Dropdown.css\";\n\nexport type DropdownMenuProps = {\n children?: ReactNode;\n className?: string;\n} & Omit<HTMLAttributes<HTMLDivElement>, \"className\">;\n\n/**\n * The popup list of commands.\n *\n * Unmounted while closed rather than hidden, so there's nothing focusable or\n * announceable left behind, and owns the roving focus the menu pattern needs.\n */\nexport function DropdownMenu({ children, className, onKeyDown, ...props }: DropdownMenuProps) {\n const { isOpen, close, focusOnOpen, triggerId, menuId, placement, align } =\n useDropdownContext(\"DropdownMenu\");\n const menuRef = useRef<HTMLDivElement>(null);\n\n /** Enabled items, in DOM order — disabled ones aren't reachable. */\n const getItems = () =>\n Array.from(\n menuRef.current?.querySelectorAll<HTMLButtonElement>(\n '[role=\"menuitem\"]:not([disabled])',\n ) ?? [],\n );\n\n // Move focus into the menu when it was opened by keyboard.\n useEffect(() => {\n if (!isOpen || !focusOnOpen) return;\n\n const items = getItems();\n const target = focusOnOpen === \"last\" ? items[items.length - 1] : items[0];\n target?.focus();\n }, [isOpen, focusOnOpen]);\n\n if (!isOpen) return null;\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented) return;\n\n // Escape is handled by Dropdown at the document level — see the note there.\n\n // Tab moves on rather than being trapped; the menu just gets out of the way.\n if (event.key === \"Tab\") {\n close({ restoreFocus: false });\n return;\n }\n\n const keys = [\"ArrowDown\", \"ArrowUp\", \"Home\", \"End\"];\n if (!keys.includes(event.key)) return;\n\n const items = getItems();\n if (items.length === 0) return;\n\n const current = items.indexOf(document.activeElement as HTMLButtonElement);\n\n let index: number;\n if (event.key === \"Home\") index = 0;\n else if (event.key === \"End\") index = items.length - 1;\n else if (current === -1) index = 0;\n // Wrap at both ends, as the menu pattern specifies.\n else if (event.key === \"ArrowDown\") index = (current + 1) % items.length;\n else index = (current - 1 + items.length) % items.length;\n\n // Stop the arrows scrolling the page behind the menu.\n event.preventDefault();\n items[index]?.focus();\n };\n\n return (\n <div\n ref={menuRef}\n id={menuId}\n className={[\n \"sh-dropdown__menu\",\n `sh-dropdown__menu--${placement}`,\n `sh-dropdown__menu--${align}`,\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n role=\"menu\"\n aria-labelledby={triggerId}\n onKeyDown={handleKeyDown}\n {...props}\n >\n {children}\n </div>\n );\n}\n","import type { ButtonHTMLAttributes, ReactNode } from \"react\";\n\nimport { useDropdownContext } from \"./dropdown.context\";\nimport \"./Dropdown.css\";\n\nexport type DropdownItemProps = {\n children?: ReactNode;\n /** Runs when the item is chosen. The menu closes afterwards. */\n onSelect?: () => void;\n /** Keeps the menu open after choosing — for items that toggle something. */\n closeOnSelect?: boolean;\n /** Icon rendered before the label. */\n icon?: ReactNode;\n /** Styles the item as a destructive action. */\n destructive?: boolean;\n className?: string;\n} & Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"className\" | \"onSelect\">;\n\n/** A single command in the menu. */\nexport function DropdownItem({\n children,\n onSelect,\n closeOnSelect = true,\n icon,\n destructive = false,\n className,\n onClick,\n ...props\n}: DropdownItemProps) {\n const { close } = useDropdownContext(\"DropdownItem\");\n\n return (\n <button\n type=\"button\"\n role=\"menuitem\"\n className={[\n \"sh-dropdown__item\",\n destructive && \"sh-dropdown__item--destructive\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n /*\n * Focus is moved here by the menu's arrow keys, so items must be\n * focusable programmatically but not stops in the page's tab order.\n */\n tabIndex={-1}\n onClick={(event) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n onSelect?.();\n if (closeOnSelect) close();\n }}\n {...props}\n >\n {icon && (\n <span className=\"sh-dropdown__item-icon\" aria-hidden=\"true\">\n {icon}\n </span>\n )}\n <span className=\"sh-dropdown__item-label\">{children}</span>\n </button>\n );\n}\n","import type { HTMLAttributes } from \"react\";\n\nimport \"./Dropdown.css\";\n\nexport type DropdownSeparatorProps = {\n className?: string;\n} & Omit<HTMLAttributes<HTMLDivElement>, \"className\">;\n\n/**\n * Divider between groups of commands. Carries `role=\"separator\"` rather than\n * `aria-hidden`, so the grouping is conveyed to assistive tech too.\n */\nexport function DropdownSeparator({ className, ...props }: DropdownSeparatorProps) {\n return (\n <div\n className={[\"sh-dropdown__separator\", className].filter(Boolean).join(\" \")}\n role=\"separator\"\n {...props}\n />\n );\n}\n","/**\n * Removes the indentation a template literal picks up from the code around it.\n *\n * Blank first and last lines go first — a template literal almost always opens\n * with the newline after the backtick and closes with the indentation before\n * it — then the smallest indent shared by every remaining non-blank line is\n * stripped from all of them. Relative indentation inside the block survives.\n *\n * Indentation is counted in characters, so a block mixing tabs and spaces at\n * the same depth won't line up. Pick one.\n */\nexport function dedentCode(source: string): string {\n const lines = source.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n\n while (lines.length > 0 && lines[0].trim() === \"\") lines.shift();\n while (lines.length > 0 && lines[lines.length - 1].trim() === \"\") lines.pop();\n if (lines.length === 0) return \"\";\n\n // Blank lines are skipped: a stray empty line would drag the shared indent\n // to zero and dedent nothing.\n const indents = lines\n .filter((line) => line.trim() !== \"\")\n .map((line) => line.length - line.trimStart().length);\n\n const shared = Math.min(...indents);\n\n return lines.map((line) => line.slice(shared)).join(\"\\n\");\n}\n","import { useEffect, useId, useRef, useState } from \"react\";\nimport type { HTMLAttributes } from \"react\";\n\nimport { dedentCode } from \"./dedentCode\";\nimport \"./CodeBlock.css\";\n\nconst CopyIcon = () => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.5} aria-hidden=\"true\">\n <rect x=\"5.75\" y=\"5.75\" width=\"8\" height=\"8\" rx=\"1.5\" />\n <path d=\"M10.5 3.5A1.5 1.5 0 0 0 9 2H3.5A1.5 1.5 0 0 0 2 3.5V9a1.5 1.5 0 0 0 1.5 1.5\" />\n </svg>\n);\n\nconst CheckIcon = () => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.75} aria-hidden=\"true\">\n <path d=\"M3.5 8.5l3 3 6-6.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n);\n\ntype CopyState = \"idle\" | \"copied\" | \"error\";\n\n/** How long the copied/failed state stays up before reverting. */\nconst FEEDBACK_MS = 2000;\n\nexport type CodeBlockProps = {\n /**\n * The code.\n *\n * A string rather than nodes, because it has to be copied to the clipboard\n * and counted into lines — neither of which is possible with arbitrary\n * children. Shared indentation is stripped, so a template literal can be\n * indented to match the code around it.\n */\n children: string;\n /** Shown on the left of the header. */\n filename?: string;\n /**\n * Puts `language-<value>` on the `<code>`, which is the hook Prism, Shiki\n * and highlight.js look for. Nothing here highlights anything — see the\n * component docs. Also labels the header when there's no filename.\n */\n language?: string;\n /** Numbers down the left of the code. Defaults to false. */\n showLineNumbers?: boolean;\n /** Soft-wraps long lines instead of scrolling sideways. Defaults to false. */\n wrap?: boolean;\n /** Whether to render the copy button. Defaults to true. */\n copyable?: boolean;\n /** Accessible name for the copy button. Defaults to \"Copy code\". */\n copyLabel?: string;\n /** Caps the height of the code area, which scrolls past it. */\n maxHeight?: number | string;\n className?: string;\n} & Omit<HTMLAttributes<HTMLDivElement>, \"className\" | \"children\">;\n\n/**\n * Code with a filename and a copy button.\n *\n * **It does not highlight anything.** A syntax highlighter is a large\n * dependency with opinions about themes and grammars, and this library ships\n * none. `language` puts the conventional `language-*` class on the `<code>`\n * so whichever highlighter the consumer already has can pick the block up.\n */\nexport function CodeBlock({\n children,\n filename,\n language,\n showLineNumbers = false,\n wrap = false,\n copyable = true,\n copyLabel = \"Copy code\",\n maxHeight,\n className,\n ...props\n}: CodeBlockProps) {\n const code = dedentCode(children);\n const labelId = useId();\n\n const [copyState, setCopyState] = useState<CopyState>(\"idle\");\n const timerRef = useRef<number | undefined>(undefined);\n\n // A pending timer would otherwise fire into an unmounted component.\n useEffect(() => () => window.clearTimeout(timerRef.current), []);\n\n const handleCopy = async () => {\n window.clearTimeout(timerRef.current);\n\n try {\n // Absent outside a secure context, where the property access itself\n // throws — hence the try rather than a feature check.\n await navigator.clipboard.writeText(code);\n setCopyState(\"copied\");\n } catch {\n setCopyState(\"error\");\n }\n\n timerRef.current = window.setTimeout(() => setCopyState(\"idle\"), FEEDBACK_MS);\n };\n\n const headerLabel = filename ?? language;\n const showHeader = headerLabel !== undefined || copyable;\n\n return (\n <div\n className={[\n \"sh-code-block\",\n wrap && \"sh-code-block--wrap\",\n showLineNumbers && \"sh-code-block--numbered\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n {...props}\n >\n {showHeader && (\n <div className=\"sh-code-block__header\">\n {headerLabel !== undefined && (\n <span id={labelId} className=\"sh-code-block__filename\">\n {headerLabel}\n </span>\n )}\n\n {copyable && (\n /*\n * margin-left: auto in the CSS rather than space-between, so the\n * button stays hard right whether or not there's a filename.\n */\n <button\n type=\"button\"\n className=\"sh-code-block__copy\"\n aria-label={copyLabel}\n onClick={handleCopy}\n >\n {copyState === \"copied\" ? <CheckIcon /> : <CopyIcon />}\n </button>\n )}\n </div>\n )}\n\n {/*\n Focusable so the code can be scrolled without a pointer. `group` rather\n than `region` because a page of code blocks shouldn't be a page of\n landmarks.\n */}\n <pre\n className=\"sh-code-block__pre\"\n tabIndex={0}\n role={headerLabel !== undefined ? \"group\" : undefined}\n aria-labelledby={headerLabel !== undefined ? labelId : undefined}\n style={maxHeight === undefined ? undefined : { maxHeight }}\n >\n <code className={[\"sh-code-block__code\", language && `language-${language}`].filter(Boolean).join(\" \")}>\n {/*\n Split into per-line elements only when numbering, so the plain case\n leaves a clean text node for a highlighter to work on. The numbers\n come from a CSS counter, which keeps them out of the clipboard and\n puts them in the right place when a line wraps.\n */}\n {showLineNumbers\n ? code\n .split(\"\\n\")\n // The index is the right key here: a line has no identity\n // beyond its position, and the whole list is re-derived\n // whenever the code changes.\n .map((line, index, all) => (\n <span key={index} className=\"sh-code-block__line\">\n {line}\n {index < all.length - 1 ? \"\\n\" : \"\"}\n </span>\n ))\n : code}\n </code>\n </pre>\n\n {copyable && (\n <span role=\"status\" aria-live=\"polite\" className=\"sh-code-block__status\">\n {copyState === \"copied\" ? \"Copied\" : copyState === \"error\" ? \"Copy failed\" : \"\"}\n </span>\n )}\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\n\n/**\n * Renders `content` elsewhere in the DOM. `true` means `document.body`.\n *\n * Not part of the public API.\n */\nexport function portalInto(content: ReactNode, portal: boolean | HTMLElement): ReactNode {\n if (!portal) return content;\n\n /*\n * `document` is absent when server rendering, where a portal contributes no\n * markup anyway — so returning nothing here matches what the client will\n * produce and can't cause a hydration mismatch.\n */\n const target =\n portal === true ? (typeof document === \"undefined\" ? null : document.body) : portal;\n\n return target ? createPortal(content, target) : null;\n}\n","/*\n * A modal <dialog> takes over the top layer but does nothing about the page\n * behind it, which happily keeps scrolling under the backdrop.\n *\n * Locking is counted rather than a boolean: with dialogs stacked, closing the\n * inner one must not hand scrolling back to the page while the outer one is\n * still up.\n */\nlet lockCount = 0;\nlet restore: (() => void) | null = null;\n\n/** Freezes page scrolling. Returns the release, which is safe to call twice. */\nexport function lockBodyScroll(): () => void {\n if (lockCount === 0) {\n const { body } = document;\n const previousOverflow = body.style.overflow;\n const previousPaddingRight = body.style.paddingRight;\n\n /*\n * Hiding the scrollbar frees up its width and everything on the page\n * shifts sideways. Pad by the same amount to hold it still.\n */\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;\n\n body.style.overflow = \"hidden\";\n if (scrollbarWidth > 0) {\n const current = Number.parseFloat(window.getComputedStyle(body).paddingRight) || 0;\n body.style.paddingRight = `${current + scrollbarWidth}px`;\n }\n\n restore = () => {\n body.style.overflow = previousOverflow;\n body.style.paddingRight = previousPaddingRight;\n };\n }\n\n lockCount += 1;\n let released = false;\n\n return () => {\n // A second release would drop the count below the dialogs still open.\n if (released) return;\n released = true;\n\n lockCount -= 1;\n if (lockCount === 0) {\n restore?.();\n restore = null;\n }\n };\n}\n","import { useEffect, useId, useRef } from \"react\";\nimport type { MouseEventHandler, RefObject } from \"react\";\n\nimport { lockBodyScroll } from \"./bodyScrollLock\";\n\n/**\n * Shared behaviour for anything built on a modal `<dialog>` — `Dialog` and\n * `Drawer` differ only in geometry, and a bug fixed in one has to be a bug\n * fixed in both.\n *\n * Not part of the public API.\n */\nexport type ModalSurfaceOptions = {\n open: boolean;\n onClose: () => void;\n closeOnEscape: boolean;\n closeOnBackdropClick: boolean;\n initialFocus?: RefObject<HTMLElement | null>;\n lockScroll: boolean;\n};\n\nexport type ModalSurface = {\n titleId: string;\n descriptionId: string;\n /** Spread onto the `<dialog>` element. */\n surfaceProps: {\n ref: RefObject<HTMLDialogElement | null>;\n onMouseDown: MouseEventHandler<HTMLDialogElement>;\n onClick: MouseEventHandler<HTMLDialogElement>;\n };\n};\n\nexport function useModalSurface({\n open,\n onClose,\n closeOnEscape,\n closeOnBackdropClick,\n initialFocus,\n lockScroll,\n}: ModalSurfaceOptions): ModalSurface {\n const dialogRef = useRef<HTMLDialogElement>(null);\n const mouseDownTargetRef = useRef<EventTarget | null>(null);\n\n const baseId = useId();\n\n /*\n * The `open` prop is the single source of truth, so the element is driven\n * imperatively. The `open` *attribute* is not an option: it produces a\n * non-modal dialog with no top layer, no backdrop and no focus trap.\n */\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n if (!open) {\n if (dialog.open) dialog.close();\n return;\n }\n\n if (!dialog.open) dialog.showModal();\n initialFocus?.current?.focus();\n\n return lockScroll ? lockBodyScroll() : undefined;\n // initialFocus is a ref container; re-running on identity changes would\n // re-steal focus mid-interaction.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, lockScroll]);\n\n /*\n * Escape reaches the element as `cancel`, and the browser closes on it\n * unless told otherwise. It's always refused here so that closing only ever\n * happens through the `open` prop — otherwise the element would already be\n * shut while React still thought it was open.\n */\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n const handleCancel = (event: Event) => {\n event.preventDefault();\n if (closeOnEscape) onClose();\n };\n\n dialog.addEventListener(\"cancel\", handleCancel);\n return () => dialog.removeEventListener(\"cancel\", handleCancel);\n }, [closeOnEscape, onClose]);\n\n return {\n titleId: `${baseId}-title`,\n descriptionId: `${baseId}-description`,\n surfaceProps: {\n ref: dialogRef,\n onMouseDown: (event) => {\n mouseDownTargetRef.current = event.target;\n },\n /*\n * Clicks on the backdrop are dispatched to the <dialog> itself, so a\n * target of the element rather than anything inside it means the\n * backdrop. This relies on the element carrying no padding of its own —\n * the panel sections supply it.\n */\n onClick: (event) => {\n if (!closeOnBackdropClick) return;\n\n // A drag that starts on a control and ends outside still fires a click\n // on the common ancestor. Selecting text in a field shouldn't close\n // anything.\n const startedOnBackdrop = mouseDownTargetRef.current === event.currentTarget;\n if (startedOnBackdrop && event.target === event.currentTarget) onClose();\n },\n },\n };\n}\n","import type { DialogHTMLAttributes, ReactNode, RefObject } from \"react\";\n\nimport { portalInto } from \"../../internal/portalInto\";\nimport { useModalSurface } from \"../../internal/useModalSurface\";\nimport type { DialogRole, DialogSize } from \"./dialog.tokens\";\nimport \"./Dialog.css\";\n\nconst CloseIcon = () => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.75} aria-hidden=\"true\">\n <path d=\"M4.5 4.5l7 7M11.5 4.5l-7 7\" strokeLinecap=\"round\" />\n </svg>\n);\n\nexport type DialogProps = {\n /**\n * Whether the dialog is showing.\n *\n * Controlled only, deliberately: a modal has no trigger of its own, so it's\n * always opened from somewhere else in the app. An uncontrolled dialog could\n * never be opened.\n */\n open: boolean;\n /**\n * Called when the dialog asks to close — the close button, the backdrop, or\n * Escape. Nothing closes on its own; this has to set `open` to false.\n */\n onClose: () => void;\n /** Accessible name, rendered as the heading. */\n title: ReactNode;\n /** Optional supporting line under the title. */\n description?: ReactNode;\n /** Body content. Scrolls when it outgrows the dialog. */\n children?: ReactNode;\n /** Action row pinned below the body — usually buttons. */\n footer?: ReactNode;\n /** Width of the dialog. Defaults to `md`. */\n size?: DialogSize;\n /** Defaults to `dialog`. Use `alertdialog` for a decision that can't wait. */\n role?: DialogRole;\n /** Whether Escape closes the dialog. Defaults to true. */\n closeOnEscape?: boolean;\n /** Whether clicking the backdrop closes the dialog. Defaults to true. */\n closeOnBackdropClick?: boolean;\n /** Whether to render the × in the header. Defaults to true. */\n showClose?: boolean;\n /** Accessible name for the × button. Defaults to \"Close\". */\n closeLabel?: string;\n /**\n * Element to focus when the dialog opens. Without it the browser focuses the\n * first focusable thing inside, or anything carrying `autoFocus`.\n */\n initialFocus?: RefObject<HTMLElement | null>;\n /** Whether to freeze page scrolling while open. Defaults to true. */\n lockScroll?: boolean;\n /**\n * Renders the dialog elsewhere in the DOM — `true` for `document.body`, or\n * an element to render into. Off by default.\n *\n * Not needed for stacking or clipping: `showModal()` puts the dialog in the\n * top layer, which sits above the whole document whatever the `z-index` and\n * `overflow` of its ancestors. Reach for this when the dialog's *position in\n * the DOM* is the problem — nested inside a `<form>` whose submission its\n * buttons would trigger, inside an element with a native click listener, or\n * under an ancestor that may become `inert` or unmount beneath it.\n *\n * It does not change event propagation in React: a portal moves the DOM\n * node, not the React tree, so a parent component's `onClick` still fires.\n */\n portal?: boolean | HTMLElement;\n className?: string;\n} & Omit<\n DialogHTMLAttributes<HTMLDialogElement>,\n \"className\" | \"title\" | \"role\" | \"open\" | \"onClose\" | \"onCancel\"\n>;\n\n/**\n * Modal dialog built on the native `<dialog>` element.\n *\n * `showModal()` puts it in the top layer, which is what makes it immune to\n * `z-index` and `overflow: hidden` on anything around it, and brings the focus\n * trap, the inert background and the backdrop with it. None of that is\n * reimplemented here.\n */\nexport function Dialog({\n open,\n onClose,\n title,\n description,\n children,\n footer,\n size = \"md\",\n role = \"dialog\",\n closeOnEscape = true,\n closeOnBackdropClick = true,\n showClose = true,\n closeLabel = \"Close\",\n initialFocus,\n lockScroll = true,\n portal = false,\n className,\n ...props\n}: DialogProps) {\n const { titleId, descriptionId, surfaceProps } = useModalSurface({\n open,\n onClose,\n closeOnEscape,\n closeOnBackdropClick,\n initialFocus,\n lockScroll,\n });\n\n const content = (\n <dialog\n role={role}\n aria-labelledby={titleId}\n aria-describedby={description ? descriptionId : undefined}\n className={[\"sh-dialog\", `sh-dialog--${size}`, className].filter(Boolean).join(\" \")}\n {...surfaceProps}\n {...props}\n >\n <div className=\"sh-dialog__header\">\n <div className=\"sh-dialog__heading\">\n <h2 id={titleId} className=\"sh-dialog__title\">\n {title}\n </h2>\n {description && (\n <p id={descriptionId} className=\"sh-dialog__description\">\n {description}\n </p>\n )}\n </div>\n\n {showClose && (\n <button\n type=\"button\"\n className=\"sh-dialog__close\"\n aria-label={closeLabel}\n onClick={onClose}\n >\n <CloseIcon />\n </button>\n )}\n </div>\n\n {children !== undefined && children !== null && children !== false && (\n <div className=\"sh-dialog__body\">{children}</div>\n )}\n\n {footer && <div className=\"sh-dialog__footer\">{footer}</div>}\n </dialog>\n );\n\n return portalInto(content, portal);\n}\n","export const dialogSizes = [\"sm\", \"md\", \"lg\", \"fullscreen\"] as const;\n\nexport type DialogSize = (typeof dialogSizes)[number];\n\n/**\n * `alertdialog` tells assistive tech the content is urgent and needs a\n * response — reserve it for confirmations and destructive warnings.\n */\nexport const dialogRoles = [\"dialog\", \"alertdialog\"] as const;\n\nexport type DialogRole = (typeof dialogRoles)[number];\n","import type { DialogHTMLAttributes, ReactNode, RefObject } from \"react\";\n\nimport { portalInto } from \"../../internal/portalInto\";\nimport { useModalSurface } from \"../../internal/useModalSurface\";\nimport type { DrawerSide, DrawerSize } from \"./drawer.tokens\";\nimport \"./Drawer.css\";\n\nconst CloseIcon = () => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.75} aria-hidden=\"true\">\n <path d=\"M4.5 4.5l7 7M11.5 4.5l-7 7\" strokeLinecap=\"round\" />\n </svg>\n);\n\nexport type DrawerProps = {\n /**\n * Whether the drawer is showing.\n *\n * Controlled only, like `Dialog`: a modal surface has no trigger of its own,\n * so an uncontrolled one could never be opened.\n */\n open: boolean;\n /**\n * Called when the drawer asks to close — the close button, the scrim, or\n * Escape. Nothing closes on its own; this has to set `open` to false.\n */\n onClose: () => void;\n /** Accessible name, rendered as the heading. */\n title: ReactNode;\n /** Optional supporting line under the title. */\n description?: ReactNode;\n /** Body content. Scrolls when it outgrows the drawer. */\n children?: ReactNode;\n /** Action row pinned below the body — usually buttons. */\n footer?: ReactNode;\n /** Edge to anchor to and slide in from. Defaults to `right`. */\n side?: DrawerSide;\n /** Extent along the drawer's own axis. Defaults to `md`. */\n size?: DrawerSize;\n /** Whether Escape closes the drawer. Defaults to true. */\n closeOnEscape?: boolean;\n /** Whether clicking the scrim closes the drawer. Defaults to true. */\n closeOnBackdropClick?: boolean;\n /** Whether to render the × in the header. Defaults to true. */\n showClose?: boolean;\n /** Accessible name for the × button. Defaults to \"Close\". */\n closeLabel?: string;\n /**\n * Element to focus when the drawer opens. Without it the browser focuses the\n * first focusable thing inside, or anything carrying `autoFocus`.\n */\n initialFocus?: RefObject<HTMLElement | null>;\n /** Whether to freeze page scrolling while open. Defaults to true. */\n lockScroll?: boolean;\n /**\n * Renders the drawer elsewhere in the DOM — `true` for `document.body`, or\n * an element to render into. Off by default.\n *\n * Not needed for stacking or clipping: `showModal()` puts the drawer in the\n * top layer, above the whole document whatever the `z-index` and `overflow`\n * of its ancestors. Reach for this when the drawer's *position in the DOM*\n * is the problem — nested inside a `<form>` whose submission its buttons\n * would trigger, inside an element with a native click listener, or under an\n * ancestor that may become `inert` or unmount beneath it.\n *\n * It does not change event propagation in React: a portal moves the DOM\n * node, not the React tree, so a parent component's `onClick` still fires.\n */\n portal?: boolean | HTMLElement;\n className?: string;\n} & Omit<\n DialogHTMLAttributes<HTMLDialogElement>,\n \"className\" | \"title\" | \"role\" | \"open\" | \"onClose\" | \"onCancel\"\n>;\n\n/**\n * Panel that slides in from an edge of the viewport, over the page.\n *\n * Shares every behaviour with `Dialog` — both are a modal native `<dialog>`,\n * so both get the top layer, the focus trap, the inert background and the\n * scrim from the browser rather than from code here. The difference is purely\n * geometric: a drawer is pinned to one edge and fills its cross axis.\n *\n * There's deliberately no `alertdialog` option. A decision urgent enough for\n * that role shouldn't arrive as a panel sliding in from the side.\n */\nexport function Drawer({\n open,\n onClose,\n title,\n description,\n children,\n footer,\n side = \"right\",\n size = \"md\",\n closeOnEscape = true,\n closeOnBackdropClick = true,\n showClose = true,\n closeLabel = \"Close\",\n initialFocus,\n lockScroll = true,\n portal = false,\n className,\n ...props\n}: DrawerProps) {\n const { titleId, descriptionId, surfaceProps } = useModalSurface({\n open,\n onClose,\n closeOnEscape,\n closeOnBackdropClick,\n initialFocus,\n lockScroll,\n });\n\n const content = (\n <dialog\n aria-labelledby={titleId}\n aria-describedby={description ? descriptionId : undefined}\n className={[\"sh-drawer\", `sh-drawer--${side}`, `sh-drawer--${size}`, className]\n .filter(Boolean)\n .join(\" \")}\n {...surfaceProps}\n {...props}\n >\n <div className=\"sh-drawer__header\">\n <div className=\"sh-drawer__heading\">\n <h2 id={titleId} className=\"sh-drawer__title\">\n {title}\n </h2>\n {description && (\n <p id={descriptionId} className=\"sh-drawer__description\">\n {description}\n </p>\n )}\n </div>\n\n {showClose && (\n <button\n type=\"button\"\n className=\"sh-drawer__close\"\n aria-label={closeLabel}\n onClick={onClose}\n >\n <CloseIcon />\n </button>\n )}\n </div>\n\n {children !== undefined && children !== null && children !== false && (\n <div className=\"sh-drawer__body\">{children}</div>\n )}\n\n {footer && <div className=\"sh-drawer__footer\">{footer}</div>}\n </dialog>\n );\n\n return portalInto(content, portal);\n}\n","/** Edge the drawer is anchored to and slides in from. */\nexport const drawerSides = [\"left\", \"right\", \"top\", \"bottom\"] as const;\n\nexport type DrawerSide = (typeof drawerSides)[number];\n\n/**\n * Extent along the drawer's own axis — width for `left`/`right`, height for\n * `top`/`bottom`. Always capped at the viewport, so `sm` on a narrow phone is\n * simply full-bleed rather than overflowing.\n */\nexport const drawerSizes = [\"sm\", \"md\", \"lg\", \"full\"] as const;\n\nexport type DrawerSize = (typeof drawerSizes)[number];\n","/** A concrete side the tip can sit on. */\nexport type TooltipSide = \"top\" | \"bottom\" | \"left\" | \"right\";\n\n/** What a `Tooltip` accepts — a fixed side, or `auto` to pick one at runtime. */\nexport type TooltipPlacement = TooltipSide | \"auto\";\n\n/** The parts of a DOMRect this needs, so callers can pass a plain object. */\nexport type TooltipRect = {\n top: number;\n bottom: number;\n left: number;\n right: number;\n};\n\nexport type ResolveTooltipPlacementOptions = {\n /** Trigger box, relative to the viewport — i.e. `getBoundingClientRect()`. */\n trigger: TooltipRect;\n /** Rendered size of the tip. */\n tip: { width: number; height: number };\n viewport: { width: number; height: number };\n /** Separation between trigger and tip. Defaults to 8, matching the CSS. */\n gap?: number;\n};\n\n/*\n * Preference order when more than one side fits. `top` leads because it's the\n * default for a fixed placement, and the sides come last: a tip beside the\n * trigger is harder to associate with it than one above or below.\n */\nconst ORDER: TooltipSide[] = [\"top\", \"bottom\", \"right\", \"left\"];\n\n/**\n * Picks the side of the trigger with room for the tip.\n *\n * Returns the first side in preference order that fits. When none do — a\n * trigger in a cramped scroll container, say — it returns whichever side\n * overflows least, so the tip is still mostly readable.\n *\n * This looks at the primary axis only: a `top` tip is centred horizontally\n * and can still overrun the left or right edge of a narrow viewport. Shifting\n * along the cross axis would need the tip to be positioned in JavaScript\n * rather than by CSS.\n */\nexport function resolveTooltipPlacement({\n trigger,\n tip,\n viewport,\n gap = 8,\n}: ResolveTooltipPlacementOptions): TooltipSide {\n const space: Record<TooltipSide, number> = {\n top: trigger.top,\n bottom: viewport.height - trigger.bottom,\n left: trigger.left,\n right: viewport.width - trigger.right,\n };\n\n const needed: Record<TooltipSide, number> = {\n top: tip.height + gap,\n bottom: tip.height + gap,\n left: tip.width + gap,\n right: tip.width + gap,\n };\n\n const fitting = ORDER.find((side) => space[side] >= needed[side]);\n if (fitting) return fitting;\n\n return ORDER.reduce((best, side) =>\n space[side] - needed[side] > space[best] - needed[best] ? side : best,\n );\n}\n","import {\n cloneElement,\n isValidElement,\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport type { HTMLAttributes, ReactElement, ReactNode } from \"react\";\n\nimport { resolveTooltipPlacement } from \"./resolveTooltipPlacement\";\nimport type { TooltipPlacement, TooltipSide } from \"./resolveTooltipPlacement\";\nimport \"./Tooltip.css\";\n\nexport type { TooltipPlacement, TooltipSide };\n\n/*\n * Measuring has to happen before paint, or the tip is visible on the wrong\n * side for a frame. useLayoutEffect warns during server rendering, where\n * there's no layout to measure in the first place.\n */\nconst useMeasureEffect = typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\n/** The one prop the tooltip needs to put on its trigger. */\ntype TriggerProps = { \"aria-describedby\"?: string };\n\nexport type TooltipProps = {\n /**\n * The element the tip describes. Must be a single element that forwards\n * props to a DOM node — the tip's id has to land on the thing a screen\n * reader focuses, and no wrapper can stand in for it.\n */\n children: ReactElement<TriggerProps>;\n /** Tip body. Nothing renders when this is empty. */\n content?: ReactNode;\n /**\n * Which side of the trigger the tip sits on. Defaults to `top`.\n *\n * `auto` measures the trigger against the viewport each time the tip opens\n * and picks a side with room for it.\n */\n placement?: TooltipPlacement;\n /** Milliseconds to wait before showing on hover. Defaults to 150. */\n delay?: number;\n /** Open state — makes the component controlled. */\n open?: boolean;\n /** Initial open state when uncontrolled. Defaults to closed. */\n defaultOpen?: boolean;\n /** Fired whenever the tip shows or hides. */\n onOpenChange?: (open: boolean) => void;\n /** Suppresses the tip entirely while leaving the trigger untouched. */\n disabled?: boolean;\n className?: string;\n} & Omit<HTMLAttributes<HTMLSpanElement>, \"className\" | \"content\">;\n\n/**\n * Short label revealed on hover or focus.\n *\n * Supplementary only: a tooltip is never the sole home for information a user\n * needs, because it can't be reached by touch and disappears on the way to\n * anything else. Use it to name an icon button or expand an abbreviation.\n */\nexport function Tooltip({\n children,\n content,\n placement = \"top\",\n delay = 150,\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n disabled = false,\n className,\n ...props\n}: TooltipProps) {\n const tipId = useId();\n const timerRef = useRef<number | undefined>(undefined);\n const wrapperRef = useRef<HTMLSpanElement>(null);\n const tipRef = useRef<HTMLSpanElement>(null);\n /*\n * Set while a press is being handled. A click fires mousedown *then* focus,\n * so without this the focus handler would immediately reopen the tip the\n * press just dismissed, and it would sit there over whatever the click did.\n */\n const pressedRef = useRef(false);\n\n const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : uncontrolledOpen;\n\n // An empty tip would otherwise leave an aria-describedby pointing at nothing.\n const hasTip = !disabled && content !== undefined && content !== null && content !== \"\";\n\n const clearTimer = () => {\n if (timerRef.current !== undefined) {\n window.clearTimeout(timerRef.current);\n timerRef.current = undefined;\n }\n };\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (!isControlled) setUncontrolledOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n const show = () => {\n if (!hasTip || isOpen || pressedRef.current) return;\n clearTimer();\n // A zero delay has to stay synchronous, or a click would land first.\n if (delay > 0) timerRef.current = window.setTimeout(() => setOpen(true), delay);\n else setOpen(true);\n };\n\n const hide = () => {\n clearTimer();\n if (isOpen) setOpen(false);\n };\n\n // A pending timer would otherwise fire into an unmounted component.\n useEffect(() => clearTimer, []);\n\n /*\n * Auto placement. Measured while open rather than once on mount, because the\n * trigger moves: scrolling it towards an edge should move the tip to the\n * side that still has room.\n */\n const [autoSide, setAutoSide] = useState<TooltipSide>(\"top\");\n const isAuto = placement === \"auto\";\n const side = isAuto ? autoSide : placement;\n\n useMeasureEffect(() => {\n if (!isAuto || !isOpen || !hasTip) return;\n\n const measure = () => {\n const wrapper = wrapperRef.current;\n const tip = tipRef.current;\n if (!wrapper || !tip) return;\n\n setAutoSide(\n resolveTooltipPlacement({\n trigger: wrapper.getBoundingClientRect(),\n // offsetWidth/Height ignore the reveal transform, unlike the rect.\n tip: { width: tip.offsetWidth, height: tip.offsetHeight },\n viewport: { width: window.innerWidth, height: window.innerHeight },\n }),\n );\n };\n\n measure();\n\n // Captured, so scrolling any ancestor container counts, not just the page.\n window.addEventListener(\"scroll\", measure, true);\n window.addEventListener(\"resize\", measure);\n return () => {\n window.removeEventListener(\"scroll\", measure, true);\n window.removeEventListener(\"resize\", measure);\n };\n }, [isAuto, isOpen, hasTip]);\n\n /*\n * Escape dismisses the tip, per the APG. Bound to the document rather than\n * the trigger because the tip can be open without focus being anywhere near\n * it — hover, or a controlled parent — and an undismissable tip can sit on\n * top of whatever the user is trying to read.\n */\n useEffect(() => {\n if (!isOpen || !hasTip) return;\n\n const handleKeyDown = (event: globalThis.KeyboardEvent) => {\n if (event.key !== \"Escape\") return;\n setOpen(false);\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, hasTip, setOpen]);\n\n if (!isValidElement(children)) {\n throw new Error(\"<Tooltip> expects a single element child to describe.\");\n }\n\n /*\n * The only prop injected into the trigger. Handlers all sit on the wrapper,\n * where they cover the whole subtree and can't collide with the child's own.\n *\n * The reference is permanent rather than added on open: assistive technology\n * computes the description when focus arrives, and a hidden element that is\n * *directly referenced* still contributes its text, so a screen reader gets\n * the tip whether or not it is visually showing.\n */\n const trigger = hasTip\n ? cloneElement(children, {\n \"aria-describedby\": [children.props[\"aria-describedby\"], tipId]\n .filter(Boolean)\n .join(\" \"),\n })\n : children;\n\n return (\n <span\n ref={wrapperRef}\n className={[\"sh-tooltip\", className].filter(Boolean).join(\" \")}\n onMouseEnter={show}\n onMouseLeave={() => {\n pressedRef.current = false;\n hide();\n }}\n onFocus={show}\n onBlur={() => {\n pressedRef.current = false;\n hide();\n }}\n // A press means the user has stopped asking what the control is.\n onMouseDown={() => {\n pressedRef.current = true;\n hide();\n }}\n {...props}\n >\n {trigger}\n\n {hasTip && (\n <span\n ref={tipRef}\n id={tipId}\n role=\"tooltip\"\n className={[\n \"sh-tooltip__tip\",\n `sh-tooltip__tip--${side}`,\n isOpen && \"sh-tooltip__tip--open\",\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {content}\n </span>\n )}\n </span>\n );\n}\n","import { useId } from \"react\";\nimport type { ReactNode, SelectHTMLAttributes } from \"react\";\n\nimport \"./Select.css\";\n\nconst ChevronIcon = () => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.5} aria-hidden=\"true\">\n <path d=\"M4 6.5 8 10.5l4-4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n);\n\nexport type SelectOption = {\n value: string;\n label: string;\n disabled?: boolean;\n};\n\nexport type SelectOptionGroup = {\n label: string;\n options: SelectOption[];\n};\n\nconst isGroup = (item: SelectOption | SelectOptionGroup): item is SelectOptionGroup =>\n \"options\" in item;\n\nexport type SelectProps = {\n /** Visible label, associated with the select via `htmlFor`/`id`. */\n label?: ReactNode;\n /** Hint shown below the select. Replaced by `error` when that's set. */\n helperText?: ReactNode;\n /** Validation message. Its presence also marks the select invalid. */\n error?: ReactNode;\n /** Options to render. Omit and pass `children` to build them yourself. */\n options?: (SelectOption | SelectOptionGroup)[];\n /** Prompt shown while nothing is chosen. Rendered as an unselectable option. */\n placeholder?: string;\n /** Decorative icon rendered at the start of the field. */\n icon?: ReactNode;\n /** Class for the wrapper element. Use `selectClassName` for the control. */\n className?: string;\n /** Class for the underlying `<select>`. */\n selectClassName?: string;\n children?: ReactNode;\n} & Omit<SelectHTMLAttributes<HTMLSelectElement>, \"className\">;\n\n/**\n * Dropdown built on the native `<select>`, so keyboard support, type-ahead,\n * form submission, and the platform's own picker on mobile all come for free.\n *\n * The closed control is fully styled; the open list is drawn by the OS and\n * can't be. A component that needs custom option rendering, search, or\n * multi-select chips would be a different, much larger widget.\n */\nexport function Select({\n label,\n helperText,\n error,\n options,\n placeholder,\n icon,\n className,\n selectClassName,\n children,\n id,\n required,\n disabled,\n multiple,\n \"aria-describedby\": ariaDescribedBy,\n ...props\n}: SelectProps) {\n // Only used when the consumer doesn't supply an id — the label needs a\n // stable target either way.\n const generatedId = useId();\n const selectId = id ?? generatedId;\n const messageId = `${selectId}-message`;\n\n const invalid = Boolean(error);\n const message = error ?? helperText;\n\n // Keep any describedby the consumer passed; don't clobber it.\n const describedBy =\n [ariaDescribedBy, message ? messageId : undefined].filter(Boolean).join(\" \") || undefined;\n\n const classes = [\n \"sh-select\",\n invalid && \"sh-select--invalid\",\n disabled && \"sh-select--disabled\",\n icon && \"sh-select--with-icon\",\n // A multiple select is a list box, not a dropdown — no chevron to draw.\n multiple && \"sh-select--multiple\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n const renderOption = (option: SelectOption) => (\n <option key={option.value} value={option.value} disabled={option.disabled}>\n {option.label}\n </option>\n );\n\n return (\n <div className={classes}>\n {label && (\n <label className=\"sh-select__label\" htmlFor={selectId}>\n {label}\n {required && (\n <span className=\"sh-select__required\" aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )}\n\n <span className=\"sh-select__field\">\n {icon && (\n <span className=\"sh-select__icon\" aria-hidden=\"true\">\n {icon}\n </span>\n )}\n\n <select\n {...props}\n id={selectId}\n className={[\"sh-select__control\", selectClassName].filter(Boolean).join(\" \")}\n required={required}\n disabled={disabled}\n multiple={multiple}\n aria-invalid={invalid || undefined}\n aria-describedby={describedBy}\n >\n {/*\n Disabled so it can't be chosen again once a real option is picked,\n while still showing as the label until one is.\n */}\n {placeholder && (\n <option value=\"\" disabled>\n {placeholder}\n </option>\n )}\n\n {options\n ? options.map((item) =>\n isGroup(item) ? (\n <optgroup key={item.label} label={item.label}>\n {item.options.map(renderOption)}\n </optgroup>\n ) : (\n renderOption(item)\n ),\n )\n : children}\n </select>\n\n {!multiple && (\n <span className=\"sh-select__chevron\" aria-hidden=\"true\">\n <ChevronIcon />\n </span>\n )}\n </span>\n\n {message && (\n <span id={messageId} className=\"sh-select__message\">\n {message}\n </span>\n )}\n </div>\n );\n}\n","import { useId } from \"react\";\nimport type { ReactNode, TextareaHTMLAttributes } from \"react\";\n\nimport \"./Textarea.css\";\n\nexport type TextareaResize = \"none\" | \"vertical\" | \"horizontal\" | \"both\";\n\nexport type TextareaProps = {\n /** Visible label, associated with the textarea via `htmlFor`/`id`. */\n label?: ReactNode;\n /** Hint shown below the textarea. Replaced by `error` when that's set. */\n helperText?: ReactNode;\n /** Validation message. Its presence also marks the textarea invalid. */\n error?: ReactNode;\n /** Which directions the user can resize. Defaults to `vertical`. */\n resize?: TextareaResize;\n /** Class for the wrapper element. Use `textareaClassName` for the control. */\n className?: string;\n /** Class for the underlying `<textarea>`. */\n textareaClassName?: string;\n} & Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, \"className\">;\n\n/** Multi-line text field with an associated label, helper text, and error state. */\nexport function Textarea({\n label,\n helperText,\n error,\n resize = \"vertical\",\n className,\n textareaClassName,\n id,\n rows = 3,\n required,\n disabled,\n \"aria-describedby\": ariaDescribedBy,\n ...props\n}: TextareaProps) {\n // Only used when the consumer doesn't supply an id — the label needs a\n // stable target either way.\n const generatedId = useId();\n const textareaId = id ?? generatedId;\n const messageId = `${textareaId}-message`;\n\n const invalid = Boolean(error);\n const message = error ?? helperText;\n\n // Keep any describedby the consumer passed; don't clobber it.\n const describedBy =\n [ariaDescribedBy, message ? messageId : undefined].filter(Boolean).join(\" \") || undefined;\n\n const classes = [\n \"sh-textarea\",\n invalid && \"sh-textarea--invalid\",\n disabled && \"sh-textarea--disabled\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div className={classes}>\n {label && (\n <label className=\"sh-textarea__label\" htmlFor={textareaId}>\n {label}\n {required && (\n <span className=\"sh-textarea__required\" aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n )}\n\n <textarea\n id={textareaId}\n className={[\n \"sh-textarea__control\",\n `sh-textarea__control--resize-${resize}`,\n textareaClassName,\n ]\n .filter(Boolean)\n .join(\" \")}\n rows={rows}\n required={required}\n disabled={disabled}\n aria-invalid={invalid || undefined}\n aria-describedby={describedBy}\n {...props}\n />\n\n {message && (\n <span id={messageId} className=\"sh-textarea__message\">\n {message}\n </span>\n )}\n </div>\n );\n}\n","import { createContext } from \"react\";\n\nexport type CheckboxGroupContextValue = {\n /** Shared `name`, so the options submit together as one field. */\n name: string;\n /** Currently selected values. Checkboxes are multi-select, unlike radios. */\n value: string[];\n /** Called with the option's value when it's toggled on or off. */\n onToggle: (value: string, checked: boolean) => void;\n /** Set when the whole group is disabled. */\n disabled?: boolean;\n};\n\n/**\n * Lets `CheckboxGroup` coordinate its `Checkbox` children without cloning\n * them. A `Checkbox` used outside a group falls back to its own props.\n * Kept in its own module so the component files only export components\n * (see the react-refresh rule in eslint.config.js).\n */\nexport const CheckboxGroupContext = createContext<CheckboxGroupContextValue | undefined>(\n undefined,\n);\n","import { useContext, useEffect, useRef } from \"react\";\nimport type { ChangeEvent, InputHTMLAttributes, ReactNode, Ref } from \"react\";\n\nimport { CheckboxGroupContext } from \"./checkbox.context\";\nimport \"./Checkbox.css\";\n\nexport type CheckboxProps = {\n /** Value this option represents. Required when inside a `CheckboxGroup`. */\n value?: string;\n /** Visible label sitting beside the control. */\n label?: ReactNode;\n /**\n * Renders the mixed state (a dash). Purely visual until toggled — a\n * checkbox is never submitted as indeterminate.\n */\n indeterminate?: boolean;\n /** Class for the wrapping `<label>`. Use `inputClassName` for the control. */\n className?: string;\n /** Class for the underlying `<input type=\"checkbox\">`. */\n inputClassName?: string;\n ref?: Ref<HTMLInputElement>;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, \"type\" | \"value\" | \"className\" | \"ref\">;\n\n/**\n * A single checkbox. Usually rendered inside a `CheckboxGroup`, which supplies\n * the shared `name` and selection; works standalone too, in which case\n * `checked`/`onChange` behave like a plain `<input type=\"checkbox\">`.\n */\nexport function Checkbox({\n value,\n label,\n indeterminate = false,\n className,\n inputClassName,\n name,\n checked,\n disabled,\n onChange,\n ref,\n ...props\n}: CheckboxProps) {\n const group = useContext(CheckboxGroupContext);\n const innerRef = useRef<HTMLInputElement>(null);\n\n // `indeterminate` has no HTML attribute — it's a DOM property only, so it\n // has to be assigned after render.\n useEffect(() => {\n if (innerRef.current) innerRef.current.indeterminate = indeterminate;\n }, [indeterminate]);\n\n // Keep our ref (needed above) without swallowing one the caller passed.\n const attachRef = (node: HTMLInputElement | null) => {\n innerRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n };\n\n // Inside a group the group owns name/selection/disabled; standalone, the\n // component's own props do.\n const resolvedName = name ?? group?.name;\n const resolvedChecked =\n group && value !== undefined ? group.value.includes(value) : checked;\n const resolvedDisabled = disabled ?? group?.disabled;\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (group && value !== undefined) group.onToggle(value, event.target.checked);\n onChange?.(event);\n };\n\n const classes = [\"sh-checkbox\", resolvedDisabled && \"sh-checkbox--disabled\", className]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <label className={classes}>\n <input\n {...props}\n type=\"checkbox\"\n ref={attachRef}\n className={[\"sh-checkbox__input\", inputClassName].filter(Boolean).join(\" \")}\n name={resolvedName}\n value={value}\n checked={resolvedChecked}\n disabled={resolvedDisabled}\n onChange={handleChange}\n />\n {label && <span className=\"sh-checkbox__label\">{label}</span>}\n </label>\n );\n}\n","import { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { CheckboxGroupContext } from \"./checkbox.context\";\nimport \"./Checkbox.css\";\n\nexport type CheckboxGroupProps = {\n children?: ReactNode;\n /** Selected values — makes the group controlled. */\n value?: string[];\n /** Initial selection when uncontrolled. */\n defaultValue?: string[];\n /** Fired with the full list of selected values. */\n onChange?: (value: string[]) => void;\n /** Visible label for the group. Provide this or `aria-label`. */\n label?: ReactNode;\n /** Hint shown below the options. Replaced by `error` when that's set. */\n helperText?: ReactNode;\n /** Validation message. Its presence also marks the group invalid. */\n error?: ReactNode;\n /** Shared field name for the options. Auto-generated when omitted. */\n name?: string;\n /** Layout direction for the options. Defaults to `vertical`. */\n orientation?: \"vertical\" | \"horizontal\";\n /** Disables every option in the group. */\n disabled?: boolean;\n /** Accessible name when there's no visible `label`. */\n \"aria-label\"?: string;\n className?: string;\n};\n\n/** Groups `Checkbox` options, coordinating their shared name and selection. */\nexport function CheckboxGroup({\n children,\n value,\n defaultValue,\n onChange,\n label,\n helperText,\n error,\n name,\n orientation = \"vertical\",\n disabled = false,\n \"aria-label\": ariaLabel,\n className,\n}: CheckboxGroupProps) {\n const generatedName = useId();\n const labelId = useId();\n const messageId = useId();\n const groupName = name ?? generatedName;\n\n const [uncontrolledValue, setUncontrolledValue] = useState<string[]>(defaultValue ?? []);\n const isControlled = value !== undefined;\n const selected = isControlled ? value : uncontrolledValue;\n\n const handleToggle = (optionValue: string, checked: boolean) => {\n // Rebuild from the current selection so the callback always receives the\n // complete list, not a delta.\n const next = checked\n ? [...selected, optionValue]\n : selected.filter((item) => item !== optionValue);\n\n if (!isControlled) setUncontrolledValue(next);\n onChange?.(next);\n };\n\n const invalid = Boolean(error);\n const message = error ?? helperText;\n\n const classes = [\"sh-checkbox-group\", invalid && \"sh-checkbox-group--invalid\", className]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div className={classes}>\n {label && (\n <span className=\"sh-checkbox-group__label\" id={labelId}>\n {label}\n </span>\n )}\n\n {/*\n `group` rather than `radiogroup` — there's no native grouping role for\n checkboxes, since each one is independently toggleable.\n */}\n <div\n className={`sh-checkbox-group__options sh-checkbox-group__options--${orientation}`}\n role=\"group\"\n aria-label={label ? undefined : ariaLabel}\n aria-labelledby={label ? labelId : undefined}\n aria-describedby={message ? messageId : undefined}\n aria-invalid={invalid || undefined}\n >\n <CheckboxGroupContext.Provider\n value={{ name: groupName, value: selected, onToggle: handleToggle, disabled }}\n >\n {children}\n </CheckboxGroupContext.Provider>\n </div>\n\n {message && (\n <span id={messageId} className=\"sh-checkbox-group__message\">\n {message}\n </span>\n )}\n </div>\n );\n}\n","import { createContext } from \"react\";\n\nexport type RadioGroupContextValue = {\n /** Shared `name`, which is what makes the browser treat them as one group. */\n name: string;\n /** Currently selected value in the group. */\n value?: string;\n /** Called with the newly selected value. */\n onSelect: (value: string) => void;\n /** Set when the whole group is disabled. */\n disabled?: boolean;\n};\n\n/**\n * Lets `RadioGroup` coordinate its `Radio` children without cloning them.\n * A `Radio` used outside a group falls back to its own props.\n * Kept in its own module so the component files only export components\n * (see the react-refresh rule in eslint.config.js).\n */\nexport const RadioGroupContext = createContext<RadioGroupContextValue | undefined>(undefined);\n","import { useContext } from \"react\";\nimport type { ChangeEvent, InputHTMLAttributes, ReactNode } from \"react\";\n\nimport { RadioGroupContext } from \"./radio.context\";\nimport \"./Radio.css\";\n\nexport type RadioProps = {\n /** Value this option represents. Required when inside a `RadioGroup`. */\n value?: string;\n /** Visible label sitting beside the control. */\n label?: ReactNode;\n /** Class for the wrapping `<label>`. Use `inputClassName` for the control. */\n className?: string;\n /** Class for the underlying `<input type=\"radio\">`. */\n inputClassName?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, \"type\" | \"value\" | \"className\">;\n\n/**\n * A single radio option. Usually rendered inside a `RadioGroup`, which\n * supplies the shared `name` and selection; works standalone too, in which\n * case `name`/`checked`/`onChange` behave like a plain `<input type=\"radio\">`.\n */\nexport function Radio({\n value,\n label,\n className,\n inputClassName,\n name,\n checked,\n disabled,\n onChange,\n ...props\n}: RadioProps) {\n const group = useContext(RadioGroupContext);\n\n // Inside a group the group owns name/selection/disabled; standalone, the\n // component's own props do.\n const resolvedName = name ?? group?.name;\n const resolvedChecked = group ? group.value === value : checked;\n const resolvedDisabled = disabled ?? group?.disabled;\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (group && value !== undefined) group.onSelect(value);\n onChange?.(event);\n };\n\n const classes = [\"sh-radio\", resolvedDisabled && \"sh-radio--disabled\", className]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <label className={classes}>\n <input\n type=\"radio\"\n className={[\"sh-radio__input\", inputClassName].filter(Boolean).join(\" \")}\n name={resolvedName}\n value={value}\n checked={resolvedChecked}\n disabled={resolvedDisabled}\n onChange={handleChange}\n {...props}\n />\n {label && <span className=\"sh-radio__label\">{label}</span>}\n </label>\n );\n}\n","import { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { RadioGroupContext } from \"./radio.context\";\nimport \"./Radio.css\";\n\nexport type RadioGroupProps = {\n children?: ReactNode;\n /** Selected value — makes the group controlled. */\n value?: string;\n /** Initial selection when uncontrolled. */\n defaultValue?: string;\n /** Fired with the newly selected value. */\n onChange?: (value: string) => void;\n /** Visible label for the group. Provide this or `aria-label`. */\n label?: ReactNode;\n /** Hint shown below the options. Replaced by `error` when that's set. */\n helperText?: ReactNode;\n /** Validation message. Its presence also marks the group invalid. */\n error?: ReactNode;\n /** Radio group name. Auto-generated when omitted. */\n name?: string;\n /** Layout direction for the options. Defaults to `vertical`. */\n orientation?: \"vertical\" | \"horizontal\";\n /** Disables every option in the group. */\n disabled?: boolean;\n /** Accessible name when there's no visible `label`. */\n \"aria-label\"?: string;\n className?: string;\n};\n\n/** Groups `Radio` options, coordinating their shared name and selection. */\nexport function RadioGroup({\n children,\n value,\n defaultValue,\n onChange,\n label,\n helperText,\n error,\n name,\n orientation = \"vertical\",\n disabled = false,\n \"aria-label\": ariaLabel,\n className,\n}: RadioGroupProps) {\n const generatedName = useId();\n const labelId = useId();\n const messageId = useId();\n const groupName = name ?? generatedName;\n\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n const isControlled = value !== undefined;\n const selected = isControlled ? value : uncontrolledValue;\n\n const handleSelect = (next: string) => {\n if (!isControlled) setUncontrolledValue(next);\n onChange?.(next);\n };\n\n const invalid = Boolean(error);\n const message = error ?? helperText;\n\n const classes = [\"sh-radio-group\", invalid && \"sh-radio-group--invalid\", className]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div className={classes}>\n {label && (\n <span className=\"sh-radio-group__label\" id={labelId}>\n {label}\n </span>\n )}\n\n <div\n className={`sh-radio-group__options sh-radio-group__options--${orientation}`}\n role=\"radiogroup\"\n aria-label={label ? undefined : ariaLabel}\n aria-labelledby={label ? labelId : undefined}\n aria-describedby={message ? messageId : undefined}\n aria-invalid={invalid || undefined}\n >\n <RadioGroupContext.Provider\n value={{ name: groupName, value: selected, onSelect: handleSelect, disabled }}\n >\n {children}\n </RadioGroupContext.Provider>\n </div>\n\n {message && (\n <span id={messageId} className=\"sh-radio-group__message\">\n {message}\n </span>\n )}\n </div>\n );\n}\n","/** A page number, or a gap standing in for pages that were left out. */\nexport type PaginationItem = number | \"ellipsis\";\n\nexport type PaginationRangeOptions = {\n /** Current page, 1-indexed. */\n page: number;\n /** Total number of pages. */\n count: number;\n /** Pages to show either side of the current one. */\n siblingCount?: number;\n /** Pages to always show at each end. */\n boundaryCount?: number;\n};\n\n/** Inclusive integer range; empty when `start` is past `end`. */\nconst range = (start: number, end: number): number[] =>\n end < start ? [] : Array.from({ length: end - start + 1 }, (_, index) => start + index);\n\n/**\n * Builds the visible page list, collapsing runs of hidden pages into gaps.\n *\n * The width is deliberately stable — a given `siblingCount`/`boundaryCount`\n * yields the same number of slots regardless of the current page, so the\n * control doesn't resize as you page through. That's why the sibling window\n * is clamped rather than simply centred on the current page.\n *\n * A gap is only used when it actually saves space: standing in for a single\n * hidden page would take as much room as the page itself, so that page is\n * shown instead.\n */\nexport function getPaginationRange({\n page,\n count,\n siblingCount = 1,\n boundaryCount = 1,\n}: PaginationRangeOptions): PaginationItem[] {\n if (count <= 0) return [];\n\n const startPages = range(1, Math.min(boundaryCount, count));\n const endPages = range(Math.max(count - boundaryCount + 1, boundaryCount + 1), count);\n\n /*\n * Bounded so the window never runs past the boundary pages at either end.\n * These bounds also absorb an out-of-range `page` — a page below 1 or above\n * `count` lands on the same window as the nearest valid one — so no separate\n * clamp on `page` is needed.\n */\n const siblingsStart = Math.max(\n Math.min(page - siblingCount, count - boundaryCount - siblingCount * 2 - 1),\n boundaryCount + 2,\n );\n const siblingsEnd = Math.min(\n Math.max(page + siblingCount, boundaryCount + siblingCount * 2 + 2),\n endPages.length > 0 ? endPages[0] - 2 : count - 1,\n );\n\n return [\n ...startPages,\n\n // Leading gap — or the single page it would have replaced.\n ...(siblingsStart > boundaryCount + 2\n ? ([\"ellipsis\"] as PaginationItem[])\n : boundaryCount + 1 < count - boundaryCount\n ? [boundaryCount + 1]\n : []),\n\n ...range(siblingsStart, siblingsEnd),\n\n // Trailing gap — same reasoning.\n ...(siblingsEnd < count - boundaryCount - 1\n ? ([\"ellipsis\"] as PaginationItem[])\n : count - boundaryCount > boundaryCount\n ? [count - boundaryCount]\n : []),\n\n ...endPages,\n ];\n}\n","import { useState } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\n\nimport { getPaginationRange } from \"./getPaginationRange\";\nimport \"./Pagination.css\";\n\nconst Chevron = ({ direction }: { direction: \"left\" | \"right\" }) => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.75} aria-hidden=\"true\">\n <path\n d={direction === \"left\" ? \"M10 3.5 5.5 8l4.5 4.5\" : \"M6 3.5 10.5 8 6 12.5\"}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nconst DoubleChevron = ({ direction }: { direction: \"left\" | \"right\" }) => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.75} aria-hidden=\"true\">\n <path\n d={direction === \"left\" ? \"M8 3.5 3.5 8 8 12.5M13 3.5 8.5 8l4.5 4.5\" : \"M8 3.5 12.5 8 8 12.5M3 3.5 7.5 8 3 12.5\"}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\nexport type PaginationProps = {\n /** Total number of pages. */\n count: number;\n /** Current page, 1-indexed — makes the component controlled. */\n page?: number;\n /** Initial page when uncontrolled. Defaults to `1`. */\n defaultPage?: number;\n /** Fired with the newly selected page. */\n onChange?: (page: number) => void;\n /** Pages to show either side of the current one. Defaults to `1`. */\n siblingCount?: number;\n /** Pages to always show at each end. Defaults to `1`. */\n boundaryCount?: number;\n /** Adds jump-to-first and jump-to-last buttons. */\n showFirstLast?: boolean;\n /** Hides the previous/next buttons. */\n hidePrevNext?: boolean;\n /** Disables every control. */\n disabled?: boolean;\n /** Labels for the navigation buttons and each page. */\n labels?: {\n first?: string;\n previous?: string;\n next?: string;\n last?: string;\n page?: (page: number) => string;\n };\n /** Accessible name for the landmark. Defaults to \"Pagination\". */\n \"aria-label\"?: string;\n className?: string;\n} & Omit<HTMLAttributes<HTMLElement>, \"className\" | \"onChange\">;\n\nconst defaultLabels = {\n first: \"First page\",\n previous: \"Previous page\",\n next: \"Next page\",\n last: \"Last page\",\n page: (page: number) => `Page ${page}`,\n};\n\n/**\n * Page navigation.\n *\n * A `nav` landmark around a list of page buttons, with runs of hidden pages\n * collapsed into gaps. The gaps are inert text, not buttons — there's nothing\n * to activate, so they stay out of the tab order and the accessibility tree.\n */\nexport function Pagination({\n count,\n page,\n defaultPage = 1,\n onChange,\n siblingCount = 1,\n boundaryCount = 1,\n showFirstLast = false,\n hidePrevNext = false,\n disabled = false,\n labels,\n \"aria-label\": ariaLabel = \"Pagination\",\n className,\n ...props\n}: PaginationProps) {\n const [uncontrolledPage, setUncontrolledPage] = useState(defaultPage);\n const isControlled = page !== undefined;\n const current = isControlled ? page : uncontrolledPage;\n\n const text = { ...defaultLabels, ...labels };\n\n const select = (next: number) => {\n // Guard the arrows at the ends, and any out-of-range page from a caller.\n if (next < 1 || next > count || next === current) return;\n if (!isControlled) setUncontrolledPage(next);\n onChange?.(next);\n };\n\n const items = getPaginationRange({ page: current, count, siblingCount, boundaryCount });\n\n // Nothing to navigate.\n if (count <= 0) return null;\n\n const navButton = (key: string, label: string, to: number, icon: ReactNode) => (\n <li className=\"sh-pagination__item\" key={key}>\n <button\n type=\"button\"\n className=\"sh-pagination__control\"\n onClick={() => select(to)}\n /*\n * Also disabled when the target is the page you're already on —\n * otherwise \"First page\" stays enabled on page 1 and does nothing\n * when clicked, which reads as broken.\n */\n disabled={disabled || to < 1 || to > count || to === current}\n aria-label={label}\n >\n {icon}\n </button>\n </li>\n );\n\n return (\n <nav\n className={[\"sh-pagination\", className].filter(Boolean).join(\" \")}\n aria-label={ariaLabel}\n {...props}\n >\n <ul className=\"sh-pagination__list\">\n {showFirstLast &&\n navButton(\"first\", text.first, 1, <DoubleChevron direction=\"left\" />)}\n {!hidePrevNext &&\n navButton(\"prev\", text.previous, current - 1, <Chevron direction=\"left\" />)}\n\n {items.map((item, index) =>\n item === \"ellipsis\" ? (\n <li className=\"sh-pagination__item\" key={`ellipsis-${index}`}>\n {/*\n Inert: there's no page to go to, and announcing \"ellipsis\"\n between page numbers is noise.\n */}\n <span className=\"sh-pagination__ellipsis\" aria-hidden=\"true\">\n …\n </span>\n </li>\n ) : (\n <li className=\"sh-pagination__item\" key={item}>\n <button\n type=\"button\"\n className={[\n \"sh-pagination__page\",\n item === current && \"sh-pagination__page--current\",\n ]\n .filter(Boolean)\n .join(\" \")}\n onClick={() => select(item)}\n disabled={disabled}\n aria-label={text.page(item)}\n aria-current={item === current ? \"page\" : undefined}\n >\n {item}\n </button>\n </li>\n ),\n )}\n\n {!hidePrevNext &&\n navButton(\"next\", text.next, current + 1, <Chevron direction=\"right\" />)}\n {showFirstLast &&\n navButton(\"last\", text.last, count, <DoubleChevron direction=\"right\" />)}\n </ul>\n </nav>\n );\n}\n","import { createContext, useContext } from \"react\";\n\n/** `single` closes the open item when another opens; `multiple` doesn't. */\nexport type AccordionType = \"single\" | \"multiple\";\n\n/** Heading rank the triggers are wrapped in, to fit the page outline. */\nexport type AccordionHeadingLevel = 2 | 3 | 4 | 5 | 6;\n\nexport type AccordionContextValue = {\n /** Values of the currently open items. */\n value: string[];\n /** Opens or closes one item, applying the single/multiple rule. */\n toggle: (value: string) => void;\n baseId: string;\n headingLevel: AccordionHeadingLevel;\n};\n\nexport const AccordionContext = createContext<AccordionContextValue | undefined>(undefined);\n\n/** Reads the surrounding `Accordion`, failing loudly rather than silently. */\nexport function useAccordionContext(component: string): AccordionContextValue {\n const context = useContext(AccordionContext);\n\n if (!context) {\n throw new Error(`<${component}> must be rendered inside <Accordion>.`);\n }\n\n return context;\n}\n\n/** Ids are derived rather than registered, so trigger and panel always agree. */\nexport const triggerId = (baseId: string, value: string) => `${baseId}-trigger-${value}`;\nexport const panelId = (baseId: string, value: string) => `${baseId}-panel-${value}`;\n","import { useId, useState } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\n\nimport { AccordionContext } from \"./accordion.context\";\nimport type { AccordionHeadingLevel, AccordionType } from \"./accordion.context\";\nimport \"./Accordion.css\";\n\nexport type AccordionProps = {\n children?: ReactNode;\n /** Whether more than one item can be open at a time. Defaults to `single`. */\n type?: AccordionType;\n /**\n * Values of the open items — makes the component controlled.\n *\n * Always an array, even for `type=\"single\"`, so the prop's type doesn't\n * change with another prop's value. A single accordion simply never holds\n * more than one entry.\n */\n value?: string[];\n /** Initially open items when uncontrolled. */\n defaultValue?: string[];\n /** Fired with the full list of open items. */\n onChange?: (value: string[]) => void;\n /**\n * For `type=\"single\"`, whether clicking the open item closes it. Defaults\n * to true; set false when one item must always stay open.\n */\n collapsible?: boolean;\n /** Heading rank wrapped around each trigger. Defaults to `3`. */\n headingLevel?: AccordionHeadingLevel;\n className?: string;\n} & Omit<HTMLAttributes<HTMLDivElement>, \"className\" | \"onChange\">;\n\n/**\n * Stack of collapsible sections.\n *\n * Each trigger is a button inside a real heading, so the sections show up in\n * the document outline and screen-reader heading navigation — an accordion\n * built from bare buttons is invisible to both.\n */\nexport function Accordion({\n children,\n type = \"single\",\n value,\n defaultValue,\n onChange,\n collapsible = true,\n headingLevel = 3,\n className,\n ...props\n}: AccordionProps) {\n const baseId = useId();\n\n const [uncontrolledValue, setUncontrolledValue] = useState<string[]>(defaultValue ?? []);\n const isControlled = value !== undefined;\n const open = isControlled ? value : uncontrolledValue;\n\n const toggle = (itemValue: string) => {\n const isOpen = open.includes(itemValue);\n\n let next: string[];\n if (type === \"multiple\") {\n next = isOpen ? open.filter((item) => item !== itemValue) : [...open, itemValue];\n } else if (isOpen) {\n // Refusing to collapse keeps the current item open rather than emptying.\n next = collapsible ? [] : open;\n } else {\n next = [itemValue];\n }\n\n if (!isControlled) setUncontrolledValue(next);\n onChange?.(next);\n };\n\n return (\n <AccordionContext.Provider value={{ value: open, toggle, baseId, headingLevel }}>\n <div className={[\"sh-accordion\", className].filter(Boolean).join(\" \")} {...props}>\n {children}\n </div>\n </AccordionContext.Provider>\n );\n}\n","import { createElement } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\n\nimport { panelId, triggerId, useAccordionContext } from \"./accordion.context\";\nimport \"./Accordion.css\";\n\nconst ChevronIcon = () => (\n <svg\n className=\"sh-accordion__chevron\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.75}\n aria-hidden=\"true\"\n >\n <path d=\"M4 6.5 8 10.5l4-4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n);\n\nexport type AccordionItemProps = {\n /** Identifies this section in the accordion's open list. */\n value: string;\n /** Content of the trigger. */\n title: ReactNode;\n /** Body revealed when open. */\n children?: ReactNode;\n /** Prevents the section being opened or closed. */\n disabled?: boolean;\n className?: string;\n} & Omit<HTMLAttributes<HTMLDivElement>, \"className\" | \"title\">;\n\n/** One collapsible section of an `Accordion`. */\nexport function AccordionItem({\n value,\n title,\n children,\n disabled = false,\n className,\n ...props\n}: AccordionItemProps) {\n const { value: openValues, toggle, baseId, headingLevel } = useAccordionContext(\n \"AccordionItem\",\n );\n const isOpen = openValues.includes(value);\n\n const trigger = (\n <button\n type=\"button\"\n id={triggerId(baseId, value)}\n className=\"sh-accordion__trigger\"\n aria-expanded={isOpen}\n aria-controls={panelId(baseId, value)}\n disabled={disabled}\n onClick={() => toggle(value)}\n >\n <span className=\"sh-accordion__title\">{title}</span>\n <ChevronIcon />\n </button>\n );\n\n return (\n <div\n className={[\n \"sh-accordion__item\",\n isOpen && \"sh-accordion__item--open\",\n disabled && \"sh-accordion__item--disabled\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n {...props}\n >\n {/*\n A real heading, at the rank the page needs, so the sections appear in\n the document outline and in screen-reader heading navigation.\n */}\n {createElement(`h${headingLevel}`, { className: \"sh-accordion__heading\" }, trigger)}\n\n {/*\n Kept mounted so the open/close transition has something to animate.\n The panel collapses to zero height and its contents are taken out of\n the accessibility tree and tab order by `visibility` — see the CSS.\n */}\n <div\n id={panelId(baseId, value)}\n className=\"sh-accordion__panel\"\n role=\"region\"\n aria-labelledby={triggerId(baseId, value)}\n >\n <div className=\"sh-accordion__panel-inner\">\n <div className=\"sh-accordion__content\">{children}</div>\n </div>\n </div>\n </div>\n );\n}\n","import { createContext, useContext } from \"react\";\n\nexport type StepperOrientation = \"horizontal\" | \"vertical\";\n\n/** Derived from position against `activeStep`, unless a step overrides it. */\nexport type StepStatus = \"complete\" | \"current\" | \"upcoming\" | \"error\";\n\nexport type StepContextValue = {\n /** Zero-based position, used for the default indicator number. */\n index: number;\n /** True for the final step, which has no connector after it. */\n isLast: boolean;\n status: StepStatus;\n orientation: StepperOrientation;\n};\n\nexport const StepContext = createContext<StepContextValue | undefined>(undefined);\n\n/** Reads the surrounding `Stepper`, failing loudly rather than silently. */\nexport function useStepContext(component: string): StepContextValue {\n const context = useContext(StepContext);\n\n if (!context) {\n throw new Error(`<${component}> must be rendered inside <Stepper>.`);\n }\n\n return context;\n}\n","import { Children, isValidElement } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\n\nimport { StepContext } from \"./stepper.context\";\nimport type { StepperOrientation, StepStatus } from \"./stepper.context\";\nimport \"./Stepper.css\";\n\nexport type StepperProps = {\n children?: ReactNode;\n /** Zero-based index of the step in progress. */\n activeStep?: number;\n /** Layout direction. Defaults to `horizontal`. */\n orientation?: StepperOrientation;\n /** Accessible name for the list. Defaults to \"Progress\". */\n \"aria-label\"?: string;\n className?: string;\n} & Omit<HTMLAttributes<HTMLOListElement>, \"className\">;\n\n/**\n * Ordered progress through a multi-step flow.\n *\n * An `ol`, because the order is the meaning. Each step's status is derived\n * from its position against `activeStep` — the position is what makes a step\n * complete or upcoming, so callers shouldn't have to restate it.\n *\n * It's a progress indicator, not a `nav` landmark: steps are only navigation\n * when they're given an `onClick`, and a landmark per progress bar would\n * clutter the landmark list.\n */\nexport function Stepper({\n children,\n activeStep = 0,\n orientation = \"horizontal\",\n \"aria-label\": ariaLabel = \"Progress\",\n className,\n ...props\n}: StepperProps) {\n const steps = Children.toArray(children).filter(isValidElement);\n\n const statusFor = (index: number): StepStatus => {\n if (index < activeStep) return \"complete\";\n if (index === activeStep) return \"current\";\n return \"upcoming\";\n };\n\n return (\n <ol\n className={[\"sh-stepper\", `sh-stepper--${orientation}`, className]\n .filter(Boolean)\n .join(\" \")}\n aria-label={ariaLabel}\n {...props}\n >\n {steps.map((step, index) => (\n <StepContext.Provider\n key={step.key ?? index}\n value={{\n index,\n isLast: index === steps.length - 1,\n status: statusFor(index),\n orientation,\n }}\n >\n {step}\n </StepContext.Provider>\n ))}\n </ol>\n );\n}\n","import type { ReactNode } from \"react\";\n\nimport { useStepContext } from \"./stepper.context\";\nimport type { StepStatus } from \"./stepper.context\";\nimport \"./Stepper.css\";\n\nconst CheckIcon = () => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path d=\"M3.5 8.5l3 3 6-6.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n);\n\nconst ErrorIcon = () => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} aria-hidden=\"true\">\n <path d=\"M8 4.5v4.5\" strokeLinecap=\"round\" />\n <circle cx=\"8\" cy=\"11.6\" r=\"0.9\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n);\n\nexport type StepProps = {\n /** Short name for the step. */\n title: ReactNode;\n /** Optional detail below the title. */\n description?: ReactNode;\n /** Overrides the status derived from position. */\n status?: StepStatus;\n /** Replaces the number or state glyph in the indicator. */\n icon?: ReactNode;\n /** Makes the step activatable, for going back to an earlier one. */\n onClick?: () => void;\n /** Prevents activation. Only meaningful alongside `onClick`. */\n disabled?: boolean;\n className?: string;\n};\n\n/** One step in a `Stepper`. */\nexport function Step({\n title,\n description,\n status,\n icon,\n onClick,\n disabled = false,\n className,\n}: StepProps) {\n const { index, isLast, status: derivedStatus, orientation } = useStepContext(\"Step\");\n const resolved = status ?? derivedStatus;\n\n const indicator =\n icon ??\n (resolved === \"complete\" ? (\n <CheckIcon />\n ) : resolved === \"error\" ? (\n <ErrorIcon />\n ) : (\n // Steps are numbered from one, whatever their array index.\n index + 1\n ));\n\n const content = (\n <>\n <span className=\"sh-step__indicator\">{indicator}</span>\n <span className=\"sh-step__text\">\n <span className=\"sh-step__title\">{title}</span>\n {description && <span className=\"sh-step__description\">{description}</span>}\n </span>\n </>\n );\n\n return (\n <li\n className={[\n \"sh-step\",\n `sh-step--${resolved}`,\n `sh-step--${orientation}`,\n isLast && \"sh-step--last\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n {onClick ? (\n <button\n type=\"button\"\n className=\"sh-step__body sh-step__body--interactive\"\n onClick={onClick}\n disabled={disabled}\n // Announced as \"current step\" rather than just being styled that way.\n aria-current={resolved === \"current\" ? \"step\" : undefined}\n >\n {content}\n </button>\n ) : (\n <span\n className=\"sh-step__body\"\n aria-current={resolved === \"current\" ? \"step\" : undefined}\n >\n {content}\n </span>\n )}\n\n {/*\n Decorative: the ordered list already conveys sequence, so the line\n between steps is presentation only.\n */}\n {!isLast && <span className=\"sh-step__connector\" aria-hidden=\"true\" />}\n </li>\n );\n}\n","import { createContext, useContext } from \"react\";\nimport type { ReactNode } from \"react\";\n\nexport type BreadcrumbContextValue = {\n /** True for the trailing crumb, which is the current page. */\n isLast: boolean;\n /** Rendered between crumbs. Decorative — always `aria-hidden`. */\n separator: ReactNode;\n};\n\nexport const BreadcrumbContext = createContext<BreadcrumbContextValue | undefined>(undefined);\n\n/** Reads the surrounding `Breadcrumb`, failing loudly rather than silently. */\nexport function useBreadcrumbContext(component: string): BreadcrumbContextValue {\n const context = useContext(BreadcrumbContext);\n\n if (!context) {\n throw new Error(`<${component}> must be rendered inside <Breadcrumb>.`);\n }\n\n return context;\n}\n","import { Children, isValidElement } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\n\nimport { BreadcrumbContext } from \"./breadcrumb.context\";\nimport \"./Breadcrumb.css\";\n\nconst ChevronIcon = () => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path d=\"M6 3.5 10.5 8 6 12.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n);\n\nexport type BreadcrumbProps = {\n children?: ReactNode;\n /** Rendered between crumbs. Defaults to a chevron. */\n separator?: ReactNode;\n /** Accessible name for the landmark. Defaults to \"Breadcrumb\". */\n \"aria-label\"?: string;\n className?: string;\n} & Omit<HTMLAttributes<HTMLElement>, \"className\">;\n\n/**\n * Trail of links showing where the current page sits in the hierarchy.\n *\n * A `nav` landmark wrapping an ordered list, since the order is meaningful.\n * The trailing crumb is treated as the current page automatically — the\n * position in the list is what makes it current, so callers shouldn't have to\n * repeat that.\n */\nexport function Breadcrumb({\n children,\n separator = <ChevronIcon />,\n \"aria-label\": ariaLabel = \"Breadcrumb\",\n className,\n ...props\n}: BreadcrumbProps) {\n const crumbs = Children.toArray(children).filter(isValidElement);\n\n return (\n <nav\n className={[\"sh-breadcrumb\", className].filter(Boolean).join(\" \")}\n aria-label={ariaLabel}\n {...props}\n >\n <ol className=\"sh-breadcrumb__list\">\n {crumbs.map((crumb, index) => (\n <BreadcrumbContext.Provider\n key={crumb.key ?? index}\n value={{ isLast: index === crumbs.length - 1, separator }}\n >\n {crumb}\n </BreadcrumbContext.Provider>\n ))}\n </ol>\n </nav>\n );\n}\n","import type { AnchorHTMLAttributes, ReactNode } from \"react\";\n\nimport { useBreadcrumbContext } from \"./breadcrumb.context\";\nimport \"./Breadcrumb.css\";\n\nexport type BreadcrumbItemProps = {\n children?: ReactNode;\n /** Destination. Omit to render plain text, or to supply your own link. */\n href?: string;\n /**\n * Marks this crumb as the current page. Defaults to true for the trailing\n * crumb; set it explicitly to override that.\n */\n current?: boolean;\n className?: string;\n} & Omit<AnchorHTMLAttributes<HTMLAnchorElement>, \"href\" | \"className\">;\n\n/**\n * One crumb in a `Breadcrumb`.\n *\n * Renders an anchor when given an `href`, plain text otherwise. The current\n * crumb is never a link — linking to the page you're already on is noise —\n * and carries `aria-current=\"page\"`.\n *\n * For router links, omit `href` and pass your own element as children; it's\n * rendered as-is. The current crumb shouldn't be a link anyway, so that only\n * applies to the earlier ones.\n */\nexport function BreadcrumbItem({\n children,\n href,\n current,\n className,\n ...props\n}: BreadcrumbItemProps) {\n const { isLast, separator } = useBreadcrumbContext(\"BreadcrumbItem\");\n const isCurrent = current ?? isLast;\n\n return (\n <li className={[\"sh-breadcrumb__item\", className].filter(Boolean).join(\" \")}>\n {isCurrent ? (\n <span className=\"sh-breadcrumb__current\" aria-current=\"page\">\n {children}\n </span>\n ) : href ? (\n <a className=\"sh-breadcrumb__link\" href={href} {...props}>\n {children}\n </a>\n ) : (\n <span className=\"sh-breadcrumb__text\">{children}</span>\n )}\n\n {/* Decorative: the list structure already conveys the hierarchy. */}\n {!isLast && (\n <span className=\"sh-breadcrumb__separator\" aria-hidden=\"true\">\n {separator}\n </span>\n )}\n </li>\n );\n}\n","import { createContext, useContext } from \"react\";\n\nexport type TabsOrientation = \"horizontal\" | \"vertical\";\n\n/**\n * `automatic` selects a tab as soon as it's focused — the ARIA-preferred\n * behaviour when panels are cheap to render. `manual` moves focus with the\n * arrow keys and only selects on Enter/Space, which is what you want when\n * switching panels is expensive.\n */\nexport type TabsActivation = \"automatic\" | \"manual\";\n\nexport type TabsContextValue = {\n /** Value of the currently selected tab. */\n value: string | undefined;\n /** Selects a tab by value. */\n select: (value: string) => void;\n /** Prefix for the generated tab/panel ids that tie the two together. */\n baseId: string;\n orientation: TabsOrientation;\n activation: TabsActivation;\n};\n\nexport const TabsContext = createContext<TabsContextValue | undefined>(undefined);\n\n/** Reads the surrounding `Tabs` context, failing loudly rather than silently. */\nexport function useTabsContext(component: string): TabsContextValue {\n const context = useContext(TabsContext);\n\n if (!context) {\n throw new Error(`<${component}> must be rendered inside <Tabs>.`);\n }\n\n return context;\n}\n\n/** Ids are derived rather than registered, so tab and panel always agree. */\nexport const tabId = (baseId: string, value: string) => `${baseId}-tab-${value}`;\nexport const panelId = (baseId: string, value: string) => `${baseId}-panel-${value}`;\n","import { useId, useState } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\n\nimport { TabsContext } from \"./tabs.context\";\nimport type { TabsActivation, TabsOrientation } from \"./tabs.context\";\nimport \"./Tabs.css\";\n\nexport type TabsProps = {\n children?: ReactNode;\n /** Selected tab value — makes the component controlled. */\n value?: string;\n /** Initially selected tab when uncontrolled. */\n defaultValue?: string;\n /** Fired with the newly selected tab's value. */\n onChange?: (value: string) => void;\n /** Layout direction. Defaults to `horizontal`. */\n orientation?: TabsOrientation;\n /** Whether arrowing to a tab selects it. Defaults to `automatic`. */\n activation?: TabsActivation;\n className?: string;\n} & Omit<HTMLAttributes<HTMLDivElement>, \"className\" | \"onChange\">;\n\n/**\n * Root of the tabs widget: owns the selection and shares it with `TabList`,\n * `Tab`, and `TabPanel` through context.\n */\nexport function Tabs({\n children,\n value,\n defaultValue,\n onChange,\n orientation = \"horizontal\",\n activation = \"automatic\",\n className,\n ...props\n}: TabsProps) {\n const baseId = useId();\n\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n const isControlled = value !== undefined;\n const selected = isControlled ? value : uncontrolledValue;\n\n const select = (next: string) => {\n if (!isControlled) setUncontrolledValue(next);\n onChange?.(next);\n };\n\n const classes = [\"sh-tabs\", `sh-tabs--${orientation}`, className].filter(Boolean).join(\" \");\n\n return (\n <TabsContext.Provider value={{ value: selected, select, baseId, orientation, activation }}>\n <div className={classes} {...props}>\n {children}\n </div>\n </TabsContext.Provider>\n );\n}\n","import { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport type { CSSProperties, HTMLAttributes, KeyboardEvent, ReactNode } from \"react\";\n\nimport { useTabsContext } from \"./tabs.context\";\nimport \"./Tabs.css\";\n\n/** Measuring has to happen before paint, but useLayoutEffect warns under SSR. */\nconst useMeasureEffect = typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\ntype Indicator = {\n offset: number;\n size: number;\n /** False on the first measurement, so the indicator doesn't fly in on mount. */\n animated: boolean;\n};\n\nexport type TabListProps = {\n children?: ReactNode;\n /** Accessible name for the tab list. */\n \"aria-label\"?: string;\n className?: string;\n} & Omit<HTMLAttributes<HTMLDivElement>, \"className\">;\n\n/**\n * Row (or column) of `Tab`s.\n *\n * Owns the keyboard behaviour the ARIA tabs pattern requires — arrow keys to\n * move, Home/End to jump — because unlike radios there's no native element\n * that provides it. Roving tabindex lives on `Tab` itself.\n *\n * Also owns the sliding selection indicator. Unlike `SegmentedControl`, whose\n * segments are equal width and can be positioned with pure CSS, tabs are\n * content-sized, so the selected tab has to be measured.\n */\nexport function TabList({ children, className, onKeyDown, ...props }: TabListProps) {\n const { value, orientation, activation, select } = useTabsContext(\"TabList\");\n const listRef = useRef<HTMLDivElement>(null);\n const [indicator, setIndicator] = useState<Indicator | null>(null);\n\n const isVertical = orientation === \"vertical\";\n\n useMeasureEffect(() => {\n const list = listRef.current;\n if (!list) return;\n\n // Matched by scanning rather than a selector, so arbitrary `value` strings\n // don't need escaping.\n const tabs = Array.from(list.querySelectorAll<HTMLElement>('[role=\"tab\"]'));\n const selectedTab = tabs.find((tab) => tab.dataset.value === value);\n\n if (!selectedTab) {\n setIndicator(null);\n return;\n }\n\n const measure = () => {\n const offset = isVertical ? selectedTab.offsetTop : selectedTab.offsetLeft;\n const size = isVertical ? selectedTab.offsetHeight : selectedTab.offsetWidth;\n // `prev !== null` is what distinguishes the first placement from a move.\n setIndicator((prev) => ({ offset, size, animated: prev !== null }));\n };\n\n measure();\n\n // Re-measure when the list reflows — a resize, a font swap, a label change.\n if (typeof ResizeObserver === \"undefined\") return;\n\n const observer = new ResizeObserver(measure);\n observer.observe(list);\n observer.observe(selectedTab);\n return () => observer.disconnect();\n }, [value, isVertical]);\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented || !listRef.current) return;\n\n const nextKey = isVertical ? \"ArrowDown\" : \"ArrowRight\";\n const prevKey = isVertical ? \"ArrowUp\" : \"ArrowLeft\";\n\n const handled = [nextKey, prevKey, \"Home\", \"End\"];\n if (!handled.includes(event.key)) return;\n\n /*\n * Read order from the DOM rather than tracking registrations: it stays\n * correct as children change, and `:not([disabled])` skips unusable tabs\n * without any extra bookkeeping.\n */\n const tabs = Array.from(\n listRef.current.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]:not([disabled])'),\n );\n if (tabs.length === 0) return;\n\n const current = tabs.indexOf(document.activeElement as HTMLButtonElement);\n\n let index: number;\n if (event.key === \"Home\") index = 0;\n else if (event.key === \"End\") index = tabs.length - 1;\n else if (current === -1) index = 0;\n // Wrap at both ends, as the pattern specifies.\n else if (event.key === nextKey) index = (current + 1) % tabs.length;\n else index = (current - 1 + tabs.length) % tabs.length;\n\n const target = tabs[index];\n if (!target) return;\n\n // Stop the arrow keys scrolling the page.\n event.preventDefault();\n target.focus();\n\n if (activation === \"automatic\") {\n const nextValue = target.dataset.value;\n if (nextValue !== undefined) select(nextValue);\n }\n };\n\n return (\n <div\n ref={listRef}\n className={[\"sh-tabs__list\", className].filter(Boolean).join(\" \")}\n role=\"tablist\"\n aria-orientation={orientation}\n onKeyDown={handleKeyDown}\n {...props}\n >\n {children}\n {indicator && (\n <span\n className={[\n \"sh-tabs__indicator\",\n indicator.animated && \"sh-tabs__indicator--animated\",\n ]\n .filter(Boolean)\n .join(\" \")}\n aria-hidden=\"true\"\n style={\n {\n \"--sh-tabs-indicator-offset\": `${indicator.offset}px`,\n \"--sh-tabs-indicator-size\": `${indicator.size}px`,\n } as CSSProperties\n }\n />\n )}\n </div>\n );\n}\n","import type { ButtonHTMLAttributes, ReactNode } from \"react\";\n\nimport { panelId, tabId, useTabsContext } from \"./tabs.context\";\nimport \"./Tabs.css\";\n\nexport type TabProps = {\n /** Ties this tab to the `TabPanel` with the same value. */\n value: string;\n children?: ReactNode;\n className?: string;\n} & Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"value\" | \"className\">;\n\n/** A single tab. Must be rendered inside a `TabList`. */\nexport function Tab({ value, children, className, disabled, onClick, ...props }: TabProps) {\n const { value: selected, select, baseId } = useTabsContext(\"Tab\");\n const isSelected = selected === value;\n\n const classes = [\"sh-tabs__tab\", isSelected && \"sh-tabs__tab--selected\", className]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <button\n type=\"button\"\n role=\"tab\"\n id={tabId(baseId, value)}\n className={classes}\n // Read back by TabList's keyboard handler to resolve the focused tab.\n data-value={value}\n aria-selected={isSelected}\n aria-controls={panelId(baseId, value)}\n /*\n * Roving tabindex: only the selected tab is in the tab order, so Tab\n * moves past the whole widget rather than through every tab. The arrow\n * keys are what move between them.\n */\n tabIndex={isSelected ? 0 : -1}\n disabled={disabled}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) select(value);\n }}\n {...props}\n >\n {children}\n </button>\n );\n}\n","import type { HTMLAttributes, ReactNode } from \"react\";\n\nimport { panelId, tabId, useTabsContext } from \"./tabs.context\";\nimport \"./Tabs.css\";\n\nexport type TabPanelProps = {\n /** Ties this panel to the `Tab` with the same value. */\n value: string;\n children?: ReactNode;\n /**\n * Keeps the panel mounted while hidden, preserving its state (scroll\n * position, form input, in-flight requests). Off by default so unselected\n * panels cost nothing.\n */\n keepMounted?: boolean;\n className?: string;\n} & Omit<HTMLAttributes<HTMLDivElement>, \"className\">;\n\n/** Content for the `Tab` with the same value. */\nexport function TabPanel({\n value,\n children,\n keepMounted = false,\n className,\n ...props\n}: TabPanelProps) {\n const { value: selected, baseId } = useTabsContext(\"TabPanel\");\n const isSelected = selected === value;\n\n if (!isSelected && !keepMounted) return null;\n\n return (\n <div\n id={panelId(baseId, value)}\n className={[\"sh-tabs__panel\", className].filter(Boolean).join(\" \")}\n role=\"tabpanel\"\n aria-labelledby={tabId(baseId, value)}\n // `hidden` rather than unmounting, so kept-alive panels stay out of the\n // accessibility tree and the tab order while retaining their state.\n hidden={!isSelected}\n /*\n * The panel is focusable so keyboard users can reach and scroll it after\n * arrowing through the tabs — its content may hold nothing focusable.\n */\n tabIndex={0}\n {...props}\n >\n {children}\n </div>\n );\n}\n","import type { CSSProperties, HTMLAttributes } from \"react\";\n\nimport type { SkeletonAnimation, SkeletonVariant } from \"./skeleton.tokens\";\nimport \"./Skeleton.css\";\n\n/** Bare numbers are pixels; strings pass through as authored (\"60%\", \"4rem\"). */\nconst toLength = (value: number | string | undefined) =>\n typeof value === \"number\" ? `${value}px` : value;\n\nexport type SkeletonProps = {\n /** Shape of the placeholder. Defaults to `text`. */\n variant?: SkeletonVariant;\n /** Width. A number is treated as pixels. */\n width?: number | string;\n /** Height. A number is treated as pixels. Circular falls back to `width`. */\n height?: number | string;\n /** Number of text lines to render. Only meaningful for `text`. */\n lines?: number;\n /** Placeholder motion. Defaults to `pulse`. */\n animation?: SkeletonAnimation;\n className?: string;\n} & Omit<HTMLAttributes<HTMLDivElement>, \"className\">;\n\n/**\n * Placeholder shown while content loads.\n *\n * Hidden from assistive tech: a screen reader shouldn't announce a wall of\n * empty boxes. The surrounding region is what should carry the loading state —\n * `aria-busy`, or a `Spinner`/live region alongside it.\n */\nexport function Skeleton({\n variant = \"text\",\n width,\n height,\n lines = 1,\n animation = \"pulse\",\n className,\n ...props\n}: SkeletonProps) {\n const itemClasses = [\n \"sh-skeleton\",\n `sh-skeleton--${variant}`,\n `sh-skeleton--${animation}`,\n ].join(\" \");\n\n const style: CSSProperties = {\n width: toLength(width),\n // A circle with only a width would otherwise collapse to zero height.\n height: toLength(height ?? (variant === \"circular\" ? width : undefined)),\n };\n\n // Multiple lines only make sense for text, and a paragraph whose last line\n // runs the full width doesn't read as text.\n if (variant === \"text\" && lines > 1) {\n return (\n <div\n className={[\"sh-skeleton-lines\", className].filter(Boolean).join(\" \")}\n aria-hidden=\"true\"\n {...props}\n >\n {Array.from({ length: lines }, (_, index) => (\n <span\n key={index}\n className={itemClasses}\n style={index === lines - 1 ? { ...style, width: \"60%\" } : style}\n />\n ))}\n </div>\n );\n }\n\n return (\n <span\n className={[itemClasses, className].filter(Boolean).join(\" \")}\n style={style}\n aria-hidden=\"true\"\n {...props}\n />\n );\n}\n","export const skeletonVariants = [\"text\", \"rectangular\", \"circular\"] as const;\n\nexport type SkeletonVariant = (typeof skeletonVariants)[number];\n\nexport const skeletonAnimations = [\"pulse\", \"wave\", \"none\"] as const;\n\nexport type SkeletonAnimation = (typeof skeletonAnimations)[number];\n","import { useId } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\n\nimport type { SpinnerSize } from \"./spinner.tokens\";\nimport \"./Spinner.css\";\n\nexport type SpinnerProps = {\n /** Size of the ring. Defaults to `md`. */\n size?: SpinnerSize;\n /**\n * What's being waited on. Always in the accessibility tree — a spinner with\n * no name announces nothing. Defaults to \"Loading\".\n */\n label?: ReactNode;\n /** Also renders the label visibly beside the ring. */\n showLabel?: boolean;\n className?: string;\n} & Omit<HTMLAttributes<HTMLSpanElement>, \"className\" | \"role\">;\n\n/**\n * Indeterminate loading indicator.\n *\n * Takes its colour from `currentColor`, so it inherits whatever it's placed\n * in — a button, a link, a paragraph — instead of needing a colour prop.\n */\nexport function Spinner({\n size = \"md\",\n label = \"Loading\",\n showLabel = false,\n className,\n ...props\n}: SpinnerProps) {\n const labelId = useId();\n\n const classes = [\n \"sh-spinner\",\n `sh-spinner--${size}`,\n showLabel && \"sh-spinner--with-label\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n /*\n * `aria-labelledby` rather than relying on the text inside: `status` isn't\n * a name-from-content role, so without this the element is an anonymous\n * status. Pointing at the label element works for any ReactNode, which\n * `aria-label` (string-only) would not.\n */\n <span className={classes} role=\"status\" aria-labelledby={labelId} {...props}>\n <span className=\"sh-spinner__ring\" aria-hidden=\"true\" />\n {/*\n Present either way: hidden visually when `showLabel` is false, but\n never removed, so the status always has a name and something to\n announce when it appears.\n */}\n <span\n id={labelId}\n className={showLabel ? \"sh-spinner__label\" : \"sh-spinner__label--visually-hidden\"}\n >\n {label}\n </span>\n </span>\n );\n}\n","export const spinnerSizes = [\"sm\", \"md\", \"lg\"] as const;\n\nexport type SpinnerSize = (typeof spinnerSizes)[number];\n","import { useId } from \"react\";\nimport type { CSSProperties, HTMLAttributes, ReactNode } from \"react\";\n\nimport type { ProgressBarSize } from \"./progressBar.tokens\";\nimport \"./ProgressBar.css\";\n\nexport type ProgressBarProps = {\n /**\n * Progress so far, between `0` and `max`. Omit for an indeterminate bar —\n * for work whose duration isn't known yet.\n */\n value?: number;\n /** Upper bound of `value`. Defaults to `100`. */\n max?: number;\n /** Visible label above the track. Provide this or `aria-label`. */\n label?: ReactNode;\n /** Shows the percentage beside the label. Ignored when indeterminate. */\n showValue?: boolean;\n /**\n * Formats the displayed value. Also drives `aria-valuetext`, so screen\n * readers announce \"3 of 8 files\" rather than a bare percentage.\n */\n formatValue?: (value: number, max: number) => string;\n /** Track thickness. Defaults to `md`. */\n size?: ProgressBarSize;\n /** Accessible name when there's no visible `label`. */\n \"aria-label\"?: string;\n className?: string;\n} & Omit<HTMLAttributes<HTMLDivElement>, \"className\" | \"role\">;\n\n/**\n * Horizontal progress indicator.\n *\n * Renders `role=\"progressbar\"`, with `aria-valuenow` omitted when\n * indeterminate — that absence is what tells assistive tech the duration\n * isn't known, rather than it sitting at zero.\n */\nexport function ProgressBar({\n value,\n max = 100,\n label,\n showValue = false,\n formatValue,\n size = \"md\",\n \"aria-label\": ariaLabel,\n className,\n ...props\n}: ProgressBarProps) {\n const labelId = useId();\n\n const isIndeterminate = value === undefined;\n\n // Guard both ends: a value outside the range would otherwise overflow the\n // track, and a non-positive max would divide by zero.\n const safeMax = max > 0 ? max : 0;\n const clamped = isIndeterminate ? 0 : Math.min(Math.max(value, 0), safeMax);\n const percent = safeMax === 0 ? 0 : (clamped / safeMax) * 100;\n\n const displayValue = formatValue\n ? formatValue(clamped, safeMax)\n : `${Math.round(percent)}%`;\n\n const classes = [\n \"sh-progress\",\n `sh-progress--${size}`,\n isIndeterminate && \"sh-progress--indeterminate\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div className={classes} {...props}>\n {(label || (showValue && !isIndeterminate)) && (\n <span className=\"sh-progress__header\">\n {label && (\n <span className=\"sh-progress__label\" id={labelId}>\n {label}\n </span>\n )}\n {showValue && !isIndeterminate && (\n <span className=\"sh-progress__value\">{displayValue}</span>\n )}\n </span>\n )}\n\n <div\n className=\"sh-progress__track\"\n role=\"progressbar\"\n aria-label={label ? undefined : ariaLabel}\n aria-labelledby={label ? labelId : undefined}\n aria-valuemin={0}\n aria-valuemax={safeMax}\n // Omitted entirely when indeterminate — that's the signal.\n aria-valuenow={isIndeterminate ? undefined : clamped}\n aria-valuetext={isIndeterminate ? undefined : formatValue ? displayValue : undefined}\n >\n <div\n className=\"sh-progress__bar\"\n style={{ \"--sh-progress-fill\": `${percent}%` } as CSSProperties}\n />\n </div>\n </div>\n );\n}\n","export const progressBarSizes = [\"sm\", \"md\", \"lg\"] as const;\n\nexport type ProgressBarSize = (typeof progressBarSizes)[number];\n","import type { HTMLAttributes, ReactNode } from \"react\";\n\nimport type { AlertVariant } from \"./alert.tokens\";\nimport \"./Alert.css\";\n\nconst icons: Record<AlertVariant, ReactNode> = {\n success: (\n <svg viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.6} aria-hidden=\"true\">\n <circle cx=\"10\" cy=\"10\" r=\"7.5\" />\n <path d=\"M6.75 10.25l2.25 2.25 4.25-4.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n ),\n info: (\n <svg viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.6} aria-hidden=\"true\">\n <circle cx=\"10\" cy=\"10\" r=\"7.5\" />\n <path d=\"M10 9v4.5\" strokeLinecap=\"round\" />\n <circle cx=\"10\" cy=\"6.4\" r=\"0.9\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n ),\n warning: (\n <svg viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.6} aria-hidden=\"true\">\n <path d=\"M10 2.8 18 16.5H2L10 2.8Z\" strokeLinejoin=\"round\" />\n <path d=\"M10 8v3.5\" strokeLinecap=\"round\" />\n <circle cx=\"10\" cy=\"13.9\" r=\"0.9\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n ),\n error: (\n <svg viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.6} aria-hidden=\"true\">\n <circle cx=\"10\" cy=\"10\" r=\"7.5\" />\n <path d=\"M7.5 7.5l5 5M12.5 7.5l-5 5\" strokeLinecap=\"round\" />\n </svg>\n ),\n};\n\nconst CloseIcon = () => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.75} aria-hidden=\"true\">\n <path d=\"M4.5 4.5l7 7M11.5 4.5l-7 7\" strokeLinecap=\"round\" />\n </svg>\n);\n\n/**\n * Errors and warnings interrupt; confirmations and information shouldn't.\n * `alert` is assertive and cuts off whatever a screen reader is saying, so\n * it's reserved for the two that warrant it.\n */\nconst defaultRole: Record<AlertVariant, \"alert\" | \"status\"> = {\n success: \"status\",\n info: \"status\",\n warning: \"alert\",\n error: \"alert\",\n};\n\nexport type AlertProps = {\n /** Status this alert conveys. Defaults to `info`. */\n variant?: AlertVariant;\n /** Bolded heading above the body. */\n title?: ReactNode;\n /** Body content. */\n children?: ReactNode;\n /** Replaces the variant's icon, or hides it entirely with `false`. */\n icon?: ReactNode | false;\n /** Renders a dismiss button and is called when it's activated. */\n onDismiss?: () => void;\n /** Accessible name for the dismiss button. Defaults to \"Dismiss\". */\n dismissLabel?: string;\n /**\n * Overrides how assistive tech announces this. Defaults to `alert` for\n * warning/error and `status` for success/info.\n */\n role?: \"alert\" | \"status\" | \"none\";\n} & Omit<HTMLAttributes<HTMLDivElement>, \"title\" | \"role\">;\n\n/** Coloured banner conveying the outcome or status of something. */\nexport function Alert({\n variant = \"info\",\n title,\n children,\n icon,\n onDismiss,\n dismissLabel = \"Dismiss\",\n role,\n className,\n ...props\n}: AlertProps) {\n const classes = [\"sh-alert\", `sh-alert--${variant}`, className].filter(Boolean).join(\" \");\n const resolvedIcon = icon === undefined ? icons[variant] : icon;\n\n return (\n <div className={classes} role={role ?? defaultRole[variant]} {...props}>\n {resolvedIcon !== false && <span className=\"sh-alert__icon\">{resolvedIcon}</span>}\n\n <div className=\"sh-alert__content\">\n {title && <p className=\"sh-alert__title\">{title}</p>}\n {children && <div className=\"sh-alert__body\">{children}</div>}\n </div>\n\n {onDismiss && (\n <button\n type=\"button\"\n className=\"sh-alert__dismiss\"\n onClick={onDismiss}\n aria-label={dismissLabel}\n >\n <CloseIcon />\n </button>\n )}\n </div>\n );\n}\n","export const alertVariants = [\"success\", \"info\", \"warning\", \"error\"] as const;\n\nexport type AlertVariant = (typeof alertVariants)[number];\n","/**\n * Matches a file against an `accept` string (the same syntax as the `accept`\n * attribute: \".pdf,image/*,text/csv\").\n *\n * The browser applies `accept` to the file picker, but **not** to drag-and-drop\n * — dropped files arrive unfiltered — so this runs on both paths to keep them\n * behaving the same.\n */\nexport function isFileAccepted(file: File, accept?: string): boolean {\n if (!accept) return true;\n\n const patterns = accept\n .split(\",\")\n .map((pattern) => pattern.trim().toLowerCase())\n .filter(Boolean);\n\n if (patterns.length === 0) return true;\n\n const name = file.name.toLowerCase();\n const type = file.type.toLowerCase();\n\n return patterns.some((pattern) => {\n // Extension: \".pdf\"\n if (pattern.startsWith(\".\")) return name.endsWith(pattern);\n // Wildcard MIME: \"image/*\" — compare against the \"image/\" prefix.\n if (pattern.endsWith(\"/*\")) return type.startsWith(pattern.slice(0, -1));\n // Exact MIME: \"text/csv\"\n return type === pattern;\n });\n}\n\n/** \"1.4 MB\" — for listing the files a user has picked. */\nexport function formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n\n const units = [\"KB\", \"MB\", \"GB\", \"TB\"];\n let size = bytes / 1024;\n let unit = 0;\n\n while (size >= 1024 && unit < units.length - 1) {\n size /= 1024;\n unit += 1;\n }\n\n // One decimal place, but no trailing \".0\".\n const rounded = Math.round(size * 10) / 10;\n return `${rounded} ${units[unit]}`;\n}\n","import { useId, useRef, useState } from \"react\";\nimport type { ChangeEvent, DragEvent, ReactNode } from \"react\";\n\nimport { formatFileSize, isFileAccepted } from \"./isFileAccepted\";\nimport \"./FileDrop.css\";\n\nconst UploadIcon = () => (\n <svg\n className=\"sh-filedrop__icon\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 16V4m0 0L8 8m4-4 4 4\" />\n <path d=\"M4 15v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3\" />\n </svg>\n);\n\nconst RemoveIcon = () => (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.75} aria-hidden=\"true\">\n <path d=\"M4.5 4.5l7 7M11.5 4.5l-7 7\" strokeLinecap=\"round\" />\n </svg>\n);\n\nexport type FileDropProps = {\n /** Visible label for the field. */\n label?: ReactNode;\n /** Hint shown below the drop zone. Replaced by `error` when that's set. */\n helperText?: ReactNode;\n /** Validation message. Its presence also marks the field invalid. */\n error?: ReactNode;\n /** Prompt inside the drop zone. */\n placeholder?: ReactNode;\n /** Allowed types, same syntax as the `accept` attribute: \".pdf,image/*\". */\n accept?: string;\n /** Allow picking more than one file. */\n multiple?: boolean;\n /** Selected files — makes the component controlled. */\n value?: File[];\n /** Initial files when uncontrolled. */\n defaultValue?: File[];\n /** Fired with the full list of selected files. */\n onChange?: (files: File[]) => void;\n /** Fired with files rejected by `accept`, so they're never dropped silently. */\n onReject?: (files: File[]) => void;\n /** Hides the list of selected files. */\n hideFileList?: boolean;\n disabled?: boolean;\n name?: string;\n /** Accessible name when there's no visible `label`. */\n \"aria-label\"?: string;\n /** Class for the wrapper. Use `inputClassName` for the file input. */\n className?: string;\n inputClassName?: string;\n};\n\n/**\n * File picker that accepts both a click and a drag-and-drop.\n *\n * A real `<input type=\"file\">` wrapped in a `<label>`, so clicking anywhere in\n * the zone opens the picker and the control stays keyboard-operable without\n * any JavaScript. The zone itself is painted alongside it.\n */\nexport function FileDrop({\n label,\n helperText,\n error,\n placeholder = \"Drag files here, or click to browse\",\n accept,\n multiple = false,\n value,\n defaultValue,\n onChange,\n onReject,\n hideFileList = false,\n disabled = false,\n name,\n \"aria-label\": ariaLabel,\n className,\n inputClassName,\n}: FileDropProps) {\n const inputId = useId();\n const messageId = useId();\n\n const [uncontrolledFiles, setUncontrolledFiles] = useState<File[]>(defaultValue ?? []);\n const isControlled = value !== undefined;\n const files = isControlled ? value : uncontrolledFiles;\n\n const [isDragging, setIsDragging] = useState(false);\n // dragenter/dragleave also fire for child elements, so a boolean alone\n // flickers. Counting entries against leaves is what keeps the state stable.\n const dragDepth = useRef(0);\n\n const invalid = Boolean(error);\n const message = error ?? helperText;\n\n const commit = (next: File[]) => {\n if (!isControlled) setUncontrolledFiles(next);\n onChange?.(next);\n };\n\n const acceptFiles = (incoming: File[]) => {\n const allowed = incoming.filter((file) => isFileAccepted(file, accept));\n const rejected = incoming.filter((file) => !isFileAccepted(file, accept));\n\n if (rejected.length > 0) onReject?.(rejected);\n if (allowed.length === 0) return;\n\n commit(multiple ? [...files, ...allowed] : [allowed[0]]);\n };\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n acceptFiles(Array.from(event.target.files ?? []));\n // Let the same file be picked again after being removed.\n event.target.value = \"\";\n };\n\n const handleDragEnter = (event: DragEvent<HTMLElement>) => {\n if (disabled) return;\n event.preventDefault();\n dragDepth.current += 1;\n setIsDragging(true);\n };\n\n const handleDragOver = (event: DragEvent<HTMLElement>) => {\n if (disabled) return;\n // Without this the browser navigates to the file instead of firing drop.\n event.preventDefault();\n };\n\n const handleDragLeave = (event: DragEvent<HTMLElement>) => {\n if (disabled) return;\n event.preventDefault();\n dragDepth.current -= 1;\n if (dragDepth.current <= 0) {\n dragDepth.current = 0;\n setIsDragging(false);\n }\n };\n\n const handleDrop = (event: DragEvent<HTMLElement>) => {\n if (disabled) return;\n event.preventDefault();\n dragDepth.current = 0;\n setIsDragging(false);\n acceptFiles(Array.from(event.dataTransfer?.files ?? []));\n };\n\n const removeFile = (index: number) => {\n commit(files.filter((_, i) => i !== index));\n };\n\n const classes = [\n \"sh-filedrop\",\n invalid && \"sh-filedrop--invalid\",\n disabled && \"sh-filedrop--disabled\",\n isDragging && \"sh-filedrop--dragging\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div className={classes}>\n {label && (\n <label className=\"sh-filedrop__label\" htmlFor={inputId}>\n {label}\n </label>\n )}\n\n {/*\n The <label> wrapper is what makes a click anywhere in the zone open the\n picker, with no onClick handler and no ref juggling.\n */}\n <label\n className=\"sh-filedrop__dropzone\"\n onDragEnter={handleDragEnter}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n <input\n id={inputId}\n type=\"file\"\n className={[\"sh-filedrop__input\", inputClassName].filter(Boolean).join(\" \")}\n accept={accept}\n multiple={multiple}\n disabled={disabled}\n name={name}\n onChange={handleInputChange}\n aria-label={label ? undefined : ariaLabel}\n aria-invalid={invalid || undefined}\n aria-describedby={message ? messageId : undefined}\n />\n <span className=\"sh-filedrop__prompt\" aria-hidden=\"true\">\n <UploadIcon />\n <span className=\"sh-filedrop__placeholder\">{placeholder}</span>\n {accept && <span className=\"sh-filedrop__accept\">{accept}</span>}\n </span>\n </label>\n\n {!hideFileList && files.length > 0 && (\n <ul className=\"sh-filedrop__files\">\n {files.map((file, index) => (\n <li className=\"sh-filedrop__file\" key={`${file.name}-${index}`}>\n <span className=\"sh-filedrop__file-name\">{file.name}</span>\n <span className=\"sh-filedrop__file-size\">{formatFileSize(file.size)}</span>\n <button\n type=\"button\"\n className=\"sh-filedrop__file-remove\"\n onClick={() => removeFile(index)}\n disabled={disabled}\n aria-label={`Remove ${file.name}`}\n >\n <RemoveIcon />\n </button>\n </li>\n ))}\n </ul>\n )}\n\n {message && (\n <span id={messageId} className=\"sh-filedrop__message\">\n {message}\n </span>\n )}\n </div>\n );\n}\n","import { useId, useState } from \"react\";\nimport type { CSSProperties, ChangeEvent, InputHTMLAttributes, ReactNode } from \"react\";\n\nimport \"./RangeSlider.css\";\n\nexport type RangeSliderProps = {\n /** Visible label, associated with the slider via `htmlFor`/`id`. */\n label?: ReactNode;\n /** Hint shown below the slider. Replaced by `error` when that's set. */\n helperText?: ReactNode;\n /** Validation message. Its presence also marks the slider invalid. */\n error?: ReactNode;\n /** Current value — makes the slider controlled. */\n value?: number;\n /** Initial value when uncontrolled. Defaults to `min`. */\n defaultValue?: number;\n /** Fired with the new value. */\n onChange?: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n /** Shows the current value beside the label. */\n showValue?: boolean;\n /**\n * Formats the displayed value. Also drives `aria-valuetext`, so screen\n * readers announce \"$50\" rather than a bare \"50\".\n */\n formatValue?: (value: number) => string;\n /** Class for the wrapper element. Use `inputClassName` for the input. */\n className?: string;\n /** Class for the underlying `<input type=\"range\">`. */\n inputClassName?: string;\n} & Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"value\" | \"defaultValue\" | \"onChange\" | \"min\" | \"max\" | \"step\" | \"className\"\n>;\n\n/**\n * Single-value slider built on the native `<input type=\"range\">`, so\n * `role=\"slider\"`, the value announcements, keyboard stepping, and form\n * submission all come from the platform.\n */\nexport function RangeSlider({\n label,\n helperText,\n error,\n value,\n defaultValue,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n showValue = false,\n formatValue,\n className,\n inputClassName,\n id,\n disabled,\n \"aria-describedby\": ariaDescribedBy,\n ...props\n}: RangeSliderProps) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const messageId = `${inputId}-message`;\n\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue ?? min);\n const isControlled = value !== undefined;\n const current = isControlled ? value : uncontrolledValue;\n\n const invalid = Boolean(error);\n const message = error ?? helperText;\n\n // Keep any describedby the consumer passed; don't clobber it.\n const describedBy =\n [ariaDescribedBy, message ? messageId : undefined].filter(Boolean).join(\" \") || undefined;\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n const next = Number(event.target.value);\n if (!isControlled) setUncontrolledValue(next);\n onChange?.(next);\n };\n\n // WebKit has no equivalent of Firefox's ::-moz-range-progress, so the\n // filled portion is a gradient stop driven by this custom property.\n const fillPercent = max === min ? 0 : ((current - min) / (max - min)) * 100;\n const displayValue = formatValue ? formatValue(current) : String(current);\n\n const classes = [\n \"sh-range\",\n invalid && \"sh-range--invalid\",\n disabled && \"sh-range--disabled\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div className={classes}>\n {(label || showValue) && (\n <span className=\"sh-range__header\">\n {label && (\n <label className=\"sh-range__label\" htmlFor={inputId}>\n {label}\n </label>\n )}\n {showValue && <span className=\"sh-range__value\">{displayValue}</span>}\n </span>\n )}\n\n <input\n {...props}\n type=\"range\"\n id={inputId}\n className={[\"sh-range__input\", inputClassName].filter(Boolean).join(\" \")}\n style={{ \"--sh-range-fill\": `${fillPercent}%` } as CSSProperties}\n min={min}\n max={max}\n step={step}\n value={current}\n disabled={disabled}\n onChange={handleChange}\n aria-invalid={invalid || undefined}\n aria-describedby={describedBy}\n aria-valuetext={formatValue ? displayValue : undefined}\n />\n\n {message && (\n <span id={messageId} className=\"sh-range__message\">\n {message}\n </span>\n )}\n </div>\n );\n}\n","import { useId, useState } from \"react\";\nimport type { CSSProperties, ChangeEvent, ReactNode } from \"react\";\n\nimport \"./MinMaxSlider.css\";\n\nexport type MinMaxValue = [number, number];\n\nexport type MinMaxSliderProps = {\n /** Visible label for the pair. Provide this or `aria-label`. */\n label?: ReactNode;\n /** Hint shown below the slider. Replaced by `error` when that's set. */\n helperText?: ReactNode;\n /** Validation message. Its presence also marks the slider invalid. */\n error?: ReactNode;\n /** Current `[from, to]` — makes the slider controlled. */\n value?: MinMaxValue;\n /** Initial `[from, to]` when uncontrolled. Defaults to `[min, max]`. */\n defaultValue?: MinMaxValue;\n /** Fired with the new `[from, to]`. */\n onChange?: (value: MinMaxValue) => void;\n min?: number;\n max?: number;\n step?: number;\n /** Smallest allowed distance between the two thumbs. Defaults to `0`. */\n minGap?: number;\n /** Shows the current range beside the label. */\n showValue?: boolean;\n /** Formats each end for display and for `aria-valuetext`. */\n formatValue?: (value: number) => string;\n /** Base field name. The thumbs submit as `${name}-min` and `${name}-max`. */\n name?: string;\n disabled?: boolean;\n /** Accessible name when there's no visible `label`. */\n \"aria-label\"?: string;\n className?: string;\n};\n\n/**\n * Two-thumb slider for picking a from–to range.\n *\n * Built from two overlaid native `<input type=\"range\">` elements rather than a\n * custom widget, so each thumb keeps real `role=\"slider\"` semantics, keyboard\n * stepping, and value announcements. The visible track and fill are decorative\n * spans; the inputs' own tracks are transparent.\n */\nexport function MinMaxSlider({\n label,\n helperText,\n error,\n value,\n defaultValue,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n minGap = 0,\n showValue = false,\n formatValue,\n name,\n disabled = false,\n \"aria-label\": ariaLabel,\n className,\n}: MinMaxSliderProps) {\n const labelId = useId();\n const messageId = useId();\n\n const [uncontrolledValue, setUncontrolledValue] = useState<MinMaxValue>(\n defaultValue ?? [min, max],\n );\n const isControlled = value !== undefined;\n const [from, to] = isControlled ? value : uncontrolledValue;\n\n const invalid = Boolean(error);\n const message = error ?? helperText;\n\n const commit = (next: MinMaxValue) => {\n if (!isControlled) setUncontrolledValue(next);\n onChange?.(next);\n };\n\n // Clamp against the other thumb so the two can never cross.\n const handleFromChange = (event: ChangeEvent<HTMLInputElement>) => {\n commit([Math.min(Number(event.target.value), to - minGap), to]);\n };\n\n const handleToChange = (event: ChangeEvent<HTMLInputElement>) => {\n commit([from, Math.max(Number(event.target.value), from + minGap)]);\n };\n\n const asPercent = (n: number) => (max === min ? 0 : ((n - min) / (max - min)) * 100);\n const fromPercent = asPercent(from);\n const toPercent = asPercent(to);\n\n const format = (n: number) => (formatValue ? formatValue(n) : String(n));\n\n /*\n * Both inputs span the full width, so their thumbs overlap. Pointer events\n * are disabled on the inputs and re-enabled on the thumbs alone, but when\n * the thumbs coincide the later element still wins. Raising the \"from\" input\n * once it's past halfway keeps it grabbable at the top of the range.\n */\n const fromOnTop = from > (min + max) / 2;\n\n const classes = [\n \"sh-minmax\",\n invalid && \"sh-minmax--invalid\",\n disabled && \"sh-minmax--disabled\",\n fromOnTop && \"sh-minmax--from-on-top\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n const accessibleName = label ? undefined : ariaLabel;\n const thumbName = (suffix: string) =>\n label || ariaLabel ? `${label ?? ariaLabel} ${suffix}` : suffix;\n\n return (\n <div\n className={classes}\n style={\n {\n \"--sh-minmax-from\": `${fromPercent}%`,\n \"--sh-minmax-to\": `${toPercent}%`,\n } as CSSProperties\n }\n >\n {(label || showValue) && (\n <span className=\"sh-minmax__header\">\n {label && (\n <span className=\"sh-minmax__label\" id={labelId}>\n {label}\n </span>\n )}\n {showValue && (\n <span className=\"sh-minmax__value\">\n {format(from)} – {format(to)}\n </span>\n )}\n </span>\n )}\n\n {/* Two sliders, so the pair is a group rather than one labelled control. */}\n <div\n className=\"sh-minmax__rail\"\n role=\"group\"\n aria-label={accessibleName}\n aria-labelledby={label ? labelId : undefined}\n aria-describedby={message ? messageId : undefined}\n aria-invalid={invalid || undefined}\n >\n <span className=\"sh-minmax__track\" aria-hidden=\"true\">\n <span className=\"sh-minmax__fill\" />\n </span>\n\n <input\n type=\"range\"\n className=\"sh-minmax__input sh-minmax__input--from\"\n name={name ? `${name}-min` : undefined}\n min={min}\n max={max}\n step={step}\n value={from}\n disabled={disabled}\n onChange={handleFromChange}\n aria-label={thumbName(\"minimum\")}\n aria-valuetext={formatValue ? format(from) : undefined}\n />\n <input\n type=\"range\"\n className=\"sh-minmax__input sh-minmax__input--to\"\n name={name ? `${name}-max` : undefined}\n min={min}\n max={max}\n step={step}\n value={to}\n disabled={disabled}\n onChange={handleToChange}\n aria-label={thumbName(\"maximum\")}\n aria-valuetext={formatValue ? format(to) : undefined}\n />\n </div>\n\n {message && (\n <span id={messageId} className=\"sh-minmax__message\">\n {message}\n </span>\n )}\n </div>\n );\n}\n","import { createContext } from \"react\";\n\nexport type SwitchGroupContextValue = {\n /** Shared `name`, so the switches submit together as one field. */\n name: string;\n /** Values of the switches currently on. Each toggles independently. */\n value: string[];\n /** Called with the switch's value when it's turned on or off. */\n onToggle: (value: string, checked: boolean) => void;\n /** Set when the whole group is disabled. */\n disabled?: boolean;\n /** Default label side for the group's switches. */\n labelPosition?: \"left\" | \"right\";\n};\n\n/**\n * Lets `SwitchGroup` coordinate its `Switch` children without cloning them.\n * A `Switch` used outside a group falls back to its own props.\n * Kept in its own module so the component files only export components\n * (see the react-refresh rule in eslint.config.js).\n */\nexport const SwitchGroupContext = createContext<SwitchGroupContextValue | undefined>(undefined);\n","import { useContext } from \"react\";\nimport type { ChangeEvent, InputHTMLAttributes, ReactNode } from \"react\";\n\nimport { SwitchGroupContext } from \"./switch.context\";\nimport \"./Switch.css\";\n\nexport type SwitchProps = {\n /** Value this switch represents. Required when inside a `SwitchGroup`. */\n value?: string;\n /** Visible label sitting beside the control. */\n label?: ReactNode;\n /** Which side the label sits on. Defaults to `right`, or the group's setting. */\n labelPosition?: \"left\" | \"right\";\n /** Class for the wrapping `<label>`. Use `inputClassName` for the control. */\n className?: string;\n /** Class for the underlying `<input>`. */\n inputClassName?: string;\n} & Omit<InputHTMLAttributes<HTMLInputElement>, \"type\" | \"value\" | \"className\">;\n\n/**\n * Boolean toggle for a setting that applies immediately.\n *\n * Renders a checkbox with `role=\"switch\"`, so it's announced as on/off rather\n * than checked/unchecked. Works standalone, or inside a `SwitchGroup` which\n * supplies the shared name and selection.\n */\nexport function Switch({\n value,\n label,\n labelPosition,\n className,\n inputClassName,\n name,\n checked,\n disabled,\n onChange,\n ...props\n}: SwitchProps) {\n const group = useContext(SwitchGroupContext);\n\n // Inside a group the group owns name/selection/disabled; standalone, the\n // component's own props do.\n const resolvedName = name ?? group?.name;\n const resolvedChecked = group && value !== undefined ? group.value.includes(value) : checked;\n const resolvedDisabled = disabled ?? group?.disabled;\n const resolvedLabelPosition = labelPosition ?? group?.labelPosition ?? \"right\";\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (group && value !== undefined) group.onToggle(value, event.target.checked);\n onChange?.(event);\n };\n\n const classes = [\n \"sh-switch\",\n `sh-switch--label-${resolvedLabelPosition}`,\n resolvedDisabled && \"sh-switch--disabled\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <label className={classes}>\n <input\n {...props}\n type=\"checkbox\"\n role=\"switch\"\n className={[\"sh-switch__input\", inputClassName].filter(Boolean).join(\" \")}\n name={resolvedName}\n value={value}\n checked={resolvedChecked}\n disabled={resolvedDisabled}\n onChange={handleChange}\n />\n {/*\n The input is visually hidden but still focusable and still the real\n control; these two are painted in its place, which is what lets the\n thumb slide on a transform instead of a background position.\n */}\n <span className=\"sh-switch__track\" aria-hidden=\"true\">\n <span className=\"sh-switch__thumb\" />\n </span>\n {label && <span className=\"sh-switch__label\">{label}</span>}\n </label>\n );\n}\n","import { useId, useState } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { SwitchGroupContext } from \"./switch.context\";\nimport \"./Switch.css\";\n\nexport type SwitchGroupProps = {\n children?: ReactNode;\n /** Values of the switches that are on — makes the group controlled. */\n value?: string[];\n /** Initially-on switches when uncontrolled. */\n defaultValue?: string[];\n /** Fired with the full list of switches that are on. */\n onChange?: (value: string[]) => void;\n /** Visible label for the group. Provide this or `aria-label`. */\n label?: ReactNode;\n /** Hint shown below the switches. Replaced by `error` when that's set. */\n helperText?: ReactNode;\n /** Validation message. Its presence also marks the group invalid. */\n error?: ReactNode;\n /** Shared field name for the switches. Auto-generated when omitted. */\n name?: string;\n /** Layout direction for the switches. Defaults to `vertical`. */\n orientation?: \"vertical\" | \"horizontal\";\n /** Default label side for every switch in the group. Individual props win. */\n labelPosition?: \"left\" | \"right\";\n /** Disables every switch in the group. */\n disabled?: boolean;\n /** Accessible name when there's no visible `label`. */\n \"aria-label\"?: string;\n className?: string;\n};\n\n/** Groups `Switch` toggles, coordinating their shared name and state. */\nexport function SwitchGroup({\n children,\n value,\n defaultValue,\n onChange,\n label,\n helperText,\n error,\n name,\n orientation = \"vertical\",\n labelPosition,\n disabled = false,\n \"aria-label\": ariaLabel,\n className,\n}: SwitchGroupProps) {\n const generatedName = useId();\n const labelId = useId();\n const messageId = useId();\n const groupName = name ?? generatedName;\n\n const [uncontrolledValue, setUncontrolledValue] = useState<string[]>(defaultValue ?? []);\n const isControlled = value !== undefined;\n const selected = isControlled ? value : uncontrolledValue;\n\n const handleToggle = (switchValue: string, checked: boolean) => {\n // Rebuild from the current selection so the callback always receives the\n // complete list, not a delta.\n const next = checked\n ? [...selected, switchValue]\n : selected.filter((item) => item !== switchValue);\n\n if (!isControlled) setUncontrolledValue(next);\n onChange?.(next);\n };\n\n const invalid = Boolean(error);\n const message = error ?? helperText;\n\n const classes = [\"sh-switch-group\", invalid && \"sh-switch-group--invalid\", className]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div className={classes}>\n {label && (\n <span className=\"sh-switch-group__label\" id={labelId}>\n {label}\n </span>\n )}\n\n {/*\n `group` rather than a select-style role — switches toggle\n independently, so there's no native grouping role for them.\n */}\n <div\n className={`sh-switch-group__options sh-switch-group__options--${orientation}`}\n role=\"group\"\n aria-label={label ? undefined : ariaLabel}\n aria-labelledby={label ? labelId : undefined}\n aria-describedby={message ? messageId : undefined}\n aria-invalid={invalid || undefined}\n >\n <SwitchGroupContext.Provider\n value={{\n name: groupName,\n value: selected,\n onToggle: handleToggle,\n disabled,\n labelPosition,\n }}\n >\n {children}\n </SwitchGroupContext.Provider>\n </div>\n\n {message && (\n <span id={messageId} className=\"sh-switch-group__message\">\n {message}\n </span>\n )}\n </div>\n );\n}\n","import { useId, useState } from \"react\";\nimport type { CSSProperties, ReactNode } from \"react\";\n\nimport \"./SegmentedControl.css\";\n\nexport type SegmentedControlOption = {\n /** Value reported to `onChange` and submitted with a form. */\n value: string;\n /** Visible content for the segment. */\n label: ReactNode;\n /** Disables just this segment. */\n disabled?: boolean;\n};\n\nexport type SegmentedControlProps = {\n /** The segments, in display order. */\n options: SegmentedControlOption[];\n /** Selected value — makes the component controlled. */\n value?: string;\n /** Initial selection when uncontrolled. */\n defaultValue?: string;\n /** Fired with the newly selected value. */\n onChange?: (value: string) => void;\n /** Visible label for the group. Provide this or `aria-label`. */\n label?: ReactNode;\n /** Radio group name. Auto-generated when omitted. */\n name?: string;\n /** Stretches the control to fill its container, splitting segments evenly. */\n fullWidth?: boolean;\n /** Disables every segment. */\n disabled?: boolean;\n /** Accessible name when there's no visible `label`. */\n \"aria-label\"?: string;\n className?: string;\n};\n\n/**\n * Single-select control rendered as a row of blocks.\n *\n * Built on native `<input type=\"radio\">` rather than `role=\"radio\"` buttons,\n * so arrow-key navigation, group semantics, and form submission all come\n * from the platform instead of being reimplemented.\n */\nexport function SegmentedControl({\n options,\n value,\n defaultValue,\n onChange,\n label,\n name,\n fullWidth = false,\n disabled = false,\n \"aria-label\": ariaLabel,\n className,\n}: SegmentedControlProps) {\n const generatedName = useId();\n const labelId = useId();\n const groupName = name ?? generatedName;\n\n const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);\n const isControlled = value !== undefined;\n const selected = isControlled ? value : uncontrolledValue;\n\n const handleChange = (next: string) => {\n if (!isControlled) setUncontrolledValue(next);\n onChange?.(next);\n };\n\n // The sliding indicator is a single ::after on the track, so CSS needs to\n // know which slot to sit in. Segments are equal-width, so the position is\n // just `index * 100%` of one segment.\n const selectedIndex = options.findIndex((option) => option.value === selected);\n\n const classes = [\n \"sh-segmented\",\n fullWidth && \"sh-segmented--full-width\",\n disabled && \"sh-segmented--disabled\",\n selectedIndex < 0 && \"sh-segmented--unselected\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n const trackStyle = {\n \"--sh-segmented-count\": options.length,\n \"--sh-segmented-index\": Math.max(selectedIndex, 0),\n } as CSSProperties;\n\n return (\n <div className=\"sh-segmented-field\">\n {label && (\n <span className=\"sh-segmented__group-label\" id={labelId}>\n {label}\n </span>\n )}\n\n <div\n className={classes}\n style={trackStyle}\n role=\"radiogroup\"\n aria-label={label ? undefined : ariaLabel}\n aria-labelledby={label ? labelId : undefined}\n >\n {options.map((option) => {\n const optionDisabled = disabled || option.disabled;\n\n return (\n <label\n key={option.value}\n className={[\n \"sh-segmented__item\",\n optionDisabled && \"sh-segmented__item--disabled\",\n ]\n .filter(Boolean)\n .join(\" \")}\n >\n <input\n className=\"sh-segmented__input\"\n type=\"radio\"\n name={groupName}\n value={option.value}\n checked={selected === option.value}\n disabled={optionDisabled}\n onChange={() => handleChange(option.value)}\n />\n <span className=\"sh-segmented__label\">{option.label}</span>\n </label>\n );\n })}\n </div>\n </div>\n );\n}\n","/**\n * TS mirror of colors.css / colors.semantic.css, for places that need\n * the raw values in JS (Storybook docs, color pickers, tests) rather\n * than a CSS var. Keep in sync with the .css files by hand — there's\n * no build step generating one from the other; `__test__/colors.test.ts`\n * parses the stylesheets and fails if the two drift apart.\n *\n * In app code prefer the CSS vars (or `colorVar()`), so colors follow\n * the active theme. The hex values here are per-theme snapshots and\n * don't flip on their own.\n */\n\nexport const accent = {\n 50: '#f6f0ff',\n 100: '#ece0ff',\n 200: '#d9c2ff',\n 300: '#c19dff',\n 400: '#a672ff',\n 500: '#8b47fa',\n 600: '#7429e0',\n 700: '#5d1fb8',\n 800: '#461890',\n 900: '#331269',\n 950: '#1f0b40',\n} as const;\n\nexport const neutral = {\n 0: '#ffffff',\n 50: '#f8f7fa',\n 100: '#efedf3',\n 200: '#e2dfe8',\n 300: '#cac6d3',\n 400: '#a29cae',\n 500: '#79728a',\n 600: '#5a5468',\n 700: '#423d4d',\n 800: '#2c2836',\n 900: '#1a1720',\n 950: '#0d0b12',\n} as const;\n\nexport const danger = {\n 50: '#fef3f2',\n 100: '#fee4e2',\n 200: '#fecdca',\n 300: '#fda29b',\n 400: '#f97066',\n 500: '#f04438',\n 600: '#d92d20',\n 700: '#b42318',\n 800: '#912018',\n 900: '#7a271a',\n 950: '#55160c',\n} as const;\n\nexport type AccentStep = keyof typeof accent;\nexport type NeutralStep = keyof typeof neutral;\nexport type DangerStep = keyof typeof danger;\n\n/** Every primitive scale, keyed by name — for iterating over the whole palette. */\nexport const palette = { accent, neutral, danger } as const;\n\nexport type PaletteName = keyof typeof palette;\n\n/** Fixed across themes — see colors.semantic.css for why. */\nexport const accentFill = {\n bg: accent[700],\n text: accent[100],\n} as const;\n\nconst themeless = {\n 'accent-fill-bg': accentFill.bg,\n 'accent-fill-text': accentFill.text,\n} as const;\n\nexport const semanticColors = {\n light: {\n 'bg-canvas': neutral[0],\n 'bg-surface': neutral[50],\n 'bg-subtle': neutral[100],\n text: neutral[900],\n 'text-subtle': neutral[600],\n 'text-inverse': neutral[0],\n border: neutral[200],\n 'border-strong': neutral[300],\n accent: accent[600],\n 'accent-hover': accent[700],\n 'accent-subtle-bg': accent[50],\n 'accent-subtle-text': accent[700],\n ...themeless,\n danger: danger[700],\n 'danger-border': danger[500],\n scrim: 'rgb(0 0 0 / 0.45)',\n 'accent-tint-1': accent[50],\n 'accent-tint-2': accent[100],\n 'accent-tint-3': accent[200],\n 'accent-tint-4': accent[300],\n 'accent-on-tint': accent[900],\n },\n dark: {\n 'bg-canvas': neutral[950],\n 'bg-surface': neutral[900],\n 'bg-subtle': neutral[800],\n text: neutral[50],\n 'text-subtle': neutral[400],\n 'text-inverse': neutral[950],\n border: neutral[700],\n 'border-strong': neutral[600],\n accent: accent[400],\n 'accent-hover': accent[300],\n 'accent-subtle-bg': accent[900],\n 'accent-subtle-text': accent[200],\n ...themeless,\n danger: danger[300],\n 'danger-border': danger[400],\n scrim: 'rgb(0 0 0 / 0.65)',\n 'accent-tint-1': accent[950],\n 'accent-tint-2': accent[900],\n 'accent-tint-3': accent[800],\n 'accent-tint-4': accent[700],\n 'accent-on-tint': accent[100],\n },\n} as const;\n\nexport type ColorTheme = keyof typeof semanticColors;\nexport type SemanticColorName = keyof typeof semanticColors.light;\n\n/**\n * The CSS var for a semantic token, ready to drop into an inline style or a\n * styled-component. Unlike the hex values above it stays theme-aware:\n *\n * <div style={{ background: colorVar('bg-surface') }} />\n */\nexport function colorVar(name: SemanticColorName): `var(--color-${SemanticColorName})` {\n return `var(--color-${name})`;\n}\n\n/**\n * The CSS var for a primitive step, e.g. `paletteVar('accent', 600)`. Reach for\n * `colorVar()` first — primitives carry no meaning and don't respond to theme.\n */\nexport function paletteVar<S extends PaletteName>(\n scale: S,\n step: keyof (typeof palette)[S],\n): string {\n return `var(--color-${scale}-${String(step)})`;\n}\n"],"mappings":"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"}
|