juxscript 1.0.25 → 1.0.26
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/machinery/compiler.js +0 -4
- package/package.json +1 -1
- package/presets/grid.jux +55 -0
- package/presets/index.jux +90 -0
- package/presets/styles/layout.css +280 -0
- package/presets/hey.jux +0 -60
package/machinery/compiler.js
CHANGED
|
@@ -653,10 +653,6 @@ export function generateIndexHtml(distDir, routes, mainJsFilename = 'main.js') {
|
|
|
653
653
|
<title>Jux Application</title>
|
|
654
654
|
</head>
|
|
655
655
|
<body data-theme="">
|
|
656
|
-
<!-- Navigation -->
|
|
657
|
-
<nav style="padding: 20px; background: #f5f5f5; border-bottom: 2px solid #ddd;">
|
|
658
|
-
${navLinks}
|
|
659
|
-
</nav>
|
|
660
656
|
<!-- App container - router renders here -->
|
|
661
657
|
<div id="app"></div>
|
|
662
658
|
${importMapScript}
|
package/package.json
CHANGED
package/presets/grid.jux
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jux } from 'juxscript';
|
|
2
|
+
|
|
3
|
+
// Import the layout styles
|
|
4
|
+
jux.include('styles/layout.css');
|
|
5
|
+
|
|
6
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
7
|
+
// GRID LAYOUT - INITIALIZATION FUNCTION
|
|
8
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
9
|
+
// Note: #app is automatically created by the Jux compiler
|
|
10
|
+
|
|
11
|
+
export function initializeGrid() {
|
|
12
|
+
// Header area
|
|
13
|
+
const appHeader = jux.container('appheader').render('#app');
|
|
14
|
+
const appHeaderContent = jux.container('appheader-content').render('#appheader');
|
|
15
|
+
const appHeaderLogo = jux.container('appheader-logo').render('#appheader-content');
|
|
16
|
+
const appHeaderNav = jux.container('appheader-nav').render('#appheader-content');
|
|
17
|
+
const appHeaderActions = jux.container('appheader-actions').render('#appheader-content');
|
|
18
|
+
|
|
19
|
+
// Left sidebar
|
|
20
|
+
const appAside = jux.container('appaside').render('#app');
|
|
21
|
+
|
|
22
|
+
// Main content area
|
|
23
|
+
const appMain = jux.container('appmain').render('#app');
|
|
24
|
+
const appMainContent = jux.container('appmain-content').render('#appmain');
|
|
25
|
+
|
|
26
|
+
// Right sidebar (optional - starts hidden)
|
|
27
|
+
const appSidebar = jux.container('appsidebar').render('#app');
|
|
28
|
+
const appSidebarHeader = jux.container('appsidebar-header').render('#appsidebar');
|
|
29
|
+
const appSidebarContent = jux.container('appsidebar-content').render('#appsidebar');
|
|
30
|
+
const appSidebarFooter = jux.container('appsidebar-footer').render('#appsidebar');
|
|
31
|
+
|
|
32
|
+
// Footer area
|
|
33
|
+
const appFooter = jux.container('appfooter').render('#app');
|
|
34
|
+
const appFooterContent = jux.container('appfooter-content').render('#appfooter');
|
|
35
|
+
const appFooterLegal = jux.container('appfooter-legal').render('#appfooter-content');
|
|
36
|
+
|
|
37
|
+
// Return references to all containers
|
|
38
|
+
return {
|
|
39
|
+
appHeader,
|
|
40
|
+
appHeaderContent,
|
|
41
|
+
appHeaderLogo,
|
|
42
|
+
appHeaderNav,
|
|
43
|
+
appHeaderActions,
|
|
44
|
+
appAside,
|
|
45
|
+
appMain,
|
|
46
|
+
appMainContent,
|
|
47
|
+
appSidebar,
|
|
48
|
+
appSidebarHeader,
|
|
49
|
+
appSidebarContent,
|
|
50
|
+
appSidebarFooter,
|
|
51
|
+
appFooter,
|
|
52
|
+
appFooterContent,
|
|
53
|
+
appFooterLegal
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { jux, state } from 'juxscript';
|
|
2
|
+
import { initializeGrid } from './grid.jux';
|
|
3
|
+
|
|
4
|
+
// Initialize the grid layout - this executes the rendering
|
|
5
|
+
const grid = initializeGrid();
|
|
6
|
+
|
|
7
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
8
|
+
// HEADER CONTENT
|
|
9
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
10
|
+
|
|
11
|
+
jux.heading('logo-text')
|
|
12
|
+
.level(1)
|
|
13
|
+
.text('JUX')
|
|
14
|
+
.render('#appheader-logo');
|
|
15
|
+
|
|
16
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
17
|
+
// MAIN CONTENT
|
|
18
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
19
|
+
|
|
20
|
+
jux.hero('welcome', {
|
|
21
|
+
title: 'Welcome to JUX',
|
|
22
|
+
subtitle: 'A JavaScript UX authorship platform'
|
|
23
|
+
}).render('#appmain-content');
|
|
24
|
+
|
|
25
|
+
jux.divider().render('#appmain-content');
|
|
26
|
+
|
|
27
|
+
jux.heading('start-heading')
|
|
28
|
+
.level(2)
|
|
29
|
+
.text('Getting Started')
|
|
30
|
+
.render('#appmain-content');
|
|
31
|
+
|
|
32
|
+
jux.paragraph('start-intro')
|
|
33
|
+
.text('Edit this file to build your app. Here are some quick tips:')
|
|
34
|
+
.style('margin: 1rem 0;')
|
|
35
|
+
.render('#appmain-content');
|
|
36
|
+
|
|
37
|
+
jux.list('quick-tips', {
|
|
38
|
+
items: [
|
|
39
|
+
'Run npx jux serve for dev mode with hot reload',
|
|
40
|
+
'Run npx jux build to compile for production',
|
|
41
|
+
'Serve jux-dist/ from your backend',
|
|
42
|
+
'Check out the docs at juxscript.com/docs'
|
|
43
|
+
]
|
|
44
|
+
}).render('#appmain-content');
|
|
45
|
+
|
|
46
|
+
jux.divider().render('#appmain-content');
|
|
47
|
+
|
|
48
|
+
jux.heading('example-heading')
|
|
49
|
+
.level(3)
|
|
50
|
+
.text('Quick Example')
|
|
51
|
+
.render('#appmain-content');
|
|
52
|
+
|
|
53
|
+
jux.code('example-code')
|
|
54
|
+
.language('javascript')
|
|
55
|
+
.code(`import { jux, state } from 'juxscript';
|
|
56
|
+
|
|
57
|
+
const count = state(0);
|
|
58
|
+
|
|
59
|
+
jux.button('increment')
|
|
60
|
+
.label('Click me!')
|
|
61
|
+
.bind('click', () => count.value++)
|
|
62
|
+
.render('#app');
|
|
63
|
+
|
|
64
|
+
jux.paragraph('counter')
|
|
65
|
+
.sync('text', count, val => \`Count: \${val}\`)
|
|
66
|
+
.render('#app');`)
|
|
67
|
+
.render('#appmain-content');
|
|
68
|
+
|
|
69
|
+
// Create a reactive counter demo
|
|
70
|
+
const count = state(0);
|
|
71
|
+
|
|
72
|
+
jux.button('increment')
|
|
73
|
+
.label('Click me!')
|
|
74
|
+
.bind('click', () => count.value++)
|
|
75
|
+
.style('margin: 1rem 0;')
|
|
76
|
+
.render('#appmain-content');
|
|
77
|
+
|
|
78
|
+
jux.paragraph('counter')
|
|
79
|
+
.sync('text', count, val => `Count: ${val}`)
|
|
80
|
+
.style('font-size: 1.25rem; font-weight: 600; color: var(--color-brand);')
|
|
81
|
+
.render('#appmain-content');
|
|
82
|
+
|
|
83
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
84
|
+
// FOOTER CONTENT
|
|
85
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
86
|
+
|
|
87
|
+
jux.paragraph('footer-text')
|
|
88
|
+
.text('© 2026 JUX Platform')
|
|
89
|
+
.style('color: var(--color-text-tertiary);')
|
|
90
|
+
.render('#appfooter-content');
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/* ============================================
|
|
2
|
+
APP CONTAINER - Main Layout Grid
|
|
3
|
+
============================================ */
|
|
4
|
+
#app {
|
|
5
|
+
display: grid;
|
|
6
|
+
grid-template-columns: auto 1fr auto;
|
|
7
|
+
grid-template-rows: auto 1fr auto;
|
|
8
|
+
grid-template-areas:
|
|
9
|
+
"header header header"
|
|
10
|
+
"sidebar main aside"
|
|
11
|
+
"footer footer footer";
|
|
12
|
+
width: 100vw;
|
|
13
|
+
height: 100vh;
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* ============================================
|
|
18
|
+
HEADER - Top Navigation Bar
|
|
19
|
+
============================================ */
|
|
20
|
+
#appheader {
|
|
21
|
+
grid-area: header;
|
|
22
|
+
background: var(--color-surface-elevated);
|
|
23
|
+
border-bottom: var(--border-width) solid var(--color-border);
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
padding: 0 var(--space-lg);
|
|
27
|
+
height: 48px;
|
|
28
|
+
z-index: 100;
|
|
29
|
+
transition: background-color var(--transition-base), border-color var(--transition-base);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
#appheader-content {
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
justify-content: space-between;
|
|
36
|
+
width: 100%;
|
|
37
|
+
gap: var(--space-xl);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#appheader-logo {
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
gap: var(--space-md);
|
|
44
|
+
font-size: var(--font-size-lg);
|
|
45
|
+
font-weight: var(--font-weight-semibold);
|
|
46
|
+
color: var(--color-text-primary);
|
|
47
|
+
text-decoration: none;
|
|
48
|
+
padding: var(--space-sm) var(--space-md);
|
|
49
|
+
border-radius: var(--radius-md);
|
|
50
|
+
transition: background-color var(--transition-fast);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
#appheader-logo:hover {
|
|
54
|
+
background: var(--color-surface-hover);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
#appheader-nav {
|
|
58
|
+
flex: 1;
|
|
59
|
+
display: flex;
|
|
60
|
+
align-items: center;
|
|
61
|
+
gap: var(--space-sm);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
#appheader-actions {
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
gap: var(--space-md);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* ============================================
|
|
71
|
+
LEFT SIDEBAR - Navigation
|
|
72
|
+
============================================ */
|
|
73
|
+
.jux-sidebar,
|
|
74
|
+
#appaside {
|
|
75
|
+
grid-area: sidebar;
|
|
76
|
+
width: 260px;
|
|
77
|
+
background: var(--color-surface-base);
|
|
78
|
+
border-right: var(--border-width) solid var(--color-border);
|
|
79
|
+
display: flex;
|
|
80
|
+
flex-direction: column;
|
|
81
|
+
overflow: hidden;
|
|
82
|
+
transition: width var(--transition-base);
|
|
83
|
+
position: relative;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* ============================================
|
|
87
|
+
MAIN CONTENT - Center Area
|
|
88
|
+
============================================ */
|
|
89
|
+
#appmain {
|
|
90
|
+
grid-area: main;
|
|
91
|
+
background: var(--color-background);
|
|
92
|
+
overflow-y: auto;
|
|
93
|
+
overflow-x: hidden;
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-direction: column;
|
|
96
|
+
position: relative;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
#appmain-content {
|
|
100
|
+
flex: 1;
|
|
101
|
+
padding: var(--space-3xl) var(--space-2xl);
|
|
102
|
+
max-width: 1600px;
|
|
103
|
+
width: 100%;
|
|
104
|
+
margin: 0 auto;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* Custom scrollbar for main content */
|
|
108
|
+
#appmain::-webkit-scrollbar {
|
|
109
|
+
width: 8px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
#appmain::-webkit-scrollbar-track {
|
|
113
|
+
background: var(--color-surface-base);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#appmain::-webkit-scrollbar-thumb {
|
|
117
|
+
background: var(--color-border);
|
|
118
|
+
border-radius: var(--radius-full);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
#appmain::-webkit-scrollbar-thumb:hover {
|
|
122
|
+
background: var(--color-border-hover);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* ============================================
|
|
126
|
+
RIGHT SIDEBAR - Optional Panel
|
|
127
|
+
============================================ */
|
|
128
|
+
#appsidebar {
|
|
129
|
+
grid-area: aside;
|
|
130
|
+
width: 280px;
|
|
131
|
+
background: var(--color-surface-base);
|
|
132
|
+
border-left: var(--border-width) solid var(--color-border);
|
|
133
|
+
display: none;
|
|
134
|
+
flex-direction: column;
|
|
135
|
+
overflow: hidden;
|
|
136
|
+
transition: width var(--transition-base), background-color var(--transition-base);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
#appsidebar.show {
|
|
140
|
+
display: flex;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
#appsidebar.collapsed {
|
|
144
|
+
width: 0;
|
|
145
|
+
border: none;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
#appsidebar-header {
|
|
149
|
+
padding: var(--space-lg);
|
|
150
|
+
border-bottom: var(--border-width) solid var(--color-border);
|
|
151
|
+
font-weight: var(--font-weight-semibold);
|
|
152
|
+
font-size: var(--font-size-sm);
|
|
153
|
+
color: var(--color-text-secondary);
|
|
154
|
+
text-transform: uppercase;
|
|
155
|
+
letter-spacing: 0.05em;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
#appsidebar-content {
|
|
159
|
+
flex: 1;
|
|
160
|
+
overflow-y: auto;
|
|
161
|
+
overflow-x: hidden;
|
|
162
|
+
padding: var(--space-lg);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
#appsidebar-content::-webkit-scrollbar {
|
|
166
|
+
width: 6px;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
#appsidebar-content::-webkit-scrollbar-track {
|
|
170
|
+
background: transparent;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
#appsidebar-content::-webkit-scrollbar-thumb {
|
|
174
|
+
background: var(--color-border);
|
|
175
|
+
border-radius: var(--radius-full);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
#appsidebar-content::-webkit-scrollbar-thumb:hover {
|
|
179
|
+
background: var(--color-border-hover);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
#appsidebar-footer {
|
|
183
|
+
padding: var(--space-lg);
|
|
184
|
+
border-top: var(--border-width) solid var(--color-border);
|
|
185
|
+
font-size: var(--font-size-xs);
|
|
186
|
+
color: var(--color-text-tertiary);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* ============================================
|
|
190
|
+
FOOTER - Bottom Bar
|
|
191
|
+
============================================ */
|
|
192
|
+
#appfooter {
|
|
193
|
+
grid-area: footer;
|
|
194
|
+
background: var(--color-surface-elevated);
|
|
195
|
+
border-top: var(--border-width) solid var(--color-border);
|
|
196
|
+
padding: var(--space-lg) var(--space-2xl);
|
|
197
|
+
display: flex;
|
|
198
|
+
align-items: center;
|
|
199
|
+
justify-content: space-between;
|
|
200
|
+
font-size: var(--font-size-sm);
|
|
201
|
+
color: var(--color-text-tertiary);
|
|
202
|
+
transition: background-color var(--transition-base), border-color var(--transition-base);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
#appfooter-content {
|
|
206
|
+
display: flex;
|
|
207
|
+
align-items: center;
|
|
208
|
+
gap: var(--space-xl);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
#appfooter-legal {
|
|
212
|
+
display: flex;
|
|
213
|
+
align-items: center;
|
|
214
|
+
gap: var(--space-lg);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
#appfooter a {
|
|
218
|
+
color: var(--color-text-secondary);
|
|
219
|
+
text-decoration: none;
|
|
220
|
+
transition: color var(--transition-fast);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
#appfooter a:hover {
|
|
224
|
+
color: var(--color-text-primary);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/* ============================================
|
|
228
|
+
RESPONSIVE GRID LAYOUTS
|
|
229
|
+
============================================ */
|
|
230
|
+
@media (max-width: 1024px) {
|
|
231
|
+
#appsidebar {
|
|
232
|
+
display: none;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
#app {
|
|
236
|
+
grid-template-columns: auto 1fr;
|
|
237
|
+
grid-template-areas:
|
|
238
|
+
"header header"
|
|
239
|
+
"sidebar main"
|
|
240
|
+
"footer footer";
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
@media (max-width: 768px) {
|
|
245
|
+
#app {
|
|
246
|
+
grid-template-columns: 1fr;
|
|
247
|
+
grid-template-areas:
|
|
248
|
+
"header"
|
|
249
|
+
"main"
|
|
250
|
+
"footer";
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.jux-sidebar,
|
|
254
|
+
#appaside {
|
|
255
|
+
display: none;
|
|
256
|
+
position: fixed;
|
|
257
|
+
left: 0;
|
|
258
|
+
top: 0;
|
|
259
|
+
bottom: 0;
|
|
260
|
+
z-index: 1000;
|
|
261
|
+
width: 260px;
|
|
262
|
+
box-shadow: var(--shadow-xl);
|
|
263
|
+
transform: translateX(-100%);
|
|
264
|
+
transition: transform var(--transition-base);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.jux-sidebar.open,
|
|
268
|
+
#appaside.open {
|
|
269
|
+
display: flex;
|
|
270
|
+
transform: translateX(0);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
#appmain-content {
|
|
274
|
+
padding: var(--space-2xl) var(--space-lg);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
#appheader {
|
|
278
|
+
padding: 0 var(--space-md) 0 calc(var(--space-md) + 48px);
|
|
279
|
+
}
|
|
280
|
+
}
|
package/presets/hey.jux
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { jux } from 'juxscript';
|
|
2
|
-
|
|
3
|
-
// Welcome page with examples
|
|
4
|
-
jux.hero('welcome', {
|
|
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('start-heading')
|
|
16
|
-
.level(2)
|
|
17
|
-
.text('Getting Started')
|
|
18
|
-
.render('#getting-started');
|
|
19
|
-
|
|
20
|
-
jux.paragraph('start-intro')
|
|
21
|
-
.text('Edit this file to build your app. Here are some quick tips:')
|
|
22
|
-
.style('margin: 1rem 0;')
|
|
23
|
-
.render('#getting-started');
|
|
24
|
-
|
|
25
|
-
jux.list('quick-tips', {
|
|
26
|
-
items: [
|
|
27
|
-
'Run npx jux serve for dev mode with hot reload',
|
|
28
|
-
'Run npx jux build to compile for production',
|
|
29
|
-
'Serve jux-dist/ from your backend',
|
|
30
|
-
'Check out the docs at juxscript.com/docs'
|
|
31
|
-
]
|
|
32
|
-
}).render('#getting-started');
|
|
33
|
-
|
|
34
|
-
jux.divider().render('#app');
|
|
35
|
-
|
|
36
|
-
jux.container('example-container')
|
|
37
|
-
.style('max-width: 800px; margin: 2rem auto; padding: 2rem; background: #f9fafb; border-radius: 8px;')
|
|
38
|
-
.render('#app');
|
|
39
|
-
|
|
40
|
-
jux.heading('example-heading')
|
|
41
|
-
.level(3)
|
|
42
|
-
.text('Quick Example')
|
|
43
|
-
.render('#example-container');
|
|
44
|
-
|
|
45
|
-
jux.code('example-code')
|
|
46
|
-
.language('javascript')
|
|
47
|
-
.code(`import { jux, state } from 'juxscript';
|
|
48
|
-
|
|
49
|
-
// Create a reactive counter
|
|
50
|
-
const count = state(0);
|
|
51
|
-
|
|
52
|
-
jux.button('increment')
|
|
53
|
-
.label('Click me!')
|
|
54
|
-
.bind('click', () => count.value++)
|
|
55
|
-
.render('#app');
|
|
56
|
-
|
|
57
|
-
jux.paragraph('counter')
|
|
58
|
-
.sync('text', count, val => \`Count: \${val}\`)
|
|
59
|
-
.render('#app');`)
|
|
60
|
-
.render('#example-container');
|