-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathCheckbox.tsx
More file actions
75 lines (70 loc) · 2.63 KB
/
Checkbox.tsx
File metadata and controls
75 lines (70 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/** @jsxImportSource @emotion/react */
import { createClassVariant } from '@jdesignlab/theme';
import { ThemeContext } from '@jdesignlab/j-provider';
import { useId, useRef, useContext, useEffect, forwardRef } from 'react';
import { arrowKeyNavigationHandler, spaceKeyToggleHandler } from '@jdesignlab/react-utils';
import { CheckboxGroup } from './CheckboxGroup';
import { CheckboxGroupContext } from '../context';
import { checkboxWrapperStyle, checkboxInputStyle, checkboxLabelStyle } from '../styles';
import type { CheckboxProps } from '../types';
type ExtendedInputProps = CheckboxProps & { Group?: typeof CheckboxGroup };
export const Checkbox = Object.assign(
forwardRef<HTMLInputElement, ExtendedInputProps>((props: CheckboxProps, extendRef) => {
const { children, value, color, readOnly, ...otherProps } = props;
const { defaultValues } = useContext(CheckboxGroupContext);
const themePreset = useContext(ThemeContext);
const checkboxRef = useRef<HTMLInputElement | null>(null);
const id = useId();
const onKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (!checkboxRef.current) return;
const el = event.target as HTMLInputElement;
const spaceKeyAction = () => {
el.checked = !el.checked;
};
const parentScope = '[role="group"]';
const selectorOfList = 'input[type="checkbox"]';
spaceKeyToggleHandler({ event, action: spaceKeyAction });
arrowKeyNavigationHandler({ event, parentScope, selectorOfList });
};
useEffect(() => {
if (defaultValues && value && checkboxRef.current) {
const initialCheck = defaultValues.some(x => x === value);
if (initialCheck) {
checkboxRef.current.checked = initialCheck;
}
}
}, [defaultValues, value, checkboxRef]);
return (
<label
htmlFor={id}
aria-labelledby={id}
className={createClassVariant('checkbox', 'wrapper')}
css={checkboxWrapperStyle}
>
<input
type="checkbox"
id={id}
className={createClassVariant('checkbox', 'input')}
css={checkboxInputStyle(themePreset, color)}
ref={e => {
if (typeof extendRef === 'function') {
extendRef(e);
}
checkboxRef.current = e;
}}
onChange={props?.onChange}
onKeyDown={e => onKeyDown(e)}
value={value}
{...otherProps}
/>
<span className={createClassVariant('checkbox', 'label')} css={checkboxLabelStyle}>
{children}
</span>
</label>
);
}),
{
displayName: 'Checkbox',
Group: CheckboxGroup
}
);