atomsystem 0.1.25 → 0.1.27
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.
- package/README.md +13 -5
- package/app/templates/Badge/Badge.tsx +2 -4
- package/app/templates/Button/Button.tsx +2 -24
- package/app/templates/Card/Card.tsx +4 -5
- package/app/templates/CodeBlock/CodeBlock.tsx +18 -2
- package/app/templates/Collapse/Collapse.tsx +10 -10
- package/app/templates/{Input/Input.tsx → Form/Form.tsx} +69 -88
- package/app/templates/Modal/Modal.tsx +7 -7
- package/app/templates/Navigation/Navigation.tsx +306 -0
- package/app/templates/Pagination/Pagination.tsx +6 -6
- package/app/templates/Tab/Tab.tsx +10 -10
- package/app/templates/Table/Table.tsx +9 -18
- package/app/templates/Theme/Theme.tsx +87 -80
- package/app/templates/Toast/Toast.tsx +4 -4
- package/build/build-tokens.js +204 -53
- package/build/css/_variables.css +315 -0
- package/build/typescript/theme.ts +14 -0
- package/cli/add.js +35 -3
- package/cli/init.js +82 -14
- package/css/badge.css +28 -0
- package/css/button.css +75 -0
- package/css/card.css +17 -0
- package/css/collapse.css +33 -0
- package/css/form.css +115 -0
- package/css/modal.css +98 -0
- package/css/navigation.css +69 -0
- package/css/pagination.css +66 -0
- package/css/tab.css +56 -0
- package/css/table.css +58 -0
- package/css/text.css +25 -0
- package/css/toast.css +69 -0
- package/package.json +10 -6
- package/tokens/tokens.json +949 -0
- package/app/templates/GlobalNav/GlobalNav.tsx +0 -199
- package/token.json +0 -492
package/cli/add.js
CHANGED
|
@@ -19,7 +19,7 @@ const components = [
|
|
|
19
19
|
"Card",
|
|
20
20
|
"Collapse",
|
|
21
21
|
"CodeBlock",
|
|
22
|
-
"
|
|
22
|
+
"Navigation",
|
|
23
23
|
"Input",
|
|
24
24
|
"Theme",
|
|
25
25
|
"Tab",
|
|
@@ -34,21 +34,53 @@ const components = [
|
|
|
34
34
|
const args = process.argv.slice(2); // 'npx atomsystem-add Button -> [Button]'
|
|
35
35
|
const component = args[0] || "all"; // '사용자가 입력하지 않으면 기본적으로 'all''
|
|
36
36
|
|
|
37
|
+
// 일부 컴포넌트의 의존성 구조 (Theme 설치시 내부적으로 Button, Form, Modal 등이 필요함)
|
|
38
|
+
const dependenciesMap = {
|
|
39
|
+
Theme: ["Button", "Form", "Modal"], // Form 안에는 Radio가 들어있음
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// 재귀 방지를 위한 Set
|
|
43
|
+
const addedComponents = new Set();
|
|
44
|
+
|
|
37
45
|
function addComponent(comp) {
|
|
46
|
+
if (addedComponents.has(comp)) return;
|
|
47
|
+
addedComponents.add(comp);
|
|
38
48
|
const componentPath = path.join(templateDir, comp, `${comp}.tsx`);
|
|
39
49
|
const targetDir = path.join(process.cwd(), "app", "components", comp);
|
|
40
50
|
const targetPath = path.join(targetDir, `${comp}.tsx`);
|
|
41
51
|
|
|
52
|
+
// 컴포넌트의 CSS 파일 복제 지원
|
|
53
|
+
const cssFileName = `${comp}.css`.toLowerCase();
|
|
54
|
+
const sourceCssPath = path.join(__dirname, "..", "css", cssFileName);
|
|
55
|
+
const targetCssPath = path.join(targetDir, cssFileName);
|
|
56
|
+
|
|
42
57
|
if (fs.existsSync(componentPath)) {
|
|
43
58
|
// 대상 디렉토리가 없으면 생성
|
|
44
59
|
if (!fs.existsSync(targetDir)) {
|
|
45
60
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
46
61
|
console.log(`Created directory: ${targetDir}`);
|
|
47
62
|
}
|
|
63
|
+
|
|
64
|
+
// 1) TSX 복사
|
|
48
65
|
copyFileSync(componentPath, targetPath);
|
|
49
|
-
console.log(
|
|
66
|
+
console.log(`✅ ${comp} component typescript has been added to ${targetPath}`);
|
|
67
|
+
|
|
68
|
+
// 2) CSS 복사
|
|
69
|
+
if (fs.existsSync(sourceCssPath)) {
|
|
70
|
+
copyFileSync(sourceCssPath, targetCssPath);
|
|
71
|
+
console.log(`✅ ${comp} component stylesheet has been added to ${targetCssPath}`);
|
|
72
|
+
}
|
|
73
|
+
// 3) 의존성 컴포넌트 자동 복사 (Recursive Copy)
|
|
74
|
+
if (dependenciesMap[comp]) {
|
|
75
|
+
console.log(`\n⏳ Checking dependencies for ${comp}...`);
|
|
76
|
+
dependenciesMap[comp].forEach((dep) => {
|
|
77
|
+
addComponent(dep);
|
|
78
|
+
});
|
|
79
|
+
console.log(`✅ Finished adding dependencies for ${comp}.\n`);
|
|
80
|
+
}
|
|
81
|
+
|
|
50
82
|
} else {
|
|
51
|
-
console.log(
|
|
83
|
+
console.log(`❌ Component ${comp} does not exist in the atomsystem.`);
|
|
52
84
|
}
|
|
53
85
|
}
|
|
54
86
|
|
package/cli/init.js
CHANGED
|
@@ -14,14 +14,23 @@ const __dirname = path.dirname(__filename);
|
|
|
14
14
|
|
|
15
15
|
// 패키지 내부 경로 설정
|
|
16
16
|
const packageRoot = path.join(__dirname, "..");
|
|
17
|
-
const tokenFile = path.join(packageRoot, "
|
|
18
|
-
const buildFile = path.join(packageRoot, "
|
|
17
|
+
const tokenFile = path.join(packageRoot, "tokens", "tokens.json");
|
|
18
|
+
const buildFile = path.join(packageRoot, "build", "build-tokens.js");
|
|
19
19
|
|
|
20
20
|
// 프로젝트 루트 경로 (사용자가 실행한 곳)
|
|
21
21
|
const projectRoot = process.cwd();
|
|
22
|
-
const
|
|
22
|
+
const targetTokenDir = path.join(projectRoot, "tokens");
|
|
23
|
+
const targetTokenFile = path.join(targetTokenDir, "tokens.json");
|
|
23
24
|
const targetBuildDir = path.join(projectRoot, "build");
|
|
24
|
-
const targetBuildFile = path.join(
|
|
25
|
+
const targetBuildFile = path.join(targetBuildDir, "build-tokens.js");
|
|
26
|
+
|
|
27
|
+
// 사용자 프로젝트에 package.json이 존재하는지 먼저 확인 (안전장치)
|
|
28
|
+
const packageJsonPath = path.join(projectRoot, "package.json");
|
|
29
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
30
|
+
console.error("❌ Error: package.json not found in the current directory.");
|
|
31
|
+
console.error("Please run 'npm init' or 'npm init -y' before running atomsystem-init.");
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
25
34
|
|
|
26
35
|
// 사용자에게 Next.js 설치 여부 질문
|
|
27
36
|
inquirer
|
|
@@ -41,9 +50,18 @@ inquirer
|
|
|
41
50
|
await execPromise(
|
|
42
51
|
"npm install next@latest react@latest react-dom@latest tailwindcss"
|
|
43
52
|
);
|
|
44
|
-
console.log("✅ Installation complete!");
|
|
53
|
+
console.log("✅ Next.js and React Installation complete!");
|
|
45
54
|
} catch (err) {
|
|
46
|
-
console.error("❌ Error during installation:", err);
|
|
55
|
+
console.error("❌ Error during Next.js/React installation:", err);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
console.log("Installing style-dictionary for atom design tokens...");
|
|
60
|
+
try {
|
|
61
|
+
await execPromise("npm install style-dictionary -D");
|
|
62
|
+
console.log("✅ style-dictionary Installation complete!");
|
|
63
|
+
} catch (err) {
|
|
64
|
+
console.error("❌ Error during style-dictionary installation:", err);
|
|
47
65
|
return;
|
|
48
66
|
}
|
|
49
67
|
|
|
@@ -54,6 +72,7 @@ inquirer
|
|
|
54
72
|
fs.readFileSync(packageJsonPath, "utf8")
|
|
55
73
|
);
|
|
56
74
|
|
|
75
|
+
packageJson.type = "module";
|
|
57
76
|
packageJson.scripts = {
|
|
58
77
|
...packageJson.scripts,
|
|
59
78
|
"token-build": "node build/build-tokens.js",
|
|
@@ -71,20 +90,68 @@ inquirer
|
|
|
71
90
|
if (!fs.existsSync(appDir)) mkdirSync(appDir);
|
|
72
91
|
|
|
73
92
|
const files = [
|
|
93
|
+
{
|
|
94
|
+
path: path.join(appDir, "ThemeProvider.tsx"),
|
|
95
|
+
content: `"use client";
|
|
96
|
+
import { useEffect, useState } from "react";
|
|
97
|
+
import { themes } from "@/build/typescript/theme";
|
|
98
|
+
|
|
99
|
+
export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
|
|
100
|
+
const [theme, setTheme] = useState<Record<string, string>>({});
|
|
101
|
+
const [isThemeLoading, setThemeLoading] = useState(false);
|
|
102
|
+
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
const listenStorageChange = () => {
|
|
105
|
+
const newThemes: Record<string, string> = {};
|
|
106
|
+
Object.entries(themes).forEach(([group, groupThemes]) => {
|
|
107
|
+
const storedKey = group === "global" ? "theme" : \`theme-\${group}\`;
|
|
108
|
+
const currentTheme = localStorage.getItem(storedKey) || groupThemes[0];
|
|
109
|
+
newThemes[group] = currentTheme;
|
|
110
|
+
|
|
111
|
+
document.documentElement.classList.remove(...groupThemes);
|
|
112
|
+
document.documentElement.classList.add(currentTheme);
|
|
113
|
+
});
|
|
114
|
+
setTheme(newThemes);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
listenStorageChange();
|
|
118
|
+
window.addEventListener("storage", listenStorageChange);
|
|
119
|
+
setThemeLoading(true);
|
|
120
|
+
return () => window.removeEventListener("storage", listenStorageChange);
|
|
121
|
+
}, []);
|
|
122
|
+
|
|
123
|
+
if (isThemeLoading === false) return null;
|
|
124
|
+
return <>{children}</>;
|
|
125
|
+
};`,
|
|
126
|
+
},
|
|
74
127
|
{
|
|
75
128
|
path: path.join(appDir, "layout.tsx"),
|
|
76
|
-
content: `
|
|
129
|
+
content: `import { ThemeProvider } from "./ThemeProvider";
|
|
130
|
+
import "../css/global.css"; // Ensure to load the CSS configuration if possible
|
|
131
|
+
|
|
132
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
77
133
|
return (
|
|
78
134
|
<html lang="en">
|
|
79
|
-
<body>
|
|
135
|
+
<body>
|
|
136
|
+
<ThemeProvider>
|
|
137
|
+
{children}
|
|
138
|
+
</ThemeProvider>
|
|
139
|
+
</body>
|
|
80
140
|
</html>
|
|
81
141
|
)
|
|
82
142
|
}`,
|
|
83
143
|
},
|
|
84
144
|
{
|
|
85
145
|
path: path.join(appDir, "page.tsx"),
|
|
86
|
-
content: `
|
|
87
|
-
|
|
146
|
+
content: `import { ThemeSelector } from "./components/Theme/Theme";
|
|
147
|
+
|
|
148
|
+
export default function Page() {
|
|
149
|
+
return (
|
|
150
|
+
<main style={{ padding: "20px" }}>
|
|
151
|
+
<h1>Hello, atomsystem!</h1>
|
|
152
|
+
<ThemeSelector />
|
|
153
|
+
</main>
|
|
154
|
+
)
|
|
88
155
|
}`,
|
|
89
156
|
},
|
|
90
157
|
];
|
|
@@ -97,13 +164,14 @@ inquirer
|
|
|
97
164
|
console.log("🚀 Installation skipped.");
|
|
98
165
|
}
|
|
99
166
|
|
|
100
|
-
// ✅ 토큰 파일 복사 (Next.js 설치 여부와 관계없이 실행)
|
|
167
|
+
// ✅ 토큰 파일과 빌드 파일 복사 (Next.js 설치 여부와 관계없이 실행)
|
|
168
|
+
if (!fs.existsSync(targetTokenDir)) mkdirSync(targetTokenDir, { recursive: true });
|
|
101
169
|
copyFileSync(tokenFile, targetTokenFile);
|
|
102
|
-
console.log(`✅ Copied:
|
|
170
|
+
console.log(`✅ Copied: tokens/tokens.json -> ${targetTokenFile}`);
|
|
103
171
|
|
|
104
|
-
if (!fs.existsSync(targetBuildDir)) mkdirSync(targetBuildDir);
|
|
172
|
+
if (!fs.existsSync(targetBuildDir)) mkdirSync(targetBuildDir, { recursive: true });
|
|
105
173
|
copyFileSync(buildFile, targetBuildFile);
|
|
106
|
-
console.log(`✅ Copied: build-
|
|
174
|
+
console.log(`✅ Copied: build-tokens.js -> ${targetBuildFile}`);
|
|
107
175
|
|
|
108
176
|
console.log("🚀 Token setup complete!");
|
|
109
177
|
})
|
package/css/badge.css
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
}
|
package/css/button.css
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
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
|
+
--btn-bg: var(--color-primary);
|
|
13
|
+
--btn-hover: var(--color-blue-600);
|
|
14
|
+
--btn-active: var(--color-blue-700);
|
|
15
|
+
--btn-bg-disabled: var(--button-primary-bg-disabled);
|
|
16
|
+
--btn-text-disabled: var(--button-primary-text-disabled);
|
|
17
|
+
--btn-border-disabled: var(--button-primary-border-disabled);
|
|
18
|
+
}
|
|
19
|
+
.btn.secondary {
|
|
20
|
+
--btn-bg: var(--color-secondary);
|
|
21
|
+
--btn-hover: var(--color-indigo-600);
|
|
22
|
+
--btn-active: var(--color-indigo-700);
|
|
23
|
+
--btn-bg-disabled: var(--button-secondary-bg-disabled);
|
|
24
|
+
--btn-text-disabled: var(--button-secondary-text-disabled);
|
|
25
|
+
--btn-border-disabled: var(--button-secondary-border-disabled);
|
|
26
|
+
}
|
|
27
|
+
.btn.success {
|
|
28
|
+
--btn-bg: var(--color-success);
|
|
29
|
+
--btn-hover: var(--color-green-600);
|
|
30
|
+
--btn-active: var(--color-green-700);
|
|
31
|
+
--btn-bg-disabled: var(--button-success-bg-disabled);
|
|
32
|
+
--btn-text-disabled: var(--button-success-text-disabled);
|
|
33
|
+
--btn-border-disabled: var(--button-success-border-disabled);
|
|
34
|
+
}
|
|
35
|
+
.btn.warning {
|
|
36
|
+
--btn-bg: var(--color-warning);
|
|
37
|
+
--btn-hover: var(--color-yellow-600);
|
|
38
|
+
--btn-active: var(--color-yellow-700);
|
|
39
|
+
--btn-bg-disabled: var(--button-warning-bg-disabled);
|
|
40
|
+
--btn-text-disabled: var(--button-warning-text-disabled);
|
|
41
|
+
--btn-border-disabled: var(--button-warning-border-disabled);
|
|
42
|
+
}
|
|
43
|
+
.btn.danger {
|
|
44
|
+
--btn-bg: var(--color-danger);
|
|
45
|
+
--btn-hover: var(--color-red-600);
|
|
46
|
+
--btn-active: var(--color-red-700);
|
|
47
|
+
--btn-bg-disabled: var(--button-danger-bg-disabled);
|
|
48
|
+
--btn-text-disabled: var(--button-danger-text-disabled);
|
|
49
|
+
--btn-border-disabled: var(--button-danger-border-disabled);
|
|
50
|
+
}
|
|
51
|
+
.btn.gray {
|
|
52
|
+
--btn-bg: var(--color-gray-500);
|
|
53
|
+
--btn-hover: var(--color-gray-600);
|
|
54
|
+
--btn-active: var(--color-gray-700);
|
|
55
|
+
--btn-bg-disabled: var(--button-gray-bg-disabled);
|
|
56
|
+
--btn-text-disabled: var(--button-gray-text-disabled);
|
|
57
|
+
--btn-border-disabled: var(--button-gray-border-disabled);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.btn {
|
|
61
|
+
background-color: var(--btn-bg);
|
|
62
|
+
}
|
|
63
|
+
.btn:hover:not(:disabled) {
|
|
64
|
+
background-color: var(--btn-hover);
|
|
65
|
+
}
|
|
66
|
+
.btn:active:not(:disabled) {
|
|
67
|
+
background-color: var(--btn-active);
|
|
68
|
+
}
|
|
69
|
+
.btn:disabled {
|
|
70
|
+
background-color: var(--btn-bg-disabled);
|
|
71
|
+
color: var(--btn-text-disabled);
|
|
72
|
+
cursor: not-allowed;
|
|
73
|
+
opacity: 0.7;
|
|
74
|
+
border: 1px solid var(--btn-border-disabled);
|
|
75
|
+
}
|
package/css/card.css
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
}
|
package/css/collapse.css
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
transition: transform 0.3s ease;
|
|
18
|
+
color: var(--text-standard);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.collapse-icon.open {
|
|
22
|
+
transform: rotate(90deg);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.collapse-icon.closed {
|
|
26
|
+
transform: rotate(0deg);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.collapse-content {
|
|
30
|
+
padding: var(--spacing-common-x);
|
|
31
|
+
color: var(--text-standard);
|
|
32
|
+
font-size: var(--text-body);
|
|
33
|
+
}
|
package/css/form.css
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
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
|
+
}
|
package/css/modal.css
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
.nav-container.nav-topnav {
|
|
4
|
+
background-color: var(--bg-topnav);
|
|
5
|
+
color: var(--text-topnav-standard);
|
|
6
|
+
border-color: var(--border-topnav);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.nav-container.nav-sidenav {
|
|
10
|
+
background-color: var(--bg-sidenav);
|
|
11
|
+
color: var(--text-sidenav-standard);
|
|
12
|
+
border-color: var(--border-sidenav);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.nav-bg.nav-topnav {
|
|
16
|
+
background-color: var(--bg-topnav);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.nav-bg.nav-sidenav {
|
|
20
|
+
background-color: var(--bg-sidenav);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.nav-border.nav-topnav {
|
|
24
|
+
border-color: var(--border-topnav);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.nav-border.nav-sidenav {
|
|
28
|
+
border-color: var(--border-sidenav);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.nav-text-standard.nav-topnav {
|
|
32
|
+
color: var(--text-topnav-standard);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.nav-text-standard.nav-sidenav {
|
|
36
|
+
color: var(--text-sidenav-standard);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.nav-text-active.nav-topnav {
|
|
40
|
+
color: var(--text-topnav-active);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.nav-text-active.nav-sidenav {
|
|
44
|
+
color: var(--text-sidenav-active);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.nav-text-sub.nav-topnav {
|
|
48
|
+
color: var(--text-topnav-sub);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.nav-text-sub.nav-sidenav {
|
|
52
|
+
color: var(--text-sidenav-sub);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.nav-padding.nav-topnav {
|
|
56
|
+
padding: var(--spacing-topnav-y) var(--spacing-topnav-x);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.nav-padding.nav-sidenav {
|
|
60
|
+
padding: var(--spacing-sidenav-y) var(--spacing-sidenav-x);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.nav-gap.nav-topnav {
|
|
64
|
+
gap: var(--spacing-topnav-gap);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.nav-gap.nav-sidenav {
|
|
68
|
+
gap: var(--spacing-sidenav-gap);
|
|
69
|
+
}
|