style(prettier): format code style

This commit is contained in:
unix
2020-05-06 14:18:28 +08:00
parent cf8e277324
commit 112c826575
263 changed files with 4927 additions and 3992 deletions

View File

@@ -9,7 +9,7 @@ describe('AutoComplete', () => {
expect(() => wrapper.unmount()).not.toThrow()
expect(<AutoComplete />).toMatchSnapshot()
})
it('should support sizes and status', () => {
const wrapper = mount(
<div>
@@ -17,37 +17,37 @@ describe('AutoComplete', () => {
<AutoComplete status="success" />
<AutoComplete size="mini" />
<AutoComplete size="large" />
</div>
</div>,
)
expect(() => wrapper.unmount()).not.toThrow()
})
it('should set input value from initial value', () => {
let wrapper = mount(<AutoComplete initialValue="value" />)
let input = wrapper.find('input').at(0).getDOMNode()
expect((input as HTMLInputElement).value).toEqual('value')
wrapper = mount(<AutoComplete value="value2" />)
input = wrapper.find('input').at(0).getDOMNode()
expect((input as HTMLInputElement).value).toEqual('value2')
})
it('should render clear icon', () => {
const wrapper = mount(<AutoComplete initialValue="value" />)
expect(wrapper.find('svg').length).toBe(0)
wrapper.setProps({ clearable: true })
expect(wrapper.find('svg').length).toBe(1)
wrapper.find('svg').simulate('click', nativeEvent)
const input = wrapper.find('input').at(0).getDOMNode()
expect((input as HTMLInputElement).value).toEqual('')
})
it('should reponse width change', () => {
const wrapper = mount(<AutoComplete initialValue="value" width="100px" />)
expect(wrapper.prop('width')).toEqual('100px')
wrapper.setProps({ width: '200px' })
expect(wrapper.prop('width')).toEqual('200px')
})

View File

@@ -2,9 +2,7 @@ import React from 'react'
import { mount, render } from 'enzyme'
import { AutoComplete } from 'components'
import { nativeEvent } from 'tests/utils'
const mockOptions = [
{ label: 'London', value: 'london' },
]
const mockOptions = [{ label: 'London', value: 'london' }]
describe('AutoComplete Search', () => {
it('should render options element', () => {
@@ -12,88 +10,85 @@ describe('AutoComplete Search', () => {
wrapper.find('input').at(0).simulate('focus')
let dropdown = wrapper.find('.auto-complete-dropdown').children()
expect(dropdown.length).not.toBe(0)
wrapper.find('input').at(0).simulate('blur')
expect(() => wrapper.unmount()).not.toThrow()
})
it('should update value when dropdown clicked', () => {
let value = ''
const wrapper = mount(<AutoComplete options={mockOptions} onChange={val => value = val} />)
const wrapper = mount(<AutoComplete options={mockOptions} onChange={(val) => (value = val)} />)
wrapper.find('input').at(0).simulate('focus')
wrapper.find('.item').at(0).simulate('click', nativeEvent)
expect(value).toEqual('london')
})
it('should ignore events when disabled', () => {
let value = ''
const wrapper = mount(
<AutoComplete disabled options={mockOptions}
onChange={val => value = val} />
<AutoComplete disabled options={mockOptions} onChange={(val) => (value = val)} />,
)
wrapper.find('input').at(0).simulate('focus')
wrapper.find('.item').at(0).simulate('click', nativeEvent)
expect(value).not.toEqual('london')
})
it('should render searching component', () => {
let wrapper = mount(
<AutoComplete searching={false} options={mockOptions}/>
)
let wrapper = mount(<AutoComplete searching={false} options={mockOptions} />)
wrapper.setProps({ searching: true })
wrapper.find('input').at(0).simulate('focus')
let dropdown = wrapper.find('.auto-complete-dropdown')
expect(dropdown.text()).not.toContain('london')
const loading = wrapper.find('.loading')
expect(loading.length).not.toBe(0)
wrapper = mount(
<AutoComplete searching options={mockOptions}>
<AutoComplete.Searching>
<span>waiting...</span>
</AutoComplete.Searching>
</AutoComplete>
</AutoComplete>,
)
wrapper.find('input').at(0).simulate('focus')
dropdown = wrapper.find('.auto-complete-dropdown')
expect(dropdown.text()).toContain('waiting')
})
it('should hide empty component', () => {
let wrapper = render(
<AutoComplete placeholder="Enter here">
<AutoComplete.Empty hidden />
</AutoComplete>
</AutoComplete>,
)
expect(wrapper).toMatchSnapshot()
wrapper = render(
<AutoComplete placeholder="Enter here">
<AutoComplete.Empty>empty</AutoComplete.Empty>
</AutoComplete>
</AutoComplete>,
)
expect(wrapper).toMatchSnapshot()
const mountWrapper = mount(
<AutoComplete placeholder="Enter here" initialValue="value">
<AutoComplete.Empty>empty</AutoComplete.Empty>
</AutoComplete>
</AutoComplete>,
)
mountWrapper.find('input').at(0).simulate('focus')
const text = mountWrapper.find('.auto-complete-dropdown').text()
expect(text).toContain('empty')
const mountWrapper2 = mount(
<AutoComplete placeholder="Enter here" initialValue="value">
<AutoComplete.Empty hidden>empty</AutoComplete.Empty>
</AutoComplete>
</AutoComplete>,
)
mountWrapper2.find('input').at(0).simulate('focus')
const text2 = mountWrapper2.find('.auto-complete-dropdown').text()
expect(text2).not.toContain('empty')
})
it('should trigger search handler', () => {
const handler = jest.fn()
const wrapper = mount(<AutoComplete initialValue="value" onSearch={handler} />)
@@ -103,20 +98,24 @@ describe('AutoComplete Search', () => {
;(input.getDOMNode() as HTMLInputElement).value = 'value'
expect(handler).toHaveBeenCalled()
})
it('should trigger select and change handler', () => {
const selectHandler = jest.fn()
const changeHandler = jest.fn()
const wrapper = mount(
<AutoComplete options={mockOptions} initialValue="value"
onSelect={selectHandler} onChange={changeHandler} />
<AutoComplete
options={mockOptions}
initialValue="value"
onSelect={selectHandler}
onChange={changeHandler}
/>,
)
wrapper.find('input').at(0).simulate('focus')
wrapper.find('.item').at(0).simulate('click', nativeEvent)
expect(selectHandler).toHaveBeenCalled()
expect(changeHandler).toHaveBeenCalled()
})
it('should work with custom options', () => {
const changeHandler = jest.fn()
const makeOption = (label: string, value: string): any => (
@@ -124,19 +123,17 @@ describe('AutoComplete Search', () => {
<span>{label}</span>
</AutoComplete.Option>
)
const options = mockOptions
.map(({ label, value }) => makeOption(label, value) as typeof AutoComplete.Option)
const wrapper = mount(
<AutoComplete options={options} onChange={changeHandler} />
const options = mockOptions.map(
({ label, value }) => makeOption(label, value) as typeof AutoComplete.Option,
)
const wrapper = mount(<AutoComplete options={options} onChange={changeHandler} />)
wrapper.find('input').at(0).simulate('focus')
wrapper.find('.item').at(0).simulate('click', nativeEvent)
expect(changeHandler).toHaveBeenCalled()
})
it('should work correctly without options', () => {
const wrapper = mount(<AutoComplete options={[]} />)
expect(() => wrapper.unmount()).not.toThrow()
})
})

View File

@@ -17,4 +17,5 @@ const defaultContext = {
export const AutoCompleteContext = React.createContext<AutoCompleteConfig>(defaultContext)
export const useAutoCompleteContext = (): AutoCompleteConfig => React.useContext<AutoCompleteConfig>(AutoCompleteContext)
export const useAutoCompleteContext = (): AutoCompleteConfig =>
React.useContext<AutoCompleteConfig>(AutoCompleteContext)

View File

@@ -7,9 +7,7 @@ interface Props {
visible: boolean
}
const AutoCompleteDropdown: React.FC<React.PropsWithChildren<Props>> = ({
children, visible
}) => {
const AutoCompleteDropdown: React.FC<React.PropsWithChildren<Props>> = ({ children, visible }) => {
const theme = useTheme()
const { ref } = useAutoCompleteContext()
const clickHandler = (event: React.MouseEvent<HTMLDivElement>) => {
@@ -17,18 +15,18 @@ const AutoCompleteDropdown: React.FC<React.PropsWithChildren<Props>> = ({
event.stopPropagation()
event.nativeEvent.stopImmediatePropagation()
}
return (
<Dropdown parent={ref} visible={visible}>
<div className="auto-complete-dropdown" onClick={clickHandler}>
{children}
<style jsx>{`
.auto-complete-dropdown {
border-radius: ${theme.layout.radius};
box-shadow: ${theme.expressiveness.shadowLarge};
background-color: ${theme.palette.background};
}
`}</style>
.auto-complete-dropdown {
border-radius: ${theme.layout.radius};
box-shadow: ${theme.expressiveness.shadowLarge};
background-color: ${theme.palette.background};
}
`}</style>
</div>
</Dropdown>
)

View File

@@ -15,7 +15,9 @@ const defaultProps = {
export type AutoCompleteEmptyProps = Props & typeof defaultProps & React.HTMLAttributes<any>
const AutoCompleteEmpty: React.FC<React.PropsWithChildren<AutoCompleteEmptyProps>> = ({
children, hidden, className,
children,
hidden,
className,
}) => {
if (hidden) return null
return <AutoCompleteSearch className={className}>{children}</AutoCompleteSearch>

View File

@@ -8,8 +8,7 @@ interface Props {
value: string
}
const defaultProps = {
}
const defaultProps = {}
export type AutoCompleteItemProps = Props & typeof defaultProps & React.HTMLAttributes<any>
@@ -24,17 +23,18 @@ const getSizes = (size: NormalSizes) => {
}
const AutoCompleteItem: React.FC<React.PropsWithChildren<AutoCompleteItemProps>> = ({
value: identValue, children,
value: identValue,
children,
}) => {
const theme = useTheme()
const { value, updateValue, size } = useAutoCompleteContext()
const selectHandler = () => {
updateValue && updateValue(identValue)
}
const isActive = useMemo(() => value === identValue, [identValue, value])
const fontSize = useMemo(() => getSizes(size), [size])
return (
<div className={`item ${isActive ? 'active' : ''}`} onClick={selectHandler}>
{children}
@@ -55,21 +55,21 @@ const AutoCompleteItem: React.FC<React.PropsWithChildren<AutoCompleteItemProps>>
cursor: pointer;
transition: background 0.2s ease 0s, border-color 0.2s ease 0s;
}
.item:first-of-type {
border-top-left-radius: ${theme.layout.radius};
border-top-right-radius: ${theme.layout.radius};
}
.item:last-of-type {
border-bottom-left-radius: ${theme.layout.radius};
border-bottom-right-radius: ${theme.layout.radius};
}
.item:hover {
background-color: ${theme.palette.accents_1};
}
.item.active {
background-color: ${theme.palette.accents_1};
color: ${theme.palette.success};

View File

@@ -13,7 +13,8 @@ const defaultProps = {
export type AutoCompleteSearchProps = Props & typeof defaultProps & React.HTMLAttributes<any>
const AutoCompleteSearch: React.FC<React.PropsWithChildren<AutoCompleteSearchProps>> = ({
children, className,
children,
className,
}) => {
const theme = useTheme()
@@ -28,7 +29,7 @@ const AutoCompleteSearch: React.FC<React.PropsWithChildren<AutoCompleteSearchPro
align-items: center;
font-weight: normal;
white-space: pre;
font-size: .875rem;
font-size: 0.875rem;
padding: ${theme.layout.gapHalf};
line-height: 1;
background-color: ${theme.palette.background};

View File

@@ -49,8 +49,7 @@ const childrenToOptionsNode = (options: Array<AutoCompleteOption>) =>
if (React.isValidElement(item)) return React.cloneElement(item, { key })
const validItem = item as AutoCompleteOption
return (
<AutoCompleteItem key={key}
value={validItem.value}>
<AutoCompleteItem key={key} value={validItem.value}>
{validItem.label}
</AutoCompleteItem>
)
@@ -64,9 +63,20 @@ const getSearchIcon = (searching?: boolean) => {
}
const AutoComplete: React.FC<React.PropsWithChildren<AutoCompleteProps>> = ({
options, initialValue: customInitialValue, onSelect, onSearch, onChange,
searching, children, size, status, value, width, clearable,
disabled, ...props
options,
initialValue: customInitialValue,
onSelect,
onSearch,
onChange,
searching,
children,
size,
status,
value,
width,
clearable,
disabled,
...props
}) => {
const ref = useRef<HTMLDivElement>(null)
const [state, setState] = useState<string>(customInitialValue)
@@ -77,7 +87,11 @@ const AutoComplete: React.FC<React.PropsWithChildren<AutoCompleteProps>> = ({
const hasSearchChild = searchChild && React.Children.count(searchChild) > 0
const hasEmptyChild = emptyChild && React.Children.count(emptyChild) > 0
if (searching) {
return hasSearchChild ? searchChild : <AutoCompleteSearching>Searching...</AutoCompleteSearching>
return hasSearchChild ? (
searchChild
) : (
<AutoCompleteSearching>Searching...</AutoCompleteSearching>
)
}
if (options.length === 0) {
if (state === '') return null
@@ -85,11 +99,8 @@ const AutoComplete: React.FC<React.PropsWithChildren<AutoCompleteProps>> = ({
}
return childrenToOptionsNode(options as Array<AutoCompleteOption>)
}, [searching, options])
const showClearIcon = useMemo(
() => clearable && searching === undefined,
[clearable, searching],
)
const showClearIcon = useMemo(() => clearable && searching === undefined, [clearable, searching])
const updateValue = (val: string) => {
if (disabled) return
onSelect && onSelect(val)
@@ -100,7 +111,7 @@ const AutoComplete: React.FC<React.PropsWithChildren<AutoCompleteProps>> = ({
onSearch && onSearch(event.target.value)
setState(event.target.value)
}
useEffect(() => {
onChange && onChange(state)
}, [state])
@@ -108,22 +119,26 @@ const AutoComplete: React.FC<React.PropsWithChildren<AutoCompleteProps>> = ({
if (value === undefined) return
setState(value)
}, [value])
const initialValue = useMemo<AutoCompleteConfig>(() => ({
ref, size,
value: state,
updateValue,
visible,
updateVisible,
}), [state, visible, size])
const initialValue = useMemo<AutoCompleteConfig>(
() => ({
ref,
size,
value: state,
updateValue,
visible,
updateVisible,
}),
[state, visible, size],
)
const toggleFocusHandler = (next: boolean) => {
setVisible(next)
if (next) {
onSearch && onSearch(state)
}
}
const inputProps = {
...props,
width,
@@ -134,22 +149,23 @@ const AutoComplete: React.FC<React.PropsWithChildren<AutoCompleteProps>> = ({
return (
<AutoCompleteContext.Provider value={initialValue}>
<div ref={ref} className="auto-complete">
<Input size={size} status={status}
<Input
size={size}
status={status}
onChange={onInputChange}
onFocus={() => toggleFocusHandler(true)}
onBlur={() => toggleFocusHandler(false)}
clearable={showClearIcon}
iconRight={getSearchIcon(searching)}
{...inputProps} />
<AutoCompleteDropdown visible={visible}>
{autoCompleteItems}
</AutoCompleteDropdown>
{...inputProps}
/>
<AutoCompleteDropdown visible={visible}>{autoCompleteItems}</AutoCompleteDropdown>
<style jsx>{`
.auto-complete {
width: ${width || 'max-content'};
}
.auto-complete :global(.loading) {
left: -3px;
right: -3px;
@@ -168,8 +184,9 @@ type AutoCompleteComponent<P = {}> = React.FC<P> & {
Empty: typeof AutoCompleteEmpty
}
type ComponentProps = Partial<typeof defaultProps> & Omit<Props, keyof typeof defaultProps> & NativeAttrs
(AutoComplete as AutoCompleteComponent<ComponentProps>).defaultProps = defaultProps
type ComponentProps = Partial<typeof defaultProps> &
Omit<Props, keyof typeof defaultProps> &
NativeAttrs
;(AutoComplete as AutoCompleteComponent<ComponentProps>).defaultProps = defaultProps
export default AutoComplete as AutoCompleteComponent<ComponentProps>