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,289 +0,0 @@
1
- "use client";
2
- import clsx from "clsx";
3
- import { useEffect, useLayoutEffect, useRef, useState } from "react";
4
- import { createPortal } from "react-dom";
5
-
6
- export const Label = ({
7
- label,
8
- required,
9
- }: {
10
- label: string;
11
- required?: boolean;
12
- }) => {
13
- return (
14
- <p className={"mb-1 text-text-standard"}>
15
- <span
16
- className={clsx("", {
17
- "after:content-['*'] after:ml-1 after:text-danger": required,
18
- })}
19
- >
20
- {label}
21
- </span>
22
- </p>
23
- );
24
- };
25
-
26
- export const Input = ({
27
- type = "text",
28
- placeholder = "값을 입력해주세요",
29
- readOnly,
30
- disabled,
31
- required,
32
- }: {
33
- type?: string;
34
- className?: string;
35
- placeholder?: string;
36
- readOnly?: boolean;
37
- disabled?: boolean;
38
- required?: boolean;
39
- }) => {
40
- return (
41
- <input
42
- className="input"
43
- type={type}
44
- placeholder={placeholder}
45
- readOnly={readOnly}
46
- disabled={disabled}
47
- required={required}
48
- />
49
- );
50
- };
51
-
52
- export const Select = ({
53
- options = [],
54
- disabled,
55
- }: {
56
- options: string[];
57
- disabled?: boolean;
58
- }) => {
59
- const [filterValue, setFilterValue] = useState("");
60
- const [isOpen, setIsOpen] = useState(false);
61
- const [menuPosition, setMenuPosition] = useState({
62
- top: 0,
63
- left: 0,
64
- width: 0,
65
- });
66
- const inputRef = useRef<HTMLInputElement>(null);
67
- const dropdownRef = useRef<HTMLUListElement>(null);
68
- const filteredOptions = options.filter((option) =>
69
- option.toLowerCase().includes(filterValue.toLowerCase())
70
- );
71
-
72
- useLayoutEffect(() => {
73
- if (isOpen && inputRef.current && dropdownRef.current) {
74
- const rect = inputRef.current.getBoundingClientRect();
75
- const dropdownRect = dropdownRef.current.getBoundingClientRect();
76
-
77
- if (Math.abs(menuPosition.width - rect.width) > 0.5) {
78
- setMenuPosition({
79
- top: rect.bottom + window.scrollY,
80
- left: rect.left,
81
- width: rect.width,
82
- });
83
- return;
84
- }
85
-
86
- let top = rect.bottom + window.scrollY;
87
-
88
- if (rect.bottom + dropdownRect.height > window.innerHeight) {
89
- top = rect.top + window.scrollY - dropdownRect.height;
90
- }
91
-
92
- setMenuPosition((prev) => {
93
- if (
94
- Math.abs(prev.top - top) < 0.5 &&
95
- Math.abs(prev.left - rect.left) < 0.5
96
- ) {
97
- return prev;
98
- }
99
- return {
100
- top,
101
- left: rect.left,
102
- width: rect.width,
103
- };
104
- });
105
- }
106
- }, [isOpen, filterValue, menuPosition.width]);
107
-
108
- useEffect(() => {
109
- // 마우스 벗어난 영역 클릭 시 드롭다운 닫기
110
- const handleClickOutside = (event: MouseEvent) => {
111
- if (
112
- dropdownRef.current &&
113
- !dropdownRef.current.contains(event.target as Node) &&
114
- inputRef.current &&
115
- !inputRef.current.contains(event.target as Node)
116
- ) {
117
- setIsOpen(false);
118
- }
119
- };
120
- document.addEventListener("mousedown", handleClickOutside);
121
- return () => document.removeEventListener("mousedown", handleClickOutside);
122
- }, []);
123
-
124
- return (
125
- <div className="relative">
126
- <label className="relative w-fit hidden md:block">
127
- <input
128
- ref={inputRef}
129
- type="text"
130
- value={filterValue}
131
- placeholder="값을 선택해주세요..."
132
- onChange={(e) => {
133
- setFilterValue(e.target.value);
134
- }}
135
- onFocus={() => setIsOpen(true)}
136
- className="select hidden sm:block"
137
- disabled={disabled}
138
- />
139
- <div
140
- className="absolute flex items-center right-0 top-0 h-full px-2"
141
- draggable
142
- >
143
- <span className="material-symbols-outlined">
144
- <span className="text-base input-text-value">arrow_drop_down</span>
145
- </span>
146
- </div>
147
- </label>
148
- {isOpen &&
149
- createPortal(
150
- <ul
151
- ref={dropdownRef}
152
- className="absolute w-full select-menu"
153
- style={{
154
- top: menuPosition.top,
155
- left: menuPosition.left,
156
- width: menuPosition.width,
157
- }}
158
- >
159
- {filteredOptions.length > 0 ? (
160
- filteredOptions.map((option, index) => (
161
- <li
162
- key={index}
163
- className="select-menu-item"
164
- onClick={() => {
165
- setFilterValue(option);
166
- setIsOpen(false);
167
- }}
168
- >
169
- {option}
170
- </li>
171
- ))
172
- ) : (
173
- <li className="select-menu-item">No results</li>
174
- )}
175
- </ul>,
176
- document.body
177
- )}
178
- <select
179
- className="select block sm:hidden"
180
- >
181
- {options.map((option, index) => {
182
- return (
183
- <option key={index} value={option}>
184
- {option}
185
- </option>
186
- );
187
- })}
188
- </select>
189
- </div>
190
- );
191
- };
192
-
193
- export const Radio = ({
194
- name,
195
- value,
196
- label,
197
- className,
198
- onChange,
199
- defaultChecked,
200
- checked,
201
- }: {
202
- name: string;
203
- value: string;
204
- label?: string;
205
- className?: string;
206
- onChange?: () => void;
207
- defaultChecked?: boolean;
208
- checked?: boolean;
209
- }) => {
210
- return (
211
- <>
212
- {label ? <p>{label}</p> : null}
213
- <label className="flex items-center gap-1">
214
- <input
215
- type="radio"
216
- className={clsx(
217
- "relative appearance-none radio rounded-full ",
218
- {
219
- "checked:bg-primary after:w-2.5 after:h-2.5 after:bg-[var(--input-background-standard)] after:content-[''] after:absolute after:rounded-full after:left-1 after:top-1":
220
- true,
221
- },
222
- { "focus:border-input-border-focus": true },
223
- { "disabled:bg-input-background-disabled": true },
224
- className
225
- )}
226
- name={name}
227
- onChange={onChange}
228
- defaultChecked={defaultChecked}
229
- checked={checked}
230
- />
231
- <span>{value}</span>
232
- </label>
233
- </>
234
- );
235
- };
236
-
237
- export const Checkbox = ({
238
- text,
239
- onChange,
240
- disabled,
241
- required,
242
- defaultChecked,
243
- }: {
244
- text?: string;
245
- className?: string;
246
- onChange?: () => void;
247
- disabled?: boolean;
248
- required?: boolean;
249
- defaultChecked?: boolean;
250
- }) => {
251
- return (
252
- <>
253
- <label className="checkbox gap-1.5">
254
- <input
255
- type="checkbox"
256
- className="appearance-none hidden"
257
- onChange={onChange}
258
- disabled={disabled}
259
- required={required}
260
- defaultChecked={defaultChecked}
261
- />
262
- <span>
263
- <svg
264
- xmlns="http://www.w3.org/2000/svg"
265
- className="h-4 w-4"
266
- viewBox="0 0 20 20"
267
- strokeWidth="1"
268
- >
269
- <path
270
- fillRule="evenodd"
271
- d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
272
- clipRule="evenodd"
273
- ></path>
274
- </svg>
275
- </span>
276
- {text ? (
277
- <span
278
- className={clsx(
279
- "text-text-standard text-nowrap select-none",
280
- { "!text-text-disabled": disabled }
281
- )}
282
- >
283
- {text}
284
- </span>
285
- ) : null}
286
- </label>
287
- </>
288
- );
289
- };
@@ -1,115 +0,0 @@
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
- }
@@ -1,71 +0,0 @@
1
- "use client";
2
-
3
- import ReactModal from "react-modal";
4
- import React, { useEffect } from "react";
5
-
6
- type ModalProps = {
7
- isOpen: boolean;
8
- onRequestClose: () => void;
9
- children: React.ReactNode;
10
- modalTitle: string;
11
- modalFooter: React.ReactNode;
12
- size?: "normal" | "middle" | "large" | "xl" | "full" | "full-screen";
13
- };
14
-
15
- export const ModalContent = ({
16
- isOpen,
17
- onRequestClose,
18
- children,
19
- modalTitle,
20
- modalFooter,
21
- size = "normal",
22
- }: ModalProps) => {
23
- useEffect(() => {
24
- ReactModal.setAppElement("#modal-root"); // 접근성 설정
25
- }, []);
26
-
27
- return (
28
- <ReactModal
29
- isOpen={isOpen}
30
- onRequestClose={onRequestClose}
31
- shouldCloseOnEsc={true}
32
- overlayClassName="modal-overlay"
33
- className={`modal modal-${size}`}
34
- >
35
- <ModalTitle onRequestClose={onRequestClose} title={modalTitle} />
36
- <div className="modal-content">{children}</div>
37
- <ModalFooter modalFooter={modalFooter} />
38
- </ReactModal>
39
- );
40
- };
41
-
42
- export const Modal = () => {
43
- return <div id="modal-root"></div>;
44
- };
45
-
46
- type ModalTitleProps = {
47
- title: string;
48
- onRequestClose: () => void;
49
- };
50
-
51
- export const ModalTitle = ({ title, onRequestClose }: ModalTitleProps) => {
52
- return (
53
- <div className="modal-header">
54
- <h6 className="modal-title">{title}</h6>
55
- <button
56
- onClick={onRequestClose}
57
- className="material-symbols-outlined modal-close"
58
- >
59
- close
60
- </button>
61
- </div>
62
- );
63
- };
64
-
65
- export const ModalFooter = ({
66
- modalFooter,
67
- }: {
68
- modalFooter: React.ReactNode;
69
- }) => {
70
- return <div className="modal-footer">{modalFooter}</div>;
71
- };
@@ -1,98 +0,0 @@
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
- }