@ktjs/mui 0.18.8 → 0.19.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.mjs CHANGED
@@ -1,5 +1,266 @@
1
- import { jsxs, jsx } from 'kt.js/jsx-runtime';
2
- import { ref as ref$1, createRedrawable as createRedrawable$1 } from 'kt.js';
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';
4
+
5
+ // Error handling utilities
6
+ const $throw = (message) => {
7
+ throw new Error('@ktjs/shared: ' + message);
8
+ };
9
+
10
+ // DOM manipulation utilities
11
+ /**
12
+ * & Remove `bind` because it is shockingly slower than wrapper
13
+ * & `window.document` is safe because it is not configurable and its setter is undefined
14
+ */
15
+ const $appendChild = HTMLElement.prototype.appendChild;
16
+ const originAppend = HTMLElement.prototype.append;
17
+ const $append = // for ie 9/10/11
18
+ typeof originAppend === 'function'
19
+ ? originAppend
20
+ : function (...nodes) {
21
+ if (nodes.length < 50) {
22
+ for (let i = 0; i < nodes.length; i++) {
23
+ const node = nodes[i];
24
+ if (typeof node === 'string') {
25
+ $appendChild.call(this, document.createTextNode(node));
26
+ }
27
+ else {
28
+ $appendChild.call(this, node);
29
+ }
30
+ }
31
+ }
32
+ else {
33
+ const fragment = document.createDocumentFragment();
34
+ for (let i = 0; i < nodes.length; i++) {
35
+ const node = nodes[i];
36
+ if (typeof node === 'string') {
37
+ $appendChild.call(fragment, document.createTextNode(node));
38
+ }
39
+ else {
40
+ $appendChild.call(fragment, node);
41
+ }
42
+ }
43
+ $appendChild.call(this, fragment);
44
+ }
45
+ };
46
+
47
+ // Shared utilities and cached native methods for kt.js framework
48
+ // Re-export all utilities
49
+ Object.defineProperty(window, '@ktjs/shared', { value: '0.19.0' });
50
+
51
+ const booleanHandler = (element, key, value) => {
52
+ if (key in element) {
53
+ element[key] = !!value;
54
+ }
55
+ else {
56
+ element.setAttribute(key, value);
57
+ }
58
+ };
59
+ const valueHandler = (element, key, value) => {
60
+ if (key in element) {
61
+ element[key] = value;
62
+ }
63
+ else {
64
+ element.setAttribute(key, value);
65
+ }
66
+ };
67
+ // Attribute handlers map for optimized lookup
68
+ const handlers = {
69
+ checked: booleanHandler,
70
+ selected: booleanHandler,
71
+ value: valueHandler,
72
+ valueAsDate: valueHandler,
73
+ valueAsNumber: valueHandler,
74
+ defaultValue: valueHandler,
75
+ defaultChecked: booleanHandler,
76
+ defaultSelected: booleanHandler,
77
+ disabled: booleanHandler,
78
+ readOnly: booleanHandler,
79
+ multiple: booleanHandler,
80
+ required: booleanHandler,
81
+ autofocus: booleanHandler,
82
+ open: booleanHandler,
83
+ controls: booleanHandler,
84
+ autoplay: booleanHandler,
85
+ loop: booleanHandler,
86
+ muted: booleanHandler,
87
+ defer: booleanHandler,
88
+ async: booleanHandler,
89
+ hidden: (element, _key, value) => (element.hidden = !!value),
90
+ };
91
+
92
+ const defaultHandler = (element, key, value) => element.setAttribute(key, value);
93
+ function attrIsObject(element, attr) {
94
+ const classValue = attr.class || attr.className;
95
+ if (classValue !== undefined) {
96
+ element.setAttribute('class', classValue);
97
+ }
98
+ const style = attr.style;
99
+ if (style) {
100
+ if (typeof style === 'string') {
101
+ element.setAttribute('style', style);
102
+ }
103
+ else if (typeof style === 'object') {
104
+ for (const key in style) {
105
+ element.style[key] = style[key];
106
+ }
107
+ }
108
+ }
109
+ for (const key in attr) {
110
+ if (key === 'class' ||
111
+ key === 'className' ||
112
+ key === 'style' ||
113
+ key === 'children' ||
114
+ key === 'k-if' ||
115
+ key === 'ref') {
116
+ continue;
117
+ }
118
+ const o = attr[key];
119
+ // normal event handler
120
+ if (key.startsWith('on:')) {
121
+ element.addEventListener(key.slice(3), o); // chop off the `on:`
122
+ }
123
+ // normal attributes
124
+ else {
125
+ (handlers[key] || defaultHandler)(element, key, o);
126
+ }
127
+ }
128
+ }
129
+ function applyAttr(element, attr) {
130
+ if (!attr) {
131
+ return;
132
+ }
133
+ if (typeof attr === 'object' && attr !== null) {
134
+ attrIsObject(element, attr);
135
+ }
136
+ else {
137
+ throw new Error('kt.js: attr must be an object.');
138
+ }
139
+ }
140
+
141
+ function apdSingle(element, c) {
142
+ // & JSX should ignore false, undefined, and null
143
+ if (c === false || c === undefined || c === null) {
144
+ return;
145
+ }
146
+ if (typeof c === 'object' && c !== null && 'isKT' in c) {
147
+ $append.call(element, c.value);
148
+ }
149
+ else {
150
+ $append.call(element, c);
151
+ // Handle KTFor anchor
152
+ const list = c.__kt_for_list__;
153
+ if ($isArray(list)) {
154
+ apd(element, list);
155
+ }
156
+ }
157
+ }
158
+ function apd(element, c) {
159
+ if ($isThenable(c)) {
160
+ c.then((r) => apd(element, r));
161
+ }
162
+ else if ($isArray(c)) {
163
+ for (let i = 0; i < c.length; i++) {
164
+ // & might be thenable here too
165
+ const ci = c[i];
166
+ if ($isThenable(ci)) {
167
+ const comment = document.createComment('ktjs-promise-placeholder');
168
+ $append.call(element, comment);
169
+ ci.then((awaited) => comment.replaceWith(awaited));
170
+ }
171
+ else {
172
+ apdSingle(element, ci);
173
+ }
174
+ }
175
+ }
176
+ else {
177
+ // & here is thened, so must be a simple elementj
178
+ apdSingle(element, c);
179
+ }
180
+ }
181
+ function applyContent(element, content) {
182
+ if ($isArray(content)) {
183
+ for (let i = 0; i < content.length; i++) {
184
+ apd(element, content[i]);
185
+ }
186
+ }
187
+ else {
188
+ apd(element, content);
189
+ }
190
+ }
191
+
192
+ const svgTempWrapper = document.createElement('div');
193
+ /**
194
+ * Create an enhanced HTMLElement.
195
+ * - Only supports HTMLElements, **NOT** SVGElements or other Elements.
196
+ * @param tag tag of an `HTMLElement`
197
+ * @param attr attribute object or className
198
+ * @param content a string or an array of HTMLEnhancedElement as child nodes
199
+ *
200
+ * ## About
201
+ * @package @ktjs/core
202
+ * @author Kasukabe Tsumugi <futami16237@gmail.com>
203
+ * @version 0.19.0 (Last Update: 2026.01.31 22:50:55.987)
204
+ * @license MIT
205
+ * @link https://github.com/baendlorel/kt.js
206
+ * @link https://baendlorel.github.io/ Welcome to my site!
207
+ * @description Core functionality for kt.js - DOM manipulation utilities with JSX/TSX support
208
+ * @copyright Copyright (c) 2026 Kasukabe Tsumugi. All rights reserved.
209
+ */
210
+ const h = (tag, attr, content) => {
211
+ if (typeof tag !== 'string') {
212
+ $throw('tagName must be a string.');
213
+ }
214
+ // * start creating the element
215
+ const element = document.createElement(tag);
216
+ // * Handle content
217
+ applyAttr(element, attr);
218
+ applyContent(element, content);
219
+ if (tag === 'svg') {
220
+ svgTempWrapper.innerHTML = element.outerHTML;
221
+ return svgTempWrapper.firstChild;
222
+ }
223
+ return element;
224
+ };
225
+
226
+ const dummyRef = { value: null };
227
+ /**
228
+ * @param tag html tag or function component
229
+ * @param props properties/attributes
230
+ */
231
+ function jsx(tag, props = {}) {
232
+ const ref = props.ref?.isKT ? props.ref : dummyRef;
233
+ let el;
234
+ const redraw = (newProps) => {
235
+ props = newProps ? { ...props, ...newProps } : props;
236
+ el = jsx(tag, props);
237
+ if (ref !== dummyRef) {
238
+ ref.value = el; // & ref setter automatically replaces old element in DOM
239
+ }
240
+ return el;
241
+ };
242
+ if ('k-if' in props && !props['k-if']) {
243
+ el = document.createComment('k-if');
244
+ ref.value = el; // & ref setter automatically replaces old element in DOM
245
+ el.redraw = redraw;
246
+ return el;
247
+ }
248
+ // Handle function components
249
+ if (typeof tag === 'function') {
250
+ el = tag(props);
251
+ }
252
+ else {
253
+ el = h(tag, props, props.children);
254
+ }
255
+ el.redraw ??= redraw;
256
+ ref.value = el;
257
+ return el;
258
+ }
259
+ /**
260
+ * JSX runtime for React 17+ automatic runtime
261
+ * This is called when using jsx: "react-jsx" or "react-jsxdev"
262
+ */
263
+ const jsxs = jsx;
3
264
 
4
265
  /**s
5
266
  * Alert component - mimics MUI Alert appearance and behavior
@@ -44,18 +305,14 @@ function Alert(props) {
44
305
  return alert;
45
306
  }
46
307
 
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
- };
308
+ // Cached native methods for performance optimization
58
309
 
310
+ // String manipulation utilities
311
+ /**
312
+ * Default empty function
313
+ */
314
+ const $emptyFn = (() => true);
315
+ // Style parsing utilities
59
316
  const parseStyle = (style) => {
60
317
  if (typeof style === 'string') {
61
318
  return style;
@@ -71,12 +328,26 @@ const parseStyle = (style) => {
71
328
  }
72
329
  return '';
73
330
  };
331
+ const generateHandler = (props, key) => {
332
+ const handler = props[key];
333
+ if (typeof handler === 'function') {
334
+ return handler;
335
+ }
336
+ else if (handler && typeof handler === 'object' && handler.isKT) {
337
+ return (value) => (handler.value = value);
338
+ }
339
+ return $emptyFn;
340
+ };
341
+
342
+ // Shared utilities and cached native methods for kt.js framework
343
+ // Re-export all utilities
344
+ Object.defineProperty(window, '@ktjs/shared', { value: '0.19.0' });
74
345
 
75
346
  /**
76
347
  * Button component - mimics MUI Button appearance and behavior
77
348
  */
78
349
  function Button(props) {
79
- const { children, variant = 'text', color = 'primary', size = 'medium', disabled = false, fullWidth = false, iconOnly = false, startIcon, endIcon, type = 'button', 'on:click': onClick = emptyFn, } = props;
350
+ const { children, variant = 'text', color = 'primary', size = 'medium', disabled = false, fullWidth = false, iconOnly = false, startIcon, endIcon, type = 'button', 'on:click': onClick = $emptyFn, } = props;
80
351
  const classes = [
81
352
  'mui-button',
82
353
  `mui-button-${variant}`,
@@ -269,7 +540,7 @@ function CheckboxGroup(props) {
269
540
  * Only handles open/close state, title and content are passed as props
270
541
  */
271
542
  function Dialog(props) {
272
- let { open = false, 'kt:close': onClose = emptyFn, title, children, actions, maxWidth = 'sm', fullWidth = false, } = props;
543
+ let { open = false, 'kt:close': onClose = $emptyFn, title, children, actions, maxWidth = 'sm', fullWidth = false, } = props;
273
544
  // Handle ESC key - store handler for cleanup
274
545
  const keyDownHandler = (e) => {
275
546
  if (e.key === 'Escape') {
@@ -342,54 +613,68 @@ function FormLabel(props) {
342
613
  return element;
343
614
  }
344
615
 
345
- const emptyPromiseHandler = () => ({});
346
- if (typeof Promise === 'undefined') {
347
- window.Promise = { resolve: emptyPromiseHandler, reject: emptyPromiseHandler };
348
- }
616
+ // Cached native methods for performance optimization
617
+
618
+ // Shared utilities and cached native methods for kt.js framework
619
+ // Re-export all utilities
620
+ Object.defineProperty(window, '@ktjs/shared', { value: '0.19.0' });
349
621
 
350
622
  document.createElement('div');
351
623
 
624
+ class KTRef {
625
+ /**
626
+ * Indicates that this is a KTRef instance
627
+ */
628
+ isKT = true;
629
+ _value;
630
+ _onChanges;
631
+ constructor(_value, _onChanges) {
632
+ this._value = _value;
633
+ this._onChanges = _onChanges;
634
+ }
635
+ /**
636
+ * If new value and old value are both nodes, the old one will be replaced in the DOM
637
+ */
638
+ get value() {
639
+ return this._value;
640
+ }
641
+ set value(newValue) {
642
+ if (newValue === this._value) {
643
+ return;
644
+ }
645
+ // replace the old node with the new one in the DOM if both are nodes
646
+ if (this._value instanceof Node && newValue instanceof Node) {
647
+ if (newValue.contains(this._value)) {
648
+ this._value.remove();
649
+ }
650
+ this._value.replaceWith(newValue);
651
+ }
652
+ const oldValue = this._value;
653
+ this._value = newValue;
654
+ for (let i = 0; i < this._onChanges.length; i++) {
655
+ this._onChanges[i](newValue, oldValue);
656
+ }
657
+ }
658
+ addOnChange(callback) {
659
+ this._onChanges.push(callback);
660
+ }
661
+ removeOnChange(callback) {
662
+ for (let i = this._onChanges.length - 1; i >= 0; i--) {
663
+ if (this._onChanges[i] === callback) {
664
+ this._onChanges.splice(i, 1);
665
+ return true;
666
+ }
667
+ }
668
+ return false;
669
+ }
670
+ }
352
671
  /**
353
672
  * Reference to the created HTML element.
354
673
  * - can alse be used to store normal values, but it is not reactive.
355
674
  * @param value mostly an HTMLElement
356
675
  */
357
676
  function ref(value, onChange) {
358
- let _value = value;
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
- };
677
+ return new KTRef(value, []);
393
678
  }
394
679
  /**
395
680
  * A helper to create redrawable elements
@@ -629,7 +914,7 @@ function Radio(props) {
629
914
  return checked;
630
915
  },
631
916
  set(newChecked) {
632
- checked = newChecked === value;
917
+ checked = newChecked;
633
918
  input.checked = checked;
634
919
  toggleIcon(checked);
635
920
  },
@@ -687,7 +972,7 @@ function Select(props) {
687
972
  const onChange = generateHandler(props, 'kt:change');
688
973
  let isOpen = false;
689
974
  let isFocused = false;
690
- const selectRef = ref$1();
975
+ const selectRef = ref();
691
976
  // Toggle dropdown
692
977
  const toggleMenu = () => {
693
978
  if (disabled) {
@@ -701,7 +986,7 @@ function Select(props) {
701
986
  if (isOpen) {
702
987
  menu.value.style.display = 'block';
703
988
  // Trigger reflow to enable animation
704
- menu.value.offsetHeight;
989
+ void menu.value.offsetHeight;
705
990
  menu.value.classList.add('mui-select-menu-open');
706
991
  }
707
992
  else {
@@ -756,7 +1041,7 @@ function Select(props) {
756
1041
  }
757
1042
  }
758
1043
  };
759
- const valueDisplay = createRedrawable$1(() => {
1044
+ const valueDisplay = createRedrawable(() => {
760
1045
  const o = options.find((opt) => opt.value === value);
761
1046
  let inner;
762
1047
  if (o === undefined) {
@@ -767,7 +1052,7 @@ function Select(props) {
767
1052
  }
768
1053
  return jsx("div", { class: "mui-select-display", children: inner });
769
1054
  });
770
- const menu = createRedrawable$1(() => {
1055
+ const menu = createRedrawable(() => {
771
1056
  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
1057
  });
773
1058
  // Create container
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ktjs/mui",
3
- "version": "0.18.8",
3
+ "version": "0.19.0",
4
4
  "description": "Material-UI inspired components for kt.js - pre-styled UI components",
5
5
  "type": "module",
6
6
  "module": "./dist/index.mjs",
@@ -35,7 +35,8 @@
35
35
  "directory": "packages/mui"
36
36
  },
37
37
  "dependencies": {
38
- "@ktjs/core": "0.18.10"
38
+ "@ktjs/shared": "0.19.0",
39
+ "@ktjs/core": "0.19.0"
39
40
  },
40
41
  "scripts": {
41
42
  "build": "rollup -c rollup.config.mjs",