import type { AnimatePresenceProps } from '@tamagui/animate-presence' import { AnimatePresence, ResetPresence } from '@tamagui/animate-presence' import { composeEventHandlers, withStaticProperties } from '@tamagui/helpers' import type { YStackProps } from '@tamagui/stacks' import { useControllableState } from '@tamagui/use-controllable-state' import type { GetProps, ViewProps, TamaguiElement } from '@tamagui/web' import { View, createStyledContext, styled } from '@tamagui/web' import * as React from 'react' /* ------------------------------------------------------------------------------------------------- * Collapsible * -----------------------------------------------------------------------------------------------*/ const COLLAPSIBLE_NAME = 'Collapsible' type ScopedProps

= P & { __scopeCollapsible?: string } type CollapsibleContextValue = { contentId: string disabled?: boolean open: boolean onOpenToggle(): void } const { Provider: CollapsibleProvider, useStyledContext: useCollapsibleContext } = createStyledContext() interface CollapsibleProps extends ViewProps { defaultOpen?: boolean open?: boolean disabled?: boolean onOpenChange?(open: boolean): void } const _Collapsible = React.forwardRef>( (props, forwardedRef) => { const { __scopeCollapsible, open: openProp, defaultOpen, disabled, onOpenChange, ...collapsibleProps } = props const [open = false, setOpen] = useControllableState({ prop: openProp, defaultProp: defaultOpen!, onChange: onOpenChange, }) return ( setOpen((prevOpen) => !prevOpen), [setOpen] )} > ) } ) _Collapsible.displayName = COLLAPSIBLE_NAME /* ------------------------------------------------------------------------------------------------- * CollapsibleTrigger * -----------------------------------------------------------------------------------------------*/ const TRIGGER_NAME = 'CollapsibleTrigger' type CollapsibleTriggerProps = GetProps const CollapsibleTriggerFrame = styled(View, { name: TRIGGER_NAME, render: 'button', }) const CollapsibleTrigger = CollapsibleTriggerFrame.styleable( (props: ScopedProps, forwardedRef) => { const { __scopeCollapsible, children, ...triggerProps } = props const context = useCollapsibleContext(__scopeCollapsible) return ( {typeof children === 'function' ? children({ open: context.open }) : children} ) } ) CollapsibleTrigger.displayName = TRIGGER_NAME /* ------------------------------------------------------------------------------------------------- * CollapsibleContent * -----------------------------------------------------------------------------------------------*/ export interface CollapsibleContentExtraProps extends AnimatePresenceProps { /** * Used to force mounting when more control is needed. Useful when * controlling animation with React animation libraries. */ forceMount?: boolean } interface CollapsibleContentProps extends CollapsibleContentExtraProps, YStackProps {} const CONTENT_NAME = 'CollapsibleContent' const CollapsibleContentFrame = styled(View, { name: CONTENT_NAME, }) const CollapsibleContent = CollapsibleContentFrame.styleable( (props, forwardedRef) => { const { forceMount, children, // @ts-expect-error __scopeCollapsible, ...contentProps } = props const context = useCollapsibleContext(__scopeCollapsible) return ( {forceMount || context.open ? ( {children} ) : null} ) } ) CollapsibleContent.displayName = CONTENT_NAME /* -----------------------------------------------------------------------------------------------*/ function getState(open?: boolean) { return open ? 'open' : 'closed' } const Collapsible = withStaticProperties(_Collapsible, { Trigger: CollapsibleTrigger, Content: CollapsibleContent, }) export { Collapsible, CollapsibleContent, CollapsibleContentFrame, CollapsibleTrigger, CollapsibleTriggerFrame, } export type { CollapsibleContentProps, CollapsibleProps, CollapsibleTriggerProps }