Files
react/components/checkbox/checkbox-group.tsx

86 lines
2.1 KiB
TypeScript

import React, { useEffect, useMemo, useState } from 'react'
import withDefaults from '../utils/with-defaults'
import { CheckboxContext } from './checkbox-context'
import useWarning from '../utils/use-warning'
import { NormalSizes } from '../utils/prop-types'
interface Props {
value: string[]
disabled?: boolean
size?: NormalSizes
onChange?: (values: string[]) => void
className?: string
}
const defaultProps = {
disabled: false,
size: 'small' as NormalSizes,
className: '',
}
type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
export type CheckboxGroupProps = Props & typeof defaultProps & NativeAttrs
export const getCheckboxSize = (size: NormalSizes): string => {
const sizes: { [key in NormalSizes]: string } = {
mini: '.75rem',
small: '.875rem',
medium: '1rem',
large: '1.125rem',
}
return sizes[size]
}
const CheckboxGroup: React.FC<React.PropsWithChildren<CheckboxGroupProps>> = ({
disabled,
onChange,
value,
size,
children,
className,
...props
}) => {
const [selfVal, setSelfVal] = useState<string[]>([])
if (!value) {
value = []
useWarning('Props "value" is required.', 'Checkbox Group')
}
const updateState = (val: string, checked: boolean) => {
const removed = selfVal.filter(v => v !== val)
const next = checked ? [...removed, val] : removed
setSelfVal(next)
onChange && onChange(next)
}
const providerValue = useMemo(() => {
return {
updateState,
disabledAll: disabled,
inGroup: true,
values: selfVal,
}
}, [disabled, selfVal])
const fontSize = useMemo(() => getCheckboxSize(size), [size])
useEffect(() => {
setSelfVal(value)
}, [value.join(',')])
return (
<CheckboxContext.Provider value={providerValue}>
<div className={`group ${className}`} {...props}>
{children}
<style jsx>{`
.group :global(label) {
margin-right: calc(${fontSize} * 2);
--checkbox-size: ${fontSize};
}
`}</style>
</div>
</CheckboxContext.Provider>
)
}
export default withDefaults(CheckboxGroup, defaultProps)