sh-ui-cli 0.76.0 → 0.78.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/data/changelog/versions.json +58 -0
- package/data/registry/react/components/code-editor/index.module.tsx +7 -1
- package/data/registry/react/components/code-editor/index.tailwind.tsx +5 -2
- package/data/registry/react/components/code-editor/index.tsx +7 -1
- package/data/registry/react/components/markdown-editor/index.module.tsx +1 -1
- package/data/registry/react/components/markdown-editor/index.tailwind.tsx +1 -1
- package/data/registry/react/components/markdown-editor/index.tsx +1 -1
- package/data/registry/react/components/select/index.module.tsx +20 -9
- package/data/registry/react/components/select/index.tailwind.tsx +21 -8
- package/data/registry/react/components/select/index.tsx +28 -9
- package/data/registry/react/components/sidebar/index.module.tsx +10 -6
- package/data/registry/react/components/sidebar/index.tailwind.tsx +10 -6
- package/data/registry/react/components/sidebar/index.tsx +20 -4
- package/data/registry/react/components/switch/index.tailwind.tsx +1 -1
- package/data/registry/react/components/switch/styles.css +6 -0
- package/data/registry/react/components/switch/styles.module.css +6 -0
- package/data/registry/react/registry.json +2 -1
- package/data/registry/react/tokens-used.json +3 -1
- package/data/tokens/src/semantic.json +16 -2
- package/package.json +1 -1
- package/src/create/architectures/index.js +2 -1
- package/src/create/architectures/mes.js +53 -0
- package/src/create/generator.js +61 -8
- package/src/create/plugins/authJwt.js +10 -0
- package/src/create/plugins/nextIntl.js +36 -2
- package/src/mcp.mjs +66 -1
- package/templates/monorepo/packages/eslint-config/mes.js +82 -0
- package/templates/monorepo/packages/eslint-config/package.json +2 -1
- package/templates/monorepo/packages/ui/ui-core/package.json +1 -1
- package/templates/nextjs-app/_arch/flat/components/layouts/RootLayout.tsx +6 -0
- package/templates/nextjs-app/_arch/fsd/src/app/layouts/RootLayout.tsx +11 -0
- package/templates/nextjs-app/_arch/mes/app/api/proxy/[...path]/route.ts +112 -0
- package/templates/nextjs-app/_arch/mes/app/layout.tsx +16 -0
- package/templates/nextjs-app/_arch/mes/app/sign-in/page.tsx +1 -0
- package/templates/nextjs-app/_arch/mes/eslint.config.js +10 -0
- package/templates/nextjs-app/_arch/mes/src/components/common/.gitkeep +0 -0
- package/templates/nextjs-app/_arch/mes/src/components/common/FallbackBoundary/index.tsx +89 -0
- package/templates/nextjs-app/_arch/mes/src/components/common/PrefetchBoundary/index.tsx +35 -0
- package/templates/nextjs-app/_arch/mes/src/components/layouts/RootLayout.tsx +19 -0
- package/templates/nextjs-app/_arch/mes/src/components/providers/GlobalProvider/index.tsx +23 -0
- package/templates/nextjs-app/_arch/mes/src/components/providers/index.tsx +1 -0
- package/templates/nextjs-app/_arch/mes/src/components/providers/tanstack/QueryClientProvider.tsx +14 -0
- package/templates/nextjs-app/_arch/mes/src/components/providers/tanstack/TanstackDevtoolsProvider.tsx +13 -0
- package/templates/nextjs-app/_arch/mes/src/components/providers/theme/ThemeProvider.tsx +27 -0
- package/templates/nextjs-app/_arch/mes/src/hooks/.gitkeep +0 -0
- package/templates/nextjs-app/_arch/mes/src/hooks/useAppMutation.ts +59 -0
- package/templates/nextjs-app/_arch/mes/src/lib/api/.gitkeep +0 -0
- package/templates/nextjs-app/_arch/mes/src/lib/api/apiTypes.ts +21 -0
- package/templates/nextjs-app/_arch/mes/src/lib/api/clientFetch.ts +40 -0
- package/templates/nextjs-app/_arch/mes/src/lib/api/error.ts +12 -0
- package/templates/nextjs-app/_arch/mes/src/lib/api/errorMessages.ts +37 -0
- package/templates/nextjs-app/_arch/mes/src/lib/api/http.ts +13 -0
- package/templates/nextjs-app/_arch/mes/src/lib/api/observability.ts +20 -0
- package/templates/nextjs-app/_arch/mes/src/lib/api/queryClient.ts +30 -0
- package/templates/nextjs-app/_arch/mes/src/lib/api/serverFetch.ts +59 -0
- package/templates/nextjs-app/_arch/mes/src/lib/config/.gitkeep +0 -0
- package/templates/nextjs-app/_arch/mes/src/lib/test/createTestQueryClient.ts +18 -0
- package/templates/nextjs-app/_arch/mes/src/lib/test/index.ts +2 -0
- package/templates/nextjs-app/_arch/mes/src/lib/test/renderWithProviders.tsx +65 -0
- package/templates/nextjs-app/_arch/mes/src/lib/utils/.gitkeep +0 -0
- package/templates/nextjs-app/_arch/mes/src/lib/utils/formatDate.ts +26 -0
- package/templates/nextjs-app/_arch/mes/src/lib/utils/formatPrice.ts +18 -0
- package/templates/nextjs-app/_arch/mes/src/lib/utils/getQueryClient.ts +14 -0
- package/templates/nextjs-app/_arch/mes/src/pages/sign-in/api.ts +3 -0
- package/templates/nextjs-app/_arch/mes/src/pages/sign-in/components/.gitkeep +0 -0
- package/templates/nextjs-app/_arch/mes/src/pages/sign-in/hooks.ts +3 -0
- package/templates/nextjs-app/_arch/mes/src/pages/sign-in/index.tsx +14 -0
- package/templates/nextjs-app/_arch/mes/src/pages/sign-in/schema.ts +2 -0
- package/templates/nextjs-app/_arch/mes/tsconfig.json +24 -0
- package/templates/nextjs-standalone/_arch/flat/app/globals.css +5 -0
- package/templates/nextjs-standalone/_arch/flat/components/layouts/RootLayout.tsx +6 -0
- package/templates/nextjs-standalone/_arch/fsd/src/app/layouts/RootLayout.tsx +6 -0
- package/templates/nextjs-standalone/_arch/mes/app/api/proxy/[...path]/route.ts +112 -0
- package/templates/nextjs-standalone/_arch/mes/app/globals.css +54 -0
- package/templates/nextjs-standalone/_arch/mes/app/layout.tsx +16 -0
- package/templates/nextjs-standalone/_arch/mes/app/sign-in/page.tsx +1 -0
- package/templates/nextjs-standalone/_arch/mes/eslint.config.js +137 -0
- package/templates/nextjs-standalone/_arch/mes/sh-ui.config.json +22 -0
- package/templates/nextjs-standalone/_arch/mes/src/components/common/.gitkeep +0 -0
- package/templates/nextjs-standalone/_arch/mes/src/components/common/FallbackBoundary/index.tsx +89 -0
- package/templates/nextjs-standalone/_arch/mes/src/components/common/PrefetchBoundary/index.tsx +35 -0
- package/templates/nextjs-standalone/_arch/mes/src/components/layouts/RootLayout.tsx +19 -0
- package/templates/nextjs-standalone/_arch/mes/src/components/providers/GlobalProvider/index.tsx +23 -0
- package/templates/nextjs-standalone/_arch/mes/src/components/providers/index.tsx +1 -0
- package/templates/nextjs-standalone/_arch/mes/src/components/providers/tanstack/QueryClientProvider.tsx +14 -0
- package/templates/nextjs-standalone/_arch/mes/src/components/providers/tanstack/TanstackDevtoolsProvider.tsx +13 -0
- package/templates/nextjs-standalone/_arch/mes/src/components/providers/theme/ThemeProvider.tsx +27 -0
- package/templates/nextjs-standalone/_arch/mes/src/hooks/.gitkeep +0 -0
- package/templates/nextjs-standalone/_arch/mes/src/hooks/useAppMutation.ts +59 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/api/.gitkeep +0 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/api/apiTypes.ts +21 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/api/clientFetch.ts +40 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/api/error.ts +12 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/api/errorMessages.ts +37 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/api/http.ts +13 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/api/observability.ts +20 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/api/queryClient.ts +30 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/api/serverFetch.ts +59 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/config/.gitkeep +0 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/styles/tokens.css +170 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/test/createTestQueryClient.ts +18 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/test/index.ts +2 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/test/renderWithProviders.tsx +65 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/utils/formatDate.ts +26 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/utils/formatPrice.ts +18 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/utils/getQueryClient.ts +14 -0
- package/templates/nextjs-standalone/_arch/mes/src/lib/utils/utils.ts +6 -0
- package/templates/nextjs-standalone/_arch/mes/src/pages/sign-in/api.ts +3 -0
- package/templates/nextjs-standalone/_arch/mes/src/pages/sign-in/components/.gitkeep +0 -0
- package/templates/nextjs-standalone/_arch/mes/src/pages/sign-in/hooks.ts +3 -0
- package/templates/nextjs-standalone/_arch/mes/src/pages/sign-in/index.tsx +14 -0
- package/templates/nextjs-standalone/_arch/mes/src/pages/sign-in/schema.ts +2 -0
- package/templates/nextjs-standalone/_arch/mes/tsconfig.json +39 -0
- package/templates/nextjs-standalone/app/globals.css +5 -0
- package/templates/ui-app-template/src/styles/globals.css +5 -0
|
@@ -2,6 +2,64 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$description": "sh-ui 릴리즈 노트 단일 소스. docs(React)와 showcase(Flutter)가 함께 읽는다. 새 릴리즈마다 맨 앞에 추가.",
|
|
4
4
|
"versions": [
|
|
5
|
+
{
|
|
6
|
+
"version": "0.78.0",
|
|
7
|
+
"date": "2026-05-12",
|
|
8
|
+
"title": "minor — Next.js 호환성 fixes (exports map · relative imports · FOUC · SelectValue label · sidebar tokens)",
|
|
9
|
+
"type": "minor",
|
|
10
|
+
"highlights": [
|
|
11
|
+
"**ui-core `package.json` exports map 수정** — `./components/*: ./src/components/*.tsx` → `./src/components/*/index.tsx`. 폴더+index 패턴에 맞춰 `@workspace/ui-core/components/<name>` import 가 즉시 resolve. v0.77 까지 scaffold 직후 매번 손으로 패치해야 했던 버그.",
|
|
12
|
+
"**registry typecheck 통과** — `markdown-editor` / `sidebar` 의 inter-component 상대 import 에 `/index.tsx` 명시 (node16/nodenext + bundler 둘 다 동작). `sidebar` 의 `PopoverTrigger` render callback 의 implicit `any` 도 명시 타입.",
|
|
13
|
+
"**`SidebarMenuButton` render 자식 `data-active` 보존** — `cloneElement` 가 사용자가 박은 `data-active` 를 sh-ui 자동값으로 덮어쓰던 버그. 이제 자식 명시값이 우선. 자기 디자인 시스템 active state 를 `[data-active]` 셀렉터로 다루는 흐름 가능.",
|
|
14
|
+
"**`SelectValue` children render 패턴 추가** — `<SelectValue>{(v) => labels[v as string]}</SelectValue>` 형태로 value → label 매핑. i18n 라벨 노출에 필수 (예: `light` → `라이트`).",
|
|
15
|
+
"**`CodeEditor` 에 `yaml` / `plaintext` 추가** — `@codemirror/lang-yaml` deps + language enum 확장. YAML convention 파일에 syntax highlighting.",
|
|
16
|
+
"**Sidebar 토큰 1급 노출** — `--sidebar-bg` / `--sidebar-fg` / `--sidebar-border` / `--sidebar-accent` / `--sidebar-accent-fg` 가 `tokens.css` 메인 셋과 globals.css 의 `@theme inline` 매핑에 정식 등재. Tailwind `bg-sidebar-bg` utility 직접 사용 가능.",
|
|
17
|
+
"**RootLayout FOUC 차단 inline script** — next-themes mount 전 첫 paint 에 dark/light class 적용. 다크모드 진입 시 light 한 frame 깜빡임 해소. 모든 arch (fsd/flat/mes) × (nextjs-app/nextjs-standalone) 템플릿에 적용.",
|
|
18
|
+
"**auth-jwt dev bypass flag** — `NEXT_PUBLIC_DEV_AUTH_BYPASS=true` 시 dev 환경에서 proxy.ts 가드 우회. `.env.example` 에 자리표시자 포함, production 빌드에선 무시.",
|
|
19
|
+
"**i18n boilerplate 확장** — `nav` / `app` / `form` 네임스페이스 + `common` 에 create/name/description/empty 추가.",
|
|
20
|
+
"**MCP 가이드 추가** — Base UI 합성 함정 (SSR hydration mismatch, `DropdownMenuItem` 안 `DialogTrigger` 가 안 열리는 패턴) 회피 코드 예시를 sh_ui_* 툴 description 에 박음."
|
|
21
|
+
],
|
|
22
|
+
"url": "https://github.com/sanghyeonKim0201/sh-ui/releases/tag/v0.78.0"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"version": "0.77.1",
|
|
26
|
+
"date": "2026-05-12",
|
|
27
|
+
"title": "security — `sh_ui_create_project` / `sh_ui_add_app` path traversal 차단",
|
|
28
|
+
"type": "patch",
|
|
29
|
+
"highlights": [
|
|
30
|
+
"**path traversal 차단** — MCP 호출자가 `name` 인자에 `../` / 절대경로 / 선행 `.` 을 넣어 부모 디렉토리 밖의 임의 경로를 지정하던 흐름 차단. 영숫자 + `_` / `-` / `.` 만 허용 (단, `.` 로 시작 불가).",
|
|
31
|
+
"**임의 디렉토리 삭제 봉쇄** — `force: true` + 내부 `yes: true` 조합으로 `fs.remove(targetDir)` 가 traversal 경로에 실행되던 흐름을 진입부 검증 + `assertWithin(parent, child)` 가드로 이중 차단.",
|
|
32
|
+
"CLI / MCP 두 경로 모두 `createProject` / `addApp` 진입부에서 일괄 검증 — 호출 표면 어느 쪽으로도 우회 불가.",
|
|
33
|
+
"회귀 가드 — `test/name-validation.test.js` 추가 (traversal, 절대경로, 숨김 디렉토리, 셸 메타문자, NUL 바이트 등 29 케이스)."
|
|
34
|
+
],
|
|
35
|
+
"url": "https://github.com/sanghyeonKim0201/sh-ui/releases/tag/v0.77.1"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"version": "0.77.0",
|
|
39
|
+
"date": "2026-05-11",
|
|
40
|
+
"title": "minor — `--arch mes` 프리셋 — 백오피스용 페이지 격리 구조",
|
|
41
|
+
"type": "minor",
|
|
42
|
+
"highlights": [
|
|
43
|
+
"**`sh-ui-cli create ... --arch mes` 신규 지원** — 스마트팩토리 MES·ERP·관리자 도구처럼 페이지 간 상호작용이 적은 CRUD-heavy 앱을 위한 페이지 격리 프리셋. FSD 의 6 레이어가 과한 백오피스 시나리오 전용.",
|
|
44
|
+
"**페이지 격리 구조** — 각 `src/pages/<name>/` 가 자기완결 슬롯 (index.tsx + components/ + api.ts + hooks.ts + schema.ts + columns.ts). `app/<route>/page.tsx` 는 `export { default } from '@/pages/<name>'` 한 줄 위임. 페이지 끼리는 import 금지 (eslint boundaries 강제).",
|
|
45
|
+
"**`src/pages/sign-in/` 스텁 동봉** — 슬롯 레이아웃을 보여주는 빈 페이지 (동작 X, 폴더 모양만). 새 페이지 추가 = 이 폴더 복사 → 이름 교체.",
|
|
46
|
+
"**tsconfig** — catch-all `@/*` → `./src/*`. 모든 import 가 `@/pages/...`, `@/components/...`, `@/lib/...` 처럼 짧고 일관.",
|
|
47
|
+
"monorepo (`apps/<name>` + `packages/ui/...`) 에서도 `--arch mes` 동작. nextjs-standalone / nextjs-app 두 템플릿 모두 mes overlay 포함."
|
|
48
|
+
],
|
|
49
|
+
"url": "https://github.com/sanghyeonKim0201/sh-ui/releases/tag/v0.77.0"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"version": "0.76.1",
|
|
53
|
+
"date": "2026-05-11",
|
|
54
|
+
"title": "patch — Switch ON 상태 thumb 가시성 (다크모드)",
|
|
55
|
+
"type": "patch",
|
|
56
|
+
"highlights": [
|
|
57
|
+
"**Switch — checked thumb 가 `--primary-foreground` 로 전환** — 다크모드는 `--primary` 가 거의 흰색(`#FAFAFA`)인데 thumb 가 하드코딩 `white` 라 ON 상태에서 thumb 와 트랙이 같은 색으로 묻혀 위치를 알 수 없던 문제 수정.",
|
|
58
|
+
"변종 4종 동기화 — `styles.css` / `styles.module.css` / `index.tailwind.tsx` / docs 복사본.",
|
|
59
|
+
"라이트/다크 양쪽 모두 트랙과 thumb 가 항상 반전 대비를 유지."
|
|
60
|
+
],
|
|
61
|
+
"url": "https://github.com/sanghyeonKim0201/sh-ui/releases/tag/v0.76.1"
|
|
62
|
+
},
|
|
5
63
|
{
|
|
6
64
|
"version": "0.76.0",
|
|
7
65
|
"date": "2026-05-11",
|
|
@@ -9,11 +9,13 @@ import { json } from "@codemirror/lang-json";
|
|
|
9
9
|
import { css as cssLang } from "@codemirror/lang-css";
|
|
10
10
|
import { html } from "@codemirror/lang-html";
|
|
11
11
|
import { markdown } from "@codemirror/lang-markdown";
|
|
12
|
+
import { yaml } from "@codemirror/lang-yaml";
|
|
12
13
|
import styles from "./styles.module.css";
|
|
13
14
|
|
|
14
15
|
import { cn } from "@SH_UI_UTILS@";
|
|
15
16
|
export type CodeEditorLanguage =
|
|
16
17
|
| "text"
|
|
18
|
+
| "plaintext"
|
|
17
19
|
| "javascript"
|
|
18
20
|
| "typescript"
|
|
19
21
|
| "jsx"
|
|
@@ -21,7 +23,8 @@ export type CodeEditorLanguage =
|
|
|
21
23
|
| "json"
|
|
22
24
|
| "css"
|
|
23
25
|
| "html"
|
|
24
|
-
| "markdown"
|
|
26
|
+
| "markdown"
|
|
27
|
+
| "yaml";
|
|
25
28
|
|
|
26
29
|
export interface CodeEditorProps {
|
|
27
30
|
/**
|
|
@@ -79,7 +82,10 @@ function languageExtension(language: CodeEditorLanguage): Extension {
|
|
|
79
82
|
return html();
|
|
80
83
|
case "markdown":
|
|
81
84
|
return markdown();
|
|
85
|
+
case "yaml":
|
|
86
|
+
return yaml();
|
|
82
87
|
case "text":
|
|
88
|
+
case "plaintext":
|
|
83
89
|
default:
|
|
84
90
|
return [];
|
|
85
91
|
}
|
|
@@ -9,11 +9,12 @@ import { json } from "@codemirror/lang-json";
|
|
|
9
9
|
import { css as cssLang } from "@codemirror/lang-css";
|
|
10
10
|
import { html } from "@codemirror/lang-html";
|
|
11
11
|
import { markdown } from "@codemirror/lang-markdown";
|
|
12
|
+
import { yaml } from "@codemirror/lang-yaml";
|
|
12
13
|
|
|
13
14
|
import { cn } from "@SH_UI_UTILS@";
|
|
14
15
|
export type CodeEditorLanguage =
|
|
15
|
-
| "text" | "javascript" | "typescript" | "jsx" | "tsx"
|
|
16
|
-
| "json" | "css" | "html" | "markdown";
|
|
16
|
+
| "text" | "plaintext" | "javascript" | "typescript" | "jsx" | "tsx"
|
|
17
|
+
| "json" | "css" | "html" | "markdown" | "yaml";
|
|
17
18
|
|
|
18
19
|
export interface CodeEditorProps {
|
|
19
20
|
value?: string;
|
|
@@ -42,7 +43,9 @@ function languageExtension(language: CodeEditorLanguage): Extension {
|
|
|
42
43
|
case "css": return cssLang();
|
|
43
44
|
case "html": return html();
|
|
44
45
|
case "markdown": return markdown();
|
|
46
|
+
case "yaml": return yaml();
|
|
45
47
|
case "text":
|
|
48
|
+
case "plaintext":
|
|
46
49
|
default: return [];
|
|
47
50
|
}
|
|
48
51
|
}
|
|
@@ -9,11 +9,13 @@ import { json } from "@codemirror/lang-json";
|
|
|
9
9
|
import { css as cssLang } from "@codemirror/lang-css";
|
|
10
10
|
import { html } from "@codemirror/lang-html";
|
|
11
11
|
import { markdown } from "@codemirror/lang-markdown";
|
|
12
|
+
import { yaml } from "@codemirror/lang-yaml";
|
|
12
13
|
import "./styles.css";
|
|
13
14
|
|
|
14
15
|
import { cn } from "@SH_UI_UTILS@";
|
|
15
16
|
export type CodeEditorLanguage =
|
|
16
17
|
| "text"
|
|
18
|
+
| "plaintext"
|
|
17
19
|
| "javascript"
|
|
18
20
|
| "typescript"
|
|
19
21
|
| "jsx"
|
|
@@ -21,7 +23,8 @@ export type CodeEditorLanguage =
|
|
|
21
23
|
| "json"
|
|
22
24
|
| "css"
|
|
23
25
|
| "html"
|
|
24
|
-
| "markdown"
|
|
26
|
+
| "markdown"
|
|
27
|
+
| "yaml";
|
|
25
28
|
|
|
26
29
|
export interface CodeEditorProps {
|
|
27
30
|
/**
|
|
@@ -79,7 +82,10 @@ function languageExtension(language: CodeEditorLanguage): Extension {
|
|
|
79
82
|
return html();
|
|
80
83
|
case "markdown":
|
|
81
84
|
return markdown();
|
|
85
|
+
case "yaml":
|
|
86
|
+
return yaml();
|
|
82
87
|
case "text":
|
|
88
|
+
case "plaintext":
|
|
83
89
|
default:
|
|
84
90
|
return [];
|
|
85
91
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import ReactMarkdown from "react-markdown";
|
|
5
5
|
import remarkGfm from "remark-gfm";
|
|
6
|
-
import { CodeEditor } from "../code-editor";
|
|
6
|
+
import { CodeEditor } from "../code-editor/index.tsx";
|
|
7
7
|
import styles from "./styles.module.css";
|
|
8
8
|
|
|
9
9
|
import { cn } from "@SH_UI_UTILS@";
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import ReactMarkdown from "react-markdown";
|
|
5
5
|
import remarkGfm from "remark-gfm";
|
|
6
|
-
import { CodeEditor } from "../code-editor";
|
|
6
|
+
import { CodeEditor } from "../code-editor/index.tsx";
|
|
7
7
|
|
|
8
8
|
import { cn } from "@SH_UI_UTILS@";
|
|
9
9
|
export interface MarkdownEditorProps {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import ReactMarkdown from "react-markdown";
|
|
5
5
|
import remarkGfm from "remark-gfm";
|
|
6
|
-
import { CodeEditor } from "../code-editor";
|
|
6
|
+
import { CodeEditor } from "../code-editor/index.tsx";
|
|
7
7
|
import "./styles.css";
|
|
8
8
|
|
|
9
9
|
import { cn } from "@SH_UI_UTILS@";
|
|
@@ -8,24 +8,35 @@ import styles from "./styles.module.css";
|
|
|
8
8
|
import { cn } from "@SH_UI_UTILS@";
|
|
9
9
|
export const Select = BaseSelect.Root;
|
|
10
10
|
|
|
11
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* shadcn 호환 SelectValue. children 으로 value → label 매핑 함수 전달 가능.
|
|
13
|
+
*
|
|
14
|
+
* <SelectValue placeholder="모드">
|
|
15
|
+
* {(v) => ({ light: "라이트", dark: "다크" })[v as string] ?? null}
|
|
16
|
+
* </SelectValue>
|
|
17
|
+
*/
|
|
12
18
|
export function SelectValue({
|
|
13
19
|
placeholder,
|
|
14
20
|
className,
|
|
21
|
+
children,
|
|
15
22
|
...props
|
|
16
|
-
}: {
|
|
23
|
+
}: {
|
|
24
|
+
placeholder?: string;
|
|
25
|
+
className?: string;
|
|
26
|
+
children?: (value: unknown) => React.ReactNode;
|
|
27
|
+
} & Omit<
|
|
17
28
|
React.ComponentPropsWithoutRef<typeof BaseSelect.Value>,
|
|
18
29
|
"children"
|
|
19
30
|
>) {
|
|
20
31
|
return (
|
|
21
32
|
<BaseSelect.Value className={cn(styles.select__value, className)} {...props}>
|
|
22
|
-
{(value) =>
|
|
23
|
-
value
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
33
|
+
{(value) => {
|
|
34
|
+
if (value === null || value === undefined || value === "") {
|
|
35
|
+
return <span className={styles.select__placeholder}>{placeholder}</span>;
|
|
36
|
+
}
|
|
37
|
+
if (children) return children(value);
|
|
38
|
+
return value as React.ReactNode;
|
|
39
|
+
}}
|
|
29
40
|
</BaseSelect.Value>
|
|
30
41
|
);
|
|
31
42
|
}
|
|
@@ -7,18 +7,31 @@ import { Select as BaseSelect } from "@base-ui/react/select";
|
|
|
7
7
|
import { cn } from "@SH_UI_UTILS@";
|
|
8
8
|
export const Select = BaseSelect.Root;
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Select 트리거 안에 현재 선택값을 표시. children 으로 value→label 매핑 함수
|
|
12
|
+
* 전달 가능 (i18n / 다른 표시 텍스트). 미지정 시 value 를 그대로 렌더.
|
|
13
|
+
*/
|
|
14
|
+
export function SelectValue({
|
|
15
|
+
placeholder,
|
|
16
|
+
className,
|
|
17
|
+
children,
|
|
18
|
+
...props
|
|
19
|
+
}: {
|
|
20
|
+
placeholder?: string;
|
|
21
|
+
className?: string;
|
|
22
|
+
children?: (value: unknown) => React.ReactNode;
|
|
23
|
+
} & Omit<
|
|
11
24
|
React.ComponentPropsWithoutRef<typeof BaseSelect.Value>, "children"
|
|
12
25
|
>) {
|
|
13
26
|
return (
|
|
14
27
|
<BaseSelect.Value className={cn("flex-1 text-left overflow-hidden text-ellipsis whitespace-nowrap", className)} {...props}>
|
|
15
|
-
{(value) =>
|
|
16
|
-
value
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
28
|
+
{(value) => {
|
|
29
|
+
if (value === null || value === undefined || value === "") {
|
|
30
|
+
return <span className="text-foreground-subtle">{placeholder}</span>;
|
|
31
|
+
}
|
|
32
|
+
if (children) return children(value);
|
|
33
|
+
return value as React.ReactNode;
|
|
34
|
+
}}
|
|
22
35
|
</BaseSelect.Value>
|
|
23
36
|
);
|
|
24
37
|
}
|
|
@@ -8,24 +8,43 @@ import "./styles.css";
|
|
|
8
8
|
import { cn } from "@SH_UI_UTILS@";
|
|
9
9
|
export const Select = BaseSelect.Root;
|
|
10
10
|
|
|
11
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Select 트리거 안에 현재 선택값을 표시. shadcn 호환 형태.
|
|
13
|
+
*
|
|
14
|
+
* 기본은 raw value 를 그대로 렌더. value 와 label 이 다르면 (예: 다국어 라벨)
|
|
15
|
+
* children 으로 매핑 함수를 전달해 직접 표시할 노드를 만든다.
|
|
16
|
+
*
|
|
17
|
+
* // 1) 기본: value 그대로 표시
|
|
18
|
+
* <SelectValue placeholder="선택" />
|
|
19
|
+
*
|
|
20
|
+
* // 2) value → label 매핑 (i18n)
|
|
21
|
+
* <SelectValue placeholder="모드">
|
|
22
|
+
* {(v) => ({ light: "라이트", dark: "다크" })[v as string] ?? null}
|
|
23
|
+
* </SelectValue>
|
|
24
|
+
*/
|
|
12
25
|
export function SelectValue({
|
|
13
26
|
placeholder,
|
|
14
27
|
className,
|
|
28
|
+
children,
|
|
15
29
|
...props
|
|
16
|
-
}: {
|
|
30
|
+
}: {
|
|
31
|
+
placeholder?: string;
|
|
32
|
+
className?: string;
|
|
33
|
+
/** value 를 표시 노드로 매핑. 미지정 시 value 를 그대로 렌더. */
|
|
34
|
+
children?: (value: unknown) => React.ReactNode;
|
|
35
|
+
} & Omit<
|
|
17
36
|
React.ComponentPropsWithoutRef<typeof BaseSelect.Value>,
|
|
18
37
|
"children"
|
|
19
38
|
>) {
|
|
20
39
|
return (
|
|
21
40
|
<BaseSelect.Value className={cn("sh-ui-select__value", className)} {...props}>
|
|
22
|
-
{(value) =>
|
|
23
|
-
value
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
41
|
+
{(value) => {
|
|
42
|
+
if (value === null || value === undefined || value === "") {
|
|
43
|
+
return <span className="sh-ui-select__placeholder">{placeholder}</span>;
|
|
44
|
+
}
|
|
45
|
+
if (children) return children(value);
|
|
46
|
+
return value as React.ReactNode;
|
|
47
|
+
}}
|
|
29
48
|
</BaseSelect.Value>
|
|
30
49
|
);
|
|
31
50
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { cn } from "@SH_UI_UTILS@";
|
|
5
5
|
import { ChevronRightIcon, PanelLeftIcon } from "lucide-react";
|
|
6
|
-
import { Popover, PopoverContent, PopoverTrigger } from "../popover";
|
|
6
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../popover/index.tsx";
|
|
7
7
|
import styles from "./styles.module.css";
|
|
8
8
|
|
|
9
9
|
const SIDEBAR_COOKIE_NAME = "sidebar_state";
|
|
@@ -643,7 +643,9 @@ export const SidebarMenuButton = React.forwardRef<HTMLButtonElement, SidebarMenu
|
|
|
643
643
|
className);
|
|
644
644
|
|
|
645
645
|
if (render && React.isValidElement(render)) {
|
|
646
|
-
const child = render as React.ReactElement<{ className?: string; children?: React.ReactNode }>;
|
|
646
|
+
const child = render as React.ReactElement<{ className?: string; children?: React.ReactNode; "data-active"?: string | boolean }>;
|
|
647
|
+
const childDataActive = child.props["data-active"];
|
|
648
|
+
const dataActive = childDataActive !== undefined ? childDataActive : resolvedIsActive || undefined;
|
|
647
649
|
return React.cloneElement(
|
|
648
650
|
child,
|
|
649
651
|
{
|
|
@@ -651,7 +653,7 @@ export const SidebarMenuButton = React.forwardRef<HTMLButtonElement, SidebarMenu
|
|
|
651
653
|
...props,
|
|
652
654
|
onClick: handleClick,
|
|
653
655
|
className: cn(child.props.className, cls),
|
|
654
|
-
"data-active":
|
|
656
|
+
"data-active": dataActive,
|
|
655
657
|
} as Record<string, unknown>,
|
|
656
658
|
children ?? child.props.children,
|
|
657
659
|
);
|
|
@@ -724,14 +726,16 @@ export const SidebarMenuSubButton = React.forwardRef<HTMLAnchorElement, SidebarM
|
|
|
724
726
|
className);
|
|
725
727
|
|
|
726
728
|
if (render && React.isValidElement(render)) {
|
|
727
|
-
const child = render as React.ReactElement<{ className?: string; children?: React.ReactNode }>;
|
|
729
|
+
const child = render as React.ReactElement<{ className?: string; children?: React.ReactNode; "data-active"?: string | boolean }>;
|
|
730
|
+
const childDataActive = child.props["data-active"];
|
|
731
|
+
const dataActive = childDataActive !== undefined ? childDataActive : resolvedIsActive || undefined;
|
|
728
732
|
return React.cloneElement(
|
|
729
733
|
child,
|
|
730
734
|
{
|
|
731
735
|
ref,
|
|
732
736
|
...props,
|
|
733
737
|
className: cn(child.props.className, cls),
|
|
734
|
-
"data-active":
|
|
738
|
+
"data-active": dataActive,
|
|
735
739
|
} as Record<string, unknown>,
|
|
736
740
|
children ?? child.props.children,
|
|
737
741
|
);
|
|
@@ -876,7 +880,7 @@ export function SidebarCollapsibleTrigger({
|
|
|
876
880
|
openOnHover
|
|
877
881
|
delay={0}
|
|
878
882
|
closeDelay={150}
|
|
879
|
-
render={(triggerProps) => (
|
|
883
|
+
render={(triggerProps: React.ButtonHTMLAttributes<HTMLButtonElement>) => (
|
|
880
884
|
<button
|
|
881
885
|
{...triggerProps}
|
|
882
886
|
{...props}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { cn } from "@SH_UI_UTILS@";
|
|
5
5
|
import { ChevronRightIcon, PanelLeftIcon } from "lucide-react";
|
|
6
|
-
import { Popover, PopoverContent, PopoverTrigger } from "../popover";
|
|
6
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../popover/index.tsx";
|
|
7
7
|
|
|
8
8
|
const SIDEBAR_COOKIE_NAME = "sidebar_state";
|
|
9
9
|
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
|
@@ -384,7 +384,9 @@ export const SidebarMenuButton = React.forwardRef<HTMLButtonElement, SidebarMenu
|
|
|
384
384
|
const cls = cn(menuButtonBase, menuButtonSize[size], className);
|
|
385
385
|
|
|
386
386
|
if (render && React.isValidElement(render)) {
|
|
387
|
-
const child = render as React.ReactElement<{ className?: string; children?: React.ReactNode }>;
|
|
387
|
+
const child = render as React.ReactElement<{ className?: string; children?: React.ReactNode; "data-active"?: string | boolean }>;
|
|
388
|
+
const childDataActive = child.props["data-active"];
|
|
389
|
+
const dataActive = childDataActive !== undefined ? childDataActive : resolvedIsActive || undefined;
|
|
388
390
|
return React.cloneElement(
|
|
389
391
|
child,
|
|
390
392
|
{
|
|
@@ -392,7 +394,7 @@ export const SidebarMenuButton = React.forwardRef<HTMLButtonElement, SidebarMenu
|
|
|
392
394
|
...props,
|
|
393
395
|
onClick: handleClick,
|
|
394
396
|
className: cn(child.props.className, cls),
|
|
395
|
-
"data-active":
|
|
397
|
+
"data-active": dataActive,
|
|
396
398
|
} as Record<string, unknown>,
|
|
397
399
|
children ?? child.props.children,
|
|
398
400
|
);
|
|
@@ -440,14 +442,16 @@ export const SidebarMenuSubButton = React.forwardRef<HTMLAnchorElement, SidebarM
|
|
|
440
442
|
const cls = cn(menuSubButtonBase, size === "sm" && "text-[length:var(--text-xs)]", className);
|
|
441
443
|
|
|
442
444
|
if (render && React.isValidElement(render)) {
|
|
443
|
-
const child = render as React.ReactElement<{ className?: string; children?: React.ReactNode }>;
|
|
445
|
+
const child = render as React.ReactElement<{ className?: string; children?: React.ReactNode; "data-active"?: string | boolean }>;
|
|
446
|
+
const childDataActive = child.props["data-active"];
|
|
447
|
+
const dataActive = childDataActive !== undefined ? childDataActive : resolvedIsActive || undefined;
|
|
444
448
|
return React.cloneElement(
|
|
445
449
|
child,
|
|
446
450
|
{
|
|
447
451
|
ref,
|
|
448
452
|
...props,
|
|
449
453
|
className: cn(child.props.className, cls),
|
|
450
|
-
"data-active":
|
|
454
|
+
"data-active": dataActive,
|
|
451
455
|
} as Record<string, unknown>,
|
|
452
456
|
children ?? child.props.children,
|
|
453
457
|
);
|
|
@@ -524,7 +528,7 @@ export function SidebarCollapsibleTrigger({ className, size = "md", children, on
|
|
|
524
528
|
openOnHover
|
|
525
529
|
delay={0}
|
|
526
530
|
closeDelay={150}
|
|
527
|
-
render={(triggerProps) => (
|
|
531
|
+
render={(triggerProps: React.ButtonHTMLAttributes<HTMLButtonElement>) => (
|
|
528
532
|
<button {...triggerProps} {...props} type="button" className={cls} data-state={isOpen ? "open" : "closed"}>
|
|
529
533
|
{content}
|
|
530
534
|
</button>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { cn } from "@SH_UI_UTILS@";
|
|
5
5
|
import { ChevronRightIcon, PanelLeftIcon } from "lucide-react";
|
|
6
|
-
import { Popover, PopoverContent, PopoverTrigger } from "../popover";
|
|
6
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../popover/index.tsx";
|
|
7
7
|
import "./styles.css";
|
|
8
8
|
|
|
9
9
|
const SIDEBAR_COOKIE_NAME = "sidebar_state";
|
|
@@ -647,7 +647,16 @@ export const SidebarMenuButton = React.forwardRef<HTMLButtonElement, SidebarMenu
|
|
|
647
647
|
const child = render as React.ReactElement<{
|
|
648
648
|
className?: string;
|
|
649
649
|
children?: React.ReactNode;
|
|
650
|
+
"data-active"?: string | boolean;
|
|
650
651
|
}>;
|
|
652
|
+
// 자식이 명시한 data-active 가 있으면 보존 (사용자가 자기 디자인 시스템의
|
|
653
|
+
// active state 를 data-active 셀렉터로 다루는 경우). 그 외엔 sh-ui 의
|
|
654
|
+
// 자동 추론값 사용.
|
|
655
|
+
const childDataActive = child.props["data-active"];
|
|
656
|
+
const dataActive =
|
|
657
|
+
childDataActive !== undefined
|
|
658
|
+
? childDataActive
|
|
659
|
+
: resolvedIsActive || undefined;
|
|
651
660
|
return React.cloneElement(
|
|
652
661
|
child,
|
|
653
662
|
{
|
|
@@ -655,7 +664,7 @@ export const SidebarMenuButton = React.forwardRef<HTMLButtonElement, SidebarMenu
|
|
|
655
664
|
...props,
|
|
656
665
|
onClick: handleClick,
|
|
657
666
|
className: cn(child.props.className, cls),
|
|
658
|
-
"data-active":
|
|
667
|
+
"data-active": dataActive,
|
|
659
668
|
} as Record<string, unknown>,
|
|
660
669
|
children ?? child.props.children,
|
|
661
670
|
);
|
|
@@ -734,14 +743,21 @@ export const SidebarMenuSubButton = React.forwardRef<HTMLAnchorElement, SidebarM
|
|
|
734
743
|
const child = render as React.ReactElement<{
|
|
735
744
|
className?: string;
|
|
736
745
|
children?: React.ReactNode;
|
|
746
|
+
"data-active"?: string | boolean;
|
|
737
747
|
}>;
|
|
748
|
+
// 자식이 명시한 data-active 우선 (자기 디자인 시스템 호환).
|
|
749
|
+
const childDataActive = child.props["data-active"];
|
|
750
|
+
const dataActive =
|
|
751
|
+
childDataActive !== undefined
|
|
752
|
+
? childDataActive
|
|
753
|
+
: resolvedIsActive || undefined;
|
|
738
754
|
return React.cloneElement(
|
|
739
755
|
child,
|
|
740
756
|
{
|
|
741
757
|
ref,
|
|
742
758
|
...props,
|
|
743
759
|
className: cn(child.props.className, cls),
|
|
744
|
-
"data-active":
|
|
760
|
+
"data-active": dataActive,
|
|
745
761
|
} as Record<string, unknown>,
|
|
746
762
|
children ?? child.props.children,
|
|
747
763
|
);
|
|
@@ -886,7 +902,7 @@ export function SidebarCollapsibleTrigger({
|
|
|
886
902
|
openOnHover
|
|
887
903
|
delay={0}
|
|
888
904
|
closeDelay={150}
|
|
889
|
-
render={(triggerProps) => (
|
|
905
|
+
render={(triggerProps: React.ButtonHTMLAttributes<HTMLButtonElement>) => (
|
|
890
906
|
<button
|
|
891
907
|
{...triggerProps}
|
|
892
908
|
{...props}
|
|
@@ -18,7 +18,7 @@ const switchRoot = cva(
|
|
|
18
18
|
);
|
|
19
19
|
|
|
20
20
|
const switchThumb = cva(
|
|
21
|
-
"block rounded-full bg-white shadow-[var(--shadow-sm)] transition-transform duration-150 ease-out motion-reduce:transition-none forced-colors:[background:ButtonText] forced-colors:data-[checked]:[background:HighlightText] forced-colors:data-[disabled]:[background:GrayText]",
|
|
21
|
+
"block rounded-full bg-white data-[checked]:bg-primary-foreground shadow-[var(--shadow-sm)] transition-transform duration-150 ease-out motion-reduce:transition-none forced-colors:[background:ButtonText] forced-colors:data-[checked]:[background:HighlightText] forced-colors:data-[disabled]:[background:GrayText]",
|
|
22
22
|
{
|
|
23
23
|
variants: {
|
|
24
24
|
size: {
|
|
@@ -74,6 +74,12 @@
|
|
|
74
74
|
transform: translateX(1.125rem);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/* checked 상태에서 thumb 와 트랙(--primary)이 같은 색으로 보이지 않도록
|
|
78
|
+
--primary-foreground 로 전환 (다크모드: primary=near-white → thumb=dark). */
|
|
79
|
+
.sh-ui-switch[data-checked] .sh-ui-switch__thumb {
|
|
80
|
+
background: var(--primary-foreground);
|
|
81
|
+
}
|
|
82
|
+
|
|
77
83
|
/* reduced motion */
|
|
78
84
|
@media (prefers-reduced-motion: reduce) {
|
|
79
85
|
.sh-ui-switch,
|
|
@@ -74,6 +74,12 @@
|
|
|
74
74
|
transform: translateX(1.125rem);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/* checked 상태에서 thumb 와 트랙(--primary)이 같은 색으로 보이지 않도록
|
|
78
|
+
--primary-foreground 로 전환 (다크모드: primary=near-white → thumb=dark). */
|
|
79
|
+
.switch[data-checked] .switch__thumb {
|
|
80
|
+
background: var(--primary-foreground);
|
|
81
|
+
}
|
|
82
|
+
|
|
77
83
|
/* reduced motion */
|
|
78
84
|
@media (prefers-reduced-motion: reduce) {
|
|
79
85
|
.switch,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$description": "컴포넌트별 토큰 의존성 (var(--*) 추출). build-registry-tokens.mjs 가 자동 생성.",
|
|
3
|
-
"$generated": "2026-05-
|
|
3
|
+
"$generated": "2026-05-11T07:02:18.245Z",
|
|
4
4
|
"components": {
|
|
5
5
|
"button": {
|
|
6
6
|
"plain": [
|
|
@@ -1556,6 +1556,7 @@
|
|
|
1556
1556
|
"--border-width-strong",
|
|
1557
1557
|
"--opacity-disabled",
|
|
1558
1558
|
"--primary",
|
|
1559
|
+
"--primary-foreground",
|
|
1559
1560
|
"--primary-hover",
|
|
1560
1561
|
"--ring",
|
|
1561
1562
|
"--shadow-sm"
|
|
@@ -1571,6 +1572,7 @@
|
|
|
1571
1572
|
"--border-width-strong",
|
|
1572
1573
|
"--opacity-disabled",
|
|
1573
1574
|
"--primary",
|
|
1575
|
+
"--primary-foreground",
|
|
1574
1576
|
"--primary-hover",
|
|
1575
1577
|
"--ring",
|
|
1576
1578
|
"--shadow-sm"
|
|
@@ -28,7 +28,14 @@
|
|
|
28
28
|
"foreground": { "$value": "{color.white}", "$type": "color" },
|
|
29
29
|
"hover": { "$value": "{color.red.700}", "$type": "color" }
|
|
30
30
|
},
|
|
31
|
-
"ring": { "$value": "{color.{base}.400}", "$type": "color" }
|
|
31
|
+
"ring": { "$value": "{color.{base}.400}", "$type": "color" },
|
|
32
|
+
"sidebar": {
|
|
33
|
+
"bg": { "$value": "{color.{base}.50}", "$type": "color" },
|
|
34
|
+
"fg": { "$value": "{color.{base}.950}", "$type": "color" },
|
|
35
|
+
"border": { "$value": "{color.{base}.200}", "$type": "color" },
|
|
36
|
+
"accent": { "$value": "{color.{base}.100}", "$type": "color" },
|
|
37
|
+
"accent-fg": { "$value": "{color.{base}.950}", "$type": "color" }
|
|
38
|
+
}
|
|
32
39
|
},
|
|
33
40
|
|
|
34
41
|
"dark": {
|
|
@@ -58,7 +65,14 @@
|
|
|
58
65
|
"foreground": { "$value": "{color.white}", "$type": "color" },
|
|
59
66
|
"hover": { "$value": "{color.red.500}", "$type": "color" }
|
|
60
67
|
},
|
|
61
|
-
"ring": { "$value": "{color.{base}.500}", "$type": "color" }
|
|
68
|
+
"ring": { "$value": "{color.{base}.500}", "$type": "color" },
|
|
69
|
+
"sidebar": {
|
|
70
|
+
"bg": { "$value": "{color.{base}.900}", "$type": "color" },
|
|
71
|
+
"fg": { "$value": "{color.{base}.50}", "$type": "color" },
|
|
72
|
+
"border": { "$value": "{color.{base}.800}", "$type": "color" },
|
|
73
|
+
"accent": { "$value": "{color.{base}.800}", "$type": "color" },
|
|
74
|
+
"accent-fg": { "$value": "{color.{base}.50}", "$type": "color" }
|
|
75
|
+
}
|
|
62
76
|
},
|
|
63
77
|
|
|
64
78
|
"radius": {
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { fsdArch } from './fsd.js';
|
|
2
2
|
import { flatArch } from './flat.js';
|
|
3
|
+
import { mesArch } from './mes.js';
|
|
3
4
|
import { validateArchitectures } from './archSchema.js';
|
|
4
5
|
|
|
5
|
-
export const allArchitectures = [fsdArch, flatArch];
|
|
6
|
+
export const allArchitectures = [fsdArch, flatArch, mesArch];
|
|
6
7
|
|
|
7
8
|
// 모듈 로드 시점에 모든 arch 디스크립터를 schema 로 검증.
|
|
8
9
|
// 누락된 키, 잘못된 형태가 있으면 즉시 에러.
|