juxscript 1.1.4 → 1.1.6
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.
- package/index.d.ts +10 -10
- package/index.d.ts.map +1 -0
- package/lib/components/alert.d.ts +32 -0
- package/lib/components/alert.d.ts.map +1 -0
- package/lib/components/alert.js +153 -0
- package/lib/components/alert.ts +200 -0
- package/lib/components/app.d.ts +89 -0
- package/lib/components/app.d.ts.map +1 -0
- package/lib/components/app.js +175 -0
- package/lib/components/app.ts +247 -0
- package/lib/components/badge.d.ts +27 -0
- package/lib/components/badge.d.ts.map +1 -0
- package/lib/components/badge.js +70 -0
- package/lib/components/badge.ts +101 -0
- package/lib/components/base/BaseComponent.d.ts +142 -0
- package/lib/components/base/BaseComponent.d.ts.map +1 -0
- package/lib/components/base/BaseComponent.js +363 -0
- package/lib/components/base/BaseComponent.ts +421 -0
- package/lib/components/base/FormInput.d.ts +73 -0
- package/lib/components/base/FormInput.d.ts.map +1 -0
- package/lib/components/base/FormInput.js +163 -0
- package/lib/components/base/FormInput.ts +227 -0
- package/lib/components/button.d.ts +48 -0
- package/lib/components/button.d.ts.map +1 -0
- package/lib/components/button.js +121 -0
- package/lib/components/button.ts +178 -0
- package/lib/components/card.d.ts +34 -0
- package/lib/components/card.d.ts.map +1 -0
- package/lib/components/card.js +127 -0
- package/lib/components/card.ts +173 -0
- package/lib/components/chart.d.ts +45 -0
- package/lib/components/chart.d.ts.map +1 -0
- package/lib/components/chart.js +186 -0
- package/lib/components/chart.ts +231 -0
- package/lib/components/checkbox.d.ts +31 -0
- package/lib/components/checkbox.d.ts.map +1 -0
- package/lib/components/checkbox.js +185 -0
- package/lib/components/checkbox.ts +242 -0
- package/lib/components/code.d.ts +24 -0
- package/lib/components/code.d.ts.map +1 -0
- package/lib/components/code.js +88 -0
- package/lib/components/code.ts +123 -0
- package/lib/components/container.d.ts +42 -0
- package/lib/components/container.d.ts.map +1 -0
- package/lib/components/container.js +93 -0
- package/lib/components/container.ts +140 -0
- package/lib/components/data.d.ts +36 -0
- package/lib/components/data.d.ts.map +1 -0
- package/lib/components/data.js +110 -0
- package/lib/components/data.ts +135 -0
- package/lib/components/datepicker.d.ts +38 -0
- package/lib/components/datepicker.d.ts.map +1 -0
- package/lib/components/datepicker.js +177 -0
- package/lib/components/datepicker.ts +234 -0
- package/lib/components/dialog.d.ts +38 -0
- package/lib/components/dialog.d.ts.map +1 -0
- package/lib/components/dialog.js +126 -0
- package/lib/components/dialog.ts +172 -0
- package/lib/components/divider.d.ts +30 -0
- package/lib/components/divider.d.ts.map +1 -0
- package/lib/components/divider.js +69 -0
- package/lib/components/divider.ts +100 -0
- package/lib/components/dropdown.d.ts +39 -0
- package/lib/components/dropdown.d.ts.map +1 -0
- package/lib/components/dropdown.js +133 -0
- package/lib/components/dropdown.ts +186 -0
- package/lib/components/element.d.ts +50 -0
- package/lib/components/element.d.ts.map +1 -0
- package/lib/components/element.js +206 -0
- package/lib/components/element.ts +267 -0
- package/lib/components/fileupload.d.ts +40 -0
- package/lib/components/fileupload.d.ts.map +1 -0
- package/lib/components/fileupload.js +241 -0
- package/lib/components/fileupload.ts +309 -0
- package/lib/components/grid.d.ts +87 -0
- package/lib/components/grid.d.ts.map +1 -0
- package/lib/components/grid.js +205 -0
- package/lib/components/grid.ts +291 -0
- package/lib/components/guard.d.ts +41 -0
- package/lib/components/guard.d.ts.map +1 -0
- package/lib/components/guard.js +56 -0
- package/lib/components/guard.ts +92 -0
- package/lib/components/heading.d.ts +24 -0
- package/lib/components/heading.d.ts.map +1 -0
- package/lib/components/heading.js +67 -0
- package/lib/components/heading.ts +96 -0
- package/lib/components/helpers.d.ts +9 -0
- package/lib/components/helpers.d.ts.map +1 -0
- package/lib/components/helpers.js +30 -0
- package/lib/components/helpers.ts +41 -0
- package/lib/components/hero.d.ts +45 -0
- package/lib/components/hero.d.ts.map +1 -0
- package/lib/components/hero.js +165 -0
- package/lib/components/hero.ts +224 -0
- package/lib/components/icon.d.ts +35 -0
- package/lib/components/icon.d.ts.map +1 -0
- package/lib/components/icon.js +132 -0
- package/lib/components/icon.ts +178 -0
- package/lib/components/icons.d.ts +25 -0
- package/lib/components/icons.d.ts.map +1 -0
- package/lib/components/icons.js +440 -0
- package/lib/components/icons.ts +464 -0
- package/lib/components/include.d.ts +120 -0
- package/lib/components/include.d.ts.map +1 -0
- package/lib/components/include.js +350 -0
- package/lib/components/include.ts +410 -0
- package/lib/components/input.d.ts +83 -0
- package/lib/components/input.d.ts.map +1 -0
- package/lib/components/input.js +348 -0
- package/lib/components/input.ts +457 -0
- package/lib/components/list.d.ts +82 -0
- package/lib/components/list.d.ts.map +1 -0
- package/lib/components/list.js +311 -0
- package/lib/components/list.ts +419 -0
- package/lib/components/loading.d.ts +24 -0
- package/lib/components/loading.d.ts.map +1 -0
- package/lib/components/loading.js +73 -0
- package/lib/components/loading.ts +100 -0
- package/lib/components/menu.d.ts +37 -0
- package/lib/components/menu.d.ts.map +1 -0
- package/lib/components/menu.js +202 -0
- package/lib/components/menu.ts +275 -0
- package/lib/components/modal.d.ts +51 -0
- package/lib/components/modal.d.ts.map +1 -0
- package/lib/components/modal.js +227 -0
- package/lib/components/modal.ts +284 -0
- package/lib/components/nav.d.ts +45 -0
- package/lib/components/nav.d.ts.map +1 -0
- package/lib/components/nav.js +190 -0
- package/lib/components/nav.ts +257 -0
- package/lib/components/paragraph.d.ts +21 -0
- package/lib/components/paragraph.d.ts.map +1 -0
- package/lib/components/paragraph.js +70 -0
- package/lib/components/paragraph.ts +97 -0
- package/lib/components/progress.d.ts +39 -0
- package/lib/components/progress.d.ts.map +1 -0
- package/lib/components/progress.js +113 -0
- package/lib/components/progress.ts +159 -0
- package/lib/components/radio.d.ts +41 -0
- package/lib/components/radio.d.ts.map +1 -0
- package/lib/components/radio.js +203 -0
- package/lib/components/radio.ts +278 -0
- package/lib/components/req.d.ts +155 -0
- package/lib/components/req.d.ts.map +1 -0
- package/lib/components/req.js +253 -0
- package/lib/components/req.ts +303 -0
- package/lib/components/script.d.ts +14 -0
- package/lib/components/script.d.ts.map +1 -0
- package/lib/components/script.js +33 -0
- package/lib/components/script.ts +41 -0
- package/lib/components/select.d.ts +40 -0
- package/lib/components/select.d.ts.map +1 -0
- package/lib/components/select.js +183 -0
- package/lib/components/select.ts +252 -0
- package/lib/components/sidebar.d.ts +48 -0
- package/lib/components/sidebar.d.ts.map +1 -0
- package/lib/components/sidebar.js +207 -0
- package/lib/components/sidebar.ts +275 -0
- package/lib/components/style.d.ts +14 -0
- package/lib/components/style.d.ts.map +1 -0
- package/lib/components/style.js +33 -0
- package/lib/components/style.ts +41 -0
- package/lib/components/switch.d.ts +32 -0
- package/lib/components/switch.d.ts.map +1 -0
- package/lib/components/switch.js +186 -0
- package/lib/components/switch.ts +246 -0
- package/lib/components/table.d.ts +137 -0
- package/lib/components/table.d.ts.map +1 -0
- package/lib/components/table.js +1045 -0
- package/lib/components/table.ts +1249 -0
- package/lib/components/tabs.d.ts +36 -0
- package/lib/components/tabs.d.ts.map +1 -0
- package/lib/components/tabs.js +198 -0
- package/lib/components/tabs.ts +250 -0
- package/lib/components/theme-toggle.d.ts +44 -0
- package/lib/components/theme-toggle.d.ts.map +1 -0
- package/lib/components/theme-toggle.js +215 -0
- package/lib/components/theme-toggle.ts +293 -0
- package/lib/components/tooltip.d.ts +30 -0
- package/lib/components/tooltip.d.ts.map +1 -0
- package/lib/components/tooltip.js +109 -0
- package/lib/components/tooltip.ts +144 -0
- package/lib/components/view.d.ts +48 -0
- package/lib/components/view.d.ts.map +1 -0
- package/lib/components/view.js +149 -0
- package/lib/components/view.ts +190 -0
- package/lib/components/write.d.ts +107 -0
- package/lib/components/write.d.ts.map +1 -0
- package/lib/components/write.js +222 -0
- package/lib/components/write.ts +272 -0
- package/lib/layouts/default.css +260 -0
- package/lib/layouts/figma.css +334 -0
- package/lib/reactivity/state.d.ts +36 -0
- package/lib/reactivity/state.d.ts.map +1 -0
- package/lib/reactivity/state.js +67 -0
- package/lib/reactivity/state.ts +78 -0
- package/lib/utils/fetch.d.ts +176 -0
- package/lib/utils/fetch.d.ts.map +1 -0
- package/lib/utils/fetch.js +427 -0
- package/lib/utils/fetch.ts +553 -0
- package/machinery/compiler3.js +78 -0
- package/machinery/doc-generator.js +136 -0
- package/machinery/imports.js +155 -0
- package/machinery/ts-shim.js +46 -0
- package/package.json +9 -15
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { BaseComponent } from './BaseComponent.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base state interface for all form inputs
|
|
5
|
+
*/
|
|
6
|
+
export interface FormInputState extends Record<string, any> {
|
|
7
|
+
label: string;
|
|
8
|
+
required: boolean;
|
|
9
|
+
disabled: boolean;
|
|
10
|
+
name: string;
|
|
11
|
+
style: string;
|
|
12
|
+
class: string;
|
|
13
|
+
errorMessage?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Abstract base class for all form input components
|
|
18
|
+
* Extends BaseComponent with form-specific functionality
|
|
19
|
+
*/
|
|
20
|
+
export abstract class FormInput<TState extends FormInputState> extends BaseComponent<TState> {
|
|
21
|
+
protected _inputElement: HTMLElement | null = null;
|
|
22
|
+
protected _labelElement: HTMLLabelElement | null = null;
|
|
23
|
+
protected _errorElement: HTMLElement | null = null;
|
|
24
|
+
protected _onValidate?: (value: any) => boolean | string;
|
|
25
|
+
protected _hasBeenValidated: boolean = false; // NEW: Track if user has submitted/validated
|
|
26
|
+
|
|
27
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
28
|
+
* ABSTRACT METHODS (Child must implement)
|
|
29
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Get the current value of the input
|
|
33
|
+
*/
|
|
34
|
+
abstract getValue(): any;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Set the value of the input
|
|
38
|
+
*/
|
|
39
|
+
abstract setValue(value: any): this;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Build the actual input element (input, select, textarea, etc.)
|
|
43
|
+
*/
|
|
44
|
+
protected abstract _buildInputElement(): HTMLElement;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Validate the current value
|
|
48
|
+
*/
|
|
49
|
+
protected abstract _validateValue(value: any): boolean | string;
|
|
50
|
+
|
|
51
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
52
|
+
* COMMON FORM INPUT API
|
|
53
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
54
|
+
|
|
55
|
+
label(value: string): this {
|
|
56
|
+
this.state.label = value;
|
|
57
|
+
if (this._labelElement) {
|
|
58
|
+
this._labelElement.textContent = value;
|
|
59
|
+
}
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
required(value: boolean): this {
|
|
64
|
+
this.state.required = value;
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
name(value: string): this {
|
|
69
|
+
this.state.name = value;
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
onValidate(handler: (value: any) => boolean | string): this {
|
|
74
|
+
this._onValidate = handler;
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
79
|
+
* VALIDATION
|
|
80
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Validate the current value and show/hide errors
|
|
84
|
+
*/
|
|
85
|
+
validate(): boolean {
|
|
86
|
+
this._hasBeenValidated = true; // Mark as validated
|
|
87
|
+
const value = this.getValue();
|
|
88
|
+
const result = this._validateValue(value);
|
|
89
|
+
|
|
90
|
+
if (result === true) {
|
|
91
|
+
this._clearError();
|
|
92
|
+
return true;
|
|
93
|
+
} else {
|
|
94
|
+
this._showError(result as string);
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Check if current value is valid without showing errors
|
|
101
|
+
*/
|
|
102
|
+
isValid(): boolean {
|
|
103
|
+
const value = this.getValue();
|
|
104
|
+
return this._validateValue(value) === true;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Show error message
|
|
109
|
+
*/
|
|
110
|
+
protected _showError(message: string): void {
|
|
111
|
+
if (this._errorElement) {
|
|
112
|
+
this._errorElement.textContent = message;
|
|
113
|
+
this._errorElement.style.display = 'block';
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (this._inputElement) {
|
|
117
|
+
this._inputElement.classList.add('jux-input-invalid');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this.state.errorMessage = message;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Clear error message
|
|
125
|
+
*/
|
|
126
|
+
protected _clearError(): void {
|
|
127
|
+
if (this._errorElement) {
|
|
128
|
+
this._errorElement.textContent = '';
|
|
129
|
+
this._errorElement.style.display = 'none';
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (this._inputElement) {
|
|
133
|
+
this._inputElement.classList.remove('jux-input-invalid');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
this.state.errorMessage = undefined;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
140
|
+
* COMMON RENDER HELPERS
|
|
141
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Build label element
|
|
145
|
+
*/
|
|
146
|
+
protected _renderLabel(): HTMLLabelElement {
|
|
147
|
+
const { label, required } = this.state;
|
|
148
|
+
|
|
149
|
+
const labelEl = document.createElement('label');
|
|
150
|
+
labelEl.className = 'jux-input-label';
|
|
151
|
+
labelEl.htmlFor = `${this._id}-input`;
|
|
152
|
+
labelEl.textContent = label;
|
|
153
|
+
|
|
154
|
+
if (required) {
|
|
155
|
+
const requiredSpan = document.createElement('span');
|
|
156
|
+
requiredSpan.className = 'jux-input-required';
|
|
157
|
+
requiredSpan.textContent = ' *';
|
|
158
|
+
labelEl.appendChild(requiredSpan);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
this._labelElement = labelEl;
|
|
162
|
+
return labelEl;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Build error element
|
|
167
|
+
*/
|
|
168
|
+
protected _renderError(): HTMLElement {
|
|
169
|
+
const errorEl = document.createElement('div');
|
|
170
|
+
errorEl.className = 'jux-input-error';
|
|
171
|
+
errorEl.id = `${this._id}-error`;
|
|
172
|
+
errorEl.style.display = 'none';
|
|
173
|
+
|
|
174
|
+
this._errorElement = errorEl;
|
|
175
|
+
return errorEl;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Wire up two-way sync for value property
|
|
180
|
+
*/
|
|
181
|
+
protected _wireFormSync(inputElement: HTMLElement, eventName: string = 'input'): void {
|
|
182
|
+
const valueSync = this._syncBindings.find(b => b.property === 'value');
|
|
183
|
+
|
|
184
|
+
if (valueSync) {
|
|
185
|
+
const { stateObj, toState, toComponent } = valueSync;
|
|
186
|
+
|
|
187
|
+
// Default transforms
|
|
188
|
+
const transformToState = toState || ((v: any) => v);
|
|
189
|
+
const transformToComponent = toComponent || ((v: any) => v);
|
|
190
|
+
|
|
191
|
+
let isUpdating = false;
|
|
192
|
+
|
|
193
|
+
// State → Component
|
|
194
|
+
stateObj.subscribe((val: any) => {
|
|
195
|
+
if (isUpdating) return;
|
|
196
|
+
const transformed = transformToComponent(val);
|
|
197
|
+
this.setValue(transformed);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// Component → State
|
|
201
|
+
inputElement.addEventListener(eventName, () => {
|
|
202
|
+
if (isUpdating) return;
|
|
203
|
+
isUpdating = true;
|
|
204
|
+
|
|
205
|
+
const value = this.getValue();
|
|
206
|
+
const transformed = transformToState(value);
|
|
207
|
+
this._clearError();
|
|
208
|
+
|
|
209
|
+
stateObj.set(transformed);
|
|
210
|
+
|
|
211
|
+
setTimeout(() => { isUpdating = false; }, 0);
|
|
212
|
+
});
|
|
213
|
+
} else {
|
|
214
|
+
// Default behavior without sync
|
|
215
|
+
inputElement.addEventListener(eventName, () => {
|
|
216
|
+
this._clearError();
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Only validate on blur IF the field has been validated before (e.g., after submit)
|
|
221
|
+
inputElement.addEventListener('blur', () => {
|
|
222
|
+
if (this._hasBeenValidated) {
|
|
223
|
+
this.validate();
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { BaseComponent } from './base/BaseComponent.js';
|
|
2
|
+
export interface ButtonOptions {
|
|
3
|
+
label?: string;
|
|
4
|
+
icon?: string;
|
|
5
|
+
variant?: 'primary' | 'secondary' | 'danger' | 'success' | 'warning' | 'info' | 'link' | string;
|
|
6
|
+
size?: 'small' | 'medium' | 'large';
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
loading?: boolean;
|
|
9
|
+
iconPosition?: 'left' | 'right';
|
|
10
|
+
fullWidth?: boolean;
|
|
11
|
+
type?: 'button' | 'submit' | 'reset';
|
|
12
|
+
style?: string;
|
|
13
|
+
class?: string;
|
|
14
|
+
}
|
|
15
|
+
type ButtonState = {
|
|
16
|
+
label: string;
|
|
17
|
+
icon: string;
|
|
18
|
+
variant: string;
|
|
19
|
+
size: string;
|
|
20
|
+
disabled: boolean;
|
|
21
|
+
loading: boolean;
|
|
22
|
+
iconPosition: string;
|
|
23
|
+
fullWidth: boolean;
|
|
24
|
+
type: 'button' | 'submit' | 'reset';
|
|
25
|
+
style: string;
|
|
26
|
+
class: string;
|
|
27
|
+
};
|
|
28
|
+
export declare class Button extends BaseComponent<ButtonState> {
|
|
29
|
+
private _buttonElement;
|
|
30
|
+
constructor(id: string, options?: ButtonOptions);
|
|
31
|
+
protected getTriggerEvents(): readonly string[];
|
|
32
|
+
protected getCallbackEvents(): readonly string[];
|
|
33
|
+
label(value: string): this;
|
|
34
|
+
icon(value: string): this;
|
|
35
|
+
variant(value: 'primary' | 'secondary' | 'danger' | 'success' | 'warning' | 'info' | 'link' | string): this;
|
|
36
|
+
size(value: 'small' | 'medium' | 'large'): this;
|
|
37
|
+
iconPosition(value: 'left' | 'right'): this;
|
|
38
|
+
fullWidth(value: boolean): this;
|
|
39
|
+
type(value: 'button' | 'submit' | 'reset'): this;
|
|
40
|
+
/**
|
|
41
|
+
* Override visible() to update the actual button element
|
|
42
|
+
*/
|
|
43
|
+
visible(value: boolean): this;
|
|
44
|
+
render(targetId?: string): this;
|
|
45
|
+
}
|
|
46
|
+
export declare function button(id: string, options?: ButtonOptions): Button;
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["button.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAOxD,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAChG,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,qBAAa,MAAO,SAAQ,aAAa,CAAC,WAAW,CAAC;IACpD,OAAO,CAAC,cAAc,CAAkC;gBAE5C,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa;IAkB/C,SAAS,CAAC,gBAAgB,IAAI,SAAS,MAAM,EAAE;IAI/C,SAAS,CAAC,iBAAiB,IAAI,SAAS,MAAM,EAAE;IAUhD,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK1B,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKzB,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI;IAK3G,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,IAAI;IAK/C,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;IAK3C,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAK/B,IAAI,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,IAAI;IAShD;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAW7B,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;CAkDhC;AAED,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAElE"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { BaseComponent } from './base/BaseComponent.js';
|
|
2
|
+
import { renderIcon } from './icons.js';
|
|
3
|
+
// Event definitions
|
|
4
|
+
const TRIGGER_EVENTS = [];
|
|
5
|
+
const CALLBACK_EVENTS = ['click']; // ✅ Button fires click events
|
|
6
|
+
export class Button extends BaseComponent {
|
|
7
|
+
constructor(id, options) {
|
|
8
|
+
const opts = options || {};
|
|
9
|
+
super(id, {
|
|
10
|
+
label: opts.label ?? 'Button',
|
|
11
|
+
icon: opts.icon ?? '',
|
|
12
|
+
variant: opts.variant ?? 'primary',
|
|
13
|
+
size: opts.size ?? 'medium',
|
|
14
|
+
disabled: opts.disabled ?? false,
|
|
15
|
+
loading: opts.loading ?? false,
|
|
16
|
+
iconPosition: opts.iconPosition ?? 'left',
|
|
17
|
+
fullWidth: opts.fullWidth ?? false,
|
|
18
|
+
type: opts.type ?? 'button',
|
|
19
|
+
style: opts.style ?? '',
|
|
20
|
+
class: opts.class ?? ''
|
|
21
|
+
});
|
|
22
|
+
this._buttonElement = null; // ✅ Store button reference
|
|
23
|
+
}
|
|
24
|
+
getTriggerEvents() {
|
|
25
|
+
return TRIGGER_EVENTS;
|
|
26
|
+
}
|
|
27
|
+
getCallbackEvents() {
|
|
28
|
+
return CALLBACK_EVENTS;
|
|
29
|
+
}
|
|
30
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
31
|
+
* FLUENT API
|
|
32
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
33
|
+
// ✅ Inherited from BaseComponent
|
|
34
|
+
label(value) {
|
|
35
|
+
this.state.label = value;
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
icon(value) {
|
|
39
|
+
this.state.icon = value;
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
variant(value) {
|
|
43
|
+
this.state.variant = value;
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
size(value) {
|
|
47
|
+
this.state.size = value;
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
iconPosition(value) {
|
|
51
|
+
this.state.iconPosition = value;
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
fullWidth(value) {
|
|
55
|
+
this.state.fullWidth = value;
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
type(value) {
|
|
59
|
+
this.state.type = value;
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
63
|
+
* RENDER
|
|
64
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
65
|
+
/**
|
|
66
|
+
* Override visible() to update the actual button element
|
|
67
|
+
*/
|
|
68
|
+
visible(value) {
|
|
69
|
+
this.state.visible = value;
|
|
70
|
+
// Update the button element directly, not the container
|
|
71
|
+
if (this._buttonElement) {
|
|
72
|
+
this._buttonElement.style.display = value ? '' : 'none';
|
|
73
|
+
}
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
render(targetId) {
|
|
77
|
+
const container = this._setupContainer(targetId);
|
|
78
|
+
const { label, variant, size, disabled, icon, iconPosition, loading, style, class: className } = this.state;
|
|
79
|
+
const button = document.createElement('button');
|
|
80
|
+
this._buttonElement = button; // ✅ Store reference
|
|
81
|
+
button.className = `jux-button jux-button-${variant} jux-button-${size}`;
|
|
82
|
+
button.id = this._id;
|
|
83
|
+
button.disabled = disabled || loading;
|
|
84
|
+
if (className)
|
|
85
|
+
button.className += ` ${className}`;
|
|
86
|
+
if (style)
|
|
87
|
+
button.setAttribute('style', style);
|
|
88
|
+
if (icon && iconPosition === 'left') {
|
|
89
|
+
const iconEl = document.createElement('span');
|
|
90
|
+
iconEl.className = 'jux-button-icon';
|
|
91
|
+
iconEl.appendChild(renderIcon(icon));
|
|
92
|
+
button.appendChild(iconEl);
|
|
93
|
+
}
|
|
94
|
+
const textEl = document.createElement('span');
|
|
95
|
+
textEl.textContent = loading ? 'Loading...' : label;
|
|
96
|
+
button.appendChild(textEl);
|
|
97
|
+
if (icon && iconPosition === 'right') {
|
|
98
|
+
const iconEl = document.createElement('span');
|
|
99
|
+
iconEl.className = 'jux-button-icon';
|
|
100
|
+
iconEl.appendChild(renderIcon(icon));
|
|
101
|
+
button.appendChild(iconEl);
|
|
102
|
+
}
|
|
103
|
+
button.addEventListener('click', (e) => {
|
|
104
|
+
if (!disabled && !loading) {
|
|
105
|
+
this._triggerCallback('click', e);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
this._wireStandardEvents(button);
|
|
109
|
+
this._wireAllSyncs();
|
|
110
|
+
container.appendChild(button);
|
|
111
|
+
requestAnimationFrame(() => {
|
|
112
|
+
if (window.lucide) {
|
|
113
|
+
window.lucide.createIcons();
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return this;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export function button(id, options) {
|
|
120
|
+
return new Button(id, options);
|
|
121
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { BaseComponent } from './base/BaseComponent.js';
|
|
2
|
+
import { renderIcon } from './icons.js';
|
|
3
|
+
|
|
4
|
+
// Event definitions
|
|
5
|
+
const TRIGGER_EVENTS = [] as const;
|
|
6
|
+
const CALLBACK_EVENTS = ['click'] as const; // ✅ Button fires click events
|
|
7
|
+
|
|
8
|
+
export interface ButtonOptions {
|
|
9
|
+
label?: string;
|
|
10
|
+
icon?: string;
|
|
11
|
+
variant?: 'primary' | 'secondary' | 'danger' | 'success' | 'warning' | 'info' | 'link' | string;
|
|
12
|
+
size?: 'small' | 'medium' | 'large';
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
loading?: boolean;
|
|
15
|
+
iconPosition?: 'left' | 'right';
|
|
16
|
+
fullWidth?: boolean;
|
|
17
|
+
type?: 'button' | 'submit' | 'reset';
|
|
18
|
+
style?: string;
|
|
19
|
+
class?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type ButtonState = {
|
|
23
|
+
label: string;
|
|
24
|
+
icon: string;
|
|
25
|
+
variant: string;
|
|
26
|
+
size: string;
|
|
27
|
+
disabled: boolean;
|
|
28
|
+
loading: boolean;
|
|
29
|
+
iconPosition: string;
|
|
30
|
+
fullWidth: boolean;
|
|
31
|
+
type: 'button' | 'submit' | 'reset';
|
|
32
|
+
style: string;
|
|
33
|
+
class: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export class Button extends BaseComponent<ButtonState> {
|
|
37
|
+
private _buttonElement: HTMLButtonElement | null = null; // ✅ Store button reference
|
|
38
|
+
|
|
39
|
+
constructor(id: string, options?: ButtonOptions) {
|
|
40
|
+
const opts = options || {};
|
|
41
|
+
|
|
42
|
+
super(id, {
|
|
43
|
+
label: opts.label ?? 'Button',
|
|
44
|
+
icon: opts.icon ?? '',
|
|
45
|
+
variant: opts.variant ?? 'primary',
|
|
46
|
+
size: opts.size ?? 'medium',
|
|
47
|
+
disabled: opts.disabled ?? false,
|
|
48
|
+
loading: opts.loading ?? false,
|
|
49
|
+
iconPosition: opts.iconPosition ?? 'left',
|
|
50
|
+
fullWidth: opts.fullWidth ?? false,
|
|
51
|
+
type: opts.type ?? 'button',
|
|
52
|
+
style: opts.style ?? '',
|
|
53
|
+
class: opts.class ?? ''
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
protected getTriggerEvents(): readonly string[] {
|
|
58
|
+
return TRIGGER_EVENTS;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
protected getCallbackEvents(): readonly string[] {
|
|
62
|
+
return CALLBACK_EVENTS;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
66
|
+
* FLUENT API
|
|
67
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
68
|
+
|
|
69
|
+
// ✅ Inherited from BaseComponent
|
|
70
|
+
|
|
71
|
+
label(value: string): this {
|
|
72
|
+
this.state.label = value;
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
icon(value: string): this {
|
|
77
|
+
this.state.icon = value;
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
variant(value: 'primary' | 'secondary' | 'danger' | 'success' | 'warning' | 'info' | 'link' | string): this {
|
|
82
|
+
this.state.variant = value;
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
size(value: 'small' | 'medium' | 'large'): this {
|
|
87
|
+
this.state.size = value;
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
iconPosition(value: 'left' | 'right'): this {
|
|
92
|
+
this.state.iconPosition = value;
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
fullWidth(value: boolean): this {
|
|
97
|
+
this.state.fullWidth = value;
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
type(value: 'button' | 'submit' | 'reset'): this {
|
|
102
|
+
this.state.type = value;
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
107
|
+
* RENDER
|
|
108
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Override visible() to update the actual button element
|
|
112
|
+
*/
|
|
113
|
+
visible(value: boolean): this {
|
|
114
|
+
(this.state as any).visible = value;
|
|
115
|
+
|
|
116
|
+
// Update the button element directly, not the container
|
|
117
|
+
if (this._buttonElement) {
|
|
118
|
+
this._buttonElement.style.display = value ? '' : 'none';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
render(targetId?: string): this {
|
|
125
|
+
const container = this._setupContainer(targetId);
|
|
126
|
+
const { label, variant, size, disabled, icon, iconPosition, loading, style, class: className } = this.state;
|
|
127
|
+
|
|
128
|
+
const button = document.createElement('button');
|
|
129
|
+
this._buttonElement = button; // ✅ Store reference
|
|
130
|
+
button.className = `jux-button jux-button-${variant} jux-button-${size}`;
|
|
131
|
+
button.id = this._id;
|
|
132
|
+
button.disabled = disabled || loading;
|
|
133
|
+
|
|
134
|
+
if (className) button.className += ` ${className}`;
|
|
135
|
+
if (style) button.setAttribute('style', style);
|
|
136
|
+
|
|
137
|
+
if (icon && iconPosition === 'left') {
|
|
138
|
+
const iconEl = document.createElement('span');
|
|
139
|
+
iconEl.className = 'jux-button-icon';
|
|
140
|
+
iconEl.appendChild(renderIcon(icon));
|
|
141
|
+
button.appendChild(iconEl);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const textEl = document.createElement('span');
|
|
145
|
+
textEl.textContent = loading ? 'Loading...' : label;
|
|
146
|
+
button.appendChild(textEl);
|
|
147
|
+
|
|
148
|
+
if (icon && iconPosition === 'right') {
|
|
149
|
+
const iconEl = document.createElement('span');
|
|
150
|
+
iconEl.className = 'jux-button-icon';
|
|
151
|
+
iconEl.appendChild(renderIcon(icon));
|
|
152
|
+
button.appendChild(iconEl);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
button.addEventListener('click', (e) => {
|
|
156
|
+
if (!disabled && !loading) {
|
|
157
|
+
this._triggerCallback('click', e);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
this._wireStandardEvents(button);
|
|
162
|
+
this._wireAllSyncs();
|
|
163
|
+
|
|
164
|
+
container.appendChild(button);
|
|
165
|
+
|
|
166
|
+
requestAnimationFrame(() => {
|
|
167
|
+
if ((window as any).lucide) {
|
|
168
|
+
(window as any).lucide.createIcons();
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
return this;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function button(id: string, options?: ButtonOptions): Button {
|
|
177
|
+
return new Button(id, options);
|
|
178
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BaseComponent } from './base/BaseComponent.js';
|
|
2
|
+
export interface CardOptions {
|
|
3
|
+
title?: string;
|
|
4
|
+
content?: string;
|
|
5
|
+
footer?: string;
|
|
6
|
+
variant?: string;
|
|
7
|
+
hoverable?: boolean;
|
|
8
|
+
icon?: string;
|
|
9
|
+
style?: string;
|
|
10
|
+
class?: string;
|
|
11
|
+
}
|
|
12
|
+
type CardState = {
|
|
13
|
+
title: string;
|
|
14
|
+
content: string;
|
|
15
|
+
footer: string;
|
|
16
|
+
variant: string;
|
|
17
|
+
hoverable: boolean;
|
|
18
|
+
icon: string;
|
|
19
|
+
style: string;
|
|
20
|
+
class: string;
|
|
21
|
+
};
|
|
22
|
+
export declare class Card extends BaseComponent<CardState> {
|
|
23
|
+
constructor(id: string, options?: CardOptions);
|
|
24
|
+
protected getTriggerEvents(): readonly string[];
|
|
25
|
+
protected getCallbackEvents(): readonly string[];
|
|
26
|
+
title(value: string): this;
|
|
27
|
+
content(value: string): this;
|
|
28
|
+
footer(value: string): this;
|
|
29
|
+
icon(value: string): this;
|
|
30
|
+
render(targetId?: string): this;
|
|
31
|
+
}
|
|
32
|
+
export declare function card(id: string, options?: CardOptions): Card;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAOxD,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,SAAS,GAAG;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,qBAAa,IAAK,SAAQ,aAAa,CAAC,SAAS,CAAC;gBACpC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB;IAajD,SAAS,CAAC,gBAAgB,IAAI,SAAS,MAAM,EAAE;IAI/C,SAAS,CAAC,iBAAiB,IAAI,SAAS,MAAM,EAAE;IAUhD,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK1B,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK3B,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IASzB,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;CAuFhC;AAED,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,IAAI,CAEhE"}
|