@uniai-fe/uds-primitives 0.3.40 → 0.3.42
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/styles.css +4 -7
- package/package.json +1 -1
- package/src/components/select/markup/foundation/Base.tsx +15 -12
- package/src/components/select/markup/foundation/Selected.tsx +71 -58
- package/src/components/select/styles/select.scss +3 -3
- package/src/components/select/styles/variables.scss +4 -4
- package/src/components/select/types/trigger.ts +4 -0
package/dist/styles.css
CHANGED
|
@@ -586,10 +586,10 @@
|
|
|
586
586
|
--select-text-large-line-height: var(--input-text-large-line-height);
|
|
587
587
|
--select-text-large-letter-spacing: var(--input-text-large-letter-spacing);
|
|
588
588
|
--select-text-large-weight: var(--input-text-large-weight);
|
|
589
|
-
--select-icon-size-xsmall:
|
|
590
|
-
--select-icon-size-small:
|
|
591
|
-
--select-icon-size-medium:
|
|
592
|
-
--select-icon-size-large:
|
|
589
|
+
--select-icon-size-xsmall: 14px;
|
|
590
|
+
--select-icon-size-small: 16px;
|
|
591
|
+
--select-icon-size-medium: 20px;
|
|
592
|
+
--select-icon-size-large: 20px;
|
|
593
593
|
--select-primary-color-placeholder: var(--input-placeholder-color);
|
|
594
594
|
/* 변경: placeholder disabled/readonly 토큰을 분리해 상태별 제어 지점을 고정한다. */
|
|
595
595
|
--select-primary-color-placeholder-disabled: var(--color-label-disabled);
|
|
@@ -3963,9 +3963,6 @@ figure.chip {
|
|
|
3963
3963
|
height: var(--select-secondary-underline-width-default);
|
|
3964
3964
|
}
|
|
3965
3965
|
.select-button:where([data-priority=table]):where([data-readonly=true]) {
|
|
3966
|
-
border-color: var(--select-table-border-readonly-color);
|
|
3967
|
-
background-color: var(--select-table-surface-readonly-color);
|
|
3968
|
-
cursor: not-allowed;
|
|
3969
3966
|
--select-icon-fill: var(--select-table-icon-color-disabled);
|
|
3970
3967
|
}
|
|
3971
3968
|
.select-button:where(:not([data-priority=secondary])):where([data-state=disabled]), .select-button:where(:not([data-priority=secondary])):disabled {
|
package/package.json
CHANGED
|
@@ -43,6 +43,7 @@ const SelectTriggerBase = forwardRef<HTMLElement, SelectTriggerBaseProps>(
|
|
|
43
43
|
buttonType = "button",
|
|
44
44
|
className,
|
|
45
45
|
children,
|
|
46
|
+
icon,
|
|
46
47
|
...rest
|
|
47
48
|
},
|
|
48
49
|
ref,
|
|
@@ -70,7 +71,7 @@ const SelectTriggerBase = forwardRef<HTMLElement, SelectTriggerBaseProps>(
|
|
|
70
71
|
return 16;
|
|
71
72
|
}
|
|
72
73
|
};
|
|
73
|
-
|
|
74
|
+
|
|
74
75
|
const {
|
|
75
76
|
["aria-haspopup"]: ariaHasPopup,
|
|
76
77
|
["aria-expanded"]: ariaExpanded,
|
|
@@ -83,7 +84,7 @@ const SelectTriggerBase = forwardRef<HTMLElement, SelectTriggerBaseProps>(
|
|
|
83
84
|
"data-size": resolvedSize,
|
|
84
85
|
...restProps,
|
|
85
86
|
// 변경: Radix Dropdown.Trigger가 주입하는 data-state(open|closed)를 최종 단계에서 덮어써 visual state를 고정한다.
|
|
86
|
-
"data-state":
|
|
87
|
+
"data-state": disabled ? "disabled" : readOnly ? "readonly" : state,
|
|
87
88
|
// 변경: readOnly도 disabled와 동일한 시각 상태를 사용하고 텍스트 컬러만 별도 스타일로 분리한다.
|
|
88
89
|
"data-readonly": readOnly ? "true" : undefined,
|
|
89
90
|
"data-open": open || undefined,
|
|
@@ -109,16 +110,18 @@ const SelectTriggerBase = forwardRef<HTMLElement, SelectTriggerBaseProps>(
|
|
|
109
110
|
return (
|
|
110
111
|
<Slot.Base ref={ref} as={as} {...sharedProps} {...elementSpecificProps}>
|
|
111
112
|
{children}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
113
|
+
{icon !== false && (
|
|
114
|
+
<figure
|
|
115
|
+
className="select-icon"
|
|
116
|
+
data-size={resolvedSize}
|
|
117
|
+
aria-hidden="true"
|
|
118
|
+
>
|
|
119
|
+
<Icon
|
|
120
|
+
viewBox={`0 0 ${iconSize()} ${iconSize()}`}
|
|
121
|
+
preserveAspectRatio="xMinYMin meet"
|
|
122
|
+
/>
|
|
123
|
+
</figure>
|
|
124
|
+
)}
|
|
122
125
|
</Slot.Base>
|
|
123
126
|
);
|
|
124
127
|
},
|
|
@@ -54,6 +54,8 @@ const SelectTriggerSelected = ({
|
|
|
54
54
|
// 2) placeholder/label은 text input에 들어갈 수 있는 문자열로 정규화한다.
|
|
55
55
|
const resolvedPlaceholder = toInputText(placeholder);
|
|
56
56
|
const resolvedLabelText = valueText || toInputText(label);
|
|
57
|
+
const isLabelTextLike =
|
|
58
|
+
typeof label === "string" || typeof label === "number";
|
|
57
59
|
|
|
58
60
|
// 3) custom mode 활성 시에만 label input focus를 부여한다.
|
|
59
61
|
useEffect(() => {
|
|
@@ -66,64 +68,75 @@ const SelectTriggerSelected = ({
|
|
|
66
68
|
|
|
67
69
|
return (
|
|
68
70
|
<div className="select-value">
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
inputProps
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
71
|
+
{readOnly && !isLabelTextLike ? (
|
|
72
|
+
// 변경 설명: readonly + ReactNode label일 때는 문자열 변환 없이 label 노드를 직접 렌더링한다.
|
|
73
|
+
<div
|
|
74
|
+
className={clsx("select-input-label", inputProps?.className, {
|
|
75
|
+
"select-input-label-placeholder": isPlaceholder,
|
|
76
|
+
})}
|
|
77
|
+
>
|
|
78
|
+
{label}
|
|
79
|
+
</div>
|
|
80
|
+
) : (
|
|
81
|
+
<input
|
|
82
|
+
ref={labelInputRef}
|
|
83
|
+
type="text"
|
|
84
|
+
// 4) 외부 inputProps는 placeholder/value/readOnly보다 먼저 병합하고,
|
|
85
|
+
// 내부 계약값을 마지막에 고정해 동작 우선순위를 명확히 한다.
|
|
86
|
+
{...inputProps}
|
|
87
|
+
className={clsx("select-input-label", inputProps?.className, {
|
|
88
|
+
"select-input-label-placeholder": isPlaceholder,
|
|
89
|
+
})}
|
|
90
|
+
placeholder={resolvedPlaceholder}
|
|
91
|
+
value={resolvedLabelText}
|
|
92
|
+
readOnly={readOnly}
|
|
93
|
+
// 5) customRegister는 name/ref/onBlur/onChange 계약을 label input에 연결한다.
|
|
94
|
+
{...customRegister}
|
|
95
|
+
onPointerDownCapture={event => {
|
|
96
|
+
inputProps?.onPointerDownCapture?.(event);
|
|
97
|
+
if (!readOnly) {
|
|
98
|
+
// 변경: 편집 가능 상태에서는 trigger 토글 이벤트 전파를 차단한다.
|
|
99
|
+
event.stopPropagation();
|
|
100
|
+
}
|
|
101
|
+
}}
|
|
102
|
+
onPointerDown={event => {
|
|
103
|
+
inputProps?.onPointerDown?.(event);
|
|
104
|
+
if (!readOnly) {
|
|
105
|
+
event.stopPropagation();
|
|
106
|
+
}
|
|
107
|
+
}}
|
|
108
|
+
onMouseDown={event => {
|
|
109
|
+
inputProps?.onMouseDown?.(event);
|
|
110
|
+
if (!readOnly) {
|
|
111
|
+
event.stopPropagation();
|
|
112
|
+
}
|
|
113
|
+
}}
|
|
114
|
+
onClickCapture={event => {
|
|
115
|
+
inputProps?.onClickCapture?.(event);
|
|
116
|
+
if (!readOnly) {
|
|
117
|
+
event.stopPropagation();
|
|
118
|
+
}
|
|
119
|
+
}}
|
|
120
|
+
onClick={event => {
|
|
121
|
+
inputProps?.onClick?.(event);
|
|
122
|
+
if (!readOnly) {
|
|
123
|
+
event.stopPropagation();
|
|
124
|
+
}
|
|
125
|
+
}}
|
|
126
|
+
onKeyDown={event => {
|
|
127
|
+
inputProps?.onKeyDown?.(event);
|
|
128
|
+
if (!readOnly) {
|
|
129
|
+
event.stopPropagation();
|
|
130
|
+
}
|
|
131
|
+
}}
|
|
132
|
+
onChange={event => {
|
|
133
|
+
// 6) RHF(customRegister) → 외부 inputProps → 내부 state 콜백 순으로 변경을 전파한다.
|
|
134
|
+
customRegister?.onChange?.(event);
|
|
135
|
+
inputProps?.onChange?.(event);
|
|
136
|
+
onLabelChange?.(event.currentTarget.value);
|
|
137
|
+
}}
|
|
138
|
+
/>
|
|
139
|
+
)}
|
|
127
140
|
<input
|
|
128
141
|
type="hidden"
|
|
129
142
|
className="select-input-value"
|
|
@@ -192,9 +192,9 @@
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
&:where([data-priority="table"]):where([data-readonly="true"]) {
|
|
195
|
-
border-color: var(--select-table-border-readonly-color);
|
|
196
|
-
background-color: var(--select-table-surface-readonly-color);
|
|
197
|
-
cursor: not-allowed;
|
|
195
|
+
// border-color: var(--select-table-border-readonly-color);
|
|
196
|
+
// background-color: var(--select-table-surface-readonly-color);
|
|
197
|
+
// cursor: not-allowed;
|
|
198
198
|
--select-icon-fill: var(--select-table-icon-color-disabled);
|
|
199
199
|
}
|
|
200
200
|
|
|
@@ -90,10 +90,10 @@
|
|
|
90
90
|
--select-text-large-letter-spacing: var(--input-text-large-letter-spacing);
|
|
91
91
|
--select-text-large-weight: var(--input-text-large-weight);
|
|
92
92
|
|
|
93
|
-
--select-icon-size-xsmall:
|
|
94
|
-
--select-icon-size-small:
|
|
95
|
-
--select-icon-size-medium:
|
|
96
|
-
--select-icon-size-large:
|
|
93
|
+
--select-icon-size-xsmall: 14px;
|
|
94
|
+
--select-icon-size-small: 16px;
|
|
95
|
+
--select-icon-size-medium: 20px;
|
|
96
|
+
--select-icon-size-large: 20px;
|
|
97
97
|
|
|
98
98
|
--select-primary-color-placeholder: var(--input-placeholder-color);
|
|
99
99
|
/* 변경: placeholder disabled/readonly 토큰을 분리해 상태별 제어 지점을 고정한다. */
|