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; /*** 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; value?: any; }; export type SwitchProps = BoxProps & RNSwitchProps & LocalSwitchProps; const useProps = createHook( (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 = ( ); /////////////////////////////////////////////////// const labelId = useUniqueId(); /////////////////////////////////////////////////// return { ...boxProps, accessibilityRole: 'checkbox', accessibilityLabelledBy: labelId, accessibilityChecked: isChecked, focusable: true, children: ( <> {align === 'left' && switchToggle} {label && ( {label} )} {align === 'right' && switchToggle} ), onPress: handlePress, }; }, { defaultProps: { align: 'left', palette: 'primary', variant: 'default', }, themeKey: 'native.Switch', } ); export const Switch = createComponent( (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; /** Label for the switch */ switchLabel?: string; }; export type SwitchFieldProps = BoxProps & FieldWrapperProps & SwitchProps & LocalSwitchFieldProps; const useSwitchFieldProps = createHook( (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: ( ), }; }, { defaultProps: { align: 'left', palette: 'primary', variant: 'default', }, themeKey: 'SwitchField', } ); export const SwitchField = createComponent( (props) => { const SwitchFieldProps = useSwitchFieldProps(props); return createElement({ children: props.children, component: styles.SwitchField, htmlProps: SwitchFieldProps, }); }, { attach: { useProps, displayName: 'SwitchField', }, themeKey: 'SwitchField', } );