/* * Portions of this file are based on code from react-spectrum. * Apache License Version 2.0, Copyright 2020 Adobe. * * Credits to the React Spectrum team: * https://github.com/adobe/react-spectrum/blob/c183944ce6a8ca1cf280a1c7b88d2ba393dd0252/packages/@react-aria/accordion/src/useAccordion.ts */ import { createGenerateId, mergeDefaultProps } from "@kobalte/utils"; import { type Component, JSX, type ValidComponent, createSignal, createUniqueId, splitProps, } from "solid-js"; import * as Collapsible from "../collapsible"; import { ElementOf, type PolymorphicProps } from "../polymorphic"; import { createRegisterId } from "../primitives"; import { useAccordionContext } from "./accordion-context"; import { AccordionItemContext, type AccordionItemContextValue, } from "./accordion-item-context"; export interface AccordionItemOptions { /** A unique value for the item. */ value: string; /** Whether the item is disabled. */ disabled?: boolean; /** * Used to force mounting the item content when more control is needed. * Useful when controlling animation with SolidJS animation libraries. */ forceMount?: boolean; } export interface AccordionItemCommonProps extends Collapsible.CollapsibleRootCommonProps {} export interface AccordionItemRenderProps extends AccordionItemCommonProps, Collapsible.CollapsibleRootRenderProps {} export type AccordionItemProps< T extends ValidComponent | HTMLElement = HTMLElement, > = AccordionItemOptions & Partial; /** * An item of the accordion, contains all the parts of a collapsible section. */ export function AccordionItem( props: PolymorphicProps>, ) { const accordionContext = useAccordionContext(); const defaultId = `${accordionContext.generateId( "item", )}-${createUniqueId()}`; const mergedProps = mergeDefaultProps( { id: defaultId }, props as AccordionItemProps, ); const [local, others] = splitProps(mergedProps, ["value", "disabled"]); const [triggerId, setTriggerId] = createSignal(); const [contentId, setContentId] = createSignal(); const selectionManager = () => accordionContext.listState().selectionManager(); const isExpanded = () => { return selectionManager().isSelected(local.value); }; const context: AccordionItemContextValue = { value: () => local.value, triggerId, contentId, generateId: createGenerateId(() => others.id!), registerTriggerId: createRegisterId(setTriggerId), registerContentId: createRegisterId(setContentId), }; return ( > > open={isExpanded()} disabled={local.disabled} {...others} /> ); }