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.
- package/bin/cli.js +121 -72
- package/lib/components/alert.ts +143 -92
- package/lib/components/badge.ts +93 -94
- package/lib/components/base/BaseComponent.ts +397 -0
- package/lib/components/base/FormInput.ts +322 -0
- package/lib/components/button.ts +40 -131
- package/lib/components/card.ts +57 -79
- package/lib/components/charts/areachart.ts +315 -0
- package/lib/components/charts/barchart.ts +421 -0
- package/lib/components/charts/doughnutchart.ts +263 -0
- package/lib/components/charts/lib/BaseChart.ts +402 -0
- package/lib/components/{chart-types.ts → charts/lib/chart-types.ts} +1 -1
- package/lib/components/{chart-utils.ts → charts/lib/chart-utils.ts} +1 -1
- package/lib/components/{chart.ts → charts/lib/chart.ts} +3 -3
- package/lib/components/checkbox.ts +255 -204
- package/lib/components/code.ts +31 -78
- package/lib/components/container.ts +113 -130
- package/lib/components/data.ts +37 -5
- package/lib/components/datepicker.ts +180 -147
- package/lib/components/dialog.ts +218 -221
- package/lib/components/divider.ts +63 -87
- package/lib/components/docs-data.json +498 -2404
- package/lib/components/dropdown.ts +191 -236
- package/lib/components/element.ts +196 -145
- package/lib/components/fileupload.ts +253 -167
- package/lib/components/guard.ts +92 -0
- package/lib/components/heading.ts +31 -97
- package/lib/components/helpers.ts +13 -6
- package/lib/components/hero.ts +51 -114
- package/lib/components/icon.ts +33 -120
- package/lib/components/icons.ts +2 -1
- package/lib/components/include.ts +76 -3
- package/lib/components/input.ts +155 -407
- package/lib/components/kpicard.ts +16 -16
- package/lib/components/list.ts +358 -261
- package/lib/components/loading.ts +142 -211
- package/lib/components/menu.ts +63 -152
- package/lib/components/modal.ts +42 -129
- package/lib/components/nav.ts +79 -101
- package/lib/components/paragraph.ts +38 -102
- package/lib/components/progress.ts +108 -166
- package/lib/components/radio.ts +283 -234
- package/lib/components/script.ts +19 -87
- package/lib/components/select.ts +189 -199
- package/lib/components/sidebar.ts +110 -141
- package/lib/components/style.ts +19 -82
- package/lib/components/switch.ts +254 -183
- package/lib/components/table.ts +1078 -208
- package/lib/components/tabs.ts +42 -106
- package/lib/components/theme-toggle.ts +73 -165
- package/lib/components/tooltip.ts +85 -316
- package/lib/components/write.ts +108 -127
- package/lib/jux.ts +67 -41
- package/machinery/build.js +466 -0
- package/machinery/compiler.js +354 -105
- package/machinery/server.js +23 -100
- package/machinery/watcher.js +153 -130
- package/package.json +1 -1
- package/presets/base.css +1166 -0
- package/presets/notion.css +2 -1975
- package/lib/adapters/base-adapter.js +0 -35
- package/lib/adapters/index.js +0 -33
- package/lib/adapters/mysql-adapter.js +0 -65
- package/lib/adapters/postgres-adapter.js +0 -70
- package/lib/adapters/sqlite-adapter.js +0 -56
- package/lib/components/areachart.ts +0 -1128
- package/lib/components/areachartsmooth.ts +0 -1380
- package/lib/components/barchart.ts +0 -1322
- package/lib/components/doughnutchart.ts +0 -1259
- package/lib/components/footer.ts +0 -165
- package/lib/components/header.ts +0 -187
- package/lib/components/layout.ts +0 -239
- package/lib/components/main.ts +0 -137
- package/lib/layouts/default.jux +0 -8
- package/lib/layouts/figma.jux +0 -0
- /package/lib/{themes → components/charts/lib}/charts.js +0 -0
|
@@ -1,98 +1,67 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { FormInput, FormInputState } from './base/FormInput.js';
|
|
2
|
+
import { renderIcon } from './icons.js';
|
|
3
|
+
|
|
4
|
+
// Event definitions
|
|
5
|
+
const TRIGGER_EVENTS = [] as const;
|
|
6
|
+
const CALLBACK_EVENTS = ['change'] as const;
|
|
3
7
|
|
|
4
8
|
export interface CheckboxOptions {
|
|
5
|
-
label?: string;
|
|
6
9
|
checked?: boolean;
|
|
10
|
+
label?: string;
|
|
11
|
+
required?: boolean;
|
|
7
12
|
disabled?: boolean;
|
|
8
13
|
name?: string;
|
|
9
14
|
value?: string;
|
|
10
15
|
style?: string;
|
|
11
16
|
class?: string;
|
|
17
|
+
onValidate?: (checked: boolean) => boolean | string;
|
|
12
18
|
}
|
|
13
19
|
|
|
14
|
-
|
|
15
|
-
label: string;
|
|
20
|
+
interface CheckboxState extends FormInputState {
|
|
16
21
|
checked: boolean;
|
|
17
|
-
disabled: boolean;
|
|
18
|
-
name: string;
|
|
19
22
|
value: string;
|
|
20
|
-
|
|
21
|
-
class: string;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Checkbox component
|
|
26
|
-
*
|
|
27
|
-
* Usage:
|
|
28
|
-
* jux.checkbox('terms', {
|
|
29
|
-
* label: 'I agree to terms',
|
|
30
|
-
* checked: false
|
|
31
|
-
* })
|
|
32
|
-
* .bind('change', (e) => console.log(e.target.checked))
|
|
33
|
-
* .render('#form');
|
|
34
|
-
*
|
|
35
|
-
* // Two-way binding with state
|
|
36
|
-
* const termsState = state(false);
|
|
37
|
-
* jux.checkbox('terms')
|
|
38
|
-
* .label('I agree to terms')
|
|
39
|
-
* .sync('checked', termsState)
|
|
40
|
-
* .render('#form');
|
|
41
|
-
*/
|
|
42
|
-
export class Checkbox {
|
|
43
|
-
state: CheckboxState;
|
|
44
|
-
container: HTMLElement | null = null;
|
|
45
|
-
_id: string;
|
|
46
|
-
id: string;
|
|
47
|
-
|
|
48
|
-
// CRITICAL: Store bind/sync instructions for deferred wiring
|
|
49
|
-
private _bindings: Array<{ event: string, handler: Function }> = [];
|
|
50
|
-
private _syncBindings: Array<{
|
|
51
|
-
property: string,
|
|
52
|
-
stateObj: State<any>,
|
|
53
|
-
toState?: Function,
|
|
54
|
-
toComponent?: Function
|
|
55
|
-
}> = [];
|
|
23
|
+
}
|
|
56
24
|
|
|
25
|
+
export class Checkbox extends FormInput<CheckboxState> {
|
|
57
26
|
constructor(id: string, options: CheckboxOptions = {}) {
|
|
58
|
-
|
|
59
|
-
this.id = id;
|
|
60
|
-
|
|
61
|
-
this.state = {
|
|
62
|
-
label: options.label ?? '',
|
|
27
|
+
super(id, {
|
|
63
28
|
checked: options.checked ?? false,
|
|
29
|
+
value: options.value ?? 'on',
|
|
30
|
+
label: options.label ?? '',
|
|
31
|
+
required: options.required ?? false,
|
|
64
32
|
disabled: options.disabled ?? false,
|
|
65
33
|
name: options.name ?? id,
|
|
66
|
-
value: options.value ?? 'on',
|
|
67
34
|
style: options.style ?? '',
|
|
68
|
-
class: options.class ?? ''
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
/* -------------------------
|
|
73
|
-
* Fluent API
|
|
74
|
-
* ------------------------- */
|
|
35
|
+
class: options.class ?? '',
|
|
36
|
+
errorMessage: undefined
|
|
37
|
+
});
|
|
75
38
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
39
|
+
if (options.onValidate) {
|
|
40
|
+
this._onValidate = options.onValidate;
|
|
41
|
+
}
|
|
79
42
|
}
|
|
80
43
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
this._updateElement();
|
|
84
|
-
return this;
|
|
44
|
+
protected getTriggerEvents(): readonly string[] {
|
|
45
|
+
return TRIGGER_EVENTS;
|
|
85
46
|
}
|
|
86
47
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
this._updateElement();
|
|
90
|
-
return this;
|
|
48
|
+
protected getCallbackEvents(): readonly string[] {
|
|
49
|
+
return CALLBACK_EVENTS;
|
|
91
50
|
}
|
|
92
51
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
52
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
53
|
+
* FLUENT API
|
|
54
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
55
|
+
|
|
56
|
+
// ✅ Inherited from FormInput/BaseComponent:
|
|
57
|
+
// - label(), required(), name(), onValidate()
|
|
58
|
+
// - validate(), isValid()
|
|
59
|
+
// - style(), class()
|
|
60
|
+
// - bind(), sync(), renderTo()
|
|
61
|
+
// - disabled(), enable(), disable()
|
|
62
|
+
|
|
63
|
+
checked(value: boolean): this {
|
|
64
|
+
return this.setValue(value);
|
|
96
65
|
}
|
|
97
66
|
|
|
98
67
|
value(value: string): this {
|
|
@@ -100,183 +69,265 @@ export class Checkbox {
|
|
|
100
69
|
return this;
|
|
101
70
|
}
|
|
102
71
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
class(value: string): this {
|
|
109
|
-
this.state.class = value;
|
|
110
|
-
return this;
|
|
111
|
-
}
|
|
72
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
73
|
+
* FORM INPUT IMPLEMENTATION
|
|
74
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
112
75
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
* DOM events only: change, click, focus, blur, etc.
|
|
116
|
-
*/
|
|
117
|
-
bind(event: string, handler: Function): this {
|
|
118
|
-
this._bindings.push({ event, handler });
|
|
119
|
-
return this;
|
|
76
|
+
getValue(): boolean {
|
|
77
|
+
return this.state.checked;
|
|
120
78
|
}
|
|
121
79
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
* @param stateObj - State object to sync with
|
|
127
|
-
* @param toState - Optional transform function when going from component to state
|
|
128
|
-
* @param toComponent - Optional transform function when going from state to component
|
|
129
|
-
*/
|
|
130
|
-
sync(property: string, stateObj: State<any>, toState?: Function, toComponent?: Function): this {
|
|
131
|
-
if (!stateObj || typeof stateObj.subscribe !== 'function') {
|
|
132
|
-
throw new Error(`Checkbox.sync: Expected a State object for property "${property}"`);
|
|
80
|
+
setValue(value: boolean): this {
|
|
81
|
+
this.state.checked = value;
|
|
82
|
+
if (this._inputElement) {
|
|
83
|
+
(this._inputElement as HTMLInputElement).checked = value;
|
|
133
84
|
}
|
|
134
|
-
this._syncBindings.push({ property, stateObj, toState, toComponent });
|
|
135
85
|
return this;
|
|
136
86
|
}
|
|
137
87
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
* ------------------------- */
|
|
88
|
+
protected _validateValue(checked: boolean): boolean | string {
|
|
89
|
+
const { required } = this.state;
|
|
141
90
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (input) {
|
|
145
|
-
input.checked = this.state.checked;
|
|
146
|
-
input.disabled = this.state.disabled;
|
|
91
|
+
if (required && !checked) {
|
|
92
|
+
return 'This field must be checked';
|
|
147
93
|
}
|
|
148
|
-
}
|
|
149
94
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
95
|
+
if (this._onValidate) {
|
|
96
|
+
const result = this._onValidate(checked);
|
|
97
|
+
if (result !== true) {
|
|
98
|
+
return result || 'Invalid value';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return true;
|
|
157
103
|
}
|
|
158
104
|
|
|
159
|
-
|
|
160
|
-
|
|
105
|
+
protected _buildInputElement(): HTMLElement {
|
|
106
|
+
const { checked, value, required, disabled, name } = this.state;
|
|
107
|
+
|
|
108
|
+
const input = document.createElement('input');
|
|
109
|
+
input.type = 'checkbox';
|
|
110
|
+
input.className = 'jux-checkbox-input';
|
|
111
|
+
input.id = `${this._id}-input`;
|
|
112
|
+
input.name = name;
|
|
113
|
+
input.value = value;
|
|
114
|
+
input.checked = checked;
|
|
115
|
+
input.required = required;
|
|
116
|
+
input.disabled = disabled;
|
|
117
|
+
|
|
118
|
+
return input;
|
|
161
119
|
}
|
|
162
120
|
|
|
163
|
-
/*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
121
|
+
/* ═════════════════════════════════════════════════════════════════
|
|
122
|
+
* RENDER
|
|
123
|
+
* ═════════════════════════════════════════════════════════════════ */
|
|
166
124
|
|
|
167
125
|
render(targetId?: string): this {
|
|
168
|
-
|
|
169
|
-
let container: HTMLElement;
|
|
170
|
-
if (targetId) {
|
|
171
|
-
const target = document.querySelector(targetId);
|
|
172
|
-
if (!target || !(target instanceof HTMLElement)) {
|
|
173
|
-
throw new Error(`Checkbox: Target "${targetId}" not found`);
|
|
174
|
-
}
|
|
175
|
-
container = target;
|
|
176
|
-
} else {
|
|
177
|
-
container = getOrCreateContainer(this._id);
|
|
178
|
-
}
|
|
179
|
-
this.container = container;
|
|
126
|
+
const container = this._setupContainer(targetId);
|
|
180
127
|
|
|
181
|
-
|
|
182
|
-
const { checked, label, disabled, name, style, class: className } = this.state;
|
|
183
|
-
const hasCheckedSync = this._syncBindings.some(b => b.property === 'checked');
|
|
128
|
+
const { style, class: className } = this.state;
|
|
184
129
|
|
|
185
|
-
//
|
|
130
|
+
// Build wrapper
|
|
186
131
|
const wrapper = document.createElement('div');
|
|
187
132
|
wrapper.className = 'jux-checkbox';
|
|
188
133
|
wrapper.id = this._id;
|
|
189
134
|
if (className) wrapper.className += ` ${className}`;
|
|
190
135
|
if (style) wrapper.setAttribute('style', style);
|
|
191
136
|
|
|
192
|
-
|
|
193
|
-
|
|
137
|
+
// Checkbox container
|
|
138
|
+
const checkboxContainer = document.createElement('label');
|
|
139
|
+
checkboxContainer.className = 'jux-checkbox-container';
|
|
140
|
+
checkboxContainer.htmlFor = `${this._id}-input`;
|
|
194
141
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
input.name = name;
|
|
200
|
-
input.checked = checked;
|
|
201
|
-
input.disabled = disabled;
|
|
142
|
+
// Input element
|
|
143
|
+
const inputEl = this._buildInputElement() as HTMLInputElement;
|
|
144
|
+
this._inputElement = inputEl;
|
|
145
|
+
checkboxContainer.appendChild(inputEl);
|
|
202
146
|
|
|
147
|
+
// Checkmark (custom styled)
|
|
203
148
|
const checkmark = document.createElement('span');
|
|
204
149
|
checkmark.className = 'jux-checkbox-checkmark';
|
|
150
|
+
checkmark.appendChild(renderIcon('check'));
|
|
151
|
+
checkboxContainer.appendChild(checkmark);
|
|
152
|
+
|
|
153
|
+
// Label text
|
|
154
|
+
if (this.state.label) {
|
|
155
|
+
const labelText = document.createElement('span');
|
|
156
|
+
labelText.className = 'jux-checkbox-label-text';
|
|
157
|
+
labelText.textContent = this.state.label;
|
|
158
|
+
if (this.state.required) {
|
|
159
|
+
const requiredSpan = document.createElement('span');
|
|
160
|
+
requiredSpan.className = 'jux-input-required';
|
|
161
|
+
requiredSpan.textContent = ' *';
|
|
162
|
+
labelText.appendChild(requiredSpan);
|
|
163
|
+
}
|
|
164
|
+
checkboxContainer.appendChild(labelText);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
wrapper.appendChild(checkboxContainer);
|
|
168
|
+
|
|
169
|
+
// Error element
|
|
170
|
+
wrapper.appendChild(this._renderError());
|
|
205
171
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
text.textContent = label;
|
|
172
|
+
// Wire events
|
|
173
|
+
this._wireStandardEvents(wrapper);
|
|
209
174
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
labelEl.appendChild(text);
|
|
213
|
-
wrapper.appendChild(labelEl);
|
|
175
|
+
// Wire checkbox-specific sync (maps 'checked' to 'value' property for consistency)
|
|
176
|
+
const valueSync = this._syncBindings.find(b => b.property === 'value' || b.property === 'checked');
|
|
214
177
|
|
|
215
|
-
|
|
178
|
+
if (valueSync) {
|
|
179
|
+
const { stateObj, toState, toComponent } = valueSync;
|
|
216
180
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
181
|
+
const transformToState = toState || ((v: boolean) => v);
|
|
182
|
+
const transformToComponent = toComponent || ((v: any) => Boolean(v));
|
|
183
|
+
|
|
184
|
+
let isUpdating = false;
|
|
185
|
+
|
|
186
|
+
// State → Component
|
|
187
|
+
stateObj.subscribe((val: any) => {
|
|
188
|
+
if (isUpdating) return;
|
|
189
|
+
const transformed = transformToComponent(val);
|
|
190
|
+
this.setValue(transformed);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Component → State
|
|
194
|
+
inputEl.addEventListener('change', () => {
|
|
195
|
+
if (isUpdating) return;
|
|
196
|
+
isUpdating = true;
|
|
197
|
+
|
|
198
|
+
const checked = inputEl.checked;
|
|
199
|
+
this.state.checked = checked;
|
|
200
|
+
this._clearError();
|
|
201
|
+
|
|
202
|
+
const transformed = transformToState(checked);
|
|
203
|
+
stateObj.set(transformed);
|
|
204
|
+
|
|
205
|
+
// 🎯 Fire the change callback event
|
|
206
|
+
this._triggerCallback('change', checked);
|
|
207
|
+
|
|
208
|
+
setTimeout(() => { isUpdating = false; }, 0);
|
|
209
|
+
});
|
|
210
|
+
} else {
|
|
211
|
+
// Default behavior without sync
|
|
212
|
+
inputEl.addEventListener('change', () => {
|
|
213
|
+
this.state.checked = inputEl.checked;
|
|
214
|
+
this._clearError();
|
|
215
|
+
|
|
216
|
+
// 🎯 Fire the change callback event
|
|
217
|
+
this._triggerCallback('change', inputEl.checked);
|
|
221
218
|
});
|
|
222
219
|
}
|
|
223
220
|
|
|
224
|
-
//
|
|
225
|
-
|
|
226
|
-
|
|
221
|
+
// Always add blur validation
|
|
222
|
+
inputEl.addEventListener('blur', () => {
|
|
223
|
+
this.validate();
|
|
227
224
|
});
|
|
228
225
|
|
|
229
|
-
//
|
|
230
|
-
this._syncBindings.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
// Component → State
|
|
248
|
-
input.addEventListener('change', () => {
|
|
249
|
-
if (isUpdating) return;
|
|
250
|
-
isUpdating = true;
|
|
251
|
-
|
|
252
|
-
const transformed = transformToState(input.checked);
|
|
253
|
-
this.state.checked = input.checked;
|
|
254
|
-
stateObj.set(transformed);
|
|
255
|
-
|
|
256
|
-
setTimeout(() => { isUpdating = false; }, 0);
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
else if (property === 'label') {
|
|
260
|
-
const transformToComponent = toComponent || ((v: any) => String(v));
|
|
261
|
-
|
|
262
|
-
stateObj.subscribe((val: any) => {
|
|
263
|
-
const transformed = transformToComponent(val);
|
|
264
|
-
text.textContent = transformed;
|
|
265
|
-
this.state.label = transformed;
|
|
266
|
-
});
|
|
226
|
+
// Sync label changes
|
|
227
|
+
const labelSync = this._syncBindings.find(b => b.property === 'label');
|
|
228
|
+
if (labelSync) {
|
|
229
|
+
const transform = labelSync.toComponent || ((v: any) => String(v));
|
|
230
|
+
labelSync.stateObj.subscribe((val: any) => {
|
|
231
|
+
this.label(transform(val));
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
container.appendChild(wrapper);
|
|
236
|
+
this._injectCheckboxStyles();
|
|
237
|
+
|
|
238
|
+
requestAnimationFrame(() => {
|
|
239
|
+
if ((window as any).lucide) {
|
|
240
|
+
(window as any).lucide.createIcons();
|
|
267
241
|
}
|
|
268
242
|
});
|
|
269
243
|
|
|
270
|
-
// === 5. RENDER: Append to DOM and finalize ===
|
|
271
|
-
container.appendChild(wrapper);
|
|
272
244
|
return this;
|
|
273
245
|
}
|
|
274
246
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
247
|
+
private _injectCheckboxStyles(): void {
|
|
248
|
+
const styleId = 'jux-checkbox-styles';
|
|
249
|
+
if (document.getElementById(styleId)) return;
|
|
250
|
+
|
|
251
|
+
const style = document.createElement('style');
|
|
252
|
+
style.id = styleId;
|
|
253
|
+
style.textContent = `
|
|
254
|
+
.jux-checkbox {
|
|
255
|
+
margin-bottom: 12px;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.jux-checkbox-container {
|
|
259
|
+
display: inline-flex;
|
|
260
|
+
align-items: center;
|
|
261
|
+
cursor: pointer;
|
|
262
|
+
user-select: none;
|
|
263
|
+
position: relative;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.jux-checkbox-input {
|
|
267
|
+
position: absolute;
|
|
268
|
+
opacity: 0;
|
|
269
|
+
cursor: pointer;
|
|
270
|
+
height: 0;
|
|
271
|
+
width: 0;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.jux-checkbox-checkmark {
|
|
275
|
+
position: relative;
|
|
276
|
+
height: 20px;
|
|
277
|
+
width: 20px;
|
|
278
|
+
border: 2px solid #d1d5db;
|
|
279
|
+
border-radius: 4px;
|
|
280
|
+
background-color: white;
|
|
281
|
+
transition: all 0.2s;
|
|
282
|
+
display: flex;
|
|
283
|
+
align-items: center;
|
|
284
|
+
justify-content: center;
|
|
285
|
+
margin-right: 8px;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.jux-checkbox-checkmark svg {
|
|
289
|
+
width: 14px;
|
|
290
|
+
height: 14px;
|
|
291
|
+
stroke: white;
|
|
292
|
+
stroke-width: 3;
|
|
293
|
+
opacity: 0;
|
|
294
|
+
transition: opacity 0.2s;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.jux-checkbox-input:checked ~ .jux-checkbox-checkmark {
|
|
298
|
+
background-color: #3b82f6;
|
|
299
|
+
border-color: #3b82f6;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.jux-checkbox-input:checked ~ .jux-checkbox-checkmark svg {
|
|
303
|
+
opacity: 1;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.jux-checkbox-input:disabled ~ .jux-checkbox-checkmark {
|
|
307
|
+
background-color: #f3f4f6;
|
|
308
|
+
border-color: #d1d5db;
|
|
309
|
+
cursor: not-allowed;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.jux-checkbox-input:disabled ~ .jux-checkbox-label-text {
|
|
313
|
+
color: #9ca3af;
|
|
314
|
+
cursor: not-allowed;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.jux-checkbox-input:focus ~ .jux-checkbox-checkmark {
|
|
318
|
+
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.jux-checkbox-input.jux-input-invalid ~ .jux-checkbox-checkmark {
|
|
322
|
+
border-color: #ef4444;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.jux-checkbox-label-text {
|
|
326
|
+
font-size: 14px;
|
|
327
|
+
color: #374151;
|
|
328
|
+
}
|
|
329
|
+
`;
|
|
330
|
+
document.head.appendChild(style);
|
|
280
331
|
}
|
|
281
332
|
}
|
|
282
333
|
|