@uniai-fe/uds-primitives 0.12.7 → 0.12.8
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/package.json +2 -2
- package/src/components/input/markup/date/Template.tsx +83 -33
- package/src/components/input/markup/date/Trigger.tsx +28 -12
- package/src/components/input/markup/date/range/Template.tsx +94 -35
- package/src/components/input/markup/time/Template.tsx +118 -5
- package/src/components/input/markup/time/Trigger.tsx +35 -2
- package/src/components/input/types/date.ts +176 -33
- package/src/components/input/types/time.ts +10 -4
- package/src/components/time-picker/markup/Footer.tsx +5 -5
- package/src/components/time-picker/markup/HourSection.tsx +7 -7
- package/src/components/time-picker/markup/MinuteSection.tsx +5 -5
- package/src/components/time-picker/markup/Summary.tsx +2 -2
- package/src/components/time-picker/markup/Template.tsx +11 -11
- package/src/components/time-picker/types/time-picker.ts +6 -0
- package/src/components/time-picker/utils/time.ts +21 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniai-fe/uds-primitives",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.8",
|
|
4
4
|
"description": "UNIAI Design System; Primitives Components Package",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -87,9 +87,9 @@
|
|
|
87
87
|
"react-hook-form": "^7.86.0",
|
|
88
88
|
"sass": "^1.102.0",
|
|
89
89
|
"typescript": "6.0.3",
|
|
90
|
-
"@uniai-fe/next-devkit": "0.4.1",
|
|
91
90
|
"@uniai-fe/eslint-config": "0.4.3",
|
|
92
91
|
"@uniai-fe/tsconfig": "0.2.0",
|
|
92
|
+
"@uniai-fe/next-devkit": "0.4.1",
|
|
93
93
|
"@uniai-fe/util-functions": "0.4.3",
|
|
94
94
|
"@uniai-fe/uds-foundation": "0.6.0"
|
|
95
95
|
},
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
ChangeEvent,
|
|
5
|
+
FocusEvent as ReactFocusEvent,
|
|
6
|
+
MouseEvent as ReactMouseEvent,
|
|
7
|
+
} from "react";
|
|
4
8
|
import { forwardRef, useCallback, useMemo, useState } from "react";
|
|
5
9
|
import { useUncontrolled } from "@mantine/hooks";
|
|
6
10
|
import { Calendar } from "../../../calendar";
|
|
@@ -26,30 +30,39 @@ const INPUT_DATE_TABLE_FORMAT = "YY-MM-DD";
|
|
|
26
30
|
* placeholder는 format과 별도 props로 처리되며, format 변경으로 placeholder가 자동 치환되지는 않는다.
|
|
27
31
|
* @component
|
|
28
32
|
* @param {InputCalendarProps} props
|
|
29
|
-
* @
|
|
30
|
-
* @
|
|
31
|
-
* @
|
|
32
|
-
* @
|
|
33
|
-
* @
|
|
34
|
-
* @
|
|
35
|
-
* @
|
|
36
|
-
* @
|
|
37
|
-
* @
|
|
38
|
-
* @
|
|
39
|
-
* @
|
|
40
|
-
* @
|
|
41
|
-
* @
|
|
42
|
-
* @
|
|
43
|
-
* @
|
|
44
|
-
* @
|
|
45
|
-
* @
|
|
46
|
-
* @
|
|
47
|
-
* @
|
|
48
|
-
* @
|
|
49
|
-
* @
|
|
50
|
-
* @
|
|
51
|
-
* @
|
|
52
|
-
* @
|
|
33
|
+
* @property {"date" | "date-time" | "time"} [props.mode="date"] Calendar layout mode. 선택 body는 date로 유지된다.
|
|
34
|
+
* @property {1 | 2} [props.columns=1] 동시 노출 달력 수
|
|
35
|
+
* @property {string | null} [props.value] 제어형 날짜 값
|
|
36
|
+
* @property {string | null} [props.defaultValue] 비제어 초기 날짜 값
|
|
37
|
+
* @property {(value: string | null) => void} [props.onChange] 값 변경 이벤트
|
|
38
|
+
* @property {(value: string | null) => void} [props.onValueChange] onChange alias
|
|
39
|
+
* @property {boolean} [props.readOnly] 읽기 전용 여부
|
|
40
|
+
* @property {boolean} [props.disabled] 비활성화 여부
|
|
41
|
+
* @property {CalendarDatePickerProps} [props.datePickerProps] Mantine DatePicker 옵션
|
|
42
|
+
* @property {string} [props.name] hidden input form name
|
|
43
|
+
* @property {string} [props.form] hidden input form id
|
|
44
|
+
* @property {UseFormRegisterReturn} [props.register] hidden input RHF register
|
|
45
|
+
* @property {boolean} [props.required] hidden input required 여부
|
|
46
|
+
* @property {InputCalendarHiddenInputProps} [props.hiddenInputProps] Template 고정값을 제외한 hidden input native props
|
|
47
|
+
* @property {string} [props.placeholder="YYYY-MM-DD"] placeholder
|
|
48
|
+
* @property {"primary" | "secondary" | "tertiary" | "table"} [props.priority="primary"] trigger input priority
|
|
49
|
+
* @property {"small" | "medium" | "large"} [props.size="medium"] trigger input size
|
|
50
|
+
* @property {"default" | "active" | "focused" | "success" | "error" | "disabled" | "loading"} [props.state="default"] trigger input state
|
|
51
|
+
* @property {boolean} [props.block=false] trigger width 100% 여부
|
|
52
|
+
* @property {"full" | "fit" | "fill" | "auto" | number | string} [props.width] trigger width preset 또는 custom width
|
|
53
|
+
* @property {(event: FocusEvent<HTMLInputElement>) => void} [props.onFocus] trigger focus 핸들러
|
|
54
|
+
* @property {(event: FocusEvent<HTMLInputElement>) => void} [props.onBlur] trigger blur 핸들러
|
|
55
|
+
* @property {ReactNode} [props.header] 패널 header 콘텐츠
|
|
56
|
+
* @property {ReactNode} [props.footer] 패널 footer 콘텐츠
|
|
57
|
+
* @property {InputCalendarTexts} [props.texts] 기본 Date 문구
|
|
58
|
+
* @property {unknown} [props.timePicker] 미구현 compatibility prop
|
|
59
|
+
* @property {boolean} [props.calendarOpened] calendar 열림 제어 상태
|
|
60
|
+
* @property {(open: boolean) => void} [props.onCalendarOpen] calendar 열림 변경 이벤트
|
|
61
|
+
* @property {(event: MouseEvent<Element>) => void} [props.onClick] trigger 클릭 핸들러
|
|
62
|
+
* @property {string} [props.id] trigger id
|
|
63
|
+
* @property {ReactNode} [props.trigger] 커스텀 trigger 슬롯
|
|
64
|
+
* @property {(props: InputCalendarTriggerRenderProps) => ReactNode} [props.renderTrigger] 커스텀 trigger 렌더 함수
|
|
65
|
+
* @desc 날짜 표시 trigger, Calendar panel과 YYYY-MM-DD hidden form storage를 조합한다.
|
|
53
66
|
*/
|
|
54
67
|
const InputDateTemplate = forwardRef<HTMLDivElement, InputCalendarProps>(
|
|
55
68
|
(
|
|
@@ -64,10 +77,18 @@ const InputDateTemplate = forwardRef<HTMLDivElement, InputCalendarProps>(
|
|
|
64
77
|
disabled,
|
|
65
78
|
datePickerProps,
|
|
66
79
|
name,
|
|
80
|
+
form,
|
|
67
81
|
register,
|
|
82
|
+
required,
|
|
83
|
+
hiddenInputProps,
|
|
68
84
|
placeholder = "YYYY-MM-DD",
|
|
69
85
|
priority = "primary",
|
|
86
|
+
size = "medium",
|
|
70
87
|
state = "default",
|
|
88
|
+
block = false,
|
|
89
|
+
width,
|
|
90
|
+
onFocus,
|
|
91
|
+
onBlur,
|
|
71
92
|
header,
|
|
72
93
|
footer,
|
|
73
94
|
texts,
|
|
@@ -88,7 +109,7 @@ const InputDateTemplate = forwardRef<HTMLDivElement, InputCalendarProps>(
|
|
|
88
109
|
* Input Date Template; Calendar open 상태 변경 전달 함수.
|
|
89
110
|
* 비제어 사용을 위해 내부 상태를 갱신하고, 제어형 사용을 위해 외부 owner에게 next open 값을 전달한다.
|
|
90
111
|
* @param {boolean} nextOpen 다음 calendar open 상태
|
|
91
|
-
* @
|
|
112
|
+
* @return {void}
|
|
92
113
|
*/
|
|
93
114
|
const handleCalendarOpenChange = useCallback(
|
|
94
115
|
(nextOpen: boolean) => {
|
|
@@ -113,7 +134,7 @@ const InputDateTemplate = forwardRef<HTMLDivElement, InputCalendarProps>(
|
|
|
113
134
|
* Input Date Template; RHF hidden input 변경 이벤트 동기화 함수.
|
|
114
135
|
* trigger 표시값과 form 저장값을 분리하기 위해 CalendarValue를 직렬화한 synthetic change를 register에 전달한다.
|
|
115
136
|
* @param {CalendarValue} nextValue 다음 calendar 선택 값
|
|
116
|
-
* @
|
|
137
|
+
* @return {void}
|
|
117
138
|
*/
|
|
118
139
|
const emitRegisterChange = useCallback(
|
|
119
140
|
(nextValue: CalendarValue) => {
|
|
@@ -140,7 +161,7 @@ const InputDateTemplate = forwardRef<HTMLDivElement, InputCalendarProps>(
|
|
|
140
161
|
* Input Date Template; calendar value 갱신 함수.
|
|
141
162
|
* 내부/제어형 value pipeline을 갱신한 뒤 RHF register 저장값을 같은 CalendarValue 기준으로 동기화한다.
|
|
142
163
|
* @param {CalendarValue} nextValue 다음 calendar 선택 값
|
|
143
|
-
* @
|
|
164
|
+
* @return {void}
|
|
144
165
|
*/
|
|
145
166
|
const updateValue = useCallback(
|
|
146
167
|
(nextValue: CalendarValue) => {
|
|
@@ -164,17 +185,33 @@ const InputDateTemplate = forwardRef<HTMLDivElement, InputCalendarProps>(
|
|
|
164
185
|
* Input Date Template; trigger click 위임 함수.
|
|
165
186
|
* Calendar Root의 PopOver toggle은 asChild trigger props가 담당하고, 이 함수는 소비자가 넘긴 trigger onClick만 보존한다.
|
|
166
187
|
* @param {ReactMouseEvent<Element>} event trigger click event
|
|
167
|
-
* @
|
|
188
|
+
* @return {void}
|
|
168
189
|
*/
|
|
169
190
|
const handleTriggerClick = (event: ReactMouseEvent<Element>) => {
|
|
170
191
|
triggerOnClick?.(event);
|
|
171
192
|
};
|
|
172
193
|
|
|
194
|
+
/**
|
|
195
|
+
* Input Date Template; trigger blur와 RHF touched 상태 동기화 함수.
|
|
196
|
+
* 표시 trigger는 form name을 소유하지 않으므로 직렬화된 hidden input 값을 synthetic blur event로 전달한다.
|
|
197
|
+
* @utility
|
|
198
|
+
* @param {ReactFocusEvent<HTMLInputElement>} event trigger blur event
|
|
199
|
+
* @desc 소비자 blur callback과 hidden input register blur를 같은 날짜 값으로 동기화한다.
|
|
200
|
+
* @return {void}
|
|
201
|
+
*/
|
|
202
|
+
const handleTriggerBlur = (event: ReactFocusEvent<HTMLInputElement>) => {
|
|
203
|
+
register?.onBlur({
|
|
204
|
+
target: { name: register.name, value: serializedCalendarValue },
|
|
205
|
+
type: "blur",
|
|
206
|
+
});
|
|
207
|
+
onBlur?.(event);
|
|
208
|
+
};
|
|
209
|
+
|
|
173
210
|
/**
|
|
174
211
|
* Input Date Template; Calendar Core change adapter 함수.
|
|
175
212
|
* Calendar.Root의 onChange 값을 Template value/RHF 동기화 pipeline으로 연결한다.
|
|
176
213
|
* @param {CalendarValue} nextValue 다음 calendar 선택 값
|
|
177
|
-
* @
|
|
214
|
+
* @return {void}
|
|
178
215
|
*/
|
|
179
216
|
const handleCalendarChange = (nextValue: CalendarValue) => {
|
|
180
217
|
updateValue(nextValue);
|
|
@@ -201,7 +238,12 @@ const InputDateTemplate = forwardRef<HTMLDivElement, InputCalendarProps>(
|
|
|
201
238
|
readOnly,
|
|
202
239
|
onClick: handleTriggerClick,
|
|
203
240
|
priority,
|
|
241
|
+
size,
|
|
204
242
|
state,
|
|
243
|
+
block,
|
|
244
|
+
width,
|
|
245
|
+
onFocus,
|
|
246
|
+
onBlur: handleTriggerBlur,
|
|
205
247
|
};
|
|
206
248
|
|
|
207
249
|
const triggerNode = trigger ?? renderTrigger?.(triggerRenderProps) ?? (
|
|
@@ -214,6 +256,11 @@ const InputDateTemplate = forwardRef<HTMLDivElement, InputCalendarProps>(
|
|
|
214
256
|
readOnly={readOnly}
|
|
215
257
|
onClick={handleTriggerClick}
|
|
216
258
|
priority={priority}
|
|
259
|
+
size={size}
|
|
260
|
+
block={block}
|
|
261
|
+
width={width}
|
|
262
|
+
onFocus={onFocus}
|
|
263
|
+
onBlur={handleTriggerBlur}
|
|
217
264
|
/>
|
|
218
265
|
);
|
|
219
266
|
|
|
@@ -228,7 +275,7 @@ const InputDateTemplate = forwardRef<HTMLDivElement, InputCalendarProps>(
|
|
|
228
275
|
readOnly={readOnly}
|
|
229
276
|
value={calendarValue}
|
|
230
277
|
onChange={handleCalendarChange}
|
|
231
|
-
//
|
|
278
|
+
// Mantine DatePicker는 valueFormat prop을 지원하지 않으므로 옵션을 그대로 전달한다.
|
|
232
279
|
datePickerProps={datePickerProps}
|
|
233
280
|
header={header}
|
|
234
281
|
footer={footerContent}
|
|
@@ -239,11 +286,14 @@ const InputDateTemplate = forwardRef<HTMLDivElement, InputCalendarProps>(
|
|
|
239
286
|
</Calendar.Root>
|
|
240
287
|
{(register?.name || name) && (
|
|
241
288
|
<input
|
|
242
|
-
//
|
|
289
|
+
// trigger 표시값과 form 저장값을 분리해 hidden input만 form에 참여한다.
|
|
290
|
+
{...hiddenInputProps}
|
|
291
|
+
{...register}
|
|
243
292
|
type="hidden"
|
|
244
293
|
value={serializedCalendarValue}
|
|
245
294
|
name={register?.name ?? name}
|
|
246
|
-
{
|
|
295
|
+
form={form ?? hiddenInputProps?.form}
|
|
296
|
+
required={required ?? hiddenInputProps?.required}
|
|
247
297
|
/>
|
|
248
298
|
)}
|
|
249
299
|
</>
|
|
@@ -19,17 +19,23 @@ import type { InputCalendarTriggerViewProps } from "../../types";
|
|
|
19
19
|
* 그 외 priority에서는 기존처럼 right 슬롯을 유지한다.
|
|
20
20
|
* @component
|
|
21
21
|
* @param {InputCalendarTriggerViewProps} props
|
|
22
|
-
* @
|
|
23
|
-
* @
|
|
24
|
-
* @
|
|
25
|
-
* @
|
|
26
|
-
* @
|
|
27
|
-
* @
|
|
28
|
-
* @
|
|
29
|
-
* @
|
|
30
|
-
* @
|
|
31
|
-
* @
|
|
32
|
-
* @
|
|
22
|
+
* @property {string} [props.className] trigger className
|
|
23
|
+
* @property {string} [props.placeholder] placeholder
|
|
24
|
+
* @property {string} [props.displayValue] 표시 문자열
|
|
25
|
+
* @property {(event: MouseEvent<Element>) => void} [props.onClick] 클릭 핸들러
|
|
26
|
+
* @property {boolean} [props.disabled] disabled 여부
|
|
27
|
+
* @property {boolean} [props.readOnly] readOnly 여부
|
|
28
|
+
* @property {"primary" | "secondary" | "tertiary" | "table"} [props.priority] trigger input priority
|
|
29
|
+
* @property {"small" | "medium" | "large"} [props.size] trigger input size
|
|
30
|
+
* @property {"default" | "active" | "focused" | "success" | "error" | "disabled" | "loading"} [props.state] trigger input state
|
|
31
|
+
* @property {boolean} [props.block] trigger width 100% 여부
|
|
32
|
+
* @property {"full" | "fit" | "fill" | "auto" | number | string} [props.width] trigger width preset 또는 custom width
|
|
33
|
+
* @property {(event: FocusEvent<HTMLInputElement>) => void} [props.onFocus] trigger focus 핸들러
|
|
34
|
+
* @property {(event: FocusEvent<HTMLInputElement>) => void} [props.onBlur] trigger blur 핸들러
|
|
35
|
+
* @property {string} [props.id] input id
|
|
36
|
+
* @property {string} [props.name] form name
|
|
37
|
+
* @property {UseFormRegisterReturn} [props.register] RHF register
|
|
38
|
+
* @desc Date 값을 직접 편집하지 않고 Calendar 선택값을 표시하는 기본 trigger다.
|
|
33
39
|
*/
|
|
34
40
|
const InputDateTrigger = forwardRef<
|
|
35
41
|
HTMLInputElement,
|
|
@@ -44,7 +50,12 @@ const InputDateTrigger = forwardRef<
|
|
|
44
50
|
disabled,
|
|
45
51
|
readOnly,
|
|
46
52
|
priority,
|
|
53
|
+
size,
|
|
47
54
|
state,
|
|
55
|
+
block,
|
|
56
|
+
width,
|
|
57
|
+
onFocus,
|
|
58
|
+
onBlur,
|
|
48
59
|
id,
|
|
49
60
|
name,
|
|
50
61
|
register,
|
|
@@ -90,7 +101,7 @@ const InputDateTrigger = forwardRef<
|
|
|
90
101
|
triggerInputRef.current?.click();
|
|
91
102
|
};
|
|
92
103
|
|
|
93
|
-
//
|
|
104
|
+
// Date trigger는 직접 타이핑을 막아 달력 선택을 단일 입력 경로로 유지한다.
|
|
94
105
|
const shouldBlockTyping = !disabled && !readOnly;
|
|
95
106
|
|
|
96
107
|
const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
|
|
@@ -170,9 +181,14 @@ const InputDateTrigger = forwardRef<
|
|
|
170
181
|
name={name ?? register?.name}
|
|
171
182
|
register={register}
|
|
172
183
|
priority={priority}
|
|
184
|
+
size={size}
|
|
173
185
|
state={state}
|
|
186
|
+
block={block}
|
|
187
|
+
width={width}
|
|
174
188
|
placeholder={placeholder}
|
|
175
189
|
className={clsx("input-date-trigger-input", className)}
|
|
190
|
+
onFocus={onFocus}
|
|
191
|
+
onBlur={onBlur}
|
|
176
192
|
onClick={handleInputClick}
|
|
177
193
|
onKeyDown={handleKeyDown}
|
|
178
194
|
onBeforeInput={handleBeforeInput}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
ChangeEvent,
|
|
5
|
+
FocusEvent as ReactFocusEvent,
|
|
6
|
+
MouseEvent as ReactMouseEvent,
|
|
7
|
+
} from "react";
|
|
4
8
|
import { forwardRef, useCallback, useMemo, useState } from "react";
|
|
5
9
|
import { useUncontrolled } from "@mantine/hooks";
|
|
6
10
|
import type { UseFormRegisterReturn } from "react-hook-form";
|
|
@@ -31,29 +35,39 @@ const INPUT_DATE_RANGE_TABLE_FORMAT = "YY-MM-DD";
|
|
|
31
35
|
* form 저장은 start/end hidden input 2개로 분리한다.
|
|
32
36
|
* @component
|
|
33
37
|
* @param {InputCalendarRangeProps} props range date props
|
|
34
|
-
* @
|
|
35
|
-
* @
|
|
36
|
-
* @
|
|
37
|
-
* @
|
|
38
|
-
* @
|
|
39
|
-
* @
|
|
40
|
-
* @
|
|
41
|
-
* @
|
|
42
|
-
* @
|
|
43
|
-
* @
|
|
44
|
-
* @
|
|
45
|
-
* @
|
|
46
|
-
* @
|
|
47
|
-
* @
|
|
48
|
-
* @
|
|
49
|
-
* @
|
|
50
|
-
* @
|
|
51
|
-
* @
|
|
52
|
-
* @
|
|
53
|
-
* @
|
|
54
|
-
* @
|
|
55
|
-
* @
|
|
56
|
-
* @
|
|
38
|
+
* @property {[string | null, string | null]} [props.value] 제어형 range 값
|
|
39
|
+
* @property {[string | null, string | null]} [props.defaultValue] 비제어 range 초기값
|
|
40
|
+
* @property {(value: [string | null, string | null]) => void} [props.onChange] range 값 변경 이벤트
|
|
41
|
+
* @property {(value: [string | null, string | null]) => void} [props.onValueChange] onChange alias
|
|
42
|
+
* @property {boolean} [props.readOnly] 읽기 전용 여부
|
|
43
|
+
* @property {boolean} [props.disabled] 비활성화 여부
|
|
44
|
+
* @property {CalendarRangeDatePickerProps} [props.datePickerProps] Mantine range DatePicker 옵션
|
|
45
|
+
* @property {string} [props.startName] 시작일 hidden input name
|
|
46
|
+
* @property {string} [props.endName] 종료일 hidden input name
|
|
47
|
+
* @property {string} [props.form] start/end hidden input form id
|
|
48
|
+
* @property {UseFormRegisterReturn} [props.startRegister] 시작일 RHF register
|
|
49
|
+
* @property {UseFormRegisterReturn} [props.endRegister] 종료일 RHF register
|
|
50
|
+
* @property {boolean} [props.required] start/end hidden input required 여부
|
|
51
|
+
* @property {InputCalendarHiddenInputProps} [props.startHiddenInputProps] 시작일 hidden input native props
|
|
52
|
+
* @property {InputCalendarHiddenInputProps} [props.endHiddenInputProps] 종료일 hidden input native props
|
|
53
|
+
* @property {string} [props.placeholder="YYYY-MM-DD ~ YYYY-MM-DD"] placeholder
|
|
54
|
+
* @property {"primary" | "secondary" | "tertiary" | "table"} [props.priority="primary"] trigger input priority
|
|
55
|
+
* @property {"small" | "medium" | "large"} [props.size="medium"] trigger input size
|
|
56
|
+
* @property {"default" | "active" | "focused" | "success" | "error" | "disabled" | "loading"} [props.state="default"] trigger input state
|
|
57
|
+
* @property {boolean} [props.block=false] trigger width 100% 여부
|
|
58
|
+
* @property {"full" | "fit" | "fill" | "auto" | number | string} [props.width] trigger width preset 또는 custom width
|
|
59
|
+
* @property {(event: FocusEvent<HTMLInputElement>) => void} [props.onFocus] trigger focus 핸들러
|
|
60
|
+
* @property {(event: FocusEvent<HTMLInputElement>) => void} [props.onBlur] trigger blur 핸들러
|
|
61
|
+
* @property {ReactNode} [props.header] 패널 header 콘텐츠
|
|
62
|
+
* @property {ReactNode} [props.footer] 패널 footer 콘텐츠
|
|
63
|
+
* @property {InputCalendarTexts} [props.texts] 기본 Date 문구
|
|
64
|
+
* @property {boolean} [props.calendarOpened] calendar 열림 제어 상태
|
|
65
|
+
* @property {(open: boolean) => void} [props.onCalendarOpen] calendar 열림 변경 이벤트
|
|
66
|
+
* @property {string} [props.id] trigger id
|
|
67
|
+
* @property {ReactNode} [props.trigger] 커스텀 trigger 슬롯
|
|
68
|
+
* @property {(props: InputCalendarTriggerRenderProps) => ReactNode} [props.renderTrigger] 커스텀 trigger 렌더 함수
|
|
69
|
+
* @property {(event: MouseEvent<Element>) => void} [props.onClick] trigger 클릭 핸들러
|
|
70
|
+
* @desc 기간 표시 trigger, Calendar.Range panel과 start/end hidden form storage를 조합한다.
|
|
57
71
|
* @example
|
|
58
72
|
* <Input.Date.Range.Template
|
|
59
73
|
* startName="start_date"
|
|
@@ -74,11 +88,20 @@ const InputDateRangeTemplate = forwardRef<HTMLElement, InputCalendarRangeProps>(
|
|
|
74
88
|
datePickerProps,
|
|
75
89
|
startName,
|
|
76
90
|
endName,
|
|
91
|
+
form,
|
|
77
92
|
startRegister,
|
|
78
93
|
endRegister,
|
|
94
|
+
required,
|
|
95
|
+
startHiddenInputProps,
|
|
96
|
+
endHiddenInputProps,
|
|
79
97
|
placeholder = "YYYY-MM-DD ~ YYYY-MM-DD",
|
|
80
98
|
priority = "primary",
|
|
99
|
+
size = "medium",
|
|
81
100
|
state = "default",
|
|
101
|
+
block = false,
|
|
102
|
+
width,
|
|
103
|
+
onFocus,
|
|
104
|
+
onBlur,
|
|
82
105
|
header,
|
|
83
106
|
footer,
|
|
84
107
|
texts,
|
|
@@ -99,7 +122,7 @@ const InputDateRangeTemplate = forwardRef<HTMLElement, InputCalendarRangeProps>(
|
|
|
99
122
|
* Input Date Range Template; Calendar open 상태 변경 전달 함수.
|
|
100
123
|
* 비제어 range calendar 상태를 갱신하고, 제어형 owner가 열림 상태를 조율할 수 있게 next open 값을 전달한다.
|
|
101
124
|
* @param {boolean} nextOpen 다음 range calendar open 상태
|
|
102
|
-
* @
|
|
125
|
+
* @return {void}
|
|
103
126
|
*/
|
|
104
127
|
const handleCalendarOpenChange = useCallback(
|
|
105
128
|
(nextOpen: boolean) => {
|
|
@@ -125,7 +148,7 @@ const InputDateRangeTemplate = forwardRef<HTMLElement, InputCalendarRangeProps>(
|
|
|
125
148
|
* Input Date Range Template; RHF hidden input 변경 이벤트 동기화 함수.
|
|
126
149
|
* range tuple의 start/end 값을 각각 직렬화해 startRegister/endRegister에 synthetic change로 전달한다.
|
|
127
150
|
* @param {CalendarRangeValue} nextValue 다음 range calendar 선택 값
|
|
128
|
-
* @
|
|
151
|
+
* @return {void}
|
|
129
152
|
*/
|
|
130
153
|
const emitRegisterChange = useCallback(
|
|
131
154
|
(nextValue: CalendarRangeValue) => {
|
|
@@ -134,7 +157,7 @@ const InputDateRangeTemplate = forwardRef<HTMLElement, InputCalendarRangeProps>(
|
|
|
134
157
|
* start 또는 end register 한쪽에 직렬화 값을 전달한다.
|
|
135
158
|
* @param {UseFormRegisterReturn | undefined} register RHF register 결과
|
|
136
159
|
* @param {CalendarValue} nextCalendarValue 다음 start/end 선택 값
|
|
137
|
-
* @
|
|
160
|
+
* @return {void}
|
|
138
161
|
*/
|
|
139
162
|
const emit = (
|
|
140
163
|
register: UseFormRegisterReturn | undefined,
|
|
@@ -169,7 +192,7 @@ const InputDateRangeTemplate = forwardRef<HTMLElement, InputCalendarRangeProps>(
|
|
|
169
192
|
* Input Date Range Template; range value 갱신 함수.
|
|
170
193
|
* Calendar.Range tuple 값을 갱신하고 start/end hidden input 저장값을 같은 tuple 기준으로 동기화한다.
|
|
171
194
|
* @param {CalendarRangeValue} nextValue 다음 range calendar 선택 값
|
|
172
|
-
* @
|
|
195
|
+
* @return {void}
|
|
173
196
|
*/
|
|
174
197
|
const updateValue = useCallback(
|
|
175
198
|
(nextValue: CalendarRangeValue) => {
|
|
@@ -194,17 +217,37 @@ const InputDateRangeTemplate = forwardRef<HTMLElement, InputCalendarRangeProps>(
|
|
|
194
217
|
* Input Date Range Template; trigger click 위임 함수.
|
|
195
218
|
* Calendar.Range Root의 PopOver toggle은 asChild trigger props가 담당하고, 이 함수는 소비자가 넘긴 trigger onClick만 보존한다.
|
|
196
219
|
* @param {ReactMouseEvent<Element>} event trigger click event
|
|
197
|
-
* @
|
|
220
|
+
* @return {void}
|
|
198
221
|
*/
|
|
199
222
|
const handleTriggerClick = (event: ReactMouseEvent<Element>) => {
|
|
200
223
|
triggerOnClick?.(event);
|
|
201
224
|
};
|
|
202
225
|
|
|
226
|
+
/**
|
|
227
|
+
* Input Date Range Template; trigger blur와 start/end RHF touched 상태 동기화 함수.
|
|
228
|
+
* 표시 trigger는 저장 endpoint를 소유하지 않으므로 직렬화한 start/end 값을 각 register에 전달한다.
|
|
229
|
+
* @utility
|
|
230
|
+
* @param {ReactFocusEvent<HTMLInputElement>} event trigger blur event
|
|
231
|
+
* @desc 소비자 blur callback과 두 hidden input register blur를 같은 range 값으로 동기화한다.
|
|
232
|
+
* @return {void}
|
|
233
|
+
*/
|
|
234
|
+
const handleTriggerBlur = (event: ReactFocusEvent<HTMLInputElement>) => {
|
|
235
|
+
startRegister?.onBlur({
|
|
236
|
+
target: { name: startRegister.name, value: serializedStartValue },
|
|
237
|
+
type: "blur",
|
|
238
|
+
});
|
|
239
|
+
endRegister?.onBlur({
|
|
240
|
+
target: { name: endRegister.name, value: serializedEndValue },
|
|
241
|
+
type: "blur",
|
|
242
|
+
});
|
|
243
|
+
onBlur?.(event);
|
|
244
|
+
};
|
|
245
|
+
|
|
203
246
|
/**
|
|
204
247
|
* Input Date Range Template; Calendar Range Core change adapter 함수.
|
|
205
248
|
* Calendar.Range.Root의 onChange 값을 Template tuple/RHF 동기화 pipeline으로 연결한다.
|
|
206
249
|
* @param {CalendarRangeValue} nextValue 다음 range calendar 선택 값
|
|
207
|
-
* @
|
|
250
|
+
* @return {void}
|
|
208
251
|
*/
|
|
209
252
|
const handleCalendarChange = (nextValue: CalendarRangeValue) => {
|
|
210
253
|
updateValue(nextValue);
|
|
@@ -232,7 +275,7 @@ const InputDateRangeTemplate = forwardRef<HTMLElement, InputCalendarRangeProps>(
|
|
|
232
275
|
>
|
|
233
276
|
{texts?.clear ?? "삭제하기"}
|
|
234
277
|
</InputDateClearButton>
|
|
235
|
-
{/*
|
|
278
|
+
{/* range footer는 삭제/적용을 같은 row에 두고 Apply 폭을 content 기준으로 줄인다. */}
|
|
236
279
|
<InputDateApplyButton
|
|
237
280
|
className="input-date-range-apply-button"
|
|
238
281
|
disabled={disabled}
|
|
@@ -252,7 +295,12 @@ const InputDateRangeTemplate = forwardRef<HTMLElement, InputCalendarRangeProps>(
|
|
|
252
295
|
readOnly,
|
|
253
296
|
onClick: handleTriggerClick,
|
|
254
297
|
priority,
|
|
298
|
+
size,
|
|
255
299
|
state,
|
|
300
|
+
block,
|
|
301
|
+
width,
|
|
302
|
+
onFocus,
|
|
303
|
+
onBlur: handleTriggerBlur,
|
|
256
304
|
};
|
|
257
305
|
|
|
258
306
|
const triggerNode = trigger ?? renderTrigger?.(triggerRenderProps) ?? (
|
|
@@ -265,6 +313,11 @@ const InputDateRangeTemplate = forwardRef<HTMLElement, InputCalendarRangeProps>(
|
|
|
265
313
|
readOnly={readOnly}
|
|
266
314
|
onClick={handleTriggerClick}
|
|
267
315
|
priority={priority}
|
|
316
|
+
size={size}
|
|
317
|
+
block={block}
|
|
318
|
+
width={width}
|
|
319
|
+
onFocus={onFocus}
|
|
320
|
+
onBlur={handleTriggerBlur}
|
|
268
321
|
/>
|
|
269
322
|
);
|
|
270
323
|
|
|
@@ -287,20 +340,26 @@ const InputDateRangeTemplate = forwardRef<HTMLElement, InputCalendarRangeProps>(
|
|
|
287
340
|
</Calendar.Range.Root>
|
|
288
341
|
{(startRegister?.name || startName) && (
|
|
289
342
|
<input
|
|
290
|
-
//
|
|
343
|
+
// range 시작일 저장값은 trigger 표시와 분리해 hidden input이 담당한다.
|
|
344
|
+
{...startHiddenInputProps}
|
|
345
|
+
{...startRegister}
|
|
291
346
|
type="hidden"
|
|
292
347
|
value={serializedStartValue}
|
|
293
348
|
name={startRegister?.name ?? startName}
|
|
294
|
-
{
|
|
349
|
+
form={form ?? startHiddenInputProps?.form}
|
|
350
|
+
required={required ?? startHiddenInputProps?.required}
|
|
295
351
|
/>
|
|
296
352
|
)}
|
|
297
353
|
{(endRegister?.name || endName) && (
|
|
298
354
|
<input
|
|
299
|
-
//
|
|
355
|
+
// range 종료일 저장값은 trigger 표시와 분리해 hidden input이 담당한다.
|
|
356
|
+
{...endHiddenInputProps}
|
|
357
|
+
{...endRegister}
|
|
300
358
|
type="hidden"
|
|
301
359
|
value={serializedEndValue}
|
|
302
360
|
name={endRegister?.name ?? endName}
|
|
303
|
-
{
|
|
361
|
+
form={form ?? endHiddenInputProps?.form}
|
|
362
|
+
required={required ?? endHiddenInputProps?.required}
|
|
304
363
|
/>
|
|
305
364
|
)}
|
|
306
365
|
</>
|