@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 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: 1.4rem;
590
- --select-icon-size-small: 1.6rem;
591
- --select-icon-size-medium: 2rem;
592
- --select-icon-size-large: 2rem;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniai-fe/uds-primitives",
3
- "version": "0.3.40",
3
+ "version": "0.3.42",
4
4
  "description": "UNIAI Design System; Primitives Components Package",
5
5
  "type": "module",
6
6
  "private": false,
@@ -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
- const resolvedState = disabled || readOnly ? "disabled" : state;
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": resolvedState,
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
- <figure
113
- className="select-icon"
114
- data-size={resolvedSize}
115
- aria-hidden="true"
116
- >
117
- <Icon
118
- viewBox={`0 0 ${iconSize()} ${iconSize()}`}
119
- preserveAspectRatio="xMinYMin meet"
120
- />
121
- </figure>
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
- <input
70
- ref={labelInputRef}
71
- type="text"
72
- // 4) 외부 inputProps placeholder/value/readOnly보다 먼저 병합하고,
73
- // 내부 계약값을 마지막에 고정해 동작 우선순위를 명확히 한다.
74
- {...inputProps}
75
- className={clsx("select-input-label", inputProps?.className, {
76
- "select-input-label-placeholder": isPlaceholder,
77
- })}
78
- placeholder={resolvedPlaceholder}
79
- value={resolvedLabelText}
80
- readOnly={readOnly}
81
- // 5) customRegister는 name/ref/onBlur/onChange 계약을 label input에 연결한다.
82
- {...customRegister}
83
- onPointerDownCapture={event => {
84
- inputProps?.onPointerDownCapture?.(event);
85
- if (!readOnly) {
86
- // 변경: 편집 가능 상태에서는 trigger 토글 이벤트 전파를 차단한다.
87
- event.stopPropagation();
88
- }
89
- }}
90
- onPointerDown={event => {
91
- inputProps?.onPointerDown?.(event);
92
- if (!readOnly) {
93
- event.stopPropagation();
94
- }
95
- }}
96
- onMouseDown={event => {
97
- inputProps?.onMouseDown?.(event);
98
- if (!readOnly) {
99
- event.stopPropagation();
100
- }
101
- }}
102
- onClickCapture={event => {
103
- inputProps?.onClickCapture?.(event);
104
- if (!readOnly) {
105
- event.stopPropagation();
106
- }
107
- }}
108
- onClick={event => {
109
- inputProps?.onClick?.(event);
110
- if (!readOnly) {
111
- event.stopPropagation();
112
- }
113
- }}
114
- onKeyDown={event => {
115
- inputProps?.onKeyDown?.(event);
116
- if (!readOnly) {
117
- event.stopPropagation();
118
- }
119
- }}
120
- onChange={event => {
121
- // 6) RHF(customRegister) → 외부 inputProps → 내부 state 콜백 순으로 변경을 전파한다.
122
- customRegister?.onChange?.(event);
123
- inputProps?.onChange?.(event);
124
- onLabelChange?.(event.currentTarget.value);
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: 1.4rem;
94
- --select-icon-size-small: 1.6rem;
95
- --select-icon-size-medium: 2rem;
96
- --select-icon-size-large: 2rem;
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 토큰을 분리해 상태별 제어 지점을 고정한다. */
@@ -84,6 +84,10 @@ export interface SelectTriggerBaseProps extends HTMLAttributes<HTMLElement> {
84
84
  * 콘텐츠
85
85
  */
86
86
  children: ReactNode;
87
+ /**
88
+ * chevron 아이콘 비활성화
89
+ */
90
+ icon?: boolean;
87
91
  }
88
92
 
89
93
  /**