import React from "react";
import type { ColorValue } from "react-native";
import { Pressable, View } from "react-native";
import type { XOR } from "ts-xor";
import { useStyles } from "./Checkbox.style";
import { Text } from "../Text";
import { Icon } from "../Icon";
import { FormField } from "../FormField";
import { useAtlantisTheme } from "../AtlantisThemeContext";
interface CommonCheckboxProps {
/**
* Label to be displayed beside the checkbox
*/
readonly label?: string;
/**
* Default value for when the checkbox is uncontrolled
*/
readonly defaultChecked?: boolean;
/**
* When true, the checkbox is shown as indeterminate
*/
readonly indeterminate?: boolean;
/**
* Checkbox is disabled
*/
readonly disabled?: boolean;
/**
* Assistive Text, shown under label
*/
readonly assistiveText?: string;
/**
* Accessibility Label for the checkbox. Defaults to label
*/
readonly accessibilityLabel?: string;
/**
* Press handler
*/
onChange?(value: boolean): void;
/**
* If the checkbox is checked. This should be set when this is intended as a controlled component
*/
readonly checked?: boolean;
/**
* Name of the checkbox; this is important when using in a form component
*/
readonly name?: string;
}
interface ControlledCheckboxProps extends CommonCheckboxProps {
/**
* Press handler
*/
onChange(value: boolean): void;
/**
* If the checkbox is checked. This should be set when this is intended as a controlled component
*/
readonly checked: boolean;
}
interface UncontrolledCheckboxProps extends CommonCheckboxProps {
/**
* Name of the checkbox; this is important when using in a form component
*/
readonly name: string;
}
export type CheckboxProps = XOR<
ControlledCheckboxProps,
UncontrolledCheckboxProps
>;
export function Checkbox(props: CheckboxProps) {
if (props.checked !== undefined && props.onChange !== undefined) {
return ;
} else if (props.name) {
return (
name={props.name} defaultValue={props.defaultChecked}>
{field => {
return (
{
props?.onChange?.(newValue);
field.onChange(newValue);
}}
/>
);
}}
);
} else {
throw new Error("Checkbox was given invalid props");
}
}
function CheckboxInternal({
label,
checked,
defaultChecked,
indeterminate = false,
disabled = false,
assistiveText,
onChange,
accessibilityLabel,
}: CheckboxProps) {
const internalValue = checked ?? !!defaultChecked;
const iconName = indeterminate ? "minus2" : "checkmark";
const textVariation = disabled ? "disabled" : "subdued";
const a11yStateChecked = indeterminate ? "mixed" : internalValue;
const backgroundColor = getBackgroundColor(
internalValue,
disabled,
indeterminate,
);
const styles = useStyles();
return (
[
{
opacity: pressed ? 0.2 : 1,
},
styles.container,
]}
onPress={() => {
onChange?.(!internalValue);
}}
>
{label && (
{label}
{assistiveText && (
{assistiveText}
)}
)}
{(internalValue || indeterminate) && (
)}
);
}
function getBackgroundColor(
checked: boolean,
disabled: boolean,
indeterminate: boolean,
): ColorValue {
const { tokens } = useAtlantisTheme();
if (checked || indeterminate) {
if (disabled) {
return tokens["color-disabled"];
} else {
return tokens["color-interactive"];
}
} else {
return tokens["color-overlay--dimmed"];
}
}