atomsystem 0.1.46 → 0.1.48

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,55 @@
1
+ "use client";
2
+ import clsx from "clsx";
3
+ import "./checkbox.css";
4
+
5
+ export const Checkbox = ({
6
+ text,
7
+ onChange,
8
+ disabled,
9
+ required,
10
+ defaultChecked,
11
+ }: {
12
+ text?: string;
13
+ className?: string;
14
+ onChange?: () => void;
15
+ disabled?: boolean;
16
+ required?: boolean;
17
+ defaultChecked?: boolean;
18
+ }) => {
19
+ return (
20
+ <label className="checkbox-container gap-1.5">
21
+ <input
22
+ type="checkbox"
23
+ className="appearance-none hidden"
24
+ onChange={onChange}
25
+ disabled={disabled}
26
+ required={required}
27
+ defaultChecked={defaultChecked}
28
+ />
29
+ <span className="checkbox-box">
30
+ <svg
31
+ xmlns="http://www.w3.org/2000/svg"
32
+ className="h-4 w-4"
33
+ viewBox="0 0 20 20"
34
+ strokeWidth="1"
35
+ >
36
+ <path
37
+ fillRule="evenodd"
38
+ 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"
39
+ clipRule="evenodd"
40
+ ></path>
41
+ </svg>
42
+ </span>
43
+ {text ? (
44
+ <span
45
+ className={clsx(
46
+ "text-text-standard text-nowrap select-none",
47
+ { "!text-text-disabled": disabled }
48
+ )}
49
+ >
50
+ {text}
51
+ </span>
52
+ ) : null}
53
+ </label>
54
+ );
55
+ };
@@ -0,0 +1,38 @@
1
+ .checkbox-container{
2
+ display: flex;
3
+ align-items: center;
4
+ position: relative;
5
+ cursor: pointer;
6
+ }
7
+
8
+ .checkbox-box {
9
+ width: var(--spacing-small);
10
+ height: var(--spacing-small);
11
+ border: 1px solid var(--color-border-standard);
12
+ border-radius: var(--radius-common);
13
+ background: var(--color-bg-input-standard);
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: center;
17
+ transition: all 0.2s;
18
+ }
19
+
20
+ .checkbox-box svg {
21
+ color: transparent;
22
+ fill: transparent;
23
+ }
24
+
25
+ input:checked + .checkbox-box {
26
+ background: var(--color-primary);
27
+ border-color: var(--color-primary);
28
+ }
29
+
30
+ input:checked + .checkbox-box svg {
31
+ color: var(--color-text-active);
32
+ fill: var(--color-text-active);
33
+ }
34
+
35
+ input:disabled + .checkbox-box {
36
+ background: var(--color-bg-input-disabled);
37
+ cursor: not-allowed;
38
+ }
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import React from "react";
3
+ import "./input.css";
4
+
5
+ export const Input = ({
6
+ type = "text",
7
+ placeholder = "값을 입력해주세요",
8
+ readOnly,
9
+ disabled,
10
+ required,
11
+ }: {
12
+ type?: string;
13
+ className?: string;
14
+ placeholder?: string;
15
+ readOnly?: boolean;
16
+ disabled?: boolean;
17
+ required?: boolean;
18
+ }) => {
19
+ return (
20
+ <input
21
+ className="input"
22
+ type={type}
23
+ placeholder={placeholder}
24
+ readOnly={readOnly}
25
+ disabled={disabled}
26
+ required={required}
27
+ />
28
+ );
29
+ };
@@ -0,0 +1,24 @@
1
+ .input{
2
+ background: var(--color-bg-input-standard);
3
+ border: 1px solid var(--color-border-standard);
4
+ color: var(--color-text-standard);
5
+ padding: var(--spacing-common-y) var(--spacing-common-x);
6
+ border-radius: var(--radius-common);
7
+ outline: none;
8
+ width: 100%;
9
+ }
10
+
11
+ .input::placeholder{
12
+ color: var(--color-text-placeholder);
13
+ }
14
+
15
+ .input:focus{
16
+ border: 1px solid var(--color-border-active);
17
+ }
18
+
19
+ .input:disabled{
20
+ background: var(--color-bg-input-disabled);
21
+ border: 1px solid var(--color-border-standard);
22
+ color: var(--color-text-disabled);
23
+ cursor: not-allowed;
24
+ }
@@ -0,0 +1,22 @@
1
+ "use client";
2
+ import clsx from "clsx";
3
+
4
+ export const Label = ({
5
+ label,
6
+ required,
7
+ }: {
8
+ label: string;
9
+ required?: boolean;
10
+ }) => {
11
+ return (
12
+ <p className={"mb-1 text-text-standard"}>
13
+ <span
14
+ className={clsx("", {
15
+ "after:content-['*'] after:ml-1 after:text-danger": required,
16
+ })}
17
+ >
18
+ {label}
19
+ </span>
20
+ </p>
21
+ );
22
+ };
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ import clsx from "clsx";
3
+ import "./radio.css";
4
+
5
+ export const Radio = ({
6
+ name,
7
+ value,
8
+ label,
9
+ className,
10
+ onChange,
11
+ defaultChecked,
12
+ checked,
13
+ }: {
14
+ name: string;
15
+ value: string;
16
+ label?: string;
17
+ className?: string;
18
+ onChange?: () => void;
19
+ defaultChecked?: boolean;
20
+ checked?: boolean;
21
+ }) => {
22
+ return (
23
+ <>
24
+ {label ? <p>{label}</p> : null}
25
+ <label className="flex items-center gap-1 cursor-pointer">
26
+ <input
27
+ type="radio"
28
+ className={clsx(
29
+ "relative appearance-none radio rounded-full ",
30
+ {
31
+ "checked:bg-primary after:w-2.5 after:h-2.5 after:bg-[var(--color-bg-input-standard)] after:content-[''] after:absolute after:rounded-full after:left-1 after:top-1":
32
+ true,
33
+ },
34
+ className
35
+ )}
36
+ name={name}
37
+ onChange={onChange}
38
+ defaultChecked={defaultChecked}
39
+ checked={checked}
40
+ />
41
+ <span>{value}</span>
42
+ </label>
43
+ </>
44
+ );
45
+ };
@@ -0,0 +1,29 @@
1
+ .radio{
2
+ position: relative;
3
+ width: var(--spacing-small);
4
+ height: var(--spacing-small);
5
+ border: 1px solid var(--color-border-standard);
6
+ background: var(--color-bg-input-standard);
7
+ color: var(--color-bg-input-standard);
8
+ cursor: pointer;
9
+ }
10
+
11
+ .radio::after{
12
+ content:'';
13
+ position:absolute;
14
+ left: 50%;
15
+ top: 50%;
16
+ transform: translate(-50%, -50%);
17
+ width: var(--spacing-common-y);
18
+ height: var(--spacing-common-y);
19
+ border-radius: var(--radius-circle);
20
+ }
21
+
22
+ .radio:checked::after{
23
+ background: var(--color-primary);
24
+ }
25
+
26
+ .radio:disabled {
27
+ background: var(--color-bg-input-disabled);
28
+ cursor: not-allowed;
29
+ }
@@ -1,289 +1,143 @@
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
+ "use client";
2
+ import { useEffect, useLayoutEffect, useRef, useState } from "react";
3
+ import { createPortal } from "react-dom";
4
+ import "./select.css";
5
+
6
+ export const Select = ({
7
+ options = [],
8
+ disabled,
9
+ }: {
10
+ options: string[];
11
+ disabled?: boolean;
12
+ }) => {
13
+ const [filterValue, setFilterValue] = useState("");
14
+ const [isOpen, setIsOpen] = useState(false);
15
+ const [menuPosition, setMenuPosition] = useState({
16
+ top: 0,
17
+ left: 0,
18
+ width: 0,
19
+ });
20
+ const inputRef = useRef<HTMLInputElement>(null);
21
+ const dropdownRef = useRef<HTMLUListElement>(null);
22
+ const filteredOptions = options.filter((option) =>
23
+ option.toLowerCase().includes(filterValue.toLowerCase())
24
+ );
25
+
26
+ useLayoutEffect(() => {
27
+ if (isOpen && inputRef.current && dropdownRef.current) {
28
+ const rect = inputRef.current.getBoundingClientRect();
29
+ const dropdownRect = dropdownRef.current.getBoundingClientRect();
30
+
31
+ if (Math.abs(menuPosition.width - rect.width) > 0.5) {
32
+ setMenuPosition({
33
+ top: rect.bottom + window.scrollY,
34
+ left: rect.left,
35
+ width: rect.width,
36
+ });
37
+ return;
38
+ }
39
+
40
+ let top = rect.bottom + window.scrollY;
41
+
42
+ if (rect.bottom + dropdownRect.height > window.innerHeight) {
43
+ top = rect.top + window.scrollY - dropdownRect.height;
44
+ }
45
+
46
+ setMenuPosition((prev) => {
47
+ if (
48
+ Math.abs(prev.top - top) < 0.5 &&
49
+ Math.abs(prev.left - rect.left) < 0.5
50
+ ) {
51
+ return prev;
52
+ }
53
+ return {
54
+ top,
55
+ left: rect.left,
56
+ width: rect.width,
57
+ };
58
+ });
59
+ }
60
+ }, [isOpen, filterValue, menuPosition.width]);
61
+
62
+ useEffect(() => {
63
+ const handleClickOutside = (event: MouseEvent) => {
64
+ if (
65
+ dropdownRef.current &&
66
+ !dropdownRef.current.contains(event.target as Node) &&
67
+ inputRef.current &&
68
+ !inputRef.current.contains(event.target as Node)
69
+ ) {
70
+ setIsOpen(false);
71
+ }
72
+ };
73
+ document.addEventListener("mousedown", handleClickOutside);
74
+ return () => document.removeEventListener("mousedown", handleClickOutside);
75
+ }, []);
76
+
77
+ return (
78
+ <div className="relative">
79
+ <label className="relative w-fit hidden md:block">
80
+ <input
81
+ ref={inputRef}
82
+ type="text"
83
+ value={filterValue}
84
+ placeholder="값을 선택해주세요..."
85
+ onChange={(e) => {
86
+ setFilterValue(e.target.value);
87
+ }}
88
+ onFocus={() => setIsOpen(true)}
89
+ className="select hidden sm:block"
90
+ disabled={disabled}
91
+ />
92
+ <div
93
+ className="absolute flex items-center right-0 top-0 h-full px-2"
94
+ >
95
+ <span className="material-symbols-outlined">
96
+ <span className="text-base">arrow_drop_down</span>
97
+ </span>
98
+ </div>
99
+ </label>
100
+ {isOpen &&
101
+ createPortal(
102
+ <ul
103
+ ref={dropdownRef}
104
+ className="absolute w-full select-menu"
105
+ style={{
106
+ top: menuPosition.top,
107
+ left: menuPosition.left,
108
+ width: menuPosition.width,
109
+ }}
110
+ >
111
+ {filteredOptions.length > 0 ? (
112
+ filteredOptions.map((option, index) => (
113
+ <li
114
+ key={index}
115
+ className="select-menu-item"
116
+ onClick={() => {
117
+ setFilterValue(option);
118
+ setIsOpen(false);
119
+ }}
120
+ >
121
+ {option}
122
+ </li>
123
+ ))
124
+ ) : (
125
+ <li className="select-menu-item">No results</li>
126
+ )}
127
+ </ul>,
128
+ document.body
129
+ )}
130
+ <select
131
+ className="select block sm:hidden"
132
+ >
133
+ {options.map((option, index) => {
134
+ return (
135
+ <option key={index} value={option}>
136
+ {option}
137
+ </option>
138
+ );
139
+ })}
140
+ </select>
141
+ </div>
142
+ );
143
+ };
@@ -0,0 +1,47 @@
1
+ .select{
2
+ background: var(--color-bg-input-standard);
3
+ border: 1px solid var(--color-border-standard);
4
+ color: var(--color-text-standard);
5
+ padding: var(--spacing-common-y) var(--spacing-common-x);
6
+ border-radius: var(--radius-common);
7
+ width: 100%;
8
+ outline: none;
9
+ cursor: pointer;
10
+ }
11
+ .select:focus{
12
+ border: 1px solid var(--color-border-active);
13
+ }
14
+
15
+ .select:disabled{
16
+ background: var(--color-bg-input-disabled);
17
+ border: 1px solid var(--color-border-standard);
18
+ color: var(--color-text-disabled);
19
+ cursor: not-allowed;
20
+ }
21
+
22
+ .select-menu {
23
+ border: 1px solid var(--color-border-active);
24
+ border-radius: var(--radius-common);
25
+ overflow:hidden;
26
+ z-index: 9999;
27
+ box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
28
+ background: var(--color-bg-input-standard);
29
+ }
30
+
31
+ .select-menu .select-menu-item {
32
+ background: var(--color-bg-input-standard);
33
+ color: var(--color-text-standard);
34
+ padding: var(--spacing-common-y) var(--spacing-common-x);
35
+ cursor:pointer;
36
+ list-style: none;
37
+ }
38
+
39
+ .select-menu .select-menu-item:hover {
40
+ background: var(--color-bg-input-hover);
41
+ }
42
+
43
+ .select-menu .select-menu-item:active,
44
+ .select-menu .select-menu-item:focus {
45
+ background: var(--color-primary);
46
+ color: var(--color-text-active);
47
+ }
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
 
3
3
  import { useEffect, useState } from "react";
4
- import { Radio } from "../Form/Form";
4
+ import { Radio } from "../Radio/Radio";
5
+
5
6
  import { themes } from "@/build/typescript/theme";
6
7
  import { Button } from "../Button/Button";
7
8
  import { ModalContent } from "../Modal/Modal";
package/dist/index.js CHANGED
@@ -1,16 +1,186 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- addComponent,
4
- components,
5
- logger
6
- } from "./chunk-US4VD4EW.js";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __esm = (fn, res) => function __init() {
5
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
+ };
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+
12
+ // node_modules/tsup/assets/esm_shims.js
13
+ import path from "path";
14
+ import { fileURLToPath } from "url";
15
+ var init_esm_shims = __esm({
16
+ "node_modules/tsup/assets/esm_shims.js"() {
17
+ "use strict";
18
+ }
19
+ });
20
+
21
+ // src/utils/logger.ts
22
+ import chalk from "chalk";
23
+ var logger;
24
+ var init_logger = __esm({
25
+ "src/utils/logger.ts"() {
26
+ "use strict";
27
+ init_esm_shims();
28
+ logger = {
29
+ error(...args) {
30
+ console.error(chalk.red(...args));
31
+ },
32
+ warn(...args) {
33
+ console.warn(chalk.yellow(...args));
34
+ },
35
+ info(...args) {
36
+ console.info(chalk.cyan(...args));
37
+ },
38
+ success(...args) {
39
+ console.log(chalk.green(...args));
40
+ },
41
+ log(...args) {
42
+ console.log(...args);
43
+ },
44
+ break() {
45
+ console.log("");
46
+ }
47
+ };
48
+ }
49
+ });
50
+
51
+ // src/utils/component.ts
52
+ var component_exports = {};
53
+ __export(component_exports, {
54
+ addComponent: () => addComponent,
55
+ baseDir: () => baseDir,
56
+ components: () => components,
57
+ dependenciesMap: () => dependenciesMap,
58
+ templateDir: () => templateDir,
59
+ updateGlobalsCss: () => updateGlobalsCss
60
+ });
61
+ import fs from "fs";
62
+ import path2 from "path";
63
+ import { fileURLToPath as fileURLToPath2 } from "url";
64
+ function getBaseDir() {
65
+ const isBuilt = path2.basename(__dirname2) === "dist" || fs.existsSync(path2.join(__dirname2, "index.js"));
66
+ if (isBuilt) {
67
+ return path2.join(__dirname2, "..");
68
+ }
69
+ if (path2.basename(__dirname2) === "utils" || path2.basename(__dirname2) === "commands") {
70
+ return path2.join(__dirname2, "..", "..");
71
+ }
72
+ return path2.join(__dirname2, "..", "..");
73
+ }
74
+ function addComponent(comp, cwd, addedComponents) {
75
+ if (addedComponents.has(comp)) return;
76
+ addedComponents.add(comp);
77
+ const componentSourceDir = path2.join(templateDir, comp);
78
+ const componentPath = path2.join(componentSourceDir, `${comp}.tsx`);
79
+ const targetDir = path2.join(cwd, "app", "components", comp);
80
+ const targetPath = path2.join(targetDir, `${comp}.tsx`);
81
+ const cssFileName = `${comp}.css`.toLowerCase();
82
+ const sourceCssPath = path2.join(componentSourceDir, cssFileName);
83
+ const targetCssPath = path2.join(targetDir, cssFileName);
84
+ if (fs.existsSync(componentPath)) {
85
+ if (!fs.existsSync(targetDir)) {
86
+ fs.mkdirSync(targetDir, { recursive: true });
87
+ logger.info(`\uB514\uB809\uD1A0\uB9AC \uC0DD\uC131: ${targetDir}`);
88
+ }
89
+ fs.copyFileSync(componentPath, targetPath);
90
+ logger.success(`\u2705 ${comp} \uCEF4\uD3EC\uB10C\uD2B8(TSX)\uAC00 \uCD94\uAC00\uB418\uC5C8\uC2B5\uB2C8\uB2E4: ${targetPath}`);
91
+ if (fs.existsSync(sourceCssPath)) {
92
+ fs.copyFileSync(sourceCssPath, targetCssPath);
93
+ logger.success(`\u2705 ${comp} \uCEF4\uD3EC\uB10C\uD2B8(CSS)\uAC00 \uCD94\uAC00\uB418\uC5C8\uC2B5\uB2C8\uB2E4: ${targetCssPath}`);
94
+ updateGlobalsCss(comp, cssFileName, cwd);
95
+ }
96
+ if (dependenciesMap[comp]) {
97
+ logger.info(`\u23F3 ${comp}\uC758 \uC758\uC874\uC131 \uCEF4\uD3EC\uB10C\uD2B8 \uD655\uC778 \uC911...`);
98
+ for (const dep of dependenciesMap[comp]) {
99
+ addComponent(dep, cwd, addedComponents);
100
+ }
101
+ }
102
+ } else {
103
+ logger.error(`\u274C ${comp} \uCEF4\uD3EC\uB10C\uD2B8\uAC00 atomsystem\uC5D0 \uC874\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: ${comp}`);
104
+ }
105
+ }
106
+ function updateGlobalsCss(comp, cssFileName, cwd) {
107
+ const globalsPath = path2.join(cwd, "app", "globals.css");
108
+ const importLine = `@import "./components/${comp}/${cssFileName}";`;
109
+ const componentSectionMarker = "/* Component Styles */";
110
+ if (fs.existsSync(globalsPath)) {
111
+ let content = fs.readFileSync(globalsPath, "utf8");
112
+ if (!content.includes(importLine)) {
113
+ if (content.includes(componentSectionMarker)) {
114
+ const markerIndex = content.indexOf(componentSectionMarker);
115
+ const afterMarker = content.slice(markerIndex);
116
+ const lastImportIndex = afterMarker.lastIndexOf("@import");
117
+ if (lastImportIndex !== -1) {
118
+ const endOfLastImport = markerIndex + lastImportIndex + afterMarker.slice(lastImportIndex).indexOf("\n") + 1;
119
+ content = content.slice(0, endOfLastImport) + importLine + "\n" + content.slice(endOfLastImport);
120
+ } else {
121
+ content = content.slice(0, markerIndex + componentSectionMarker.length) + "\n" + importLine + "\n" + content.slice(markerIndex + componentSectionMarker.length);
122
+ }
123
+ } else {
124
+ content = content.trimEnd() + "\n\n" + componentSectionMarker + "\n" + importLine + "\n";
125
+ }
126
+ fs.writeFileSync(globalsPath, content, "utf8");
127
+ logger.success(`\u2705 globals.css\uC5D0 ${comp} @import\uB97C \uCD94\uAC00\uD588\uC2B5\uB2C8\uB2E4.`);
128
+ }
129
+ } else {
130
+ logger.warn(`\u26A0\uFE0F globals.css\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC218\uB3D9\uC73C\uB85C \uCD94\uAC00\uD574 \uC8FC\uC138\uC694:
131
+ ${importLine}`);
132
+ }
133
+ }
134
+ var __filename2, __dirname2, baseDir, templateDir, components, dependenciesMap;
135
+ var init_component = __esm({
136
+ "src/utils/component.ts"() {
137
+ "use strict";
138
+ init_esm_shims();
139
+ init_logger();
140
+ __filename2 = fileURLToPath2(import.meta.url);
141
+ __dirname2 = path2.dirname(__filename2);
142
+ baseDir = getBaseDir();
143
+ templateDir = path2.join(baseDir, "app", "templates");
144
+ logger.info(`\u{1F50D} Debug: baseDir=${baseDir}`);
145
+ logger.info(`\u{1F50D} Debug: templateDir=${templateDir}`);
146
+ components = [
147
+ "Button",
148
+ "Badge",
149
+ "Card",
150
+ "Collapse",
151
+ "CodeBlock",
152
+ "Navigation",
153
+ "Sidebar",
154
+ "Input",
155
+ "Theme",
156
+ "Tab",
157
+ "Toast",
158
+ "Pagination",
159
+ "Table",
160
+ "Modal",
161
+ "TOC",
162
+ "Dropdown",
163
+ "Checkbox",
164
+ "Radio",
165
+ "Select",
166
+ "Label"
167
+ ];
168
+ dependenciesMap = {
169
+ Theme: ["Button", "Radio", "Modal"]
170
+ };
171
+ }
172
+ });
7
173
 
8
174
  // src/index.ts
175
+ init_esm_shims();
9
176
  import { Command as Command3 } from "commander";
10
177
 
11
178
  // src/commands/add.ts
179
+ init_esm_shims();
180
+ init_logger();
181
+ init_component();
12
182
  import { Command } from "commander";
13
- import path from "path";
183
+ import path3 from "path";
14
184
  import prompts from "prompts";
15
185
  import { z } from "zod";
16
186
  var addOptionsSchema = z.object({
@@ -23,7 +193,7 @@ var add = new Command().name("add").description("\uD504\uB85C\uC81D\uD2B8\uC5D0
23
193
  const options = addOptionsSchema.parse({
24
194
  components: componentsArg,
25
195
  ...opts,
26
- cwd: path.resolve(opts.cwd)
196
+ cwd: path3.resolve(opts.cwd)
27
197
  });
28
198
  let selectedComponents = options.components || [];
29
199
  if (options.all) {
@@ -53,17 +223,20 @@ var add = new Command().name("add").description("\uD504\uB85C\uC81D\uD2B8\uC5D0
53
223
  });
54
224
 
55
225
  // src/commands/init.ts
226
+ init_esm_shims();
227
+ init_logger();
228
+ init_component();
56
229
  import { Command as Command2 } from "commander";
57
- import fs from "fs";
58
- import path2 from "path";
230
+ import fs2 from "fs";
231
+ import path4 from "path";
59
232
  import { exec } from "child_process";
60
233
  import { promisify } from "util";
61
234
  import ora from "ora";
62
235
  import prompts2 from "prompts";
63
- import { fileURLToPath } from "url";
236
+ import { fileURLToPath as fileURLToPath3 } from "url";
64
237
  import { z as z2 } from "zod";
65
- var __filename2 = fileURLToPath(import.meta.url);
66
- var __dirname2 = path2.dirname(__filename2);
238
+ var __filename3 = fileURLToPath3(import.meta.url);
239
+ var __dirname3 = path4.dirname(__filename3);
67
240
  var execPromise = promisify(exec);
68
241
  var initOptionsSchema = z2.object({
69
242
  cwd: z2.string(),
@@ -73,11 +246,11 @@ var init = new Command2().name("init").description("\uD504\uB85C\uC81D\uD2B8\uB9
73
246
  try {
74
247
  const options = initOptionsSchema.parse({
75
248
  ...opts,
76
- cwd: path2.resolve(opts.cwd)
249
+ cwd: path4.resolve(opts.cwd)
77
250
  });
78
251
  const projectRoot = options.cwd;
79
- const packageJsonPath = path2.join(projectRoot, "package.json");
80
- if (!fs.existsSync(packageJsonPath)) {
252
+ const packageJsonPath = path4.join(projectRoot, "package.json");
253
+ if (!fs2.existsSync(packageJsonPath)) {
81
254
  logger.error("\u274C \uC624\uB958: \uD604\uC7AC \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C package.json\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
82
255
  logger.info("'npm init'\uC744 \uBA3C\uC800 \uC2E4\uD589\uD55C \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574 \uC8FC\uC138\uC694.");
83
256
  process.exit(1);
@@ -120,7 +293,7 @@ var init = new Command2().name("init").description("\uD504\uB85C\uC81D\uD2B8\uB9
120
293
  return;
121
294
  }
122
295
  try {
123
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
296
+ const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf8"));
124
297
  packageJson.type = "module";
125
298
  packageJson.scripts = {
126
299
  ...packageJson.scripts,
@@ -130,17 +303,17 @@ var init = new Command2().name("init").description("\uD504\uB85C\uC81D\uD2B8\uB9
130
303
  "lint": "next lint",
131
304
  "token-build": "node build/build-tokens.js"
132
305
  };
133
- fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
306
+ fs2.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
134
307
  logger.success("\u2705 package.json \uC2A4\uD06C\uB9BD\uD2B8 \uC5C5\uB370\uC774\uD2B8 \uC644\uB8CC.");
135
308
  } catch (err) {
136
309
  logger.error("\u274C package.json \uC5C5\uB370\uC774\uD2B8 \uC624\uB958:", err);
137
310
  return;
138
311
  }
139
- const appDir = path2.join(projectRoot, "app");
140
- if (!fs.existsSync(appDir)) fs.mkdirSync(appDir, { recursive: true });
312
+ const appDir = path4.join(projectRoot, "app");
313
+ if (!fs2.existsSync(appDir)) fs2.mkdirSync(appDir, { recursive: true });
141
314
  const files = [
142
315
  {
143
- path: path2.join(appDir, "layout.tsx"),
316
+ path: path4.join(appDir, "layout.tsx"),
144
317
  content: `import { ThemeProvider } from "./components/Theme/Theme";
145
318
  import "./globals.css";
146
319
 
@@ -157,13 +330,13 @@ export default function RootLayout({ children }: { children: React.ReactNode })
157
330
  }`
158
331
  },
159
332
  {
160
- path: path2.join(appDir, "globals.css"),
333
+ path: path4.join(appDir, "globals.css"),
161
334
  content: `@import "tailwindcss";
162
335
  @import "../build/css/_variables.css";
163
336
  @import "../css/text.css";`
164
337
  },
165
338
  {
166
- path: path2.join(appDir, "page.tsx"),
339
+ path: path4.join(appDir, "page.tsx"),
167
340
  content: `import { ThemeSelector } from "./components/Theme/Theme";
168
341
  import { Button } from "./components/Button/Button";
169
342
  import { Card, CardHeader, CardContent, CardFooter } from "./components/Card/Card";
@@ -203,7 +376,7 @@ export default function Page() {
203
376
  }`
204
377
  },
205
378
  {
206
- path: path2.join(projectRoot, "tsconfig.json"),
379
+ path: path4.join(projectRoot, "tsconfig.json"),
207
380
  content: JSON.stringify({
208
381
  compilerOptions: {
209
382
  target: "ES2017",
@@ -229,25 +402,25 @@ export default function Page() {
229
402
  }, null, 2)
230
403
  },
231
404
  {
232
- path: path2.join(projectRoot, "next.config.ts"),
405
+ path: path4.join(projectRoot, "next.config.ts"),
233
406
  content: `import type { NextConfig } from "next";
234
407
 
235
408
  const nextConfig: NextConfig = { reactStrictMode: false };
236
409
  export default nextConfig;`
237
410
  },
238
411
  {
239
- path: path2.join(projectRoot, "postcss.config.mjs"),
412
+ path: path4.join(projectRoot, "postcss.config.mjs"),
240
413
  content: `/** @type {import('postcss-load-config').Config} */
241
414
  const config = { plugins: { "@tailwindcss/postcss": {} } };
242
415
  export default config;`
243
416
  }
244
417
  ];
245
418
  for (const file of files) {
246
- fs.writeFileSync(file.path, file.content);
419
+ fs2.writeFileSync(file.path, file.content);
247
420
  logger.info(`\u2705 \uD30C\uC77C \uC0DD\uC131: ${file.path}`);
248
421
  }
249
- const buildTokensPath = path2.join(projectRoot, "build", "build-tokens.js");
250
- if (fs.existsSync(buildTokensPath)) {
422
+ const buildTokensPath = path4.join(projectRoot, "build", "build-tokens.js");
423
+ if (fs2.existsSync(buildTokensPath)) {
251
424
  const spin = ora("\uB514\uC790\uC778 \uD1A0\uD070 \uBE4C\uB4DC \uC911...").start();
252
425
  try {
253
426
  await execPromise(`node "${buildTokensPath}"`, { cwd: projectRoot });
@@ -258,14 +431,14 @@ export default config;`
258
431
  }
259
432
  }
260
433
  }
261
- const { baseDir: pkgRoot } = await import("./component-SFV77SNH.js");
434
+ const { baseDir: pkgRoot } = await Promise.resolve().then(() => (init_component(), component_exports));
262
435
  logger.info(`\u{1F50D} Debug: pkgRoot=${pkgRoot}`);
263
- const tokenFile = path2.join(pkgRoot, "tokens", "tokens.json");
264
- const buildFile = path2.join(pkgRoot, "build", "build-tokens.js");
265
- const textCssFile = path2.join(pkgRoot, "css", "text.css");
266
- copyFile(tokenFile, path2.join(projectRoot, "tokens", "tokens.json"));
267
- copyFile(buildFile, path2.join(projectRoot, "build", "build-tokens.js"));
268
- copyFile(textCssFile, path2.join(projectRoot, "css", "text.css"));
436
+ const tokenFile = path4.join(pkgRoot, "tokens", "tokens.json");
437
+ const buildFile = path4.join(pkgRoot, "build", "build-tokens.js");
438
+ const textCssFile = path4.join(pkgRoot, "css", "text.css");
439
+ copyFile(tokenFile, path4.join(projectRoot, "tokens", "tokens.json"));
440
+ copyFile(buildFile, path4.join(projectRoot, "build", "build-tokens.js"));
441
+ copyFile(textCssFile, path4.join(projectRoot, "css", "text.css"));
269
442
  const addedComponents = /* @__PURE__ */ new Set();
270
443
  logger.info("\u23F3 \uAE30\uBCF8 \uB370\uBAA8 \uCEF4\uD3EC\uB10C\uD2B8 \uC124\uCE58 \uC911...");
271
444
  addComponent("Button", projectRoot, addedComponents);
@@ -278,10 +451,10 @@ export default config;`
278
451
  }
279
452
  });
280
453
  function copyFile(src, dest) {
281
- const dir = path2.dirname(dest);
282
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
283
- if (fs.existsSync(src)) {
284
- fs.copyFileSync(src, dest);
454
+ const dir = path4.dirname(dest);
455
+ if (!fs2.existsSync(dir)) fs2.mkdirSync(dir, { recursive: true });
456
+ if (fs2.existsSync(src)) {
457
+ fs2.copyFileSync(src, dest);
285
458
  logger.info(`\u2705 \uBCF5\uC0AC \uC644\uB8CC: ${src} -> ${dest}`);
286
459
  } else {
287
460
  logger.warn(`\u26A0\uFE0F \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC5B4 \uBCF5\uC0AC\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${src}`);
@@ -291,12 +464,12 @@ function copyFile(src, dest) {
291
464
  // src/index.ts
292
465
  import { readFileSync } from "fs";
293
466
  import { join } from "path";
294
- import { fileURLToPath as fileURLToPath2 } from "url";
467
+ import { fileURLToPath as fileURLToPath4 } from "url";
295
468
  import { dirname } from "path";
296
- var __filename3 = fileURLToPath2(import.meta.url);
297
- var __dirname3 = dirname(__filename3);
469
+ var __filename4 = fileURLToPath4(import.meta.url);
470
+ var __dirname4 = dirname(__filename4);
298
471
  async function main() {
299
- const packageJsonPath = join(__dirname3, "..", "package.json");
472
+ const packageJsonPath = join(__dirname4, "..", "package.json");
300
473
  const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
301
474
  const program = new Command3().name("atomsystem").description("Atom Ground Design System CLI").version(packageJson.version);
302
475
  program.addCommand(add);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atomsystem",
3
- "version": "0.1.46",
3
+ "version": "0.1.48",
4
4
  "type": "module",
5
5
  "homepage": "https://system.atomground.com",
6
6
  "bin": {
@@ -15,12 +15,12 @@
15
15
  "css"
16
16
  ],
17
17
  "scripts": {
18
- "dev": "node build/build-tokens.js && next dev",
18
+ "dev": "node build/build-tokens.js && next dev --webpack",
19
19
  "build": "next build",
20
20
  "start": "next start",
21
21
  "lint": "next lint",
22
22
  "token-build": "node build/build-tokens.js",
23
- "cli:build": "tsup src/index.ts --format esm --clean --shims --target node20",
23
+ "cli:build": "tsup src/index.ts --format esm --clean --shims --target node20 --no-splitting",
24
24
  "cli:dev": "tsx src/index.ts"
25
25
  },
26
26
  "peerDependencies": {
@@ -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
- }