import type { JSX } from 'solid-js'; import { createComponent, createUniqueId, mergeProps } from 'solid-js'; import { omitProps } from 'solid-use/props'; import type { CheckStateControlledOptions, CheckStateRenderProps, CheckStateUncontrolledOptions, } from '../../states/create-check-state'; import { CheckStateProvider, createCheckState } from '../../states/create-check-state'; import createDynamic from '../../utils/create-dynamic'; import type { DynamicProps, HeadlessProps, ValidConstructor } from '../../utils/dynamic-prop'; import { createARIADisabledState, createCheckedState, createDisabledState, } from '../../utils/state-props'; import type { Prettify } from '../../utils/types'; import { CheckboxContext } from './CheckboxContext'; import { CHECKBOX_TAG } from './tags'; export type CheckboxControlledBaseProps = Prettify< CheckStateControlledOptions & CheckStateRenderProps >; export type CheckboxControlledProps = HeadlessProps< T, CheckboxControlledBaseProps >; export type CheckboxUncontrolledBaseProps = Prettify< CheckStateUncontrolledOptions & CheckStateRenderProps >; export type CheckboxUncontrolledProps = HeadlessProps< T, CheckboxUncontrolledBaseProps >; export type CheckboxProps = | CheckboxControlledProps | CheckboxUncontrolledProps; function isCheckboxUncontrolled( props: CheckboxProps, ): props is CheckboxUncontrolledProps { return 'defaultChecked' in props; } /** * A checkbox that can be checked, unchecked, or indeterminate. It is a wrapper * only: the tickable control is `CheckboxIndicator`, and the state lives in * `defaultChecked`/`checked`, where `undefined` means indeterminate. * * Renders a `
` by default. * * @see {@link https://github.com/lxsmnsyc/terracotta/blob/main/docs/components/checkbox.md} */ export function Checkbox(props: CheckboxProps): JSX.Element { const ownerID = createUniqueId(); const labelID = createUniqueId(); const indicatorID = createUniqueId(); const descriptionID = createUniqueId(); const state = createCheckState(props); return createComponent(CheckboxContext.Provider, { value: { ownerID, labelID, indicatorID, descriptionID, }, get children() { return createDynamic( () => props.as ?? 'div', mergeProps( CHECKBOX_TAG, createDisabledState(() => state.disabled()), createARIADisabledState(() => state.disabled()), createCheckedState(() => state.checked()), isCheckboxUncontrolled(props) ? omitProps(props, ['as', 'children', 'defaultChecked', 'disabled', 'onChange']) : omitProps(props, ['as', 'children', 'checked', 'disabled', 'onChange']), { get children() { return createComponent(CheckStateProvider, { state, get children() { return props.children; }, }); }, }, ) as DynamicProps, ); }, }); }