juxscript 1.0.59 → 1.0.61

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.
@@ -69,11 +69,25 @@ async function serve(httpPort = 3000, wsPort = 3001, distDir = './.jux-dist') {
69
69
  next();
70
70
  });
71
71
 
72
+ // ✅ ADD: Explicit MIME type for JavaScript files
73
+ app.use((req, res, next) => {
74
+ if (req.path.endsWith('.js')) {
75
+ res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
76
+ }
77
+ next();
78
+ });
79
+
72
80
  // Serve static files
73
81
  app.use(express.static(absoluteDistDir));
74
82
 
75
- // SPA fallback
76
- app.get('*', (req, res) => {
83
+ // ✅ FIX: Only apply SPA fallback to routes, not static files
84
+ app.use((req, res, next) => {
85
+ // Skip SPA fallback for file extensions (static assets)
86
+ if (/\.[a-zA-Z0-9]+$/.test(req.path)) {
87
+ return res.status(404).send('File not found');
88
+ }
89
+
90
+ // SPA fallback for routes only
77
91
  if (req.accepts('html')) {
78
92
  const indexPath = path.join(absoluteDistDir, 'index.html');
79
93
  if (fs.existsSync(indexPath)) {
@@ -0,0 +1,46 @@
1
+ import esbuild from 'esbuild';
2
+
3
+ /**
4
+ * TypeScript Shim - Strips type annotations using esbuild
5
+ * This is rock-solid and handles ALL TypeScript syntax correctly
6
+ */
7
+
8
+ /**
9
+ * Strip TypeScript type annotations from code using esbuild
10
+ *
11
+ * @param {string} code - TypeScript source code
12
+ * @returns {string} - JavaScript code with types removed
13
+ */
14
+ export function stripTypes(code) {
15
+ try {
16
+ // ✅ Use esbuild to transform TypeScript → JavaScript
17
+ const result = esbuild.transformSync(code, {
18
+ loader: 'ts',
19
+ format: 'esm',
20
+ target: 'es2020'
21
+ });
22
+
23
+ return result.code;
24
+ } catch (err) {
25
+ console.error('❌ Failed to strip TypeScript:', err.message);
26
+ // Return original code if transformation fails
27
+ return code;
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Check if a file is TypeScript based on extension
33
+ */
34
+ export function isTypeScript(filePath) {
35
+ return filePath.endsWith('.ts') || filePath.endsWith('.tsx');
36
+ }
37
+
38
+ /**
39
+ * Load and parse a file, automatically stripping types if it's TypeScript
40
+ */
41
+ export function loadAndStripTypes(filePath, fileContent) {
42
+ if (isTypeScript(filePath)) {
43
+ return stripTypes(fileContent);
44
+ }
45
+ return fileContent;
46
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.0.59",
3
+ "version": "1.0.61",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "lib/jux.js",
@@ -57,6 +57,9 @@
57
57
  "find-jux-classes": "node scripts/find-jux-classes.js"
58
58
  },
59
59
  "dependencies": {
60
+ "acorn": "^8.15.0",
61
+ "axios": "^1.6.0",
62
+ "chart.js": "^4.5.1",
60
63
  "chokidar": "^3.5.3",
61
64
  "esbuild": "^0.19.0",
62
65
  "express": "^4.18.2",
@@ -67,6 +70,7 @@
67
70
  "@types/express": "^4.17.17",
68
71
  "@types/node": "^20.0.0",
69
72
  "@types/ws": "^8.5.5",
73
+ "acorn-walk": "^8.3.4",
70
74
  "jsdom": "^27.4.0",
71
75
  "typescript": "^5.0.0"
72
76
  }
@@ -21,9 +21,9 @@ jux.hero('all-hero', {
21
21
  }).render("#appmain-content");
22
22
  jux.divider().render("#appmain-content");
23
23
 
24
- jux.heading('chart-heading').level(3).text('jux.chart').render("#appmain-content");
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
25
  jux.element('all-element')
26
- .text('Need Charts!')
26
+ .text('Need Elements! shadcn and tailwind analysis. Mobiles. ios/android - .text')
27
27
  .render("#appmain-content");
28
28
  jux.divider().render("#appmain-content");
29
29
 
@@ -1489,4 +1489,124 @@ p {
1489
1489
  .jux-radio-options {
1490
1490
  flex-direction: column;
1491
1491
  }
1492
+ }
1493
+
1494
+ /* ============================================
1495
+ GRID COMPONENT
1496
+ ============================================ */
1497
+ .jux-grid {
1498
+ display: grid;
1499
+ position: relative;
1500
+ }
1501
+
1502
+ .jux-grid-cell {
1503
+ position: relative;
1504
+ overflow: auto;
1505
+ min-width: 0; /* Prevent grid blowout */
1506
+ min-height: 0;
1507
+ }
1508
+
1509
+ /* ============================================
1510
+ GRID GRIDDER MODE (Blueprint Visualization)
1511
+ ============================================ */
1512
+ .jux-grid-gridder {
1513
+ /* Blueprint-style background */
1514
+ background-color: #0a1929;
1515
+ background-image:
1516
+ linear-gradient(rgba(59, 130, 246, 0.1) 1px, transparent 1px),
1517
+ linear-gradient(90deg, rgba(59, 130, 246, 0.1) 1px, transparent 1px);
1518
+ background-size: 20px 20px;
1519
+ padding: 2px;
1520
+ border: 2px solid #3b82f6;
1521
+ box-shadow:
1522
+ 0 0 0 1px rgba(59, 130, 246, 0.2),
1523
+ inset 0 0 20px rgba(59, 130, 246, 0.1);
1524
+ }
1525
+
1526
+ .jux-grid-gridder .jux-grid-cell {
1527
+ /* Cell styling in gridder mode */
1528
+ background: rgba(15, 23, 42, 0.8);
1529
+ border: 1px solid rgba(59, 130, 246, 0.4);
1530
+ box-shadow: inset 0 0 10px rgba(59, 130, 246, 0.05);
1531
+ min-height: 80px; /* Ensure cells are visible */
1532
+ display: flex;
1533
+ align-items: center;
1534
+ justify-content: center;
1535
+ position: relative;
1536
+ transition: all 0.2s ease;
1537
+ }
1538
+
1539
+ .jux-grid-gridder .jux-grid-cell:hover {
1540
+ background: rgba(30, 41, 59, 0.9);
1541
+ border-color: rgba(59, 130, 246, 0.8);
1542
+ box-shadow:
1543
+ inset 0 0 15px rgba(59, 130, 246, 0.15),
1544
+ 0 0 10px rgba(59, 130, 246, 0.3);
1545
+ }
1546
+
1547
+ /* Coordinate label (top-left corner) */
1548
+ .jux-grid-gridder .jux-grid-cell::before {
1549
+ content: attr(data-row) ',' attr(data-col);
1550
+ position: absolute;
1551
+ top: 4px;
1552
+ left: 4px;
1553
+ font-size: 10px;
1554
+ font-family: 'SF Mono', Monaco, 'Courier New', monospace;
1555
+ font-weight: 600;
1556
+ color: rgba(59, 130, 246, 0.8);
1557
+ background: rgba(15, 23, 42, 0.95);
1558
+ padding: 2px 6px;
1559
+ border-radius: 3px;
1560
+ border: 1px solid rgba(59, 130, 246, 0.3);
1561
+ letter-spacing: 0.5px;
1562
+ z-index: 10;
1563
+ }
1564
+
1565
+ /* ID label (bottom-right corner) */
1566
+ .jux-grid-gridder .jux-grid-cell::after {
1567
+ content: '#' attr(id);
1568
+ position: absolute;
1569
+ bottom: 4px;
1570
+ right: 4px;
1571
+ font-size: 9px;
1572
+ font-family: 'SF Mono', Monaco, 'Courier New', monospace;
1573
+ color: rgba(148, 163, 184, 0.6);
1574
+ background: rgba(15, 23, 42, 0.8);
1575
+ padding: 2px 5px;
1576
+ border-radius: 2px;
1577
+ border: 1px solid rgba(71, 85, 105, 0.3);
1578
+ max-width: calc(100% - 12px);
1579
+ overflow: hidden;
1580
+ text-overflow: ellipsis;
1581
+ white-space: nowrap;
1582
+ }
1583
+
1584
+ /* Grid lines (column separators) */
1585
+ .jux-grid-gridder .jux-grid-cell:not(:nth-child(1))::before {
1586
+ box-shadow: 0 0 5px rgba(59, 130, 246, 0.4);
1587
+ }
1588
+
1589
+ /* Remove default debug styles when gridder is active */
1590
+ .jux-grid-gridder.jux-grid-debug .jux-grid-cell {
1591
+ /* Gridder overrides debug mode */
1592
+ border-color: rgba(59, 130, 246, 0.4);
1593
+ background: rgba(15, 23, 42, 0.8);
1594
+ }
1595
+
1596
+ /* ============================================
1597
+ GRID DEBUG MODE (Legacy - simpler version)
1598
+ ============================================ */
1599
+ .jux-grid-debug .jux-grid-cell {
1600
+ border: 1px dashed var(--color-border);
1601
+ background: var(--color-surface-base);
1602
+ }
1603
+
1604
+ .jux-grid-debug .jux-grid-cell::before {
1605
+ content: attr(data-row) '-' attr(data-col);
1606
+ position: absolute;
1607
+ top: 2px;
1608
+ left: 2px;
1609
+ font-size: 10px;
1610
+ color: var(--color-text-tertiary);
1611
+ opacity: 0.5;
1492
1612
  }
@@ -1,315 +0,0 @@
1
- import { BaseChart, BaseChartState, ChartDataPoint } from './lib/BaseChart.js';
2
-
3
- export interface AreaChartOptions {
4
- data?: ChartDataPoint[];
5
- title?: string;
6
- subtitle?: string;
7
- xAxisLabel?: string;
8
- yAxisLabel?: string;
9
- showTicksX?: boolean;
10
- showTicksY?: boolean;
11
- showScaleX?: boolean;
12
- showScaleY?: boolean;
13
- scaleXUnit?: string;
14
- scaleYUnit?: string;
15
- showLegend?: boolean;
16
- legendOrientation?: 'horizontal' | 'vertical';
17
- showDataTable?: boolean;
18
- showDataLabels?: boolean;
19
- animate?: boolean;
20
- animationDuration?: number;
21
- width?: number;
22
- height?: number;
23
- colors?: string[];
24
- class?: string;
25
- style?: string;
26
- theme?: 'google' | 'seriesa' | 'hr' | 'figma' | 'notion' | 'chalk' | 'mint';
27
- styleMode?: 'default' | 'gradient' | 'outline' | 'dashed' | 'glow' | 'glass';
28
- borderRadius?: number;
29
- }
30
-
31
- interface AreaChartState extends BaseChartState {
32
- data: ChartDataPoint[];
33
- }
34
-
35
- export class AreaChart extends BaseChart<AreaChartState> {
36
- constructor(id: string, options: AreaChartOptions = {}) {
37
- const defaultColors = ['#3b82f6', '#ef4444', '#10b981', '#f59e0b', '#8b5cf6'];
38
- const randomColor = defaultColors[Math.floor(Math.random() * defaultColors.length)];
39
-
40
- super(id, {
41
- data: options.data ?? [],
42
- title: options.title ?? '',
43
- subtitle: options.subtitle ?? '',
44
- xAxisLabel: options.xAxisLabel ?? '',
45
- yAxisLabel: options.yAxisLabel ?? '',
46
- showTicksX: options.showTicksX ?? true,
47
- showTicksY: options.showTicksY ?? true,
48
- showScaleX: options.showScaleX ?? true,
49
- showScaleY: options.showScaleY ?? true,
50
- scaleXUnit: options.scaleXUnit ?? '',
51
- scaleYUnit: options.scaleYUnit ?? '',
52
- showLegend: options.showLegend ?? false,
53
- legendOrientation: options.legendOrientation ?? 'horizontal',
54
- showDataTable: options.showDataTable ?? false,
55
- showDataLabels: options.showDataLabels ?? true,
56
- animate: options.animate ?? true,
57
- animationDuration: options.animationDuration ?? 800,
58
- width: options.width ?? 600,
59
- height: options.height ?? 400,
60
- colors: options.colors ?? [randomColor],
61
- class: options.class ?? '',
62
- style: options.style ?? '',
63
- theme: options.theme,
64
- styleMode: options.styleMode ?? 'default',
65
- borderRadius: options.borderRadius ?? 4
66
- });
67
- }
68
-
69
- protected _getChartClassName(): string {
70
- return 'jux-areachart';
71
- }
72
-
73
- protected _createSVG(): SVGSVGElement {
74
- const { data, width, height, colors, animate, animationDuration } = this.state;
75
-
76
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
77
- svg.setAttribute('width', width.toString());
78
- svg.setAttribute('height', height.toString());
79
- svg.setAttribute('class', 'jux-areachart-svg');
80
-
81
- if (!data.length) return svg;
82
-
83
- if (animate) this._addAnimationStyles(svg);
84
-
85
- const padding = { top: 40, right: 40, bottom: 60, left: 60 };
86
- const chartWidth = width - padding.left - padding.right;
87
- const chartHeight = height - padding.top - padding.bottom;
88
- const maxValue = Math.max(...data.map(d => d.value));
89
-
90
- this._renderAreaChart(svg, padding, chartWidth, chartHeight, maxValue);
91
-
92
- return svg;
93
- }
94
-
95
- protected _getBaseStyles(): string {
96
- return `
97
- .jux-areachart {
98
- font-family: var(--chart-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
99
- display: inline-block;
100
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
101
- border-radius: 12px;
102
- background: white;
103
- padding: 24px;
104
- }
105
- .jux-areachart-title {
106
- margin: 0 0 0.5rem 0;
107
- font-size: 1.25rem;
108
- font-weight: 600;
109
- }
110
- .jux-areachart-subtitle {
111
- margin: 0 0 1rem 0;
112
- font-size: 0.875rem;
113
- color: #6b7280;
114
- }
115
- .jux-areachart-legend {
116
- display: flex;
117
- flex-wrap: wrap;
118
- gap: 1rem;
119
- margin-top: 1rem;
120
- justify-content: center;
121
- }
122
- .jux-areachart-legend-item {
123
- display: flex;
124
- align-items: center;
125
- gap: 0.5rem;
126
- }
127
- .jux-areachart-legend-swatch {
128
- width: 12px;
129
- height: 12px;
130
- border-radius: 2px;
131
- }
132
- .jux-areachart-legend-label {
133
- font-size: 0.875rem;
134
- color: #374151;
135
- }
136
- .jux-areachart-table {
137
- width: 100%;
138
- margin-top: 1rem;
139
- border-collapse: collapse;
140
- font-size: 0.875rem;
141
- }
142
- .jux-areachart-table thead th {
143
- text-align: center;
144
- padding: 0.5rem;
145
- border-bottom: 2px solid #e5e7eb;
146
- font-weight: 600;
147
- }
148
- .jux-areachart-table tbody td {
149
- padding: 0.5rem;
150
- border-bottom: 1px solid #f3f4f6;
151
- text-align: center;
152
- }
153
- .jux-areachart-svg {
154
- font-family: inherit;
155
- }
156
- `;
157
- }
158
-
159
- private _addAnimationStyles(svg: SVGSVGElement): void {
160
- const { animationDuration } = this.state;
161
- const animationId = `area-grow-${this._id}`;
162
- const style = document.createElementNS('http://www.w3.org/2000/svg', 'style');
163
-
164
- style.textContent = `
165
- @keyframes ${animationId} {
166
- from { opacity: 0; transform: scaleY(0); }
167
- to { opacity: 1; transform: scaleY(1); }
168
- }
169
- .jux-area-animated {
170
- transform-origin: bottom;
171
- animation: ${animationId} ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
172
- }
173
- `;
174
- svg.appendChild(style);
175
- }
176
-
177
- private _renderAreaChart(svg: SVGSVGElement, padding: any, chartWidth: number, chartHeight: number, maxValue: number): void {
178
- const { data, width, height, colors, showDataLabels, animate, xAxisLabel, yAxisLabel, showTicksX, showTicksY, showScaleX, showScaleY, scaleYUnit } = this.state;
179
-
180
- const yScale = chartHeight / maxValue;
181
- const xStep = chartWidth / (data.length - 1 || 1);
182
- const color = colors[0];
183
-
184
- // Axes
185
- if (showScaleY) {
186
- this._renderAxis(svg, padding.left, padding.top, padding.left, height - padding.bottom);
187
- if (yAxisLabel && showTicksY) {
188
- this._renderAxisLabel(svg, yAxisLabel, 20, padding.top + chartHeight / 2, -90);
189
- }
190
- if (showTicksY) {
191
- this._renderYTicks(svg, maxValue, yScale, padding, width, height, scaleYUnit, chartHeight);
192
- }
193
- }
194
-
195
- if (showScaleX) {
196
- this._renderAxis(svg, padding.left, height - padding.bottom, width - padding.right, height - padding.bottom);
197
- if (xAxisLabel && showTicksX) {
198
- this._renderAxisLabel(svg, xAxisLabel, padding.left + chartWidth / 2, height - 15, 0);
199
- }
200
- }
201
-
202
- // Build area path
203
- let pathData = `M ${padding.left} ${height - padding.bottom}`;
204
- data.forEach((point, i) => {
205
- const x = padding.left + (i * xStep);
206
- const y = height - padding.bottom - (point.value * yScale);
207
- pathData += ` L ${x} ${y}`;
208
- });
209
- pathData += ` L ${padding.left + ((data.length - 1) * xStep)} ${height - padding.bottom} Z`;
210
-
211
- const areaPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
212
- areaPath.setAttribute('d', pathData);
213
- areaPath.setAttribute('fill', color);
214
- areaPath.setAttribute('fill-opacity', '0.3');
215
- if (animate) areaPath.classList.add('jux-area-animated');
216
- svg.appendChild(areaPath);
217
-
218
- // Line path
219
- let lineData = '';
220
- data.forEach((point, i) => {
221
- const x = padding.left + (i * xStep);
222
- const y = height - padding.bottom - (point.value * yScale);
223
- lineData += (i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`);
224
- });
225
-
226
- const linePath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
227
- linePath.setAttribute('d', lineData);
228
- linePath.setAttribute('stroke', color);
229
- linePath.setAttribute('stroke-width', '3');
230
- linePath.setAttribute('fill', 'none');
231
- svg.appendChild(linePath);
232
-
233
- // Data points
234
- data.forEach((point, i) => {
235
- const x = padding.left + (i * xStep);
236
- const y = height - padding.bottom - (point.value * yScale);
237
-
238
- const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
239
- circle.setAttribute('cx', x.toString());
240
- circle.setAttribute('cy', y.toString());
241
- circle.setAttribute('r', '4');
242
- circle.setAttribute('fill', color);
243
- circle.setAttribute('stroke', 'white');
244
- circle.setAttribute('stroke-width', '2');
245
- svg.appendChild(circle);
246
-
247
- if (showDataLabels) {
248
- const label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
249
- label.setAttribute('x', x.toString());
250
- label.setAttribute('y', (y - 10).toString());
251
- label.setAttribute('text-anchor', 'middle');
252
- label.setAttribute('fill', '#374151');
253
- label.setAttribute('font-size', '11');
254
- label.setAttribute('font-weight', '600');
255
- label.textContent = point.value.toString();
256
- svg.appendChild(label);
257
- }
258
- });
259
- }
260
-
261
- private _renderAxis(svg: SVGSVGElement, x1: number, y1: number, x2: number, y2: number): void {
262
- const axis = document.createElementNS('http://www.w3.org/2000/svg', 'line');
263
- axis.setAttribute('x1', x1.toString());
264
- axis.setAttribute('y1', y1.toString());
265
- axis.setAttribute('x2', x2.toString());
266
- axis.setAttribute('y2', y2.toString());
267
- axis.setAttribute('stroke', '#9ca3af');
268
- axis.setAttribute('stroke-width', '2');
269
- svg.appendChild(axis);
270
- }
271
-
272
- private _renderAxisLabel(svg: SVGSVGElement, text: string, x: number, y: number, rotate: number): void {
273
- const label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
274
- label.setAttribute('x', x.toString());
275
- label.setAttribute('y', y.toString());
276
- label.setAttribute('text-anchor', 'middle');
277
- if (rotate !== 0) label.setAttribute('transform', `rotate(${rotate}, ${x}, ${y})`);
278
- label.setAttribute('fill', '#6b7280');
279
- label.setAttribute('font-size', '12');
280
- label.setAttribute('font-weight', '500');
281
- label.textContent = text;
282
- svg.appendChild(label);
283
- }
284
-
285
- private _renderYTicks(svg: SVGSVGElement, maxValue: number, yScale: number, padding: any, width: number, height: number, unit: string, chartHeight: number): void {
286
- const numTicks = 5;
287
- for (let i = 0; i <= numTicks; i++) {
288
- const value = (maxValue / numTicks) * i;
289
- const y = height - padding.bottom - (value * yScale);
290
-
291
- const gridLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
292
- gridLine.setAttribute('x1', padding.left.toString());
293
- gridLine.setAttribute('y1', y.toString());
294
- gridLine.setAttribute('x2', (width - padding.right).toString());
295
- gridLine.setAttribute('y2', y.toString());
296
- gridLine.setAttribute('stroke', '#e5e7eb');
297
- gridLine.setAttribute('stroke-width', '1');
298
- gridLine.setAttribute('stroke-dasharray', '4,4');
299
- svg.appendChild(gridLine);
300
-
301
- const tickLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
302
- tickLabel.setAttribute('x', (padding.left - 10).toString());
303
- tickLabel.setAttribute('y', (y + 4).toString());
304
- tickLabel.setAttribute('text-anchor', 'end');
305
- tickLabel.setAttribute('fill', '#6b7280');
306
- tickLabel.setAttribute('font-size', '11');
307
- tickLabel.textContent = Math.round(value).toString() + (unit || '');
308
- svg.appendChild(tickLabel);
309
- }
310
- }
311
- }
312
-
313
- export function areachart(id: string, options: AreaChartOptions = {}): AreaChart {
314
- return new AreaChart(id, options);
315
- }