import type { JSX } from 'solid-js'; import { createComponent, createUniqueId, mergeProps } from 'solid-js'; import { omitProps } from 'solid-use/props'; import type { DisclosureStateControlledOptions, DisclosureStateRenderProps, DisclosureStateUncontrolledOptions, } from '../../states/create-disclosure-state'; import { DisclosureStateProvider, createDisclosureState, } from '../../states/create-disclosure-state'; import createDynamic from '../../utils/create-dynamic'; import type { DynamicProps, HeadlessProps, ValidConstructor, } from '../../utils/dynamic-prop'; import { createARIADisabledState, createDisabledState, createExpandedState, } from '../../utils/state-props'; import type { Prettify } from '../../utils/types'; import { DisclosureContext } from './DisclosureContext'; import { DISCLOSURE_TAG } from './tags'; export type DisclosureControlledBaseProps = Prettify< DisclosureStateControlledOptions & DisclosureStateRenderProps >; export type DisclosureControlledProps = HeadlessProps; export type DisclosureUncontrolledBaseProps = Prettify< DisclosureStateUncontrolledOptions & DisclosureStateRenderProps >; export type DisclosureUncontrolledProps = HeadlessProps; export type DisclosureProps = | DisclosureControlledProps | DisclosureUncontrolledProps; function isDisclosureUncontrolled( props: DisclosureProps, ): props is DisclosureUncontrolledProps { return 'defaultOpen' in props; } export function Disclosure( props: DisclosureProps, ): JSX.Element { const ownerID = createUniqueId(); const buttonID = createUniqueId(); const panelID = createUniqueId(); const state = createDisclosureState(props); return createComponent(DisclosureContext.Provider, { value: { ownerID, buttonID, panelID, }, get children() { return createDynamic( () => props.as || 'div', mergeProps( DISCLOSURE_TAG, createDisabledState(() => state.disabled()), createARIADisabledState(() => state.disabled()), createExpandedState(() => state.isOpen()), isDisclosureUncontrolled(props) ? omitProps(props, [ 'as', 'children', 'defaultOpen', 'disabled', 'onChange', 'onClose', 'onOpen', ]) : omitProps(props, [ 'as', 'children', 'isOpen', 'disabled', 'onChange', 'onClose', 'onOpen', ]), { get children() { return createComponent(DisclosureStateProvider, { state, get children() { return props.children; }, }); }, }, ) as DynamicProps, ); }, }); }