// Styled Select = the unstyled @tamagui/ui Select behavior primitive + the // default v2-look skin, layered here in `tamagui`. Single skin definition; the // shadcn registry item is generated from this file. Default chevron/check icons // are dependency-free glyphs (see IconGlyph) so `tamagui` stays lean and native- // bundleable — no react-native-svg pulled into the core package. Consumers can // pass their own icon components as children of the icon parts. // // Sizing is preset-based: `size` is one of xs sm md lg xl (default md), owned // inline here like every other skin. import { type ComponentSize, createStyledContext, type GetProps, styled, withStaticProperties, } from '@tamagui/core' import { Select as SelectBehavior, SelectNativeComponentContext, type SelectProps as SelectBehaviorProps, type SelectScopedProps, } from '@tamagui/select' import { SizableText } from '@tamagui/text' const IconGlyph = styled(SizableText, { displayName: 'SelectIconGlyph', color: 'color', userSelect: 'none', }) const ChevronDown = ({ size = 16 }: { size?: number }) => ( ▾ ) const ChevronUp = ({ size = 16 }: { size?: number }) => ( ▴ ) const Check = ({ size = 14 }: { size?: number }) => ( ✓ ) export type SelectSize = ComponentSize | boolean const SelectContext = createStyledContext<{ size?: SelectSize }>({ size: 'md' }) const selectFrameSize = { xs: { paddingInline: '2', paddingBlock: '1', borderRadius: 'sm', gap: '1' }, sm: { paddingInline: '3', paddingBlock: '1.5', borderRadius: 'md', gap: '1.5' }, md: { paddingInline: '4', paddingBlock: '2', borderRadius: 'md', gap: '2' }, lg: { paddingInline: '6', paddingBlock: '2', borderRadius: 'md', gap: '2' }, xl: { paddingInline: '8', paddingBlock: '2.5', borderRadius: 'lg', gap: '2.5' }, } as const const selectTextSize = { xs: { fontSize: 'xs', lineHeight: 'xs' }, sm: { fontSize: 'sm', lineHeight: 'sm' }, md: { fontSize: 'sm', lineHeight: 'sm' }, lg: { fontSize: 'base', lineHeight: 'base' }, xl: { fontSize: 'lg', lineHeight: 'lg' }, } as const const selectItemSize = { xs: { gap: '1', paddingHorizontal: '2', paddingVertical: '1' }, sm: { gap: '1.5', paddingHorizontal: '3', paddingVertical: '1.5' }, md: { gap: '2', paddingHorizontal: '4', paddingVertical: '2' }, lg: { gap: '2', paddingHorizontal: '6', paddingVertical: '2' }, xl: { gap: '2.5', paddingHorizontal: '8', paddingVertical: '2.5' }, } as const // appearance: none drops the platform arrow, so the skin draws its own chevron: // two 5px gradient strokes in currentColor (it follows the theme), centered in // where the trigger's 16px icon sits, one 16px box in from the inline padding const nativeChevronStroke = (angle: number) => `linear-gradient(${angle}deg, transparent calc(50% - 0.75px), currentColor calc(50% - 0.75px) calc(50% + 0.75px), transparent calc(50% + 0.75px))` const nativeChevronPosition = (paddingInline: number) => { const center = paddingInline + 8 return `calc(100% - ${center - 0.25}px) 50%, calc(100% - ${center - 4.75}px) 50%` } const selectNativeSize = { // a native