import * as React from 'react'; import { createComponent, createElement, createHook, useUniqueId } from 'bumbag/utils'; import { Box, BoxProps } from '../Box'; import { TextProps } from '../Text'; import { IconProps } from '../Icon'; import { FieldWrapper, FieldWrapperProps } from '../FieldWrapper'; import * as styles from './Checkbox.styles'; export type LocalCheckboxProps = { /** Aligns the checkbox to the left or right side. */ align?: 'left' | 'right'; /** Indicates if the checkbox is checked. */ checked?: boolean; /** Sets the default checked state. */ defaultChecked?: boolean; /** Disables the checkbox */ disabled?: boolean; /*** Sets the props of the icon */ iconProps?: Partial; /*** Sets the props of the icon wrapper */ iconWrapperProps?: Partial; /** Checkbox label */ label?: string; /*** Sets the props of the label */ labelProps?: Partial; /*** Sets the color of the checkbox */ palette?: string; /** Function to invoke when checkbox has changed */ onChange?: ({ checked, value }: { checked: boolean; value?: any }) => void; /** State of the checkbox. Can be any color in the palette. */ state?: string; value?: any; }; export type CheckboxProps = BoxProps & LocalCheckboxProps; const useProps = createHook( (props) => { const { align, colorMode, checked, disabled, defaultChecked, iconProps, iconWrapperProps, label, labelProps, palette, onChange, overrides, state, value, variant, } = 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 checkedIconColor = `${palette}Inverted`; if (variant === 'ghost') { checkedIconColor = palette; } if (disabled) { checkedIconColor = 'gray300'; } let iconSize = '200'; if (variant === 'ghost') { iconSize = '300'; } const checkbox = ( {isChecked && ( )} ); /////////////////////////////////////////////////// const labelId = useUniqueId(); /////////////////////////////////////////////////// return { ...boxProps, accessibilityRole: 'checkbox', accessibilityLabelledBy: labelId, accessibilityChecked: isChecked, focusable: true, children: ( <> {align === 'left' && checkbox} {label} {align === 'right' && checkbox} ), onPress: handlePress, }; }, { defaultProps: { align: 'left', palette: 'primary', variant: 'default', }, themeKey: 'native.Checkbox', } ); export const Checkbox = createComponent( (props) => { const htmlProps = useProps(props); return createElement({ children: props.children, component: styles.Checkbox, htmlProps, }); }, { attach: { useProps, displayName: 'native.Checkbox', }, themeKey: 'native.Checkbox', } ); //////////////////////////////////////////////////////////////// export type LocalCheckboxFieldProps = { /** Additional props for the Checkbox component */ checkboxProps?: Partial; /** Label for the checkbox */ checkboxLabel?: string; }; export type CheckboxFieldProps = BoxProps & FieldWrapperProps & CheckboxProps & LocalCheckboxFieldProps; const useCheckboxFieldProps = createHook( (props) => { const { align, checkboxLabel, checked, defaultChecked, description, disabled, hint, iconProps, iconWrapperProps, 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: 'CheckboxField', } ); export const CheckboxField = createComponent( (props) => { const CheckboxFieldProps = useCheckboxFieldProps(props); return createElement({ children: props.children, component: styles.CheckboxField, htmlProps: CheckboxFieldProps, }); }, { attach: { useProps: useCheckboxFieldProps, displayName: 'CheckboxField', }, themeKey: 'CheckboxField', } );