@spectrabrain/eds 0.3.1 → 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/AI.md +4 -4
- package/AI_CONTEXT.json +2 -2
- package/CHANGELOG.md +12 -0
- package/CONSUMER_AGENT.md +2 -2
- package/FRONTEND_CONVENTIONS.md +1 -1
- package/QUICKSTART.md +1 -1
- package/README.md +4 -6
- package/TAILWIND_V4.md +1 -3
- package/TOKEN_CONTEXT.md +2 -18
- package/consumer/generate-tailwind.mjs +0 -30
- package/consumer/scan-classes.mjs +9 -19
- package/dist/components/Button/README.md +2 -4
- package/dist/components/Button/spec.json +6208 -5
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +6284 -381
- package/dist/index.mjs +6285 -382
- package/dist/tokens.css +0 -30
- package/dist/tokens.d.mts +1 -1
- package/dist/tokens.d.ts +1 -1
- package/dist/tokens.js +0 -300
- package/dist/tokens.json +0 -360
- package/dist/tokens.mjs +0 -300
- package/llms.txt +1 -1
- package/package.json +3 -2
package/AI.md
CHANGED
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
## 공개 범위
|
|
6
6
|
|
|
7
|
-
- light theme, `AI_CONTEXT.json`의 `components`에 있는 컴포넌트(현재 `Button`), 공개 semantic color·typography
|
|
8
|
-
- 패키지는 Tailwind preset·plugin을 export하지 않습니다. `eds sync`는 공개 semantic token alias를 `src/styles/eds-tokens.css`에 추가합니다.
|
|
9
|
-
- dark theme과 목록 밖 컴포넌트는 지원 범위 밖입니다. EDS component가 없거나 필요한 prop·variant·state·slot contract가 맞지 않으면 소비처에서 로컬 UI를 구현하고, 공개 token
|
|
7
|
+
- light theme, `AI_CONTEXT.json`의 `components`에 있는 컴포넌트(현재 `Button`), 공개 semantic color·typography token과 token runtime API(`@spectrabrain/eds/tokens`)를 제공합니다.
|
|
8
|
+
- 패키지는 Tailwind preset·plugin을 export하지 않습니다. `eds sync`는 공개 semantic token alias를 `src/styles/eds-tokens.css`에 추가합니다. spacing·radius token은 제공하지 않으며, 해당 값에는 Tailwind CSS v4 기본 utility를 권장합니다(`TOKEN_CONTEXT.md`).
|
|
9
|
+
- dark theme과 목록 밖 컴포넌트는 지원 범위 밖입니다. EDS component가 없거나 필요한 prop·variant·state·slot contract가 맞지 않으면 소비처에서 로컬 UI를 구현하고, 색상·typography에는 공개 token을 사용합니다.
|
|
10
10
|
- CSS 진입점 구성은 `CONSUMER_AGENT.md` 「font 정책」을 따릅니다.
|
|
11
11
|
|
|
12
12
|
## 사용 경계
|
|
13
13
|
|
|
14
14
|
- 문서·`spec.json`·`tokens.json`에 있는 API·prop·variant·token·export 경로만 씁니다. component 여부와 사용 계약은 `AI_CONTEXT.json.components`, component README, TypeScript contract로 확인합니다. 아이콘 이름 확인이나 기계 판독 계약이 필요할 때만 `spec.json`을 읽습니다. contract가 맞지 않으면 `QUICKSTART.md`의 컴포넌트 선택 기준에 따라 소비처 로컬 UI로 분기합니다.
|
|
15
15
|
- EDS 컴포넌트의 native element·accessible name·keyboard 동작은 그대로 둡니다. icon-only Button에는 비어 있지 않은 `aria-label`(또는 `aria-labelledby`)을 지정합니다.
|
|
16
|
-
-
|
|
16
|
+
- Button 이름 슬롯은 `ButtonIconName`이 제공하는 `lucide-react` 아이콘 이름과 alias를 받습니다. custom 아이콘은 ReactElement 슬롯을 사용합니다. 전체 계약은 `dist/components/Button/README.md` 「Layout과 아이콘」에 있습니다.
|
|
17
17
|
|
|
18
18
|
## 문서와 manifest
|
|
19
19
|
|
package/AI_CONTEXT.json
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"specifier": "@spectrabrain/eds/TOKEN_CONTEXT.md",
|
|
31
31
|
"kind": "token-selection",
|
|
32
32
|
"required": false,
|
|
33
|
-
"when": "
|
|
33
|
+
"when": "Choose an EDS color or typography token, or spacing/radius utilities outside an EDS component"
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
"file": "TAILWIND_V4.md",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"specifier": "@spectrabrain/eds/components/{name}/README.md",
|
|
59
59
|
"kind": "component-guide",
|
|
60
60
|
"required": false,
|
|
61
|
-
"when": "A requested UI may fit an EDS component; read its usage context and selection guidance before deciding. If selected, follow its props and accessibility contract
|
|
61
|
+
"when": "A requested UI may fit an EDS component; read its usage context and selection guidance before deciding. If selected, follow its props and accessibility contract."
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
"file": "dist/components/{name}/spec.json",
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @spectrabrain/eds
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 863888b: 소비처 조치: 없습니다.
|
|
8
|
+
|
|
9
|
+
Button 이름 슬롯에서 설치된 `lucide-react`의 모든 아이콘 component 이름과 alias를 사용할 수 있습니다. custom 아이콘의 ReactElement 슬롯은 그대로 지원합니다.
|
|
10
|
+
|
|
11
|
+
- 0a3ed23: 소비처 조치: `p-eds-spacing-*`·`rounded-eds-radius-*`와 spacing·radius용 `cssVar()` 호출을 `p-4`·`rounded-lg` 같은 Tailwind CSS v4 기본 utility로 바꿉니다. Tailwind CSS를 쓰지 않는 화면은 기존 CSS 규칙을 따릅니다.
|
|
12
|
+
|
|
13
|
+
Breaking change: 소비처용 semantic spacing·radius token, CSS 변수, Tailwind 별칭과 TypeScript 이름을 제거합니다.
|
|
14
|
+
|
|
3
15
|
## 0.3.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/CONSUMER_AGENT.md
CHANGED
|
@@ -81,7 +81,7 @@ EDS CLI는 가장 가까운 lockfile(현재 디렉터리부터 git 루트까지)
|
|
|
81
81
|
|
|
82
82
|
sync는 모든 변경을 먼저 계산하고, 계산 중 하나라도 실패하면 어떤 파일도 바꾸지 않습니다. 쓰는 내용은 다음과 같습니다.
|
|
83
83
|
|
|
84
|
-
1. `src/styles/eds-tokens.css`를 생성하고, Tailwind root의 마지막 Tailwind import 바로 다음 줄에 `@import "@spectrabrain/eds/styles.css";`와 생성 CSS의 상대 경로 `@import`를 추가합니다. 이미 있는 import는 다시 추가하지 않습니다. 생성 CSS의 `@theme inline`에는 공개 color
|
|
84
|
+
1. `src/styles/eds-tokens.css`를 생성하고, Tailwind root의 마지막 Tailwind import 바로 다음 줄에 `@import "@spectrabrain/eds/styles.css";`와 생성 CSS의 상대 경로 `@import`를 추가합니다. 이미 있는 import는 다시 추가하지 않습니다. 생성 CSS의 `@theme inline`에는 공개 color alias와 `--font-sans: var(--eds-typography-body1-fontFamily);`가 들어갑니다. Typography utility도 함께 생성됩니다. root CSS 예시는 `TAILWIND_V4.md`에 있습니다.
|
|
85
85
|
2. `src/` 아래 JS·TS 파일에서 `eds-tokens.css`를 import하는 줄을 제거합니다. Tailwind는 JS에서 import한 CSS를 compile하지 않기 때문입니다.
|
|
86
86
|
3. `AGENTS.md` managed block을 넣거나 갱신합니다.
|
|
87
87
|
4. `CLAUDE.md`가 있으면 `@AGENTS.md`, `CLAUDE.md` 없이 `.claude/CLAUDE.md`가 있으면 `@../AGENTS.md`, `GEMINI.md`가 있으면 `@./AGENTS.md` import를 `<!-- EDS:CLAUDE:BEGIN/END -->`·`<!-- EDS:GEMINI:BEGIN/END -->` marker로 감싸 파일 끝에 한 번 추가합니다. sync는 이 marker로 import를 찾으므로 marker와 import를 함께 유지합니다. 파일이 없으면 만들지 않고, `AGENTS.md`와 같은 파일(symlink)이면 추가하지 않습니다.
|
|
@@ -117,7 +117,7 @@ EDS text style은 font family `Pretendard`를 참조하며, 이 family는 `@spec
|
|
|
117
117
|
| `missing:`·`stale:`·`legacy:`(생성 CSS, root CSS import, `AGENTS.md` block, `CLAUDE.md`·`GEMINI.md` import) | `npm run sync:eds`로 고칩니다. `sync:eds`가 등록되지 않았으면 `eds doctor`가 출력한 `init` 명령을 실행합니다. 이 명령이 script를 등록하고 sync합니다. |
|
|
118
118
|
| `missing:` EDS font import(Tailwind root가 없는 저장소) | 앱 진입점에서 `@spectrabrain/eds/styles.css`를 import합니다. 이 경우 sync는 CSS를 고치지 않습니다. |
|
|
119
119
|
| `scripts:` | 등록되지 않았으면 「첫 setup 절차」의 `init`으로 등록합니다(init이 sync까지 실행합니다). 같은 이름의 다른 script이면 init이 덮어쓰지 않으므로, 그 script가 `eds sync`·`eds doctor`를 실행하도록 고치거나 이름을 바꾼 뒤 init을 실행합니다. |
|
|
120
|
-
| `unknown: <파일:줄> <class>` | 공개 token이 없는 `eds-*` class입니다. Tailwind는 이런 class를 조용히 버리므로 `src/styles/eds-tokens.css`에 있는 class로 고칩니다. class
|
|
120
|
+
| `unknown: <파일:줄> <class>` | 공개 token이 없는 `eds-*` class입니다. Tailwind는 이런 class를 조용히 버리므로 `src/styles/eds-tokens.css`에 있는 class로 고칩니다. EDS class는 color token의 `<utility>-eds-<이름>`과 typography utility `eds-typography-<style>`입니다. padding·margin·gap·radius에는 Tailwind CSS v4 기본 utility를 씁니다. |
|
|
121
121
|
| `invalid:` | `AGENTS.md`의 EDS marker가 중복되거나 한쪽만 있습니다. sync는 이 상태를 고치지 않습니다. 출력에 적힌 줄에서 BEGIN 한 줄과 그 뒤의 END 한 줄만 남기고 나머지 marker 줄을 지운 뒤 sync를 다시 실행합니다. |
|
|
122
122
|
|
|
123
123
|
`npm run eds:doctor -- --warn`과 `EDS_DOCTOR=warn`은 같은 출력에 warn mode 경고를 더하고 exit 0으로 끝나며, `EDS_DOCTOR=off`는 출력 없이 exit 0으로 끝납니다. 이 설정은 hook을 잠시 풀어야 할 때 사용자가 쓰는 것이며, 이 상태의 exit 0은 완료가 아닙니다.
|
package/FRONTEND_CONVENTIONS.md
CHANGED
|
@@ -25,7 +25,7 @@ EVA 서비스의 Vite + React 프론트엔드 규칙입니다. `eds align`은
|
|
|
25
25
|
| client-state | `zustand` 5 | `redux`, `@reduxjs/toolkit`, `jotai`, `recoil`, `mobx` | `entities/<domain>/stores`에 둡니다. 저장이 필요하면 `persist`와 `partialize`를 씁니다. |
|
|
26
26
|
| form | `useState` 또는 Context + `useReducer` | `react-hook-form`, `formik` | 단순한 form은 `useState`, 여러 단계 form은 feature의 `lib/<Name>FormContext.tsx`에 Context + `useReducer`를 둡니다. |
|
|
27
27
|
| validation | TypeScript 타입과 검증 함수 | `zod`, `yup`, `valibot` | 검증 함수는 화면에 표시할 오류 문구를 돌려줍니다. backend 코드가 import하는 validation 라이브러리는 패키지를 유지하고, 프론트엔드 코드만 검증 함수로 옮깁니다. |
|
|
28
|
-
| styling | Tailwind CSS 4 + EDS token | `styled-components`, `@emotion/*`, `sass`, CSS Modules | 스타일은 `className`으로 쓰고 전역 CSS는 `app/styles/index.css` 하나에 둡니다. |
|
|
28
|
+
| styling | Tailwind CSS 4 + EDS color·typography token | `styled-components`, `@emotion/*`, `sass`, CSS Modules | spacing·radius에는 Tailwind CSS v4 기본 utility를 씁니다. 스타일은 `className`으로 쓰고 전역 CSS는 `app/styles/index.css` 하나에 둡니다. |
|
|
29
29
|
| ui-kit | EDS `Button` + shadcn/ui(Radix) | `@mui/material`, `@chakra-ui/react`, `antd`, `@mantine/core` | 버튼은 EDS `Button`, 그 밖의 UI 요소는 `shared/ui`의 shadcn/ui 컴포넌트를 씁니다. |
|
|
30
30
|
| icon | `lucide-react` | `react-icons`, `@heroicons/react`, `@fortawesome/*` | EDS `Button`의 아이콘은 `dist/components/Button/README.md` 「Layout과 아이콘」의 슬롯 규칙을 따릅니다. `lucide-react`는 EDS package root `package.json`의 `dependencies["lucide-react"]`와 같은 버전으로 선언합니다. |
|
|
31
31
|
| toast | `sonner` | `react-toastify`, `react-hot-toast` | `app/App.tsx`에 `<Toaster position="top-right" richColors />`를 한 번 둡니다. |
|
package/QUICKSTART.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
1. 사용자의 명시적 요청에 따르고 접근성·보안·framework 제약을 지킵니다. 그 안에서 문서화된 소비처 제품 요구를 우선합니다. 이를 충족하는 같은 역할의 EDS component(현재 `Button`)가 있고 공개 contract도 맞으면 쓰고, 아니면 소비처 로컬 UI를 씁니다.
|
|
14
14
|
2. `AI_CONTEXT.json.components`의 후보를 확인하고, 요청에 맞는지 판단하기 전에 component `README.md`의 사용 맥락·선택 기준을 읽습니다. 필요한 prop·variant·state·slot이 README와 TypeScript contract에 모두 맞아야 합니다. 후보가 없거나 맞지 않으면 로컬 UI를 쓰고, `spec.json`은 아이콘 이름이나 기계 판독 계약 확인에만 씁니다.
|
|
15
|
-
3. 색상·typography
|
|
15
|
+
3. 색상·typography는 EDS token을 씁니다. sync한 Tailwind v4 root에서는 `text-eds-fg-*`·`bg-eds-bg-*`·`border-eds-stroke-*`·`eds-typography-*`, 그 밖에는 `var(--eds-color-*)`·`var(--eds-typography-*)` 또는 `cssVar()`를 씁니다. padding·margin·gap·radius에는 Tailwind v4 기본(`p-4`·`m-2`·`gap-3`·`rounded-lg`)을 권장합니다. EDS spacing·radius token은 없으며, Tailwind v4가 없으면 소비처 CSS 규칙을 따릅니다. `TOKEN_CONTEXT.md`를 따릅니다.
|
|
16
16
|
4. raw 색상·typography 값, 비공개 CSS variable, 패키지 비공개 경로는 쓰지 않습니다. EDS component의 `className`은 바깥 배치에만 씁니다.
|
|
17
17
|
5. Tailwind를 쓰는 저장소에서는 EDS 밖 요소도 `className`으로 쓰고, `index.css` 같은 전역 CSS에 컴포넌트별 규칙을 추가하지 않습니다.
|
|
18
18
|
|
package/README.md
CHANGED
|
@@ -24,11 +24,11 @@ npx @spectrabrain/eds init
|
|
|
24
24
|
## 현재 제공 범위
|
|
25
25
|
|
|
26
26
|
- foreground, background, stroke 역할의 semantic color token을 제공합니다.
|
|
27
|
-
- 소비처
|
|
27
|
+
- 소비처 padding·margin·gap·radius token은 제공하지 않습니다. Tailwind CSS v4를 쓰는 앱에는 기본 utility(예: `p-4`, `rounded-lg`) 사용을 권장합니다.
|
|
28
28
|
- Display, Heading, Title, Body, Caption semantic text style을 제공합니다. 각 style은 font family, weight, size, line height, letter spacing token으로 구성합니다.
|
|
29
29
|
- `styles.css`에서 사용할 수 있는 Pretendard Variable v1.3.9 webfont를 제공합니다.
|
|
30
30
|
- 자동완성을 지원하는 TypeScript token API와 CSS custom property를 제공합니다.
|
|
31
|
-
- React `Button` 컴포넌트를 제공합니다.
|
|
31
|
+
- React `Button` 컴포넌트를 제공합니다. 이름 슬롯은 설치된 `lucide-react`의 모든 아이콘 이름과 alias를 지원합니다.
|
|
32
32
|
- 소비처 setup용 `eds` CLI(`npx @spectrabrain/eds init`, `npm run sync:eds`, `npm run eds:doctor`)를 제공합니다.
|
|
33
33
|
- Vite + React 프로토타입을 EVA 프론트엔드 컨벤션에 맞추는 일회성 명령 `npx @spectrabrain/eds align`과 컨벤션 문서를 제공합니다.
|
|
34
34
|
|
|
@@ -49,7 +49,7 @@ export function SaveButton() {
|
|
|
49
49
|
}
|
|
50
50
|
~~~
|
|
51
51
|
|
|
52
|
-
허용 role·variant 조합, `neutral/link`의 `href` 필수 조건, 이름
|
|
52
|
+
허용 role·variant 조합, `neutral/link`의 `href` 필수 조건, 이름 아이콘과 ReactElement 슬롯, 접근성·loading 동작은 설치된 버전의 `@spectrabrain/eds/components/Button/README.md`와 `@spectrabrain/eds/components/Button/spec.json`(package root의 `dist/components/Button/`)이 기준입니다.
|
|
53
53
|
|
|
54
54
|
## 토큰 사용
|
|
55
55
|
|
|
@@ -63,8 +63,6 @@ const token: SemanticTokenName = "color-fg-brand-contrast";
|
|
|
63
63
|
const color = cssVar(token); // var(--eds-color-fg-brand-contrast)
|
|
64
64
|
~~~
|
|
65
65
|
|
|
66
|
-
`spacing-0.5`처럼 소수점이 있는 public 이름은 `cssVar("spacing-0.5")`로 전달합니다. 반환되는 CSS reference는 `var(--eds-spacing-0\.5)`처럼 점을 escape합니다. Tailwind CSS v4에서는 `p-eds-spacing-0-5`, `rounded-eds-radius-1` 같은 CSS-safe alias를 사용합니다.
|
|
67
|
-
|
|
68
66
|
TypeScript의 `moduleResolution`이 `node`(node10), `node16` 또는 `bundler`인 소비처에서도 `@spectrabrain/eds/tokens`의 타입을 사용할 수 있습니다.
|
|
69
67
|
|
|
70
68
|
역할에 맞는 exact token이 없을 때 가까운 공개 token을 고르는 순서는 [TOKEN_CONTEXT.md](TOKEN_CONTEXT.md)에 있습니다. 그래도 없으면 임의 색상값을 만들지 않고 디자인 시스템 담당자에게 요청합니다.
|
|
@@ -73,7 +71,7 @@ TypeScript의 `moduleResolution`이 `node`(node10), `node16` 또는 `bundler`인
|
|
|
73
71
|
|
|
74
72
|
## Tailwind CSS v4에서 token 사용
|
|
75
73
|
|
|
76
|
-
EDS는 Tailwind preset·plugin을 제공하지 않습니다. Tailwind CSS v4 저장소에서는 `npm run sync:eds`가 `tokens.json`에서 `src/styles/eds-tokens.css`를 생성해 `@import "tailwindcss"`가 있는 Tailwind root CSS에 연결합니다. 이 파일에서 `text-eds-fg-*`, `bg-eds-bg-*`, `border-eds-stroke-*`, `eds-typography
|
|
74
|
+
EDS는 Tailwind preset·plugin을 제공하지 않습니다. Tailwind CSS v4 저장소에서는 `npm run sync:eds`가 `tokens.json`에서 `src/styles/eds-tokens.css`를 생성해 `@import "tailwindcss"`가 있는 Tailwind root CSS에 연결합니다. 이 파일에서 `text-eds-fg-*`, `bg-eds-bg-*`, `border-eds-stroke-*`, `eds-typography-*` class를 사용할 수 있습니다. padding·margin·gap·radius에는 Tailwind CSS v4 기본 utility를 씁니다. 생성된 `@theme inline`에는 `--font-sans: var(--eds-typography-body1-fontFamily);`도 들어가므로 Tailwind의 기본 sans font가 Pretendard가 됩니다. 설정 방법은 [Tailwind CSS v4 token 설정 가이드](./TAILWIND_V4.md)를 확인합니다.
|
|
77
75
|
|
|
78
76
|
## Text style 사용
|
|
79
77
|
|
package/TAILWIND_V4.md
CHANGED
|
@@ -66,8 +66,6 @@ sync는 설치된 package의 공개 `@spectrabrain/eds/tokens.json`에서 token
|
|
|
66
66
|
/* Generated from @spectrabrain/eds@<version>. Do not edit manually. */
|
|
67
67
|
@theme inline {
|
|
68
68
|
--color-eds-fg-brand: var(--eds-color-fg-brand);
|
|
69
|
-
--spacing-eds-spacing-0-5: var(--eds-spacing-0\.5);
|
|
70
|
-
--radius-eds-radius-1: var(--eds-radius-1);
|
|
71
69
|
--font-sans: var(--eds-typography-body1-fontFamily);
|
|
72
70
|
}
|
|
73
71
|
|
|
@@ -81,7 +79,7 @@ sync는 설치된 package의 공개 `@spectrabrain/eds/tokens.json`에서 token
|
|
|
81
79
|
```
|
|
82
80
|
|
|
83
81
|
- `--font-sans`는 `@theme inline`의 마지막 줄이며 Tailwind의 기본 sans font를 EDS body1 font family로 바꿉니다.
|
|
84
|
-
-
|
|
82
|
+
- padding·margin·gap·radius에는 Tailwind CSS v4 기본 utility를 씁니다. 예: `p-4`, `m-2`, `gap-3`, `rounded-lg`. EDS token 별칭은 색상과 typography에만 생성합니다. 선택 기준은 `TOKEN_CONTEXT.md`를 따릅니다.
|
|
85
83
|
- `@theme`의 EDS alias는 sync가 생성한 `var(--eds-*)` 참조만 두고, EDS를 업데이트할 때마다 `npm run sync:eds`로 다시 생성합니다.
|
|
86
84
|
- `eds-tokens.css`는 `@theme`·`@utility`를 담으므로 Tailwind root CSS에서만 import합니다. `@spectrabrain/eds/styles.css`와 `eds-tokens.css`는 각각 한 곳에서만 import합니다.
|
|
87
85
|
- `src/styles/eds-tokens.css`는 생성물이지만 저장소에 commit합니다. install은 이 파일을 만들지 않으므로, 파일이 없으면 Tailwind root의 `@import`가 깨지고, `pretypecheck`·`prebuild` hook(yarn berry는 `typecheck`·`build` 앞의 `eds doctor`)과 `--print-ci` CI job의 `eds doctor`가 `missing:`으로 실패합니다.
|
package/TOKEN_CONTEXT.md
CHANGED
|
@@ -90,25 +90,9 @@ import { cssVar } from "@spectrabrain/eds/tokens";
|
|
|
90
90
|
|
|
91
91
|
## Spacing과 radius
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
- spacing: `spacing-none`, `spacing-0.5`, `spacing-1`, `spacing-1.5`, `spacing-2`, `spacing-2.5`, `spacing-3`, `spacing-3.5`, `spacing-4`, `spacing-4.5`, `spacing-5`, `spacing-6`, `spacing-7`, `spacing-7.5`, `spacing-8`, `spacing-9`, `spacing-10`, `spacing-11`, `spacing-12`
|
|
96
|
-
- radius: `radius-none`, `radius-1`, `radius-2`, `radius-3`, `radius-4`, `radius-5`, `radius-6`, `radius-7`, `radius-8`, `radius-9`, `radius-10`
|
|
97
|
-
|
|
98
|
-
EDS와 sync한 Tailwind CSS v4 root가 있는 저장소에서는 CSS-safe alias를 사용합니다. `spacing-0.5`는 `p-eds-spacing-0-5`, `radius-1`은 `rounded-eds-radius-1`처럼 씁니다. `0.5`·`1.5`·`2.5`·`3.5`·`4.5`·`7.5`의 점은 alias에서 `-`로 바뀝니다.
|
|
99
|
-
|
|
100
|
-
Tailwind CSS v4 alias를 사용하지 않는 저장소에서는 `@spectrabrain/eds/tokens`의 `SemanticTokenName` 자동완성과 `cssVar()`를 사용합니다. public 이름은 `spacing-0.5`로 전달하고, CSS reference에서만 점이 escape됩니다.
|
|
101
|
-
|
|
102
|
-
```tsx
|
|
103
|
-
import { cssVar } from "@spectrabrain/eds/tokens";
|
|
104
|
-
|
|
105
|
-
<div style={{ padding: cssVar("spacing-0.5"), borderRadius: cssVar("radius-1") }}>…</div>;
|
|
106
|
-
// var(--eds-spacing-0\.5), var(--eds-radius-1)
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
직접 CSS를 쓸 때도 `tokens.json`의 `tokens.<name>.$extensions.eds.cssVariable` mapping을 따릅니다. CSS custom property 선언과 `var()` reference에서만 `.`을 escape하며, public token 이름은 바꾸지 않습니다.
|
|
93
|
+
padding, margin, gap, radius에는 Tailwind CSS v4 기본 utility를 권장합니다(예: `p-4`, `m-2`, `gap-3`, `rounded-lg`). EDS는 spacing·radius token과 utility를 제공하지 않습니다. Tailwind CSS v4를 쓰지 않는 소비처는 기존 CSS 규칙을 따릅니다.
|
|
110
94
|
|
|
111
95
|
## 확인 목록
|
|
112
96
|
|
|
113
|
-
-
|
|
97
|
+
- 공개 CSS variable은 설치된 `tokens.json`의 `cssVariable` mapping을 따릅니다. `eds doctor`는 Tailwind CSS v4 root가 있을 때만 `eds-*` class를 검사하고, typecheck는 `cssVar()` 인자를 검사합니다.
|
|
114
98
|
- typography는 preset 하나(`eds-typography-*` class 또는 같은 preset의 변수 다섯 개)로 지정합니다.
|
|
@@ -11,10 +11,6 @@ const propertyNames = [
|
|
|
11
11
|
|
|
12
12
|
export const fontSansStyleName = "body1";
|
|
13
13
|
|
|
14
|
-
function safeTailwindAlias(name) {
|
|
15
|
-
return "eds-" + name.replace(/\./g, "-");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
14
|
function cssVariableForToken(manifest, name) {
|
|
19
15
|
const cssVariable = manifest.tokens?.[name]?.$extensions?.eds?.cssVariable;
|
|
20
16
|
if (typeof cssVariable === "string") {
|
|
@@ -24,27 +20,9 @@ function cssVariableForToken(manifest, name) {
|
|
|
24
20
|
return "--eds-" + name.replace(/\./g, "\\.");
|
|
25
21
|
}
|
|
26
22
|
|
|
27
|
-
function collectDimensionAliases(manifest, prefix) {
|
|
28
|
-
const aliases = new Map();
|
|
29
|
-
|
|
30
|
-
for (const name of Object.keys(manifest.tokens ?? {}).filter((entry) => entry.startsWith(prefix))) {
|
|
31
|
-
const alias = safeTailwindAlias(name);
|
|
32
|
-
const existing = aliases.get(alias);
|
|
33
|
-
if (existing !== undefined && existing !== name) {
|
|
34
|
-
throw new Error(`Tailwind alias collision: ${existing} and ${name} both map to ${alias}.`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
aliases.set(alias, name);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return [...aliases.entries()].sort(([left], [right]) => left.localeCompare(right));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
23
|
export function renderTailwindCss(manifest, version) {
|
|
44
24
|
const tokens = Object.keys(manifest.tokens ?? {});
|
|
45
25
|
const colorNames = tokens.filter((name) => name.startsWith("color-"));
|
|
46
|
-
const spacingAliases = collectDimensionAliases(manifest, "spacing-");
|
|
47
|
-
const radiusAliases = collectDimensionAliases(manifest, "radius-");
|
|
48
26
|
const typography = new Map();
|
|
49
27
|
|
|
50
28
|
for (const name of tokens.filter((entry) => entry.startsWith("typography-"))) {
|
|
@@ -74,12 +52,6 @@ export function renderTailwindCss(manifest, version) {
|
|
|
74
52
|
const colorAliases = colorNames
|
|
75
53
|
.map((name) => ` --color-eds-${name.slice("color-".length)}: var(${cssVariableForToken(manifest, name)});`)
|
|
76
54
|
.join("\n");
|
|
77
|
-
const spacingThemeAliases = spacingAliases
|
|
78
|
-
.map(([alias, name]) => ` --spacing-${alias}: var(${cssVariableForToken(manifest, name)});`)
|
|
79
|
-
.join("\n");
|
|
80
|
-
const radiusThemeAliases = radiusAliases
|
|
81
|
-
.map(([alias, name]) => ` --radius-${alias}: var(${cssVariableForToken(manifest, name)});`)
|
|
82
|
-
.join("\n");
|
|
83
55
|
// Last line of the @theme block: Tailwind's default font family becomes the EDS body font.
|
|
84
56
|
const fontSans = ` --font-sans: var(--eds-typography-${fontSansStyleName}-fontFamily);`;
|
|
85
57
|
const typographyUtilities = [...typography.keys()].sort().map((styleName) => [
|
|
@@ -96,8 +68,6 @@ export function renderTailwindCss(manifest, version) {
|
|
|
96
68
|
`/* Generated from @spectrabrain/eds@${version}. Do not edit manually. */`,
|
|
97
69
|
"@theme inline {",
|
|
98
70
|
colorAliases,
|
|
99
|
-
spacingThemeAliases,
|
|
100
|
-
radiusThemeAliases,
|
|
101
71
|
fontSans,
|
|
102
72
|
"}",
|
|
103
73
|
"",
|
|
@@ -10,9 +10,10 @@ const opacity = "(?:/[0-9]{1,3})?";
|
|
|
10
10
|
|
|
11
11
|
const edsColorClass = new RegExp(boundaryBefore + variantPrefix + colorUtility + "-eds-([A-Za-z0-9-]+)" + opacity + boundaryAfter, "g");
|
|
12
12
|
const edsTypographyClass = new RegExp(boundaryBefore + variantPrefix + "eds-typography-([A-Za-z0-9-]+)" + boundaryAfter, "g");
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const retiredDimensionClass = new RegExp(
|
|
14
|
+
boundaryBefore + variantPrefix + "-?[A-Za-z0-9-]+-eds-(?:spacing|radius)-[A-Za-z0-9-]+" + boundaryAfter,
|
|
15
|
+
"g",
|
|
16
|
+
);
|
|
16
17
|
const rawColorClass = new RegExp(
|
|
17
18
|
boundaryBefore + variantPrefix + colorUtility +
|
|
18
19
|
"-(?:(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-[0-9]{2,3}|white|black|\\[(?:#|rgba?\\(|hsla?\\(|oklch\\(|oklab\\(|color\\()[^\\]]*\\])" +
|
|
@@ -20,11 +21,10 @@ const rawColorClass = new RegExp(
|
|
|
20
21
|
"g",
|
|
21
22
|
);
|
|
22
23
|
|
|
23
|
-
//
|
|
24
|
+
// EDS publishes color and typography utilities. Spacing and radius use Tailwind CSS v4 defaults.
|
|
24
25
|
export function publicClassNames(manifest) {
|
|
25
26
|
const colors = new Set();
|
|
26
27
|
const typography = new Set();
|
|
27
|
-
const dimensions = new Set();
|
|
28
28
|
for (const name of Object.keys(manifest.tokens ?? {})) {
|
|
29
29
|
if (name.startsWith("color-")) {
|
|
30
30
|
colors.add("eds-" + name.slice("color-".length));
|
|
@@ -35,18 +35,15 @@ export function publicClassNames(manifest) {
|
|
|
35
35
|
typography.add(match[1]);
|
|
36
36
|
continue;
|
|
37
37
|
}
|
|
38
|
-
if (name.startsWith("spacing-") || name.startsWith("radius-")) {
|
|
39
|
-
dimensions.add("eds-" + name.replace(/\./g, "-"));
|
|
40
|
-
}
|
|
41
38
|
}
|
|
42
|
-
return { colors, typography
|
|
39
|
+
return { colors, typography };
|
|
43
40
|
}
|
|
44
41
|
|
|
45
42
|
// files: [{ path, contents }] as readSources() lists them (the generated eds-tokens.css is not among them).
|
|
46
43
|
// unknown: eds-* classes that no public token backs (always a mistake, Tailwind silently drops them).
|
|
47
44
|
// raw: Tailwind palette, white/black and arbitrary color classes that bypass the EDS tokens (informational).
|
|
48
45
|
export function scanClassNames({ consumerRoot, manifest, files }) {
|
|
49
|
-
const { colors, typography
|
|
46
|
+
const { colors, typography } = publicClassNames(manifest);
|
|
50
47
|
const unknown = [];
|
|
51
48
|
const raw = [];
|
|
52
49
|
for (const file of files) {
|
|
@@ -70,15 +67,8 @@ export function scanClassNames({ consumerRoot, manifest, files }) {
|
|
|
70
67
|
unknown.push({ location, className: match[0] });
|
|
71
68
|
}
|
|
72
69
|
}
|
|
73
|
-
for (const match of line.matchAll(
|
|
74
|
-
|
|
75
|
-
unknown.push({ location, className: match[0] });
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
for (const match of line.matchAll(edsRadiusClass)) {
|
|
79
|
-
if (match[1] !== undefined && !dimensions.has("eds-" + match[1])) {
|
|
80
|
-
unknown.push({ location, className: match[0] });
|
|
81
|
-
}
|
|
70
|
+
for (const match of line.matchAll(retiredDimensionClass)) {
|
|
71
|
+
unknown.push({ location, className: match[0] });
|
|
82
72
|
}
|
|
83
73
|
for (const match of line.matchAll(rawColorClass)) {
|
|
84
74
|
raw.push({ location, className: match[0] });
|
|
@@ -65,10 +65,8 @@ Layout은 prop으로 지정하지 않고 슬롯 조합에서 추론합니다.
|
|
|
65
65
|
| `iconBoth` | `children`과 앞·뒤 아이콘을 모두 지정합니다. | 양쪽 아이콘이 모두 의미를 더하는 명확한 경우에만 사용합니다. |
|
|
66
66
|
| `iconOnly` | `children` 없이 `icon` 또는 `iconName`과 `aria-label`을 지정합니다. | |
|
|
67
67
|
|
|
68
|
-
- 이름 슬롯(`iconName`·`startIconName`·`endIconName`)은
|
|
69
|
-
-
|
|
70
|
-
- 목록 밖 아이콘은 `icon`, `startIcon`, `endIcon`에 `ReactElement`로 전달하며, 같은 슬롯에 이름과 custom element를 함께 지정하지 않습니다. `lucide-react`에서 직접 import할 때는 EDS package root `package.json`의 `dependencies["lucide-react"]`와 같은 exact 버전을 소비처 `package.json`에 선언합니다. pnpm처럼 엄격한 node_modules에서는 선언 없이 resolve되지 않고, 버전이 다르면 아이콘 코드가 두 벌 번들됩니다. custom lucide 아이콘은 lucide 기본 stroke를 그대로 써서 이름으로 지정한 아이콘과 맞춥니다.
|
|
71
|
-
- 목록 밖 아이콘을 `ReactElement`로 썼다면 완료 보고에 아이콘 이름과 사용 파일을 allowlist 추가 후보로 적습니다.
|
|
68
|
+
- 이름 슬롯(`iconName`·`startIconName`·`endIconName`)은 설치된 `lucide-react`의 실제 아이콘 component 이름과 alias를 모두 받습니다. `ButtonIconName`이 이 목록을 자동완성하며, 전체 이름은 `spec.json`의 `api.iconNames`에 있습니다. 잘못된 이름은 TypeScript 오류이고 런타임에도 render 오류입니다.
|
|
69
|
+
- custom 아이콘은 `icon`·`startIcon`·`endIcon`에 `ReactElement`로 전달합니다. 같은 슬롯에 이름과 custom element를 함께 지정하지 않습니다. `lucide-react`에서 직접 import할 때는 EDS package root `package.json`의 `dependencies["lucide-react"]`와 같은 exact 버전을 소비처 `package.json`에 선언합니다. pnpm처럼 엄격한 node_modules에서는 선언 없이 resolve되지 않고, 버전이 다르면 아이콘 코드가 두 벌 번들됩니다. 이름 슬롯은 설치된 아이콘 크기와 stroke를 사용합니다.
|
|
72
70
|
|
|
73
71
|
### State
|
|
74
72
|
|