@howssatoshi/quantumcss 1.4.3 → 1.5.0
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 +8 -7
- package/dist/quantum.min.css +1 -4678
- package/examples/blog-template.html +2 -16
- package/examples/gaming-template.html +0 -20
- package/examples/index.html +5 -8
- package/examples/news-template.html +5 -18
- package/examples/shopping/index.html +5 -19
- package/examples/starlight.html +3 -16
- package/examples/theme-test.html +174 -0
- package/examples/travel/index.html +3 -16
- package/examples/verify_fixes.html +1 -0
- package/examples/verify_presets.html +2 -1
- package/package.json +7 -1
- package/src/generator.js +19 -8
- package/src/starlight.js +406 -15
- package/src/styles/quantum-animations.css +3 -2
- package/src/styles/quantum-base.css +295 -91
- package/src/styles/quantum-components.css +47 -47
- package/src/styles/quantum-responsive.css +5 -4
- package/src/styles/starlight.css +184 -184
|
@@ -260,22 +260,8 @@
|
|
|
260
260
|
</footer>
|
|
261
261
|
|
|
262
262
|
<script>
|
|
263
|
-
// Theme
|
|
264
|
-
|
|
265
|
-
if (themeBtn) {
|
|
266
|
-
themeBtn.addEventListener('click', () => {
|
|
267
|
-
document.body.classList.toggle('light-mode');
|
|
268
|
-
const isLight = document.body.classList.contains('light-mode');
|
|
269
|
-
|
|
270
|
-
// Update all icons
|
|
271
|
-
document.querySelectorAll('.sun-icon').forEach(icon => {
|
|
272
|
-
icon.classList.toggle('hidden', !isLight);
|
|
273
|
-
});
|
|
274
|
-
document.querySelectorAll('.moon-icon').forEach(icon => {
|
|
275
|
-
icon.classList.toggle('hidden', isLight);
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
}
|
|
263
|
+
// Theme initialization is handled automatically by starlight.js
|
|
264
|
+
// Custom template logic can go here
|
|
279
265
|
</script>
|
|
280
266
|
|
|
281
267
|
</body>
|
|
@@ -333,26 +333,6 @@
|
|
|
333
333
|
|
|
334
334
|
<script src="../src/starlight.js"></script>
|
|
335
335
|
<script>
|
|
336
|
-
const themeBtns = [document.getElementById('theme-btn'), document.getElementById('theme-btn-mobile')];
|
|
337
|
-
|
|
338
|
-
// Theme Toggle Logic
|
|
339
|
-
themeBtns.forEach(btn => {
|
|
340
|
-
if (btn) {
|
|
341
|
-
btn.addEventListener('click', () => {
|
|
342
|
-
document.body.classList.toggle('light-mode');
|
|
343
|
-
const isLight = document.body.classList.contains('light-mode');
|
|
344
|
-
|
|
345
|
-
// Update all icons
|
|
346
|
-
document.querySelectorAll('.sun-icon').forEach(icon => {
|
|
347
|
-
icon.classList.toggle('hidden', !isLight);
|
|
348
|
-
});
|
|
349
|
-
document.querySelectorAll('.moon-icon').forEach(icon => {
|
|
350
|
-
icon.classList.toggle('hidden', isLight);
|
|
351
|
-
});
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
|
|
356
336
|
// Accordion Logic
|
|
357
337
|
document.querySelectorAll('.accordion-header').forEach(header => {
|
|
358
338
|
header.addEventListener('click', () => {
|
package/examples/index.html
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
flex-shrink: 0;
|
|
20
20
|
}
|
|
21
21
|
.theme-toggle:hover { background: rgba(255,255,255,0.1); transform: scale(1.05); }
|
|
22
|
-
|
|
22
|
+
html[data-theme="light"] .theme-toggle { background: #fff; border-color: #cbd5e1; box-shadow: 0 4px 12px rgba(0,0,0,0.05); }
|
|
23
23
|
.theme-toggle svg { width: 1.5rem; height: 1.5rem; }
|
|
24
24
|
.hidden { display: none; }
|
|
25
25
|
</style>
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
|
|
62
62
|
<header class="hero container">
|
|
63
63
|
<div class="pt-8 pb-12 text-center">
|
|
64
|
-
<span class="text-[10px] font-black tracking-[0.3em] text-starlight uppercase mb-6 block">QuantumCSS v1.
|
|
64
|
+
<span class="text-[10px] font-black tracking-[0.3em] text-starlight uppercase mb-6 block">QuantumCSS v1.5.0</span>
|
|
65
65
|
<h1 class="text-7xl md:text-8xl text-gradient-starlight font-black uppercase italic tracking-tighter mb-8">Starlight Design</h1>
|
|
66
66
|
<p class="text-xl text-slate-400 max-w-3xl mx-auto mb-12 font-medium leading-relaxed">
|
|
67
67
|
A standardized, high-performance UI library.
|
|
@@ -128,14 +128,11 @@
|
|
|
128
128
|
</main>
|
|
129
129
|
|
|
130
130
|
<script>
|
|
131
|
-
function toggleTheme() {
|
|
132
|
-
document.body.classList.toggle('light-mode');
|
|
133
|
-
const isLight = document.body.classList.contains('light-mode');
|
|
134
|
-
document.querySelector('.sun-icon').classList.toggle('hidden', !isLight);
|
|
135
|
-
document.querySelector('.moon-icon').classList.toggle('hidden', isLight);
|
|
136
|
-
}
|
|
137
131
|
function openDialog() { document.getElementById('dialog').style.display = 'flex'; }
|
|
138
132
|
function closeDialog() { document.getElementById('dialog').style.display = 'none'; }
|
|
133
|
+
|
|
134
|
+
// Theme initialization and system preference detection are now handled
|
|
135
|
+
// automatically by Starlight.initTheme() in starlight.js
|
|
139
136
|
</script>
|
|
140
137
|
</body>
|
|
141
138
|
</html>
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Quantum News | Decoding the Future</title>
|
|
7
7
|
<link rel="stylesheet" href="../dist/quantum.min.css">
|
|
8
|
+
<script src="../src/starlight.js"></script>
|
|
8
9
|
<style>
|
|
9
10
|
body { background-color: #020617; color: #f1f5f9; transition: background-color 0.5s ease, color 0.5s ease; }
|
|
10
|
-
|
|
11
|
+
html[data-theme="light"] body { background-color: #ffffff; color: #0f172a; }
|
|
11
12
|
.news-grid { display: grid; grid-template-columns: 1fr; gap: 2rem; }
|
|
12
13
|
@media (min-width: 1024px) {
|
|
13
14
|
.news-grid { grid-template-columns: 3fr 1fr; }
|
|
@@ -147,7 +148,7 @@
|
|
|
147
148
|
.sun-icon { display: none; }
|
|
148
149
|
</style>
|
|
149
150
|
</head>
|
|
150
|
-
<body class="font-sans antialiased
|
|
151
|
+
<body class="font-sans antialiased">
|
|
151
152
|
<!-- Top Bar -->
|
|
152
153
|
<div class="border-b border-slate-100 py-2 bg-slate-50">
|
|
153
154
|
<div class="container mx-auto px-6 flex justify-between items-center text-[10px] font-bold uppercase tracking-widest text-slate-500">
|
|
@@ -312,22 +313,8 @@
|
|
|
312
313
|
}
|
|
313
314
|
</style>
|
|
314
315
|
<script>
|
|
315
|
-
// Theme
|
|
316
|
-
|
|
317
|
-
if (themeBtn) {
|
|
318
|
-
themeBtn.addEventListener('click', () => {
|
|
319
|
-
document.body.classList.toggle('light-mode');
|
|
320
|
-
const isLight = document.body.classList.contains('light-mode');
|
|
321
|
-
|
|
322
|
-
// Update all icons
|
|
323
|
-
document.querySelectorAll('.sun-icon').forEach(icon => {
|
|
324
|
-
icon.style.display = isLight ? 'block' : 'none';
|
|
325
|
-
});
|
|
326
|
-
document.querySelectorAll('.moon-icon').forEach(icon => {
|
|
327
|
-
icon.style.display = isLight ? 'none' : 'block';
|
|
328
|
-
});
|
|
329
|
-
});
|
|
330
|
-
}
|
|
316
|
+
// Theme initialization and management is now handled
|
|
317
|
+
// automatically by Starlight.initTheme() in starlight.js
|
|
331
318
|
</script>
|
|
332
319
|
</body>
|
|
333
320
|
</html>
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Quantum Store | Future of Fashion</title>
|
|
7
7
|
<link rel="stylesheet" href="../../dist/quantum.min.css">
|
|
8
|
+
<script src="../../src/starlight.js"></script>
|
|
8
9
|
<style>
|
|
9
10
|
body { background-color: #f8fafc; color: #0f172a; transition: background-color 0.5s ease, color 0.5s ease; }
|
|
10
11
|
body.dark-mode { background-color: #020617; color: #f1f5f9; }
|
|
@@ -111,7 +112,7 @@
|
|
|
111
112
|
.moon-icon { display: none; }
|
|
112
113
|
</style>
|
|
113
114
|
</head>
|
|
114
|
-
<body class="
|
|
115
|
+
<body class="">
|
|
115
116
|
<!-- Announcement Bar -->
|
|
116
117
|
<div class="bg-slate-900 text-white py-3 text-center text-[10px] font-black tracking-[0.3em] uppercase">
|
|
117
118
|
Interstellar Shipping Enabled • New Drops Every Sunday
|
|
@@ -313,24 +314,6 @@
|
|
|
313
314
|
</footer>
|
|
314
315
|
|
|
315
316
|
<script>
|
|
316
|
-
// Theme Toggle Logic
|
|
317
|
-
const themeBtn = document.getElementById('theme-btn');
|
|
318
|
-
if (themeBtn) {
|
|
319
|
-
themeBtn.addEventListener('click', () => {
|
|
320
|
-
document.body.classList.toggle('light-mode');
|
|
321
|
-
document.body.classList.toggle('dark-mode');
|
|
322
|
-
const isDark = document.body.classList.contains('dark-mode');
|
|
323
|
-
|
|
324
|
-
// Update all icons
|
|
325
|
-
document.querySelectorAll('.sun-icon').forEach(icon => {
|
|
326
|
-
icon.style.display = isDark ? 'none' : 'block';
|
|
327
|
-
});
|
|
328
|
-
document.querySelectorAll('.moon-icon').forEach(icon => {
|
|
329
|
-
icon.style.display = isDark ? 'block' : 'none';
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
|
|
334
317
|
// Color Swatch Selection
|
|
335
318
|
const swatches = document.querySelectorAll('.color-swatch');
|
|
336
319
|
swatches.forEach(swatch => {
|
|
@@ -339,6 +322,9 @@
|
|
|
339
322
|
swatch.classList.add('selected');
|
|
340
323
|
});
|
|
341
324
|
});
|
|
325
|
+
|
|
326
|
+
// Theme initialization and management is now handled
|
|
327
|
+
// automatically by Starlight.initTheme() in starlight.js
|
|
342
328
|
</script>
|
|
343
329
|
</body>
|
|
344
330
|
</html>
|
package/examples/starlight.html
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Starlight AI - Design System</title>
|
|
7
7
|
<link rel="stylesheet" href="../dist/quantum.min.css">
|
|
8
|
+
<script src="../src/starlight.js"></script>
|
|
8
9
|
<style>
|
|
9
10
|
body {
|
|
10
11
|
background: linear-gradient(135deg, #0a0a1a 0%, #1a1a3a 100%);
|
|
@@ -153,22 +154,8 @@
|
|
|
153
154
|
</div>
|
|
154
155
|
|
|
155
156
|
<script>
|
|
156
|
-
// Theme
|
|
157
|
-
|
|
158
|
-
if (themeBtn) {
|
|
159
|
-
themeBtn.addEventListener('click', () => {
|
|
160
|
-
document.body.classList.toggle('light-mode');
|
|
161
|
-
const isLight = document.body.classList.contains('light-mode');
|
|
162
|
-
|
|
163
|
-
// Update all icons
|
|
164
|
-
document.querySelectorAll('.sun-icon').forEach(icon => {
|
|
165
|
-
icon.classList.toggle('hidden', !isLight);
|
|
166
|
-
});
|
|
167
|
-
document.querySelectorAll('.moon-icon').forEach(icon => {
|
|
168
|
-
icon.classList.toggle('hidden', isLight);
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
}
|
|
157
|
+
// Theme initialization and management is now handled
|
|
158
|
+
// automatically by Starlight.initTheme() in starlight.js
|
|
172
159
|
</script>
|
|
173
160
|
</body>
|
|
174
161
|
</html>
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Theme Auto-Detection Test</title>
|
|
7
|
+
<link rel="stylesheet" href="../dist/quantum.min.css">
|
|
8
|
+
<script src="../src/starlight.js"></script>
|
|
9
|
+
<style>
|
|
10
|
+
body { min-height: 100vh; }
|
|
11
|
+
.demo-section {
|
|
12
|
+
margin: 2rem auto;
|
|
13
|
+
max-width: 600px;
|
|
14
|
+
padding: 2rem;
|
|
15
|
+
}
|
|
16
|
+
.theme-controls {
|
|
17
|
+
display: flex;
|
|
18
|
+
gap: 1rem;
|
|
19
|
+
margin-bottom: 2rem;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
}
|
|
22
|
+
.status-message {
|
|
23
|
+
background: var(--glass-bg);
|
|
24
|
+
border: 1px solid var(--glass-border);
|
|
25
|
+
border-radius: var(--radius-lg);
|
|
26
|
+
padding: 1rem;
|
|
27
|
+
margin-top: 1rem;
|
|
28
|
+
font-family: monospace;
|
|
29
|
+
font-size: 0.875rem;
|
|
30
|
+
}
|
|
31
|
+
</style>
|
|
32
|
+
</head>
|
|
33
|
+
<body>
|
|
34
|
+
<div class="starlight-stars" id="stars"></div>
|
|
35
|
+
|
|
36
|
+
<div class="demo-section starlight-card">
|
|
37
|
+
<h1>🎨 Theme Auto-Detection Test</h1>
|
|
38
|
+
|
|
39
|
+
<div class="theme-controls">
|
|
40
|
+
<button class="btn-starlight" onclick="setTheme('light')">☀️ Light</button>
|
|
41
|
+
<button class="btn-secondary" onclick="setTheme('dark')">🌙 Dark</button>
|
|
42
|
+
<button class="btn-outline" onclick="setTheme('auto')">🖥️ Follow System</button>
|
|
43
|
+
<button class="btn-ghost" onclick="toggleTheme()">🔄 Cycle</button>
|
|
44
|
+
<button class="btn-success" onclick="resetToAuto()">🔄 Reset to Auto</button>
|
|
45
|
+
<button class="btn-warning" onclick="forceRefresh()">🔃 Force Refresh</button>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div class="status-message" id="status">
|
|
49
|
+
Loading theme information...
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<h3>Instructions:</h3>
|
|
53
|
+
<ol>
|
|
54
|
+
<li>Click "Follow System" to enable automatic theme switching</li>
|
|
55
|
+
<li>Change your OS theme (macOS: System Settings → Appearance, Windows: Settings → Personalization → Colors)</li>
|
|
56
|
+
<li>The webpage should automatically switch to match your OS</li>
|
|
57
|
+
<li>Try "Cycle" to rotate through all available themes</li>
|
|
58
|
+
</ol>
|
|
59
|
+
|
|
60
|
+
<h3>Current State:</h3>
|
|
61
|
+
<div id="current-state"></div>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<script>
|
|
65
|
+
// Monitor theme changes
|
|
66
|
+
function updateStatus() {
|
|
67
|
+
const html = document.documentElement;
|
|
68
|
+
const currentTheme = html.getAttribute('data-theme');
|
|
69
|
+
const savedTheme = localStorage.getItem('theme');
|
|
70
|
+
const effectiveTheme = localStorage.getItem('theme-effective');
|
|
71
|
+
const systemPrefers = window.matchMedia('(prefers-color-scheme: light)').matches;
|
|
72
|
+
|
|
73
|
+
const statusEl = document.getElementById('status');
|
|
74
|
+
const stateEl = document.getElementById('current-state');
|
|
75
|
+
|
|
76
|
+
// Debug information
|
|
77
|
+
console.log('Theme Debug:', {
|
|
78
|
+
currentTheme,
|
|
79
|
+
savedTheme,
|
|
80
|
+
effectiveTheme,
|
|
81
|
+
systemPrefers,
|
|
82
|
+
htmlDataTheme: html.getAttribute('data-theme'),
|
|
83
|
+
htmlAttributes: Object.keys(html.attributes).map(attr => `${attr}: ${html.getAttribute(attr)}`)
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
statusEl.innerHTML = `
|
|
87
|
+
<strong>Current Theme:</strong> ${currentTheme || 'null'}<br>
|
|
88
|
+
<strong>Saved Preference:</strong> ${savedTheme || 'none'}<br>
|
|
89
|
+
<strong>Effective Theme:</strong> ${effectiveTheme || currentTheme || 'null'}<br>
|
|
90
|
+
<strong>System Prefers:</strong> ${systemPrefers ? 'light' : 'dark'}
|
|
91
|
+
`;
|
|
92
|
+
|
|
93
|
+
stateEl.innerHTML = `
|
|
94
|
+
<div class="starlight-card" style="padding: 1rem; margin-top: 1rem;">
|
|
95
|
+
<h4>🎯 Theme Configuration:</h4>
|
|
96
|
+
<p><strong>html[data-theme]:</strong> ${currentTheme}</p>
|
|
97
|
+
<p><strong>localStorage theme:</strong> ${savedTheme || 'null'}</p>
|
|
98
|
+
<p><strong>localStorage theme-effective:</strong> ${effectiveTheme || 'null'}</p>
|
|
99
|
+
<p><strong>System prefers-color-scheme:</strong> ${systemPrefers ? 'light' : 'dark'}</p>
|
|
100
|
+
|
|
101
|
+
<h5>💡 How this works:</h5>
|
|
102
|
+
<ul>
|
|
103
|
+
<li>If theme is "auto", the system preference is followed</li>
|
|
104
|
+
<li>System theme changes are automatically detected</li>
|
|
105
|
+
<li>Your manual choice is saved and restored</li>
|
|
106
|
+
</ul>
|
|
107
|
+
</div>
|
|
108
|
+
`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Listen for theme changes
|
|
112
|
+
window.addEventListener('themechange', (e) => {
|
|
113
|
+
console.log('Theme changed:', e.detail);
|
|
114
|
+
updateStatus();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Listen for system theme changes
|
|
118
|
+
window.matchMedia('(prefers-color-scheme: light)').addEventListener('change', (e) => {
|
|
119
|
+
console.log('System theme changed to:', e.matches ? 'light' : 'dark');
|
|
120
|
+
updateStatus();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Initial update - wait for first themechange event or timeout
|
|
124
|
+
let themeInitialized = false;
|
|
125
|
+
const firstThemeChange = (e) => {
|
|
126
|
+
if (!themeInitialized) {
|
|
127
|
+
themeInitialized = true;
|
|
128
|
+
window.removeEventListener('themechange', firstThemeChange);
|
|
129
|
+
updateStatus();
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
window.addEventListener('themechange', firstThemeChange);
|
|
134
|
+
|
|
135
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
136
|
+
// Wait for Starlight to initialize, then check status
|
|
137
|
+
setTimeout(() => {
|
|
138
|
+
if (!themeInitialized) {
|
|
139
|
+
// If no themechange event fired yet, check current state
|
|
140
|
+
themeInitialized = true;
|
|
141
|
+
window.removeEventListener('themechange', firstThemeChange);
|
|
142
|
+
updateStatus();
|
|
143
|
+
}
|
|
144
|
+
}, 500); // Longer delay to ensure Starlight initialization
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Reset to auto function
|
|
148
|
+
function resetToAuto() {
|
|
149
|
+
console.log('Resetting to auto theme...');
|
|
150
|
+
if (typeof setTheme === 'function') {
|
|
151
|
+
setTheme('auto');
|
|
152
|
+
updateStatus();
|
|
153
|
+
} else {
|
|
154
|
+
console.error('setTheme function not available');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Also update every 2 seconds to show real-time changes
|
|
159
|
+
setInterval(updateStatus, 2000);
|
|
160
|
+
|
|
161
|
+
// Force refresh function
|
|
162
|
+
function forceRefresh() {
|
|
163
|
+
console.log('Forcing theme refresh...');
|
|
164
|
+
// Manually trigger Starlight theme initialization
|
|
165
|
+
if (window.Starlight && window.Starlight.initTheme) {
|
|
166
|
+
window.Starlight.initTheme();
|
|
167
|
+
setTimeout(updateStatus, 100);
|
|
168
|
+
} else {
|
|
169
|
+
console.error('Starlight not available');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
</script>
|
|
173
|
+
</body>
|
|
174
|
+
</html>
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Nebula Voyage | Starlight Travel</title>
|
|
7
7
|
<link rel="stylesheet" href="../../dist/quantum.min.css">
|
|
8
|
+
<script src="../../src/starlight.js"></script>
|
|
8
9
|
<style>
|
|
9
10
|
body {
|
|
10
11
|
background: radial-gradient(circle at top right, #08081a, #000);
|
|
@@ -246,22 +247,8 @@
|
|
|
246
247
|
</footer>
|
|
247
248
|
|
|
248
249
|
<script>
|
|
249
|
-
// Theme
|
|
250
|
-
|
|
251
|
-
if (themeBtn) {
|
|
252
|
-
themeBtn.addEventListener('click', () => {
|
|
253
|
-
document.body.classList.toggle('light-mode');
|
|
254
|
-
const isLight = document.body.classList.contains('light-mode');
|
|
255
|
-
|
|
256
|
-
// Update all icons
|
|
257
|
-
document.querySelectorAll('.sun-icon').forEach(icon => {
|
|
258
|
-
icon.classList.toggle('hidden', !isLight);
|
|
259
|
-
});
|
|
260
|
-
document.querySelectorAll('.moon-icon').forEach(icon => {
|
|
261
|
-
icon.classList.toggle('hidden', isLight);
|
|
262
|
-
});
|
|
263
|
-
});
|
|
264
|
-
}
|
|
250
|
+
// Theme initialization and management is now handled
|
|
251
|
+
// automatically by Starlight.initTheme() in starlight.js
|
|
265
252
|
</script>
|
|
266
253
|
</body>
|
|
267
254
|
</html>
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<title>Verification of Fixes</title>
|
|
6
6
|
<link rel="stylesheet" href="../dist/quantum.min.css">
|
|
7
|
+
<script src="../src/starlight.js"></script>
|
|
7
8
|
</head>
|
|
8
9
|
<body class="p-10 space-y-8 bg-black text-white">
|
|
9
10
|
<nav class="sticky top-0 z-50 glass p-4 mb-8">
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Quantum CSS - Verify Presets</title>
|
|
7
|
-
<link rel="stylesheet" href="../dist/quantum.css">
|
|
7
|
+
<link rel="stylesheet" href="../dist/quantum.min.css">
|
|
8
|
+
<script src="../src/starlight.js"></script>
|
|
8
9
|
</head>
|
|
9
10
|
<body class="bg-gray-50 p-12">
|
|
10
11
|
<div class="max-w-4xl mx-auto space-y-12">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@howssatoshi/quantumcss",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Advanced utility-first CSS framework with JIT generation and modern components",
|
|
5
5
|
"main": "dist/quantum.min.css",
|
|
6
6
|
"bin": {
|
|
@@ -46,5 +46,11 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"chokidar": "^5.0.0",
|
|
48
48
|
"glob": "^13.0.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@eslint/js": "^9.39.2",
|
|
52
|
+
"eslint": "^9.39.2",
|
|
53
|
+
"stylelint": "^17.1.1",
|
|
54
|
+
"stylelint-config-standard": "^40.0.0"
|
|
49
55
|
}
|
|
50
56
|
}
|
package/src/generator.js
CHANGED
|
@@ -58,7 +58,9 @@ function generateCSS(configPath) {
|
|
|
58
58
|
while ((match = classAttrRegex.exec(content)) !== null) {
|
|
59
59
|
match[1].split(/\s+/).forEach(cls => { if (cls) rawClasses.add(cls); });
|
|
60
60
|
}
|
|
61
|
-
} catch
|
|
61
|
+
} catch {
|
|
62
|
+
// Ignore errors reading files
|
|
63
|
+
}
|
|
62
64
|
});
|
|
63
65
|
|
|
64
66
|
const utilities = new Set();
|
|
@@ -67,6 +69,15 @@ function generateCSS(configPath) {
|
|
|
67
69
|
dark: new Set()
|
|
68
70
|
};
|
|
69
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Escapes a class name for use in a CSS selector
|
|
74
|
+
* @param {string} cls - The raw class name
|
|
75
|
+
* @returns {string} The escaped selector
|
|
76
|
+
*/
|
|
77
|
+
const escapeSelector = (cls) => {
|
|
78
|
+
return cls.replace(/([:[\]/.\\])/g, '\\$1');
|
|
79
|
+
};
|
|
80
|
+
|
|
70
81
|
const sideMap = {
|
|
71
82
|
p: 'padding', pt: 'padding-top', pr: 'padding-right', pb: 'padding-bottom', pl: 'padding-left',
|
|
72
83
|
px: ['padding-left', 'padding-right'], py: ['padding-top', 'padding-bottom'],
|
|
@@ -159,8 +170,8 @@ function generateCSS(configPath) {
|
|
|
159
170
|
} else if (prefix === 'col' && cParts[1] === 'span') {
|
|
160
171
|
property = 'grid-column'; value = `span ${cParts[2]} / span ${cParts[2]}`;
|
|
161
172
|
} else if (prefix === 'space') {
|
|
162
|
-
const amount = theme.spacing[cParts[2]] || `${
|
|
163
|
-
const escaped = fullCls
|
|
173
|
+
const amount = theme.spacing[cParts[2]] || `${parseFloat(cParts[2]) * 0.25}rem`;
|
|
174
|
+
const escaped = escapeSelector(fullCls);
|
|
164
175
|
customSelector = `.${escaped} > * + *`;
|
|
165
176
|
property = cParts[1] === 'y' ? 'margin-top' : 'margin-left';
|
|
166
177
|
value = isNeg ? `-${amount}` : amount;
|
|
@@ -169,12 +180,12 @@ function generateCSS(configPath) {
|
|
|
169
180
|
if (valKey.startsWith('[') && valKey.endsWith(']')) value = valKey.slice(1, -1);
|
|
170
181
|
else if (theme.borderRadius[valKey]) value = theme.borderRadius[valKey];
|
|
171
182
|
else {
|
|
172
|
-
const num =
|
|
183
|
+
const num = parseFloat(valKey);
|
|
173
184
|
value = isNaN(num) ? '0.375rem' : `${num * 0.125}rem`;
|
|
174
185
|
}
|
|
175
186
|
} else if (prefix === 'scale') {
|
|
176
187
|
property = 'transform';
|
|
177
|
-
value = `scale(${
|
|
188
|
+
value = `scale(${parseFloat(valKey) / 100})`;
|
|
178
189
|
} else if (prefix === 'transition') {
|
|
179
190
|
property = 'transition-property';
|
|
180
191
|
if (valKey === 'all') value = 'all';
|
|
@@ -193,8 +204,8 @@ function generateCSS(configPath) {
|
|
|
193
204
|
property = sideMap[prefix];
|
|
194
205
|
let v = valKey;
|
|
195
206
|
if (v.startsWith('[') && v.endsWith(']')) v = v.slice(1, -1);
|
|
196
|
-
else if (v.includes('/')) v = `${(
|
|
197
|
-
else v = theme.spacing[v] || v;
|
|
207
|
+
else if (v.includes('/')) v = `${(parseFloat(v.split('/')[0])/parseFloat(v.split('/')[1])*100).toFixed(2)}%`;
|
|
208
|
+
else v = theme.spacing[v] || (isNaN(parseFloat(v)) ? v : `${parseFloat(v) * 0.25}rem`);
|
|
198
209
|
value = isNeg ? (Array.isArray(v) ? v.map(x => `-${x}`) : `-${v}`) : v;
|
|
199
210
|
} else if (prefix === 'shadow') {
|
|
200
211
|
if (theme.shadows[valKey]) { property = 'box-shadow'; value = theme.shadows[valKey]; }
|
|
@@ -235,7 +246,7 @@ function generateCSS(configPath) {
|
|
|
235
246
|
|
|
236
247
|
merged.forEach(group => {
|
|
237
248
|
const { breakpoint, variant, customSelector, rules } = group;
|
|
238
|
-
const escapedFull = fullCls
|
|
249
|
+
const escapedFull = escapeSelector(fullCls);
|
|
239
250
|
let selector = customSelector || `.${escapedFull}`;
|
|
240
251
|
if (variant) { if (variant === 'group-hover') selector = `.group:hover ${selector}`; else selector += `:${variant}`}
|
|
241
252
|
|