atomsystem 0.1.47 → 0.1.49

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.
Files changed (62) hide show
  1. package/README.md +153 -55
  2. package/atom.design.md +155 -0
  3. package/atom.uxPattern.md +431 -0
  4. package/components/ui/Badge.tsx +20 -0
  5. package/components/ui/Button.tsx +33 -0
  6. package/components/ui/Card.tsx +20 -0
  7. package/components/ui/Input.tsx +35 -0
  8. package/components/ui/Modal.tsx +54 -0
  9. package/components/ui/index.ts +5 -0
  10. package/css/atom-ui.css +216 -0
  11. package/dist/cli.cjs +105 -0
  12. package/dist/cli.cjs.map +1 -0
  13. package/dist/cli.d.cts +1 -0
  14. package/dist/cli.d.ts +1 -0
  15. package/dist/cli.js +97 -0
  16. package/dist/cli.js.map +1 -0
  17. package/dist/index.cjs +7897 -0
  18. package/dist/index.cjs.map +1 -0
  19. package/dist/index.d.cts +218 -0
  20. package/dist/index.d.ts +218 -0
  21. package/dist/index.js +7845 -447
  22. package/dist/index.js.map +1 -0
  23. package/package.json +120 -81
  24. package/presets/default.design.md +155 -0
  25. package/presets/uxPattern.md +431 -0
  26. package/skills/atomsystem.skill.md +104 -0
  27. package/tokens/token.json +319 -0
  28. package/tokens/tokens.json +318 -976
  29. package/app/templates/Animations/Animation.tsx +0 -282
  30. package/app/templates/Badge/Badge.tsx +0 -28
  31. package/app/templates/Badge/badge.css +0 -28
  32. package/app/templates/Button/Button.tsx +0 -31
  33. package/app/templates/Button/button.css +0 -135
  34. package/app/templates/Card/Card.tsx +0 -50
  35. package/app/templates/Card/card.css +0 -17
  36. package/app/templates/CodeBlock/CodeBlock.tsx +0 -68
  37. package/app/templates/Collapse/Collapse.tsx +0 -207
  38. package/app/templates/Collapse/collapse.css +0 -24
  39. package/app/templates/Dropdown/Dropdown.css +0 -112
  40. package/app/templates/Dropdown/Dropdown.tsx +0 -103
  41. package/app/templates/Form/Form.tsx +0 -289
  42. package/app/templates/Form/form.css +0 -115
  43. package/app/templates/Modal/Modal.tsx +0 -71
  44. package/app/templates/Modal/modal.css +0 -98
  45. package/app/templates/Navigation/Navigation.tsx +0 -169
  46. package/app/templates/Navigation/navigation.css +0 -59
  47. package/app/templates/Pagination/Pagination.tsx +0 -104
  48. package/app/templates/Pagination/pagination.css +0 -66
  49. package/app/templates/Sidebar/Sidebar.tsx +0 -139
  50. package/app/templates/Sidebar/sidebar.css +0 -4
  51. package/app/templates/TOC/TOC.tsx +0 -165
  52. package/app/templates/Tab/Tab.tsx +0 -117
  53. package/app/templates/Tab/tab.css +0 -56
  54. package/app/templates/Table/Table.tsx +0 -54
  55. package/app/templates/Table/table.css +0 -58
  56. package/app/templates/Theme/Theme.tsx +0 -121
  57. package/app/templates/Toast/Toast.tsx +0 -106
  58. package/app/templates/Toast/toast.css +0 -69
  59. package/build/build-tokens.js +0 -223
  60. package/build/css/_variables.css +0 -251
  61. package/build/typescript/theme.ts +0 -6
  62. package/css/text.css +0 -18
@@ -1,282 +0,0 @@
1
- "use client";
2
- import { ReactNode, useEffect, useRef, useState } from "react";
3
- import gsap from "gsap";
4
- import { ScrollTrigger } from "gsap/ScrollTrigger";
5
- import { ScrollToPlugin } from "gsap/ScrollToPlugin";
6
- import { useGSAP } from "@gsap/react";
7
-
8
- gsap.registerPlugin(ScrollTrigger, ScrollToPlugin, useGSAP);
9
-
10
- export const UpAnimation = ({
11
- children,
12
- trigger,
13
- toggleActions = "play none reverse none",
14
- overflow = "overflow-hidden",
15
- stagger,
16
- className,
17
- markers,
18
- AnimationContainer,
19
- }: {
20
- children: ReactNode;
21
- trigger?: string | HTMLElement;
22
- toggleActions?: string;
23
- overflow?: string;
24
- className?: string;
25
- stagger?: boolean;
26
- markers?: boolean;
27
- AnimationContainer?: gsap.core.Animation | undefined;
28
- }) => {
29
- const animationRef = useRef<HTMLDivElement>(null);
30
-
31
- useGSAP(
32
- () => {
33
- if (!animationRef.current) return;
34
-
35
- const target = stagger
36
- ? animationRef.current.children
37
- : animationRef.current;
38
-
39
- gsap.set(target, { y: 500, opacity: 0 }); // 초기 상태 설정
40
-
41
- gsap.fromTo(
42
- target,
43
- {
44
- y: 500,
45
- opacity: 0,
46
- },
47
- {
48
- y: 0,
49
- opacity: 1,
50
- stagger: 0.2,
51
- duration: 3,
52
- ease: "power4.out",
53
- scrollTrigger: {
54
- trigger: trigger ? trigger : animationRef.current,
55
- start: "top center",
56
- end: "bottom bottom",
57
- toggleActions: toggleActions,
58
- markers: markers,
59
- invalidateOnRefresh: true,
60
- containerAnimation: AnimationContainer,
61
- },
62
- }
63
- );
64
- },
65
- {
66
- dependencies: [
67
- trigger,
68
- toggleActions,
69
- markers,
70
- stagger,
71
- AnimationContainer,
72
- ],
73
- }
74
- );
75
-
76
- return stagger ? (
77
- <div ref={animationRef} className={`${overflow} ${className}`}>
78
- {children}
79
- </div>
80
- ) : (
81
- <div className={`${overflow} ${className}`}>
82
- <div ref={animationRef}>{children}</div>
83
- </div>
84
- );
85
- };
86
-
87
- export const MaskAnimation = ({
88
- children,
89
- trigger,
90
- maskColor,
91
- markers,
92
- }: {
93
- children: ReactNode;
94
- maskColor: string;
95
- trigger?: string;
96
- markers?: boolean;
97
- }) => {
98
- const animationRef = useRef<HTMLDivElement>(null);
99
- const [maskSize, setMaskSize] = useState<number>(0);
100
-
101
- // 리사이즈 핸들러
102
- const updateMaskSize = () => {
103
- if (animationRef.current) {
104
- setMaskSize(animationRef.current.offsetWidth);
105
- }
106
- };
107
-
108
- useEffect(() => {
109
- updateMaskSize(); // 초기 사이즈 설정
110
-
111
- window.addEventListener("resize", updateMaskSize);
112
- return () => {
113
- window.removeEventListener("resize", updateMaskSize);
114
- };
115
- }, []);
116
-
117
- useGSAP(
118
- () => {
119
- if (!animationRef.current) return;
120
-
121
- setMaskSize(animationRef.current.offsetWidth);
122
-
123
- gsap.fromTo(
124
- animationRef.current,
125
- {
126
- left: 0,
127
- },
128
- {
129
- left: -maskSize,
130
- stagger: 0.2,
131
- duration: 3,
132
- ease: "power4.out",
133
- scrollTrigger: {
134
- trigger: trigger ? trigger : animationRef.current,
135
- start: "top center",
136
- end: "bottom bottom",
137
- toggleActions: "play none none none",
138
- markers: markers,
139
- invalidateOnRefresh: true,
140
- },
141
- }
142
- );
143
- },
144
- { dependencies: [maskSize, trigger] }
145
- );
146
-
147
- return (
148
- <div className="relative overflow-hidden">
149
- <div>{children}</div>
150
- <div
151
- ref={animationRef}
152
- className={`absolute top-0 w-full h-full ${maskColor} z-20`}
153
- ></div>
154
- </div>
155
- );
156
- };
157
-
158
- export const SlidAnimation = ({ children }: { children: React.ReactNode }) => {
159
- const slideRef = useRef<HTMLDivElement>(null);
160
- const [slideX, setSlideX] = useState(0);
161
-
162
- useGSAP(
163
- () => {
164
- if (!slideRef.current) return;
165
-
166
- if (!slideRef.current) return;
167
- setSlideX(slideRef.current.offsetWidth / 2);
168
-
169
- gsap.to(slideRef.current, {
170
- x: -slideX,
171
- duration: 40,
172
- repeat: -1,
173
- ease: "none",
174
- });
175
- },
176
- { dependencies: [slideX], scope: slideRef }
177
- );
178
-
179
- return (
180
- <div ref={slideRef} className="flex gap-0 flex-nowrap">
181
- {children}
182
- {children}
183
- </div>
184
- );
185
- };
186
-
187
- export const HorizonScroll = ({
188
- children,
189
- callbackTween,
190
- }: {
191
- children: React.ReactNode;
192
- callbackTween?: (tween: gsap.core.Tween) => void;
193
- }) => {
194
- const horizonRef = useRef<HTMLDivElement>(null);
195
- const horizonWrapperRef = useRef<HTMLDivElement>(null);
196
-
197
- useGSAP(() => {
198
- if (!horizonWrapperRef.current) return;
199
- if (!horizonRef.current) return;
200
-
201
- const isLarge = window.matchMedia("(min-width: 640px)").matches;
202
- if (!isLarge) return; // lg 미만이면 애니메이션 적용 안 함
203
-
204
- const horizonWrapper = horizonWrapperRef.current;
205
- const horizon = horizonRef.current;
206
-
207
- const horizonTween = gsap.to(horizon, {
208
- x: () => -1 * (horizonWrapper.scrollWidth - innerWidth),
209
- ease: "none",
210
- scrollTrigger: {
211
- trigger: horizonWrapperRef.current,
212
- pin: true,
213
- start: "top top",
214
- scrub: 1,
215
- end: () => "+=" + (horizon.scrollWidth - innerWidth),
216
- invalidateOnRefresh: true,
217
- // markers: true,
218
- },
219
- });
220
-
221
- if (callbackTween && isLarge && horizonTween) {
222
- callbackTween(horizonTween);
223
- }
224
- }, [callbackTween]);
225
-
226
- return (
227
- <div
228
- ref={horizonWrapperRef}
229
- className="w-full h-full relative overflow-hidden"
230
- >
231
- <div
232
- className="flex flex-col sm:flex-row flex-nowrap translate-x-0 w-full"
233
- ref={horizonRef}
234
- >
235
- {children}
236
- </div>
237
- </div>
238
- );
239
- };
240
-
241
- export const HorizonScrollNav = ({
242
- sections,
243
- listClass,
244
- }: {
245
- sections: { id: string; title: string }[];
246
- listClass?: string;
247
- }) => {
248
- const scrollToSection = (id: string) => {
249
- const el = document.getElementById(id);
250
- if (!el) return;
251
-
252
- const index = sections.findIndex((section) => section.id === id);
253
- if (index === -1) return;
254
-
255
- const isLarge = window.matchMedia("(min-width: 640px)").matches;
256
- const scrollPos = isLarge ? el.offsetLeft : el.offsetTop;
257
-
258
- gsap.to(window, {
259
- scrollTo: {
260
- y: scrollPos,
261
- autoKill: false,
262
- },
263
- duration: 1,
264
- });
265
- };
266
- return (
267
- <ul className={`${listClass}`}>
268
- {sections.map((section, index) => {
269
- return (
270
- <li key={index}>
271
- <button
272
- className="cursor-pointer text-sm"
273
- onClick={() => scrollToSection(section.id)}
274
- >
275
- {section.title}
276
- </button>
277
- </li>
278
- );
279
- })}
280
- </ul>
281
- );
282
- };
@@ -1,28 +0,0 @@
1
- export const Badge = ({
2
- children,
3
- color,
4
- type,
5
- }: {
6
- children: React.ReactNode;
7
- color: "primary" | "secondary" | "warning" | "danger";
8
- type?: "default" | "tint";
9
- }) => {
10
- switch (type) {
11
- case "tint":
12
- return (
13
- <span
14
- className={`badge-tint ${color}`}
15
- >
16
- {children}
17
- </span>
18
- );
19
- default:
20
- return (
21
- <span
22
- className={`badge ${color}`}
23
- >
24
- {children}
25
- </span>
26
- );
27
- }
28
- };
@@ -1,28 +0,0 @@
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
- }
@@ -1,31 +0,0 @@
1
- "use client";
2
- import clsx from "clsx";
3
-
4
- export const Button = ({
5
- children,
6
- type = "primary",
7
- size = "md",
8
- className,
9
- style,
10
- disabled,
11
- onClick,
12
- }: {
13
- children: React.ReactNode;
14
- type?: "primary" | "secondary" | "success" | "warning" | "danger" | "gray" | "outline";
15
- size?: "sm" | "md" | "lg";
16
- className?: string;
17
- style?: React.CSSProperties;
18
- disabled?: boolean;
19
- onClick?: () => void;
20
- }) => {
21
- return (
22
- <button
23
- className={clsx("btn", type, size, className)}
24
- style={style}
25
- disabled={disabled}
26
- onClick={onClick}
27
- >
28
- {children}
29
- </button>
30
- );
31
- };
@@ -1,135 +0,0 @@
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
- background-color: var(--color-primary);
13
- color: var(--color-white);
14
- }
15
- .btn.primary:hover:not(:disabled) {
16
- background-color: var(--color-blue-600);
17
- }
18
- .btn.primary:active:not(:disabled) {
19
- background-color: var(--color-blue-700);
20
- }
21
- .btn.primary:disabled {
22
- background-color: var(--button-primary-bg-disabled);
23
- color: var(--button-primary-text-disabled);
24
- border: 1px solid var(--button-primary-border-disabled);
25
- }
26
-
27
- .btn.secondary {
28
- background-color: var(--color-secondary);
29
- color: var(--color-white);
30
- }
31
- .btn.secondary:hover:not(:disabled) {
32
- background-color: var(--color-indigo-600);
33
- }
34
- .btn.secondary:active:not(:disabled) {
35
- background-color: var(--color-indigo-700);
36
- }
37
- .btn.secondary:disabled {
38
- background-color: var(--button-secondary-bg-disabled);
39
- color: var(--button-secondary-text-disabled);
40
- border: 1px solid var(--button-secondary-border-disabled);
41
- }
42
-
43
- .btn.success {
44
- background-color: var(--color-success);
45
- color: var(--color-white);
46
- }
47
- .btn.success:hover:not(:disabled) {
48
- background-color: var(--color-green-600);
49
- }
50
- .btn.success:active:not(:disabled) {
51
- background-color: var(--color-green-700);
52
- }
53
- .btn.success:disabled {
54
- background-color: var(--button-success-bg-disabled);
55
- color: var(--button-success-text-disabled);
56
- border: 1px solid var(--button-success-border-disabled);
57
- }
58
-
59
- .btn.warning {
60
- background-color: var(--color-warning);
61
- color: var(--color-white);
62
- }
63
- .btn.warning:hover:not(:disabled) {
64
- background-color: var(--color-yellow-600);
65
- }
66
- .btn.warning:active:not(:disabled) {
67
- background-color: var(--color-yellow-700);
68
- }
69
- .btn.warning:disabled {
70
- background-color: var(--button-warning-bg-disabled);
71
- color: var(--button-warning-text-disabled);
72
- border: 1px solid var(--button-warning-border-disabled);
73
- }
74
-
75
- .btn.danger {
76
- background-color: var(--color-danger);
77
- color: var(--color-white);
78
- }
79
- .btn.danger:hover:not(:disabled) {
80
- background-color: var(--color-red-600);
81
- }
82
- .btn.danger:active:not(:disabled) {
83
- background-color: var(--color-red-700);
84
- }
85
- .btn.danger:disabled {
86
- background-color: var(--button-danger-bg-disabled);
87
- color: var(--button-danger-text-disabled);
88
- border: 1px solid var(--button-danger-border-disabled);
89
- }
90
-
91
- .btn.gray {
92
- background-color: var(--color-gray-500);
93
- color: var(--color-white);
94
- }
95
- .btn.gray:hover:not(:disabled) {
96
- background-color: var(--color-gray-600);
97
- }
98
- .btn.gray:active:not(:disabled) {
99
- background-color: var(--color-gray-700);
100
- }
101
- .btn.gray:disabled {
102
- background-color: var(--button-gray-bg-disabled);
103
- color: var(--button-gray-text-disabled);
104
- border: 1px solid var(--button-gray-border-disabled);
105
- }
106
-
107
- .btn.outline {
108
- background-color: transparent;
109
- border: 1px solid var(--color-border-standard);
110
- color: var(--color-text-body);
111
- }
112
- .btn.outline:hover:not(:disabled) {
113
- background-color: var(--color-bg-hover);
114
- }
115
- .btn.outline:active:not(:disabled) {
116
- background-color: var(--color-bg-input-standard);
117
- }
118
-
119
- .btn.sm {
120
- padding: var(--spacing-sm-y) var(--spacing-common-x);
121
- font-size: var(--text-sm);
122
- }
123
- .btn.md {
124
- padding: var(--spacing-common-y) var(--spacing-common-x);
125
- font-size: var(--text-body);
126
- }
127
- .btn.lg {
128
- padding: var(--spacing-small) var(--spacing-common-x);
129
- font-size: var(--text-h6);
130
- }
131
-
132
- .btn:disabled {
133
- cursor: not-allowed;
134
- opacity: 0.7;
135
- }
@@ -1,50 +0,0 @@
1
- import React from "react";
2
-
3
- export const Card = ({
4
- children,
5
- className = "",
6
- overflow = "overflow-auto",
7
- }: {
8
- children: React.ReactNode;
9
- className?: string;
10
- type?: "standard" | "group";
11
- overflow?: "overflow-auto" | "overflow-hidden" | "overflow-none";
12
- }) => {
13
- return (
14
- <div
15
- className={`card ${className} ${overflow}`}
16
- >
17
- {children}
18
- </div>
19
- );
20
- };
21
-
22
- export const CardHeader = ({
23
- children,
24
- noMargin,
25
- }: {
26
- children: React.ReactNode;
27
- noMargin?: boolean;
28
- }) => {
29
- return <div className={`card-header ${noMargin ? "no-margin" : ""}`}>{children}</div>;
30
- };
31
-
32
- export const CardContent = ({
33
- children,
34
- noMargin,
35
- }: {
36
- children: React.ReactNode;
37
- noMargin?: boolean;
38
- }) => {
39
- return <div className={`card-content ${noMargin ? "no-margin" : ""}`}>{children}</div>;
40
- };
41
-
42
- export const CardFooter = ({
43
- children,
44
- noMargin,
45
- }: {
46
- children: React.ReactNode;
47
- noMargin?: boolean;
48
- }) => {
49
- return <div className={`card-footer ${noMargin ? "no-margin" : ""}`}>{children}</div>;
50
- };
@@ -1,17 +0,0 @@
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
- }
@@ -1,68 +0,0 @@
1
- "use client";
2
- import { useEffect, useRef, useState } from "react";
3
- import hljs from "highlight.js";
4
- import "highlight.js/styles/atom-one-dark.css"; // 스타일 파일
5
-
6
- const CodeBlock = ({
7
- language,
8
- children,
9
- }: {
10
- language: string;
11
- children: React.ReactNode;
12
- }) => {
13
- const codeRef = useRef<HTMLElement | null>(null);
14
- const [copied, setCopied] = useState(false);
15
- const [isHeightCheck, setHeightCheck] = useState(false);
16
- const [isOpen, setIsOpen] = useState(false);
17
-
18
- useEffect(() => {
19
- if (codeRef.current) {
20
- hljs.highlightElement(codeRef.current); // 코드 블록 하이라이트
21
-
22
- if (codeRef.current.offsetHeight >= 300) {
23
- setHeightCheck(true);
24
- }
25
- }
26
- }, [children]);
27
-
28
- const handleCopy = async () => {
29
- if (!codeRef.current) return;
30
-
31
- try {
32
- await navigator.clipboard.writeText(codeRef.current.innerText);
33
- setCopied(true);
34
- setTimeout(() => setCopied(false), 1500); // 1.5초 후 메시지 제거
35
- } catch (err) {
36
- console.error("복사 실패:", err);
37
- }
38
- };
39
-
40
- return (
41
- <div className="relative">
42
- <pre className={`${isOpen ? "max-h-fit" : "max-h-60"} overflow-hidden`}>
43
- <code ref={codeRef} className={language}>
44
- {children}
45
- </code>
46
- </pre>
47
-
48
- <button
49
- onClick={handleCopy}
50
- className="absolute top-2 right-2 bg-[var(--color-bg-card)] hover:bg-[var(--color-bg-wrapper)] text-[var(--text-standard)] text-xs px-2 py-1 rounded cursor-pointer "
51
- >
52
- {copied ? "Copied!" : "Copy"}
53
- </button>
54
-
55
- {isHeightCheck ? (
56
- <button
57
- onClick={() => setIsOpen(!isOpen)}
58
- className="
59
- w-full cursor-pointer hover:bg-[var(--color-bg-wrapper)] text-center py-2 px-8"
60
- >
61
- {isOpen ? "Close" : "Open"}
62
- </button>
63
- ) : null}
64
- </div>
65
- );
66
- };
67
-
68
- export default CodeBlock;