@xonic0506/sonic-ui 0.3.0 → 0.4.1
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/DESIGN.md +76 -12
- package/README.md +1 -1
- package/dist/components/dialog.d.ts +1 -1
- package/dist/components/dialog.js +2 -2
- package/dist/components/empty-state.d.ts +1 -1
- package/dist/components/empty-state.js +12 -10
- package/dist/components/error-page.d.ts +13 -0
- package/dist/components/error-page.js +45 -0
- package/dist/components/error-state.d.ts +1 -1
- package/dist/components/error-state.js +7 -5
- package/dist/components/file-upload.js +7 -1
- package/dist/components/illustration.d.ts +7 -0
- package/dist/components/illustration.js +11 -0
- package/dist/components/input.d.ts +1 -1
- package/dist/components/input.js +1 -1
- package/dist/components/state-layout.d.ts +4 -1
- package/dist/components/state-layout.js +14 -8
- package/dist/components/tabs.js +9 -6
- package/dist/illustrations/empty.webp +0 -0
- package/dist/illustrations/error-403.webp +0 -0
- package/dist/illustrations/error-404.webp +0 -0
- package/dist/illustrations/error-500.webp +0 -0
- package/dist/illustrations/error.webp +0 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +17 -16
- package/dist/styles.css +1 -1
- package/package.json +2 -2
package/DESIGN.md
CHANGED
|
@@ -142,6 +142,23 @@ import { Plus } from 'lucide-react';
|
|
|
142
142
|
<Button size="icon-md" variant="ghost" aria-label="더 보기"><Ellipsis /></Button>
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
+
### 3.7 일러스트 (캐릭터)
|
|
146
|
+
|
|
147
|
+
빈 상태, 불러오기 실패, 에러 페이지에는 Sonic 캐릭터 일러스트를 써요. Figma에서는 Foundations › 05 Illustration, `Source illustrations`에 `Illustration / <이름>` 컴포넌트로 있어요.
|
|
148
|
+
|
|
149
|
+
| 이름 | 표시 크기 | 쓰는 곳 |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| `empty` | 120 | EmptyState 기본 |
|
|
152
|
+
| `error` | 120 | ErrorState 기본 |
|
|
153
|
+
| `error-404` · `error-403` · `error-500` | 320 | ErrorPage |
|
|
154
|
+
|
|
155
|
+
- **색 토큰 규칙 밖의 이미지 자산이에요.** 캐릭터의 주황은 화면 강조색이 아니라 그림의 일부라서 §1 "강조는 한 곳에만"과 섞지 않아요. 그래서 위 세 곳 말고는 쓰지 않아요(버튼, 카드 장식, 배너 X).
|
|
156
|
+
- 배경이 투명해서 Light/Dark에 같은 그림을 써요.
|
|
157
|
+
- 장식이라 `alt=""`로 숨겨요. 무엇이 없는지, 무엇이 실패했는지는 제목과 설명이 전해요.
|
|
158
|
+
- 이미지는 패키지에 webp 파일로 들어 있어요(`dist/illustrations`, 표시 크기의 2배). 쓰는 쪽은 설정 없이 Vite와 Next.js가 자산으로 처리해요.
|
|
159
|
+
- Popover, Select 안처럼 좁은 곳에서는 `icon`을 넘겨 아이콘으로 바꿔요(§10 EmptyState).
|
|
160
|
+
- 추가할 때: 같은 캐릭터, 투명 배경, 표시 크기 2배로 만들어 Figma `Source illustrations`와 `src/illustrations`에 함께 넣어요.
|
|
161
|
+
|
|
145
162
|
## 4. Auto layout 규칙 (Figma)
|
|
146
163
|
|
|
147
164
|
- 자식이 둘 이상인 프레임은 모두 auto layout을 씁니다. 절대 좌표 배치는 쓰지 않아요.
|
|
@@ -170,6 +187,18 @@ import { Plus } from 'lucide-react';
|
|
|
170
187
|
- 문구는 한국어 해요체예요. 취소 버튼은 "취소"로 충분해요. 무엇을 취소하는지는 바로 옆 primary 버튼 문구가 알려 줘요.
|
|
171
188
|
- Avatar 이니셜은 이름에서 1~2글자를 써요(한글은 이름 첫 글자, 영문은 이름·성 첫 글자).
|
|
172
189
|
|
|
190
|
+
### 좁은 화면 (모바일)
|
|
191
|
+
|
|
192
|
+
좁은 화면은 너비 640 미만(Tailwind `sm` 미만)이에요. Figma에서는 375 프레임으로 그려요.
|
|
193
|
+
|
|
194
|
+
| 대상 | 규칙 |
|
|
195
|
+
|---|---|
|
|
196
|
+
| Dialog·AlertDialog Footer | 버튼이 전체 너비, 높이 40(lg)으로 위아래로 쌓여요. primary가 위, 취소가 아래예요. 엄지가 쉽게 닿는 아래쪽에 취소가 있어서 위험한 동작을 잘못 누르기 어려워요. 컴포넌트가 자동으로 처리해요 |
|
|
197
|
+
| 그 밖의 버튼 묶음 (Card Footer 등) | 자동으로 바꾸지 않아요. 화면을 그릴 때 누르기 쉬운지 보고, 필요하면 버튼을 FILL로 늘려요 |
|
|
198
|
+
| 버튼 크기 | 터치 화면의 주요 동작은 md(32) 이상을 써요. sm·icon-sm(28)과 ToggleGroup 항목(24)은 WCAG 최소 기준(24)은 넘지만, 손가락으로 누르기엔 작아서 보조 자리에만 써요 |
|
|
199
|
+
| Tooltip | 터치 기기에는 hover가 없어서 거의 보이지 않아요. 아이콘 버튼의 이름은 aria-label이 전하고, Tooltip에만 있는 정보를 두지 않아요 |
|
|
200
|
+
| 입력 글자 | Input·Textarea·Select는 iOS가 입력란을 확대하지 않도록 16px로 커져요(높이는 그대로). 코드만의 동작이라 Figma에는 그리지 않아요 |
|
|
201
|
+
|
|
173
202
|
## 5. 해야 할 것 / 하지 말아야 할 것
|
|
174
203
|
|
|
175
204
|
| 해야 할 것 | 하지 말아야 할 것 |
|
|
@@ -221,11 +250,11 @@ hover, focus는 **컴포넌트 variant로 만들지 않아요.** React prop이
|
|
|
221
250
|
|
|
222
251
|
| 계층 | 위치 | 기준 | 예 |
|
|
223
252
|
|---|---|---|---|
|
|
224
|
-
| **Core** | sonic-ui `src/components/` | 더 나눌 수 없고, 도메인을 전혀 모름 | Button, Input, Textarea, Checkbox, RadioGroup, Switch, Select, Text, Card, Avatar, Dialog, AlertDialog, Menu, Popover, Tooltip, Tabs, Separator, Toast, Badge, Progress, Link, Table, ToggleGroup, Accordion, FileDropzone, FileList, Field, Skeleton, EmptyState, ErrorState |
|
|
253
|
+
| **Core** | sonic-ui `src/components/` | 더 나눌 수 없고, 도메인을 전혀 모름 | Button, Input, Textarea, Checkbox, RadioGroup, Switch, Select, Text, Card, Avatar, Dialog, AlertDialog, Menu, Popover, Tooltip, Tabs, Separator, Toast, Badge, Progress, Link, Table, ToggleGroup, Accordion, FileDropzone, FileList, Field, Skeleton, EmptyState, ErrorState, ErrorPage |
|
|
225
254
|
| **Pattern** | sonic-ui `src/patterns/` | Core 조합이고 도메인을 모르지만, **두 프로젝트 이상에서 같은 형태로 복사됨** | (아직 없음) |
|
|
226
255
|
| **Domain** | 각 프로젝트 | 도메인 타입, API, 비즈니스 로직 중 하나라도 앎 | `UserProfileCard`, `ApiKeyList` |
|
|
227
256
|
|
|
228
|
-
예외: EmptyState
|
|
257
|
+
예외: EmptyState, ErrorState, ErrorPage는 Core 조합이라 원래는 Pattern 후보지만, §8 규칙과 모든 프로젝트의 에러 화면이 요구하는 **시스템 컴포넌트**라서 Core에 둬요.
|
|
229
258
|
|
|
230
259
|
판단 순서:
|
|
231
260
|
1. props에 도메인 타입(`User`, `Order`)이 들어가나요? → **Domain**
|
|
@@ -303,7 +332,7 @@ Figma Core 페이지의 컴포넌트 속성 이름 = React props 이름이에요
|
|
|
303
332
|
| `disabled` | boolean |
|
|
304
333
|
| 그 외 | 기본 `<input>` 속성 전부 |
|
|
305
334
|
|
|
306
|
-
높이 `space/8`, 좌우 padding `space/3`, radius `radius/md`, 바탕 `bg/surface`, 테두리 `border/default`(hover `border/strong`, invalid `border/danger`), 입력값 `body` + `text/default`, placeholder `text/muted`, 너비는 부모를 채움.
|
|
335
|
+
높이 `space/8`, 좌우 padding `space/3`, radius `radius/md`, 바탕 `bg/surface`, 테두리 `border/default`(hover `border/strong`, invalid `border/danger`), 입력값 `body` + `text/default`, placeholder `text/muted`, 너비는 부모를 채움. 좁은 화면(640 미만)에서는 입력 글자가 16px이에요(iOS 자동 확대 방지, Textarea·Select 트리거도 같음).
|
|
307
336
|
|
|
308
337
|
focus 링은 2px, 간격 2px이고, 색은 기본 `border/focus`, invalid일 때 `border/danger`예요. 에러 상태에서 파란 링이 뜨면 상태 신호가 섞이기 때문이에요.
|
|
309
338
|
|
|
@@ -356,8 +385,10 @@ radius `radius/full`, 바탕 `bg/subtle`, fallback 글자 `text/muted`. 이미
|
|
|
356
385
|
```
|
|
357
386
|
|
|
358
387
|
- `DialogPopup`이 Portal과 Backdrop을 함께 그려요. 쓰는 쪽에서 Backdrop을 따로 넣지 않아요.
|
|
359
|
-
- Backdrop `bg/overlay`. Popup 너비 440(화면이 좁으면 좌우 `space/4`를 뺀
|
|
388
|
+
- Backdrop `bg/overlay`. Popup 너비 440(화면이 좁으면 좌우 `space/4`를 뺀 너비, Figma `viewport=mobile` variant), padding `space/6`, 영역 사이 `space/4`, 바탕 `bg/surface`, 테두리 1px, radius `radius/lg`.
|
|
360
389
|
- 열기/닫기: `duration/normal` + `easing/standard`. `[data-starting-style]`과 `[data-ending-style]`에서 opacity 0, scale 0.98. Backdrop은 opacity만 바꿔요.
|
|
390
|
+
- Popup 최대 높이는 화면 높이에서 위아래 `space/4`를 뺀 값이에요. 키보드가 올라오거나 가로 화면이라 넘치면 Popup 안쪽이 스크롤돼요.
|
|
391
|
+
- 좁은 화면(640 미만)에서는 Footer 버튼이 전체 너비, 높이 40(lg)으로 위아래로 쌓여요. 쓰는 쪽은 그대로 `<Button>`을 넣으면 돼요. primary가 위, 취소가 아래예요(Figma `viewport=mobile`). 코드 순서는 그대로(취소 → primary)라 키보드 이동 순서는 화면과 반대지만, 모바일에서는 영향이 작아요.
|
|
361
392
|
- `open`, `onOpenChange`로 제어할 수 있어요. Esc와 바깥 클릭으로 닫혀요.
|
|
362
393
|
|
|
363
394
|
#### 트리거가 밖에 있을 때 (Dialog, AlertDialog 공통)
|
|
@@ -428,19 +459,49 @@ const retryRef = useRef<HTMLButtonElement>(null);
|
|
|
428
459
|
### EmptyState / ErrorState
|
|
429
460
|
|
|
430
461
|
```tsx
|
|
431
|
-
<EmptyState
|
|
462
|
+
<EmptyState title="API 키가 없어요" description="키를 만들면 여기에서 사용량을 볼 수 있어요." action={<Button>API 키 만들기</Button>} />
|
|
432
463
|
<ErrorState title="API 키를 불러오지 못했어요" description="네트워크 연결을 확인하고 다시 시도해 주세요." onRetry={refetch} />
|
|
464
|
+
<EmptyState icon={<Inbox />} title="결과가 없어요" /> // 좁은 곳: 아이콘
|
|
433
465
|
```
|
|
434
466
|
|
|
435
467
|
| | EmptyState | ErrorState |
|
|
436
468
|
|---|---|---|
|
|
437
|
-
|
|
|
469
|
+
| 그림 (기본) | 캐릭터 `empty` 120 (§3.7) | 캐릭터 `error` 120 |
|
|
470
|
+
| 아이콘 (`icon`을 넘기면) | 24, `text/muted`, `bg/subtle` 원 `space/12` | 24, `text/danger` (예: `triangle-alert`), 원은 같음 |
|
|
438
471
|
| 제목 / 설명 | `body-strong` / `body` + `text/muted`, 가운데 정렬 | 같음 |
|
|
439
472
|
| 행동 | `action` (보통 primary Button 하나) | `onRetry`가 있으면 secondary Button + `refresh-cw`, 문구 `retryLabel`(기본 "다시 시도") |
|
|
440
473
|
| 간격 | 요소 사이 `space/4`, 위아래 `space/12`, 좌우 `space/6` | 같음 |
|
|
441
474
|
|
|
442
475
|
에러 문구는 사과하지 않고, 무엇이 실패했고 어떻게 하면 되는지 써요.
|
|
443
476
|
|
|
477
|
+
그림(120)은 카드나 표 안의 빈 상태·에러에 써요. Popover, Select, 좁은 사이드 패널처럼 공간이 작으면 `icon`을 넘겨요. 그림이 있으면 정상 화면보다 높이가 커질 수 있으니, 4가지 상태를 그릴 때 영역 높이를 함께 확인해요.
|
|
478
|
+
|
|
479
|
+
### ErrorPage
|
|
480
|
+
|
|
481
|
+
```tsx
|
|
482
|
+
// Next.js app/not-found.tsx
|
|
483
|
+
export default function NotFound() {
|
|
484
|
+
return <ErrorPage status={404} action={<Button render={<NextLink href="/" />}>홈으로 가기</Button>} />;
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
| prop | 값 | 기본값 |
|
|
489
|
+
|---|---|---|
|
|
490
|
+
| `status` | `404` · `403` · `500` (필수) | — |
|
|
491
|
+
| `title`, `description` | 바꿀 문구 | 상태별 문구 (아래) |
|
|
492
|
+
| `action` | primary Button 하나 (상태별 권장은 아래 표) | 없음 |
|
|
493
|
+
|
|
494
|
+
| status | 그림 | 제목 | 설명 | 권장 action |
|
|
495
|
+
|---|---|---|---|---|
|
|
496
|
+
| 404 | `error-404` | 페이지를 찾을 수 없어요 | 주소가 바뀌었거나 삭제된 페이지예요. 주소를 확인해 주세요. | 홈으로 가기 |
|
|
497
|
+
| 403 | `error-403` | 이 페이지를 볼 권한이 없어요 | 관리자에게 권한을 요청해 주세요. | 홈으로 가기 |
|
|
498
|
+
| 500 | `error-500` | 서버에 문제가 생겼어요 | 잠시 뒤 다시 시도해 주세요. | `refresh-cw` + 다시 시도 (페이지 다시 불러오기) |
|
|
499
|
+
|
|
500
|
+
- 화면 전체를 쓰는 에러예요. 카드 하나가 실패하면 ErrorState, 페이지 자체를 보여 줄 수 없을 때 ErrorPage를 써요.
|
|
501
|
+
- 그림 320(§3.7), 그 아래 오류 코드 `mono-caption` + `text/muted`("오류 코드 404", 문의할 때 쓰도록), 제목 `title`(페이지의 `h1`), 설명 `body` + `text/muted`, 가운데 정렬. 숫자는 그림 안에 있어서 크게 따로 쓰지 않아요.
|
|
502
|
+
- 너비는 부모를 채우고, 위아래 `space/16`, 좌우 `space/6`, 요소 사이 `space/6`(글자 묶음 안 `space/2`).
|
|
503
|
+
- 500은 일시적인 실패일 때가 많아서 홈으로 보내지 않고 그 자리에서 다시 불러오게 해요. Next.js `error.tsx`는 클라이언트 컴포넌트라 `reset`을 연결해요: `<ErrorPage status={500} action={<Button onClick={reset}><RefreshCw />다시 시도</Button>} />`. `reset`이 없으면 `location.reload()`를 써요.
|
|
504
|
+
|
|
444
505
|
### Textarea
|
|
445
506
|
|
|
446
507
|
`<Textarea rows={3} invalid disabled />` — Input과 같은 테두리·hover·focus·invalid 규칙이에요. 최소 높이 80(약 3줄), padding `space/3`·`space/2`, 세로로만 크기를 바꿀 수 있어요. Field 안에서 라벨·에러와 함께 써요.
|
|
@@ -553,7 +614,7 @@ const retryRef = useRef<HTMLButtonElement>(null);
|
|
|
553
614
|
</Tabs>
|
|
554
615
|
```
|
|
555
616
|
|
|
556
|
-
같은 대상의 다른 보기를 오갈 때만 써요(페이지 이동 링크에는 쓰지 않아요). 탭 높이 32, padding `space/3`, `body-strong`. 선택 `text/default`, 나머지 `text/muted`(hover 시 `text/default`). 목록 아래 1px `border/default`, 선택 표시 막대 2px `bg/primary`가 `duration/normal`로 움직여요. 목록과 패널 사이 `space/4`예요.
|
|
617
|
+
같은 대상의 다른 보기를 오갈 때만 써요(페이지 이동 링크에는 쓰지 않아요). 탭 높이 32, padding `space/3`, `body-strong`. 선택 `text/default`, 나머지 `text/muted`(hover 시 `text/default`). 목록 아래 1px `border/default`, 선택 표시 막대 2px `bg/primary`가 `duration/normal`로 움직여요. 목록과 패널 사이 `space/4`예요. 탭이 많아 넘치면 목록이 가로로 스크롤돼요(스크롤 막대는 숨기고, 탭은 줄지 않아요).
|
|
557
618
|
|
|
558
619
|
키보드: 기본은 화살표 키로 이동하면 **바로 탭이 바뀌어요**(`activateOnFocus`, 기본 `true`). 탭을 바꿀 때 무거운 내용을 불러온다면 `<TabsList activateOnFocus={false}>`로 화살표는 이동만, Enter·Space로 전환하게 해요. 끝에서 처음으로 돌아가는 `loopFocus`도 기본 `true`예요. 키보드 조작 자체를 끄는 옵션은 없어요. 포커스 링은 탭끼리 겹치지 않도록 탭 **안쪽**(offset −2px)에 그려요. 패널(`TabsPanel`)은 Tab 키로 들어갈 수 있어서(WAI-ARIA Tabs 패턴), 키보드 포커스일 때 패널 **바깥**에 같은 2px 링(offset 2px)을 그려요. 마우스로 누를 때는 보이지 않아요(Figma › 10 Navigation › Tabs › Focus).
|
|
559
620
|
|
|
@@ -723,6 +784,7 @@ const [items, setItems] = useState<FileItemData[]>(serverFiles.map(toItem)); /
|
|
|
723
784
|
- **다른 폼 항목처럼 Field로 감싸요.** Field의 라벨이 버튼 이름이 되고, 설명·에러·`invalid`·`disabled`가 자동으로 연결돼요(Base UI `Field.Control`). Field 없이 쓰면 영역 안 제목이 버튼 이름이 돼요.
|
|
724
785
|
- 에러는 두 종류예요. 고르는 순간 조건에 맞지 않은 파일은 **영역 안**에 바로 알려 주고, "1개 이상 올려 주세요"처럼 제출할 때 확인하는 규칙은 Field `error`로 **아래**에 보여 줘요.
|
|
725
786
|
- 영역 전체가 버튼이라 눌러도, Enter·Space를 눌러도 파일 선택 창이 열려요. 파일을 끌어다 놓아도 돼요.
|
|
787
|
+
- 터치 기기(`pointer: coarse`)에는 끌어다 놓기가 없어서, 기본 제목이 "눌러서 파일을 고르세요"(image는 "눌러서 이미지를 고르세요")로 바뀌어요. `title`을 넘기면 그 문구를 그대로 써요.
|
|
726
788
|
- 조건(형식 `type`, 크기 `size`, 개수 `count`)에 맞지 않는 파일은 `rejected`로 넘기고, 영역 안에 고치는 방법을 기본 문구로 보여 줘요(예: "계약서.pdf: 10MB보다 큰 파일은 올릴 수 없어요"). 문구는 `rejected[].message`로 바꿀 수 있어요.
|
|
727
789
|
- 점선 1px `border/strong` + `bg/surface` + `radius/lg`, 위아래 `space/6`, 좌우 `space/4`, 요소 사이 `space/2`. 아이콘 24(`upload` · `image`, `text/muted`), 제목 `body-strong`, 조건 `caption` + `text/muted`. hover `bg/subtle`, 끌어다 놓는 중 `border/focus` + `bg/subtle`, 거부되면 `border/danger` + 문구 `text/danger`.
|
|
728
790
|
|
|
@@ -773,17 +835,18 @@ Sonic 팀은 Figma Pro 요금제라 Code Connect(Organization 이상)를 쓸 수
|
|
|
773
835
|
| Text | `5:110` | `<Text variant tone as>` | `src/components/text.tsx` |
|
|
774
836
|
| Avatar | `5:117` | `<Avatar size src alt fallback>` | `src/components/avatar.tsx` |
|
|
775
837
|
| Card | `6:2` | `Card`, `CardHeader`, `CardTitle`, `CardDescription`, `CardBody`, `CardFooter` | `src/components/card.tsx` |
|
|
776
|
-
| Dialog | `
|
|
838
|
+
| Dialog | `106:4859` | (`viewport` → prop 아님. 좁은 화면은 코드가 자동 처리) `Dialog`, `DialogTrigger`, `DialogPopup`, `DialogTitle`, `DialogDescription`, `DialogClose`, `DialogFooter` | `src/components/dialog.tsx` |
|
|
777
839
|
| Field | `31:1543` | `<Field label description error invalid disabled>` + `<Input />` | `src/components/field.tsx` |
|
|
778
840
|
| Skeleton | `31:1547` | `<Skeleton shape>` | `src/components/skeleton.tsx` |
|
|
779
|
-
| EmptyState | `
|
|
780
|
-
| ErrorState | `
|
|
841
|
+
| EmptyState | `92:5905` | `<EmptyState icon title description action>` (`media=illustration`이 기본, `media=icon` → `icon` prop) | `src/components/empty-state.tsx` |
|
|
842
|
+
| ErrorState | `92:5919` | `<ErrorState icon title description onRetry retryLabel>` (`media`는 EmptyState와 같음) | `src/components/error-state.tsx` |
|
|
843
|
+
| ErrorPage | `92:5953` | `<ErrorPage status title description action>` (`status` → 같은 prop, `action` → 넘길지) | `src/components/error-page.tsx` |
|
|
781
844
|
| Textarea | `44:2239` | `<Textarea invalid disabled placeholder>` | `src/components/textarea.tsx` |
|
|
782
845
|
| Checkbox | `44:2266` | `<Checkbox checked indeterminate disabled>` (`checked=indeterminate` → `indeterminate`) | `src/components/checkbox.tsx` |
|
|
783
846
|
| Radio | `44:2281` | `<RadioGroup label>` + `<Radio value disabled>` | `src/components/radio-group.tsx` |
|
|
784
847
|
| Switch | `44:2298` | `<Switch checked disabled>` | `src/components/switch.tsx` |
|
|
785
848
|
| Select Trigger · Item · Popup | `44:2315` · `44:2372` · `44:2373` | `<Select options multiple placeholder invalid disabled>` (Trigger `state=open`은 열린 상태, Item은 `options`에서 자동 생성) | `src/components/select.tsx` |
|
|
786
|
-
| AlertDialog | `
|
|
849
|
+
| AlertDialog | `106:4869` | (`viewport`는 Dialog와 같음) `AlertDialog`, `AlertDialogTrigger`, `AlertDialogPopup`, `…Title`, `…Description`, `…Close`, `…Footer` | `src/components/alert-dialog.tsx` |
|
|
787
850
|
| Menu Item · Menu Popup | `49:3092` · `49:3093` | `<MenuItem tone disabled>` (`showIcon`/`icon` → 자식 아이콘), `MenuPopup`, `MenuSeparator` | `src/components/menu.tsx` |
|
|
788
851
|
| Popover | `49:4247` | `Popover`, `PopoverTrigger`, `PopoverPopup`, `PopoverTitle`, `PopoverDescription`, `PopoverClose` | `src/components/popover.tsx` |
|
|
789
852
|
| Tooltip | `49:3040` | `<Tooltip content>` | `src/components/tooltip.tsx` |
|
|
@@ -797,6 +860,7 @@ Sonic 팀은 Figma Pro 요금제라 Code Connect(Organization 이상)를 쓸 수
|
|
|
797
860
|
| Toggle Item · Toggle Group | `66:3760` · `66:3761` | `<ToggleGroup multiple>` + `<ToggleGroupItem value disabled>` (`pressed` → 현재 값, `content=icon`이면 `aria-label`) | `src/components/toggle-group.tsx` |
|
|
798
861
|
| Accordion Item · Accordion | `66:3792` · `66:3793` | `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionPanel` (`open` → 현재 값, `title`/`content` → 자식) | `src/components/accordion.tsx` |
|
|
799
862
|
| File Dropzone · File Item | `71:4191` · `72:4251` | `<FileDropzone variant accept multiple maxSize maxFiles onFilesChange>` (`state` → 끌어다 놓기·거부·`disabled`), `<FileList layout items onRemove onRetry>` (`status` → `items[].status`) | `src/components/file-upload.tsx` |
|
|
800
|
-
|
|
|
863
|
+
| Illustration (5개) | Foundations `Source illustrations` | 코드에서 직접 쓰지 않음. EmptyState·ErrorState·ErrorPage 안에 들어 있어요(§3.7) | `src/illustrations/*.webp` |
|
|
864
|
+
| Icon (37개) | Foundations `Source icons` | `lucide-react`의 같은 이름 컴포넌트 (`Icon / chevron-down` → `<ChevronDown />`) | 쓰는 쪽에서 설치 |
|
|
801
865
|
|
|
802
866
|
Figma 속성 → props 변환 규칙: variant 속성은 같은 이름의 prop으로, 텍스트 속성 `children`은 자식으로, boolean `header`/`footer`는 해당 하위 컴포넌트를 넣을지 말지로 옮겨요. Button의 `iconLeft`/`iconRight`(+ `leftIcon`/`rightIcon` 교체)와 Button Icon의 `icon`은 prop이 아니라 **자식 순서**예요: `<Button><Plus />추가하기<ChevronDown /></Button>`.
|
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Figma (원본) → DESIGN.md (룰) → @xonic0506/sonic-ui (코드) → 실제
|
|
|
35
35
|
| 폼 | Field, Checkbox, CheckboxGroup, RadioGroup, Switch, Select (단일·다중) |
|
|
36
36
|
| 오버레이 | Dialog, AlertDialog, Menu, Popover, Tooltip |
|
|
37
37
|
| 탐색 | Tabs |
|
|
38
|
-
| 피드백·상태 | Toast, Badge, Progress, Skeleton, EmptyState, ErrorState |
|
|
38
|
+
| 피드백·상태 | Toast, Badge, Progress, Skeleton, EmptyState, ErrorState, ErrorPage |
|
|
39
39
|
|
|
40
40
|
컴포넌트별 props와 스펙은 [DESIGN.md §10](./DESIGN.md#10-컴포넌트-스펙-core)에 있어요.
|
|
41
41
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
export declare const backdropClass = "sn:fixed sn:inset-0 sn:z-50 sn:bg-overlay sn:transition-opacity sn:duration-(--sn-duration-normal) sn:ease-standard sn:data-starting-style:opacity-0 sn:data-ending-style:opacity-0 sn:motion-reduce:transition-none";
|
|
3
|
-
export declare const dialogPopupClass = "sn:fixed sn:top-1/2 sn:left-1/2 sn:z-50 sn:box-border sn:flex sn:w-110 sn:max-w-[calc(100vw-2*var(--sn-space-4))] sn:-translate-x-1/2 sn:-translate-y-1/2 sn:flex-col sn:gap-4 sn:rounded-lg sn:border sn:border-default sn:bg-surface sn:p-6 sn:font-sans sn:text-body sn:text-default sn:outline-none sn:transition-[opacity,scale] sn:duration-(--sn-duration-normal) sn:ease-standard sn:data-starting-style:scale-98 sn:data-starting-style:opacity-0 sn:data-ending-style:scale-98 sn:data-ending-style:opacity-0 sn:motion-reduce:transition-none";
|
|
3
|
+
export declare const dialogPopupClass = "sn:fixed sn:top-1/2 sn:left-1/2 sn:z-50 sn:box-border sn:flex sn:w-110 sn:max-w-[calc(100vw-2*var(--sn-space-4))] sn:max-h-[calc(100dvh-2*var(--sn-space-4))] sn:overflow-y-auto sn:-translate-x-1/2 sn:-translate-y-1/2 sn:flex-col sn:gap-4 sn:rounded-lg sn:border sn:border-default sn:bg-surface sn:p-6 sn:font-sans sn:text-body sn:text-default sn:outline-none sn:transition-[opacity,scale] sn:duration-(--sn-duration-normal) sn:ease-standard sn:data-starting-style:scale-98 sn:data-starting-style:opacity-0 sn:data-ending-style:scale-98 sn:data-ending-style:opacity-0 sn:motion-reduce:transition-none";
|
|
4
4
|
export declare const dialogTitleClass = "sn:m-0 sn:text-title sn:text-default";
|
|
5
5
|
export declare const dialogDescriptionClass = "sn:-mt-3 sn:mb-0 sn:text-caption sn:text-muted";
|
|
6
6
|
export interface DialogProps {
|
|
@@ -4,7 +4,7 @@ import * as t from "react";
|
|
|
4
4
|
import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
5
5
|
import { Dialog as i } from "@base-ui/react/dialog";
|
|
6
6
|
//#region src/components/dialog.tsx
|
|
7
|
-
var a = "sn:fixed sn:inset-0 sn:z-50 sn:bg-overlay sn:transition-opacity sn:duration-(--sn-duration-normal) sn:ease-standard sn:data-starting-style:opacity-0 sn:data-ending-style:opacity-0 sn:motion-reduce:transition-none", o = "sn:fixed sn:top-1/2 sn:left-1/2 sn:z-50 sn:box-border sn:flex sn:w-110 sn:max-w-[calc(100vw-2*var(--sn-space-4))] sn:-translate-x-1/2 sn:-translate-y-1/2 sn:flex-col sn:gap-4 sn:rounded-lg sn:border sn:border-default sn:bg-surface sn:p-6 sn:font-sans sn:text-body sn:text-default sn:outline-none sn:transition-[opacity,scale] sn:duration-(--sn-duration-normal) sn:ease-standard sn:data-starting-style:scale-98 sn:data-starting-style:opacity-0 sn:data-ending-style:scale-98 sn:data-ending-style:opacity-0 sn:motion-reduce:transition-none", s = "sn:m-0 sn:text-title sn:text-default", c = "sn:-mt-3 sn:mb-0 sn:text-caption sn:text-muted";
|
|
7
|
+
var a = "sn:fixed sn:inset-0 sn:z-50 sn:bg-overlay sn:transition-opacity sn:duration-(--sn-duration-normal) sn:ease-standard sn:data-starting-style:opacity-0 sn:data-ending-style:opacity-0 sn:motion-reduce:transition-none", o = "sn:fixed sn:top-1/2 sn:left-1/2 sn:z-50 sn:box-border sn:flex sn:w-110 sn:max-w-[calc(100vw-2*var(--sn-space-4))] sn:max-h-[calc(100dvh-2*var(--sn-space-4))] sn:overflow-y-auto sn:-translate-x-1/2 sn:-translate-y-1/2 sn:flex-col sn:gap-4 sn:rounded-lg sn:border sn:border-default sn:bg-surface sn:p-6 sn:font-sans sn:text-body sn:text-default sn:outline-none sn:transition-[opacity,scale] sn:duration-(--sn-duration-normal) sn:ease-standard sn:data-starting-style:scale-98 sn:data-starting-style:opacity-0 sn:data-ending-style:scale-98 sn:data-ending-style:opacity-0 sn:motion-reduce:transition-none", s = "sn:m-0 sn:text-title sn:text-default", c = "sn:-mt-3 sn:mb-0 sn:text-caption sn:text-muted";
|
|
8
8
|
function l({ onOpenChange: e, ...t }) {
|
|
9
9
|
return /* @__PURE__ */ n(i.Root, {
|
|
10
10
|
...t,
|
|
@@ -44,7 +44,7 @@ var u = t.forwardRef(function(e, t) {
|
|
|
44
44
|
}), h = t.forwardRef(function({ className: t, ...r }, i) {
|
|
45
45
|
return /* @__PURE__ */ n("div", {
|
|
46
46
|
ref: i,
|
|
47
|
-
className: e("sn:mt-2 sn:flex sn:justify-end sn:gap-2", t),
|
|
47
|
+
className: e("sn:mt-2 sn:flex sn:justify-end sn:gap-2 sn:max-sm:flex-col-reverse sn:max-sm:*:h-10 sn:max-sm:*:w-full", t),
|
|
48
48
|
...r
|
|
49
49
|
});
|
|
50
50
|
});
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { illustrations as e } from "./illustration.js";
|
|
3
|
+
import { StateLayout as t } from "./state-layout.js";
|
|
3
4
|
import "react";
|
|
4
|
-
import { jsx as
|
|
5
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
5
6
|
//#region src/components/empty-state.tsx
|
|
6
|
-
function
|
|
7
|
-
return /* @__PURE__ */ t
|
|
8
|
-
icon:
|
|
7
|
+
function r({ icon: r, title: i, description: a, action: o, className: s }) {
|
|
8
|
+
return /* @__PURE__ */ n(t, {
|
|
9
|
+
icon: r,
|
|
9
10
|
iconClassName: "sn:text-muted",
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
illustration: e.empty,
|
|
12
|
+
title: i,
|
|
13
|
+
description: a,
|
|
14
|
+
className: s,
|
|
15
|
+
children: o
|
|
14
16
|
});
|
|
15
17
|
}
|
|
16
18
|
//#endregion
|
|
17
|
-
export {
|
|
19
|
+
export { r as EmptyState };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export type ErrorPageStatus = 404 | 403 | 500;
|
|
3
|
+
export interface ErrorPageProps {
|
|
4
|
+
status: ErrorPageStatus;
|
|
5
|
+
/** 기본값: 상태별 문구 */
|
|
6
|
+
title?: React.ReactNode;
|
|
7
|
+
description?: React.ReactNode;
|
|
8
|
+
/** 보통 primary <Button> 하나 (예: 홈으로 가기) */
|
|
9
|
+
action?: React.ReactNode;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
/** 화면 전체 에러. 제목이 페이지의 h1이에요 */
|
|
13
|
+
export declare function ErrorPage({ status, title, description, action, className }: ErrorPageProps): React.JSX.Element;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn as e } from "../lib/cn.js";
|
|
3
|
+
import { illustrations as t } from "./illustration.js";
|
|
4
|
+
import "react";
|
|
5
|
+
import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/error-page.tsx
|
|
7
|
+
var i = {
|
|
8
|
+
404: ["페이지를 찾을 수 없어요", "주소가 바뀌었거나 삭제된 페이지예요. 주소를 확인해 주세요."],
|
|
9
|
+
403: ["이 페이지를 볼 권한이 없어요", "관리자에게 권한을 요청해 주세요."],
|
|
10
|
+
500: ["서버에 문제가 생겼어요", "잠시 뒤 다시 시도해 주세요."]
|
|
11
|
+
};
|
|
12
|
+
function a({ status: a, title: o = i[a][0], description: s = i[a][1], action: c, className: l }) {
|
|
13
|
+
return /* @__PURE__ */ r("div", {
|
|
14
|
+
className: e("sn:box-border sn:flex sn:w-full sn:flex-col sn:items-center sn:gap-6 sn:px-6 sn:py-16 sn:text-center sn:font-sans", l),
|
|
15
|
+
children: [
|
|
16
|
+
/* @__PURE__ */ n("img", {
|
|
17
|
+
src: t[a],
|
|
18
|
+
alt: "",
|
|
19
|
+
width: 320,
|
|
20
|
+
height: 213,
|
|
21
|
+
className: "sn:block sn:h-auto sn:max-w-full"
|
|
22
|
+
}),
|
|
23
|
+
/* @__PURE__ */ r("div", {
|
|
24
|
+
className: "sn:flex sn:flex-col sn:items-center sn:gap-2",
|
|
25
|
+
children: [
|
|
26
|
+
/* @__PURE__ */ r("p", {
|
|
27
|
+
className: "sn:m-0 sn:font-mono sn:text-caption sn:tabular-nums sn:text-muted",
|
|
28
|
+
children: ["오류 코드 ", a]
|
|
29
|
+
}),
|
|
30
|
+
/* @__PURE__ */ n("h1", {
|
|
31
|
+
className: "sn:m-0 sn:text-title sn:text-default",
|
|
32
|
+
children: o
|
|
33
|
+
}),
|
|
34
|
+
s && /* @__PURE__ */ n("p", {
|
|
35
|
+
className: "sn:m-0 sn:text-body sn:text-muted",
|
|
36
|
+
children: s
|
|
37
|
+
})
|
|
38
|
+
]
|
|
39
|
+
}),
|
|
40
|
+
c
|
|
41
|
+
]
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { a as ErrorPage };
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Button as e } from "./button.js";
|
|
3
|
-
import {
|
|
3
|
+
import { illustrations as t } from "./illustration.js";
|
|
4
|
+
import { StateLayout as n } from "./state-layout.js";
|
|
4
5
|
import "react";
|
|
5
|
-
import { RefreshCw as
|
|
6
|
+
import { RefreshCw as r } from "lucide-react";
|
|
6
7
|
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
7
8
|
//#region src/components/error-state.tsx
|
|
8
|
-
function o({ icon: o
|
|
9
|
-
return /* @__PURE__ */ i(
|
|
9
|
+
function o({ icon: o, title: s, description: c, onRetry: l, retryLabel: u = "다시 시도", className: d }) {
|
|
10
|
+
return /* @__PURE__ */ i(n, {
|
|
10
11
|
role: "alert",
|
|
11
12
|
icon: o,
|
|
12
13
|
iconClassName: "sn:text-danger",
|
|
14
|
+
illustration: t.error,
|
|
13
15
|
title: s,
|
|
14
16
|
description: c,
|
|
15
17
|
className: d,
|
|
16
18
|
children: l && /* @__PURE__ */ a(e, {
|
|
17
19
|
variant: "secondary",
|
|
18
20
|
onClick: l,
|
|
19
|
-
children: [/* @__PURE__ */ i(
|
|
21
|
+
children: [/* @__PURE__ */ i(r, {}), u]
|
|
20
22
|
})
|
|
21
23
|
});
|
|
22
24
|
}
|
|
@@ -78,7 +78,13 @@ function v({ onFilesChange: t, accept: n, multiple: r, maxFiles: a, maxSize: o,
|
|
|
78
78
|
/* @__PURE__ */ f(A, { className: "sn:size-6 sn:text-muted sn:group-data-invalid:text-danger sn:group-aria-invalid:text-danger" }),
|
|
79
79
|
/* @__PURE__ */ f("span", {
|
|
80
80
|
className: "sn:text-body-strong sn:text-default",
|
|
81
|
-
children: u ??
|
|
81
|
+
children: u ?? /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ f("span", {
|
|
82
|
+
className: "sn:pointer-coarse:hidden",
|
|
83
|
+
children: c === "image" ? "이미지를 끌어다 놓거나 눌러서 고르세요" : "파일을 끌어다 놓거나 눌러서 고르세요"
|
|
84
|
+
}), /* @__PURE__ */ f("span", {
|
|
85
|
+
className: "sn:hidden sn:pointer-coarse:inline",
|
|
86
|
+
children: c === "image" ? "눌러서 이미지를 고르세요" : "눌러서 파일을 고르세요"
|
|
87
|
+
})] })
|
|
82
88
|
}),
|
|
83
89
|
/* @__PURE__ */ f("span", {
|
|
84
90
|
id: D,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
//#region src/components/illustration.ts
|
|
3
|
+
var e = {
|
|
4
|
+
empty: new URL("../illustrations/empty.webp", import.meta.url).href,
|
|
5
|
+
error: new URL("../illustrations/error.webp", import.meta.url).href,
|
|
6
|
+
404: new URL("../illustrations/error-404.webp", import.meta.url).href,
|
|
7
|
+
403: new URL("../illustrations/error-403.webp", import.meta.url).href,
|
|
8
|
+
500: new URL("../illustrations/error-500.webp", import.meta.url).href
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { e as illustrations };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
export declare const inputClass = "sn:box-border sn:m-0 sn:w-full sn:min-w-0 sn:rounded-md sn:border sn:border-default sn:bg-surface sn:px-3 sn:font-sans sn:text-body sn:text-default sn:placeholder:text-muted sn:transition-colors sn:duration-(--sn-duration-fast) sn:ease-standard sn:hover:not-data-disabled:border-strong sn:focus-visible:outline-2 sn:focus-visible:outline-offset-2 sn:focus-visible:outline-focus sn:aria-invalid:focus-visible:outline-danger sn:data-invalid:focus-visible:outline-danger sn:aria-invalid:border-danger sn:hover:aria-invalid:border-danger sn:data-invalid:border-danger sn:data-disabled:cursor-not-allowed sn:data-disabled:opacity-(--sn-opacity-disabled)";
|
|
2
|
+
export declare const inputClass = "sn:box-border sn:m-0 sn:w-full sn:min-w-0 sn:rounded-md sn:border sn:border-default sn:bg-surface sn:px-3 sn:font-sans sn:text-body sn:max-sm:text-[16px] sn:text-default sn:placeholder:text-muted sn:transition-colors sn:duration-(--sn-duration-fast) sn:ease-standard sn:hover:not-data-disabled:border-strong sn:focus-visible:outline-2 sn:focus-visible:outline-offset-2 sn:focus-visible:outline-focus sn:aria-invalid:focus-visible:outline-danger sn:data-invalid:focus-visible:outline-danger sn:aria-invalid:border-danger sn:hover:aria-invalid:border-danger sn:data-invalid:border-danger sn:data-disabled:cursor-not-allowed sn:data-disabled:opacity-(--sn-opacity-disabled)";
|
|
3
3
|
export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'className' | 'size'> {
|
|
4
4
|
/** 에러 상태. aria-invalid로 전달돼요 */
|
|
5
5
|
invalid?: boolean;
|
package/dist/components/input.js
CHANGED
|
@@ -4,7 +4,7 @@ import * as t from "react";
|
|
|
4
4
|
import { jsx as n } from "react/jsx-runtime";
|
|
5
5
|
import { Input as r } from "@base-ui/react/input";
|
|
6
6
|
//#region src/components/input.tsx
|
|
7
|
-
var i = "sn:box-border sn:m-0 sn:w-full sn:min-w-0 sn:rounded-md sn:border sn:border-default sn:bg-surface sn:px-3 sn:font-sans sn:text-body sn:text-default sn:placeholder:text-muted sn:transition-colors sn:duration-(--sn-duration-fast) sn:ease-standard sn:hover:not-data-disabled:border-strong sn:focus-visible:outline-2 sn:focus-visible:outline-offset-2 sn:focus-visible:outline-focus sn:aria-invalid:focus-visible:outline-danger sn:data-invalid:focus-visible:outline-danger sn:aria-invalid:border-danger sn:hover:aria-invalid:border-danger sn:data-invalid:border-danger sn:data-disabled:cursor-not-allowed sn:data-disabled:opacity-(--sn-opacity-disabled)", a = t.forwardRef(function({ invalid: t, className: a, ...o }, s) {
|
|
7
|
+
var i = "sn:box-border sn:m-0 sn:w-full sn:min-w-0 sn:rounded-md sn:border sn:border-default sn:bg-surface sn:px-3 sn:font-sans sn:text-body sn:max-sm:text-[16px] sn:text-default sn:placeholder:text-muted sn:transition-colors sn:duration-(--sn-duration-fast) sn:ease-standard sn:hover:not-data-disabled:border-strong sn:focus-visible:outline-2 sn:focus-visible:outline-offset-2 sn:focus-visible:outline-focus sn:aria-invalid:focus-visible:outline-danger sn:data-invalid:focus-visible:outline-danger sn:aria-invalid:border-danger sn:hover:aria-invalid:border-danger sn:data-invalid:border-danger sn:data-disabled:cursor-not-allowed sn:data-disabled:opacity-(--sn-opacity-disabled)", a = t.forwardRef(function({ invalid: t, className: a, ...o }, s) {
|
|
8
8
|
return /* @__PURE__ */ n(r, {
|
|
9
9
|
ref: s,
|
|
10
10
|
"aria-invalid": t || void 0,
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
export interface StateLayoutProps {
|
|
3
|
+
/** 넘기면 아이콘 원(48), 없으면 일러스트(120) */
|
|
3
4
|
icon?: React.ReactNode;
|
|
4
5
|
iconClassName: string;
|
|
6
|
+
/** 일러스트 주소 */
|
|
7
|
+
illustration: string;
|
|
5
8
|
title: React.ReactNode;
|
|
6
9
|
description?: React.ReactNode;
|
|
7
10
|
className?: string;
|
|
8
11
|
role?: 'alert';
|
|
9
12
|
children?: React.ReactNode;
|
|
10
13
|
}
|
|
11
|
-
export declare function StateLayout({ icon, iconClassName, title, description, className, role, children }: StateLayoutProps): React.JSX.Element;
|
|
14
|
+
export declare function StateLayout({ icon, iconClassName, illustration, title, description, className, role, children }: StateLayoutProps): React.JSX.Element;
|
|
@@ -3,27 +3,33 @@ import { cn as e } from "../lib/cn.js";
|
|
|
3
3
|
import "react";
|
|
4
4
|
import { jsx as t, jsxs as n } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/state-layout.tsx
|
|
6
|
-
function r({ icon: r, iconClassName: i,
|
|
6
|
+
function r({ icon: r, iconClassName: i, illustration: a, title: o, description: s, className: c, role: l, children: u }) {
|
|
7
7
|
return /* @__PURE__ */ n("div", {
|
|
8
|
-
role:
|
|
9
|
-
className: e("sn:box-border sn:flex sn:flex-col sn:items-center sn:gap-4 sn:px-6 sn:py-12 sn:text-center sn:font-sans",
|
|
8
|
+
role: l,
|
|
9
|
+
className: e("sn:box-border sn:flex sn:flex-col sn:items-center sn:gap-4 sn:px-6 sn:py-12 sn:text-center sn:font-sans", c),
|
|
10
10
|
children: [
|
|
11
|
-
r
|
|
11
|
+
r ? /* @__PURE__ */ t("span", {
|
|
12
12
|
"aria-hidden": !0,
|
|
13
13
|
className: e("sn:inline-flex sn:size-12 sn:items-center sn:justify-center sn:rounded-full sn:bg-subtle sn:[&_svg]:size-6", i),
|
|
14
14
|
children: r
|
|
15
|
+
}) : /* @__PURE__ */ t("img", {
|
|
16
|
+
src: a,
|
|
17
|
+
alt: "",
|
|
18
|
+
width: 120,
|
|
19
|
+
height: 120,
|
|
20
|
+
className: "sn:block"
|
|
15
21
|
}),
|
|
16
22
|
/* @__PURE__ */ n("div", {
|
|
17
23
|
className: "sn:flex sn:flex-col sn:gap-1",
|
|
18
24
|
children: [/* @__PURE__ */ t("p", {
|
|
19
25
|
className: "sn:m-0 sn:text-body-strong sn:text-default",
|
|
20
|
-
children: a
|
|
21
|
-
}), o && /* @__PURE__ */ t("p", {
|
|
22
|
-
className: "sn:m-0 sn:text-body sn:text-muted",
|
|
23
26
|
children: o
|
|
27
|
+
}), s && /* @__PURE__ */ t("p", {
|
|
28
|
+
className: "sn:m-0 sn:text-body sn:text-muted",
|
|
29
|
+
children: s
|
|
24
30
|
})]
|
|
25
31
|
}),
|
|
26
|
-
|
|
32
|
+
u
|
|
27
33
|
]
|
|
28
34
|
});
|
|
29
35
|
}
|
package/dist/components/tabs.js
CHANGED
|
@@ -14,11 +14,14 @@ function a({ value: t, defaultValue: r, onValueChange: a, className: o, children
|
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
function o({ activateOnFocus: t = !0, loopFocus: a = !0, className: o, children: s }) {
|
|
17
|
-
return /* @__PURE__ */
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
return /* @__PURE__ */ n("div", {
|
|
18
|
+
className: "sn:-mb-px sn:overflow-x-auto sn:pb-px sn:[scrollbar-width:none]",
|
|
19
|
+
children: /* @__PURE__ */ r(i.List, {
|
|
20
|
+
activateOnFocus: t,
|
|
21
|
+
loopFocus: a,
|
|
22
|
+
className: e("sn:relative sn:flex sn:w-max sn:min-w-full sn:border-b sn:border-default", o),
|
|
23
|
+
children: [s, /* @__PURE__ */ n(i.Indicator, { className: "sn:absolute sn:bottom-[-1px] sn:left-0 sn:h-0.5 sn:w-(--active-tab-width) sn:translate-x-(--active-tab-left) sn:bg-primary sn:transition-[translate,width] sn:duration-(--sn-duration-normal) sn:ease-standard sn:motion-reduce:transition-none" })]
|
|
24
|
+
})
|
|
22
25
|
});
|
|
23
26
|
}
|
|
24
27
|
var s = t.forwardRef(function({ value: t, disabled: r, className: a, children: o }, s) {
|
|
@@ -26,7 +29,7 @@ var s = t.forwardRef(function({ value: t, disabled: r, className: a, children: o
|
|
|
26
29
|
ref: s,
|
|
27
30
|
value: t,
|
|
28
31
|
disabled: r,
|
|
29
|
-
className: e("sn:box-border sn:flex sn:h-8 sn:items-center sn:border-0 sn:bg-transparent sn:px-3 sn:font-sans sn:text-body-strong sn:text-muted sn:cursor-pointer sn:focus-visible:outline-2 sn:focus-visible:-outline-offset-2 sn:focus-visible:outline-focus sn:transition-colors sn:duration-(--sn-duration-fast) sn:hover:not-data-disabled:text-default sn:data-active:text-default sn:data-disabled:cursor-not-allowed sn:data-disabled:opacity-(--sn-opacity-disabled)", a),
|
|
32
|
+
className: e("sn:box-border sn:flex sn:h-8 sn:shrink-0 sn:items-center sn:whitespace-nowrap sn:border-0 sn:bg-transparent sn:px-3 sn:font-sans sn:text-body-strong sn:text-muted sn:cursor-pointer sn:focus-visible:outline-2 sn:focus-visible:-outline-offset-2 sn:focus-visible:outline-focus sn:transition-colors sn:duration-(--sn-duration-fast) sn:hover:not-data-disabled:text-default sn:data-active:text-default sn:data-disabled:cursor-not-allowed sn:data-disabled:opacity-(--sn-opacity-disabled)", a),
|
|
30
33
|
children: o
|
|
31
34
|
});
|
|
32
35
|
});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export { Field, type FieldProps } from './components/field';
|
|
|
12
12
|
export { Skeleton, type SkeletonProps } from './components/skeleton';
|
|
13
13
|
export { EmptyState, type EmptyStateProps } from './components/empty-state';
|
|
14
14
|
export { ErrorState, type ErrorStateProps } from './components/error-state';
|
|
15
|
+
export { ErrorPage, type ErrorPageProps, type ErrorPageStatus } from './components/error-page';
|
|
15
16
|
export { Dialog, DialogTrigger, DialogPopup, DialogTitle, DialogDescription, DialogClose, DialogFooter, type DialogProps, type DialogButtonProps, type DialogPopupProps, } from './components/dialog';
|
|
16
17
|
export { AlertDialog, AlertDialogTrigger, AlertDialogPopup, AlertDialogTitle, AlertDialogDescription, AlertDialogClose, AlertDialogFooter, } from './components/alert-dialog';
|
|
17
18
|
export { Menu, MenuTrigger, MenuPopup, MenuItem, MenuSeparator, type MenuProps, type MenuTriggerProps, type MenuPopupProps, type MenuItemProps } from './components/menu';
|
package/dist/index.js
CHANGED
|
@@ -13,19 +13,20 @@ import { Field as _ } from "./components/field.js";
|
|
|
13
13
|
import { Skeleton as v } from "./components/skeleton.js";
|
|
14
14
|
import { EmptyState as y } from "./components/empty-state.js";
|
|
15
15
|
import { ErrorState as b } from "./components/error-state.js";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
|
|
16
|
+
import { ErrorPage as x } from "./components/error-page.js";
|
|
17
|
+
import { Dialog as S, DialogClose as C, DialogDescription as w, DialogFooter as T, DialogPopup as E, DialogTitle as D, DialogTrigger as O } from "./components/dialog.js";
|
|
18
|
+
import { AlertDialog as k, AlertDialogClose as A, AlertDialogDescription as j, AlertDialogFooter as M, AlertDialogPopup as N, AlertDialogTitle as P, AlertDialogTrigger as F } from "./components/alert-dialog.js";
|
|
19
|
+
import { Menu as I, MenuItem as L, MenuPopup as R, MenuSeparator as z, MenuTrigger as B } from "./components/menu.js";
|
|
20
|
+
import { Popover as V, PopoverClose as H, PopoverDescription as U, PopoverPopup as W, PopoverTitle as G, PopoverTrigger as K } from "./components/popover.js";
|
|
21
|
+
import { Tooltip as q } from "./components/tooltip.js";
|
|
22
|
+
import { Tab as J, Tabs as Y, TabsList as X, TabsPanel as Z } from "./components/tabs.js";
|
|
23
|
+
import { Separator as Q } from "./components/separator.js";
|
|
24
|
+
import { ToastProvider as $, useToast as ee } from "./components/toast.js";
|
|
25
|
+
import { Badge as te } from "./components/badge.js";
|
|
26
|
+
import { Progress as ne } from "./components/progress.js";
|
|
27
|
+
import { Link as re } from "./components/link.js";
|
|
28
|
+
import { Table as ie, TableBody as ae, TableCell as oe, TableHead as se, TableHeader as ce, TableRow as le } from "./components/table.js";
|
|
29
|
+
import { ToggleGroup as ue, ToggleGroupItem as de } from "./components/toggle-group.js";
|
|
30
|
+
import { Accordion as fe, AccordionItem as pe, AccordionPanel as me, AccordionTrigger as he } from "./components/accordion.js";
|
|
31
|
+
import { FileDropzone as ge, FileList as _e, formatBytes as ve } from "./components/file-upload.js";
|
|
32
|
+
export { fe as Accordion, pe as AccordionItem, me as AccordionPanel, he as AccordionTrigger, k as AlertDialog, A as AlertDialogClose, j as AlertDialogDescription, M as AlertDialogFooter, N as AlertDialogPopup, P as AlertDialogTitle, F as AlertDialogTrigger, g as Avatar, te as Badge, e as Button, u as Card, d as CardBody, f as CardDescription, p as CardFooter, m as CardHeader, h as CardTitle, r as Checkbox, i as CheckboxGroup, S as Dialog, C as DialogClose, w as DialogDescription, T as DialogFooter, E as DialogPopup, D as DialogTitle, O as DialogTrigger, y as EmptyState, x as ErrorPage, b as ErrorState, _ as Field, ge as FileDropzone, _e as FileList, t as Input, re as Link, I as Menu, L as MenuItem, R as MenuPopup, z as MenuSeparator, B as MenuTrigger, V as Popover, H as PopoverClose, U as PopoverDescription, W as PopoverPopup, G as PopoverTitle, K as PopoverTrigger, ne as Progress, a as Radio, o as RadioGroup, c as Select, Q as Separator, v as Skeleton, s as Switch, J as Tab, ie as Table, ae as TableBody, oe as TableCell, se as TableHead, ce as TableHeader, le as TableRow, Y as Tabs, X as TabsList, Z as TabsPanel, l as Text, n as Textarea, $ as ToastProvider, ue as ToggleGroup, de as ToggleGroupItem, q as Tooltip, ve as formatBytes, ee as useToast };
|
package/dist/styles.css
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/*! sonic-ui | 전체가 @layer sonic 안에 있어요. 쓰는 쪽: @layer theme, base, sonic, components, utilities; */
|
|
2
2
|
@property --tw-border-spacing-x{syntax:"<length>";inherits:false;initial-value:0}@property --tw-border-spacing-y{syntax:"<length>";inherits:false;initial-value:0}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@layer sonic{/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
3
|
-
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-duration:initial;--tw-ease:initial;--tw-outline-style:solid;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme;@layer utilities{.sn\:sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.sn\:absolute{position:absolute}.sn\:fixed{position:fixed}.sn\:relative{position:relative}.sn\:inset-0{inset:0}.sn\:top-1\/2{top:50%}.sn\:right-4{right:calc(var(--sn-space-1) * 4)}.sn\:bottom-4{bottom:calc(var(--sn-space-1) * 4)}.sn\:bottom-\[-1px\]{bottom:-1px}.sn\:left-0{left:0}.sn\:left-1\/2{left:50%}.sn\:z-50{z-index:50}.sn\:m-0{margin:0}.sn\:my-1{margin-block:var(--sn-space-1)}.sn\:-mt-2{margin-top:calc(var(--sn-space-1) * -2)}.sn\:-mt-3{margin-top:calc(var(--sn-space-1) * -3)}.sn\:mt-2{margin-top:calc(var(--sn-space-1) * 2)}.sn\:mb-0{margin-bottom:0}.sn\:ml-1{margin-left:var(--sn-space-1)}.sn\:box-border{box-sizing:border-box}.sn\:block{display:block}.sn\:flex{display:flex}.sn\:hidden{display:none}.sn\:inline-block{display:inline-block}.sn\:inline-flex{display:inline-flex}.sn\:size-2{width:calc(var(--sn-space-1) * 2);height:calc(var(--sn-space-1) * 2)}.sn\:size-3{width:calc(var(--sn-space-1) * 3);height:calc(var(--sn-space-1) * 3)}.sn\:size-4{width:calc(var(--sn-space-1) * 4);height:calc(var(--sn-space-1) * 4)}.sn\:size-6{width:calc(var(--sn-space-1) * 6);height:calc(var(--sn-space-1) * 6)}.sn\:size-7{width:calc(var(--sn-space-1) * 7);height:calc(var(--sn-space-1) * 7)}.sn\:size-8{width:calc(var(--sn-space-1) * 8);height:calc(var(--sn-space-1) * 8)}.sn\:size-10{width:calc(var(--sn-space-1) * 10);height:calc(var(--sn-space-1) * 10)}.sn\:size-12{width:calc(var(--sn-space-1) * 12);height:calc(var(--sn-space-1) * 12)}.sn\:size-24{width:calc(var(--sn-space-1) * 24);height:calc(var(--sn-space-1) * 24)}.sn\:size-full{width:100%;height:100%}.sn\:h-\(--accordion-panel-height\){height:var(--accordion-panel-height)}.sn\:h-0\.5{height:calc(var(--sn-space-1) * .5)}.sn\:h-1{height:var(--sn-space-1)}.sn\:h-3{height:calc(var(--sn-space-1) * 3)}.sn\:h-4{height:calc(var(--sn-space-1) * 4)}.sn\:h-5{height:calc(var(--sn-space-1) * 5)}.sn\:h-6{height:calc(var(--sn-space-1) * 6)}.sn\:h-7{height:calc(var(--sn-space-1) * 7)}.sn\:h-8{height:calc(var(--sn-space-1) * 8)}.sn\:h-10{height:calc(var(--sn-space-1) * 10)}.sn\:h-16{height:calc(var(--sn-space-1) * 16)}.sn\:h-full{height:100%}.sn\:h-px{height:1px}.sn\:max-h-\(--available-height\){max-height:var(--available-height)}.sn\:min-h-20{min-height:calc(var(--sn-space-1) * 20)}.sn\:w-\(--active-tab-width\){width:var(--active-tab-width)}.sn\:w-6{width:calc(var(--sn-space-1) * 6)}.sn\:w-7{width:calc(var(--sn-space-1) * 7)}.sn\:w-24{width:calc(var(--sn-space-1) * 24)}.sn\:w-80{width:calc(var(--sn-space-1) * 80)}.sn\:w-90{width:calc(var(--sn-space-1) * 90)}.sn\:w-110{width:calc(var(--sn-space-1) * 110)}.sn\:w-full{width:100%}.sn\:w-px{width:1px}.sn\:max-w-\[calc\(100vw-2\*var\(--sn-space-4\)\)\]{max-width:calc(100vw - 2 * var(--sn-space-4))}.sn\:min-w-\(--anchor-width\){min-width:var(--anchor-width)}.sn\:min-w-0{min-width:0}.sn\:min-w-48{min-width:calc(var(--sn-space-1) * 48)}.sn\:flex-1{flex:1}.sn\:shrink-0{flex-shrink:0}.sn\:border-separate{border-collapse:separate}.sn\:border-spacing-0{--tw-border-spacing-x:0px;--tw-border-spacing-y:0px;border-spacing:var(--tw-border-spacing-x) var(--tw-border-spacing-y)}.sn\:origin-\(--transform-origin\){transform-origin:var(--transform-origin)}.sn\:-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.sn\:translate-x-\(--active-tab-left\){--tw-translate-x:var(--active-tab-left);translate:var(--tw-translate-x) var(--tw-translate-y)}.sn\:-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.sn\:animate-\[sn-pulse_var\(--sn-duration-loop\)_ease-in-out_infinite\]{animation:sn-pulse var(--sn-duration-loop) ease-in-out infinite}.sn\:animate-\[sn-spin_var\(--sn-duration-loop\)_linear_infinite\]{animation:sn-spin var(--sn-duration-loop) linear infinite}.sn\:cursor-default{cursor:default}.sn\:cursor-not-allowed{cursor:not-allowed}.sn\:cursor-pointer{cursor:pointer}.sn\:resize-y{resize:vertical}.sn\:list-none{list-style-type:none}.sn\:flex-col{flex-direction:column}.sn\:flex-col-reverse{flex-direction:column-reverse}.sn\:flex-wrap{flex-wrap:wrap}.sn\:items-center{align-items:center}.sn\:items-start{align-items:flex-start}.sn\:justify-between{justify-content:space-between}.sn\:justify-center{justify-content:center}.sn\:justify-end{justify-content:flex-end}.sn\:gap-1{gap:var(--sn-space-1)}.sn\:gap-2{gap:calc(var(--sn-space-1) * 2)}.sn\:gap-3{gap:calc(var(--sn-space-1) * 3)}.sn\:gap-4{gap:calc(var(--sn-space-1) * 4)}.sn\:gap-6{gap:calc(var(--sn-space-1) * 6)}.sn\:gap-10{gap:calc(var(--sn-space-1) * 10)}.sn\:self-stretch{align-self:stretch}.sn\:truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.sn\:overflow-hidden{overflow:hidden}.sn\:overflow-x-auto{overflow-x:auto}.sn\:overflow-y-auto{overflow-y:auto}.sn\:rounded-full{border-radius:var(--sn-radius-full)}.sn\:rounded-lg{border-radius:var(--sn-radius-lg)}.sn\:rounded-md{border-radius:var(--sn-radius-md)}.sn\:rounded-sm{border-radius:var(--sn-radius-sm)}.sn\:border{border-style:var(--tw-border-style);border-width:1px}.sn\:border-0{border-style:var(--tw-border-style);border-width:0}.sn\:border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.sn\:border-dashed{--tw-border-style:dashed;border-style:dashed}.sn\:border-danger{border-color:var(--sn-color-border-danger)}.sn\:border-default{border-color:var(--sn-color-border-default)}.sn\:border-strong{border-color:var(--sn-color-border-strong)}.sn\:border-transparent{border-color:#0000}.sn\:bg-\(--sn-color-border-default\){background-color:var(--sn-color-border-default)}.sn\:bg-\(--sn-color-text-on-primary\){background-color:var(--sn-color-text-on-primary)}.sn\:bg-canvas{background-color:var(--sn-color-bg-canvas)}.sn\:bg-danger{background-color:var(--sn-color-bg-danger)}.sn\:bg-danger-subtle{background-color:var(--sn-color-bg-danger-subtle)}.sn\:bg-inverse{background-color:var(--sn-color-bg-inverse)}.sn\:bg-overlay{background-color:var(--sn-color-bg-overlay)}.sn\:bg-primary{background-color:var(--sn-color-bg-primary)}.sn\:bg-subtle{background-color:var(--sn-color-bg-subtle)}.sn\:bg-success{background-color:var(--sn-color-bg-success)}.sn\:bg-success-subtle{background-color:var(--sn-color-bg-success-subtle)}.sn\:bg-surface{background-color:var(--sn-color-bg-surface)}.sn\:bg-transparent{background-color:#0000}.sn\:bg-warning{background-color:var(--sn-color-bg-warning)}.sn\:bg-warning-subtle{background-color:var(--sn-color-bg-warning-subtle)}.sn\:object-cover{object-fit:cover}.sn\:p-0{padding:0}.sn\:p-1{padding:var(--sn-space-1)}.sn\:p-3{padding:calc(var(--sn-space-1) * 3)}.sn\:p-4{padding:calc(var(--sn-space-1) * 4)}.sn\:p-5{padding:calc(var(--sn-space-1) * 5)}.sn\:p-6{padding:calc(var(--sn-space-1) * 6)}.sn\:p-px{padding:1px}.sn\:px-0{padding-inline:0}.sn\:px-2{padding-inline:calc(var(--sn-space-1) * 2)}.sn\:px-3{padding-inline:calc(var(--sn-space-1) * 3)}.sn\:px-4{padding-inline:calc(var(--sn-space-1) * 4)}.sn\:px-6{padding-inline:calc(var(--sn-space-1) * 6)}.sn\:py-0{padding-block:0}.sn\:py-1{padding-block:var(--sn-space-1)}.sn\:py-2{padding-block:calc(var(--sn-space-1) * 2)}.sn\:py-3{padding-block:calc(var(--sn-space-1) * 3)}.sn\:py-6{padding-block:calc(var(--sn-space-1) * 6)}.sn\:py-12{padding-block:calc(var(--sn-space-1) * 12)}.sn\:pt-1{padding-top:var(--sn-space-1)}.sn\:pb-4{padding-bottom:calc(var(--sn-space-1) * 4)}.sn\:text-center{text-align:center}.sn\:text-left{text-align:left}.sn\:text-right{text-align:right}.sn\:align-middle{vertical-align:middle}.sn\:align-text-bottom{vertical-align:text-bottom}.sn\:font-mono{font-family:var(--sn-font-mono)}.sn\:font-sans{font-family:var(--sn-font-sans)}.sn\:text-body{font-size:var(--sn-text-body);line-height:var(--tw-leading,var(--sn-text-body--line-height));letter-spacing:var(--tw-tracking,var(--sn-text-body--letter-spacing));font-weight:var(--tw-font-weight,var(--sn-text-body--font-weight))}.sn\:text-body-strong{font-size:var(--sn-text-body-strong);line-height:var(--tw-leading,var(--sn-text-body-strong--line-height));letter-spacing:var(--tw-tracking,var(--sn-text-body-strong--letter-spacing));font-weight:var(--tw-font-weight,var(--sn-text-body-strong--font-weight))}.sn\:text-caption{font-size:var(--sn-text-caption);line-height:var(--tw-leading,var(--sn-text-caption--line-height));letter-spacing:var(--tw-tracking,var(--sn-text-caption--letter-spacing));font-weight:var(--tw-font-weight,var(--sn-text-caption--font-weight))}.sn\:text-display{font-size:var(--sn-text-display);line-height:var(--tw-leading,var(--sn-text-display--line-height));letter-spacing:var(--tw-tracking,var(--sn-text-display--letter-spacing));font-weight:var(--tw-font-weight,var(--sn-text-display--font-weight))}.sn\:text-label{font-size:var(--sn-text-label);line-height:var(--tw-leading,var(--sn-text-label--line-height));letter-spacing:var(--tw-tracking,var(--sn-text-label--letter-spacing));font-weight:var(--tw-font-weight,var(--sn-text-label--font-weight))}.sn\:text-title{font-size:var(--sn-text-title);line-height:var(--tw-leading,var(--sn-text-title--line-height));letter-spacing:var(--tw-tracking,var(--sn-text-title--letter-spacing));font-weight:var(--tw-font-weight,var(--sn-text-title--font-weight))}.sn\:whitespace-nowrap{white-space:nowrap}.sn\:text-danger{color:var(--sn-color-text-danger)}.sn\:text-default{color:var(--sn-color-text-default)}.sn\:text-inverse{color:var(--sn-color-text-inverse)}.sn\:text-muted{color:var(--sn-color-text-muted)}.sn\:text-on-danger{color:var(--sn-color-text-on-danger)}.sn\:text-on-primary{color:var(--sn-color-text-on-primary)}.sn\:text-on-success{color:var(--sn-color-text-on-success)}.sn\:text-on-warning{color:var(--sn-color-text-on-warning)}.sn\:text-success{color:var(--sn-color-text-success)}.sn\:text-warning{color:var(--sn-color-text-warning)}.sn\:tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.sn\:underline{text-decoration-line:underline}.sn\:underline-offset-2{text-underline-offset:2px}.sn\:opacity-\(--sn-opacity-disabled\){opacity:var(--sn-opacity-disabled)}.sn\:transition-\[height\]{transition-property:height;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-\[opacity\,scale\]{transition-property:opacity,scale;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-\[opacity\,translate\]{transition-property:opacity,translate;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-\[translate\,width\]{transition-property:translate,width;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:duration-\(--sn-duration-fast\){--tw-duration:var(--sn-duration-fast);transition-duration:var(--sn-duration-fast)}.sn\:duration-\(--sn-duration-normal\){--tw-duration:var(--sn-duration-normal);transition-duration:var(--sn-duration-normal)}.sn\:ease-standard{--tw-ease:var(--sn-easing-standard);transition-timing-function:var(--sn-easing-standard)}.sn\:outline-none{--tw-outline-style:none;outline-style:none}.sn\:select-none{-webkit-user-select:none;user-select:none}.sn\:group-aria-invalid\:text-danger:is(:where(.sn\:group)[aria-invalid=true] *),.sn\:group-data-invalid\:text-danger:is(:where(.sn\:group)[data-invalid] *){color:var(--sn-color-text-danger)}.sn\:group-data-panel-open\:rotate-180:is(:where(.sn\:group)[data-panel-open] *),.sn\:group-data-popup-open\:rotate-180:is(:where(.sn\:group)[data-popup-open] *){rotate:180deg}.sn\:group-data-selected\:border-transparent:is(:where(.sn\:group)[data-selected] *){border-color:#0000}.sn\:group-data-selected\:bg-primary:is(:where(.sn\:group)[data-selected] *){background-color:var(--sn-color-bg-primary)}.sn\:placeholder\:text-muted::placeholder{color:var(--sn-color-text-muted)}@media (hover:hover){.sn\:hover\:text-muted:hover{color:var(--sn-color-text-muted)}.sn\:hover\:not-disabled\:bg-subtle:hover:not(:disabled){background-color:var(--sn-color-bg-subtle)}.sn\:hover\:not-data-disabled\:border-strong:hover:not([data-disabled]){border-color:var(--sn-color-border-strong)}.sn\:hover\:not-data-disabled\:bg-primary-hover:hover:not([data-disabled]){background-color:var(--sn-color-bg-primary-hover)}.sn\:hover\:not-data-disabled\:bg-subtle:hover:not([data-disabled]){background-color:var(--sn-color-bg-subtle)}.sn\:hover\:not-data-disabled\:text-default:hover:not([data-disabled]){color:var(--sn-color-text-default)}}.sn\:focus-visible\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.sn\:focus-visible\:-outline-offset-2:focus-visible{outline-offset:calc(2px * -1)}.sn\:focus-visible\:outline-offset-2:focus-visible{outline-offset:2px}.sn\:focus-visible\:outline-focus:focus-visible{outline-color:var(--sn-color-border-focus)}.sn\:disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.sn\:disabled\:opacity-\(--sn-opacity-disabled\):disabled{opacity:var(--sn-opacity-disabled)}.sn\:aria-invalid\:border-danger[aria-invalid=true]{border-color:var(--sn-color-border-danger)}@media (hover:hover){.sn\:hover\:aria-invalid\:border-danger:hover[aria-invalid=true]{border-color:var(--sn-color-border-danger)}}.sn\:aria-invalid\:focus-visible\:outline-danger[aria-invalid=true]:focus-visible{outline-color:var(--sn-color-border-danger)}.sn\:data-active\:text-default[data-active]{color:var(--sn-color-text-default)}.sn\:data-checked\:translate-x-3[data-checked]{--tw-translate-x:calc(var(--sn-space-1) * 3);translate:var(--tw-translate-x) var(--tw-translate-y)}.sn\:data-checked\:border-transparent[data-checked]{border-color:#0000}.sn\:data-checked\:bg-\(--sn-color-text-on-primary\)[data-checked]{background-color:var(--sn-color-text-on-primary)}.sn\:data-checked\:bg-primary[data-checked]{background-color:var(--sn-color-bg-primary)}.sn\:data-disabled\:cursor-not-allowed[data-disabled]{cursor:not-allowed}.sn\:data-disabled\:opacity-\(--sn-opacity-disabled\)[data-disabled]{opacity:var(--sn-opacity-disabled)}.sn\:data-disabled\:not-data-loading\:cursor-not-allowed[data-disabled]:not([data-loading]){cursor:not-allowed}.sn\:data-disabled\:not-data-loading\:opacity-\(--sn-opacity-disabled\)[data-disabled]:not([data-loading]){opacity:var(--sn-opacity-disabled)}.sn\:data-dragging\:border-focus[data-dragging]{border-color:var(--sn-color-border-focus)}.sn\:data-dragging\:bg-subtle[data-dragging]{background-color:var(--sn-color-bg-subtle)}.sn\:data-ending-style\:h-0[data-ending-style]{height:0}.sn\:data-ending-style\:translate-y-2[data-ending-style]{--tw-translate-y:calc(var(--sn-space-1) * 2);translate:var(--tw-translate-x) var(--tw-translate-y)}.sn\:data-ending-style\:scale-98[data-ending-style]{--tw-scale-x:98%;--tw-scale-y:98%;--tw-scale-z:98%;scale:var(--tw-scale-x) var(--tw-scale-y)}.sn\:data-ending-style\:opacity-0[data-ending-style]{opacity:0}.sn\:data-highlighted\:bg-subtle[data-highlighted]{background-color:var(--sn-color-bg-subtle)}.sn\:data-indeterminate\:border-transparent[data-indeterminate]{border-color:#0000}.sn\:data-indeterminate\:bg-primary[data-indeterminate]{background-color:var(--sn-color-bg-primary)}.sn\:data-invalid\:border-danger[data-invalid]{border-color:var(--sn-color-border-danger)}.sn\:data-invalid\:focus-visible\:outline-danger[data-invalid]:focus-visible{outline-color:var(--sn-color-border-danger)}.sn\:data-limited\:hidden[data-limited]{display:none}.sn\:data-loading\:cursor-progress[data-loading]{cursor:progress}.sn\:data-placeholder\:text-muted[data-placeholder]{color:var(--sn-color-text-muted)}.sn\:data-popup-open\:border-focus[data-popup-open]{border-color:var(--sn-color-border-focus)}.sn\:data-pressed\:border-default[data-pressed]{border-color:var(--sn-color-border-default)}.sn\:data-pressed\:bg-surface[data-pressed]{background-color:var(--sn-color-bg-surface)}.sn\:data-pressed\:text-default[data-pressed]{color:var(--sn-color-text-default)}.sn\:data-starting-style\:h-0[data-starting-style]{height:0}.sn\:data-starting-style\:translate-y-2[data-starting-style]{--tw-translate-y:calc(var(--sn-space-1) * 2);translate:var(--tw-translate-x) var(--tw-translate-y)}.sn\:data-starting-style\:scale-98[data-starting-style]{--tw-scale-x:98%;--tw-scale-y:98%;--tw-scale-z:98%;scale:var(--tw-scale-x) var(--tw-scale-y)}.sn\:data-starting-style\:opacity-0[data-starting-style]{opacity:0}@media (prefers-reduced-motion:reduce){.sn\:motion-reduce\:animate-none{animation:none}.sn\:motion-reduce\:transition-none{transition-property:none}}.sn\:\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.sn\:\[\&_svg\]\:size-3 svg{width:calc(var(--sn-space-1) * 3);height:calc(var(--sn-space-1) * 3)}.sn\:\[\&_svg\]\:size-4 svg{width:calc(var(--sn-space-1) * 4);height:calc(var(--sn-space-1) * 4)}.sn\:\[\&_svg\]\:size-5 svg{width:calc(var(--sn-space-1) * 5);height:calc(var(--sn-space-1) * 5)}.sn\:\[\&_svg\]\:size-6 svg{width:calc(var(--sn-space-1) * 6);height:calc(var(--sn-space-1) * 6)}.sn\:\[\&_svg\]\:shrink-0 svg{flex-shrink:0}}:root{--sn-space-0:0px;--sn-space-1:4px;--sn-space-2:8px;--sn-space-3:12px;--sn-space-4:16px;--sn-space-5:20px;--sn-space-6:24px;--sn-space-7:28px;--sn-space-8:32px;--sn-space-10:40px;--sn-space-12:48px;--sn-space-16:64px;--sn-radius-sm:2px;--sn-radius-md:4px;--sn-radius-lg:6px;--sn-radius-full:9999px;--sn-stroke-default:1px;--sn-stroke-focus:2px;--sn-duration-fast:.12s;--sn-duration-normal:.2s;--sn-easing-standard:cubic-bezier(.2, 0, 0, 1);--sn-duration-loop:1s;--sn-opacity-disabled:.45;--sn-font-sans:"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;--sn-font-mono:"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;--sn-text-display:32px;--sn-text-display--line-height:40px;--sn-text-display--font-weight:600;--sn-text-display--letter-spacing:-.02em;--sn-text-title:20px;--sn-text-title--line-height:28px;--sn-text-title--font-weight:600;--sn-text-title--letter-spacing:-.01em;--sn-text-body:14px;--sn-text-body--line-height:20px;--sn-text-body--font-weight:400;--sn-text-body--letter-spacing:0em;--sn-text-body-strong:14px;--sn-text-body-strong--line-height:20px;--sn-text-body-strong--font-weight:500;--sn-text-body-strong--letter-spacing:0em;--sn-text-label:13px;--sn-text-label--line-height:16px;--sn-text-label--font-weight:500;--sn-text-label--letter-spacing:0em;--sn-text-caption:12px;--sn-text-caption--line-height:16px;--sn-text-caption--font-weight:400;--sn-text-caption--letter-spacing:0em;--sn-text-mono:14px;--sn-text-mono--line-height:20px;--sn-text-mono--font-weight:400;--sn-text-mono--letter-spacing:0em;--sn-text-mono-caption:12px;--sn-text-mono-caption--line-height:16px;--sn-text-mono-caption--font-weight:400;--sn-text-mono-caption--letter-spacing:0em}:root,[data-theme=light]{color-scheme:light;--sn-color-bg-canvas:#f4f6f8;--sn-color-bg-surface:#fff;--sn-color-bg-subtle:#e6eaee;--sn-color-bg-primary:#2340d0;--sn-color-bg-primary-hover:#1b33ae;--sn-color-bg-danger:#c8312b;--sn-color-bg-overlay:#0e121680;--sn-color-text-default:#0e1216;--sn-color-text-muted:#5b6672;--sn-color-text-on-primary:#fff;--sn-color-text-on-danger:#fff;--sn-color-text-danger:#c8312b;--sn-color-border-default:#d5dbe1;--sn-color-border-strong:#8d99a6;--sn-color-border-focus:#2340d0;--sn-color-border-danger:#c8312b;--sn-color-bg-inverse:#0e1216;--sn-color-text-inverse:#fff;--sn-color-bg-success:#16804f;--sn-color-text-on-success:#fff;--sn-color-bg-success-subtle:#eaf7f0;--sn-color-text-success:#0f6640;--sn-color-bg-warning:#e3a43a;--sn-color-text-on-warning:#0e1216;--sn-color-bg-warning-subtle:#fcf5e6;--sn-color-text-warning:#85520a;--sn-color-bg-danger-subtle:#fcedec;--sn-color-border-success:#16804f;--sn-color-border-warning:#a86c12}[data-theme=dark]{color-scheme:dark;--sn-color-bg-canvas:#0e1216;--sn-color-bg-surface:#161b21;--sn-color-bg-subtle:#1e252d;--sn-color-bg-primary:#6e86ff;--sn-color-bg-primary-hover:#8c9fff;--sn-color-bg-danger:#f06a5f;--sn-color-bg-overlay:#0e121680;--sn-color-text-default:#e6eaee;--sn-color-text-muted:#8d99a6;--sn-color-text-on-primary:#0e1216;--sn-color-text-on-danger:#0e1216;--sn-color-text-danger:#f06a5f;--sn-color-border-default:#2a323b;--sn-color-border-strong:#5b6672;--sn-color-border-focus:#6e86ff;--sn-color-border-danger:#f06a5f;--sn-color-bg-inverse:#e6eaee;--sn-color-text-inverse:#0e1216;--sn-color-bg-success:#3db882;--sn-color-text-on-success:#0e1216;--sn-color-bg-success-subtle:#0b2218;--sn-color-text-success:#6bd1a0;--sn-color-bg-warning:#e3a43a;--sn-color-text-on-warning:#0e1216;--sn-color-bg-warning-subtle:#24190a;--sn-color-text-warning:#eec46a;--sn-color-bg-danger-subtle:#2b1311;--sn-color-border-success:#3db882;--sn-color-border-warning:#e3a43a}@keyframes sn-pulse{50%{opacity:.5}}@keyframes sn-spin{to{transform:rotate(360deg)}}}
|
|
3
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-duration:initial;--tw-ease:initial;--tw-outline-style:solid;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer utilities{.sn\:sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.sn\:absolute{position:absolute}.sn\:fixed{position:fixed}.sn\:relative{position:relative}.sn\:inset-0{inset:0}.sn\:top-1\/2{top:50%}.sn\:right-4{right:calc(var(--sn-space-1) * 4)}.sn\:bottom-4{bottom:calc(var(--sn-space-1) * 4)}.sn\:bottom-\[-1px\]{bottom:-1px}.sn\:left-0{left:0}.sn\:left-1\/2{left:50%}.sn\:z-50{z-index:50}.sn\:m-0{margin:0}.sn\:my-1{margin-block:var(--sn-space-1)}.sn\:-mt-2{margin-top:calc(var(--sn-space-1) * -2)}.sn\:-mt-3{margin-top:calc(var(--sn-space-1) * -3)}.sn\:mt-2{margin-top:calc(var(--sn-space-1) * 2)}.sn\:-mb-px{margin-bottom:-1px}.sn\:mb-0{margin-bottom:0}.sn\:ml-1{margin-left:var(--sn-space-1)}.sn\:box-border{box-sizing:border-box}.sn\:block{display:block}.sn\:flex{display:flex}.sn\:hidden{display:none}.sn\:inline-block{display:inline-block}.sn\:inline-flex{display:inline-flex}.sn\:size-2{width:calc(var(--sn-space-1) * 2);height:calc(var(--sn-space-1) * 2)}.sn\:size-3{width:calc(var(--sn-space-1) * 3);height:calc(var(--sn-space-1) * 3)}.sn\:size-4{width:calc(var(--sn-space-1) * 4);height:calc(var(--sn-space-1) * 4)}.sn\:size-6{width:calc(var(--sn-space-1) * 6);height:calc(var(--sn-space-1) * 6)}.sn\:size-7{width:calc(var(--sn-space-1) * 7);height:calc(var(--sn-space-1) * 7)}.sn\:size-8{width:calc(var(--sn-space-1) * 8);height:calc(var(--sn-space-1) * 8)}.sn\:size-10{width:calc(var(--sn-space-1) * 10);height:calc(var(--sn-space-1) * 10)}.sn\:size-12{width:calc(var(--sn-space-1) * 12);height:calc(var(--sn-space-1) * 12)}.sn\:size-24{width:calc(var(--sn-space-1) * 24);height:calc(var(--sn-space-1) * 24)}.sn\:size-full{width:100%;height:100%}.sn\:h-\(--accordion-panel-height\){height:var(--accordion-panel-height)}.sn\:h-0\.5{height:calc(var(--sn-space-1) * .5)}.sn\:h-1{height:var(--sn-space-1)}.sn\:h-3{height:calc(var(--sn-space-1) * 3)}.sn\:h-4{height:calc(var(--sn-space-1) * 4)}.sn\:h-5{height:calc(var(--sn-space-1) * 5)}.sn\:h-6{height:calc(var(--sn-space-1) * 6)}.sn\:h-7{height:calc(var(--sn-space-1) * 7)}.sn\:h-8{height:calc(var(--sn-space-1) * 8)}.sn\:h-10{height:calc(var(--sn-space-1) * 10)}.sn\:h-16{height:calc(var(--sn-space-1) * 16)}.sn\:h-auto{height:auto}.sn\:h-full{height:100%}.sn\:h-px{height:1px}.sn\:max-h-\(--available-height\){max-height:var(--available-height)}.sn\:max-h-\[calc\(100dvh-2\*var\(--sn-space-4\)\)\]{max-height:calc(100dvh - 2 * var(--sn-space-4))}.sn\:min-h-20{min-height:calc(var(--sn-space-1) * 20)}.sn\:w-\(--active-tab-width\){width:var(--active-tab-width)}.sn\:w-6{width:calc(var(--sn-space-1) * 6)}.sn\:w-7{width:calc(var(--sn-space-1) * 7)}.sn\:w-24{width:calc(var(--sn-space-1) * 24)}.sn\:w-80{width:calc(var(--sn-space-1) * 80)}.sn\:w-90{width:calc(var(--sn-space-1) * 90)}.sn\:w-110{width:calc(var(--sn-space-1) * 110)}.sn\:w-full{width:100%}.sn\:w-max{width:max-content}.sn\:w-px{width:1px}.sn\:max-w-\[calc\(100vw-2\*var\(--sn-space-4\)\)\]{max-width:calc(100vw - 2 * var(--sn-space-4))}.sn\:max-w-full{max-width:100%}.sn\:min-w-\(--anchor-width\){min-width:var(--anchor-width)}.sn\:min-w-0{min-width:0}.sn\:min-w-48{min-width:calc(var(--sn-space-1) * 48)}.sn\:min-w-full{min-width:100%}.sn\:flex-1{flex:1}.sn\:shrink-0{flex-shrink:0}.sn\:border-separate{border-collapse:separate}.sn\:border-spacing-0{--tw-border-spacing-x:0px;--tw-border-spacing-y:0px;border-spacing:var(--tw-border-spacing-x) var(--tw-border-spacing-y)}.sn\:origin-\(--transform-origin\){transform-origin:var(--transform-origin)}.sn\:-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.sn\:translate-x-\(--active-tab-left\){--tw-translate-x:var(--active-tab-left);translate:var(--tw-translate-x) var(--tw-translate-y)}.sn\:-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.sn\:animate-\[sn-pulse_var\(--sn-duration-loop\)_ease-in-out_infinite\]{animation:sn-pulse var(--sn-duration-loop) ease-in-out infinite}.sn\:animate-\[sn-spin_var\(--sn-duration-loop\)_linear_infinite\]{animation:sn-spin var(--sn-duration-loop) linear infinite}.sn\:cursor-default{cursor:default}.sn\:cursor-not-allowed{cursor:not-allowed}.sn\:cursor-pointer{cursor:pointer}.sn\:resize-y{resize:vertical}.sn\:\[scrollbar-width\:none\]{scrollbar-width:none}.sn\:list-none{list-style-type:none}.sn\:flex-col{flex-direction:column}.sn\:flex-col-reverse{flex-direction:column-reverse}.sn\:flex-wrap{flex-wrap:wrap}.sn\:items-center{align-items:center}.sn\:items-start{align-items:flex-start}.sn\:justify-between{justify-content:space-between}.sn\:justify-center{justify-content:center}.sn\:justify-end{justify-content:flex-end}.sn\:gap-1{gap:var(--sn-space-1)}.sn\:gap-2{gap:calc(var(--sn-space-1) * 2)}.sn\:gap-3{gap:calc(var(--sn-space-1) * 3)}.sn\:gap-4{gap:calc(var(--sn-space-1) * 4)}.sn\:gap-6{gap:calc(var(--sn-space-1) * 6)}.sn\:gap-10{gap:calc(var(--sn-space-1) * 10)}.sn\:self-stretch{align-self:stretch}.sn\:truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.sn\:overflow-hidden{overflow:hidden}.sn\:overflow-x-auto{overflow-x:auto}.sn\:overflow-y-auto{overflow-y:auto}.sn\:rounded-full{border-radius:var(--sn-radius-full)}.sn\:rounded-lg{border-radius:var(--sn-radius-lg)}.sn\:rounded-md{border-radius:var(--sn-radius-md)}.sn\:rounded-sm{border-radius:var(--sn-radius-sm)}.sn\:border{border-style:var(--tw-border-style);border-width:1px}.sn\:border-0{border-style:var(--tw-border-style);border-width:0}.sn\:border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.sn\:border-dashed{--tw-border-style:dashed;border-style:dashed}.sn\:border-danger{border-color:var(--sn-color-border-danger)}.sn\:border-default{border-color:var(--sn-color-border-default)}.sn\:border-strong{border-color:var(--sn-color-border-strong)}.sn\:border-transparent{border-color:#0000}.sn\:bg-\(--sn-color-border-default\){background-color:var(--sn-color-border-default)}.sn\:bg-\(--sn-color-text-on-primary\){background-color:var(--sn-color-text-on-primary)}.sn\:bg-canvas{background-color:var(--sn-color-bg-canvas)}.sn\:bg-danger{background-color:var(--sn-color-bg-danger)}.sn\:bg-danger-subtle{background-color:var(--sn-color-bg-danger-subtle)}.sn\:bg-inverse{background-color:var(--sn-color-bg-inverse)}.sn\:bg-overlay{background-color:var(--sn-color-bg-overlay)}.sn\:bg-primary{background-color:var(--sn-color-bg-primary)}.sn\:bg-subtle{background-color:var(--sn-color-bg-subtle)}.sn\:bg-success{background-color:var(--sn-color-bg-success)}.sn\:bg-success-subtle{background-color:var(--sn-color-bg-success-subtle)}.sn\:bg-surface{background-color:var(--sn-color-bg-surface)}.sn\:bg-transparent{background-color:#0000}.sn\:bg-warning{background-color:var(--sn-color-bg-warning)}.sn\:bg-warning-subtle{background-color:var(--sn-color-bg-warning-subtle)}.sn\:object-cover{object-fit:cover}.sn\:p-0{padding:0}.sn\:p-1{padding:var(--sn-space-1)}.sn\:p-3{padding:calc(var(--sn-space-1) * 3)}.sn\:p-4{padding:calc(var(--sn-space-1) * 4)}.sn\:p-5{padding:calc(var(--sn-space-1) * 5)}.sn\:p-6{padding:calc(var(--sn-space-1) * 6)}.sn\:p-px{padding:1px}.sn\:px-0{padding-inline:0}.sn\:px-2{padding-inline:calc(var(--sn-space-1) * 2)}.sn\:px-3{padding-inline:calc(var(--sn-space-1) * 3)}.sn\:px-4{padding-inline:calc(var(--sn-space-1) * 4)}.sn\:px-6{padding-inline:calc(var(--sn-space-1) * 6)}.sn\:py-0{padding-block:0}.sn\:py-1{padding-block:var(--sn-space-1)}.sn\:py-2{padding-block:calc(var(--sn-space-1) * 2)}.sn\:py-3{padding-block:calc(var(--sn-space-1) * 3)}.sn\:py-6{padding-block:calc(var(--sn-space-1) * 6)}.sn\:py-12{padding-block:calc(var(--sn-space-1) * 12)}.sn\:py-16{padding-block:calc(var(--sn-space-1) * 16)}.sn\:pt-1{padding-top:var(--sn-space-1)}.sn\:pb-4{padding-bottom:calc(var(--sn-space-1) * 4)}.sn\:pb-px{padding-bottom:1px}.sn\:text-center{text-align:center}.sn\:text-left{text-align:left}.sn\:text-right{text-align:right}.sn\:align-middle{vertical-align:middle}.sn\:align-text-bottom{vertical-align:text-bottom}.sn\:font-mono{font-family:var(--sn-font-mono)}.sn\:font-sans{font-family:var(--sn-font-sans)}.sn\:text-body{font-size:var(--sn-text-body);line-height:var(--tw-leading,var(--sn-text-body--line-height));letter-spacing:var(--tw-tracking,var(--sn-text-body--letter-spacing));font-weight:var(--tw-font-weight,var(--sn-text-body--font-weight))}.sn\:text-body-strong{font-size:var(--sn-text-body-strong);line-height:var(--tw-leading,var(--sn-text-body-strong--line-height));letter-spacing:var(--tw-tracking,var(--sn-text-body-strong--letter-spacing));font-weight:var(--tw-font-weight,var(--sn-text-body-strong--font-weight))}.sn\:text-caption{font-size:var(--sn-text-caption);line-height:var(--tw-leading,var(--sn-text-caption--line-height));letter-spacing:var(--tw-tracking,var(--sn-text-caption--letter-spacing));font-weight:var(--tw-font-weight,var(--sn-text-caption--font-weight))}.sn\:text-display{font-size:var(--sn-text-display);line-height:var(--tw-leading,var(--sn-text-display--line-height));letter-spacing:var(--tw-tracking,var(--sn-text-display--letter-spacing));font-weight:var(--tw-font-weight,var(--sn-text-display--font-weight))}.sn\:text-label{font-size:var(--sn-text-label);line-height:var(--tw-leading,var(--sn-text-label--line-height));letter-spacing:var(--tw-tracking,var(--sn-text-label--letter-spacing));font-weight:var(--tw-font-weight,var(--sn-text-label--font-weight))}.sn\:text-title{font-size:var(--sn-text-title);line-height:var(--tw-leading,var(--sn-text-title--line-height));letter-spacing:var(--tw-tracking,var(--sn-text-title--letter-spacing));font-weight:var(--tw-font-weight,var(--sn-text-title--font-weight))}.sn\:whitespace-nowrap{white-space:nowrap}.sn\:text-danger{color:var(--sn-color-text-danger)}.sn\:text-default{color:var(--sn-color-text-default)}.sn\:text-inverse{color:var(--sn-color-text-inverse)}.sn\:text-muted{color:var(--sn-color-text-muted)}.sn\:text-on-danger{color:var(--sn-color-text-on-danger)}.sn\:text-on-primary{color:var(--sn-color-text-on-primary)}.sn\:text-on-success{color:var(--sn-color-text-on-success)}.sn\:text-on-warning{color:var(--sn-color-text-on-warning)}.sn\:text-success{color:var(--sn-color-text-success)}.sn\:text-warning{color:var(--sn-color-text-warning)}.sn\:tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.sn\:underline{text-decoration-line:underline}.sn\:underline-offset-2{text-underline-offset:2px}.sn\:opacity-\(--sn-opacity-disabled\){opacity:var(--sn-opacity-disabled)}.sn\:transition-\[height\]{transition-property:height;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-\[opacity\,scale\]{transition-property:opacity,scale;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-\[opacity\,translate\]{transition-property:opacity,translate;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-\[translate\,width\]{transition-property:translate,width;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,ease);transition-duration:var(--tw-duration,0s)}.sn\:duration-\(--sn-duration-fast\){--tw-duration:var(--sn-duration-fast);transition-duration:var(--sn-duration-fast)}.sn\:duration-\(--sn-duration-normal\){--tw-duration:var(--sn-duration-normal);transition-duration:var(--sn-duration-normal)}.sn\:ease-standard{--tw-ease:var(--sn-easing-standard);transition-timing-function:var(--sn-easing-standard)}.sn\:outline-none{--tw-outline-style:none;outline-style:none}.sn\:select-none{-webkit-user-select:none;user-select:none}.sn\:group-aria-invalid\:text-danger:is(:where(.sn\:group)[aria-invalid=true] *),.sn\:group-data-invalid\:text-danger:is(:where(.sn\:group)[data-invalid] *){color:var(--sn-color-text-danger)}.sn\:group-data-panel-open\:rotate-180:is(:where(.sn\:group)[data-panel-open] *),.sn\:group-data-popup-open\:rotate-180:is(:where(.sn\:group)[data-popup-open] *){rotate:180deg}.sn\:group-data-selected\:border-transparent:is(:where(.sn\:group)[data-selected] *){border-color:#0000}.sn\:group-data-selected\:bg-primary:is(:where(.sn\:group)[data-selected] *){background-color:var(--sn-color-bg-primary)}.sn\:placeholder\:text-muted::placeholder{color:var(--sn-color-text-muted)}@media (hover:hover){.sn\:hover\:text-muted:hover{color:var(--sn-color-text-muted)}.sn\:hover\:not-disabled\:bg-subtle:hover:not(:disabled){background-color:var(--sn-color-bg-subtle)}.sn\:hover\:not-data-disabled\:border-strong:hover:not([data-disabled]){border-color:var(--sn-color-border-strong)}.sn\:hover\:not-data-disabled\:bg-primary-hover:hover:not([data-disabled]){background-color:var(--sn-color-bg-primary-hover)}.sn\:hover\:not-data-disabled\:bg-subtle:hover:not([data-disabled]){background-color:var(--sn-color-bg-subtle)}.sn\:hover\:not-data-disabled\:text-default:hover:not([data-disabled]){color:var(--sn-color-text-default)}}.sn\:focus-visible\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.sn\:focus-visible\:-outline-offset-2:focus-visible{outline-offset:calc(2px * -1)}.sn\:focus-visible\:outline-offset-2:focus-visible{outline-offset:2px}.sn\:focus-visible\:outline-focus:focus-visible{outline-color:var(--sn-color-border-focus)}.sn\:disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.sn\:disabled\:opacity-\(--sn-opacity-disabled\):disabled{opacity:var(--sn-opacity-disabled)}.sn\:aria-invalid\:border-danger[aria-invalid=true]{border-color:var(--sn-color-border-danger)}@media (hover:hover){.sn\:hover\:aria-invalid\:border-danger:hover[aria-invalid=true]{border-color:var(--sn-color-border-danger)}}.sn\:aria-invalid\:focus-visible\:outline-danger[aria-invalid=true]:focus-visible{outline-color:var(--sn-color-border-danger)}.sn\:data-active\:text-default[data-active]{color:var(--sn-color-text-default)}.sn\:data-checked\:translate-x-3[data-checked]{--tw-translate-x:calc(var(--sn-space-1) * 3);translate:var(--tw-translate-x) var(--tw-translate-y)}.sn\:data-checked\:border-transparent[data-checked]{border-color:#0000}.sn\:data-checked\:bg-\(--sn-color-text-on-primary\)[data-checked]{background-color:var(--sn-color-text-on-primary)}.sn\:data-checked\:bg-primary[data-checked]{background-color:var(--sn-color-bg-primary)}.sn\:data-disabled\:cursor-not-allowed[data-disabled]{cursor:not-allowed}.sn\:data-disabled\:opacity-\(--sn-opacity-disabled\)[data-disabled]{opacity:var(--sn-opacity-disabled)}.sn\:data-disabled\:not-data-loading\:cursor-not-allowed[data-disabled]:not([data-loading]){cursor:not-allowed}.sn\:data-disabled\:not-data-loading\:opacity-\(--sn-opacity-disabled\)[data-disabled]:not([data-loading]){opacity:var(--sn-opacity-disabled)}.sn\:data-dragging\:border-focus[data-dragging]{border-color:var(--sn-color-border-focus)}.sn\:data-dragging\:bg-subtle[data-dragging]{background-color:var(--sn-color-bg-subtle)}.sn\:data-ending-style\:h-0[data-ending-style]{height:0}.sn\:data-ending-style\:translate-y-2[data-ending-style]{--tw-translate-y:calc(var(--sn-space-1) * 2);translate:var(--tw-translate-x) var(--tw-translate-y)}.sn\:data-ending-style\:scale-98[data-ending-style]{--tw-scale-x:98%;--tw-scale-y:98%;--tw-scale-z:98%;scale:var(--tw-scale-x) var(--tw-scale-y)}.sn\:data-ending-style\:opacity-0[data-ending-style]{opacity:0}.sn\:data-highlighted\:bg-subtle[data-highlighted]{background-color:var(--sn-color-bg-subtle)}.sn\:data-indeterminate\:border-transparent[data-indeterminate]{border-color:#0000}.sn\:data-indeterminate\:bg-primary[data-indeterminate]{background-color:var(--sn-color-bg-primary)}.sn\:data-invalid\:border-danger[data-invalid]{border-color:var(--sn-color-border-danger)}.sn\:data-invalid\:focus-visible\:outline-danger[data-invalid]:focus-visible{outline-color:var(--sn-color-border-danger)}.sn\:data-limited\:hidden[data-limited]{display:none}.sn\:data-loading\:cursor-progress[data-loading]{cursor:progress}.sn\:data-placeholder\:text-muted[data-placeholder]{color:var(--sn-color-text-muted)}.sn\:data-popup-open\:border-focus[data-popup-open]{border-color:var(--sn-color-border-focus)}.sn\:data-pressed\:border-default[data-pressed]{border-color:var(--sn-color-border-default)}.sn\:data-pressed\:bg-surface[data-pressed]{background-color:var(--sn-color-bg-surface)}.sn\:data-pressed\:text-default[data-pressed]{color:var(--sn-color-text-default)}.sn\:data-starting-style\:h-0[data-starting-style]{height:0}.sn\:data-starting-style\:translate-y-2[data-starting-style]{--tw-translate-y:calc(var(--sn-space-1) * 2);translate:var(--tw-translate-x) var(--tw-translate-y)}.sn\:data-starting-style\:scale-98[data-starting-style]{--tw-scale-x:98%;--tw-scale-y:98%;--tw-scale-z:98%;scale:var(--tw-scale-x) var(--tw-scale-y)}.sn\:data-starting-style\:opacity-0[data-starting-style]{opacity:0}@media (prefers-reduced-motion:reduce){.sn\:motion-reduce\:animate-none{animation:none}.sn\:motion-reduce\:transition-none{transition-property:none}}@media not all and (min-width:40rem){.sn\:max-sm\:flex-col-reverse{flex-direction:column-reverse}.sn\:max-sm\:text-\[16px\]{font-size:16px}:is(.sn\:max-sm\:\*\:h-10>*){height:calc(var(--sn-space-1) * 10)}:is(.sn\:max-sm\:\*\:w-full>*){width:100%}}@media (pointer:coarse){.sn\:pointer-coarse\:hidden{display:none}.sn\:pointer-coarse\:inline{display:inline}}.sn\:\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.sn\:\[\&_svg\]\:size-3 svg{width:calc(var(--sn-space-1) * 3);height:calc(var(--sn-space-1) * 3)}.sn\:\[\&_svg\]\:size-4 svg{width:calc(var(--sn-space-1) * 4);height:calc(var(--sn-space-1) * 4)}.sn\:\[\&_svg\]\:size-5 svg{width:calc(var(--sn-space-1) * 5);height:calc(var(--sn-space-1) * 5)}.sn\:\[\&_svg\]\:size-6 svg{width:calc(var(--sn-space-1) * 6);height:calc(var(--sn-space-1) * 6)}.sn\:\[\&_svg\]\:shrink-0 svg{flex-shrink:0}}:root{--sn-space-0:0px;--sn-space-1:4px;--sn-space-2:8px;--sn-space-3:12px;--sn-space-4:16px;--sn-space-5:20px;--sn-space-6:24px;--sn-space-7:28px;--sn-space-8:32px;--sn-space-10:40px;--sn-space-12:48px;--sn-space-16:64px;--sn-radius-sm:2px;--sn-radius-md:4px;--sn-radius-lg:6px;--sn-radius-full:9999px;--sn-stroke-default:1px;--sn-stroke-focus:2px;--sn-duration-fast:.12s;--sn-duration-normal:.2s;--sn-easing-standard:cubic-bezier(.2, 0, 0, 1);--sn-duration-loop:1s;--sn-opacity-disabled:.45;--sn-font-sans:"IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;--sn-font-mono:"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;--sn-text-display:32px;--sn-text-display--line-height:40px;--sn-text-display--font-weight:600;--sn-text-display--letter-spacing:-.02em;--sn-text-title:20px;--sn-text-title--line-height:28px;--sn-text-title--font-weight:600;--sn-text-title--letter-spacing:-.01em;--sn-text-body:14px;--sn-text-body--line-height:20px;--sn-text-body--font-weight:400;--sn-text-body--letter-spacing:0em;--sn-text-body-strong:14px;--sn-text-body-strong--line-height:20px;--sn-text-body-strong--font-weight:500;--sn-text-body-strong--letter-spacing:0em;--sn-text-label:13px;--sn-text-label--line-height:16px;--sn-text-label--font-weight:500;--sn-text-label--letter-spacing:0em;--sn-text-caption:12px;--sn-text-caption--line-height:16px;--sn-text-caption--font-weight:400;--sn-text-caption--letter-spacing:0em;--sn-text-mono:14px;--sn-text-mono--line-height:20px;--sn-text-mono--font-weight:400;--sn-text-mono--letter-spacing:0em;--sn-text-mono-caption:12px;--sn-text-mono-caption--line-height:16px;--sn-text-mono-caption--font-weight:400;--sn-text-mono-caption--letter-spacing:0em}:root,[data-theme=light]{color-scheme:light;--sn-color-bg-canvas:#f4f6f8;--sn-color-bg-surface:#fff;--sn-color-bg-subtle:#e6eaee;--sn-color-bg-primary:#2340d0;--sn-color-bg-primary-hover:#1b33ae;--sn-color-bg-danger:#c8312b;--sn-color-bg-overlay:#0e121680;--sn-color-text-default:#0e1216;--sn-color-text-muted:#5b6672;--sn-color-text-on-primary:#fff;--sn-color-text-on-danger:#fff;--sn-color-text-danger:#c8312b;--sn-color-border-default:#d5dbe1;--sn-color-border-strong:#8d99a6;--sn-color-border-focus:#2340d0;--sn-color-border-danger:#c8312b;--sn-color-bg-inverse:#0e1216;--sn-color-text-inverse:#fff;--sn-color-bg-success:#16804f;--sn-color-text-on-success:#fff;--sn-color-bg-success-subtle:#eaf7f0;--sn-color-text-success:#0f6640;--sn-color-bg-warning:#e3a43a;--sn-color-text-on-warning:#0e1216;--sn-color-bg-warning-subtle:#fcf5e6;--sn-color-text-warning:#85520a;--sn-color-bg-danger-subtle:#fcedec;--sn-color-border-success:#16804f;--sn-color-border-warning:#a86c12}[data-theme=dark]{color-scheme:dark;--sn-color-bg-canvas:#0e1216;--sn-color-bg-surface:#161b21;--sn-color-bg-subtle:#1e252d;--sn-color-bg-primary:#6e86ff;--sn-color-bg-primary-hover:#8c9fff;--sn-color-bg-danger:#f06a5f;--sn-color-bg-overlay:#0e121680;--sn-color-text-default:#e6eaee;--sn-color-text-muted:#8d99a6;--sn-color-text-on-primary:#0e1216;--sn-color-text-on-danger:#0e1216;--sn-color-text-danger:#f06a5f;--sn-color-border-default:#2a323b;--sn-color-border-strong:#5b6672;--sn-color-border-focus:#6e86ff;--sn-color-border-danger:#f06a5f;--sn-color-bg-inverse:#e6eaee;--sn-color-text-inverse:#0e1216;--sn-color-bg-success:#3db882;--sn-color-text-on-success:#0e1216;--sn-color-bg-success-subtle:#0b2218;--sn-color-text-success:#6bd1a0;--sn-color-bg-warning:#e3a43a;--sn-color-text-on-warning:#0e1216;--sn-color-bg-warning-subtle:#24190a;--sn-color-text-warning:#eec46a;--sn-color-bg-danger-subtle:#2b1311;--sn-color-border-success:#3db882;--sn-color-border-warning:#e3a43a}@keyframes sn-pulse{50%{opacity:.5}}@keyframes sn-spin{to{transform:rotate(360deg)}}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xonic0506/sonic-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Figma-first personal design system (Base UI + Tailwind v4, prebuilt CSS)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"scripts": {
|
|
33
33
|
"tokens": "node scripts/build-tokens.mjs",
|
|
34
34
|
"build:css": "node scripts/build-css.mjs",
|
|
35
|
-
"build:js": "vite build && tsc -p tsconfig.build.json",
|
|
35
|
+
"build:js": "vite build && cp -R src/illustrations dist/ && tsc -p tsconfig.build.json",
|
|
36
36
|
"build": "rm -rf dist && npm run tokens && npm run build:js && npm run build:css",
|
|
37
37
|
"typecheck": "tsc --noEmit",
|
|
38
38
|
"test": "vitest run",
|