import * as React from 'react' ; import { Platform , SwitchProps as RNSwitchProps } from 'react-native' ; import { createComponent , createElement , createHook , useUniqueId } from 'bumbag/utils' ; import { usePalette } from '../utils' ; import { Box , BoxProps } from '../Box' ; import { TextProps } from '../Text' ; import { FieldWrapper , FieldWrapperProps } from '../FieldWrapper' ; import * as styles from './Switch.styles' ; export type LocalSwitchProps = { /** Color of the active thumb (web only). */ activeThumbColor ? : string ; /** Color of the active track (web only). */ activeTrackColor ? : string ; /** Aligns the switch to the left or right side. */ align ? : 'left' | 'right' ; /** Indicates if the switch is checked. */ checked ? : boolean ; /** Sets the default checked state. */ defaultChecked ? : boolean ; /** Disables the switch */ disabled ? : boolean ; /** Switch label */ label ? : string ; /*** Sets the props of the label */ labelProps ? : Partial < TextProps > ; /*** Sets the color of the switch */ palette ? : string ; /** Function to invoke when switch has changed */ onChange ? : ( { checked , value } : { checked : boolean ; value ? : any ; } ) => void ; /** State of the switch. Can be any color in the palette. */ state ? : string ; switchProps ? : Partial < RNSwitchProps > ; value ? : any ; } ; export type SwitchProps = BoxProps & RNSwitchProps & LocalSwitchProps ; const useProps = createHook < SwitchProps > ( ( props ) => { const { align , colorMode , checked , disabled , defaultChecked , label , labelProps , palette , onChange , overrides , switchProps , state , value , } = props ; const boxProps = Box . useProps ( props ) ; const [ controlledChecked , setControlledChecked ] = React . useState ( defaultChecked ) ; const handlePress = React . useCallback ( ( ) => { if ( typeof checked === 'undefined' ) { setControlledChecked ( ! controlledChecked ) ; } else { onChange && onChange ( { checked : ! checked , value } ) ; } } , [ checked , controlledChecked , onChange , value ] ) ; const isChecked = checked || controlledChecked ; let trackColor = props . trackColor || 'white900' ; if ( state && Platform . OS !== 'ios' ) { trackColor = `${ state }100` ; } let thumbColor = props . thumbColor || 'white' ; if ( state && Platform . OS !== 'ios' ) { thumbColor = state ; } let activeThumbColor = usePalette ( props . activeThumbColor || palette ) ; let activeTrackColor = usePalette ( props . activeTrackColor || `${ palette }100` ) ; let thumbPalette = usePalette ( thumbColor ) ; let trackPalette = usePalette ( trackColor as any ) ; const switchToggle = ( < styles . SwitchToggle activeThumbColor = { activeThumbColor } activeTrackColor = { activeTrackColor } thumbColor = { thumbPalette } trackColor = { trackPalette } align = { align } colorMode = { colorMode } disabled = { disabled } onValueChange = { handlePress } value = { isChecked } { ... switchProps } />); const labelId = useUniqueId ( ) ; return { ... boxProps , accessibilityRole : 'checkbox' , accessibilityLabelledBy : labelId , accessibilityChecked : isChecked , focusable : true , children : ( < > { align === 'left' && switchToggle } { label && ( < styles . SwitchLabel nativeID = { labelId } colorMode = { colorMode } overrides = { overrides } { ... labelProps } > { label } < /styles.SwitchLabel>)} { align === 'right' && switchToggle } < />), onPress : handlePress , } ; } , { defaultProps : { align : 'left' , palette : 'primary' , variant : 'default' , } , themeKey : 'native.Switch' , } ) ; export const Switch = createComponent < SwitchProps > ( ( props ) => { const htmlProps = useProps ( props ) ; return createElement ( { children : props . children , component : styles . Switch , htmlProps , } ) ; } , { attach : { useProps , displayName : 'native.Switch' , } , themeKey : 'native.Switch' , } ) ; export type LocalSwitchFieldProps = { /** Additional props for the Switch component */ switchProps ? : Partial < SwitchProps > ; /** Label for the switch */ switchLabel ? : string ; } ; export type SwitchFieldProps = BoxProps & FieldWrapperProps & SwitchProps & LocalSwitchFieldProps ; const useSwitchFieldProps = createHook < SwitchFieldProps > ( ( props ) => { const { align , switchLabel , checked , defaultChecked , description , disabled , hint , isOptional , isRequired , label , labelProps , onChange , overrides , palette , state , variant , validationText , value , ... restProps } = props ; const boxProps = Box . useProps ( restProps ) ; return { ... boxProps , children : ( < FieldWrapper description = { description } hint = { hint } isOptional = { isOptional } isRequired = { isRequired } label = { label } overrides = { overrides } state = { state } variant = { variant } validationText = { validationText } > < Switch align = { align } checked = { checked } defaultChecked = { defaultChecked } disabled = { disabled } label = { switchLabel } labelProps = { labelProps } onChange = { onChange } palette = { palette } state = { state } overrides = { overrides } value = { value } / > < /FieldWrapper>), } ; } , { defaultProps : { align : 'left' , palette : 'primary' , variant : 'default' , } , themeKey : 'SwitchField' , } ) ; export const SwitchField = createComponent < SwitchFieldProps > ( ( props ) => { const SwitchFieldProps = useSwitchFieldProps ( props ) ; return createElement ( { children : props . children , component : styles . SwitchField , htmlProps : SwitchFieldProps , } ) ; } , { attach : { useProps , displayName : 'SwitchField' , } , themeKey : 'SwitchField' , } ) ;