@ktjs/mui 0.23.2 → 0.24.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.
@@ -1,1454 +0,0 @@
1
- var __ktjs_mui__ = (function (exports) {
2
- 'use strict';
3
-
4
- // Shared constants
5
- // Empty for now - can be extended with framework-wide constants
6
- /**
7
- * Mark the attribute as SVG to handle special cases during rendering.
8
- */
9
- const $defines = Object.defineProperties;
10
- const $entries = Object.entries;
11
- const $random$2 = Math.random;
12
- const { get: $buttonDisabledGetter$2, set: $buttonDisabledSetter$2 } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
13
- const parseStyle = (style) => {
14
- if (!style) {
15
- return '';
16
- }
17
- if (typeof style === 'string') {
18
- return style;
19
- }
20
- if (style && typeof style === 'object') {
21
- if (style.isKT) {
22
- return parseStyle(style.value);
23
- }
24
- return $entries(style)
25
- .map((entry) => {
26
- const cssKey = entry[0].replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
27
- return `${cssKey}:${entry[1]}`;
28
- })
29
- .join(';');
30
- }
31
- return '';
32
- };
33
-
34
- // String manipulation utilities
35
- /**
36
- * Default empty function
37
- */
38
- const $emptyFn = (() => true);
39
-
40
- if (typeof Symbol === 'undefined') {
41
- window.Symbol = function Symbol(description) {
42
- return `@@SYMBOL_${description || ''}_${$random$2().toString(36).slice(2)}`;
43
- };
44
- }
45
-
46
- // Shared utilities and cached native methods for kt.js framework
47
- Object.defineProperty(window, '__ktjs__', { value: '0.23.4' });
48
-
49
- // Shared constants
50
- // Empty for now - can be extended with framework-wide constants
51
- /**
52
- * Mark the attribute as SVG to handle special cases during rendering.
53
- */
54
- const SVG_ATTR_FLAG = '__kt_svg__';
55
- /**
56
- * Mark the attribute as MathML to handle special cases during rendering.
57
- */
58
- const MATHML_ATTR_FLAG = '__kt_mathml__';
59
-
60
- // Cached native methods for performance optimization
61
- const $isArray = Array.isArray;
62
- const $random$1 = Math.random;
63
- const $isThenable = (o) => typeof o?.then === 'function';
64
-
65
- // DOM manipulation utilities
66
- // # dom natives
67
- const $isNode$1 = (x) => x?.nodeType > 0;
68
- /**
69
- * Safe replace `oldNode` With `newNode`
70
- */
71
- const $replaceNode$1 = (oldNode, newNode) => {
72
- if ($isNode$1(oldNode) && $isNode$1(newNode)) {
73
- if (newNode.contains(oldNode)) {
74
- newNode.remove();
75
- }
76
- oldNode.replaceWith(newNode);
77
- }
78
- };
79
- /**
80
- * & Remove `bind` because it is shockingly slower than wrapper
81
- * & `window.document` is safe because it is not configurable and its setter is undefined
82
- */
83
- const $appendChild = HTMLElement.prototype.appendChild;
84
- const originAppend = HTMLElement.prototype.append;
85
- const $append = // for ie 9/10/11
86
- typeof originAppend === 'function'
87
- ? originAppend
88
- : function (...nodes) {
89
- if (nodes.length < 50) {
90
- for (let i = 0; i < nodes.length; i++) {
91
- const node = nodes[i];
92
- if (typeof node === 'string') {
93
- $appendChild.call(this, document.createTextNode(node));
94
- }
95
- else {
96
- $appendChild.call(this, node);
97
- }
98
- }
99
- }
100
- else {
101
- const fragment = document.createDocumentFragment();
102
- for (let i = 0; i < nodes.length; i++) {
103
- const node = nodes[i];
104
- if (typeof node === 'string') {
105
- $appendChild.call(fragment, document.createTextNode(node));
106
- }
107
- else {
108
- $appendChild.call(fragment, node);
109
- }
110
- }
111
- $appendChild.call(this, fragment);
112
- }
113
- };
114
- const { get: $buttonDisabledGetter$1, set: $buttonDisabledSetter$1 } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
115
- /**
116
- * Used for `k-model`
117
- */
118
- const applyModel = (element, valueRef, propName, eventName) => {
119
- element[propName] = valueRef.value; // initialize
120
- valueRef.addOnChange((newValue) => (element[propName] = newValue));
121
- element.addEventListener(eventName, () => (valueRef.value = element[propName]));
122
- };
123
-
124
- if (typeof Symbol === 'undefined') {
125
- window.Symbol = function Symbol(description) {
126
- return `@@SYMBOL_${description || ''}_${$random$1().toString(36).slice(2)}`;
127
- };
128
- }
129
-
130
- // Shared utilities and cached native methods for kt.js framework
131
- Object.defineProperty(window, '__ktjs__', { value: '0.23.4' });
132
-
133
- const isKT$1 = (obj) => obj?.isKT;
134
- const isRef = (obj) => obj?.ktType === 1 /* KTReactiveType.REF */;
135
- const isComputed = (obj) => obj?.ktType === 2 /* KTReactiveType.COMPUTED */;
136
-
137
- const booleanHandler = (element, key, value) => {
138
- if (key in element) {
139
- element[key] = !!value;
140
- }
141
- else {
142
- element.setAttribute(key, value);
143
- }
144
- };
145
- const valueHandler = (element, key, value) => {
146
- if (key in element) {
147
- element[key] = value;
148
- }
149
- else {
150
- element.setAttribute(key, value);
151
- }
152
- };
153
- // Attribute handlers map for optimized lookup
154
- const handlers = {
155
- checked: booleanHandler,
156
- selected: booleanHandler,
157
- value: valueHandler,
158
- valueAsDate: valueHandler,
159
- valueAsNumber: valueHandler,
160
- defaultValue: valueHandler,
161
- defaultChecked: booleanHandler,
162
- defaultSelected: booleanHandler,
163
- disabled: booleanHandler,
164
- readOnly: booleanHandler,
165
- multiple: booleanHandler,
166
- required: booleanHandler,
167
- autofocus: booleanHandler,
168
- open: booleanHandler,
169
- controls: booleanHandler,
170
- autoplay: booleanHandler,
171
- loop: booleanHandler,
172
- muted: booleanHandler,
173
- defer: booleanHandler,
174
- async: booleanHandler,
175
- hidden: (element, _key, value) => (element.hidden = !!value),
176
- };
177
-
178
- const defaultHandler = (element, key, value) => element.setAttribute(key, value);
179
- const setElementStyle = (element, style) => {
180
- if (typeof style === 'string') {
181
- element.style.cssText = style;
182
- return;
183
- }
184
- for (const key in style) {
185
- element.style[key] = style[key];
186
- }
187
- };
188
- function attrIsObject(element, attr) {
189
- const classValue = attr.class || attr.className;
190
- if (classValue !== undefined) {
191
- if (isKT$1(classValue)) {
192
- element.setAttribute('class', classValue.value);
193
- classValue.addOnChange((v) => element.setAttribute('class', v));
194
- }
195
- else {
196
- element.setAttribute('class', classValue);
197
- }
198
- }
199
- const style = attr.style;
200
- if (style) {
201
- if (typeof style === 'string') {
202
- element.setAttribute('style', style);
203
- }
204
- else if (typeof style === 'object') {
205
- if (isKT$1(style)) {
206
- setElementStyle(element, style.value);
207
- style.addOnChange((v) => setElementStyle(element, v));
208
- }
209
- else {
210
- setElementStyle(element, style);
211
- }
212
- }
213
- }
214
- if ('k-html' in attr) {
215
- const html = attr['k-html'];
216
- if (isKT$1(html)) {
217
- element.innerHTML = html.value;
218
- html.addOnChange((v) => (element.innerHTML = v));
219
- }
220
- else {
221
- element.innerHTML = html;
222
- }
223
- }
224
- for (const key in attr) {
225
- if (key === 'k-if' ||
226
- key === 'k-model' ||
227
- key === 'ref' ||
228
- key === 'class' ||
229
- key === 'className' ||
230
- key === 'style' ||
231
- key === 'children' ||
232
- key === 'k-html') {
233
- continue;
234
- }
235
- const o = attr[key];
236
- // normal event handler
237
- if (key.startsWith('on:')) {
238
- element.addEventListener(key.slice(3), o); // chop off the `on:`
239
- }
240
- // normal attributes
241
- else {
242
- const handler = handlers[key] || defaultHandler;
243
- if (isKT$1(o)) {
244
- handler(element, key, o.value);
245
- o.addOnChange((v) => handler(element, key, v));
246
- }
247
- else {
248
- handler(element, key, o);
249
- }
250
- }
251
- }
252
- }
253
- function applyAttr(element, attr) {
254
- if (!attr) {
255
- return;
256
- }
257
- if (typeof attr === 'object' && attr !== null) {
258
- attrIsObject(element, attr);
259
- }
260
- else {
261
- throw new Error('[kt.js error] attr must be an object.');
262
- }
263
- }
264
-
265
- const assureNode = (o) => ($isNode$1(o) ? o : document.createTextNode(o));
266
- function apdSingle(element, c) {
267
- // & JSX should ignore false, undefined, and null
268
- if (c === false || c === undefined || c === null) {
269
- return;
270
- }
271
- if (isKT$1(c)) {
272
- let node = assureNode(c.value);
273
- $append.call(element, node);
274
- c.addOnChange((newValue, oldValue) => {
275
- if ($isNode$1(newValue) && $isNode$1(oldValue)) {
276
- // & this case is handled automically in `class KTRef`
277
- return;
278
- }
279
- const oldNode = node;
280
- node = assureNode(newValue);
281
- oldNode.replaceWith(node);
282
- });
283
- }
284
- else {
285
- $append.call(element, c);
286
- // Handle KTFor anchor
287
- const list = c.__kt_for_list__;
288
- if ($isArray(list)) {
289
- apd(element, list);
290
- }
291
- }
292
- }
293
- function apd(element, c) {
294
- if ($isThenable(c)) {
295
- c.then((r) => apd(element, r));
296
- }
297
- else if ($isArray(c)) {
298
- for (let i = 0; i < c.length; i++) {
299
- // & might be thenable here too
300
- const ci = c[i];
301
- if ($isThenable(ci)) {
302
- const comment = document.createComment('ktjs-promise-placeholder');
303
- $append.call(element, comment);
304
- ci.then((awaited) => comment.replaceWith(awaited));
305
- }
306
- else {
307
- apdSingle(element, ci);
308
- }
309
- }
310
- }
311
- else {
312
- // & here is thened, so must be a simple elementj
313
- apdSingle(element, c);
314
- }
315
- }
316
- function applyContent(element, content) {
317
- if ($isArray(content)) {
318
- for (let i = 0; i < content.length; i++) {
319
- apd(element, content[i]);
320
- }
321
- }
322
- else {
323
- apd(element, content);
324
- }
325
- }
326
-
327
- function applyKModel(element, valueRef) {
328
- if (!isKT$1(valueRef)) {
329
- console.warn('[kt.js warn]','k-model value must be a KTRef.');
330
- return;
331
- }
332
- if (element instanceof HTMLInputElement) {
333
- if (element.type === 'radio' || element.type === 'checkbox') {
334
- applyModel(element, valueRef, 'checked', 'change');
335
- }
336
- else {
337
- applyModel(element, valueRef, 'value', 'input');
338
- }
339
- }
340
- else if (element instanceof HTMLSelectElement) {
341
- applyModel(element, valueRef, 'value', 'change');
342
- }
343
- else if (element instanceof HTMLTextAreaElement) {
344
- applyModel(element, valueRef, 'value', 'input');
345
- }
346
- else {
347
- console.warn('[kt.js warn]','not supported element for k-model:');
348
- }
349
- }
350
-
351
- const htmlCreator = (tag) => document.createElement(tag);
352
- const svgCreator = (tag) => document.createElementNS('http://www.w3.org/2000/svg', tag);
353
- const mathMLCreator = (tag) => document.createElementNS('http://www.w3.org/1998/Math/MathML', tag);
354
- let creator = htmlCreator;
355
- /**
356
- * Create an enhanced HTMLElement.
357
- * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
358
- * @param tag tag of an `HTMLElement`
359
- * @param attr attribute object or className
360
- * @param content a string or an array of HTMLEnhancedElement as child nodes
361
- *
362
- * ## About
363
- * @package @ktjs/core
364
- * @author Kasukabe Tsumugi <futami16237@gmail.com>
365
- * @version 0.26.9 (Last Update: 2026.02.09 00:03:34.324)
366
- * @license MIT
367
- * @link https://github.com/baendlorel/kt.js
368
- * @link https://baendlorel.github.io/ Welcome to my site!
369
- * @description Core functionality for kt.js - DOM manipulation utilities with JSX/TSX support
370
- * @copyright Copyright (c) 2026 Kasukabe Tsumugi. All rights reserved.
371
- */
372
- const h = (tag, attr, content) => {
373
- if (typeof tag !== 'string') {
374
- throw new Error('[kt.js error] tagName must be a string.');
375
- }
376
- if (attr) {
377
- if (SVG_ATTR_FLAG in attr) {
378
- delete attr[SVG_ATTR_FLAG];
379
- creator = svgCreator;
380
- }
381
- else if (MATHML_ATTR_FLAG in attr) {
382
- delete attr[MATHML_ATTR_FLAG];
383
- creator = mathMLCreator;
384
- }
385
- else {
386
- creator = htmlCreator;
387
- }
388
- }
389
- // * start creating the element
390
- const element = creator(tag);
391
- // * Handle content
392
- applyAttr(element, attr);
393
- applyContent(element, content);
394
- if (typeof attr === 'object' && attr !== null && 'k-model' in attr) {
395
- applyKModel(element, attr['k-model']);
396
- }
397
- return element;
398
- };
399
-
400
- const dummyRef = { value: null };
401
- const create = (tag, props) => {
402
- if (typeof tag === 'function') {
403
- return tag(props);
404
- }
405
- else {
406
- return h(tag, props, props.children);
407
- }
408
- };
409
- const placeholder = () => document.createComment('k-if');
410
- /**
411
- * @param tag html tag or function component
412
- * @param props properties/attributes
413
- */
414
- function jsx(tag, props) {
415
- if (isComputed(props.ref)) {
416
- throw new Error('[kt.js error] Cannot assign a computed value to an element.');
417
- }
418
- const maybeDummyRef = isRef(props.ref) ? props.ref : dummyRef;
419
- let el;
420
- if ('k-if' in props) {
421
- const kif = props['k-if'];
422
- let condition = kif; // assume boolean by default
423
- // Handle reactive k-if
424
- if (isKT$1(kif)) {
425
- kif.addOnChange((newValue, oldValue) => {
426
- if (newValue === oldValue) {
427
- return;
428
- }
429
- const oldEl = el;
430
- el = newValue ? create(tag, props) : placeholder();
431
- $replaceNode$1(oldEl, el);
432
- maybeDummyRef.value = el;
433
- });
434
- condition = kif.value;
435
- }
436
- if (!condition) {
437
- // & make comment placeholder in case that ref might be redrawn later
438
- el = placeholder();
439
- maybeDummyRef.value = el;
440
- return el;
441
- }
442
- }
443
- el = create(tag, props);
444
- maybeDummyRef.value = el;
445
- return el;
446
- }
447
- /**
448
- * JSX runtime for React 17+ automatic runtime
449
- * This is called when using jsx: "react-jsx" or "react-jsxdev"
450
- */
451
- const jsxs = jsx;
452
-
453
- function Alert(props) {
454
- const { children, severity = 'info', variant = 'standard', icon, 'on:close': onClose } = props;
455
- const classes = `mui-alert mui-alert-${severity} mui-alert-${variant} ${props.class ? props.class : ''}`;
456
- // Icon SVG paths for different severities
457
- const getIcon = () => {
458
- if (icon === false) {
459
- return null;
460
- }
461
- if (icon) {
462
- return icon;
463
- }
464
- const iconSize = '22px';
465
- const iconClass = 'mui-alert-icon';
466
- switch (severity) {
467
- case 'success':
468
- return (jsx("svg", { class: iconClass, viewBox: "0 0 24 24", width: iconSize, height: iconSize, children: jsx("path", { fill: "currentColor", d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" }) }));
469
- case 'error':
470
- return (jsx("svg", { class: iconClass, viewBox: "0 0 24 24", width: iconSize, height: iconSize, children: jsx("path", { fill: "currentColor", d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" }) }));
471
- case 'warning':
472
- return (jsx("svg", { class: iconClass, viewBox: "0 0 24 24", width: iconSize, height: iconSize, children: jsx("path", { fill: "currentColor", d: "M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" }) }));
473
- case 'info':
474
- default:
475
- return (jsx("svg", { class: iconClass, viewBox: "0 0 24 24", width: iconSize, height: iconSize, children: jsx("path", { fill: "currentColor", d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z" }) }));
476
- }
477
- };
478
- const alertIcon = getIcon();
479
- const alert = (jsxs("div", { class: classes, style: parseStyle(props.style), role: "alert", children: [alertIcon && jsx("div", { class: "mui-alert-icon-wrapper", children: alertIcon }), jsx("div", { class: "mui-alert-message", children: children }), jsx("button", { "k-if": onClose, class: "mui-alert-close", "on:click": onClose, "aria-label": "Close", children: jsx("svg", { viewBox: "0 0 24 24", width: "18px", height: "18px", children: jsx("path", { fill: "currentColor", d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }) }) })] }));
480
- return alert;
481
- }
482
-
483
- // Shared constants
484
- // Empty for now - can be extended with framework-wide constants
485
- /**
486
- * Mark the attribute as SVG to handle special cases during rendering.
487
- */
488
- const $is = Object.is;
489
- const $random = Math.random;
490
-
491
- // DOM manipulation utilities
492
- // # dom natives
493
- const $isNode = (x) => x?.nodeType > 0;
494
- /**
495
- * Safe replace `oldNode` With `newNode`
496
- */
497
- const $replaceNode = (oldNode, newNode) => {
498
- if ($isNode(oldNode) && $isNode(newNode)) {
499
- if (newNode.contains(oldNode)) {
500
- newNode.remove();
501
- }
502
- oldNode.replaceWith(newNode);
503
- }
504
- };
505
- const { get: $buttonDisabledGetter, set: $buttonDisabledSetter } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
506
-
507
- if (typeof Symbol === 'undefined') {
508
- window.Symbol = function Symbol(description) {
509
- return `@@SYMBOL_${description || ''}_${$random().toString(36).slice(2)}`;
510
- };
511
- }
512
-
513
- // Shared utilities and cached native methods for kt.js framework
514
- Object.defineProperty(window, '__ktjs__', { value: '0.23.4' });
515
-
516
- const isKT = (obj) => obj?.isKT;
517
-
518
- class KTRef {
519
- /**
520
- * Indicates that this is a KTRef instance
521
- */
522
- isKT = true;
523
- ktType = 1 /* KTReactiveType.REF */;
524
- /**
525
- * @internal
526
- */
527
- _value;
528
- /**
529
- * @internal
530
- */
531
- _onChanges;
532
- constructor(_value, _onChanges) {
533
- this._value = _value;
534
- this._onChanges = _onChanges;
535
- }
536
- /**
537
- * If new value and old value are both nodes, the old one will be replaced in the DOM
538
- */
539
- get value() {
540
- return this._value;
541
- }
542
- set value(newValue) {
543
- if ($is(newValue, this._value)) {
544
- return;
545
- }
546
- const oldValue = this._value;
547
- $replaceNode(oldValue, newValue);
548
- this._value = newValue;
549
- for (let i = 0; i < this._onChanges.length; i++) {
550
- this._onChanges[i](newValue, oldValue);
551
- }
552
- }
553
- /**
554
- * Register a callback when the value changes
555
- * @param callback (newValue, oldValue) => xxx
556
- */
557
- addOnChange(callback) {
558
- if (typeof callback !== 'function') {
559
- throw new Error('[kt.js error] KTRef.addOnChange: callback must be a function');
560
- }
561
- this._onChanges.push(callback);
562
- }
563
- removeOnChange(callback) {
564
- for (let i = this._onChanges.length - 1; i >= 0; i--) {
565
- if (this._onChanges[i] === callback) {
566
- this._onChanges.splice(i, 1);
567
- return true;
568
- }
569
- }
570
- return false;
571
- }
572
- }
573
- /**
574
- * Reference to the created HTML element.
575
- * - **Only** respond to `ref.value` changes, not reactive to internal changes of the element.
576
- * - can alse be used to store normal values, but it is not reactive.
577
- * - if the value is already a `KTRef`, it will be returned **directly**.
578
- * @param value mostly an HTMLElement
579
- */
580
- function ref(value, onChange) {
581
- return new KTRef(value, onChange ? [onChange] : []);
582
- }
583
- function deref(value) {
584
- return isKT(value) ? value.value : value;
585
- }
586
- // # asserts
587
- /**
588
- * Assert k-model to be a ref object
589
- */
590
- const $modelOrRef = (props, defaultValue) => {
591
- // & props is an object. Won't use it in any other place
592
- if ('k-model' in props) {
593
- const kmodel = props['k-model'];
594
- if (!kmodel?.isKT) {
595
- throw new Error(`[kt.js error] k-model data must be a KTRef object, please use 'ref(...)' to wrap it.`);
596
- }
597
- return kmodel;
598
- }
599
- return ref(defaultValue);
600
- };
601
-
602
- class KTComputed {
603
- /**
604
- * Indicates that this is a KTRef instance
605
- */
606
- isKT = true;
607
- ktType = 2 /* KTReactiveType.COMPUTED */;
608
- /**
609
- * @internal
610
- */
611
- _calculator;
612
- /**
613
- * @internal
614
- */
615
- _value;
616
- /**
617
- * @internal
618
- */
619
- _onChanges = [];
620
- /**
621
- * @internal
622
- */
623
- _subscribe(reactives) {
624
- for (let i = 0; i < reactives.length; i++) {
625
- const reactive = reactives[i];
626
- reactive.addOnChange(() => {
627
- const oldValue = this._value;
628
- this._value = this._calculator();
629
- if (oldValue === this._value) {
630
- return;
631
- }
632
- $replaceNode(oldValue, this._value);
633
- for (let i = 0; i < this._onChanges.length; i++) {
634
- this._onChanges[i](this._value, oldValue);
635
- }
636
- });
637
- }
638
- }
639
- constructor(_calculator, reactives) {
640
- this._calculator = _calculator;
641
- this._value = _calculator();
642
- this._subscribe(reactives);
643
- }
644
- /**
645
- * If new value and old value are both nodes, the old one will be replaced in the DOM
646
- */
647
- get value() {
648
- return this._value;
649
- }
650
- set value(_newValue) {
651
- throw new Error('[kt.js error] KTComputed: cannot set value of a computed value');
652
- }
653
- /**
654
- * Register a callback when the value changes
655
- * @param callback (newValue, oldValue) => xxx
656
- */
657
- addOnChange(callback) {
658
- if (typeof callback !== 'function') {
659
- throw new Error('[kt.js error] KTRef.addOnChange: callback must be a function');
660
- }
661
- this._onChanges.push(callback);
662
- }
663
- /**
664
- * Unregister a callback
665
- * @param callback (newValue, oldValue) => xxx
666
- */
667
- removeOnChange(callback) {
668
- for (let i = this._onChanges.length - 1; i >= 0; i--) {
669
- if (this._onChanges[i] === callback) {
670
- this._onChanges.splice(i, 1);
671
- return true;
672
- }
673
- }
674
- return false;
675
- }
676
- }
677
- /**
678
- * Create a reactive computed value
679
- * @param computeFn
680
- * @param reactives refs and computeds that this computed depends on
681
- */
682
- function computed(computeFn, reactives) {
683
- if (reactives.some((v) => !isKT(v))) {
684
- throw new Error('[kt.js error] computed: all reactives must be KTRef or KTComputed instances');
685
- }
686
- return new KTComputed(computeFn, reactives);
687
- }
688
-
689
- const toReactive = (value, onChange) => {
690
- if (isKT(value)) {
691
- if (onChange) {
692
- value.addOnChange(onChange);
693
- }
694
- return value;
695
- }
696
- else {
697
- return ref(value, onChange);
698
- }
699
- };
700
-
701
- const registerPrefixedEventsForButton = (element, props) => {
702
- for (const key in props) {
703
- if (key.startsWith('on:') && key !== 'on:click' && key !== 'on:dblclick') {
704
- element.addEventListener(key.slice(3), props[key]);
705
- }
706
- }
707
- };
708
-
709
- /**
710
- * Button component - mimics MUI Button appearance and behavior
711
- */
712
- function Button(props) {
713
- 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
714
- } = props;
715
- const updateClass = () => {
716
- container.className = [
717
- 'mui-button',
718
- `mui-button-${variant}`,
719
- `mui-button-${variant}-${color}`,
720
- `mui-button-size-${size}`,
721
- fullWidth ? 'mui-button-fullwidth' : '',
722
- iconOnly ? 'mui-button-icon-only' : '',
723
- disabledRef.value ? 'mui-button-disabled' : '',
724
- props.class ? props.class : '',
725
- ].join(' ');
726
- };
727
- const disabledRef = toReactive(disabled, (v) => {
728
- container.disabled = v;
729
- updateClass();
730
- });
731
- const rippleContainer = jsx("span", { class: "mui-button-ripple" });
732
- const createRippleEffect = (mouseX, mouseY) => {
733
- const rect = container.getBoundingClientRect();
734
- const size = Math.max(rect.width, rect.height);
735
- const x = mouseX - rect.left - size / 2;
736
- const y = mouseY - rect.top - size / 2;
737
- const ripple = (jsx("span", { class: "mui-button-ripple-effect", style: `width:${size}px; height:${size}px; left:${x}px; top:${y}px;` }));
738
- rippleContainer.appendChild(ripple);
739
- setTimeout(() => ripple.remove(), 600); // Remove ripple after animation
740
- };
741
- const handleClick = (e) => {
742
- if (disabledRef.value) {
743
- e.preventDefault();
744
- return;
745
- }
746
- createRippleEffect(e.clientX, e.clientY);
747
- onClick(e);
748
- };
749
- 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] }));
750
- const onDblclick = props['on:dblclick'];
751
- if (onDblclick) {
752
- container.addEventListener('dblclick', (e) => {
753
- if (disabledRef.value) {
754
- e.preventDefault();
755
- return;
756
- }
757
- createRippleEffect(e.clientX, e.clientY);
758
- onDblclick(e);
759
- });
760
- }
761
- registerPrefixedEventsForButton(container, props);
762
- // # initialize
763
- updateClass();
764
- return container;
765
- }
766
-
767
- const $ArrayPushUnique = (arr, item) => {
768
- if (!arr.includes(item)) {
769
- arr.push(item);
770
- }
771
- };
772
- const $ArrayDelete = (arr, item) => {
773
- const index = arr.indexOf(item);
774
- if (index > -1) {
775
- arr.splice(index, 1);
776
- }
777
- };
778
-
779
- 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" }) }) }));
780
- 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" }) }) }));
781
- 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" }) }) }));
782
- /**
783
- * Checkbox component - mimics MUI Checkbox appearance and behavior
784
- */
785
- function Checkbox(props) {
786
- const toggleIcon = (checked, indeterminate) => {
787
- if (indeterminate) {
788
- uncheckedIcon.style.display = 'none';
789
- checkedIcon.style.display = 'none';
790
- indeterminateIcon.style.display = '';
791
- }
792
- else {
793
- uncheckedIcon.style.display = checked ? 'none' : '';
794
- checkedIcon.style.display = checked ? '' : 'none';
795
- indeterminateIcon.style.display = 'none';
796
- }
797
- };
798
- // Handle change
799
- const handleChange = () => {
800
- if (disabledRef.value) {
801
- return;
802
- }
803
- modelRef.value = inputEl.checked;
804
- interminateRef.value = false;
805
- toggleIcon(modelRef.value, interminateRef.value);
806
- onChange(modelRef.value, valueRef.value);
807
- };
808
- const onChange = props['on:change'] ?? $emptyFn;
809
- const labelRef = toReactive(props.label ?? '');
810
- const valueRef = toReactive(props.value ?? '');
811
- const interminateRef = toReactive(props.indeterminate ?? false);
812
- const colorRef = toReactive(props.color ?? 'primary');
813
- const sizeRef = toReactive(props.size ?? 'medium');
814
- const disabledRef = toReactive(props.disabled ?? false, (v) => {
815
- inputEl.disabled = v;
816
- container.classList.toggle('mui-checkbox-disabled', v);
817
- });
818
- const modelRef = $modelOrRef(props, props.checked ?? false);
819
- modelRef.addOnChange((newValue) => {
820
- inputEl.checked = newValue;
821
- toggleIcon(newValue, interminateRef.value);
822
- });
823
- const inputEl = (jsx("input", { type: "checkbox", class: "mui-checkbox-input", checked: modelRef.value, value: valueRef, disabled: disabledRef, "on:change": handleChange }));
824
- const uncheckedIcon = createUncheckedIcon();
825
- const checkedIcon = createCheckedIcon();
826
- const indeterminateIcon = createIndeterminateIcon();
827
- // Initialize icon state
828
- toggleIcon(modelRef.value, interminateRef.value);
829
- const classRef = computed(() => {
830
- return `mui-checkbox-wrapper mui-checkbox-size-${sizeRef.value} ${disabledRef.value ? 'mui-checkbox-disabled' : ''} mui-checkbox-color-${colorRef.value}`;
831
- }, [colorRef, disabledRef, sizeRef]);
832
- 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 })] }));
833
- return container;
834
- }
835
- /**
836
- * CheckboxGroup component - groups multiple checkboxes together
837
- */
838
- function CheckboxGroup(props) {
839
- let { row = false, 'on:change': onChange = $emptyFn } = props;
840
- const changeHandler = (checked, checkboxValue) => {
841
- if (checked) {
842
- $ArrayPushUnique(modelRef.value, checkboxValue);
843
- }
844
- else {
845
- $ArrayDelete(modelRef.value, checkboxValue);
846
- }
847
- onChange(modelRef.value);
848
- };
849
- const rowRef = toReactive(props.row ?? true);
850
- const sizeRef = toReactive(props.size ?? 'medium');
851
- const modelRef = $modelOrRef(props, props.value ?? []);
852
- modelRef.addOnChange((newValues) => {
853
- for (let i = 0; i < checkboxes.value.length; i++) {
854
- const c = checkboxes.value[i];
855
- c.checked = newValues.includes(c.value);
856
- }
857
- });
858
- const customClassRef = toReactive(props.class ?? '');
859
- const classRef = computed(() => {
860
- return `mui-checkbox-group ${rowRef.value ? 'mui-checkbox-group-row' : ''} ${customClassRef.value}`;
861
- }, [rowRef, customClassRef]);
862
- const styleRef = toReactive(parseStyle(props.style ?? ''));
863
- const optionsRef = toReactive(props.options);
864
- const checkboxes = computed(() => {
865
- return optionsRef.value.map((o) => {
866
- o.size = sizeRef.value;
867
- o.checked = modelRef.value.includes(o.value);
868
- const originalChange = o['on:change'];
869
- if (originalChange) {
870
- if (typeof originalChange !== 'function') {
871
- throw new Error('[kt.js error] CheckboxGroup: handler must be a function');
872
- }
873
- o['on:change'] = (checked, value) => {
874
- originalChange(checked, value);
875
- changeHandler(checked, value);
876
- };
877
- }
878
- else {
879
- o['on:change'] = changeHandler;
880
- }
881
- return Checkbox(o);
882
- });
883
- }, [optionsRef, sizeRef]);
884
- console.log('checkboxes', checkboxes.value);
885
- const container = (jsx("div", { class: classRef, style: styleRef, role: "group", children: checkboxes }));
886
- return container;
887
- }
888
-
889
- /**
890
- * Dialog component - mimics MUI Dialog appearance and behavior
891
- * Only handles open/close state, title and content are passed as props
892
- */
893
- function Dialog(props) {
894
- let { 'on:close': onClose = $emptyFn, children, actions } = props;
895
- const titleRef = toReactive(props.title ?? '');
896
- const openRef = toReactive(props.open ?? false, (isOpen) => {
897
- if (isOpen) {
898
- // Opening: set display first, then add class with double RAF for animation
899
- container.style.display = 'flex';
900
- setTimeout(() => container.classList.add('kt-dialog-backdrop-open'), 50);
901
- }
902
- else {
903
- container.classList.remove('kt-dialog-backdrop-open');
904
- setTimeout(() => {
905
- if (!openRef.value) {
906
- container.style.display = 'none';
907
- }
908
- }, 225);
909
- }
910
- });
911
- const sizeRef = toReactive(props.size ?? 'sm');
912
- const fullWidthRef = toReactive(props.fullWidth ?? false);
913
- const classNameRef = computed(() => `kt-dialog-paper ${sizeRef.value ? `kt-dialog-maxWidth-${sizeRef.value}` : ''} ${fullWidthRef.value ? 'kt-dialog-fullWidth' : ''}`, [sizeRef, fullWidthRef]);
914
- // Handle ESC key - store handler for cleanup
915
- const keyDownHandler = (e) => {
916
- if (e.key === 'Escape') {
917
- openRef.value = false;
918
- onClose();
919
- }
920
- };
921
- const handleBackdropClick = (e) => {
922
- if (e.target === container) {
923
- onClose();
924
- }
925
- };
926
- // Backdrop element
927
- 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 })] }) }));
928
- document.addEventListener('keydown', keyDownHandler);
929
- // Store cleanup function
930
- const originalRemove = container.remove;
931
- container.remove = () => {
932
- if (keyDownHandler) {
933
- document.removeEventListener('keydown', keyDownHandler);
934
- }
935
- return originalRemove.call(container);
936
- };
937
- return container;
938
- }
939
-
940
- /**
941
- * FormLabel component - mimics MUI FormLabel appearance and behavior
942
- */
943
- function FormLabel(props) {
944
- const { children, required = false, error = false, disabled = false, focused = false, filled = false, component = 'label', htmlFor, } = props;
945
- const classes = [
946
- 'mui-form-label',
947
- error && 'mui-form-label-error',
948
- disabled && 'mui-form-label-disabled',
949
- focused && 'mui-form-label-focused',
950
- filled && 'mui-form-label-filled',
951
- ]
952
- .filter(Boolean)
953
- .join(' ');
954
- const labelProps = {
955
- class: classes,
956
- };
957
- if (htmlFor) {
958
- labelProps.for = htmlFor;
959
- }
960
- const element = component === 'legend' ? (jsxs("legend", { ...labelProps, children: [children, required && jsx("span", { class: "mui-form-label-asterisk", children: " *" })] })) : (jsxs("label", { ...labelProps, children: [children, required && jsx("span", { class: "mui-form-label-asterisk", children: " *" })] }));
961
- return element;
962
- }
963
-
964
- function LinearProgress(props) {
965
- const valueRef = ref(props.progress ?? 0);
966
- const customClassRef = toReactive(props.class ?? '');
967
- const colorRef = toReactive(props.color ?? 'primary');
968
- const variantRef = toReactive(props.variant ?? 'indeterminate');
969
- const classRef = computed(() => {
970
- return `mui-linear-progress mui-linear-progress-${variantRef.value} mui-linear-progress-${colorRef.value} ${customClassRef.value}`;
971
- }, [customClassRef, colorRef, variantRef]);
972
- const styleRef = toReactive(props.style ?? '');
973
- const barLengthRef = computed(() => {
974
- return variantRef.value === 'determinate' ? `width: ${valueRef.value}%` : '';
975
- }, [variantRef, valueRef]);
976
- const container = (jsx("div", { class: classRef, style: styleRef, role: "progressbar", "aria-valuenow": valueRef, children: jsx("div", { class: "mui-linear-progress-bar", style: barLengthRef }) }));
977
- return container;
978
- }
979
-
980
- function TextField(props) {
981
- // # events
982
- const onInput = props['on:input'] ?? $emptyFn;
983
- const onInputTrim = props['on-trim:input'] ?? $emptyFn;
984
- const onChange = props['on:change'] ?? $emptyFn;
985
- const onChangeTrim = props['on-trim:change'] ?? $emptyFn;
986
- const onBlur = props['on:blur'] ?? $emptyFn;
987
- const onFocus = props['on:focus'] ?? $emptyFn;
988
- const isFocusedRef = ref(false);
989
- // # methods
990
- const handleInput = () => {
991
- if (inputType === 'number') {
992
- const v = Number(inputEl.value);
993
- modelRef.value = v;
994
- onInput(v);
995
- onInputTrim(v);
996
- }
997
- else {
998
- modelRef.value = inputEl.value;
999
- onInput(inputEl.value);
1000
- onInputTrim(inputEl.value.trim());
1001
- }
1002
- };
1003
- const handleChange = () => {
1004
- if (inputType === 'number') {
1005
- const v = Number(inputEl.value);
1006
- modelRef.value = v;
1007
- onChange(v);
1008
- onChangeTrim(v);
1009
- }
1010
- else {
1011
- modelRef.value = inputEl.value;
1012
- onChange(inputEl.value);
1013
- onChangeTrim(inputEl.value.trim());
1014
- }
1015
- };
1016
- const handleFocus = () => {
1017
- isFocused.value = true;
1018
- onFocus(inputEl.value);
1019
- };
1020
- const handleBlur = () => {
1021
- isFocused.value = false;
1022
- onBlur(inputEl.value);
1023
- };
1024
- const handleWrapperMouseDown = (e) => {
1025
- if (disabledRef.value) {
1026
- return;
1027
- }
1028
- const target = e.target;
1029
- if (!target || target === inputEl) {
1030
- return;
1031
- }
1032
- setTimeout(() => inputEl.focus(), 0);
1033
- };
1034
- const getPlaceholder = () => (labelRef.value && !isFocused && !modelRef.value ? '' : placeholderRef.value);
1035
- // # non-refs
1036
- const inputType = deref(props.type ?? 'text');
1037
- const multiline = props.multiline;
1038
- // # refs
1039
- // Create refs for all reactive properties
1040
- const labelRef = toReactive(props.label ?? '');
1041
- const placeholderRef = toReactive(props.placeholder ?? '', () => (inputEl.placeholder = getPlaceholder()));
1042
- const disabledRef = toReactive(props.disabled ?? false);
1043
- const readOnlyRef = toReactive(props.readOnly ?? false);
1044
- const requiredRef = toReactive(props.required ?? false);
1045
- const errorRef = toReactive(props.error ?? false);
1046
- const helperTextRef = toReactive(props.helperText ?? '');
1047
- const fullWidthRef = toReactive(props.fullWidth ?? false);
1048
- const rowsRef = toReactive(props.rows ?? 3);
1049
- const sizeRef = toReactive(props.size ?? 'medium');
1050
- // k-model takes precedence over value prop for two-way binding
1051
- const modelRef = $modelOrRef(props, props.value ?? '');
1052
- // Add change listeners for reactive properties
1053
- // `k-if` changing triggers redrawing, no need to do this again
1054
- // // labelRef.addOnChange(() => {
1055
- // // wrapperRef.redraw();
1056
- // // updateContainerClass();
1057
- // // });
1058
- const isFocused = ref(false);
1059
- const inputEl = multiline
1060
- ? (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 }))
1061
- : (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 }));
1062
- modelRef.addOnChange((newValue) => (inputEl.value = newValue));
1063
- const styleRef = toReactive(parseStyle(props.style ?? ''));
1064
- const customClassRef = toReactive(props.class ?? '');
1065
- const classRef = computed(() => {
1066
- const className = [
1067
- 'mui-textfield-root',
1068
- `mui-textfield-size-${sizeRef.value}`,
1069
- isFocusedRef.value ? 'mui-textfield-focused' : '',
1070
- errorRef.value ? 'mui-textfield-error' : '',
1071
- disabledRef.value ? 'mui-textfield-disabled' : '',
1072
- fullWidthRef.value ? 'mui-textfield-fullwidth' : '',
1073
- labelRef.value && inputEl.value ? 'mui-textfield-has-value' : '',
1074
- labelRef.value ? '' : 'mui-textfield-no-label',
1075
- customClassRef.value ? customClassRef.value : '',
1076
- ].join(' ');
1077
- return className;
1078
- }, [sizeRef, errorRef, disabledRef, fullWidthRef, labelRef, isFocusedRef, customClassRef]);
1079
- // if (multiline) {
1080
- // rowsRef.addOnChange((newRows) => ((inputEl as HTMLTextAreaElement).rows = newRows));
1081
- // }
1082
- 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 })] }));
1083
- return container;
1084
- }
1085
-
1086
- /**
1087
- * Radio component - mimics MUI Radio appearance and behavior
1088
- */
1089
- function Radio(props) {
1090
- const onChange = props['on:change'] ?? $emptyFn;
1091
- const toggleIcon = (checked) => {
1092
- uncheckedIcon.style.display = checked ? 'none' : '';
1093
- checkedIcon.style.display = checked ? '' : 'none';
1094
- };
1095
- // Handle change
1096
- const handleChange = () => {
1097
- if (disabled) {
1098
- return;
1099
- }
1100
- checked = input.checked;
1101
- toggleIcon(checked);
1102
- onChange(checked, value);
1103
- };
1104
- let { checked = false, value = '', label: text = '', size = 'small', disabled = false, color = 'primary' } = props;
1105
- const valueRef = toReactive(props.value ?? '');
1106
- const disabledRef = toReactive(props.disabled ?? false);
1107
- const input = (jsx("input", { type: "radio", class: "mui-radio-input", checked: checked, value: valueRef, disabled: disabledRef, "on:change": handleChange }));
1108
- 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" }) }) }));
1109
- 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" }) }) }));
1110
- // initialize icon state
1111
- toggleIcon(checked);
1112
- const container = (jsxs("label", { class: `mui-radio-wrapper ${props.class ?? ''} mui-radio-size-${size} ${disabled ? 'mui-radio-disabled' : ''} mui-radio-color-${color}`, style: parseStyle(props.style), children: [input, jsxs("span", { class: "mui-radio-icon", children: [uncheckedIcon, checkedIcon] }), jsx("span", { class: "mui-radio-label", children: text })] }));
1113
- $defines(container, {
1114
- value: {
1115
- get() {
1116
- return value;
1117
- },
1118
- },
1119
- checked: {
1120
- get() {
1121
- return checked;
1122
- },
1123
- set(newChecked) {
1124
- checked = newChecked;
1125
- input.checked = checked;
1126
- toggleIcon(checked);
1127
- },
1128
- },
1129
- });
1130
- return container;
1131
- }
1132
- /**
1133
- * RadioGroup component - groups multiple radios together
1134
- */
1135
- function RadioGroup(props) {
1136
- let { value = '', size = 'small', row = false } = props;
1137
- const onChange = props['on:change'] ?? $emptyFn;
1138
- const changeHandler = (checked, value) => {
1139
- if (checked) {
1140
- onChange(value);
1141
- }
1142
- radios.forEach((radio) => (radio.checked = radio.value === value));
1143
- };
1144
- const radios = props.options.map((o) => {
1145
- o.size = size;
1146
- o.checked = value === o.value;
1147
- const originalChange = o['on:change'];
1148
- if (originalChange) {
1149
- o['on:change'] = (checked, newValue) => {
1150
- originalChange(checked, newValue);
1151
- changeHandler(checked, newValue);
1152
- };
1153
- }
1154
- else {
1155
- o['on:change'] = changeHandler;
1156
- }
1157
- return Radio(o);
1158
- });
1159
- const container = (jsx("div", { class: `mui-radio-group ${row ? 'mui-radio-group-row' : ''} ${props.class ?? ''}`, style: parseStyle(props.style), role: "radiogroup", children: radios }));
1160
- $defines(container, {
1161
- value: {
1162
- get() {
1163
- return value;
1164
- },
1165
- set(newValue) {
1166
- value = newValue;
1167
- radios.forEach((radio) => (radio.checked = radio.value === value));
1168
- },
1169
- },
1170
- });
1171
- return container;
1172
- }
1173
-
1174
- /**
1175
- * Select component - mimics MUI Select appearance and behavior
1176
- */
1177
- function Select(props) {
1178
- const onChange = props['on:change'] ?? $emptyFn;
1179
- // # refs
1180
- const isFocusedRef = ref(false);
1181
- const open = ref(false, (isOpen) => {
1182
- if (isOpen) {
1183
- menu.value.style.display = 'block';
1184
- void menu.value.offsetHeight; // & Trigger reflow to enable animation
1185
- }
1186
- else {
1187
- // Hide after animation completes
1188
- setTimeout(() => {
1189
- if (!isOpen) {
1190
- menu.value.style.display = 'none';
1191
- }
1192
- }, 200);
1193
- }
1194
- menu.value.classList.toggle('mui-select-menu-open', isOpen);
1195
- container.classList.toggle('mui-select-open', isOpen);
1196
- });
1197
- // # ref props
1198
- const placeholderRef = toReactive(props.placeholder ?? '');
1199
- const labelRef = toReactive(props.label ?? '');
1200
- const optionsRef = toReactive(props.options, (newOptions) => {
1201
- if (!newOptions.find((o) => o.value === modelRef.value)) {
1202
- onChange((modelRef.value = ''));
1203
- }
1204
- });
1205
- const disabledRef = toReactive(props.disabled ?? false, (v) => container.classList.toggle('mui-select-disabled', v));
1206
- const modelRef = $modelOrRef(props, props.value ?? '');
1207
- const styleRef = toReactive(parseStyle(props.style ?? ''));
1208
- const classRef = toReactive(props.class ?? '');
1209
- const sizeRef = toReactive(props.size ?? 'medium');
1210
- const fullwidthRef = toReactive(props.fullWidth ?? false);
1211
- const className = computed(() => {
1212
- return `mui-select-wrapper mui-select-size-${sizeRef.value} ${fullwidthRef.value ? 'mui-select-fullWidth' : ''} ${classRef.value} ${disabledRef.value ? 'mui-select-disabled' : ''}`;
1213
- }, [sizeRef, fullwidthRef, classRef, disabledRef]);
1214
- const label = computed(() => {
1215
- if (labelRef.value) {
1216
- return (jsx("label", { class: `mui-select-label ${modelRef.value || isFocusedRef.value || placeholderRef.value ? 'focused' : ''}`, children: labelRef }));
1217
- }
1218
- return '';
1219
- }, [labelRef, modelRef, isFocusedRef, placeholderRef]);
1220
- // Toggle dropdown
1221
- const toggleMenu = () => {
1222
- if (!disabledRef.value) {
1223
- open.value = !open.value;
1224
- }
1225
- };
1226
- // Handle option click
1227
- const handleOptionClick = (e) => {
1228
- const newValue = e.currentTarget.dataset.value;
1229
- modelRef.value = newValue;
1230
- onChange(newValue);
1231
- open.value = false;
1232
- };
1233
- // Close menu when clicking outside
1234
- const handleClickOutside = (e) => {
1235
- if (!container.contains(e.target)) {
1236
- open.value = false;
1237
- }
1238
- };
1239
- // Handle focus
1240
- const handleFocus = () => (isFocusedRef.value = true);
1241
- const handleBlur = () => (isFocusedRef.value = false);
1242
- const defaultEmpty = jsx("span", { class: "mui-select-placeholder", children: placeholderRef.value || '\u00a0' });
1243
- const displayedValue = computed(() => {
1244
- const o = optionsRef.value.find((item) => item.value === modelRef.value);
1245
- return jsx("div", { class: "mui-select-display", children: o?.label ?? defaultEmpty });
1246
- }, [modelRef]);
1247
- const menu = computed(() => {
1248
- 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 }))), ' '] }));
1249
- }, [optionsRef, modelRef]);
1250
- // Create container
1251
- 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] }));
1252
- // Add global click listener
1253
- setTimeout(() => {
1254
- document.removeEventListener('click', handleClickOutside);
1255
- document.addEventListener('click', handleClickOutside);
1256
- }, 0);
1257
- return container;
1258
- }
1259
-
1260
- /**
1261
- * Card component - mimics MUI Card appearance and behavior
1262
- */
1263
- function Card(props) {
1264
- // # ref props
1265
- const variantRef = toReactive(props.variant ?? 'elevation');
1266
- const elevationRef = toReactive(props.elevation ?? 1);
1267
- const squareRef = toReactive(props.square ?? false);
1268
- const raisedRef = toReactive(props.raised ?? false);
1269
- const styleRef = toReactive(parseStyle(props.style ?? ''));
1270
- const classRef = toReactive(props.class ?? '');
1271
- const className = computed(() => {
1272
- const base = 'mui-card';
1273
- const variantClass = `mui-card-${variantRef.value}`;
1274
- const elevationClass = variantRef.value === 'elevation' ? `mui-card-elevation-${Math.min(24, Math.max(0, elevationRef.value))}` : '';
1275
- const squareClass = squareRef.value ? 'mui-card-square' : '';
1276
- const raisedClass = raisedRef.value ? 'mui-card-raised' : '';
1277
- return `${base} ${variantClass} ${elevationClass} ${squareClass} ${raisedClass} ${classRef.value}`.trim().replace(/\s+/g, ' ');
1278
- }, [variantRef, elevationRef, squareRef, raisedRef, classRef]);
1279
- // Handle click
1280
- const handleClick = props['on:click'] ?? (() => { });
1281
- const container = (jsx("div", { class: className, style: styleRef, "on:click": handleClick, children: props.children }));
1282
- return container;
1283
- }
1284
-
1285
- /**
1286
- * Switch component - mimics MUI Switch appearance and behavior
1287
- */
1288
- function Switch(props) {
1289
- const onChange = props['on:change'] ?? $emptyFn;
1290
- // # ref props
1291
- const labelRef = toReactive(props.label ?? '');
1292
- const valueRef = toReactive(props.value ?? '');
1293
- const colorRef = toReactive(props.color ?? 'primary');
1294
- const sizeRef = toReactive(props.size ?? 'medium');
1295
- const disabledRef = toReactive(props.disabled ?? false, (v) => {
1296
- inputEl.disabled = v;
1297
- container.classList.toggle('mui-switch-disabled', v);
1298
- });
1299
- const modelRef = $modelOrRef(props, props.checked ?? false);
1300
- modelRef.addOnChange((newValue) => {
1301
- inputEl.checked = newValue;
1302
- track.classList.toggle('mui-switch-track-checked', newValue);
1303
- thumb.classList.toggle('mui-switch-thumb-checked', newValue);
1304
- });
1305
- const styleRef = toReactive(parseStyle(props.style ?? ''));
1306
- const classRef = toReactive(props.class ?? '');
1307
- const className = computed(() => {
1308
- return `mui-switch-wrapper mui-switch-size-${sizeRef.value} ${disabledRef.value ? 'mui-switch-disabled' : ''} mui-switch-color-${colorRef.value} ${classRef.value}`;
1309
- }, [colorRef, disabledRef, sizeRef, classRef]);
1310
- // Handle change
1311
- const handleChange = () => {
1312
- if (disabledRef.value) {
1313
- return;
1314
- }
1315
- modelRef.value = inputEl.checked;
1316
- onChange(modelRef.value, valueRef.value);
1317
- };
1318
- const inputEl = (jsx("input", { type: "checkbox", class: "mui-switch-input", checked: modelRef.value, value: valueRef, disabled: disabledRef, "on:change": handleChange }));
1319
- const track = jsx("span", { class: "mui-switch-track" });
1320
- const thumb = jsx("span", { class: "mui-switch-thumb" });
1321
- 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 })] }));
1322
- // Initialize state
1323
- track.classList.toggle('mui-switch-track-checked', modelRef.value);
1324
- thumb.classList.toggle('mui-switch-thumb-checked', modelRef.value);
1325
- return container;
1326
- }
1327
-
1328
- function DownloadIcon(props) {
1329
- 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" }) }));
1330
- }
1331
-
1332
- function CompressIcon(props) {
1333
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M4 9h16v2H4zm0 4h16v2H4zm8-9 4 4H8zm0 14 4-4H8z" }) }));
1334
- }
1335
-
1336
- function SubtitlesIcon(props) {
1337
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM4 12h4v2H4v-2zm10 6H4v-2h10v2zm6 0h-4v-2h4v2zm0-4H10v-2h10v2z" }) }));
1338
- }
1339
-
1340
- function SettingsIcon(props) {
1341
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.07.62-.07.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z" }) }));
1342
- }
1343
-
1344
- function NewReleasesIcon(props) {
1345
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "m23 12-2.44-2.79.34-3.69-3.61-.82-1.89-3.2L12 2.96 8.6 1.5 6.71 4.69 3.1 5.5l.34 3.7L1 12l2.44 2.79-.34 3.7 3.61.82L8.6 22.5l3.4-1.47 3.4 1.46 1.89-3.19 3.61-.82-.34-3.69L23 12zm-12.91 4.72-3.8-3.81 1.48-1.48 2.32 2.33 5.85-5.87 1.48 1.48-7.33 7.35z" }) }));
1346
- }
1347
-
1348
- function FolderOpenIcon(props) {
1349
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z" }) }));
1350
- }
1351
-
1352
- function PlayArrowIcon(props) {
1353
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M8 5v14l11-7z" }) }));
1354
- }
1355
-
1356
- function ContentPasteIcon(props) {
1357
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z" }) }));
1358
- }
1359
-
1360
- function DeleteIcon(props) {
1361
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" }) }));
1362
- }
1363
-
1364
- function StopIcon(props) {
1365
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M6 6h12v12H6z" }) }));
1366
- }
1367
-
1368
- function FileOpenIcon(props) {
1369
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H15l6-6V4c0-1.1-.9-2-2-2zm-1 7V3.5L18.5 9H13z" }) }));
1370
- }
1371
-
1372
- function ColorLensIcon(props) {
1373
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z" }) }));
1374
- }
1375
-
1376
- function WallpaperIcon(props) {
1377
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M4 4h7V2H4c-1.1 0-2 .9-2 2v7h2V4zm6 9-4 5h12l-3-4-2.03 2.71L10 13zm7-4.5c0-.83-.67-1.5-1.5-1.5S14 7.67 14 8.5s.67 1.5 1.5 1.5S17 9.33 17 8.5zM20 2h-7v2h7v7h2V4c0-1.1-.9-2-2-2zm0 18h-7v2h7c1.1 0 2-.9 2-2v-7h-2v7zM4 13H2v7c0 1.1.9 2 2 2h7v-2H4v-7z" }) }));
1378
- }
1379
-
1380
- function ExpandMoreIcon(props) {
1381
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M16.59 8.59 12 13.17 7.41 8.59 6 10l6 6 6-6z" }) }));
1382
- }
1383
-
1384
- function SaveIcon(props) {
1385
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z" }) }));
1386
- }
1387
-
1388
- function UploadFileIcon(props) {
1389
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11zM8 15.01l1.41 1.41L11 14.84V19h2v-4.16l1.59 1.59L16 15.01 12.01 11z" }) }));
1390
- }
1391
-
1392
- function VideoFileIcon(props) {
1393
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zM6 20V4h7v5h5v11H6zm10-7v-1.5l2 1.5-2 1.5V13H8v-2h8z" }) }));
1394
- }
1395
-
1396
- function QueuePlayNextIcon(props) {
1397
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M21 3H3c-1.11 0-2 .89-2 2v12c0 1.1.89 2 2 2h5v2h8v-2h2v-2H3V5h18v8h2V5c0-1.11-.9-2-2-2zm-8 7V7h-2v3H8v2h3v3h2v-3h3v-2h-3zm11 8-4.5 4.5L18 21l3-3-3-3 1.5-1.5L24 18z" }) }));
1398
- }
1399
-
1400
- function MenuIcon(props) {
1401
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" }) }));
1402
- }
1403
-
1404
- function HomeIcon(props) {
1405
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" }) }));
1406
- }
1407
-
1408
- function ContentCopyIcon(props) {
1409
- return (jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "1em", height: "1em", ...props, children: jsx("path", { d: "M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" }) }));
1410
- }
1411
-
1412
- function SelectAllIcon(props) {
1413
- 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" }) }));
1414
- }
1415
-
1416
- exports.Alert = Alert;
1417
- exports.Button = Button;
1418
- exports.Card = Card;
1419
- exports.Checkbox = Checkbox;
1420
- exports.CheckboxGroup = CheckboxGroup;
1421
- exports.ColorLensIcon = ColorLensIcon;
1422
- exports.CompressIcon = CompressIcon;
1423
- exports.ContentCopyIcon = ContentCopyIcon;
1424
- exports.ContentPasteIcon = ContentPasteIcon;
1425
- exports.DeleteIcon = DeleteIcon;
1426
- exports.Dialog = Dialog;
1427
- exports.DownloadIcon = DownloadIcon;
1428
- exports.ExpandMoreIcon = ExpandMoreIcon;
1429
- exports.FileOpenIcon = FileOpenIcon;
1430
- exports.FolderOpenIcon = FolderOpenIcon;
1431
- exports.FormLabel = FormLabel;
1432
- exports.HomeIcon = HomeIcon;
1433
- exports.LinearProgress = LinearProgress;
1434
- exports.MenuIcon = MenuIcon;
1435
- exports.NewReleasesIcon = NewReleasesIcon;
1436
- exports.PlayArrowIcon = PlayArrowIcon;
1437
- exports.QueuePlayNextIcon = QueuePlayNextIcon;
1438
- exports.Radio = Radio;
1439
- exports.RadioGroup = RadioGroup;
1440
- exports.SaveIcon = SaveIcon;
1441
- exports.Select = Select;
1442
- exports.SelectAllIcon = SelectAllIcon;
1443
- exports.SettingsIcon = SettingsIcon;
1444
- exports.StopIcon = StopIcon;
1445
- exports.SubtitlesIcon = SubtitlesIcon;
1446
- exports.Switch = Switch;
1447
- exports.TextField = TextField;
1448
- exports.UploadFileIcon = UploadFileIcon;
1449
- exports.VideoFileIcon = VideoFileIcon;
1450
- exports.WallpaperIcon = WallpaperIcon;
1451
-
1452
- return exports;
1453
-
1454
- })({});