import { ActionsDelete, NavigationCircleDown, NavigationCircleUp } from '@repay/cactus-icons' import React, { Fragment, ReactElement, useCallback, useState } from 'react' import { Accordion, Box, Flex, IconButton, Text, TextButton } from '../' import { Action, actions, HIDE_CONTROL, SPACE, Story, STRING } from '../helpers/storybook' interface ContentManagerState { [group: number]: number } type ContentManagerParams = ContentManagerState & { changeContent: (group: number, increase?: boolean) => void } const initializeContent = (): ContentManagerState => { let num = 4 const state: ContentManagerState = {} do { state[num] = 0 } while (--num >= 0) return state } const ContentManager = ({ children, }: { children: (params: ContentManagerParams) => JSX.Element }): ReactElement => { const [state, setState] = useState(initializeContent) const changeContent = useCallback( (group: number, increase?: boolean): void => setState((s): ContentManagerState => { let value = s[group] || 0 if (increase) { ++value } else if (value > 0) { --value } return { ...s, [group]: value } }), [setState] ) return children({ ...state, changeContent }) } const ContentBlocks = ({ number: num }: { number: number }): ReactElement | null => { if (num < 1) { return null } const children = [] for (let i = 0; i < num; ++i) { children.push( {longText} ) } return {children} } type ChangeArg = { onChange: Action } type ControlledArgs = { isControlled: boolean } & ChangeArg const WithOutline: Story = ({ isControlled, onChange, ...args }) => { const [open, setOpen] = useState([]) const toggleAccordion = (toggleId: string) => { setOpen((currentOpen) => { if (currentOpen.includes(toggleId)) { return currentOpen.filter((id) => id !== toggleId) } return [...currentOpen, toggleId] }) } const [accordionHeaders, setAccordionHeaders] = useState([ 'First Accordion', 'Second Accordion', 'Third Accordion', 'Fourth Accordion', 'Fifth Accordion', ]) const handleChange = isControlled ? onChange.wrap(toggleAccordion) : onChange const handleUpClick = (index: number): void => { const headersCopy = [...accordionHeaders] const temp = headersCopy[index - 1] headersCopy[index - 1] = headersCopy[index] headersCopy[index] = temp setAccordionHeaders(headersCopy) } const handleDownClick = (index: number): void => { const headersCopy = [...accordionHeaders] const temp = headersCopy[index + 1] headersCopy[index + 1] = headersCopy[index] headersCopy[index] = temp setAccordionHeaders(headersCopy) } const handleDelete = (index: number): void => { const headersCopy = [...accordionHeaders] headersCopy.splice(index, 1) setAccordionHeaders(headersCopy) } return ( {accordionHeaders.map( (header, index): ReactElement => ( { return ( {header} {isOpen && ( ): void => { handleDelete(index) e.stopPropagation() }} > )} ): void => { handleDownClick(index) e.stopPropagation() }} disabled={index === accordionHeaders.length - 1} > ): void => { handleUpClick(index) e.stopPropagation() }} disabled={index === 0} > ) }} /> {longText} ) )} ) } export default { title: 'Accordion', component: Accordion, argTypes: { defaultOpen: HIDE_CONTROL }, } as const interface LabelArgs { header: string content: string } // Force remount when defaultOpen changes, otherwise it has no effect. export const BasicUsage: Story = ({ header, content, margin, ...props }) => ( {header} {content} ) BasicUsage.argTypes = { defaultOpen: { control: 'boolean' }, header: STRING, content: STRING, margin: SPACE, } BasicUsage.args = { header: 'Accordion', content: 'Some Accordion Content', } export const Long: Story = ({ header, content, ...props }) => ( {header} {content} ) Long.argTypes = { header: STRING, content: STRING } Long.args = BasicUsage.args const longText = ` Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas pulvinar, mauris eu tempor accumsan, arcu nibh mattis tortor, id feugiat velit diam et massa. Vestibulum lacinia ultrices urna, non rhoncus justo mollis vitae. Integer facilisis gravida ex, nec euismod augue aliquam vel. ` interface ProviderArgs { accordions: string[] maxOpen: number } export const Provider: Story = ({ accordions, maxOpen, ...props }) => ( {accordions.map((header, ix) => ( {header} {longText} ))} ) Provider.args = { maxOpen: 1, accordions: ['Accordion 1', 'Accordion 2', 'Accordion 3', 'Accordion 4'], } Provider.parameters = { cactus: { overrides: { height: '150vh' } } } export const WithDynamicContent: Story = (args) => ( {({ changeContent, ...state }): ReactElement => { return ( {((): JSX.Element[] => { const blocks = [] let index = 0 while (typeof state[index] === 'number') { const group = index blocks.push( {group} Accordion {(!state[group] || state[group] < 10) && ( changeContent(group, true)} variant="action" > Add One Block )} {state[group] > 0 && ( changeContent(group)} variant="danger"> Remove One Block )} ) index++ } return blocks })()} ) }} ) type OpenArgs = ProviderArgs & ChangeArg export const WithOpenInitialization: Story = ({ accordions, maxOpen, onChange, ...args }) => ( {accordions.map((header, ix) => ( {header} {longText} ))} ) WithOpenInitialization.argTypes = actions('onChange') WithOpenInitialization.args = { maxOpen: 2, accordions: ['Accordion 1', 'Accordion 2'] } export { WithOutline } WithOutline.argTypes = actions('onChange') WithOutline.args = { variant: 'outline', isControlled: false }