atomsystem 0.1.24 → 0.1.26

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.
@@ -0,0 +1 @@
1
+ const NavToggle = () => {};
@@ -0,0 +1,314 @@
1
+ "use client";
2
+ import Link from "next/link";
3
+ import Image from "next/image";
4
+ import { useEffect, useState } from "react";
5
+ import { usePathname } from "next/navigation";
6
+ import clsx from "clsx";
7
+ import { useMediaQuery } from "react-responsive";
8
+
9
+ interface NavItemsAttr {
10
+ navMenu: {
11
+ name: string;
12
+ path?: string;
13
+ }[];
14
+ }
15
+
16
+ const navStandardStyle =
17
+ "bg-[var(--background-card)] text-text-standard border-[var(--color-border)]";
18
+
19
+ const navToggle = (targetId: string) => {
20
+ const el = document.getElementById(targetId);
21
+ if (el) {
22
+ const isHidden = el.style.display === "none" || el.style.display === "";
23
+ el.style.display = isHidden ? "block" : "none";
24
+ }
25
+ };
26
+
27
+ const Navigation = ({
28
+ children,
29
+ id,
30
+ className,
31
+ }: {
32
+ children: React.ReactNode;
33
+ id?: string;
34
+ className?: string;
35
+ }) => {
36
+ const isMobile = useMediaQuery({ maxWidth: 767 });
37
+
38
+ const mobileClose = (e: React.MouseEvent) => {
39
+ if (isMobile) {
40
+ e.preventDefault();
41
+ if (id) {
42
+ navToggle(id);
43
+ }
44
+ }
45
+ };
46
+
47
+ return (
48
+ <nav
49
+ id={id ? id : undefined}
50
+ className={`${navStandardStyle} ${className} overflow-auto`}
51
+ onClick={mobileClose}
52
+ >
53
+ {children}
54
+ </nav>
55
+ );
56
+ };
57
+
58
+ const NavItems = ({ navMenu }: NavItemsAttr) => {
59
+ const pathname = usePathname();
60
+
61
+ return (
62
+ <ul>
63
+ {navMenu.map((menu) => {
64
+ return (
65
+ <li className="relative group" key={menu.name}>
66
+ <div className={clsx("flex justify-between items-center pr-4")}>
67
+ {menu.path ? (
68
+ <Link
69
+ href={menu.path}
70
+ className={`${pathname === menu.path ? `text-primary` : `text-[var(--text-standard)]`} px-4 py-2 block `}
71
+ >
72
+ {menu.name}
73
+ </Link>
74
+ ) : (
75
+ <p className={`px-4 py-2 block text-[var(--text-standard)]`}>
76
+ {menu.name}
77
+ </p>
78
+ )}
79
+ </div>
80
+ </li>
81
+ );
82
+ })}
83
+ </ul>
84
+ );
85
+ };
86
+
87
+ const NavToggleButton = ({
88
+ children,
89
+ targetId,
90
+ className,
91
+ }: {
92
+ children: React.ReactNode;
93
+ targetId: string;
94
+ className?: string;
95
+ }) => {
96
+ return (
97
+ <button className={className} onClick={() => navToggle(targetId)}>
98
+ {children}
99
+ </button>
100
+ );
101
+ };
102
+
103
+ const Sidebar = ({ navMenu }: NavItemsAttr) => {
104
+ return (
105
+ <nav
106
+ className={clsx(
107
+ `relative ${navStandardStyle} w-full md:w-[320px] h-full z-20 left-0 overflow-auto`
108
+ )}
109
+ >
110
+ <ul>
111
+ {navMenu.map((menu, idx) => {
112
+ return (
113
+ <li className="relative group" key={menu.name}>
114
+ <div className={clsx("flex justify-between items-center pr-4")}>
115
+ {menu.path ? (
116
+ <Link
117
+ href={menu.path}
118
+ className={clsx(
119
+ "px-4 py-2 block text-[var(--text-standard)]"
120
+ )}
121
+ >
122
+ {menu.name}
123
+ </Link>
124
+ ) : (
125
+ <p></p>
126
+ )}
127
+ </div>
128
+ </li>
129
+ );
130
+ })}
131
+ </ul>
132
+ </nav>
133
+ );
134
+ };
135
+
136
+ const GlobalNav = ({
137
+ type = "sidebar",
138
+ navMenu,
139
+ brand = true,
140
+ }: {
141
+ type?: "sidebar" | "topmenu" | "mobile";
142
+ navMenu: {
143
+ name: string;
144
+ path?: string;
145
+ subItems?: { name: string; path: string }[];
146
+ label?: boolean;
147
+ }[];
148
+ brand?: boolean;
149
+ }) => {
150
+ const [windowSize, setWindowSize] = useState<number>(); // 초기값 설정
151
+ const [toggleMenu, setToggleMenu] = useState<boolean>(true);
152
+ const pathname = usePathname();
153
+ const [openSubMenu, setOpenSubMenu] = useState<Record<string, boolean>>({});
154
+
155
+ // 윈도우 사이즈 추적
156
+ useEffect(() => {
157
+ const handleResize = () => {
158
+ setWindowSize(window.innerWidth); // 윈도우 사이즈 업데이트
159
+ };
160
+
161
+ window.addEventListener("resize", handleResize); // 리사이즈 이벤트 리스너 추가
162
+
163
+ return () => window.removeEventListener("resize", handleResize); // 컴포넌트 언마운트 시 리스너 제거
164
+ }, [windowSize]);
165
+
166
+ // 초기 토글 값 설정
167
+ useEffect(() => {
168
+ if (window.innerWidth > 768) {
169
+ } else {
170
+ setToggleMenu(false);
171
+ }
172
+ }, []);
173
+
174
+ const toggleSubMenu = (menuName: string) => {
175
+ setOpenSubMenu((prev) => ({
176
+ ...prev,
177
+ [menuName]: !prev[menuName],
178
+ }));
179
+ };
180
+
181
+ return (
182
+ <nav
183
+ className={clsx(
184
+ `fixed top-0 md:relative w-full bg-[var(--background-card)] text-text-standard z-20 left-0 ${toggleMenu ? "block" : "hidden"}`,
185
+ { "h-full max-w-80 overflow-auto": type == "sidebar" },
186
+ { "h-auto flex flex-row items-center": type == "topmenu" }
187
+ )}
188
+ >
189
+ {/* brand */}
190
+ {brand ? (
191
+ <div className="brand">
192
+ <div className={`flex items-center justify-between`}>
193
+ <Link href={"/"}>
194
+ <Image
195
+ src={"/images/global/logo.png"}
196
+ alt="Logo"
197
+ width={180}
198
+ height={45}
199
+ draggable="false"
200
+ ></Image>
201
+ </Link>
202
+ <button
203
+ className={`fixed shadow-md rounded-full bg-[var(--background-card)] w-12 h-12 top-6 left-6 cursor-pointer z-50`}
204
+ onClick={() => setToggleMenu(!toggleMenu)}
205
+ >
206
+ <span
207
+ className="material-symbols-outlined text-[var(--text-standard)]"
208
+ style={{ fontSize: "16px" }}
209
+ >
210
+ menu
211
+ </span>
212
+ </button>
213
+ </div>
214
+ </div>
215
+ ) : null}
216
+ {/* List */}
217
+ <ul
218
+ className={clsx("", {
219
+ "flex flex-row": type == "topmenu",
220
+ })}
221
+ >
222
+ {navMenu.map((menu, idx) => {
223
+ switch (true) {
224
+ case menu.label === true && type == "sidebar":
225
+ return (
226
+ <p
227
+ key={menu.name + idx}
228
+ className="px-4 text-sm text-sub mt-2 mb-0"
229
+ >
230
+ {menu.name}
231
+ </p>
232
+ );
233
+ default:
234
+ if (!menu.path) return null;
235
+ return (
236
+ <li className="relative group" key={menu.name}>
237
+ <div
238
+ className={clsx("flex justify-between items-center pr-4")}
239
+ >
240
+ <Link
241
+ href={menu.path}
242
+ className={clsx(
243
+ "px-4 py-2 block text-[var(--text-standard)]",
244
+ {
245
+ "text-primary":
246
+ menu.path == pathname ||
247
+ menu.subItems?.some((sub) => sub.path === pathname),
248
+ }
249
+ )}
250
+ >
251
+ {menu.name}
252
+ </Link>
253
+ {menu.subItems && type == "sidebar" ? (
254
+ <button
255
+ className="cursor-pointer"
256
+ onClick={() => toggleSubMenu(menu.name)}
257
+ >
258
+ <span
259
+ className={clsx(
260
+ "material-symbols-outlined text-[var(--text-sub)] transition-transform",
261
+ {
262
+ "rotate-90": openSubMenu[menu.name],
263
+ }
264
+ )}
265
+ style={{ fontSize: "16px" }}
266
+ >
267
+ keyboard_arrow_right
268
+ </span>
269
+ </button>
270
+ ) : null}
271
+ </div>
272
+ {menu.subItems ? (
273
+ <ul
274
+ className={clsx(
275
+ "block",
276
+ {
277
+ "hidden absolute top-[42px] group-hover:block hover:block bg-[var(--background-card)]":
278
+ type == "topmenu",
279
+ },
280
+ {
281
+ hidden: !openSubMenu[menu.name] && type == "sidebar",
282
+ }
283
+ )}
284
+ >
285
+ {menu.subItems.map((submenu) => {
286
+ return (
287
+ <li key={submenu.name}>
288
+ <Link
289
+ className={clsx(
290
+ "px-4 py-2 block text-[var(--text-standard)]",
291
+ {
292
+ "text-primary": submenu.path == pathname,
293
+ },
294
+ { "pl-12 ": type == "sidebar" }
295
+ )}
296
+ href={submenu.path}
297
+ >
298
+ {submenu.name}
299
+ </Link>
300
+ </li>
301
+ );
302
+ })}
303
+ </ul>
304
+ ) : null}
305
+ </li>
306
+ );
307
+ }
308
+ })}
309
+ </ul>
310
+ </nav>
311
+ );
312
+ };
313
+ export default Navigation;
314
+ export { Sidebar, GlobalNav, NavToggleButton, NavItems };
package/cli/add.js CHANGED
@@ -19,7 +19,7 @@ const components = [
19
19
  "Card",
20
20
  "Collapse",
21
21
  "CodeBlock",
22
- "GlobalNav",
22
+ "Navigation",
23
23
  "Input",
24
24
  "Theme",
25
25
  "Tab",
package/cli/init.js CHANGED
@@ -103,7 +103,7 @@ inquirer
103
103
 
104
104
  if (!fs.existsSync(targetBuildDir)) mkdirSync(targetBuildDir);
105
105
  copyFileSync(buildFile, targetBuildFile);
106
- console.log(`✅ Copied: ${buildFile} -> ${targetTokenFile}`);
106
+ console.log(`✅ Copied: build-token.json -> ${targetTokenFile}`);
107
107
 
108
108
  console.log("🚀 Token setup complete!");
109
109
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atomsystem",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "type": "module",
5
5
  "homepage": "https://system.atomground.com",
6
6
  "bin": {
@@ -41,6 +41,7 @@
41
41
  "react": "^18.0.0",
42
42
  "react-dom": "^18.0.0",
43
43
  "react-modal": "^3.16.3",
44
+ "react-responsive": "^10.0.1",
44
45
  "sd-tailwindcss-transformer": "^2.0.0",
45
46
  "style-dictionary": "^4.2.0"
46
47
  },
@@ -1,199 +0,0 @@
1
- "use client";
2
- import Link from "next/link";
3
- import Image from "next/image";
4
- import { useEffect, useState } from "react";
5
- import { usePathname } from "next/navigation";
6
- import clsx from "clsx";
7
-
8
- const GlobalNav = ({
9
- type = "sidebar",
10
- navMenu,
11
- }: {
12
- type?: "sidebar" | "topmenu" | "mobile";
13
- navMenu: {
14
- name: string;
15
- path?: string;
16
- subItems?: { name: string; path: string }[];
17
- label?: boolean;
18
- }[];
19
- }) => {
20
- const [windowSize, setWindowSize] = useState<number>(); // 초기값 설정
21
- const [toggleMenu, setToggleMenu] = useState<boolean>(true);
22
- const pathname = usePathname();
23
- const [openSubMenu, setOpenSubMenu] = useState<Record<string, boolean>>({});
24
-
25
- // 윈도우 사이즈 추적
26
- useEffect(() => {
27
- const handleResize = () => {
28
- setWindowSize(window.innerWidth); // 윈도우 사이즈 업데이트
29
- };
30
-
31
- window.addEventListener("resize", handleResize); // 리사이즈 이벤트 리스너 추가
32
-
33
- return () => window.removeEventListener("resize", handleResize); // 컴포넌트 언마운트 시 리스너 제거
34
- }, [windowSize]);
35
-
36
- // 초기 토글 값 설정
37
- useEffect(() => {
38
- if (window.innerWidth > 768) {
39
- } else {
40
- setToggleMenu(false);
41
- }
42
- }, []);
43
-
44
- const toggleSubMenu = (menuName: string) => {
45
- setOpenSubMenu((prev) => ({
46
- ...prev,
47
- [menuName]: !prev[menuName],
48
- }));
49
- };
50
-
51
- return (
52
- <>
53
- <nav
54
- className={clsx(
55
- `fixed top-0 md:relative w-full bg-[var(--background-card)] text-text-standard z-20 left-0 ${toggleMenu ? "block" : "hidden"}`,
56
- { "h-full max-w-80 overflow-auto": type == "sidebar" },
57
- { "h-auto flex flex-row items-center": type == "topmenu" }
58
- )}
59
- >
60
- {/* brand */}
61
- <div className="brand">
62
- <div className="flex items-center justify-between">
63
- <Link href={"/"}>
64
- <Image
65
- src={"/images/global/logo.png"}
66
- alt="Logo"
67
- width={180}
68
- height={45}
69
- draggable="false"
70
- ></Image>
71
- </Link>
72
- {type == "sidebar" ? (
73
- <button className="p-4 cursor-pointer">
74
- <span
75
- className="material-symbols-outlined text-[var(--text-standard)]"
76
- onClick={() => setToggleMenu(false)}
77
- style={{ fontSize: "16px" }}
78
- >
79
- close
80
- </span>
81
- </button>
82
- ) : null}
83
- </div>
84
- </div>
85
-
86
- {/* List */}
87
- <ul
88
- className={clsx("", {
89
- "flex flex-row": type == "topmenu",
90
- })}
91
- >
92
- {navMenu.map((menu, idx) => {
93
- switch (true) {
94
- case menu.label === true && type == "sidebar":
95
- return (
96
- <p
97
- key={menu.name + idx}
98
- className="px-4 text-sm text-sub mt-2 mb-0"
99
- >
100
- {menu.name}
101
- </p>
102
- );
103
- default:
104
- if (!menu.path) return null;
105
- return (
106
- <li className="relative group" key={menu.name}>
107
- <div
108
- className={clsx("flex justify-between items-center pr-4")}
109
- >
110
- <Link
111
- href={menu.path}
112
- className={clsx(
113
- "px-4 py-2 block text-[var(--text-standard)]",
114
- {
115
- "text-primary":
116
- menu.path == pathname ||
117
- menu.subItems?.some(
118
- (sub) => sub.path === pathname
119
- ),
120
- }
121
- )}
122
- >
123
- {menu.name}
124
- </Link>
125
- {menu.subItems && type == "sidebar" ? (
126
- <button
127
- className="cursor-pointer"
128
- onClick={() => toggleSubMenu(menu.name)}
129
- >
130
- <span
131
- className={clsx(
132
- "material-symbols-outlined text-[var(--text-sub)] transition-transform",
133
- {
134
- "rotate-90": openSubMenu[menu.name],
135
- }
136
- )}
137
- style={{ fontSize: "16px" }}
138
- >
139
- keyboard_arrow_right
140
- </span>
141
- </button>
142
- ) : null}
143
- </div>
144
- {menu.subItems ? (
145
- <ul
146
- className={clsx(
147
- "block",
148
- {
149
- "hidden absolute top-[42px] group-hover:block hover:block bg-[var(--background-card)]":
150
- type == "topmenu",
151
- },
152
- {
153
- hidden:
154
- !openSubMenu[menu.name] && type == "sidebar",
155
- }
156
- )}
157
- >
158
- {menu.subItems.map((submenu) => {
159
- return (
160
- <li key={submenu.name}>
161
- <Link
162
- className={clsx(
163
- "px-4 py-2 block text-[var(--text-standard)]",
164
- {
165
- "text-primary": submenu.path == pathname,
166
- },
167
- { "pl-12 ": type == "sidebar" }
168
- )}
169
- href={submenu.path}
170
- >
171
- {submenu.name}
172
- </Link>
173
- </li>
174
- );
175
- })}
176
- </ul>
177
- ) : null}
178
- </li>
179
- );
180
- }
181
- })}
182
- </ul>
183
- </nav>
184
- <button
185
- className={`fixed shadow-md rounded-full bg-[var(--background-card)] w-12 h-12 top-6 left-6 z-10 cursor-pointer ${toggleMenu ? "hidden" : "block"} `}
186
- onClick={() => setToggleMenu(true)}
187
- >
188
- <span
189
- className="material-symbols-outlined text-[var(--text-standard)]"
190
- style={{ fontSize: "16px" }}
191
- >
192
- menu
193
- </span>
194
- </button>
195
- </>
196
- );
197
- };
198
-
199
- export default GlobalNav;