@uniai-fe/uds-primitives 0.2.1 → 0.2.3
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/README.md +1 -1
- package/dist/styles.css +391 -81
- package/package.json +17 -8
- package/src/components/button/index.tsx +0 -2
- package/src/components/button/markup/Base.tsx +22 -1
- package/src/components/button/styles/button.scss +24 -2
- package/src/components/button/styles/variables.scss +4 -0
- package/src/components/button/types/index.ts +7 -0
- package/src/components/{input/img/calendar → calendar/img}/calendar.svg +5 -0
- package/src/components/calendar/index.tsx +5 -3
- package/src/components/calendar/markup/Core.tsx +67 -0
- package/src/components/calendar/markup/Icon.tsx +20 -0
- package/src/components/calendar/markup/Root.tsx +126 -0
- package/src/components/calendar/markup/index.tsx +24 -2
- package/src/components/calendar/markup/layout/Body.tsx +12 -0
- package/src/components/calendar/markup/layout/Container.tsx +43 -0
- package/src/components/calendar/markup/layout/Footer.tsx +12 -0
- package/src/components/calendar/markup/layout/Header.tsx +12 -0
- package/src/components/calendar/styles/index.scss +2 -0
- package/src/components/calendar/styles/layout.scss +21 -0
- package/src/components/calendar/styles/mantine-calendar.scss +240 -0
- package/src/components/calendar/types/calendar.ts +208 -0
- package/src/components/calendar/types/index.ts +1 -4
- package/src/components/calendar/utils/index.ts +1 -4
- package/src/components/calendar/utils/value-mapper.ts +24 -0
- package/src/components/checkbox/markup/Checkbox.tsx +31 -25
- package/src/components/dropdown/markup/index.tsx +10 -1
- package/src/components/input/hooks/index.ts +1 -0
- package/src/components/input/hooks/useAddress.ts +247 -0
- package/src/components/input/index.scss +5 -1
- package/src/components/input/markup/address/Button.tsx +65 -0
- package/src/components/input/markup/address/Template.tsx +135 -0
- package/src/components/input/markup/address/index.ts +9 -0
- package/src/components/input/markup/date/Template.tsx +181 -0
- package/src/components/input/markup/date/Trigger.tsx +79 -0
- package/src/components/input/markup/date/button/ApplyButton.tsx +38 -0
- package/src/components/input/markup/date/button/ClearButton.tsx +36 -0
- package/src/components/input/markup/date/button/TodayButton.tsx +36 -0
- package/src/components/input/markup/date/footer/Container.tsx +24 -0
- package/src/components/input/markup/date/footer/Template.tsx +36 -0
- package/src/components/input/markup/date/footer/UtilContainer.tsx +23 -0
- package/src/components/input/markup/date/footer/index.ts +3 -0
- package/src/components/input/markup/date/index.tsx +27 -0
- package/src/components/input/markup/foundation/Input.tsx +20 -1
- package/src/components/input/markup/index.tsx +4 -4
- package/src/components/input/styles/address.scss +24 -0
- package/src/components/input/styles/date.scss +45 -0
- package/src/components/input/styles/foundation.scss +28 -2
- package/src/components/input/styles/variables.scss +4 -0
- package/src/components/input/types/address.ts +249 -0
- package/src/components/input/types/date.ts +366 -0
- package/src/components/input/types/foundation.ts +6 -0
- package/src/components/input/types/index.ts +2 -1
- package/src/components/input/utils/address.ts +165 -0
- package/src/components/input/utils/date.ts +61 -0
- package/src/components/input/utils/index.tsx +2 -0
- package/src/components/pop-over/index.scss +1 -0
- package/src/components/pop-over/index.tsx +4 -0
- package/src/components/pop-over/markup/Content.tsx +77 -0
- package/src/components/pop-over/markup/Root.tsx +28 -0
- package/src/components/pop-over/markup/Trigger.tsx +26 -0
- package/src/components/pop-over/markup/index.tsx +17 -0
- package/src/components/pop-over/styles/base.scss +5 -0
- package/src/components/pop-over/styles/content.scss +24 -0
- package/src/components/pop-over/styles/index.scss +2 -0
- package/src/components/pop-over/types/index.ts +1 -0
- package/src/components/pop-over/types/pop-over.ts +86 -0
- package/src/components/radio/markup/Radio.tsx +10 -2
- package/src/components/radio/markup/RadioCard.tsx +6 -1
- package/src/components/radio/markup/RadioCardGroup.tsx +6 -1
- package/src/components/select/markup/Default.tsx +2 -0
- package/src/components/select/markup/foundation/Container.tsx +23 -0
- package/src/components/select/markup/multiple/Multiple.tsx +2 -0
- package/src/components/select/styles/select.scss +25 -2
- package/src/components/select/styles/variables.scss +4 -0
- package/src/components/select/types/props.ts +24 -5
- package/src/index.scss +1 -0
- package/src/index.tsx +3 -1
- package/src/init/mantine.css +5 -0
- package/src/init/mantine.ts +2 -0
- package/src/components/input/markup/calendar/Base.tsx +0 -329
- package/src/components/input/markup/calendar/index.tsx +0 -8
- package/src/components/input/styles/calendar.scss +0 -110
- package/src/components/input/styles/index.scss +0 -4
- package/src/components/input/types/calendar.ts +0 -208
- /package/src/components/{input/img/calendar → calendar/img}/chevron-down.svg +0 -0
- /package/src/components/{input/img/calendar → calendar/img}/chevron-left.svg +0 -0
- /package/src/components/{input/img/calendar → calendar/img}/chevron-right.svg +0 -0
- /package/src/components/{input/img/calendar → calendar/img}/chevron-up.svg +0 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
.calendar-root,
|
|
2
|
+
.calendar-grid {
|
|
3
|
+
// Calendar 기준 폭/패딩/컬럼 간격을 모듈 내부에서 고정한다.
|
|
4
|
+
--calendar-width: 375px;
|
|
5
|
+
--calendar-inline-padding: var(--spacing-padding-6);
|
|
6
|
+
--calendar-body-width: calc(
|
|
7
|
+
var(--calendar-width) - (var(--calendar-inline-padding) * 2)
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.calendar-root {
|
|
12
|
+
// Calendar 내부 레이아웃 스킨(표면 스타일은 PopOver.Content가 담당).
|
|
13
|
+
padding: var(--spacing-padding-10) var(--spacing-padding-6)
|
|
14
|
+
var(--spacing-padding-6);
|
|
15
|
+
display: grid;
|
|
16
|
+
gap: var(--spacing-gap-3);
|
|
17
|
+
width: var(--calendar-width);
|
|
18
|
+
min-width: var(--calendar-width);
|
|
19
|
+
max-width: min(100vw - (var(--spacing-padding-5) * 2), 420px);
|
|
20
|
+
box-sizing: border-box;
|
|
21
|
+
z-index: 30;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.calendar-header {
|
|
25
|
+
margin-bottom: var(--spacing-gap-2);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.calendar-body {
|
|
29
|
+
display: grid;
|
|
30
|
+
gap: var(--spacing-gap-5);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.calendar-grid {
|
|
34
|
+
width: var(--calendar-body-width);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.calendar-grid table {
|
|
38
|
+
width: auto;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.calendar-month-level {
|
|
42
|
+
width: 100%;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.calendar-month-level > [data-month-level="true"],
|
|
46
|
+
.calendar-month-level > [data-year-level="true"],
|
|
47
|
+
.calendar-month-level > [data-decade-level="true"] {
|
|
48
|
+
width: 100%;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.calendar-header-row {
|
|
52
|
+
display: grid;
|
|
53
|
+
grid-template-columns: 44px 1fr 44px;
|
|
54
|
+
align-items: center;
|
|
55
|
+
width: 100%;
|
|
56
|
+
max-width: none;
|
|
57
|
+
column-gap: var(--spacing-gap-5);
|
|
58
|
+
padding: 0 var(--spacing-padding-9);
|
|
59
|
+
margin-bottom: var(--spacing-gap-5);
|
|
60
|
+
--dch-fz: var(--font-heading-small-size) !important;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.calendar-header-control {
|
|
64
|
+
width: 44px;
|
|
65
|
+
height: 44px;
|
|
66
|
+
border-radius: 999px;
|
|
67
|
+
display: inline-flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
justify-content: center;
|
|
70
|
+
color: var(--color-label-alternative);
|
|
71
|
+
transition:
|
|
72
|
+
background-color 0.2s ease,
|
|
73
|
+
color 0.2s ease;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.calendar-header-control[data-direction="previous"] {
|
|
77
|
+
justify-self: start;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.calendar-header-control[data-direction="next"] {
|
|
81
|
+
justify-self: end;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.calendar-header-level {
|
|
85
|
+
justify-self: center;
|
|
86
|
+
font-size: var(--font-heading-small-size);
|
|
87
|
+
font-weight: var(--font-heading-small-weight);
|
|
88
|
+
text-align: center;
|
|
89
|
+
white-space: nowrap;
|
|
90
|
+
writing-mode: horizontal-tb;
|
|
91
|
+
letter-spacing: 0.2px;
|
|
92
|
+
/* Month/Year 헤더 텍스트는 디자인 기준에 맞춰 strong 컬러를 사용한다. */
|
|
93
|
+
color: var(--color-label-strong);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.calendar-header-control:where(:not([data-disabled="true"])):hover {
|
|
97
|
+
background-color: var(--color-tertiary-default);
|
|
98
|
+
color: var(--color-label-standard);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.calendar-month-table {
|
|
102
|
+
width: 100%;
|
|
103
|
+
max-width: 100%;
|
|
104
|
+
margin: 0 auto;
|
|
105
|
+
table-layout: fixed;
|
|
106
|
+
border-collapse: collapse;
|
|
107
|
+
border-spacing: 0;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.calendar-month-cell {
|
|
111
|
+
width: 46px;
|
|
112
|
+
padding: 1px;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.calendar-months-list {
|
|
116
|
+
width: 100%;
|
|
117
|
+
max-width: 100%;
|
|
118
|
+
margin: 0 auto;
|
|
119
|
+
table-layout: fixed;
|
|
120
|
+
border-collapse: separate;
|
|
121
|
+
border-spacing: var(--spacing-gap-3);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.calendar-months-list-cell {
|
|
125
|
+
padding: 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.calendar-months-list-control {
|
|
129
|
+
width: 100%;
|
|
130
|
+
min-width: 0;
|
|
131
|
+
height: 44px;
|
|
132
|
+
padding: 0 var(--spacing-padding-2);
|
|
133
|
+
border: none;
|
|
134
|
+
border-radius: var(--theme-radius-medium-3);
|
|
135
|
+
font-size: var(--font-body-medium-size);
|
|
136
|
+
font-weight: var(--font-body-medium-weight);
|
|
137
|
+
line-height: 1.5;
|
|
138
|
+
color: var(--color-label-standard);
|
|
139
|
+
text-transform: none;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.calendar-months-list-control[data-selected="true"] {
|
|
143
|
+
background-color: var(--color-primary-default);
|
|
144
|
+
color: var(--color-common-100);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.calendar-months-list-control:where(
|
|
148
|
+
:not([data-disabled="true"], [data-selected="true"])
|
|
149
|
+
):hover {
|
|
150
|
+
background-color: var(--color-secondary-default);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.calendar-years-list {
|
|
154
|
+
width: 100%;
|
|
155
|
+
max-width: 100%;
|
|
156
|
+
margin: 0 auto;
|
|
157
|
+
table-layout: fixed;
|
|
158
|
+
border-collapse: separate;
|
|
159
|
+
border-spacing: var(--spacing-gap-3);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.calendar-years-list-cell {
|
|
163
|
+
padding: 0;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.calendar-years-list-control {
|
|
167
|
+
width: 100%;
|
|
168
|
+
min-width: 0;
|
|
169
|
+
height: 44px;
|
|
170
|
+
padding: 0 var(--spacing-padding-2);
|
|
171
|
+
border: none;
|
|
172
|
+
border-radius: var(--theme-radius-medium-3);
|
|
173
|
+
font-size: var(--font-body-medium-size);
|
|
174
|
+
font-weight: var(--font-body-medium-weight);
|
|
175
|
+
line-height: 1.5;
|
|
176
|
+
color: var(--color-label-standard);
|
|
177
|
+
text-transform: none;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.calendar-years-list-control[data-selected="true"] {
|
|
181
|
+
background-color: var(--color-primary-default);
|
|
182
|
+
color: var(--color-common-100);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.calendar-years-list-control:where(
|
|
186
|
+
:not([data-disabled="true"], [data-selected="true"])
|
|
187
|
+
):hover {
|
|
188
|
+
background-color: var(--color-secondary-default);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.calendar-weekdays {
|
|
192
|
+
text-transform: none;
|
|
193
|
+
--wr-fz: var(--font-heading-xxsmall-size) !important;
|
|
194
|
+
--wr-spacing: 10px !important;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.calendar-weekday {
|
|
198
|
+
text-transform: none;
|
|
199
|
+
width: 46px;
|
|
200
|
+
min-width: 46px;
|
|
201
|
+
height: 30px;
|
|
202
|
+
padding-bottom: 5px;
|
|
203
|
+
font-size: var(--font-heading-xxsmall-size);
|
|
204
|
+
font-weight: var(--font-heading-xxsmall-weight);
|
|
205
|
+
line-height: 1.5;
|
|
206
|
+
letter-spacing: 0.2px;
|
|
207
|
+
color: var(--color-label-alternative);
|
|
208
|
+
text-align: center;
|
|
209
|
+
vertical-align: middle;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.calendar-day {
|
|
213
|
+
width: 44px;
|
|
214
|
+
height: 44px;
|
|
215
|
+
padding: 0;
|
|
216
|
+
border: none;
|
|
217
|
+
border-radius: var(--theme-radius-large-1);
|
|
218
|
+
font-size: var(--font-body-medium-size);
|
|
219
|
+
color: var(--color-label-standard);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.calendar-day[data-outside="true"] {
|
|
223
|
+
color: var(--color-label-alternative);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.calendar-day[data-selected="true"],
|
|
227
|
+
.calendar-day[data-focused="true"] {
|
|
228
|
+
background-color: var(--color-primary-default);
|
|
229
|
+
color: var(--color-common-100);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.calendar-day:where(:not([data-disabled="true"])):hover {
|
|
233
|
+
background-color: var(--color-secondary-default);
|
|
234
|
+
color: var(--color-label-standard);
|
|
235
|
+
border: none;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.calendar-footer {
|
|
239
|
+
width: 100%;
|
|
240
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DatePickerProps as MantineDatePickerProps,
|
|
3
|
+
DatePickerStylesNames,
|
|
4
|
+
} from "@mantine/dates";
|
|
5
|
+
import type { ReactNode } from "react";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Calendar 모드.
|
|
9
|
+
* @property {"date" | "date-time" | "time"} mode 날짜/시간 표시 모드
|
|
10
|
+
*/
|
|
11
|
+
export type CalendarMode = "date" | "date-time" | "time";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Calendar 컬럼 수.
|
|
15
|
+
* @property {1 | 2} columns 단일/이중 컬럼 개수
|
|
16
|
+
*/
|
|
17
|
+
export type CalendarColumns = 1 | 2;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Calendar value 직렬화 타입.
|
|
21
|
+
* @property {string | null} value YYYY-MM-DD 문자열 또는 null
|
|
22
|
+
*/
|
|
23
|
+
export type CalendarValue = string | null;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Calendar 값 변경 핸들러.
|
|
27
|
+
* @param {CalendarValue} value 선택된 직렬화 값
|
|
28
|
+
* @example
|
|
29
|
+
* const onChange = (value: CalendarValue) => {
|
|
30
|
+
* console.log(value);
|
|
31
|
+
* };
|
|
32
|
+
*/
|
|
33
|
+
export type CalendarOnChange = (value: CalendarValue) => void;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Mantine DatePicker 공개 옵션.
|
|
37
|
+
* @property {Partial<Record<DatePickerStylesNames, string>>} [classNames] Mantine 내부 스타일 클래스 매핑
|
|
38
|
+
*/
|
|
39
|
+
export type CalendarDatePickerProps = Partial<
|
|
40
|
+
Omit<
|
|
41
|
+
MantineDatePickerProps<"default">,
|
|
42
|
+
| "value"
|
|
43
|
+
| "defaultValue"
|
|
44
|
+
| "onChange"
|
|
45
|
+
| "type"
|
|
46
|
+
| "numberOfColumns"
|
|
47
|
+
| "classNames"
|
|
48
|
+
| "styles"
|
|
49
|
+
>
|
|
50
|
+
> & {
|
|
51
|
+
/**
|
|
52
|
+
* Mantine 내부 스타일 classNames override.
|
|
53
|
+
*/
|
|
54
|
+
classNames?: Partial<Record<DatePickerStylesNames, string>>;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Calendar Grid props.
|
|
59
|
+
* @property {CalendarValue} value 현재 선택 값
|
|
60
|
+
* @property {CalendarOnChange} onChange 값 변경 핸들러
|
|
61
|
+
* @property {CalendarDatePickerProps} [datePickerProps] Mantine DatePicker 옵션
|
|
62
|
+
*/
|
|
63
|
+
export interface CalendarGridProps {
|
|
64
|
+
/**
|
|
65
|
+
* 현재 선택 값
|
|
66
|
+
*/
|
|
67
|
+
value: CalendarValue;
|
|
68
|
+
/**
|
|
69
|
+
* 값 변경 핸들러
|
|
70
|
+
*/
|
|
71
|
+
onChange: CalendarOnChange;
|
|
72
|
+
/**
|
|
73
|
+
* Mantine DatePicker 옵션
|
|
74
|
+
*/
|
|
75
|
+
datePickerProps?: CalendarDatePickerProps;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Calendar Layout Container props.
|
|
80
|
+
* @property {ReactNode} [header] 상단 콘텐츠
|
|
81
|
+
* @property {ReactNode} body 본문(Calendar Grid) 콘텐츠
|
|
82
|
+
* @property {ReactNode} [footer] 하단 콘텐츠
|
|
83
|
+
* @property {CalendarMode} [mode="date"] calendar 모드
|
|
84
|
+
* @property {CalendarColumns} [columns=1] 동시 표시 컬럼 수
|
|
85
|
+
* @property {boolean} [disabled] 비활성화 상태
|
|
86
|
+
* @property {boolean} [readOnly] 읽기 전용 상태
|
|
87
|
+
*/
|
|
88
|
+
export interface CalendarContainerProps {
|
|
89
|
+
/**
|
|
90
|
+
* 상단 콘텐츠
|
|
91
|
+
*/
|
|
92
|
+
header?: ReactNode;
|
|
93
|
+
/**
|
|
94
|
+
* 본문(Calendar Grid) 콘텐츠
|
|
95
|
+
*/
|
|
96
|
+
body: ReactNode;
|
|
97
|
+
/**
|
|
98
|
+
* 하단 콘텐츠
|
|
99
|
+
*/
|
|
100
|
+
footer?: ReactNode;
|
|
101
|
+
/**
|
|
102
|
+
* calendar 모드
|
|
103
|
+
*/
|
|
104
|
+
mode?: CalendarMode;
|
|
105
|
+
/**
|
|
106
|
+
* 동시 표시 컬럼 수
|
|
107
|
+
*/
|
|
108
|
+
columns?: CalendarColumns;
|
|
109
|
+
/**
|
|
110
|
+
* 비활성화 상태
|
|
111
|
+
*/
|
|
112
|
+
disabled?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* 읽기 전용 상태
|
|
115
|
+
*/
|
|
116
|
+
readOnly?: boolean;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Calendar Root props.
|
|
121
|
+
* @extends CalendarContainerProps
|
|
122
|
+
* @property {string} [className] Trigger element className override
|
|
123
|
+
* @property {CalendarValue} value 현재 선택 값
|
|
124
|
+
* @property {CalendarOnChange} onChange 값 변경 핸들러
|
|
125
|
+
* @property {CalendarDatePickerProps} [datePickerProps] Mantine DatePicker 옵션
|
|
126
|
+
* @property {ReactNode} children Trigger 슬롯(children)
|
|
127
|
+
* @property {boolean} [open] 제어형 open 상태
|
|
128
|
+
* @property {boolean} [defaultOpen] 비제어 초기 open 상태
|
|
129
|
+
* @property {(open: boolean) => void} [onOpenChange] open 상태 변경 핸들러
|
|
130
|
+
* @property {"top" | "right" | "bottom" | "left"} [side="bottom"] content 배치 방향
|
|
131
|
+
* @property {"start" | "center" | "end"} [align="start"] content 정렬 기준
|
|
132
|
+
* @property {number} [sideOffset=4] trigger와 content 간격
|
|
133
|
+
* @property {number} [alignOffset] 정렬 보정값
|
|
134
|
+
* @property {boolean} [withPortal=true] Portal 사용 여부
|
|
135
|
+
* @property {HTMLElement | null} [portalContainer] Portal 컨테이너
|
|
136
|
+
*/
|
|
137
|
+
export interface CalendarRootProps extends Omit<
|
|
138
|
+
CalendarContainerProps,
|
|
139
|
+
"body"
|
|
140
|
+
> {
|
|
141
|
+
/**
|
|
142
|
+
* Trigger element className override
|
|
143
|
+
*/
|
|
144
|
+
className?: string;
|
|
145
|
+
/**
|
|
146
|
+
* 현재 선택 값
|
|
147
|
+
*/
|
|
148
|
+
value: CalendarValue;
|
|
149
|
+
/**
|
|
150
|
+
* 값 변경 핸들러
|
|
151
|
+
*/
|
|
152
|
+
onChange: CalendarOnChange;
|
|
153
|
+
/**
|
|
154
|
+
* Mantine DatePicker 옵션
|
|
155
|
+
*/
|
|
156
|
+
datePickerProps?: CalendarDatePickerProps;
|
|
157
|
+
/**
|
|
158
|
+
* Trigger 슬롯(children)
|
|
159
|
+
*/
|
|
160
|
+
children: ReactNode;
|
|
161
|
+
/**
|
|
162
|
+
* 제어형 open 상태
|
|
163
|
+
*/
|
|
164
|
+
open?: boolean;
|
|
165
|
+
/**
|
|
166
|
+
* 비제어 초기 open 상태
|
|
167
|
+
*/
|
|
168
|
+
defaultOpen?: boolean;
|
|
169
|
+
/**
|
|
170
|
+
* open 상태 변경 핸들러
|
|
171
|
+
*/
|
|
172
|
+
onOpenChange?: (open: boolean) => void;
|
|
173
|
+
/**
|
|
174
|
+
* content 배치 방향
|
|
175
|
+
*/
|
|
176
|
+
side?: "top" | "right" | "bottom" | "left";
|
|
177
|
+
/**
|
|
178
|
+
* content 정렬 기준
|
|
179
|
+
*/
|
|
180
|
+
align?: "start" | "center" | "end";
|
|
181
|
+
/**
|
|
182
|
+
* trigger와 content 간격
|
|
183
|
+
*/
|
|
184
|
+
sideOffset?: number;
|
|
185
|
+
/**
|
|
186
|
+
* 정렬 보정값
|
|
187
|
+
*/
|
|
188
|
+
alignOffset?: number;
|
|
189
|
+
/**
|
|
190
|
+
* Portal 사용 여부
|
|
191
|
+
*/
|
|
192
|
+
withPortal?: boolean;
|
|
193
|
+
/**
|
|
194
|
+
* Portal 컨테이너
|
|
195
|
+
*/
|
|
196
|
+
portalContainer?: HTMLElement | null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Calendar 섹션 공용 props.
|
|
201
|
+
* @property {ReactNode} [children] 섹션 내부 콘텐츠
|
|
202
|
+
*/
|
|
203
|
+
export interface CalendarSectionProps {
|
|
204
|
+
/**
|
|
205
|
+
* 섹션 내부 콘텐츠
|
|
206
|
+
*/
|
|
207
|
+
children?: ReactNode;
|
|
208
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { dayjs } from "../../../init/dayjs";
|
|
2
|
+
import type { CalendarValue } from "../types";
|
|
3
|
+
|
|
4
|
+
const DATE_FORMAT = "YYYY-MM-DD";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Calendar value를 DatePicker value로 변환한다.
|
|
8
|
+
* @param {CalendarValue} value YYYY-MM-DD 문자열 값
|
|
9
|
+
* @returns {Date | null} DatePicker value
|
|
10
|
+
* @example
|
|
11
|
+
* mapValueToPicker("2026-02-13");
|
|
12
|
+
*/
|
|
13
|
+
export const mapValueToPicker = (value: CalendarValue) =>
|
|
14
|
+
value ? dayjs(value).toDate() : null;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* DatePicker value를 Calendar 직렬화 값으로 변환한다.
|
|
18
|
+
* @param {Date | null} value DatePicker value
|
|
19
|
+
* @returns {CalendarValue} YYYY-MM-DD 직렬화 값
|
|
20
|
+
* @example
|
|
21
|
+
* parseValueFromPicker(new Date("2026-02-13"));
|
|
22
|
+
*/
|
|
23
|
+
export const parseValueFromPicker = (value: Date | null): CalendarValue =>
|
|
24
|
+
value ? dayjs(value).format(DATE_FORMAT) : null;
|
|
@@ -31,31 +31,32 @@ const getIndicatorIcon = (size: CheckboxSize) =>
|
|
|
31
31
|
* @example
|
|
32
32
|
* <Checkbox size="medium" checked />
|
|
33
33
|
*/
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
)
|
|
39
|
-
const IndicatorIcon = getIndicatorIcon(size);
|
|
34
|
+
const Checkbox = forwardRef<HTMLButtonElement, CheckboxProps>(function Checkbox(
|
|
35
|
+
{ size = "medium", className, disabled, ...restProps },
|
|
36
|
+
ref,
|
|
37
|
+
) {
|
|
38
|
+
const IndicatorIcon = getIndicatorIcon(size);
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
40
|
+
return (
|
|
41
|
+
<CheckboxPrimitive.Root
|
|
42
|
+
ref={ref}
|
|
43
|
+
disabled={disabled}
|
|
44
|
+
data-size={size}
|
|
45
|
+
data-disabled={disabled ? "true" : undefined}
|
|
46
|
+
className={clsx(CHECKBOX_CLASSNAME, className)}
|
|
47
|
+
{...restProps}
|
|
48
|
+
>
|
|
49
|
+
<span className={CHECKBOX_SURFACE_CLASSNAME} aria-hidden="true">
|
|
50
|
+
<CheckboxPrimitive.Indicator className={CHECKBOX_INDICATOR_CLASSNAME}>
|
|
51
|
+
<IndicatorIcon aria-hidden />
|
|
52
|
+
</CheckboxPrimitive.Indicator>
|
|
53
|
+
</span>
|
|
54
|
+
</CheckboxPrimitive.Root>
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// forwardRef Tooltip 유지를 위해 displayName 지정.
|
|
59
|
+
Checkbox.displayName = "Checkbox";
|
|
59
60
|
|
|
60
61
|
/**
|
|
61
62
|
* 체크박스 필드 컴포넌트; label/helper 텍스트 래퍼
|
|
@@ -76,7 +77,7 @@ export const Checkbox = forwardRef<HTMLButtonElement, CheckboxProps>(
|
|
|
76
77
|
* @example
|
|
77
78
|
* <CheckboxField label="약관 동의" helperText="필수" checked />
|
|
78
79
|
*/
|
|
79
|
-
|
|
80
|
+
const CheckboxField = forwardRef<HTMLButtonElement, CheckboxFieldProps>(
|
|
80
81
|
function CheckboxField(
|
|
81
82
|
{
|
|
82
83
|
label,
|
|
@@ -146,3 +147,8 @@ export const CheckboxField = forwardRef<HTMLButtonElement, CheckboxFieldProps>(
|
|
|
146
147
|
);
|
|
147
148
|
},
|
|
148
149
|
);
|
|
150
|
+
|
|
151
|
+
// forwardRef Tooltip 유지를 위해 displayName 지정.
|
|
152
|
+
CheckboxField.displayName = "CheckboxField";
|
|
153
|
+
|
|
154
|
+
export { Checkbox, CheckboxField };
|
|
@@ -2,7 +2,16 @@ import { DropdownFoundation } from "./foundation";
|
|
|
2
2
|
import DropdownTemplate from "./Template";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Dropdown
|
|
5
|
+
* Dropdown
|
|
6
|
+
* - Provider
|
|
7
|
+
* - Root
|
|
8
|
+
* - Container
|
|
9
|
+
* - Menu
|
|
10
|
+
* - Item
|
|
11
|
+
* - List
|
|
12
|
+
* - Panel
|
|
13
|
+
* - Trigger
|
|
14
|
+
* - Template
|
|
6
15
|
*/
|
|
7
16
|
export const Dropdown = {
|
|
8
17
|
...DropdownFoundation,
|