juxscript 1.0.25 → 1.0.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.
@@ -173,7 +173,7 @@ export async function transpileProjectTypeScript(srcDir, destDir) {
173
173
  }
174
174
 
175
175
  /**
176
- * Copy presets folder from lib to dist
176
+ * Copy presets folder from lib to dist (maintaining directory structure)
177
177
  *
178
178
  * @param {string} packageRoot - Source package root directory
179
179
  * @param {string} distDir - Destination directory
@@ -195,21 +195,30 @@ export async function copyPresetsToOutput(packageRoot, distDir) {
195
195
 
196
196
  fs.mkdirSync(presetsDest, { recursive: true });
197
197
 
198
- // Copy all files in presets directory
199
- const files = fs.readdirSync(presetsSrc);
198
+ // Recursively copy entire presets directory structure
200
199
  let copiedCount = 0;
201
200
 
202
- for (const file of files) {
203
- const srcPath = path.join(presetsSrc, file);
204
- const destPath = path.join(presetsDest, file);
201
+ function copyRecursive(src, dest) {
202
+ const entries = fs.readdirSync(src, { withFileTypes: true });
205
203
 
206
- if (fs.statSync(srcPath).isFile()) {
207
- fs.copyFileSync(srcPath, destPath);
208
- console.log(` ✓ ${file}`);
209
- copiedCount++;
204
+ for (const entry of entries) {
205
+ const srcPath = path.join(src, entry.name);
206
+ const destPath = path.join(dest, entry.name);
207
+
208
+ if (entry.isDirectory()) {
209
+ fs.mkdirSync(destPath, { recursive: true });
210
+ copyRecursive(srcPath, destPath);
211
+ } else if (entry.isFile()) {
212
+ fs.copyFileSync(srcPath, destPath);
213
+ const relativePath = path.relative(presetsSrc, srcPath);
214
+ console.log(` ✓ ${relativePath}`);
215
+ copiedCount++;
216
+ }
210
217
  }
211
218
  }
212
219
 
220
+ copyRecursive(presetsSrc, presetsDest);
221
+
213
222
  console.log(`✅ Copied ${copiedCount} preset file(s)\n`);
214
223
  }
215
224
 
@@ -653,10 +662,6 @@ export function generateIndexHtml(distDir, routes, mainJsFilename = 'main.js') {
653
662
  <title>Jux Application</title>
654
663
  </head>
655
664
  <body data-theme="">
656
- <!-- Navigation -->
657
- <nav style="padding: 20px; background: #f5f5f5; border-bottom: 2px solid #ddd;">
658
- ${navLinks}
659
- </nav>
660
665
  <!-- App container - router renders here -->
661
666
  <div id="app"></div>
662
667
  ${importMapScript}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.0.25",
3
+ "version": "1.0.27",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "lib/jux.js",
@@ -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');