@xonic0506/sonic-ui 0.3.0 → 0.4.0

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 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을 씁니다. 절대 좌표 배치는 쓰지 않아요.
@@ -221,11 +238,11 @@ hover, focus는 **컴포넌트 variant로 만들지 않아요.** React prop이
221
238
 
222
239
  | 계층 | 위치 | 기준 | 예 |
223
240
  |---|---|---|---|
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 |
241
+ | **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
242
  | **Pattern** | sonic-ui `src/patterns/` | Core 조합이고 도메인을 모르지만, **두 프로젝트 이상에서 같은 형태로 복사됨** | (아직 없음) |
226
243
  | **Domain** | 각 프로젝트 | 도메인 타입, API, 비즈니스 로직 중 하나라도 앎 | `UserProfileCard`, `ApiKeyList` |
227
244
 
228
- 예외: EmptyState와 ErrorState는 Core 조합이라 원래는 Pattern 후보지만, §8 규칙이 모든 데이터 화면에 요구하는 **시스템 컴포넌트**라서 Core에 둬요.
245
+ 예외: EmptyState, ErrorState, ErrorPage는 Core 조합이라 원래는 Pattern 후보지만, §8 규칙과 모든 프로젝트의 에러 화면이 요구하는 **시스템 컴포넌트**라서 Core에 둬요.
229
246
 
230
247
  판단 순서:
231
248
  1. props에 도메인 타입(`User`, `Order`)이 들어가나요? → **Domain**
@@ -428,19 +445,49 @@ const retryRef = useRef<HTMLButtonElement>(null);
428
445
  ### EmptyState / ErrorState
429
446
 
430
447
  ```tsx
431
- <EmptyState icon={<Inbox />} title="API 키가 없어요" description="키를 만들면 여기에서 사용량을 볼 수 있어요." action={<Button>API 키 만들기</Button>} />
448
+ <EmptyState title="API 키가 없어요" description="키를 만들면 여기에서 사용량을 볼 수 있어요." action={<Button>API 키 만들기</Button>} />
432
449
  <ErrorState title="API 키를 불러오지 못했어요" description="네트워크 연결을 확인하고 다시 시도해 주세요." onRetry={refetch} />
450
+ <EmptyState icon={<Inbox />} title="결과가 없어요" /> // 좁은 곳: 아이콘
433
451
  ```
434
452
 
435
453
  | | EmptyState | ErrorState |
436
454
  |---|---|---|
437
- | 아이콘 | `icon` prop (24, `text/muted`, `bg/subtle` 원 `space/12`) | 기본 `triangle-alert` (`text/danger`), `icon`으로 바꿀 수 있음 |
455
+ | 그림 (기본) | 캐릭터 `empty` 120 (§3.7) | 캐릭터 `error` 120 |
456
+ | 아이콘 (`icon`을 넘기면) | 24, `text/muted`, `bg/subtle` 원 `space/12` | 24, `text/danger` (예: `triangle-alert`), 원은 같음 |
438
457
  | 제목 / 설명 | `body-strong` / `body` + `text/muted`, 가운데 정렬 | 같음 |
439
458
  | 행동 | `action` (보통 primary Button 하나) | `onRetry`가 있으면 secondary Button + `refresh-cw`, 문구 `retryLabel`(기본 "다시 시도") |
440
459
  | 간격 | 요소 사이 `space/4`, 위아래 `space/12`, 좌우 `space/6` | 같음 |
441
460
 
442
461
  에러 문구는 사과하지 않고, 무엇이 실패했고 어떻게 하면 되는지 써요.
443
462
 
463
+ 그림(120)은 카드나 표 안의 빈 상태·에러에 써요. Popover, Select, 좁은 사이드 패널처럼 공간이 작으면 `icon`을 넘겨요. 그림이 있으면 정상 화면보다 높이가 커질 수 있으니, 4가지 상태를 그릴 때 영역 높이를 함께 확인해요.
464
+
465
+ ### ErrorPage
466
+
467
+ ```tsx
468
+ // Next.js app/not-found.tsx
469
+ export default function NotFound() {
470
+ return <ErrorPage status={404} action={<Button render={<NextLink href="/" />}>홈으로 가기</Button>} />;
471
+ }
472
+ ```
473
+
474
+ | prop | 값 | 기본값 |
475
+ |---|---|---|
476
+ | `status` | `404` · `403` · `500` (필수) | — |
477
+ | `title`, `description` | 바꿀 문구 | 상태별 문구 (아래) |
478
+ | `action` | primary Button 하나 (상태별 권장은 아래 표) | 없음 |
479
+
480
+ | status | 그림 | 제목 | 설명 | 권장 action |
481
+ |---|---|---|---|---|
482
+ | 404 | `error-404` | 페이지를 찾을 수 없어요 | 주소가 바뀌었거나 삭제된 페이지예요. 주소를 확인해 주세요. | 홈으로 가기 |
483
+ | 403 | `error-403` | 이 페이지를 볼 권한이 없어요 | 관리자에게 권한을 요청해 주세요. | 홈으로 가기 |
484
+ | 500 | `error-500` | 서버에 문제가 생겼어요 | 잠시 뒤 다시 시도해 주세요. | `refresh-cw` + 다시 시도 (페이지 다시 불러오기) |
485
+
486
+ - 화면 전체를 쓰는 에러예요. 카드 하나가 실패하면 ErrorState, 페이지 자체를 보여 줄 수 없을 때 ErrorPage를 써요.
487
+ - 그림 320(§3.7), 그 아래 오류 코드 `mono-caption` + `text/muted`("오류 코드 404", 문의할 때 쓰도록), 제목 `title`(페이지의 `h1`), 설명 `body` + `text/muted`, 가운데 정렬. 숫자는 그림 안에 있어서 크게 따로 쓰지 않아요.
488
+ - 너비는 부모를 채우고, 위아래 `space/16`, 좌우 `space/6`, 요소 사이 `space/6`(글자 묶음 안 `space/2`).
489
+ - 500은 일시적인 실패일 때가 많아서 홈으로 보내지 않고 그 자리에서 다시 불러오게 해요. Next.js `error.tsx`는 클라이언트 컴포넌트라 `reset`을 연결해요: `<ErrorPage status={500} action={<Button onClick={reset}><RefreshCw />다시 시도</Button>} />`. `reset`이 없으면 `location.reload()`를 써요.
490
+
444
491
  ### Textarea
445
492
 
446
493
  `<Textarea rows={3} invalid disabled />` — Input과 같은 테두리·hover·focus·invalid 규칙이에요. 최소 높이 80(약 3줄), padding `space/3`·`space/2`, 세로로만 크기를 바꿀 수 있어요. Field 안에서 라벨·에러와 함께 써요.
@@ -776,8 +823,9 @@ Sonic 팀은 Figma Pro 요금제라 Code Connect(Organization 이상)를 쓸 수
776
823
  | Dialog | `6:13` | `Dialog`, `DialogTrigger`, `DialogPopup`, `DialogTitle`, `DialogDescription`, `DialogClose`, `DialogFooter` | `src/components/dialog.tsx` |
777
824
  | Field | `31:1543` | `<Field label description error invalid disabled>` + `<Input />` | `src/components/field.tsx` |
778
825
  | Skeleton | `31:1547` | `<Skeleton shape>` | `src/components/skeleton.tsx` |
779
- | EmptyState | `31:1548` | `<EmptyState icon title description action>` | `src/components/empty-state.tsx` |
780
- | ErrorState | `31:1561` | `<ErrorState icon title description onRetry retryLabel>` | `src/components/error-state.tsx` |
826
+ | EmptyState | `92:5905` | `<EmptyState icon title description action>` (`media=illustration`이 기본, `media=icon` → `icon` prop) | `src/components/empty-state.tsx` |
827
+ | ErrorState | `92:5919` | `<ErrorState icon title description onRetry retryLabel>` (`media`는 EmptyState와 같음) | `src/components/error-state.tsx` |
828
+ | ErrorPage | `92:5953` | `<ErrorPage status title description action>` (`status` → 같은 prop, `action` → 넘길지) | `src/components/error-page.tsx` |
781
829
  | Textarea | `44:2239` | `<Textarea invalid disabled placeholder>` | `src/components/textarea.tsx` |
782
830
  | Checkbox | `44:2266` | `<Checkbox checked indeterminate disabled>` (`checked=indeterminate` → `indeterminate`) | `src/components/checkbox.tsx` |
783
831
  | Radio | `44:2281` | `<RadioGroup label>` + `<Radio value disabled>` | `src/components/radio-group.tsx` |
@@ -797,6 +845,7 @@ Sonic 팀은 Figma Pro 요금제라 Code Connect(Organization 이상)를 쓸 수
797
845
  | Toggle Item · Toggle Group | `66:3760` · `66:3761` | `<ToggleGroup multiple>` + `<ToggleGroupItem value disabled>` (`pressed` → 현재 값, `content=icon`이면 `aria-label`) | `src/components/toggle-group.tsx` |
798
846
  | Accordion Item · Accordion | `66:3792` · `66:3793` | `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionPanel` (`open` → 현재 값, `title`/`content` → 자식) | `src/components/accordion.tsx` |
799
847
  | 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` |
848
+ | Illustration (5개) | Foundations `Source illustrations` | 코드에서 직접 쓰지 않음. EmptyState·ErrorState·ErrorPage 안에 들어 있어요(§3.7) | `src/illustrations/*.webp` |
800
849
  | Icon (35개) | Foundations `Source icons` | `lucide-react`의 같은 이름 컴포넌트 (`Icon / chevron-down` → `<ChevronDown />`) | 쓰는 쪽에서 설치 |
801
850
 
802
851
  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 interface EmptyStateProps {
3
- /** lucide 아이콘 (24px로 맞춰져요) */
3
+ /** 없으면 캐릭터 일러스트(120). 좁은 곳에서는 lucide 아이콘을 넘겨요 (24px로 맞춰져요) */
4
4
  icon?: React.ReactNode;
5
5
  title: React.ReactNode;
6
6
  description?: React.ReactNode;
@@ -1,17 +1,19 @@
1
1
  "use client";
2
- import { StateLayout as e } from "./state-layout.js";
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 t } from "react/jsx-runtime";
5
+ import { jsx as n } from "react/jsx-runtime";
5
6
  //#region src/components/empty-state.tsx
6
- function n({ icon: n, title: r, description: i, action: a, className: o }) {
7
- return /* @__PURE__ */ t(e, {
8
- icon: n,
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
- title: r,
11
- description: i,
12
- className: o,
13
- children: a
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 { n as EmptyState };
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,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  export interface ErrorStateProps {
3
- /** 기본값: triangle-alert */
3
+ /** 없으면 캐릭터 일러스트(120). 좁은 곳에서는 <TriangleAlert /> 같은 아이콘을 넘겨요 */
4
4
  icon?: React.ReactNode;
5
5
  title: React.ReactNode;
6
6
  description?: React.ReactNode;
@@ -1,22 +1,24 @@
1
1
  "use client";
2
2
  import { Button as e } from "./button.js";
3
- import { StateLayout as t } from "./state-layout.js";
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 n, TriangleAlert as r } from "lucide-react";
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 = /* @__PURE__ */ i(r, {}), title: s, description: c, onRetry: l, retryLabel: u = "다시 시도", className: d }) {
9
- return /* @__PURE__ */ i(t, {
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(n, {}), u]
21
+ children: [/* @__PURE__ */ i(r, {}), u]
20
22
  })
21
23
  });
22
24
  }
@@ -0,0 +1,7 @@
1
+ export declare const illustrations: {
2
+ empty: string;
3
+ error: string;
4
+ 404: string;
5
+ 403: string;
6
+ 500: string;
7
+ };
@@ -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,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, title: a, description: o, className: s, role: c, children: l }) {
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: c,
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", s),
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 && /* @__PURE__ */ t("span", {
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
- l
32
+ u
27
33
  ]
28
34
  });
29
35
  }
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 { Dialog as x, DialogClose as S, DialogDescription as C, DialogFooter as w, DialogPopup as T, DialogTitle as E, DialogTrigger as D } from "./components/dialog.js";
17
- import { AlertDialog as O, AlertDialogClose as k, AlertDialogDescription as A, AlertDialogFooter as j, AlertDialogPopup as M, AlertDialogTitle as N, AlertDialogTrigger as P } from "./components/alert-dialog.js";
18
- import { Menu as F, MenuItem as I, MenuPopup as L, MenuSeparator as R, MenuTrigger as z } from "./components/menu.js";
19
- import { Popover as B, PopoverClose as V, PopoverDescription as H, PopoverPopup as U, PopoverTitle as W, PopoverTrigger as G } from "./components/popover.js";
20
- import { Tooltip as K } from "./components/tooltip.js";
21
- import { Tab as q, Tabs as J, TabsList as Y, TabsPanel as X } from "./components/tabs.js";
22
- import { Separator as Z } from "./components/separator.js";
23
- import { ToastProvider as Q, useToast as $ } from "./components/toast.js";
24
- import { Badge as ee } from "./components/badge.js";
25
- import { Progress as te } from "./components/progress.js";
26
- import { Link as ne } from "./components/link.js";
27
- import { Table as re, TableBody as ie, TableCell as ae, TableHead as oe, TableHeader as se, TableRow as ce } from "./components/table.js";
28
- import { ToggleGroup as le, ToggleGroupItem as ue } from "./components/toggle-group.js";
29
- import { Accordion as de, AccordionItem as fe, AccordionPanel as pe, AccordionTrigger as me } from "./components/accordion.js";
30
- import { FileDropzone as he, FileList as ge, formatBytes as _e } from "./components/file-upload.js";
31
- export { de as Accordion, fe as AccordionItem, pe as AccordionPanel, me as AccordionTrigger, O as AlertDialog, k as AlertDialogClose, A as AlertDialogDescription, j as AlertDialogFooter, M as AlertDialogPopup, N as AlertDialogTitle, P as AlertDialogTrigger, g as Avatar, ee 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, x as Dialog, S as DialogClose, C as DialogDescription, w as DialogFooter, T as DialogPopup, E as DialogTitle, D as DialogTrigger, y as EmptyState, b as ErrorState, _ as Field, he as FileDropzone, ge as FileList, t as Input, ne as Link, F as Menu, I as MenuItem, L as MenuPopup, R as MenuSeparator, z as MenuTrigger, B as Popover, V as PopoverClose, H as PopoverDescription, U as PopoverPopup, W as PopoverTitle, G as PopoverTrigger, te as Progress, a as Radio, o as RadioGroup, c as Select, Z as Separator, v as Skeleton, s as Switch, q as Tab, re as Table, ie as TableBody, ae as TableCell, oe as TableHead, se as TableHeader, ce as TableRow, J as Tabs, Y as TabsList, X as TabsPanel, l as Text, n as Textarea, Q as ToastProvider, le as ToggleGroup, ue as ToggleGroupItem, K as Tooltip, _e as formatBytes, $ as useToast };
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 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-auto{height:auto}.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\: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\: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\: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\: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)}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xonic0506/sonic-ui",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
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",