juxscript 1.0.21 → 1.0.22
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/bin/cli.js +60 -57
- package/machinery/server.js +29 -5
- package/package.json +1 -1
- package/presets/hey.jux +46 -0
- package/presets/{base.css → styles/base.css} +437 -223
- /package/presets/{notion.css → styles/notion.css} +0 -0
package/bin/cli.js
CHANGED
|
@@ -49,6 +49,7 @@ console.log(` Output: ${PATHS.frontendDist}`);
|
|
|
49
49
|
console.log(` Lib: ${PATHS.juxLib}\n`);
|
|
50
50
|
|
|
51
51
|
const command = process.argv[2];
|
|
52
|
+
const subCommand = process.argv[3]; // For serve <pagename>
|
|
52
53
|
const watchMode = process.argv.includes('--watch');
|
|
53
54
|
const bundleMode = process.argv.includes('--bundle');
|
|
54
55
|
|
|
@@ -233,41 +234,34 @@ async function buildProject(isServe = false) {
|
|
|
233
234
|
// Create structure
|
|
234
235
|
fs.mkdirSync(juxDir, { recursive: true });
|
|
235
236
|
|
|
236
|
-
//
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
.gap(20)
|
|
247
|
-
.style('padding: 40px;')
|
|
248
|
-
.render('body');
|
|
249
|
-
|
|
250
|
-
jux.hero('welcome-hero', {
|
|
251
|
-
title: 'Welcome to JUX',
|
|
252
|
-
subtitle: 'A JavaScript UX authorship platform'
|
|
253
|
-
}).render('#app-container');
|
|
254
|
-
|
|
255
|
-
jux.divider({}).render('#app-container');
|
|
256
|
-
|
|
257
|
-
jux.write(\`
|
|
258
|
-
<h2>Getting Started</h2>
|
|
259
|
-
<p>Edit <code>jux/index.jux</code> to build your app.</p>
|
|
260
|
-
<ul>
|
|
261
|
-
<li>Run <code>npx jux build</code> to compile</li>
|
|
262
|
-
<li>Run <code>npx jux serve</code> for dev mode</li>
|
|
263
|
-
<li>Serve <code>jux-dist/</code> from your backend</li>
|
|
264
|
-
</ul>
|
|
265
|
-
\`).render('#app-container');
|
|
266
|
-
`;
|
|
237
|
+
// Copy hey.jux from presets as starter template
|
|
238
|
+
const heyTemplatePath = path.join(PATHS.packageRoot, 'presets', 'hey.jux');
|
|
239
|
+
const heyTargetPath = path.join(juxDir, 'hey.jux');
|
|
240
|
+
|
|
241
|
+
if (fs.existsSync(heyTemplatePath)) {
|
|
242
|
+
fs.copyFileSync(heyTemplatePath, heyTargetPath);
|
|
243
|
+
console.log('+ Created jux/hey.jux (starter template)');
|
|
244
|
+
} else {
|
|
245
|
+
console.warn('⚠️ hey.jux template not found in presets/');
|
|
246
|
+
}
|
|
267
247
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
248
|
+
// Copy over presets/*.css as styles/ to jux/
|
|
249
|
+
const presetsSrc = path.join(PATHS.packageRoot, 'presets');
|
|
250
|
+
const stylesDest = path.join(juxDir, 'styles');
|
|
251
|
+
|
|
252
|
+
if (fs.existsSync(presetsSrc)) {
|
|
253
|
+
fs.mkdirSync(stylesDest, { recursive: true });
|
|
254
|
+
|
|
255
|
+
const presetFiles = fs.readdirSync(presetsSrc);
|
|
256
|
+
presetFiles.forEach(file => {
|
|
257
|
+
if (file.endsWith('.css')) {
|
|
258
|
+
const srcFile = path.join(presetsSrc, file);
|
|
259
|
+
const destFile = path.join(stylesDest, file);
|
|
260
|
+
fs.copyFileSync(srcFile, destFile);
|
|
261
|
+
console.log(`+ Copied preset style: styles/${file}`);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
271
265
|
|
|
272
266
|
// Create package.json if it doesn't exist
|
|
273
267
|
const pkgPath = path.join(PATHS.projectRoot, 'package.json');
|
|
@@ -297,15 +291,13 @@ node_modules/
|
|
|
297
291
|
|
|
298
292
|
if (!fs.existsSync(gitignorePath)) {
|
|
299
293
|
fs.writeFileSync(gitignorePath, gitignoreContent);
|
|
300
|
-
console.log('
|
|
294
|
+
console.log('+ Created .gitignore');
|
|
301
295
|
}
|
|
302
296
|
|
|
303
|
-
console.log('
|
|
297
|
+
console.log('+ Created jux/ directory\n');
|
|
304
298
|
console.log('Next steps:');
|
|
305
|
-
console.log('
|
|
306
|
-
console.log('
|
|
307
|
-
console.log(' 3. npx jux build # Compile to jux-dist/');
|
|
308
|
-
console.log(' 4. Serve jux-dist/ from your backend\n');
|
|
299
|
+
console.log(' npx jux serve hey # Start dev server for hey.jux\n');
|
|
300
|
+
console.log('Check out the docs: https://juxscript.com/docs\n');
|
|
309
301
|
|
|
310
302
|
} else if (command === 'build') {
|
|
311
303
|
// ✅ Always builds router bundle
|
|
@@ -313,28 +305,37 @@ node_modules/
|
|
|
313
305
|
console.log(`✅ Build complete: ${PATHS.frontendDist}`);
|
|
314
306
|
|
|
315
307
|
} else if (command === 'serve') {
|
|
316
|
-
// ✅
|
|
308
|
+
// ✅ Serve with optional page parameter
|
|
309
|
+
const pageName = subCommand; // e.g., "hey" from "npx jux serve hey"
|
|
310
|
+
|
|
311
|
+
if (pageName) {
|
|
312
|
+
console.log(`🎯 Serving specific page: ${pageName}\n`);
|
|
313
|
+
}
|
|
314
|
+
|
|
317
315
|
await buildProject(true);
|
|
318
316
|
|
|
319
|
-
const port = parseInt(
|
|
320
|
-
|
|
317
|
+
const port = pageName ? 3000 : (parseInt(subCommand) || 3000);
|
|
318
|
+
|
|
319
|
+
// Start server
|
|
320
|
+
await start(port, pageName);
|
|
321
321
|
|
|
322
322
|
} else {
|
|
323
323
|
console.log(`
|
|
324
324
|
JUX CLI - A JavaScript UX authorship platform
|
|
325
325
|
|
|
326
326
|
Usage:
|
|
327
|
-
npx jux init
|
|
328
|
-
npx jux build
|
|
329
|
-
npx jux serve [
|
|
327
|
+
npx jux init Initialize a new JUX project
|
|
328
|
+
npx jux build Build router bundle to ./jux-dist/
|
|
329
|
+
npx jux serve [page] Start dev server (optionally for specific page)
|
|
330
|
+
npx jux serve [port] Start dev server on custom port
|
|
330
331
|
|
|
331
332
|
Project Structure:
|
|
332
333
|
my-project/
|
|
333
334
|
├── jux/ # Your .jux source files
|
|
334
|
-
│ ├──
|
|
335
|
-
│ └── pages/
|
|
336
|
-
├── jux-dist/
|
|
337
|
-
├── server/
|
|
335
|
+
│ ├── hey.jux # Starter page (created by init)
|
|
336
|
+
│ └── pages/ # Additional pages
|
|
337
|
+
├── jux-dist/ # Build output (git-ignore this)
|
|
338
|
+
├── server/ # Your backend
|
|
338
339
|
└── package.json
|
|
339
340
|
|
|
340
341
|
Import Style:
|
|
@@ -343,15 +344,17 @@ Import Style:
|
|
|
343
344
|
import 'juxscript/presets/notion.js';
|
|
344
345
|
|
|
345
346
|
Getting Started:
|
|
346
|
-
1. npx jux init
|
|
347
|
-
2. npm install
|
|
348
|
-
3. npx jux serve # Dev server
|
|
349
|
-
4.
|
|
347
|
+
1. npx jux init # Create project structure
|
|
348
|
+
2. npm install # Install dependencies
|
|
349
|
+
3. npx jux serve hey # Dev server for hey.jux at localhost:3000/hey
|
|
350
|
+
4. npx jux serve # Dev server for all pages
|
|
351
|
+
5. Serve jux-dist/ from your backend
|
|
350
352
|
|
|
351
353
|
Examples:
|
|
352
|
-
npx jux build
|
|
353
|
-
npx jux serve
|
|
354
|
-
npx jux serve
|
|
354
|
+
npx jux build Build production bundle
|
|
355
|
+
npx jux serve Start dev server on port 3000 (all pages)
|
|
356
|
+
npx jux serve hey Start dev server at localhost:3000/hey
|
|
357
|
+
npx jux serve 8080 Start dev server on port 8080
|
|
355
358
|
`);
|
|
356
359
|
}
|
|
357
360
|
})();
|
package/machinery/server.js
CHANGED
|
@@ -87,9 +87,12 @@ async function serve(port = 3000, distDir = './jux-dist') {
|
|
|
87
87
|
|
|
88
88
|
// Start HTTP server
|
|
89
89
|
server.listen(port, () => {
|
|
90
|
-
console.log(
|
|
91
|
-
console.log(`
|
|
92
|
-
|
|
90
|
+
console.log(`\n🚀 JUX dev server running`);
|
|
91
|
+
console.log(` Local: http://localhost:${port}${pageName ? '/' + pageName : ''}`);
|
|
92
|
+
if (pageName) {
|
|
93
|
+
console.log(` (Root redirects to /${pageName})`);
|
|
94
|
+
}
|
|
95
|
+
console.log('');
|
|
93
96
|
});
|
|
94
97
|
|
|
95
98
|
// Start file watcher
|
|
@@ -113,6 +116,27 @@ async function serve(port = 3000, distDir = './jux-dist') {
|
|
|
113
116
|
return { server };
|
|
114
117
|
}
|
|
115
118
|
|
|
116
|
-
export async function start(port = 3000) {
|
|
117
|
-
|
|
119
|
+
export async function start(port = 3000, pageName = null) {
|
|
120
|
+
const app = express();
|
|
121
|
+
|
|
122
|
+
// ...existing code for static files...
|
|
123
|
+
|
|
124
|
+
// If pageName specified, redirect root to that page
|
|
125
|
+
if (pageName) {
|
|
126
|
+
app.get('/', (req, res) => {
|
|
127
|
+
res.redirect(`/${pageName}`);
|
|
128
|
+
});
|
|
129
|
+
console.log(`🎯 Root (/) redirects to /${pageName}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ...existing code...
|
|
133
|
+
|
|
134
|
+
app.listen(port, () => {
|
|
135
|
+
console.log(`\n🚀 JUX dev server running`);
|
|
136
|
+
console.log(` Local: http://localhost:${port}${pageName ? '/' + pageName : ''}`);
|
|
137
|
+
if (pageName) {
|
|
138
|
+
console.log(` (Root redirects to /${pageName})`);
|
|
139
|
+
}
|
|
140
|
+
console.log('');
|
|
141
|
+
});
|
|
118
142
|
}
|
package/package.json
CHANGED
package/presets/hey.jux
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jux } from 'juxscript';
|
|
2
|
+
|
|
3
|
+
// Welcome page - edit this to build your app
|
|
4
|
+
jux.hero('welcome-hero', {
|
|
5
|
+
title: 'Welcome to JUX',
|
|
6
|
+
subtitle: 'A JavaScript UX authorship platform'
|
|
7
|
+
}).render('#app');
|
|
8
|
+
|
|
9
|
+
jux.divider().render('#app');
|
|
10
|
+
|
|
11
|
+
jux.container('getting-started')
|
|
12
|
+
.style('max-width: 800px; margin: 2rem auto; padding: 2rem;')
|
|
13
|
+
.render('#app');
|
|
14
|
+
|
|
15
|
+
jux.heading('gs-title')
|
|
16
|
+
.level(2)
|
|
17
|
+
.text('Getting Started')
|
|
18
|
+
.render('#getting-started');
|
|
19
|
+
|
|
20
|
+
jux.paragraph('gs-intro')
|
|
21
|
+
.text('Edit jux/hey.jux to start building your application.')
|
|
22
|
+
.style('margin: 1rem 0;')
|
|
23
|
+
.render('#getting-started');
|
|
24
|
+
|
|
25
|
+
jux.list('gs-steps', {
|
|
26
|
+
items: [
|
|
27
|
+
'Run npx jux build to compile',
|
|
28
|
+
'Run npx jux serve to dev with hot reload',
|
|
29
|
+
'Run npx jux serve hey to serve just this page',
|
|
30
|
+
'Serve jux-dist/ from your backend in production'
|
|
31
|
+
]
|
|
32
|
+
}).render('#getting-started');
|
|
33
|
+
|
|
34
|
+
jux.divider().render('#app');
|
|
35
|
+
|
|
36
|
+
jux.button('demo-button')
|
|
37
|
+
.label('Click Me!')
|
|
38
|
+
.variant('primary')
|
|
39
|
+
.bind('click', () => {
|
|
40
|
+
jux.alert('demo-alert')
|
|
41
|
+
.type('success')
|
|
42
|
+
.message('Button clicked! You are ready to build with JUX.')
|
|
43
|
+
.render('#app');
|
|
44
|
+
})
|
|
45
|
+
.style('margin: 2rem auto; display: block;')
|
|
46
|
+
.render('#app');
|
|
@@ -45,8 +45,6 @@ body {
|
|
|
45
45
|
align-items: center;
|
|
46
46
|
padding: 0 var(--space-lg);
|
|
47
47
|
height: 48px;
|
|
48
|
-
position: sticky;
|
|
49
|
-
top: 0;
|
|
50
48
|
z-index: 100;
|
|
51
49
|
transition: background-color var(--transition-base), border-color var(--transition-base);
|
|
52
50
|
}
|
|
@@ -92,7 +90,8 @@ body {
|
|
|
92
90
|
/* ============================================
|
|
93
91
|
SIDEBAR - Left Navigation
|
|
94
92
|
============================================ */
|
|
95
|
-
|
|
93
|
+
.jux-sidebar,
|
|
94
|
+
#appaside {
|
|
96
95
|
grid-area: sidebar;
|
|
97
96
|
width: 260px;
|
|
98
97
|
background: var(--color-surface-base);
|
|
@@ -100,47 +99,95 @@ body {
|
|
|
100
99
|
display: flex;
|
|
101
100
|
flex-direction: column;
|
|
102
101
|
overflow: hidden;
|
|
103
|
-
transition: width var(--transition-base)
|
|
102
|
+
transition: width var(--transition-base);
|
|
103
|
+
position: relative;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
.jux-sidebar-collapsed,
|
|
107
|
+
#appaside.jux-sidebar-collapsed {
|
|
108
|
+
width: 60px;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.jux-sidebar-expand-on-hover.jux-sidebar-collapsed.jux-sidebar-hover-expanded,
|
|
112
|
+
#appaside.jux-sidebar-expand-on-hover.jux-sidebar-collapsed.jux-sidebar-hover-expanded {
|
|
113
|
+
width: 260px;
|
|
114
|
+
z-index: 1000;
|
|
115
|
+
/* box-shadow: var(--shadow-lg); */
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.jux-sidebar-menu {
|
|
107
119
|
flex: 1;
|
|
108
120
|
overflow-y: auto;
|
|
109
121
|
overflow-x: hidden;
|
|
110
|
-
padding: var(--space-
|
|
122
|
+
padding: var(--space-sm);
|
|
111
123
|
}
|
|
112
124
|
|
|
113
|
-
|
|
114
|
-
#appsidebar-content::-webkit-scrollbar {
|
|
125
|
+
.jux-sidebar-menu::-webkit-scrollbar {
|
|
115
126
|
width: 6px;
|
|
116
127
|
}
|
|
117
128
|
|
|
118
|
-
|
|
119
|
-
background: transparent;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
#appsidebar-content::-webkit-scrollbar-thumb {
|
|
129
|
+
.jux-sidebar-menu::-webkit-scrollbar-thumb {
|
|
123
130
|
background: var(--color-border);
|
|
124
131
|
border-radius: var(--radius-full);
|
|
125
132
|
}
|
|
126
133
|
|
|
127
|
-
|
|
128
|
-
|
|
134
|
+
.jux-sidebar-toggle {
|
|
135
|
+
margin-top: auto;
|
|
136
|
+
order: 999;
|
|
137
|
+
width: 32px;
|
|
138
|
+
height: 32px;
|
|
139
|
+
margin-left: auto;
|
|
140
|
+
margin-right: var(--space-lg);
|
|
141
|
+
margin-bottom: var(--space-lg);
|
|
142
|
+
border: none;
|
|
143
|
+
background: var(--color-surface-elevated);
|
|
144
|
+
color: var(--color-text-secondary);
|
|
145
|
+
border-radius: var(--radius-md);
|
|
146
|
+
cursor: pointer;
|
|
147
|
+
display: flex;
|
|
148
|
+
align-items: center;
|
|
149
|
+
justify-content: center;
|
|
150
|
+
transition: all var(--transition-base);
|
|
151
|
+
border: var(--border-width) solid var(--color-border);
|
|
129
152
|
}
|
|
130
153
|
|
|
131
|
-
|
|
154
|
+
.jux-sidebar-toggle:hover {
|
|
155
|
+
background: var(--color-surface-hover);
|
|
156
|
+
color: var(--color-text-primary);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.jux-sidebar-collapsed .jux-sidebar-toggle,
|
|
160
|
+
#appaside.jux-sidebar-collapsed .jux-sidebar-toggle {
|
|
161
|
+
margin-left: 14px;
|
|
162
|
+
margin-right: 14px;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.jux-sidebar-hover-expanded .jux-sidebar-toggle,
|
|
166
|
+
#appaside.jux-sidebar-hover-expanded .jux-sidebar-toggle {
|
|
167
|
+
margin-left: auto;
|
|
168
|
+
margin-right: var(--space-lg);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.jux-sidebar-toggle-icon {
|
|
172
|
+
display: flex;
|
|
173
|
+
align-items: center;
|
|
174
|
+
justify-content: center;
|
|
175
|
+
font-size: var(--font-size-lg);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* Menu inside sidebar */
|
|
179
|
+
.jux-sidebar .jux-menu {
|
|
132
180
|
display: flex;
|
|
133
181
|
flex-direction: column;
|
|
134
182
|
gap: var(--space-xs);
|
|
135
183
|
}
|
|
136
184
|
|
|
137
|
-
|
|
138
|
-
#appsidebar-menu .jux-menu-item {
|
|
185
|
+
.jux-sidebar .jux-menu-item {
|
|
139
186
|
list-style: none;
|
|
140
187
|
}
|
|
141
188
|
|
|
142
|
-
|
|
143
|
-
|
|
189
|
+
.jux-sidebar .jux-menu-link,
|
|
190
|
+
.jux-sidebar .jux-menu-button {
|
|
144
191
|
display: flex;
|
|
145
192
|
align-items: center;
|
|
146
193
|
gap: var(--space-md);
|
|
@@ -156,29 +203,83 @@ body {
|
|
|
156
203
|
background: transparent;
|
|
157
204
|
width: 100%;
|
|
158
205
|
text-align: left;
|
|
206
|
+
white-space: nowrap;
|
|
207
|
+
position: relative;
|
|
159
208
|
}
|
|
160
209
|
|
|
161
|
-
|
|
162
|
-
|
|
210
|
+
.jux-sidebar .jux-menu-link:hover,
|
|
211
|
+
.jux-sidebar .jux-menu-button:hover {
|
|
163
212
|
background: var(--color-surface-hover);
|
|
164
213
|
color: var(--color-text-primary);
|
|
165
214
|
}
|
|
166
215
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/* Active menu item */
|
|
173
|
-
#appsidebar-menu .jux-menu-item.active .jux-menu-button,
|
|
174
|
-
#appsidebar-menu .jux-menu-item.active a {
|
|
216
|
+
.jux-sidebar .jux-menu-item-active > .jux-menu-link,
|
|
217
|
+
.jux-sidebar .jux-menu-item-active > .jux-menu-button,
|
|
218
|
+
.jux-sidebar .jux-menu-link-active {
|
|
175
219
|
background: var(--color-brand-subtle);
|
|
176
220
|
color: var(--color-brand);
|
|
177
221
|
font-weight: var(--font-weight-semibold);
|
|
178
222
|
}
|
|
179
223
|
|
|
180
|
-
|
|
181
|
-
|
|
224
|
+
.jux-sidebar .jux-menu-icon {
|
|
225
|
+
flex-shrink: 0;
|
|
226
|
+
width: 20px;
|
|
227
|
+
display: flex;
|
|
228
|
+
align-items: center;
|
|
229
|
+
justify-content: center;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.jux-sidebar .jux-menu-label {
|
|
233
|
+
flex: 1;
|
|
234
|
+
overflow: hidden;
|
|
235
|
+
text-overflow: ellipsis;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.jux-sidebar .jux-menu-chevron {
|
|
239
|
+
flex-shrink: 0;
|
|
240
|
+
transition: transform var(--transition-fast);
|
|
241
|
+
font-size: var(--font-size-sm);
|
|
242
|
+
color: var(--color-text-tertiary);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.jux-sidebar .jux-menu-item-open > .jux-menu-button .jux-menu-chevron {
|
|
246
|
+
transform: rotate(90deg);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* Collapsed state - hide labels and chevrons */
|
|
250
|
+
.jux-sidebar-collapsed .jux-menu-label,
|
|
251
|
+
.jux-sidebar-collapsed .jux-menu-chevron,
|
|
252
|
+
#appaside.jux-sidebar-collapsed .jux-menu-label,
|
|
253
|
+
#appaside.jux-sidebar-collapsed .jux-menu-chevron {
|
|
254
|
+
display: none;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.jux-sidebar-collapsed .jux-menu-link,
|
|
258
|
+
.jux-sidebar-collapsed .jux-menu-button,
|
|
259
|
+
#appaside.jux-sidebar-collapsed .jux-menu-link,
|
|
260
|
+
#appaside.jux-sidebar-collapsed .jux-menu-button {
|
|
261
|
+
justify-content: center;
|
|
262
|
+
padding: var(--space-sm);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/* Hover-expanded state - show labels */
|
|
266
|
+
.jux-sidebar-hover-expanded .jux-menu-label,
|
|
267
|
+
.jux-sidebar-hover-expanded .jux-menu-chevron,
|
|
268
|
+
#appaside.jux-sidebar-hover-expanded .jux-menu-label,
|
|
269
|
+
#appaside.jux-sidebar-hover-expanded .jux-menu-chevron {
|
|
270
|
+
display: inline;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.jux-sidebar-hover-expanded .jux-menu-link,
|
|
274
|
+
.jux-sidebar-hover-expanded .jux-menu-button,
|
|
275
|
+
#appaside.jux-sidebar-hover-expanded .jux-menu-link,
|
|
276
|
+
#appaside.jux-sidebar-hover-expanded .jux-menu-button {
|
|
277
|
+
justify-content: flex-start;
|
|
278
|
+
padding: var(--space-sm) var(--space-md);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/* Submenus */
|
|
282
|
+
.jux-sidebar .jux-menu-submenu {
|
|
182
283
|
display: none;
|
|
183
284
|
flex-direction: column;
|
|
184
285
|
gap: var(--space-xs);
|
|
@@ -188,21 +289,26 @@ body {
|
|
|
188
289
|
margin-left: var(--space-lg);
|
|
189
290
|
}
|
|
190
291
|
|
|
191
|
-
|
|
292
|
+
.jux-sidebar .jux-menu-item-open > .jux-menu-submenu {
|
|
192
293
|
display: flex;
|
|
193
294
|
}
|
|
194
295
|
|
|
195
|
-
|
|
196
|
-
|
|
296
|
+
.jux-sidebar .jux-menu-submenu .jux-menu-link,
|
|
297
|
+
.jux-sidebar .jux-menu-submenu .jux-menu-button {
|
|
197
298
|
font-size: var(--font-size-xs);
|
|
198
299
|
padding: var(--space-xs) var(--space-md);
|
|
199
300
|
}
|
|
200
301
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
302
|
+
/* Hide submenus when collapsed */
|
|
303
|
+
.jux-sidebar-collapsed .jux-menu-submenu,
|
|
304
|
+
#appaside.jux-sidebar-collapsed .jux-menu-submenu {
|
|
305
|
+
display: none !important;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/* Show submenus when hover-expanded and open */
|
|
309
|
+
.jux-sidebar-hover-expanded .jux-menu-item-open > .jux-menu-submenu,
|
|
310
|
+
#appaside.jux-sidebar-hover-expanded .jux-menu-item-open > .jux-menu-submenu {
|
|
311
|
+
display: flex !important;
|
|
206
312
|
}
|
|
207
313
|
|
|
208
314
|
/* ============================================
|
|
@@ -245,29 +351,29 @@ body {
|
|
|
245
351
|
}
|
|
246
352
|
|
|
247
353
|
/* ============================================
|
|
248
|
-
RIGHT SIDEBAR
|
|
354
|
+
RIGHT SIDEBAR - Optional Panel
|
|
249
355
|
============================================ */
|
|
250
|
-
#
|
|
356
|
+
#appsidebar {
|
|
251
357
|
grid-area: aside;
|
|
252
358
|
width: 280px;
|
|
253
359
|
background: var(--color-surface-base);
|
|
254
360
|
border-left: var(--border-width) solid var(--color-border);
|
|
255
|
-
display: none;
|
|
361
|
+
display: none;
|
|
256
362
|
flex-direction: column;
|
|
257
363
|
overflow: hidden;
|
|
258
364
|
transition: width var(--transition-base), background-color var(--transition-base);
|
|
259
365
|
}
|
|
260
366
|
|
|
261
|
-
#
|
|
367
|
+
#appsidebar.show {
|
|
262
368
|
display: flex;
|
|
263
369
|
}
|
|
264
370
|
|
|
265
|
-
#
|
|
371
|
+
#appsidebar.collapsed {
|
|
266
372
|
width: 0;
|
|
267
373
|
border: none;
|
|
268
374
|
}
|
|
269
375
|
|
|
270
|
-
#
|
|
376
|
+
#appsidebar-header {
|
|
271
377
|
padding: var(--space-lg);
|
|
272
378
|
border-bottom: var(--border-width) solid var(--color-border);
|
|
273
379
|
font-weight: var(--font-weight-semibold);
|
|
@@ -277,31 +383,31 @@ body {
|
|
|
277
383
|
letter-spacing: 0.05em;
|
|
278
384
|
}
|
|
279
385
|
|
|
280
|
-
#
|
|
386
|
+
#appsidebar-content {
|
|
281
387
|
flex: 1;
|
|
282
388
|
overflow-y: auto;
|
|
283
389
|
overflow-x: hidden;
|
|
284
390
|
padding: var(--space-lg);
|
|
285
391
|
}
|
|
286
392
|
|
|
287
|
-
#
|
|
393
|
+
#appsidebar-content::-webkit-scrollbar {
|
|
288
394
|
width: 6px;
|
|
289
395
|
}
|
|
290
396
|
|
|
291
|
-
#
|
|
397
|
+
#appsidebar-content::-webkit-scrollbar-track {
|
|
292
398
|
background: transparent;
|
|
293
399
|
}
|
|
294
400
|
|
|
295
|
-
#
|
|
401
|
+
#appsidebar-content::-webkit-scrollbar-thumb {
|
|
296
402
|
background: var(--color-border);
|
|
297
403
|
border-radius: var(--radius-full);
|
|
298
404
|
}
|
|
299
405
|
|
|
300
|
-
#
|
|
406
|
+
#appsidebar-content::-webkit-scrollbar-thumb:hover {
|
|
301
407
|
background: var(--color-border-hover);
|
|
302
408
|
}
|
|
303
409
|
|
|
304
|
-
#
|
|
410
|
+
#appsidebar-footer {
|
|
305
411
|
padding: var(--space-lg);
|
|
306
412
|
border-top: var(--border-width) solid var(--color-border);
|
|
307
413
|
font-size: var(--font-size-xs);
|
|
@@ -380,6 +486,24 @@ body {
|
|
|
380
486
|
transform: scale(0.95);
|
|
381
487
|
}
|
|
382
488
|
|
|
489
|
+
/* Mobile Sidebar Backdrop */
|
|
490
|
+
.jux-sidebar-backdrop {
|
|
491
|
+
display: none;
|
|
492
|
+
position: fixed;
|
|
493
|
+
top: 0;
|
|
494
|
+
left: 0;
|
|
495
|
+
right: 0;
|
|
496
|
+
bottom: 0;
|
|
497
|
+
background: rgba(0, 0, 0, 0.5);
|
|
498
|
+
z-index: 999;
|
|
499
|
+
backdrop-filter: blur(4px);
|
|
500
|
+
animation: fadeIn 0.2s ease-out;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
.jux-sidebar-backdrop.show {
|
|
504
|
+
display: block;
|
|
505
|
+
}
|
|
506
|
+
|
|
383
507
|
/* ============================================
|
|
384
508
|
RESPONSIVE DESIGN
|
|
385
509
|
============================================ */
|
|
@@ -391,24 +515,40 @@ body {
|
|
|
391
515
|
#app {
|
|
392
516
|
grid-template-columns: auto 1fr;
|
|
393
517
|
grid-template-areas:
|
|
394
|
-
"
|
|
518
|
+
"sidebar header"
|
|
395
519
|
"sidebar main"
|
|
396
|
-
"
|
|
520
|
+
"sidebar footer";
|
|
397
521
|
}
|
|
398
522
|
}
|
|
399
523
|
|
|
400
524
|
@media (max-width: 768px) {
|
|
401
|
-
|
|
525
|
+
/* Move sidebar toggle to header on mobile */
|
|
526
|
+
.jux-sidebar-toggle,
|
|
527
|
+
#appaside .jux-sidebar-toggle {
|
|
528
|
+
position: fixed;
|
|
529
|
+
top: 8px;
|
|
530
|
+
left: var(--space-md);
|
|
531
|
+
z-index: 1001;
|
|
532
|
+
margin: 0;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
.jux-sidebar,
|
|
536
|
+
#appaside {
|
|
537
|
+
display: none;
|
|
402
538
|
position: fixed;
|
|
403
539
|
left: 0;
|
|
404
|
-
top:
|
|
540
|
+
top: 0;
|
|
405
541
|
bottom: 0;
|
|
406
|
-
z-index:
|
|
542
|
+
z-index: 1000;
|
|
543
|
+
width: 260px;
|
|
544
|
+
box-shadow: var(--shadow-xl);
|
|
407
545
|
transform: translateX(-100%);
|
|
408
546
|
transition: transform var(--transition-base);
|
|
409
547
|
}
|
|
410
548
|
|
|
411
|
-
|
|
549
|
+
.jux-sidebar.open,
|
|
550
|
+
#appaside.open {
|
|
551
|
+
display: flex;
|
|
412
552
|
transform: translateX(0);
|
|
413
553
|
}
|
|
414
554
|
|
|
@@ -425,7 +565,7 @@ body {
|
|
|
425
565
|
}
|
|
426
566
|
|
|
427
567
|
#appheader {
|
|
428
|
-
padding: 0 var(--space-md);
|
|
568
|
+
padding: 0 var(--space-md) 0 calc(var(--space-md) + 48px);
|
|
429
569
|
}
|
|
430
570
|
}
|
|
431
571
|
|
|
@@ -466,6 +606,23 @@ body {
|
|
|
466
606
|
JUX COMPONENT STYLES
|
|
467
607
|
============================================ */
|
|
468
608
|
|
|
609
|
+
/* Icon Component */
|
|
610
|
+
.jux-icon {
|
|
611
|
+
display: inline-flex;
|
|
612
|
+
align-items: center;
|
|
613
|
+
justify-content: center;
|
|
614
|
+
vertical-align: middle;
|
|
615
|
+
line-height: 1;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
.jux-icon img,
|
|
619
|
+
.jux-icon svg {
|
|
620
|
+
display: block;
|
|
621
|
+
width: 100%;
|
|
622
|
+
height: 100%;
|
|
623
|
+
object-fit: contain;
|
|
624
|
+
}
|
|
625
|
+
|
|
469
626
|
/* Hero Component */
|
|
470
627
|
.jux-hero {
|
|
471
628
|
padding: var(--space-3xl) 0;
|
|
@@ -519,6 +676,7 @@ body {
|
|
|
519
676
|
background: linear-gradient(90deg, var(--color-brand), var(--color-info));
|
|
520
677
|
transform: translateY(-100%);
|
|
521
678
|
transition: transform var(--transition-base);
|
|
679
|
+
z-index: 1;
|
|
522
680
|
}
|
|
523
681
|
|
|
524
682
|
.jux-card:hover {
|
|
@@ -537,6 +695,9 @@ body {
|
|
|
537
695
|
color: var(--color-text-primary);
|
|
538
696
|
margin-bottom: var(--space-lg);
|
|
539
697
|
letter-spacing: -0.01em;
|
|
698
|
+
position: relative;
|
|
699
|
+
z-index: 2;
|
|
700
|
+
padding-right: calc(var(--font-size-2xl) + var(--space-lg));
|
|
540
701
|
}
|
|
541
702
|
|
|
542
703
|
.jux-card-icon {
|
|
@@ -547,6 +708,7 @@ body {
|
|
|
547
708
|
line-height: 1;
|
|
548
709
|
opacity: 0.8;
|
|
549
710
|
transition: opacity var(--transition-fast);
|
|
711
|
+
z-index: 2;
|
|
550
712
|
}
|
|
551
713
|
|
|
552
714
|
.jux-card:hover .jux-card-icon {
|
|
@@ -557,6 +719,8 @@ body {
|
|
|
557
719
|
font-size: var(--font-size-sm);
|
|
558
720
|
color: var(--color-text-secondary);
|
|
559
721
|
line-height: var(--line-height-relaxed);
|
|
722
|
+
position: relative;
|
|
723
|
+
z-index: 2;
|
|
560
724
|
}
|
|
561
725
|
|
|
562
726
|
.jux-card-body .jux-card-title {
|
|
@@ -579,51 +743,119 @@ body {
|
|
|
579
743
|
font-weight: var(--font-weight-normal);
|
|
580
744
|
}
|
|
581
745
|
|
|
746
|
+
.jux-card-footer {
|
|
747
|
+
margin-top: var(--space-xl);
|
|
748
|
+
padding-top: var(--space-lg);
|
|
749
|
+
border-top: var(--border-width) solid var(--color-border);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
.jux-card-actions {
|
|
753
|
+
display: flex;
|
|
754
|
+
gap: var(--space-md);
|
|
755
|
+
justify-content: flex-start;
|
|
756
|
+
}
|
|
757
|
+
|
|
582
758
|
/* List Component */
|
|
583
759
|
.jux-list {
|
|
584
760
|
display: flex;
|
|
585
761
|
flex-direction: column;
|
|
586
|
-
gap: var(--space-
|
|
762
|
+
gap: var(--space-md);
|
|
587
763
|
list-style: none;
|
|
588
764
|
padding: 0;
|
|
589
|
-
margin:
|
|
765
|
+
margin: var(--space-lg);
|
|
590
766
|
}
|
|
591
767
|
|
|
592
768
|
.jux-list-wrapper {
|
|
593
|
-
|
|
769
|
+
display: flex;
|
|
770
|
+
flex-direction: column;
|
|
771
|
+
gap: var(--space-md);
|
|
594
772
|
}
|
|
595
773
|
|
|
596
774
|
.jux-list-header {
|
|
597
|
-
font-size: var(--font-size-
|
|
775
|
+
font-size: var(--font-size-sm);
|
|
598
776
|
font-weight: var(--font-weight-semibold);
|
|
599
|
-
color: var(--color-text-
|
|
777
|
+
color: var(--color-text-secondary);
|
|
600
778
|
margin-bottom: var(--space-lg);
|
|
601
|
-
|
|
779
|
+
padding: 0 var(--space-lg);
|
|
780
|
+
text-transform: uppercase;
|
|
781
|
+
letter-spacing: 0.05em;
|
|
602
782
|
}
|
|
603
783
|
|
|
604
784
|
.jux-list-item {
|
|
605
785
|
display: flex;
|
|
606
786
|
align-items: center;
|
|
607
|
-
gap: var(--space-
|
|
787
|
+
gap: var(--space-lg);
|
|
608
788
|
padding: var(--space-lg);
|
|
609
|
-
background: var(--color-surface-
|
|
789
|
+
background: var(--color-surface-elevated);
|
|
610
790
|
border: var(--border-width) solid var(--color-border);
|
|
611
|
-
border-radius: var(--radius-
|
|
612
|
-
transition: all var(--transition-
|
|
791
|
+
border-radius: var(--radius-lg);
|
|
792
|
+
transition: all var(--transition-base);
|
|
613
793
|
cursor: pointer;
|
|
614
794
|
}
|
|
615
795
|
|
|
616
796
|
.jux-list-item:hover {
|
|
617
797
|
background: var(--color-surface-hover);
|
|
618
798
|
border-color: var(--color-border-hover);
|
|
619
|
-
transform: translateX(4px);
|
|
620
799
|
box-shadow: var(--shadow-sm);
|
|
621
800
|
}
|
|
622
801
|
|
|
623
|
-
.jux-list-item
|
|
624
|
-
|
|
625
|
-
|
|
802
|
+
.jux-list-item.jux-list-item-selected {
|
|
803
|
+
border-color: var(--color-brand);
|
|
804
|
+
box-shadow: 0 0 0 3px var(--color-brand-subtle);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
.jux-list-item-icon {
|
|
808
|
+
display: flex;
|
|
809
|
+
align-items: center;
|
|
810
|
+
justify-content: center;
|
|
626
811
|
flex-shrink: 0;
|
|
812
|
+
width: 24px;
|
|
813
|
+
height: 24px;
|
|
814
|
+
color: var(--color-text-primary);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
.jux-list-item-content {
|
|
818
|
+
flex: 1;
|
|
819
|
+
display: flex;
|
|
820
|
+
flex-direction: column;
|
|
821
|
+
gap: var(--space-xs);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
.jux-list-item-title {
|
|
825
|
+
font-size: var(--font-size-base);
|
|
826
|
+
font-weight: var(--font-weight-semibold);
|
|
827
|
+
color: var(--color-text-primary);
|
|
828
|
+
line-height: var(--line-height-tight);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
.jux-list-item-body {
|
|
832
|
+
font-size: var(--font-size-sm);
|
|
833
|
+
color: var(--color-text-secondary);
|
|
834
|
+
line-height: var(--line-height-normal);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
.jux-list-item-metadata {
|
|
838
|
+
font-size: var(--font-size-xs);
|
|
839
|
+
color: var(--color-text-tertiary);
|
|
840
|
+
margin-left: auto;
|
|
841
|
+
padding-left: var(--space-lg);
|
|
842
|
+
white-space: nowrap;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
.jux-list-item-success {
|
|
846
|
+
border-left: 3px solid var(--color-success);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
.jux-list-item-warning {
|
|
850
|
+
border-left: 3px solid var(--color-warning);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
.jux-list-item-error {
|
|
854
|
+
border-left: 3px solid var(--color-danger);
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
.jux-list-item-info {
|
|
858
|
+
border-left: 3px solid var(--color-info);
|
|
627
859
|
}
|
|
628
860
|
|
|
629
861
|
/* Container Component */
|
|
@@ -841,103 +1073,122 @@ body {
|
|
|
841
1073
|
|
|
842
1074
|
/* File Upload Component */
|
|
843
1075
|
.jux-fileupload {
|
|
844
|
-
margin
|
|
845
|
-
|
|
1076
|
+
margin: var(--space-xl);
|
|
1077
|
+
display: flex;
|
|
1078
|
+
flex-direction: column;
|
|
1079
|
+
gap: var(--space-sm);
|
|
1080
|
+
min-width: 200px;
|
|
1081
|
+
flex: 1;
|
|
1082
|
+
align-items: center;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
.jux-fileupload-label {
|
|
1086
|
+
display: block;
|
|
1087
|
+
font-size: var(--font-size-xs);
|
|
1088
|
+
font-weight: var(--font-weight-semibold);
|
|
1089
|
+
color: var(--color-text-tertiary);
|
|
1090
|
+
text-transform: uppercase;
|
|
1091
|
+
letter-spacing: 0.05em;
|
|
1092
|
+
margin-bottom: 2px;
|
|
1093
|
+
width: fit-content;
|
|
1094
|
+
text-align: center;
|
|
1095
|
+
white-space: nowrap;
|
|
846
1096
|
}
|
|
847
1097
|
|
|
848
1098
|
.jux-fileupload-input {
|
|
849
1099
|
display: none;
|
|
850
1100
|
}
|
|
851
1101
|
|
|
852
|
-
.jux-fileupload-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
1102
|
+
.jux-fileupload-button {
|
|
1103
|
+
display: flex;
|
|
1104
|
+
flex-direction: column;
|
|
1105
|
+
align-items: center;
|
|
1106
|
+
justify-content: center;
|
|
1107
|
+
gap: var(--space-lg);
|
|
1108
|
+
padding: var(--space-2xl) var(--space-lg);
|
|
857
1109
|
background: var(--color-surface-elevated);
|
|
858
|
-
|
|
1110
|
+
border: 2px dashed var(--color-border);
|
|
1111
|
+
border-radius: var(--radius-xl);
|
|
1112
|
+
color: var(--color-text-secondary);
|
|
1113
|
+
font-family: inherit;
|
|
1114
|
+
font-size: var(--font-size-sm);
|
|
859
1115
|
cursor: pointer;
|
|
1116
|
+
transition: all var(--transition-base);
|
|
860
1117
|
position: relative;
|
|
1118
|
+
overflow: wrap;
|
|
1119
|
+
width: 100%;
|
|
861
1120
|
}
|
|
862
1121
|
|
|
863
|
-
.jux-fileupload-
|
|
864
|
-
|
|
865
|
-
|
|
1122
|
+
.jux-fileupload-icon {
|
|
1123
|
+
font-size: 2rem;
|
|
1124
|
+
line-height: 1;
|
|
1125
|
+
opacity: 0.6;
|
|
1126
|
+
transition: opacity var(--transition-fast), transform var(--transition-bounce);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
.jux-fileupload-button:hover .jux-fileupload-icon {
|
|
1130
|
+
opacity: 1;
|
|
1131
|
+
transform: translateY(-4px);
|
|
866
1132
|
}
|
|
867
1133
|
|
|
868
|
-
.jux-fileupload-
|
|
1134
|
+
.jux-fileupload-text {
|
|
1135
|
+
font-weight: var(--font-weight-medium);
|
|
1136
|
+
margin-top: var(--space-xs);
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
.jux-fileupload-button:hover:not(:disabled) {
|
|
1140
|
+
background: var(--color-surface-hover);
|
|
869
1141
|
border-color: var(--color-brand);
|
|
870
|
-
|
|
871
|
-
|
|
1142
|
+
color: var(--color-brand);
|
|
1143
|
+
box-shadow: var(--shadow-md);
|
|
872
1144
|
}
|
|
873
1145
|
|
|
874
|
-
.jux-fileupload-
|
|
875
|
-
|
|
876
|
-
margin-bottom: var(--space-md);
|
|
877
|
-
opacity: 0.5;
|
|
1146
|
+
.jux-fileupload-button:active:not(:disabled) {
|
|
1147
|
+
transform: scale(0.98);
|
|
878
1148
|
}
|
|
879
1149
|
|
|
880
|
-
.jux-fileupload-
|
|
881
|
-
|
|
882
|
-
|
|
1150
|
+
.jux-fileupload-button:disabled {
|
|
1151
|
+
opacity: 0.5;
|
|
1152
|
+
cursor: not-allowed;
|
|
1153
|
+
background: var(--color-surface-base);
|
|
883
1154
|
}
|
|
884
1155
|
|
|
885
1156
|
.jux-fileupload-list {
|
|
886
|
-
margin-top: var(--space-lg);
|
|
887
1157
|
display: flex;
|
|
888
1158
|
flex-direction: column;
|
|
889
|
-
gap: var(--space-
|
|
1159
|
+
gap: var(--space-xs);
|
|
1160
|
+
margin-top: var(--space-xs);
|
|
1161
|
+
color: var(--color-text-tertiary);
|
|
1162
|
+
font-style: italic;
|
|
1163
|
+
font-size: var(--font-size-xs);
|
|
890
1164
|
}
|
|
891
1165
|
|
|
892
|
-
.jux-fileupload-
|
|
1166
|
+
.jux-fileupload-item {
|
|
893
1167
|
display: flex;
|
|
894
1168
|
align-items: center;
|
|
895
1169
|
gap: var(--space-md);
|
|
896
|
-
padding: var(--space-
|
|
897
|
-
background: var(--color-surface-
|
|
1170
|
+
padding: var(--space-sm) var(--space-md);
|
|
1171
|
+
background: var(--color-surface-base);
|
|
898
1172
|
border: var(--border-width) solid var(--color-border);
|
|
899
1173
|
border-radius: var(--radius-md);
|
|
1174
|
+
color: var(--color-text-primary);
|
|
1175
|
+
font-size: var(--font-size-sm);
|
|
1176
|
+
font-style: normal;
|
|
1177
|
+
animation: slideIn var(--transition-base) ease-out;
|
|
900
1178
|
transition: all var(--transition-fast);
|
|
901
1179
|
}
|
|
902
1180
|
|
|
903
|
-
.jux-fileupload-
|
|
1181
|
+
.jux-fileupload-item:hover {
|
|
904
1182
|
background: var(--color-surface-hover);
|
|
905
1183
|
border-color: var(--color-border-hover);
|
|
1184
|
+
transform: translateX(2px);
|
|
1185
|
+
box-shadow: var(--shadow-xs);
|
|
906
1186
|
}
|
|
907
1187
|
|
|
908
|
-
.jux-fileupload-
|
|
909
|
-
|
|
910
|
-
font-size:
|
|
911
|
-
|
|
912
|
-
color: var(--color-text-primary);
|
|
913
|
-
white-space: nowrap;
|
|
914
|
-
overflow: hidden;
|
|
915
|
-
text-overflow: ellipsis;
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
.jux-fileupload-file-size {
|
|
919
|
-
font-size: var(--font-size-xs);
|
|
920
|
-
color: var(--color-text-tertiary);
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
.jux-fileupload-file-remove {
|
|
924
|
-
padding: var(--space-xs) var(--space-sm);
|
|
925
|
-
border: none;
|
|
926
|
-
background: transparent;
|
|
927
|
-
color: var(--color-text-tertiary);
|
|
928
|
-
cursor: pointer;
|
|
929
|
-
border-radius: var(--radius-sm);
|
|
930
|
-
transition: all var(--transition-fast);
|
|
931
|
-
font-size: var(--font-size-xl);
|
|
932
|
-
line-height: 1;
|
|
933
|
-
display: flex;
|
|
934
|
-
align-items: center;
|
|
935
|
-
justify-content: center;
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
.jux-fileupload-file-remove:hover {
|
|
939
|
-
background: var(--color-surface-active);
|
|
940
|
-
color: var(--color-danger);
|
|
1188
|
+
.jux-fileupload-item::before {
|
|
1189
|
+
content: '📄';
|
|
1190
|
+
font-size: 1.1rem;
|
|
1191
|
+
filter: saturate(0.5);
|
|
941
1192
|
}
|
|
942
1193
|
|
|
943
1194
|
/* Progress Component */
|
|
@@ -1031,30 +1282,56 @@ body {
|
|
|
1031
1282
|
align-items: flex-start;
|
|
1032
1283
|
gap: var(--space-md);
|
|
1033
1284
|
padding: var(--space-lg);
|
|
1034
|
-
border-radius: var(--radius-
|
|
1285
|
+
border-radius: var(--radius-lg);
|
|
1035
1286
|
border: var(--border-width) solid;
|
|
1036
|
-
margin-bottom: var(--space-lg);
|
|
1037
1287
|
font-size: var(--font-size-sm);
|
|
1038
1288
|
line-height: var(--line-height-normal);
|
|
1039
|
-
|
|
1040
|
-
animation: slideIn var(--transition-base) ease-out;
|
|
1289
|
+
animation: alertSlideIn var(--transition-base) ease-out;
|
|
1041
1290
|
transition: all var(--transition-fast);
|
|
1042
|
-
box-shadow: var(--shadow-
|
|
1291
|
+
box-shadow: var(--shadow-lg);
|
|
1292
|
+
width: 100%;
|
|
1293
|
+
position: relative;
|
|
1294
|
+
z-index: 1000;
|
|
1295
|
+
transform-origin: top center;
|
|
1296
|
+
margin-bottom: 0;
|
|
1043
1297
|
}
|
|
1044
1298
|
|
|
1045
|
-
.jux-alert-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1299
|
+
/* Alert Stack Effect (Scoped to .jux-alert-stack container) */
|
|
1300
|
+
.jux-alert-stack {
|
|
1301
|
+
position: relative;
|
|
1302
|
+
min-height: 80px;
|
|
1049
1303
|
display: flex;
|
|
1050
|
-
|
|
1051
|
-
justify-content: center;
|
|
1304
|
+
flex-direction: column-reverse; /* Keep newest at bottom of DOM but appearing correctly */
|
|
1052
1305
|
}
|
|
1053
1306
|
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1307
|
+
/* Base stack state: Hidden for all */
|
|
1308
|
+
.jux-alert-stack .jux-alert {
|
|
1309
|
+
display: none !important;
|
|
1310
|
+
transition: all var(--transition-bounce), opacity var(--transition-base);
|
|
1311
|
+
margin-bottom: 0;
|
|
1312
|
+
transform-origin: top center;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
/* Top Visible Alert: The one with no UN-HIDDEN siblings after it in the DOM */
|
|
1316
|
+
.jux-alert-stack .jux-alert:not([style*="display: none"]):not(:has(~ .jux-alert:not([style*="display: none"]))) {
|
|
1317
|
+
display: flex !important;
|
|
1318
|
+
position: relative;
|
|
1319
|
+
z-index: 20;
|
|
1320
|
+
opacity: 1;
|
|
1321
|
+
transform: translateY(0) scale(1);
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
/* Second Visible Alert: The one with exactly one UN-HIDDEN sibling after it */
|
|
1325
|
+
.jux-alert-stack .jux-alert:not([style*="display: none"]):has(~ .jux-alert:not([style*="display: none"])):not(:has(~ .jux-alert:not([style*="display: none"]) ~ .jux-alert:not([style*="display: none"]))) {
|
|
1326
|
+
display: flex !important;
|
|
1327
|
+
position: absolute;
|
|
1328
|
+
top: 0;
|
|
1329
|
+
left: 0;
|
|
1330
|
+
right: 0;
|
|
1331
|
+
z-index: 10;
|
|
1332
|
+
opacity: 0.5;
|
|
1333
|
+
transform: translateY(var(--space-sm)) scale(0.98);
|
|
1334
|
+
pointer-events: none;
|
|
1058
1335
|
}
|
|
1059
1336
|
|
|
1060
1337
|
.jux-alert-close {
|
|
@@ -1076,91 +1353,28 @@ body {
|
|
|
1076
1353
|
opacity: 0.6;
|
|
1077
1354
|
}
|
|
1078
1355
|
|
|
1079
|
-
.jux-alert-close:hover {
|
|
1080
|
-
opacity: 1;
|
|
1081
|
-
background: rgba(0, 0, 0, 0.1);
|
|
1082
|
-
transform: scale(1.1);
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
.jux-alert-close:active {
|
|
1086
|
-
transform: scale(0.95);
|
|
1087
|
-
}
|
|
1088
1356
|
|
|
1089
1357
|
/* Alert Type Variants */
|
|
1090
1358
|
.jux-alert-info {
|
|
1091
|
-
background:
|
|
1092
|
-
border-color:
|
|
1093
|
-
color:
|
|
1359
|
+
background: var(--color-surface-elevated);
|
|
1360
|
+
border-color: currentColor;
|
|
1361
|
+
color: var(--color-info);
|
|
1094
1362
|
}
|
|
1095
1363
|
|
|
1096
1364
|
.jux-alert-success {
|
|
1097
|
-
background:
|
|
1098
|
-
border-color:
|
|
1099
|
-
color:
|
|
1365
|
+
background: var(--color-surface-elevated);
|
|
1366
|
+
border-color: currentColor;
|
|
1367
|
+
color: var(--color-success);
|
|
1100
1368
|
}
|
|
1101
1369
|
|
|
1102
1370
|
.jux-alert-warning {
|
|
1103
|
-
background:
|
|
1104
|
-
border-color:
|
|
1105
|
-
color:
|
|
1371
|
+
background: var(--color-surface-elevated);
|
|
1372
|
+
border-color: currentColor;
|
|
1373
|
+
color: var(--color-warning);
|
|
1106
1374
|
}
|
|
1107
1375
|
|
|
1108
1376
|
.jux-alert-error {
|
|
1109
|
-
background:
|
|
1110
|
-
border-color:
|
|
1111
|
-
color:
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
|
-
/* Dark mode adjustments for alerts */
|
|
1115
|
-
@media (prefers-color-scheme: dark) {
|
|
1116
|
-
.jux-alert-info {
|
|
1117
|
-
background: rgba(59, 130, 246, 0.15);
|
|
1118
|
-
border-color: rgba(59, 130, 246, 0.4);
|
|
1119
|
-
color: #60a5fa;
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
.jux-alert-success {
|
|
1123
|
-
background: rgba(34, 197, 94, 0.15);
|
|
1124
|
-
border-color: rgba(34, 197, 94, 0.4);
|
|
1125
|
-
color: #4ade80;
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
.jux-alert-warning {
|
|
1129
|
-
background: rgba(251, 191, 36, 0.15);
|
|
1130
|
-
border-color: rgba(251, 191, 36, 0.4);
|
|
1131
|
-
color: #fbbf24;
|
|
1132
|
-
}
|
|
1133
|
-
|
|
1134
|
-
.jux-alert-error {
|
|
1135
|
-
background: rgba(239, 68, 68, 0.15);
|
|
1136
|
-
border-color: rgba(239, 68, 68, 0.4);
|
|
1137
|
-
color: #f87171;
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
/* Alert animations */
|
|
1142
|
-
@keyframes alertSlideIn {
|
|
1143
|
-
from {
|
|
1144
|
-
opacity: 0;
|
|
1145
|
-
transform: translateY(-10px);
|
|
1146
|
-
}
|
|
1147
|
-
to {
|
|
1148
|
-
opacity: 1;
|
|
1149
|
-
transform: translateY(0);
|
|
1150
|
-
}
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
|
-
@keyframes alertSlideOut {
|
|
1154
|
-
from {
|
|
1155
|
-
opacity: 1;
|
|
1156
|
-
transform: translateY(0);
|
|
1157
|
-
}
|
|
1158
|
-
to {
|
|
1159
|
-
opacity: 0;
|
|
1160
|
-
transform: translateY(-10px);
|
|
1161
|
-
}
|
|
1162
|
-
}
|
|
1163
|
-
|
|
1164
|
-
.jux-alert[style*="display: none"] {
|
|
1165
|
-
animation: alertSlideOut var(--transition-fast) ease-out forwards;
|
|
1377
|
+
background: var(--color-surface-elevated);
|
|
1378
|
+
border-color: currentColor;
|
|
1379
|
+
color: var(--color-danger);
|
|
1166
1380
|
}
|
|
File without changes
|