@gryt/ui 0.21.1 → 0.23.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/dist/components/Avatar/Avatar.d.ts +20 -0
- package/dist/components/Avatar/Avatar.d.ts.map +1 -1
- package/dist/components/ThemeEditor/ColorField.d.ts +20 -0
- package/dist/components/ThemeEditor/ColorField.d.ts.map +1 -0
- package/dist/components/ThemeEditor/ContrastReport.d.ts +16 -0
- package/dist/components/ThemeEditor/ContrastReport.d.ts.map +1 -0
- package/dist/components/ThemeEditor/ScaleStrip.d.ts +15 -0
- package/dist/components/ThemeEditor/ScaleStrip.d.ts.map +1 -0
- package/dist/components/ThemeEditor/ThemeEditor.d.ts +23 -0
- package/dist/components/ThemeEditor/ThemeEditor.d.ts.map +1 -0
- package/dist/components/ThemeEditor/contrast.d.ts +21 -0
- package/dist/components/ThemeEditor/contrast.d.ts.map +1 -0
- package/dist/components/ThemeEditor/draft.d.ts +35 -0
- package/dist/components/ThemeEditor/draft.d.ts.map +1 -0
- package/dist/components/ThemeEditor/generate.d.ts +43 -0
- package/dist/components/ThemeEditor/generate.d.ts.map +1 -0
- package/dist/components/ThemeEditor/share.d.ts +17 -0
- package/dist/components/ThemeEditor/share.d.ts.map +1 -0
- package/dist/index.cjs +18 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1706 -909
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +3 -3
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/portalContainer.ts","../src/GrytProvider.tsx","../src/components/utils/cn.ts","../src/components/Button/Button.tsx","../src/components/utils/styles.ts","../src/components/IconButton/IconButton.tsx","../src/components/Surface/Surface.tsx","../src/components/MessageBubble/MessageBubble.tsx","../src/components/TextField/TextField.tsx","../src/components/Composer/Composer.tsx","../src/components/Avatar/Avatar.tsx","../src/components/ConversationItem/ConversationItem.tsx","../src/components/Badge/Badge.tsx","../src/components/Chip/Chip.tsx","../src/components/Checkbox/Checkbox.tsx","../src/components/Radio/Radio.tsx","../src/components/Switch/Switch.tsx","../src/components/Slider/Slider.tsx","../src/components/Select/Select.tsx","../src/components/Tooltip/Tooltip.tsx","../src/components/Divider/Divider.tsx","../src/components/Card/Card.tsx","../src/components/Alert/Alert.tsx","../src/components/Progress/Progress.tsx","../src/components/Skeleton/Skeleton.tsx","../src/components/Dialog/Dialog.tsx","../src/components/utils/useMediaQuery.ts","../src/components/Drawer/Drawer.tsx","../src/components/Menu/Menu.tsx","../src/components/Tabs/Tabs.tsx","../src/components/Accordion/Accordion.tsx","../src/components/ContextMenu/ContextMenu.tsx","../src/components/Popover/Popover.tsx","../src/components/Toast/Toast.tsx","../src/components/ScrollArea/ScrollArea.tsx","../src/components/Toggle/Toggle.tsx","../src/components/Meter/Meter.tsx","../src/components/AlertDialog/AlertDialog.tsx","../src/components/Combobox/Combobox.tsx","../src/components/Autocomplete/Autocomplete.tsx","../src/components/Checkbox/CheckboxGroup.tsx","../src/components/Collapsible/Collapsible.tsx","../src/components/Form/Form.tsx","../src/components/NavigationMenu/NavigationMenu.tsx","../src/components/NumberField/NumberField.tsx","../src/components/OtpField/OtpField.tsx","../src/components/PreviewCard/PreviewCard.tsx","../src/components/Toolbar/Toolbar.tsx"],"sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { RefObject } from \"react\";\n\n/**\n * Where overlays below this point should render.\n *\n * Base UI portals a popup to `document.body`, which is outside whatever element\n * GrytProvider put the theme variables on. For an app with one theme that is\n * exactly right — the overlay wants the app's theme and it gets it from\n * `:root`. It is wrong only when a second theme is being rendered inside a\n * page: the docs site previews a theme in a panel, and a Select or Tooltip\n * opened inside that panel comes up in the site's own colours (GRYT-242).\n *\n * Deliberately a context rather than a prop on each component. Select carries a\n * long comment about why its popup portals to the body — a popup left inside a\n * positioned dialog lands hundreds of pixels off — and a per-call `container`\n * prop is exactly the thing somebody reaches for to fix a layout problem, which\n * is how that bug got made the first time. A container that is set once, for a\n * subtree, by whoever established the theme, cannot be used that way by\n * accident.\n *\n * Base UI has no equivalent to reuse. Its own `PortalContext` is a boolean —\n * \"am I inside a portal\" — not a carrier for the container.\n */\nexport const PortalContainerContext = createContext<\n RefObject<HTMLElement | null> | undefined\n>(undefined);\n\n/**\n * The container overlays should portal into, or `undefined` for Base UI's\n * default of `document.body`.\n */\nexport function usePortalContainer(): RefObject<HTMLElement | null> | undefined {\n return useContext(PortalContainerContext);\n}\n","import { Tooltip } from \"@base-ui/react/tooltip\";\nimport { useRef } from \"react\";\nimport type { CSSProperties, ReactNode } from \"react\";\nimport { createGrytTheme } from \"@gryt/theme\";\nimport type { GrytThemeOptions } from \"@gryt/theme\";\nimport { PortalContainerContext } from \"./portalContainer\";\n\nexport interface GrytProviderProps {\n children: ReactNode;\n // Either the object from createGrytTheme, or the options to build one from.\n theme?: CSSProperties | GrytThemeOptions;\n className?: string;\n // Shared hover delay for every Tooltip below this provider, in milliseconds.\n tooltipDelay?: number;\n /**\n * Render overlays inside this provider's element rather than in `document.body`.\n *\n * Off by default, and should stay off for an app with one theme: the body is\n * the right place for a popup, and `:root` already carries the variables it\n * needs. Turn it on when this provider is one theme inside a page that has\n * another — previewing a theme in a panel — where an overlay in the body\n * would come up in the surrounding page's colours instead (GRYT-242).\n */\n containOverlays?: boolean;\n}\n\nfunction isCssVariables(value: object): value is CSSProperties {\n return Object.keys(value).some((key) => key.startsWith(\"--\"));\n}\n\n// There is no ThemeProvider and no CssBaseline any more. What a provider still\n// has to do is put the theme variables somewhere the components can read them,\n// and mount Base UI's tooltip provider so hover timing is shared between\n// triggers rather than restarting at every one.\nexport function GrytProvider({\n children,\n className,\n theme,\n tooltipDelay = 400,\n containOverlays = false\n}: GrytProviderProps) {\n // A ref rather than state: Base UI's `container` accepts one, so the element\n // does not have to exist on the first render and nothing has to re-render\n // when it does.\n const containerRef = useRef<HTMLDivElement | null>(null);\n /**\n * No theme, no variables.\n *\n * This used to paint the full default palette onto the wrapper whenever the\n * prop was absent, which looked harmless and was not: the stylesheet already\n * declares those values on :root, so the copy added nothing, and it sat below\n * the root in the cascade — an app that themed itself the documented way, by\n * putting variables on the root element where overlays can reach them, found\n * every one of them overridden by a provider re-stating the defaults.\n *\n * It cost this site an afternoon. The header can put the docs in Nord now,\n * and the reason it could not before was one div.\n */\n const style =\n theme === undefined\n ? undefined\n : isCssVariables(theme)\n ? theme\n : createGrytTheme(theme);\n\n return (\n <div className={className} style={style} ref={containerRef}>\n <PortalContainerContext.Provider\n value={containOverlays ? containerRef : undefined}\n >\n <Tooltip.Provider delay={tooltipDelay}>{children}</Tooltip.Provider>\n </PortalContainerContext.Provider>\n </div>\n );\n}\n","import { clsx } from \"clsx\";\nimport type { ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}","import { Button as BaseButton } from \"@base-ui/react/button\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\ntype ButtonTone = \"primary\" | \"secondary\" | \"neutral\" | \"danger\" | \"ghost\";\ntype ButtonSize = \"xsmall\" | \"small\" | \"medium\" | \"large\";\n\n// Base UI marks a disabled button with data-disabled rather than the native\n// attribute, because it stays focusable when disabled. Hover and press styles\n// hang off not-data-disabled so they don't fire on a dead button.\n//\n// **Disabled drops the fill rather than fading it.** Every tone used to share\n// one `opacity-50`, and on the low-contrast tones that reads — they are already\n// quiet, so halving them puts them under the surrounding text. On a filled tone\n// it does not: the accent at half opacity over a dark page is still a saturated\n// purple button, and there is nothing in it that says it will not respond. On\n// the phone that cost somebody two taps on a Save button to believe it was\n// inert, and the somebody had written the disabled condition half an hour\n// earlier. GRYT-511.\n//\n// So a disabled filled button becomes the surface it sits on, with a muted\n// label — it keeps its size and its word and stops claiming to be the action.\n// Ghost has no fill to lose and its label is already muted, so the opacity\n// below is what carries it.\nconst toneStyles: Record<ButtonTone, string> = {\n primary:\n \"bg-gryt-accent text-gryt-on-accent hover:not-data-disabled:bg-gryt-accent-light data-disabled:bg-gryt-surface-raised data-disabled:text-gryt-muted\",\n secondary:\n \"bg-gryt-secondary text-gryt-on-secondary hover:not-data-disabled:bg-gryt-secondary-light data-disabled:bg-gryt-surface-raised data-disabled:text-gryt-muted\",\n neutral:\n \"bg-gryt-surface-raised text-gryt-text hover:not-data-disabled:bg-gryt-surface-hover data-disabled:text-gryt-muted\",\n danger:\n \"bg-gryt-danger text-gryt-on-danger hover:not-data-disabled:bg-gryt-danger-light data-disabled:bg-gryt-surface-raised data-disabled:text-gryt-muted\",\n ghost:\n \"bg-transparent text-gryt-muted hover:not-data-disabled:bg-white/8 hover:not-data-disabled:text-gryt-text\"\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n xsmall: \"min-h-8 px-3 text-xs\",\n small: \"min-h-9 px-4 text-sm\",\n medium: \"min-h-10 px-5 text-sm\",\n large: \"min-h-12 px-6 text-base\"\n};\n\nexport interface ButtonProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseButton>, \"className\"> {\n tone?: ButtonTone;\n size?: ButtonSize;\n className?: string;\n // Carried over from the MUI-based Button. Base UI has no equivalent, but\n // dropping them would break every existing call site for no gain — the flex\n // gap below already spaces them correctly.\n startIcon?: ReactNode;\n endIcon?: ReactNode;\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n function Button(\n {\n children,\n className,\n endIcon,\n size = \"medium\",\n startIcon,\n tone = \"primary\",\n ...props\n },\n ref\n ) {\n return (\n <BaseButton\n ref={ref}\n className={cn(\n \"gryt-button\",\n \"inline-flex cursor-pointer items-center justify-center gap-2 border-0 shadow-none\",\n \"rounded-(--gryt-radius-full) font-semibold whitespace-nowrap select-none\",\n // scale, not transform: Tailwind v4's scale-* utilities set the\n // standalone `scale` property, so transitioning `transform` alone\n // leaves the hover grow snapping instantly.\n \"transition-[scale,background-color,color]\",\n \"duration-(--gryt-dur-spring) ease-spring\",\n\n // Press travels further than hover, so the button reads as being\n // pushed down rather than just acknowledging the cursor.\n // A button that opens something does not grow under the cursor.\n // Base UI positions the popup against the trigger's measured box, and\n // it keeps measuring while the popup is open — so a trigger that\n // scales on hover drags its own menu a pixel or two sideways every\n // time the pointer crosses it. aria-haspopup is how the trigger says\n // that is what it is; Base UI puts it there, nothing to pass.\n \"motion-safe:not-[[aria-haspopup]]:hover:not-data-disabled:scale-[1.03]\",\n \"motion-safe:not-[[aria-haspopup]]:active:not-data-disabled:scale-[0.96]\",\n\n \"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gryt-accent-light\",\n // Lighter than it was, because the fill swap above is doing the work\n // now. It is kept because `startIcon` and `endIcon` are the caller's\n // elements with the caller's colours — nothing here can mute those,\n // and an icon at full strength on a dead button is the same lie in\n // miniature.\n \"data-disabled:cursor-not-allowed data-disabled:opacity-60\",\n sizeStyles[size],\n toneStyles[tone],\n className\n )}\n {...props}\n >\n {startIcon}\n {children}\n {endIcon}\n </BaseButton>\n );\n }\n);\n","// Shared class fragments. These exist so that \"flat, Gryt palette\" is decided\n// once rather than 24 times, and so a change to the focus ring or the popup\n// surface lands everywhere at once.\n\nexport const focusRing =\n \"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gryt-accent-light\";\n\n// The same ring, for a control whose focusable element is a child rather than\n// itself. Base UI's Slider is the case: the thumb you can see is a div, and\n// the thing that takes focus is a visually hidden input inside it, so\n// focus-visible on the thumb never matches and the ring never appears.\nexport const focusRingWithin =\n \"has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-gryt-accent-light\";\n\n/**\n * What a text input looks like: TextField, and the typeahead inputs on\n * Combobox and Autocomplete.\n *\n * Shared because they had already drifted. The listbox inputs asked for\n * `rounded-(--gryt-radius-input)`, a token that does not exist — the library\n * ships sm, md, lg, xl and full — so the declaration was invalid and both\n * rendered with square corners in a library where every other control is\n * rounded. That is the kind of thing a shared constant makes impossible rather\n * than merely unlikely.\n *\n * The border *colour* is left to the caller: TextField swaps it for danger when\n * the field is invalid, and baking one in here would mean fighting it back off.\n */\nexport const fieldControl = [\n \"w-full rounded-(--gryt-radius-xl) border bg-gryt-surface-raised\",\n \"text-gryt-text outline-none placeholder:text-gryt-muted\",\n \"transition-colors duration-150 motion-reduce:transition-none\",\n \"hover:border-gryt-accent-light focus:border-gryt-accent\",\n \"disabled:cursor-not-allowed disabled:opacity-60\"\n].join(\" \");\n\n/** Matching heights and padding for the two sizes a field comes in. */\nexport const fieldSizes = {\n small: \"min-h-9 px-3 py-1.5 text-sm\",\n medium: \"min-h-11 px-4 py-2.5 text-sm\"\n} as const;\n\nexport type FieldSize = keyof typeof fieldSizes;\n\n// Every floating surface: menu, select list, tooltip, dialog, drawer. Flat —\n// a border rather than a shadow.\nexport const popupSurface =\n \"rounded-(--gryt-radius-xl) border border-gryt-border bg-gryt-surface text-gryt-text\";\n\n// Base UI sets data-starting-style and data-ending-style for one frame either\n// side of open and close. The element carries the transition itself.\nexport const popupMotion = [\n // scale and translate are named explicitly because Tailwind v4 sets them as\n // standalone CSS properties rather than folding them into `transform`, so\n // transitioning `transform` would leave the popup snapping into place.\n \"transition-[opacity,scale,translate] duration-(--gryt-dur-spring) ease-spring motion-reduce:transition-none\",\n \"data-starting-style:scale-[0.98] data-starting-style:opacity-0\",\n \"data-ending-style:scale-[0.98] data-ending-style:opacity-0\"\n].join(\" \");\n\nexport const disabledState =\n \"cursor-pointer data-disabled:cursor-not-allowed data-disabled:opacity-50\";\n\n// The tones shared by Checkbox, Radio, Switch and Slider. One union so a\n// component cannot invent its own sixth colour. Button and IconButton keep\n// their own lists, because \"ghost\" only makes sense on a button.\nexport type Tone =\n | \"primary\"\n | \"secondary\"\n | \"neutral\"\n | \"danger\"\n | \"success\"\n | \"warning\";\n\n// Step 11, the text step, not the flat name. The flat name is step 9 — the\n// solid fill, the same colour in both appearances — which reads on a dark page\n// and disappears on a white one.\nexport const toneAccent: Record<Tone, string> = {\n primary: \"text-gryt-accent-11\",\n secondary: \"text-gryt-secondary-11\",\n neutral: \"text-gryt-muted\",\n danger: \"text-gryt-danger-11\",\n success: \"text-gryt-success-11\",\n warning: \"text-gryt-warning-11\"\n};\n\n// Filled backgrounds, for the checked state of a control.\nexport const toneFill: Record<Tone, string> = {\n primary: \"bg-gryt-accent text-gryt-on-accent\",\n secondary: \"bg-gryt-secondary text-gryt-on-secondary\",\n neutral: \"bg-gryt-surface-hover text-gryt-text\",\n danger: \"bg-gryt-danger text-gryt-on-danger\",\n success: \"bg-gryt-success text-gryt-on-accent\",\n warning: \"bg-gryt-warning text-gryt-on-accent\"\n};\n\nexport const toneBorder: Record<Tone, string> = {\n primary: \"border-gryt-accent\",\n secondary: \"border-gryt-secondary\",\n neutral: \"border-gryt-border\",\n danger: \"border-gryt-danger\",\n success: \"border-gryt-success\",\n warning: \"border-gryt-warning\"\n};\n\n// Written out in full rather than composed from toneFill at runtime. Tailwind\n// scans source text for class names, so a class built by interpolation exists\n// on the element and nowhere in the stylesheet.\nexport const toneCheckedFill: Record<Tone, string> = {\n primary: \"data-checked:bg-gryt-accent data-checked:text-gryt-on-accent\",\n secondary:\n \"data-checked:bg-gryt-secondary data-checked:text-gryt-on-secondary\",\n neutral: \"data-checked:bg-gryt-surface-hover data-checked:text-gryt-text\",\n danger: \"data-checked:bg-gryt-danger data-checked:text-gryt-on-danger\",\n success: \"data-checked:bg-gryt-success data-checked:text-gryt-on-accent\",\n warning: \"data-checked:bg-gryt-warning data-checked:text-gryt-on-accent\"\n};\n\n// Track fill for Switch, and bar fill for Slider.\nexport const toneBg: Record<Tone, string> = {\n primary: \"bg-gryt-accent\",\n secondary: \"bg-gryt-secondary\",\n neutral: \"bg-gryt-surface-hover\",\n danger: \"bg-gryt-danger\",\n success: \"bg-gryt-success\",\n warning: \"bg-gryt-warning\"\n};\n\nexport const toneCheckedBorder: Record<Tone, string> = {\n primary: \"data-checked:border-gryt-accent\",\n secondary: \"data-checked:border-gryt-secondary\",\n neutral: \"data-checked:border-gryt-muted\",\n danger: \"data-checked:border-gryt-danger\",\n success: \"data-checked:border-gryt-success\",\n warning: \"data-checked:border-gryt-warning\"\n};\n\nexport const toneCheckedBg: Record<Tone, string> = {\n primary: \"data-checked:bg-gryt-accent\",\n secondary: \"data-checked:bg-gryt-secondary\",\n neutral: \"data-checked:bg-gryt-surface-hover\",\n danger: \"data-checked:bg-gryt-danger\",\n success: \"data-checked:bg-gryt-success\",\n warning: \"data-checked:bg-gryt-warning\"\n};\n","import { Button as BaseButton } from \"@base-ui/react/button\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { disabledState, focusRing } from \"../utils/styles\";\n\ntype IconButtonTone = \"primary\" | \"secondary\" | \"neutral\" | \"danger\" | \"ghost\";\ntype IconButtonSize = \"xsmall\" | \"small\" | \"medium\" | \"large\";\n\n// The hover fills are the tone colour at low alpha, so an icon button reads as\n// a tinted target rather than a filled one.\nconst toneStyles: Record<IconButtonTone, string> = {\n primary: \"text-gryt-accent-11 hover:not-data-disabled:bg-gryt-accent-3\",\n secondary:\n \"text-gryt-secondary-11 hover:not-data-disabled:bg-gryt-secondary-3\",\n neutral:\n \"text-gryt-muted hover:not-data-disabled:bg-white/8 hover:not-data-disabled:text-gryt-text\",\n danger: \"text-gryt-danger-11 hover:not-data-disabled:bg-gryt-danger-3\",\n ghost:\n \"text-gryt-muted hover:not-data-disabled:bg-white/8 hover:not-data-disabled:text-gryt-text\"\n};\n\nconst sizeStyles: Record<IconButtonSize, string> = {\n xsmall: \"h-8 w-8\",\n small: \"h-9 w-9\",\n medium: \"h-10 w-10\",\n large: \"h-12 w-12\"\n};\n\nexport interface IconButtonProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseButton>, \"className\"> {\n tone?: IconButtonTone;\n size?: IconButtonSize;\n className?: string;\n}\n\nexport const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(\n function IconButton(\n { className, size = \"medium\", tone = \"neutral\", ...props },\n ref\n ) {\n return (\n <BaseButton\n ref={ref}\n className={cn(\n \"gryt-icon-button\",\n \"inline-flex shrink-0 items-center justify-center border-0 bg-transparent p-0\",\n \"rounded-(--gryt-radius-full) select-none\",\n // scale rather than transform — see the note in Button.\n \"transition-[scale,background-color,color] duration-(--gryt-dur-spring) ease-spring\",\n // A button that opens something does not grow under the cursor.\n // Base UI positions the popup against the trigger's measured box, and\n // it keeps measuring while the popup is open — so a trigger that\n // scales on hover drags its own menu a pixel or two sideways every\n // time the pointer crosses it. aria-haspopup is how the trigger says\n // that is what it is; Base UI puts it there, nothing to pass.\n \"motion-safe:not-[[aria-haspopup]]:hover:not-data-disabled:scale-[1.06]\",\n \"motion-safe:not-[[aria-haspopup]]:active:not-data-disabled:scale-[0.94]\",\n focusRing,\n disabledState,\n sizeStyles[size],\n toneStyles[tone],\n className\n )}\n {...props}\n />\n );\n }\n);\n","import { forwardRef } from \"react\";\nimport type { HTMLAttributes } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport interface SurfaceProps extends HTMLAttributes<HTMLDivElement> {\n elevated?: boolean;\n}\n\nexport const Surface = forwardRef<HTMLDivElement, SurfaceProps>(\n function Surface({ className, elevated = false, ...props }, ref) {\n return (\n <div\n ref={ref}\n className={cn(\n \"gryt-surface rounded-(--gryt-radius-lg) border border-gryt-border p-4 text-gryt-text\",\n elevated ? \"bg-gryt-surface-raised\" : \"bg-gryt-surface\",\n className\n )}\n {...props}\n />\n );\n }\n);\n","import { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport interface MessageBubbleProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n from?: \"user\" | \"assistant\" | \"system\";\n}\n\nexport const MessageBubble = forwardRef<HTMLDivElement, MessageBubbleProps>(\n function MessageBubble(\n { children, className, from = \"assistant\", ...props },\n ref\n ) {\n return (\n <div\n ref={ref}\n className={cn(\n \"gryt-message-bubble\",\n from === \"user\" && \"ml-auto bg-gryt-accent text-gryt-on-accent\",\n from === \"assistant\" &&\n \"mr-auto border border-gryt-border bg-gryt-surface text-gryt-text\",\n from === \"system\" &&\n \"mx-auto border border-dashed border-gryt-border bg-transparent text-gryt-muted\",\n className\n )}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n","import { Field } from \"@base-ui/react/field\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { fieldControl, fieldSizes } from \"../utils/styles\";\n\n// The two sizes live in utils/styles, shared with the Combobox and\n// Autocomplete inputs so all three keep the same shape.\nexport type TextFieldSize = \"small\" | \"medium\";\n\nexport interface TextFieldProps\n extends Omit<\n ComponentPropsWithoutRef<typeof Field.Control>,\n \"className\" | \"size\"\n > {\n label?: ReactNode;\n helperText?: ReactNode;\n error?: boolean;\n size?: TextFieldSize;\n multiline?: boolean;\n minRows?: number;\n className?: string;\n fieldClassName?: string;\n}\n\nexport const TextField = forwardRef<HTMLInputElement, TextFieldProps>(\n function TextField(\n {\n className,\n error = false,\n fieldClassName,\n helperText,\n label,\n minRows = 3,\n multiline = false,\n size = \"medium\",\n ...props\n },\n ref\n ) {\n const control = (\n <Field.Control\n ref={ref}\n // Field.Control renders an input by default; render swaps the element\n // while keeping the field wiring, which is how label association and\n // aria-describedby survive the switch to a textarea.\n render={multiline ? <textarea rows={minRows} /> : undefined}\n className={cn(\n \"gryt-text-field-control\",\n fieldControl,\n multiline && \"resize-y leading-6\",\n error ? \"border-gryt-danger\" : \"border-gryt-border\",\n fieldSizes[size],\n className\n )}\n {...props}\n />\n );\n\n return (\n <Field.Root\n className={cn(\n \"gryt-text-field flex w-full flex-col gap-1.5\",\n fieldClassName\n )}\n >\n {label ? (\n <Field.Label className=\"text-xs font-medium text-gryt-muted\">\n {label}\n </Field.Label>\n ) : null}\n {control}\n {helperText ? (\n <Field.Description\n className={cn(\n \"text-xs\",\n error ? \"text-gryt-danger-11\" : \"text-gryt-muted\"\n )}\n >\n {helperText}\n </Field.Description>\n ) : null}\n </Field.Root>\n );\n }\n);\n","import { PaperPlaneTilt } from \"@phosphor-icons/react\";\nimport { useCallback, useLayoutEffect, useRef } from \"react\";\nimport type {\n FormEvent,\n FormEventHandler,\n TextareaHTMLAttributes\n} from \"react\";\nimport { forwardRef } from \"react\";\nimport { Button } from \"../Button/Button\";\nimport { cn } from \"../utils/cn\";\n\nexport interface ComposerProps\n extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, \"onSubmit\"> {\n onSubmit?: FormEventHandler<HTMLFormElement>;\n submitLabel?: string;\n disabled?: boolean;\n minRows?: number;\n maxRows?: number;\n}\n\nexport const Composer = forwardRef<HTMLTextAreaElement, ComposerProps>(\n function Composer(\n {\n className,\n disabled = false,\n maxRows = 8,\n minRows = 1,\n onSubmit,\n placeholder = \"Message Gryt\",\n submitLabel = \"Send\",\n ...props\n },\n ref\n ) {\n const innerRef = useRef<HTMLTextAreaElement | null>(null);\n\n // Replaces MUI's TextareaAutosize. Reset to auto first, otherwise\n // scrollHeight only ever reports the current height and the box can grow\n // but never shrink.\n const resize = useCallback(() => {\n const node = innerRef.current;\n if (!node) {\n return;\n }\n\n const styles = window.getComputedStyle(node);\n const lineHeight = parseFloat(styles.lineHeight) || 24;\n const vertical =\n parseFloat(styles.paddingTop) + parseFloat(styles.paddingBottom);\n\n node.style.height = \"auto\";\n node.style.height = `${Math.min(\n Math.max(node.scrollHeight, lineHeight * minRows + vertical),\n lineHeight * maxRows + vertical\n )}px`;\n }, [maxRows, minRows]);\n\n useLayoutEffect(resize, [resize, props.value]);\n\n function handleSubmit(event: FormEvent<HTMLFormElement>) {\n if (!onSubmit) {\n event.preventDefault();\n return;\n }\n\n onSubmit(event);\n }\n\n return (\n <form className={cn(\"gryt-composer\", className)} onSubmit={handleSubmit}>\n <textarea\n ref={(node) => {\n innerRef.current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n }}\n rows={minRows}\n disabled={disabled}\n placeholder={placeholder}\n onInput={resize}\n className=\"gryt-composer-textarea disabled:cursor-not-allowed disabled:opacity-60\"\n {...props}\n />\n <Button\n type=\"submit\"\n disabled={disabled}\n size=\"small\"\n endIcon={<PaperPlaneTilt size={14} weight=\"fill\" />}\n >\n {submitLabel}\n </Button>\n </form>\n );\n }\n);\n","import { Avatar as BaseAvatar } from \"@base-ui/react/avatar\";\nimport { owlAvatarDataUri } from \"@gryt/owl\";\nimport { forwardRef, useMemo } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type AvatarSize = \"small\" | \"medium\" | \"large\";\n\nconst sizeStyles: Record<AvatarSize, string> = {\n small: \"h-8 w-8 text-xs\",\n medium: \"h-10 w-10 text-sm\",\n large: \"h-12 w-12 text-base\"\n};\n\n// The intrinsic size of the generated SVG, which CSS then overrides. One number\n// for every avatar size on purpose: it is vector, so nothing is gained by\n// matching the box, and a single value means one memo entry per person rather\n// than one per person per size.\nconst OWL_SIZE = 256;\n\nexport interface AvatarProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseAvatar.Root>, \"className\"> {\n src?: string;\n alt?: string;\n size?: AvatarSize;\n className?: string;\n /**\n * Draws this person's owl, from @gryt/owl.\n *\n * Used when there is no `src`, and also when `src` is given and fails to\n * load — somebody whose uploaded avatar 404s should get their own owl back\n * rather than a letter.\n *\n * Pass `avatarSeed(nickname)` rather than the nickname itself. The two\n * differ for anyone whose name is not already lower case, and an avatar\n * drawn from one seed beside a voice tile tinted from the other is the bug\n * that rule exists to prevent.\n */\n seed?: string;\n // Shown while the image loads and if it fails. Falls back to children, which\n // is how the old MUI-based Avatar was called: <Avatar>G</Avatar>.\n fallback?: ReactNode;\n}\n\nexport const Avatar = forwardRef<HTMLSpanElement, AvatarProps>(function Avatar(\n { alt, children, className, fallback, seed, size = \"medium\", src, ...props },\n ref\n) {\n // Memoised because avatars render in member lists that repaint often, and\n // the seed never changes under a row.\n const owl = useMemo(\n () => (seed ? owlAvatarDataUri(seed, { size: OWL_SIZE }) : undefined),\n [seed]\n );\n\n return (\n <BaseAvatar.Root\n ref={ref}\n className={cn(\n \"gryt-avatar inline-flex shrink-0 items-center justify-center overflow-hidden align-middle select-none\",\n \"rounded-(--gryt-radius-full) bg-gryt-surface-raised font-medium text-gryt-text ring-1 ring-gryt-border\",\n sizeStyles[size],\n className\n )}\n {...props}\n >\n {src ? (\n <BaseAvatar.Image\n src={src}\n alt={alt}\n className=\"h-full w-full object-cover\"\n />\n ) : null}\n {/* The owl goes here rather than through BaseAvatar.Image, and that is\n the whole of what \"no src\" means: the fallback is the only thing\n rendered, so it shows immediately. Base UI's Image renders nothing\n until the browser reports the image loaded, which is right for a URL\n over the network and pointless for a data URI that is already in\n memory — it would blank the avatar for a frame every time.\n\n It also gets the broken-upload case for free: an avatar URL that 404s\n leaves Base UI on the fallback, which is this person's owl. */}\n <BaseAvatar.Fallback className=\"flex h-full w-full items-center justify-center\">\n {owl ? (\n <img src={owl} alt={alt} className=\"h-full w-full object-cover\" />\n ) : (\n (fallback ?? children)\n )}\n </BaseAvatar.Fallback>\n </BaseAvatar.Root>\n );\n});\n","import { Avatar } from \"../Avatar/Avatar\";\nimport type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport { forwardRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport interface ConversationItemProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n title: string;\n subtitle?: string;\n active?: boolean;\n avatar?: ReactNode;\n}\n\nexport const ConversationItem = forwardRef<\n HTMLButtonElement,\n ConversationItemProps\n>(function ConversationItem(\n { active = false, avatar, className, subtitle, title, ...props },\n ref\n) {\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cn(\n \"gryt-conversation-item enabled:cursor-pointer disabled:cursor-not-allowed disabled:opacity-50\",\n active\n ? \"bg-gryt-accent text-gryt-on-accent\"\n : \"text-gryt-text hover:bg-white/5\",\n className\n )}\n {...props}\n >\n {avatar ?? (\n <Avatar\n size=\"small\"\n className={cn(\n active\n // Step 9 by number rather than by its flat name: this is the\n // filled-button pair inverted — the accent as ink on the ink\n // colour it normally carries — and naming the step says so.\n ? \"bg-gryt-on-accent text-gryt-accent-9 ring-transparent\"\n : \"bg-gryt-surface-raised text-gryt-text\"\n )}\n >\n {title.slice(0, 1).toUpperCase()}\n </Avatar>\n )}\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-semibold\">{title}</span>\n {subtitle ? (\n <span\n className={cn(\n \"block truncate text-xs\",\n active ? \"text-gryt-on-accent/85\" : \"text-gryt-muted\"\n )}\n >\n {subtitle}\n </span>\n ) : null}\n </span>\n </button>\n );\n});\n","import { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {\n // Anchored to the top-right of children. A count, a dot, or anything else.\n badgeContent?: ReactNode;\n // Hide when the count is zero, matching how a notification badge is normally\n // wanted. Set false to keep a literal 0 on screen.\n showZero?: boolean;\n max?: number;\n}\n\nexport const Badge = forwardRef<HTMLSpanElement, BadgeProps>(function Badge(\n { badgeContent, children, className, max = 99, showZero = false, ...props },\n ref\n) {\n const numeric = typeof badgeContent === \"number\" ? badgeContent : null;\n const hidden = numeric !== null && numeric === 0 && !showZero;\n const display =\n numeric !== null && numeric > max ? `${max}+` : badgeContent;\n\n return (\n <span\n ref={ref}\n className={cn(\"gryt-badge relative inline-flex\", className)}\n {...props}\n >\n {children}\n {badgeContent !== undefined && !hidden ? (\n <span\n className={cn(\n \"gryt-badge-dot absolute -top-1 -right-1 z-10 inline-flex items-center justify-center\",\n \"min-w-5 rounded-(--gryt-radius-full) px-1.5 py-0.5\",\n \"bg-gryt-accent text-[0.65rem] leading-none font-semibold text-gryt-on-accent\",\n \"ring-2 ring-gryt-bg\"\n )}\n >\n {display}\n </span>\n ) : null}\n </span>\n );\n});\n","import { X } from \"@phosphor-icons/react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing } from \"../utils/styles\";\n\nexport type ChipTone =\n | \"neutral\"\n | \"primary\"\n | \"secondary\"\n | \"success\"\n | \"warning\"\n | \"danger\";\n\n/**\n * Three steps of one scale, rather than three alphas of the fill.\n *\n * The flat name is step 9, the solid step, and it is the same colour in both\n * appearances on purpose. That makes it right for a filled button and wrong for\n * text: on a white panel a success chip came out bright green on pale green.\n * Step 3 is the component background, 6 the hairline and 11 the text, each\n * defined per appearance and each measured.\n */\nconst toneStyles: Record<ChipTone, string> = {\n neutral: \"border-gryt-border bg-gryt-surface-raised text-gryt-text\",\n primary: \"border-gryt-accent-6 bg-gryt-accent-3 text-gryt-accent-11\",\n secondary:\n \"border-gryt-secondary-6 bg-gryt-secondary-3 text-gryt-secondary-11\",\n success: \"border-gryt-success-6 bg-gryt-success-3 text-gryt-success-11\",\n warning: \"border-gryt-warning-6 bg-gryt-warning-3 text-gryt-warning-11\",\n danger: \"border-gryt-danger-6 bg-gryt-danger-3 text-gryt-danger-11\"\n};\n\nexport interface ChipProps\n extends Omit<HTMLAttributes<HTMLSpanElement>, \"onDelete\"> {\n label?: ReactNode;\n tone?: ChipTone;\n icon?: ReactNode;\n onDelete?: () => void;\n}\n\nexport const Chip = forwardRef<HTMLSpanElement, ChipProps>(function Chip(\n { children, className, icon, label, onDelete, tone = \"neutral\", ...props },\n ref\n) {\n return (\n <span\n ref={ref}\n className={cn(\n \"gryt-chip inline-flex items-center gap-1.5 rounded-(--gryt-radius-full) border px-3 py-1 text-xs font-medium\",\n toneStyles[tone],\n className\n )}\n {...props}\n >\n {icon}\n {label ?? children}\n {onDelete ? (\n <button\n type=\"button\"\n aria-label=\"Remove\"\n onClick={onDelete}\n className={cn(\n \"-mr-1 inline-flex h-4 w-4 cursor-pointer items-center justify-center rounded-(--gryt-radius-full)\",\n \"opacity-70 transition-opacity hover:opacity-100\",\n focusRing\n )}\n >\n <X size={10} weight=\"bold\" aria-hidden=\"true\" />\n </button>\n ) : null}\n </span>\n );\n});\n","import { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { Check } from \"@phosphor-icons/react\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { disabledState, focusRing, toneCheckedFill } from \"../utils/styles\";\nimport type { Tone } from \"../utils/styles\";\n\nexport interface CheckboxProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseCheckbox.Root>,\n \"className\"\n > {\n tone?: Tone;\n className?: string;\n}\n\nexport const Checkbox = forwardRef<HTMLButtonElement, CheckboxProps>(\n function Checkbox({ className, tone = \"primary\", ...props }, ref) {\n return (\n <BaseCheckbox.Root\n ref={ref}\n className={cn(\n \"gryt-checkbox flex h-5 w-5 shrink-0 items-center justify-center\",\n \"rounded-(--gryt-radius-sm) border border-gryt-border bg-gryt-surface-raised\",\n \"transition-[scale,background-color,border-color] duration-(--gryt-dur-spring) ease-spring\",\n \"data-checked:border-transparent\",\n // Same grow-and-press as the buttons, so a control reacts to the\n // cursor before it is clicked rather than only after.\n \"hover:not-data-disabled:border-gryt-accent-light\",\n \"motion-safe:hover:not-data-disabled:scale-[1.08]\",\n \"motion-safe:active:not-data-disabled:scale-[0.92]\",\n focusRing,\n disabledState,\n // Unchecked stays a neutral outline; the tone only paints once checked.\n toneCheckedFill[tone],\n className\n )}\n {...props}\n >\n {/* keepMounted is load-bearing: without it Base UI unmounts the\n indicator whenever the box is unchecked, so data-unchecked never\n applies to anything and there is no element to transition from —\n the tick just appears. Kept in the DOM, it can scale and fade in\n both directions. */}\n <BaseCheckbox.Indicator\n keepMounted\n className={cn(\n \"flex origin-center\",\n \"transition-[scale,opacity] duration-(--gryt-dur-spring) ease-spring\",\n // Scaling from 0 rather than from something near 1 is deliberate.\n // The spring's overshoot is a percentage of the travel, so a tick\n // going 0 -> 1 overshoots to 1.12 and visibly springs, while one\n // going 0.95 -> 1 overshoots by 0.006 and does nothing at all.\n \"data-unchecked:scale-0 data-unchecked:opacity-0\",\n \"motion-reduce:transition-none\"\n )}\n >\n <Check size={12} weight=\"bold\" />\n </BaseCheckbox.Indicator>\n </BaseCheckbox.Root>\n );\n }\n);\n","import { Radio as BaseRadio } from \"@base-ui/react/radio\";\nimport { RadioGroup as BaseRadioGroup } from \"@base-ui/react/radio-group\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport {\n disabledState,\n focusRing,\n toneBg,\n toneCheckedBorder\n} from \"../utils/styles\";\nimport type { Tone } from \"../utils/styles\";\n\nexport interface RadioProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseRadio.Root>, \"className\"> {\n tone?: Tone;\n className?: string;\n}\n\nexport const Radio = forwardRef<HTMLButtonElement, RadioProps>(function Radio(\n { className, tone = \"primary\", ...props },\n ref\n) {\n return (\n <BaseRadio.Root\n ref={ref}\n className={cn(\n \"gryt-radio flex h-5 w-5 shrink-0 items-center justify-center\",\n \"rounded-(--gryt-radius-full) border border-gryt-border bg-gryt-surface-raised\",\n \"transition-[scale,background-color,border-color] duration-(--gryt-dur-spring) ease-spring\",\n \"hover:not-data-disabled:border-gryt-accent-light\",\n \"motion-safe:hover:not-data-disabled:scale-[1.08]\",\n \"motion-safe:active:not-data-disabled:scale-[0.92]\",\n focusRing,\n disabledState,\n // Border takes the tone when selected; the dot inside carries the fill.\n toneCheckedBorder[tone],\n className\n )}\n {...props}\n >\n {/* keepMounted so there is an element to transition — see Checkbox. */}\n <BaseRadio.Indicator\n keepMounted\n className={cn(\n \"h-2.5 w-2.5 origin-center rounded-(--gryt-radius-full)\",\n \"transition-[scale,opacity] duration-(--gryt-dur-spring) ease-spring\",\n // From 0, for the same reason as the Checkbox tick — see the note there.\n \"data-unchecked:scale-0 data-unchecked:opacity-0\",\n \"motion-reduce:transition-none\",\n toneBg[tone]\n )}\n />\n </BaseRadio.Root>\n );\n});\n\nexport type RadioGroupProps = ComponentPropsWithoutRef<typeof BaseRadioGroup>;\n\nexport const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(\n function RadioGroup({ className, ...props }, ref) {\n return (\n <BaseRadioGroup\n ref={ref}\n className={cn(\"gryt-radio-group flex flex-col gap-2\", className)}\n {...props}\n />\n );\n }\n);\n","import { Switch as BaseSwitch } from \"@base-ui/react/switch\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { disabledState, focusRing, toneCheckedBg } from \"../utils/styles\";\nimport type { Tone } from \"../utils/styles\";\n\nexport interface SwitchProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseSwitch.Root>, \"className\"> {\n tone?: Tone;\n className?: string;\n}\n\nexport const Switch = forwardRef<HTMLButtonElement, SwitchProps>(\n function Switch({ className, tone = \"primary\", ...props }, ref) {\n return (\n <BaseSwitch.Root\n ref={ref}\n className={cn(\n \"gryt-switch relative inline-flex h-6 w-10 shrink-0 items-center\",\n \"rounded-(--gryt-radius-full) border border-gryt-border bg-gryt-surface-raised p-0.5\",\n \"transition-[scale,background-color,border-color] duration-(--gryt-dur-spring) ease-spring\",\n \"data-checked:border-transparent\",\n \"hover:not-data-disabled:border-gryt-accent-light\",\n \"motion-safe:hover:not-data-disabled:scale-[1.05]\",\n \"motion-safe:active:not-data-disabled:scale-[0.95]\",\n focusRing,\n disabledState,\n toneCheckedBg[tone],\n className\n )}\n {...props}\n >\n <BaseSwitch.Thumb\n className={cn(\n \"h-4.5 w-4.5 rounded-(--gryt-radius-full) bg-gryt-text\",\n \"transition-transform duration-(--gryt-dur-spring) ease-spring motion-reduce:transition-none\",\n \"data-checked:translate-x-4 data-checked:bg-gryt-bg\"\n )}\n />\n </BaseSwitch.Root>\n );\n }\n);\n","import { Slider as BaseSlider } from \"@base-ui/react/slider\";\nimport { useEffect, useRef, useState } from \"react\";\nimport type { ComponentPropsWithoutRef, PointerEvent as ReactPointerEvent } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRingWithin, toneBg } from \"../utils/styles\";\nimport type { Tone } from \"../utils/styles\";\n\nexport interface SliderProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseSlider.Root>, \"className\"> {\n tone?: Tone;\n className?: string;\n \"aria-label\"?: string;\n}\n\n/** How far the pointer has to move before a press counts as a drag. */\nconst DRAG_SLOP = 3;\n\n/**\n * The travel is animated, on the spring.\n *\n * Two things about that are worth reading before changing it.\n *\n * It uses --ease-spring-tight rather than --ease-spring. The overshoot in the\n * standard spring is a percentage of the travel, which is texture on a control\n * that scales in place and a problem on one whose travel is its own width: a\n * full-track jump measured 110% along a 919px track, putting the thumb 96px\n * outside the slider before it came back. The thumb still scales on the\n * standard spring, where the overshoot belongs.\n *\n * And it animates on a click or an arrow key but not under a dragging pointer,\n * where a transition means the thumb lags behind the cursor. Base UI's\n * data-dragging is not the right signal for that: it appears on pointerdown,\n * which is also how you click the track, so keying off it would kill the\n * animation for the most common interaction there is. What matters is whether\n * the pointer has actually moved, so that is what is tracked here — with a few\n * pixels of slop, because a mouse rarely stays perfectly still through a click.\n */\nexport function Slider({\n className,\n tone = \"primary\",\n \"aria-label\": ariaLabel,\n ...props\n}: SliderProps) {\n const [dragging, setDragging] = useState(false);\n const origin = useRef<{ x: number; y: number } | null>(null);\n\n useEffect(() => {\n if (!dragging && origin.current === null) {\n return;\n }\n\n // On window rather than the control: the pointer is very often released\n // outside a 6px-tall track, and a pointerup we never hear about leaves the\n // slider stuck in its dragging state with the animation off for good.\n const end = () => {\n origin.current = null;\n setDragging(false);\n };\n\n window.addEventListener(\"pointerup\", end);\n window.addEventListener(\"pointercancel\", end);\n\n return () => {\n window.removeEventListener(\"pointerup\", end);\n window.removeEventListener(\"pointercancel\", end);\n };\n }, [dragging]);\n\n function handlePointerDown(event: ReactPointerEvent<HTMLDivElement>) {\n origin.current = { x: event.clientX, y: event.clientY };\n }\n\n function handlePointerMove(event: ReactPointerEvent<HTMLDivElement>) {\n const start = origin.current;\n if (start === null || dragging) {\n return;\n }\n\n const moved =\n Math.abs(event.clientX - start.x) > DRAG_SLOP ||\n Math.abs(event.clientY - start.y) > DRAG_SLOP;\n\n if (moved) {\n setDragging(true);\n }\n }\n\n // Base UI positions the thumb with inset-inline-start and sizes the fill with\n // width, so those are the properties that move. `translate` stays out of it:\n // that holds the -50% centring offset, and animating it would drift the thumb\n // off the track rather than along it.\n const travel = dragging\n ? \"transition-none\"\n : \"duration-(--gryt-dur-spring) ease-spring-tight motion-reduce:transition-none\";\n\n return (\n <BaseSlider.Root className={cn(\"gryt-slider w-full\", className)} {...props}>\n <BaseSlider.Control\n className=\"flex w-full cursor-pointer touch-none items-center py-2 select-none\"\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n >\n <BaseSlider.Track className=\"h-1.5 w-full rounded-(--gryt-radius-full) bg-gryt-surface-raised select-none\">\n <BaseSlider.Indicator\n className={cn(\n \"h-full rounded-(--gryt-radius-full) select-none\",\n \"transition-[width]\",\n travel,\n toneBg[tone]\n )}\n />\n {/* Two elements because they animate on two curves, and one element\n gets one timing function. The thumb travels on the tight spring;\n the dot inside it scales on the standard one, so the press still\n has the overshoot every other control here has. */}\n <BaseSlider.Thumb\n aria-label={ariaLabel}\n className={cn(\n \"group h-4 w-4 rounded-(--gryt-radius-full) select-none\",\n \"transition-[inset-inline-start]\",\n travel,\n // The ring goes on the thumb but the focus lands on the visually\n // hidden input inside it, so this has to match a descendant.\n // Without it the slider is the one control here you cannot see\n // yourself tab to.\n focusRingWithin\n )}\n >\n <span\n className={cn(\n \"block h-full w-full rounded-(--gryt-radius-full) bg-gryt-text\",\n \"transition-[scale] duration-(--gryt-dur-spring) ease-spring\",\n \"motion-safe:group-hover:scale-[1.12] motion-safe:group-active:scale-[0.94]\",\n \"motion-reduce:transition-none\"\n )}\n />\n </BaseSlider.Thumb>\n </BaseSlider.Track>\n </BaseSlider.Control>\n </BaseSlider.Root>\n );\n}\n","import { Select as BaseSelect } from \"@base-ui/react/select\";\nimport { CaretUpDown, Check } from \"@phosphor-icons/react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { usePortalContainer } from \"../../portalContainer\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing, popupMotion, popupSurface } from \"../utils/styles\";\n\nexport interface SelectOption {\n label: ReactNode;\n value: string | number;\n disabled?: boolean;\n}\n\nexport type SelectSize = \"small\" | \"medium\";\n\nconst sizeStyles: Record<SelectSize, string> = {\n small: \"min-h-9 px-3 text-sm\",\n medium: \"min-h-11 px-4 text-sm\"\n};\n\nexport interface SelectProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseSelect.Root>,\n \"children\" | \"items\"\n > {\n options?: SelectOption[];\n label?: ReactNode;\n placeholder?: string;\n size?: SelectSize;\n className?: string;\n}\n\n/*\n * The popup portals to the document body, and no caller can change that per\n * call site. It follows GrytProvider's `containOverlays` and nothing else.\n *\n * A `portalContainer` prop existed briefly so a Select inside a dialog could\n * render into it rather than beside it. It does not work, and it caused the\n * dropdowns in the client's server settings to open in the wrong place.\n *\n * Base UI positions the popup by computing coordinates against the viewport. A\n * dialog is `position: fixed` and centres itself with `translate: -50% -50%`,\n * and both of those make it a containing block for positioned descendants — so\n * the coordinates get resolved against the dialog and its own offset is counted\n * twice. Measured in a browser, with the dialog at (16, 226): the popup landed\n * 227px too low and 17px too far right, matching the dialog's origin.\n *\n * Neither escape works. `positionMethod=\"fixed\"` changes nothing. Removing the\n * translate fixes the vertical error and leaves the horizontal one, because the\n * dialog is still positioned.\n *\n * Portalling to the body is correct on both axes and already renders above the\n * dialog, so there was never a stacking problem to solve.\n *\n * The other half of GRYT-242 — a popup that genuinely needs to live inside a\n * themed subtree, because a second theme is being previewed inside a page — is\n * now `containOverlays` on GrytProvider. Deliberately not this prop back: the\n * container is set once, for a subtree, by whoever established the theme. A\n * per-call prop is the thing somebody reaches for to fix a layout problem,\n * which is how the bug above got made.\n */\nexport function Select({\n className,\n label,\n options = [],\n placeholder = \"Select\",\n size = \"medium\",\n ...props\n}: SelectProps) {\n const portalContainer = usePortalContainer();\n\n return (\n <BaseSelect.Root items={options} {...props}>\n <div className={cn(\"gryt-select flex w-full flex-col gap-1.5\", className)}>\n {label ? (\n <BaseSelect.Label className=\"text-xs font-medium text-gryt-muted\">\n {label}\n </BaseSelect.Label>\n ) : null}\n <BaseSelect.Trigger\n className={cn(\n \"flex w-full cursor-pointer items-center justify-between gap-2\",\n \"rounded-(--gryt-radius-xl) border border-gryt-border bg-gryt-surface-raised\",\n \"text-gryt-text select-none\",\n \"transition-colors duration-150 hover:border-gryt-accent-light\",\n \"data-disabled:cursor-not-allowed data-disabled:opacity-60\",\n focusRing,\n sizeStyles[size]\n )}\n >\n <BaseSelect.Value placeholder={placeholder} />\n <BaseSelect.Icon className=\"shrink-0 text-gryt-muted\">\n <CaretUpDown size={16} />\n </BaseSelect.Icon>\n </BaseSelect.Trigger>\n </div>\n\n <BaseSelect.Portal container={portalContainer}>\n <BaseSelect.Positioner\n sideOffset={6}\n className=\"gryt-select-positioner outline-none\"\n >\n <BaseSelect.Popup\n className={cn(\"min-w-(--anchor-width) p-1\", popupSurface, popupMotion)}\n >\n <BaseSelect.List>\n {options.map((option) => (\n <BaseSelect.Item\n key={String(option.value)}\n value={option.value}\n disabled={option.disabled}\n className={cn(\n \"flex cursor-pointer items-center justify-between gap-2\",\n \"rounded-(--gryt-radius-md) px-3 py-2 text-sm text-gryt-text\",\n \"outline-none select-none data-highlighted:bg-gryt-surface-raised\",\n \"data-disabled:cursor-not-allowed data-disabled:opacity-50\"\n )}\n >\n <BaseSelect.ItemText>{option.label}</BaseSelect.ItemText>\n <BaseSelect.ItemIndicator className=\"text-gryt-accent-11\">\n <Check size={14} weight=\"bold\" />\n </BaseSelect.ItemIndicator>\n </BaseSelect.Item>\n ))}\n </BaseSelect.List>\n </BaseSelect.Popup>\n </BaseSelect.Positioner>\n </BaseSelect.Portal>\n </BaseSelect.Root>\n );\n}\n","import { Tooltip as BaseTooltip } from \"@base-ui/react/tooltip\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport { usePortalContainer } from \"../../portalContainer\";\nimport { cn } from \"../utils/cn\";\nimport { popupMotion } from \"../utils/styles\";\n\nexport interface TooltipProps {\n // Kept as a single-child wrapper rather than exposing Base UI's five parts.\n // Both MUI and Radix Themes spell a tooltip this way, so client call sites\n // move across unchanged, and a tooltip has no useful middle ground to\n // compose anyway.\n title: ReactNode;\n children: ReactElement;\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n sideOffset?: number;\n className?: string;\n}\n\n// Hover delay is not set here — it belongs to Tooltip.Provider, which shares\n// timing across every tooltip so moving between two triggers does not restart\n// the wait. GrytProvider renders one; see its tooltipDelay prop.\nexport function Tooltip({\n children,\n className,\n side = \"top\",\n sideOffset = 8,\n title\n}: TooltipProps) {\n const portalContainer = usePortalContainer();\n\n return (\n <BaseTooltip.Root>\n <BaseTooltip.Trigger render={children} />\n <BaseTooltip.Portal container={portalContainer}>\n <BaseTooltip.Positioner\n side={side}\n sideOffset={sideOffset}\n className=\"gryt-tooltip-positioner\"\n >\n <BaseTooltip.Popup\n className={cn(\n \"gryt-tooltip rounded-(--gryt-radius-md) border border-gryt-border bg-gryt-surface-raised\",\n \"px-2.5 py-1.5 text-xs text-gryt-text\",\n popupMotion,\n className\n )}\n >\n {title}\n </BaseTooltip.Popup>\n </BaseTooltip.Positioner>\n </BaseTooltip.Portal>\n </BaseTooltip.Root>\n );\n}\n\n// Base UI shares hover timing across tooltips through this provider, so moving\n// between two triggers skips the delay the second time. GrytProvider renders\n// one already; this is exported for apps that do not use GrytProvider.\nexport const TooltipProvider = BaseTooltip.Provider;\n","import { Separator } from \"@base-ui/react/separator\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport interface DividerProps\n extends Omit<ComponentPropsWithoutRef<typeof Separator>, \"className\"> {\n className?: string;\n}\n\nexport const Divider = forwardRef<HTMLDivElement, DividerProps>(\n function Divider({ className, orientation = \"horizontal\", ...props }, ref) {\n return (\n <Separator\n ref={ref}\n orientation={orientation}\n className={cn(\n \"gryt-divider bg-gryt-border\",\n orientation === \"vertical\" ? \"h-full w-px\" : \"h-px w-full\",\n className\n )}\n {...props}\n />\n );\n }\n);\n","import { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type CardProps = HTMLAttributes<HTMLDivElement>;\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(function Card(\n { className, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cn(\n \"gryt-card rounded-(--gryt-radius-xl) border border-gryt-border bg-gryt-surface text-gryt-text\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport interface CardHeaderProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n title?: ReactNode;\n subheader?: ReactNode;\n}\n\nexport function CardHeader({\n children,\n className,\n subheader,\n title,\n ...props\n}: CardHeaderProps) {\n return (\n <div\n className={cn(\"gryt-card-header flex flex-col gap-1 p-4\", className)}\n {...props}\n >\n {title ? (\n <span className=\"text-base font-semibold text-gryt-text\">{title}</span>\n ) : null}\n {subheader ? (\n <span className=\"text-sm text-gryt-muted\">{subheader}</span>\n ) : null}\n {children}\n </div>\n );\n}\n\nexport function CardContent({\n className,\n ...props\n}: HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn(\n \"gryt-card-content px-4 pb-4 text-sm text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport function CardActions({\n className,\n ...props\n}: HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn(\n \"gryt-card-actions flex items-center gap-2 px-4 pb-4\",\n className\n )}\n {...props}\n />\n );\n}\n","import { forwardRef } from \"react\";\nimport type { HTMLAttributes } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type AlertSeverity = \"info\" | \"success\" | \"warning\" | \"error\";\n\n// Tinted background at low alpha with a matching border, rather than a solid\n// fill — an alert should read as a note on the surface, not a block on top of\n// it.\nconst severityStyles: Record<AlertSeverity, string> = {\n info: \"border-gryt-secondary-6 bg-gryt-secondary-3 text-gryt-secondary-11\",\n success: \"border-gryt-success-6 bg-gryt-success-3 text-gryt-success-11\",\n warning: \"border-gryt-warning-6 bg-gryt-warning-3 text-gryt-warning-11\",\n error: \"border-gryt-danger-6 bg-gryt-danger-3 text-gryt-danger-11\"\n};\n\nexport interface AlertProps extends HTMLAttributes<HTMLDivElement> {\n severity?: AlertSeverity;\n}\n\nexport const Alert = forwardRef<HTMLDivElement, AlertProps>(function Alert(\n { className, severity = \"info\", ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(\n \"gryt-alert rounded-(--gryt-radius-lg) border px-4 py-3 text-sm\",\n severityStyles[severity],\n className\n )}\n {...props}\n />\n );\n});\n","import { Progress as BaseProgress } from \"@base-ui/react/progress\";\nimport { CircleNotch } from \"@phosphor-icons/react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport interface ProgressProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseProgress.Root>,\n \"className\" | \"value\"\n > {\n className?: string;\n // Optional, unlike Base UI's own prop: omitting it gives an indeterminate\n // bar, which is the common case when there is no measurable total.\n value?: number | null;\n}\n\nexport function Progress({ className, value = null, ...props }: ProgressProps) {\n return (\n <BaseProgress.Root\n // null is Base UI's indeterminate, so the default has to be null rather\n // than undefined — undefined is not assignable to its value prop.\n value={value}\n className={cn(\"gryt-progress w-full\", className)}\n {...props}\n >\n <BaseProgress.Track className=\"h-1.5 w-full overflow-hidden rounded-(--gryt-radius-full) bg-gryt-surface-raised\">\n {/* ease-out, not the spring.\n A progress bar is a reading, and the spring overshoots 12% of the\n travel — so a jump to 100% ran past the end of the track and came\n back, which says the job finished, then unfinished, then finished.\n Bouncing is for controls the user just pushed. */}\n <BaseProgress.Indicator\n className={cn(\n \"h-full rounded-(--gryt-radius-full) bg-gryt-accent\",\n \"transition-[width] duration-300 ease-out motion-reduce:transition-none\",\n // Base UI marks the indicator indeterminate and leaves its width\n // unset, and nothing styled that — so an indeterminate Progress\n // rendered a track with an invisible indicator. An empty bar reads\n // as \"nothing has happened yet\", which is why it went unnoticed\n // rather than being reported. GRYT-382.\n value === null && \"gryt-progress-indeterminate\"\n )}\n />\n </BaseProgress.Track>\n </BaseProgress.Root>\n );\n}\n\nexport interface SpinnerProps {\n size?: number;\n className?: string;\n \"aria-label\"?: string;\n}\n\n// Base UI has no spinner — an indeterminate circular indicator is animation\n// rather than behaviour. Phosphor's CircleNotch is the shape, and the spin is\n// a Tailwind utility.\nexport function Spinner({\n className,\n size = 24,\n \"aria-label\": ariaLabel = \"Loading\"\n}: SpinnerProps) {\n return (\n <CircleNotch\n role=\"status\"\n aria-label={ariaLabel}\n size={size}\n weight=\"bold\"\n className={cn(\n \"gryt-spinner text-gryt-accent-11 motion-safe:animate-spin\",\n className\n )}\n />\n );\n}\n","import type { CSSProperties, HTMLAttributes } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type SkeletonVariant = \"text\" | \"rounded\" | \"circular\" | \"rectangular\";\n\nconst variantStyles: Record<SkeletonVariant, string> = {\n text: \"h-4 rounded-(--gryt-radius-sm)\",\n rounded: \"rounded-(--gryt-radius-lg)\",\n circular: \"rounded-(--gryt-radius-full)\",\n rectangular: \"rounded-none\"\n};\n\nexport interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {\n variant?: SkeletonVariant;\n width?: number | string;\n height?: number | string;\n}\n\nexport function Skeleton({\n className,\n height,\n style,\n variant = \"text\",\n width,\n ...props\n}: SkeletonProps) {\n const sizing: CSSProperties = {\n width,\n height,\n ...style\n };\n\n return (\n <div\n aria-hidden=\"true\"\n className={cn(\n // Not bg-gryt-surface-raised. #1e2028 against #1a1d24 is four points of\n // luminance, which is invisible on a laptop screen at an angle — the\n // placeholder that is meant to say \"something is coming\" said nothing.\n // A white wash instead of a fixed colour, so it stays visible on any of\n // the surfaces it can land on rather than only the one it was picked\n // against, and it dims rather than brightens as it pulses.\n \"gryt-skeleton bg-white/9 motion-safe:animate-pulse\",\n variantStyles[variant],\n className\n )}\n style={sizing}\n {...props}\n />\n );\n}\n","import { Dialog as BaseDialog } from \"@base-ui/react/dialog\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, HTMLAttributes } from \"react\";\nimport { cn } from \"../utils/cn\";\n\n// Base UI drives enter and exit animation through data-starting-style and\n// data-ending-style, which it sets for one frame either side of the transition.\n// The element has to carry the transition itself; there is no JS timing.\nconst motion =\n \"transition-[opacity,scale,translate] duration-(--gryt-dur-spring) ease-spring motion-reduce:transition-none\";\n\nexport type DialogBackdropProps = ComponentPropsWithoutRef<\n typeof BaseDialog.Backdrop\n>;\n\nconst Backdrop = forwardRef<HTMLDivElement, DialogBackdropProps>(\n function DialogBackdrop({ className, ...props }, ref) {\n return (\n <BaseDialog.Backdrop\n ref={ref}\n className={cn(\n \"gryt-dialog-backdrop fixed inset-0 min-h-dvh bg-black/60\",\n \"backdrop-blur-(--gryt-backdrop-blur)\",\n motion,\n \"data-starting-style:opacity-0 data-ending-style:opacity-0\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport type DialogPopupProps = ComponentPropsWithoutRef<\n typeof BaseDialog.Popup\n>;\n\n// 32rem, not the 24rem this used to be. Radix Themes, which the client is\n// migrating off, gives Dialog.Content 600px, so a dialog ported across to this\n// one shrank by a third for no reason anybody chose — and the client had grown\n// a w-[27rem]..w-[30rem] override on every dialog to claw some of it back.\n// tailwind-merge means those overrides still win, so this only moves the ones\n// that never said anything. AlertDialog carries the same width deliberately.\nconst Popup = forwardRef<HTMLDivElement, DialogPopupProps>(\n function DialogPopup({ className, ...props }, ref) {\n return (\n <BaseDialog.Popup\n ref={ref}\n className={cn(\n \"gryt-dialog fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2\",\n \"flex w-[32rem] max-w-[calc(100vw-3rem)] flex-col gap-4\",\n \"rounded-(--gryt-radius-lg) border border-gryt-border bg-gryt-surface p-5 text-gryt-text\",\n motion,\n \"data-starting-style:scale-[0.98] data-starting-style:opacity-0\",\n \"data-ending-style:scale-[0.98] data-ending-style:opacity-0\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport type DialogTitleProps = ComponentPropsWithoutRef<\n typeof BaseDialog.Title\n>;\n\nconst Title = forwardRef<HTMLHeadingElement, DialogTitleProps>(\n function DialogTitle({ className, ...props }, ref) {\n return (\n <BaseDialog.Title\n ref={ref}\n className={cn(\n \"gryt-dialog-title text-base font-semibold text-gryt-text\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport type DialogDescriptionProps = ComponentPropsWithoutRef<\n typeof BaseDialog.Description\n>;\n\nconst Description = forwardRef<HTMLParagraphElement, DialogDescriptionProps>(\n function DialogDescription({ className, ...props }, ref) {\n return (\n <BaseDialog.Description\n ref={ref}\n className={cn(\n \"gryt-dialog-description text-sm text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport type DialogFooterProps = HTMLAttributes<HTMLDivElement>;\n\n// Replaces MUI's DialogActions. Base UI has no equivalent part, because it is\n// a plain row of buttons and nothing about it needs behaviour.\nconst Footer = forwardRef<HTMLDivElement, DialogFooterProps>(\n function DialogFooter({ className, ...props }, ref) {\n return (\n <div\n ref={ref}\n className={cn(\n \"gryt-dialog-footer flex justify-end gap-3\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport const Dialog = {\n Root: BaseDialog.Root,\n Trigger: BaseDialog.Trigger,\n Portal: BaseDialog.Portal,\n Close: BaseDialog.Close,\n Backdrop,\n Popup,\n Title,\n Description,\n Footer\n};\n","import { useCallback, useSyncExternalStore } from \"react\";\n\nconst noop = () => () => {};\n\n/**\n * Matches a media query, safely on the server.\n *\n * Written here rather than taken from Base UI's `unstable-use-media-query`,\n * because a component library should not put an explicitly unstable export on\n * its public path.\n *\n * useSyncExternalStore rather than useState in an effect: matchMedia is an\n * external store, and reading it into state after mount means an extra render\n * on every consumer plus a frame where the answer is wrong. The server snapshot\n * is false so the first client paint agrees with the server's.\n */\nexport function useMediaQuery(query: string): boolean {\n const subscribe = useCallback(\n (onChange: () => void) => {\n if (typeof window === \"undefined\" || !window.matchMedia) return noop();\n const list = window.matchMedia(query);\n list.addEventListener(\"change\", onChange);\n return () => list.removeEventListener(\"change\", onChange);\n },\n [query]\n );\n\n const getSnapshot = useCallback(() => {\n if (typeof window === \"undefined\" || !window.matchMedia) return false;\n return window.matchMedia(query).matches;\n }, [query]);\n\n return useSyncExternalStore(subscribe, getSnapshot, () => false);\n}\n","import { Drawer as BaseDrawer } from \"@base-ui/react/drawer\";\nimport { createContext, forwardRef, useContext } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { useMediaQuery } from \"../utils/useMediaQuery\";\n\nexport type DrawerSide = \"left\" | \"right\" | \"top\" | \"bottom\";\n\n/**\n * A panel pinned to an edge of the screen, and a sheet on small screens.\n *\n * Built on Base UI's `drawer` rather than on `dialog`, which is what this used\n * to be. A dialog pinned to an edge looks like a drawer and does none of what\n * one is for: it cannot be dragged away, it does not follow the finger, and it\n * does not know which edge it belongs to. The primitive brings swipe-to-dismiss,\n * snap points and nested stacking, and it drives the drag through CSS variables\n * so the panel tracks the pointer without a re-render per frame.\n *\n * `side` lives on Root, not on Popup as it used to. It has to: the swipe\n * direction is Root's business, and Viewport and Popup both need to agree with\n * it. Callers passing `side` to Popup will need to move it up one level.\n */\n\n/** Which way you drag to dismiss, per edge. */\nconst swipeBySide = {\n left: \"left\",\n right: \"right\",\n top: \"up\",\n bottom: \"down\"\n} as const;\n\nconst SideContext = createContext<DrawerSide>(\"right\");\n\n/** Where the panel sits inside the viewport. */\nconst viewportBySide: Record<DrawerSide, string> = {\n left: \"items-stretch justify-start\",\n right: \"items-stretch justify-end\",\n top: \"items-start justify-center\",\n bottom: \"items-end justify-center\"\n};\n\n/**\n * Corners are rounded on the edges away from the origin only.\n *\n * A sheet coming up from the bottom is still attached to the bottom of the\n * screen, so rounding its bottom corners would float it off an edge it has not\n * left. Rounding the leading edge alone is what makes it read as attached.\n */\nconst radiusBySide: Record<DrawerSide, string> = {\n left: \"rounded-r-(--gryt-radius-xl)\",\n right: \"rounded-l-(--gryt-radius-xl)\",\n top: \"rounded-b-(--gryt-radius-xl)\",\n bottom: \"rounded-t-(--gryt-radius-xl)\"\n};\n\n/**\n * Size, the overhang, and the off-screen resting transform.\n *\n * The panel runs --gryt-drawer-bleed past its edge and hangs that much\n * off-screen, with matching padding so content sits where it would have. The\n * spring settles onto its target from both directions, and without the overhang\n * a fractional undershoot shows a seam of backdrop down the edge.\n */\nconst popupBySide: Record<DrawerSide, string> = {\n left: [\n \"h-full w-[calc(20rem+var(--gryt-drawer-bleed))] max-w-[calc(85vw+var(--gryt-drawer-bleed))]\",\n \"-ml-(--gryt-drawer-bleed) border-r py-5 pr-5 pl-[calc(1.25rem+var(--gryt-drawer-bleed))]\",\n \"[transform:translateX(var(--drawer-swipe-movement-x))]\",\n \"data-starting-style:[transform:translateX(calc(-100%+var(--gryt-drawer-bleed)))]\",\n \"data-ending-style:[transform:translateX(calc(-100%+var(--gryt-drawer-bleed)))]\"\n ].join(\" \"),\n right: [\n \"h-full w-[calc(20rem+var(--gryt-drawer-bleed))] max-w-[calc(85vw+var(--gryt-drawer-bleed))]\",\n \"-mr-(--gryt-drawer-bleed) border-l py-5 pl-5 pr-[calc(1.25rem+var(--gryt-drawer-bleed))]\",\n \"[transform:translateX(var(--drawer-swipe-movement-x))]\",\n \"data-starting-style:[transform:translateX(calc(100%-var(--gryt-drawer-bleed)))]\",\n \"data-ending-style:[transform:translateX(calc(100%-var(--gryt-drawer-bleed)))]\"\n ].join(\" \"),\n top: [\n \"w-full max-h-[calc(85vh+var(--gryt-drawer-bleed))]\",\n \"-mt-(--gryt-drawer-bleed) border-b px-5 pb-5 pt-[calc(1.25rem+var(--gryt-drawer-bleed))]\",\n \"[transform:translateY(var(--drawer-swipe-movement-y))]\",\n \"data-starting-style:[transform:translateY(calc(-100%+var(--gryt-drawer-bleed)))]\",\n \"data-ending-style:[transform:translateY(calc(-100%+var(--gryt-drawer-bleed)))]\"\n ].join(\" \"),\n bottom: [\n \"w-full max-h-[calc(85vh+var(--gryt-drawer-bleed))]\",\n \"-mb-(--gryt-drawer-bleed) border-t px-5 pt-5 pb-[calc(1.25rem+var(--gryt-drawer-bleed))]\",\n \"[transform:translateY(var(--drawer-swipe-movement-y))]\",\n \"data-starting-style:[transform:translateY(calc(100%-var(--gryt-drawer-bleed)))]\",\n \"data-ending-style:[transform:translateY(calc(100%-var(--gryt-drawer-bleed)))]\"\n ].join(\" \")\n};\n\nexport interface DrawerRootProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseDrawer.Root>,\n \"swipeDirection\"\n > {\n /** Edge the panel is pinned to. Ignored on small screens unless sheetOnMobile is false. */\n side?: DrawerSide;\n /**\n * Become a bottom sheet under 768px.\n *\n * A side panel is a desktop shape. On a phone it eats the width the content\n * needs and puts the drag gesture on the axis the browser uses for back\n * navigation. Set false to keep `side` at every width.\n */\n sheetOnMobile?: boolean;\n children?: ReactNode;\n}\n\nfunction Root({\n side = \"right\",\n sheetOnMobile = true,\n children,\n ...props\n}: DrawerRootProps) {\n const isMobile = useMediaQuery(\"(max-width: 767px)\");\n const resolved: DrawerSide = sheetOnMobile && isMobile ? \"bottom\" : side;\n\n return (\n <SideContext.Provider value={resolved}>\n <BaseDrawer.Root swipeDirection={swipeBySide[resolved]} {...props}>\n {children}\n </BaseDrawer.Root>\n </SideContext.Provider>\n );\n}\n\nexport type DrawerViewportProps = ComponentPropsWithoutRef<\n typeof BaseDrawer.Viewport\n>;\n\nconst Viewport = forwardRef<HTMLDivElement, DrawerViewportProps>(\n function DrawerViewport({ className, ...props }, ref) {\n const side = useContext(SideContext);\n return (\n <BaseDrawer.Viewport\n ref={ref}\n className={cn(\n // z-50 matters: the popup is no longer positioned itself, so the\n // viewport is what has to sit above the page. Without it a sticky\n // site header renders over the panel.\n \"gryt-drawer-viewport fixed inset-0 z-50 flex\",\n viewportBySide[side],\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport type DrawerPopupProps = ComponentPropsWithoutRef<\n typeof BaseDrawer.Popup\n>;\n\nconst Popup = forwardRef<HTMLDivElement, DrawerPopupProps>(function DrawerPopup(\n { className, ...props },\n ref\n) {\n const side = useContext(SideContext);\n return (\n <BaseDrawer.Popup\n ref={ref}\n className={cn(\n \"gryt-drawer flex flex-col gap-4 border-gryt-border bg-gryt-surface text-gryt-text\",\n \"overflow-y-auto overscroll-contain outline-none\",\n \"transition-transform duration-(--gryt-dur-spring-soft) ease-spring-tight\",\n // While the finger is down the panel must track it exactly. Any\n // duration here turns a drag into a drag plus lag.\n \"data-swiping:duration-0 data-swiping:select-none\",\n \"motion-reduce:transition-none\",\n popupBySide[side],\n radiusBySide[side],\n className\n )}\n {...props}\n />\n );\n});\n\nconst Backdrop = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseDrawer.Backdrop>\n>(function DrawerBackdrop({ className, ...props }, ref) {\n return (\n <BaseDrawer.Backdrop\n ref={ref}\n className={cn(\n \"gryt-drawer-backdrop fixed inset-0 z-50 min-h-dvh bg-black/60\",\n \"backdrop-blur-(--gryt-backdrop-blur)\",\n // Lightens as the panel is dragged away, so letting go halfway does not\n // leave a full-strength scrim over a half-gone sheet.\n \"[opacity:calc(1-var(--drawer-swipe-progress,0))]\",\n \"transition-opacity duration-(--gryt-dur-spring-soft) ease-spring-tight\",\n \"data-swiping:duration-0\",\n \"data-starting-style:opacity-0 data-ending-style:opacity-0\",\n \"motion-reduce:transition-none\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport interface DrawerGrabberProps {\n className?: string;\n}\n\n/**\n * The bar people expect to drag on a sheet.\n *\n * Rendered only for the top and bottom edges: on a left or right panel it would\n * be pointing the wrong way, and a horizontal drawer is a desktop shape where\n * nobody reaches for a grab bar anyway. Decorative — the whole popup is\n * draggable, so this is a hint, not the control.\n */\nfunction Grabber({ className }: DrawerGrabberProps) {\n const side = useContext(SideContext);\n if (side !== \"bottom\" && side !== \"top\") return null;\n\n return (\n <div\n aria-hidden\n className={cn(\n \"gryt-drawer-grabber mx-auto h-1.5 w-10 shrink-0 rounded-(--gryt-radius-full) bg-gryt-border\",\n side === \"top\" && \"order-last\",\n className\n )}\n />\n );\n}\n\nexport const Drawer = {\n Root,\n Trigger: BaseDrawer.Trigger,\n Portal: BaseDrawer.Portal,\n Backdrop,\n Viewport,\n Popup,\n Content: BaseDrawer.Content,\n Grabber,\n Close: BaseDrawer.Close,\n Title: BaseDrawer.Title,\n Description: BaseDrawer.Description\n};\n","import { Menu as BaseMenu } from \"@base-ui/react/menu\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { popupMotion, popupSurface } from \"../utils/styles\";\n\nexport type MenuPopupProps = ComponentPropsWithoutRef<typeof BaseMenu.Popup>;\nexport type MenuItemProps = ComponentPropsWithoutRef<typeof BaseMenu.Item>;\nexport type MenuPositionerProps = ComponentPropsWithoutRef<\n typeof BaseMenu.Positioner\n>;\n\nconst Positioner = forwardRef<HTMLDivElement, MenuPositionerProps>(\n function MenuPositioner({ className, sideOffset = 8, ...props }, ref) {\n return (\n <BaseMenu.Positioner\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\"gryt-menu-positioner outline-none\", className)}\n {...props}\n />\n );\n }\n);\n\nconst Popup = forwardRef<HTMLDivElement, MenuPopupProps>(function MenuPopup(\n { className, ...props },\n ref\n) {\n return (\n <BaseMenu.Popup\n ref={ref}\n className={cn(\n \"gryt-menu min-w-44 p-1 outline-none\",\n popupSurface,\n popupMotion,\n className\n )}\n {...props}\n />\n );\n});\n\nconst Item = forwardRef<HTMLDivElement, MenuItemProps>(function MenuItem(\n { className, ...props },\n ref\n) {\n return (\n <BaseMenu.Item\n ref={ref}\n className={cn(\n \"gryt-menu-item flex cursor-pointer items-center gap-2 rounded-(--gryt-radius-md)\",\n \"px-3 py-2 text-sm text-gryt-text outline-none select-none\",\n // Base UI drives keyboard and pointer highlight through the same\n // attribute, so arrow keys and the mouse land on identical styling.\n \"data-highlighted:bg-gryt-surface-raised\",\n \"data-disabled:cursor-not-allowed data-disabled:opacity-50\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Separator = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseMenu.Separator>\n>(function MenuSeparator({ className, ...props }, ref) {\n return (\n <BaseMenu.Separator\n ref={ref}\n className={cn(\"gryt-menu-separator my-1 h-px bg-gryt-border\", className)}\n {...props}\n />\n );\n});\n\nexport const Menu = {\n Root: BaseMenu.Root,\n Trigger: BaseMenu.Trigger,\n Portal: BaseMenu.Portal,\n Positioner,\n Popup,\n Item,\n Separator\n};\n","import { Tabs as BaseTabs } from \"@base-ui/react/tabs\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing } from \"../utils/styles\";\n\nexport type TabsProps = ComponentPropsWithoutRef<typeof BaseTabs.Root>;\nexport type TabsListProps = ComponentPropsWithoutRef<typeof BaseTabs.List>;\nexport type TabProps = ComponentPropsWithoutRef<typeof BaseTabs.Tab>;\nexport type TabsPanelProps = ComponentPropsWithoutRef<typeof BaseTabs.Panel>;\n\n/**\n * Orientation is Base UI's `orientation` prop on Root, and every part below\n * styles itself from the `data-orientation` it puts on the DOM rather than from\n * a prop of ours. That is why none of these take an orientation of their own:\n * setting it in two places is how a list ends up vertical and its indicator\n * still travelling sideways.\n *\n * Vertical is the same visual language turned ninety degrees — the accent pill\n * still slides between rows. It suits a rail of five or six destinations. Past\n * about a dozen the filled pill becomes a block of accent parked in the corner\n * of the screen, and a quieter marker is the better call; the docs sidebar is\n * that case and deliberately does not use this.\n */\nconst Root = forwardRef<HTMLDivElement, TabsProps>(function TabsRoot(\n { className, ...props },\n ref\n) {\n return (\n <BaseTabs.Root\n ref={ref}\n className={cn(\n \"gryt-tabs\",\n // Vertical puts the rail and the panel side by side. min-w-0 on the\n // panel does the rest; without the flex here the panel lands under the\n // rail and the layout reads as a very tall accordion.\n \"data-[orientation=vertical]:flex data-[orientation=vertical]:items-stretch\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst List = forwardRef<HTMLDivElement, TabsListProps>(function TabsList(\n { className, ...props },\n ref\n) {\n return (\n <BaseTabs.List\n ref={ref}\n className={cn(\n \"gryt-tabs-list relative inline-flex items-center gap-1 rounded-(--gryt-radius-full) bg-gryt-surface-raised p-1\",\n // A rail, not a pill: rows are full width and the corner radius drops\n // to lg, because a 999px radius on a tall box bows its short edges.\n \"data-[orientation=vertical]:flex data-[orientation=vertical]:shrink-0\",\n \"data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch\",\n \"data-[orientation=vertical]:rounded-(--gryt-radius-lg)\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Tab = forwardRef<HTMLButtonElement, TabProps>(function Tab(\n { className, ...props },\n ref\n) {\n return (\n <BaseTabs.Tab\n ref={ref}\n className={cn(\n \"gryt-tab inline-flex min-h-8 cursor-pointer items-center justify-center whitespace-nowrap\",\n \"rounded-(--gryt-radius-full) border-0 bg-transparent px-4 py-1.5\",\n \"text-sm font-medium text-gryt-muted select-none\",\n // Scale as well as colour, matching Button exactly — 1.03 under the\n // cursor, 0.96 pressed, on the spring duration and curve. A tab that\n // only changed colour read as not being a button at all next to\n // anything that did move, and the owl designer's rail was reported as\n // \"not using the Gryt UI tabs\" for precisely that reason.\n //\n // motion-safe, so the whole thing is colour-only for anybody who asked\n // for reduced motion.\n \"relative z-10 hover:text-gryt-text\",\n \"transition-[scale,color,background-color] duration-(--gryt-dur-spring) ease-spring\",\n \"motion-safe:hover:scale-[1.03] motion-safe:active:scale-[0.96]\",\n \"motion-reduce:transition-colors motion-reduce:duration-150\",\n // Base UI marks the selected tab with data-active, not data-selected.\n // The fill moved to Indicator so it can travel between tabs; the tab\n // itself only changes its text colour.\n \"data-active:text-gryt-on-accent\",\n // Left-aligned and taller in a rail. Centred labels in a vertical list\n // leave the text edge ragged, which is what makes a rail look untidy.\n \"data-[orientation=vertical]:min-h-9 data-[orientation=vertical]:justify-start\",\n \"data-[orientation=vertical]:gap-2.5 data-[orientation=vertical]:px-3\",\n \"data-[orientation=vertical]:rounded-(--gryt-radius-md)\",\n \"data-disabled:cursor-not-allowed data-disabled:opacity-50\",\n focusRing,\n className\n )}\n {...props}\n />\n );\n});\n\nexport type TabsIndicatorProps = ComponentPropsWithoutRef<\n typeof BaseTabs.Indicator\n>;\n\n// Base UI measures the active tab and publishes --active-tab-left and\n// --active-tab-width, plus --active-tab-top and --active-tab-height, which is\n// what lets the pill slide rather than jump. renderBeforeHydration keeps it\n// positioned on the first paint instead of animating in from the left edge.\n//\n// The vertical rules hang off the ancestor's data-orientation rather than the\n// indicator's own. Root is the part guaranteed to carry it, and an indicator\n// that reads its orientation from somewhere other than the root it belongs to\n// is a bug waiting for someone to nest two sets of tabs.\nconst Indicator = forwardRef<HTMLSpanElement, TabsIndicatorProps>(\n function TabsIndicator({ className, ...props }, ref) {\n return (\n <BaseTabs.Indicator\n ref={ref}\n renderBeforeHydration\n className={cn(\n \"gryt-tabs-indicator absolute top-1 left-0 z-0 h-[calc(100%-0.5rem)]\",\n \"w-(--active-tab-width) translate-x-(--active-tab-left)\",\n \"rounded-(--gryt-radius-full) bg-gryt-accent\",\n \"transition-[translate,width] duration-(--gryt-dur-spring) ease-spring\",\n \"motion-reduce:transition-none\",\n // Same pill, travelling down the rail instead of across the row.\n \"[[data-orientation=vertical]_&]:top-0 [[data-orientation=vertical]_&]:left-1\",\n \"[[data-orientation=vertical]_&]:h-(--active-tab-height)\",\n \"[[data-orientation=vertical]_&]:w-[calc(100%-0.5rem)]\",\n \"[[data-orientation=vertical]_&]:translate-x-0\",\n \"[[data-orientation=vertical]_&]:translate-y-(--active-tab-top)\",\n \"[[data-orientation=vertical]_&]:rounded-(--gryt-radius-md)\",\n \"[[data-orientation=vertical]_&]:transition-[translate,height]\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Panel = forwardRef<HTMLDivElement, TabsPanelProps>(function TabsPanel(\n { className, ...props },\n ref\n) {\n return (\n <BaseTabs.Panel\n ref={ref}\n className={cn(\n \"gryt-tabs-panel pt-3 text-sm text-gryt-text\",\n // Beside the rail rather than under it, and allowed to shrink so long\n // content wraps instead of pushing the rail off screen.\n \"data-[orientation=vertical]:min-w-0 data-[orientation=vertical]:flex-1\",\n \"data-[orientation=vertical]:pt-0 data-[orientation=vertical]:pl-4\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport const Tabs = Object.assign(Root, { List, Tab, Panel, Indicator });\nexport { Tab };\n","import { Accordion as BaseAccordion } from \"@base-ui/react/accordion\";\nimport { CaretDown } from \"@phosphor-icons/react\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing } from \"../utils/styles\";\n\nexport type AccordionProps = ComponentPropsWithoutRef<\n typeof BaseAccordion.Root\n>;\nexport type AccordionItemProps = ComponentPropsWithoutRef<\n typeof BaseAccordion.Item\n>;\nexport type AccordionPanelProps = ComponentPropsWithoutRef<\n typeof BaseAccordion.Panel\n>;\n\nconst Root = forwardRef<HTMLDivElement, AccordionProps>(function AccordionRoot(\n { className, ...props },\n ref\n) {\n return (\n <BaseAccordion.Root\n ref={ref}\n className={cn(\n \"gryt-accordion flex w-full flex-col gap-2 rounded-(--gryt-radius-xl) border border-gryt-border bg-gryt-surface p-2\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Item = forwardRef<HTMLDivElement, AccordionItemProps>(\n function AccordionItem({ className, ...props }, ref) {\n return (\n <BaseAccordion.Item\n ref={ref}\n className={cn(\"gryt-accordion-item\", className)}\n {...props}\n />\n );\n }\n);\n\nexport interface AccordionTriggerProps\n extends ComponentPropsWithoutRef<typeof BaseAccordion.Trigger> {\n // Defaults to a caret that rotates when the panel opens. Pass one to\n // override it, or null for no indicator at all.\n expandIcon?: ReactNode;\n}\n\nconst Trigger = forwardRef<HTMLButtonElement, AccordionTriggerProps>(\n function AccordionTrigger({ children, className, expandIcon, ...props }, ref) {\n return (\n <BaseAccordion.Header className=\"gryt-accordion-header m-0\">\n <BaseAccordion.Trigger\n ref={ref}\n className={cn(\n \"gryt-accordion-trigger flex w-full cursor-pointer items-center justify-between gap-3\",\n \"rounded-(--gryt-radius-lg) border-0 bg-transparent px-3 py-2.5\",\n \"text-left text-sm font-medium text-gryt-text select-none\",\n \"transition-colors duration-150 hover:bg-gryt-surface-raised\",\n \"data-disabled:cursor-not-allowed data-disabled:opacity-50\",\n focusRing,\n className\n )}\n {...props}\n >\n {children}\n {expandIcon === undefined ? (\n <CaretDown\n size={16}\n // Base UI flags the open panel on the trigger, so the caret needs\n // no state of its own.\n className=\"shrink-0 transition-transform duration-(--gryt-dur-spring) ease-spring data-panel-open:rotate-180 motion-reduce:transition-none\"\n />\n ) : (\n expandIcon\n )}\n </BaseAccordion.Trigger>\n </BaseAccordion.Header>\n );\n }\n);\n\nconst Panel = forwardRef<HTMLDivElement, AccordionPanelProps>(\n function AccordionPanel({ children, className, ...props }, ref) {\n return (\n <BaseAccordion.Panel\n ref={ref}\n className={cn(\n \"gryt-accordion-panel overflow-hidden text-sm text-gryt-muted\",\n // Base UI measures the panel and exposes the height as a variable,\n // which is what makes a real open and close transition possible.\n \"h-[var(--accordion-panel-height)] transition-[height] duration-(--gryt-dur-spring-soft) ease-spring\",\n \"data-starting-style:h-0 data-ending-style:h-0\",\n \"motion-reduce:transition-none\",\n className\n )}\n {...props}\n >\n <div className=\"px-3 pt-1 pb-3\">{children}</div>\n </BaseAccordion.Panel>\n );\n }\n);\n\nexport const Accordion = Object.assign(Root, { Item, Trigger, Panel });\n","import { ContextMenu as BaseContextMenu } from \"@base-ui/react/context-menu\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Menu } from \"../Menu/Menu\";\n\nexport type ContextMenuPositionerProps = ComponentPropsWithoutRef<\n typeof BaseContextMenu.Positioner\n>;\n\n/**\n * A right-click menu: a message, a member, a channel.\n *\n * Base UI builds this out of Menu's own parts — its Popup, Item and Separator\n * are literally Menu's components — so this reuses the styled ones rather than\n * restyling them. A context menu that drifted from the dropdown menu would be\n * a bug nobody notices until both are on screen at once.\n */\nconst Positioner = forwardRef<HTMLDivElement, ContextMenuPositionerProps>(\n function ContextMenuPositioner({ className, sideOffset = 2, ...props }, ref) {\n return (\n <BaseContextMenu.Positioner\n ref={ref}\n // Smaller than Menu's 8. This anchors to the pointer rather than to a\n // trigger element, and 8px from the cursor reads as a menu that missed.\n sideOffset={sideOffset}\n className={cn(\"gryt-context-menu-positioner outline-none\", className)}\n {...props}\n />\n );\n }\n);\n\nexport const ContextMenu = {\n Root: BaseContextMenu.Root,\n Trigger: BaseContextMenu.Trigger,\n Portal: BaseContextMenu.Portal,\n Positioner,\n Popup: Menu.Popup,\n Item: Menu.Item,\n Separator: Menu.Separator,\n Group: BaseContextMenu.Group,\n GroupLabel: BaseContextMenu.GroupLabel,\n SubmenuRoot: BaseContextMenu.SubmenuRoot,\n SubmenuTrigger: BaseContextMenu.SubmenuTrigger\n};\n","import { Popover as BasePopover } from \"@base-ui/react/popover\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { popupMotion, popupSurface } from \"../utils/styles\";\n\nexport type PopoverPopupProps = ComponentPropsWithoutRef<\n typeof BasePopover.Popup\n>;\nexport type PopoverPositionerProps = ComponentPropsWithoutRef<\n typeof BasePopover.Positioner\n>;\n\nconst Positioner = forwardRef<HTMLDivElement, PopoverPositionerProps>(\n function PopoverPositioner({ className, sideOffset = 8, ...props }, ref) {\n return (\n <BasePopover.Positioner\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\"gryt-popover-positioner outline-none\", className)}\n {...props}\n />\n );\n }\n);\n\n// Wider default than Menu: this holds prose and controls — a member card, a\n// permissions summary — rather than a column of one-line items.\nconst Popup = forwardRef<HTMLDivElement, PopoverPopupProps>(\n function PopoverPopup({ className, ...props }, ref) {\n return (\n <BasePopover.Popup\n ref={ref}\n className={cn(\n \"gryt-popover max-w-[min(20rem,calc(100vw-2rem))] p-4 outline-none\",\n popupSurface,\n popupMotion,\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Title = forwardRef<\n HTMLHeadingElement,\n ComponentPropsWithoutRef<typeof BasePopover.Title>\n>(function PopoverTitle({ className, ...props }, ref) {\n return (\n <BasePopover.Title\n ref={ref}\n className={cn(\n \"gryt-popover-title text-sm font-semibold text-gryt-text\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Description = forwardRef<\n HTMLParagraphElement,\n ComponentPropsWithoutRef<typeof BasePopover.Description>\n>(function PopoverDescription({ className, ...props }, ref) {\n return (\n <BasePopover.Description\n ref={ref}\n className={cn(\n \"gryt-popover-description mt-1 text-sm leading-6 text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport const Popover = {\n Root: BasePopover.Root,\n Trigger: BasePopover.Trigger,\n Portal: BasePopover.Portal,\n Positioner,\n Popup,\n Title,\n Description,\n Close: BasePopover.Close,\n Arrow: BasePopover.Arrow\n};\n","import { Toast as BaseToast } from \"@base-ui/react/toast\";\nimport { X } from \"@phosphor-icons/react\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type ToastSeverity =\n | \"neutral\"\n | \"info\"\n | \"success\"\n | \"warning\"\n | \"danger\";\n\n/**\n * Severity is a tinted edge and a wash, not a filled card.\n *\n * Alert tints its whole surface, and that is right for something sitting in\n * the page where it has to compete with the content around it. A toast is\n * already floating over everything with nothing to compete with, so the same\n * treatment reads as shouting. The border carries the colour and the fill stays\n * near the surface underneath.\n */\nconst severityStyles: Record<ToastSeverity, string> = {\n neutral: \"border-white/8 bg-gryt-surface\",\n info: \"border-gryt-secondary-6 bg-gryt-secondary-2\",\n success: \"border-gryt-success-6 bg-gryt-success-2\",\n warning: \"border-gryt-warning-6 bg-gryt-warning-2\",\n danger: \"border-gryt-danger-6 bg-gryt-danger-2\"\n};\n\nexport interface ToastRootProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseToast.Root>, \"className\"> {\n severity?: ToastSeverity;\n className?: string;\n}\nexport type ToastViewportProps = ComponentPropsWithoutRef<\n typeof BaseToast.Viewport\n>;\n\n/**\n * Transient notice: connection lost, invite copied, message failed to send.\n *\n * design.md's stance is silent success — most things that worked should say\n * nothing. This is for the cases where the user is not looking at the thing\n * that changed, which in a voice client is most of them.\n */\nconst Viewport = forwardRef<HTMLDivElement, ToastViewportProps>(\n function ToastViewport({ className, ...props }, ref) {\n return (\n <BaseToast.Viewport\n ref={ref}\n className={cn(\n \"gryt-toast-viewport fixed right-4 bottom-4 z-50 flex w-[min(22rem,calc(100vw-2rem))]\",\n \"flex-col gap-2 outline-none\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Root = forwardRef<HTMLDivElement, ToastRootProps>(function ToastRoot(\n { className, severity = \"neutral\", ...props },\n ref\n) {\n return (\n <BaseToast.Root\n ref={ref}\n className={cn(\n \"gryt-toast relative flex flex-col p-3 pr-9\",\n // Not popupSurface. That border is --gryt-border, a solid slate line\n // that is right for a menu anchored to the thing that opened it and too\n // heavy for a card floating in the corner with nothing behind it. A\n // white hairline separates it from the page without drawing a box\n // around it.\n \"rounded-(--gryt-radius-xl) border text-gryt-text\",\n severityStyles[severity],\n // Swiping is a pointer gesture, so the toast follows the finger\n // through Base UI's swipe variables before it animates out.\n \"transition-[opacity,transform] duration-(--gryt-dur-spring) ease-spring\",\n \"data-starting-style:translate-y-2 data-starting-style:opacity-0\",\n \"data-ending-style:translate-y-2 data-ending-style:opacity-0\",\n \"motion-reduce:transition-none\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Title = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseToast.Title>\n>(function ToastTitle({ className, ...props }, ref) {\n return (\n <BaseToast.Title\n ref={ref}\n className={cn(\n \"gryt-toast-title text-sm font-semibold text-gryt-text\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Description = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseToast.Description>\n>(function ToastDescription({ className, ...props }, ref) {\n return (\n <BaseToast.Description\n ref={ref}\n className={cn(\n \"gryt-toast-description mt-0.5 text-sm leading-6 text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Close = forwardRef<\n HTMLButtonElement,\n ComponentPropsWithoutRef<typeof BaseToast.Close>\n>(function ToastClose({ className, children, ...props }, ref) {\n return (\n <BaseToast.Close\n ref={ref}\n aria-label=\"Close\"\n className={cn(\n \"gryt-toast-close absolute top-2.5 right-2.5 inline-flex h-6 w-6 items-center justify-center\",\n \"rounded-(--gryt-radius-full) border-0 bg-transparent text-gryt-muted\",\n \"transition-colors hover:bg-white/8 hover:text-gryt-text motion-reduce:transition-none\",\n \"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gryt-accent-light\",\n className\n )}\n {...props}\n >\n {children ?? <X size={14} weight=\"bold\" />}\n </BaseToast.Close>\n );\n});\n\nconst Action = forwardRef<\n HTMLButtonElement,\n ComponentPropsWithoutRef<typeof BaseToast.Action>\n>(function ToastAction({ className, ...props }, ref) {\n return (\n <BaseToast.Action\n ref={ref}\n className={cn(\n \"gryt-toast-action mt-2 self-start rounded-(--gryt-radius-full) border-0\",\n \"bg-gryt-accent px-3 py-1.5 text-sm font-medium text-gryt-on-accent\",\n \"transition-[scale] duration-(--gryt-dur-spring) ease-spring\",\n \"motion-safe:hover:scale-[1.04] motion-safe:active:scale-[0.96]\",\n \"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gryt-accent-light\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport const Toast = {\n Provider: BaseToast.Provider,\n Portal: BaseToast.Portal,\n Viewport,\n Root,\n Title,\n Description,\n Close,\n Action\n};\n\n/**\n * Raise a toast without importing Base UI directly.\n *\n * Taken off the namespace rather than re-exported from \"@base-ui/react/toast\":\n * at that path the hook is a type-only declaration, and re-exporting it as a\n * value fails under isolatedModules. The value lives on the parts namespace.\n */\nexport const useToastManager = BaseToast.useToastManager;\n","import { ScrollArea as BaseScrollArea } from \"@base-ui/react/scroll-area\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type ScrollAreaRootProps = ComponentPropsWithoutRef<\n typeof BaseScrollArea.Root\n>;\nexport type ScrollAreaViewportProps = ComponentPropsWithoutRef<\n typeof BaseScrollArea.Viewport\n>;\nexport type ScrollAreaScrollbarProps = ComponentPropsWithoutRef<\n typeof BaseScrollArea.Scrollbar\n>;\n\nconst Root = forwardRef<HTMLDivElement, ScrollAreaRootProps>(\n function ScrollAreaRoot({ className, ...props }, ref) {\n return (\n <BaseScrollArea.Root\n ref={ref}\n className={cn(\"gryt-scroll-area relative\", className)}\n {...props}\n />\n );\n }\n);\n\n// overscroll-contain so a message list that hits its end does not hand the\n// scroll to the page behind it.\nconst Viewport = forwardRef<HTMLDivElement, ScrollAreaViewportProps>(\n function ScrollAreaViewport({ className, ...props }, ref) {\n return (\n <BaseScrollArea.Viewport\n ref={ref}\n className={cn(\n \"gryt-scroll-area-viewport h-full w-full overscroll-contain\",\n \"focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-gryt-accent-light\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Scrollbar = forwardRef<HTMLDivElement, ScrollAreaScrollbarProps>(\n function ScrollAreaScrollbar({ className, orientation, ...props }, ref) {\n return (\n <BaseScrollArea.Scrollbar\n ref={ref}\n orientation={orientation}\n className={cn(\n \"gryt-scroll-area-scrollbar flex touch-none p-0.5 select-none\",\n // Fades in on hover or while scrolling rather than sitting there\n // permanently — a chat sidebar is mostly not being scrolled.\n \"opacity-0 transition-opacity duration-(--gryt-dur-fast)\",\n \"data-hovering:opacity-100 data-scrolling:opacity-100\",\n \"motion-reduce:transition-none\",\n orientation === \"horizontal\" ? \"h-2 flex-col\" : \"w-2\",\n className\n )}\n {...props}\n >\n <BaseScrollArea.Thumb className=\"flex-1 rounded-(--gryt-radius-full) bg-gryt-border transition-colors hover:bg-gryt-muted motion-reduce:transition-none\" />\n </BaseScrollArea.Scrollbar>\n );\n }\n);\n\nexport const ScrollArea = {\n Root,\n Viewport,\n Scrollbar,\n Content: BaseScrollArea.Content,\n Corner: BaseScrollArea.Corner\n};\n","import { Toggle as BaseToggle } from \"@base-ui/react/toggle\";\nimport { ToggleGroup as BaseToggleGroup } from \"@base-ui/react/toggle-group\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { disabledState, focusRing } from \"../utils/styles\";\n\ntype ToggleTone = \"primary\" | \"secondary\" | \"neutral\" | \"danger\";\ntype ToggleSize = \"xsmall\" | \"small\" | \"medium\" | \"large\";\n\n// Unpressed reads like IconButton's tinted target; pressed fills. A mute button\n// has to be legible as on or off from across the room, so the two states differ\n// in fill rather than only in colour.\nconst toneStyles: Record<ToggleTone, string> = {\n primary: [\n \"text-gryt-muted hover:not-data-disabled:bg-white/8\",\n \"data-pressed:bg-gryt-accent data-pressed:text-gryt-on-accent\",\n \"data-pressed:hover:not-data-disabled:bg-gryt-accent\"\n ].join(\" \"),\n secondary: [\n \"text-gryt-muted hover:not-data-disabled:bg-white/8\",\n \"data-pressed:bg-gryt-secondary data-pressed:text-gryt-on-secondary\",\n \"data-pressed:hover:not-data-disabled:bg-gryt-secondary\"\n ].join(\" \"),\n neutral: [\n \"text-gryt-muted hover:not-data-disabled:bg-white/8\",\n \"data-pressed:bg-gryt-surface-hover data-pressed:text-gryt-text\"\n ].join(\" \"),\n // For destructive-while-active controls: mic muted, camera off.\n danger: [\n \"text-gryt-muted hover:not-data-disabled:bg-white/8\",\n \"data-pressed:bg-gryt-danger data-pressed:text-gryt-on-danger\",\n \"data-pressed:hover:not-data-disabled:bg-gryt-danger\"\n ].join(\" \")\n};\n\nconst sizeStyles: Record<ToggleSize, string> = {\n xsmall: \"h-8 min-w-8 px-2 text-xs\",\n small: \"h-9 min-w-9 px-2.5 text-sm\",\n medium: \"h-10 min-w-10 px-3 text-sm\",\n large: \"h-12 min-w-12 px-4 text-base\"\n};\n\nexport interface ToggleProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseToggle>, \"className\"> {\n tone?: ToggleTone;\n size?: ToggleSize;\n className?: string;\n}\n\nexport const Toggle = forwardRef<HTMLButtonElement, ToggleProps>(\n function Toggle(\n { className, size = \"medium\", tone = \"primary\", ...props },\n ref\n ) {\n return (\n <BaseToggle\n ref={ref}\n className={cn(\n \"gryt-toggle\",\n \"inline-flex shrink-0 items-center justify-center gap-2 border-0 bg-transparent\",\n \"rounded-(--gryt-radius-full) font-medium select-none\",\n // scale rather than transform — see the note in Button.\n \"transition-[scale,background-color,color] duration-(--gryt-dur-spring) ease-spring\",\n \"motion-safe:hover:not-data-disabled:scale-[1.06]\",\n \"motion-safe:active:not-data-disabled:scale-[0.94]\",\n focusRing,\n disabledState,\n sizeStyles[size],\n toneStyles[tone],\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport interface ToggleGroupProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseToggleGroup>, \"className\"> {\n className?: string;\n}\n\n// A rail around a set of Toggles. Base UI handles roving focus, so arrow keys\n// move between items and only one tab stop enters the group.\nexport const ToggleGroup = forwardRef<HTMLDivElement, ToggleGroupProps>(\n function ToggleGroup({ className, ...props }, ref) {\n return (\n <BaseToggleGroup\n ref={ref}\n className={cn(\n \"gryt-toggle-group inline-flex items-center gap-1\",\n \"rounded-(--gryt-radius-full) border border-gryt-border bg-gryt-surface p-1\",\n className\n )}\n {...props}\n />\n );\n }\n);\n","import { Meter as BaseMeter } from \"@base-ui/react/meter\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type MeterTone = \"primary\" | \"success\" | \"warning\" | \"danger\";\n\nconst toneFill: Record<MeterTone, string> = {\n primary: \"bg-gryt-accent\",\n success: \"bg-gryt-success\",\n warning: \"bg-gryt-warning\",\n danger: \"bg-gryt-danger\"\n};\n\nexport interface MeterProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseMeter.Root>,\n \"className\" | \"value\"\n > {\n value: number;\n label?: ReactNode;\n /** Show the formatted value at the end of the label row. */\n showValue?: boolean;\n tone?: MeterTone;\n className?: string;\n}\n\n/**\n * A measurement inside a known range — mic input level, disk used, how full a\n * server is.\n *\n * Deliberately not Progress. Progress says \"this task is 40% done and heading\n * for 100%\"; a meter says \"this is the reading right now\", and a reading at\n * 100% is often the bad case rather than the finished one. They also announce\n * differently to a screen reader, which is the part that actually matters.\n *\n * The indicator moves rather than snapping, but only just — 120ms and ease-out,\n * no spring. This used to have no transition at all, on the grounds that the\n * common caller is a mic level updating every animation frame and easing a\n * value that changes 60 times a second only makes it lag behind the sound.\n * That reasoning holds for the mic and nothing else: disk used, server\n * capacity, a level polled a few times a second all read as broken when they\n * teleport. 120ms is shorter than the gap between polls at 4Hz, so a fast feed\n * still lands on every value it is handed.\n */\nexport function Meter({\n className,\n value,\n label,\n showValue = false,\n tone = \"primary\",\n ...props\n}: MeterProps) {\n return (\n <BaseMeter.Root\n value={value}\n className={cn(\"gryt-meter flex w-full flex-col gap-1.5\", className)}\n {...props}\n >\n {(label || showValue) && (\n <div className=\"flex items-baseline justify-between gap-2\">\n {label ? (\n <BaseMeter.Label className=\"text-sm text-gryt-muted\">\n {label}\n </BaseMeter.Label>\n ) : (\n <span />\n )}\n {showValue && (\n <BaseMeter.Value className=\"font-mono text-xs text-gryt-muted tabular-nums\" />\n )}\n </div>\n )}\n <BaseMeter.Track className=\"h-1.5 w-full overflow-hidden rounded-(--gryt-radius-full) bg-gryt-surface-raised\">\n {/* Short and linear-ish, so the bar moves rather than snapping.\n The note above says no transition, and that was written for a mic\n level updating every frame — easing a value that changes 60 times a\n second only makes it lag. But most meters are not that: disk used,\n how full a server is, a level polled a few times a second, and those\n all read as broken when they teleport. 120ms is under the gap\n between polls at 4Hz, so a fast feed still lands on every value it\n is given; it just gets there over two frames instead of one. */}\n <BaseMeter.Indicator\n className={cn(\n \"h-full rounded-(--gryt-radius-full)\",\n \"transition-[width] duration-120 ease-out motion-reduce:transition-none\",\n toneFill[tone]\n )}\n />\n </BaseMeter.Track>\n </BaseMeter.Root>\n );\n}\n","import { AlertDialog as BaseAlertDialog } from \"@base-ui/react/alert-dialog\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type AlertDialogPopupProps = ComponentPropsWithoutRef<\n typeof BaseAlertDialog.Popup\n>;\n\n/**\n * A dialog you cannot dismiss by accident — for \"Leave this server?\".\n *\n * Styled identically to Dialog on purpose; the difference is behaviour, not\n * looks. Escape and clicking the backdrop do nothing here, so answering\n * requires picking one of the buttons. Using this where Dialog belongs is worse\n * than not having it, because it takes away the escape people expect.\n */\nconst Popup = forwardRef<HTMLDivElement, AlertDialogPopupProps>(\n function AlertDialogPopup({ className, ...props }, ref) {\n return (\n <BaseAlertDialog.Popup\n ref={ref}\n className={cn(\n \"gryt-alert-dialog fixed top-1/2 left-1/2 z-50 -translate-x-1/2 -translate-y-1/2\",\n \"flex w-[32rem] max-w-[calc(100vw-3rem)] flex-col gap-4\",\n \"rounded-(--gryt-radius-lg) border border-gryt-border bg-gryt-surface p-5 text-gryt-text\",\n \"outline-none\",\n \"transition-[opacity,scale] duration-(--gryt-dur-spring) ease-spring motion-reduce:transition-none\",\n \"data-starting-style:scale-[0.98] data-starting-style:opacity-0\",\n \"data-ending-style:scale-[0.98] data-ending-style:opacity-0\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Backdrop = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseAlertDialog.Backdrop>\n>(function AlertDialogBackdrop({ className, ...props }, ref) {\n return (\n <BaseAlertDialog.Backdrop\n ref={ref}\n className={cn(\n \"gryt-alert-dialog-backdrop fixed inset-0 z-50 min-h-dvh bg-black/60\",\n \"backdrop-blur-(--gryt-backdrop-blur)\",\n \"transition-opacity duration-(--gryt-dur-spring) ease-spring motion-reduce:transition-none\",\n \"data-starting-style:opacity-0 data-ending-style:opacity-0\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Title = forwardRef<\n HTMLHeadingElement,\n ComponentPropsWithoutRef<typeof BaseAlertDialog.Title>\n>(function AlertDialogTitle({ className, ...props }, ref) {\n return (\n <BaseAlertDialog.Title\n ref={ref}\n className={cn(\n \"gryt-alert-dialog-title text-lg font-semibold text-gryt-text\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Description = forwardRef<\n HTMLParagraphElement,\n ComponentPropsWithoutRef<typeof BaseAlertDialog.Description>\n>(function AlertDialogDescription({ className, ...props }, ref) {\n return (\n <BaseAlertDialog.Description\n ref={ref}\n className={cn(\n \"gryt-alert-dialog-description text-sm leading-6 text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport const AlertDialog = {\n Root: BaseAlertDialog.Root,\n Trigger: BaseAlertDialog.Trigger,\n Portal: BaseAlertDialog.Portal,\n Backdrop,\n Popup,\n Title,\n Description,\n Close: BaseAlertDialog.Close\n};\n","import { Combobox as BaseCombobox } from \"@base-ui/react/combobox\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport {\n fieldControl,\n fieldSizes,\n focusRing,\n popupMotion,\n popupSurface\n} from \"../utils/styles\";\n\n/**\n * Shared with Autocomplete, which is the same list wearing different\n * semantics. Exported so the two cannot drift, the way ContextMenu shares\n * Menu's item.\n */\nexport const listboxItemClass = [\n \"flex cursor-default items-center gap-2 rounded-(--gryt-radius-md)\",\n \"px-3 py-2 text-sm text-gryt-text outline-none select-none\",\n // Base UI drives keyboard and pointer highlight through one attribute, so\n // arrow keys and the mouse land on identical styling.\n \"data-highlighted:bg-gryt-surface-raised\",\n \"data-selected:text-gryt-accent-11\",\n \"data-disabled:cursor-not-allowed data-disabled:opacity-50\"\n].join(\" \");\n\n/**\n * The typeahead input on both Combobox and Autocomplete.\n *\n * This is TextField's control, through the same shared constant, so the three\n * places you can type in this library are the same shape. It used to be its own\n * class list asking for `rounded-(--gryt-radius-input)` — a token that has never\n * existed — so it rendered with square corners next to a fully rounded\n * TextField.\n */\nexport const listboxInputClass = [\n fieldControl,\n fieldSizes.medium,\n \"border-gryt-border\",\n focusRing\n].join(\" \");\n\nexport type ComboboxPopupProps = ComponentPropsWithoutRef<\n typeof BaseCombobox.Popup\n>;\n\nconst Input = forwardRef<\n HTMLInputElement,\n ComponentPropsWithoutRef<typeof BaseCombobox.Input>\n>(function ComboboxInput({ className, ...props }, ref) {\n return (\n <BaseCombobox.Input\n ref={ref}\n className={cn(\"gryt-combobox-input\", listboxInputClass, className)}\n {...props}\n />\n );\n});\n\nconst Positioner = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseCombobox.Positioner>\n>(function ComboboxPositioner({ className, sideOffset = 6, ...props }, ref) {\n return (\n <BaseCombobox.Positioner\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\"gryt-combobox-positioner outline-none\", className)}\n {...props}\n />\n );\n});\n\nconst Popup = forwardRef<HTMLDivElement, ComboboxPopupProps>(\n function ComboboxPopup({ className, ...props }, ref) {\n return (\n <BaseCombobox.Popup\n ref={ref}\n className={cn(\n \"gryt-combobox max-h-64 w-(--anchor-width) overflow-y-auto overscroll-contain p-1 outline-none\",\n popupSurface,\n popupMotion,\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Item = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseCombobox.Item>\n>(function ComboboxItem({ className, ...props }, ref) {\n return (\n <BaseCombobox.Item\n ref={ref}\n className={cn(\"gryt-combobox-item\", listboxItemClass, className)}\n {...props}\n />\n );\n});\n\nconst Empty = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseCombobox.Empty>\n>(function ComboboxEmpty({ className, ...props }, ref) {\n return (\n <BaseCombobox.Empty\n ref={ref}\n className={cn(\n \"gryt-combobox-empty px-3 py-2 text-sm text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n});\n\n/**\n * Pick from a list, narrowed by typing. Select with a filter, in effect.\n *\n * Supports multiple selection with chips, which is what a member picker or a\n * role assignment wants. Use Autocomplete instead when the value is free text\n * and the list is only a suggestion.\n */\nexport const Combobox = {\n Root: BaseCombobox.Root,\n Input,\n InputGroup: BaseCombobox.InputGroup,\n Trigger: BaseCombobox.Trigger,\n Icon: BaseCombobox.Icon,\n Clear: BaseCombobox.Clear,\n Value: BaseCombobox.Value,\n Chips: BaseCombobox.Chips,\n Chip: BaseCombobox.Chip,\n ChipRemove: BaseCombobox.ChipRemove,\n Portal: BaseCombobox.Portal,\n Positioner,\n Popup,\n List: BaseCombobox.List,\n Item,\n ItemIndicator: BaseCombobox.ItemIndicator,\n Group: BaseCombobox.Group,\n GroupLabel: BaseCombobox.GroupLabel,\n Empty,\n Separator: BaseCombobox.Separator\n};\n","import { Autocomplete as BaseAutocomplete } from \"@base-ui/react/autocomplete\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { listboxInputClass, listboxItemClass } from \"../Combobox/Combobox\";\nimport { popupMotion, popupSurface } from \"../utils/styles\";\n\n/**\n * A text input that suggests as you type.\n *\n * The difference from Combobox is what the value is allowed to be: here the\n * typed text is the answer and the list is a suggestion, so a search box or a\n * tag input belongs here. Combobox is for when the value must come from the\n * list. They share item and input styling deliberately — two lists that look\n * different for no reason is worse than one that looks the same.\n */\n\nconst Input = forwardRef<\n HTMLInputElement,\n ComponentPropsWithoutRef<typeof BaseAutocomplete.Input>\n>(function AutocompleteInput({ className, ...props }, ref) {\n return (\n <BaseAutocomplete.Input\n ref={ref}\n className={cn(\"gryt-autocomplete-input\", listboxInputClass, className)}\n {...props}\n />\n );\n});\n\nconst Positioner = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseAutocomplete.Positioner>\n>(function AutocompletePositioner({ className, sideOffset = 6, ...props }, ref) {\n return (\n <BaseAutocomplete.Positioner\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\"gryt-autocomplete-positioner outline-none\", className)}\n {...props}\n />\n );\n});\n\nconst Popup = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseAutocomplete.Popup>\n>(function AutocompletePopup({ className, ...props }, ref) {\n return (\n <BaseAutocomplete.Popup\n ref={ref}\n className={cn(\n \"gryt-autocomplete max-h-64 w-(--anchor-width) overflow-y-auto overscroll-contain p-1 outline-none\",\n popupSurface,\n popupMotion,\n className\n )}\n {...props}\n />\n );\n});\n\nconst Item = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseAutocomplete.Item>\n>(function AutocompleteItem({ className, ...props }, ref) {\n return (\n <BaseAutocomplete.Item\n ref={ref}\n className={cn(\"gryt-autocomplete-item\", listboxItemClass, className)}\n {...props}\n />\n );\n});\n\nconst Empty = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseAutocomplete.Empty>\n>(function AutocompleteEmpty({ className, ...props }, ref) {\n return (\n <BaseAutocomplete.Empty\n ref={ref}\n className={cn(\n \"gryt-autocomplete-empty px-3 py-2 text-sm text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport const Autocomplete = {\n Root: BaseAutocomplete.Root,\n Input,\n InputGroup: BaseAutocomplete.InputGroup,\n Trigger: BaseAutocomplete.Trigger,\n Icon: BaseAutocomplete.Icon,\n Clear: BaseAutocomplete.Clear,\n Value: BaseAutocomplete.Value,\n Portal: BaseAutocomplete.Portal,\n Positioner,\n Popup,\n List: BaseAutocomplete.List,\n Item,\n Group: BaseAutocomplete.Group,\n GroupLabel: BaseAutocomplete.GroupLabel,\n Empty,\n Separator: BaseAutocomplete.Separator\n};\n","import { CheckboxGroup as BaseCheckboxGroup } from \"@base-ui/react/checkbox-group\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type CheckboxGroupProps = ComponentPropsWithoutRef<\n typeof BaseCheckboxGroup\n>;\n\n/**\n * A set of checkboxes sharing one value array.\n *\n * Worth having over a hand-rolled array of Checkboxes for the parent case: give\n * it `allValues` and a checkbox marked `parent` becomes a working\n * indeterminate tri-state, which is fiddly to get right by hand and is exactly\n * what a permissions list needs.\n */\nexport const CheckboxGroup = forwardRef<HTMLDivElement, CheckboxGroupProps>(\n function CheckboxGroup({ className, ...props }, ref) {\n return (\n <BaseCheckboxGroup\n ref={ref}\n className={cn(\"gryt-checkbox-group flex flex-col gap-2\", className)}\n {...props}\n />\n );\n }\n);\n","import { Collapsible as BaseCollapsible } from \"@base-ui/react/collapsible\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing } from \"../utils/styles\";\n\nexport type CollapsibleTriggerProps = ComponentPropsWithoutRef<\n typeof BaseCollapsible.Trigger\n>;\nexport type CollapsiblePanelProps = ComponentPropsWithoutRef<\n typeof BaseCollapsible.Panel\n>;\n\n/**\n * One region that opens and closes — a channel category, an advanced section.\n *\n * Accordion is a set of these that know about each other. Reach for this when\n * there is only one, so nothing has to pretend to be a one-item accordion.\n */\nconst Trigger = forwardRef<HTMLButtonElement, CollapsibleTriggerProps>(\n function CollapsibleTrigger({ className, ...props }, ref) {\n return (\n <BaseCollapsible.Trigger\n ref={ref}\n className={cn(\n \"gryt-collapsible-trigger flex w-full items-center justify-between gap-2\",\n \"rounded-(--gryt-radius-md) border-0 bg-transparent px-2 py-2 text-left\",\n \"text-sm font-medium text-gryt-text select-none\",\n \"transition-colors hover:bg-gryt-surface-raised motion-reduce:transition-none\",\n focusRing,\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Panel = forwardRef<HTMLDivElement, CollapsiblePanelProps>(\n function CollapsiblePanel({ className, ...props }, ref) {\n return (\n <BaseCollapsible.Panel\n ref={ref}\n className={cn(\n \"gryt-collapsible-panel overflow-hidden\",\n // Base UI measures the panel and exposes the height as a variable, so\n // this animates to the content's real height rather than to a guess.\n \"h-(--collapsible-panel-height) transition-[height] duration-(--gryt-dur-spring) ease-spring\",\n \"data-starting-style:h-0 data-ending-style:h-0\",\n \"motion-reduce:transition-none\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport const Collapsible = {\n Root: BaseCollapsible.Root,\n Trigger,\n Panel\n};\n","import { Form as BaseForm } from \"@base-ui/react/form\";\nimport { Fieldset as BaseFieldset } from \"@base-ui/react/fieldset\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type FormProps = ComponentPropsWithoutRef<typeof BaseForm>;\n\n/**\n * Wires server-side errors back to the fields that caused them.\n *\n * Pass `errors` keyed by field name and Base UI routes each message to the\n * matching Field, so a rejected form points at the input rather than printing a\n * paragraph at the top that the user has to map back themselves.\n */\nexport const Form = forwardRef<HTMLFormElement, FormProps>(function Form(\n { className, ...props },\n ref\n) {\n return (\n <BaseForm\n ref={ref}\n className={cn(\"gryt-form flex flex-col gap-(--gryt-space-lg)\", className)}\n {...props}\n />\n );\n});\n\nexport type FieldsetProps = ComponentPropsWithoutRef<typeof BaseFieldset.Root>;\n\nconst FieldsetRoot = forwardRef<HTMLFieldSetElement, FieldsetProps>(\n function Fieldset({ className, ...props }, ref) {\n return (\n <BaseFieldset.Root\n ref={ref}\n className={cn(\n \"gryt-fieldset flex min-w-0 flex-col gap-3 border-0 p-0\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Legend = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseFieldset.Legend>\n>(function FieldsetLegend({ className, ...props }, ref) {\n return (\n <BaseFieldset.Legend\n ref={ref}\n className={cn(\n \"gryt-fieldset-legend text-sm font-semibold text-gryt-text\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport const Fieldset = { Root: FieldsetRoot, Legend };\n","import { Menubar as BaseMenubar } from \"@base-ui/react/menubar\";\nimport { NavigationMenu as BaseNavigationMenu } from \"@base-ui/react/navigation-menu\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing, popupMotion, popupSurface } from \"../utils/styles\";\n\n/**\n * A bar of menus that behave as one — File, Edit, View.\n *\n * Once any menu is open, moving along the bar opens the next without a second\n * click, which is the behaviour that separates a menubar from several\n * independent Menus sitting next to each other.\n */\nexport type MenubarProps = ComponentPropsWithoutRef<typeof BaseMenubar>;\n\nexport const Menubar = forwardRef<HTMLDivElement, MenubarProps>(\n function Menubar({ className, ...props }, ref) {\n return (\n <BaseMenubar\n ref={ref}\n className={cn(\n \"gryt-menubar flex items-center gap-1\",\n \"rounded-(--gryt-radius-md) border border-gryt-border bg-gryt-surface p-1\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\n/**\n * Site-level navigation whose items open panels.\n *\n * Distinct from Menubar: the items are links first and the panels can hold\n * layout — a column of sections, a promo — rather than a list of commands. The\n * viewport animates between panels so moving along the bar resizes rather than\n * closing and reopening.\n */\nconst Trigger = forwardRef<\n HTMLButtonElement,\n ComponentPropsWithoutRef<typeof BaseNavigationMenu.Trigger>\n>(function NavigationMenuTrigger({ className, ...props }, ref) {\n return (\n <BaseNavigationMenu.Trigger\n ref={ref}\n className={cn(\n \"gryt-navigation-menu-trigger flex items-center gap-1.5 rounded-(--gryt-radius-md)\",\n \"border-0 bg-transparent px-3 py-2 text-sm font-medium text-gryt-text select-none\",\n \"transition-colors hover:bg-gryt-surface-raised motion-reduce:transition-none\",\n \"data-popup-open:bg-gryt-surface-raised\",\n focusRing,\n className\n )}\n {...props}\n />\n );\n});\n\nconst Popup = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseNavigationMenu.Popup>\n>(function NavigationMenuPopup({ className, ...props }, ref) {\n return (\n <BaseNavigationMenu.Popup\n ref={ref}\n className={cn(\n \"gryt-navigation-menu-popup outline-none\",\n popupSurface,\n popupMotion,\n className\n )}\n {...props}\n />\n );\n});\n\n// Wrapped rather than re-exported raw, so it carries a class the app can hang a\n// z-index on. Every other popup in here already has one; this was the last\n// positioner without, and a consumer cannot style what it cannot select.\nconst Positioner = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseNavigationMenu.Positioner>\n>(function NavigationMenuPositioner({ className, ...props }, ref) {\n return (\n <BaseNavigationMenu.Positioner\n ref={ref}\n className={cn(\"gryt-navigation-menu-positioner outline-none\", className)}\n {...props}\n />\n );\n});\n\nconst Viewport = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseNavigationMenu.Viewport>\n>(function NavigationMenuViewport({ className, ...props }, ref) {\n return (\n <BaseNavigationMenu.Viewport\n ref={ref}\n className={cn(\n \"gryt-navigation-menu-viewport relative overflow-hidden\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Link = forwardRef<\n HTMLAnchorElement,\n ComponentPropsWithoutRef<typeof BaseNavigationMenu.Link>\n>(function NavigationMenuLink({ className, ...props }, ref) {\n return (\n <BaseNavigationMenu.Link\n ref={ref}\n className={cn(\n \"gryt-navigation-menu-link block rounded-(--gryt-radius-md) px-3 py-2\",\n \"text-sm text-gryt-text no-underline outline-none\",\n \"transition-colors hover:bg-gryt-surface-raised motion-reduce:transition-none\",\n focusRing,\n className\n )}\n {...props}\n />\n );\n});\n\nexport const NavigationMenu = {\n Root: BaseNavigationMenu.Root,\n List: BaseNavigationMenu.List,\n Item: BaseNavigationMenu.Item,\n Trigger,\n Content: BaseNavigationMenu.Content,\n Portal: BaseNavigationMenu.Portal,\n Positioner,\n Viewport,\n Popup,\n Link,\n Icon: BaseNavigationMenu.Icon,\n Arrow: BaseNavigationMenu.Arrow\n};\n","import { NumberField as BaseNumberField } from \"@base-ui/react/number-field\";\nimport { Minus, Plus } from \"@phosphor-icons/react\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { disabledState, focusRing } from \"../utils/styles\";\n\nexport interface NumberFieldProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseNumberField.Root>,\n \"className\"\n > {\n label?: ReactNode;\n className?: string;\n /**\n * Drag the label sideways to change the value.\n *\n * Base UI calls this a scrub area, and it is the reason to use this over a\n * plain input for things like volume or bitrate — coarse adjustment by drag,\n * exact entry by typing, without two controls.\n */\n scrubbable?: boolean;\n}\n\nconst stepButton =\n \"flex h-9 w-9 shrink-0 items-center justify-center border-0 bg-transparent text-gryt-muted transition-colors hover:not-data-disabled:bg-white/8 hover:not-data-disabled:text-gryt-text motion-reduce:transition-none disabled:cursor-not-allowed disabled:opacity-50\";\n\nexport const NumberField = forwardRef<HTMLDivElement, NumberFieldProps>(\n function NumberField(\n { className, label, scrubbable = false, ...props },\n ref\n ) {\n return (\n <BaseNumberField.Root\n ref={ref}\n className={cn(\"gryt-number-field flex flex-col gap-1.5\", className)}\n {...props}\n >\n {label &&\n (scrubbable ? (\n <BaseNumberField.ScrubArea className=\"cursor-ew-resize text-sm text-gryt-muted select-none\">\n {label}\n <BaseNumberField.ScrubAreaCursor />\n </BaseNumberField.ScrubArea>\n ) : (\n <span className=\"text-sm text-gryt-muted\">{label}</span>\n ))}\n <BaseNumberField.Group\n className={cn(\n \"flex w-fit items-center overflow-hidden rounded-(--gryt-radius-full)\",\n \"border border-gryt-border bg-gryt-surface-raised\",\n \"focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-gryt-accent-light\",\n disabledState\n )}\n >\n <BaseNumberField.Decrement\n aria-label=\"Decrease\"\n className={cn(stepButton, \"rounded-l-(--gryt-radius-full)\")}\n >\n <Minus size={14} weight=\"bold\" />\n </BaseNumberField.Decrement>\n <BaseNumberField.Input\n className={cn(\n \"w-16 border-0 bg-transparent px-1 py-2 text-center\",\n \"font-mono text-sm text-gryt-text tabular-nums outline-none\",\n focusRing\n )}\n />\n <BaseNumberField.Increment\n aria-label=\"Increase\"\n className={cn(stepButton, \"rounded-r-(--gryt-radius-full)\")}\n >\n <Plus size={14} weight=\"bold\" />\n </BaseNumberField.Increment>\n </BaseNumberField.Group>\n </BaseNumberField.Root>\n );\n }\n);\n","import { OTPField as BaseOtpField } from \"@base-ui/react/otp-field\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing } from \"../utils/styles\";\n\nexport interface OtpFieldProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseOtpField.Root>,\n \"className\" | \"length\"\n > {\n /** How many characters the code has. Required by Base UI; defaulted here. */\n length?: number;\n className?: string;\n}\n\n/**\n * A one-time code, one box per character.\n *\n * Base UI handles the parts that are tedious and easy to get wrong: paste a\n * whole code into any box and it distributes across all of them, backspace\n * steps back a box, and the arrow keys move between them.\n */\nexport const OtpField = forwardRef<HTMLDivElement, OtpFieldProps>(\n function OtpField({ className, length = 6, ...props }, ref) {\n return (\n <BaseOtpField.Root\n ref={ref}\n length={length}\n className={cn(\"gryt-otp-field flex gap-2\", className)}\n {...props}\n >\n {/* No index prop: Base UI assigns each input its slot by render order\n and exposes the index through state. */}\n {Array.from({ length }, (_unused, index) => (\n <BaseOtpField.Input\n key={index}\n className={cn(\n \"gryt-otp-input h-12 w-10 rounded-(--gryt-radius-md) text-center\",\n \"border border-gryt-border bg-gryt-surface-raised\",\n \"font-mono text-lg text-gryt-text tabular-nums outline-none\",\n \"transition-colors duration-(--gryt-dur-fast) motion-reduce:transition-none\",\n \"data-filled:border-gryt-accent\",\n focusRing\n )}\n />\n ))}\n </BaseOtpField.Root>\n );\n }\n);\n","import { PreviewCard as BasePreviewCard } from \"@base-ui/react/preview-card\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { popupMotion, popupSurface } from \"../utils/styles\";\n\nexport type PreviewCardPopupProps = ComponentPropsWithoutRef<\n typeof BasePreviewCard.Popup\n>;\nexport type PreviewCardPositionerProps = ComponentPropsWithoutRef<\n typeof BasePreviewCard.Positioner\n>;\n\n/**\n * What appears when you hover a username.\n *\n * Not a Tooltip and not a Popover. A tooltip labels a control and opens\n * instantly; this holds real content, so it waits before opening and stays put\n * long enough to move the pointer into it. Popover is the click-to-open\n * equivalent — reach for that when the panel has controls, since content that\n * only appears on hover is unreachable from a keyboard or a touchscreen.\n */\nconst Positioner = forwardRef<HTMLDivElement, PreviewCardPositionerProps>(\n function PreviewCardPositioner({ className, sideOffset = 8, ...props }, ref) {\n return (\n <BasePreviewCard.Positioner\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\"gryt-preview-card-positioner outline-none\", className)}\n {...props}\n />\n );\n }\n);\n\nconst Popup = forwardRef<HTMLDivElement, PreviewCardPopupProps>(\n function PreviewCardPopup({ className, ...props }, ref) {\n return (\n <BasePreviewCard.Popup\n ref={ref}\n className={cn(\n \"gryt-preview-card w-64 max-w-[calc(100vw-2rem)] p-4 outline-none\",\n popupSurface,\n popupMotion,\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport const PreviewCard = {\n Root: BasePreviewCard.Root,\n Trigger: BasePreviewCard.Trigger,\n Portal: BasePreviewCard.Portal,\n Positioner,\n Popup,\n Arrow: BasePreviewCard.Arrow\n};\n","import { Toolbar as BaseToolbar } from \"@base-ui/react/toolbar\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type ToolbarRootProps = ComponentPropsWithoutRef<\n typeof BaseToolbar.Root\n>;\n\n/**\n * A strip of controls that share one tab stop.\n *\n * The point is the keyboard model: Tab enters the toolbar once and the arrow\n * keys move between its buttons, so a call bar with eight controls costs one\n * stop on the way to the message box instead of eight.\n */\nconst Root = forwardRef<HTMLDivElement, ToolbarRootProps>(function Toolbar(\n { className, ...props },\n ref\n) {\n return (\n <BaseToolbar.Root\n ref={ref}\n className={cn(\n \"gryt-toolbar flex items-center gap-1\",\n \"rounded-(--gryt-radius-full) border border-gryt-border bg-gryt-surface p-1\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Separator = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseToolbar.Separator>\n>(function ToolbarSeparator({ className, ...props }, ref) {\n return (\n <BaseToolbar.Separator\n ref={ref}\n className={cn(\"gryt-toolbar-separator mx-1 h-6 w-px bg-gryt-border\", className)}\n {...props}\n />\n );\n});\n\nexport const Toolbar = {\n Root,\n Group: BaseToolbar.Group,\n Button: BaseToolbar.Button,\n Link: BaseToolbar.Link,\n Input: BaseToolbar.Input,\n Separator\n};\n"],"names":["PortalContainerContext","createContext","usePortalContainer","useContext","isCssVariables","value","key","GrytProvider","children","className","theme","tooltipDelay","containOverlays","containerRef","useRef","style","createGrytTheme","jsx","Tooltip","cn","inputs","twMerge","clsx","toneStyles","sizeStyles","Button","forwardRef","endIcon","size","startIcon","tone","props","ref","jsxs","BaseButton","focusRing","focusRingWithin","fieldControl","fieldSizes","popupSurface","popupMotion","disabledState","toneCheckedFill","toneBg","toneCheckedBorder","toneCheckedBg","IconButton","Surface","elevated","MessageBubble","from","TextField","error","fieldClassName","helperText","label","minRows","multiline","control","Field","Composer","disabled","maxRows","onSubmit","placeholder","submitLabel","innerRef","resize","useCallback","node","styles","lineHeight","vertical","useLayoutEffect","handleSubmit","event","PaperPlaneTilt","OWL_SIZE","Avatar","alt","fallback","seed","src","owl","useMemo","owlAvatarDataUri","BaseAvatar","ConversationItem","active","avatar","subtitle","title","Badge","badgeContent","max","showZero","numeric","hidden","display","Chip","icon","onDelete","X","Checkbox","BaseCheckbox","Check","Radio","BaseRadio","RadioGroup","BaseRadioGroup","Switch","BaseSwitch","DRAG_SLOP","Slider","ariaLabel","dragging","setDragging","useState","origin","useEffect","end","handlePointerDown","handlePointerMove","start","travel","BaseSlider","Select","options","portalContainer","BaseSelect","CaretUpDown","option","side","sideOffset","BaseTooltip","TooltipProvider","Divider","orientation","Separator","Card","CardHeader","subheader","CardContent","CardActions","severityStyles","Alert","severity","Progress","BaseProgress","Spinner","CircleNotch","variantStyles","Skeleton","height","variant","width","sizing","motion","Backdrop","BaseDialog","Popup","Title","Description","Footer","Dialog","noop","useMediaQuery","query","subscribe","onChange","list","getSnapshot","useSyncExternalStore","swipeBySide","SideContext","viewportBySide","radiusBySide","popupBySide","Root","sheetOnMobile","isMobile","resolved","BaseDrawer","Viewport","Grabber","Drawer","Positioner","BaseMenu","Item","Menu","BaseTabs","List","Tab","Indicator","Panel","Tabs","BaseAccordion","Trigger","expandIcon","CaretDown","Accordion","BaseContextMenu","ContextMenu","BasePopover","Popover","BaseToast","Close","Action","Toast","useToastManager","BaseScrollArea","Scrollbar","ScrollArea","Toggle","BaseToggle","ToggleGroup","BaseToggleGroup","toneFill","Meter","showValue","BaseMeter","BaseAlertDialog","AlertDialog","listboxItemClass","listboxInputClass","Input","BaseCombobox","Empty","Combobox","BaseAutocomplete","Autocomplete","CheckboxGroup","BaseCheckboxGroup","BaseCollapsible","Collapsible","Form","BaseForm","FieldsetRoot","BaseFieldset","Legend","Fieldset","Menubar","BaseMenubar","BaseNavigationMenu","Link","NavigationMenu","stepButton","NumberField","scrubbable","BaseNumberField","Minus","Plus","OtpField","length","BaseOtpField","_unused","index","BasePreviewCard","PreviewCard","BaseToolbar","Toolbar"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/portalContainer.ts","../src/GrytProvider.tsx","../src/components/utils/cn.ts","../src/components/Button/Button.tsx","../src/components/utils/styles.ts","../src/components/IconButton/IconButton.tsx","../src/components/Surface/Surface.tsx","../src/components/MessageBubble/MessageBubble.tsx","../src/components/TextField/TextField.tsx","../src/components/Composer/Composer.tsx","../src/components/Avatar/Avatar.tsx","../src/components/ConversationItem/ConversationItem.tsx","../src/components/Badge/Badge.tsx","../src/components/Chip/Chip.tsx","../src/components/Checkbox/Checkbox.tsx","../src/components/Radio/Radio.tsx","../src/components/Switch/Switch.tsx","../src/components/Slider/Slider.tsx","../src/components/Select/Select.tsx","../src/components/Tooltip/Tooltip.tsx","../src/components/Divider/Divider.tsx","../src/components/Card/Card.tsx","../src/components/Alert/Alert.tsx","../src/components/Progress/Progress.tsx","../src/components/Skeleton/Skeleton.tsx","../src/components/Dialog/Dialog.tsx","../src/components/utils/useMediaQuery.ts","../src/components/Drawer/Drawer.tsx","../src/components/Menu/Menu.tsx","../src/components/Tabs/Tabs.tsx","../src/components/Accordion/Accordion.tsx","../src/components/ContextMenu/ContextMenu.tsx","../src/components/Popover/Popover.tsx","../src/components/Toast/Toast.tsx","../src/components/ScrollArea/ScrollArea.tsx","../src/components/Toggle/Toggle.tsx","../src/components/ThemeEditor/draft.ts","../src/components/ThemeEditor/ColorField.tsx","../src/components/ThemeEditor/ContrastReport.tsx","../src/components/ThemeEditor/ScaleStrip.tsx","../src/components/ThemeEditor/contrast.ts","../src/components/ThemeEditor/generate.ts","../src/components/ThemeEditor/share.ts","../src/components/ThemeEditor/ThemeEditor.tsx","../src/components/Meter/Meter.tsx","../src/components/AlertDialog/AlertDialog.tsx","../src/components/Combobox/Combobox.tsx","../src/components/Autocomplete/Autocomplete.tsx","../src/components/Checkbox/CheckboxGroup.tsx","../src/components/Collapsible/Collapsible.tsx","../src/components/Form/Form.tsx","../src/components/NavigationMenu/NavigationMenu.tsx","../src/components/NumberField/NumberField.tsx","../src/components/OtpField/OtpField.tsx","../src/components/PreviewCard/PreviewCard.tsx","../src/components/Toolbar/Toolbar.tsx"],"sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { RefObject } from \"react\";\n\n/**\n * Where overlays below this point should render.\n *\n * Base UI portals a popup to `document.body`, which is outside whatever element\n * GrytProvider put the theme variables on. For an app with one theme that is\n * exactly right — the overlay wants the app's theme and it gets it from\n * `:root`. It is wrong only when a second theme is being rendered inside a\n * page: the docs site previews a theme in a panel, and a Select or Tooltip\n * opened inside that panel comes up in the site's own colours (GRYT-242).\n *\n * Deliberately a context rather than a prop on each component. Select carries a\n * long comment about why its popup portals to the body — a popup left inside a\n * positioned dialog lands hundreds of pixels off — and a per-call `container`\n * prop is exactly the thing somebody reaches for to fix a layout problem, which\n * is how that bug got made the first time. A container that is set once, for a\n * subtree, by whoever established the theme, cannot be used that way by\n * accident.\n *\n * Base UI has no equivalent to reuse. Its own `PortalContext` is a boolean —\n * \"am I inside a portal\" — not a carrier for the container.\n */\nexport const PortalContainerContext = createContext<\n RefObject<HTMLElement | null> | undefined\n>(undefined);\n\n/**\n * The container overlays should portal into, or `undefined` for Base UI's\n * default of `document.body`.\n */\nexport function usePortalContainer(): RefObject<HTMLElement | null> | undefined {\n return useContext(PortalContainerContext);\n}\n","import { Tooltip } from \"@base-ui/react/tooltip\";\nimport { useRef } from \"react\";\nimport type { CSSProperties, ReactNode } from \"react\";\nimport { createGrytTheme } from \"@gryt/theme\";\nimport type { GrytThemeOptions } from \"@gryt/theme\";\nimport { PortalContainerContext } from \"./portalContainer\";\n\nexport interface GrytProviderProps {\n children: ReactNode;\n // Either the object from createGrytTheme, or the options to build one from.\n theme?: CSSProperties | GrytThemeOptions;\n className?: string;\n // Shared hover delay for every Tooltip below this provider, in milliseconds.\n tooltipDelay?: number;\n /**\n * Render overlays inside this provider's element rather than in `document.body`.\n *\n * Off by default, and should stay off for an app with one theme: the body is\n * the right place for a popup, and `:root` already carries the variables it\n * needs. Turn it on when this provider is one theme inside a page that has\n * another — previewing a theme in a panel — where an overlay in the body\n * would come up in the surrounding page's colours instead (GRYT-242).\n */\n containOverlays?: boolean;\n}\n\nfunction isCssVariables(value: object): value is CSSProperties {\n return Object.keys(value).some((key) => key.startsWith(\"--\"));\n}\n\n// There is no ThemeProvider and no CssBaseline any more. What a provider still\n// has to do is put the theme variables somewhere the components can read them,\n// and mount Base UI's tooltip provider so hover timing is shared between\n// triggers rather than restarting at every one.\nexport function GrytProvider({\n children,\n className,\n theme,\n tooltipDelay = 400,\n containOverlays = false\n}: GrytProviderProps) {\n // A ref rather than state: Base UI's `container` accepts one, so the element\n // does not have to exist on the first render and nothing has to re-render\n // when it does.\n const containerRef = useRef<HTMLDivElement | null>(null);\n /**\n * No theme, no variables.\n *\n * This used to paint the full default palette onto the wrapper whenever the\n * prop was absent, which looked harmless and was not: the stylesheet already\n * declares those values on :root, so the copy added nothing, and it sat below\n * the root in the cascade — an app that themed itself the documented way, by\n * putting variables on the root element where overlays can reach them, found\n * every one of them overridden by a provider re-stating the defaults.\n *\n * It cost this site an afternoon. The header can put the docs in Nord now,\n * and the reason it could not before was one div.\n */\n const style =\n theme === undefined\n ? undefined\n : isCssVariables(theme)\n ? theme\n : createGrytTheme(theme);\n\n return (\n <div className={className} style={style} ref={containerRef}>\n <PortalContainerContext.Provider\n value={containOverlays ? containerRef : undefined}\n >\n <Tooltip.Provider delay={tooltipDelay}>{children}</Tooltip.Provider>\n </PortalContainerContext.Provider>\n </div>\n );\n}\n","import { clsx } from \"clsx\";\nimport type { ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}","import { Button as BaseButton } from \"@base-ui/react/button\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\ntype ButtonTone = \"primary\" | \"secondary\" | \"neutral\" | \"danger\" | \"ghost\";\ntype ButtonSize = \"xsmall\" | \"small\" | \"medium\" | \"large\";\n\n// Base UI marks a disabled button with data-disabled rather than the native\n// attribute, because it stays focusable when disabled. Hover and press styles\n// hang off not-data-disabled so they don't fire on a dead button.\n//\n// **Disabled drops the fill rather than fading it.** Every tone used to share\n// one `opacity-50`, and on the low-contrast tones that reads — they are already\n// quiet, so halving them puts them under the surrounding text. On a filled tone\n// it does not: the accent at half opacity over a dark page is still a saturated\n// purple button, and there is nothing in it that says it will not respond. On\n// the phone that cost somebody two taps on a Save button to believe it was\n// inert, and the somebody had written the disabled condition half an hour\n// earlier. GRYT-511.\n//\n// So a disabled filled button becomes the surface it sits on, with a muted\n// label — it keeps its size and its word and stops claiming to be the action.\n// Ghost has no fill to lose and its label is already muted, so the opacity\n// below is what carries it.\nconst toneStyles: Record<ButtonTone, string> = {\n primary:\n \"bg-gryt-accent text-gryt-on-accent hover:not-data-disabled:bg-gryt-accent-light data-disabled:bg-gryt-surface-raised data-disabled:text-gryt-muted\",\n secondary:\n \"bg-gryt-secondary text-gryt-on-secondary hover:not-data-disabled:bg-gryt-secondary-light data-disabled:bg-gryt-surface-raised data-disabled:text-gryt-muted\",\n neutral:\n \"bg-gryt-surface-raised text-gryt-text hover:not-data-disabled:bg-gryt-surface-hover data-disabled:text-gryt-muted\",\n danger:\n \"bg-gryt-danger text-gryt-on-danger hover:not-data-disabled:bg-gryt-danger-light data-disabled:bg-gryt-surface-raised data-disabled:text-gryt-muted\",\n ghost:\n \"bg-transparent text-gryt-muted hover:not-data-disabled:bg-white/8 hover:not-data-disabled:text-gryt-text\"\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n xsmall: \"min-h-8 px-3 text-xs\",\n small: \"min-h-9 px-4 text-sm\",\n medium: \"min-h-10 px-5 text-sm\",\n large: \"min-h-12 px-6 text-base\"\n};\n\nexport interface ButtonProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseButton>, \"className\"> {\n tone?: ButtonTone;\n size?: ButtonSize;\n className?: string;\n // Carried over from the MUI-based Button. Base UI has no equivalent, but\n // dropping them would break every existing call site for no gain — the flex\n // gap below already spaces them correctly.\n startIcon?: ReactNode;\n endIcon?: ReactNode;\n}\n\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n function Button(\n {\n children,\n className,\n endIcon,\n size = \"medium\",\n startIcon,\n tone = \"primary\",\n ...props\n },\n ref\n ) {\n return (\n <BaseButton\n ref={ref}\n className={cn(\n \"gryt-button\",\n \"inline-flex cursor-pointer items-center justify-center gap-2 border-0 shadow-none\",\n \"rounded-(--gryt-radius-full) font-semibold whitespace-nowrap select-none\",\n // scale, not transform: Tailwind v4's scale-* utilities set the\n // standalone `scale` property, so transitioning `transform` alone\n // leaves the hover grow snapping instantly.\n \"transition-[scale,background-color,color]\",\n \"duration-(--gryt-dur-spring) ease-spring\",\n\n // Press travels further than hover, so the button reads as being\n // pushed down rather than just acknowledging the cursor.\n // A button that opens something does not grow under the cursor.\n // Base UI positions the popup against the trigger's measured box, and\n // it keeps measuring while the popup is open — so a trigger that\n // scales on hover drags its own menu a pixel or two sideways every\n // time the pointer crosses it. aria-haspopup is how the trigger says\n // that is what it is; Base UI puts it there, nothing to pass.\n \"motion-safe:not-[[aria-haspopup]]:hover:not-data-disabled:scale-[1.03]\",\n \"motion-safe:not-[[aria-haspopup]]:active:not-data-disabled:scale-[0.96]\",\n\n \"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gryt-accent-light\",\n // Lighter than it was, because the fill swap above is doing the work\n // now. It is kept because `startIcon` and `endIcon` are the caller's\n // elements with the caller's colours — nothing here can mute those,\n // and an icon at full strength on a dead button is the same lie in\n // miniature.\n \"data-disabled:cursor-not-allowed data-disabled:opacity-60\",\n sizeStyles[size],\n toneStyles[tone],\n className\n )}\n {...props}\n >\n {startIcon}\n {children}\n {endIcon}\n </BaseButton>\n );\n }\n);\n","// Shared class fragments. These exist so that \"flat, Gryt palette\" is decided\n// once rather than 24 times, and so a change to the focus ring or the popup\n// surface lands everywhere at once.\n\nexport const focusRing =\n \"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gryt-accent-light\";\n\n// The same ring, for a control whose focusable element is a child rather than\n// itself. Base UI's Slider is the case: the thumb you can see is a div, and\n// the thing that takes focus is a visually hidden input inside it, so\n// focus-visible on the thumb never matches and the ring never appears.\nexport const focusRingWithin =\n \"has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-gryt-accent-light\";\n\n/**\n * What a text input looks like: TextField, and the typeahead inputs on\n * Combobox and Autocomplete.\n *\n * Shared because they had already drifted. The listbox inputs asked for\n * `rounded-(--gryt-radius-input)`, a token that does not exist — the library\n * ships sm, md, lg, xl and full — so the declaration was invalid and both\n * rendered with square corners in a library where every other control is\n * rounded. That is the kind of thing a shared constant makes impossible rather\n * than merely unlikely.\n *\n * The border *colour* is left to the caller: TextField swaps it for danger when\n * the field is invalid, and baking one in here would mean fighting it back off.\n */\nexport const fieldControl = [\n \"w-full rounded-(--gryt-radius-xl) border bg-gryt-surface-raised\",\n \"text-gryt-text outline-none placeholder:text-gryt-muted\",\n \"transition-colors duration-150 motion-reduce:transition-none\",\n \"hover:border-gryt-accent-light focus:border-gryt-accent\",\n \"disabled:cursor-not-allowed disabled:opacity-60\"\n].join(\" \");\n\n/** Matching heights and padding for the two sizes a field comes in. */\nexport const fieldSizes = {\n small: \"min-h-9 px-3 py-1.5 text-sm\",\n medium: \"min-h-11 px-4 py-2.5 text-sm\"\n} as const;\n\nexport type FieldSize = keyof typeof fieldSizes;\n\n// Every floating surface: menu, select list, tooltip, dialog, drawer. Flat —\n// a border rather than a shadow.\nexport const popupSurface =\n \"rounded-(--gryt-radius-xl) border border-gryt-border bg-gryt-surface text-gryt-text\";\n\n// Base UI sets data-starting-style and data-ending-style for one frame either\n// side of open and close. The element carries the transition itself.\nexport const popupMotion = [\n // scale and translate are named explicitly because Tailwind v4 sets them as\n // standalone CSS properties rather than folding them into `transform`, so\n // transitioning `transform` would leave the popup snapping into place.\n \"transition-[opacity,scale,translate] duration-(--gryt-dur-spring) ease-spring motion-reduce:transition-none\",\n \"data-starting-style:scale-[0.98] data-starting-style:opacity-0\",\n \"data-ending-style:scale-[0.98] data-ending-style:opacity-0\"\n].join(\" \");\n\nexport const disabledState =\n \"cursor-pointer data-disabled:cursor-not-allowed data-disabled:opacity-50\";\n\n// The tones shared by Checkbox, Radio, Switch and Slider. One union so a\n// component cannot invent its own sixth colour. Button and IconButton keep\n// their own lists, because \"ghost\" only makes sense on a button.\nexport type Tone =\n | \"primary\"\n | \"secondary\"\n | \"neutral\"\n | \"danger\"\n | \"success\"\n | \"warning\";\n\n// Step 11, the text step, not the flat name. The flat name is step 9 — the\n// solid fill, the same colour in both appearances — which reads on a dark page\n// and disappears on a white one.\nexport const toneAccent: Record<Tone, string> = {\n primary: \"text-gryt-accent-11\",\n secondary: \"text-gryt-secondary-11\",\n neutral: \"text-gryt-muted\",\n danger: \"text-gryt-danger-11\",\n success: \"text-gryt-success-11\",\n warning: \"text-gryt-warning-11\"\n};\n\n// Filled backgrounds, for the checked state of a control.\nexport const toneFill: Record<Tone, string> = {\n primary: \"bg-gryt-accent text-gryt-on-accent\",\n secondary: \"bg-gryt-secondary text-gryt-on-secondary\",\n neutral: \"bg-gryt-surface-hover text-gryt-text\",\n danger: \"bg-gryt-danger text-gryt-on-danger\",\n success: \"bg-gryt-success text-gryt-on-accent\",\n warning: \"bg-gryt-warning text-gryt-on-accent\"\n};\n\nexport const toneBorder: Record<Tone, string> = {\n primary: \"border-gryt-accent\",\n secondary: \"border-gryt-secondary\",\n neutral: \"border-gryt-border\",\n danger: \"border-gryt-danger\",\n success: \"border-gryt-success\",\n warning: \"border-gryt-warning\"\n};\n\n// Written out in full rather than composed from toneFill at runtime. Tailwind\n// scans source text for class names, so a class built by interpolation exists\n// on the element and nowhere in the stylesheet.\nexport const toneCheckedFill: Record<Tone, string> = {\n primary: \"data-checked:bg-gryt-accent data-checked:text-gryt-on-accent\",\n secondary:\n \"data-checked:bg-gryt-secondary data-checked:text-gryt-on-secondary\",\n neutral: \"data-checked:bg-gryt-surface-hover data-checked:text-gryt-text\",\n danger: \"data-checked:bg-gryt-danger data-checked:text-gryt-on-danger\",\n success: \"data-checked:bg-gryt-success data-checked:text-gryt-on-accent\",\n warning: \"data-checked:bg-gryt-warning data-checked:text-gryt-on-accent\"\n};\n\n// Track fill for Switch, and bar fill for Slider.\nexport const toneBg: Record<Tone, string> = {\n primary: \"bg-gryt-accent\",\n secondary: \"bg-gryt-secondary\",\n neutral: \"bg-gryt-surface-hover\",\n danger: \"bg-gryt-danger\",\n success: \"bg-gryt-success\",\n warning: \"bg-gryt-warning\"\n};\n\nexport const toneCheckedBorder: Record<Tone, string> = {\n primary: \"data-checked:border-gryt-accent\",\n secondary: \"data-checked:border-gryt-secondary\",\n neutral: \"data-checked:border-gryt-muted\",\n danger: \"data-checked:border-gryt-danger\",\n success: \"data-checked:border-gryt-success\",\n warning: \"data-checked:border-gryt-warning\"\n};\n\nexport const toneCheckedBg: Record<Tone, string> = {\n primary: \"data-checked:bg-gryt-accent\",\n secondary: \"data-checked:bg-gryt-secondary\",\n neutral: \"data-checked:bg-gryt-surface-hover\",\n danger: \"data-checked:bg-gryt-danger\",\n success: \"data-checked:bg-gryt-success\",\n warning: \"data-checked:bg-gryt-warning\"\n};\n","import { Button as BaseButton } from \"@base-ui/react/button\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { disabledState, focusRing } from \"../utils/styles\";\n\ntype IconButtonTone = \"primary\" | \"secondary\" | \"neutral\" | \"danger\" | \"ghost\";\ntype IconButtonSize = \"xsmall\" | \"small\" | \"medium\" | \"large\";\n\n// The hover fills are the tone colour at low alpha, so an icon button reads as\n// a tinted target rather than a filled one.\nconst toneStyles: Record<IconButtonTone, string> = {\n primary: \"text-gryt-accent-11 hover:not-data-disabled:bg-gryt-accent-3\",\n secondary:\n \"text-gryt-secondary-11 hover:not-data-disabled:bg-gryt-secondary-3\",\n neutral:\n \"text-gryt-muted hover:not-data-disabled:bg-white/8 hover:not-data-disabled:text-gryt-text\",\n danger: \"text-gryt-danger-11 hover:not-data-disabled:bg-gryt-danger-3\",\n ghost:\n \"text-gryt-muted hover:not-data-disabled:bg-white/8 hover:not-data-disabled:text-gryt-text\"\n};\n\nconst sizeStyles: Record<IconButtonSize, string> = {\n xsmall: \"h-8 w-8\",\n small: \"h-9 w-9\",\n medium: \"h-10 w-10\",\n large: \"h-12 w-12\"\n};\n\nexport interface IconButtonProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseButton>, \"className\"> {\n tone?: IconButtonTone;\n size?: IconButtonSize;\n className?: string;\n}\n\nexport const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(\n function IconButton(\n { className, size = \"medium\", tone = \"neutral\", ...props },\n ref\n ) {\n return (\n <BaseButton\n ref={ref}\n className={cn(\n \"gryt-icon-button\",\n \"inline-flex shrink-0 items-center justify-center border-0 bg-transparent p-0\",\n \"rounded-(--gryt-radius-full) select-none\",\n // scale rather than transform — see the note in Button.\n \"transition-[scale,background-color,color] duration-(--gryt-dur-spring) ease-spring\",\n // A button that opens something does not grow under the cursor.\n // Base UI positions the popup against the trigger's measured box, and\n // it keeps measuring while the popup is open — so a trigger that\n // scales on hover drags its own menu a pixel or two sideways every\n // time the pointer crosses it. aria-haspopup is how the trigger says\n // that is what it is; Base UI puts it there, nothing to pass.\n \"motion-safe:not-[[aria-haspopup]]:hover:not-data-disabled:scale-[1.06]\",\n \"motion-safe:not-[[aria-haspopup]]:active:not-data-disabled:scale-[0.94]\",\n focusRing,\n disabledState,\n sizeStyles[size],\n toneStyles[tone],\n className\n )}\n {...props}\n />\n );\n }\n);\n","import { forwardRef } from \"react\";\nimport type { HTMLAttributes } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport interface SurfaceProps extends HTMLAttributes<HTMLDivElement> {\n elevated?: boolean;\n}\n\nexport const Surface = forwardRef<HTMLDivElement, SurfaceProps>(\n function Surface({ className, elevated = false, ...props }, ref) {\n return (\n <div\n ref={ref}\n className={cn(\n \"gryt-surface rounded-(--gryt-radius-lg) border border-gryt-border p-4 text-gryt-text\",\n elevated ? \"bg-gryt-surface-raised\" : \"bg-gryt-surface\",\n className\n )}\n {...props}\n />\n );\n }\n);\n","import { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport interface MessageBubbleProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n from?: \"user\" | \"assistant\" | \"system\";\n}\n\nexport const MessageBubble = forwardRef<HTMLDivElement, MessageBubbleProps>(\n function MessageBubble(\n { children, className, from = \"assistant\", ...props },\n ref\n ) {\n return (\n <div\n ref={ref}\n className={cn(\n \"gryt-message-bubble\",\n from === \"user\" && \"ml-auto bg-gryt-accent text-gryt-on-accent\",\n from === \"assistant\" &&\n \"mr-auto border border-gryt-border bg-gryt-surface text-gryt-text\",\n from === \"system\" &&\n \"mx-auto border border-dashed border-gryt-border bg-transparent text-gryt-muted\",\n className\n )}\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n","import { Field } from \"@base-ui/react/field\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { fieldControl, fieldSizes } from \"../utils/styles\";\n\n// The two sizes live in utils/styles, shared with the Combobox and\n// Autocomplete inputs so all three keep the same shape.\nexport type TextFieldSize = \"small\" | \"medium\";\n\nexport interface TextFieldProps\n extends Omit<\n ComponentPropsWithoutRef<typeof Field.Control>,\n \"className\" | \"size\"\n > {\n label?: ReactNode;\n helperText?: ReactNode;\n error?: boolean;\n size?: TextFieldSize;\n multiline?: boolean;\n minRows?: number;\n className?: string;\n fieldClassName?: string;\n}\n\nexport const TextField = forwardRef<HTMLInputElement, TextFieldProps>(\n function TextField(\n {\n className,\n error = false,\n fieldClassName,\n helperText,\n label,\n minRows = 3,\n multiline = false,\n size = \"medium\",\n ...props\n },\n ref\n ) {\n const control = (\n <Field.Control\n ref={ref}\n // Field.Control renders an input by default; render swaps the element\n // while keeping the field wiring, which is how label association and\n // aria-describedby survive the switch to a textarea.\n render={multiline ? <textarea rows={minRows} /> : undefined}\n className={cn(\n \"gryt-text-field-control\",\n fieldControl,\n multiline && \"resize-y leading-6\",\n error ? \"border-gryt-danger\" : \"border-gryt-border\",\n fieldSizes[size],\n className\n )}\n {...props}\n />\n );\n\n return (\n <Field.Root\n className={cn(\n \"gryt-text-field flex w-full flex-col gap-1.5\",\n fieldClassName\n )}\n >\n {label ? (\n <Field.Label className=\"text-xs font-medium text-gryt-muted\">\n {label}\n </Field.Label>\n ) : null}\n {control}\n {helperText ? (\n <Field.Description\n className={cn(\n \"text-xs\",\n error ? \"text-gryt-danger-11\" : \"text-gryt-muted\"\n )}\n >\n {helperText}\n </Field.Description>\n ) : null}\n </Field.Root>\n );\n }\n);\n","import { PaperPlaneTilt } from \"@phosphor-icons/react\";\nimport { useCallback, useLayoutEffect, useRef } from \"react\";\nimport type {\n FormEvent,\n FormEventHandler,\n TextareaHTMLAttributes\n} from \"react\";\nimport { forwardRef } from \"react\";\nimport { Button } from \"../Button/Button\";\nimport { cn } from \"../utils/cn\";\n\nexport interface ComposerProps\n extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, \"onSubmit\"> {\n onSubmit?: FormEventHandler<HTMLFormElement>;\n submitLabel?: string;\n disabled?: boolean;\n minRows?: number;\n maxRows?: number;\n}\n\nexport const Composer = forwardRef<HTMLTextAreaElement, ComposerProps>(\n function Composer(\n {\n className,\n disabled = false,\n maxRows = 8,\n minRows = 1,\n onSubmit,\n placeholder = \"Message Gryt\",\n submitLabel = \"Send\",\n ...props\n },\n ref\n ) {\n const innerRef = useRef<HTMLTextAreaElement | null>(null);\n\n // Replaces MUI's TextareaAutosize. Reset to auto first, otherwise\n // scrollHeight only ever reports the current height and the box can grow\n // but never shrink.\n const resize = useCallback(() => {\n const node = innerRef.current;\n if (!node) {\n return;\n }\n\n const styles = window.getComputedStyle(node);\n const lineHeight = parseFloat(styles.lineHeight) || 24;\n const vertical =\n parseFloat(styles.paddingTop) + parseFloat(styles.paddingBottom);\n\n node.style.height = \"auto\";\n node.style.height = `${Math.min(\n Math.max(node.scrollHeight, lineHeight * minRows + vertical),\n lineHeight * maxRows + vertical\n )}px`;\n }, [maxRows, minRows]);\n\n useLayoutEffect(resize, [resize, props.value]);\n\n function handleSubmit(event: FormEvent<HTMLFormElement>) {\n if (!onSubmit) {\n event.preventDefault();\n return;\n }\n\n onSubmit(event);\n }\n\n return (\n <form className={cn(\"gryt-composer\", className)} onSubmit={handleSubmit}>\n <textarea\n ref={(node) => {\n innerRef.current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n }}\n rows={minRows}\n disabled={disabled}\n placeholder={placeholder}\n onInput={resize}\n className=\"gryt-composer-textarea disabled:cursor-not-allowed disabled:opacity-60\"\n {...props}\n />\n <Button\n type=\"submit\"\n disabled={disabled}\n size=\"small\"\n endIcon={<PaperPlaneTilt size={14} weight=\"fill\" />}\n >\n {submitLabel}\n </Button>\n </form>\n );\n }\n);\n","import { Avatar as BaseAvatar } from \"@base-ui/react/avatar\";\nimport { eggAvatarDataUri, owlAvatarDataUri } from \"@gryt/owl\";\nimport { forwardRef, useMemo } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type AvatarSize = \"small\" | \"medium\" | \"large\";\n\nconst sizeStyles: Record<AvatarSize, string> = {\n small: \"h-8 w-8 text-xs\",\n medium: \"h-10 w-10 text-sm\",\n large: \"h-12 w-12 text-base\"\n};\n\n// The intrinsic size of the generated SVG, which CSS then overrides. One number\n// for every avatar size on purpose: it is vector, so nothing is gained by\n// matching the box, and a single value means one memo entry per person rather\n// than one per person per size.\nconst OWL_SIZE = 256;\n\nexport interface AvatarProps extends Omit<\n ComponentPropsWithoutRef<typeof BaseAvatar.Root>,\n \"className\"\n> {\n src?: string;\n alt?: string;\n size?: AvatarSize;\n className?: string;\n /**\n * Draws this person's owl, from @gryt/owl.\n *\n * Used when there is no `src`, and also when `src` is given and fails to\n * load — somebody whose uploaded avatar 404s should get their own owl back\n * rather than a letter.\n *\n * Pass `avatarSeed(nickname)` rather than the nickname itself. The two\n * differ for anyone whose name is not already lower case, and an avatar\n * drawn from one seed beside a voice tile tinted from the other is the bug\n * that rule exists to prevent.\n */\n seed?: string;\n /**\n * Draws this seed's eggs, from @gryt/owl.\n *\n * Named for the drawing rather than for what it stands for, because what it\n * stands for has already changed once. These were written for server icons,\n * and are now the generated image for a group chat that has not uploaded\n * one; server icons are getting their own generator. A prop called\n * `serverSeed` would have been wrong twice over — wrong for group chats, and\n * squatting on the name the real server one will want.\n *\n * Separate from `seed` rather than a flag on it. `seed` draws a person's\n * owl, and passing the wrong prop should give you the wrong kind of thing\n * rather than the same thing in another colour.\n *\n * The corner is the caller's. This clips to whatever radius its className\n * sets and the drawing is square, so asking for `rounded-(--gryt-radius-md)`\n * gets the theme's radius in pixels rather than a fraction of the box baked\n * into the SVG.\n */\n eggSeed?: string;\n // Shown while the image loads and if it fails. Falls back to children, which\n // is how the old MUI-based Avatar was called: <Avatar>G</Avatar>.\n fallback?: ReactNode;\n}\n\nexport const Avatar = forwardRef<HTMLSpanElement, AvatarProps>(function Avatar(\n {\n alt,\n children,\n className,\n fallback,\n seed,\n eggSeed,\n size = \"medium\",\n src,\n ...props\n },\n ref\n) {\n // Memoised because avatars render in member lists that repaint often, and\n // the seed never changes under a row.\n const owl = useMemo(\n () => (seed ? owlAvatarDataUri(seed, { size: OWL_SIZE }) : undefined),\n [seed]\n );\n\n // No cornerRadius: the root clips, so the corner is whatever the theme's\n // radius is in pixels rather than a fraction of the drawing.\n const egg = useMemo(\n () =>\n eggSeed ? eggAvatarDataUri(eggSeed, { size: OWL_SIZE }) : undefined,\n [eggSeed]\n );\n\n // A person wins, on the grounds that passing both is a caller bug and\n // drawing the more specific thing makes it the more obvious one.\n const generated = owl ?? egg;\n\n return (\n <BaseAvatar.Root\n ref={ref}\n className={cn(\n \"gryt-avatar inline-flex shrink-0 items-center justify-center overflow-hidden align-middle select-none\",\n \"rounded-(--gryt-radius-full) bg-gryt-surface-raised font-medium text-gryt-text ring-1 ring-gryt-border\",\n sizeStyles[size],\n className\n )}\n {...props}\n >\n {src ? (\n <BaseAvatar.Image\n src={src}\n alt={alt}\n className=\"h-full w-full object-cover\"\n />\n ) : null}\n {/* The owl goes here rather than through BaseAvatar.Image, and that is\n the whole of what \"no src\" means: the fallback is the only thing\n rendered, so it shows immediately. Base UI's Image renders nothing\n until the browser reports the image loaded, which is right for a URL\n over the network and pointless for a data URI that is already in\n memory — it would blank the avatar for a frame every time.\n\n It also gets the broken-upload case for free: an avatar URL that 404s\n leaves Base UI on the fallback, which is this person's owl. */}\n <BaseAvatar.Fallback className=\"flex h-full w-full items-center justify-center\">\n {generated ? (\n <img\n src={generated}\n alt={alt}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n (fallback ?? children)\n )}\n </BaseAvatar.Fallback>\n </BaseAvatar.Root>\n );\n});\n","import { Avatar } from \"../Avatar/Avatar\";\nimport type { ButtonHTMLAttributes, ReactNode } from \"react\";\nimport { forwardRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport interface ConversationItemProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n title: string;\n subtitle?: string;\n active?: boolean;\n avatar?: ReactNode;\n}\n\nexport const ConversationItem = forwardRef<\n HTMLButtonElement,\n ConversationItemProps\n>(function ConversationItem(\n { active = false, avatar, className, subtitle, title, ...props },\n ref\n) {\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cn(\n \"gryt-conversation-item enabled:cursor-pointer disabled:cursor-not-allowed disabled:opacity-50\",\n active\n ? \"bg-gryt-accent text-gryt-on-accent\"\n : \"text-gryt-text hover:bg-white/5\",\n className\n )}\n {...props}\n >\n {avatar ?? (\n <Avatar\n size=\"small\"\n className={cn(\n active\n // Step 9 by number rather than by its flat name: this is the\n // filled-button pair inverted — the accent as ink on the ink\n // colour it normally carries — and naming the step says so.\n ? \"bg-gryt-on-accent text-gryt-accent-9 ring-transparent\"\n : \"bg-gryt-surface-raised text-gryt-text\"\n )}\n >\n {title.slice(0, 1).toUpperCase()}\n </Avatar>\n )}\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-sm font-semibold\">{title}</span>\n {subtitle ? (\n <span\n className={cn(\n \"block truncate text-xs\",\n active ? \"text-gryt-on-accent/85\" : \"text-gryt-muted\"\n )}\n >\n {subtitle}\n </span>\n ) : null}\n </span>\n </button>\n );\n});\n","import { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {\n // Anchored to the top-right of children. A count, a dot, or anything else.\n badgeContent?: ReactNode;\n // Hide when the count is zero, matching how a notification badge is normally\n // wanted. Set false to keep a literal 0 on screen.\n showZero?: boolean;\n max?: number;\n}\n\nexport const Badge = forwardRef<HTMLSpanElement, BadgeProps>(function Badge(\n { badgeContent, children, className, max = 99, showZero = false, ...props },\n ref\n) {\n const numeric = typeof badgeContent === \"number\" ? badgeContent : null;\n const hidden = numeric !== null && numeric === 0 && !showZero;\n const display =\n numeric !== null && numeric > max ? `${max}+` : badgeContent;\n\n return (\n <span\n ref={ref}\n className={cn(\"gryt-badge relative inline-flex\", className)}\n {...props}\n >\n {children}\n {badgeContent !== undefined && !hidden ? (\n <span\n className={cn(\n \"gryt-badge-dot absolute -top-1 -right-1 z-10 inline-flex items-center justify-center\",\n \"min-w-5 rounded-(--gryt-radius-full) px-1.5 py-0.5\",\n \"bg-gryt-accent text-[0.65rem] leading-none font-semibold text-gryt-on-accent\",\n \"ring-2 ring-gryt-bg\"\n )}\n >\n {display}\n </span>\n ) : null}\n </span>\n );\n});\n","import { X } from \"@phosphor-icons/react\";\nimport { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing } from \"../utils/styles\";\n\nexport type ChipTone =\n | \"neutral\"\n | \"primary\"\n | \"secondary\"\n | \"success\"\n | \"warning\"\n | \"danger\";\n\n/**\n * Three steps of one scale, rather than three alphas of the fill.\n *\n * The flat name is step 9, the solid step, and it is the same colour in both\n * appearances on purpose. That makes it right for a filled button and wrong for\n * text: on a white panel a success chip came out bright green on pale green.\n * Step 3 is the component background, 6 the hairline and 11 the text, each\n * defined per appearance and each measured.\n */\nconst toneStyles: Record<ChipTone, string> = {\n neutral: \"border-gryt-border bg-gryt-surface-raised text-gryt-text\",\n primary: \"border-gryt-accent-6 bg-gryt-accent-3 text-gryt-accent-11\",\n secondary:\n \"border-gryt-secondary-6 bg-gryt-secondary-3 text-gryt-secondary-11\",\n success: \"border-gryt-success-6 bg-gryt-success-3 text-gryt-success-11\",\n warning: \"border-gryt-warning-6 bg-gryt-warning-3 text-gryt-warning-11\",\n danger: \"border-gryt-danger-6 bg-gryt-danger-3 text-gryt-danger-11\"\n};\n\nexport interface ChipProps\n extends Omit<HTMLAttributes<HTMLSpanElement>, \"onDelete\"> {\n label?: ReactNode;\n tone?: ChipTone;\n icon?: ReactNode;\n onDelete?: () => void;\n}\n\nexport const Chip = forwardRef<HTMLSpanElement, ChipProps>(function Chip(\n { children, className, icon, label, onDelete, tone = \"neutral\", ...props },\n ref\n) {\n return (\n <span\n ref={ref}\n className={cn(\n \"gryt-chip inline-flex items-center gap-1.5 rounded-(--gryt-radius-full) border px-3 py-1 text-xs font-medium\",\n toneStyles[tone],\n className\n )}\n {...props}\n >\n {icon}\n {label ?? children}\n {onDelete ? (\n <button\n type=\"button\"\n aria-label=\"Remove\"\n onClick={onDelete}\n className={cn(\n \"-mr-1 inline-flex h-4 w-4 cursor-pointer items-center justify-center rounded-(--gryt-radius-full)\",\n \"opacity-70 transition-opacity hover:opacity-100\",\n focusRing\n )}\n >\n <X size={10} weight=\"bold\" aria-hidden=\"true\" />\n </button>\n ) : null}\n </span>\n );\n});\n","import { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { Check } from \"@phosphor-icons/react\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { disabledState, focusRing, toneCheckedFill } from \"../utils/styles\";\nimport type { Tone } from \"../utils/styles\";\n\nexport interface CheckboxProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseCheckbox.Root>,\n \"className\"\n > {\n tone?: Tone;\n className?: string;\n}\n\nexport const Checkbox = forwardRef<HTMLButtonElement, CheckboxProps>(\n function Checkbox({ className, tone = \"primary\", ...props }, ref) {\n return (\n <BaseCheckbox.Root\n ref={ref}\n className={cn(\n \"gryt-checkbox flex h-5 w-5 shrink-0 items-center justify-center\",\n \"rounded-(--gryt-radius-sm) border border-gryt-border bg-gryt-surface-raised\",\n \"transition-[scale,background-color,border-color] duration-(--gryt-dur-spring) ease-spring\",\n \"data-checked:border-transparent\",\n // Same grow-and-press as the buttons, so a control reacts to the\n // cursor before it is clicked rather than only after.\n \"hover:not-data-disabled:border-gryt-accent-light\",\n \"motion-safe:hover:not-data-disabled:scale-[1.08]\",\n \"motion-safe:active:not-data-disabled:scale-[0.92]\",\n focusRing,\n disabledState,\n // Unchecked stays a neutral outline; the tone only paints once checked.\n toneCheckedFill[tone],\n className\n )}\n {...props}\n >\n {/* keepMounted is load-bearing: without it Base UI unmounts the\n indicator whenever the box is unchecked, so data-unchecked never\n applies to anything and there is no element to transition from —\n the tick just appears. Kept in the DOM, it can scale and fade in\n both directions. */}\n <BaseCheckbox.Indicator\n keepMounted\n className={cn(\n \"flex origin-center\",\n \"transition-[scale,opacity] duration-(--gryt-dur-spring) ease-spring\",\n // Scaling from 0 rather than from something near 1 is deliberate.\n // The spring's overshoot is a percentage of the travel, so a tick\n // going 0 -> 1 overshoots to 1.12 and visibly springs, while one\n // going 0.95 -> 1 overshoots by 0.006 and does nothing at all.\n \"data-unchecked:scale-0 data-unchecked:opacity-0\",\n \"motion-reduce:transition-none\"\n )}\n >\n <Check size={12} weight=\"bold\" />\n </BaseCheckbox.Indicator>\n </BaseCheckbox.Root>\n );\n }\n);\n","import { Radio as BaseRadio } from \"@base-ui/react/radio\";\nimport { RadioGroup as BaseRadioGroup } from \"@base-ui/react/radio-group\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport {\n disabledState,\n focusRing,\n toneBg,\n toneCheckedBorder\n} from \"../utils/styles\";\nimport type { Tone } from \"../utils/styles\";\n\nexport interface RadioProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseRadio.Root>, \"className\"> {\n tone?: Tone;\n className?: string;\n}\n\nexport const Radio = forwardRef<HTMLButtonElement, RadioProps>(function Radio(\n { className, tone = \"primary\", ...props },\n ref\n) {\n return (\n <BaseRadio.Root\n ref={ref}\n className={cn(\n \"gryt-radio flex h-5 w-5 shrink-0 items-center justify-center\",\n \"rounded-(--gryt-radius-full) border border-gryt-border bg-gryt-surface-raised\",\n \"transition-[scale,background-color,border-color] duration-(--gryt-dur-spring) ease-spring\",\n \"hover:not-data-disabled:border-gryt-accent-light\",\n \"motion-safe:hover:not-data-disabled:scale-[1.08]\",\n \"motion-safe:active:not-data-disabled:scale-[0.92]\",\n focusRing,\n disabledState,\n // Border takes the tone when selected; the dot inside carries the fill.\n toneCheckedBorder[tone],\n className\n )}\n {...props}\n >\n {/* keepMounted so there is an element to transition — see Checkbox. */}\n <BaseRadio.Indicator\n keepMounted\n className={cn(\n \"h-2.5 w-2.5 origin-center rounded-(--gryt-radius-full)\",\n \"transition-[scale,opacity] duration-(--gryt-dur-spring) ease-spring\",\n // From 0, for the same reason as the Checkbox tick — see the note there.\n \"data-unchecked:scale-0 data-unchecked:opacity-0\",\n \"motion-reduce:transition-none\",\n toneBg[tone]\n )}\n />\n </BaseRadio.Root>\n );\n});\n\nexport type RadioGroupProps = ComponentPropsWithoutRef<typeof BaseRadioGroup>;\n\nexport const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(\n function RadioGroup({ className, ...props }, ref) {\n return (\n <BaseRadioGroup\n ref={ref}\n className={cn(\"gryt-radio-group flex flex-col gap-2\", className)}\n {...props}\n />\n );\n }\n);\n","import { Switch as BaseSwitch } from \"@base-ui/react/switch\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { disabledState, focusRing, toneCheckedBg } from \"../utils/styles\";\nimport type { Tone } from \"../utils/styles\";\n\nexport interface SwitchProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseSwitch.Root>, \"className\"> {\n tone?: Tone;\n className?: string;\n}\n\nexport const Switch = forwardRef<HTMLButtonElement, SwitchProps>(\n function Switch({ className, tone = \"primary\", ...props }, ref) {\n return (\n <BaseSwitch.Root\n ref={ref}\n className={cn(\n \"gryt-switch relative inline-flex h-6 w-10 shrink-0 items-center\",\n \"rounded-(--gryt-radius-full) border border-gryt-border bg-gryt-surface-raised p-0.5\",\n \"transition-[scale,background-color,border-color] duration-(--gryt-dur-spring) ease-spring\",\n \"data-checked:border-transparent\",\n \"hover:not-data-disabled:border-gryt-accent-light\",\n \"motion-safe:hover:not-data-disabled:scale-[1.05]\",\n \"motion-safe:active:not-data-disabled:scale-[0.95]\",\n focusRing,\n disabledState,\n toneCheckedBg[tone],\n className\n )}\n {...props}\n >\n <BaseSwitch.Thumb\n className={cn(\n \"h-4.5 w-4.5 rounded-(--gryt-radius-full) bg-gryt-text\",\n \"transition-transform duration-(--gryt-dur-spring) ease-spring motion-reduce:transition-none\",\n \"data-checked:translate-x-4 data-checked:bg-gryt-bg\"\n )}\n />\n </BaseSwitch.Root>\n );\n }\n);\n","import { Slider as BaseSlider } from \"@base-ui/react/slider\";\nimport { useEffect, useRef, useState } from \"react\";\nimport type { ComponentPropsWithoutRef, PointerEvent as ReactPointerEvent } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRingWithin, toneBg } from \"../utils/styles\";\nimport type { Tone } from \"../utils/styles\";\n\nexport interface SliderProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseSlider.Root>, \"className\"> {\n tone?: Tone;\n className?: string;\n \"aria-label\"?: string;\n}\n\n/** How far the pointer has to move before a press counts as a drag. */\nconst DRAG_SLOP = 3;\n\n/**\n * The travel is animated, on the spring.\n *\n * Two things about that are worth reading before changing it.\n *\n * It uses --ease-spring-tight rather than --ease-spring. The overshoot in the\n * standard spring is a percentage of the travel, which is texture on a control\n * that scales in place and a problem on one whose travel is its own width: a\n * full-track jump measured 110% along a 919px track, putting the thumb 96px\n * outside the slider before it came back. The thumb still scales on the\n * standard spring, where the overshoot belongs.\n *\n * And it animates on a click or an arrow key but not under a dragging pointer,\n * where a transition means the thumb lags behind the cursor. Base UI's\n * data-dragging is not the right signal for that: it appears on pointerdown,\n * which is also how you click the track, so keying off it would kill the\n * animation for the most common interaction there is. What matters is whether\n * the pointer has actually moved, so that is what is tracked here — with a few\n * pixels of slop, because a mouse rarely stays perfectly still through a click.\n */\nexport function Slider({\n className,\n tone = \"primary\",\n \"aria-label\": ariaLabel,\n ...props\n}: SliderProps) {\n const [dragging, setDragging] = useState(false);\n const origin = useRef<{ x: number; y: number } | null>(null);\n\n useEffect(() => {\n if (!dragging && origin.current === null) {\n return;\n }\n\n // On window rather than the control: the pointer is very often released\n // outside a 6px-tall track, and a pointerup we never hear about leaves the\n // slider stuck in its dragging state with the animation off for good.\n const end = () => {\n origin.current = null;\n setDragging(false);\n };\n\n window.addEventListener(\"pointerup\", end);\n window.addEventListener(\"pointercancel\", end);\n\n return () => {\n window.removeEventListener(\"pointerup\", end);\n window.removeEventListener(\"pointercancel\", end);\n };\n }, [dragging]);\n\n function handlePointerDown(event: ReactPointerEvent<HTMLDivElement>) {\n origin.current = { x: event.clientX, y: event.clientY };\n }\n\n function handlePointerMove(event: ReactPointerEvent<HTMLDivElement>) {\n const start = origin.current;\n if (start === null || dragging) {\n return;\n }\n\n const moved =\n Math.abs(event.clientX - start.x) > DRAG_SLOP ||\n Math.abs(event.clientY - start.y) > DRAG_SLOP;\n\n if (moved) {\n setDragging(true);\n }\n }\n\n // Base UI positions the thumb with inset-inline-start and sizes the fill with\n // width, so those are the properties that move. `translate` stays out of it:\n // that holds the -50% centring offset, and animating it would drift the thumb\n // off the track rather than along it.\n const travel = dragging\n ? \"transition-none\"\n : \"duration-(--gryt-dur-spring) ease-spring-tight motion-reduce:transition-none\";\n\n return (\n <BaseSlider.Root className={cn(\"gryt-slider w-full\", className)} {...props}>\n <BaseSlider.Control\n className=\"flex w-full cursor-pointer touch-none items-center py-2 select-none\"\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n >\n <BaseSlider.Track className=\"h-1.5 w-full rounded-(--gryt-radius-full) bg-gryt-surface-raised select-none\">\n <BaseSlider.Indicator\n className={cn(\n \"h-full rounded-(--gryt-radius-full) select-none\",\n \"transition-[width]\",\n travel,\n toneBg[tone]\n )}\n />\n {/* Two elements because they animate on two curves, and one element\n gets one timing function. The thumb travels on the tight spring;\n the dot inside it scales on the standard one, so the press still\n has the overshoot every other control here has. */}\n <BaseSlider.Thumb\n aria-label={ariaLabel}\n className={cn(\n \"group h-4 w-4 rounded-(--gryt-radius-full) select-none\",\n \"transition-[inset-inline-start]\",\n travel,\n // The ring goes on the thumb but the focus lands on the visually\n // hidden input inside it, so this has to match a descendant.\n // Without it the slider is the one control here you cannot see\n // yourself tab to.\n focusRingWithin\n )}\n >\n <span\n className={cn(\n \"block h-full w-full rounded-(--gryt-radius-full) bg-gryt-text\",\n \"transition-[scale] duration-(--gryt-dur-spring) ease-spring\",\n \"motion-safe:group-hover:scale-[1.12] motion-safe:group-active:scale-[0.94]\",\n \"motion-reduce:transition-none\"\n )}\n />\n </BaseSlider.Thumb>\n </BaseSlider.Track>\n </BaseSlider.Control>\n </BaseSlider.Root>\n );\n}\n","import { Select as BaseSelect } from \"@base-ui/react/select\";\nimport { CaretUpDown, Check } from \"@phosphor-icons/react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { usePortalContainer } from \"../../portalContainer\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing, popupMotion, popupSurface } from \"../utils/styles\";\n\nexport interface SelectOption {\n label: ReactNode;\n value: string | number;\n disabled?: boolean;\n}\n\nexport type SelectSize = \"small\" | \"medium\";\n\nconst sizeStyles: Record<SelectSize, string> = {\n small: \"min-h-9 px-3 text-sm\",\n medium: \"min-h-11 px-4 text-sm\"\n};\n\nexport interface SelectProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseSelect.Root>,\n \"children\" | \"items\"\n > {\n options?: SelectOption[];\n label?: ReactNode;\n placeholder?: string;\n size?: SelectSize;\n className?: string;\n}\n\n/*\n * The popup portals to the document body, and no caller can change that per\n * call site. It follows GrytProvider's `containOverlays` and nothing else.\n *\n * A `portalContainer` prop existed briefly so a Select inside a dialog could\n * render into it rather than beside it. It does not work, and it caused the\n * dropdowns in the client's server settings to open in the wrong place.\n *\n * Base UI positions the popup by computing coordinates against the viewport. A\n * dialog is `position: fixed` and centres itself with `translate: -50% -50%`,\n * and both of those make it a containing block for positioned descendants — so\n * the coordinates get resolved against the dialog and its own offset is counted\n * twice. Measured in a browser, with the dialog at (16, 226): the popup landed\n * 227px too low and 17px too far right, matching the dialog's origin.\n *\n * Neither escape works. `positionMethod=\"fixed\"` changes nothing. Removing the\n * translate fixes the vertical error and leaves the horizontal one, because the\n * dialog is still positioned.\n *\n * Portalling to the body is correct on both axes and already renders above the\n * dialog, so there was never a stacking problem to solve.\n *\n * The other half of GRYT-242 — a popup that genuinely needs to live inside a\n * themed subtree, because a second theme is being previewed inside a page — is\n * now `containOverlays` on GrytProvider. Deliberately not this prop back: the\n * container is set once, for a subtree, by whoever established the theme. A\n * per-call prop is the thing somebody reaches for to fix a layout problem,\n * which is how the bug above got made.\n */\nexport function Select({\n className,\n label,\n options = [],\n placeholder = \"Select\",\n size = \"medium\",\n ...props\n}: SelectProps) {\n const portalContainer = usePortalContainer();\n\n return (\n <BaseSelect.Root items={options} {...props}>\n <div className={cn(\"gryt-select flex w-full flex-col gap-1.5\", className)}>\n {label ? (\n <BaseSelect.Label className=\"text-xs font-medium text-gryt-muted\">\n {label}\n </BaseSelect.Label>\n ) : null}\n <BaseSelect.Trigger\n className={cn(\n \"flex w-full cursor-pointer items-center justify-between gap-2\",\n \"rounded-(--gryt-radius-xl) border border-gryt-border bg-gryt-surface-raised\",\n \"text-gryt-text select-none\",\n \"transition-colors duration-150 hover:border-gryt-accent-light\",\n \"data-disabled:cursor-not-allowed data-disabled:opacity-60\",\n focusRing,\n sizeStyles[size]\n )}\n >\n <BaseSelect.Value placeholder={placeholder} />\n <BaseSelect.Icon className=\"shrink-0 text-gryt-muted\">\n <CaretUpDown size={16} />\n </BaseSelect.Icon>\n </BaseSelect.Trigger>\n </div>\n\n <BaseSelect.Portal container={portalContainer}>\n <BaseSelect.Positioner\n sideOffset={6}\n className=\"gryt-select-positioner outline-none\"\n >\n <BaseSelect.Popup\n className={cn(\"min-w-(--anchor-width) p-1\", popupSurface, popupMotion)}\n >\n <BaseSelect.List>\n {options.map((option) => (\n <BaseSelect.Item\n key={String(option.value)}\n value={option.value}\n disabled={option.disabled}\n className={cn(\n \"flex cursor-pointer items-center justify-between gap-2\",\n \"rounded-(--gryt-radius-md) px-3 py-2 text-sm text-gryt-text\",\n \"outline-none select-none data-highlighted:bg-gryt-surface-raised\",\n \"data-disabled:cursor-not-allowed data-disabled:opacity-50\"\n )}\n >\n <BaseSelect.ItemText>{option.label}</BaseSelect.ItemText>\n <BaseSelect.ItemIndicator className=\"text-gryt-accent-11\">\n <Check size={14} weight=\"bold\" />\n </BaseSelect.ItemIndicator>\n </BaseSelect.Item>\n ))}\n </BaseSelect.List>\n </BaseSelect.Popup>\n </BaseSelect.Positioner>\n </BaseSelect.Portal>\n </BaseSelect.Root>\n );\n}\n","import { Tooltip as BaseTooltip } from \"@base-ui/react/tooltip\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport { usePortalContainer } from \"../../portalContainer\";\nimport { cn } from \"../utils/cn\";\nimport { popupMotion } from \"../utils/styles\";\n\nexport interface TooltipProps {\n // Kept as a single-child wrapper rather than exposing Base UI's five parts.\n // Both MUI and Radix Themes spell a tooltip this way, so client call sites\n // move across unchanged, and a tooltip has no useful middle ground to\n // compose anyway.\n title: ReactNode;\n children: ReactElement;\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n sideOffset?: number;\n className?: string;\n}\n\n// Hover delay is not set here — it belongs to Tooltip.Provider, which shares\n// timing across every tooltip so moving between two triggers does not restart\n// the wait. GrytProvider renders one; see its tooltipDelay prop.\nexport function Tooltip({\n children,\n className,\n side = \"top\",\n sideOffset = 8,\n title\n}: TooltipProps) {\n const portalContainer = usePortalContainer();\n\n return (\n <BaseTooltip.Root>\n <BaseTooltip.Trigger render={children} />\n <BaseTooltip.Portal container={portalContainer}>\n <BaseTooltip.Positioner\n side={side}\n sideOffset={sideOffset}\n className=\"gryt-tooltip-positioner\"\n >\n <BaseTooltip.Popup\n className={cn(\n \"gryt-tooltip rounded-(--gryt-radius-md) border border-gryt-border bg-gryt-surface-raised\",\n \"px-2.5 py-1.5 text-xs text-gryt-text\",\n popupMotion,\n className\n )}\n >\n {title}\n </BaseTooltip.Popup>\n </BaseTooltip.Positioner>\n </BaseTooltip.Portal>\n </BaseTooltip.Root>\n );\n}\n\n// Base UI shares hover timing across tooltips through this provider, so moving\n// between two triggers skips the delay the second time. GrytProvider renders\n// one already; this is exported for apps that do not use GrytProvider.\nexport const TooltipProvider = BaseTooltip.Provider;\n","import { Separator } from \"@base-ui/react/separator\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport interface DividerProps\n extends Omit<ComponentPropsWithoutRef<typeof Separator>, \"className\"> {\n className?: string;\n}\n\nexport const Divider = forwardRef<HTMLDivElement, DividerProps>(\n function Divider({ className, orientation = \"horizontal\", ...props }, ref) {\n return (\n <Separator\n ref={ref}\n orientation={orientation}\n className={cn(\n \"gryt-divider bg-gryt-border\",\n orientation === \"vertical\" ? \"h-full w-px\" : \"h-px w-full\",\n className\n )}\n {...props}\n />\n );\n }\n);\n","import { forwardRef } from \"react\";\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type CardProps = HTMLAttributes<HTMLDivElement>;\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(function Card(\n { className, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cn(\n \"gryt-card rounded-(--gryt-radius-xl) border border-gryt-border bg-gryt-surface text-gryt-text\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport interface CardHeaderProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"title\"> {\n title?: ReactNode;\n subheader?: ReactNode;\n}\n\nexport function CardHeader({\n children,\n className,\n subheader,\n title,\n ...props\n}: CardHeaderProps) {\n return (\n <div\n className={cn(\"gryt-card-header flex flex-col gap-1 p-4\", className)}\n {...props}\n >\n {title ? (\n <span className=\"text-base font-semibold text-gryt-text\">{title}</span>\n ) : null}\n {subheader ? (\n <span className=\"text-sm text-gryt-muted\">{subheader}</span>\n ) : null}\n {children}\n </div>\n );\n}\n\nexport function CardContent({\n className,\n ...props\n}: HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn(\n \"gryt-card-content px-4 pb-4 text-sm text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport function CardActions({\n className,\n ...props\n}: HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn(\n \"gryt-card-actions flex items-center gap-2 px-4 pb-4\",\n className\n )}\n {...props}\n />\n );\n}\n","import { forwardRef } from \"react\";\nimport type { HTMLAttributes } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type AlertSeverity = \"info\" | \"success\" | \"warning\" | \"error\";\n\n// Tinted background at low alpha with a matching border, rather than a solid\n// fill — an alert should read as a note on the surface, not a block on top of\n// it.\nconst severityStyles: Record<AlertSeverity, string> = {\n info: \"border-gryt-secondary-6 bg-gryt-secondary-3 text-gryt-secondary-11\",\n success: \"border-gryt-success-6 bg-gryt-success-3 text-gryt-success-11\",\n warning: \"border-gryt-warning-6 bg-gryt-warning-3 text-gryt-warning-11\",\n error: \"border-gryt-danger-6 bg-gryt-danger-3 text-gryt-danger-11\"\n};\n\nexport interface AlertProps extends HTMLAttributes<HTMLDivElement> {\n severity?: AlertSeverity;\n}\n\nexport const Alert = forwardRef<HTMLDivElement, AlertProps>(function Alert(\n { className, severity = \"info\", ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(\n \"gryt-alert rounded-(--gryt-radius-lg) border px-4 py-3 text-sm\",\n severityStyles[severity],\n className\n )}\n {...props}\n />\n );\n});\n","import { Progress as BaseProgress } from \"@base-ui/react/progress\";\nimport { CircleNotch } from \"@phosphor-icons/react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport interface ProgressProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseProgress.Root>,\n \"className\" | \"value\"\n > {\n className?: string;\n // Optional, unlike Base UI's own prop: omitting it gives an indeterminate\n // bar, which is the common case when there is no measurable total.\n value?: number | null;\n}\n\nexport function Progress({ className, value = null, ...props }: ProgressProps) {\n return (\n <BaseProgress.Root\n // null is Base UI's indeterminate, so the default has to be null rather\n // than undefined — undefined is not assignable to its value prop.\n value={value}\n className={cn(\"gryt-progress w-full\", className)}\n {...props}\n >\n <BaseProgress.Track className=\"h-1.5 w-full overflow-hidden rounded-(--gryt-radius-full) bg-gryt-surface-raised\">\n {/* ease-out, not the spring.\n A progress bar is a reading, and the spring overshoots 12% of the\n travel — so a jump to 100% ran past the end of the track and came\n back, which says the job finished, then unfinished, then finished.\n Bouncing is for controls the user just pushed. */}\n <BaseProgress.Indicator\n className={cn(\n \"h-full rounded-(--gryt-radius-full) bg-gryt-accent\",\n \"transition-[width] duration-300 ease-out motion-reduce:transition-none\",\n // Base UI marks the indicator indeterminate and leaves its width\n // unset, and nothing styled that — so an indeterminate Progress\n // rendered a track with an invisible indicator. An empty bar reads\n // as \"nothing has happened yet\", which is why it went unnoticed\n // rather than being reported. GRYT-382.\n value === null && \"gryt-progress-indeterminate\"\n )}\n />\n </BaseProgress.Track>\n </BaseProgress.Root>\n );\n}\n\nexport interface SpinnerProps {\n size?: number;\n className?: string;\n \"aria-label\"?: string;\n}\n\n// Base UI has no spinner — an indeterminate circular indicator is animation\n// rather than behaviour. Phosphor's CircleNotch is the shape, and the spin is\n// a Tailwind utility.\nexport function Spinner({\n className,\n size = 24,\n \"aria-label\": ariaLabel = \"Loading\"\n}: SpinnerProps) {\n return (\n <CircleNotch\n role=\"status\"\n aria-label={ariaLabel}\n size={size}\n weight=\"bold\"\n className={cn(\n \"gryt-spinner text-gryt-accent-11 motion-safe:animate-spin\",\n className\n )}\n />\n );\n}\n","import type { CSSProperties, HTMLAttributes } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type SkeletonVariant = \"text\" | \"rounded\" | \"circular\" | \"rectangular\";\n\nconst variantStyles: Record<SkeletonVariant, string> = {\n text: \"h-4 rounded-(--gryt-radius-sm)\",\n rounded: \"rounded-(--gryt-radius-lg)\",\n circular: \"rounded-(--gryt-radius-full)\",\n rectangular: \"rounded-none\"\n};\n\nexport interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {\n variant?: SkeletonVariant;\n width?: number | string;\n height?: number | string;\n}\n\nexport function Skeleton({\n className,\n height,\n style,\n variant = \"text\",\n width,\n ...props\n}: SkeletonProps) {\n const sizing: CSSProperties = {\n width,\n height,\n ...style\n };\n\n return (\n <div\n aria-hidden=\"true\"\n className={cn(\n // Not bg-gryt-surface-raised. #1e2028 against #1a1d24 is four points of\n // luminance, which is invisible on a laptop screen at an angle — the\n // placeholder that is meant to say \"something is coming\" said nothing.\n // A white wash instead of a fixed colour, so it stays visible on any of\n // the surfaces it can land on rather than only the one it was picked\n // against, and it dims rather than brightens as it pulses.\n \"gryt-skeleton bg-white/9 motion-safe:animate-pulse\",\n variantStyles[variant],\n className\n )}\n style={sizing}\n {...props}\n />\n );\n}\n","import { Dialog as BaseDialog } from \"@base-ui/react/dialog\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, HTMLAttributes } from \"react\";\nimport { cn } from \"../utils/cn\";\n\n// Base UI drives enter and exit animation through data-starting-style and\n// data-ending-style, which it sets for one frame either side of the transition.\n// The element has to carry the transition itself; there is no JS timing.\nconst motion =\n \"transition-[opacity,scale,translate] duration-(--gryt-dur-spring) ease-spring motion-reduce:transition-none\";\n\nexport type DialogBackdropProps = ComponentPropsWithoutRef<\n typeof BaseDialog.Backdrop\n>;\n\nconst Backdrop = forwardRef<HTMLDivElement, DialogBackdropProps>(\n function DialogBackdrop({ className, ...props }, ref) {\n return (\n <BaseDialog.Backdrop\n ref={ref}\n className={cn(\n \"gryt-dialog-backdrop fixed inset-0 min-h-dvh bg-black/60\",\n \"backdrop-blur-(--gryt-backdrop-blur)\",\n motion,\n \"data-starting-style:opacity-0 data-ending-style:opacity-0\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport type DialogPopupProps = ComponentPropsWithoutRef<\n typeof BaseDialog.Popup\n>;\n\n// 32rem, not the 24rem this used to be. Radix Themes, which the client is\n// migrating off, gives Dialog.Content 600px, so a dialog ported across to this\n// one shrank by a third for no reason anybody chose — and the client had grown\n// a w-[27rem]..w-[30rem] override on every dialog to claw some of it back.\n// tailwind-merge means those overrides still win, so this only moves the ones\n// that never said anything. AlertDialog carries the same width deliberately.\nconst Popup = forwardRef<HTMLDivElement, DialogPopupProps>(\n function DialogPopup({ className, ...props }, ref) {\n return (\n <BaseDialog.Popup\n ref={ref}\n className={cn(\n \"gryt-dialog fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2\",\n \"flex w-[32rem] max-w-[calc(100vw-3rem)] flex-col gap-4\",\n \"rounded-(--gryt-radius-lg) border border-gryt-border bg-gryt-surface p-5 text-gryt-text\",\n motion,\n \"data-starting-style:scale-[0.98] data-starting-style:opacity-0\",\n \"data-ending-style:scale-[0.98] data-ending-style:opacity-0\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport type DialogTitleProps = ComponentPropsWithoutRef<\n typeof BaseDialog.Title\n>;\n\nconst Title = forwardRef<HTMLHeadingElement, DialogTitleProps>(\n function DialogTitle({ className, ...props }, ref) {\n return (\n <BaseDialog.Title\n ref={ref}\n className={cn(\n \"gryt-dialog-title text-base font-semibold text-gryt-text\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport type DialogDescriptionProps = ComponentPropsWithoutRef<\n typeof BaseDialog.Description\n>;\n\nconst Description = forwardRef<HTMLParagraphElement, DialogDescriptionProps>(\n function DialogDescription({ className, ...props }, ref) {\n return (\n <BaseDialog.Description\n ref={ref}\n className={cn(\n \"gryt-dialog-description text-sm text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport type DialogFooterProps = HTMLAttributes<HTMLDivElement>;\n\n// Replaces MUI's DialogActions. Base UI has no equivalent part, because it is\n// a plain row of buttons and nothing about it needs behaviour.\nconst Footer = forwardRef<HTMLDivElement, DialogFooterProps>(\n function DialogFooter({ className, ...props }, ref) {\n return (\n <div\n ref={ref}\n className={cn(\n \"gryt-dialog-footer flex justify-end gap-3\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport const Dialog = {\n Root: BaseDialog.Root,\n Trigger: BaseDialog.Trigger,\n Portal: BaseDialog.Portal,\n Close: BaseDialog.Close,\n Backdrop,\n Popup,\n Title,\n Description,\n Footer\n};\n","import { useCallback, useSyncExternalStore } from \"react\";\n\nconst noop = () => () => {};\n\n/**\n * Matches a media query, safely on the server.\n *\n * Written here rather than taken from Base UI's `unstable-use-media-query`,\n * because a component library should not put an explicitly unstable export on\n * its public path.\n *\n * useSyncExternalStore rather than useState in an effect: matchMedia is an\n * external store, and reading it into state after mount means an extra render\n * on every consumer plus a frame where the answer is wrong. The server snapshot\n * is false so the first client paint agrees with the server's.\n */\nexport function useMediaQuery(query: string): boolean {\n const subscribe = useCallback(\n (onChange: () => void) => {\n if (typeof window === \"undefined\" || !window.matchMedia) return noop();\n const list = window.matchMedia(query);\n list.addEventListener(\"change\", onChange);\n return () => list.removeEventListener(\"change\", onChange);\n },\n [query]\n );\n\n const getSnapshot = useCallback(() => {\n if (typeof window === \"undefined\" || !window.matchMedia) return false;\n return window.matchMedia(query).matches;\n }, [query]);\n\n return useSyncExternalStore(subscribe, getSnapshot, () => false);\n}\n","import { Drawer as BaseDrawer } from \"@base-ui/react/drawer\";\nimport { createContext, forwardRef, useContext } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { useMediaQuery } from \"../utils/useMediaQuery\";\n\nexport type DrawerSide = \"left\" | \"right\" | \"top\" | \"bottom\";\n\n/**\n * A panel pinned to an edge of the screen, and a sheet on small screens.\n *\n * Built on Base UI's `drawer` rather than on `dialog`, which is what this used\n * to be. A dialog pinned to an edge looks like a drawer and does none of what\n * one is for: it cannot be dragged away, it does not follow the finger, and it\n * does not know which edge it belongs to. The primitive brings swipe-to-dismiss,\n * snap points and nested stacking, and it drives the drag through CSS variables\n * so the panel tracks the pointer without a re-render per frame.\n *\n * `side` lives on Root, not on Popup as it used to. It has to: the swipe\n * direction is Root's business, and Viewport and Popup both need to agree with\n * it. Callers passing `side` to Popup will need to move it up one level.\n */\n\n/** Which way you drag to dismiss, per edge. */\nconst swipeBySide = {\n left: \"left\",\n right: \"right\",\n top: \"up\",\n bottom: \"down\"\n} as const;\n\nconst SideContext = createContext<DrawerSide>(\"right\");\n\n/** Where the panel sits inside the viewport. */\nconst viewportBySide: Record<DrawerSide, string> = {\n left: \"items-stretch justify-start\",\n right: \"items-stretch justify-end\",\n top: \"items-start justify-center\",\n bottom: \"items-end justify-center\"\n};\n\n/**\n * Corners are rounded on the edges away from the origin only.\n *\n * A sheet coming up from the bottom is still attached to the bottom of the\n * screen, so rounding its bottom corners would float it off an edge it has not\n * left. Rounding the leading edge alone is what makes it read as attached.\n */\nconst radiusBySide: Record<DrawerSide, string> = {\n left: \"rounded-r-(--gryt-radius-xl)\",\n right: \"rounded-l-(--gryt-radius-xl)\",\n top: \"rounded-b-(--gryt-radius-xl)\",\n bottom: \"rounded-t-(--gryt-radius-xl)\"\n};\n\n/**\n * Size, the overhang, and the off-screen resting transform.\n *\n * The panel runs --gryt-drawer-bleed past its edge and hangs that much\n * off-screen, with matching padding so content sits where it would have. The\n * spring settles onto its target from both directions, and without the overhang\n * a fractional undershoot shows a seam of backdrop down the edge.\n */\nconst popupBySide: Record<DrawerSide, string> = {\n left: [\n \"h-full w-[calc(20rem+var(--gryt-drawer-bleed))] max-w-[calc(85vw+var(--gryt-drawer-bleed))]\",\n \"-ml-(--gryt-drawer-bleed) border-r py-5 pr-5 pl-[calc(1.25rem+var(--gryt-drawer-bleed))]\",\n \"[transform:translateX(var(--drawer-swipe-movement-x))]\",\n \"data-starting-style:[transform:translateX(calc(-100%+var(--gryt-drawer-bleed)))]\",\n \"data-ending-style:[transform:translateX(calc(-100%+var(--gryt-drawer-bleed)))]\"\n ].join(\" \"),\n right: [\n \"h-full w-[calc(20rem+var(--gryt-drawer-bleed))] max-w-[calc(85vw+var(--gryt-drawer-bleed))]\",\n \"-mr-(--gryt-drawer-bleed) border-l py-5 pl-5 pr-[calc(1.25rem+var(--gryt-drawer-bleed))]\",\n \"[transform:translateX(var(--drawer-swipe-movement-x))]\",\n \"data-starting-style:[transform:translateX(calc(100%-var(--gryt-drawer-bleed)))]\",\n \"data-ending-style:[transform:translateX(calc(100%-var(--gryt-drawer-bleed)))]\"\n ].join(\" \"),\n top: [\n \"w-full max-h-[calc(85vh+var(--gryt-drawer-bleed))]\",\n \"-mt-(--gryt-drawer-bleed) border-b px-5 pb-5 pt-[calc(1.25rem+var(--gryt-drawer-bleed))]\",\n \"[transform:translateY(var(--drawer-swipe-movement-y))]\",\n \"data-starting-style:[transform:translateY(calc(-100%+var(--gryt-drawer-bleed)))]\",\n \"data-ending-style:[transform:translateY(calc(-100%+var(--gryt-drawer-bleed)))]\"\n ].join(\" \"),\n bottom: [\n \"w-full max-h-[calc(85vh+var(--gryt-drawer-bleed))]\",\n \"-mb-(--gryt-drawer-bleed) border-t px-5 pt-5 pb-[calc(1.25rem+var(--gryt-drawer-bleed))]\",\n \"[transform:translateY(var(--drawer-swipe-movement-y))]\",\n \"data-starting-style:[transform:translateY(calc(100%-var(--gryt-drawer-bleed)))]\",\n \"data-ending-style:[transform:translateY(calc(100%-var(--gryt-drawer-bleed)))]\"\n ].join(\" \")\n};\n\nexport interface DrawerRootProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseDrawer.Root>,\n \"swipeDirection\"\n > {\n /** Edge the panel is pinned to. Ignored on small screens unless sheetOnMobile is false. */\n side?: DrawerSide;\n /**\n * Become a bottom sheet under 768px.\n *\n * A side panel is a desktop shape. On a phone it eats the width the content\n * needs and puts the drag gesture on the axis the browser uses for back\n * navigation. Set false to keep `side` at every width.\n */\n sheetOnMobile?: boolean;\n children?: ReactNode;\n}\n\nfunction Root({\n side = \"right\",\n sheetOnMobile = true,\n children,\n ...props\n}: DrawerRootProps) {\n const isMobile = useMediaQuery(\"(max-width: 767px)\");\n const resolved: DrawerSide = sheetOnMobile && isMobile ? \"bottom\" : side;\n\n return (\n <SideContext.Provider value={resolved}>\n <BaseDrawer.Root swipeDirection={swipeBySide[resolved]} {...props}>\n {children}\n </BaseDrawer.Root>\n </SideContext.Provider>\n );\n}\n\nexport type DrawerViewportProps = ComponentPropsWithoutRef<\n typeof BaseDrawer.Viewport\n>;\n\nconst Viewport = forwardRef<HTMLDivElement, DrawerViewportProps>(\n function DrawerViewport({ className, ...props }, ref) {\n const side = useContext(SideContext);\n return (\n <BaseDrawer.Viewport\n ref={ref}\n className={cn(\n // z-50 matters: the popup is no longer positioned itself, so the\n // viewport is what has to sit above the page. Without it a sticky\n // site header renders over the panel.\n \"gryt-drawer-viewport fixed inset-0 z-50 flex\",\n viewportBySide[side],\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport type DrawerPopupProps = ComponentPropsWithoutRef<\n typeof BaseDrawer.Popup\n>;\n\nconst Popup = forwardRef<HTMLDivElement, DrawerPopupProps>(function DrawerPopup(\n { className, ...props },\n ref\n) {\n const side = useContext(SideContext);\n return (\n <BaseDrawer.Popup\n ref={ref}\n className={cn(\n \"gryt-drawer flex flex-col gap-4 border-gryt-border bg-gryt-surface text-gryt-text\",\n \"overflow-y-auto overscroll-contain outline-none\",\n \"transition-transform duration-(--gryt-dur-spring-soft) ease-spring-tight\",\n // While the finger is down the panel must track it exactly. Any\n // duration here turns a drag into a drag plus lag.\n \"data-swiping:duration-0 data-swiping:select-none\",\n \"motion-reduce:transition-none\",\n popupBySide[side],\n radiusBySide[side],\n className\n )}\n {...props}\n />\n );\n});\n\nconst Backdrop = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseDrawer.Backdrop>\n>(function DrawerBackdrop({ className, ...props }, ref) {\n return (\n <BaseDrawer.Backdrop\n ref={ref}\n className={cn(\n \"gryt-drawer-backdrop fixed inset-0 z-50 min-h-dvh bg-black/60\",\n \"backdrop-blur-(--gryt-backdrop-blur)\",\n // Lightens as the panel is dragged away, so letting go halfway does not\n // leave a full-strength scrim over a half-gone sheet.\n \"[opacity:calc(1-var(--drawer-swipe-progress,0))]\",\n \"transition-opacity duration-(--gryt-dur-spring-soft) ease-spring-tight\",\n \"data-swiping:duration-0\",\n \"data-starting-style:opacity-0 data-ending-style:opacity-0\",\n \"motion-reduce:transition-none\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport interface DrawerGrabberProps {\n className?: string;\n}\n\n/**\n * The bar people expect to drag on a sheet.\n *\n * Rendered only for the top and bottom edges: on a left or right panel it would\n * be pointing the wrong way, and a horizontal drawer is a desktop shape where\n * nobody reaches for a grab bar anyway. Decorative — the whole popup is\n * draggable, so this is a hint, not the control.\n */\nfunction Grabber({ className }: DrawerGrabberProps) {\n const side = useContext(SideContext);\n if (side !== \"bottom\" && side !== \"top\") return null;\n\n return (\n <div\n aria-hidden\n className={cn(\n \"gryt-drawer-grabber mx-auto h-1.5 w-10 shrink-0 rounded-(--gryt-radius-full) bg-gryt-border\",\n side === \"top\" && \"order-last\",\n className\n )}\n />\n );\n}\n\nexport const Drawer = {\n Root,\n Trigger: BaseDrawer.Trigger,\n Portal: BaseDrawer.Portal,\n Backdrop,\n Viewport,\n Popup,\n Content: BaseDrawer.Content,\n Grabber,\n Close: BaseDrawer.Close,\n Title: BaseDrawer.Title,\n Description: BaseDrawer.Description\n};\n","import { Menu as BaseMenu } from \"@base-ui/react/menu\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { popupMotion, popupSurface } from \"../utils/styles\";\n\nexport type MenuPopupProps = ComponentPropsWithoutRef<typeof BaseMenu.Popup>;\nexport type MenuItemProps = ComponentPropsWithoutRef<typeof BaseMenu.Item>;\nexport type MenuPositionerProps = ComponentPropsWithoutRef<\n typeof BaseMenu.Positioner\n>;\n\nconst Positioner = forwardRef<HTMLDivElement, MenuPositionerProps>(\n function MenuPositioner({ className, sideOffset = 8, ...props }, ref) {\n return (\n <BaseMenu.Positioner\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\"gryt-menu-positioner outline-none\", className)}\n {...props}\n />\n );\n }\n);\n\nconst Popup = forwardRef<HTMLDivElement, MenuPopupProps>(function MenuPopup(\n { className, ...props },\n ref\n) {\n return (\n <BaseMenu.Popup\n ref={ref}\n className={cn(\n \"gryt-menu min-w-44 p-1 outline-none\",\n popupSurface,\n popupMotion,\n className\n )}\n {...props}\n />\n );\n});\n\nconst Item = forwardRef<HTMLDivElement, MenuItemProps>(function MenuItem(\n { className, ...props },\n ref\n) {\n return (\n <BaseMenu.Item\n ref={ref}\n className={cn(\n \"gryt-menu-item flex cursor-pointer items-center gap-2 rounded-(--gryt-radius-md)\",\n \"px-3 py-2 text-sm text-gryt-text outline-none select-none\",\n // Base UI drives keyboard and pointer highlight through the same\n // attribute, so arrow keys and the mouse land on identical styling.\n \"data-highlighted:bg-gryt-surface-raised\",\n \"data-disabled:cursor-not-allowed data-disabled:opacity-50\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Separator = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseMenu.Separator>\n>(function MenuSeparator({ className, ...props }, ref) {\n return (\n <BaseMenu.Separator\n ref={ref}\n className={cn(\"gryt-menu-separator my-1 h-px bg-gryt-border\", className)}\n {...props}\n />\n );\n});\n\nexport const Menu = {\n Root: BaseMenu.Root,\n Trigger: BaseMenu.Trigger,\n Portal: BaseMenu.Portal,\n Positioner,\n Popup,\n Item,\n Separator\n};\n","import { Tabs as BaseTabs } from \"@base-ui/react/tabs\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing } from \"../utils/styles\";\n\nexport type TabsProps = ComponentPropsWithoutRef<typeof BaseTabs.Root>;\nexport type TabsListProps = ComponentPropsWithoutRef<typeof BaseTabs.List>;\nexport type TabProps = ComponentPropsWithoutRef<typeof BaseTabs.Tab>;\nexport type TabsPanelProps = ComponentPropsWithoutRef<typeof BaseTabs.Panel>;\n\n/**\n * Orientation is Base UI's `orientation` prop on Root, and every part below\n * styles itself from the `data-orientation` it puts on the DOM rather than from\n * a prop of ours. That is why none of these take an orientation of their own:\n * setting it in two places is how a list ends up vertical and its indicator\n * still travelling sideways.\n *\n * Vertical is the same visual language turned ninety degrees — the accent pill\n * still slides between rows. It suits a rail of five or six destinations. Past\n * about a dozen the filled pill becomes a block of accent parked in the corner\n * of the screen, and a quieter marker is the better call; the docs sidebar is\n * that case and deliberately does not use this.\n */\nconst Root = forwardRef<HTMLDivElement, TabsProps>(function TabsRoot(\n { className, ...props },\n ref\n) {\n return (\n <BaseTabs.Root\n ref={ref}\n className={cn(\n \"gryt-tabs\",\n // Vertical puts the rail and the panel side by side. min-w-0 on the\n // panel does the rest; without the flex here the panel lands under the\n // rail and the layout reads as a very tall accordion.\n \"data-[orientation=vertical]:flex data-[orientation=vertical]:items-stretch\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst List = forwardRef<HTMLDivElement, TabsListProps>(function TabsList(\n { className, ...props },\n ref\n) {\n return (\n <BaseTabs.List\n ref={ref}\n className={cn(\n \"gryt-tabs-list relative inline-flex items-center gap-1 rounded-(--gryt-radius-full) bg-gryt-surface-raised p-1\",\n // A rail, not a pill: rows are full width and the corner radius drops\n // to lg, because a 999px radius on a tall box bows its short edges.\n \"data-[orientation=vertical]:flex data-[orientation=vertical]:shrink-0\",\n \"data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch\",\n \"data-[orientation=vertical]:rounded-(--gryt-radius-lg)\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Tab = forwardRef<HTMLButtonElement, TabProps>(function Tab(\n { className, ...props },\n ref\n) {\n return (\n <BaseTabs.Tab\n ref={ref}\n className={cn(\n \"gryt-tab inline-flex min-h-8 cursor-pointer items-center justify-center whitespace-nowrap\",\n \"rounded-(--gryt-radius-full) border-0 bg-transparent px-4 py-1.5\",\n \"text-sm font-medium text-gryt-muted select-none\",\n // Scale as well as colour, matching Button exactly — 1.03 under the\n // cursor, 0.96 pressed, on the spring duration and curve. A tab that\n // only changed colour read as not being a button at all next to\n // anything that did move, and the owl designer's rail was reported as\n // \"not using the Gryt UI tabs\" for precisely that reason.\n //\n // motion-safe, so the whole thing is colour-only for anybody who asked\n // for reduced motion.\n \"relative z-10 hover:text-gryt-text\",\n \"transition-[scale,color,background-color] duration-(--gryt-dur-spring) ease-spring\",\n \"motion-safe:hover:scale-[1.03] motion-safe:active:scale-[0.96]\",\n \"motion-reduce:transition-colors motion-reduce:duration-150\",\n // Base UI marks the selected tab with data-active, not data-selected.\n // The fill moved to Indicator so it can travel between tabs; the tab\n // itself only changes its text colour.\n \"data-active:text-gryt-on-accent\",\n // Left-aligned and taller in a rail. Centred labels in a vertical list\n // leave the text edge ragged, which is what makes a rail look untidy.\n \"data-[orientation=vertical]:min-h-9 data-[orientation=vertical]:justify-start\",\n \"data-[orientation=vertical]:gap-2.5 data-[orientation=vertical]:px-3\",\n \"data-[orientation=vertical]:rounded-(--gryt-radius-md)\",\n \"data-disabled:cursor-not-allowed data-disabled:opacity-50\",\n focusRing,\n className\n )}\n {...props}\n />\n );\n});\n\nexport type TabsIndicatorProps = ComponentPropsWithoutRef<\n typeof BaseTabs.Indicator\n>;\n\n// Base UI measures the active tab and publishes --active-tab-left and\n// --active-tab-width, plus --active-tab-top and --active-tab-height, which is\n// what lets the pill slide rather than jump. renderBeforeHydration keeps it\n// positioned on the first paint instead of animating in from the left edge.\n//\n// The vertical rules hang off the ancestor's data-orientation rather than the\n// indicator's own. Root is the part guaranteed to carry it, and an indicator\n// that reads its orientation from somewhere other than the root it belongs to\n// is a bug waiting for someone to nest two sets of tabs.\nconst Indicator = forwardRef<HTMLSpanElement, TabsIndicatorProps>(\n function TabsIndicator({ className, ...props }, ref) {\n return (\n <BaseTabs.Indicator\n ref={ref}\n renderBeforeHydration\n className={cn(\n \"gryt-tabs-indicator absolute top-1 left-0 z-0 h-[calc(100%-0.5rem)]\",\n \"w-(--active-tab-width) translate-x-(--active-tab-left)\",\n \"rounded-(--gryt-radius-full) bg-gryt-accent\",\n \"transition-[translate,width] duration-(--gryt-dur-spring) ease-spring\",\n \"motion-reduce:transition-none\",\n // Same pill, travelling down the rail instead of across the row.\n \"[[data-orientation=vertical]_&]:top-0 [[data-orientation=vertical]_&]:left-1\",\n \"[[data-orientation=vertical]_&]:h-(--active-tab-height)\",\n \"[[data-orientation=vertical]_&]:w-[calc(100%-0.5rem)]\",\n \"[[data-orientation=vertical]_&]:translate-x-0\",\n \"[[data-orientation=vertical]_&]:translate-y-(--active-tab-top)\",\n \"[[data-orientation=vertical]_&]:rounded-(--gryt-radius-md)\",\n \"[[data-orientation=vertical]_&]:transition-[translate,height]\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Panel = forwardRef<HTMLDivElement, TabsPanelProps>(function TabsPanel(\n { className, ...props },\n ref\n) {\n return (\n <BaseTabs.Panel\n ref={ref}\n className={cn(\n \"gryt-tabs-panel pt-3 text-sm text-gryt-text\",\n // Beside the rail rather than under it, and allowed to shrink so long\n // content wraps instead of pushing the rail off screen.\n \"data-[orientation=vertical]:min-w-0 data-[orientation=vertical]:flex-1\",\n \"data-[orientation=vertical]:pt-0 data-[orientation=vertical]:pl-4\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport const Tabs = Object.assign(Root, { List, Tab, Panel, Indicator });\nexport { Tab };\n","import { Accordion as BaseAccordion } from \"@base-ui/react/accordion\";\nimport { CaretDown } from \"@phosphor-icons/react\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing } from \"../utils/styles\";\n\nexport type AccordionProps = ComponentPropsWithoutRef<\n typeof BaseAccordion.Root\n>;\nexport type AccordionItemProps = ComponentPropsWithoutRef<\n typeof BaseAccordion.Item\n>;\nexport type AccordionPanelProps = ComponentPropsWithoutRef<\n typeof BaseAccordion.Panel\n>;\n\nconst Root = forwardRef<HTMLDivElement, AccordionProps>(function AccordionRoot(\n { className, ...props },\n ref\n) {\n return (\n <BaseAccordion.Root\n ref={ref}\n className={cn(\n \"gryt-accordion flex w-full flex-col gap-2 rounded-(--gryt-radius-xl) border border-gryt-border bg-gryt-surface p-2\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Item = forwardRef<HTMLDivElement, AccordionItemProps>(\n function AccordionItem({ className, ...props }, ref) {\n return (\n <BaseAccordion.Item\n ref={ref}\n className={cn(\"gryt-accordion-item\", className)}\n {...props}\n />\n );\n }\n);\n\nexport interface AccordionTriggerProps\n extends ComponentPropsWithoutRef<typeof BaseAccordion.Trigger> {\n // Defaults to a caret that rotates when the panel opens. Pass one to\n // override it, or null for no indicator at all.\n expandIcon?: ReactNode;\n}\n\nconst Trigger = forwardRef<HTMLButtonElement, AccordionTriggerProps>(\n function AccordionTrigger({ children, className, expandIcon, ...props }, ref) {\n return (\n <BaseAccordion.Header className=\"gryt-accordion-header m-0\">\n <BaseAccordion.Trigger\n ref={ref}\n className={cn(\n \"gryt-accordion-trigger flex w-full cursor-pointer items-center justify-between gap-3\",\n \"rounded-(--gryt-radius-lg) border-0 bg-transparent px-3 py-2.5\",\n \"text-left text-sm font-medium text-gryt-text select-none\",\n \"transition-colors duration-150 hover:bg-gryt-surface-raised\",\n \"data-disabled:cursor-not-allowed data-disabled:opacity-50\",\n focusRing,\n className\n )}\n {...props}\n >\n {children}\n {expandIcon === undefined ? (\n <CaretDown\n size={16}\n // Base UI flags the open panel on the trigger, so the caret needs\n // no state of its own.\n className=\"shrink-0 transition-transform duration-(--gryt-dur-spring) ease-spring data-panel-open:rotate-180 motion-reduce:transition-none\"\n />\n ) : (\n expandIcon\n )}\n </BaseAccordion.Trigger>\n </BaseAccordion.Header>\n );\n }\n);\n\nconst Panel = forwardRef<HTMLDivElement, AccordionPanelProps>(\n function AccordionPanel({ children, className, ...props }, ref) {\n return (\n <BaseAccordion.Panel\n ref={ref}\n className={cn(\n \"gryt-accordion-panel overflow-hidden text-sm text-gryt-muted\",\n // Base UI measures the panel and exposes the height as a variable,\n // which is what makes a real open and close transition possible.\n \"h-[var(--accordion-panel-height)] transition-[height] duration-(--gryt-dur-spring-soft) ease-spring\",\n \"data-starting-style:h-0 data-ending-style:h-0\",\n \"motion-reduce:transition-none\",\n className\n )}\n {...props}\n >\n <div className=\"px-3 pt-1 pb-3\">{children}</div>\n </BaseAccordion.Panel>\n );\n }\n);\n\nexport const Accordion = Object.assign(Root, { Item, Trigger, Panel });\n","import { ContextMenu as BaseContextMenu } from \"@base-ui/react/context-menu\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Menu } from \"../Menu/Menu\";\n\nexport type ContextMenuPositionerProps = ComponentPropsWithoutRef<\n typeof BaseContextMenu.Positioner\n>;\n\n/**\n * A right-click menu: a message, a member, a channel.\n *\n * Base UI builds this out of Menu's own parts — its Popup, Item and Separator\n * are literally Menu's components — so this reuses the styled ones rather than\n * restyling them. A context menu that drifted from the dropdown menu would be\n * a bug nobody notices until both are on screen at once.\n */\nconst Positioner = forwardRef<HTMLDivElement, ContextMenuPositionerProps>(\n function ContextMenuPositioner({ className, sideOffset = 2, ...props }, ref) {\n return (\n <BaseContextMenu.Positioner\n ref={ref}\n // Smaller than Menu's 8. This anchors to the pointer rather than to a\n // trigger element, and 8px from the cursor reads as a menu that missed.\n sideOffset={sideOffset}\n className={cn(\"gryt-context-menu-positioner outline-none\", className)}\n {...props}\n />\n );\n }\n);\n\nexport const ContextMenu = {\n Root: BaseContextMenu.Root,\n Trigger: BaseContextMenu.Trigger,\n Portal: BaseContextMenu.Portal,\n Positioner,\n Popup: Menu.Popup,\n Item: Menu.Item,\n Separator: Menu.Separator,\n Group: BaseContextMenu.Group,\n GroupLabel: BaseContextMenu.GroupLabel,\n SubmenuRoot: BaseContextMenu.SubmenuRoot,\n SubmenuTrigger: BaseContextMenu.SubmenuTrigger\n};\n","import { Popover as BasePopover } from \"@base-ui/react/popover\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { popupMotion, popupSurface } from \"../utils/styles\";\n\nexport type PopoverPopupProps = ComponentPropsWithoutRef<\n typeof BasePopover.Popup\n>;\nexport type PopoverPositionerProps = ComponentPropsWithoutRef<\n typeof BasePopover.Positioner\n>;\n\nconst Positioner = forwardRef<HTMLDivElement, PopoverPositionerProps>(\n function PopoverPositioner({ className, sideOffset = 8, ...props }, ref) {\n return (\n <BasePopover.Positioner\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\"gryt-popover-positioner outline-none\", className)}\n {...props}\n />\n );\n }\n);\n\n// Wider default than Menu: this holds prose and controls — a member card, a\n// permissions summary — rather than a column of one-line items.\nconst Popup = forwardRef<HTMLDivElement, PopoverPopupProps>(\n function PopoverPopup({ className, ...props }, ref) {\n return (\n <BasePopover.Popup\n ref={ref}\n className={cn(\n \"gryt-popover max-w-[min(20rem,calc(100vw-2rem))] p-4 outline-none\",\n popupSurface,\n popupMotion,\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Title = forwardRef<\n HTMLHeadingElement,\n ComponentPropsWithoutRef<typeof BasePopover.Title>\n>(function PopoverTitle({ className, ...props }, ref) {\n return (\n <BasePopover.Title\n ref={ref}\n className={cn(\n \"gryt-popover-title text-sm font-semibold text-gryt-text\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Description = forwardRef<\n HTMLParagraphElement,\n ComponentPropsWithoutRef<typeof BasePopover.Description>\n>(function PopoverDescription({ className, ...props }, ref) {\n return (\n <BasePopover.Description\n ref={ref}\n className={cn(\n \"gryt-popover-description mt-1 text-sm leading-6 text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport const Popover = {\n Root: BasePopover.Root,\n Trigger: BasePopover.Trigger,\n Portal: BasePopover.Portal,\n Positioner,\n Popup,\n Title,\n Description,\n Close: BasePopover.Close,\n Arrow: BasePopover.Arrow\n};\n","import { Toast as BaseToast } from \"@base-ui/react/toast\";\nimport { X } from \"@phosphor-icons/react\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type ToastSeverity =\n | \"neutral\"\n | \"info\"\n | \"success\"\n | \"warning\"\n | \"danger\";\n\n/**\n * Severity is a tinted edge and a wash, not a filled card.\n *\n * Alert tints its whole surface, and that is right for something sitting in\n * the page where it has to compete with the content around it. A toast is\n * already floating over everything with nothing to compete with, so the same\n * treatment reads as shouting. The border carries the colour and the fill stays\n * near the surface underneath.\n */\nconst severityStyles: Record<ToastSeverity, string> = {\n neutral: \"border-white/8 bg-gryt-surface\",\n info: \"border-gryt-secondary-6 bg-gryt-secondary-2\",\n success: \"border-gryt-success-6 bg-gryt-success-2\",\n warning: \"border-gryt-warning-6 bg-gryt-warning-2\",\n danger: \"border-gryt-danger-6 bg-gryt-danger-2\"\n};\n\nexport interface ToastRootProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseToast.Root>, \"className\"> {\n severity?: ToastSeverity;\n className?: string;\n}\nexport type ToastViewportProps = ComponentPropsWithoutRef<\n typeof BaseToast.Viewport\n>;\n\n/**\n * Transient notice: connection lost, invite copied, message failed to send.\n *\n * design.md's stance is silent success — most things that worked should say\n * nothing. This is for the cases where the user is not looking at the thing\n * that changed, which in a voice client is most of them.\n */\nconst Viewport = forwardRef<HTMLDivElement, ToastViewportProps>(\n function ToastViewport({ className, ...props }, ref) {\n return (\n <BaseToast.Viewport\n ref={ref}\n className={cn(\n \"gryt-toast-viewport fixed right-4 bottom-4 z-50 flex w-[min(22rem,calc(100vw-2rem))]\",\n \"flex-col gap-2 outline-none\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Root = forwardRef<HTMLDivElement, ToastRootProps>(function ToastRoot(\n { className, severity = \"neutral\", ...props },\n ref\n) {\n return (\n <BaseToast.Root\n ref={ref}\n className={cn(\n \"gryt-toast relative flex flex-col p-3 pr-9\",\n // Not popupSurface. That border is --gryt-border, a solid slate line\n // that is right for a menu anchored to the thing that opened it and too\n // heavy for a card floating in the corner with nothing behind it. A\n // white hairline separates it from the page without drawing a box\n // around it.\n \"rounded-(--gryt-radius-xl) border text-gryt-text\",\n severityStyles[severity],\n // Swiping is a pointer gesture, so the toast follows the finger\n // through Base UI's swipe variables before it animates out.\n \"transition-[opacity,transform] duration-(--gryt-dur-spring) ease-spring\",\n \"data-starting-style:translate-y-2 data-starting-style:opacity-0\",\n \"data-ending-style:translate-y-2 data-ending-style:opacity-0\",\n \"motion-reduce:transition-none\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Title = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseToast.Title>\n>(function ToastTitle({ className, ...props }, ref) {\n return (\n <BaseToast.Title\n ref={ref}\n className={cn(\n \"gryt-toast-title text-sm font-semibold text-gryt-text\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Description = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseToast.Description>\n>(function ToastDescription({ className, ...props }, ref) {\n return (\n <BaseToast.Description\n ref={ref}\n className={cn(\n \"gryt-toast-description mt-0.5 text-sm leading-6 text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Close = forwardRef<\n HTMLButtonElement,\n ComponentPropsWithoutRef<typeof BaseToast.Close>\n>(function ToastClose({ className, children, ...props }, ref) {\n return (\n <BaseToast.Close\n ref={ref}\n aria-label=\"Close\"\n className={cn(\n \"gryt-toast-close absolute top-2.5 right-2.5 inline-flex h-6 w-6 items-center justify-center\",\n \"rounded-(--gryt-radius-full) border-0 bg-transparent text-gryt-muted\",\n \"transition-colors hover:bg-white/8 hover:text-gryt-text motion-reduce:transition-none\",\n \"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gryt-accent-light\",\n className\n )}\n {...props}\n >\n {children ?? <X size={14} weight=\"bold\" />}\n </BaseToast.Close>\n );\n});\n\nconst Action = forwardRef<\n HTMLButtonElement,\n ComponentPropsWithoutRef<typeof BaseToast.Action>\n>(function ToastAction({ className, ...props }, ref) {\n return (\n <BaseToast.Action\n ref={ref}\n className={cn(\n \"gryt-toast-action mt-2 self-start rounded-(--gryt-radius-full) border-0\",\n \"bg-gryt-accent px-3 py-1.5 text-sm font-medium text-gryt-on-accent\",\n \"transition-[scale] duration-(--gryt-dur-spring) ease-spring\",\n \"motion-safe:hover:scale-[1.04] motion-safe:active:scale-[0.96]\",\n \"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gryt-accent-light\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport const Toast = {\n Provider: BaseToast.Provider,\n Portal: BaseToast.Portal,\n Viewport,\n Root,\n Title,\n Description,\n Close,\n Action\n};\n\n/**\n * Raise a toast without importing Base UI directly.\n *\n * Taken off the namespace rather than re-exported from \"@base-ui/react/toast\":\n * at that path the hook is a type-only declaration, and re-exporting it as a\n * value fails under isolatedModules. The value lives on the parts namespace.\n */\nexport const useToastManager = BaseToast.useToastManager;\n","import { ScrollArea as BaseScrollArea } from \"@base-ui/react/scroll-area\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type ScrollAreaRootProps = ComponentPropsWithoutRef<\n typeof BaseScrollArea.Root\n>;\nexport type ScrollAreaViewportProps = ComponentPropsWithoutRef<\n typeof BaseScrollArea.Viewport\n>;\nexport type ScrollAreaScrollbarProps = ComponentPropsWithoutRef<\n typeof BaseScrollArea.Scrollbar\n>;\n\nconst Root = forwardRef<HTMLDivElement, ScrollAreaRootProps>(\n function ScrollAreaRoot({ className, ...props }, ref) {\n return (\n <BaseScrollArea.Root\n ref={ref}\n className={cn(\"gryt-scroll-area relative\", className)}\n {...props}\n />\n );\n }\n);\n\n// overscroll-contain so a message list that hits its end does not hand the\n// scroll to the page behind it.\nconst Viewport = forwardRef<HTMLDivElement, ScrollAreaViewportProps>(\n function ScrollAreaViewport({ className, ...props }, ref) {\n return (\n <BaseScrollArea.Viewport\n ref={ref}\n className={cn(\n \"gryt-scroll-area-viewport h-full w-full overscroll-contain\",\n \"focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-gryt-accent-light\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Scrollbar = forwardRef<HTMLDivElement, ScrollAreaScrollbarProps>(\n function ScrollAreaScrollbar({ className, orientation, ...props }, ref) {\n return (\n <BaseScrollArea.Scrollbar\n ref={ref}\n orientation={orientation}\n className={cn(\n \"gryt-scroll-area-scrollbar flex touch-none p-0.5 select-none\",\n // Fades in on hover or while scrolling rather than sitting there\n // permanently — a chat sidebar is mostly not being scrolled.\n \"opacity-0 transition-opacity duration-(--gryt-dur-fast)\",\n \"data-hovering:opacity-100 data-scrolling:opacity-100\",\n \"motion-reduce:transition-none\",\n orientation === \"horizontal\" ? \"h-2 flex-col\" : \"w-2\",\n className\n )}\n {...props}\n >\n <BaseScrollArea.Thumb className=\"flex-1 rounded-(--gryt-radius-full) bg-gryt-border transition-colors hover:bg-gryt-muted motion-reduce:transition-none\" />\n </BaseScrollArea.Scrollbar>\n );\n }\n);\n\nexport const ScrollArea = {\n Root,\n Viewport,\n Scrollbar,\n Content: BaseScrollArea.Content,\n Corner: BaseScrollArea.Corner\n};\n","import { Toggle as BaseToggle } from \"@base-ui/react/toggle\";\nimport { ToggleGroup as BaseToggleGroup } from \"@base-ui/react/toggle-group\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { disabledState, focusRing } from \"../utils/styles\";\n\ntype ToggleTone = \"primary\" | \"secondary\" | \"neutral\" | \"danger\";\ntype ToggleSize = \"xsmall\" | \"small\" | \"medium\" | \"large\";\n\n// Unpressed reads like IconButton's tinted target; pressed fills. A mute button\n// has to be legible as on or off from across the room, so the two states differ\n// in fill rather than only in colour.\nconst toneStyles: Record<ToggleTone, string> = {\n primary: [\n \"text-gryt-muted hover:not-data-disabled:bg-white/8\",\n \"data-pressed:bg-gryt-accent data-pressed:text-gryt-on-accent\",\n \"data-pressed:hover:not-data-disabled:bg-gryt-accent\"\n ].join(\" \"),\n secondary: [\n \"text-gryt-muted hover:not-data-disabled:bg-white/8\",\n \"data-pressed:bg-gryt-secondary data-pressed:text-gryt-on-secondary\",\n \"data-pressed:hover:not-data-disabled:bg-gryt-secondary\"\n ].join(\" \"),\n neutral: [\n \"text-gryt-muted hover:not-data-disabled:bg-white/8\",\n \"data-pressed:bg-gryt-surface-hover data-pressed:text-gryt-text\"\n ].join(\" \"),\n // For destructive-while-active controls: mic muted, camera off.\n danger: [\n \"text-gryt-muted hover:not-data-disabled:bg-white/8\",\n \"data-pressed:bg-gryt-danger data-pressed:text-gryt-on-danger\",\n \"data-pressed:hover:not-data-disabled:bg-gryt-danger\"\n ].join(\" \")\n};\n\nconst sizeStyles: Record<ToggleSize, string> = {\n xsmall: \"h-8 min-w-8 px-2 text-xs\",\n small: \"h-9 min-w-9 px-2.5 text-sm\",\n medium: \"h-10 min-w-10 px-3 text-sm\",\n large: \"h-12 min-w-12 px-4 text-base\"\n};\n\nexport interface ToggleProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseToggle>, \"className\"> {\n tone?: ToggleTone;\n size?: ToggleSize;\n className?: string;\n}\n\nexport const Toggle = forwardRef<HTMLButtonElement, ToggleProps>(\n function Toggle(\n { className, size = \"medium\", tone = \"primary\", ...props },\n ref\n ) {\n return (\n <BaseToggle\n ref={ref}\n className={cn(\n \"gryt-toggle\",\n \"inline-flex shrink-0 items-center justify-center gap-2 border-0 bg-transparent\",\n \"rounded-(--gryt-radius-full) font-medium select-none\",\n // scale rather than transform — see the note in Button.\n \"transition-[scale,background-color,color] duration-(--gryt-dur-spring) ease-spring\",\n \"motion-safe:hover:not-data-disabled:scale-[1.06]\",\n \"motion-safe:active:not-data-disabled:scale-[0.94]\",\n focusRing,\n disabledState,\n sizeStyles[size],\n toneStyles[tone],\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport interface ToggleGroupProps\n extends Omit<ComponentPropsWithoutRef<typeof BaseToggleGroup>, \"className\"> {\n className?: string;\n}\n\n// A rail around a set of Toggles. Base UI handles roving focus, so arrow keys\n// move between items and only one tab stop enters the group.\nexport const ToggleGroup = forwardRef<HTMLDivElement, ToggleGroupProps>(\n function ToggleGroup({ className, ...props }, ref) {\n return (\n <BaseToggleGroup\n ref={ref}\n className={cn(\n \"gryt-toggle-group inline-flex items-center gap-1\",\n \"rounded-(--gryt-radius-full) border border-gryt-border bg-gryt-surface p-1\",\n className\n )}\n {...props}\n />\n );\n }\n);\n","/* What a theme is, on this page.\n *\n * The document itself — two sets of neutrals, one or two sets of hues, five\n * radii — belongs to the library now, next to createGrytTheme, because the\n * client reads the same format when somebody pastes a link into it. What is\n * left here is what only an editor needs: the labels beside each field, what\n * each radius step is actually on, and the small helpers this page reaches for.\n *\n * Why the document has that shape is in packages/ui/src/theme/theme.ts. The\n * short version: dark and light neutrals do not derive from each other, and the\n * hues are shared because step 9 is the same colour in both appearances by\n * design.\n */\n\nimport {\n GRYT_HUE_KEYS,\n GRYT_NEUTRAL_KEYS,\n GRYT_RADIUS_KEYS,\n createGrytTheme,\n grytTheme,\n grytThemeHues,\n grytThemeToOptions,\n isHexColor,\n normalizeHexColor\n} from \"@gryt/theme\";\nimport type {\n GrytAppearance,\n GrytHueKey,\n GrytHues,\n GrytNeutralKey,\n GrytNeutrals,\n GrytRadiusKey,\n GrytTheme\n} from \"@gryt/theme\";\nimport type { CSSProperties } from \"react\";\n\nexport type Appearance = GrytAppearance;\nexport type HueKey = GrytHueKey;\nexport type NeutralKey = GrytNeutralKey;\nexport type RadiusKey = GrytRadiusKey;\nexport type HueSet = GrytHues;\nexport type NeutralSet = GrytNeutrals;\nexport type ThemeDraft = GrytTheme;\n\nexport const HUE_KEYS = GRYT_HUE_KEYS;\nexport const NEUTRAL_KEYS = GRYT_NEUTRAL_KEYS;\nexport const RADIUS_KEYS = GRYT_RADIUS_KEYS;\n\nexport { isHexColor as isHex, normalizeHexColor as normalizeHex };\n\n/** Where this appearance's hues live, which is what an edit has to write to. */\nexport type DraftPath =\n | `hue.${HueKey}`\n | `lightHue.${HueKey}`\n | `dark.${NeutralKey}`\n | `light.${NeutralKey}`;\n\nexport const grytDraft: ThemeDraft = grytTheme;\n\nexport function hueSlot(\n draft: ThemeDraft,\n appearance: Appearance\n): \"hue\" | \"lightHue\" {\n return appearance === \"light\" && draft.lightHue !== null ? \"lightHue\" : \"hue\";\n}\n\nexport const huesFor = grytThemeHues;\n\nexport function cloneDraft(draft: ThemeDraft): ThemeDraft {\n return {\n hue: { ...draft.hue },\n lightHue: draft.lightHue === null ? null : { ...draft.lightHue },\n dark: { ...draft.dark },\n light: { ...draft.light },\n radius: { ...draft.radius }\n };\n}\n\n/** The colours createGrytTheme wants, for one appearance. */\nexport function colorsFor(\n draft: ThemeDraft,\n appearance: Appearance\n): Record<string, string> {\n return { ...huesFor(draft, appearance), ...draft[appearance] };\n}\n\n/** The theme itself: CSS custom properties, ready for a style prop. */\nexport function themeStyle(\n draft: ThemeDraft,\n appearance: Appearance\n): CSSProperties {\n return createGrytTheme(grytThemeToOptions(draft, appearance));\n}\n\n/** A generated scale, read back off the built theme rather than regenerated. */\nexport function scaleFrom(theme: CSSProperties, family: string): string[] {\n const vars = theme as unknown as Record<string, string>;\n return Array.from(\n { length: 12 },\n (_, index) => vars[`--gryt-${family}-${index + 1}`]\n );\n}\n\nexport const SCALE_FAMILIES = [\n \"neutral\",\n \"accent\",\n \"secondary\",\n \"success\",\n \"danger\",\n \"warning\"\n] as const;\n\n/** Changes anywhere in the draft, as one string. Cheap memo key. */\nexport function draftSignature(draft: ThemeDraft): string {\n return JSON.stringify(draft);\n}\n\n/** Human labels, used by the editor and by the contrast report alike. */\nexport const HUE_LABELS: Record<HueKey, string> = {\n accent: \"Accent\",\n accentLight: \"Accent, light\",\n secondary: \"Secondary\",\n secondaryLight: \"Secondary, light\",\n success: \"Success\",\n danger: \"Danger\",\n dangerLight: \"Danger, light\",\n warning: \"Warning\",\n onAccent: \"Text on accent\",\n onSecondary: \"Text on secondary\",\n onDanger: \"Text on danger\"\n};\n\nexport const NEUTRAL_LABELS: Record<NeutralKey, string> = {\n bg: \"Page\",\n surface: \"Surface\",\n surfaceRaised: \"Raised surface\",\n surfaceHover: \"Surface, hovered\",\n border: \"Border\",\n muted: \"Muted text\",\n text: \"Text\"\n};\n\nexport const RADIUS_LABELS: Record<RadiusKey, string> = {\n sm: \"Small\",\n md: \"Medium\",\n lg: \"Large\",\n xl: \"Extra large\",\n full: \"Full\"\n};\n\n/** What each radius step is actually on, so the numbers mean something. */\nexport const RADIUS_HINTS: Record<RadiusKey, string> = {\n sm: \"Chips, swatches, small insets\",\n md: \"Menu rows, list items\",\n lg: \"Cards and panels\",\n xl: \"Dialogs, composers, bubbles\",\n full: \"Buttons, fields, avatars\"\n};\n","import { TextField } from \"../TextField/TextField\";\nimport { Warning } from \"@phosphor-icons/react\";\nimport { useId, useState } from \"react\";\nimport { isHex, normalizeHex } from \"./draft\";\n\nexport interface ColorFieldProps {\n label: string;\n value: string;\n onChange: (value: string) => void;\n /** Set when a contrast check blames this colour. */\n warning?: string;\n /** Shown but not editable, for values something else is computing. */\n disabled?: boolean;\n}\n\n/**\n * One anchor: the swatch, and the hex beside it.\n *\n * Two controls for one value, because they are good at different things. The\n * native picker is how you find a colour you cannot name; the text box is how\n * you paste the one your brand already has. The text box only commits when what\n * is in it parses, so typing \"#1a\" halfway through does not repaint the page\n * with black.\n */\nexport function ColorField({\n label,\n value,\n onChange,\n warning,\n disabled = false\n}: ColorFieldProps) {\n const id = useId();\n const [text, setText] = useState(value);\n const [seen, setSeen] = useState(value);\n\n // A preset, a generated theme or a shared link all change the value from\n // outside, and the box has to follow. Adjusted during render rather than in\n // an effect: React re-runs this component before anything paints, so the\n // stale text is never on screen.\n if (value !== seen) {\n setSeen(value);\n setText(value);\n }\n\n function commit(next: string) {\n setText(next);\n if (isHex(next)) onChange(normalizeHex(next));\n }\n\n return (\n <div className=\"min-w-0\">\n <span\n className=\"mb-1 flex items-center gap-1.5 text-xs font-medium text-gryt-muted\"\n id={`${id}-label`}\n >\n <span className=\"truncate\">{label}</span>\n {warning ? (\n <span className=\"inline-flex shrink-0 text-gryt-warning-11\" title={warning}>\n <Warning aria-label={warning} size={13} />\n </span>\n ) : null}\n </span>\n <span className=\"flex items-center gap-2\">\n <input\n aria-label={`${label}, colour picker`}\n className=\"docs-swatch disabled:cursor-not-allowed disabled:opacity-60\"\n disabled={disabled}\n onChange={(event) => commit(event.target.value)}\n type=\"color\"\n value={normalizeHex(value)}\n />\n <TextField\n aria-label={`${label}, hex value`}\n className=\"font-mono\"\n disabled={disabled}\n onBlur={() => setText(value)}\n onChange={(event) => commit(event.target.value)}\n size=\"small\"\n spellCheck={false}\n value={text}\n />\n </span>\n </div>\n );\n}\n","import { Button } from \"../Button/Button\";\nimport { Check, Warning, X } from \"@phosphor-icons/react\";\nimport type { ContrastCheck } from \"./contrast\";\n\nexport interface ContrastReportProps {\n checks: ContrastCheck[];\n /** Absent when nothing is failing. */\n onRepair?: () => void;\n}\n\nconst ICONS = {\n pass: Check,\n tight: Warning,\n fail: X\n};\n\nconst TONES = {\n pass: \"text-gryt-success-11\",\n tight: \"text-gryt-warning-11\",\n fail: \"text-gryt-danger-11\"\n};\n\n/**\n * What the library's own tests would say about this theme.\n *\n * Ratios rather than a verdict, because \"3.9 against 4.5\" tells somebody how\n * far off they are and \"fails\" does not. The repair only moves the colours\n * whose job is to be read — it will not quietly redesign an accent somebody\n * chose on purpose.\n */\nexport function ContrastReport({ checks, onRepair }: ContrastReportProps) {\n const failures = checks.filter(\n (item) => !item.advisory && item.level === \"fail\"\n ).length;\n\n return (\n <section className=\"min-w-0\">\n <header className=\"flex items-center justify-between gap-2 pb-2\">\n <h2 className=\"m-0 text-[11px] font-semibold uppercase tracking-wider text-gryt-muted\">\n Contrast\n </h2>\n {failures > 0 ? (\n <span className=\"text-xs text-gryt-danger-11\">\n {failures} of {checks.length}\n </span>\n ) : (\n <span className=\"text-xs text-gryt-muted\">\n {checks.length} checks pass\n </span>\n )}\n </header>\n\n <ul className=\"m-0 list-none space-y-1 p-0\">\n {checks.map((item) => {\n const state = item.advisory && item.level === \"fail\" ? \"tight\" : item.level;\n const Icon = ICONS[state];\n return (\n <li\n key={item.id}\n className=\"flex items-center justify-between gap-2 text-xs\"\n >\n <span className=\"flex min-w-0 items-center gap-1.5\">\n <Icon aria-hidden=\"true\" className={TONES[state]} size={12} />\n <span className=\"truncate text-gryt-muted\">{item.label}</span>\n </span>\n <span className=\"shrink-0 font-mono text-[11px] text-gryt-muted\">\n <span className={state === \"pass\" ? \"text-gryt-text\" : TONES[state]}>\n {item.ratio.toFixed(1)}\n </span>\n <span aria-hidden=\"true\"> / {item.min}</span>\n <span className=\"sr-only\"> against a minimum of {item.min}</span>\n {/* AAA is not the bar any of these have to clear, so it is a\n note rather than a verdict. Worth showing because it is the\n difference people ask about. */}\n {!item.advisory && item.ratio >= 7 ? (\n <span className=\"pl-1.5 text-[10px] text-gryt-success-11\">AAA</span>\n ) : null}\n </span>\n </li>\n );\n })}\n </ul>\n\n {onRepair ? (\n <div className=\"pt-3\">\n <Button onClick={onRepair} size=\"small\" tone=\"neutral\">\n Fix the text colours\n </Button>\n </div>\n ) : null}\n </section>\n );\n}\n","/**\n * The twelve steps a family generated, under the anchors that generated them.\n *\n * This is the part that makes the page worth building rather than describing.\n * Changing one hex value moves a whole ramp — component backgrounds, hover\n * states, borders, the text step — and seeing that happen is the difference\n * between \"it takes a colour\" and \"it takes a colour and knows what to do with\n * it\".\n */\nexport interface ScaleStripProps {\n label: string;\n steps: string[];\n}\n\nexport function ScaleStrip({ label, steps }: ScaleStripProps) {\n return (\n <div className=\"min-w-0\">\n <span className=\"mb-1 block text-[11px] font-medium tracking-wide text-gryt-muted\">\n {label}\n </span>\n <ol className=\"m-0 flex list-none gap-px overflow-hidden rounded-(--gryt-radius-sm) border border-gryt-border p-0\">\n {steps.map((step, index) => (\n <li\n key={`${label}-${index}`}\n className=\"h-6 min-w-0 flex-1\"\n style={{ backgroundColor: step }}\n title={`${label} ${index + 1} · ${step}`}\n />\n ))}\n </ol>\n </div>\n );\n}\n","/* The checks the library asserts on its own palette, run against yours.\n *\n * packages/ui/src/theme/theme.test.ts fails the build if Gryt's own scales stop\n * carrying text. A theme built here gets no such build, so the same ratios are\n * measured live and reported next to the colour that caused them — the point\n * being to say so while somebody is picking the colour, rather than letting\n * them export something unreadable and find out in their own app.\n *\n * Thresholds are WCAG AA: 4.5 for text, and one advisory below that for a\n * border, which is not text and has no required ratio but does need to be\n * visible at all. AA rather than the 7:1 the library holds its own text step\n * to — several published palettes sit between the two, and calling Catppuccin\n * Latte broken because its text is 6.6:1 rather than 7 would be reporting a\n * preference as a failure.\n */\n\nimport { contrast } from \"@gryt/theme\";\nimport type { CSSProperties } from \"react\";\nimport type { Appearance, DraftPath, ThemeDraft } from \"./draft\";\nimport { hueSlot, huesFor, scaleFrom } from \"./draft\";\n\nexport type CheckLevel = \"pass\" | \"tight\" | \"fail\";\n\nexport interface ContrastCheck {\n id: string;\n label: string;\n foreground: string;\n background: string;\n ratio: number;\n min: number;\n level: CheckLevel;\n /** Advisory checks never read as a failure; they read as \"look at this\". */\n advisory: boolean;\n /** Which editable colours are responsible, so the fields can flag. */\n paths: DraftPath[];\n}\n\nconst HUES = [\n { family: \"accent\", label: \"Accent\" },\n { family: \"secondary\", label: \"Secondary\" },\n { family: \"success\", label: \"Success\" },\n { family: \"danger\", label: \"Danger\" },\n { family: \"warning\", label: \"Warning\" }\n] as const;\n\nfunction level(ratio: number, min: number): CheckLevel {\n if (ratio < min) return \"fail\";\n // Within a tenth of the line. Worth knowing, because a step that only just\n // clears it here will fail the moment somebody nudges the anchor.\n if (ratio < min * 1.1) return \"tight\";\n return \"pass\";\n}\n\nfunction check(\n id: string,\n label: string,\n foreground: string,\n background: string,\n min: number,\n paths: DraftPath[],\n advisory = false\n): ContrastCheck {\n const ratio = contrast(foreground, background);\n return {\n id,\n label,\n foreground,\n background,\n ratio,\n min,\n level: level(ratio, min),\n advisory,\n paths\n };\n}\n\nexport function contrastChecks(\n draft: ThemeDraft,\n theme: CSSProperties,\n appearance: Appearance\n): ContrastCheck[] {\n const neutral = scaleFrom(theme, \"neutral\");\n const page = neutral[0];\n const surface = neutral[1];\n const text = neutral[11];\n const muted = neutral[10];\n const border = neutral[5];\n\n const a = appearance;\n // Which hue set this appearance is reading, so a warning points at the field\n // somebody can actually edit rather than at the one the other half uses.\n const h = hueSlot(draft, appearance);\n const hues = huesFor(draft, appearance);\n const checks: ContrastCheck[] = [\n check(\"text-page\", \"Text on the page\", text, page, 4.5, [\n `${a}.text`,\n `${a}.bg`\n ]),\n check(\"text-surface\", \"Text on a surface\", text, surface, 4.5, [\n `${a}.text`,\n `${a}.surface`\n ]),\n check(\"muted-page\", \"Muted text on the page\", muted, page, 4.5, [\n `${a}.muted`,\n `${a}.bg`\n ]),\n check(\"muted-surface\", \"Muted text on a surface\", muted, surface, 4.5, [\n `${a}.muted`,\n `${a}.surface`\n ])\n ];\n\n for (const { family, label } of HUES) {\n const steps = scaleFrom(theme, family);\n checks.push(\n check(\n `${family}-text`,\n `${label} text on the page`,\n steps[10],\n page,\n 4.5,\n [`${h}.${family}`, `${a}.bg`]\n )\n );\n }\n\n // The filled-button case: the label sits on step 9, and step 9 is whatever\n // hue was picked. This is the check somebody breaks first, because a pale\n // accent looks good in a swatch and takes its dark ink with it.\n const fills = [\n { family: \"accent\", on: \"onAccent\", label: \"Label on a filled button\" },\n { family: \"secondary\", on: \"onSecondary\", label: \"Label on a secondary button\" },\n { family: \"danger\", on: \"onDanger\", label: \"Label on a danger button\" }\n ] as const;\n\n for (const { family, on, label } of fills) {\n checks.push(\n check(`${on}-fill`, label, hues[on], scaleFrom(theme, family)[8], 4.5, [\n `${h}.${on}`,\n `${h}.${family}`\n ])\n );\n }\n\n checks.push(\n check(\n \"border-page\",\n \"Border against the page\",\n border,\n page,\n 1.15,\n [`${a}.border`, `${a}.bg`],\n true\n )\n );\n\n return checks;\n}\n\n/** Every field a failing check blames, for the warning markers on the editor. */\nexport function failingPaths(checks: ContrastCheck[]): Set<DraftPath> {\n const paths = new Set<DraftPath>();\n for (const item of checks) {\n if (item.advisory || item.level !== \"fail\") continue;\n for (const path of item.paths) paths.add(path);\n }\n return paths;\n}\n\nexport function countFailures(checks: ContrastCheck[]): number {\n return checks.filter((item) => !item.advisory && item.level === \"fail\").length;\n}\n","/* Generate a whole theme from nothing, and repair one that has drifted.\n *\n * The useful thing about a random theme is not the randomness. It is that a\n * palette of eighteen colours is a lot to pick by hand before you know whether\n * you like where it is going, and one button that produces a coherent starting\n * point is worth more than an empty set of pickers.\n *\n * Coherent is the whole trick. Random hex values produce noise, so almost\n * nothing here is free: the lightness of every step is fixed at roughly what\n * Gryt's own palette uses, the neutrals are tinted toward the accent's hue\n * rather than picked separately, and the status hues stay in the arcs people\n * read as go, careful and stop. What actually varies is the hue, how far the\n * neutrals lean into it, and the corner radius. That is enough to make two\n * rolls look unrelated while both of them still work.\n */\n\nimport { contrast as ratio, hexToOklch, oklchToHex } from \"@gryt/theme\";\nimport { contrastChecks } from \"./contrast\";\nimport type { Appearance, HueSet, RadiusKey, ThemeDraft } from \"./draft\";\nimport { cloneDraft, themeStyle } from \"./draft\";\n\nfunction rand(min: number, max: number): number {\n return min + Math.random() * (max - min);\n}\n\nfunction pick<T>(values: readonly T[]): T {\n return values[Math.floor(Math.random() * values.length)];\n}\n\nconst RADIUS_FAMILIES: Array<Record<RadiusKey, number>> = [\n { sm: 8, md: 12, lg: 20, xl: 28, full: 999 },\n { sm: 6, md: 8, lg: 14, xl: 18, full: 999 },\n { sm: 4, md: 6, lg: 10, xl: 14, full: 8 },\n { sm: 2, md: 4, lg: 6, xl: 8, full: 4 },\n { sm: 10, md: 16, lg: 24, xl: 32, full: 999 }\n];\n\nexport function generateDraft(): ThemeDraft {\n const hue = rand(0, 360);\n // How far the greys lean into the accent's hue. At 0.4 they read as grey\n // with a cast; at 2 the whole page is obviously tinted, which is what makes\n // a warm theme feel warm rather than \"grey with an orange button\".\n const tint = pick([0.4, 0.8, 1.4, 2.2]);\n // Far enough round the wheel to read as a second colour rather than a shade\n // of the first, and either side so it is not always the same direction.\n const secondaryHue = hue + pick([-1, 1]) * rand(110, 200);\n\n const grey = (l: number, chroma: number, h = hue) =>\n oklchToHex({ l, c: chroma * tint, h });\n\n const bgL = rand(0.15, 0.21);\n const dark = {\n bg: grey(bgL, 0.011),\n surface: grey(bgL + 0.045, 0.014),\n surfaceRaised: grey(bgL + 0.062, 0.016),\n surfaceHover: grey(bgL + 0.125, 0.022),\n border: grey(bgL + 0.125, 0.024),\n muted: grey(rand(0.62, 0.665), 0.008),\n text: grey(rand(0.9, 0.925), 0.008)\n };\n\n // Light is not the dark set inverted. The page is the grey one and the\n // surface above it is white, which is the arrangement the library's light\n // ramp is built around.\n const lightBgL = rand(0.95, 0.968);\n const light = {\n bg: grey(lightBgL, 0.006),\n surface: grey(rand(0.995, 1), 0.001),\n surfaceRaised: grey(lightBgL + 0.016, 0.004),\n surfaceHover: grey(lightBgL - 0.035, 0.01),\n border: grey(rand(0.878, 0.9), 0.014),\n muted: grey(rand(0.46, 0.5), 0.014),\n text: grey(rand(0.23, 0.27), 0.014)\n };\n\n const accent = oklchToHex({ l: rand(0.67, 0.74), c: rand(0.13, 0.17), h: hue });\n const secondary = oklchToHex({\n l: rand(0.79, 0.85),\n c: rand(0.09, 0.13),\n h: secondaryHue\n });\n const danger = oklchToHex({ l: rand(0.67, 0.72), c: rand(0.15, 0.19), h: rand(18, 30) });\n\n const hueSet = {\n accent,\n accentLight: lighten(accent, 0.085),\n secondary,\n secondaryLight: lighten(secondary, 0.07),\n success: oklchToHex({ l: rand(0.8, 0.85), c: rand(0.15, 0.19), h: rand(140, 156) }),\n danger,\n dangerLight: lighten(danger, 0.08),\n warning: oklchToHex({ l: rand(0.82, 0.86), c: rand(0.14, 0.17), h: rand(72, 90) }),\n onAccent: \"\",\n onSecondary: \"\",\n onDanger: \"\"\n };\n\n hueSet.onAccent = readableOn(accent);\n hueSet.onSecondary = readableOn(secondary);\n hueSet.onDanger = readableOn(danger);\n\n return {\n hue: hueSet,\n // Generated themes keep one hue set. Splitting light off is a decision\n // somebody makes about their own palette, not something to roll for them.\n lightHue: null,\n dark,\n light,\n radius: { ...pick(RADIUS_FAMILIES) }\n };\n}\n\n/** Same hue and chroma, further up the lightness ramp. */\nfunction lighten(hex: string, by: number): string {\n const { l, c, h } = hexToOklch(hex);\n return oklchToHex({ l: Math.min(0.97, l + by), c: c * 0.85, h });\n}\n\n/**\n * A label colour for a filled control.\n *\n * Ink or paper, whichever reads better on the fill, tinted toward the fill's\n * own hue so it looks chosen rather than dropped in — black-or-white passes the\n * same checks and looks like a placeholder.\n *\n * Then pushed until it clears 7:1 rather than the 4.5 the checks require. The\n * label on a filled button is the one piece of text in an app that always sits\n * on a saturated colour, it is usually a verb somebody is about to press, and\n * the whole cost of AAA here is a shade of a colour that was already nearly\n * black. Where the fill cannot carry 7 with any label at all — a mid-lightness\n * blue tops out around 6 — this returns the best there is and the report says\n * what it came to.\n */\nexport function readableOn(fill: string): string {\n const { c, h } = hexToOklch(fill);\n const ink = oklchToHex({ l: 0.17, c: Math.min(0.05, c * 0.3), h });\n const paper = oklchToHex({ l: 0.97, c: Math.min(0.03, c * 0.2), h });\n const better = ratio(ink, fill) >= ratio(paper, fill) ? ink : paper;\n return ensureContrast(better, fill, 7);\n}\n\n/** The three label colours, recomputed from the fills they sit on. */\nexport function withAutoLabels(hues: HueSet): HueSet {\n return {\n ...hues,\n onAccent: readableOn(hues.accent),\n onSecondary: readableOn(hues.secondary),\n onDanger: readableOn(hues.danger)\n };\n}\n\n/** Whether a hue set already carries the labels the auto pick would give it. */\nexport function labelsAreAuto(hues: HueSet): boolean {\n const auto = withAutoLabels(hues);\n return (\n auto.onAccent === hues.onAccent &&\n auto.onSecondary === hues.onSecondary &&\n auto.onDanger === hues.onDanger\n );\n}\n\n/**\n * Push a colour away from its background until it carries text.\n *\n * Lightness only. Moving the hue would change which colour it is, and moving\n * chroma barely moves contrast at all — lightness is the axis that decides\n * whether something is readable.\n */\nexport function ensureContrast(\n foreground: string,\n background: string,\n min: number\n): string {\n if (ratio(foreground, background) >= min) return foreground;\n\n const { l, c, h } = hexToOklch(foreground);\n const direction = l >= hexToOklch(background).l ? 1 : -1;\n\n let next = l;\n for (let step = 0; step < 120; step++) {\n next = Math.min(1, Math.max(0, next + direction * 0.008));\n const candidate = oklchToHex({ l: next, c, h });\n if (ratio(candidate, background) >= min) return candidate;\n if (next === 0 || next === 1) break;\n }\n // Ran out of ramp: black or white is the best this hue can do.\n return direction === 1 ? \"#ffffff\" : \"#000000\";\n}\n\n/**\n * Fix what the contrast report is complaining about, without redesigning the\n * theme.\n *\n * Only the colours whose job is to be read get moved — text, muted text, and\n * the labels on filled controls. The anchors somebody actually chose, the\n * background and the accent, are left exactly where they are: a repair that\n * changed the accent would be answering a question nobody asked.\n */\nexport function repairDraft(draft: ThemeDraft): ThemeDraft {\n const next = cloneDraft(draft);\n\n for (const appearance of [\"dark\", \"light\"] as const) {\n next[appearance].text = ensureContrast(\n next[appearance].text,\n next[appearance].bg,\n 7\n );\n next[appearance].text = ensureContrast(\n next[appearance].text,\n next[appearance].surface,\n 7\n );\n next[appearance].muted = ensureContrast(\n next[appearance].muted,\n next[appearance].bg,\n 4.5\n );\n next[appearance].muted = ensureContrast(\n next[appearance].muted,\n next[appearance].surface,\n 4.5\n );\n }\n\n for (const hues of [next.hue, next.lightHue]) {\n if (hues === null) continue;\n for (const [on, family] of [\n [\"onAccent\", \"accent\"],\n [\"onSecondary\", \"secondary\"],\n [\"onDanger\", \"danger\"]\n ] as const) {\n const fill = hues[family];\n // 7 rather than 4.5, to match what the automatic pick aims for. A repair\n // that left the label at \"just about legible\" would have to be run again\n // the moment somebody turned the automatic pick on.\n if (ratio(hues[on], fill) < 7) hues[on] = readableOn(fill);\n }\n }\n\n return next;\n}\n\n/** Whether a repair would change anything, so the button can say so. */\nexport function needsRepair(draft: ThemeDraft): boolean {\n return ([\"dark\", \"light\"] as const).some((appearance: Appearance) =>\n contrastChecks(draft, themeStyle(draft, appearance), appearance).some(\n (item) => !item.advisory && item.level === \"fail\"\n )\n );\n}\n","/* Getting a theme out of the page, and back into it.\n *\n * The link and the JSON are the library's format now — the client reads the\n * same one — so encoding and parsing live there and this file is what the page\n * puts around them: the createGrytTheme call somebody pastes into an app, and\n * the error strings for a paste that did not work out.\n *\n * Three ways out, because they answer three different questions. The\n * createGrytTheme call is what you paste into an app. The JSON is what you keep\n * or hand to someone else's tooling. The link is what you send in a message,\n * and it is the one people will actually use.\n */\n\nimport {\n decodeGrytTheme,\n encodeGrytTheme,\n grytLightTokens,\n grytTokens,\n normalizeHexColor\n} from \"@gryt/theme\";\nimport { RADIUS_KEYS, colorsFor } from \"./draft\";\nimport type { Appearance, RadiusKey, ThemeDraft } from \"./draft\";\n\nexport { encodeGrytTheme as encodeDraft, decodeGrytTheme };\n\n/** The library's own values for one appearance, which is what \"default\" means. */\nfunction defaultsFor(appearance: Appearance): Record<string, string> {\n return appearance === \"light\"\n ? { ...grytTokens.color, ...grytLightTokens }\n : { ...grytTokens.color };\n}\n\n/** Only what this theme changes. An export full of unchanged values is noise. */\nfunction changedColors(\n draft: ThemeDraft,\n appearance: Appearance\n): Array<[string, string]> {\n const defaults = defaultsFor(appearance);\n return Object.entries(colorsFor(draft, appearance)).filter(\n ([key, value]) =>\n normalizeHexColor(value) !== normalizeHexColor(defaults[key] ?? \"\")\n );\n}\n\nfunction changedRadius(draft: ThemeDraft): Array<[RadiusKey, number]> {\n return RADIUS_KEYS.filter(\n (key) => draft.radius[key] !== grytTokens.radius[key]\n ).map((key) => [key, draft.radius[key]] as [RadiusKey, number]);\n}\n\nfunction optionsLiteral(draft: ThemeDraft, appearance: Appearance): string {\n const lines: string[] = [];\n if (appearance === \"light\") lines.push(` appearance: \"light\",`);\n\n const colors = changedColors(draft, appearance);\n if (colors.length > 0) {\n lines.push(\" color: {\");\n colors.forEach(([key, value], index) => {\n const comma = index === colors.length - 1 ? \"\" : \",\";\n lines.push(` ${key}: \"${normalizeHexColor(value)}\"${comma}`);\n });\n lines.push(\" },\");\n }\n\n const radius = changedRadius(draft);\n if (radius.length > 0) {\n lines.push(\n ` radius: { ${radius.map(([key, value]) => `${key}: ${value}`).join(\", \")} }`\n );\n }\n\n // Trailing comma off whichever line turned out to be the last.\n const last = lines.length - 1;\n if (last >= 0) lines[last] = lines[last].replace(/,$/, \"\");\n\n return lines.length === 0 ? \"\" : `{\\n${lines.join(\"\\n\")}\\n}`;\n}\n\nexport function themeCode(draft: ThemeDraft): string {\n const dark = optionsLiteral(draft, \"dark\");\n const light = optionsLiteral(draft, \"light\");\n\n return `import { createGrytTheme, GrytProvider } from \"@gryt/ui\";\n\n// One call per appearance. The scales are regenerated from these anchors, so\n// every component moves with them — not just the tokens named here.\nconst dark = createGrytTheme(${dark});\n\nconst light = createGrytTheme(${light});\n\nexport function App({ appearance }: { appearance: \"dark\" | \"light\" }) {\n return (\n <GrytProvider theme={appearance === \"light\" ? light : dark}>\n {/* your app */}\n </GrytProvider>\n );\n}`;\n}\n\n/** The whole draft, spelled out. What import reads back. */\nexport function themeJson(draft: ThemeDraft): string {\n return JSON.stringify(draft, null, 2);\n}\n\nexport interface ImportResult {\n draft?: ThemeDraft;\n appearance?: Appearance;\n error?: string;\n}\n\n/**\n * Takes either of the two things somebody will paste: the JSON this page\n * exports, or a link it produced.\n */\nexport function importTheme(input: string): ImportResult {\n const text = input.trim();\n if (text === \"\") return { error: \"Nothing to import.\" };\n\n const decoded = decodeGrytTheme(text);\n if (decoded === null) {\n return {\n error: text.startsWith(\"{\")\n ? \"No theme in that JSON.\"\n : \"No theme in that link.\"\n };\n }\n return { draft: decoded.theme, appearance: decoded.appearance };\n}\n","/* The theme controls, as a component rather than as a page.\n *\n * These lived in the docs site, which made the docs site the only place a\n * theme could be built. That is the wrong way round: what somebody wants to\n * know is whether a colour survives a member list, a voice tile and a mention,\n * and none of those are on a documentation page. The client needs the same\n * controls over the top of the real app, and two copies of a thousand lines\n * drift the moment one of them is touched.\n *\n * So it ships here, next to the components it is editing, and both mount the\n * same one — the argument the presets file already makes for itself.\n *\n * What is deliberately not in here:\n *\n * - **The preview.** In the docs it is a panel of specimens; in the client it\n * is the client. Neither belongs to the editor.\n * - **The address bar.** The docs page writes the theme into the query string\n * so the link in the bar is the link you paste. There is no bar in a desktop\n * app, so copying is a slot the host fills.\n * - **Export as code.** Rendering `createGrytTheme` needs a syntax\n * highlighter, which is a docs dependency and not something to drag into a\n * component library. `footer` is where that goes.\n *\n * Import stays, because pasting a link somebody sent you is the other half of\n * sharing one and it needs nothing but the decoder.\n */\nimport type { GrytAppearance } from \"@gryt/theme\";\nimport { GRYT_THEME_NAME_MAX, grytPresets, grytPresetsById } from \"@gryt/theme\";\nimport { ArrowsClockwise } from \"@phosphor-icons/react\";\nimport { useMemo, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Button } from \"../Button/Button\";\nimport { Checkbox } from \"../Checkbox/Checkbox\";\nimport { Select } from \"../Select/Select\";\nimport { Slider } from \"../Slider/Slider\";\nimport { TextField } from \"../TextField/TextField\";\nimport { Toggle, ToggleGroup } from \"../Toggle/Toggle\";\nimport { cn } from \"../utils/cn\";\nimport { ColorField } from \"./ColorField\";\nimport { ContrastReport } from \"./ContrastReport\";\nimport { ScaleStrip } from \"./ScaleStrip\";\nimport { contrastChecks } from \"./contrast\";\nimport {\n HUE_LABELS,\n NEUTRAL_LABELS,\n RADIUS_HINTS,\n RADIUS_KEYS,\n RADIUS_LABELS,\n draftSignature,\n hueSlot,\n huesFor,\n scaleFrom,\n themeStyle\n} from \"./draft\";\nimport type {\n DraftPath,\n HueKey,\n NeutralKey,\n RadiusKey,\n ThemeDraft\n} from \"./draft\";\nimport { generateDraft, labelsAreAuto, repairDraft, withAutoLabels } from \"./generate\";\nimport { importTheme } from \"./share\";\n\n/**\n * How far each radius slider travels.\n *\n * `full` is the odd one: the token is 999px, and a slider that ran to 999 would\n * put every value anybody wants inside the first four percent of the track. So\n * it travels to 40 and the far end means pill, which is the only thing past 40\n * that anyone picks.\n */\nconst RADIUS_MAX: Record<RadiusKey, number> = {\n sm: 24,\n md: 32,\n lg: 48,\n xl: 64,\n full: 40\n};\nconst PILL = 999;\n\nconst SURFACE_KEYS: NeutralKey[] = [\n \"bg\",\n \"surface\",\n \"surfaceRaised\",\n \"surfaceHover\",\n \"border\"\n];\nconst TEXT_KEYS: NeutralKey[] = [\"text\", \"muted\"];\n\nexport interface ThemeEditorProps {\n /** The theme being edited. Controlled, so the host can preview it. */\n value: ThemeDraft;\n onChange: (next: ThemeDraft) => void;\n /**\n * Which half is on the bench.\n *\n * The host's, not the editor's: editing the light half while the app around\n * it is dark would be looking at two themes at once.\n */\n appearance: GrytAppearance;\n onAppearanceChange: (next: GrytAppearance) => void;\n /** End of the header row. Where a host puts its own copy or save control. */\n actions?: ReactNode;\n /** Under the controls. Where the docs site puts the export tabs. */\n footer?: ReactNode;\n className?: string;\n}\n\nexport function ThemeEditor({\n value: draft,\n onChange,\n appearance,\n onAppearanceChange,\n actions,\n footer,\n className\n}: ThemeEditorProps) {\n /**\n * Whether the label colours follow their fills.\n *\n * On by default, because picking the ink for a filled button by hand is a\n * job with one right answer and it is the answer people get wrong — the\n * library's own accent shipped at 6.7:1 for a year. It turns itself off when\n * a theme arrives carrying labels somebody else chose, which is every ported\n * preset: overwriting Dracula's ink would make it not Dracula.\n */\n const [autoLabels, setAutoLabels] = useState(\n () =>\n labelsAreAuto(draft.hue) &&\n (draft.lightHue === null || labelsAreAuto(draft.lightHue))\n );\n\n /**\n * A theme the editor did not produce is a theme somebody else chose.\n *\n * The host can replace `value` at any time — a shared link on arrival, a\n * preset picked somewhere else in the app — and when it does, the automatic\n * labels have to be reconsidered exactly as they are for a preset picked in\n * here. Without this, opening a link to Dracula and then touching one slider\n * would quietly rewrite its ink.\n */\n // State rather than a ref, because this is read while rendering and a ref\n // read during render is a lie about when it was written.\n const [emitted, setEmitted] = useState<ThemeDraft | null>(null);\n if (emitted !== null && emitted !== draft) {\n setEmitted(null);\n const auto =\n labelsAreAuto(draft.hue) &&\n (draft.lightHue === null || labelsAreAuto(draft.lightHue));\n if (auto !== autoLabels) setAutoLabels(auto);\n }\n\n const [importText, setImportText] = useState(\"\");\n const [importError, setImportError] = useState<string | null>(null);\n\n const theme = useMemo(() => themeStyle(draft, appearance), [draft, appearance]);\n const checks = useMemo(\n () => contrastChecks(draft, theme, appearance),\n [draft, theme, appearance]\n );\n const warnings = useMemo(() => {\n const map = new Map<DraftPath, string>();\n for (const item of checks) {\n if (item.advisory || item.level !== \"fail\") continue;\n for (const path of item.paths) {\n if (!map.has(path)) {\n map.set(path, `${item.label}: ${item.ratio.toFixed(1)}, needs ${item.min}`);\n }\n }\n }\n return map;\n }, [checks]);\n\n const signature = draftSignature(draft);\n const activePreset =\n grytPresets.find((preset) => draftSignature(preset.theme) === signature)?.id ??\n \"custom\";\n\n const neutrals = draft[appearance];\n const slot = hueSlot(draft, appearance);\n const hues = huesFor(draft, appearance);\n const failures = checks.filter(\n (item) => !item.advisory && item.level === \"fail\"\n ).length;\n\n function emit(next: ThemeDraft) {\n setEmitted(next);\n onChange(next);\n }\n\n /** Every edit goes through here, so the automatic labels cannot be bypassed. */\n function commit(change: (current: ThemeDraft) => ThemeDraft) {\n const next = change(draft);\n emit(\n autoLabels\n ? {\n ...next,\n hue: withAutoLabels(next.hue),\n lightHue:\n next.lightHue === null ? null : withAutoLabels(next.lightHue)\n }\n : next\n );\n }\n\n /** A whole theme from elsewhere: a preset, a link, a paste. */\n function adopt(next: ThemeDraft) {\n setAutoLabels(\n labelsAreAuto(next.hue) &&\n (next.lightHue === null || labelsAreAuto(next.lightHue))\n );\n emit(next);\n }\n\n function setHue(key: HueKey, value: string) {\n commit((current) => {\n const target = hueSlot(current, appearance);\n return {\n ...current,\n [target]: { ...huesFor(current, appearance), [key]: value }\n };\n });\n }\n\n /**\n * Give light its own hues, or take them away again.\n *\n * Off is the library's own arrangement and the right default: a filled\n * button that changes colour when somebody flips appearance is usually a\n * mistake. On is for palettes where it is not — Catppuccin and GitHub both\n * publish a different accent per half, and forcing one on them would make\n * the preset wrong in one of the two.\n */\n function toggleSplit(split: boolean) {\n commit((current) => ({\n ...current,\n lightHue: split ? { ...current.hue } : null\n }));\n }\n\n /** Turning it on repairs what is there; turning it off leaves it as it is. */\n function toggleAutoLabels(auto: boolean) {\n setAutoLabels(auto);\n if (!auto) return;\n emit({\n ...draft,\n hue: withAutoLabels(draft.hue),\n lightHue: draft.lightHue === null ? null : withAutoLabels(draft.lightHue)\n });\n }\n\n function setNeutral(key: NeutralKey, value: string) {\n commit((current) => ({\n ...current,\n [appearance]: { ...current[appearance], [key]: value }\n }));\n }\n\n function setName(value: string) {\n // Kept as typed and tidied on the way out, so a trailing space while\n // somebody is still typing does not disappear under the cursor.\n commit((current) => ({ ...current, name: value === \"\" ? undefined : value }));\n }\n\n function setRadius(key: RadiusKey, value: number) {\n commit((current) => ({\n ...current,\n radius: { ...current.radius, [key]: value }\n }));\n }\n\n function load(text: string) {\n const result = importTheme(text);\n if (result.error !== undefined || result.draft === undefined) {\n setImportError(result.error ?? \"That did not look like a theme.\");\n return;\n }\n adopt(result.draft);\n if (result.appearance !== undefined) onAppearanceChange(result.appearance);\n setImportError(null);\n setImportText(\"\");\n }\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-(--space-md)\", className)}>\n <div className=\"flex flex-wrap items-end gap-3 border-y border-gryt-border py-3\">\n <div className=\"w-52\">\n <Select\n label=\"Preset\"\n onValueChange={(value) => {\n const preset = grytPresetsById.get(String(value));\n if (preset) adopt(preset.theme);\n }}\n options={[\n ...grytPresets.map((preset) => ({\n label: preset.name,\n value: preset.id\n })),\n ...(activePreset === \"custom\"\n ? [{ label: \"Custom\", value: \"custom\" }]\n : [])\n ]}\n size=\"small\"\n value={activePreset}\n />\n </div>\n\n {/* Named here rather than by whoever receives it. The name rides in\n the link, so a theme arrives at the client already called\n something, and the person importing it is not asked a question its\n author already answered. */}\n <div className=\"w-48\">\n <TextField\n label=\"Name\"\n maxLength={GRYT_THEME_NAME_MAX}\n onChange={(event) => setName(event.target.value)}\n placeholder=\"Untitled theme\"\n size=\"small\"\n value={draft.name ?? \"\"}\n />\n </div>\n\n <Button onClick={() => adopt(generateDraft())} size=\"small\" tone=\"neutral\">\n <ArrowsClockwise aria-hidden=\"true\" size={15} />\n Generate\n </Button>\n\n <div className=\"ml-auto flex items-end gap-3\">\n <ToggleGroup\n aria-label=\"Appearance\"\n // Last one wins, and an empty array is a click on the one already\n // pressed — which should leave the appearance alone rather than\n // switch to neither.\n onValueChange={(value: string[]) => {\n const next = value[value.length - 1];\n if (next === \"dark\" || next === \"light\") onAppearanceChange(next);\n }}\n value={[appearance]}\n >\n <Toggle size=\"small\" value=\"dark\">\n Dark\n </Toggle>\n <Toggle size=\"small\" value=\"light\">\n Light\n </Toggle>\n </ToggleGroup>\n {actions}\n </div>\n </div>\n\n <p className=\"m-0 text-xs text-gryt-muted\">\n Editing the {appearance} half. The neutrals below belong to it\n {draft.lightHue === null\n ? \"; the hues are shared, because step 9 is the same colour in both.\"\n : \" and so do the hues.\"}\n </p>\n\n <div className=\"flex flex-col gap-2\">\n {appearance === \"light\" ? (\n <label className=\"flex cursor-pointer items-center gap-2 text-xs text-gryt-muted\">\n <Checkbox\n checked={draft.lightHue !== null}\n onCheckedChange={toggleSplit}\n />\n Light has its own hues\n </label>\n ) : null}\n <label className=\"flex cursor-pointer items-center gap-2 text-xs text-gryt-muted\">\n <Checkbox checked={autoLabels} onCheckedChange={toggleAutoLabels} />\n Pick label colours automatically\n </label>\n </div>\n\n <div className=\"flex flex-col gap-(--space-md)\">\n <Group title=\"Surfaces\">\n {SURFACE_KEYS.map((key) => (\n <ColorField\n key={key}\n label={NEUTRAL_LABELS[key]}\n onChange={(value) => setNeutral(key, value)}\n value={neutrals[key]}\n warning={warnings.get(`${appearance}.${key}`)}\n />\n ))}\n <ScaleStrip label=\"neutral\" steps={scaleFrom(theme, \"neutral\")} />\n </Group>\n\n <Group title=\"Text\">\n {TEXT_KEYS.map((key) => (\n <ColorField\n key={key}\n label={NEUTRAL_LABELS[key]}\n onChange={(value) => setNeutral(key, value)}\n value={neutrals[key]}\n warning={warnings.get(`${appearance}.${key}`)}\n />\n ))}\n </Group>\n\n <Group title=\"Accent\">\n {([\"accent\", \"accentLight\", \"onAccent\"] as HueKey[]).map((key) => (\n <ColorField\n key={key}\n disabled={autoLabels && key === \"onAccent\"}\n label={HUE_LABELS[key]}\n onChange={(value) => setHue(key, value)}\n value={hues[key]}\n warning={warnings.get(`${slot}.${key}`)}\n />\n ))}\n <ScaleStrip label=\"accent\" steps={scaleFrom(theme, \"accent\")} />\n </Group>\n\n <Group title=\"Secondary\">\n {([\"secondary\", \"secondaryLight\", \"onSecondary\"] as HueKey[]).map(\n (key) => (\n <ColorField\n key={key}\n disabled={autoLabels && key === \"onSecondary\"}\n label={HUE_LABELS[key]}\n onChange={(value) => setHue(key, value)}\n value={hues[key]}\n warning={warnings.get(`${slot}.${key}`)}\n />\n )\n )}\n <ScaleStrip label=\"secondary\" steps={scaleFrom(theme, \"secondary\")} />\n </Group>\n\n <Group title=\"Status\">\n {(\n [\n \"success\",\n \"danger\",\n \"dangerLight\",\n \"onDanger\",\n \"warning\"\n ] as HueKey[]\n ).map((key) => (\n <ColorField\n key={key}\n disabled={autoLabels && key === \"onDanger\"}\n label={HUE_LABELS[key]}\n onChange={(value) => setHue(key, value)}\n value={hues[key]}\n warning={warnings.get(`${slot}.${key}`)}\n />\n ))}\n <ScaleStrip label=\"success\" steps={scaleFrom(theme, \"success\")} />\n <ScaleStrip label=\"danger\" steps={scaleFrom(theme, \"danger\")} />\n <ScaleStrip label=\"warning\" steps={scaleFrom(theme, \"warning\")} />\n </Group>\n\n <Group title=\"Radius\">\n {RADIUS_KEYS.map((key) => {\n const value = draft.radius[key];\n const position =\n key === \"full\" && value >= PILL ? RADIUS_MAX.full : value;\n return (\n <div key={key} className=\"min-w-0\">\n <div className=\"mb-1 flex items-baseline justify-between gap-2\">\n <span className=\"text-xs font-medium text-gryt-muted\">\n {RADIUS_LABELS[key]}\n </span>\n <span className=\"font-mono text-[11px] text-gryt-muted\">\n {value >= PILL ? \"pill\" : `${value}px`}\n </span>\n </div>\n <Slider\n aria-label={`${RADIUS_LABELS[key]} radius`}\n max={RADIUS_MAX[key]}\n min={0}\n onValueChange={(next) => {\n const number = Number(next);\n setRadius(\n key,\n key === \"full\" && number >= RADIUS_MAX.full ? PILL : number\n );\n }}\n value={Math.min(position, RADIUS_MAX[key])}\n />\n <p className=\"m-0 pt-1 text-[11px] text-gryt-muted\">\n {RADIUS_HINTS[key]}\n </p>\n </div>\n );\n })}\n </Group>\n\n <ContrastReport\n checks={checks}\n onRepair={failures > 0 ? () => emit(repairDraft(draft)) : undefined}\n />\n\n <section className=\"min-w-0\">\n <h2 className=\"m-0 pb-2 text-[11px] font-semibold uppercase tracking-wider text-gryt-muted\">\n Load one back\n </h2>\n <p className=\"m-0 pb-2 text-sm text-gryt-muted\">\n Paste a theme’s JSON, or a link somebody sent you.\n </p>\n <div className=\"flex flex-col gap-2 sm:flex-row\">\n <textarea\n aria-label=\"Theme JSON or a shared link\"\n className=\"min-h-11 flex-1 rounded-(--gryt-radius-xl) border border-gryt-border bg-gryt-surface-raised px-4 py-2.5 font-mono text-sm text-gryt-text outline-none placeholder:text-gryt-muted focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gryt-accent-light\"\n onChange={(event) => setImportText(event.target.value)}\n placeholder=\"{ …\"\n rows={2}\n spellCheck={false}\n value={importText}\n />\n <Button onClick={() => load(importText)} tone=\"neutral\">\n Load\n </Button>\n </div>\n {importError ? (\n <p className=\"m-0 pt-2 text-sm text-gryt-danger-11\">{importError}</p>\n ) : null}\n </section>\n\n {footer}\n </div>\n </div>\n );\n}\n\nfunction Group({ title, children }: { title: string; children: ReactNode }) {\n return (\n <section className=\"min-w-0\">\n <h2 className=\"m-0 pb-2 text-[11px] font-semibold uppercase tracking-wider text-gryt-muted\">\n {title}\n </h2>\n <div className=\"flex flex-col gap-3\">{children}</div>\n </section>\n );\n}\n","import { Meter as BaseMeter } from \"@base-ui/react/meter\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type MeterTone = \"primary\" | \"success\" | \"warning\" | \"danger\";\n\nconst toneFill: Record<MeterTone, string> = {\n primary: \"bg-gryt-accent\",\n success: \"bg-gryt-success\",\n warning: \"bg-gryt-warning\",\n danger: \"bg-gryt-danger\"\n};\n\nexport interface MeterProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseMeter.Root>,\n \"className\" | \"value\"\n > {\n value: number;\n label?: ReactNode;\n /** Show the formatted value at the end of the label row. */\n showValue?: boolean;\n tone?: MeterTone;\n className?: string;\n}\n\n/**\n * A measurement inside a known range — mic input level, disk used, how full a\n * server is.\n *\n * Deliberately not Progress. Progress says \"this task is 40% done and heading\n * for 100%\"; a meter says \"this is the reading right now\", and a reading at\n * 100% is often the bad case rather than the finished one. They also announce\n * differently to a screen reader, which is the part that actually matters.\n *\n * The indicator moves rather than snapping, but only just — 120ms and ease-out,\n * no spring. This used to have no transition at all, on the grounds that the\n * common caller is a mic level updating every animation frame and easing a\n * value that changes 60 times a second only makes it lag behind the sound.\n * That reasoning holds for the mic and nothing else: disk used, server\n * capacity, a level polled a few times a second all read as broken when they\n * teleport. 120ms is shorter than the gap between polls at 4Hz, so a fast feed\n * still lands on every value it is handed.\n */\nexport function Meter({\n className,\n value,\n label,\n showValue = false,\n tone = \"primary\",\n ...props\n}: MeterProps) {\n return (\n <BaseMeter.Root\n value={value}\n className={cn(\"gryt-meter flex w-full flex-col gap-1.5\", className)}\n {...props}\n >\n {(label || showValue) && (\n <div className=\"flex items-baseline justify-between gap-2\">\n {label ? (\n <BaseMeter.Label className=\"text-sm text-gryt-muted\">\n {label}\n </BaseMeter.Label>\n ) : (\n <span />\n )}\n {showValue && (\n <BaseMeter.Value className=\"font-mono text-xs text-gryt-muted tabular-nums\" />\n )}\n </div>\n )}\n <BaseMeter.Track className=\"h-1.5 w-full overflow-hidden rounded-(--gryt-radius-full) bg-gryt-surface-raised\">\n {/* Short and linear-ish, so the bar moves rather than snapping.\n The note above says no transition, and that was written for a mic\n level updating every frame — easing a value that changes 60 times a\n second only makes it lag. But most meters are not that: disk used,\n how full a server is, a level polled a few times a second, and those\n all read as broken when they teleport. 120ms is under the gap\n between polls at 4Hz, so a fast feed still lands on every value it\n is given; it just gets there over two frames instead of one. */}\n <BaseMeter.Indicator\n className={cn(\n \"h-full rounded-(--gryt-radius-full)\",\n \"transition-[width] duration-120 ease-out motion-reduce:transition-none\",\n toneFill[tone]\n )}\n />\n </BaseMeter.Track>\n </BaseMeter.Root>\n );\n}\n","import { AlertDialog as BaseAlertDialog } from \"@base-ui/react/alert-dialog\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type AlertDialogPopupProps = ComponentPropsWithoutRef<\n typeof BaseAlertDialog.Popup\n>;\n\n/**\n * A dialog you cannot dismiss by accident — for \"Leave this server?\".\n *\n * Styled identically to Dialog on purpose; the difference is behaviour, not\n * looks. Escape and clicking the backdrop do nothing here, so answering\n * requires picking one of the buttons. Using this where Dialog belongs is worse\n * than not having it, because it takes away the escape people expect.\n */\nconst Popup = forwardRef<HTMLDivElement, AlertDialogPopupProps>(\n function AlertDialogPopup({ className, ...props }, ref) {\n return (\n <BaseAlertDialog.Popup\n ref={ref}\n className={cn(\n \"gryt-alert-dialog fixed top-1/2 left-1/2 z-50 -translate-x-1/2 -translate-y-1/2\",\n \"flex w-[32rem] max-w-[calc(100vw-3rem)] flex-col gap-4\",\n \"rounded-(--gryt-radius-lg) border border-gryt-border bg-gryt-surface p-5 text-gryt-text\",\n \"outline-none\",\n \"transition-[opacity,scale] duration-(--gryt-dur-spring) ease-spring motion-reduce:transition-none\",\n \"data-starting-style:scale-[0.98] data-starting-style:opacity-0\",\n \"data-ending-style:scale-[0.98] data-ending-style:opacity-0\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Backdrop = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseAlertDialog.Backdrop>\n>(function AlertDialogBackdrop({ className, ...props }, ref) {\n return (\n <BaseAlertDialog.Backdrop\n ref={ref}\n className={cn(\n \"gryt-alert-dialog-backdrop fixed inset-0 z-50 min-h-dvh bg-black/60\",\n \"backdrop-blur-(--gryt-backdrop-blur)\",\n \"transition-opacity duration-(--gryt-dur-spring) ease-spring motion-reduce:transition-none\",\n \"data-starting-style:opacity-0 data-ending-style:opacity-0\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Title = forwardRef<\n HTMLHeadingElement,\n ComponentPropsWithoutRef<typeof BaseAlertDialog.Title>\n>(function AlertDialogTitle({ className, ...props }, ref) {\n return (\n <BaseAlertDialog.Title\n ref={ref}\n className={cn(\n \"gryt-alert-dialog-title text-lg font-semibold text-gryt-text\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Description = forwardRef<\n HTMLParagraphElement,\n ComponentPropsWithoutRef<typeof BaseAlertDialog.Description>\n>(function AlertDialogDescription({ className, ...props }, ref) {\n return (\n <BaseAlertDialog.Description\n ref={ref}\n className={cn(\n \"gryt-alert-dialog-description text-sm leading-6 text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport const AlertDialog = {\n Root: BaseAlertDialog.Root,\n Trigger: BaseAlertDialog.Trigger,\n Portal: BaseAlertDialog.Portal,\n Backdrop,\n Popup,\n Title,\n Description,\n Close: BaseAlertDialog.Close\n};\n","import { Combobox as BaseCombobox } from \"@base-ui/react/combobox\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport {\n fieldControl,\n fieldSizes,\n focusRing,\n popupMotion,\n popupSurface\n} from \"../utils/styles\";\n\n/**\n * Shared with Autocomplete, which is the same list wearing different\n * semantics. Exported so the two cannot drift, the way ContextMenu shares\n * Menu's item.\n */\nexport const listboxItemClass = [\n \"flex cursor-default items-center gap-2 rounded-(--gryt-radius-md)\",\n \"px-3 py-2 text-sm text-gryt-text outline-none select-none\",\n // Base UI drives keyboard and pointer highlight through one attribute, so\n // arrow keys and the mouse land on identical styling.\n \"data-highlighted:bg-gryt-surface-raised\",\n \"data-selected:text-gryt-accent-11\",\n \"data-disabled:cursor-not-allowed data-disabled:opacity-50\"\n].join(\" \");\n\n/**\n * The typeahead input on both Combobox and Autocomplete.\n *\n * This is TextField's control, through the same shared constant, so the three\n * places you can type in this library are the same shape. It used to be its own\n * class list asking for `rounded-(--gryt-radius-input)` — a token that has never\n * existed — so it rendered with square corners next to a fully rounded\n * TextField.\n */\nexport const listboxInputClass = [\n fieldControl,\n fieldSizes.medium,\n \"border-gryt-border\",\n focusRing\n].join(\" \");\n\nexport type ComboboxPopupProps = ComponentPropsWithoutRef<\n typeof BaseCombobox.Popup\n>;\n\nconst Input = forwardRef<\n HTMLInputElement,\n ComponentPropsWithoutRef<typeof BaseCombobox.Input>\n>(function ComboboxInput({ className, ...props }, ref) {\n return (\n <BaseCombobox.Input\n ref={ref}\n className={cn(\"gryt-combobox-input\", listboxInputClass, className)}\n {...props}\n />\n );\n});\n\nconst Positioner = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseCombobox.Positioner>\n>(function ComboboxPositioner({ className, sideOffset = 6, ...props }, ref) {\n return (\n <BaseCombobox.Positioner\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\"gryt-combobox-positioner outline-none\", className)}\n {...props}\n />\n );\n});\n\nconst Popup = forwardRef<HTMLDivElement, ComboboxPopupProps>(\n function ComboboxPopup({ className, ...props }, ref) {\n return (\n <BaseCombobox.Popup\n ref={ref}\n className={cn(\n \"gryt-combobox max-h-64 w-(--anchor-width) overflow-y-auto overscroll-contain p-1 outline-none\",\n popupSurface,\n popupMotion,\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Item = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseCombobox.Item>\n>(function ComboboxItem({ className, ...props }, ref) {\n return (\n <BaseCombobox.Item\n ref={ref}\n className={cn(\"gryt-combobox-item\", listboxItemClass, className)}\n {...props}\n />\n );\n});\n\nconst Empty = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseCombobox.Empty>\n>(function ComboboxEmpty({ className, ...props }, ref) {\n return (\n <BaseCombobox.Empty\n ref={ref}\n className={cn(\n \"gryt-combobox-empty px-3 py-2 text-sm text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n});\n\n/**\n * Pick from a list, narrowed by typing. Select with a filter, in effect.\n *\n * Supports multiple selection with chips, which is what a member picker or a\n * role assignment wants. Use Autocomplete instead when the value is free text\n * and the list is only a suggestion.\n */\nexport const Combobox = {\n Root: BaseCombobox.Root,\n Input,\n InputGroup: BaseCombobox.InputGroup,\n Trigger: BaseCombobox.Trigger,\n Icon: BaseCombobox.Icon,\n Clear: BaseCombobox.Clear,\n Value: BaseCombobox.Value,\n Chips: BaseCombobox.Chips,\n Chip: BaseCombobox.Chip,\n ChipRemove: BaseCombobox.ChipRemove,\n Portal: BaseCombobox.Portal,\n Positioner,\n Popup,\n List: BaseCombobox.List,\n Item,\n ItemIndicator: BaseCombobox.ItemIndicator,\n Group: BaseCombobox.Group,\n GroupLabel: BaseCombobox.GroupLabel,\n Empty,\n Separator: BaseCombobox.Separator\n};\n","import { Autocomplete as BaseAutocomplete } from \"@base-ui/react/autocomplete\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { listboxInputClass, listboxItemClass } from \"../Combobox/Combobox\";\nimport { popupMotion, popupSurface } from \"../utils/styles\";\n\n/**\n * A text input that suggests as you type.\n *\n * The difference from Combobox is what the value is allowed to be: here the\n * typed text is the answer and the list is a suggestion, so a search box or a\n * tag input belongs here. Combobox is for when the value must come from the\n * list. They share item and input styling deliberately — two lists that look\n * different for no reason is worse than one that looks the same.\n */\n\nconst Input = forwardRef<\n HTMLInputElement,\n ComponentPropsWithoutRef<typeof BaseAutocomplete.Input>\n>(function AutocompleteInput({ className, ...props }, ref) {\n return (\n <BaseAutocomplete.Input\n ref={ref}\n className={cn(\"gryt-autocomplete-input\", listboxInputClass, className)}\n {...props}\n />\n );\n});\n\nconst Positioner = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseAutocomplete.Positioner>\n>(function AutocompletePositioner({ className, sideOffset = 6, ...props }, ref) {\n return (\n <BaseAutocomplete.Positioner\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\"gryt-autocomplete-positioner outline-none\", className)}\n {...props}\n />\n );\n});\n\nconst Popup = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseAutocomplete.Popup>\n>(function AutocompletePopup({ className, ...props }, ref) {\n return (\n <BaseAutocomplete.Popup\n ref={ref}\n className={cn(\n \"gryt-autocomplete max-h-64 w-(--anchor-width) overflow-y-auto overscroll-contain p-1 outline-none\",\n popupSurface,\n popupMotion,\n className\n )}\n {...props}\n />\n );\n});\n\nconst Item = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseAutocomplete.Item>\n>(function AutocompleteItem({ className, ...props }, ref) {\n return (\n <BaseAutocomplete.Item\n ref={ref}\n className={cn(\"gryt-autocomplete-item\", listboxItemClass, className)}\n {...props}\n />\n );\n});\n\nconst Empty = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseAutocomplete.Empty>\n>(function AutocompleteEmpty({ className, ...props }, ref) {\n return (\n <BaseAutocomplete.Empty\n ref={ref}\n className={cn(\n \"gryt-autocomplete-empty px-3 py-2 text-sm text-gryt-muted\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport const Autocomplete = {\n Root: BaseAutocomplete.Root,\n Input,\n InputGroup: BaseAutocomplete.InputGroup,\n Trigger: BaseAutocomplete.Trigger,\n Icon: BaseAutocomplete.Icon,\n Clear: BaseAutocomplete.Clear,\n Value: BaseAutocomplete.Value,\n Portal: BaseAutocomplete.Portal,\n Positioner,\n Popup,\n List: BaseAutocomplete.List,\n Item,\n Group: BaseAutocomplete.Group,\n GroupLabel: BaseAutocomplete.GroupLabel,\n Empty,\n Separator: BaseAutocomplete.Separator\n};\n","import { CheckboxGroup as BaseCheckboxGroup } from \"@base-ui/react/checkbox-group\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type CheckboxGroupProps = ComponentPropsWithoutRef<\n typeof BaseCheckboxGroup\n>;\n\n/**\n * A set of checkboxes sharing one value array.\n *\n * Worth having over a hand-rolled array of Checkboxes for the parent case: give\n * it `allValues` and a checkbox marked `parent` becomes a working\n * indeterminate tri-state, which is fiddly to get right by hand and is exactly\n * what a permissions list needs.\n */\nexport const CheckboxGroup = forwardRef<HTMLDivElement, CheckboxGroupProps>(\n function CheckboxGroup({ className, ...props }, ref) {\n return (\n <BaseCheckboxGroup\n ref={ref}\n className={cn(\"gryt-checkbox-group flex flex-col gap-2\", className)}\n {...props}\n />\n );\n }\n);\n","import { Collapsible as BaseCollapsible } from \"@base-ui/react/collapsible\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing } from \"../utils/styles\";\n\nexport type CollapsibleTriggerProps = ComponentPropsWithoutRef<\n typeof BaseCollapsible.Trigger\n>;\nexport type CollapsiblePanelProps = ComponentPropsWithoutRef<\n typeof BaseCollapsible.Panel\n>;\n\n/**\n * One region that opens and closes — a channel category, an advanced section.\n *\n * Accordion is a set of these that know about each other. Reach for this when\n * there is only one, so nothing has to pretend to be a one-item accordion.\n */\nconst Trigger = forwardRef<HTMLButtonElement, CollapsibleTriggerProps>(\n function CollapsibleTrigger({ className, ...props }, ref) {\n return (\n <BaseCollapsible.Trigger\n ref={ref}\n className={cn(\n \"gryt-collapsible-trigger flex w-full items-center justify-between gap-2\",\n \"rounded-(--gryt-radius-md) border-0 bg-transparent px-2 py-2 text-left\",\n \"text-sm font-medium text-gryt-text select-none\",\n \"transition-colors hover:bg-gryt-surface-raised motion-reduce:transition-none\",\n focusRing,\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Panel = forwardRef<HTMLDivElement, CollapsiblePanelProps>(\n function CollapsiblePanel({ className, ...props }, ref) {\n return (\n <BaseCollapsible.Panel\n ref={ref}\n className={cn(\n \"gryt-collapsible-panel overflow-hidden\",\n // Base UI measures the panel and exposes the height as a variable, so\n // this animates to the content's real height rather than to a guess.\n \"h-(--collapsible-panel-height) transition-[height] duration-(--gryt-dur-spring) ease-spring\",\n \"data-starting-style:h-0 data-ending-style:h-0\",\n \"motion-reduce:transition-none\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport const Collapsible = {\n Root: BaseCollapsible.Root,\n Trigger,\n Panel\n};\n","import { Form as BaseForm } from \"@base-ui/react/form\";\nimport { Fieldset as BaseFieldset } from \"@base-ui/react/fieldset\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type FormProps = ComponentPropsWithoutRef<typeof BaseForm>;\n\n/**\n * Wires server-side errors back to the fields that caused them.\n *\n * Pass `errors` keyed by field name and Base UI routes each message to the\n * matching Field, so a rejected form points at the input rather than printing a\n * paragraph at the top that the user has to map back themselves.\n */\nexport const Form = forwardRef<HTMLFormElement, FormProps>(function Form(\n { className, ...props },\n ref\n) {\n return (\n <BaseForm\n ref={ref}\n className={cn(\"gryt-form flex flex-col gap-(--gryt-space-lg)\", className)}\n {...props}\n />\n );\n});\n\nexport type FieldsetProps = ComponentPropsWithoutRef<typeof BaseFieldset.Root>;\n\nconst FieldsetRoot = forwardRef<HTMLFieldSetElement, FieldsetProps>(\n function Fieldset({ className, ...props }, ref) {\n return (\n <BaseFieldset.Root\n ref={ref}\n className={cn(\n \"gryt-fieldset flex min-w-0 flex-col gap-3 border-0 p-0\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\nconst Legend = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseFieldset.Legend>\n>(function FieldsetLegend({ className, ...props }, ref) {\n return (\n <BaseFieldset.Legend\n ref={ref}\n className={cn(\n \"gryt-fieldset-legend text-sm font-semibold text-gryt-text\",\n className\n )}\n {...props}\n />\n );\n});\n\nexport const Fieldset = { Root: FieldsetRoot, Legend };\n","import { Menubar as BaseMenubar } from \"@base-ui/react/menubar\";\nimport { NavigationMenu as BaseNavigationMenu } from \"@base-ui/react/navigation-menu\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing, popupMotion, popupSurface } from \"../utils/styles\";\n\n/**\n * A bar of menus that behave as one — File, Edit, View.\n *\n * Once any menu is open, moving along the bar opens the next without a second\n * click, which is the behaviour that separates a menubar from several\n * independent Menus sitting next to each other.\n */\nexport type MenubarProps = ComponentPropsWithoutRef<typeof BaseMenubar>;\n\nexport const Menubar = forwardRef<HTMLDivElement, MenubarProps>(\n function Menubar({ className, ...props }, ref) {\n return (\n <BaseMenubar\n ref={ref}\n className={cn(\n \"gryt-menubar flex items-center gap-1\",\n \"rounded-(--gryt-radius-md) border border-gryt-border bg-gryt-surface p-1\",\n className\n )}\n {...props}\n />\n );\n }\n);\n\n/**\n * Site-level navigation whose items open panels.\n *\n * Distinct from Menubar: the items are links first and the panels can hold\n * layout — a column of sections, a promo — rather than a list of commands. The\n * viewport animates between panels so moving along the bar resizes rather than\n * closing and reopening.\n */\nconst Trigger = forwardRef<\n HTMLButtonElement,\n ComponentPropsWithoutRef<typeof BaseNavigationMenu.Trigger>\n>(function NavigationMenuTrigger({ className, ...props }, ref) {\n return (\n <BaseNavigationMenu.Trigger\n ref={ref}\n className={cn(\n \"gryt-navigation-menu-trigger flex items-center gap-1.5 rounded-(--gryt-radius-md)\",\n \"border-0 bg-transparent px-3 py-2 text-sm font-medium text-gryt-text select-none\",\n \"transition-colors hover:bg-gryt-surface-raised motion-reduce:transition-none\",\n \"data-popup-open:bg-gryt-surface-raised\",\n focusRing,\n className\n )}\n {...props}\n />\n );\n});\n\nconst Popup = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseNavigationMenu.Popup>\n>(function NavigationMenuPopup({ className, ...props }, ref) {\n return (\n <BaseNavigationMenu.Popup\n ref={ref}\n className={cn(\n \"gryt-navigation-menu-popup outline-none\",\n popupSurface,\n popupMotion,\n className\n )}\n {...props}\n />\n );\n});\n\n// Wrapped rather than re-exported raw, so it carries a class the app can hang a\n// z-index on. Every other popup in here already has one; this was the last\n// positioner without, and a consumer cannot style what it cannot select.\nconst Positioner = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseNavigationMenu.Positioner>\n>(function NavigationMenuPositioner({ className, ...props }, ref) {\n return (\n <BaseNavigationMenu.Positioner\n ref={ref}\n className={cn(\"gryt-navigation-menu-positioner outline-none\", className)}\n {...props}\n />\n );\n});\n\nconst Viewport = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseNavigationMenu.Viewport>\n>(function NavigationMenuViewport({ className, ...props }, ref) {\n return (\n <BaseNavigationMenu.Viewport\n ref={ref}\n className={cn(\n \"gryt-navigation-menu-viewport relative overflow-hidden\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Link = forwardRef<\n HTMLAnchorElement,\n ComponentPropsWithoutRef<typeof BaseNavigationMenu.Link>\n>(function NavigationMenuLink({ className, ...props }, ref) {\n return (\n <BaseNavigationMenu.Link\n ref={ref}\n className={cn(\n \"gryt-navigation-menu-link block rounded-(--gryt-radius-md) px-3 py-2\",\n \"text-sm text-gryt-text no-underline outline-none\",\n \"transition-colors hover:bg-gryt-surface-raised motion-reduce:transition-none\",\n focusRing,\n className\n )}\n {...props}\n />\n );\n});\n\nexport const NavigationMenu = {\n Root: BaseNavigationMenu.Root,\n List: BaseNavigationMenu.List,\n Item: BaseNavigationMenu.Item,\n Trigger,\n Content: BaseNavigationMenu.Content,\n Portal: BaseNavigationMenu.Portal,\n Positioner,\n Viewport,\n Popup,\n Link,\n Icon: BaseNavigationMenu.Icon,\n Arrow: BaseNavigationMenu.Arrow\n};\n","import { NumberField as BaseNumberField } from \"@base-ui/react/number-field\";\nimport { Minus, Plus } from \"@phosphor-icons/react\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { disabledState, focusRing } from \"../utils/styles\";\n\nexport interface NumberFieldProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseNumberField.Root>,\n \"className\"\n > {\n label?: ReactNode;\n className?: string;\n /**\n * Drag the label sideways to change the value.\n *\n * Base UI calls this a scrub area, and it is the reason to use this over a\n * plain input for things like volume or bitrate — coarse adjustment by drag,\n * exact entry by typing, without two controls.\n */\n scrubbable?: boolean;\n}\n\nconst stepButton =\n \"flex h-9 w-9 shrink-0 items-center justify-center border-0 bg-transparent text-gryt-muted transition-colors hover:not-data-disabled:bg-white/8 hover:not-data-disabled:text-gryt-text motion-reduce:transition-none disabled:cursor-not-allowed disabled:opacity-50\";\n\nexport const NumberField = forwardRef<HTMLDivElement, NumberFieldProps>(\n function NumberField(\n { className, label, scrubbable = false, ...props },\n ref\n ) {\n return (\n <BaseNumberField.Root\n ref={ref}\n className={cn(\"gryt-number-field flex flex-col gap-1.5\", className)}\n {...props}\n >\n {label &&\n (scrubbable ? (\n <BaseNumberField.ScrubArea className=\"cursor-ew-resize text-sm text-gryt-muted select-none\">\n {label}\n <BaseNumberField.ScrubAreaCursor />\n </BaseNumberField.ScrubArea>\n ) : (\n <span className=\"text-sm text-gryt-muted\">{label}</span>\n ))}\n <BaseNumberField.Group\n className={cn(\n \"flex w-fit items-center overflow-hidden rounded-(--gryt-radius-full)\",\n \"border border-gryt-border bg-gryt-surface-raised\",\n \"focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-gryt-accent-light\",\n disabledState\n )}\n >\n <BaseNumberField.Decrement\n aria-label=\"Decrease\"\n className={cn(stepButton, \"rounded-l-(--gryt-radius-full)\")}\n >\n <Minus size={14} weight=\"bold\" />\n </BaseNumberField.Decrement>\n <BaseNumberField.Input\n className={cn(\n \"w-16 border-0 bg-transparent px-1 py-2 text-center\",\n \"font-mono text-sm text-gryt-text tabular-nums outline-none\",\n focusRing\n )}\n />\n <BaseNumberField.Increment\n aria-label=\"Increase\"\n className={cn(stepButton, \"rounded-r-(--gryt-radius-full)\")}\n >\n <Plus size={14} weight=\"bold\" />\n </BaseNumberField.Increment>\n </BaseNumberField.Group>\n </BaseNumberField.Root>\n );\n }\n);\n","import { OTPField as BaseOtpField } from \"@base-ui/react/otp-field\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { focusRing } from \"../utils/styles\";\n\nexport interface OtpFieldProps\n extends Omit<\n ComponentPropsWithoutRef<typeof BaseOtpField.Root>,\n \"className\" | \"length\"\n > {\n /** How many characters the code has. Required by Base UI; defaulted here. */\n length?: number;\n className?: string;\n}\n\n/**\n * A one-time code, one box per character.\n *\n * Base UI handles the parts that are tedious and easy to get wrong: paste a\n * whole code into any box and it distributes across all of them, backspace\n * steps back a box, and the arrow keys move between them.\n */\nexport const OtpField = forwardRef<HTMLDivElement, OtpFieldProps>(\n function OtpField({ className, length = 6, ...props }, ref) {\n return (\n <BaseOtpField.Root\n ref={ref}\n length={length}\n className={cn(\"gryt-otp-field flex gap-2\", className)}\n {...props}\n >\n {/* No index prop: Base UI assigns each input its slot by render order\n and exposes the index through state. */}\n {Array.from({ length }, (_unused, index) => (\n <BaseOtpField.Input\n key={index}\n className={cn(\n \"gryt-otp-input h-12 w-10 rounded-(--gryt-radius-md) text-center\",\n \"border border-gryt-border bg-gryt-surface-raised\",\n \"font-mono text-lg text-gryt-text tabular-nums outline-none\",\n \"transition-colors duration-(--gryt-dur-fast) motion-reduce:transition-none\",\n \"data-filled:border-gryt-accent\",\n focusRing\n )}\n />\n ))}\n </BaseOtpField.Root>\n );\n }\n);\n","import { PreviewCard as BasePreviewCard } from \"@base-ui/react/preview-card\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { popupMotion, popupSurface } from \"../utils/styles\";\n\nexport type PreviewCardPopupProps = ComponentPropsWithoutRef<\n typeof BasePreviewCard.Popup\n>;\nexport type PreviewCardPositionerProps = ComponentPropsWithoutRef<\n typeof BasePreviewCard.Positioner\n>;\n\n/**\n * What appears when you hover a username.\n *\n * Not a Tooltip and not a Popover. A tooltip labels a control and opens\n * instantly; this holds real content, so it waits before opening and stays put\n * long enough to move the pointer into it. Popover is the click-to-open\n * equivalent — reach for that when the panel has controls, since content that\n * only appears on hover is unreachable from a keyboard or a touchscreen.\n */\nconst Positioner = forwardRef<HTMLDivElement, PreviewCardPositionerProps>(\n function PreviewCardPositioner({ className, sideOffset = 8, ...props }, ref) {\n return (\n <BasePreviewCard.Positioner\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\"gryt-preview-card-positioner outline-none\", className)}\n {...props}\n />\n );\n }\n);\n\nconst Popup = forwardRef<HTMLDivElement, PreviewCardPopupProps>(\n function PreviewCardPopup({ className, ...props }, ref) {\n return (\n <BasePreviewCard.Popup\n ref={ref}\n className={cn(\n \"gryt-preview-card w-64 max-w-[calc(100vw-2rem)] p-4 outline-none\",\n popupSurface,\n popupMotion,\n className\n )}\n {...props}\n />\n );\n }\n);\n\nexport const PreviewCard = {\n Root: BasePreviewCard.Root,\n Trigger: BasePreviewCard.Trigger,\n Portal: BasePreviewCard.Portal,\n Positioner,\n Popup,\n Arrow: BasePreviewCard.Arrow\n};\n","import { Toolbar as BaseToolbar } from \"@base-ui/react/toolbar\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type ToolbarRootProps = ComponentPropsWithoutRef<\n typeof BaseToolbar.Root\n>;\n\n/**\n * A strip of controls that share one tab stop.\n *\n * The point is the keyboard model: Tab enters the toolbar once and the arrow\n * keys move between its buttons, so a call bar with eight controls costs one\n * stop on the way to the message box instead of eight.\n */\nconst Root = forwardRef<HTMLDivElement, ToolbarRootProps>(function Toolbar(\n { className, ...props },\n ref\n) {\n return (\n <BaseToolbar.Root\n ref={ref}\n className={cn(\n \"gryt-toolbar flex items-center gap-1\",\n \"rounded-(--gryt-radius-full) border border-gryt-border bg-gryt-surface p-1\",\n className\n )}\n {...props}\n />\n );\n});\n\nconst Separator = forwardRef<\n HTMLDivElement,\n ComponentPropsWithoutRef<typeof BaseToolbar.Separator>\n>(function ToolbarSeparator({ className, ...props }, ref) {\n return (\n <BaseToolbar.Separator\n ref={ref}\n className={cn(\"gryt-toolbar-separator mx-1 h-6 w-px bg-gryt-border\", className)}\n {...props}\n />\n );\n});\n\nexport const Toolbar = {\n Root,\n Group: BaseToolbar.Group,\n Button: BaseToolbar.Button,\n Link: BaseToolbar.Link,\n Input: BaseToolbar.Input,\n Separator\n};\n"],"names":["PortalContainerContext","createContext","usePortalContainer","useContext","isCssVariables","value","key","GrytProvider","children","className","theme","tooltipDelay","containOverlays","containerRef","useRef","style","createGrytTheme","jsx","Tooltip","cn","inputs","twMerge","clsx","toneStyles","sizeStyles","Button","forwardRef","endIcon","size","startIcon","tone","props","ref","jsxs","BaseButton","focusRing","focusRingWithin","fieldControl","fieldSizes","popupSurface","popupMotion","disabledState","toneCheckedFill","toneBg","toneCheckedBorder","toneCheckedBg","IconButton","Surface","elevated","MessageBubble","from","TextField","error","fieldClassName","helperText","label","minRows","multiline","control","Field","Composer","disabled","maxRows","onSubmit","placeholder","submitLabel","innerRef","resize","useCallback","node","styles","lineHeight","vertical","useLayoutEffect","handleSubmit","event","PaperPlaneTilt","OWL_SIZE","Avatar","alt","fallback","seed","eggSeed","src","owl","useMemo","owlAvatarDataUri","egg","eggAvatarDataUri","generated","BaseAvatar","ConversationItem","active","avatar","subtitle","title","Badge","badgeContent","max","showZero","numeric","hidden","display","Chip","icon","onDelete","X","Checkbox","BaseCheckbox","Check","Radio","BaseRadio","RadioGroup","BaseRadioGroup","Switch","BaseSwitch","DRAG_SLOP","Slider","ariaLabel","dragging","setDragging","useState","origin","useEffect","end","handlePointerDown","handlePointerMove","start","travel","BaseSlider","Select","options","portalContainer","BaseSelect","CaretUpDown","option","side","sideOffset","BaseTooltip","TooltipProvider","Divider","orientation","Separator","Card","CardHeader","subheader","CardContent","CardActions","severityStyles","Alert","severity","Progress","BaseProgress","Spinner","CircleNotch","variantStyles","Skeleton","height","variant","width","sizing","motion","Backdrop","BaseDialog","Popup","Title","Description","Footer","Dialog","noop","useMediaQuery","query","subscribe","onChange","list","getSnapshot","useSyncExternalStore","swipeBySide","SideContext","viewportBySide","radiusBySide","popupBySide","Root","sheetOnMobile","isMobile","resolved","BaseDrawer","Viewport","Grabber","Drawer","Positioner","BaseMenu","Item","Menu","BaseTabs","List","Tab","Indicator","Panel","Tabs","BaseAccordion","Trigger","expandIcon","CaretDown","Accordion","BaseContextMenu","ContextMenu","BasePopover","Popover","BaseToast","Close","Action","Toast","useToastManager","BaseScrollArea","Scrollbar","ScrollArea","Toggle","BaseToggle","ToggleGroup","BaseToggleGroup","RADIUS_KEYS","GRYT_RADIUS_KEYS","grytDraft","grytTheme","hueSlot","draft","appearance","huesFor","grytThemeHues","cloneDraft","colorsFor","themeStyle","grytThemeToOptions","scaleFrom","family","vars","_","index","draftSignature","HUE_LABELS","NEUTRAL_LABELS","RADIUS_LABELS","RADIUS_HINTS","ColorField","warning","id","useId","text","setText","seen","setSeen","commit","next","isHex","normalizeHex","Warning","ICONS","TONES","ContrastReport","checks","onRepair","failures","item","state","Icon","ScaleStrip","steps","step","HUES","level","ratio","min","check","foreground","background","paths","advisory","contrast","contrastChecks","neutral","page","surface","muted","border","a","h","hues","fills","on","rand","pick","values","RADIUS_FAMILIES","generateDraft","hue","tint","secondaryHue","grey","l","chroma","oklchToHex","bgL","dark","lightBgL","light","accent","secondary","danger","hueSet","lighten","readableOn","hex","by","c","hexToOklch","fill","ink","paper","better","ensureContrast","withAutoLabels","labelsAreAuto","auto","direction","candidate","repairDraft","defaultsFor","grytTokens","grytLightTokens","changedColors","defaults","normalizeHexColor","changedRadius","optionsLiteral","lines","colors","comma","radius","last","themeCode","themeJson","importTheme","input","decoded","decodeGrytTheme","RADIUS_MAX","PILL","SURFACE_KEYS","TEXT_KEYS","ThemeEditor","onAppearanceChange","actions","footer","autoLabels","setAutoLabels","emitted","setEmitted","importText","setImportText","importError","setImportError","warnings","map","path","signature","activePreset","grytPresets","preset","neutrals","slot","emit","change","adopt","setHue","current","target","toggleSplit","split","toggleAutoLabels","setNeutral","setName","setRadius","load","result","grytPresetsById","GRYT_THEME_NAME_MAX","ArrowsClockwise","Group","position","number","toneFill","Meter","showValue","BaseMeter","BaseAlertDialog","AlertDialog","listboxItemClass","listboxInputClass","Input","BaseCombobox","Empty","Combobox","BaseAutocomplete","Autocomplete","CheckboxGroup","BaseCheckboxGroup","BaseCollapsible","Collapsible","Form","BaseForm","FieldsetRoot","BaseFieldset","Legend","Fieldset","Menubar","BaseMenubar","BaseNavigationMenu","Link","NavigationMenu","stepButton","NumberField","scrubbable","BaseNumberField","Minus","Plus","OtpField","length","BaseOtpField","_unused","BasePreviewCard","PreviewCard","BaseToolbar","Toolbar"],"mappings":"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"}
|