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,15 +1,14 @@
1
- import { getOrCreateContainer } from './helpers.js';
2
- import { State } from '../reactivity/state.js';
1
+ import { BaseComponent } from './base/BaseComponent.js';
2
+
3
+ // Event definitions
4
+ const TRIGGER_EVENTS = [] as const;
5
+ const CALLBACK_EVENTS = [] as const;
3
6
 
4
7
  export interface ProgressOptions {
5
8
  value?: number;
6
9
  max?: number;
7
- label?: string;
10
+ variant?: 'default' | 'success' | 'warning' | 'error';
8
11
  showPercentage?: boolean;
9
- variant?: 'default' | 'success' | 'warning' | 'error' | 'info';
10
- size?: 'sm' | 'md' | 'lg';
11
- striped?: boolean;
12
- animated?: boolean;
13
12
  style?: string;
14
13
  class?: string;
15
14
  }
@@ -17,233 +16,176 @@ export interface ProgressOptions {
17
16
  type ProgressState = {
18
17
  value: number;
19
18
  max: number;
20
- label: string;
21
- showPercentage: boolean;
22
19
  variant: string;
23
- size: string;
24
- striped: boolean;
25
- animated: boolean;
20
+ showPercentage: boolean;
26
21
  style: string;
27
22
  class: string;
28
23
  };
29
24
 
30
- export class Progress {
31
- state: ProgressState;
32
- container: HTMLElement | null = null;
33
- _id: string;
34
- id: string;
35
-
36
- // CRITICAL: Store bind/sync instructions for deferred wiring
37
- private _bindings: Array<{ event: string, handler: Function }> = [];
38
- private _syncBindings: Array<{
39
- property: string,
40
- stateObj: State<any>,
41
- toState?: Function,
42
- toComponent?: Function
43
- }> = [];
25
+ export class Progress extends BaseComponent<ProgressState> {
26
+ private _bar: HTMLElement | null = null;
27
+ private _label: HTMLElement | null = null;
44
28
 
45
29
  constructor(id: string, options: ProgressOptions = {}) {
46
- this._id = id;
47
- this.id = id;
48
-
49
- this.state = {
30
+ super(id, {
50
31
  value: options.value ?? 0,
51
32
  max: options.max ?? 100,
52
- label: options.label ?? '',
53
- showPercentage: options.showPercentage ?? false,
54
33
  variant: options.variant ?? 'default',
55
- size: options.size ?? 'md',
56
- striped: options.striped ?? false,
57
- animated: options.animated ?? false,
34
+ showPercentage: options.showPercentage ?? false,
58
35
  style: options.style ?? '',
59
36
  class: options.class ?? ''
60
- };
61
- }
62
-
63
- /* -------------------------
64
- * Fluent API
65
- * ------------------------- */
66
-
67
- value(value: number): this {
68
- this.state.value = value;
69
- this._updateProgress();
70
- return this;
71
- }
72
-
73
- max(value: number): this {
74
- this.state.max = value;
75
- this._updateProgress();
76
- return this;
77
- }
78
-
79
- label(value: string): this {
80
- this.state.label = value;
81
- return this;
82
- }
83
-
84
- showPercentage(value: boolean): this {
85
- this.state.showPercentage = value;
86
- return this;
87
- }
88
-
89
- variant(value: 'default' | 'success' | 'warning' | 'error' | 'info'): this {
90
- this.state.variant = value;
91
- return this;
37
+ });
92
38
  }
93
39
 
94
- size(value: 'sm' | 'md' | 'lg'): this {
95
- this.state.size = value;
96
- return this;
40
+ protected getTriggerEvents(): readonly string[] {
41
+ return TRIGGER_EVENTS;
97
42
  }
98
43
 
99
- striped(value: boolean): this {
100
- this.state.striped = value;
101
- return this;
44
+ protected getCallbackEvents(): readonly string[] {
45
+ return CALLBACK_EVENTS;
102
46
  }
103
47
 
104
- animated(value: boolean): this {
105
- this.state.animated = value;
106
- return this;
107
- }
48
+ /* ═════════════════════════════════════════════════════════════════
49
+ * FLUENT API
50
+ * ═════════════════════════════════════════════════════════════════ */
108
51
 
109
- style(value: string): this {
110
- this.state.style = value;
52
+ value(val: number): this {
53
+ this.state.value = Math.max(0, Math.min(val, this.state.max));
54
+ this._updateProgress();
111
55
  return this;
112
56
  }
113
57
 
114
- class(value: string): this {
115
- this.state.class = value;
58
+ max(val: number): this {
59
+ this.state.max = val;
60
+ this._updateProgress();
116
61
  return this;
117
62
  }
118
63
 
119
- bind(event: string, handler: Function): this {
120
- this._bindings.push({ event, handler });
64
+ variant(value: 'default' | 'success' | 'warning' | 'error'): this {
65
+ this.state.variant = value;
121
66
  return this;
122
67
  }
123
68
 
124
- sync(property: string, stateObj: State<any>, toState?: Function, toComponent?: Function): this {
125
- if (!stateObj || typeof stateObj.subscribe !== 'function') {
126
- throw new Error(`Progress.sync: Expected a State object for property "${property}"`);
127
- }
128
- this._syncBindings.push({ property, stateObj, toState, toComponent });
69
+ showPercentage(value: boolean): this {
70
+ this.state.showPercentage = value;
129
71
  return this;
130
72
  }
131
73
 
132
- getPercentage(): number {
133
- return Math.round((this.state.value / this.state.max) * 100);
134
- }
135
-
136
74
  private _updateProgress(): void {
137
- const bar = document.getElementById(`${this._id}-bar`);
138
- const percentageEl = document.getElementById(`${this._id}-percentage`);
139
-
140
- if (bar) {
141
- const percentage = this.getPercentage();
142
- bar.style.width = `${percentage}%`;
143
-
144
- if (percentageEl) {
145
- percentageEl.textContent = `${percentage}%`;
75
+ if (this._bar) {
76
+ const percentage = (this.state.value / this.state.max) * 100;
77
+ this._bar.style.width = `${percentage}%`;
78
+ if (this._label) {
79
+ this._label.textContent = `${Math.round(percentage)}%`;
146
80
  }
147
81
  }
148
82
  }
149
83
 
150
- /* -------------------------
151
- * Render
152
- * ------------------------- */
84
+ /* ═════════════════════════════════════════════════════════════════
85
+ * RENDER
86
+ * ═════════════════════════════════════════════════════════════════ */
153
87
 
154
88
  render(targetId?: string): this {
155
- // === 1. SETUP: Get or create container ===
156
- let container: HTMLElement;
157
- if (targetId) {
158
- const target = document.querySelector(targetId);
159
- if (!target || !(target instanceof HTMLElement)) {
160
- throw new Error(`Progress: Target "${targetId}" not found`);
161
- }
162
- container = target;
163
- } else {
164
- container = getOrCreateContainer(this._id);
165
- }
166
- this.container = container;
89
+ const container = this._setupContainer(targetId);
167
90
 
168
- // === 2. PREPARE: Destructure state ===
169
- const { value, max, variant, showPercentage, label, style, class: className } = this.state;
170
- const percentage = Math.min(100, Math.max(0, (value / max) * 100));
91
+ const { value, max, variant, showPercentage, style, class: className } = this.state;
171
92
 
172
- // === 3. BUILD: Create DOM elements ===
173
93
  const wrapper = document.createElement('div');
174
94
  wrapper.className = 'jux-progress';
175
95
  wrapper.id = this._id;
176
96
  if (className) wrapper.className += ` ${className}`;
177
97
  if (style) wrapper.setAttribute('style', style);
178
98
 
179
- if (showPercentage || label) {
180
- const labelEl = document.createElement('div');
181
- labelEl.className = 'jux-progress-label';
182
- labelEl.textContent = label || `${Math.round(percentage)}%`;
183
- wrapper.appendChild(labelEl);
184
- }
185
-
186
99
  const track = document.createElement('div');
187
100
  track.className = 'jux-progress-track';
188
101
 
189
102
  const bar = document.createElement('div');
190
103
  bar.className = `jux-progress-bar jux-progress-bar-${variant}`;
191
- bar.id = `${this._id}-bar`;
104
+ const percentage = (value / max) * 100;
192
105
  bar.style.width = `${percentage}%`;
106
+ this._bar = bar;
107
+
108
+ if (showPercentage) {
109
+ const label = document.createElement('span');
110
+ label.className = 'jux-progress-label';
111
+ label.textContent = `${Math.round(percentage)}%`;
112
+ bar.appendChild(label);
113
+ this._label = label;
114
+ }
193
115
 
194
116
  track.appendChild(bar);
195
117
  wrapper.appendChild(track);
196
118
 
197
- // === 4. WIRE: Attach event listeners and sync bindings ===
198
-
199
- // Wire custom bindings from .bind() calls
200
- this._bindings.forEach(({ event, handler }) => {
201
- wrapper.addEventListener(event, handler as EventListener);
202
- });
119
+ this._wireStandardEvents(wrapper);
203
120
 
204
- // Wire sync bindings from .sync() calls
121
+ // Wire sync for value
205
122
  this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
206
123
  if (property === 'value') {
207
- const transformToComponent = toComponent || ((v: any) => Number(v));
208
-
124
+ const transform = toComponent || ((v: any) => Number(v));
209
125
  stateObj.subscribe((val: any) => {
210
- const transformed = transformToComponent(val);
211
- this.state.value = transformed;
212
- const newPercentage = Math.min(100, Math.max(0, (transformed / this.state.max) * 100));
213
- bar.style.width = `${newPercentage}%`;
214
-
215
- if (showPercentage && !label) {
216
- const labelEl = wrapper.querySelector('.jux-progress-label');
217
- if (labelEl) {
218
- labelEl.textContent = `${Math.round(newPercentage)}%`;
219
- }
220
- }
221
- });
222
- }
223
- else if (property === 'label') {
224
- const transformToComponent = toComponent || ((v: any) => String(v));
225
-
226
- stateObj.subscribe((val: any) => {
227
- const transformed = transformToComponent(val);
228
- const labelEl = wrapper.querySelector('.jux-progress-label');
229
- if (labelEl) {
230
- labelEl.textContent = transformed;
231
- }
232
- this.state.label = transformed;
126
+ this.value(transform(val));
233
127
  });
234
128
  }
235
129
  });
236
130
 
237
- // === 5. RENDER: Append to DOM and finalize ===
238
131
  container.appendChild(wrapper);
132
+ this._injectProgressStyles();
133
+
239
134
  return this;
240
135
  }
241
136
 
242
- renderTo(juxComponent: any): this {
243
- if (!juxComponent?._id) {
244
- throw new Error('Progress.renderTo: Invalid component');
245
- }
246
- return this.render(`#${juxComponent._id}`);
137
+ private _injectProgressStyles(): void {
138
+ const styleId = 'jux-progress-styles';
139
+ if (document.getElementById(styleId)) return;
140
+
141
+ const style = document.createElement('style');
142
+ style.id = styleId;
143
+ style.textContent = `
144
+ .jux-progress {
145
+ width: 100%;
146
+ margin-bottom: 1rem;
147
+ }
148
+
149
+ .jux-progress-track {
150
+ width: 100%;
151
+ height: 1.5rem;
152
+ background-color: #e5e7eb;
153
+ border-radius: 0.5rem;
154
+ overflow: hidden;
155
+ }
156
+
157
+ .jux-progress-bar {
158
+ height: 100%;
159
+ display: flex;
160
+ align-items: center;
161
+ justify-content: center;
162
+ color: white;
163
+ font-size: 0.75rem;
164
+ font-weight: 600;
165
+ transition: width 0.3s ease;
166
+ }
167
+
168
+ .jux-progress-bar-default {
169
+ background-color: #3b82f6;
170
+ }
171
+
172
+ .jux-progress-bar-success {
173
+ background-color: #10b981;
174
+ }
175
+
176
+ .jux-progress-bar-warning {
177
+ background-color: #f59e0b;
178
+ }
179
+
180
+ .jux-progress-bar-error {
181
+ background-color: #ef4444;
182
+ }
183
+
184
+ .jux-progress-label {
185
+ padding: 0 0.5rem;
186
+ }
187
+ `;
188
+ document.head.appendChild(style);
247
189
  }
248
190
  }
249
191