juxscript 1.0.19 → 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 (77) hide show
  1. package/bin/cli.js +121 -72
  2. package/lib/components/alert.ts +212 -165
  3. package/lib/components/badge.ts +93 -103
  4. package/lib/components/base/BaseComponent.ts +397 -0
  5. package/lib/components/base/FormInput.ts +322 -0
  6. package/lib/components/button.ts +63 -122
  7. package/lib/components/card.ts +109 -155
  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/charts/lib/chart-types.ts +159 -0
  13. package/lib/components/charts/lib/chart-utils.ts +160 -0
  14. package/lib/components/charts/lib/chart.ts +707 -0
  15. package/lib/components/checkbox.ts +264 -127
  16. package/lib/components/code.ts +75 -108
  17. package/lib/components/container.ts +113 -130
  18. package/lib/components/data.ts +37 -5
  19. package/lib/components/datepicker.ts +195 -147
  20. package/lib/components/dialog.ts +187 -157
  21. package/lib/components/divider.ts +85 -191
  22. package/lib/components/docs-data.json +544 -2027
  23. package/lib/components/dropdown.ts +178 -136
  24. package/lib/components/element.ts +227 -171
  25. package/lib/components/fileupload.ts +285 -228
  26. package/lib/components/guard.ts +92 -0
  27. package/lib/components/heading.ts +46 -69
  28. package/lib/components/helpers.ts +13 -6
  29. package/lib/components/hero.ts +107 -95
  30. package/lib/components/icon.ts +160 -0
  31. package/lib/components/icons.ts +175 -0
  32. package/lib/components/include.ts +153 -5
  33. package/lib/components/input.ts +174 -374
  34. package/lib/components/kpicard.ts +16 -16
  35. package/lib/components/list.ts +378 -240
  36. package/lib/components/loading.ts +142 -211
  37. package/lib/components/menu.ts +103 -97
  38. package/lib/components/modal.ts +138 -144
  39. package/lib/components/nav.ts +169 -90
  40. package/lib/components/paragraph.ts +49 -150
  41. package/lib/components/progress.ts +118 -200
  42. package/lib/components/radio.ts +297 -149
  43. package/lib/components/script.ts +19 -87
  44. package/lib/components/select.ts +184 -186
  45. package/lib/components/sidebar.ts +152 -140
  46. package/lib/components/style.ts +19 -82
  47. package/lib/components/switch.ts +258 -188
  48. package/lib/components/table.ts +1117 -170
  49. package/lib/components/tabs.ts +162 -145
  50. package/lib/components/theme-toggle.ts +108 -169
  51. package/lib/components/tooltip.ts +86 -157
  52. package/lib/components/write.ts +108 -127
  53. package/lib/jux.ts +86 -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 -2
  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 -1246
  67. package/lib/components/areachartsmooth.ts +0 -1380
  68. package/lib/components/barchart.ts +0 -1250
  69. package/lib/components/chart.ts +0 -127
  70. package/lib/components/doughnutchart.ts +0 -1191
  71. package/lib/components/footer.ts +0 -165
  72. package/lib/components/header.ts +0 -187
  73. package/lib/components/layout.ts +0 -239
  74. package/lib/components/main.ts +0 -137
  75. package/lib/layouts/default.jux +0 -8
  76. package/lib/layouts/figma.jux +0 -0
  77. /package/lib/{themes → components/charts/lib}/charts.js +0 -0
package/bin/cli.js CHANGED
@@ -1,6 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { compileJuxFile, copyLibToOutput, copyProjectAssets, transpileProjectTypeScript, copyPresetsToOutput } from '../machinery/compiler.js';
3
+ import {
4
+ copyLibToOutput,
5
+ copyProjectAssets,
6
+ transpileProjectTypeScript,
7
+ copyPresetsToOutput,
8
+ bundleJuxFilesToRouter,
9
+ generateIndexHtml
10
+ } from '../machinery/compiler.js';
4
11
  import { generateDocs } from '../machinery/doc-generator.js';
5
12
  import { start } from '../machinery/server.js';
6
13
  import path from 'path';
@@ -42,13 +49,11 @@ console.log(` Output: ${PATHS.frontendDist}`);
42
49
  console.log(` Lib: ${PATHS.juxLib}\n`);
43
50
 
44
51
  const command = process.argv[2];
52
+ const watchMode = process.argv.includes('--watch');
53
+ const bundleMode = process.argv.includes('--bundle');
45
54
 
46
55
  /**
47
56
  * Recursively find .jux files in a directory
48
- *
49
- * @param {string} dir - Directory to search
50
- * @param {string[]} fileList - Accumulator for found files
51
- * @returns {string[]} Array of .jux file paths
52
57
  */
53
58
  function findJuxFiles(dir, fileList = []) {
54
59
  if (!fs.existsSync(dir)) return fileList;
@@ -72,11 +77,12 @@ function findJuxFiles(dir, fileList = []) {
72
77
  }
73
78
 
74
79
  /**
75
- * Build the entire JUX project
80
+ * Build the entire JUX project (ALWAYS uses router bundle)
76
81
  *
77
- * @param {boolean} isServe - Whether building for dev server with hot reload
82
+ * @param {boolean} isServe - Whether building for dev server
78
83
  */
79
84
  async function buildProject(isServe = false) {
85
+ const buildStartTime = performance.now();
80
86
  console.log('🔨 Building JUX frontend...\n');
81
87
 
82
88
  try {
@@ -93,80 +99,121 @@ async function buildProject(isServe = false) {
93
99
  }
94
100
  fs.mkdirSync(PATHS.frontendDist, { recursive: true });
95
101
 
96
- // Step 1: Generate documentation from jux lib
102
+ // Step 1: Generate documentation
103
+ const docsStartTime = performance.now();
104
+ let docsTime = 0; // ✅ Declare with default value
97
105
  console.log('📚 Generating documentation...');
98
106
  try {
99
107
  await generateDocs(PATHS.juxLib);
100
- console.log('✅ Documentation generated\n');
108
+ docsTime = performance.now() - docsStartTime;
109
+ console.log(`✅ Documentation generated (${docsTime.toFixed(0)}ms)\n`);
101
110
  } catch (error) {
102
- console.warn('⚠️ Failed to generate docs:', error.message);
111
+ docsTime = performance.now() - docsStartTime; // ✅ Still calculate time even on error
112
+ console.warn(`⚠️ Failed to generate docs (${docsTime.toFixed(0)}ms):`, error.message);
103
113
  }
104
114
 
105
115
  // Step 2: Copy jux lib to frontend dist
116
+ const libStartTime = performance.now();
106
117
  await copyLibToOutput(PATHS.juxLib, PATHS.frontendDist);
118
+ const libTime = performance.now() - libStartTime;
119
+ console.log(`⏱️ Lib copy time: ${libTime.toFixed(0)}ms\n`);
107
120
 
108
- // Step 2.5: Copy presets folder
121
+ // Step 3: Copy presets folder
122
+ const presetsStartTime = performance.now();
109
123
  await copyPresetsToOutput(PATHS.packageRoot, PATHS.frontendDist);
124
+ const presetsTime = performance.now() - presetsStartTime;
125
+ console.log(`⏱️ Presets copy time: ${presetsTime.toFixed(0)}ms\n`);
110
126
 
111
- // Step 3: Copy project assets from jux/ (CSS, JS, images)
127
+ // Step 4: Copy project assets (CSS, JS, images)
128
+ const assetsStartTime = performance.now();
112
129
  await copyProjectAssets(PATHS.juxSource, PATHS.frontendDist);
130
+ const assetsTime = performance.now() - assetsStartTime;
131
+ console.log(`⏱️ Assets copy time: ${assetsTime.toFixed(0)}ms\n`);
113
132
 
114
- // Step 4: Transpile TypeScript files from jux/ to jux-dist/
133
+ // Step 5: Transpile TypeScript files
134
+ const tsStartTime = performance.now();
115
135
  await transpileProjectTypeScript(PATHS.juxSource, PATHS.frontendDist);
136
+ const tsTime = performance.now() - tsStartTime;
137
+ console.log(`⏱️ TypeScript transpile time: ${tsTime.toFixed(0)}ms\n`);
116
138
 
117
- // Step 5: Compile .jux files from jux/ directory ONLY
139
+ // Step 6: Bundle all .jux files into router
118
140
  const projectJuxFiles = findJuxFiles(PATHS.juxSource);
119
141
  console.log(`📝 Found ${projectJuxFiles.length} .jux file(s) in /jux\n`);
120
142
 
121
- for (const file of projectJuxFiles) {
122
- try {
123
- await compileJuxFile(file, {
124
- distDir: PATHS.frontendDist,
125
- projectRoot: PATHS.juxSource,
126
- isServe
127
- });
128
- } catch (err) {
129
- console.error(`Error compiling ${file}:`, err.message);
130
- }
143
+ if (projectJuxFiles.length === 0) {
144
+ console.warn('⚠️ No .jux files found to bundle');
145
+ process.exit(1);
131
146
  }
132
147
 
133
- // Step 6: Compile vendor layouts
134
- const layoutsDir = path.join(PATHS.juxLib, 'layouts');
135
-
136
- if (fs.existsSync(layoutsDir)) {
137
- console.log('\n📐 Compiling vendor layouts...');
138
- const vendorJuxFiles = findJuxFiles(layoutsDir);
139
- console.log(`Found ${vendorJuxFiles.length} vendor layout(s)\n`);
140
-
141
- for (const file of vendorJuxFiles) {
142
- try {
143
- const relPath = path.relative(PATHS.juxLib, file);
144
-
145
- await compileJuxFile(file, {
146
- distDir: path.join(PATHS.frontendDist, 'lib'),
147
- projectRoot: PATHS.juxLib,
148
- isServe
149
- });
150
-
151
- console.log(` ✓ Compiled: ${relPath}`);
152
- } catch (err) {
153
- console.error(`Error compiling vendor layout ${file}:`, err.message);
154
- }
155
- }
148
+ // Bundle and get the generated filename
149
+ const bundleStartTime = performance.now();
150
+ const mainJsFilename = await bundleJuxFilesToRouter(PATHS.juxSource, PATHS.frontendDist, {
151
+ routePrefix: ''
152
+ });
153
+ const bundleTime = performance.now() - bundleStartTime;
154
+
155
+ // Generate routes for index.html
156
+ const routes = projectJuxFiles.map(juxFile => {
157
+ const relativePath = path.relative(PATHS.juxSource, juxFile);
158
+ const parsedPath = path.parse(relativePath);
159
+
160
+ const rawFunctionName = parsedPath.dir
161
+ ? `${parsedPath.dir.replace(/\//g, '_')}_${parsedPath.name}`
162
+ : parsedPath.name;
163
+
164
+ const functionName = rawFunctionName
165
+ .replace(/[-_]/g, ' ')
166
+ .split(' ')
167
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
168
+ .join('');
169
+
170
+ const routePath = '/' + (parsedPath.dir ? `${parsedPath.dir}/` : '') + parsedPath.name;
171
+
172
+ return {
173
+ path: routePath.replace(/\/+/g, '/'),
174
+ functionName
175
+ };
176
+ });
177
+
178
+ // ✅ Generate unified index.html
179
+ const indexStartTime = performance.now();
180
+ generateIndexHtml(PATHS.frontendDist, routes, mainJsFilename);
181
+ const indexTime = performance.now() - indexStartTime;
182
+
183
+ const totalBuildTime = performance.now() - buildStartTime;
184
+
185
+ console.log(`\n✅ Bundled ${projectJuxFiles.length} page(s) → ${PATHS.frontendDist}/${mainJsFilename}\n`);
186
+
187
+ // ✅ Build summary with timing breakdown
188
+ console.log(`📊 Build Summary:`);
189
+ console.log(` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
190
+ console.log(` Documentation: ${docsTime.toFixed(0)}ms`);
191
+ console.log(` Library copy: ${libTime.toFixed(0)}ms`);
192
+ console.log(` Presets copy: ${presetsTime.toFixed(0)}ms`);
193
+ console.log(` Assets copy: ${assetsTime.toFixed(0)}ms`);
194
+ console.log(` TypeScript: ${tsTime.toFixed(0)}ms`);
195
+ console.log(` Router bundle: ${bundleTime.toFixed(0)}ms`);
196
+ console.log(` Index generation: ${indexTime.toFixed(0)}ms`);
197
+ console.log(` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
198
+ console.log(` Total build time: ${totalBuildTime.toFixed(0)}ms\n`);
199
+
200
+ // Show usage
201
+ if (!isServe) {
202
+ console.log('📦 Serve from your backend:');
203
+ console.log(` Express: app.use(express.static('jux-dist'))`);
204
+ console.log(` Flask: app = Flask(__name__, static_folder='jux-dist')`);
205
+ console.log(` FastAPI: app.mount("/", StaticFiles(directory="jux-dist"), name="static")`);
206
+ console.log('');
207
+ console.log('📍 Available routes:');
208
+ routes.forEach(r => {
209
+ console.log(` ${r.path}`);
210
+ });
211
+ console.log('');
156
212
  }
157
213
 
158
- console.log(`\n✅ Built ${projectJuxFiles.length} file(s) → ${PATHS.frontendDist}\n`);
159
-
160
- // Show backend integration examples
161
- console.log('📦 Serve from your backend:');
162
- console.log(` Express: app.use(express.static('jux-dist'))`);
163
- console.log(` Flask: app = Flask(__name__, static_folder='jux-dist')`);
164
- console.log(` FastAPI: app.mount("/", StaticFiles(directory="jux-dist"), name="static")`);
165
- console.log(` Laravel: Route::view('/', 'jux-dist/index.html')`);
166
- console.log('');
167
-
168
214
  } catch (err) {
169
- console.error('❌ Build error:', err.message);
215
+ const failTime = performance.now() - buildStartTime;
216
+ console.error(`❌ Build error after ${failTime.toFixed(0)}ms:`, err.message);
170
217
  console.error(err.stack);
171
218
  process.exit(1);
172
219
  }
@@ -261,10 +308,12 @@ node_modules/
261
308
  console.log(' 4. Serve jux-dist/ from your backend\n');
262
309
 
263
310
  } else if (command === 'build') {
311
+ // ✅ Always builds router bundle
264
312
  await buildProject(false);
265
313
  console.log(`✅ Build complete: ${PATHS.frontendDist}`);
266
314
 
267
315
  } else if (command === 'serve') {
316
+ // ✅ Always serves router bundle
268
317
  await buildProject(true);
269
318
 
270
319
  const port = parseInt(process.argv[3]) || 3000;
@@ -275,17 +324,17 @@ node_modules/
275
324
  JUX CLI - A JavaScript UX authorship platform
276
325
 
277
326
  Usage:
278
- npx jux init Initialize a new JUX project
279
- npx jux build Compile .jux files from ./jux/ to ./jux-dist/
280
- npx jux serve [port] Start dev server with hot reload (default: 3000)
327
+ npx jux init Initialize a new JUX project
328
+ npx jux build Build router bundle to ./jux-dist/
329
+ npx jux serve [port] Start dev server with hot reload (default: 3000)
281
330
 
282
331
  Project Structure:
283
332
  my-project/
284
- ├── jux/ # Your .jux source files
285
- │ ├── index.jux # Entry point (uses 'juxscript' imports)
286
- │ └── pages/ # Additional pages
287
- ├── jux-dist/ # Build output (git-ignore this)
288
- ├── server/ # Your backend
333
+ ├── jux/ # Your .jux source files
334
+ │ ├── index.jux # Entry point
335
+ │ └── pages/ # Additional pages
336
+ ├── jux-dist/ # Build output (git-ignore this)
337
+ ├── server/ # Your backend
289
338
  └── package.json
290
339
 
291
340
  Import Style:
@@ -294,15 +343,15 @@ Import Style:
294
343
  import 'juxscript/presets/notion.js';
295
344
 
296
345
  Getting Started:
297
- 1. npx jux init # Create project structure
298
- 2. npm install # Install dependencies
299
- 3. npx jux build # Build to jux-dist/
346
+ 1. npx jux init # Create project structure
347
+ 2. npm install # Install dependencies
348
+ 3. npx jux serve # Dev server with hot reload
300
349
  4. Serve jux-dist/ from your backend
301
350
 
302
351
  Examples:
303
- npx jux build Build for production
304
- npx jux serve Start dev server
305
- npx jux serve 8080 Start on port 8080
352
+ npx jux build Build production bundle
353
+ npx jux serve Start dev server on port 3000
354
+ npx jux serve 8080 Start dev server on port 8080
306
355
  `);
307
356
  }
308
357
  })();