@uniai-fe/uds-primitives 0.0.18 → 0.0.20

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.
Files changed (49) hide show
  1. package/README.md +9 -5
  2. package/dist/styles.css +55 -1017
  3. package/package.json +1 -6
  4. package/src/components/alternate/styles/index.scss +0 -2
  5. package/src/components/badge/styles/index.scss +1 -3
  6. package/src/components/button/styles/button.scss +0 -1
  7. package/src/components/button/styles/round-button.scss +0 -2
  8. package/src/components/button/styles/text-button.scss +0 -2
  9. package/src/components/calendar/styles/index.scss +0 -2
  10. package/src/components/checkbox/styles/index.scss +1 -3
  11. package/src/components/chip/styles/index.scss +1 -3
  12. package/src/components/drawer/styles/index.scss +1 -3
  13. package/src/components/dropdown/styles/index.scss +0 -2
  14. package/src/components/input/styles/index.scss +2 -3
  15. package/src/components/label/styles/index.scss +0 -2
  16. package/src/components/navigation/styles/index.scss +1 -3
  17. package/src/components/pagination/styles/index.scss +0 -2
  18. package/src/components/radio/styles/index.scss +1 -3
  19. package/src/components/scrollbar/styles/index.scss +0 -2
  20. package/src/components/segmented-control/markup/Container.tsx +255 -0
  21. package/src/components/segmented-control/markup/Indicator.tsx +31 -0
  22. package/src/components/segmented-control/markup/List.tsx +125 -0
  23. package/src/components/segmented-control/markup/index.ts +1 -1
  24. package/src/components/segmented-control/styles/index.scss +51 -50
  25. package/src/components/segmented-control/types/index.ts +48 -10
  26. package/src/components/select/styles/index.scss +0 -2
  27. package/src/components/spinner/styles/index.scss +0 -2
  28. package/src/components/tab/styles/index.scss +0 -2
  29. package/src/components/table/styles/index.scss +0 -2
  30. package/src/index.scss +2 -4
  31. package/src/index.tsx +1 -2
  32. package/src/components/dialog/hooks/index.ts +0 -4
  33. package/src/components/dialog/img/.gitkeep +0 -0
  34. package/src/components/dialog/index.scss +0 -1
  35. package/src/components/dialog/index.tsx +0 -6
  36. package/src/components/dialog/markup/ConfirmDialog.tsx +0 -339
  37. package/src/components/dialog/markup/NoticeDialog.tsx +0 -209
  38. package/src/components/dialog/markup/index.tsx +0 -4
  39. package/src/components/dialog/styles/base.scss +0 -153
  40. package/src/components/dialog/styles/confirm.scss +0 -58
  41. package/src/components/dialog/styles/index.scss +0 -3
  42. package/src/components/dialog/styles/notice.scss +0 -65
  43. package/src/components/dialog/types/index.ts +0 -113
  44. package/src/components/dialog/utils/index.ts +0 -4
  45. package/src/components/segmented-control/markup/SegmentedControl.tsx +0 -129
  46. package/src/theme/ThemeProvider.tsx +0 -25
  47. package/src/theme/config.ts +0 -29
  48. package/src/theme/index.ts +0 -3
  49. package/src/theme/overrides.scss +0 -215
@@ -1,129 +0,0 @@
1
- import { SegmentedControl as RadixSegmentedControl } from "@radix-ui/themes";
2
- import clsx from "clsx";
3
- import {
4
- forwardRef,
5
- useMemo,
6
- useState,
7
- type KeyboardEvent,
8
- type MouseEvent,
9
- type PointerEvent,
10
- } from "react";
11
- import type { SegmentedControlProps, SegmentedControlValue } from "../types";
12
-
13
- const toNullableValue = (value?: SegmentedControlValue) =>
14
- value === undefined || value === "" ? undefined : value;
15
-
16
- /**
17
- * SegmentedControl — Radix SegmentedControl wrapper with keepSelected toggle.
18
- * @component
19
- * @param {SegmentedControlProps} props
20
- * @param {SegmentedControlOption[]} props.options 렌더링할 옵션 배열.
21
- * @param {string} props.ariaLabel 스크린리더용 라벨(필수).
22
- * @param {boolean} [props.keepSelected=true] 선택된 항목을 다시 클릭했을 때 해제하지 않고 유지할지 여부.
23
- * @param {SegmentedControlValue} [props.value] 제어형 value.
24
- * @param {SegmentedControlValue} [props.defaultValue] 비제어 초기 value.
25
- * @param {(value: SegmentedControlValue) => void} [props.onValueChange] 값 변경 콜백.
26
- * @param {string} [props.className] root className.
27
- */
28
- const SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
29
- (
30
- {
31
- options,
32
- ariaLabel,
33
- keepSelected = true,
34
- className,
35
- onValueChange,
36
- value: valueProp,
37
- defaultValue,
38
- ...restProps
39
- },
40
- forwardedRef,
41
- ) => {
42
- const isControlled = valueProp !== undefined;
43
- const [uncontrolledValue, setUncontrolledValue] = useState<
44
- SegmentedControlValue | undefined
45
- >(toNullableValue(defaultValue));
46
- const selectedValue = toNullableValue(
47
- isControlled ? valueProp : uncontrolledValue,
48
- );
49
-
50
- const emitChange = (nextValue: SegmentedControlValue | undefined) => {
51
- if (!isControlled) {
52
- setUncontrolledValue(nextValue);
53
- }
54
- onValueChange?.(nextValue ?? "");
55
- };
56
-
57
- const handleRootValueChange = (nextValue: string) => {
58
- emitChange(nextValue);
59
- };
60
-
61
- const resolvedValue = useMemo(
62
- () => selectedValue ?? undefined,
63
- [selectedValue],
64
- );
65
-
66
- return (
67
- <RadixSegmentedControl.Root
68
- {...restProps}
69
- ref={forwardedRef}
70
- aria-label={ariaLabel}
71
- className={clsx("segmented-control", className)}
72
- value={resolvedValue}
73
- onValueChange={handleRootValueChange}
74
- data-keep-selected={keepSelected ? "true" : undefined}
75
- >
76
- {options.map(option => {
77
- const isDisabled = Boolean(option.disabled);
78
- const isSelected = selectedValue === option.value;
79
-
80
- const preventDisabledInteraction = (
81
- event:
82
- | MouseEvent<HTMLButtonElement>
83
- | PointerEvent<HTMLButtonElement>
84
- | KeyboardEvent<HTMLButtonElement>,
85
- ) => {
86
- if (!isDisabled) {
87
- return;
88
- }
89
- event.preventDefault();
90
- event.stopPropagation();
91
- };
92
-
93
- const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
94
- preventDisabledInteraction(event);
95
- if (isDisabled) {
96
- return;
97
- }
98
- if (!keepSelected && isSelected) {
99
- event.preventDefault();
100
- emitChange(undefined);
101
- }
102
- };
103
-
104
- return (
105
- <RadixSegmentedControl.Item
106
- key={option.value}
107
- value={option.value}
108
- className="segmented-control-item"
109
- aria-disabled={isDisabled || undefined}
110
- data-disabled={isDisabled ? "true" : undefined}
111
- tabIndex={isDisabled ? -1 : undefined}
112
- onPointerDown={preventDisabledInteraction}
113
- onKeyDown={preventDisabledInteraction}
114
- onClick={handleClick}
115
- >
116
- <span className="segmented-control-item-label">
117
- {option.label}
118
- </span>
119
- </RadixSegmentedControl.Item>
120
- );
121
- })}
122
- </RadixSegmentedControl.Root>
123
- );
124
- },
125
- );
126
-
127
- SegmentedControl.displayName = "SegmentedControl";
128
-
129
- export { SegmentedControl };
@@ -1,25 +0,0 @@
1
- import { Theme } from "@radix-ui/themes";
2
- import "@radix-ui/themes/styles.css";
3
- import type { PropsWithChildren } from "react";
4
- import { defaultThemeOptions, type ThemeProviderProps } from "./config";
5
-
6
- // foundation CSS와 overrides.scss는 @uniai-fe/uds-primitives/styles에서 전역 import한다.
7
-
8
- /**
9
- * Radix Theme와 foundation 토큰을 한 번에 초기화하는 Provider.
10
- * Storybook 데코레이터 및 애플리케이션 루트에서 활용한다.
11
- */
12
- function ThemeProvider({
13
- children,
14
- theme = defaultThemeOptions,
15
- className,
16
- }: PropsWithChildren<ThemeProviderProps>) {
17
- const composedClass = className ?? "theme-root";
18
- return (
19
- <Theme {...theme} className={composedClass}>
20
- {children}
21
- </Theme>
22
- );
23
- }
24
-
25
- export { ThemeProvider };
@@ -1,29 +0,0 @@
1
- import type { ThemeProps } from "@radix-ui/themes";
2
-
3
- /**
4
- * Radix Theme 설정 옵션. foundation 토큰과 매핑할 예정이므로
5
- * appearance/accentColor 등은 추후 토큰 담당자와 확정 후 업데이트한다.
6
- */
7
- export type ThemeOptions = ThemeProps;
8
-
9
- /**
10
- * foundation 토큰 → Radix Theme 옵션 초기 매핑.
11
- * 현재는 Radix Theme 기본 키를 사용하고, CSS override(`overrides.scss`)에서
12
- * 실제 색상/폰트/간격 값을 foundation 토큰으로 덮어쓴다.
13
- */
14
- export const defaultThemeOptions: ThemeOptions = {
15
- appearance: "light",
16
- accentColor: "blue",
17
- grayColor: "gray",
18
- scaling: "95%",
19
- radius: "medium",
20
- };
21
-
22
- /**
23
- * Theme Provider에 전달할 props 타입.
24
- * `children`은 React node이며, `theme`를 전달하지 않으면 `defaultThemeOptions`가 사용된다.
25
- */
26
- export type ThemeProviderProps = {
27
- theme?: ThemeOptions;
28
- className?: string;
29
- };
@@ -1,3 +0,0 @@
1
- export { ThemeProvider } from "./ThemeProvider";
2
- export type { ThemeOptions, ThemeProviderProps } from "./config";
3
- export { defaultThemeOptions } from "./config";
@@ -1,215 +0,0 @@
1
- @use "@uniai-fe/uds-foundation/css";
2
-
3
- /**
4
- * Radix Theme가 사용하는 CSS 변수에 foundation 토큰을 연결하기 위한 placeholder.
5
- * - 추후 토큰 매핑이 확정되면, 실제 색상/타이포/간격 값을 아래에 정의한다.
6
- */
7
- /* ThemeProvider 기본 className(theme-root)와 Radix Theme 루트(.radix-themes)에 scope 지정 */
8
- :where(.radix-themes, .theme-root, :root) {
9
- /* Foundation 기본 폰트로 통일 */
10
- --default-font-family: var(--font-body-medium-family, "Pretendard");
11
-
12
- /* 서피스/라벨/피드백 계층을 foundation 시멘틱 토큰으로 변환 */
13
- --color-background: var(--color-bg-surface-static-white);
14
- --color-panel-solid: var(--color-bg-surface-static-white);
15
- --color-panel-translucent: var(--color-bg-surface-neutral);
16
- --color-surface: var(--color-bg-surface-standard);
17
- --color-overlay: var(--color-border-standard-heavy);
18
- --color-interaction-static: var(--color-interaction-static);
19
- --color-interaction-disabled: var(--color-interaction-disabled);
20
- --color-border: var(--color-border-standard-cool-gray);
21
- --color-border-strong: var(--color-border-standard-strong);
22
- --color-border-heavy: var(--color-border-standard-heavy);
23
-
24
- /* Primary(blue) 팔레트를 foundation blue 단계로 재정의 */
25
- --blue-1: var(--color-blue-99);
26
- --blue-2: var(--color-blue-95);
27
- --blue-3: var(--color-blue-90);
28
- --blue-4: var(--color-blue-80);
29
- --blue-5: var(--color-blue-70);
30
- --blue-6: var(--color-blue-60);
31
- --blue-7: var(--color-blue-55);
32
- --blue-8: var(--color-blue-50);
33
- --blue-9: var(--color-blue-45);
34
- --blue-10: var(--color-blue-40);
35
- --blue-11: var(--color-blue-30);
36
- --blue-12: var(--color-blue-20);
37
- --blue-contrast: var(--color-common-100);
38
- --blue-surface: var(--color-bg-surface-static-blue);
39
- --blue-indicator: var(--color-primary-default);
40
- --blue-track: var(--color-secondary-strong);
41
-
42
- /* Secondary(sky) 팔레트 → foundation secondary 토큰 */
43
- --sky-1: var(--color-blue-99);
44
- --sky-2: var(--color-blue-95);
45
- --sky-3: var(--color-blue-90);
46
- --sky-4: var(--color-blue-80);
47
- --sky-5: var(--color-blue-70);
48
- --sky-6: var(--color-blue-60);
49
- --sky-7: var(--color-blue-55);
50
- --sky-8: var(--color-blue-50);
51
- --sky-9: var(--color-secondary-strong);
52
- --sky-10: var(--color-secondary-heavy);
53
- --sky-11: var(--color-secondary-default);
54
- --sky-12: var(--color-blue-45);
55
- --sky-contrast: var(--color-primary-heavy);
56
- --sky-surface: var(--color-bg-surface-static-blue);
57
- --sky-indicator: var(--color-secondary-strong);
58
- --sky-track: var(--color-secondary-heavy);
59
-
60
- /* Tertiary(gray) 팔레트 → cool gray 단계 */
61
- --gray-1: var(--color-cool-gray-99);
62
- --gray-2: var(--color-cool-gray-95);
63
- --gray-3: var(--color-cool-gray-90);
64
- --gray-4: var(--color-cool-gray-85);
65
- --gray-5: var(--color-cool-gray-80);
66
- --gray-6: var(--color-cool-gray-75);
67
- --gray-7: var(--color-cool-gray-70);
68
- --gray-8: var(--color-cool-gray-65);
69
- --gray-9: var(--color-cool-gray-60);
70
- --gray-10: var(--color-cool-gray-55);
71
- --gray-11: var(--color-cool-gray-45);
72
- --gray-12: var(--color-cool-gray-20);
73
- --gray-contrast: var(--color-label-strong);
74
- --gray-surface: var(--color-bg-surface-standard);
75
- --gray-indicator: var(--color-label-neutral);
76
- --gray-track: var(--color-label-assistive);
77
-
78
- /* 공간 단위(spacing)는 foundation gap/padding 토큰으로 재정의 */
79
- --space-1: var(--spacing-gap-1);
80
- --space-2: var(--spacing-gap-2);
81
- --space-3: var(--spacing-gap-3);
82
- --space-4: var(--spacing-gap-4);
83
- --space-5: var(--spacing-gap-8);
84
- --space-6: var(--spacing-gap-10);
85
- --space-7: var(--spacing-gap-11);
86
- --space-8: var(--spacing-gap-12);
87
- --space-9: var(--spacing-gap-14);
88
-
89
- /* 글꼴 스케일을 foundation 타이포 토큰으로 매핑 */
90
- --font-size-1: var(--font-caption-large-size);
91
- --font-size-2: var(--font-label-medium-size);
92
- --font-size-3: var(--font-label-large-size);
93
- --font-size-4: var(--font-heading-xsmall-size);
94
- --font-size-5: var(--font-heading-small-size);
95
- --font-size-6: var(--font-heading-medium-size);
96
- --font-size-7: var(--font-heading-large-size);
97
- --font-size-8: var(--font-heading-xlarge-size);
98
- --font-size-9: var(--font-display-large-size);
99
-
100
- --line-height-1: var(--font-caption-large-line-height);
101
- --line-height-2: var(--font-label-medium-line-height);
102
- --line-height-3: var(--font-label-large-line-height);
103
- --line-height-4: var(--font-heading-xsmall-line-height);
104
- --line-height-5: var(--font-heading-small-line-height);
105
- --line-height-6: var(--font-heading-medium-line-height);
106
- --line-height-7: var(--font-heading-large-line-height);
107
- --line-height-8: var(--font-heading-xlarge-line-height);
108
- --line-height-9: var(--font-display-large-line-height);
109
-
110
- --letter-spacing-1: var(--font-caption-large-letter-spacing);
111
- --letter-spacing-2: var(--font-label-medium-letter-spacing);
112
- --letter-spacing-3: var(--font-label-large-letter-spacing);
113
- --letter-spacing-4: var(--font-heading-xsmall-letter-spacing);
114
- --letter-spacing-5: var(--font-heading-small-letter-spacing);
115
- --letter-spacing-6: var(--font-heading-medium-letter-spacing);
116
- --letter-spacing-7: var(--font-heading-large-letter-spacing);
117
- --letter-spacing-8: var(--font-heading-xlarge-letter-spacing);
118
- --letter-spacing-9: var(--font-display-large-letter-spacing);
119
-
120
- --font-weight-light: var(--font-label-small-weight);
121
- --font-weight-regular: var(--font-body-small-weight);
122
- --font-weight-medium: var(--font-body-medium-weight);
123
- --font-weight-bold: var(--font-display-large-weight);
124
-
125
- --default-font-family: var(--font-body-medium-family, "Pretendard");
126
- --default-font-size: var(--font-body-medium-size);
127
- --default-font-style: normal;
128
- --default-font-weight: var(--font-body-medium-weight);
129
- --default-line-height: var(--font-body-medium-line-height);
130
- --default-letter-spacing: var(--font-body-medium-letter-spacing);
131
- --default-leading-trim-start: 0.42em;
132
- --default-leading-trim-end: 0.36em;
133
-
134
- --heading-font-family: var(--font-body-medium-family, "Pretendard");
135
- --heading-font-size-adjust: 1;
136
- --heading-font-style: normal;
137
- --heading-leading-trim-start: var(--default-leading-trim-start);
138
- --heading-leading-trim-end: var(--default-leading-trim-end);
139
- --heading-letter-spacing: var(--font-heading-small-letter-spacing);
140
- --heading-line-height-1: var(--font-heading-xxsmall-line-height);
141
- --heading-line-height-2: var(--font-heading-xsmall-line-height);
142
- --heading-line-height-3: var(--font-heading-small-line-height);
143
- --heading-line-height-4: var(--font-heading-medium-line-height);
144
- --heading-line-height-5: var(--font-heading-large-line-height);
145
- --heading-line-height-6: var(--font-heading-xlarge-line-height);
146
- --heading-line-height-7: var(--font-display-small-line-height, 1.4em);
147
- --heading-line-height-8: var(--font-display-medium-line-height);
148
- --heading-line-height-9: var(--font-display-large-line-height);
149
-
150
- --code-font-family:
151
- "Menlo", "Consolas", "Bitstream Vera Sans Mono", monospace;
152
- --code-font-style: normal;
153
- --code-letter-spacing: -0.007em;
154
- --strong-font-family: var(--font-body-medium-family, "Pretendard");
155
- --strong-font-weight: var(--font-display-medium-weight, 700);
156
- --em-font-family: "Times New Roman", "Times", serif;
157
- --quote-font-family: "Times New Roman", "Times", serif;
158
- --tab-active-letter-spacing: var(--font-label-medium-letter-spacing);
159
- --tab-inactive-letter-spacing: var(--font-label-medium-letter-spacing);
160
- --tab-active-word-spacing: 0em;
161
- --tab-inactive-word-spacing: 0em;
162
-
163
- /* 입력/텍스트 요소에서 커서 컬러는 본문 텍스트와 동일하게 유지한다. */
164
- input,
165
- textarea {
166
- caret-color: var(--color-label-strong);
167
- }
168
-
169
- /* 커서/컨테이너 기본값 */
170
- --cursor-button: default;
171
- --cursor-checkbox: default;
172
- --cursor-disabled: not-allowed;
173
- --cursor-link: pointer;
174
- --cursor-menu-item: default;
175
- --cursor-radio: default;
176
- --cursor-slider-thumb: default;
177
- --cursor-slider-thumb-active: default;
178
- --cursor-switch: default;
179
- --container-1: 448px;
180
- --container-2: 688px;
181
- --container-3: 880px;
182
- --container-4: 1136px;
183
- --scrollarea-scrollbar-horizontal-margin-top: var(--space-1);
184
- --scrollarea-scrollbar-horizontal-margin-bottom: var(--space-1);
185
- --scrollarea-scrollbar-horizontal-margin-left: var(--space-1);
186
- --scrollarea-scrollbar-horizontal-margin-right: var(--space-1);
187
- --scrollarea-scrollbar-vertical-margin-top: var(--space-1);
188
- --scrollarea-scrollbar-vertical-margin-bottom: var(--space-1);
189
- --scrollarea-scrollbar-vertical-margin-left: var(--space-1);
190
- --scrollarea-scrollbar-vertical-margin-right: var(--space-1);
191
- --segmented-control-transition-duration: 100ms;
192
- --spinner-animation-duration: 800ms;
193
- --spinner-opacity: 0.65;
194
- overflow-wrap: break-word;
195
- font-family: var(--default-font-family);
196
- font-size: var(--default-font-size);
197
- font-weight: var(--default-font-weight);
198
- font-style: var(--default-font-style);
199
- line-height: var(--default-line-height);
200
- letter-spacing: var(--default-letter-spacing);
201
- -webkit-text-size-adjust: none;
202
- text-size-adjust: none;
203
- -webkit-font-smoothing: antialiased;
204
- -moz-osx-font-smoothing: grayscale;
205
- color: var(--gray-12);
206
- }
207
-
208
- /* Radix Themes reset(`.rt-reset`)이 foundation reset보다 우선하지 않도록 기본 박스 모델 재정의 */
209
- :where(.radix-themes, .theme-root)
210
- :is(.rt-reset, .rt-reset::before, .rt-reset::after) {
211
- box-sizing: border-box;
212
- margin: 0;
213
- padding: 0;
214
- border: 0;
215
- }