forked from mantinedev/mantine
/
Radio.tsx
126 lines (109 loc) · 2.98 KB
/
Radio.tsx
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import React, { forwardRef } from 'react';
import { useId } from '@mantine/hooks';
import {
DefaultProps,
MantineSize,
MantineColor,
Selectors,
extractSystemStyles,
useComponentDefaultProps,
} from '@mantine/styles';
import { ForwardRefWithStaticComponents } from '@mantine/utils';
import { Box } from '../Box';
import { RadioIcon } from './RadioIcon';
import { useRadioGroupContext } from './RadioGroup.context';
import { RadioGroup } from './RadioGroup/RadioGroup';
import useStyles, { RadioStylesParams } from './Radio.styles';
export type RadioStylesNames = Selectors<typeof useStyles>;
export interface RadioProps
extends DefaultProps<RadioStylesNames, RadioStylesParams>,
Omit<React.ComponentPropsWithoutRef<'input'>, 'size'> {
/** Radio label */
label?: React.ReactNode;
/** Radio value */
value: string;
/** Active radio color from theme.colors */
color?: MantineColor;
/** Predefined label fontSize, radio width, height and border-radius */
size?: MantineSize;
/** Replace default icon */
icon?: React.FC<React.ComponentPropsWithoutRef<'svg'>>;
/** Animation duration in ms */
transitionDuration?: number;
/** Props spread to root element */
wrapperProps?: Record<string, any>;
}
const defaultProps: Partial<RadioProps> = {
icon: RadioIcon,
transitionDuration: 100,
size: 'sm',
};
type RadioComponent = ForwardRefWithStaticComponents<
HTMLInputElement,
RadioProps,
{ Group: typeof RadioGroup }
>;
export const Radio: RadioComponent = forwardRef<HTMLInputElement, RadioProps>((props, ref) => {
const {
className,
style,
id,
label,
size,
title,
disabled,
color,
classNames,
styles,
sx,
icon: Icon,
transitionDuration,
wrapperProps,
unstyled,
...others
} = useComponentDefaultProps('Radio', defaultProps, props);
const ctx = useRadioGroupContext();
const { classes, cx } = useStyles(
{ color, size: ctx?.size || size, transitionDuration },
{ classNames, styles, unstyled, name: 'Radio' }
);
const { systemStyles, rest } = extractSystemStyles(others);
const uuid = useId(id);
const contextProps = ctx
? {
checked: ctx.value === rest.value,
name: rest.name ?? ctx.name,
onChange: ctx.onChange,
}
: {};
return (
<Box
className={cx(classes.radioWrapper, className)}
style={style}
title={title}
sx={sx}
{...systemStyles}
{...wrapperProps}
>
<div className={classes.inner}>
<input
ref={ref}
className={classes.radio}
type="radio"
id={uuid}
disabled={disabled}
{...rest}
{...contextProps}
/>
<Icon className={classes.icon} aria-hidden />
</div>
{label && (
<label data-disabled={disabled || undefined} className={classes.label} htmlFor={uuid}>
{label}
</label>
)}
</Box>
);
}) as any;
Radio.displayName = '@mantine/core/Radio';
Radio.Group = RadioGroup;