@teamturing/react-kit 2.53.8 → 2.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/CheckboxGroup/CheckboxGroupOption.d.ts +44 -0
- package/dist/core/CheckboxGroup/index.d.ts +48 -0
- package/dist/core/CheckboxOrRadioGroupFormControl/CheckboxOrRadioGroupFormControlCaption.d.ts +5 -0
- package/dist/core/CheckboxOrRadioGroupFormControl/CheckboxOrRadioGroupFormControlErrorMessage.d.ts +5 -0
- package/dist/core/CheckboxOrRadioGroupFormControl/CheckboxOrRadioGroupFormControlLabel.d.ts +8 -0
- package/dist/core/CheckboxOrRadioGroupFormControl/CheckboxOrRadioGroupFormControlSuccessMessage.d.ts +5 -0
- package/dist/core/CheckboxOrRadioGroupFormControl/CheckboxOrRadioGroupFormControlTooltipIcon.d.ts +7 -0
- package/dist/core/CheckboxOrRadioGroupFormControl/index.d.ts +61 -0
- package/dist/core/RadioGroup/RadioGroupOption.d.ts +44 -0
- package/dist/core/RadioGroup/index.d.ts +48 -0
- package/dist/core/Spinner/index.d.ts +7 -484
- package/dist/index.d.ts +6 -0
- package/dist/index.js +3675 -3168
- package/dist/theme/index.d.ts +15 -0
- package/dist/utils/createSafeContext.d.ts +6 -0
- package/esm/core/CheckboxGroup/CheckboxGroupOption.js +56 -0
- package/esm/core/CheckboxGroup/index.js +54 -0
- package/esm/core/CheckboxOrRadioGroupFormControl/CheckboxOrRadioGroupFormControlCaption.js +21 -0
- package/esm/core/CheckboxOrRadioGroupFormControl/CheckboxOrRadioGroupFormControlErrorMessage.js +34 -0
- package/esm/core/CheckboxOrRadioGroupFormControl/CheckboxOrRadioGroupFormControlLabel.js +92 -0
- package/esm/core/CheckboxOrRadioGroupFormControl/CheckboxOrRadioGroupFormControlSuccessMessage.js +34 -0
- package/esm/core/CheckboxOrRadioGroupFormControl/CheckboxOrRadioGroupFormControlTooltipIcon.js +25 -0
- package/esm/core/CheckboxOrRadioGroupFormControl/index.js +98 -0
- package/esm/core/FormControl/index.js +2 -2
- package/esm/core/RadioGroup/RadioGroupOption.js +54 -0
- package/esm/core/RadioGroup/index.js +54 -0
- package/esm/core/Spinner/index.js +30 -7
- package/esm/index.js +3 -0
- package/esm/theme/index.js +18 -3
- package/esm/utils/createSafeContext.js +25 -0
- package/package.json +2 -2
package/dist/theme/index.d.ts
CHANGED
|
@@ -305,6 +305,11 @@ declare const theme: {
|
|
|
305
305
|
opacity: {
|
|
306
306
|
readonly disabled: number;
|
|
307
307
|
};
|
|
308
|
+
components: {
|
|
309
|
+
spinner: {
|
|
310
|
+
defaultVariant: "progress-gradient";
|
|
311
|
+
};
|
|
312
|
+
};
|
|
308
313
|
};
|
|
309
314
|
declare const gpaiLightTheme: {
|
|
310
315
|
colors: {
|
|
@@ -502,6 +507,11 @@ declare const gpaiLightTheme: {
|
|
|
502
507
|
readonly 'text/danger': "#F22735";
|
|
503
508
|
readonly 'text/selected': "#33373B";
|
|
504
509
|
};
|
|
510
|
+
components: {
|
|
511
|
+
spinner: {
|
|
512
|
+
defaultVariant: "progress-line";
|
|
513
|
+
};
|
|
514
|
+
};
|
|
505
515
|
breakpoints: string[];
|
|
506
516
|
space: {
|
|
507
517
|
readonly '-80': number;
|
|
@@ -810,6 +820,11 @@ declare const gpaiDarkTheme: {
|
|
|
810
820
|
readonly 'text/danger': "#F5525D";
|
|
811
821
|
readonly 'text/selected': "#F9FAFB";
|
|
812
822
|
};
|
|
823
|
+
components: {
|
|
824
|
+
spinner: {
|
|
825
|
+
defaultVariant: "progress-line";
|
|
826
|
+
};
|
|
827
|
+
};
|
|
813
828
|
breakpoints: string[];
|
|
814
829
|
space: {
|
|
815
830
|
readonly '-80': number;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function createSafeContext<ContextValue>({ errorMessage }: {
|
|
2
|
+
errorMessage: string;
|
|
3
|
+
}): readonly [({ children, value }: {
|
|
4
|
+
value: ContextValue;
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
}) => import("react/jsx-runtime").JSX.Element, () => ContextValue & ({} | undefined)];
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { forwardRef } from 'react';
|
|
2
|
+
import Checkbox from '../Checkbox/index.js';
|
|
3
|
+
import FormControl from '../FormControl/index.js';
|
|
4
|
+
import { useCheckboxGroupContext } from './index.js';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
const CheckboxGroupOption = ({
|
|
8
|
+
value,
|
|
9
|
+
label,
|
|
10
|
+
disabled: optionDisabled,
|
|
11
|
+
onChange: onOptionChange,
|
|
12
|
+
children,
|
|
13
|
+
...checkboxProps
|
|
14
|
+
}, ref) => {
|
|
15
|
+
const {
|
|
16
|
+
name,
|
|
17
|
+
value: groupValue,
|
|
18
|
+
onChange: onGroupChange,
|
|
19
|
+
disabled: groupDisabled,
|
|
20
|
+
required
|
|
21
|
+
} = useCheckboxGroupContext();
|
|
22
|
+
|
|
23
|
+
// CheckboxGroup의 value 배열에 현재 value가 포함되어 있는지 확인
|
|
24
|
+
const checked = groupValue ? groupValue.includes(value) : false;
|
|
25
|
+
const disabled = groupDisabled || optionDisabled;
|
|
26
|
+
const displayLabel = children || label;
|
|
27
|
+
const handleChange = e => {
|
|
28
|
+
// CheckboxGroup의 onChange 호출
|
|
29
|
+
onGroupChange?.(e);
|
|
30
|
+
// Option의 개별 onChange 호출
|
|
31
|
+
onOptionChange?.(value, e);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// FormControl ID 생성 (접근성)
|
|
35
|
+
const formControlId = name ? `${name}-${value}` : String(value);
|
|
36
|
+
return /*#__PURE__*/jsxs(FormControl, {
|
|
37
|
+
id: formControlId,
|
|
38
|
+
disabled: disabled,
|
|
39
|
+
required: required,
|
|
40
|
+
children: [/*#__PURE__*/jsx(Checkbox, {
|
|
41
|
+
ref: ref,
|
|
42
|
+
name: name,
|
|
43
|
+
value: String(value) // HTML input value는 string
|
|
44
|
+
,
|
|
45
|
+
checked: checked,
|
|
46
|
+
onChange: handleChange,
|
|
47
|
+
"aria-label": typeof displayLabel === 'string' ? displayLabel : undefined,
|
|
48
|
+
...checkboxProps
|
|
49
|
+
}), displayLabel && /*#__PURE__*/jsx(FormControl.Label, {
|
|
50
|
+
children: displayLabel
|
|
51
|
+
})]
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
var CheckboxGroupOption$1 = /*#__PURE__*/forwardRef(CheckboxGroupOption);
|
|
55
|
+
|
|
56
|
+
export { CheckboxGroupOption$1 as default };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Children } from 'react';
|
|
2
|
+
import { createSafeContext } from '../../utils/createSafeContext.js';
|
|
3
|
+
import Grid from '../Grid/index.js';
|
|
4
|
+
import CheckboxGroupOption from './CheckboxGroupOption.js';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
const [CheckboxGroupContextProvider, useCheckboxGroupContext] = createSafeContext({
|
|
8
|
+
errorMessage: 'CheckboxGroupContext 안에서 사용해야 합니다.'
|
|
9
|
+
});
|
|
10
|
+
const CheckboxGroup = ({
|
|
11
|
+
children,
|
|
12
|
+
name,
|
|
13
|
+
required = true,
|
|
14
|
+
disabled = false,
|
|
15
|
+
value,
|
|
16
|
+
onChange,
|
|
17
|
+
renderContainer = children => /*#__PURE__*/jsx(Grid, {
|
|
18
|
+
gapX: 3,
|
|
19
|
+
gapY: 3,
|
|
20
|
+
children: children
|
|
21
|
+
}),
|
|
22
|
+
renderItemWrapper = (children, i) => /*#__PURE__*/jsx(Grid.Unit, {
|
|
23
|
+
size: 1,
|
|
24
|
+
children: children
|
|
25
|
+
}, i),
|
|
26
|
+
...ariaProps
|
|
27
|
+
}) => {
|
|
28
|
+
// Children을 배열로 변환하여 renderItemWrapper 적용
|
|
29
|
+
const wrappedChildren = Children.toArray(children).map((child, index) => renderItemWrapper(child, index));
|
|
30
|
+
return /*#__PURE__*/jsx(CheckboxGroupContextProvider, {
|
|
31
|
+
value: {
|
|
32
|
+
name,
|
|
33
|
+
required,
|
|
34
|
+
disabled,
|
|
35
|
+
value,
|
|
36
|
+
onChange
|
|
37
|
+
},
|
|
38
|
+
children: /*#__PURE__*/jsx("fieldset", {
|
|
39
|
+
role: 'group',
|
|
40
|
+
...ariaProps,
|
|
41
|
+
style: {
|
|
42
|
+
border: 'none',
|
|
43
|
+
padding: 0,
|
|
44
|
+
margin: 0
|
|
45
|
+
},
|
|
46
|
+
children: renderContainer(wrappedChildren)
|
|
47
|
+
})
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
var CheckboxGroup$1 = Object.assign(CheckboxGroup, {
|
|
51
|
+
Option: CheckboxGroupOption
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
export { CheckboxGroup$1 as default, useCheckboxGroupContext };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import Text from '../Text/index.js';
|
|
3
|
+
import { CheckboxOrRadioGroupFormControlContext } from './index.js';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
const CheckboxOrRadioGroupFormControlCaption = ({
|
|
7
|
+
children
|
|
8
|
+
}) => {
|
|
9
|
+
const {
|
|
10
|
+
id
|
|
11
|
+
} = useContext(CheckboxOrRadioGroupFormControlContext);
|
|
12
|
+
return /*#__PURE__*/jsx(Text, {
|
|
13
|
+
as: 'span',
|
|
14
|
+
id: id,
|
|
15
|
+
typography: 'xxs',
|
|
16
|
+
color: 'text/neutral/subtlest',
|
|
17
|
+
children: children
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { CheckboxOrRadioGroupFormControlCaption as default };
|
package/esm/core/CheckboxOrRadioGroupFormControl/CheckboxOrRadioGroupFormControlErrorMessage.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import styled, { keyframes } from 'styled-components';
|
|
3
|
+
import Text from '../Text/index.js';
|
|
4
|
+
import { CheckboxOrRadioGroupFormControlContext } from './index.js';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
const CheckboxOrRadioGroupFormControlErrorMessage = ({
|
|
8
|
+
children
|
|
9
|
+
}) => {
|
|
10
|
+
const {
|
|
11
|
+
id
|
|
12
|
+
} = useContext(CheckboxOrRadioGroupFormControlContext);
|
|
13
|
+
return /*#__PURE__*/jsx(StyledText, {
|
|
14
|
+
id: id,
|
|
15
|
+
typography: 'xxs',
|
|
16
|
+
color: 'text/danger',
|
|
17
|
+
children: children
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
const errorMessageKeyframe = keyframes`
|
|
21
|
+
0% {
|
|
22
|
+
opacity: 0;
|
|
23
|
+
transform: translateY(-100%);
|
|
24
|
+
}
|
|
25
|
+
100% {
|
|
26
|
+
opacity: 1;
|
|
27
|
+
transform: translateY(0);
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
const StyledText = styled(Text)`
|
|
31
|
+
animation: 170ms ${errorMessageKeyframe} cubic-bezier(0.44, 0.74, 0.36, 1);
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
export { CheckboxOrRadioGroupFormControlErrorMessage as default };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { sx } from '@teamturing/react-kit';
|
|
2
|
+
import { forcePixelValue } from '@teamturing/utils';
|
|
3
|
+
import { useContext } from 'react';
|
|
4
|
+
import styled from 'styled-components';
|
|
5
|
+
import View from '../View/index.js';
|
|
6
|
+
import { CheckboxOrRadioGroupFormControlContext } from './index.js';
|
|
7
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
const CheckboxOrRadioGroupFormControlLabel = ({
|
|
10
|
+
children,
|
|
11
|
+
visuallyHidden,
|
|
12
|
+
...props
|
|
13
|
+
}) => {
|
|
14
|
+
const {
|
|
15
|
+
id,
|
|
16
|
+
disabled,
|
|
17
|
+
required
|
|
18
|
+
} = useContext(CheckboxOrRadioGroupFormControlContext);
|
|
19
|
+
return /*#__PURE__*/jsx(VisuallyHidden, {
|
|
20
|
+
as: 'label',
|
|
21
|
+
htmlFor: id,
|
|
22
|
+
sx: {
|
|
23
|
+
width: 'fit-content',
|
|
24
|
+
display: 'contents'
|
|
25
|
+
},
|
|
26
|
+
isVisible: !visuallyHidden,
|
|
27
|
+
children: /*#__PURE__*/jsxs(LabelWrapper, {
|
|
28
|
+
...props,
|
|
29
|
+
disabled: disabled,
|
|
30
|
+
children: [children, typeof required === 'boolean' && required === false ? /*#__PURE__*/jsx(View, {
|
|
31
|
+
as: 'span',
|
|
32
|
+
className: 'checkbox_or_radio_group_form_control_label__required__false',
|
|
33
|
+
"aria-hidden": "true",
|
|
34
|
+
children: ' (선택)'
|
|
35
|
+
}) : null]
|
|
36
|
+
})
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
const VisuallyHidden = styled.span`
|
|
40
|
+
${({
|
|
41
|
+
isVisible = false
|
|
42
|
+
}) => {
|
|
43
|
+
if (isVisible) {
|
|
44
|
+
return sx;
|
|
45
|
+
}
|
|
46
|
+
return `
|
|
47
|
+
position: absolute;
|
|
48
|
+
width: 1px;
|
|
49
|
+
height: 1px;
|
|
50
|
+
padding: 0;
|
|
51
|
+
margin: -1px;
|
|
52
|
+
overflow: hidden;
|
|
53
|
+
clip: rect(0, 0, 0, 0);
|
|
54
|
+
white-space: nowrap;
|
|
55
|
+
border-width: 0;
|
|
56
|
+
`;
|
|
57
|
+
}}
|
|
58
|
+
`;
|
|
59
|
+
const LabelWrapper = styled(View)`
|
|
60
|
+
display: inline-block;
|
|
61
|
+
align-self: flex-start;
|
|
62
|
+
|
|
63
|
+
font-size: ${({
|
|
64
|
+
theme
|
|
65
|
+
}) => forcePixelValue(theme.fontSizes.xs)};
|
|
66
|
+
font-weight: ${({
|
|
67
|
+
theme
|
|
68
|
+
}) => theme.fontWeights.medium};
|
|
69
|
+
line-height: ${({
|
|
70
|
+
theme
|
|
71
|
+
}) => theme.lineHeights[2]};
|
|
72
|
+
|
|
73
|
+
color: ${({
|
|
74
|
+
theme
|
|
75
|
+
}) => theme.colors['text/neutral/subtle']};
|
|
76
|
+
|
|
77
|
+
cursor: ${({
|
|
78
|
+
disabled
|
|
79
|
+
}) => disabled ? 'not-allowed' : 'pointer'};
|
|
80
|
+
|
|
81
|
+
span.checkbox_or_radio_group_form_control_label__required__false {
|
|
82
|
+
font-size: inherit;
|
|
83
|
+
font-weight: inherit;
|
|
84
|
+
color: ${({
|
|
85
|
+
theme
|
|
86
|
+
}) => theme.colors['text/neutral/subtlest']};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
${sx};
|
|
90
|
+
`;
|
|
91
|
+
|
|
92
|
+
export { CheckboxOrRadioGroupFormControlLabel as default };
|
package/esm/core/CheckboxOrRadioGroupFormControl/CheckboxOrRadioGroupFormControlSuccessMessage.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import styled, { keyframes } from 'styled-components';
|
|
3
|
+
import Text from '../Text/index.js';
|
|
4
|
+
import { CheckboxOrRadioGroupFormControlContext } from './index.js';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
const CheckboxOrRadioGroupFormControlSuccessMessage = ({
|
|
8
|
+
children
|
|
9
|
+
}) => {
|
|
10
|
+
const {
|
|
11
|
+
id
|
|
12
|
+
} = useContext(CheckboxOrRadioGroupFormControlContext);
|
|
13
|
+
return /*#__PURE__*/jsx(StyledText, {
|
|
14
|
+
id: id,
|
|
15
|
+
typography: 'xxs',
|
|
16
|
+
color: 'text/success',
|
|
17
|
+
children: children
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
const successMessageKeyframe = keyframes`
|
|
21
|
+
0% {
|
|
22
|
+
opacity: 0;
|
|
23
|
+
transform: translateY(-100%);
|
|
24
|
+
}
|
|
25
|
+
100% {
|
|
26
|
+
opacity: 1;
|
|
27
|
+
transform: translateY(0);
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
const StyledText = styled(Text)`
|
|
31
|
+
animation: 170ms ${successMessageKeyframe} cubic-bezier(0.44, 0.74, 0.36, 1);
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
export { CheckboxOrRadioGroupFormControlSuccessMessage as default };
|
package/esm/core/CheckboxOrRadioGroupFormControl/CheckboxOrRadioGroupFormControlTooltipIcon.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { InfoInCircleIcon } from '@teamturing/icons';
|
|
2
|
+
import StyledIcon from '../StyledIcon/index.js';
|
|
3
|
+
import Tooltip from '../Tooltip/index.js';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
const CheckboxOrRadioGroupFormControlTooltipIcon = ({
|
|
7
|
+
text,
|
|
8
|
+
direction,
|
|
9
|
+
icon = InfoInCircleIcon,
|
|
10
|
+
size = 16,
|
|
11
|
+
color = 'icon/neutral',
|
|
12
|
+
...props
|
|
13
|
+
}) => /*#__PURE__*/jsx(Tooltip, {
|
|
14
|
+
text: text,
|
|
15
|
+
direction: direction,
|
|
16
|
+
mouseOnly: false,
|
|
17
|
+
children: /*#__PURE__*/jsx(StyledIcon, {
|
|
18
|
+
icon: icon,
|
|
19
|
+
size: size,
|
|
20
|
+
color: color,
|
|
21
|
+
...props
|
|
22
|
+
})
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export { CheckboxOrRadioGroupFormControlTooltipIcon as default };
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { useRelocation } from '@teamturing/react-kit';
|
|
2
|
+
import { forwardRef, createContext, isValidElement, cloneElement } from 'react';
|
|
3
|
+
import CheckboxGroup from '../CheckboxGroup/index.js';
|
|
4
|
+
import RadioGroup from '../RadioGroup/index.js';
|
|
5
|
+
import View from '../View/index.js';
|
|
6
|
+
import CheckboxOrRadioGroupFormControlCaption from './CheckboxOrRadioGroupFormControlCaption.js';
|
|
7
|
+
import CheckboxOrRadioGroupFormControlErrorMessage from './CheckboxOrRadioGroupFormControlErrorMessage.js';
|
|
8
|
+
import CheckboxOrRadioGroupFormControlLabel from './CheckboxOrRadioGroupFormControlLabel.js';
|
|
9
|
+
import CheckboxOrRadioGroupFormControlSuccessMessage from './CheckboxOrRadioGroupFormControlSuccessMessage.js';
|
|
10
|
+
import CheckboxOrRadioGroupFormControlTooltipIcon from './CheckboxOrRadioGroupFormControlTooltipIcon.js';
|
|
11
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
12
|
+
|
|
13
|
+
const CheckboxOrRadioGroupFormControlContext = /*#__PURE__*/createContext({});
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* RadioGroup 및 CheckboxGroup을 위한 FormControl
|
|
17
|
+
* bombe의 FormControl과 동일한 구조이지만, 그룹 컴포넌트에 특화되어 있습니다.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <CheckboxOrRadioGroupFormControl id="choice" required>
|
|
22
|
+
* <CheckboxOrRadioGroupFormControl.Label>Choose one</CheckboxOrRadioGroupFormControl.Label>
|
|
23
|
+
* <CheckboxOrRadioGroupFormControl.TooltipIcon text="Help text" />
|
|
24
|
+
* <CheckboxOrRadioGroupFormControl.Caption>Select your preference</CheckboxOrRadioGroupFormControl.Caption>
|
|
25
|
+
*
|
|
26
|
+
* <RadioGroup name="choice" value={value} onChange={onChange}>
|
|
27
|
+
* <RadioGroup.Option value="a" label="Option A" />
|
|
28
|
+
* <RadioGroup.Option value="b" label="Option B" />
|
|
29
|
+
* </RadioGroup>
|
|
30
|
+
*
|
|
31
|
+
* <CheckboxOrRadioGroupFormControl.ErrorMessage>Error message</CheckboxOrRadioGroupFormControl.ErrorMessage>
|
|
32
|
+
* </CheckboxOrRadioGroupFormControl>
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
const CheckboxOrRadioGroupFormControl = ({
|
|
36
|
+
children: propChildren,
|
|
37
|
+
id,
|
|
38
|
+
disabled,
|
|
39
|
+
required = true,
|
|
40
|
+
sx,
|
|
41
|
+
...props
|
|
42
|
+
}, ref) => {
|
|
43
|
+
const [relocatableComponentsObject, restComponents] = useRelocation({
|
|
44
|
+
children: propChildren,
|
|
45
|
+
config: {
|
|
46
|
+
label: CheckboxOrRadioGroupFormControlLabel,
|
|
47
|
+
caption: CheckboxOrRadioGroupFormControlCaption,
|
|
48
|
+
errorMessage: CheckboxOrRadioGroupFormControlErrorMessage,
|
|
49
|
+
successMessage: CheckboxOrRadioGroupFormControlSuccessMessage,
|
|
50
|
+
tooltipIcon: CheckboxOrRadioGroupFormControlTooltipIcon
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const groupInputComponentCandidates = [RadioGroup, CheckboxGroup];
|
|
54
|
+
const GroupInputComponent = restComponents.find(component => groupInputComponentCandidates.some(candidate => /*#__PURE__*/isValidElement(component) && component.type === candidate));
|
|
55
|
+
return /*#__PURE__*/jsx(CheckboxOrRadioGroupFormControlContext.Provider, {
|
|
56
|
+
value: {
|
|
57
|
+
id,
|
|
58
|
+
disabled,
|
|
59
|
+
required
|
|
60
|
+
},
|
|
61
|
+
children: /*#__PURE__*/jsxs(View, {
|
|
62
|
+
ref: ref,
|
|
63
|
+
display: 'flex',
|
|
64
|
+
flexDirection: 'column',
|
|
65
|
+
sx: {
|
|
66
|
+
'& .checkbox_or_radio_group_form_control__label_wrapper': {
|
|
67
|
+
mb: relocatableComponentsObject.label?.props.visuallyHidden ? 0 : relocatableComponentsObject.caption ? 0.5 : 3
|
|
68
|
+
},
|
|
69
|
+
'& > span': {
|
|
70
|
+
mb: 3
|
|
71
|
+
},
|
|
72
|
+
...sx
|
|
73
|
+
},
|
|
74
|
+
...props,
|
|
75
|
+
children: [/*#__PURE__*/jsxs(View, {
|
|
76
|
+
className: 'checkbox_or_radio_group_form_control__label_wrapper',
|
|
77
|
+
display: 'flex',
|
|
78
|
+
alignItems: 'center',
|
|
79
|
+
sx: {
|
|
80
|
+
columnGap: 1
|
|
81
|
+
},
|
|
82
|
+
children: [relocatableComponentsObject.label, relocatableComponentsObject.tooltipIcon]
|
|
83
|
+
}), relocatableComponentsObject.caption, relocatableComponentsObject.errorMessage, relocatableComponentsObject.successMessage, /*#__PURE__*/cloneElement(GroupInputComponent, {
|
|
84
|
+
id,
|
|
85
|
+
disabled
|
|
86
|
+
})]
|
|
87
|
+
})
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
var index = Object.assign( /*#__PURE__*/forwardRef(CheckboxOrRadioGroupFormControl), {
|
|
91
|
+
Label: CheckboxOrRadioGroupFormControlLabel,
|
|
92
|
+
Caption: CheckboxOrRadioGroupFormControlCaption,
|
|
93
|
+
ErrorMessage: CheckboxOrRadioGroupFormControlErrorMessage,
|
|
94
|
+
SuccessMessage: CheckboxOrRadioGroupFormControlSuccessMessage,
|
|
95
|
+
TooltipIcon: CheckboxOrRadioGroupFormControlTooltipIcon
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
export { CheckboxOrRadioGroupFormControlContext, index as default };
|
|
@@ -103,7 +103,7 @@ const FormControl = ({
|
|
|
103
103
|
})
|
|
104
104
|
});
|
|
105
105
|
};
|
|
106
|
-
var
|
|
106
|
+
var FormControl$1 = Object.assign( /*#__PURE__*/forwardRef(FormControl), {
|
|
107
107
|
Label: FormControlLabel,
|
|
108
108
|
Caption: FormControlCaption,
|
|
109
109
|
ErrorMessage: FormControlErrorMessage,
|
|
@@ -111,4 +111,4 @@ var index = Object.assign( /*#__PURE__*/forwardRef(FormControl), {
|
|
|
111
111
|
TooltipIcon: FormControlTooltipIcon
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
-
export { FormControlContext,
|
|
114
|
+
export { FormControlContext, FormControl$1 as default };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { forwardRef } from 'react';
|
|
2
|
+
import FormControl from '../FormControl/index.js';
|
|
3
|
+
import Radio from '../Radio/index.js';
|
|
4
|
+
import { useRadioGroupContext } from './index.js';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
const RadioGroupOption = ({
|
|
8
|
+
value,
|
|
9
|
+
label,
|
|
10
|
+
disabled: optionDisabled,
|
|
11
|
+
onChange: onOptionChange,
|
|
12
|
+
children,
|
|
13
|
+
...radioProps
|
|
14
|
+
}, ref) => {
|
|
15
|
+
const {
|
|
16
|
+
name,
|
|
17
|
+
value: groupValue,
|
|
18
|
+
onChange: onGroupChange,
|
|
19
|
+
disabled: groupDisabled,
|
|
20
|
+
required
|
|
21
|
+
} = useRadioGroupContext();
|
|
22
|
+
const checked = groupValue === value;
|
|
23
|
+
const disabled = groupDisabled || optionDisabled;
|
|
24
|
+
const displayLabel = children || label;
|
|
25
|
+
const handleChange = e => {
|
|
26
|
+
// RadioGroup의 onChange 호출
|
|
27
|
+
onGroupChange?.(e);
|
|
28
|
+
// Option의 개별 onChange 호출
|
|
29
|
+
onOptionChange?.(value, e);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// FormControl ID 생성 (접근성)
|
|
33
|
+
const formControlId = name ? `${name}-${value}` : String(value);
|
|
34
|
+
return /*#__PURE__*/jsxs(FormControl, {
|
|
35
|
+
id: formControlId,
|
|
36
|
+
disabled: disabled,
|
|
37
|
+
required: required,
|
|
38
|
+
children: [/*#__PURE__*/jsx(Radio, {
|
|
39
|
+
ref: ref,
|
|
40
|
+
name: name,
|
|
41
|
+
value: String(value) // HTML input value는 string
|
|
42
|
+
,
|
|
43
|
+
checked: checked,
|
|
44
|
+
onChange: handleChange,
|
|
45
|
+
"aria-label": typeof displayLabel === 'string' ? displayLabel : undefined,
|
|
46
|
+
...radioProps
|
|
47
|
+
}), displayLabel && /*#__PURE__*/jsx(FormControl.Label, {
|
|
48
|
+
children: displayLabel
|
|
49
|
+
})]
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
var RadioGroupOption$1 = /*#__PURE__*/forwardRef(RadioGroupOption);
|
|
53
|
+
|
|
54
|
+
export { RadioGroupOption$1 as default };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Children } from 'react';
|
|
2
|
+
import { createSafeContext } from '../../utils/createSafeContext.js';
|
|
3
|
+
import Grid from '../Grid/index.js';
|
|
4
|
+
import RadioGroupOption from './RadioGroupOption.js';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
const [RadioGroupContextProvider, useRadioGroupContext] = createSafeContext({
|
|
8
|
+
errorMessage: 'RadioGroupContext 안에서 사용해야 합니다.'
|
|
9
|
+
});
|
|
10
|
+
const RadioGroup = ({
|
|
11
|
+
children,
|
|
12
|
+
name,
|
|
13
|
+
required = true,
|
|
14
|
+
disabled = false,
|
|
15
|
+
value,
|
|
16
|
+
onChange,
|
|
17
|
+
renderContainer = children => /*#__PURE__*/jsx(Grid, {
|
|
18
|
+
gapX: 3,
|
|
19
|
+
gapY: 3,
|
|
20
|
+
children: children
|
|
21
|
+
}),
|
|
22
|
+
renderItemWrapper = (children, i) => /*#__PURE__*/jsx(Grid.Unit, {
|
|
23
|
+
size: 1,
|
|
24
|
+
children: children
|
|
25
|
+
}, i),
|
|
26
|
+
...ariaProps
|
|
27
|
+
}) => {
|
|
28
|
+
// Children을 배열로 변환하여 renderItemWrapper 적용
|
|
29
|
+
const wrappedChildren = Children.toArray(children).map((child, index) => renderItemWrapper(child, index));
|
|
30
|
+
return /*#__PURE__*/jsx(RadioGroupContextProvider, {
|
|
31
|
+
value: {
|
|
32
|
+
name,
|
|
33
|
+
required,
|
|
34
|
+
disabled,
|
|
35
|
+
value,
|
|
36
|
+
onChange
|
|
37
|
+
},
|
|
38
|
+
children: /*#__PURE__*/jsx("fieldset", {
|
|
39
|
+
role: 'radiogroup',
|
|
40
|
+
...ariaProps,
|
|
41
|
+
style: {
|
|
42
|
+
border: 'none',
|
|
43
|
+
padding: 0,
|
|
44
|
+
margin: 0
|
|
45
|
+
},
|
|
46
|
+
children: renderContainer(wrappedChildren)
|
|
47
|
+
})
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
var RadioGroup$1 = Object.assign(RadioGroup, {
|
|
51
|
+
Option: RadioGroupOption
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
export { RadioGroup$1 as default, useRadioGroupContext };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { ProgressGradientIcon } from '@teamturing/icons';
|
|
2
|
-
import
|
|
1
|
+
import { ProgressGradientIcon, ProgressLineIcon } from '@teamturing/icons';
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import styled, { keyframes, useTheme } from 'styled-components';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
5
|
|
|
4
6
|
const spin = keyframes`
|
|
5
7
|
from {
|
|
@@ -9,15 +11,36 @@ const spin = keyframes`
|
|
|
9
11
|
transform: rotate(360deg);
|
|
10
12
|
}
|
|
11
13
|
`;
|
|
12
|
-
const
|
|
14
|
+
const ProgressGradientSpinner = styled(ProgressGradientIcon)`
|
|
13
15
|
color: ${({
|
|
14
16
|
theme
|
|
15
17
|
}) => theme.colors['icon/neutral']};
|
|
16
18
|
animation: ${spin} 1000ms infinite steps(8, end);
|
|
17
19
|
`;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
};
|
|
20
|
+
const ProgressLineSpinner = styled(ProgressLineIcon)`
|
|
21
|
+
color: ${({
|
|
22
|
+
theme
|
|
23
|
+
}) => theme.colors['icon/neutral']};
|
|
24
|
+
animation: ${spin} 1000ms infinite linear;
|
|
25
|
+
`;
|
|
26
|
+
const Spinner = /*#__PURE__*/forwardRef(({
|
|
27
|
+
variant: propsVariant,
|
|
28
|
+
width = 32,
|
|
29
|
+
height = 32,
|
|
30
|
+
...props
|
|
31
|
+
}, ref) => {
|
|
32
|
+
const theme = useTheme();
|
|
33
|
+
const variant = propsVariant ?? theme.components?.spinner?.defaultVariant ?? 'progress-gradient';
|
|
34
|
+
const SpinnerComponent = {
|
|
35
|
+
'progress-gradient': ProgressGradientSpinner,
|
|
36
|
+
'progress-line': ProgressLineSpinner
|
|
37
|
+
}[variant];
|
|
38
|
+
return /*#__PURE__*/jsx(SpinnerComponent, {
|
|
39
|
+
ref: ref,
|
|
40
|
+
width: width,
|
|
41
|
+
height: height,
|
|
42
|
+
...props
|
|
43
|
+
});
|
|
44
|
+
});
|
|
22
45
|
|
|
23
46
|
export { Spinner as default };
|
package/esm/index.js
CHANGED
|
@@ -8,6 +8,8 @@ export { default as Breadcrumbs } from './core/Breadcrumbs/index.js';
|
|
|
8
8
|
export { default as Button } from './core/Button/index.js';
|
|
9
9
|
export { default as Card } from './core/Card/index.js';
|
|
10
10
|
export { default as Checkbox } from './core/Checkbox/index.js';
|
|
11
|
+
export { default as CheckboxGroup } from './core/CheckboxGroup/index.js';
|
|
12
|
+
export { default as CheckboxOrRadioGroupFormControl } from './core/CheckboxOrRadioGroupFormControl/index.js';
|
|
11
13
|
export { default as Chip } from './core/Chip/index.js';
|
|
12
14
|
export { default as ClickArea } from './core/ClickArea/index.js';
|
|
13
15
|
export { default as CounterBadge } from './core/CounterBadge/index.js';
|
|
@@ -32,6 +34,7 @@ export { default as OverlayPopper } from './core/OverlayPopper/index.js';
|
|
|
32
34
|
export { default as Pagination } from './core/Pagination/index.js';
|
|
33
35
|
export { default as Pill } from './core/Pill/index.js';
|
|
34
36
|
export { default as Radio } from './core/Radio/index.js';
|
|
37
|
+
export { default as RadioGroup } from './core/RadioGroup/index.js';
|
|
35
38
|
export { default as SearchSelectInput } from './core/SearchSelectInput/index.js';
|
|
36
39
|
export { default as Select } from './core/Select/index.js';
|
|
37
40
|
export { default as Space } from './core/Space/index.js';
|