import React, { useState, ChangeEvent, useEffect } from 'react' import styled from 'styled-components' import { Label } from '../label' import focusShadowStyle from '../../utils/focus-shadow.style' const Icon = styled.svg` fill: none; stroke: white; stroke-width: 2px; ` export const CheckboxRadioContainer = styled.span` position: relative; display: inline-block; vertical-align: middle; & + ${Label} { margin-left: ${({ theme }): string => theme.space.default}; vertical-align: middle; margin-bottom: ${({ theme }): string => theme.space.sm}; } ` // Hide checkbox visually but remain accessible to screen readers. // Source: https://polished.js.org/docs/#hidevisually const HiddenCheckbox = styled.input.attrs({ type: 'checkbox' })` border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; white-space: nowrap; width: 1px; ` type StyledProps = { checked?: boolean; disabled?: boolean; } const checkboxBackground = (theme, checked, disabled): string => { if (checked) { return disabled ? theme.colors.grey40 : theme.colors.primary100 } return theme.colors.white } const StyledCheckbox = styled.a` display: inline-block; width: 16px; /* when it is placed within a container setting different font size */ font-size: 12px; cursor: pointer; border: 1px solid ${({ theme }): string => theme.colors.grey40}; height: 16px; background: ${({ checked, theme, disabled }): string => checkboxBackground(theme, checked, disabled)}; transition: all 150ms; position: relative; ${HiddenCheckbox}:focus + & { ${({ theme }): string => `box-shadow: ${focusShadowStyle(theme)};`}; } ${HiddenCheckbox}:hover + & { border-color: ${({ theme }): string => theme.colors.grey60}; } ${Icon} { visibility: ${(props): string => (props.checked ? 'visible' : 'hidden')}; } &:after { content: ''; position: absolute; left: -5px; top: -5px; width: 24px; height: 24px; opacity: 0; background: ${({ theme }): string => theme.colors.primary100}; } &:after:before { opacity: 0.1; } ` export type CheckBoxProps = React.HTMLProps /** * @typedef {object} CheckBoxProps * @alias CheckBoxProps * @memberof module:@adminjs/design-system.CheckBox * @property {string} [...] All props default to _checkbox_ html input like `onChange`, * `checked` etc. */ /** * @classdesc * * * * HTML CheckBox * * ### Usage * * ```javascript * import { CheckBox, CheckBoxProps } from '@adminjs/design-system' * ``` * * @component * @see {@link https://storybook.adminjs.co/?path=/story/designsystem-atoms-checkbox--default StoryBook} * @hideconstructor * @subcategory Atoms * @example * return ( * * * * * ) * @section design-system */ const CheckBox: React.FC = (props) => { const { className, checked, onChange, disabled, ...restProps } = props const [isChecked, setChecked] = useState(checked ?? false) const handleChange = (event: ChangeEvent): void => { if (onChange) { onChange(event) } else { setChecked(!event.target.checked) } } useEffect(() => { setChecked(checked ?? false) }, [checked]) return ( handleChange && handleChange(event as any)} > ) } export { CheckBox } export default CheckBox