import React from 'react' import { View } from '../View' import { InputBase, InputBaseDefaultOrder, selectInputBaseProps } from '../InputBase' import { useAnimatedVariantStyles } from '../..' import { Touchable } from '../Touchable' import { Icon } from '../Icon' import { CheckboxProps } from './types' import { AnyRecord, AppIcon, IJSX, StyledComponentProps } from '@codeleap/styles' import { MobileStyleRegistry } from '../../Registry' import { useStylesFor } from '../../hooks' import { useInputBase } from '../InputBase/useInputBase' import { fields } from '@codeleap/form' export * from './styles' export * from './types' /** Reversed order puts the innerWrapper (the visual checkbox) before the label, matching right-aligned checkbox layouts without a separate style override. */ const reversedOrder = [...InputBaseDefaultOrder].reverse() export const Checkbox = (props: CheckboxProps) => { const { inputBaseProps, others, } = selectInputBaseProps({ ...Checkbox.defaultProps, ...props, }) const { style, disabled, debugName, checkboxOnLeft, checkIcon, field, forceError, value, onValueChange, } = others const styles = useStylesFor(Checkbox.styleRegistryName, style) const { validation, wrapperRef, inputValue, onInputValueChange, } = useInputBase(field, fields.boolean, { value, onValueChange }) const boxAnimation = useAnimatedVariantStyles({ variantStyles: styles, animatedProperties: ['box:unchecked', 'box:disabled', 'box:checked', 'box:disabled-checked', 'box:disabled-unchecked'], transition: styles['box:transition'], updater: () => { 'worklet' let disabledStyle = {} if (disabled) { disabledStyle = inputValue ? styles['box:disabled-checked'] : styles['box:disabled-unchecked'] } const style = inputValue ? styles['box:checked'] : styles['box:unchecked'] return { ...style, ...disabledStyle, } }, dependencies: [inputValue, disabled], }) const checkmarkWrapperAnimation = useAnimatedVariantStyles({ variantStyles: styles, animatedProperties: ['checkmarkWrapper:unchecked', 'checkmarkWrapper:disabled', 'checkmarkWrapper:checked', 'checkmarkWrapper:disabled-unchecked', 'checkmarkWrapper:disabled-checked'], transition: styles['checkmarkWrapper:transition'], updater: () => { 'worklet' let disabledStyle = {} if (disabled) { disabledStyle = inputValue ? styles['checkmarkWrapper:disabled-checked'] : styles['checkmarkWrapper:disabled-unchecked'] } const style = inputValue ? styles['checkmarkWrapper:checked'] : styles['checkmarkWrapper:unchecked'] return { ...style, ...disabledStyle, } }, dependencies: [inputValue, disabled], }) /** Same `__props` escape-hatch as RadioGroup — lets the style variant set the default side without requiring a prop at every call site. */ // @ts-expect-error const _checkboxOnLeft = checkboxOnLeft ?? styles.__props?.checkboxOnLeft const hasError = validation?.showError || forceError return onInputValueChange(!inputValue), disabled, rippleDisabled: true, }} order={_checkboxOnLeft ? reversedOrder : InputBaseDefaultOrder} > } Checkbox.styleRegistryName = 'Checkbox' Checkbox.rootElement = 'wrapper' Checkbox.elements = [...InputBase.elements, 'checkmark', 'box', '__props'] Checkbox.withVariantTypes = (styles: S) => { return Checkbox as (props: StyledComponentProps) => IJSX } Checkbox.defaultProps = { checkIcon: 'check' as AppIcon, } as Partial MobileStyleRegistry.registerComponent(Checkbox)