atomsystem 0.1.29 → 0.1.31
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/cli/init.js +56 -43
- package/package.json +1 -1
package/cli/init.js
CHANGED
|
@@ -96,67 +96,65 @@ inquirer
|
|
|
96
96
|
const appDir = path.join(projectRoot, "app");
|
|
97
97
|
if (!fs.existsSync(appDir)) mkdirSync(appDir);
|
|
98
98
|
|
|
99
|
+
// components 및 Theme 디렉토리 생성은 add.js 가 알아서 처리하므로 여기서는 page.tsx 와 layout.tsx, globals.css 만 생성합니다.
|
|
99
100
|
const files = [
|
|
100
|
-
{
|
|
101
|
-
path: path.join(appDir, "ThemeProvider.tsx"),
|
|
102
|
-
content: `"use client";
|
|
103
|
-
import { useEffect, useState } from "react";
|
|
104
|
-
import { themes } from "@/build/typescript/theme";
|
|
105
|
-
|
|
106
|
-
export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
|
|
107
|
-
const [theme, setTheme] = useState<Record<string, string>>({});
|
|
108
|
-
const [isThemeLoading, setThemeLoading] = useState(false);
|
|
109
|
-
|
|
110
|
-
useEffect(() => {
|
|
111
|
-
const listenStorageChange = () => {
|
|
112
|
-
const newThemes: Record<string, string> = {};
|
|
113
|
-
Object.entries(themes).forEach(([group, groupThemes]) => {
|
|
114
|
-
const storedKey = group === "global" ? "theme" : \`theme-\${group}\`;
|
|
115
|
-
const currentTheme = localStorage.getItem(storedKey) || groupThemes[0];
|
|
116
|
-
newThemes[group] = currentTheme;
|
|
117
|
-
|
|
118
|
-
document.documentElement.classList.remove(...groupThemes);
|
|
119
|
-
document.documentElement.classList.add(currentTheme);
|
|
120
|
-
});
|
|
121
|
-
setTheme(newThemes);
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
listenStorageChange();
|
|
125
|
-
window.addEventListener("storage", listenStorageChange);
|
|
126
|
-
setThemeLoading(true);
|
|
127
|
-
return () => window.removeEventListener("storage", listenStorageChange);
|
|
128
|
-
}, []);
|
|
129
|
-
|
|
130
|
-
if (isThemeLoading === false) return null;
|
|
131
|
-
return <>{children}</>;
|
|
132
|
-
};`,
|
|
133
|
-
},
|
|
134
101
|
{
|
|
135
102
|
path: path.join(appDir, "layout.tsx"),
|
|
136
|
-
content: `import { ThemeProvider } from "./
|
|
137
|
-
import "
|
|
103
|
+
content: `import { ThemeProvider } from "./components/Theme/Theme";
|
|
104
|
+
import "./globals.css";
|
|
138
105
|
|
|
139
106
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
140
107
|
return (
|
|
141
|
-
<html lang="en">
|
|
108
|
+
<html lang="en" suppressHydrationWarning>
|
|
142
109
|
<body>
|
|
143
|
-
<ThemeProvider
|
|
144
|
-
|
|
145
|
-
</ThemeProvider>
|
|
110
|
+
<ThemeProvider />
|
|
111
|
+
{children}
|
|
146
112
|
</body>
|
|
147
113
|
</html>
|
|
148
114
|
)
|
|
149
115
|
}`,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
path: path.join(appDir, "globals.css"),
|
|
119
|
+
content: `@import "tailwindcss";
|
|
120
|
+
@import "../build/css/_variables.css";`,
|
|
150
121
|
},
|
|
151
122
|
{
|
|
152
123
|
path: path.join(appDir, "page.tsx"),
|
|
153
124
|
content: `import { ThemeSelector } from "./components/Theme/Theme";
|
|
125
|
+
import { Button } from "./components/Button/Button";
|
|
126
|
+
import { Card, CardHeader, CardContent, CardFooter } from "./components/Card/Card";
|
|
154
127
|
|
|
155
128
|
export default function Page() {
|
|
156
129
|
return (
|
|
157
|
-
<main style={{ padding: "
|
|
158
|
-
<
|
|
159
|
-
|
|
130
|
+
<main style={{ padding: "40px", minHeight: "100vh", background: "var(--color-bg-wrapper)", transition: "background 0.3s ease" }}>
|
|
131
|
+
<div style={{ maxWidth: "800px", margin: "0 auto", display: "flex", flexDirection: "column", gap: "24px" }}>
|
|
132
|
+
<h1 style={{ fontSize: "var(--font-sizes-h2)", color: "var(--color-text-standard)", margin: 0 }}>Hello, atomsystem!</h1>
|
|
133
|
+
<p style={{ color: "var(--color-text-standard)", fontSize: "var(--font-sizes-body)", margin: 0 }}>
|
|
134
|
+
이 화면은 디자인 토큰이 적용된 샘플 화면입니다. 아래 테마를 변경해보세요.
|
|
135
|
+
</p>
|
|
136
|
+
|
|
137
|
+
<ThemeSelector />
|
|
138
|
+
|
|
139
|
+
<Card>
|
|
140
|
+
<CardHeader>
|
|
141
|
+
<h2 style={{ fontSize: "var(--font-sizes-h3)", margin: 0 }}>Sample Card Components</h2>
|
|
142
|
+
</CardHeader>
|
|
143
|
+
<CardContent>
|
|
144
|
+
<p style={{ margin: 0, color: "var(--color-text-disabled)" }}>
|
|
145
|
+
이 카드는 테마 변경 시 배경색, 텍스트 색상, 테두리 색상이 자동으로 변경됩니다.
|
|
146
|
+
여기 있는 버튼들은 제공된 Button 컴포넌트로 구성되었습니다.
|
|
147
|
+
</p>
|
|
148
|
+
</CardContent>
|
|
149
|
+
<CardFooter>
|
|
150
|
+
<div style={{ display: "flex", gap: "12px" }}>
|
|
151
|
+
<Button type="primary">Primary Button</Button>
|
|
152
|
+
<Button type="secondary">Secondary Button</Button>
|
|
153
|
+
<Button type="gray">Gray Button</Button>
|
|
154
|
+
</div>
|
|
155
|
+
</CardFooter>
|
|
156
|
+
</Card>
|
|
157
|
+
</div>
|
|
160
158
|
</main>
|
|
161
159
|
)
|
|
162
160
|
}`,
|
|
@@ -167,6 +165,21 @@ export default function Page() {
|
|
|
167
165
|
fs.writeFileSync(path, content);
|
|
168
166
|
console.log(`✅ Created ${path}`);
|
|
169
167
|
});
|
|
168
|
+
|
|
169
|
+
// add.js를 실행하여 Theme, Card 컴포넌트 및 하위 의존성을 복사합니다.
|
|
170
|
+
const addScriptPath = path.join(__dirname, "add.js");
|
|
171
|
+
if (fs.existsSync(addScriptPath)) {
|
|
172
|
+
console.log("⏳ Adding default components via add.js...");
|
|
173
|
+
try {
|
|
174
|
+
// Theme 설치 (Theme 내부에 Button 등이 포함되어 있음)
|
|
175
|
+
await execPromise(`node "${addScriptPath}" Theme`, { cwd: projectRoot });
|
|
176
|
+
// Card 설치
|
|
177
|
+
await execPromise(`node "${addScriptPath}" Card`, { cwd: projectRoot });
|
|
178
|
+
console.log("✅ Default components (Theme, Card, Button 등) added successfully.");
|
|
179
|
+
} catch (err) {
|
|
180
|
+
console.error("❌ Failed to add components:", err);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
170
183
|
} else {
|
|
171
184
|
console.log("🚀 Installation skipped.");
|
|
172
185
|
}
|