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,207 +0,0 @@
1
- "use client";
2
-
3
- import { createContext, useContext, useState, ReactNode, useRef } from "react";
4
- import gsap from 'gsap';
5
- import { useGSAP } from '@gsap/react';
6
-
7
- gsap.registerPlugin(useGSAP);
8
-
9
- // Types
10
- export interface CollapseProps {
11
- children: ReactNode;
12
- type?: "accordion" | "collapse";
13
- defaultActiveKeys?: (string | number)[];
14
- }
15
-
16
- interface CollapseContextValue {
17
- type: "accordion" | "collapse";
18
- activeKeys: Set<string | number>;
19
- toggle: (key: string | number) => void;
20
- }
21
-
22
- const CollapseContext = createContext<CollapseContextValue | undefined>(undefined);
23
-
24
- const useCollapseContext = () => {
25
- const context = useContext(CollapseContext);
26
- if (!context) {
27
- return { type: "collapse" as const, activeKeys: new Set<string | number>(), toggle: () => {} };
28
- }
29
- return context;
30
- };
31
-
32
- // Provider
33
- const CollapseProvider = ({
34
- children,
35
- type = "collapse",
36
- defaultActiveKeys = []
37
- }: CollapseProps) => {
38
- const [activeKeys, setActiveKeys] = useState<Set<string | number>>(new Set(defaultActiveKeys));
39
-
40
- const toggle = (key: string | number) => {
41
- setActiveKeys((prev) => {
42
- const next = new Set(prev);
43
- if (next.has(key)) {
44
- next.delete(key);
45
- } else {
46
- if (type === "accordion") {
47
- next.clear();
48
- }
49
- next.add(key);
50
- }
51
- return next;
52
- });
53
- };
54
-
55
- return (
56
- <CollapseContext.Provider value={{ type, activeKeys, toggle }}>
57
- {children}
58
- </CollapseContext.Provider>
59
- );
60
- };
61
-
62
- // Root Container
63
- const Collapse = ({ children, className }: { children: ReactNode; className?: string }) => {
64
- return <div className={`collapse-group ${className || ""}`}>{children}</div>;
65
- };
66
-
67
- // Item Context for child components
68
- const ItemContext = createContext<{ value: string | number } | undefined>(undefined);
69
- const useItemContext = () => {
70
- const context = useContext(ItemContext);
71
- if (!context) throw new Error("Collapse sub-components must be used within CollapseItem");
72
- return context;
73
- };
74
-
75
- const CollapseItem = ({
76
- value,
77
- children,
78
- className
79
- }: {
80
- value: string | number;
81
- children: ReactNode;
82
- className?: string;
83
- }) => {
84
- const { activeKeys } = useCollapseContext();
85
- const isOpen = activeKeys.has(value);
86
-
87
- return (
88
- <ItemContext.Provider value={{ value }}>
89
- <div
90
- className={`collapse-item ${isOpen ? "open" : "closed"} ${className || ""}`}
91
- data-state={isOpen ? "open" : "closed"}
92
- >
93
- {children}
94
- </div>
95
- </ItemContext.Provider>
96
- );
97
- };
98
-
99
- const CollapseHeader = ({
100
- children,
101
- className
102
- }: {
103
- children: ReactNode;
104
- className?: string;
105
- }) => {
106
- const { value } = useItemContext();
107
- const { activeKeys, toggle } = useCollapseContext();
108
- const isOpen = activeKeys.has(value);
109
- const iconRef = useRef<HTMLSpanElement>(null);
110
-
111
- useGSAP(() => {
112
- if (iconRef.current) {
113
- gsap.to(iconRef.current, {
114
- rotation: isOpen ? 90 : 0,
115
- duration: 0.4,
116
- ease: "power2.inOut",
117
- overwrite: true
118
- });
119
- }
120
- }, [isOpen]);
121
-
122
- return (
123
- <div
124
- className={`collapse-header cursor-pointer flex items-center justify-between ${className || ""}`}
125
- onClick={() => toggle(value)}
126
- >
127
- {children}
128
- <span
129
- ref={iconRef}
130
- className="material-symbols-outlined collapse-icon"
131
- >
132
- keyboard_arrow_right
133
- </span>
134
- </div>
135
- );
136
- };
137
-
138
- const CollapseContent = ({
139
- children,
140
- className
141
- }: {
142
- children: ReactNode;
143
- className?: string;
144
- }) => {
145
- const { value } = useItemContext();
146
- const { activeKeys } = useCollapseContext();
147
- const isOpen = activeKeys.has(value);
148
- const contentRef = useRef<HTMLDivElement>(null);
149
-
150
- useGSAP(() => {
151
- if (!contentRef.current) return;
152
-
153
- if (isOpen) {
154
- // 열기: 현재 높이가 0이거나 display: none인 상태에서도 부드럽게 시작할 수 있도록 처리
155
- gsap.fromTo(contentRef.current,
156
- { height: 0, opacity: 0, display: "block" },
157
- {
158
- height: "auto",
159
- opacity: 1,
160
- duration: 0.4,
161
- ease: "power2.out",
162
- overwrite: true,
163
- onComplete: () => {
164
- // 애니메이션 완료 후 height를 auto로 고정하여 반응형 대응
165
- if (contentRef.current) {
166
- gsap.set(contentRef.current, { clearProps: "height" });
167
- }
168
- }
169
- }
170
- );
171
- } else {
172
- // 닫기
173
- gsap.to(contentRef.current, {
174
- height: 0,
175
- opacity: 0,
176
- duration: 0.3,
177
- ease: "power2.inOut",
178
- overwrite: true,
179
- onComplete: () => {
180
- if (contentRef.current && !isOpen) {
181
- gsap.set(contentRef.current, { display: "none" });
182
- }
183
- }
184
- });
185
- }
186
- }, [isOpen]);
187
-
188
- return (
189
- <div
190
- ref={contentRef}
191
- className={`collapse-content overflow-hidden ${className || ""}`}
192
- style={{ height: 0, opacity: 0, display: "none" }}
193
- >
194
- <div style={{ padding: "var(--spacing-common-x)" }}>
195
- {children}
196
- </div>
197
- </div>
198
- );
199
- };
200
-
201
- export {
202
- Collapse,
203
- CollapseProvider,
204
- CollapseItem,
205
- CollapseHeader,
206
- CollapseContent
207
- };
@@ -1,24 +0,0 @@
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
- color: var(--text-standard);
18
- display: inline-block; /* 회전 중심을 위해 적용 */
19
- }
20
-
21
- .collapse-content {
22
- color: var(--text-standard);
23
- font-size: var(--text-body);
24
- }
@@ -1,112 +0,0 @@
1
- .dropdown-container {
2
- position: relative;
3
- display: inline-block;
4
- }
5
-
6
- .dropdown-trigger {
7
- cursor: pointer;
8
- display: flex;
9
- }
10
-
11
- .dropdown-content {
12
- position: absolute;
13
- z-index: 100;
14
- background-color: var(--bg-card);
15
- border: 1px solid var(--border-standard);
16
- border-radius: 12px;
17
- box-shadow: 0 10px 30px -5px rgba(0, 0, 0, 0.1), 0 8px 15px -6px rgba(0, 0, 0, 0.08);
18
- padding: 1rem;
19
- min-width: 200px;
20
- opacity: 0;
21
- visibility: hidden;
22
- transform: scale(0.95) translateY(10px);
23
- transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
24
- pointer-events: none;
25
- background-clip: padding-box;
26
- }
27
-
28
- .dropdown-content.is-open {
29
- opacity: 1;
30
- visibility: visible;
31
- transform: scale(1) translateY(0);
32
- pointer-events: auto;
33
- }
34
-
35
- /* Positions with directional scaling */
36
- .dropdown-content.bottom-right {
37
- top: 100%;
38
- right: 0;
39
- margin-top: 12px;
40
- transform-origin: top right;
41
- }
42
-
43
- .dropdown-content.bottom-left {
44
- top: 100%;
45
- left: 0;
46
- margin-top: 12px;
47
- transform-origin: top left;
48
- }
49
-
50
- .dropdown-content.top-right {
51
- bottom: 100%;
52
- right: 0;
53
- margin-bottom: 12px;
54
- transform-origin: bottom right;
55
- }
56
-
57
- .dropdown-content.top-left {
58
- bottom: 100%;
59
- left: 0;
60
- margin-bottom: 12px;
61
- transform-origin: bottom left;
62
- }
63
-
64
- /* Premium Blur and Dark Mode Polish */
65
- @supports (backdrop-filter: blur(20px)) {
66
- .dropdown-content {
67
- background-color: rgba(var(--dropdown-bg, 255, 255, 255), 0.85);
68
- backdrop-filter: blur(20px);
69
- }
70
- }
71
-
72
- .dark .dropdown-content {
73
- --dropdown-bg: 34, 34, 34;
74
- background-color: rgba(34, 34, 34, 0.85);
75
- box-shadow: 0 20px 40px -5px rgba(0, 0, 0, 0.4), 0 10px 20px -5px rgba(0, 0, 0, 0.3);
76
- border-color: rgba(255, 255, 255, 0.08);
77
- }
78
-
79
- .dropdown-item {
80
- display: flex;
81
- align-items: center;
82
- gap: var(--spacing-gap-small);
83
- padding: var(--spacing-sm-y, 8px) var(--spacing-common-x);
84
- border-radius: var(--radius-common);
85
- cursor: pointer;
86
- transition: all 0.2s ease;
87
- border: 1px solid transparent;
88
- color: var(--text-standard);
89
- }
90
-
91
-
92
- .dropdown-item:hover {
93
- background-color: var(--color-gray-100);
94
- border-color: var(--color-gray-200);
95
- }
96
-
97
- .dark .dropdown-item:hover {
98
- background-color: var(--color-dark-400);
99
- border-color: var(--color-dark-500);
100
- }
101
-
102
- .dropdown-item:active {
103
- background-color: var(--color-gray-200);
104
- transform: scale(0.98);
105
- }
106
-
107
- .dark .dropdown-item:active {
108
- background-color: var(--color-dark-500);
109
- }
110
-
111
-
112
-
@@ -1,103 +0,0 @@
1
- "use client";
2
-
3
- import { useEffect, useRef, useState } from "react";
4
- import clsx from "clsx";
5
- import "./Dropdown.css";
6
-
7
- type DropdownPosition = "bottom-right" | "bottom-left" | "top-right" | "top-left";
8
-
9
- interface DropdownProps {
10
- trigger: React.ReactNode;
11
- children: React.ReactNode;
12
- className?: string;
13
- contentClassName?: string;
14
- position?: DropdownPosition;
15
- isOpen?: boolean;
16
- onOpenChange?: (open: boolean) => void;
17
- }
18
-
19
- export const Dropdown = ({
20
- trigger,
21
- children,
22
- className,
23
- contentClassName,
24
- position = "bottom-right",
25
- isOpen: controlledIsOpen,
26
- onOpenChange,
27
- }: DropdownProps) => {
28
- const [internalIsOpen, setInternalIsOpen] = useState(false);
29
- const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;
30
-
31
- const dropdownRef = useRef<HTMLDivElement>(null);
32
-
33
- const toggle = () => {
34
- const nextValue = !isOpen;
35
- if (controlledIsOpen === undefined) {
36
- setInternalIsOpen(nextValue);
37
- }
38
- onOpenChange?.(nextValue);
39
- };
40
-
41
- const close = () => {
42
- if (controlledIsOpen === undefined) {
43
- setInternalIsOpen(false);
44
- }
45
- onOpenChange?.(false);
46
- };
47
-
48
- useEffect(() => {
49
- const handleClickOutside = (event: MouseEvent) => {
50
- if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
51
- close();
52
- }
53
- };
54
-
55
- if (isOpen) {
56
- document.addEventListener("mousedown", handleClickOutside);
57
- } else {
58
- document.removeEventListener("mousedown", handleClickOutside);
59
- }
60
-
61
- return () => {
62
- document.removeEventListener("mousedown", handleClickOutside);
63
- };
64
- }, [isOpen]);
65
-
66
- return (
67
- <div className={clsx("dropdown-container", className)} ref={dropdownRef}>
68
- <div className="dropdown-trigger" onClick={toggle}>
69
- {trigger}
70
- </div>
71
- <div
72
- className={clsx(
73
- "dropdown-content",
74
- position,
75
- isOpen && "is-open",
76
- contentClassName
77
- )}
78
- >
79
- {children}
80
- </div>
81
- </div>
82
- );
83
- };
84
-
85
- export const DropdownItem = ({
86
- children,
87
- className,
88
- onClick,
89
- }: {
90
- children: React.ReactNode;
91
- className?: string;
92
- onClick?: () => void;
93
- }) => {
94
- return (
95
- <div
96
- className={clsx("dropdown-item", className)}
97
- onClick={onClick}
98
- >
99
- {children}
100
- </div>
101
- );
102
- };
103
-