import { useContainer } from '@tldraw/editor' import classNames from 'classnames' import { Select as _Select } from 'radix-ui' import * as React from 'react' import { useMenuIsOpen } from '../../hooks/useMenuIsOpen' import { useDirection } from '../../hooks/useTranslation/useTranslation' import { TLUiIconType } from '../../icon-types' import { TldrawUiIcon } from './TldrawUiIcon' /* --------------------- Root --------------------- */ /** @public */ export interface TLUiSelectProps { id: string value: string onValueChange(value: string): void onOpenChange?(isOpen: boolean): void disabled?: boolean className?: string children: React.ReactNode 'data-testid'?: string 'aria-label'?: string } /** * A select dropdown component. * * @example * ```tsx * * * * * * * * * * ``` * * @public * @react */ export function TldrawUiSelect({ id, value, onValueChange, onOpenChange, disabled, className, children, 'data-testid': dataTestId, 'aria-label': ariaLabel, }: TLUiSelectProps) { const [open, handleOpenChange] = useMenuIsOpen(id, onOpenChange) const dir = useDirection() return ( <_Select.Root value={value} onValueChange={onValueChange} onOpenChange={handleOpenChange} open={open} disabled={disabled} dir={dir} >
{children}
) } /* --------------------- Trigger --------------------- */ /** @public */ export interface TLUiSelectTriggerProps { children: React.ReactNode className?: string } /** * The trigger button for the select dropdown. * * @public * @react */ export const TldrawUiSelectTrigger = React.forwardRef( function TldrawUiSelectTrigger({ children, className }, ref) { return ( <_Select.Trigger ref={ref} className={classNames('tlui-button tlui-select__trigger', className)} > {children} <_Select.Icon className="tlui-select__chevron"> ) } ) /* --------------------- Value --------------------- */ /** @public */ export interface TLUiSelectValueProps { placeholder?: string icon?: TLUiIconType | Exclude children?: React.ReactNode } /** * Displays the currently selected value in the trigger. * * @public * @react */ export function TldrawUiSelectValue({ placeholder, icon, children }: TLUiSelectValueProps) { return ( <_Select.Value placeholder={placeholder}> {icon && } {children} ) } /* --------------------- Content --------------------- */ /** @public */ export interface TLUiSelectContentProps { children: React.ReactNode side?: 'top' | 'bottom' align?: 'start' | 'center' | 'end' className?: string } /** * The dropdown content container for select items. * * @public * @react */ export function TldrawUiSelectContent({ children, side = 'bottom', align = 'start', className, }: TLUiSelectContentProps) { const container = useContainer() return ( <_Select.Portal container={container}> <_Select.Content className={classNames('tlui-menu tlui-select__content', className)} position="popper" side={side} align={align} sideOffset={4} collisionPadding={4} > <_Select.Viewport className="tlui-select__viewport">{children} ) } /* --------------------- Item --------------------- */ /** @public */ export interface TLUiSelectItemProps { value: string label: string icon?: TLUiIconType | Exclude disabled?: boolean className?: string } /** * An item in the select dropdown. Styled to match TldrawUiMenuCheckboxItem. * * @public * @react */ export function TldrawUiSelectItem({ value, label, icon, disabled, className, }: TLUiSelectItemProps) { return ( <_Select.Item value={value} disabled={disabled} className={classNames( 'tlui-button tlui-button__menu tlui-button__checkbox tlui-select__item', className )} > {icon && } <_Select.ItemText className="tlui-button__label">{label} ) }