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
@@ -1,273 +1,191 @@
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
- /**
5
- * Progress component options
6
- */
7
7
  export interface ProgressOptions {
8
8
  value?: number;
9
9
  max?: number;
10
- label?: string;
10
+ variant?: 'default' | 'success' | 'warning' | 'error';
11
11
  showPercentage?: boolean;
12
- variant?: 'default' | 'success' | 'warning' | 'error' | 'info';
13
- size?: 'sm' | 'md' | 'lg';
14
- striped?: boolean;
15
- animated?: boolean;
16
12
  style?: string;
17
13
  class?: string;
18
14
  }
19
15
 
20
- /**
21
- * Progress component state
22
- */
23
16
  type ProgressState = {
24
17
  value: number;
25
18
  max: number;
26
- label: string;
27
- showPercentage: boolean;
28
19
  variant: string;
29
- size: string;
30
- striped: boolean;
31
- animated: boolean;
20
+ showPercentage: boolean;
32
21
  style: string;
33
22
  class: string;
34
23
  };
35
24
 
36
- /**
37
- * Progress component - Progress bar for loading/completion
38
- *
39
- * Usage:
40
- * jux.progress('upload', {
41
- * value: 45,
42
- * max: 100,
43
- * label: 'Uploading...',
44
- * showPercentage: true,
45
- * animated: true
46
- * }).render('#app');
47
- *
48
- * // Update progress
49
- * const prog = jux.progress('upload').render('#app');
50
- * prog.value(75);
51
- */
52
- export class Progress {
53
- state: ProgressState;
54
- container: HTMLElement | null = null;
55
- _id: string;
56
- id: string;
57
- private _boundState?: State<number>;
25
+ export class Progress extends BaseComponent<ProgressState> {
26
+ private _bar: HTMLElement | null = null;
27
+ private _label: HTMLElement | null = null;
58
28
 
59
29
  constructor(id: string, options: ProgressOptions = {}) {
60
- this._id = id;
61
- this.id = id;
62
-
63
- this.state = {
30
+ super(id, {
64
31
  value: options.value ?? 0,
65
32
  max: options.max ?? 100,
66
- label: options.label ?? '',
67
- showPercentage: options.showPercentage ?? false,
68
33
  variant: options.variant ?? 'default',
69
- size: options.size ?? 'md',
70
- striped: options.striped ?? false,
71
- animated: options.animated ?? false,
34
+ showPercentage: options.showPercentage ?? false,
72
35
  style: options.style ?? '',
73
36
  class: options.class ?? ''
74
- };
75
- }
76
-
77
- /* -------------------------
78
- * Fluent API
79
- * ------------------------- */
80
-
81
- value(value: number): this {
82
- this.state.value = Math.max(0, Math.min(value, this.state.max));
83
- this._updateElement();
84
- return this;
85
- }
86
-
87
- max(value: number): this {
88
- this.state.max = value;
89
- return this;
90
- }
91
-
92
- label(value: string): this {
93
- this.state.label = value;
94
- this._updateElement();
95
- return this;
37
+ });
96
38
  }
97
39
 
98
- showPercentage(value: boolean): this {
99
- this.state.showPercentage = value;
100
- this._updateElement();
101
- return this;
40
+ protected getTriggerEvents(): readonly string[] {
41
+ return TRIGGER_EVENTS;
102
42
  }
103
43
 
104
- variant(value: 'default' | 'success' | 'warning' | 'error' | 'info'): this {
105
- this.state.variant = value;
106
- this._updateElement();
107
- return this;
44
+ protected getCallbackEvents(): readonly string[] {
45
+ return CALLBACK_EVENTS;
108
46
  }
109
47
 
110
- size(value: 'sm' | 'md' | 'lg'): this {
111
- this.state.size = value;
112
- return this;
113
- }
48
+ /* ═════════════════════════════════════════════════════════════════
49
+ * FLUENT API
50
+ * ═════════════════════════════════════════════════════════════════ */
114
51
 
115
- striped(value: boolean): this {
116
- this.state.striped = value;
117
- this._updateElement();
52
+ value(val: number): this {
53
+ this.state.value = Math.max(0, Math.min(val, this.state.max));
54
+ this._updateProgress();
118
55
  return this;
119
56
  }
120
57
 
121
- animated(value: boolean): this {
122
- this.state.animated = value;
123
- this._updateElement();
58
+ max(val: number): this {
59
+ this.state.max = val;
60
+ this._updateProgress();
124
61
  return this;
125
62
  }
126
63
 
127
- style(value: string): this {
128
- this.state.style = value;
129
- return this;
130
- }
131
-
132
- class(value: string): this {
133
- this.state.class = value;
64
+ variant(value: 'default' | 'success' | 'warning' | 'error'): this {
65
+ this.state.variant = value;
134
66
  return this;
135
67
  }
136
68
 
137
- /**
138
- * Two-way binding to state
139
- */
140
- bind(stateObj: State<number>): this {
141
- this._boundState = stateObj;
142
-
143
- stateObj.subscribe((val) => {
144
- this.value(val);
145
- });
146
-
69
+ showPercentage(value: boolean): this {
70
+ this.state.showPercentage = value;
147
71
  return this;
148
72
  }
149
73
 
150
- /* -------------------------
151
- * Helpers
152
- * ------------------------- */
153
-
154
- private _updateElement(): void {
155
- const wrapper = document.getElementById(this._id);
156
- const bar = document.getElementById(`${this._id}-bar`);
157
- const labelEl = document.getElementById(`${this._id}-label`);
158
-
159
- // If element has a value attribute set externally (e.g., by bindValue), sync state
160
- if (wrapper && wrapper.hasAttribute('data-value')) {
161
- const externalValue = parseFloat(wrapper.getAttribute('data-value') || '0');
162
- this.state.value = externalValue;
163
- }
164
-
165
- if (bar) {
74
+ private _updateProgress(): void {
75
+ if (this._bar) {
166
76
  const percentage = (this.state.value / this.state.max) * 100;
167
- bar.style.width = `${percentage}%`;
168
- bar.setAttribute('aria-valuenow', this.state.value.toString());
169
- bar.className = `jux-progress-bar jux-progress-bar-${this.state.variant}`;
170
-
171
- if (this.state.striped) {
172
- bar.classList.add('jux-progress-bar-striped');
173
- }
174
- if (this.state.animated) {
175
- bar.classList.add('jux-progress-bar-animated');
77
+ this._bar.style.width = `${percentage}%`;
78
+ if (this._label) {
79
+ this._label.textContent = `${Math.round(percentage)}%`;
176
80
  }
177
81
  }
178
-
179
- if (labelEl) {
180
- const percentage = Math.round((this.state.value / this.state.max) * 100);
181
- const text = this.state.showPercentage
182
- ? `${this.state.label} ${percentage}%`.trim()
183
- : this.state.label;
184
- labelEl.textContent = text;
185
- }
186
- }
187
-
188
- getPercentage(): number {
189
- return Math.round((this.state.value / this.state.max) * 100);
190
82
  }
191
83
 
192
- /* -------------------------
193
- * Render
194
- * ------------------------- */
84
+ /* ═════════════════════════════════════════════════════════════════
85
+ * RENDER
86
+ * ═════════════════════════════════════════════════════════════════ */
195
87
 
196
88
  render(targetId?: string): this {
197
- let container: HTMLElement;
89
+ const container = this._setupContainer(targetId);
198
90
 
199
- if (targetId) {
200
- const target = document.querySelector(targetId);
201
- if (!target || !(target instanceof HTMLElement)) {
202
- throw new Error(`Progress: Target element "${targetId}" not found`);
203
- }
204
- container = target;
205
- } else {
206
- container = getOrCreateContainer(this._id);
207
- }
208
-
209
- this.container = container;
210
- const { value, max, label, showPercentage, variant, size, striped, animated, style, class: className } = this.state;
91
+ const { value, max, variant, showPercentage, style, class: className } = this.state;
211
92
 
212
93
  const wrapper = document.createElement('div');
213
- wrapper.className = `jux-progress jux-progress-${size}`;
94
+ wrapper.className = 'jux-progress';
214
95
  wrapper.id = this._id;
96
+ if (className) wrapper.className += ` ${className}`;
97
+ if (style) wrapper.setAttribute('style', style);
215
98
 
216
- if (className) {
217
- wrapper.className += ` ${className}`;
218
- }
219
-
220
- if (style) {
221
- wrapper.setAttribute('style', style);
222
- }
223
-
224
- // Label
225
- if (label || showPercentage) {
226
- const labelEl = document.createElement('div');
227
- labelEl.className = 'jux-progress-label';
228
- labelEl.id = `${this._id}-label`;
229
- const percentage = Math.round((value / max) * 100);
230
- const text = showPercentage
231
- ? `${label} ${percentage}%`.trim()
232
- : label;
233
- labelEl.textContent = text;
234
- wrapper.appendChild(labelEl);
235
- }
236
-
237
- // Progress track
238
99
  const track = document.createElement('div');
239
100
  track.className = 'jux-progress-track';
240
101
 
241
- // Progress bar
242
102
  const bar = document.createElement('div');
243
103
  bar.className = `jux-progress-bar jux-progress-bar-${variant}`;
244
- bar.id = `${this._id}-bar`;
245
- bar.setAttribute('role', 'progressbar');
246
- bar.setAttribute('aria-valuenow', value.toString());
247
- bar.setAttribute('aria-valuemin', '0');
248
- bar.setAttribute('aria-valuemax', max.toString());
249
-
250
104
  const percentage = (value / max) * 100;
251
105
  bar.style.width = `${percentage}%`;
252
-
253
- if (striped) {
254
- bar.classList.add('jux-progress-bar-striped');
255
- }
256
- if (animated) {
257
- bar.classList.add('jux-progress-bar-animated');
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;
258
114
  }
259
115
 
260
116
  track.appendChild(bar);
261
117
  wrapper.appendChild(track);
118
+
119
+ this._wireStandardEvents(wrapper);
120
+
121
+ // Wire sync for value
122
+ this._syncBindings.forEach(({ property, stateObj, toState, toComponent }) => {
123
+ if (property === 'value') {
124
+ const transform = toComponent || ((v: any) => Number(v));
125
+ stateObj.subscribe((val: any) => {
126
+ this.value(transform(val));
127
+ });
128
+ }
129
+ });
130
+
262
131
  container.appendChild(wrapper);
132
+ this._injectProgressStyles();
133
+
263
134
  return this;
264
135
  }
265
136
 
266
- renderTo(juxComponent: any): this {
267
- if (!juxComponent?._id) {
268
- throw new Error('Progress.renderTo: Invalid component');
269
- }
270
- 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);
271
189
  }
272
190
  }
273
191