@ktjs/mui 0.18.9 → 0.20.0
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.d.ts +1296 -33
- package/dist/index.iife.js +492 -203
- package/dist/index.mjs +443 -156
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -1,30 +1,311 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// Cached native methods for performance optimization
|
|
2
|
+
const $isArray = Array.isArray;
|
|
3
|
+
const $isThenable = (o) => typeof o === 'object' && o !== null && typeof o.then === 'function';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
// Error handling utilities
|
|
6
|
+
const $throw = (message) => {
|
|
7
|
+
throw new Error('@ktjs/shared: ' + message);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// DOM manipulation utilities
|
|
11
|
+
// # dom natives
|
|
12
|
+
/**
|
|
13
|
+
* & Remove `bind` because it is shockingly slower than wrapper
|
|
14
|
+
* & `window.document` is safe because it is not configurable and its setter is undefined
|
|
6
15
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
const $appendChild = HTMLElement.prototype.appendChild;
|
|
17
|
+
const originAppend = HTMLElement.prototype.append;
|
|
18
|
+
const $append = // for ie 9/10/11
|
|
19
|
+
typeof originAppend === 'function'
|
|
20
|
+
? originAppend
|
|
21
|
+
: function (...nodes) {
|
|
22
|
+
if (nodes.length < 50) {
|
|
23
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
24
|
+
const node = nodes[i];
|
|
25
|
+
if (typeof node === 'string') {
|
|
26
|
+
$appendChild.call(this, document.createTextNode(node));
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
$appendChild.call(this, node);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const fragment = document.createDocumentFragment();
|
|
35
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
36
|
+
const node = nodes[i];
|
|
37
|
+
if (typeof node === 'string') {
|
|
38
|
+
$appendChild.call(fragment, document.createTextNode(node));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
$appendChild.call(fragment, node);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
$appendChild.call(this, fragment);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const { get: $buttonDisabledGetter$2, set: $buttonDisabledSetter$2 } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
|
|
48
|
+
|
|
49
|
+
// Shared utilities and cached native methods for kt.js framework
|
|
50
|
+
// Re-export all utilities
|
|
51
|
+
Object.defineProperty(window, '@ktjs/shared', { value: '0.20.0' });
|
|
52
|
+
|
|
53
|
+
const booleanHandler = (element, key, value) => {
|
|
54
|
+
if (key in element) {
|
|
55
|
+
element[key] = !!value;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
element.setAttribute(key, value);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const valueHandler = (element, key, value) => {
|
|
62
|
+
if (key in element) {
|
|
63
|
+
element[key] = value;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
element.setAttribute(key, value);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
// Attribute handlers map for optimized lookup
|
|
70
|
+
const handlers = {
|
|
71
|
+
checked: booleanHandler,
|
|
72
|
+
selected: booleanHandler,
|
|
73
|
+
value: valueHandler,
|
|
74
|
+
valueAsDate: valueHandler,
|
|
75
|
+
valueAsNumber: valueHandler,
|
|
76
|
+
defaultValue: valueHandler,
|
|
77
|
+
defaultChecked: booleanHandler,
|
|
78
|
+
defaultSelected: booleanHandler,
|
|
79
|
+
disabled: booleanHandler,
|
|
80
|
+
readOnly: booleanHandler,
|
|
81
|
+
multiple: booleanHandler,
|
|
82
|
+
required: booleanHandler,
|
|
83
|
+
autofocus: booleanHandler,
|
|
84
|
+
open: booleanHandler,
|
|
85
|
+
controls: booleanHandler,
|
|
86
|
+
autoplay: booleanHandler,
|
|
87
|
+
loop: booleanHandler,
|
|
88
|
+
muted: booleanHandler,
|
|
89
|
+
defer: booleanHandler,
|
|
90
|
+
async: booleanHandler,
|
|
91
|
+
hidden: (element, _key, value) => (element.hidden = !!value),
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const defaultHandler = (element, key, value) => element.setAttribute(key, value);
|
|
95
|
+
function attrIsObject(element, attr) {
|
|
96
|
+
const classValue = attr.class || attr.className;
|
|
97
|
+
if (classValue !== undefined) {
|
|
98
|
+
element.setAttribute('class', classValue);
|
|
99
|
+
}
|
|
100
|
+
const style = attr.style;
|
|
101
|
+
if (style) {
|
|
102
|
+
if (typeof style === 'string') {
|
|
103
|
+
element.setAttribute('style', style);
|
|
104
|
+
}
|
|
105
|
+
else if (typeof style === 'object') {
|
|
106
|
+
for (const key in style) {
|
|
107
|
+
element.style[key] = style[key];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
for (const key in attr) {
|
|
112
|
+
if (key === 'class' ||
|
|
113
|
+
key === 'className' ||
|
|
114
|
+
key === 'style' ||
|
|
115
|
+
key === 'children' ||
|
|
116
|
+
key === 'k-if' ||
|
|
117
|
+
key === 'ref') {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const o = attr[key];
|
|
121
|
+
// normal event handler
|
|
122
|
+
if (key.startsWith('on:')) {
|
|
123
|
+
element.addEventListener(key.slice(3), o); // chop off the `on:`
|
|
124
|
+
}
|
|
125
|
+
// normal attributes
|
|
126
|
+
else {
|
|
127
|
+
(handlers[key] || defaultHandler)(element, key, o);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function applyAttr(element, attr) {
|
|
132
|
+
if (!attr) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (typeof attr === 'object' && attr !== null) {
|
|
136
|
+
attrIsObject(element, attr);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
throw new Error('kt.js: attr must be an object.');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function apdSingle(element, c) {
|
|
144
|
+
// & JSX should ignore false, undefined, and null
|
|
145
|
+
if (c === false || c === undefined || c === null) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (typeof c === 'object' && c !== null && 'isKT' in c) {
|
|
149
|
+
$append.call(element, c.value);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
$append.call(element, c);
|
|
153
|
+
// Handle KTFor anchor
|
|
154
|
+
const list = c.__kt_for_list__;
|
|
155
|
+
if ($isArray(list)) {
|
|
156
|
+
apd(element, list);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function apd(element, c) {
|
|
161
|
+
if ($isThenable(c)) {
|
|
162
|
+
c.then((r) => apd(element, r));
|
|
163
|
+
}
|
|
164
|
+
else if ($isArray(c)) {
|
|
165
|
+
for (let i = 0; i < c.length; i++) {
|
|
166
|
+
// & might be thenable here too
|
|
167
|
+
const ci = c[i];
|
|
168
|
+
if ($isThenable(ci)) {
|
|
169
|
+
const comment = document.createComment('ktjs-promise-placeholder');
|
|
170
|
+
$append.call(element, comment);
|
|
171
|
+
ci.then((awaited) => comment.replaceWith(awaited));
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
apdSingle(element, ci);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
// & here is thened, so must be a simple elementj
|
|
180
|
+
apdSingle(element, c);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function applyContent(element, content) {
|
|
184
|
+
if ($isArray(content)) {
|
|
185
|
+
for (let i = 0; i < content.length; i++) {
|
|
186
|
+
apd(element, content[i]);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
apd(element, content);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const svgTempWrapper = document.createElement('div');
|
|
195
|
+
/**
|
|
196
|
+
* Create an enhanced HTMLElement.
|
|
197
|
+
* - Only supports HTMLElements, **NOT** SVGElements or other Elements.
|
|
198
|
+
* @param tag tag of an `HTMLElement`
|
|
199
|
+
* @param attr attribute object or className
|
|
200
|
+
* @param content a string or an array of HTMLEnhancedElement as child nodes
|
|
201
|
+
*
|
|
202
|
+
* ## About
|
|
203
|
+
* @package @ktjs/core
|
|
204
|
+
* @author Kasukabe Tsumugi <futami16237@gmail.com>
|
|
205
|
+
* @version 0.20.0 (Last Update: 2026.02.01 00:47:09.995)
|
|
206
|
+
* @license MIT
|
|
207
|
+
* @link https://github.com/baendlorel/kt.js
|
|
208
|
+
* @link https://baendlorel.github.io/ Welcome to my site!
|
|
209
|
+
* @description Core functionality for kt.js - DOM manipulation utilities with JSX/TSX support
|
|
210
|
+
* @copyright Copyright (c) 2026 Kasukabe Tsumugi. All rights reserved.
|
|
211
|
+
*/
|
|
212
|
+
const h = (tag, attr, content) => {
|
|
213
|
+
if (typeof tag !== 'string') {
|
|
214
|
+
$throw('tagName must be a string.');
|
|
215
|
+
}
|
|
216
|
+
// * start creating the element
|
|
217
|
+
const element = document.createElement(tag);
|
|
218
|
+
// * Handle content
|
|
219
|
+
applyAttr(element, attr);
|
|
220
|
+
applyContent(element, content);
|
|
221
|
+
if (tag === 'svg') {
|
|
222
|
+
svgTempWrapper.innerHTML = element.outerHTML;
|
|
223
|
+
return svgTempWrapper.firstChild;
|
|
224
|
+
}
|
|
225
|
+
return element;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const dummyRef = { value: null };
|
|
229
|
+
/**
|
|
230
|
+
* @param tag html tag or function component
|
|
231
|
+
* @param props properties/attributes
|
|
232
|
+
*/
|
|
233
|
+
function jsx(tag, props = {}) {
|
|
234
|
+
const ref = props.ref?.isKT ? props.ref : dummyRef;
|
|
235
|
+
let el;
|
|
236
|
+
if ('k-if' in props && !props['k-if']) {
|
|
237
|
+
// & make comment placeholder in case that ref might be redrawn later
|
|
238
|
+
el = document.createComment('k-if');
|
|
239
|
+
ref.value = el;
|
|
240
|
+
return el;
|
|
241
|
+
}
|
|
242
|
+
// Handle function components
|
|
243
|
+
if (typeof tag === 'function') {
|
|
244
|
+
el = tag(props);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
el = h(tag, props, props.children);
|
|
248
|
+
}
|
|
249
|
+
ref.value = el;
|
|
250
|
+
return el;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* JSX runtime for React 17+ automatic runtime
|
|
254
|
+
* This is called when using jsx: "react-jsx" or "react-jsxdev"
|
|
255
|
+
*/
|
|
256
|
+
const jsxs = jsx;
|
|
257
|
+
|
|
258
|
+
// Cached native methods for performance optimization
|
|
259
|
+
const $defines = Object.defineProperties;
|
|
260
|
+
|
|
261
|
+
// String manipulation utilities
|
|
262
|
+
/**
|
|
263
|
+
* Default empty function
|
|
264
|
+
*/
|
|
265
|
+
const $emptyFn = (() => true);
|
|
266
|
+
const { get: $buttonDisabledGetter$1, set: $buttonDisabledSetter$1 } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
|
|
267
|
+
// # DOM utilities
|
|
268
|
+
const parseStyle = (style) => {
|
|
269
|
+
if (typeof style === 'string') {
|
|
270
|
+
return style;
|
|
271
|
+
}
|
|
12
272
|
if (style && typeof style === 'object') {
|
|
13
|
-
|
|
273
|
+
return Object.entries(style)
|
|
14
274
|
.map(([key, value]) => {
|
|
15
275
|
// Convert camelCase to kebab-case
|
|
16
276
|
const cssKey = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
17
277
|
return `${cssKey}: ${value}`;
|
|
18
278
|
})
|
|
19
279
|
.join('; ');
|
|
20
|
-
styleString = styleString ? `${styleString}; ${sxStyles}` : sxStyles;
|
|
21
280
|
}
|
|
281
|
+
return '';
|
|
282
|
+
};
|
|
283
|
+
const generateHandler = (props, key) => {
|
|
284
|
+
const handler = props[key];
|
|
285
|
+
if (typeof handler === 'function') {
|
|
286
|
+
return handler;
|
|
287
|
+
}
|
|
288
|
+
else if (handler && typeof handler === 'object' && handler.isKT) {
|
|
289
|
+
return (value) => (handler.value = value);
|
|
290
|
+
}
|
|
291
|
+
return $emptyFn;
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
// Shared utilities and cached native methods for kt.js framework
|
|
295
|
+
// Re-export all utilities
|
|
296
|
+
Object.defineProperty(window, '@ktjs/shared', { value: '0.20.0' });
|
|
297
|
+
|
|
298
|
+
function Alert(props) {
|
|
299
|
+
const { children, severity = 'info', variant = 'standard', icon, 'kt:close': onClose } = props;
|
|
300
|
+
const classes = `mui-alert mui-alert-${severity} mui-alert-${variant} ${props.class ? props.class : ''}`;
|
|
22
301
|
// Icon SVG paths for different severities
|
|
23
302
|
const getIcon = () => {
|
|
24
|
-
if (icon === false)
|
|
303
|
+
if (icon === false) {
|
|
25
304
|
return null;
|
|
26
|
-
|
|
305
|
+
}
|
|
306
|
+
if (icon) {
|
|
27
307
|
return icon;
|
|
308
|
+
}
|
|
28
309
|
const iconSize = '22px';
|
|
29
310
|
const iconClass = 'mui-alert-icon';
|
|
30
311
|
switch (severity) {
|
|
@@ -40,55 +321,26 @@ function Alert(props) {
|
|
|
40
321
|
}
|
|
41
322
|
};
|
|
42
323
|
const alertIcon = getIcon();
|
|
43
|
-
const alert = (jsxs("div", { class: classes, style:
|
|
324
|
+
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 }), onClose && (jsx("button", { 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" }) }) }))] }));
|
|
44
325
|
return alert;
|
|
45
326
|
}
|
|
46
327
|
|
|
47
|
-
const emptyFn = () => { };
|
|
48
|
-
const generateHandler = (props, key) => {
|
|
49
|
-
const handler = props[key];
|
|
50
|
-
if (typeof handler === 'function') {
|
|
51
|
-
return handler;
|
|
52
|
-
}
|
|
53
|
-
else if (handler && typeof handler === 'object' && handler.isKT) {
|
|
54
|
-
return (value) => (handler.value = value);
|
|
55
|
-
}
|
|
56
|
-
return emptyFn;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const parseStyle = (style) => {
|
|
60
|
-
if (typeof style === 'string') {
|
|
61
|
-
return style;
|
|
62
|
-
}
|
|
63
|
-
if (style && typeof style === 'object') {
|
|
64
|
-
return Object.entries(style)
|
|
65
|
-
.map(([key, value]) => {
|
|
66
|
-
// Convert camelCase to kebab-case
|
|
67
|
-
const cssKey = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
68
|
-
return `${cssKey}: ${value}`;
|
|
69
|
-
})
|
|
70
|
-
.join('; ');
|
|
71
|
-
}
|
|
72
|
-
return '';
|
|
73
|
-
};
|
|
74
|
-
|
|
75
328
|
/**
|
|
76
329
|
* Button component - mimics MUI Button appearance and behavior
|
|
77
330
|
*/
|
|
78
331
|
function Button(props) {
|
|
79
|
-
|
|
332
|
+
let { children, variant = 'text', color = 'primary', size = 'medium', disabled = false, fullWidth = false, iconOnly = false, startIcon, endIcon, type = 'button', 'on:click': onClick = $emptyFn, } = props;
|
|
80
333
|
const classes = [
|
|
81
334
|
'mui-button',
|
|
82
335
|
`mui-button-${variant}`,
|
|
83
336
|
`mui-button-${variant}-${color}`,
|
|
84
337
|
`mui-button-size-${size}`,
|
|
85
|
-
fullWidth
|
|
86
|
-
iconOnly
|
|
87
|
-
disabled
|
|
338
|
+
fullWidth ? 'mui-button-fullwidth' : '',
|
|
339
|
+
iconOnly ? 'mui-button-icon-only' : '',
|
|
340
|
+
disabled ? 'mui-button-disabled' : '',
|
|
88
341
|
props.class ? props.class : '',
|
|
89
|
-
]
|
|
90
|
-
|
|
91
|
-
.join(' ');
|
|
342
|
+
].join(' ');
|
|
343
|
+
const rippleContainer = jsx("span", { class: "mui-button-ripple" });
|
|
92
344
|
const handleClick = (e) => {
|
|
93
345
|
if (disabled) {
|
|
94
346
|
e.preventDefault();
|
|
@@ -96,7 +348,6 @@ function Button(props) {
|
|
|
96
348
|
}
|
|
97
349
|
// Create ripple effect
|
|
98
350
|
const button = e.currentTarget;
|
|
99
|
-
const rippleContainer = button.querySelector('.mui-button-ripple');
|
|
100
351
|
if (rippleContainer) {
|
|
101
352
|
const rect = button.getBoundingClientRect();
|
|
102
353
|
const size = Math.max(rect.width, rect.height);
|
|
@@ -109,13 +360,21 @@ function Button(props) {
|
|
|
109
360
|
ripple.classList.add('mui-button-ripple-effect');
|
|
110
361
|
rippleContainer.appendChild(ripple);
|
|
111
362
|
// Remove ripple after animation
|
|
112
|
-
setTimeout(() =>
|
|
113
|
-
ripple.remove();
|
|
114
|
-
}, 600);
|
|
363
|
+
setTimeout(() => ripple.remove(), 600);
|
|
115
364
|
}
|
|
116
365
|
onClick(e);
|
|
117
366
|
};
|
|
118
|
-
|
|
367
|
+
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] }));
|
|
368
|
+
$defines(container, {
|
|
369
|
+
disabled: {
|
|
370
|
+
get: $buttonDisabledGetter$1,
|
|
371
|
+
set: function (value) {
|
|
372
|
+
$buttonDisabledSetter$1.call(this, value);
|
|
373
|
+
this.classList.toggle('mui-button-disabled', value);
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
});
|
|
377
|
+
return container;
|
|
119
378
|
}
|
|
120
379
|
|
|
121
380
|
/**
|
|
@@ -156,7 +415,7 @@ function Checkbox(props) {
|
|
|
156
415
|
// Initialize icon state
|
|
157
416
|
toggleIcon(checked, indeterminate);
|
|
158
417
|
const container = (jsxs("label", { class: `mui-checkbox-wrapper mui-checkbox-size-${size} ${disabled ? 'mui-checkbox-disabled' : ''} mui-checkbox-color-${color}`, children: [inputEl, jsxs("span", { class: "mui-checkbox-icon", children: [uncheckedIcon, checkedIcon, indeterminateIcon] }), jsx("span", { "k-if": label, class: "mui-checkbox-label", children: label })] }));
|
|
159
|
-
|
|
418
|
+
$defines(container, {
|
|
160
419
|
checked: {
|
|
161
420
|
get() {
|
|
162
421
|
return checked;
|
|
@@ -222,7 +481,7 @@ function CheckboxGroup(props) {
|
|
|
222
481
|
return Checkbox(o);
|
|
223
482
|
});
|
|
224
483
|
const container = (jsx("div", { class: `mui-checkbox-group ${row ? 'mui-checkbox-group-row' : ''} ${props.class ? props.class : ''}`, style: props.style ? props.style : '', role: "group", children: checkboxes }));
|
|
225
|
-
|
|
484
|
+
$defines(container, {
|
|
226
485
|
value: {
|
|
227
486
|
get() {
|
|
228
487
|
return Array.from(selectedValues);
|
|
@@ -269,7 +528,7 @@ function CheckboxGroup(props) {
|
|
|
269
528
|
* Only handles open/close state, title and content are passed as props
|
|
270
529
|
*/
|
|
271
530
|
function Dialog(props) {
|
|
272
|
-
let { open = false, 'kt:close': onClose = emptyFn, title, children, actions, maxWidth = 'sm', fullWidth = false, } = props;
|
|
531
|
+
let { open = false, 'kt:close': onClose = $emptyFn, title, children, actions, maxWidth = 'sm', fullWidth = false, } = props;
|
|
273
532
|
// Handle ESC key - store handler for cleanup
|
|
274
533
|
const keyDownHandler = (e) => {
|
|
275
534
|
if (e.key === 'Escape') {
|
|
@@ -293,26 +552,28 @@ function Dialog(props) {
|
|
|
293
552
|
}
|
|
294
553
|
return originalRemove.call(container);
|
|
295
554
|
};
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
555
|
+
$defines(container, {
|
|
556
|
+
open: {
|
|
557
|
+
get: () => open,
|
|
558
|
+
set: (isOpen) => {
|
|
559
|
+
if (isOpen === open) {
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
open = isOpen;
|
|
563
|
+
if (isOpen) {
|
|
564
|
+
// Opening: set display first, then add class with double RAF for animation
|
|
565
|
+
container.style.display = 'flex';
|
|
566
|
+
setTimeout(() => container.classList.add('kt-dialog-backdrop-open'), 50);
|
|
567
|
+
}
|
|
568
|
+
else {
|
|
569
|
+
container.classList.remove('kt-dialog-backdrop-open');
|
|
570
|
+
setTimeout(() => {
|
|
571
|
+
if (!open) {
|
|
572
|
+
container.style.display = 'none';
|
|
573
|
+
}
|
|
574
|
+
}, 225);
|
|
575
|
+
}
|
|
576
|
+
},
|
|
316
577
|
},
|
|
317
578
|
});
|
|
318
579
|
return container;
|
|
@@ -342,54 +603,69 @@ function FormLabel(props) {
|
|
|
342
603
|
return element;
|
|
343
604
|
}
|
|
344
605
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
606
|
+
// Cached native methods for performance optimization
|
|
607
|
+
const { get: $buttonDisabledGetter, set: $buttonDisabledSetter } = Object.getOwnPropertyDescriptor(HTMLButtonElement.prototype, 'disabled');
|
|
608
|
+
|
|
609
|
+
// Shared utilities and cached native methods for kt.js framework
|
|
610
|
+
// Re-export all utilities
|
|
611
|
+
Object.defineProperty(window, '@ktjs/shared', { value: '0.20.0' });
|
|
349
612
|
|
|
350
613
|
document.createElement('div');
|
|
351
614
|
|
|
615
|
+
class KTRef {
|
|
616
|
+
/**
|
|
617
|
+
* Indicates that this is a KTRef instance
|
|
618
|
+
*/
|
|
619
|
+
isKT = true;
|
|
620
|
+
_value;
|
|
621
|
+
_onChanges;
|
|
622
|
+
constructor(_value, _onChanges) {
|
|
623
|
+
this._value = _value;
|
|
624
|
+
this._onChanges = _onChanges;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* If new value and old value are both nodes, the old one will be replaced in the DOM
|
|
628
|
+
*/
|
|
629
|
+
get value() {
|
|
630
|
+
return this._value;
|
|
631
|
+
}
|
|
632
|
+
set value(newValue) {
|
|
633
|
+
if (newValue === this._value) {
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
// replace the old node with the new one in the DOM if both are nodes
|
|
637
|
+
if (this._value instanceof Node && newValue instanceof Node) {
|
|
638
|
+
if (newValue.contains(this._value)) {
|
|
639
|
+
this._value.remove();
|
|
640
|
+
}
|
|
641
|
+
this._value.replaceWith(newValue);
|
|
642
|
+
}
|
|
643
|
+
const oldValue = this._value;
|
|
644
|
+
this._value = newValue;
|
|
645
|
+
for (let i = 0; i < this._onChanges.length; i++) {
|
|
646
|
+
this._onChanges[i](newValue, oldValue);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
addOnChange(callback) {
|
|
650
|
+
this._onChanges.push(callback);
|
|
651
|
+
}
|
|
652
|
+
removeOnChange(callback) {
|
|
653
|
+
for (let i = this._onChanges.length - 1; i >= 0; i--) {
|
|
654
|
+
if (this._onChanges[i] === callback) {
|
|
655
|
+
this._onChanges.splice(i, 1);
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
352
662
|
/**
|
|
353
663
|
* Reference to the created HTML element.
|
|
354
664
|
* - can alse be used to store normal values, but it is not reactive.
|
|
355
665
|
* @param value mostly an HTMLElement
|
|
356
666
|
*/
|
|
357
667
|
function ref(value, onChange) {
|
|
358
|
-
|
|
359
|
-
let _onChanges = [];
|
|
360
|
-
return {
|
|
361
|
-
isKT: true,
|
|
362
|
-
get value() {
|
|
363
|
-
return _value;
|
|
364
|
-
},
|
|
365
|
-
set value(newValue) {
|
|
366
|
-
if (newValue === _value) {
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
// replace the old node with the new one in the DOM if both are nodes
|
|
370
|
-
if (_value instanceof Node && newValue instanceof Node) {
|
|
371
|
-
if (newValue.contains(_value)) {
|
|
372
|
-
_value.remove();
|
|
373
|
-
}
|
|
374
|
-
_value.replaceWith(newValue);
|
|
375
|
-
}
|
|
376
|
-
const oldValue = _value;
|
|
377
|
-
_value = newValue;
|
|
378
|
-
for (let i = 0; i < _onChanges.length; i++) {
|
|
379
|
-
_onChanges[i](newValue, oldValue);
|
|
380
|
-
}
|
|
381
|
-
},
|
|
382
|
-
addOnChange: (callback) => _onChanges.push(callback),
|
|
383
|
-
removeOnChange: (callback) => {
|
|
384
|
-
for (let i = _onChanges.length - 1; i >= 0; i--) {
|
|
385
|
-
if (_onChanges[i] === callback) {
|
|
386
|
-
_onChanges.splice(i, 1);
|
|
387
|
-
return true;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
return false;
|
|
391
|
-
},
|
|
392
|
-
};
|
|
668
|
+
return new KTRef(value, []);
|
|
393
669
|
}
|
|
394
670
|
/**
|
|
395
671
|
* A helper to create redrawable elements
|
|
@@ -407,13 +683,12 @@ function ref(value, onChange) {
|
|
|
407
683
|
*/
|
|
408
684
|
function createRedrawable(creator) {
|
|
409
685
|
const elRef = ref();
|
|
410
|
-
elRef.value = creator();
|
|
411
686
|
const redraw = () => {
|
|
412
687
|
elRef.value = creator(); // ref setter automatically calls replaceWith
|
|
413
|
-
elRef.
|
|
688
|
+
elRef.redraw = redraw;
|
|
414
689
|
return elRef.value;
|
|
415
690
|
};
|
|
416
|
-
|
|
691
|
+
redraw();
|
|
417
692
|
return elRef;
|
|
418
693
|
}
|
|
419
694
|
|
|
@@ -433,15 +708,17 @@ function LinearProgress(props) {
|
|
|
433
708
|
let progressValue = Math.min(Math.max(value, 0), 100);
|
|
434
709
|
const barRef = ref();
|
|
435
710
|
const container = (jsx("div", { class: classes, style: styleString, role: "progressbar", "aria-valuenow": progressValue, children: jsx("div", { ref: barRef, class: "mui-linear-progress-bar", style: variant === 'determinate' ? `width: ${progressValue}%` : '' }) }));
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
711
|
+
$defines(container, {
|
|
712
|
+
progress: {
|
|
713
|
+
get() {
|
|
714
|
+
return progressValue;
|
|
715
|
+
},
|
|
716
|
+
set(newValue) {
|
|
717
|
+
progressValue = Math.min(Math.max(newValue, 0), 100);
|
|
718
|
+
if (variant === 'determinate') {
|
|
719
|
+
barRef.value.style.width = `${progressValue}%`;
|
|
720
|
+
}
|
|
721
|
+
},
|
|
445
722
|
},
|
|
446
723
|
});
|
|
447
724
|
return container;
|
|
@@ -514,7 +791,7 @@ function TextField(props) {
|
|
|
514
791
|
const container = (jsxs("div", { class: 'mui-textfield-root ' + (props.class ? props.class : ''), style: parseStyle(props.style), children: [wrapperRef, helperTextEl] }));
|
|
515
792
|
// Initialize classes
|
|
516
793
|
setTimeout(() => updateContainerClass(), 0);
|
|
517
|
-
|
|
794
|
+
$defines(container, {
|
|
518
795
|
value: {
|
|
519
796
|
get() {
|
|
520
797
|
return inputEl.value;
|
|
@@ -530,7 +807,7 @@ function TextField(props) {
|
|
|
530
807
|
},
|
|
531
808
|
set(newLabel) {
|
|
532
809
|
label = newLabel;
|
|
533
|
-
wrapperRef.
|
|
810
|
+
wrapperRef.redraw(); // label takes too much and should be redrawn
|
|
534
811
|
updateContainerClass();
|
|
535
812
|
},
|
|
536
813
|
},
|
|
@@ -618,7 +895,7 @@ function Radio(props) {
|
|
|
618
895
|
// initialize icon state
|
|
619
896
|
toggleIcon(checked);
|
|
620
897
|
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 })] }));
|
|
621
|
-
|
|
898
|
+
$defines(container, {
|
|
622
899
|
value: {
|
|
623
900
|
get() {
|
|
624
901
|
return value;
|
|
@@ -665,7 +942,7 @@ function RadioGroup(props) {
|
|
|
665
942
|
return Radio(o);
|
|
666
943
|
});
|
|
667
944
|
const container = (jsx("div", { class: `mui-radio-group ${row ? 'mui-radio-group-row' : ''} ${props.class ?? ''}`, style: parseStyle(props.style), role: "radiogroup", children: radios }));
|
|
668
|
-
|
|
945
|
+
$defines(container, {
|
|
669
946
|
value: {
|
|
670
947
|
get() {
|
|
671
948
|
return value;
|
|
@@ -687,7 +964,8 @@ function Select(props) {
|
|
|
687
964
|
const onChange = generateHandler(props, 'kt:change');
|
|
688
965
|
let isOpen = false;
|
|
689
966
|
let isFocused = false;
|
|
690
|
-
const selectRef = ref
|
|
967
|
+
const selectRef = ref();
|
|
968
|
+
const selectLabelRef = ref();
|
|
691
969
|
// Toggle dropdown
|
|
692
970
|
const toggleMenu = () => {
|
|
693
971
|
if (disabled) {
|
|
@@ -700,12 +978,9 @@ function Select(props) {
|
|
|
700
978
|
const updateMenu = () => {
|
|
701
979
|
if (isOpen) {
|
|
702
980
|
menu.value.style.display = 'block';
|
|
703
|
-
// Trigger reflow to enable animation
|
|
704
|
-
menu.value.offsetHeight;
|
|
705
|
-
menu.value.classList.add('mui-select-menu-open');
|
|
981
|
+
void menu.value.offsetHeight; // & Trigger reflow to enable animation
|
|
706
982
|
}
|
|
707
983
|
else {
|
|
708
|
-
menu.value.classList.remove('mui-select-menu-open');
|
|
709
984
|
// Hide after animation completes
|
|
710
985
|
setTimeout(() => {
|
|
711
986
|
if (!isOpen) {
|
|
@@ -713,6 +988,7 @@ function Select(props) {
|
|
|
713
988
|
}
|
|
714
989
|
}, 200);
|
|
715
990
|
}
|
|
991
|
+
menu.value.classList.toggle('mui-select-menu-open', isOpen);
|
|
716
992
|
selectRef.value.classList.toggle('mui-select-open', isOpen);
|
|
717
993
|
};
|
|
718
994
|
// Handle option click
|
|
@@ -722,11 +998,8 @@ function Select(props) {
|
|
|
722
998
|
onChange(value);
|
|
723
999
|
updateMenu();
|
|
724
1000
|
updateLabelState();
|
|
725
|
-
valueDisplay.
|
|
726
|
-
setTimeout(() =>
|
|
727
|
-
// Trigger redraw of parent if needed
|
|
728
|
-
menu.value.redraw();
|
|
729
|
-
}, 200);
|
|
1001
|
+
valueDisplay.redraw();
|
|
1002
|
+
setTimeout(() => menu.redraw(), 200);
|
|
730
1003
|
};
|
|
731
1004
|
// Close menu when clicking outside
|
|
732
1005
|
const handleClickOutside = (e) => {
|
|
@@ -746,17 +1019,9 @@ function Select(props) {
|
|
|
746
1019
|
};
|
|
747
1020
|
// Update label focused state
|
|
748
1021
|
const updateLabelState = () => {
|
|
749
|
-
|
|
750
|
-
if (labelElement) {
|
|
751
|
-
if (isFocused || value) {
|
|
752
|
-
labelElement.classList.add('focused');
|
|
753
|
-
}
|
|
754
|
-
else {
|
|
755
|
-
labelElement.classList.remove('focused');
|
|
756
|
-
}
|
|
757
|
-
}
|
|
1022
|
+
selectLabelRef.value.classList?.toggle('focused', isFocused || !!value);
|
|
758
1023
|
};
|
|
759
|
-
const valueDisplay = createRedrawable
|
|
1024
|
+
const valueDisplay = createRedrawable(() => {
|
|
760
1025
|
const o = options.find((opt) => opt.value === value);
|
|
761
1026
|
let inner;
|
|
762
1027
|
if (o === undefined) {
|
|
@@ -767,11 +1032,33 @@ function Select(props) {
|
|
|
767
1032
|
}
|
|
768
1033
|
return jsx("div", { class: "mui-select-display", children: inner });
|
|
769
1034
|
});
|
|
770
|
-
const menu = createRedrawable
|
|
771
|
-
return (jsx("div", { class: "mui-select-menu", style:
|
|
1035
|
+
const menu = createRedrawable(() => {
|
|
1036
|
+
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 }))) }));
|
|
772
1037
|
});
|
|
773
1038
|
// Create container
|
|
774
|
-
const container = (jsxs("div", { ref: selectRef, class: `mui-select-wrapper mui-select-size-${size} ${props.class ?? ''} ${fullWidth ? 'mui-select-fullWidth' : ''} ${disabled ? 'mui-select-disabled' : ''}`, style: parseStyle(props.style), children: [
|
|
1039
|
+
const container = (jsxs("div", { ref: selectRef, class: `mui-select-wrapper mui-select-size-${size} ${props.class ?? ''} ${fullWidth ? 'mui-select-fullWidth' : ''} ${disabled ? 'mui-select-disabled' : ''}`, style: parseStyle(props.style), children: [jsx("label", { "k-if": label, ref: selectLabelRef, class: `mui-select-label ${value || isFocused ? 'focused' : ''}`, children: label }), jsxs("div", { class: "mui-select-control mui-select-outlined", "on:click": toggleMenu, "on:focus": handleFocus, "on:blur": handleBlur, tabIndex: disabled ? -1 : 0, children: [valueDisplay, jsx("input", { type: "hidden", value: value }), jsx("fieldset", { class: "mui-select-fieldset", children: jsx("legend", { children: jsx("span", { children: label }) }) }), 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] }));
|
|
1040
|
+
$defines(container, {
|
|
1041
|
+
value: {
|
|
1042
|
+
get: () => value,
|
|
1043
|
+
set: (newValue) => {
|
|
1044
|
+
value = newValue;
|
|
1045
|
+
updateLabelState();
|
|
1046
|
+
valueDisplay.redraw();
|
|
1047
|
+
menu.redraw();
|
|
1048
|
+
},
|
|
1049
|
+
},
|
|
1050
|
+
disabled: {
|
|
1051
|
+
get: () => disabled,
|
|
1052
|
+
set: (newDisabled) => {
|
|
1053
|
+
disabled = newDisabled;
|
|
1054
|
+
if (disabled) {
|
|
1055
|
+
isOpen = false;
|
|
1056
|
+
updateMenu();
|
|
1057
|
+
}
|
|
1058
|
+
container.classList.toggle('mui-select-disabled', disabled);
|
|
1059
|
+
},
|
|
1060
|
+
},
|
|
1061
|
+
});
|
|
775
1062
|
// Add global click listener
|
|
776
1063
|
setTimeout(() => {
|
|
777
1064
|
document.removeEventListener('click', handleClickOutside);
|
|
@@ -869,4 +1156,4 @@ function SelectAllIcon(props) {
|
|
|
869
1156
|
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" }) }));
|
|
870
1157
|
}
|
|
871
1158
|
|
|
872
|
-
export { Alert, Button, Checkbox, CheckboxGroup, ColorLensIcon, CompressIcon, ContentCopyIcon, ContentPasteIcon, DeleteIcon, Dialog, DownloadIcon, ExpandMoreIcon, FileOpenIcon
|
|
1159
|
+
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 };
|