import * as Checkbox from '@radix-ui/react-checkbox';
import { useAugmentedRef, useIsomorphicLayoutEffect } from '~/components/primitives/hooks';
import * as Slot from '~/components/primitives/slot';
import * as React from 'react';
import { GestureResponderEvent, Pressable, View } from 'react-native';
import type { IndicatorProps, IndicatorRef, RootProps, RootRef } from './types';
const CheckboxContext = React.createContext<RootProps | null>(null);
const Root = React.forwardRef<RootRef, RootProps>(
{ asChild, disabled, checked, onCheckedChange, onPress: onPressProp, role: _role, ...props },
const augmentedRef = useAugmentedRef({ ref });
function onPress(ev: GestureResponderEvent) {
onCheckedChange(!checked);
useIsomorphicLayoutEffect(() => {
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLButtonElement;
augRef.dataset.state = checked ? 'checked' : 'unchecked';
augRef.value = checked ? 'on' : 'off';
useIsomorphicLayoutEffect(() => {
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<IndicatorRef, IndicatorProps>(
({ asChild, forceMount, ...props }, ref) => {
const { checked, disabled } = useCheckboxContext();
const augmentedRef = useAugmentedRef({ ref });
useIsomorphicLayoutEffect(() => {
if (augmentedRef.current) {
const augRef = augmentedRef.current as unknown as HTMLDivElement;
augRef.dataset.state = checked ? 'checked' : 'unchecked';
useIsomorphicLayoutEffect(() => {
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 };