mirror of
https://github.com/zhigang1992/react.git
synced 2026-04-25 21:05:36 +08:00
style(prettier): format code style
This commit is contained in:
@@ -9,64 +9,64 @@ describe('Collapse Group', () => {
|
||||
<Collapse.Group>
|
||||
<Collapse title="title1">content1</Collapse>
|
||||
<Collapse title="title2">content2</Collapse>
|
||||
</Collapse.Group>
|
||||
</Collapse.Group>,
|
||||
)
|
||||
|
||||
|
||||
expect(wrapper).toMatchSnapshot()
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
|
||||
it('should be no errors when children are missing', () => {
|
||||
const wrapper = mount(<Collapse.Group></Collapse.Group>)
|
||||
|
||||
|
||||
expect(wrapper).toMatchSnapshot()
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
|
||||
it('should work without accordion', () => {
|
||||
const wrapper = render(
|
||||
<Collapse.Group accordion={false}>
|
||||
<Collapse title="title1">content1</Collapse>
|
||||
<Collapse title="title2">content2</Collapse>
|
||||
</Collapse.Group>
|
||||
</Collapse.Group>,
|
||||
)
|
||||
expect(wrapper).toMatchSnapshot()
|
||||
})
|
||||
|
||||
|
||||
it('should be display all when without accordion', async () => {
|
||||
const wrapper = mount(
|
||||
<Collapse.Group accordion={false}>
|
||||
<Collapse title="title1">content1</Collapse>
|
||||
<Collapse title="title2">content2</Collapse>
|
||||
</Collapse.Group>
|
||||
</Collapse.Group>,
|
||||
)
|
||||
|
||||
|
||||
const views = wrapper.find('.view')
|
||||
views.at(0).simulate('click')
|
||||
views.at(1).simulate('click')
|
||||
await updateWrapper(wrapper, 300)
|
||||
expect(wrapper.find('.expanded').length).toBe(2)
|
||||
|
||||
|
||||
views.at(0).simulate('click')
|
||||
views.at(1).simulate('click')
|
||||
await updateWrapper(wrapper, 300)
|
||||
expect(wrapper.find('.expanded').length).toBe(0)
|
||||
})
|
||||
|
||||
|
||||
it('should be display one when in accordion mode', async () => {
|
||||
const wrapper = mount(
|
||||
<Collapse.Group>
|
||||
<Collapse title="title1">content1</Collapse>
|
||||
<Collapse title="title2">content2</Collapse>
|
||||
</Collapse.Group>
|
||||
</Collapse.Group>,
|
||||
)
|
||||
|
||||
|
||||
const views = wrapper.find('.view')
|
||||
views.at(0).simulate('click')
|
||||
views.at(1).simulate('click')
|
||||
await updateWrapper(wrapper, 300)
|
||||
expect(wrapper.find('.expanded').length).toBe(1)
|
||||
|
||||
|
||||
views.at(1).simulate('click')
|
||||
await updateWrapper(wrapper, 300)
|
||||
expect(wrapper.find('.expanded').length).toBe(0)
|
||||
|
||||
@@ -9,38 +9,45 @@ describe('Collapse', () => {
|
||||
expect(wrapper).toMatchSnapshot()
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
|
||||
it('should work with subtitle and shadow', () => {
|
||||
const wrapper = render(
|
||||
<div>
|
||||
<Collapse title="title" subtitle="subtitle">content</Collapse>
|
||||
<Collapse title="title" subtitle="subtitle" shadow>content</Collapse>
|
||||
</div>
|
||||
<Collapse title="title" subtitle="subtitle">
|
||||
content
|
||||
</Collapse>
|
||||
<Collapse title="title" subtitle="subtitle" shadow>
|
||||
content
|
||||
</Collapse>
|
||||
</div>,
|
||||
)
|
||||
expect(wrapper).toMatchSnapshot()
|
||||
})
|
||||
|
||||
|
||||
it('should work with initial visible', () => {
|
||||
const wrapper = render(
|
||||
<div>
|
||||
<Collapse title="title" subtitle="subtitle">content</Collapse>
|
||||
<Collapse title="title" initialVisible>content</Collapse>
|
||||
</div>
|
||||
<Collapse title="title" subtitle="subtitle">
|
||||
content
|
||||
</Collapse>
|
||||
<Collapse title="title" initialVisible>
|
||||
content
|
||||
</Collapse>
|
||||
</div>,
|
||||
)
|
||||
expect(wrapper).toMatchSnapshot()
|
||||
})
|
||||
|
||||
|
||||
it('should throw error when title missing', () => {
|
||||
const Component = Collapse as any
|
||||
let errorMessage = ''
|
||||
const errorSpy = jest.spyOn(console, 'error')
|
||||
.mockImplementation(msg => errorMessage = msg)
|
||||
|
||||
const errorSpy = jest.spyOn(console, 'error').mockImplementation((msg) => (errorMessage = msg))
|
||||
|
||||
mount(<Component subtitle="subtitle">content</Component>)
|
||||
expect(errorMessage.toLowerCase()).not.toEqual('')
|
||||
errorSpy.mockRestore()
|
||||
})
|
||||
|
||||
|
||||
it('should expand when title clicked', async () => {
|
||||
const wrapper = mount(<Collapse title="title">content</Collapse>)
|
||||
wrapper.find('.view').at(0).simulate('click')
|
||||
|
||||
@@ -11,4 +11,5 @@ const defaultContext = {
|
||||
|
||||
export const CollapseContext = React.createContext<CollapseConfig>(defaultContext)
|
||||
|
||||
export const useCollapseContext = (): CollapseConfig => React.useContext<CollapseConfig>(CollapseContext)
|
||||
export const useCollapseContext = (): CollapseConfig =>
|
||||
React.useContext<CollapseConfig>(CollapseContext)
|
||||
|
||||
@@ -20,17 +20,20 @@ type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type CollapseGroupProps = Props & typeof defaultProps & NativeAttrs
|
||||
|
||||
const CollapseGroup: React.FC<React.PropsWithChildren<CollapseGroupProps>> = ({
|
||||
children, accordion, className, ...props
|
||||
children,
|
||||
accordion,
|
||||
className,
|
||||
...props
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const [state, setState, stateRef] = useCurrentState<Array<number>>([])
|
||||
const updateValues = (currentIndex: number, nextState: boolean) => {
|
||||
const hasChild = stateRef.current.find(val => val === currentIndex)
|
||||
const hasChild = stateRef.current.find((val) => val === currentIndex)
|
||||
if (accordion) {
|
||||
if (nextState) return setState([currentIndex])
|
||||
return setState([])
|
||||
}
|
||||
|
||||
|
||||
if (nextState) {
|
||||
// In a few cases, the user will set Collapse Component state manually.
|
||||
// If the user incorrectly set the state, Group component should ignore it.
|
||||
@@ -38,14 +41,17 @@ const CollapseGroup: React.FC<React.PropsWithChildren<CollapseGroupProps>> = ({
|
||||
if (hasChild) return
|
||||
return setState([...stateRef.current, currentIndex])
|
||||
}
|
||||
setState(stateRef.current.filter(item => item !== currentIndex))
|
||||
setState(stateRef.current.filter((item) => item !== currentIndex))
|
||||
}
|
||||
|
||||
const initialValue = useMemo<CollapseConfig>(() => ({
|
||||
values: state,
|
||||
updateValues,
|
||||
}), [state.join(',')])
|
||||
|
||||
|
||||
const initialValue = useMemo<CollapseConfig>(
|
||||
() => ({
|
||||
values: state,
|
||||
updateValues,
|
||||
}),
|
||||
[state.join(',')],
|
||||
)
|
||||
|
||||
const hasIndexChildren = useMemo(() => setChildrenIndex(children, [Collapse]), [children])
|
||||
|
||||
return (
|
||||
@@ -57,8 +63,8 @@ const CollapseGroup: React.FC<React.PropsWithChildren<CollapseGroupProps>> = ({
|
||||
width: auto;
|
||||
padding: 0 ${theme.layout.gapHalf};
|
||||
}
|
||||
|
||||
.collapse-group > :global(div+div) {
|
||||
|
||||
.collapse-group > :global(div + div) {
|
||||
border-top: none;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
@@ -6,10 +6,19 @@ interface Props {
|
||||
|
||||
const CollapseIcon: React.FC<Props> = ({ active }) => {
|
||||
return (
|
||||
<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"
|
||||
strokeLinejoin="round" fill="none" shapeRendering="geometricPrecision" style={{ color: 'currentColor' }}>
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
height="24"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
fill="none"
|
||||
shapeRendering="geometricPrecision"
|
||||
style={{ color: 'currentColor' }}>
|
||||
<path d="M6 9l6 6 6-6" />
|
||||
|
||||
|
||||
<style jsx>{`
|
||||
svg {
|
||||
transition: transform 200ms ease;
|
||||
|
||||
@@ -26,20 +26,26 @@ type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type CollapseProps = Props & typeof defaultProps & NativeAttrs
|
||||
|
||||
const Collapse: React.FC<React.PropsWithChildren<CollapseProps>> = ({
|
||||
children, title, subtitle, initialVisible, shadow, className,
|
||||
index, ...props
|
||||
children,
|
||||
title,
|
||||
subtitle,
|
||||
initialVisible,
|
||||
shadow,
|
||||
className,
|
||||
index,
|
||||
...props
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const [visible, setVisible, visibleRef] = useCurrentState<boolean>(initialVisible)
|
||||
const { values, updateValues } = useCollapseContext()
|
||||
|
||||
|
||||
if (!title) {
|
||||
useWarning('"title" is required.', 'Collapse')
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!values.length) return
|
||||
const isActive = !!values.find(item => item === index)
|
||||
const isActive = !!values.find((item) => item === index)
|
||||
setVisible(isActive)
|
||||
}, [values.join(',')])
|
||||
|
||||
@@ -48,7 +54,7 @@ const Collapse: React.FC<React.PropsWithChildren<CollapseProps>> = ({
|
||||
setVisible(next)
|
||||
updateValues && updateValues(index, next)
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className={`collapse ${shadow ? 'shadow' : ''} ${className}`} {...props}>
|
||||
<div className="view" role="button" onClick={clickHandler}>
|
||||
@@ -58,18 +64,15 @@ const Collapse: React.FC<React.PropsWithChildren<CollapseProps>> = ({
|
||||
{subtitle && <div className="subtitle">{subtitle}</div>}
|
||||
</div>
|
||||
<Expand isExpanded={visible}>
|
||||
<div className="content">
|
||||
{children}
|
||||
</div>
|
||||
<div className="content">{children}</div>
|
||||
</Expand>
|
||||
<style jsx>{`
|
||||
.collapse {
|
||||
padding: ${theme.layout.gap} 0;
|
||||
border-top: 1px solid ${theme.palette.border};
|
||||
border-bottom: 1px solid ${theme.palette.border};
|
||||
|
||||
}
|
||||
|
||||
|
||||
.shadow {
|
||||
box-shadow: ${theme.expressiveness.shadowSmall};
|
||||
border: none;
|
||||
@@ -81,37 +84,37 @@ const Collapse: React.FC<React.PropsWithChildren<CollapseProps>> = ({
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: ${theme.palette.foreground};
|
||||
}
|
||||
|
||||
|
||||
.title h3 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
.subtitle {
|
||||
color: ${theme.palette.accents_5};
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
.subtitle > :global(*) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
.content {
|
||||
font-size: 1rem;
|
||||
line-height: 1.625rem;
|
||||
padding: ${theme.layout.gap} 0;
|
||||
}
|
||||
|
||||
|
||||
.content > :global(*:first-child) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
|
||||
.content > :global(*:last-child) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
@@ -126,6 +129,8 @@ type CollapseComponent<P = {}> = React.FC<P> & {
|
||||
Group: typeof CollapseGroup
|
||||
}
|
||||
|
||||
type ComponentProps = Partial<typeof defaultProps> & Omit<Props, keyof typeof defaultProps> & NativeAttrs
|
||||
type ComponentProps = Partial<typeof defaultProps> &
|
||||
Omit<Props, keyof typeof defaultProps> &
|
||||
NativeAttrs
|
||||
|
||||
export default Collapse as CollapseComponent<ComponentProps>
|
||||
|
||||
Reference in New Issue
Block a user