import * as Checkbox from '@radix-ui/react-checkbox';
import { useAugmentedRef } from '~/components/primitives/hooks';
import * as Slot from '~/components/primitives/slot';
ComponentPropsWithAsChild,
} from '~/components/primitives/types';
import * as React from 'react';
import { GestureResponderEvent, Pressable, View } from 'react-native';
import type { CheckboxIndicator, CheckboxRootProps } from './types';
const CheckboxContext = React.createContext<CheckboxRootProps | null>(null);
const Root = React.forwardRef<PressableRef, SlottablePressableProps & CheckboxRootProps>(
{ asChild, disabled, checked, onCheckedChange, onPress: onPressProp, role: _role, ...props },
const augmentedRef = useAugmentedRef({ ref });
function onPress(ev: GestureResponderEvent) {
onCheckedChange(!checked);
React.useLayoutEffect(() => {
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLButtonElement;
augRef.dataset.state = checked ? 'checked' : 'unchecked';
augRef.value = checked ? 'on' : 'off';
React.useLayoutEffect(() => {
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLButtonElement;
augRef.role = 'checkbox';
augRef.dataset.disabled = 'true';
augRef.dataset.disabled = undefined;
const Component = asChild ? Slot.Pressable : Pressable;
<CheckboxContext.Provider value={{ checked, disabled, onCheckedChange }}>
onCheckedChange={onCheckedChange}
</CheckboxContext.Provider>
Root.displayName = 'RootWebCheckbox';
function useCheckboxContext() {
const context = React.useContext(CheckboxContext);
'Checkbox compound components cannot be rendered outside the Checkbox component'
const Indicator = React.forwardRef<
React.ElementRef<typeof View>,
ComponentPropsWithAsChild<typeof View> & CheckboxIndicator
>(({ asChild, forceMount, ...props }, ref) => {
const { checked, disabled } = useCheckboxContext();
const augmentedRef = useAugmentedRef({ ref });
React.useLayoutEffect(() => {
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLDivElement;
augRef.dataset.state = checked ? 'checked' : 'unchecked';
React.useLayoutEffect(() => {
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLDivElement;
augRef.dataset.disabled = 'true';
augRef.dataset.disabled = undefined;
const Component = asChild ? Slot.View : View;
<Checkbox.Indicator forceMount={forceMount} asChild>
<Component ref={ref} {...props} />
Indicator.displayName = 'IndicatorWebCheckbox';
export { Indicator, Root };