juxscript 1.0.20 → 1.0.21

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.
Files changed (76) hide show
  1. package/bin/cli.js +121 -72
  2. package/lib/components/alert.ts +143 -92
  3. package/lib/components/badge.ts +93 -94
  4. package/lib/components/base/BaseComponent.ts +397 -0
  5. package/lib/components/base/FormInput.ts +322 -0
  6. package/lib/components/button.ts +40 -131
  7. package/lib/components/card.ts +57 -79
  8. package/lib/components/charts/areachart.ts +315 -0
  9. package/lib/components/charts/barchart.ts +421 -0
  10. package/lib/components/charts/doughnutchart.ts +263 -0
  11. package/lib/components/charts/lib/BaseChart.ts +402 -0
  12. package/lib/components/{chart-types.ts → charts/lib/chart-types.ts} +1 -1
  13. package/lib/components/{chart-utils.ts → charts/lib/chart-utils.ts} +1 -1
  14. package/lib/components/{chart.ts → charts/lib/chart.ts} +3 -3
  15. package/lib/components/checkbox.ts +255 -204
  16. package/lib/components/code.ts +31 -78
  17. package/lib/components/container.ts +113 -130
  18. package/lib/components/data.ts +37 -5
  19. package/lib/components/datepicker.ts +180 -147
  20. package/lib/components/dialog.ts +218 -221
  21. package/lib/components/divider.ts +63 -87
  22. package/lib/components/docs-data.json +498 -2404
  23. package/lib/components/dropdown.ts +191 -236
  24. package/lib/components/element.ts +196 -145
  25. package/lib/components/fileupload.ts +253 -167
  26. package/lib/components/guard.ts +92 -0
  27. package/lib/components/heading.ts +31 -97
  28. package/lib/components/helpers.ts +13 -6
  29. package/lib/components/hero.ts +51 -114
  30. package/lib/components/icon.ts +33 -120
  31. package/lib/components/icons.ts +2 -1
  32. package/lib/components/include.ts +76 -3
  33. package/lib/components/input.ts +155 -407
  34. package/lib/components/kpicard.ts +16 -16
  35. package/lib/components/list.ts +358 -261
  36. package/lib/components/loading.ts +142 -211
  37. package/lib/components/menu.ts +63 -152
  38. package/lib/components/modal.ts +42 -129
  39. package/lib/components/nav.ts +79 -101
  40. package/lib/components/paragraph.ts +38 -102
  41. package/lib/components/progress.ts +108 -166
  42. package/lib/components/radio.ts +283 -234
  43. package/lib/components/script.ts +19 -87
  44. package/lib/components/select.ts +189 -199
  45. package/lib/components/sidebar.ts +110 -141
  46. package/lib/components/style.ts +19 -82
  47. package/lib/components/switch.ts +254 -183
  48. package/lib/components/table.ts +1078 -208
  49. package/lib/components/tabs.ts +42 -106
  50. package/lib/components/theme-toggle.ts +73 -165
  51. package/lib/components/tooltip.ts +85 -316
  52. package/lib/components/write.ts +108 -127
  53. package/lib/jux.ts +67 -41
  54. package/machinery/build.js +466 -0
  55. package/machinery/compiler.js +354 -105
  56. package/machinery/server.js +23 -100
  57. package/machinery/watcher.js +153 -130
  58. package/package.json +1 -1
  59. package/presets/base.css +1166 -0
  60. package/presets/notion.css +2 -1975
  61. package/lib/adapters/base-adapter.js +0 -35
  62. package/lib/adapters/index.js +0 -33
  63. package/lib/adapters/mysql-adapter.js +0 -65
  64. package/lib/adapters/postgres-adapter.js +0 -70
  65. package/lib/adapters/sqlite-adapter.js +0 -56
  66. package/lib/components/areachart.ts +0 -1128
  67. package/lib/components/areachartsmooth.ts +0 -1380
  68. package/lib/components/barchart.ts +0 -1322
  69. package/lib/components/doughnutchart.ts +0 -1259
  70. package/lib/components/footer.ts +0 -165
  71. package/lib/components/header.ts +0 -187
  72. package/lib/components/layout.ts +0 -239
  73. package/lib/components/main.ts +0 -137
  74. package/lib/layouts/default.jux +0 -8
  75. package/lib/layouts/figma.jux +0 -0
  76. /package/lib/{themes → components/charts/lib}/charts.js +0 -0
@@ -1,148 +1,171 @@
1
- import chokidar from 'chokidar';
2
- import path from 'path';
3
- import { compileJuxFile, copyLibToOutput } from './compiler.js';
4
1
  import fs from 'fs';
5
- import { glob } from 'glob';
6
-
7
- export function startWatcher(projectRoot, distDir, clients = []) {
8
- console.log('🔍 Watcher Configuration:');
9
- console.log(' Project Root:', projectRoot);
10
- console.log(' Dist Dir:', distDir);
11
-
12
- // Manually find all files to watch
13
- console.log('\n📋 Finding files to watch...');
14
-
15
- // Project .jux files
16
- const juxFiles = glob.sync('**/*.jux', {
17
- cwd: projectRoot,
18
- ignore: ['node_modules/**', 'dist/**', '.git/**'],
19
- absolute: true
20
- });
21
-
22
- // Vendor layout .jux files
23
- const libRoot = path.resolve(projectRoot, '../lib');
24
- const vendorJuxFiles = glob.sync('layouts/**/*.jux', {
25
- cwd: libRoot,
26
- absolute: true
27
- });
28
-
29
- const cssFiles = glob.sync('**/*.css', {
30
- cwd: projectRoot,
31
- ignore: ['node_modules/**', 'dist/**', '.git/**'],
32
- absolute: true
33
- });
34
-
35
- const libFiles = glob.sync('**/*.{ts,js,css}', {
36
- cwd: libRoot,
37
- absolute: true
38
- });
39
-
40
- const machineryFiles = glob.sync('machinery/**/*.js', {
41
- cwd: path.resolve(projectRoot, '..'),
42
- absolute: true
43
- });
2
+ import path from 'path';
3
+ import {
4
+ copyLibToOutput,
5
+ bundleJuxFilesToRouter,
6
+ generateIndexHtml
7
+ } from './compiler.js';
44
8
 
45
- const allFiles = [...juxFiles, ...vendorJuxFiles, ...cssFiles, ...libFiles, ...machineryFiles];
46
-
47
- console.log(` Found ${juxFiles.length} project .jux files`);
48
- console.log(` Found ${vendorJuxFiles.length} vendor .jux files`);
49
- console.log(` Found ${cssFiles.length} .css files`);
50
- console.log(` Found ${libFiles.length} lib/ files`);
51
- console.log(` Found ${machineryFiles.length} machinery/ files`);
52
- console.log(` Total: ${allFiles.length} files\n`);
53
-
54
- if (allFiles.length === 0) {
55
- console.error('❌ No files found to watch!');
56
- return null;
57
- }
9
+ let isRebuilding = false;
10
+ let rebuildQueued = false;
11
+
12
+ /**
13
+ * Find all .jux files in a directory
14
+ */
15
+ function findJuxFiles(dir, fileList = []) {
16
+ if (!fs.existsSync(dir)) return fileList;
17
+
18
+ const files = fs.readdirSync(dir);
58
19
 
59
- // Watch the specific files we found
60
- const watcher = chokidar.watch(allFiles, {
61
- persistent: true,
62
- ignoreInitial: true,
63
- awaitWriteFinish: {
64
- stabilityThreshold: 100,
65
- pollInterval: 50
20
+ files.forEach(file => {
21
+ const filePath = path.join(dir, file);
22
+ const stat = fs.statSync(filePath);
23
+
24
+ if (stat.isDirectory()) {
25
+ if (file !== 'node_modules' && file !== 'jux-dist' && file !== '.git' && file !== 'server') {
26
+ findJuxFiles(filePath, fileList);
27
+ }
28
+ } else if (file.endsWith('.jux')) {
29
+ fileList.push(filePath);
66
30
  }
67
31
  });
68
32
 
69
- watcher.on('ready', () => {
70
- console.log('✅ Watching for changes...\n');
71
- allFiles.forEach(file => {
72
- const rel = path.relative(path.resolve(projectRoot, '..'), file);
73
- console.log(` 👁️ ${rel}`);
33
+ return fileList;
34
+ }
35
+
36
+ /**
37
+ * Full rebuild of the entire bundle
38
+ */
39
+ async function fullRebuild(juxSource, distDir) {
40
+ const startTime = performance.now(); // ✅ Start timing
41
+ console.log('\n🔄 Rebuilding bundle...');
42
+
43
+ try {
44
+ // Find all .jux files
45
+ const projectJuxFiles = findJuxFiles(juxSource);
46
+ console.log(` Found ${projectJuxFiles.length} .jux file(s)`);
47
+
48
+ // ✅ Time the bundling step
49
+ const bundleStartTime = performance.now();
50
+
51
+ // Bundle all files
52
+ const mainJsFilename = await bundleJuxFilesToRouter(juxSource, distDir, {
53
+ routePrefix: ''
74
54
  });
75
- console.log('');
76
- });
77
55
 
78
- watcher.on('change', async (filePath) => {
79
- const relativePath = path.relative(path.resolve(projectRoot, '..'), filePath);
80
- console.log(`\n🔄 Changed: ${relativePath}`);
81
-
82
- try {
83
- if (filePath.endsWith('.jux')) {
84
- console.log(' → Compiling .jux file...');
85
-
86
- // Determine if it's a vendor or project file
87
- if (filePath.includes('/lib/layouts/')) {
88
- // Vendor layout file
89
- await compileJuxFile(filePath, {
90
- distDir: path.join(distDir, 'lib'),
91
- projectRoot: libRoot,
92
- isServe: true
93
- });
94
- } else {
95
- // Project file
96
- await compileJuxFile(filePath, { distDir, projectRoot, isServe: true });
97
- }
98
-
99
- console.log(`✅ Recompiled: ${relativePath}`);
100
- } else if (filePath.includes('/lib/')) {
101
- console.log(' → Rebuilding lib files...');
102
- await copyLibToOutput(projectRoot, distDir);
103
- console.log(`✅ Rebuilt lib files`);
104
- } else if (filePath.endsWith('.css')) {
105
- console.log(' → CSS file changed');
106
- console.log(`✅ CSS change detected`);
107
- } else if (filePath.includes('/machinery/')) {
108
- console.log(' → Machinery file changed');
109
- console.log(`⚠️ Restart server to apply changes`);
110
- }
56
+ const bundleTime = performance.now() - bundleStartTime;
111
57
 
112
- console.log(` → Notifying ${clients.length} client(s)`);
113
- notifyClients(clients);
114
- } catch (err) {
115
- console.error(`❌ Error processing ${relativePath}:`, err.message);
116
- console.error(err.stack);
117
- }
118
- });
58
+ // Time the route generation step
59
+ const routeStartTime = performance.now();
119
60
 
120
- watcher.on('add', (filePath) => {
121
- const relativePath = path.relative(path.resolve(projectRoot, '..'), filePath);
122
- console.log(`➕ New file detected: ${relativePath}`);
123
- });
61
+ // Generate routes for index.html
62
+ const routes = projectJuxFiles.map(juxFile => {
63
+ const relativePath = path.relative(juxSource, juxFile);
64
+ const parsedPath = path.parse(relativePath);
124
65
 
125
- watcher.on('unlink', (filePath) => {
126
- const relativePath = path.relative(path.resolve(projectRoot, '..'), filePath);
127
- console.log(`➖ File deleted: ${relativePath}`);
128
- });
66
+ const rawFunctionName = parsedPath.dir
67
+ ? `${parsedPath.dir.replace(/\//g, '_')}_${parsedPath.name}`
68
+ : parsedPath.name;
129
69
 
130
- watcher.on('error', (error) => {
131
- console.error(' Watcher error:', error);
132
- });
70
+ const functionName = rawFunctionName
71
+ .replace(/[-_]/g, ' ')
72
+ .split(' ')
73
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
74
+ .join('');
133
75
 
134
- return watcher;
76
+ const routePath = '/' + (parsedPath.dir ? `${parsedPath.dir}/` : '') + parsedPath.name;
77
+
78
+ return {
79
+ path: routePath.replace(/\/+/g, '/'),
80
+ functionName
81
+ };
82
+ });
83
+
84
+ // Generate index.html
85
+ generateIndexHtml(distDir, routes, mainJsFilename);
86
+
87
+ const routeTime = performance.now() - routeStartTime;
88
+ const totalTime = performance.now() - startTime;
89
+
90
+ // ✅ Pretty-print timing breakdown
91
+ console.log(`\n⏱️ Rebuild Performance:`);
92
+ console.log(` Bundle generation: ${bundleTime.toFixed(0)}ms`);
93
+ console.log(` Route/index.html: ${routeTime.toFixed(0)}ms`);
94
+ console.log(` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
95
+ console.log(` Total rebuild: ${totalTime.toFixed(0)}ms`);
96
+
97
+ // ✅ Color-coded performance indicator
98
+ if (totalTime < 100) {
99
+ console.log(` ✅ Lightning fast! ⚡`);
100
+ } else if (totalTime < 500) {
101
+ console.log(` ✅ Fast rebuild`);
102
+ } else if (totalTime < 1000) {
103
+ console.log(` ⚠️ Moderate speed`);
104
+ } else {
105
+ console.log(` 🐌 Slow rebuild (consider optimizing)`);
106
+ }
107
+
108
+ console.log(`✅ Bundle rebuilt: ${mainJsFilename}\n`);
109
+ return true;
110
+
111
+ } catch (err) {
112
+ const failTime = performance.now() - startTime;
113
+ console.error(`❌ Rebuild failed after ${failTime.toFixed(0)}ms:`, err.message);
114
+ return false;
115
+ }
135
116
  }
136
117
 
137
- function notifyClients(clients) {
138
- let notified = 0;
139
- clients.forEach(client => {
140
- if (client.readyState === 1) {
141
- client.send(JSON.stringify({ type: 'reload' }));
142
- notified++;
118
+ /**
119
+ * Start watching for file changes and rebuild on change
120
+ */
121
+ export function startWatcher(juxSource, distDir, wsClients) {
122
+ console.log(`👀 Watching: ${juxSource}`);
123
+
124
+ const watcher = fs.watch(juxSource, { recursive: true }, async (eventType, filename) => {
125
+ // Ignore non-.jux files and certain patterns
126
+ if (!filename ||
127
+ !filename.endsWith('.jux') ||
128
+ filename.includes('node_modules') ||
129
+ filename.includes('jux-dist') ||
130
+ filename.startsWith('.')) {
131
+ return;
132
+ }
133
+
134
+ // Debounce: If already rebuilding, queue another rebuild
135
+ if (isRebuilding) {
136
+ rebuildQueued = true;
137
+ return;
138
+ }
139
+
140
+ isRebuilding = true;
141
+ console.log(`\n📝 File changed: ${filename}`);
142
+
143
+ // Rebuild the entire bundle
144
+ const success = await fullRebuild(juxSource, distDir);
145
+
146
+ isRebuilding = false;
147
+
148
+ // Notify all WebSocket clients to reload
149
+ if (success && wsClients && wsClients.length > 0) {
150
+ console.log(`🔌 Notifying ${wsClients.length} client(s) to reload`);
151
+
152
+ // ✅ Add small delay to ensure file is fully written
153
+ setTimeout(() => {
154
+ wsClients.forEach(client => {
155
+ if (client.readyState === 1) { // OPEN
156
+ client.send(JSON.stringify({ type: 'reload' }));
157
+ }
158
+ });
159
+ }, 100);
160
+ }
161
+
162
+ // Process queued rebuild if needed
163
+ if (rebuildQueued) {
164
+ rebuildQueued = false;
165
+ console.log('🔄 Processing queued rebuild...');
166
+ setTimeout(() => watcher.emit('change', 'change', filename), 500);
143
167
  }
144
168
  });
145
- if (notified > 0) {
146
- console.log(` ✉️ Reloaded ${notified} client(s)`);
147
- }
169
+
170
+ return watcher;
148
171
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.0.20",
3
+ "version": "1.0.21",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "lib/jux.js",