@uniai-fe/uds-primitives 0.3.51 → 0.3.52
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
|
@@ -162,10 +162,25 @@ export function SelectDefault<OptionData = unknown>({
|
|
|
162
162
|
[mergedOptions, uncontrolledSelectedValue],
|
|
163
163
|
);
|
|
164
164
|
|
|
165
|
-
// 9)
|
|
165
|
+
// 9) customOptions가 있는 경우 inputProps.value가 있고 option 매칭이 없으면 custom mode로 간주한다.
|
|
166
|
+
const forcedCustomLabelValue = toInputText(inputProps?.value as ReactNode);
|
|
167
|
+
const shouldForceCustomFromInput = Boolean(
|
|
168
|
+
customOptions && !selectedOption && forcedCustomLabelValue,
|
|
169
|
+
);
|
|
170
|
+
const resolvedSelectedOption = useMemo(
|
|
171
|
+
() =>
|
|
172
|
+
shouldForceCustomFromInput
|
|
173
|
+
? mergedOptions.find(option =>
|
|
174
|
+
isSameSelectedValue(option.value, SELECT_CUSTOM_OPTION_VALUE),
|
|
175
|
+
)
|
|
176
|
+
: selectedOption,
|
|
177
|
+
[mergedOptions, selectedOption, shouldForceCustomFromInput],
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
// 10) custom mode는 custom option selected 상태(또는 forced custom 상태)로 판단한다.
|
|
166
181
|
const isCustomInputActive = Boolean(
|
|
167
182
|
customOptions &&
|
|
168
|
-
toSelectedValueKey(
|
|
183
|
+
toSelectedValueKey(resolvedSelectedOption?.value) ===
|
|
169
184
|
toSelectedValueKey(SELECT_CUSTOM_OPTION_VALUE),
|
|
170
185
|
);
|
|
171
186
|
|
|
@@ -176,21 +191,22 @@ export function SelectDefault<OptionData = unknown>({
|
|
|
176
191
|
}
|
|
177
192
|
}, [isCustomInputActive]);
|
|
178
193
|
|
|
179
|
-
//
|
|
194
|
+
// 11) 외부 displayLabel이 있으면 우선 사용하고, 없으면 선택 option label을 사용한다.
|
|
180
195
|
const resolvedDisplayLabel =
|
|
181
|
-
displayLabel ??
|
|
196
|
+
displayLabel ??
|
|
197
|
+
(isCustomInputActive ? undefined : resolvedSelectedOption?.label);
|
|
182
198
|
|
|
183
|
-
//
|
|
199
|
+
// 12) open 제어형/비제어형 계약은 공용 hook으로 통합 처리한다.
|
|
184
200
|
const { open: dropdownOpen, setOpen } = useSelectDropdownOpenState({
|
|
185
201
|
open,
|
|
186
202
|
defaultOpen,
|
|
187
203
|
onOpen,
|
|
188
204
|
});
|
|
189
205
|
|
|
190
|
-
//
|
|
206
|
+
// 13) disabled/readOnly 상태에서는 open/option 선택 인터랙션을 모두 차단한다.
|
|
191
207
|
const isInteractionBlocked = disabled || readOnly;
|
|
192
208
|
|
|
193
|
-
//
|
|
209
|
+
// 14) open 상태 변경 처리: 차단 상태면 닫힘 고정, 아니면 nextOpen 반영.
|
|
194
210
|
const handleOpenChange = (nextOpen: boolean) => {
|
|
195
211
|
if (isInteractionBlocked) {
|
|
196
212
|
setOpen(false);
|
|
@@ -199,7 +215,7 @@ export function SelectDefault<OptionData = unknown>({
|
|
|
199
215
|
setOpen(nextOpen);
|
|
200
216
|
};
|
|
201
217
|
|
|
202
|
-
//
|
|
218
|
+
// 15) option 선택 처리: onSelectOption 호출 후, value가 변경될 때만 onSelectChange를 호출한다.
|
|
203
219
|
const handleOptionSelect = (
|
|
204
220
|
option: SelectDropdownOption<OptionData>,
|
|
205
221
|
event: Event,
|
|
@@ -208,7 +224,7 @@ export function SelectDefault<OptionData = unknown>({
|
|
|
208
224
|
return;
|
|
209
225
|
}
|
|
210
226
|
|
|
211
|
-
const previousOption =
|
|
227
|
+
const previousOption = resolvedSelectedOption;
|
|
212
228
|
const hasChanged = !isSameSelectedValue(
|
|
213
229
|
previousOption?.value,
|
|
214
230
|
option.value,
|
|
@@ -224,7 +240,7 @@ export function SelectDefault<OptionData = unknown>({
|
|
|
224
240
|
setOpen(false);
|
|
225
241
|
};
|
|
226
242
|
|
|
227
|
-
//
|
|
243
|
+
// 16) label input 값은 custom mode에서만 사용자 입력값/controlled inputProps.value를 사용한다.
|
|
228
244
|
const labelInputValue = isCustomInputActive
|
|
229
245
|
? typeof inputProps?.value === "string" ||
|
|
230
246
|
typeof inputProps?.value === "number"
|
|
@@ -232,7 +248,7 @@ export function SelectDefault<OptionData = unknown>({
|
|
|
232
248
|
: customLabelValue
|
|
233
249
|
: toInputText(resolvedDisplayLabel);
|
|
234
250
|
|
|
235
|
-
//
|
|
251
|
+
// 17) 렌더: Container → Dropdown.Root → Trigger → Menu.List 구조를 유지한다.
|
|
236
252
|
return (
|
|
237
253
|
<Container
|
|
238
254
|
className={clsx("select-trigger-container", className)}
|
|
@@ -284,7 +300,7 @@ export function SelectDefault<OptionData = unknown>({
|
|
|
284
300
|
valueFieldValue={
|
|
285
301
|
isCustomInputActive && !customRegister
|
|
286
302
|
? labelInputValue
|
|
287
|
-
: (
|
|
303
|
+
: (resolvedSelectedOption?.value ?? "")
|
|
288
304
|
}
|
|
289
305
|
// 변경: custom mode 진입 시 label input에 focus를 연결한다.
|
|
290
306
|
shouldFocusInput={isCustomInputActive}
|
|
@@ -310,7 +326,7 @@ export function SelectDefault<OptionData = unknown>({
|
|
|
310
326
|
right={option.right}
|
|
311
327
|
multiple={Boolean(option.multiple)}
|
|
312
328
|
isSelected={isSameSelectedValue(
|
|
313
|
-
|
|
329
|
+
resolvedSelectedOption?.value,
|
|
314
330
|
option.value,
|
|
315
331
|
)}
|
|
316
332
|
onSelect={event => {
|