juxscript 1.0.64 → 1.0.65
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 +17 -2
- package/create/all.jux +343 -0
- package/create/index.jux +90 -0
- package/create/layout.jux +57 -0
- package/create/style.css +1952 -0
- package/create/themes/assets/jux.svg +34 -0
- package/create/themes/base.css +60 -0
- package/create/themes/base2.css +54 -0
- package/create/themes/layouts/base.jux +16 -0
- package/create/themes/layouts/base_blog.jux +0 -0
- package/create/themes/layouts/base_docs.jux +0 -0
- package/create/themes/layouts/base_login.jux +0 -0
- package/create/themes/layouts/base_marketing.jux +0 -0
- package/create/themes/layouts/base_saas.jux +0 -0
- package/package.json +4 -11
- package/tests/dropdown-test.js +25 -0
- package/tests/juxerrors/bad_syntax.jux +8 -0
- package/tests/juxerrors/ghost_dep.jux +10 -0
- package/tests/server_plugin_test.ts +191 -0
- package/docs/DEPRECATIONS.md +0 -244
- package/docs/deprecation-code.png +0 -0
- package/docs/deprecation-console.png +0 -0
- package/docs/grid.png +0 -0
- package/docs/v2comps/HEADLESS.md +0 -83
- package/docs/v2comps/ISOMORPHISM.md +0 -10
package/bin/cli.js
CHANGED
|
@@ -14,8 +14,8 @@ const command = process.argv[2];
|
|
|
14
14
|
// ═══════════════════════════════════════════════════════════════════
|
|
15
15
|
|
|
16
16
|
if (command === 'create') {
|
|
17
|
-
|
|
18
|
-
const projectName = process.argv[3] ||
|
|
17
|
+
// ✅ FIX: Removed timestamp fallback from default name
|
|
18
|
+
const projectName = process.argv[3] || 'my-jux-app';
|
|
19
19
|
|
|
20
20
|
const projectPath = path.join(process.cwd(), projectName);
|
|
21
21
|
|
|
@@ -309,11 +309,26 @@ function findJuxFiles(dir, fileList = []) {
|
|
|
309
309
|
for (const entry of entries) {
|
|
310
310
|
if (entry.isFile()) {
|
|
311
311
|
fs.copyFileSync(path.join(defaultPresetSrc, entry.name), path.join(juxDir, entry.name));
|
|
312
|
+
filesCopied++;
|
|
312
313
|
// console.log(`+ Created ${entry.name}`);
|
|
313
314
|
}
|
|
314
315
|
}
|
|
315
316
|
}
|
|
316
317
|
|
|
318
|
+
// ✅ ADD: Safe fallback if presets are missing so build doesn't fail
|
|
319
|
+
if (filesCopied === 0) {
|
|
320
|
+
console.warn('⚠️ Presets not found. Creating default index.jux...');
|
|
321
|
+
const indexContent = `import { jux } from 'juxscript';
|
|
322
|
+
|
|
323
|
+
jux.hero('welcome', {
|
|
324
|
+
title: 'Welcome to JUX',
|
|
325
|
+
subtitle: 'Start building in jux/index.jux'
|
|
326
|
+
}).render('#app');
|
|
327
|
+
`;
|
|
328
|
+
fs.writeFileSync(path.join(juxDir, 'index.jux'), indexContent);
|
|
329
|
+
console.log('+ Created index.jux');
|
|
330
|
+
}
|
|
331
|
+
|
|
317
332
|
// Create juxconfig.js
|
|
318
333
|
const configExampleSrc = path.join(PATHS.packageRoot, 'juxconfig.example.js');
|
|
319
334
|
const configDest = path.join(PATHS.projectRoot, 'juxconfig.js');
|
package/create/all.jux
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { jux, state } from 'juxscript';
|
|
2
|
+
import { initializeGrid } from 'layout.jux';
|
|
3
|
+
|
|
4
|
+
// Initialize the grid layout - this executes the rendering
|
|
5
|
+
const grid = initializeGrid();
|
|
6
|
+
|
|
7
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
8
|
+
// ALL COMPONENTS SHOWCASE - Maximum DOM nodes per component
|
|
9
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
10
|
+
|
|
11
|
+
// Hero - All DOM-generating options
|
|
12
|
+
jux.heading('hero-heading').level(3).text('jux.hero').render("#appmain-content");
|
|
13
|
+
jux.hero('all-hero', {
|
|
14
|
+
title: 'Hero Title',
|
|
15
|
+
subtitle: 'Hero Subtitle',
|
|
16
|
+
content: 'Hero body content goes here',
|
|
17
|
+
cta: 'Call to Action',
|
|
18
|
+
ctaLink: '#',
|
|
19
|
+
backgroundOverlay: true,
|
|
20
|
+
centered: true
|
|
21
|
+
}).render("#appmain-content");
|
|
22
|
+
jux.divider().render("#appmain-content");
|
|
23
|
+
|
|
24
|
+
jux.heading('chart-heading').level(3).text('jux.chart, jux.calendar, jux.chatbox, jux.aiwidget, jux.media, jux.icons, jux.data!').render("#appmain-content");
|
|
25
|
+
jux.element('all-element')
|
|
26
|
+
.text('Need Elements! shadcn and tailwind analysis. Mobiles. ios/android - .text')
|
|
27
|
+
.render("#appmain-content");
|
|
28
|
+
jux.divider().render("#appmain-content");
|
|
29
|
+
|
|
30
|
+
jux.heading('alert-heading').level(3).text('jux.alert').render("#appmain-content");
|
|
31
|
+
jux.alert('all-alert')
|
|
32
|
+
.message('this is it - .message').render("#appmain-content");
|
|
33
|
+
jux.divider().render("#appmain-content");
|
|
34
|
+
|
|
35
|
+
jux.heading('badge-heading').level(3).text('jux.badge').render("#appmain-content");
|
|
36
|
+
jux.badge('all-badge')
|
|
37
|
+
.text('Badge Text - .text').render("#appmain-content");
|
|
38
|
+
jux.divider().render("#appmain-content");
|
|
39
|
+
|
|
40
|
+
jux.heading('button-heading').level(3).text('jux.button').render("#appmain-content");
|
|
41
|
+
jux.button('all-button')
|
|
42
|
+
.label('Button Label - .label').render("#appmain-content");
|
|
43
|
+
jux.divider().render("#appmain-content");
|
|
44
|
+
|
|
45
|
+
jux.heading('card-heading').level(3).text('jux.card').render("#appmain-content");
|
|
46
|
+
jux.card('all-card')
|
|
47
|
+
.title('Card Title - .title')
|
|
48
|
+
.content('Card content goes here - .content')
|
|
49
|
+
.footer('Card Footer - .footer')
|
|
50
|
+
.render("#appmain-content");
|
|
51
|
+
jux.divider().render("#appmain-content");
|
|
52
|
+
|
|
53
|
+
jux.heading('checkbox-heading').level(3).text('jux.checkbox').render("#appmain-content");
|
|
54
|
+
jux.checkbox('all-checkbox')
|
|
55
|
+
.label('Checkbox Label - .label')
|
|
56
|
+
.render("#appmain-content");
|
|
57
|
+
jux.divider().render("#appmain-content");
|
|
58
|
+
|
|
59
|
+
jux.heading('code-heading').level(3).text('jux.code').render("#appmain-content");
|
|
60
|
+
jux.code('all-code')
|
|
61
|
+
.code(`// Sample code - .code`)
|
|
62
|
+
.language('javascript')
|
|
63
|
+
.render("#appmain-content");
|
|
64
|
+
jux.divider().render("#appmain-content");
|
|
65
|
+
|
|
66
|
+
jux.heading('container-heading').level(3).text('jux.container').render("#appmain-content");
|
|
67
|
+
jux.container('all-container')
|
|
68
|
+
.render("#appmain-content");
|
|
69
|
+
jux.divider().render("#appmain-content");
|
|
70
|
+
|
|
71
|
+
jux.heading('datepicker-heading').level(3).text('jux.datepicker').render("#appmain-content");
|
|
72
|
+
jux.datepicker('all-datepicker')
|
|
73
|
+
.label('Select Date - .label')
|
|
74
|
+
.render("#appmain-content");
|
|
75
|
+
jux.divider().render("#appmain-content");
|
|
76
|
+
|
|
77
|
+
jux.heading('dropdown-heading').level(3).text('jux.dropdown').render("#appmain-content");
|
|
78
|
+
jux.dropdown('all-dropdown', {
|
|
79
|
+
items: [{ label: 'Item 1', value: '1' }, { label: 'Item 2', value: '2' }]
|
|
80
|
+
})
|
|
81
|
+
.render("#appmain-content");
|
|
82
|
+
jux.divider().render("#appmain-content");
|
|
83
|
+
|
|
84
|
+
jux.heading('fileupload-heading').level(3).text('jux.fileupload').render("#appmain-content");
|
|
85
|
+
jux.fileupload('all-fileupload')
|
|
86
|
+
.label('File Upload - .label')
|
|
87
|
+
.render("#appmain-content");
|
|
88
|
+
jux.divider().render("#appmain-content");
|
|
89
|
+
|
|
90
|
+
jux.heading('heading-heading').level(3).text('jux.heading').render("#appmain-content");
|
|
91
|
+
jux.heading('all-h1')
|
|
92
|
+
.text('Heading Level 1 - .text')
|
|
93
|
+
.level(1)
|
|
94
|
+
.render("#appmain-content");
|
|
95
|
+
jux.divider().render("#appmain-content");
|
|
96
|
+
|
|
97
|
+
// jux.heading('icon-heading').level(3).text('jux.icon').render("#appmain-content");
|
|
98
|
+
// jux.icon('all-icon').render("#appmain-content");
|
|
99
|
+
// jux.divider().render("#appmain-content");
|
|
100
|
+
|
|
101
|
+
jux.heading('input-heading').level(3).text('jux.input').render("#appmain-content");
|
|
102
|
+
jux.input('all-input')
|
|
103
|
+
.label('Input Label - .label')
|
|
104
|
+
.render("#appmain-content");
|
|
105
|
+
jux.divider().render("#appmain-content");
|
|
106
|
+
|
|
107
|
+
jux.heading('kpicard-heading').level(3).text('jux.kpicard').render("#appmain-content");
|
|
108
|
+
jux.kpicard('all-kpicard')
|
|
109
|
+
.delta('+5% - .delta')
|
|
110
|
+
.prefix('$ - .prefix')
|
|
111
|
+
.value('1,000 - .value')
|
|
112
|
+
.title('KPI Card Title - .title')
|
|
113
|
+
.render("#appmain-content");
|
|
114
|
+
jux.divider().render("#appmain-content");
|
|
115
|
+
|
|
116
|
+
jux.heading('list-heading').level(3).text('jux.list').render("#appmain-content");
|
|
117
|
+
jux.list('all-list', {
|
|
118
|
+
items: ['Item 1', 'Item 2', 'Item 3']
|
|
119
|
+
})
|
|
120
|
+
.render("#appmain-content");
|
|
121
|
+
jux.divider().render("#appmain-content");
|
|
122
|
+
|
|
123
|
+
jux.heading('loading-heading').level(3).text('jux.loading').render("#appmain-content");
|
|
124
|
+
jux.loading('all-loading')
|
|
125
|
+
.variant('spinner')
|
|
126
|
+
.size('lg')
|
|
127
|
+
.render("#appmain-content");
|
|
128
|
+
jux.divider().render("#appmain-content");
|
|
129
|
+
|
|
130
|
+
jux.heading('sidebar-heading').level(3).text('jux.sidebar').render("#appaside");
|
|
131
|
+
jux.sidebar('all-sidebar')
|
|
132
|
+
.collapsible(true)
|
|
133
|
+
.render("#appaside");
|
|
134
|
+
jux.divider().render("#appaside");
|
|
135
|
+
|
|
136
|
+
jux.heading('menu-heading').level(3).text('jux.menu').render("#appaside");
|
|
137
|
+
jux.menu('all-menu', {
|
|
138
|
+
items: [{ label: 'Home', path: '/' }, { label: 'About', path: '/about' }]
|
|
139
|
+
})
|
|
140
|
+
.render("#appaside");
|
|
141
|
+
jux.divider().render("#appaside");
|
|
142
|
+
|
|
143
|
+
jux.heading('nav-heading').level(3).text('jux.nav').render("#appmain-content");
|
|
144
|
+
jux.nav('all-nav', {
|
|
145
|
+
items: [{ label: 'Home', path: '/' }, { label: 'About', path: '/about' }]
|
|
146
|
+
}).render("#appmain-content");
|
|
147
|
+
jux.divider().render("#appmain-content");
|
|
148
|
+
|
|
149
|
+
jux.heading('paragraph-heading').level(3).text('jux.paragraph').render("#appmain-content");
|
|
150
|
+
jux.paragraph('all-paragraph')
|
|
151
|
+
.text('This is a sample paragraph created with jux.paragraph - .text')
|
|
152
|
+
.render("#appmain-content");
|
|
153
|
+
jux.divider().render("#appmain-content");
|
|
154
|
+
|
|
155
|
+
jux.heading('progress-heading').level(3).text('jux.progress').render("#appmain-content");
|
|
156
|
+
jux.progress('all-progress')
|
|
157
|
+
.value(70)
|
|
158
|
+
.max(100)
|
|
159
|
+
.variant('success')
|
|
160
|
+
.render("#appmain-content");
|
|
161
|
+
jux.divider().render("#appmain-content");
|
|
162
|
+
|
|
163
|
+
jux.heading('radio-heading').level(3).text('jux.radio').render("#appmain-content");
|
|
164
|
+
jux.radio('all-radio', {
|
|
165
|
+
options: [{ label: 'Option 1', value: '1' }, { label: 'Option 2', value: '2' }]
|
|
166
|
+
})
|
|
167
|
+
.label('Radio Label - .label')
|
|
168
|
+
.render("#appmain-content");
|
|
169
|
+
jux.divider().render("#appmain-content");
|
|
170
|
+
|
|
171
|
+
jux.heading('select-heading').level(3).text('jux.select').render("#appmain-content");
|
|
172
|
+
jux.select('all-select', {
|
|
173
|
+
options: [{ label: 'Option 1', value: '1' }, { label: 'Option 2', value: '2' }]
|
|
174
|
+
})
|
|
175
|
+
.label('Select Label - .label')
|
|
176
|
+
.render("#appmain-content");
|
|
177
|
+
jux.divider().render("#appmain-content");
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
jux.heading('switch-heading').level(3).text('jux.switch').render("#appmain-content");
|
|
182
|
+
jux.switch('all-switch')
|
|
183
|
+
.label('Switch Label - .label')
|
|
184
|
+
.render("#appmain-content");
|
|
185
|
+
jux.divider().render("#appmain-content");
|
|
186
|
+
|
|
187
|
+
jux.heading('table-heading').level(3).text('jux.table').render("#appmain-content");
|
|
188
|
+
jux.table('all-table', {
|
|
189
|
+
columns: ['Name', 'Age'],
|
|
190
|
+
rows: [
|
|
191
|
+
{ Name: 'John', Age: '25' },
|
|
192
|
+
{ Name: 'Jane', Age: '30' },
|
|
193
|
+
{ Name: 'Jane', Age: '30' },
|
|
194
|
+
{ Name: 'Jane', Age: '30' },
|
|
195
|
+
{ Name: 'Jane', Age: '30' }
|
|
196
|
+
]
|
|
197
|
+
})
|
|
198
|
+
.bordered(true)
|
|
199
|
+
.selectable(true)
|
|
200
|
+
.filterable(true)
|
|
201
|
+
.paginated(true)
|
|
202
|
+
.rowsPerPage(2)
|
|
203
|
+
.render("#appmain-content");
|
|
204
|
+
jux.divider().render("#appmain-content");
|
|
205
|
+
|
|
206
|
+
jux.heading('tabs-heading').level(3).text('jux.tabs').render("#appmain-content");
|
|
207
|
+
jux.tabs('all-tabs', {
|
|
208
|
+
tabs: [{ id: 1, label: 'Tab 1', content: 'Content 1' }, { id: 2, label: 'Tab 2', content: 'Content 2' }]
|
|
209
|
+
})
|
|
210
|
+
.activeTab('1')
|
|
211
|
+
.render("#appmain-content");
|
|
212
|
+
jux.divider().render("#appmain-content");
|
|
213
|
+
|
|
214
|
+
jux.heading('tooltip-heading').level(3).text('jux.tooltip').render("#appmain-content");
|
|
215
|
+
jux.button('tooltip-trigger').label('Hover for tooltip').render("#appmain-content");
|
|
216
|
+
jux.tooltip('all-tooltip', {
|
|
217
|
+
text: 'Tooltip content',
|
|
218
|
+
position: 'top'
|
|
219
|
+
}).render('#tooltip-trigger');
|
|
220
|
+
jux.divider().render("#appmain-content");
|
|
221
|
+
|
|
222
|
+
jux.heading('view-heading').level(3).text('jux.view').render("#appmain-content");
|
|
223
|
+
jux.view('all-view')
|
|
224
|
+
.title('View Title - Need to Rethink - this is for nesting! - .title')
|
|
225
|
+
.render("#appmain-content");
|
|
226
|
+
jux.divider().render("#appmain-content");
|
|
227
|
+
|
|
228
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
229
|
+
// SELF-ANALYSIS: Build component tree from #app
|
|
230
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
231
|
+
|
|
232
|
+
function buildComponentTree(element, depth = 0) {
|
|
233
|
+
const indent = ' '.repeat(depth);
|
|
234
|
+
const tagName = element.tagName.toLowerCase();
|
|
235
|
+
// ✅ Fix: Check if className exists and is a string
|
|
236
|
+
const classes = (element.className && typeof element.className === 'string')
|
|
237
|
+
? `.${element.className.split(' ').join('.')}`
|
|
238
|
+
: '';
|
|
239
|
+
|
|
240
|
+
let tree = `${indent}${tagName}${classes}\n`;
|
|
241
|
+
|
|
242
|
+
// Recurse through children
|
|
243
|
+
Array.from(element.children).forEach(child => {
|
|
244
|
+
tree += buildComponentTree(child, depth + 1);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
return tree;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function analyzeComponents() {
|
|
251
|
+
const app = document.getElementById('app');
|
|
252
|
+
if (!app) return 'No #app container found';
|
|
253
|
+
|
|
254
|
+
const components = Array.from(app.children);
|
|
255
|
+
const componentTypes = new Map();
|
|
256
|
+
|
|
257
|
+
let analysis = `═══════════════════════════════════════════════════════════════
|
|
258
|
+
COMPONENT TREE ANALYSIS
|
|
259
|
+
═══════════════════════════════════════════════════════════════
|
|
260
|
+
|
|
261
|
+
Found ${components.length} components in #app
|
|
262
|
+
|
|
263
|
+
`;
|
|
264
|
+
|
|
265
|
+
components.forEach((component, index) => {
|
|
266
|
+
const componentId = component.id || `component-${index}`;
|
|
267
|
+
// ✅ Fix: Safely handle className
|
|
268
|
+
const className = (component.className && typeof component.className === 'string')
|
|
269
|
+
? component.className
|
|
270
|
+
: '';
|
|
271
|
+
const rootClasses = className.split(' ').filter(c => c);
|
|
272
|
+
const primaryClass = rootClasses.find(c => c.startsWith('jux-')) || rootClasses[0] || 'unknown';
|
|
273
|
+
|
|
274
|
+
const componentName = primaryClass
|
|
275
|
+
.replace(/^jux-/, '')
|
|
276
|
+
.split('-')
|
|
277
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
278
|
+
.join('');
|
|
279
|
+
|
|
280
|
+
// Track component types
|
|
281
|
+
const typeName = primaryClass.replace(/^jux-/, '');
|
|
282
|
+
componentTypes.set(typeName, (componentTypes.get(typeName) || 0) + 1);
|
|
283
|
+
|
|
284
|
+
analysis += `┌─ ${componentName} (${componentId})\n`;
|
|
285
|
+
analysis += '│\n';
|
|
286
|
+
|
|
287
|
+
const tree = buildComponentTree(component);
|
|
288
|
+
tree.split('\n').forEach(line => {
|
|
289
|
+
if (line.trim()) {
|
|
290
|
+
analysis += `│ ${line}\n`;
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
analysis += `└${'─'.repeat(66)}\n\n`;
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
// Add summary
|
|
298
|
+
analysis += `═══════════════════════════════════════════════════════════════
|
|
299
|
+
SUMMARY
|
|
300
|
+
═══════════════════════════════════════════════════════════════
|
|
301
|
+
|
|
302
|
+
Component Types:
|
|
303
|
+
`;
|
|
304
|
+
|
|
305
|
+
Array.from(componentTypes.entries())
|
|
306
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
307
|
+
.forEach(([type, count]) => {
|
|
308
|
+
analysis += ` - ${type}: ${count}\n`;
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
analysis += `\nTotal: ${components.length} components rendered\n`;
|
|
312
|
+
|
|
313
|
+
return analysis;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Wait for DOM to be fully rendered
|
|
317
|
+
setTimeout(() => {
|
|
318
|
+
const analysis = analyzeComponents();
|
|
319
|
+
|
|
320
|
+
// Create analysis display
|
|
321
|
+
jux.container('analysis-container')
|
|
322
|
+
.style('margin-top: 3rem; padding: 2rem; background: #1e1e1e; border-radius: 8px;')
|
|
323
|
+
.render("#appmain-content");
|
|
324
|
+
|
|
325
|
+
jux.heading('analysis-title')
|
|
326
|
+
.level(2)
|
|
327
|
+
.text('🔍 Self-Analysis')
|
|
328
|
+
.style('color: #10b981; margin-bottom: 1rem;')
|
|
329
|
+
.render('#analysis-container');
|
|
330
|
+
|
|
331
|
+
jux.code('component-tree')
|
|
332
|
+
.language('text')
|
|
333
|
+
.code(analysis)
|
|
334
|
+
.style('background: #0d1117; color: #c9d1d9; font-size: 0.875rem; max-height: 600px; overflow-y: auto;')
|
|
335
|
+
.render('#analysis-container');
|
|
336
|
+
|
|
337
|
+
jux.paragraph('analysis-note')
|
|
338
|
+
.text('This tree was generated by JavaScript analyzing the DOM structure of this page.')
|
|
339
|
+
.style('margin-top: 1rem; color: #8b949e; font-size: 0.875rem;')
|
|
340
|
+
.render('#analysis-container');
|
|
341
|
+
}, 100);
|
|
342
|
+
|
|
343
|
+
|
package/create/index.jux
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { jux, state } from 'juxscript';
|
|
2
|
+
import { initializeGrid } from 'layout.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.set(count.value + 1))
|
|
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.set(count.value + 1))
|
|
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 Authoring Framework')
|
|
89
|
+
.style('color: var(--color-text-tertiary);')
|
|
90
|
+
.render('#appfooter-content');
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jux } from 'juxscript';
|
|
2
|
+
|
|
3
|
+
// Import the layout styles - testing link.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
7
|
+
// GRID LAYOUT - INITIALIZATION FUNCTION
|
|
8
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
9
|
+
// Note: #app is automatically created by the Jux compiler
|
|
10
|
+
|
|
11
|
+
export function initializeGrid() {
|
|
12
|
+
// add the base jux styles
|
|
13
|
+
jux.include('style.css');
|
|
14
|
+
// Header area
|
|
15
|
+
const appHeader = jux.container('appheader').render('#app');
|
|
16
|
+
const appHeaderContent = jux.container('appheader-content').render('#appheader');
|
|
17
|
+
const appHeaderLogo = jux.container('appheader-logo').render('#appheader-content');
|
|
18
|
+
const appHeaderNav = jux.container('appheader-nav').render('#appheader-content');
|
|
19
|
+
const appHeaderActions = jux.container('appheader-actions').render('#appheader-content');
|
|
20
|
+
|
|
21
|
+
// Left sidebar
|
|
22
|
+
const appAside = jux.container('appaside').render('#app');
|
|
23
|
+
|
|
24
|
+
// Main content area
|
|
25
|
+
const appMain = jux.container('appmain').render('#app');
|
|
26
|
+
const appMainContent = jux.container('appmain-content').render('#appmain');
|
|
27
|
+
|
|
28
|
+
// Right sidebar (optional - starts hidden)
|
|
29
|
+
const appSidebar = jux.container('appsidebar').render('#app');
|
|
30
|
+
const appSidebarHeader = jux.container('appsidebar-header').render('#appsidebar');
|
|
31
|
+
const appSidebarContent = jux.container('appsidebar-content').render('#appsidebar');
|
|
32
|
+
const appSidebarFooter = jux.container('appsidebar-footer').render('#appsidebar');
|
|
33
|
+
|
|
34
|
+
// Footer area
|
|
35
|
+
const appFooter = jux.container('appfooter').render('#app');
|
|
36
|
+
const appFooterContent = jux.container('appfooter-content').render('#appfooter');
|
|
37
|
+
const appFooterLegal = jux.container('appfooter-legal').render('#appfooter-content');
|
|
38
|
+
|
|
39
|
+
// Return references to all containers
|
|
40
|
+
return {
|
|
41
|
+
appHeader,
|
|
42
|
+
appHeaderContent,
|
|
43
|
+
appHeaderLogo,
|
|
44
|
+
appHeaderNav,
|
|
45
|
+
appHeaderActions,
|
|
46
|
+
appAside,
|
|
47
|
+
appMain,
|
|
48
|
+
appMainContent,
|
|
49
|
+
appSidebar,
|
|
50
|
+
appSidebarHeader,
|
|
51
|
+
appSidebarContent,
|
|
52
|
+
appSidebarFooter,
|
|
53
|
+
appFooter,
|
|
54
|
+
appFooterContent,
|
|
55
|
+
appFooterLegal
|
|
56
|
+
};
|
|
57
|
+
}
|