{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "select",
  "type": "registry:ui",
  "title": "Select",
  "description": "Custom select dropdown for Tile UI.",
  "dependencies": [
    "react-dom"
  ],
  "devDependencies": [
    "sass"
  ],
  "registryDependencies": [
    "@tile-ui/core",
    "@tile-ui/portal",
    "@tile-ui/styles"
  ],
  "files": [
    {
      "path": "packages/react/src/components/select/select.tsx",
      "type": "registry:ui",
      "target": "components/ui/select/select.tsx",
      "content": "import React, { createContext, useCallback, useContext, useEffect, useId, useLayoutEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { getSelectCheckState, getSelectPosition, getSelectState, selectStyleKeys } from '../lib/core';\nimport type { SelectBaseProps, SelectContentBaseProps, SelectItemBaseProps, SelectPositionResult, SelectTriggerBaseProps } from '../lib/core';\nimport { usePortalContainer, type PortalContainer } from '../portal';\nimport styles from './select.module.scss';\n\ninterface SelectContextValue {\n\topen: boolean;\n\tsetOpen: (open: boolean) => void;\n\tvalue: string | undefined;\n\tsetValue: (value: string) => void;\n\ttriggerRef: React.RefObject<HTMLButtonElement | null>;\n\tcontentId: string;\n\titemTexts: Record<string, string>;\n\tregisterItemText: (value: string, text: string) => void;\n}\n\nconst SelectContext = createContext<SelectContextValue | null>(null);\n\nfunction useSelectContext(): SelectContextValue {\n\tconst context = useContext(SelectContext);\n\tif (!context) {\n\t\tthrow new Error('Select 子组件必须位于 <Select> 内部。');\n\t}\n\treturn context;\n}\n\ninterface SelectContentContextValue {\n\titemsRef: React.RefObject<HTMLElement[]>;\n\tclose: () => void;\n}\n\nconst SelectContentContext = createContext<SelectContentContextValue | null>(null);\n\nfunction useSelectContentContext(): SelectContentContextValue {\n\tconst context = useContext(SelectContentContext);\n\tif (!context) {\n\t\tthrow new Error('SelectItem 必须位于 <SelectContent> 内部。');\n\t}\n\treturn context;\n}\n\nfunction SelectCheckIcon() {\n\treturn (\n\t\t<svg\n\t\t\tclassName={styles[selectStyleKeys.checkIcon]}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\">\n\t\t\t<path d=\"M20 6 9 17l-5-5\" />\n\t\t</svg>\n\t);\n}\n\nfunction SelectChevronIcon() {\n\treturn (\n\t\t<svg\n\t\t\tclassName={styles[selectStyleKeys.chevron]}\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\twidth=\"16\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 24 24\"\n\t\t\tfill=\"none\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"2\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t\tstrokeLinejoin=\"round\"\n\t\t\taria-hidden=\"true\">\n\t\t\t<path d=\"m6 9 6 6 6-6\" />\n\t\t</svg>\n\t);\n}\n\nexport interface SelectProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'defaultValue'>, SelectBaseProps {}\n\nconst Select = React.forwardRef<HTMLDivElement, SelectProps>(\n\t({ className = '', open, defaultOpen = false, onOpenChange, value, defaultValue, onValueChange, children, ...props }, ref) => {\n\t\tconst [internalOpen, setInternalOpen] = useState(defaultOpen);\n\t\tconst isOpen = open !== undefined ? open : internalOpen;\n\n\t\tconst [internalValue, setInternalValue] = useState(defaultValue);\n\t\tconst resolvedValue = value !== undefined ? value : internalValue;\n\n\t\tconst triggerRef = useRef<HTMLButtonElement | null>(null);\n\t\tconst contentId = useId();\n\t\tconst [itemTexts, setItemTexts] = useState<Record<string, string>>({});\n\n\t\tconst setOpen = useCallback(\n\t\t\t(next: boolean) => {\n\t\t\t\tif (open === undefined) {\n\t\t\t\t\tsetInternalOpen(next);\n\t\t\t\t}\n\t\t\t\tonOpenChange?.(next);\n\t\t\t},\n\t\t\t[open, onOpenChange],\n\t\t);\n\n\t\tconst setValue = useCallback(\n\t\t\t(next: string) => {\n\t\t\t\tif (value === undefined) {\n\t\t\t\t\tsetInternalValue(next);\n\t\t\t\t}\n\t\t\t\tonValueChange?.(next);\n\t\t\t},\n\t\t\t[value, onValueChange],\n\t\t);\n\n\t\tconst registerItemText = useCallback((itemValue: string, text: string) => {\n\t\t\tsetItemTexts((prev) => (prev[itemValue] === text ? prev : { ...prev, [itemValue]: text }));\n\t\t}, []);\n\n\t\treturn (\n\t\t\t<SelectContext.Provider value={{ open: isOpen, setOpen, value: resolvedValue, setValue, triggerRef, contentId, itemTexts, registerItemText }}>\n\t\t\t\t<div ref={ref} className={`${styles[selectStyleKeys.root]} ${className}`} {...props}>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t</SelectContext.Provider>\n\t\t);\n\t},\n);\nSelect.displayName = 'Select';\n\nexport interface SelectTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, SelectTriggerBaseProps {}\n\nconst SelectTrigger = React.forwardRef<HTMLButtonElement, SelectTriggerProps>(({ className = '', size = 'default', children, onClick, onKeyDown, ...props }, ref) => {\n\tconst context = useSelectContext();\n\n\tfunction setRef(element: HTMLButtonElement | null) {\n\t\tcontext.triggerRef.current = element;\n\t\tif (typeof ref === 'function') {\n\t\t\tref(element);\n\t\t} else if (ref) {\n\t\t\tref.current = element;\n\t\t}\n\t}\n\n\tfunction handleClick(event: React.MouseEvent<HTMLButtonElement>) {\n\t\tonClick?.(event);\n\t\tif (event.defaultPrevented) {\n\t\t\treturn;\n\t\t}\n\t\tcontext.setOpen(!context.open);\n\t}\n\n\tfunction handleKeyDown(event: React.KeyboardEvent<HTMLButtonElement>) {\n\t\tonKeyDown?.(event);\n\t\tif (event.defaultPrevented) {\n\t\t\treturn;\n\t\t}\n\t\tif (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n\t\t\tevent.preventDefault();\n\t\t\tcontext.setOpen(true);\n\t\t}\n\t}\n\n\tconst state = getSelectState(context.open);\n\tconst classes = [styles[selectStyleKeys.trigger], className].filter(Boolean).join(' ');\n\n\treturn (\n\t\t<button\n\t\t\tref={setRef}\n\t\t\ttype=\"button\"\n\t\t\trole=\"combobox\"\n\t\t\taria-haspopup=\"listbox\"\n\t\t\taria-expanded={context.open}\n\t\t\taria-controls={context.contentId}\n\t\t\tdata-state={state}\n\t\t\tdata-size={size}\n\t\t\tclassName={classes}\n\t\t\tonClick={handleClick}\n\t\t\tonKeyDown={handleKeyDown}\n\t\t\t{...props}>\n\t\t\t{children}\n\t\t\t<SelectChevronIcon />\n\t\t</button>\n\t);\n});\nSelectTrigger.displayName = 'SelectTrigger';\n\nexport interface SelectValueProps extends React.HTMLAttributes<HTMLSpanElement> {\n\t/** 未选中时展示的占位文本 */\n\tplaceholder?: string;\n}\n\nconst SelectValue = React.forwardRef<HTMLSpanElement, SelectValueProps>(({ className = '', placeholder, children, ...props }, ref) => {\n\tconst { value, itemTexts } = useSelectContext();\n\tconst text = value !== undefined ? itemTexts[value] : undefined;\n\tconst showPlaceholder = !text;\n\tconst classes = [styles[selectStyleKeys.value], className].filter(Boolean).join(' ');\n\n\treturn (\n\t\t<span ref={ref} data-placeholder={showPlaceholder} className={classes} {...props}>\n\t\t\t{text ?? placeholder ?? children}\n\t\t</span>\n\t);\n});\nSelectValue.displayName = 'SelectValue';\n\nexport interface SelectContentProps extends React.HTMLAttributes<HTMLDivElement>, SelectContentBaseProps {\n\tcontainer?: PortalContainer;\n}\n\nconst SelectContent = React.forwardRef<HTMLDivElement, SelectContentProps>(\n\t({ className = '', position = 'item-aligned', align = 'center', sideOffset = 4, container, children, onKeyDown, ...props }, ref) => {\n\t\tconst { open, setOpen, triggerRef, contentId } = useSelectContext();\n\t\tconst portalContainer = usePortalContainer(container);\n\t\tconst [coords, setCoords] = useState<SelectPositionResult | null>(null);\n\t\tconst contentRef = useRef<HTMLDivElement | null>(null);\n\t\tconst itemsRef = useRef<HTMLElement[]>([]);\n\n\t\tfunction setRef(element: HTMLDivElement | null) {\n\t\t\tcontentRef.current = element;\n\t\t\tif (typeof ref === 'function') {\n\t\t\t\tref(element);\n\t\t\t} else if (ref) {\n\t\t\t\tref.current = element;\n\t\t\t}\n\t\t}\n\n\t\tuseLayoutEffect(() => {\n\t\t\tif (!open) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfunction updatePosition() {\n\t\t\t\tconst trigger = triggerRef.current;\n\t\t\t\tconst content = contentRef.current;\n\t\t\t\tif (!trigger || !content) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst triggerRect = trigger.getBoundingClientRect();\n\t\t\t\tconst contentSize = { width: content.offsetWidth, height: content.offsetHeight };\n\t\t\t\tconst viewport = { width: window.innerWidth, height: window.innerHeight };\n\t\t\t\tsetCoords(getSelectPosition({ triggerRect, contentSize, align, sideOffset, viewport }));\n\t\t\t}\n\n\t\t\tfunction highlightSelected() {\n\t\t\t\tconst items = itemsRef.current;\n\t\t\t\titems.forEach((item) => item.removeAttribute('data-highlighted'));\n\t\t\t\tconst selected = items.find((item) => item.getAttribute('aria-selected') === 'true');\n\t\t\t\tconst target = selected ?? items[0];\n\t\t\t\tif (target) {\n\t\t\t\t\ttarget.setAttribute('data-highlighted', 'true');\n\t\t\t\t\ttarget.focus();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tupdatePosition();\n\t\t\thighlightSelected();\n\t\t\twindow.addEventListener('resize', updatePosition);\n\t\t\tdocument.addEventListener('scroll', updatePosition, true);\n\n\t\t\treturn () => {\n\t\t\t\twindow.removeEventListener('resize', updatePosition);\n\t\t\t\tdocument.removeEventListener('scroll', updatePosition, true);\n\t\t\t};\n\t\t}, [open, align, sideOffset, triggerRef]);\n\n\t\tuseEffect(() => {\n\t\t\tif (!open) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfunction handlePointerDown(event: PointerEvent) {\n\t\t\t\tconst target = event.target as Node | null;\n\t\t\t\tif (!target) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst content = contentRef.current;\n\t\t\t\tconst trigger = triggerRef.current;\n\t\t\t\tif (content && content.contains(target)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (trigger && trigger.contains(target)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsetOpen(false);\n\t\t\t}\n\n\t\t\tdocument.addEventListener('pointerdown', handlePointerDown);\n\t\t\treturn () => document.removeEventListener('pointerdown', handlePointerDown);\n\t\t}, [open, triggerRef, setOpen]);\n\n\t\tfunction handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n\t\t\tonKeyDown?.(event);\n\t\t\tif (event.defaultPrevented) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst items = itemsRef.current.filter((item) => item.getAttribute('data-disabled') !== 'true');\n\t\t\tif (items.length === 0) {\n\t\t\t\tif (event.key === 'Escape') {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tsetOpen(false);\n\t\t\t\t\ttriggerRef.current?.focus();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst currentIndex = items.findIndex((item) => item.getAttribute('data-highlighted') === 'true');\n\n\t\t\tconst highlight = (next: number) => {\n\t\t\t\titems.forEach((item) => item.removeAttribute('data-highlighted'));\n\t\t\t\titems[next].setAttribute('data-highlighted', 'true');\n\t\t\t\titems[next].focus();\n\t\t\t};\n\n\t\t\tswitch (event.key) {\n\t\t\t\tcase 'ArrowDown':\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\thighlight(currentIndex < 0 ? 0 : (currentIndex + 1) % items.length);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'ArrowUp':\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\thighlight(currentIndex < 0 ? items.length - 1 : (currentIndex - 1 + items.length) % items.length);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'Home':\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\thighlight(0);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'End':\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\thighlight(items.length - 1);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'Enter':\n\t\t\t\tcase ' ':\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t(currentIndex >= 0 ? items[currentIndex] : items[0]).click();\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'Escape':\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tsetOpen(false);\n\t\t\t\t\ttriggerRef.current?.focus();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tconst state = getSelectState(open);\n\t\tconst classes = [styles[selectStyleKeys.content], className].filter(Boolean).join(' ');\n\n\t\tconst content = (\n\t\t\t<SelectContentContext.Provider value={{ itemsRef, close: () => setOpen(false) }}>\n\t\t\t\t<div\n\t\t\t\t\tref={setRef}\n\t\t\t\t\tid={contentId}\n\t\t\t\t\trole=\"listbox\"\n\t\t\t\t\ttabIndex={-1}\n\t\t\t\t\tdata-state={state}\n\t\t\t\t\tdata-position={position}\n\t\t\t\t\tclassName={classes}\n\t\t\t\t\tstyle={coords ? { top: `${coords.top}px`, left: `${coords.left}px` } : undefined}\n\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t{...props}>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t</SelectContentContext.Provider>\n\t\t);\n\n\t\tif (!portalContainer) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn createPortal(content, portalContainer);\n\t},\n);\nSelectContent.displayName = 'SelectContent';\n\nexport interface SelectGroupProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst SelectGroup = React.forwardRef<HTMLDivElement, SelectGroupProps>(({ className = '', children, ...props }, ref) => {\n\treturn (\n\t\t<div ref={ref} role=\"group\" className={`${styles[selectStyleKeys.group]} ${className}`} {...props}>\n\t\t\t{children}\n\t\t</div>\n\t);\n});\nSelectGroup.displayName = 'SelectGroup';\n\nexport interface SelectLabelProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst SelectLabel = React.forwardRef<HTMLDivElement, SelectLabelProps>(({ className = '', children, ...props }, ref) => {\n\tconst classes = [styles[selectStyleKeys.label], className].filter(Boolean).join(' ');\n\treturn (\n\t\t<div ref={ref} className={classes} {...props}>\n\t\t\t{children}\n\t\t</div>\n\t);\n});\nSelectLabel.displayName = 'SelectLabel';\n\nexport interface SelectItemProps extends React.HTMLAttributes<HTMLDivElement>, SelectItemBaseProps {}\n\nconst SelectItem = React.forwardRef<HTMLDivElement, SelectItemProps>(({ className = '', value, disabled = false, children, onClick, ...props }, ref) => {\n\tconst { itemsRef, close } = useSelectContentContext();\n\tconst { value: selectedValue, setValue, registerItemText } = useSelectContext();\n\tconst itemRef = useRef<HTMLDivElement | null>(null);\n\tconst isSelected = selectedValue === value;\n\n\tuseEffect(() => {\n\t\tconst element = itemRef.current;\n\t\tif (!element) {\n\t\t\treturn;\n\t\t}\n\t\titemsRef.current.push(element);\n\t\treturn () => {\n\t\t\titemsRef.current = itemsRef.current.filter((item) => item !== element);\n\t\t};\n\t}, [itemsRef]);\n\n\tuseLayoutEffect(() => {\n\t\tconst element = itemRef.current;\n\t\tif (element) {\n\t\t\tregisterItemText(value, element.textContent ?? '');\n\t\t}\n\t}, [value, registerItemText, children]);\n\n\tfunction setRef(element: HTMLDivElement | null) {\n\t\titemRef.current = element;\n\t\tif (typeof ref === 'function') {\n\t\t\tref(element);\n\t\t} else if (ref) {\n\t\t\tref.current = element;\n\t\t}\n\t}\n\n\tfunction handleClick(event: React.MouseEvent<HTMLDivElement>) {\n\t\tonClick?.(event);\n\t\tif (event.defaultPrevented) {\n\t\t\treturn;\n\t\t}\n\t\tif (disabled) {\n\t\t\treturn;\n\t\t}\n\t\tsetValue(value);\n\t\tclose();\n\t}\n\n\tconst classes = [styles[selectStyleKeys.item], className].filter(Boolean).join(' ');\n\treturn (\n\t\t<div\n\t\t\tref={setRef}\n\t\t\trole=\"option\"\n\t\t\ttabIndex={-1}\n\t\t\taria-selected={isSelected}\n\t\t\tdata-checked={getSelectCheckState(isSelected)}\n\t\t\tdata-disabled={disabled}\n\t\t\tclassName={classes}\n\t\t\tonClick={handleClick}\n\t\t\t{...props}>\n\t\t\t<span className={styles[selectStyleKeys.indicator]}>{isSelected && <SelectCheckIcon />}</span>\n\t\t\t{children}\n\t\t</div>\n\t);\n});\nSelectItem.displayName = 'SelectItem';\n\nexport interface SelectSeparatorProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst SelectSeparator = React.forwardRef<HTMLDivElement, SelectSeparatorProps>(({ className = '', ...props }, ref) => {\n\tconst classes = [styles[selectStyleKeys.separator], className].filter(Boolean).join(' ');\n\treturn <div ref={ref} role=\"separator\" className={classes} {...props} />;\n});\nSelectSeparator.displayName = 'SelectSeparator';\n\nexport interface SelectScrollUpButtonProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst SelectScrollUpButton = React.forwardRef<HTMLDivElement, SelectScrollUpButtonProps>(({ className = '', ...props }, ref) => {\n\tconst classes = [styles[selectStyleKeys.scrollButton], className].filter(Boolean).join(' ');\n\treturn (\n\t\t<div ref={ref} className={classes} {...props}>\n\t\t\t<svg\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\twidth=\"16\"\n\t\t\t\theight=\"16\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\taria-hidden=\"true\">\n\t\t\t\t<path d=\"m18 15-6-6-6 6\" />\n\t\t\t</svg>\n\t\t</div>\n\t);\n});\nSelectScrollUpButton.displayName = 'SelectScrollUpButton';\n\nexport interface SelectScrollDownButtonProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst SelectScrollDownButton = React.forwardRef<HTMLDivElement, SelectScrollDownButtonProps>(({ className = '', ...props }, ref) => {\n\tconst classes = [styles[selectStyleKeys.scrollButton], className].filter(Boolean).join(' ');\n\treturn (\n\t\t<div ref={ref} className={classes} {...props}>\n\t\t\t<svg\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\twidth=\"16\"\n\t\t\t\theight=\"16\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\taria-hidden=\"true\">\n\t\t\t\t<path d=\"m6 9 6 6 6-6\" />\n\t\t\t</svg>\n\t\t</div>\n\t);\n});\nSelectScrollDownButton.displayName = 'SelectScrollDownButton';\n\nexport { Select, SelectTrigger, SelectValue, SelectContent, SelectGroup, SelectLabel, SelectItem, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton };\nexport default Select;\n"
    },
    {
      "path": "packages/styles/scss/components/select.module.scss",
      "type": "registry:file",
      "target": "components/ui/select/select.module.scss",
      "content": "@use '../../../styles/variables/colors' as *;\n\n// 根容器\n.root {\n\tposition: relative;\n\tdisplay: inline-flex;\n}\n\n// 触发器按钮\n.trigger {\n\tdisplay: inline-flex;\n\twidth: fit-content;\n\talign-items: center;\n\tjustify-content: space-between;\n\tgap: $spacing-2;\n\tborder-radius: var(--tile-select-trigger-radius, $radius);\n\tborder: 1px solid var(--tile-select-trigger-border, $input);\n\tbackground-color: var(--tile-select-trigger-background, transparent);\n\tpadding: var(--tile-select-trigger-padding, $spacing-2 $spacing-3);\n\tfont-size: var(--tile-select-font-size, $text-sm);\n\twhite-space: nowrap;\n\tcolor: var(--tile-select-foreground, $foreground);\n\tbox-shadow: var(--tile-select-trigger-shadow, $shadow-sm);\n\ttransition:\n\t\tcolor $transition-fast,\n\t\tbox-shadow $transition-fast;\n\toutline: none;\n\tcursor: pointer;\n\n\t&:focus-visible {\n\t\tborder-color: var(--tile-select-focus-border, $ring);\n\t\tbox-shadow: var(--tile-select-focus-shadow, 0 0 0 3px color-mix(in srgb, $ring 50%, transparent));\n\t}\n\n\t&[data-size='default'] {\n\t\theight: var(--tile-select-height, 2.25rem);\n\t}\n\n\t&[data-size='sm'] {\n\t\theight: var(--tile-select-sm-height, 2rem);\n\t\tfont-size: var(--tile-select-sm-font-size, $text-sm);\n\t}\n\n\t&[data-disabled='true'] {\n\t\tcursor: not-allowed;\n\t\topacity: 0.5;\n\t}\n\n\t&[data-placeholder='true'] {\n\t\tcolor: var(--tile-select-placeholder, $muted-foreground);\n\t}\n\n\t& > svg {\n\t\tpointer-events: none;\n\t\tflex-shrink: 0;\n\t\twidth: 1rem;\n\t\theight: 1rem;\n\t\tcolor: var(--tile-select-subtle, $muted-foreground);\n\t}\n}\n\n// 触发器内展示的选中值\n.value {\n\tpointer-events: none;\n\tline-clamp: 1;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: $spacing-2;\n\toverflow: hidden;\n}\n\n// 弹出内容面板\n.content {\n\tposition: fixed;\n\tz-index: $z-dropdown;\n\tmin-width: 8rem;\n\tmax-height: 300px;\n\toverflow-x: hidden;\n\toverflow-y: auto;\n\tborder-radius: var(--tile-select-panel-radius, $radius);\n\tborder: 1px solid var(--tile-select-panel-border, $border);\n\tbackground-color: var(--tile-select-panel-background, $popover);\n\tcolor: var(--tile-select-panel-foreground, $popover-foreground);\n\tpadding: var(--tile-select-panel-padding, $spacing-1);\n\tbox-shadow: var(--tile-select-panel-shadow, $shadow-md);\n\toutline: none;\n\ttransition:\n\t\topacity $transition-fast,\n\t\tvisibility $transition-fast,\n\t\ttransform $transition-fast;\n\n\t&[data-state='closed'] {\n\t\topacity: 0;\n\t\tvisibility: hidden;\n\t\tpointer-events: none;\n\t\ttransform: translateY(-0.25rem) scale(0.95);\n\t}\n\n\t&[data-state='open'] {\n\t\topacity: 1;\n\t\tvisibility: visible;\n\t\tpointer-events: auto;\n\t\ttransform: translate(0, 0) scale(1);\n\t}\n}\n\n// 分组容器\n.group {\n\tdisplay: block;\n}\n\n// 内容视口（可滚动）\n.viewport {\n\tpadding: var(--tile-select-viewport-padding, $spacing-1);\n}\n\n// 选项\n.item {\n\tposition: relative;\n\tdisplay: flex;\n\twidth: 100%;\n\talign-items: center;\n\tgap: $spacing-2;\n\tborder-radius: var(--tile-select-item-radius, $radius-sm);\n\tpadding: var(--tile-select-item-padding, $spacing-1_5 $spacing-2 $spacing-1_5 $spacing-8);\n\tfont-size: var(--tile-select-font-size, $text-sm);\n\tline-height: $leading-normal;\n\tcolor: var(--tile-select-panel-foreground, $popover-foreground);\n\toutline: none;\n\tcursor: default;\n\tuser-select: none;\n\n\t&[data-highlighted='true'] {\n\t\tbackground-color: var(--tile-select-highlight-background, $accent);\n\t\tcolor: var(--tile-select-highlight-foreground, $accent-foreground);\n\t}\n\n\t&[data-disabled='true'] {\n\t\tpointer-events: none;\n\t\topacity: 0.5;\n\t}\n\n\t& > svg {\n\t\tpointer-events: none;\n\t\tflex-shrink: 0;\n\t\twidth: 1rem;\n\t\theight: 1rem;\n\t\tcolor: var(--tile-select-subtle, $muted-foreground);\n\t}\n\n\t&:focus-visible {\n\t\tbox-shadow: var(--tile-select-item-focus-shadow, none);\n\t}\n}\n\n// 选中指示器\n.indicator {\n\tposition: absolute;\n\tleft: var(--tile-select-indicator-left, $spacing-2);\n\tright: var(--tile-select-indicator-right, auto);\n\tdisplay: inline-flex;\n\twidth: 0.875rem;\n\theight: 0.875rem;\n\talign-items: center;\n\tjustify-content: center;\n\n\t.checkIcon {\n\t\twidth: 1rem;\n\t\theight: 1rem;\n\t}\n}\n\n// 分组标题\n.label {\n\tpadding: var(--tile-select-label-padding, $spacing-1_5 $spacing-2);\n\tfont-size: var(--tile-select-label-font-size, $text-xs);\n\tfont-weight: var(--tile-select-label-font-weight, $font-medium);\n\tcolor: var(--tile-select-subtle, $muted-foreground);\n}\n\n// 分隔线\n.separator {\n\tmargin: $spacing-1 (-$spacing-1);\n\theight: 1px;\n\tbackground-color: var(--tile-select-separator, $border);\n}\n\n// 上下滚动按钮\n.scrollButton {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tpadding: $spacing-1;\n\tcolor: var(--tile-select-subtle, $muted-foreground);\n\n\t& > svg {\n\t\twidth: 1rem;\n\t\theight: 1rem;\n\t}\n}\n\n// 触发器箭头\n.chevron {\n\twidth: 1rem;\n\theight: 1rem;\n\topacity: var(--tile-select-chevron-opacity, 0.5);\n}\n\n@media (prefers-reduced-motion: reduce) {\n\t.content {\n\t\ttransition: none;\n\t}\n}\n"
    },
    {
      "path": "packages/react/src/components/select/index.ts",
      "type": "registry:ui",
      "target": "components/ui/select/index.ts",
      "content": "export {\n\tSelect,\n\tSelectTrigger,\n\tSelectValue,\n\tSelectContent,\n\tSelectGroup,\n\tSelectLabel,\n\tSelectItem,\n\tSelectSeparator,\n\tSelectScrollUpButton,\n\tSelectScrollDownButton,\n\ttype SelectProps,\n\ttype SelectTriggerProps,\n\ttype SelectValueProps,\n\ttype SelectContentProps,\n\ttype SelectGroupProps,\n\ttype SelectLabelProps,\n\ttype SelectItemProps,\n\ttype SelectSeparatorProps,\n\ttype SelectScrollUpButtonProps,\n\ttype SelectScrollDownButtonProps,\n} from './select';\n"
    }
  ]
}
