@ktjs/mui 0.20.2 → 0.23.2
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/dist/index.css +1 -1
- package/dist/index.d.ts +626 -679
- package/dist/index.iife.css +1 -1
- package/dist/index.iife.js +831 -615
- package/dist/index.mjs +830 -616
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,14 +1,78 @@
|
|
|
1
|
+
// Shared constants
|
|
2
|
+
// Empty for now - can be extended with framework-wide constants
|
|
3
|
+
/**
|
|
4
|
+
* Mark the attribute as SVG to handle special cases during rendering.
|
|
5
|
+
*/
|
|
6
|
+
const $defines = Object.defineProperties;
|
|
7
|
+
const $entries = Object.entries;
|
|
8
|
+
const $random$2 = Math.random;
|
|
9
|
+
const { get: $buttonDisabledGetter$2, set: $buttonDisabledSetter$2 } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
|
|
10
|
+
const parseStyle = (style) => {
|
|
11
|
+
if (!style) {
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
14
|
+
if (typeof style === 'string') {
|
|
15
|
+
return style;
|
|
16
|
+
}
|
|
17
|
+
if (style && typeof style === 'object') {
|
|
18
|
+
if (style.isKT) {
|
|
19
|
+
return parseStyle(style.value);
|
|
20
|
+
}
|
|
21
|
+
return $entries(style)
|
|
22
|
+
.map((entry) => {
|
|
23
|
+
const cssKey = entry[0].replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
24
|
+
return `${cssKey}:${entry[1]}`;
|
|
25
|
+
})
|
|
26
|
+
.join(';');
|
|
27
|
+
}
|
|
28
|
+
return '';
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// String manipulation utilities
|
|
32
|
+
/**
|
|
33
|
+
* Default empty function
|
|
34
|
+
*/
|
|
35
|
+
const $emptyFn = (() => true);
|
|
36
|
+
|
|
37
|
+
if (typeof Symbol === 'undefined') {
|
|
38
|
+
window.Symbol = function Symbol(description) {
|
|
39
|
+
return `@@SYMBOL_${description || ''}_${$random$2().toString(36).slice(2)}`;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Shared utilities and cached native methods for kt.js framework
|
|
44
|
+
Object.defineProperty(window, '__ktjs__', { value: '0.23.4' });
|
|
45
|
+
|
|
46
|
+
// Shared constants
|
|
47
|
+
// Empty for now - can be extended with framework-wide constants
|
|
48
|
+
/**
|
|
49
|
+
* Mark the attribute as SVG to handle special cases during rendering.
|
|
50
|
+
*/
|
|
51
|
+
const SVG_ATTR_FLAG = '__kt_svg__';
|
|
52
|
+
/**
|
|
53
|
+
* Mark the attribute as MathML to handle special cases during rendering.
|
|
54
|
+
*/
|
|
55
|
+
const MATHML_ATTR_FLAG = '__kt_mathml__';
|
|
56
|
+
|
|
1
57
|
// Cached native methods for performance optimization
|
|
2
58
|
const $isArray = Array.isArray;
|
|
3
|
-
const $
|
|
4
|
-
|
|
5
|
-
// Error handling utilities
|
|
6
|
-
const $throw = (message) => {
|
|
7
|
-
throw new Error('@ktjs/shared: ' + message);
|
|
8
|
-
};
|
|
59
|
+
const $random$1 = Math.random;
|
|
60
|
+
const $isThenable = (o) => typeof o?.then === 'function';
|
|
9
61
|
|
|
10
62
|
// DOM manipulation utilities
|
|
11
63
|
// # dom natives
|
|
64
|
+
const $isNode$1 = (x) => x?.nodeType > 0;
|
|
65
|
+
/**
|
|
66
|
+
* Safe replace `oldNode` With `newNode`
|
|
67
|
+
*/
|
|
68
|
+
const $replaceNode$1 = (oldNode, newNode) => {
|
|
69
|
+
if ($isNode$1(oldNode) && $isNode$1(newNode)) {
|
|
70
|
+
if (newNode.contains(oldNode)) {
|
|
71
|
+
newNode.remove();
|
|
72
|
+
}
|
|
73
|
+
oldNode.replaceWith(newNode);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
12
76
|
/**
|
|
13
77
|
* & Remove `bind` because it is shockingly slower than wrapper
|
|
14
78
|
* & `window.document` is safe because it is not configurable and its setter is undefined
|
|
@@ -44,11 +108,28 @@ const $append = // for ie 9/10/11
|
|
|
44
108
|
$appendChild.call(this, fragment);
|
|
45
109
|
}
|
|
46
110
|
};
|
|
47
|
-
const { get: $buttonDisabledGetter$
|
|
111
|
+
const { get: $buttonDisabledGetter$1, set: $buttonDisabledSetter$1 } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
|
|
112
|
+
/**
|
|
113
|
+
* Used for `k-model`
|
|
114
|
+
*/
|
|
115
|
+
const applyModel = (element, valueRef, propName, eventName) => {
|
|
116
|
+
element[propName] = valueRef.value; // initialize
|
|
117
|
+
valueRef.addOnChange((newValue) => (element[propName] = newValue));
|
|
118
|
+
element.addEventListener(eventName, () => (valueRef.value = element[propName]));
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
if (typeof Symbol === 'undefined') {
|
|
122
|
+
window.Symbol = function Symbol(description) {
|
|
123
|
+
return `@@SYMBOL_${description || ''}_${$random$1().toString(36).slice(2)}`;
|
|
124
|
+
};
|
|
125
|
+
}
|
|
48
126
|
|
|
49
127
|
// Shared utilities and cached native methods for kt.js framework
|
|
50
|
-
|
|
51
|
-
|
|
128
|
+
Object.defineProperty(window, '__ktjs__', { value: '0.23.4' });
|
|
129
|
+
|
|
130
|
+
const isKT$1 = (obj) => obj?.isKT;
|
|
131
|
+
const isRef = (obj) => obj?.ktType === 1 /* KTReactiveType.REF */;
|
|
132
|
+
const isComputed = (obj) => obj?.ktType === 2 /* KTReactiveType.COMPUTED */;
|
|
52
133
|
|
|
53
134
|
const booleanHandler = (element, key, value) => {
|
|
54
135
|
if (key in element) {
|
|
@@ -92,10 +173,25 @@ const handlers = {
|
|
|
92
173
|
};
|
|
93
174
|
|
|
94
175
|
const defaultHandler = (element, key, value) => element.setAttribute(key, value);
|
|
176
|
+
const setElementStyle = (element, style) => {
|
|
177
|
+
if (typeof style === 'string') {
|
|
178
|
+
element.style.cssText = style;
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
for (const key in style) {
|
|
182
|
+
element.style[key] = style[key];
|
|
183
|
+
}
|
|
184
|
+
};
|
|
95
185
|
function attrIsObject(element, attr) {
|
|
96
186
|
const classValue = attr.class || attr.className;
|
|
97
187
|
if (classValue !== undefined) {
|
|
98
|
-
|
|
188
|
+
if (isKT$1(classValue)) {
|
|
189
|
+
element.setAttribute('class', classValue.value);
|
|
190
|
+
classValue.addOnChange((v) => element.setAttribute('class', v));
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
element.setAttribute('class', classValue);
|
|
194
|
+
}
|
|
99
195
|
}
|
|
100
196
|
const style = attr.style;
|
|
101
197
|
if (style) {
|
|
@@ -103,18 +199,34 @@ function attrIsObject(element, attr) {
|
|
|
103
199
|
element.setAttribute('style', style);
|
|
104
200
|
}
|
|
105
201
|
else if (typeof style === 'object') {
|
|
106
|
-
|
|
107
|
-
element
|
|
202
|
+
if (isKT$1(style)) {
|
|
203
|
+
setElementStyle(element, style.value);
|
|
204
|
+
style.addOnChange((v) => setElementStyle(element, v));
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
setElementStyle(element, style);
|
|
108
208
|
}
|
|
109
209
|
}
|
|
110
210
|
}
|
|
211
|
+
if ('k-html' in attr) {
|
|
212
|
+
const html = attr['k-html'];
|
|
213
|
+
if (isKT$1(html)) {
|
|
214
|
+
element.innerHTML = html.value;
|
|
215
|
+
html.addOnChange((v) => (element.innerHTML = v));
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
element.innerHTML = html;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
111
221
|
for (const key in attr) {
|
|
112
|
-
if (key === '
|
|
222
|
+
if (key === 'k-if' ||
|
|
223
|
+
key === 'k-model' ||
|
|
224
|
+
key === 'ref' ||
|
|
225
|
+
key === 'class' ||
|
|
113
226
|
key === 'className' ||
|
|
114
227
|
key === 'style' ||
|
|
115
228
|
key === 'children' ||
|
|
116
|
-
key === 'k-
|
|
117
|
-
key === 'ref') {
|
|
229
|
+
key === 'k-html') {
|
|
118
230
|
continue;
|
|
119
231
|
}
|
|
120
232
|
const o = attr[key];
|
|
@@ -124,7 +236,14 @@ function attrIsObject(element, attr) {
|
|
|
124
236
|
}
|
|
125
237
|
// normal attributes
|
|
126
238
|
else {
|
|
127
|
-
|
|
239
|
+
const handler = handlers[key] || defaultHandler;
|
|
240
|
+
if (isKT$1(o)) {
|
|
241
|
+
handler(element, key, o.value);
|
|
242
|
+
o.addOnChange((v) => handler(element, key, v));
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
handler(element, key, o);
|
|
246
|
+
}
|
|
128
247
|
}
|
|
129
248
|
}
|
|
130
249
|
}
|
|
@@ -136,17 +255,28 @@ function applyAttr(element, attr) {
|
|
|
136
255
|
attrIsObject(element, attr);
|
|
137
256
|
}
|
|
138
257
|
else {
|
|
139
|
-
throw new Error('kt.js
|
|
258
|
+
throw new Error('[kt.js error] attr must be an object.');
|
|
140
259
|
}
|
|
141
260
|
}
|
|
142
261
|
|
|
262
|
+
const assureNode = (o) => ($isNode$1(o) ? o : document.createTextNode(o));
|
|
143
263
|
function apdSingle(element, c) {
|
|
144
264
|
// & JSX should ignore false, undefined, and null
|
|
145
265
|
if (c === false || c === undefined || c === null) {
|
|
146
266
|
return;
|
|
147
267
|
}
|
|
148
|
-
if (
|
|
149
|
-
|
|
268
|
+
if (isKT$1(c)) {
|
|
269
|
+
let node = assureNode(c.value);
|
|
270
|
+
$append.call(element, node);
|
|
271
|
+
c.addOnChange((newValue, oldValue) => {
|
|
272
|
+
if ($isNode$1(newValue) && $isNode$1(oldValue)) {
|
|
273
|
+
// & this case is handled automically in `class KTRef`
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const oldNode = node;
|
|
277
|
+
node = assureNode(newValue);
|
|
278
|
+
oldNode.replaceWith(node);
|
|
279
|
+
});
|
|
150
280
|
}
|
|
151
281
|
else {
|
|
152
282
|
$append.call(element, c);
|
|
@@ -191,14 +321,34 @@ function applyContent(element, content) {
|
|
|
191
321
|
}
|
|
192
322
|
}
|
|
193
323
|
|
|
194
|
-
|
|
324
|
+
function applyKModel(element, valueRef) {
|
|
325
|
+
if (!isKT$1(valueRef)) {
|
|
326
|
+
console.warn('[kt.js warn]','k-model value must be a KTRef.');
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (element instanceof HTMLInputElement) {
|
|
330
|
+
if (element.type === 'radio' || element.type === 'checkbox') {
|
|
331
|
+
applyModel(element, valueRef, 'checked', 'change');
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
applyModel(element, valueRef, 'value', 'input');
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
else if (element instanceof HTMLSelectElement) {
|
|
338
|
+
applyModel(element, valueRef, 'value', 'change');
|
|
339
|
+
}
|
|
340
|
+
else if (element instanceof HTMLTextAreaElement) {
|
|
341
|
+
applyModel(element, valueRef, 'value', 'input');
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
console.warn('[kt.js warn]','not supported element for k-model:');
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
195
348
|
const htmlCreator = (tag) => document.createElement(tag);
|
|
196
349
|
const svgCreator = (tag) => document.createElementNS('http://www.w3.org/2000/svg', tag);
|
|
197
350
|
const mathMLCreator = (tag) => document.createElementNS('http://www.w3.org/1998/Math/MathML', tag);
|
|
198
351
|
let creator = htmlCreator;
|
|
199
|
-
// # consts
|
|
200
|
-
const SVG_ATTR_FLAG = '__kt_svg__';
|
|
201
|
-
const MATHML_ATTR_FLAG = '__kt_mathml__';
|
|
202
352
|
/**
|
|
203
353
|
* Create an enhanced HTMLElement.
|
|
204
354
|
* - Only supports HTMLElements, **NOT** SVGElements or other Elements.
|
|
@@ -209,7 +359,7 @@ const MATHML_ATTR_FLAG = '__kt_mathml__';
|
|
|
209
359
|
* ## About
|
|
210
360
|
* @package @ktjs/core
|
|
211
361
|
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
212
|
-
* @version 0.
|
|
362
|
+
* @version 0.26.9 (Last Update: 2026.02.09 00:03:34.324)
|
|
213
363
|
* @license MIT
|
|
214
364
|
* @link https://github.com/baendlorel/kt.js
|
|
215
365
|
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
@@ -218,7 +368,7 @@ const MATHML_ATTR_FLAG = '__kt_mathml__';
|
|
|
218
368
|
*/
|
|
219
369
|
const h = (tag, attr, content) => {
|
|
220
370
|
if (typeof tag !== 'string') {
|
|
221
|
-
|
|
371
|
+
throw new Error('[kt.js error] tagName must be a string.');
|
|
222
372
|
}
|
|
223
373
|
if (attr) {
|
|
224
374
|
if (SVG_ATTR_FLAG in attr) {
|
|
@@ -238,39 +388,57 @@ const h = (tag, attr, content) => {
|
|
|
238
388
|
// * Handle content
|
|
239
389
|
applyAttr(element, attr);
|
|
240
390
|
applyContent(element, content);
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
// }
|
|
245
|
-
// if (tag === 'math') {
|
|
246
|
-
// tempWrapper.innerHTML = element.outerHTML;
|
|
247
|
-
// return tempWrapper.firstChild as HTML<T>;
|
|
248
|
-
// }
|
|
391
|
+
if (typeof attr === 'object' && attr !== null && 'k-model' in attr) {
|
|
392
|
+
applyKModel(element, attr['k-model']);
|
|
393
|
+
}
|
|
249
394
|
return element;
|
|
250
395
|
};
|
|
251
396
|
|
|
252
397
|
const dummyRef = { value: null };
|
|
398
|
+
const create = (tag, props) => {
|
|
399
|
+
if (typeof tag === 'function') {
|
|
400
|
+
return tag(props);
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
return h(tag, props, props.children);
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
const placeholder = () => document.createComment('k-if');
|
|
253
407
|
/**
|
|
254
408
|
* @param tag html tag or function component
|
|
255
409
|
* @param props properties/attributes
|
|
256
410
|
*/
|
|
257
411
|
function jsx(tag, props) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
if ('k-if' in props && !props['k-if']) {
|
|
261
|
-
// & make comment placeholder in case that ref might be redrawn later
|
|
262
|
-
el = document.createComment('k-if');
|
|
263
|
-
ref.value = el;
|
|
264
|
-
return el;
|
|
265
|
-
}
|
|
266
|
-
// Handle function components
|
|
267
|
-
if (typeof tag === 'function') {
|
|
268
|
-
el = tag(props);
|
|
412
|
+
if (isComputed(props.ref)) {
|
|
413
|
+
throw new Error('[kt.js error] Cannot assign a computed value to an element.');
|
|
269
414
|
}
|
|
270
|
-
|
|
271
|
-
|
|
415
|
+
const maybeDummyRef = isRef(props.ref) ? props.ref : dummyRef;
|
|
416
|
+
let el;
|
|
417
|
+
if ('k-if' in props) {
|
|
418
|
+
const kif = props['k-if'];
|
|
419
|
+
let condition = kif; // assume boolean by default
|
|
420
|
+
// Handle reactive k-if
|
|
421
|
+
if (isKT$1(kif)) {
|
|
422
|
+
kif.addOnChange((newValue, oldValue) => {
|
|
423
|
+
if (newValue === oldValue) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
const oldEl = el;
|
|
427
|
+
el = newValue ? create(tag, props) : placeholder();
|
|
428
|
+
$replaceNode$1(oldEl, el);
|
|
429
|
+
maybeDummyRef.value = el;
|
|
430
|
+
});
|
|
431
|
+
condition = kif.value;
|
|
432
|
+
}
|
|
433
|
+
if (!condition) {
|
|
434
|
+
// & make comment placeholder in case that ref might be redrawn later
|
|
435
|
+
el = placeholder();
|
|
436
|
+
maybeDummyRef.value = el;
|
|
437
|
+
return el;
|
|
438
|
+
}
|
|
272
439
|
}
|
|
273
|
-
|
|
440
|
+
el = create(tag, props);
|
|
441
|
+
maybeDummyRef.value = el;
|
|
274
442
|
return el;
|
|
275
443
|
}
|
|
276
444
|
/**
|
|
@@ -279,48 +447,8 @@ function jsx(tag, props) {
|
|
|
279
447
|
*/
|
|
280
448
|
const jsxs = jsx;
|
|
281
449
|
|
|
282
|
-
// Cached native methods for performance optimization
|
|
283
|
-
const $defines = Object.defineProperties;
|
|
284
|
-
|
|
285
|
-
// String manipulation utilities
|
|
286
|
-
/**
|
|
287
|
-
* Default empty function
|
|
288
|
-
*/
|
|
289
|
-
const $emptyFn = (() => true);
|
|
290
|
-
const { get: $buttonDisabledGetter$1, set: $buttonDisabledSetter$1 } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
|
|
291
|
-
// # DOM utilities
|
|
292
|
-
const parseStyle = (style) => {
|
|
293
|
-
if (typeof style === 'string') {
|
|
294
|
-
return style;
|
|
295
|
-
}
|
|
296
|
-
if (style && typeof style === 'object') {
|
|
297
|
-
return Object.entries(style)
|
|
298
|
-
.map(([key, value]) => {
|
|
299
|
-
// Convert camelCase to kebab-case
|
|
300
|
-
const cssKey = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
301
|
-
return `${cssKey}: ${value}`;
|
|
302
|
-
})
|
|
303
|
-
.join('; ');
|
|
304
|
-
}
|
|
305
|
-
return '';
|
|
306
|
-
};
|
|
307
|
-
const generateHandler = (props, key) => {
|
|
308
|
-
const handler = props[key];
|
|
309
|
-
if (typeof handler === 'function') {
|
|
310
|
-
return handler;
|
|
311
|
-
}
|
|
312
|
-
else if (handler && typeof handler === 'object' && handler.isKT) {
|
|
313
|
-
return (value) => (handler.value = value);
|
|
314
|
-
}
|
|
315
|
-
return $emptyFn;
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
// Shared utilities and cached native methods for kt.js framework
|
|
319
|
-
// Re-export all utilities
|
|
320
|
-
Object.defineProperty(window, '@ktjs/shared', { value: '0.20.0' });
|
|
321
|
-
|
|
322
450
|
function Alert(props) {
|
|
323
|
-
const { children, severity = 'info', variant = 'standard', icon, '
|
|
451
|
+
const { children, severity = 'info', variant = 'standard', icon, 'on:close': onClose } = props;
|
|
324
452
|
const classes = `mui-alert mui-alert-${severity} mui-alert-${variant} ${props.class ? props.class : ''}`;
|
|
325
453
|
// Icon SVG paths for different severities
|
|
326
454
|
const getIcon = () => {
|
|
@@ -349,201 +477,409 @@ function Alert(props) {
|
|
|
349
477
|
return alert;
|
|
350
478
|
}
|
|
351
479
|
|
|
480
|
+
// Shared constants
|
|
481
|
+
// Empty for now - can be extended with framework-wide constants
|
|
352
482
|
/**
|
|
353
|
-
*
|
|
483
|
+
* Mark the attribute as SVG to handle special cases during rendering.
|
|
354
484
|
*/
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
const classes = [
|
|
358
|
-
'mui-button',
|
|
359
|
-
`mui-button-${variant}`,
|
|
360
|
-
`mui-button-${variant}-${color}`,
|
|
361
|
-
`mui-button-size-${size}`,
|
|
362
|
-
fullWidth ? 'mui-button-fullwidth' : '',
|
|
363
|
-
iconOnly ? 'mui-button-icon-only' : '',
|
|
364
|
-
disabled ? 'mui-button-disabled' : '',
|
|
365
|
-
props.class ? props.class : '',
|
|
366
|
-
].join(' ');
|
|
367
|
-
const rippleContainer = jsx("span", { class: "mui-button-ripple" });
|
|
368
|
-
const handleClick = (e) => {
|
|
369
|
-
if (disabled) {
|
|
370
|
-
e.preventDefault();
|
|
371
|
-
return;
|
|
372
|
-
}
|
|
373
|
-
// Create ripple effect
|
|
374
|
-
const button = e.currentTarget;
|
|
375
|
-
if (rippleContainer) {
|
|
376
|
-
const rect = button.getBoundingClientRect();
|
|
377
|
-
const size = Math.max(rect.width, rect.height);
|
|
378
|
-
const x = e.clientX - rect.left - size / 2;
|
|
379
|
-
const y = e.clientY - rect.top - size / 2;
|
|
380
|
-
const ripple = document.createElement('span');
|
|
381
|
-
ripple.style.width = ripple.style.height = `${size}px`;
|
|
382
|
-
ripple.style.left = `${x}px`;
|
|
383
|
-
ripple.style.top = `${y}px`;
|
|
384
|
-
ripple.classList.add('mui-button-ripple-effect');
|
|
385
|
-
rippleContainer.appendChild(ripple);
|
|
386
|
-
// Remove ripple after animation
|
|
387
|
-
setTimeout(() => ripple.remove(), 600);
|
|
388
|
-
}
|
|
389
|
-
onClick(e);
|
|
390
|
-
};
|
|
391
|
-
const container = (jsxs("button", { class: classes, style: parseStyle(props.style), type: type, disabled: disabled, "on:click": handleClick, children: [startIcon && jsx("span", { class: "mui-button-start-icon", children: startIcon }), jsx("span", { class: "mui-button-label", children: children }), endIcon && jsx("span", { class: "mui-button-end-icon", children: endIcon }), rippleContainer] }));
|
|
392
|
-
$defines(container, {
|
|
393
|
-
disabled: {
|
|
394
|
-
get: $buttonDisabledGetter$1,
|
|
395
|
-
set: function (value) {
|
|
396
|
-
$buttonDisabledSetter$1.call(this, value);
|
|
397
|
-
this.classList.toggle('mui-button-disabled', value);
|
|
398
|
-
},
|
|
399
|
-
},
|
|
400
|
-
});
|
|
401
|
-
return container;
|
|
402
|
-
}
|
|
485
|
+
const $is = Object.is;
|
|
486
|
+
const $random = Math.random;
|
|
403
487
|
|
|
488
|
+
// DOM manipulation utilities
|
|
489
|
+
// # dom natives
|
|
490
|
+
const $isNode = (x) => x?.nodeType > 0;
|
|
404
491
|
/**
|
|
405
|
-
*
|
|
492
|
+
* Safe replace `oldNode` With `newNode`
|
|
406
493
|
*/
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
if (
|
|
410
|
-
|
|
411
|
-
checkedIcon.style.display = 'none';
|
|
412
|
-
indeterminateIcon.style.display = '';
|
|
413
|
-
}
|
|
414
|
-
else {
|
|
415
|
-
uncheckedIcon.style.display = checked ? 'none' : '';
|
|
416
|
-
checkedIcon.style.display = checked ? '' : 'none';
|
|
417
|
-
indeterminateIcon.style.display = 'none';
|
|
494
|
+
const $replaceNode = (oldNode, newNode) => {
|
|
495
|
+
if ($isNode(oldNode) && $isNode(newNode)) {
|
|
496
|
+
if (newNode.contains(oldNode)) {
|
|
497
|
+
newNode.remove();
|
|
418
498
|
}
|
|
499
|
+
oldNode.replaceWith(newNode);
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
const { get: $buttonDisabledGetter, set: $buttonDisabledSetter } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
|
|
503
|
+
|
|
504
|
+
if (typeof Symbol === 'undefined') {
|
|
505
|
+
window.Symbol = function Symbol(description) {
|
|
506
|
+
return `@@SYMBOL_${description || ''}_${$random().toString(36).slice(2)}`;
|
|
419
507
|
};
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Shared utilities and cached native methods for kt.js framework
|
|
511
|
+
Object.defineProperty(window, '__ktjs__', { value: '0.23.4' });
|
|
512
|
+
|
|
513
|
+
const isKT = (obj) => obj?.isKT;
|
|
514
|
+
|
|
515
|
+
class KTRef {
|
|
516
|
+
/**
|
|
517
|
+
* Indicates that this is a KTRef instance
|
|
518
|
+
*/
|
|
519
|
+
isKT = true;
|
|
520
|
+
ktType = 1 /* KTReactiveType.REF */;
|
|
521
|
+
/**
|
|
522
|
+
* @internal
|
|
523
|
+
*/
|
|
524
|
+
_value;
|
|
525
|
+
/**
|
|
526
|
+
* @internal
|
|
527
|
+
*/
|
|
528
|
+
_onChanges;
|
|
529
|
+
constructor(_value, _onChanges) {
|
|
530
|
+
this._value = _value;
|
|
531
|
+
this._onChanges = _onChanges;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* If new value and old value are both nodes, the old one will be replaced in the DOM
|
|
535
|
+
*/
|
|
536
|
+
get value() {
|
|
537
|
+
return this._value;
|
|
538
|
+
}
|
|
539
|
+
set value(newValue) {
|
|
540
|
+
if ($is(newValue, this._value)) {
|
|
423
541
|
return;
|
|
424
542
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
toggleIcon(checked, indeterminate);
|
|
452
|
-
},
|
|
453
|
-
},
|
|
454
|
-
value: {
|
|
455
|
-
get() {
|
|
456
|
-
return value;
|
|
457
|
-
},
|
|
458
|
-
set(newValue) {
|
|
459
|
-
value = newValue;
|
|
460
|
-
inputEl.value = value;
|
|
461
|
-
},
|
|
462
|
-
},
|
|
463
|
-
disabled: {
|
|
464
|
-
get() {
|
|
465
|
-
return disabled;
|
|
466
|
-
},
|
|
467
|
-
set(newDisabled) {
|
|
468
|
-
disabled = Boolean(newDisabled);
|
|
469
|
-
inputEl.disabled = disabled;
|
|
470
|
-
container.classList.toggle('mui-checkbox-disabled', disabled);
|
|
471
|
-
},
|
|
472
|
-
},
|
|
473
|
-
});
|
|
474
|
-
return container;
|
|
543
|
+
const oldValue = this._value;
|
|
544
|
+
$replaceNode(oldValue, newValue);
|
|
545
|
+
this._value = newValue;
|
|
546
|
+
for (let i = 0; i < this._onChanges.length; i++) {
|
|
547
|
+
this._onChanges[i](newValue, oldValue);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Register a callback when the value changes
|
|
552
|
+
* @param callback (newValue, oldValue) => xxx
|
|
553
|
+
*/
|
|
554
|
+
addOnChange(callback) {
|
|
555
|
+
if (typeof callback !== 'function') {
|
|
556
|
+
throw new Error('[kt.js error] KTRef.addOnChange: callback must be a function');
|
|
557
|
+
}
|
|
558
|
+
this._onChanges.push(callback);
|
|
559
|
+
}
|
|
560
|
+
removeOnChange(callback) {
|
|
561
|
+
for (let i = this._onChanges.length - 1; i >= 0; i--) {
|
|
562
|
+
if (this._onChanges[i] === callback) {
|
|
563
|
+
this._onChanges.splice(i, 1);
|
|
564
|
+
return true;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
475
569
|
}
|
|
476
570
|
/**
|
|
477
|
-
*
|
|
571
|
+
* Reference to the created HTML element.
|
|
572
|
+
* - **Only** respond to `ref.value` changes, not reactive to internal changes of the element.
|
|
573
|
+
* - can alse be used to store normal values, but it is not reactive.
|
|
574
|
+
* - if the value is already a `KTRef`, it will be returned **directly**.
|
|
575
|
+
* @param value mostly an HTMLElement
|
|
478
576
|
*/
|
|
479
|
-
function
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
577
|
+
function ref(value, onChange) {
|
|
578
|
+
return new KTRef(value, onChange ? [onChange] : []);
|
|
579
|
+
}
|
|
580
|
+
function deref(value) {
|
|
581
|
+
return isKT(value) ? value.value : value;
|
|
582
|
+
}
|
|
583
|
+
// # asserts
|
|
584
|
+
/**
|
|
585
|
+
* Assert k-model to be a ref object
|
|
586
|
+
*/
|
|
587
|
+
const $modelOrRef = (props, defaultValue) => {
|
|
588
|
+
// & props is an object. Won't use it in any other place
|
|
589
|
+
if ('k-model' in props) {
|
|
590
|
+
const kmodel = props['k-model'];
|
|
591
|
+
if (!kmodel?.isKT) {
|
|
592
|
+
throw new Error(`[kt.js error] k-model data must be a KTRef object, please use 'ref(...)' to wrap it.`);
|
|
489
593
|
}
|
|
490
|
-
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
594
|
+
return kmodel;
|
|
595
|
+
}
|
|
596
|
+
return ref(defaultValue);
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
class KTComputed {
|
|
600
|
+
/**
|
|
601
|
+
* Indicates that this is a KTRef instance
|
|
602
|
+
*/
|
|
603
|
+
isKT = true;
|
|
604
|
+
ktType = 2 /* KTReactiveType.COMPUTED */;
|
|
605
|
+
/**
|
|
606
|
+
* @internal
|
|
607
|
+
*/
|
|
608
|
+
_calculator;
|
|
609
|
+
/**
|
|
610
|
+
* @internal
|
|
611
|
+
*/
|
|
612
|
+
_value;
|
|
613
|
+
/**
|
|
614
|
+
* @internal
|
|
615
|
+
*/
|
|
616
|
+
_onChanges = [];
|
|
617
|
+
/**
|
|
618
|
+
* @internal
|
|
619
|
+
*/
|
|
620
|
+
_subscribe(reactives) {
|
|
621
|
+
for (let i = 0; i < reactives.length; i++) {
|
|
622
|
+
const reactive = reactives[i];
|
|
623
|
+
reactive.addOnChange(() => {
|
|
624
|
+
const oldValue = this._value;
|
|
625
|
+
this._value = this._calculator();
|
|
626
|
+
if (oldValue === this._value) {
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
$replaceNode(oldValue, this._value);
|
|
630
|
+
for (let i = 0; i < this._onChanges.length; i++) {
|
|
631
|
+
this._onChanges[i](this._value, oldValue);
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
constructor(_calculator, reactives) {
|
|
637
|
+
this._calculator = _calculator;
|
|
638
|
+
this._value = _calculator();
|
|
639
|
+
this._subscribe(reactives);
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* If new value and old value are both nodes, the old one will be replaced in the DOM
|
|
643
|
+
*/
|
|
644
|
+
get value() {
|
|
645
|
+
return this._value;
|
|
646
|
+
}
|
|
647
|
+
set value(_newValue) {
|
|
648
|
+
throw new Error('[kt.js error] KTComputed: cannot set value of a computed value');
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Register a callback when the value changes
|
|
652
|
+
* @param callback (newValue, oldValue) => xxx
|
|
653
|
+
*/
|
|
654
|
+
addOnChange(callback) {
|
|
655
|
+
if (typeof callback !== 'function') {
|
|
656
|
+
throw new Error('[kt.js error] KTRef.addOnChange: callback must be a function');
|
|
657
|
+
}
|
|
658
|
+
this._onChanges.push(callback);
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Unregister a callback
|
|
662
|
+
* @param callback (newValue, oldValue) => xxx
|
|
663
|
+
*/
|
|
664
|
+
removeOnChange(callback) {
|
|
665
|
+
for (let i = this._onChanges.length - 1; i >= 0; i--) {
|
|
666
|
+
if (this._onChanges[i] === callback) {
|
|
667
|
+
this._onChanges.splice(i, 1);
|
|
668
|
+
return true;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
return false;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Create a reactive computed value
|
|
676
|
+
* @param computeFn
|
|
677
|
+
* @param reactives refs and computeds that this computed depends on
|
|
678
|
+
*/
|
|
679
|
+
function computed(computeFn, reactives) {
|
|
680
|
+
if (reactives.some((v) => !isKT(v))) {
|
|
681
|
+
throw new Error('[kt.js error] computed: all reactives must be KTRef or KTComputed instances');
|
|
682
|
+
}
|
|
683
|
+
return new KTComputed(computeFn, reactives);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
const toReactive = (value, onChange) => {
|
|
687
|
+
if (isKT(value)) {
|
|
688
|
+
if (onChange) {
|
|
689
|
+
value.addOnChange(onChange);
|
|
690
|
+
}
|
|
691
|
+
return value;
|
|
692
|
+
}
|
|
693
|
+
else {
|
|
694
|
+
return ref(value, onChange);
|
|
695
|
+
}
|
|
696
|
+
};
|
|
697
|
+
|
|
698
|
+
const registerPrefixedEventsForButton = (element, props) => {
|
|
699
|
+
for (const key in props) {
|
|
700
|
+
if (key.startsWith('on:') && key !== 'on:click' && key !== 'on:dblclick') {
|
|
701
|
+
element.addEventListener(key.slice(3), props[key]);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
};
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Button component - mimics MUI Button appearance and behavior
|
|
708
|
+
*/
|
|
709
|
+
function Button(props) {
|
|
710
|
+
let { children, variant = 'text', color = 'primary', size = 'medium', disabled = false, fullWidth = false, iconOnly = false, startIcon, endIcon, type = 'button', 'on:click': onClick = $emptyFn, // & must be bound because of the ripple effect
|
|
711
|
+
} = props;
|
|
712
|
+
const updateClass = () => {
|
|
713
|
+
container.className = [
|
|
714
|
+
'mui-button',
|
|
715
|
+
`mui-button-${variant}`,
|
|
716
|
+
`mui-button-${variant}-${color}`,
|
|
717
|
+
`mui-button-size-${size}`,
|
|
718
|
+
fullWidth ? 'mui-button-fullwidth' : '',
|
|
719
|
+
iconOnly ? 'mui-button-icon-only' : '',
|
|
720
|
+
disabledRef.value ? 'mui-button-disabled' : '',
|
|
721
|
+
props.class ? props.class : '',
|
|
722
|
+
].join(' ');
|
|
723
|
+
};
|
|
724
|
+
const disabledRef = toReactive(disabled, (v) => {
|
|
725
|
+
container.disabled = v;
|
|
726
|
+
updateClass();
|
|
727
|
+
});
|
|
728
|
+
const rippleContainer = jsx("span", { class: "mui-button-ripple" });
|
|
729
|
+
const createRippleEffect = (mouseX, mouseY) => {
|
|
730
|
+
const rect = container.getBoundingClientRect();
|
|
731
|
+
const size = Math.max(rect.width, rect.height);
|
|
732
|
+
const x = mouseX - rect.left - size / 2;
|
|
733
|
+
const y = mouseY - rect.top - size / 2;
|
|
734
|
+
const ripple = (jsx("span", { class: "mui-button-ripple-effect", style: `width:${size}px; height:${size}px; left:${x}px; top:${y}px;` }));
|
|
735
|
+
rippleContainer.appendChild(ripple);
|
|
736
|
+
setTimeout(() => ripple.remove(), 600); // Remove ripple after animation
|
|
737
|
+
};
|
|
738
|
+
const handleClick = (e) => {
|
|
739
|
+
if (disabledRef.value) {
|
|
740
|
+
e.preventDefault();
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
createRippleEffect(e.clientX, e.clientY);
|
|
744
|
+
onClick(e);
|
|
745
|
+
};
|
|
746
|
+
const container = (jsxs("button", { style: parseStyle(props.style), type: type, disabled: disabledRef.value, "on:click": handleClick, children: [jsx("span", { "k-if": startIcon, class: "mui-button-start-icon", children: startIcon }), jsx("span", { class: "mui-button-label", children: children }), jsx("span", { "k-if": endIcon, class: "mui-button-end-icon", children: endIcon }), rippleContainer] }));
|
|
747
|
+
const onDblclick = props['on:dblclick'];
|
|
748
|
+
if (onDblclick) {
|
|
749
|
+
container.addEventListener('dblclick', (e) => {
|
|
750
|
+
if (disabledRef.value) {
|
|
751
|
+
e.preventDefault();
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
createRippleEffect(e.clientX, e.clientY);
|
|
755
|
+
onDblclick(e);
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
registerPrefixedEventsForButton(container, props);
|
|
759
|
+
// # initialize
|
|
760
|
+
updateClass();
|
|
761
|
+
return container;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
const $ArrayPushUnique = (arr, item) => {
|
|
765
|
+
if (!arr.includes(item)) {
|
|
766
|
+
arr.push(item);
|
|
767
|
+
}
|
|
768
|
+
};
|
|
769
|
+
const $ArrayDelete = (arr, item) => {
|
|
770
|
+
const index = arr.indexOf(item);
|
|
771
|
+
if (index > -1) {
|
|
772
|
+
arr.splice(index, 1);
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
|
|
776
|
+
const createUncheckedIcon = () => (jsx("span", { class: "mui-checkbox-icon-unchecked", children: jsx("svg", { viewBox: "0 0 24 24", children: jsx("path", { d: "M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z" }) }) }));
|
|
777
|
+
const createCheckedIcon = () => (jsx("span", { class: "mui-checkbox-icon-checked", children: jsx("svg", { viewBox: "0 0 24 24", children: jsx("path", { d: "M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" }) }) }));
|
|
778
|
+
const createIndeterminateIcon = () => (jsx("span", { class: "mui-checkbox-icon-indeterminate", children: jsx("svg", { viewBox: "0 0 24 24", children: jsx("path", { d: "M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10H7v-2h10v2z" }) }) }));
|
|
779
|
+
/**
|
|
780
|
+
* Checkbox component - mimics MUI Checkbox appearance and behavior
|
|
781
|
+
*/
|
|
782
|
+
function Checkbox(props) {
|
|
783
|
+
const toggleIcon = (checked, indeterminate) => {
|
|
784
|
+
if (indeterminate) {
|
|
785
|
+
uncheckedIcon.style.display = 'none';
|
|
786
|
+
checkedIcon.style.display = 'none';
|
|
787
|
+
indeterminateIcon.style.display = '';
|
|
501
788
|
}
|
|
502
789
|
else {
|
|
503
|
-
|
|
790
|
+
uncheckedIcon.style.display = checked ? 'none' : '';
|
|
791
|
+
checkedIcon.style.display = checked ? '' : 'none';
|
|
792
|
+
indeterminateIcon.style.display = 'none';
|
|
793
|
+
}
|
|
794
|
+
};
|
|
795
|
+
// Handle change
|
|
796
|
+
const handleChange = () => {
|
|
797
|
+
if (disabledRef.value) {
|
|
798
|
+
return;
|
|
504
799
|
}
|
|
505
|
-
|
|
800
|
+
modelRef.value = inputEl.checked;
|
|
801
|
+
interminateRef.value = false;
|
|
802
|
+
toggleIcon(modelRef.value, interminateRef.value);
|
|
803
|
+
onChange(modelRef.value, valueRef.value);
|
|
804
|
+
};
|
|
805
|
+
const onChange = props['on:change'] ?? $emptyFn;
|
|
806
|
+
const labelRef = toReactive(props.label ?? '');
|
|
807
|
+
const valueRef = toReactive(props.value ?? '');
|
|
808
|
+
const interminateRef = toReactive(props.indeterminate ?? false);
|
|
809
|
+
const colorRef = toReactive(props.color ?? 'primary');
|
|
810
|
+
const sizeRef = toReactive(props.size ?? 'medium');
|
|
811
|
+
const disabledRef = toReactive(props.disabled ?? false, (v) => {
|
|
812
|
+
inputEl.disabled = v;
|
|
813
|
+
container.classList.toggle('mui-checkbox-disabled', v);
|
|
506
814
|
});
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
return Array.from(selectedValues);
|
|
512
|
-
},
|
|
513
|
-
set(newValues) {
|
|
514
|
-
selectedValues = new Set(newValues);
|
|
515
|
-
for (let i = 0; i < checkboxes.length; i++) {
|
|
516
|
-
const checkbox = checkboxes[i];
|
|
517
|
-
checkbox.checked = selectedValues.has(checkbox.value);
|
|
518
|
-
}
|
|
519
|
-
},
|
|
520
|
-
},
|
|
521
|
-
disabled: {
|
|
522
|
-
get() {
|
|
523
|
-
return checkboxes.map((cb) => cb.disabled);
|
|
524
|
-
},
|
|
525
|
-
set(newDisabled) {
|
|
526
|
-
for (let i = 0; i < checkboxes.length; i++) {
|
|
527
|
-
const checkbox = checkboxes[i];
|
|
528
|
-
checkbox.disabled = Boolean(newDisabled);
|
|
529
|
-
}
|
|
530
|
-
},
|
|
531
|
-
},
|
|
532
|
-
disableAll: {
|
|
533
|
-
value: () => {
|
|
534
|
-
for (let i = 0; i < checkboxes.length; i++) {
|
|
535
|
-
checkboxes[i].disabled = true;
|
|
536
|
-
}
|
|
537
|
-
},
|
|
538
|
-
},
|
|
539
|
-
enableAll: {
|
|
540
|
-
value: () => {
|
|
541
|
-
for (let i = 0; i < checkboxes.length; i++) {
|
|
542
|
-
checkboxes[i].disabled = false;
|
|
543
|
-
}
|
|
544
|
-
},
|
|
545
|
-
},
|
|
815
|
+
const modelRef = $modelOrRef(props, props.checked ?? false);
|
|
816
|
+
modelRef.addOnChange((newValue) => {
|
|
817
|
+
inputEl.checked = newValue;
|
|
818
|
+
toggleIcon(newValue, interminateRef.value);
|
|
546
819
|
});
|
|
820
|
+
const inputEl = (jsx("input", { type: "checkbox", class: "mui-checkbox-input", checked: modelRef.value, value: valueRef, disabled: disabledRef, "on:change": handleChange }));
|
|
821
|
+
const uncheckedIcon = createUncheckedIcon();
|
|
822
|
+
const checkedIcon = createCheckedIcon();
|
|
823
|
+
const indeterminateIcon = createIndeterminateIcon();
|
|
824
|
+
// Initialize icon state
|
|
825
|
+
toggleIcon(modelRef.value, interminateRef.value);
|
|
826
|
+
const classRef = computed(() => {
|
|
827
|
+
return `mui-checkbox-wrapper mui-checkbox-size-${sizeRef.value} ${disabledRef.value ? 'mui-checkbox-disabled' : ''} mui-checkbox-color-${colorRef.value}`;
|
|
828
|
+
}, [colorRef, disabledRef, sizeRef]);
|
|
829
|
+
const container = (jsxs("label", { class: classRef, children: [inputEl, jsxs("span", { class: "mui-checkbox-icon", children: [uncheckedIcon, checkedIcon, indeterminateIcon] }), jsx("span", { "k-if": labelRef, class: "mui-checkbox-label", children: labelRef })] }));
|
|
830
|
+
return container;
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* CheckboxGroup component - groups multiple checkboxes together
|
|
834
|
+
*/
|
|
835
|
+
function CheckboxGroup(props) {
|
|
836
|
+
let { row = false, 'on:change': onChange = $emptyFn } = props;
|
|
837
|
+
const changeHandler = (checked, checkboxValue) => {
|
|
838
|
+
if (checked) {
|
|
839
|
+
$ArrayPushUnique(modelRef.value, checkboxValue);
|
|
840
|
+
}
|
|
841
|
+
else {
|
|
842
|
+
$ArrayDelete(modelRef.value, checkboxValue);
|
|
843
|
+
}
|
|
844
|
+
onChange(modelRef.value);
|
|
845
|
+
};
|
|
846
|
+
const rowRef = toReactive(props.row ?? true);
|
|
847
|
+
const sizeRef = toReactive(props.size ?? 'medium');
|
|
848
|
+
const modelRef = $modelOrRef(props, props.value ?? []);
|
|
849
|
+
modelRef.addOnChange((newValues) => {
|
|
850
|
+
for (let i = 0; i < checkboxes.value.length; i++) {
|
|
851
|
+
const c = checkboxes.value[i];
|
|
852
|
+
c.checked = newValues.includes(c.value);
|
|
853
|
+
}
|
|
854
|
+
});
|
|
855
|
+
const customClassRef = toReactive(props.class ?? '');
|
|
856
|
+
const classRef = computed(() => {
|
|
857
|
+
return `mui-checkbox-group ${rowRef.value ? 'mui-checkbox-group-row' : ''} ${customClassRef.value}`;
|
|
858
|
+
}, [rowRef, customClassRef]);
|
|
859
|
+
const styleRef = toReactive(parseStyle(props.style ?? ''));
|
|
860
|
+
const optionsRef = toReactive(props.options);
|
|
861
|
+
const checkboxes = computed(() => {
|
|
862
|
+
return optionsRef.value.map((o) => {
|
|
863
|
+
o.size = sizeRef.value;
|
|
864
|
+
o.checked = modelRef.value.includes(o.value);
|
|
865
|
+
const originalChange = o['on:change'];
|
|
866
|
+
if (originalChange) {
|
|
867
|
+
if (typeof originalChange !== 'function') {
|
|
868
|
+
throw new Error('[kt.js error] CheckboxGroup: handler must be a function');
|
|
869
|
+
}
|
|
870
|
+
o['on:change'] = (checked, value) => {
|
|
871
|
+
originalChange(checked, value);
|
|
872
|
+
changeHandler(checked, value);
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
else {
|
|
876
|
+
o['on:change'] = changeHandler;
|
|
877
|
+
}
|
|
878
|
+
return Checkbox(o);
|
|
879
|
+
});
|
|
880
|
+
}, [optionsRef, sizeRef]);
|
|
881
|
+
console.log('checkboxes', checkboxes.value);
|
|
882
|
+
const container = (jsx("div", { class: classRef, style: styleRef, role: "group", children: checkboxes }));
|
|
547
883
|
return container;
|
|
548
884
|
}
|
|
549
885
|
|
|
@@ -552,11 +888,30 @@ function CheckboxGroup(props) {
|
|
|
552
888
|
* Only handles open/close state, title and content are passed as props
|
|
553
889
|
*/
|
|
554
890
|
function Dialog(props) {
|
|
555
|
-
let {
|
|
891
|
+
let { 'on:close': onClose = $emptyFn, children, actions } = props;
|
|
892
|
+
const titleRef = toReactive(props.title ?? '');
|
|
893
|
+
const openRef = toReactive(props.open ?? false, (isOpen) => {
|
|
894
|
+
if (isOpen) {
|
|
895
|
+
// Opening: set display first, then add class with double RAF for animation
|
|
896
|
+
container.style.display = 'flex';
|
|
897
|
+
setTimeout(() => container.classList.add('kt-dialog-backdrop-open'), 50);
|
|
898
|
+
}
|
|
899
|
+
else {
|
|
900
|
+
container.classList.remove('kt-dialog-backdrop-open');
|
|
901
|
+
setTimeout(() => {
|
|
902
|
+
if (!openRef.value) {
|
|
903
|
+
container.style.display = 'none';
|
|
904
|
+
}
|
|
905
|
+
}, 225);
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
const sizeRef = toReactive(props.size ?? 'sm');
|
|
909
|
+
const fullWidthRef = toReactive(props.fullWidth ?? false);
|
|
910
|
+
const classNameRef = computed(() => `kt-dialog-paper ${sizeRef.value ? `kt-dialog-maxWidth-${sizeRef.value}` : ''} ${fullWidthRef.value ? 'kt-dialog-fullWidth' : ''}`, [sizeRef, fullWidthRef]);
|
|
556
911
|
// Handle ESC key - store handler for cleanup
|
|
557
912
|
const keyDownHandler = (e) => {
|
|
558
913
|
if (e.key === 'Escape') {
|
|
559
|
-
|
|
914
|
+
openRef.value = false;
|
|
560
915
|
onClose();
|
|
561
916
|
}
|
|
562
917
|
};
|
|
@@ -566,7 +921,7 @@ function Dialog(props) {
|
|
|
566
921
|
}
|
|
567
922
|
};
|
|
568
923
|
// Backdrop element
|
|
569
|
-
const container = (jsx("div", { class: `kt-dialog-backdrop ${
|
|
924
|
+
const container = (jsx("div", { class: `kt-dialog-backdrop ${openRef.value ? 'kt-dialog-backdrop-open' : ''}`, style: { display: openRef.value ? 'flex' : 'none' }, "on:click": handleBackdropClick, children: jsxs("div", { class: classNameRef, "on:click": (e) => e.stopPropagation(), children: [jsx("div", { "k-if": titleRef, class: "kt-dialog-title", children: jsx("h2", { children: titleRef }) }), jsx("div", { "k-if": children, class: "kt-dialog-content", children: children }), jsx("div", { "k-if": actions, class: "kt-dialog-actions", children: actions })] }) }));
|
|
570
925
|
document.addEventListener('keydown', keyDownHandler);
|
|
571
926
|
// Store cleanup function
|
|
572
927
|
const originalRemove = container.remove;
|
|
@@ -576,30 +931,6 @@ function Dialog(props) {
|
|
|
576
931
|
}
|
|
577
932
|
return originalRemove.call(container);
|
|
578
933
|
};
|
|
579
|
-
$defines(container, {
|
|
580
|
-
open: {
|
|
581
|
-
get: () => open,
|
|
582
|
-
set: (isOpen) => {
|
|
583
|
-
if (isOpen === open) {
|
|
584
|
-
return;
|
|
585
|
-
}
|
|
586
|
-
open = isOpen;
|
|
587
|
-
if (isOpen) {
|
|
588
|
-
// Opening: set display first, then add class with double RAF for animation
|
|
589
|
-
container.style.display = 'flex';
|
|
590
|
-
setTimeout(() => container.classList.add('kt-dialog-backdrop-open'), 50);
|
|
591
|
-
}
|
|
592
|
-
else {
|
|
593
|
-
container.classList.remove('kt-dialog-backdrop-open');
|
|
594
|
-
setTimeout(() => {
|
|
595
|
-
if (!open) {
|
|
596
|
-
container.style.display = 'none';
|
|
597
|
-
}
|
|
598
|
-
}, 225);
|
|
599
|
-
}
|
|
600
|
-
},
|
|
601
|
-
},
|
|
602
|
-
});
|
|
603
934
|
return container;
|
|
604
935
|
}
|
|
605
936
|
|
|
@@ -627,192 +958,68 @@ function FormLabel(props) {
|
|
|
627
958
|
return element;
|
|
628
959
|
}
|
|
629
960
|
|
|
630
|
-
// Cached native methods for performance optimization
|
|
631
|
-
const { get: $buttonDisabledGetter, set: $buttonDisabledSetter } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
|
|
632
|
-
|
|
633
|
-
// Shared utilities and cached native methods for kt.js framework
|
|
634
|
-
// Re-export all utilities
|
|
635
|
-
Object.defineProperty(window, '@ktjs/shared', { value: '0.20.0' });
|
|
636
|
-
|
|
637
|
-
document.createElement('div');
|
|
638
|
-
|
|
639
|
-
class KTRef {
|
|
640
|
-
/**
|
|
641
|
-
* Indicates that this is a KTRef instance
|
|
642
|
-
*/
|
|
643
|
-
isKT = true;
|
|
644
|
-
/**
|
|
645
|
-
* @internal
|
|
646
|
-
*/
|
|
647
|
-
_value;
|
|
648
|
-
/**
|
|
649
|
-
* @internal
|
|
650
|
-
*/
|
|
651
|
-
_onChanges;
|
|
652
|
-
constructor(_value, _onChanges) {
|
|
653
|
-
this._value = _value;
|
|
654
|
-
this._onChanges = _onChanges;
|
|
655
|
-
}
|
|
656
|
-
/**
|
|
657
|
-
* If new value and old value are both nodes, the old one will be replaced in the DOM
|
|
658
|
-
*/
|
|
659
|
-
get value() {
|
|
660
|
-
return this._value;
|
|
661
|
-
}
|
|
662
|
-
set value(newValue) {
|
|
663
|
-
if (newValue === this._value) {
|
|
664
|
-
return;
|
|
665
|
-
}
|
|
666
|
-
// replace the old node with the new one in the DOM if both are nodes
|
|
667
|
-
if (this._value instanceof Node && newValue instanceof Node) {
|
|
668
|
-
if (newValue.contains(this._value)) {
|
|
669
|
-
this._value.remove();
|
|
670
|
-
}
|
|
671
|
-
this._value.replaceWith(newValue);
|
|
672
|
-
}
|
|
673
|
-
const oldValue = this._value;
|
|
674
|
-
this._value = newValue;
|
|
675
|
-
for (let i = 0; i < this._onChanges.length; i++) {
|
|
676
|
-
this._onChanges[i](newValue, oldValue);
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
addOnChange(callback) {
|
|
680
|
-
this._onChanges.push(callback);
|
|
681
|
-
}
|
|
682
|
-
removeOnChange(callback) {
|
|
683
|
-
for (let i = this._onChanges.length - 1; i >= 0; i--) {
|
|
684
|
-
if (this._onChanges[i] === callback) {
|
|
685
|
-
this._onChanges.splice(i, 1);
|
|
686
|
-
return true;
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
return false;
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
/**
|
|
693
|
-
* Reference to the created HTML element.
|
|
694
|
-
* - can alse be used to store normal values, but it is not reactive.
|
|
695
|
-
* @param value mostly an HTMLElement
|
|
696
|
-
*/
|
|
697
|
-
function ref(value, onChange) {
|
|
698
|
-
return new KTRef(value, []);
|
|
699
|
-
}
|
|
700
|
-
/**
|
|
701
|
-
* A helper to create redrawable elements
|
|
702
|
-
* ```tsx
|
|
703
|
-
* export function MyComponent() {
|
|
704
|
-
* let aa = 10;
|
|
705
|
-
* // ...
|
|
706
|
-
* // aa might be changed
|
|
707
|
-
* return createRedrawable(() => <div>{aa}</div>);
|
|
708
|
-
* }
|
|
709
|
-
* ```
|
|
710
|
-
* Then the returned element has a `redraw` method to redraw itself with new values.
|
|
711
|
-
* @param creator a simple creator function that returns an element
|
|
712
|
-
* @returns created element's ref
|
|
713
|
-
*/
|
|
714
|
-
function createRedrawable(creator) {
|
|
715
|
-
const elRef = ref();
|
|
716
|
-
const redraw = () => {
|
|
717
|
-
elRef.value = creator(); // ref setter automatically calls replaceWith
|
|
718
|
-
elRef.redraw = redraw;
|
|
719
|
-
return elRef.value;
|
|
720
|
-
};
|
|
721
|
-
redraw();
|
|
722
|
-
return elRef;
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
/**
|
|
726
|
-
* LinearProgress component - mimics MUI LinearProgress appearance and behavior
|
|
727
|
-
*/
|
|
728
961
|
function LinearProgress(props) {
|
|
729
|
-
|
|
730
|
-
const
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
]
|
|
736
|
-
const
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
const container = (jsx("div", { class:
|
|
741
|
-
$defines(container, {
|
|
742
|
-
progress: {
|
|
743
|
-
get() {
|
|
744
|
-
return progressValue;
|
|
745
|
-
},
|
|
746
|
-
set(newValue) {
|
|
747
|
-
progressValue = Math.min(Math.max(newValue, 0), 100);
|
|
748
|
-
if (variant === 'determinate') {
|
|
749
|
-
barRef.value.style.width = `${progressValue}%`;
|
|
750
|
-
}
|
|
751
|
-
},
|
|
752
|
-
},
|
|
753
|
-
});
|
|
962
|
+
const valueRef = ref(props.progress ?? 0);
|
|
963
|
+
const customClassRef = toReactive(props.class ?? '');
|
|
964
|
+
const colorRef = toReactive(props.color ?? 'primary');
|
|
965
|
+
const variantRef = toReactive(props.variant ?? 'indeterminate');
|
|
966
|
+
const classRef = computed(() => {
|
|
967
|
+
return `mui-linear-progress mui-linear-progress-${variantRef.value} mui-linear-progress-${colorRef.value} ${customClassRef.value}`;
|
|
968
|
+
}, [customClassRef, colorRef, variantRef]);
|
|
969
|
+
const styleRef = toReactive(props.style ?? '');
|
|
970
|
+
const barLengthRef = computed(() => {
|
|
971
|
+
return variantRef.value === 'determinate' ? `width: ${valueRef.value}%` : '';
|
|
972
|
+
}, [variantRef, valueRef]);
|
|
973
|
+
const container = (jsx("div", { class: classRef, style: styleRef, role: "progressbar", "aria-valuenow": valueRef, children: jsx("div", { class: "mui-linear-progress-bar", style: barLengthRef }) }));
|
|
754
974
|
return container;
|
|
755
975
|
}
|
|
756
976
|
|
|
757
|
-
/**
|
|
758
|
-
* TextField component - mimics MUI TextField appearance and behavior
|
|
759
|
-
*/
|
|
760
977
|
function TextField(props) {
|
|
761
|
-
|
|
762
|
-
const onInput =
|
|
763
|
-
const onInputTrim =
|
|
764
|
-
const onChange =
|
|
765
|
-
const onChangeTrim =
|
|
766
|
-
const onBlur =
|
|
767
|
-
const onFocus =
|
|
768
|
-
const
|
|
769
|
-
|
|
770
|
-
'mui-textfield-root',
|
|
771
|
-
`mui-textfield-size-${size}`,
|
|
772
|
-
isFocused ? 'mui-textfield-focused' : '',
|
|
773
|
-
error ? 'mui-textfield-error' : '',
|
|
774
|
-
disabled ? 'mui-textfield-disabled' : '',
|
|
775
|
-
fullWidth ? 'mui-textfield-fullwidth' : '',
|
|
776
|
-
label && inputEl.value ? 'mui-textfield-has-value' : '',
|
|
777
|
-
label ? '' : 'mui-textfield-no-label',
|
|
778
|
-
].join(' ');
|
|
779
|
-
};
|
|
978
|
+
// # events
|
|
979
|
+
const onInput = props['on:input'] ?? $emptyFn;
|
|
980
|
+
const onInputTrim = props['on-trim:input'] ?? $emptyFn;
|
|
981
|
+
const onChange = props['on:change'] ?? $emptyFn;
|
|
982
|
+
const onChangeTrim = props['on-trim:change'] ?? $emptyFn;
|
|
983
|
+
const onBlur = props['on:blur'] ?? $emptyFn;
|
|
984
|
+
const onFocus = props['on:focus'] ?? $emptyFn;
|
|
985
|
+
const isFocusedRef = ref(false);
|
|
986
|
+
// # methods
|
|
780
987
|
const handleInput = () => {
|
|
781
|
-
|
|
782
|
-
if (type === 'number') {
|
|
988
|
+
if (inputType === 'number') {
|
|
783
989
|
const v = Number(inputEl.value);
|
|
990
|
+
modelRef.value = v;
|
|
784
991
|
onInput(v);
|
|
785
992
|
onInputTrim(v);
|
|
786
993
|
}
|
|
787
994
|
else {
|
|
995
|
+
modelRef.value = inputEl.value;
|
|
788
996
|
onInput(inputEl.value);
|
|
789
997
|
onInputTrim(inputEl.value.trim());
|
|
790
998
|
}
|
|
791
999
|
};
|
|
792
1000
|
const handleChange = () => {
|
|
793
|
-
|
|
794
|
-
if (type === 'number') {
|
|
1001
|
+
if (inputType === 'number') {
|
|
795
1002
|
const v = Number(inputEl.value);
|
|
1003
|
+
modelRef.value = v;
|
|
796
1004
|
onChange(v);
|
|
797
1005
|
onChangeTrim(v);
|
|
798
1006
|
}
|
|
799
1007
|
else {
|
|
1008
|
+
modelRef.value = inputEl.value;
|
|
800
1009
|
onChange(inputEl.value);
|
|
801
1010
|
onChangeTrim(inputEl.value.trim());
|
|
802
1011
|
}
|
|
803
1012
|
};
|
|
804
1013
|
const handleFocus = () => {
|
|
805
|
-
isFocused = true;
|
|
806
|
-
updateContainerClass();
|
|
1014
|
+
isFocused.value = true;
|
|
807
1015
|
onFocus(inputEl.value);
|
|
808
1016
|
};
|
|
809
1017
|
const handleBlur = () => {
|
|
810
|
-
isFocused = false;
|
|
811
|
-
updateContainerClass();
|
|
1018
|
+
isFocused.value = false;
|
|
812
1019
|
onBlur(inputEl.value);
|
|
813
1020
|
};
|
|
814
1021
|
const handleWrapperMouseDown = (e) => {
|
|
815
|
-
if (
|
|
1022
|
+
if (disabledRef.value) {
|
|
816
1023
|
return;
|
|
817
1024
|
}
|
|
818
1025
|
const target = e.target;
|
|
@@ -821,92 +1028,55 @@ function TextField(props) {
|
|
|
821
1028
|
}
|
|
822
1029
|
setTimeout(() => inputEl.focus(), 0);
|
|
823
1030
|
};
|
|
824
|
-
const getPlaceholder = () => (
|
|
825
|
-
|
|
1031
|
+
const getPlaceholder = () => (labelRef.value && !isFocused && !modelRef.value ? '' : placeholderRef.value);
|
|
1032
|
+
// # non-refs
|
|
1033
|
+
const inputType = deref(props.type ?? 'text');
|
|
1034
|
+
const multiline = props.multiline;
|
|
1035
|
+
// # refs
|
|
1036
|
+
// Create refs for all reactive properties
|
|
1037
|
+
const labelRef = toReactive(props.label ?? '');
|
|
1038
|
+
const placeholderRef = toReactive(props.placeholder ?? '', () => (inputEl.placeholder = getPlaceholder()));
|
|
1039
|
+
const disabledRef = toReactive(props.disabled ?? false);
|
|
1040
|
+
const readOnlyRef = toReactive(props.readOnly ?? false);
|
|
1041
|
+
const requiredRef = toReactive(props.required ?? false);
|
|
1042
|
+
const errorRef = toReactive(props.error ?? false);
|
|
1043
|
+
const helperTextRef = toReactive(props.helperText ?? '');
|
|
1044
|
+
const fullWidthRef = toReactive(props.fullWidth ?? false);
|
|
1045
|
+
const rowsRef = toReactive(props.rows ?? 3);
|
|
1046
|
+
const sizeRef = toReactive(props.size ?? 'medium');
|
|
1047
|
+
// k-model takes precedence over value prop for two-way binding
|
|
1048
|
+
const modelRef = $modelOrRef(props, props.value ?? '');
|
|
1049
|
+
// Add change listeners for reactive properties
|
|
1050
|
+
// `k-if` changing triggers redrawing, no need to do this again
|
|
1051
|
+
// // labelRef.addOnChange(() => {
|
|
1052
|
+
// // wrapperRef.redraw();
|
|
1053
|
+
// // updateContainerClass();
|
|
1054
|
+
// // });
|
|
1055
|
+
const isFocused = ref(false);
|
|
826
1056
|
const inputEl = multiline
|
|
827
|
-
? (jsx("textarea", { class: "mui-textfield-input", placeholder: getPlaceholder(), value: value, disabled:
|
|
828
|
-
: (jsx("input", { type:
|
|
829
|
-
|
|
830
|
-
const
|
|
831
|
-
const
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
wrapperRef.redraw(); // label takes too much and should be redrawn
|
|
851
|
-
updateContainerClass();
|
|
852
|
-
},
|
|
853
|
-
},
|
|
854
|
-
placeholder: {
|
|
855
|
-
get() {
|
|
856
|
-
return placeholder;
|
|
857
|
-
},
|
|
858
|
-
set(newPlaceholder) {
|
|
859
|
-
placeholder = newPlaceholder;
|
|
860
|
-
inputEl.placeholder = getPlaceholder();
|
|
861
|
-
},
|
|
862
|
-
},
|
|
863
|
-
type: {
|
|
864
|
-
get() {
|
|
865
|
-
return type;
|
|
866
|
-
},
|
|
867
|
-
set(newType) {
|
|
868
|
-
type = newType || 'text';
|
|
869
|
-
inputEl.type = type;
|
|
870
|
-
},
|
|
871
|
-
},
|
|
872
|
-
disabled: {
|
|
873
|
-
get() {
|
|
874
|
-
return disabled;
|
|
875
|
-
},
|
|
876
|
-
set(val) {
|
|
877
|
-
disabled = !!val;
|
|
878
|
-
inputEl.disabled = disabled;
|
|
879
|
-
container.classList.toggle('mui-textfield-disabled', disabled);
|
|
880
|
-
},
|
|
881
|
-
},
|
|
882
|
-
readonly: {
|
|
883
|
-
get() {
|
|
884
|
-
return readonly;
|
|
885
|
-
},
|
|
886
|
-
set(val) {
|
|
887
|
-
readonly = Boolean(val);
|
|
888
|
-
inputEl.readOnly = readonly;
|
|
889
|
-
},
|
|
890
|
-
},
|
|
891
|
-
error: {
|
|
892
|
-
get() {
|
|
893
|
-
return error;
|
|
894
|
-
},
|
|
895
|
-
set(val) {
|
|
896
|
-
error = Boolean(val);
|
|
897
|
-
container.classList.toggle('mui-textfield-error', error);
|
|
898
|
-
},
|
|
899
|
-
},
|
|
900
|
-
helperText: {
|
|
901
|
-
get() {
|
|
902
|
-
return helperText;
|
|
903
|
-
},
|
|
904
|
-
set(text) {
|
|
905
|
-
helperTextEl.textContent = text;
|
|
906
|
-
helperTextEl.style.display = text ? 'block' : 'none';
|
|
907
|
-
},
|
|
908
|
-
},
|
|
909
|
-
});
|
|
1057
|
+
? (jsx("textarea", { class: "mui-textfield-input", placeholder: getPlaceholder(), value: modelRef.value, disabled: disabledRef, readOnly: readOnlyRef, required: requiredRef, rows: rowsRef, "on:input": handleInput, "on:change": handleChange, "on:focus": handleFocus, "on:blur": handleBlur }))
|
|
1058
|
+
: (jsx("input", { type: inputType, class: "mui-textfield-input", placeholder: getPlaceholder(), value: modelRef.value, disabled: disabledRef, readOnly: readOnlyRef, required: requiredRef, "on:input": handleInput, "on:change": handleChange, "on:focus": handleFocus, "on:blur": handleBlur }));
|
|
1059
|
+
modelRef.addOnChange((newValue) => (inputEl.value = newValue));
|
|
1060
|
+
const styleRef = toReactive(parseStyle(props.style ?? ''));
|
|
1061
|
+
const customClassRef = toReactive(props.class ?? '');
|
|
1062
|
+
const classRef = computed(() => {
|
|
1063
|
+
const className = [
|
|
1064
|
+
'mui-textfield-root',
|
|
1065
|
+
`mui-textfield-size-${sizeRef.value}`,
|
|
1066
|
+
isFocusedRef.value ? 'mui-textfield-focused' : '',
|
|
1067
|
+
errorRef.value ? 'mui-textfield-error' : '',
|
|
1068
|
+
disabledRef.value ? 'mui-textfield-disabled' : '',
|
|
1069
|
+
fullWidthRef.value ? 'mui-textfield-fullwidth' : '',
|
|
1070
|
+
labelRef.value && inputEl.value ? 'mui-textfield-has-value' : '',
|
|
1071
|
+
labelRef.value ? '' : 'mui-textfield-no-label',
|
|
1072
|
+
customClassRef.value ? customClassRef.value : '',
|
|
1073
|
+
].join(' ');
|
|
1074
|
+
return className;
|
|
1075
|
+
}, [sizeRef, errorRef, disabledRef, fullWidthRef, labelRef, isFocusedRef, customClassRef]);
|
|
1076
|
+
// if (multiline) {
|
|
1077
|
+
// rowsRef.addOnChange((newRows) => ((inputEl as HTMLTextAreaElement).rows = newRows));
|
|
1078
|
+
// }
|
|
1079
|
+
const container = (jsxs("div", { class: classRef, style: styleRef, children: [jsxs("div", { class: "mui-textfield-wrapper", "on:mousedown": handleWrapperMouseDown, children: [jsxs("label", { class: "mui-textfield-label", children: [labelRef, jsx("span", { "k-if": requiredRef, class: "mui-textfield-required", children: "*" })] }), jsx("div", { class: "mui-textfield-input-wrapper", children: inputEl }), jsx("fieldset", { class: "mui-textfield-fieldset", children: jsx("legend", { class: "mui-textfield-legend", children: jsxs("span", { children: [labelRef, jsx("span", { "k-if": requiredRef, children: "*" })] }) }) })] }), jsx("p", { class: "mui-textfield-helper-text", children: helperTextRef })] }));
|
|
910
1080
|
return container;
|
|
911
1081
|
}
|
|
912
1082
|
|
|
@@ -914,7 +1084,7 @@ function TextField(props) {
|
|
|
914
1084
|
* Radio component - mimics MUI Radio appearance and behavior
|
|
915
1085
|
*/
|
|
916
1086
|
function Radio(props) {
|
|
917
|
-
const onChange =
|
|
1087
|
+
const onChange = props['on:change'] ?? $emptyFn;
|
|
918
1088
|
const toggleIcon = (checked) => {
|
|
919
1089
|
uncheckedIcon.style.display = checked ? 'none' : '';
|
|
920
1090
|
checkedIcon.style.display = checked ? '' : 'none';
|
|
@@ -929,7 +1099,9 @@ function Radio(props) {
|
|
|
929
1099
|
onChange(checked, value);
|
|
930
1100
|
};
|
|
931
1101
|
let { checked = false, value = '', label: text = '', size = 'small', disabled = false, color = 'primary' } = props;
|
|
932
|
-
const
|
|
1102
|
+
const valueRef = toReactive(props.value ?? '');
|
|
1103
|
+
const disabledRef = toReactive(props.disabled ?? false);
|
|
1104
|
+
const input = (jsx("input", { type: "radio", class: "mui-radio-input", checked: checked, value: valueRef, disabled: disabledRef, "on:change": handleChange }));
|
|
933
1105
|
const uncheckedIcon = (jsx("span", { class: "mui-radio-icon-unchecked", children: jsx("svg", { viewBox: "0 0 24 24", children: jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" }) }) }));
|
|
934
1106
|
const checkedIcon = (jsx("span", { class: "mui-radio-icon-checked", children: jsx("svg", { viewBox: "0 0 24 24", children: jsx("path", { d: "M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" }) }) }));
|
|
935
1107
|
// initialize icon state
|
|
@@ -959,7 +1131,7 @@ function Radio(props) {
|
|
|
959
1131
|
*/
|
|
960
1132
|
function RadioGroup(props) {
|
|
961
1133
|
let { value = '', size = 'small', row = false } = props;
|
|
962
|
-
const onChange =
|
|
1134
|
+
const onChange = props['on:change'] ?? $emptyFn;
|
|
963
1135
|
const changeHandler = (checked, value) => {
|
|
964
1136
|
if (checked) {
|
|
965
1137
|
onChange(value);
|
|
@@ -969,15 +1141,15 @@ function RadioGroup(props) {
|
|
|
969
1141
|
const radios = props.options.map((o) => {
|
|
970
1142
|
o.size = size;
|
|
971
1143
|
o.checked = value === o.value;
|
|
972
|
-
const originalChange = o['
|
|
1144
|
+
const originalChange = o['on:change'];
|
|
973
1145
|
if (originalChange) {
|
|
974
|
-
o['
|
|
1146
|
+
o['on:change'] = (checked, newValue) => {
|
|
975
1147
|
originalChange(checked, newValue);
|
|
976
1148
|
changeHandler(checked, newValue);
|
|
977
1149
|
};
|
|
978
1150
|
}
|
|
979
1151
|
else {
|
|
980
|
-
o['
|
|
1152
|
+
o['on:change'] = changeHandler;
|
|
981
1153
|
}
|
|
982
1154
|
return Radio(o);
|
|
983
1155
|
});
|
|
@@ -1000,22 +1172,10 @@ function RadioGroup(props) {
|
|
|
1000
1172
|
* Select component - mimics MUI Select appearance and behavior
|
|
1001
1173
|
*/
|
|
1002
1174
|
function Select(props) {
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
const selectRef = ref();
|
|
1008
|
-
const selectLabelRef = ref();
|
|
1009
|
-
// Toggle dropdown
|
|
1010
|
-
const toggleMenu = () => {
|
|
1011
|
-
if (disabled) {
|
|
1012
|
-
return;
|
|
1013
|
-
}
|
|
1014
|
-
isOpen = !isOpen;
|
|
1015
|
-
updateMenu();
|
|
1016
|
-
};
|
|
1017
|
-
// Update menu visibility
|
|
1018
|
-
const updateMenu = () => {
|
|
1175
|
+
const onChange = props['on:change'] ?? $emptyFn;
|
|
1176
|
+
// # refs
|
|
1177
|
+
const isFocusedRef = ref(false);
|
|
1178
|
+
const open = ref(false, (isOpen) => {
|
|
1019
1179
|
if (isOpen) {
|
|
1020
1180
|
menu.value.style.display = 'block';
|
|
1021
1181
|
void menu.value.offsetHeight; // & Trigger reflow to enable animation
|
|
@@ -1029,85 +1189,139 @@ function Select(props) {
|
|
|
1029
1189
|
}, 200);
|
|
1030
1190
|
}
|
|
1031
1191
|
menu.value.classList.toggle('mui-select-menu-open', isOpen);
|
|
1032
|
-
|
|
1192
|
+
container.classList.toggle('mui-select-open', isOpen);
|
|
1193
|
+
});
|
|
1194
|
+
// # ref props
|
|
1195
|
+
const placeholderRef = toReactive(props.placeholder ?? '');
|
|
1196
|
+
const labelRef = toReactive(props.label ?? '');
|
|
1197
|
+
const optionsRef = toReactive(props.options, (newOptions) => {
|
|
1198
|
+
if (!newOptions.find((o) => o.value === modelRef.value)) {
|
|
1199
|
+
onChange((modelRef.value = ''));
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1202
|
+
const disabledRef = toReactive(props.disabled ?? false, (v) => container.classList.toggle('mui-select-disabled', v));
|
|
1203
|
+
const modelRef = $modelOrRef(props, props.value ?? '');
|
|
1204
|
+
const styleRef = toReactive(parseStyle(props.style ?? ''));
|
|
1205
|
+
const classRef = toReactive(props.class ?? '');
|
|
1206
|
+
const sizeRef = toReactive(props.size ?? 'medium');
|
|
1207
|
+
const fullwidthRef = toReactive(props.fullWidth ?? false);
|
|
1208
|
+
const className = computed(() => {
|
|
1209
|
+
return `mui-select-wrapper mui-select-size-${sizeRef.value} ${fullwidthRef.value ? 'mui-select-fullWidth' : ''} ${classRef.value} ${disabledRef.value ? 'mui-select-disabled' : ''}`;
|
|
1210
|
+
}, [sizeRef, fullwidthRef, classRef, disabledRef]);
|
|
1211
|
+
const label = computed(() => {
|
|
1212
|
+
if (labelRef.value) {
|
|
1213
|
+
return (jsx("label", { class: `mui-select-label ${modelRef.value || isFocusedRef.value || placeholderRef.value ? 'focused' : ''}`, children: labelRef }));
|
|
1214
|
+
}
|
|
1215
|
+
return '';
|
|
1216
|
+
}, [labelRef, modelRef, isFocusedRef, placeholderRef]);
|
|
1217
|
+
// Toggle dropdown
|
|
1218
|
+
const toggleMenu = () => {
|
|
1219
|
+
if (!disabledRef.value) {
|
|
1220
|
+
open.value = !open.value;
|
|
1221
|
+
}
|
|
1033
1222
|
};
|
|
1034
1223
|
// Handle option click
|
|
1035
|
-
const handleOptionClick = (
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
onChange(
|
|
1039
|
-
|
|
1040
|
-
updateLabelState();
|
|
1041
|
-
valueDisplay.redraw();
|
|
1042
|
-
setTimeout(() => menu.redraw(), 200);
|
|
1224
|
+
const handleOptionClick = (e) => {
|
|
1225
|
+
const newValue = e.currentTarget.dataset.value;
|
|
1226
|
+
modelRef.value = newValue;
|
|
1227
|
+
onChange(newValue);
|
|
1228
|
+
open.value = false;
|
|
1043
1229
|
};
|
|
1044
1230
|
// Close menu when clicking outside
|
|
1045
1231
|
const handleClickOutside = (e) => {
|
|
1046
|
-
if (!
|
|
1047
|
-
|
|
1048
|
-
updateMenu();
|
|
1232
|
+
if (!container.contains(e.target)) {
|
|
1233
|
+
open.value = false;
|
|
1049
1234
|
}
|
|
1050
1235
|
};
|
|
1051
1236
|
// Handle focus
|
|
1052
|
-
const handleFocus = () =>
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
selectLabelRef.value.classList?.toggle('focused', isFocused || !!value);
|
|
1063
|
-
};
|
|
1064
|
-
const valueDisplay = createRedrawable(() => {
|
|
1065
|
-
const o = options.find((opt) => opt.value === value);
|
|
1066
|
-
let inner;
|
|
1067
|
-
if (o === undefined) {
|
|
1068
|
-
inner = jsx("span", { class: "mui-select-placeholder", children: placeholder || '\u00a0' });
|
|
1069
|
-
}
|
|
1070
|
-
else {
|
|
1071
|
-
inner = o.label;
|
|
1072
|
-
}
|
|
1073
|
-
return jsx("div", { class: "mui-select-display", children: inner });
|
|
1074
|
-
});
|
|
1075
|
-
const menu = createRedrawable(() => {
|
|
1076
|
-
return (jsx("div", { class: "mui-select-menu", style: "display: none;", children: options.map((option) => (jsx("div", { class: `mui-select-option ${option.value === value ? 'selected' : ''}`, "on:click": () => handleOptionClick(option.value), children: option.label }))) }));
|
|
1077
|
-
});
|
|
1237
|
+
const handleFocus = () => (isFocusedRef.value = true);
|
|
1238
|
+
const handleBlur = () => (isFocusedRef.value = false);
|
|
1239
|
+
const defaultEmpty = jsx("span", { class: "mui-select-placeholder", children: placeholderRef.value || '\u00a0' });
|
|
1240
|
+
const displayedValue = computed(() => {
|
|
1241
|
+
const o = optionsRef.value.find((item) => item.value === modelRef.value);
|
|
1242
|
+
return jsx("div", { class: "mui-select-display", children: o?.label ?? defaultEmpty });
|
|
1243
|
+
}, [modelRef]);
|
|
1244
|
+
const menu = computed(() => {
|
|
1245
|
+
return (jsxs("div", { class: "mui-select-menu", style: "display: none;", children: [optionsRef.value.map((o) => (jsx("div", { class: `mui-select-option ${o.value === modelRef.value ? 'selected' : ''}`, "data-value": o.value, "on:click": handleOptionClick, children: o.label }))), ' '] }));
|
|
1246
|
+
}, [optionsRef, modelRef]);
|
|
1078
1247
|
// Create container
|
|
1079
|
-
const container = (jsxs("div", {
|
|
1080
|
-
$defines(container, {
|
|
1081
|
-
value: {
|
|
1082
|
-
get: () => value,
|
|
1083
|
-
set: (newValue) => {
|
|
1084
|
-
value = newValue;
|
|
1085
|
-
updateLabelState();
|
|
1086
|
-
valueDisplay.redraw();
|
|
1087
|
-
menu.redraw();
|
|
1088
|
-
},
|
|
1089
|
-
},
|
|
1090
|
-
disabled: {
|
|
1091
|
-
get: () => disabled,
|
|
1092
|
-
set: (newDisabled) => {
|
|
1093
|
-
disabled = newDisabled;
|
|
1094
|
-
if (disabled) {
|
|
1095
|
-
isOpen = false;
|
|
1096
|
-
updateMenu();
|
|
1097
|
-
}
|
|
1098
|
-
container.classList.toggle('mui-select-disabled', disabled);
|
|
1099
|
-
},
|
|
1100
|
-
},
|
|
1101
|
-
});
|
|
1248
|
+
const container = (jsxs("div", { class: className, style: styleRef, children: [label, jsxs("div", { class: "mui-select-control mui-select-outlined", "on:click": toggleMenu, "on:focus": handleFocus, "on:blur": handleBlur, tabIndex: disabledRef.value ? -1 : 0, children: [displayedValue, jsx("input", { type: "hidden", value: modelRef }), jsx("fieldset", { class: "mui-select-fieldset", children: jsx("legend", { class: "mui-select-legend", children: jsx("span", { children: labelRef }) }) }), jsx("svg", { class: "mui-select-icon", focusable: "false", "aria-hidden": "true", viewBox: "0 0 24 24", width: "24", height: "24", children: jsx("path", { d: "M7 10l5 5 5-5Z", fill: "currentColor" }) })] }), menu] }));
|
|
1102
1249
|
// Add global click listener
|
|
1103
1250
|
setTimeout(() => {
|
|
1104
1251
|
document.removeEventListener('click', handleClickOutside);
|
|
1105
1252
|
document.addEventListener('click', handleClickOutside);
|
|
1106
|
-
updateLabelState();
|
|
1107
1253
|
}, 0);
|
|
1108
1254
|
return container;
|
|
1109
1255
|
}
|
|
1110
1256
|
|
|
1257
|
+
/**
|
|
1258
|
+
* Card component - mimics MUI Card appearance and behavior
|
|
1259
|
+
*/
|
|
1260
|
+
function Card(props) {
|
|
1261
|
+
// # ref props
|
|
1262
|
+
const variantRef = toReactive(props.variant ?? 'elevation');
|
|
1263
|
+
const elevationRef = toReactive(props.elevation ?? 1);
|
|
1264
|
+
const squareRef = toReactive(props.square ?? false);
|
|
1265
|
+
const raisedRef = toReactive(props.raised ?? false);
|
|
1266
|
+
const styleRef = toReactive(parseStyle(props.style ?? ''));
|
|
1267
|
+
const classRef = toReactive(props.class ?? '');
|
|
1268
|
+
const className = computed(() => {
|
|
1269
|
+
const base = 'mui-card';
|
|
1270
|
+
const variantClass = `mui-card-${variantRef.value}`;
|
|
1271
|
+
const elevationClass = variantRef.value === 'elevation' ? `mui-card-elevation-${Math.min(24, Math.max(0, elevationRef.value))}` : '';
|
|
1272
|
+
const squareClass = squareRef.value ? 'mui-card-square' : '';
|
|
1273
|
+
const raisedClass = raisedRef.value ? 'mui-card-raised' : '';
|
|
1274
|
+
return `${base} ${variantClass} ${elevationClass} ${squareClass} ${raisedClass} ${classRef.value}`.trim().replace(/\s+/g, ' ');
|
|
1275
|
+
}, [variantRef, elevationRef, squareRef, raisedRef, classRef]);
|
|
1276
|
+
// Handle click
|
|
1277
|
+
const handleClick = props['on:click'] ?? (() => { });
|
|
1278
|
+
const container = (jsx("div", { class: className, style: styleRef, "on:click": handleClick, children: props.children }));
|
|
1279
|
+
return container;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
/**
|
|
1283
|
+
* Switch component - mimics MUI Switch appearance and behavior
|
|
1284
|
+
*/
|
|
1285
|
+
function Switch(props) {
|
|
1286
|
+
const onChange = props['on:change'] ?? $emptyFn;
|
|
1287
|
+
// # ref props
|
|
1288
|
+
const labelRef = toReactive(props.label ?? '');
|
|
1289
|
+
const valueRef = toReactive(props.value ?? '');
|
|
1290
|
+
const colorRef = toReactive(props.color ?? 'primary');
|
|
1291
|
+
const sizeRef = toReactive(props.size ?? 'medium');
|
|
1292
|
+
const disabledRef = toReactive(props.disabled ?? false, (v) => {
|
|
1293
|
+
inputEl.disabled = v;
|
|
1294
|
+
container.classList.toggle('mui-switch-disabled', v);
|
|
1295
|
+
});
|
|
1296
|
+
const modelRef = $modelOrRef(props, props.checked ?? false);
|
|
1297
|
+
modelRef.addOnChange((newValue) => {
|
|
1298
|
+
inputEl.checked = newValue;
|
|
1299
|
+
track.classList.toggle('mui-switch-track-checked', newValue);
|
|
1300
|
+
thumb.classList.toggle('mui-switch-thumb-checked', newValue);
|
|
1301
|
+
});
|
|
1302
|
+
const styleRef = toReactive(parseStyle(props.style ?? ''));
|
|
1303
|
+
const classRef = toReactive(props.class ?? '');
|
|
1304
|
+
const className = computed(() => {
|
|
1305
|
+
return `mui-switch-wrapper mui-switch-size-${sizeRef.value} ${disabledRef.value ? 'mui-switch-disabled' : ''} mui-switch-color-${colorRef.value} ${classRef.value}`;
|
|
1306
|
+
}, [colorRef, disabledRef, sizeRef, classRef]);
|
|
1307
|
+
// Handle change
|
|
1308
|
+
const handleChange = () => {
|
|
1309
|
+
if (disabledRef.value) {
|
|
1310
|
+
return;
|
|
1311
|
+
}
|
|
1312
|
+
modelRef.value = inputEl.checked;
|
|
1313
|
+
onChange(modelRef.value, valueRef.value);
|
|
1314
|
+
};
|
|
1315
|
+
const inputEl = (jsx("input", { type: "checkbox", class: "mui-switch-input", checked: modelRef.value, value: valueRef, disabled: disabledRef, "on:change": handleChange }));
|
|
1316
|
+
const track = jsx("span", { class: "mui-switch-track" });
|
|
1317
|
+
const thumb = jsx("span", { class: "mui-switch-thumb" });
|
|
1318
|
+
const container = (jsxs("label", { class: className, style: styleRef, children: [inputEl, jsxs("span", { class: "mui-switch-base", children: [track, thumb] }), jsx("span", { "k-if": labelRef, class: "mui-switch-label", children: labelRef })] }));
|
|
1319
|
+
// Initialize state
|
|
1320
|
+
track.classList.toggle('mui-switch-track-checked', modelRef.value);
|
|
1321
|
+
thumb.classList.toggle('mui-switch-thumb-checked', modelRef.value);
|
|
1322
|
+
return container;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1111
1325
|
function DownloadIcon(props) {
|
|
1112
1326
|
return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z" }) }));
|
|
1113
1327
|
}
|
|
@@ -1196,4 +1410,4 @@ function SelectAllIcon(props) {
|
|
|
1196
1410
|
return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M3 5h2V3c-1.1 0-2 .9-2 2zm0 8h2v-2H3v2zm4 8h2v-2H7v2zM3 9h2V7H3v2zm10-6h-2v2h2V3zm6 0v2h2c0-1.1-.9-2-2-2zM5 21v-2H3c0 1.1.9 2 2 2zm-2-4h2v-2H3v2zM9 3H7v2h2V3zm2 18h2v-2h-2v2zm8-8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2zm0-12h2V7h-2v2zm0 8h2v-2h-2v2zm-4 4h2v-2h-2v2zm0-16h2V3h-2v2zM7 17h10V7H7v10zm2-8h6v6H9V9z" }) }));
|
|
1197
1411
|
}
|
|
1198
1412
|
|
|
1199
|
-
export { Alert, Button, Checkbox, CheckboxGroup, ColorLensIcon, CompressIcon, ContentCopyIcon, ContentPasteIcon, DeleteIcon, Dialog, DownloadIcon, ExpandMoreIcon, FileOpenIcon, FolderOpenIcon, FormLabel, HomeIcon, LinearProgress, MenuIcon, NewReleasesIcon, PlayArrowIcon, QueuePlayNextIcon, Radio, RadioGroup, SaveIcon, Select, SelectAllIcon, SettingsIcon, StopIcon, SubtitlesIcon, TextField, UploadFileIcon, VideoFileIcon, WallpaperIcon };
|
|
1413
|
+
export { Alert, Button, Card, Checkbox, CheckboxGroup, ColorLensIcon, CompressIcon, ContentCopyIcon, ContentPasteIcon, DeleteIcon, Dialog, DownloadIcon, ExpandMoreIcon, FileOpenIcon, FolderOpenIcon, FormLabel, HomeIcon, LinearProgress, MenuIcon, NewReleasesIcon, PlayArrowIcon, QueuePlayNextIcon, Radio, RadioGroup, SaveIcon, Select, SelectAllIcon, SettingsIcon, StopIcon, SubtitlesIcon, Switch, TextField, UploadFileIcon, VideoFileIcon, WallpaperIcon };
|