@uniai-fe/uds-primitives 0.3.26 → 0.3.28

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniai-fe/uds-primitives",
3
- "version": "0.3.26",
3
+ "version": "0.3.28",
4
4
  "description": "UNIAI Design System; Primitives Components Package",
5
5
  "type": "module",
6
6
  "private": false,
@@ -35,3 +35,11 @@ export type SelectState = "default" | "focused" | "error" | "disabled";
35
35
  * - reset: form reset trigger
36
36
  */
37
37
  export type SelectTriggerButtonType = "button" | "submit" | "reset";
38
+
39
+ /**
40
+ * Select option data optionality
41
+ * @typedef {"optional" | "required"} SelectOptionDataOptionality
42
+ * - optional: option.data를 선택 속성으로 유지
43
+ * - required: option.data를 필수 속성으로 강제
44
+ */
45
+ export type SelectOptionDataOptionality = "optional" | "required";
@@ -1,4 +1,5 @@
1
1
  import type { ReactNode } from "react";
2
+ import type { SelectOptionDataOptionality } from "./base";
2
3
 
3
4
  /**
4
5
  * Select option value 타입
@@ -15,7 +16,7 @@ export type SelectOptionValue = string | number;
15
16
  * @property {boolean} [selected] uncontrolled 초기 선택 여부(권장 초기화 필드)
16
17
  * @property {OptionData} [data] 도메인 확장 payload(서비스 2차 활용 데이터)
17
18
  */
18
- export interface SelectOptionData<OptionData = unknown> {
19
+ export interface SelectOptionDataBase {
19
20
  /**
20
21
  * 선택 상태 추적용 고유 id
21
22
  * - UI 선택 상태 비교의 기준값이다.
@@ -42,13 +43,61 @@ export interface SelectOptionData<OptionData = unknown> {
42
43
  * - selectedOptionIds 없이도 초기값을 선언할 수 있는 권장 필드다.
43
44
  */
44
45
  selected?: boolean;
45
- /**
46
- * 도메인 확장 payload
47
- * - 선택 후 서비스 코드에서 2차 데이터로 활용할 수 있다.
48
- */
49
- data?: OptionData;
50
46
  }
51
47
 
48
+ /**
49
+ * Select option data payload; optionality 제어 타입
50
+ * @property {OptionData} [data] optional 모드 데이터(생략 가능)
51
+ * @property {OptionData} data required 모드 데이터(필수)
52
+ * @example
53
+ * type OptionalPayload = SelectOptionDataPayload<{ id: number }, "optional">;
54
+ * // { data?: { id: number } }
55
+ *
56
+ * type RequiredPayload = SelectOptionDataPayload<{ id: number }, "required">;
57
+ * // { data: { id: number } }
58
+ */
59
+ export type SelectOptionDataPayload<
60
+ OptionData = unknown,
61
+ DataOptionality extends SelectOptionDataOptionality = "optional",
62
+ > = DataOptionality extends "required"
63
+ ? {
64
+ /**
65
+ * 도메인 확장 payload
66
+ * - 선택 후 서비스 코드에서 2차 데이터로 활용한다.
67
+ * - required 모드에서는 필수다.
68
+ */
69
+ data: OptionData;
70
+ }
71
+ : {
72
+ /**
73
+ * 도메인 확장 payload
74
+ * - 선택 후 서비스 코드에서 2차 데이터로 활용한다.
75
+ * - optional 모드에서는 생략 가능하다.
76
+ */
77
+ data?: OptionData;
78
+ };
79
+
80
+ /**
81
+ * Select option data; optionality 제어가 포함된 최종 데이터 계약
82
+ * @property {string} id 선택 상태 추적용 고유 id
83
+ * @property {SelectOptionValue} value 실제 제출값
84
+ * @property {ReactNode} label 사용자 표시 라벨
85
+ * @property {boolean} [disabled] 선택 불가 상태 여부
86
+ * @property {boolean} [selected] uncontrolled 초기 선택 여부
87
+ * @property {OptionData} [data] optionality="optional"일 때 선택 payload
88
+ * @property {OptionData} data optionality="required"일 때 필수 payload
89
+ * @example
90
+ * type OptionalOption = SelectOptionData<{ code: string }, "optional">;
91
+ * // data?: { code: string }
92
+ *
93
+ * type RequiredOption = SelectOptionData<{ code: string }, "required">;
94
+ * // data: { code: string }
95
+ */
96
+ export type SelectOptionData<
97
+ OptionData = unknown,
98
+ DataOptionality extends SelectOptionDataOptionality = "optional",
99
+ > = SelectOptionDataBase & SelectOptionDataPayload<OptionData, DataOptionality>;
100
+
52
101
  /**
53
102
  * Select option render data; Dropdown.Menu.Item 시각 보조 정보
54
103
  * @property {ReactNode} [description] 보조 텍스트
@@ -88,11 +137,27 @@ export interface SelectOptionRenderData {
88
137
  * @property {ReactNode} label 사용자 노출 라벨
89
138
  * @property {boolean} [disabled] 비활성 여부
90
139
  * @property {boolean} [selected] uncontrolled 초기 선택 여부
91
- * @property {OptionData} [data] 추가 데이터 payload
140
+ * @property {OptionData} [data] optionality="optional"일 때 추가 데이터 payload
141
+ * @property {OptionData} data optionality="required"일 때 추가 데이터 payload(필수)
92
142
  * @property {ReactNode} [description] 보조 텍스트
93
143
  * @property {ReactNode} [left] 좌측 콘텐츠
94
144
  * @property {ReactNode} [right] 우측 콘텐츠
95
145
  * @property {boolean} [multiple] multi select 스타일 여부
146
+ * @example
147
+ * const optionA: SelectDropdownOption<{ metaKey: number }, "optional"> = {
148
+ * id: "1",
149
+ * value: 1,
150
+ * label: "기본",
151
+ * };
152
+ *
153
+ * const optionB: SelectDropdownOption<{ metaKey: number }, "required"> = {
154
+ * id: "2",
155
+ * value: 2,
156
+ * label: "필수",
157
+ * data: { metaKey: 2 },
158
+ * };
96
159
  */
97
- export interface SelectDropdownOption<OptionData = unknown>
98
- extends SelectOptionData<OptionData>, SelectOptionRenderData {}
160
+ export type SelectDropdownOption<
161
+ OptionData = unknown,
162
+ DataOptionality extends SelectOptionDataOptionality = "optional",
163
+ > = SelectOptionData<OptionData, DataOptionality> & SelectOptionRenderData;
@@ -12,7 +12,12 @@ import type {
12
12
  DropdownPanelWidth,
13
13
  } from "../../dropdown/types";
14
14
  import type { FormFieldWidth } from "../../form/types";
15
- import type { SelectPriority, SelectSize, SelectState } from "./base";
15
+ import type {
16
+ SelectOptionDataOptionality,
17
+ SelectPriority,
18
+ SelectSize,
19
+ SelectState,
20
+ } from "./base";
16
21
  import type { SelectDropdownOption } from "./option";
17
22
  import type {
18
23
  SelectTriggerDefaultProps,
@@ -165,13 +170,22 @@ export interface SelectFormRegisterExtension {
165
170
 
166
171
  /**
167
172
  * Select callback params
168
- * @property {SelectDropdownOption} [nextOption] 현재 상호작용한 option
169
- * @property {SelectDropdownOption} [prevOption] 이전 기준 option
173
+ * @property {SelectDropdownOption<OptionData, DataOptionality>} [nextOption] 현재 상호작용한 option
174
+ * @property {SelectDropdownOption<OptionData, DataOptionality>} [prevOption] 이전 기준 option
170
175
  * @property {Event} [event] 원본 메뉴 선택 이벤트
176
+ * @example
177
+ * const onChange: SelectCallbackParams<{ code: string }, "required"> = (
178
+ * nextOption,
179
+ * ) => {
180
+ * // nextOption?.data 는 { code: string } | undefined
181
+ * };
171
182
  */
172
- export type SelectCallbackParams<OptionData = unknown> = (
173
- nextOption?: SelectDropdownOption<OptionData>,
174
- prevOption?: SelectDropdownOption<OptionData>,
183
+ export type SelectCallbackParams<
184
+ OptionData = unknown,
185
+ DataOptionality extends SelectOptionDataOptionality = "optional",
186
+ > = (
187
+ nextOption?: SelectDropdownOption<OptionData, DataOptionality>,
188
+ prevOption?: SelectDropdownOption<OptionData, DataOptionality>,
175
189
  event?: Event,
176
190
  ) => void;
177
191
 
@@ -213,24 +227,30 @@ export interface SelectDropdownExtension {
213
227
 
214
228
  /**
215
229
  * Select dropdown 옵션 구성 props
216
- * @property {SelectDropdownOption[]} [items] dropdown item 리스트(권장: items[].selected 초기값)
217
- * @property {SelectCallbackParams} [onSelectOption] option 선택 액션 콜백
218
- * @property {SelectCallbackParams} [onSelectChange] 선택값 변경 콜백
230
+ * @property {SelectDropdownOption<OptionData, DataOptionality>[]} [items] dropdown item 리스트(권장: items[].selected 초기값)
231
+ * @property {SelectCallbackParams<OptionData, DataOptionality>} [onSelectOption] option 선택 액션 콜백
232
+ * @property {SelectCallbackParams<OptionData, DataOptionality>} [onSelectChange] 선택값 변경 콜백
219
233
  * @property {SelectDropdownExtension} [dropdown] dropdown 확장 옵션
234
+ * @example
235
+ * type Config = SelectDropdownConfigProps<{ metaKey: number }, "required">;
236
+ * // Config.items의 option은 data를 반드시 포함해야 한다.
220
237
  */
221
- export interface SelectDropdownConfigProps<OptionData = unknown> {
238
+ export interface SelectDropdownConfigProps<
239
+ OptionData = unknown,
240
+ DataOptionality extends SelectOptionDataOptionality = "optional",
241
+ > {
222
242
  /**
223
243
  * dropdown item 리스트
224
244
  */
225
- items: SelectDropdownOption<OptionData>[];
245
+ items: SelectDropdownOption<OptionData, DataOptionality>[];
226
246
  /**
227
247
  * option 선택 액션 콜백
228
248
  */
229
- onSelectOption?: SelectCallbackParams<OptionData>;
249
+ onSelectOption?: SelectCallbackParams<OptionData, DataOptionality>;
230
250
  /**
231
251
  * 선택값 변경 콜백
232
252
  */
233
- onSelectChange?: SelectCallbackParams<OptionData>;
253
+ onSelectChange?: SelectCallbackParams<OptionData, DataOptionality>;
234
254
  /**
235
255
  * dropdown 확장 옵션
236
256
  */
@@ -316,9 +336,9 @@ export type SelectProps = SelectStyleOptions &
316
336
  * @property {boolean} [readOnly] readOnly 여부
317
337
  * @property {SelectTriggerButtonType} [buttonType] button type
318
338
  * @property {FormFieldWidth} [width] width preset 옵션
319
- * @property {SelectDropdownOption[]} [items] dropdown item 리스트
320
- * @property {SelectCallbackParams} [onSelectOption] option 선택 액션 콜백
321
- * @property {SelectCallbackParams} [onSelectChange] 선택값 변경 콜백
339
+ * @property {SelectDropdownOption<OptionData>[]} [items] dropdown item 리스트
340
+ * @property {SelectCallbackParams<OptionData>} [onSelectOption] option 선택 액션 콜백
341
+ * @property {SelectCallbackParams<OptionData>} [onSelectChange] 선택값 변경 콜백
322
342
  * @property {SelectDropdownExtension} [dropdown] dropdown 확장 옵션
323
343
  * @property {boolean} [open] dropdown open 상태
324
344
  * @property {boolean} [defaultOpen] uncontrolled 초기 open 상태
@@ -328,6 +348,10 @@ export type SelectProps = SelectStyleOptions &
328
348
  * @property {SelectCustomInputProps} [inputProps] 직접 입력 input 구성
329
349
  * @property {UseFormRegisterReturn} [register] source field register
330
350
  * @property {UseFormRegisterReturn} [customRegister] custom field register
351
+ * @example
352
+ * type DefaultProps = SelectDefaultComponentProps<{ metaKey: number }>;
353
+ * type RequiredChange = SelectCallbackParams<{ metaKey: number }, "required">;
354
+ * // optionality 제어는 콜백/옵션 타입에서 필요할 때만 명시적으로 사용한다.
331
355
  */
332
356
  export type SelectDefaultComponentProps<OptionData = unknown> =
333
357
  SelectTriggerDefaultProps &
@@ -367,9 +391,9 @@ export interface SelectMultipleAllOptionProps {
367
391
  * @property {boolean} [disabled] disabled 여부
368
392
  * @property {boolean} [readOnly] readOnly 여부
369
393
  * @property {FormFieldWidth} [width] width preset 옵션
370
- * @property {SelectDropdownOption[]} [items] dropdown item 리스트
371
- * @property {SelectCallbackParams} [onSelectOption] option 선택 액션 콜백
372
- * @property {SelectCallbackParams} [onSelectChange] 선택값 변경 콜백
394
+ * @property {SelectDropdownOption<OptionData>[]} [items] dropdown item 리스트
395
+ * @property {SelectCallbackParams<OptionData>} [onSelectOption] option 선택 액션 콜백
396
+ * @property {SelectCallbackParams<OptionData>} [onSelectChange] 선택값 변경 콜백
373
397
  * @property {SelectDropdownExtension} [dropdown] dropdown 확장 옵션
374
398
  * @property {boolean} [open] dropdown open 상태
375
399
  * @property {boolean} [defaultOpen] uncontrolled 초기 open 상태
@@ -377,6 +401,10 @@ export interface SelectMultipleAllOptionProps {
377
401
  * @property {HTMLAttributes<HTMLElement>} [triggerProps] trigger native 속성/이벤트
378
402
  * @property {boolean} [showSelectAllOption] dropdown 첫 행에 "전체" 옵션 노출 여부
379
403
  * @property {ReactNode} [selectAllLabel] "전체" 옵션 라벨 커스터마이징
404
+ * @example
405
+ * type MultipleProps = SelectMultipleComponentProps<{ metaKey: number }>;
406
+ * type RequiredChange = SelectCallbackParams<{ metaKey: number }, "required">;
407
+ * // optionality 제어는 콜백/옵션 타입에서 필요할 때만 명시적으로 사용한다.
380
408
  */
381
409
  export type SelectMultipleComponentProps<OptionData = unknown> =
382
410
  SelectTriggerMultipleProps &