import React from 'react'; import { resolveFieldState, resolveIndicatorSize, resolveSelectionControlColors, resolveSelectionControlNextChecked, } from '../../../../../internal/resolvers'; import { useControllableState } from '../../../../../internal/useControllableState'; import type { InteractionState } from '../../../../../types/pressable'; import type { SwitchProps } from '../../../../../types/switch'; import { View } from '../../../../layout/public'; import { Pressable } from '../../../../pressable/public'; import { useTheme } from '../../../../theme/runtime'; import { Text } from '../../../../typography/public'; /*** Renders a controlled or uncontrolled accessible switch. */ export function Switch({ children, checked, defaultChecked = false, onCheckedChange, color = 'primary', size = 'm', disabled = false, invalid = false, readOnly = false, accessibilityLabel, testID, ...props }: SwitchProps) { const { theme } = useTheme(); const [isChecked, setChecked] = useControllableState({ value: checked, defaultValue: defaultChecked, onChange: onCheckedChange, }); const nextChecked = resolveSelectionControlNextChecked({ checked: isChecked, disabled, kind: 'switch', readOnly, }); return ( setChecked(nextChecked)} testID={testID} > {(interactionState) => renderSwitchContent( { children, color, disabled, invalid, isChecked, readOnly, size, theme }, interactionState, ) } ); } interface SwitchContentInput { children: React.ReactNode; color: NonNullable; disabled: boolean; invalid: boolean; isChecked: boolean; readOnly: boolean; size: NonNullable; theme: ReturnType['theme']; } /*** Resolves switch presentation for one interaction state and renders the visual control. */ function renderSwitchContent(input: SwitchContentInput, interactionState: InteractionState) { const fieldState = resolveFieldState({ disabled: input.disabled, focused: interactionState.focused, invalid: input.invalid, readOnly: input.readOnly, }); const colors = resolveSelectionControlColors(input.theme, { checked: input.isChecked, fieldState, hovered: interactionState.hovered, pressed: interactionState.pressed, color: input.color, }); const indicatorSize = resolveIndicatorSize(input.size); const labelEmphasis = colors.labelColor === input.theme.semantics.content.muted ? 'muted' : 'default'; return ( {input.children ? ( {input.children} ) : null} ); }