atomsystem 0.1.26 → 0.1.27

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 CHANGED
@@ -14,14 +14,23 @@ const __dirname = path.dirname(__filename);
14
14
 
15
15
  // 패키지 내부 경로 설정
16
16
  const packageRoot = path.join(__dirname, "..");
17
- const tokenFile = path.join(packageRoot, "token.json");
18
- const buildFile = path.join(packageRoot, "/build/build-tokens.js");
17
+ const tokenFile = path.join(packageRoot, "tokens", "tokens.json");
18
+ const buildFile = path.join(packageRoot, "build", "build-tokens.js");
19
19
 
20
20
  // 프로젝트 루트 경로 (사용자가 실행한 곳)
21
21
  const projectRoot = process.cwd();
22
- const targetTokenFile = path.join(projectRoot, "token.json");
22
+ const targetTokenDir = path.join(projectRoot, "tokens");
23
+ const targetTokenFile = path.join(targetTokenDir, "tokens.json");
23
24
  const targetBuildDir = path.join(projectRoot, "build");
24
- const targetBuildFile = path.join(projectRoot, "/build/build-tokens.js");
25
+ const targetBuildFile = path.join(targetBuildDir, "build-tokens.js");
26
+
27
+ // 사용자 프로젝트에 package.json이 존재하는지 먼저 확인 (안전장치)
28
+ const packageJsonPath = path.join(projectRoot, "package.json");
29
+ if (!fs.existsSync(packageJsonPath)) {
30
+ console.error("❌ Error: package.json not found in the current directory.");
31
+ console.error("Please run 'npm init' or 'npm init -y' before running atomsystem-init.");
32
+ process.exit(1);
33
+ }
25
34
 
26
35
  // 사용자에게 Next.js 설치 여부 질문
27
36
  inquirer
@@ -41,9 +50,18 @@ inquirer
41
50
  await execPromise(
42
51
  "npm install next@latest react@latest react-dom@latest tailwindcss"
43
52
  );
44
- console.log("✅ Installation complete!");
53
+ console.log("✅ Next.js and React Installation complete!");
45
54
  } catch (err) {
46
- console.error("❌ Error during installation:", err);
55
+ console.error("❌ Error during Next.js/React installation:", err);
56
+ return;
57
+ }
58
+
59
+ console.log("Installing style-dictionary for atom design tokens...");
60
+ try {
61
+ await execPromise("npm install style-dictionary -D");
62
+ console.log("✅ style-dictionary Installation complete!");
63
+ } catch (err) {
64
+ console.error("❌ Error during style-dictionary installation:", err);
47
65
  return;
48
66
  }
49
67
 
@@ -54,6 +72,7 @@ inquirer
54
72
  fs.readFileSync(packageJsonPath, "utf8")
55
73
  );
56
74
 
75
+ packageJson.type = "module";
57
76
  packageJson.scripts = {
58
77
  ...packageJson.scripts,
59
78
  "token-build": "node build/build-tokens.js",
@@ -71,20 +90,68 @@ inquirer
71
90
  if (!fs.existsSync(appDir)) mkdirSync(appDir);
72
91
 
73
92
  const files = [
93
+ {
94
+ path: path.join(appDir, "ThemeProvider.tsx"),
95
+ content: `"use client";
96
+ import { useEffect, useState } from "react";
97
+ import { themes } from "@/build/typescript/theme";
98
+
99
+ export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
100
+ const [theme, setTheme] = useState<Record<string, string>>({});
101
+ const [isThemeLoading, setThemeLoading] = useState(false);
102
+
103
+ useEffect(() => {
104
+ const listenStorageChange = () => {
105
+ const newThemes: Record<string, string> = {};
106
+ Object.entries(themes).forEach(([group, groupThemes]) => {
107
+ const storedKey = group === "global" ? "theme" : \`theme-\${group}\`;
108
+ const currentTheme = localStorage.getItem(storedKey) || groupThemes[0];
109
+ newThemes[group] = currentTheme;
110
+
111
+ document.documentElement.classList.remove(...groupThemes);
112
+ document.documentElement.classList.add(currentTheme);
113
+ });
114
+ setTheme(newThemes);
115
+ };
116
+
117
+ listenStorageChange();
118
+ window.addEventListener("storage", listenStorageChange);
119
+ setThemeLoading(true);
120
+ return () => window.removeEventListener("storage", listenStorageChange);
121
+ }, []);
122
+
123
+ if (isThemeLoading === false) return null;
124
+ return <>{children}</>;
125
+ };`,
126
+ },
74
127
  {
75
128
  path: path.join(appDir, "layout.tsx"),
76
- content: `export default function RootLayout({ children }: { children: React.ReactNode }) {
129
+ content: `import { ThemeProvider } from "./ThemeProvider";
130
+ import "../css/global.css"; // Ensure to load the CSS configuration if possible
131
+
132
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
77
133
  return (
78
134
  <html lang="en">
79
- <body>{children}</body>
135
+ <body>
136
+ <ThemeProvider>
137
+ {children}
138
+ </ThemeProvider>
139
+ </body>
80
140
  </html>
81
141
  )
82
142
  }`,
83
143
  },
84
144
  {
85
145
  path: path.join(appDir, "page.tsx"),
86
- content: `export default function Page() {
87
- return <h1>Hello, Next.js!</h1>
146
+ content: `import { ThemeSelector } from "./components/Theme/Theme";
147
+
148
+ export default function Page() {
149
+ return (
150
+ <main style={{ padding: "20px" }}>
151
+ <h1>Hello, atomsystem!</h1>
152
+ <ThemeSelector />
153
+ </main>
154
+ )
88
155
  }`,
89
156
  },
90
157
  ];
@@ -97,13 +164,14 @@ inquirer
97
164
  console.log("🚀 Installation skipped.");
98
165
  }
99
166
 
100
- // ✅ 토큰 파일 복사 (Next.js 설치 여부와 관계없이 실행)
167
+ // ✅ 토큰 파일과 빌드 파일 복사 (Next.js 설치 여부와 관계없이 실행)
168
+ if (!fs.existsSync(targetTokenDir)) mkdirSync(targetTokenDir, { recursive: true });
101
169
  copyFileSync(tokenFile, targetTokenFile);
102
- console.log(`✅ Copied: token.json -> ${targetTokenFile}`);
170
+ console.log(`✅ Copied: tokens/tokens.json -> ${targetTokenFile}`);
103
171
 
104
- if (!fs.existsSync(targetBuildDir)) mkdirSync(targetBuildDir);
172
+ if (!fs.existsSync(targetBuildDir)) mkdirSync(targetBuildDir, { recursive: true });
105
173
  copyFileSync(buildFile, targetBuildFile);
106
- console.log(`✅ Copied: build-token.json -> ${targetTokenFile}`);
174
+ console.log(`✅ Copied: build-tokens.js -> ${targetBuildFile}`);
107
175
 
108
176
  console.log("🚀 Token setup complete!");
109
177
  })
package/css/badge.css ADDED
@@ -0,0 +1,28 @@
1
+ .badge,
2
+ .badge-tint {
3
+ font-size: var(--text-sm);
4
+ padding: 0 var(--spacing-common-y);
5
+ border-radius: var(--radius-common);
6
+ }
7
+
8
+
9
+
10
+ .badge.primary { --badge-bg: var(--color-primary); }
11
+ .badge.secondary { --badge-bg: var(--color-secondary); }
12
+ .badge.warning { --badge-bg: var(--color-warning); }
13
+ .badge.danger { --badge-bg: var(--color-danger); }
14
+
15
+ .badge {
16
+ background-color: var(--badge-bg);
17
+ color: var(--color-white);
18
+ }
19
+
20
+ .badge-tint.primary { --badge-bg: var(--color-blue-100); --text-color: var(--color-primary); }
21
+ .badge-tint.secondary { --badge-bg: var(--color-indigo-100); --text-color: var(--color-secondary); }
22
+ .badge-tint.warning { --badge-bg: var(--color-yellow-100); --text-color: var(--color-warning); }
23
+ .badge-tint.danger { --badge-bg: var(--color-red-100); --text-color: var(--color-danger); }
24
+
25
+ .badge-tint {
26
+ background-color: var(--badge-bg);
27
+ color: var(--text-color);
28
+ }
package/css/button.css ADDED
@@ -0,0 +1,75 @@
1
+ .btn {
2
+ padding: var(--spacing-common-y) var(--spacing-common-x);
3
+ color: var(--color-white);
4
+ transition: all 0.2s;
5
+ cursor: pointer;
6
+ border-radius: var(--radius-common);
7
+ border: none;
8
+ font-family: var(--font-spoqaNeo);
9
+ }
10
+
11
+ .btn.primary {
12
+ --btn-bg: var(--color-primary);
13
+ --btn-hover: var(--color-blue-600);
14
+ --btn-active: var(--color-blue-700);
15
+ --btn-bg-disabled: var(--button-primary-bg-disabled);
16
+ --btn-text-disabled: var(--button-primary-text-disabled);
17
+ --btn-border-disabled: var(--button-primary-border-disabled);
18
+ }
19
+ .btn.secondary {
20
+ --btn-bg: var(--color-secondary);
21
+ --btn-hover: var(--color-indigo-600);
22
+ --btn-active: var(--color-indigo-700);
23
+ --btn-bg-disabled: var(--button-secondary-bg-disabled);
24
+ --btn-text-disabled: var(--button-secondary-text-disabled);
25
+ --btn-border-disabled: var(--button-secondary-border-disabled);
26
+ }
27
+ .btn.success {
28
+ --btn-bg: var(--color-success);
29
+ --btn-hover: var(--color-green-600);
30
+ --btn-active: var(--color-green-700);
31
+ --btn-bg-disabled: var(--button-success-bg-disabled);
32
+ --btn-text-disabled: var(--button-success-text-disabled);
33
+ --btn-border-disabled: var(--button-success-border-disabled);
34
+ }
35
+ .btn.warning {
36
+ --btn-bg: var(--color-warning);
37
+ --btn-hover: var(--color-yellow-600);
38
+ --btn-active: var(--color-yellow-700);
39
+ --btn-bg-disabled: var(--button-warning-bg-disabled);
40
+ --btn-text-disabled: var(--button-warning-text-disabled);
41
+ --btn-border-disabled: var(--button-warning-border-disabled);
42
+ }
43
+ .btn.danger {
44
+ --btn-bg: var(--color-danger);
45
+ --btn-hover: var(--color-red-600);
46
+ --btn-active: var(--color-red-700);
47
+ --btn-bg-disabled: var(--button-danger-bg-disabled);
48
+ --btn-text-disabled: var(--button-danger-text-disabled);
49
+ --btn-border-disabled: var(--button-danger-border-disabled);
50
+ }
51
+ .btn.gray {
52
+ --btn-bg: var(--color-gray-500);
53
+ --btn-hover: var(--color-gray-600);
54
+ --btn-active: var(--color-gray-700);
55
+ --btn-bg-disabled: var(--button-gray-bg-disabled);
56
+ --btn-text-disabled: var(--button-gray-text-disabled);
57
+ --btn-border-disabled: var(--button-gray-border-disabled);
58
+ }
59
+
60
+ .btn {
61
+ background-color: var(--btn-bg);
62
+ }
63
+ .btn:hover:not(:disabled) {
64
+ background-color: var(--btn-hover);
65
+ }
66
+ .btn:active:not(:disabled) {
67
+ background-color: var(--btn-active);
68
+ }
69
+ .btn:disabled {
70
+ background-color: var(--btn-bg-disabled);
71
+ color: var(--btn-text-disabled);
72
+ cursor: not-allowed;
73
+ opacity: 0.7;
74
+ border: 1px solid var(--btn-border-disabled);
75
+ }
package/css/card.css ADDED
@@ -0,0 +1,17 @@
1
+ .card {
2
+ background-color: var(--color-bg-card);
3
+ border-radius: var(--radius-common);
4
+ border: 1px solid var(--border-standard);
5
+ }
6
+
7
+ .card-header,
8
+ .card-content,
9
+ .card-footer {
10
+ padding: var(--spacing-common-x);
11
+ }
12
+
13
+ .card-header.no-margin,
14
+ .card-content.no-margin,
15
+ .card-footer.no-margin {
16
+ padding: 0;
17
+ }
@@ -0,0 +1,33 @@
1
+ .collapse-item {
2
+ border-top: 1px solid var(--border-standard);
3
+ background-color: var(--color-bg-card);
4
+ }
5
+
6
+ .collapse-header {
7
+ display: flex;
8
+ justify-content: space-between;
9
+ align-items: center;
10
+ cursor: pointer;
11
+ padding: var(--spacing-common-x);
12
+ color: var(--text-standard);
13
+ font-size: var(--text-body);
14
+ }
15
+
16
+ .collapse-icon {
17
+ transition: transform 0.3s ease;
18
+ color: var(--text-standard);
19
+ }
20
+
21
+ .collapse-icon.open {
22
+ transform: rotate(90deg);
23
+ }
24
+
25
+ .collapse-icon.closed {
26
+ transform: rotate(0deg);
27
+ }
28
+
29
+ .collapse-content {
30
+ padding: var(--spacing-common-x);
31
+ color: var(--text-standard);
32
+ font-size: var(--text-body);
33
+ }
package/css/form.css ADDED
@@ -0,0 +1,115 @@
1
+
2
+ .input{
3
+ background: var(--bg-input-standard);
4
+ border: 1px solid var(--border-standard);
5
+ color: var(--text-standard);
6
+ padding: var(--spacing-common-y) var(--spacing-common-x);
7
+ border-radius: var(--radius-common);
8
+ }
9
+
10
+ .input::placeholder{
11
+ color: var(--text-placeholder);
12
+ }
13
+
14
+ .input:focus{
15
+ border: 1px solid var(--border-active);
16
+ }
17
+
18
+ .input:disabled{
19
+ background: var(--bg-input-disabled);
20
+ border: 1px solid var(--border-standard);
21
+ color: var(--text-disabled);
22
+ }
23
+
24
+ .select{
25
+ background: var(--bg-input-standard);
26
+ border: 1px solid var(--border-standard);
27
+ color: var(--text-standard);
28
+ padding: var(--spacing-common-y) var(--spacing-common-x);
29
+ border-radius: var(--radius-common);
30
+ }
31
+ .select:focus{
32
+ border: 1px solid var(--border-active);
33
+ }
34
+
35
+ .select:disabled{
36
+ background: var(--bg-input-disabled);
37
+ border: 1px solid var(--border-standard);
38
+ color: var(--text-disabled);
39
+ }
40
+
41
+ .select-menu {
42
+ border: 1px solid var(--border-active);
43
+ border-radius: var(--radius-common);
44
+ overflow:hidden;
45
+ }
46
+
47
+ .select-menu .select-menu-item {
48
+ background: var(--bg-input-standard);
49
+ border: 1px solid var(--border-standard);
50
+ color: var(--text-standard);
51
+ padding: var(--spacing-common-y) var(--spacing-common-x);
52
+ cursor:pointer
53
+ }
54
+
55
+ .select-menu .select-menu-item:hover {
56
+ background: var(--bg-input-hover);
57
+ }
58
+
59
+ .select-menu .select-menu-item:active,
60
+ .select-menu .select-menu-item:focus {
61
+ background: var(--color-primary);
62
+ border: 1px solid var(--color-primary);
63
+ color: var(--text-active);
64
+ }
65
+
66
+ .checkbox{
67
+ display: flex;
68
+ align-items: center;
69
+ position: relative;
70
+ width: var(--spacing-small);
71
+ height: var(--spacing-small);
72
+ border: 1px solid var(--border-standard);
73
+ border-radius: var(--radius-common);
74
+ background: var(--bg-input-standard);
75
+ color: var(--bg-input-standard);
76
+ }
77
+
78
+ .checkbox span svg{
79
+ color: var(--bg-input-standard);
80
+ fill: var(--bg-input-standard);
81
+ }
82
+
83
+ .checkbox:has(input:checked){
84
+ background: var(--color-primary);
85
+ border: 1px solid var(--color-primary);
86
+ }
87
+
88
+ .checkbox:has(input:checked) span svg{
89
+ color: var(--text-active);
90
+ fill: var(--text-active);
91
+ }
92
+
93
+ .radio{
94
+ position: relative;
95
+ width: var(--spacing-small);
96
+ height: var(--spacing-small);
97
+ border: 1px solid var(--border-standard);
98
+ background: var(--bg-input-standard);
99
+ color: var(--bg-input-standard);
100
+ }
101
+
102
+ .radio::after{
103
+ content:'';
104
+ position:absolute;
105
+ left: 50%;
106
+ top: 50%;
107
+ transform: translate(-50%, -50%);
108
+ width: var(--spacing-common-y);
109
+ height: var(--spacing-common-y);
110
+ border-radius: var(--radius-circle);
111
+ }
112
+
113
+ .radio:checked::after{
114
+ background: var(--color-primary);
115
+ }
package/css/modal.css ADDED
@@ -0,0 +1,98 @@
1
+ .modal-overlay {
2
+ position: fixed;
3
+ inset: 0;
4
+ background-color: rgba(0, 0, 0, 0.4);
5
+ display: flex;
6
+ justify-content: center;
7
+ align-items: center;
8
+ z-index: 50;
9
+ }
10
+
11
+ .modal {
12
+ background-color: var(--color-bg-card);
13
+ padding: 0;
14
+ border-radius: var(--radius-common);
15
+ box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
16
+ width: 100%;
17
+ display: flex;
18
+ flex-direction: column;
19
+ color: var(--color-text-standard);
20
+ border: 1px solid var(--color-border-standard);
21
+ max-height: 90vh;
22
+ }
23
+
24
+ .modal-content {
25
+ padding: var(--spacing-common-x);
26
+ width: 100%;
27
+ overflow-y: auto;
28
+ flex: 1;
29
+ }
30
+
31
+ .modal-header {
32
+ display: flex;
33
+ justify-content: space-between;
34
+ align-items: center;
35
+ padding: var(--spacing-common-y) var(--spacing-common-x);
36
+ border-bottom: 1px solid var(--color-border-standard);
37
+ }
38
+
39
+ .modal-title {
40
+ font-size: var(--text-h6);
41
+ font-weight: var(--font-weight-header);
42
+ margin: 0;
43
+ color: var(--color-text-standard);
44
+ }
45
+
46
+ .modal-close {
47
+ cursor: pointer;
48
+ background: transparent;
49
+ border: none;
50
+ color: var(--color-text-standard);
51
+ display: flex;
52
+ align-items: center;
53
+ justify-content: center;
54
+ padding: 0;
55
+ transition: color 0.2s ease-in-out;
56
+ }
57
+
58
+ .modal-close:hover {
59
+ color: var(--color-danger);
60
+ }
61
+
62
+ .modal-footer {
63
+ display: flex;
64
+ justify-content: flex-end;
65
+ padding: var(--spacing-common-y) var(--spacing-common-x);
66
+ border-top: 1px solid var(--color-border-standard);
67
+ gap: var(--spacing-gap-small);
68
+ }
69
+
70
+ /* Modal Sizes */
71
+ .modal-normal {
72
+ max-width: 28rem; /* Tailwind max-w-md */
73
+ }
74
+
75
+ .modal-middle {
76
+ max-width: 36rem; /* Tailwind max-w-xl */
77
+ }
78
+
79
+ .modal-large {
80
+ max-width: 64rem; /* Tailwind max-w-5xl */
81
+ }
82
+
83
+ .modal-xl {
84
+ max-width: 72rem; /* Tailwind max-w-6xl */
85
+ }
86
+
87
+ .modal-full {
88
+ max-width: calc(100vw - (var(--spacing-common-x) * 2));
89
+ }
90
+
91
+ .modal-full-screen {
92
+ width: 100vw;
93
+ height: 100vh;
94
+ max-height: 100vh;
95
+ max-width: 100vw;
96
+ border-radius: 0;
97
+ border: none;
98
+ }
@@ -0,0 +1,69 @@
1
+
2
+
3
+ .nav-container.nav-topnav {
4
+ background-color: var(--bg-topnav);
5
+ color: var(--text-topnav-standard);
6
+ border-color: var(--border-topnav);
7
+ }
8
+
9
+ .nav-container.nav-sidenav {
10
+ background-color: var(--bg-sidenav);
11
+ color: var(--text-sidenav-standard);
12
+ border-color: var(--border-sidenav);
13
+ }
14
+
15
+ .nav-bg.nav-topnav {
16
+ background-color: var(--bg-topnav);
17
+ }
18
+
19
+ .nav-bg.nav-sidenav {
20
+ background-color: var(--bg-sidenav);
21
+ }
22
+
23
+ .nav-border.nav-topnav {
24
+ border-color: var(--border-topnav);
25
+ }
26
+
27
+ .nav-border.nav-sidenav {
28
+ border-color: var(--border-sidenav);
29
+ }
30
+
31
+ .nav-text-standard.nav-topnav {
32
+ color: var(--text-topnav-standard);
33
+ }
34
+
35
+ .nav-text-standard.nav-sidenav {
36
+ color: var(--text-sidenav-standard);
37
+ }
38
+
39
+ .nav-text-active.nav-topnav {
40
+ color: var(--text-topnav-active);
41
+ }
42
+
43
+ .nav-text-active.nav-sidenav {
44
+ color: var(--text-sidenav-active);
45
+ }
46
+
47
+ .nav-text-sub.nav-topnav {
48
+ color: var(--text-topnav-sub);
49
+ }
50
+
51
+ .nav-text-sub.nav-sidenav {
52
+ color: var(--text-sidenav-sub);
53
+ }
54
+
55
+ .nav-padding.nav-topnav {
56
+ padding: var(--spacing-topnav-y) var(--spacing-topnav-x);
57
+ }
58
+
59
+ .nav-padding.nav-sidenav {
60
+ padding: var(--spacing-sidenav-y) var(--spacing-sidenav-x);
61
+ }
62
+
63
+ .nav-gap.nav-topnav {
64
+ gap: var(--spacing-topnav-gap);
65
+ }
66
+
67
+ .nav-gap.nav-sidenav {
68
+ gap: var(--spacing-sidenav-gap);
69
+ }
@@ -0,0 +1,66 @@
1
+ .pagination {
2
+ display: flex;
3
+ align-items: center;
4
+ color: var(--color-text-standard);
5
+ }
6
+
7
+ .pagination-btn {
8
+ padding: var(--spacing-common-y) var(--spacing-common-x);
9
+ cursor: pointer;
10
+ background: transparent;
11
+ border: none;
12
+ border-radius: var(--radius-common);
13
+ color: inherit;
14
+ transition: all 0.2s ease;
15
+ display: flex;
16
+ align-items: center;
17
+ justify-content: center;
18
+ }
19
+
20
+ .pagination-btn:hover:not(:disabled) {
21
+ background-color: var(--color-pagination-bg-hover);
22
+ color: var(--color-primary);
23
+ }
24
+
25
+ .pagination-btn:disabled {
26
+ opacity: 0.4;
27
+ cursor: not-allowed;
28
+ color: var(--color-text-disabled);
29
+ }
30
+
31
+ .pagination-list {
32
+ display: flex;
33
+ width: 100%;
34
+ list-style: none;
35
+ padding: 0;
36
+ margin: 0;
37
+ }
38
+
39
+ .pagination-item {
40
+ flex: 1; /* w-full behavior mapped */
41
+ text-align: center;
42
+ padding: var(--spacing-common-y) var(--spacing-common-x);
43
+ cursor: pointer;
44
+ color: inherit;
45
+ border-radius: var(--radius-common);
46
+ transition: all 0.2s ease;
47
+ user-select: none;
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: center;
51
+ }
52
+
53
+ .pagination-item:hover {
54
+ background-color: var(--color-pagination-bg-hover);
55
+ color: var(--color-primary);
56
+ }
57
+
58
+ .pagination-item-active {
59
+ color: var(--color-primary);
60
+ font-weight: var(--font-weight-header);
61
+ }
62
+
63
+ .pagination-item-active:hover {
64
+ background-color: transparent; /* Reset hover if it's the active one */
65
+ cursor: default;
66
+ }