juxscript 1.0.64 → 1.0.66

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 CHANGED
@@ -14,8 +14,8 @@ const command = process.argv[2];
14
14
  // ═══════════════════════════════════════════════════════════════════
15
15
 
16
16
  if (command === 'create') {
17
- const timestamp = new Date().toISOString().slice(0, 16).replace(/[-:T]/g, '').slice(0, 12);
18
- const projectName = process.argv[3] || `my-jux-app-${timestamp}`;
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
 
@@ -302,6 +302,7 @@ function findJuxFiles(dir, fileList = []) {
302
302
 
303
303
  fs.mkdirSync(juxDir, { recursive: true }); // create it.
304
304
 
305
+ let filesCopied = 0;
305
306
  // Copy default presets
306
307
  const defaultPresetSrc = path.join(PATHS.packageRoot, 'create');
307
308
  if (fs.existsSync(defaultPresetSrc)) {
@@ -309,11 +310,26 @@ function findJuxFiles(dir, fileList = []) {
309
310
  for (const entry of entries) {
310
311
  if (entry.isFile()) {
311
312
  fs.copyFileSync(path.join(defaultPresetSrc, entry.name), path.join(juxDir, entry.name));
313
+ filesCopied++;
312
314
  // console.log(`+ Created ${entry.name}`);
313
315
  }
314
316
  }
315
317
  }
316
318
 
319
+ // ✅ ADD: Safe fallback if presets are missing so build doesn't fail
320
+ if (filesCopied === 0) {
321
+ console.warn('⚠️ Install pages not available. Creating default index.jux...');
322
+ const indexContent = `import { jux } from 'juxscript';
323
+
324
+ jux.hero('welcome', {
325
+ title: 'Welcome to JUX',
326
+ subtitle: 'Start building in jux/index.jux'
327
+ }).render('#app');
328
+ `;
329
+ fs.writeFileSync(path.join(juxDir, 'index.jux'), indexContent);
330
+ console.log('+ Created index.jux');
331
+ }
332
+
317
333
  // Create juxconfig.js
318
334
  const configExampleSrc = path.join(PATHS.packageRoot, 'juxconfig.example.js');
319
335
  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
+
@@ -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
+ }