@ktjs/mui 0.17.9 → 0.18.1
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 +31 -16
- package/dist/index.iife.js +262 -76
- package/dist/index.mjs +265 -79
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { KTHTMLElement, KTAttribute } from 'kt.js';
|
|
2
|
-
import { KTHTMLElement as KTHTMLElement$1 } from '@ktjs/core';
|
|
2
|
+
import { KTHTMLElement as KTHTMLElement$1, KTRef } from '@ktjs/core';
|
|
3
3
|
|
|
4
4
|
interface AlertProps {
|
|
5
5
|
class?: string;
|
|
@@ -9,7 +9,7 @@ interface AlertProps {
|
|
|
9
9
|
severity?: 'error' | 'warning' | 'info' | 'success';
|
|
10
10
|
variant?: 'standard' | 'filled' | 'outlined';
|
|
11
11
|
icon?: HTMLElement | KTHTMLElement | false;
|
|
12
|
-
'
|
|
12
|
+
'kt:close'?: () => void;
|
|
13
13
|
}
|
|
14
14
|
/**s
|
|
15
15
|
* Alert component - mimics MUI Alert appearance and behavior
|
|
@@ -41,7 +41,7 @@ interface CheckboxProps {
|
|
|
41
41
|
label?: string | KTHTMLElement | HTMLElement;
|
|
42
42
|
checked?: boolean;
|
|
43
43
|
size?: 'small' | 'medium';
|
|
44
|
-
'
|
|
44
|
+
'kt:change'?: (checked: boolean, value: string) => void;
|
|
45
45
|
disabled?: boolean;
|
|
46
46
|
color?: 'primary' | 'secondary' | 'default' | 'success' | 'error' | 'warning';
|
|
47
47
|
indeterminate?: boolean;
|
|
@@ -49,9 +49,13 @@ interface CheckboxProps {
|
|
|
49
49
|
type KTMuiCheckbox = KTHTMLElement & {
|
|
50
50
|
checked: boolean;
|
|
51
51
|
value: string;
|
|
52
|
+
disabled: boolean;
|
|
52
53
|
};
|
|
53
54
|
type KTMuiCheckboxGroup = KTHTMLElement & {
|
|
54
55
|
value: string[];
|
|
56
|
+
disabled: boolean[];
|
|
57
|
+
disableAll: () => void;
|
|
58
|
+
enableAll: () => void;
|
|
55
59
|
};
|
|
56
60
|
/**
|
|
57
61
|
* Checkbox component - mimics MUI Checkbox appearance and behavior
|
|
@@ -63,7 +67,7 @@ interface CheckboxGroupProps {
|
|
|
63
67
|
value?: string[];
|
|
64
68
|
size?: 'small' | 'medium';
|
|
65
69
|
options: CheckboxProps[];
|
|
66
|
-
'
|
|
70
|
+
'kt:change'?: (values: string[]) => void;
|
|
67
71
|
row?: boolean;
|
|
68
72
|
}
|
|
69
73
|
/**
|
|
@@ -73,7 +77,7 @@ declare function CheckboxGroup(props: CheckboxGroupProps): KTMuiCheckboxGroup;
|
|
|
73
77
|
|
|
74
78
|
interface DialogProps {
|
|
75
79
|
open?: boolean;
|
|
76
|
-
'
|
|
80
|
+
'kt:close'?: () => void;
|
|
77
81
|
title?: string;
|
|
78
82
|
children?: HTMLElement | HTMLElement[] | string;
|
|
79
83
|
actions?: HTMLElement | HTMLElement[];
|
|
@@ -123,6 +127,8 @@ type KTMuiLinearProgress = KTHTMLElement$1 & {
|
|
|
123
127
|
*/
|
|
124
128
|
declare function LinearProgress(props: LinearProgressProps): KTMuiLinearProgress;
|
|
125
129
|
|
|
130
|
+
type ChangeHandler<T = string> = (value: T) => void;
|
|
131
|
+
|
|
126
132
|
interface TextFieldProps {
|
|
127
133
|
class?: string;
|
|
128
134
|
style?: string;
|
|
@@ -138,15 +144,24 @@ interface TextFieldProps {
|
|
|
138
144
|
fullWidth?: boolean;
|
|
139
145
|
multiline?: boolean;
|
|
140
146
|
rows?: number;
|
|
141
|
-
maxRows?: number;
|
|
142
147
|
size?: 'small' | 'medium';
|
|
143
|
-
'
|
|
144
|
-
'
|
|
145
|
-
'
|
|
146
|
-
'
|
|
148
|
+
'kt:input'?: ChangeHandler | KTRef<string>;
|
|
149
|
+
'kt-trim:input'?: ChangeHandler | KTRef<string>;
|
|
150
|
+
'kt:change'?: ChangeHandler | KTRef<string>;
|
|
151
|
+
'kt-trim:change'?: ChangeHandler | KTRef<string>;
|
|
152
|
+
'kt:blur'?: ChangeHandler | KTRef<string>;
|
|
153
|
+
'kt:focus'?: ChangeHandler | KTRef<string>;
|
|
147
154
|
}
|
|
148
|
-
type KTMuiTextField = KTHTMLElement & {
|
|
155
|
+
type KTMuiTextField = KTHTMLElement$1 & {
|
|
149
156
|
value: string;
|
|
157
|
+
label: string;
|
|
158
|
+
placeholder: string;
|
|
159
|
+
type: string;
|
|
160
|
+
disabled: boolean;
|
|
161
|
+
readonly: boolean;
|
|
162
|
+
required: boolean;
|
|
163
|
+
error: boolean;
|
|
164
|
+
helperText: string;
|
|
150
165
|
};
|
|
151
166
|
/**
|
|
152
167
|
* TextField component - mimics MUI TextField appearance and behavior
|
|
@@ -158,7 +173,7 @@ interface RadioProps {
|
|
|
158
173
|
text: string | KTHTMLElement | HTMLElement;
|
|
159
174
|
checked?: boolean;
|
|
160
175
|
size?: 'small' | 'medium';
|
|
161
|
-
'
|
|
176
|
+
'kt:change'?: (checked: boolean, value: string) => void;
|
|
162
177
|
disabled?: boolean;
|
|
163
178
|
color?: 'primary' | 'secondary' | 'default';
|
|
164
179
|
}
|
|
@@ -176,8 +191,8 @@ interface RadioGroupProps {
|
|
|
176
191
|
name?: string;
|
|
177
192
|
size?: 'small' | 'medium';
|
|
178
193
|
options: RadioProps[];
|
|
179
|
-
'
|
|
180
|
-
'
|
|
194
|
+
'kt:change'?: (value: string) => void;
|
|
195
|
+
'kt:click'?: (checked: boolean) => void;
|
|
181
196
|
row?: boolean;
|
|
182
197
|
}
|
|
183
198
|
/**
|
|
@@ -197,7 +212,7 @@ interface SelectProps {
|
|
|
197
212
|
options: SelectOption[];
|
|
198
213
|
label?: string;
|
|
199
214
|
placeholder?: string;
|
|
200
|
-
'
|
|
215
|
+
'kt:change'?: (value: string) => void;
|
|
201
216
|
fullWidth?: boolean;
|
|
202
217
|
disabled?: boolean;
|
|
203
218
|
}
|
|
@@ -251,4 +266,4 @@ declare function ContentCopyIcon(props: KTAttribute): JSX.Element;
|
|
|
251
266
|
declare function SelectAllIcon(props: KTAttribute): JSX.Element;
|
|
252
267
|
|
|
253
268
|
export { Alert, Button, Checkbox, CheckboxGroup, ColorLensIcon, CompressIcon, ContentCopyIcon, ContentPasteIcon, DeleteIcon, Dialog, DownloadIcon, ExpandMoreIcon, FileOpenIcon as FileOpen, FileOpenIcon, FolderOpenIcon, FormLabel, HomeIcon, LinearProgress, MenuIcon, NewReleasesIcon, PlayArrowIcon, QueuePlayNextIcon, Radio, RadioGroup, SaveIcon, Select, SelectAllIcon, SettingsIcon, StopIcon, SubtitlesIcon, TextField, UploadFileIcon, VideoFileIcon, WallpaperIcon };
|
|
254
|
-
export type { KTMuiDialog, KTMuiLinearProgress };
|
|
269
|
+
export type { KTMuiDialog, KTMuiLinearProgress, KTMuiTextField };
|
package/dist/index.iife.js
CHANGED
|
@@ -5,7 +5,7 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
|
|
|
5
5
|
* Alert component - mimics MUI Alert appearance and behavior
|
|
6
6
|
*/
|
|
7
7
|
function Alert(props) {
|
|
8
|
-
const { children, severity = 'info', variant = 'standard', icon, '
|
|
8
|
+
const { children, severity = 'info', variant = 'standard', icon, 'kt:close': onClose, sx } = props;
|
|
9
9
|
const classes = `mui-alert mui-alert-${severity} mui-alert-${variant} ${props.class ? props.class : ''}`;
|
|
10
10
|
// Convert sx object to style string
|
|
11
11
|
let styleString = props.style || '';
|
|
@@ -44,12 +44,23 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
|
|
|
44
44
|
return alert;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
const emptyFn$
|
|
47
|
+
const emptyFn$3 = () => { };
|
|
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$3;
|
|
57
|
+
};
|
|
58
|
+
|
|
48
59
|
/**
|
|
49
60
|
* Button component - mimics MUI Button appearance and behavior
|
|
50
61
|
*/
|
|
51
62
|
function Button(props) {
|
|
52
|
-
const { children, variant = 'text', color = 'primary', size = 'medium', disabled = false, fullWidth = false, iconOnly = false, startIcon, endIcon, type = 'button', 'on:click': onClick = emptyFn$
|
|
63
|
+
const { children, variant = 'text', color = 'primary', size = 'medium', disabled = false, fullWidth = false, iconOnly = false, startIcon, endIcon, type = 'button', 'on:click': onClick = emptyFn$3, } = props;
|
|
53
64
|
const classes = [
|
|
54
65
|
'mui-button',
|
|
55
66
|
`mui-button-${variant}`,
|
|
@@ -91,7 +102,7 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
|
|
|
91
102
|
return (jsxRuntime.jsxs("button", { class: classes, style: props.style ? props.style : '', type: type, disabled: disabled, "on:click": handleClick, children: [startIcon && jsxRuntime.jsx("span", { class: "mui-button-start-icon", children: startIcon }), jsxRuntime.jsx("span", { class: "mui-button-label", children: children }), endIcon && jsxRuntime.jsx("span", { class: "mui-button-end-icon", children: endIcon }), jsxRuntime.jsx("span", { class: "mui-button-ripple" })] }));
|
|
92
103
|
}
|
|
93
104
|
|
|
94
|
-
const emptyFn$
|
|
105
|
+
const emptyFn$2 = () => { };
|
|
95
106
|
/**
|
|
96
107
|
* Checkbox component - mimics MUI Checkbox appearance and behavior
|
|
97
108
|
*/
|
|
@@ -113,13 +124,13 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
|
|
|
113
124
|
if (disabled) {
|
|
114
125
|
return;
|
|
115
126
|
}
|
|
116
|
-
checked =
|
|
127
|
+
checked = inputEl.checked;
|
|
117
128
|
indeterminate = false;
|
|
118
129
|
toggleIcon(checked, indeterminate);
|
|
119
130
|
onChange(checked, value);
|
|
120
131
|
};
|
|
121
|
-
let { checked = false, value = '', label = '', size = 'medium', '
|
|
122
|
-
const
|
|
132
|
+
let { checked = false, value = '', label = '', size = 'medium', 'kt:change': onChange = emptyFn$2, disabled = false, color = 'primary', indeterminate = false, } = props;
|
|
133
|
+
const inputEl = (jsxRuntime.jsx("input", { type: "checkbox", class: "mui-checkbox-input", checked: checked, value: value, disabled: disabled, "on:change": handleChange }));
|
|
123
134
|
// Unchecked icon
|
|
124
135
|
const uncheckedIcon = (jsxRuntime.jsx("span", { class: "mui-checkbox-icon-unchecked", children: jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", children: jsxRuntime.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" }) }) }));
|
|
125
136
|
// Checked icon
|
|
@@ -128,26 +139,47 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
|
|
|
128
139
|
const indeterminateIcon = (jsxRuntime.jsx("span", { class: "mui-checkbox-icon-indeterminate", children: jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", children: jsxRuntime.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" }) }) }));
|
|
129
140
|
// Initialize icon state
|
|
130
141
|
toggleIcon(checked, indeterminate);
|
|
131
|
-
const container = (jsxRuntime.jsxs("label", { class: `mui-checkbox-wrapper mui-checkbox-size-${size} ${disabled ? 'mui-checkbox-disabled' : ''} mui-checkbox-color-${color}`, children: [
|
|
132
|
-
Object.
|
|
133
|
-
|
|
134
|
-
|
|
142
|
+
const container = (jsxRuntime.jsxs("label", { class: `mui-checkbox-wrapper mui-checkbox-size-${size} ${disabled ? 'mui-checkbox-disabled' : ''} mui-checkbox-color-${color}`, children: [inputEl, jsxRuntime.jsxs("span", { class: "mui-checkbox-icon", children: [uncheckedIcon, checkedIcon, indeterminateIcon] }), jsxRuntime.jsx("span", { "k-if": label, class: "mui-checkbox-label", children: label })] }));
|
|
143
|
+
Object.defineProperties(container, {
|
|
144
|
+
checked: {
|
|
145
|
+
get() {
|
|
146
|
+
return checked;
|
|
147
|
+
},
|
|
148
|
+
set(newChecked) {
|
|
149
|
+
checked = newChecked;
|
|
150
|
+
indeterminate = false;
|
|
151
|
+
inputEl.checked = checked;
|
|
152
|
+
toggleIcon(checked, indeterminate);
|
|
153
|
+
},
|
|
135
154
|
},
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
155
|
+
value: {
|
|
156
|
+
get() {
|
|
157
|
+
return value;
|
|
158
|
+
},
|
|
159
|
+
set(newValue) {
|
|
160
|
+
value = newValue;
|
|
161
|
+
inputEl.value = value;
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
disabled: {
|
|
165
|
+
get() {
|
|
166
|
+
return disabled;
|
|
167
|
+
},
|
|
168
|
+
set(newDisabled) {
|
|
169
|
+
disabled = Boolean(newDisabled);
|
|
170
|
+
inputEl.disabled = disabled;
|
|
171
|
+
container.classList.toggle('mui-checkbox-disabled', disabled);
|
|
172
|
+
},
|
|
141
173
|
},
|
|
142
174
|
});
|
|
143
|
-
container.value = value;
|
|
144
175
|
return container;
|
|
145
176
|
}
|
|
146
177
|
/**
|
|
147
178
|
* CheckboxGroup component - groups multiple checkboxes together
|
|
148
179
|
*/
|
|
149
180
|
function CheckboxGroup(props) {
|
|
150
|
-
let { value = [], size = 'medium',
|
|
181
|
+
let { value = [], size = 'medium', row = false } = props;
|
|
182
|
+
const onChange = generateHandler(props, 'kt:change');
|
|
151
183
|
let selectedValues = new Set(value);
|
|
152
184
|
const changeHandler = (checked, checkboxValue) => {
|
|
153
185
|
if (checked) {
|
|
@@ -161,29 +193,56 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
|
|
|
161
193
|
const checkboxes = props.options.map((o) => {
|
|
162
194
|
o.size = size;
|
|
163
195
|
o.checked = selectedValues.has(o.value);
|
|
164
|
-
const originalChange = o['
|
|
196
|
+
const originalChange = o['kt:change'];
|
|
165
197
|
if (originalChange) {
|
|
166
|
-
o['
|
|
198
|
+
o['kt:change'] = (checked, value) => {
|
|
167
199
|
originalChange(checked, value);
|
|
168
200
|
changeHandler(checked, value);
|
|
169
201
|
};
|
|
170
202
|
}
|
|
171
203
|
else {
|
|
172
|
-
o['
|
|
204
|
+
o['kt:change'] = changeHandler;
|
|
173
205
|
}
|
|
174
206
|
return Checkbox(o);
|
|
175
207
|
});
|
|
176
208
|
const container = (jsxRuntime.jsx("div", { class: `mui-checkbox-group ${row ? 'mui-checkbox-group-row' : ''} ${props.class ? props.class : ''}`, style: props.style ? props.style : '', role: "group", children: checkboxes }));
|
|
177
|
-
Object.
|
|
178
|
-
|
|
179
|
-
|
|
209
|
+
Object.defineProperties(container, {
|
|
210
|
+
value: {
|
|
211
|
+
get() {
|
|
212
|
+
return Array.from(selectedValues);
|
|
213
|
+
},
|
|
214
|
+
set(newValues) {
|
|
215
|
+
selectedValues = new Set(newValues);
|
|
216
|
+
for (let i = 0; i < checkboxes.length; i++) {
|
|
217
|
+
const checkbox = checkboxes[i];
|
|
218
|
+
checkbox.checked = selectedValues.has(checkbox.value);
|
|
219
|
+
}
|
|
220
|
+
},
|
|
180
221
|
},
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
222
|
+
disabled: {
|
|
223
|
+
get() {
|
|
224
|
+
return checkboxes.map((cb) => cb.disabled);
|
|
225
|
+
},
|
|
226
|
+
set(newDisabled) {
|
|
227
|
+
for (let i = 0; i < checkboxes.length; i++) {
|
|
228
|
+
const checkbox = checkboxes[i];
|
|
229
|
+
checkbox.disabled = Boolean(newDisabled);
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
disableAll: {
|
|
234
|
+
value: () => {
|
|
235
|
+
for (let i = 0; i < checkboxes.length; i++) {
|
|
236
|
+
checkboxes[i].disabled = true;
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
enableAll: {
|
|
241
|
+
value: () => {
|
|
242
|
+
for (let i = 0; i < checkboxes.length; i++) {
|
|
243
|
+
checkboxes[i].disabled = false;
|
|
244
|
+
}
|
|
245
|
+
},
|
|
187
246
|
},
|
|
188
247
|
});
|
|
189
248
|
return container;
|
|
@@ -195,7 +254,7 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
|
|
|
195
254
|
* Only handles open/close state, title and content are passed as props
|
|
196
255
|
*/
|
|
197
256
|
function Dialog(props) {
|
|
198
|
-
let { open = false, '
|
|
257
|
+
let { open = false, 'kt:close': onClose = noop, title, children, actions, maxWidth = 'sm', fullWidth = false, } = props;
|
|
199
258
|
// Handle ESC key - store handler for cleanup
|
|
200
259
|
const keyDownHandler = (e) => {
|
|
201
260
|
if (e.key === 'Escape') {
|
|
@@ -280,8 +339,67 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
|
|
|
280
339
|
* - can alse be used to store normal values, but it is not reactive.
|
|
281
340
|
* @param value mostly an HTMLElement
|
|
282
341
|
*/
|
|
283
|
-
function ref(value) {
|
|
284
|
-
|
|
342
|
+
function ref(value, onChange) {
|
|
343
|
+
let _value = value;
|
|
344
|
+
let _onChanges = [];
|
|
345
|
+
return {
|
|
346
|
+
isKT: true,
|
|
347
|
+
get value() {
|
|
348
|
+
return _value;
|
|
349
|
+
},
|
|
350
|
+
set value(newValue) {
|
|
351
|
+
if (newValue === _value) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
// replace the old node with the new one in the DOM if both are nodes
|
|
355
|
+
if (_value instanceof Node && newValue instanceof Node) {
|
|
356
|
+
if (newValue.contains(_value)) {
|
|
357
|
+
_value.remove();
|
|
358
|
+
}
|
|
359
|
+
_value.replaceWith(newValue);
|
|
360
|
+
}
|
|
361
|
+
const oldValue = _value;
|
|
362
|
+
_value = newValue;
|
|
363
|
+
for (let i = 0; i < _onChanges.length; i++) {
|
|
364
|
+
_onChanges[i](newValue, oldValue);
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
addOnChange: (callback) => _onChanges.push(callback),
|
|
368
|
+
removeOnChange: (callback) => {
|
|
369
|
+
for (let i = _onChanges.length - 1; i >= 0; i--) {
|
|
370
|
+
if (_onChanges[i] === callback) {
|
|
371
|
+
_onChanges.splice(i, 1);
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return false;
|
|
376
|
+
},
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* A helper to create redrawable elements
|
|
381
|
+
* ```tsx
|
|
382
|
+
* export function MyComponent() {
|
|
383
|
+
* let aa = 10;
|
|
384
|
+
* // ...
|
|
385
|
+
* // aa might be changed
|
|
386
|
+
* return createRedrawable(() => <div>{aa}</div>);
|
|
387
|
+
* }
|
|
388
|
+
* ```
|
|
389
|
+
* Then the returned element has a `redraw` method to redraw itself with new values.
|
|
390
|
+
* @param creator a simple creator function that returns an element
|
|
391
|
+
* @returns created element's ref
|
|
392
|
+
*/
|
|
393
|
+
function createRedrawable(creator) {
|
|
394
|
+
const elRef = ref();
|
|
395
|
+
elRef.value = creator();
|
|
396
|
+
const redraw = () => {
|
|
397
|
+
elRef.value = creator(); // ref setter automatically calls replaceWith
|
|
398
|
+
elRef.value.redraw = redraw;
|
|
399
|
+
return elRef.value;
|
|
400
|
+
};
|
|
401
|
+
elRef.value.redraw = redraw;
|
|
402
|
+
return elRef;
|
|
285
403
|
}
|
|
286
404
|
|
|
287
405
|
/**
|
|
@@ -325,64 +443,132 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
|
|
|
325
443
|
return container;
|
|
326
444
|
}
|
|
327
445
|
|
|
328
|
-
const emptyFn$2 = () => { };
|
|
329
446
|
/**
|
|
330
447
|
* TextField component - mimics MUI TextField appearance and behavior
|
|
331
448
|
*/
|
|
332
449
|
function TextField(props) {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
|
|
450
|
+
let { label = '', placeholder = '', value = '', type = 'text', disabled = false, readonly = false, required = false, error = false, helperText = '', fullWidth = false, multiline = false, rows = 3, size = 'medium', } = props;
|
|
451
|
+
const onInput = generateHandler(props, 'kt:input');
|
|
452
|
+
const onInputTrim = generateHandler(props, 'kt-trim:input');
|
|
453
|
+
const onChange = generateHandler(props, 'kt:change');
|
|
454
|
+
const onChangeTrim = generateHandler(props, 'kt-trim:change');
|
|
455
|
+
const onBlur = generateHandler(props, 'kt:blur');
|
|
456
|
+
const onFocus = generateHandler(props, 'kt:focus');
|
|
457
|
+
const updateContainerClass = () => {
|
|
458
|
+
container.className = [
|
|
340
459
|
'mui-textfield-root',
|
|
341
460
|
`mui-textfield-size-${size}`,
|
|
342
461
|
isFocused ? 'mui-textfield-focused' : '',
|
|
343
462
|
error ? 'mui-textfield-error' : '',
|
|
344
463
|
disabled ? 'mui-textfield-disabled' : '',
|
|
345
464
|
fullWidth ? 'mui-textfield-fullwidth' : '',
|
|
346
|
-
label &&
|
|
465
|
+
label && isFocused && inputEl.value ? 'mui-textfield-has-value' : '',
|
|
347
466
|
label ? '' : 'mui-textfield-no-label',
|
|
348
|
-
];
|
|
349
|
-
container.className = classes.join(' ');
|
|
467
|
+
].join(' ');
|
|
350
468
|
};
|
|
351
|
-
const handleInput = (
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
469
|
+
const handleInput = () => {
|
|
470
|
+
updateContainerClass();
|
|
471
|
+
onInput(inputEl.value);
|
|
472
|
+
onInputTrim(inputEl.value.trim());
|
|
355
473
|
};
|
|
356
|
-
const handleChange = (
|
|
357
|
-
|
|
358
|
-
|
|
474
|
+
const handleChange = () => {
|
|
475
|
+
onChange(inputEl.value);
|
|
476
|
+
onChangeTrim(inputEl.value.trim());
|
|
359
477
|
};
|
|
360
|
-
const handleFocus = (
|
|
478
|
+
const handleFocus = () => {
|
|
361
479
|
isFocused = true;
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
onFocus(target.value, e);
|
|
480
|
+
updateContainerClass();
|
|
481
|
+
onFocus(inputEl.value);
|
|
365
482
|
};
|
|
366
|
-
const handleBlur = (
|
|
483
|
+
const handleBlur = () => {
|
|
367
484
|
isFocused = false;
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
onBlur(target.value, e);
|
|
485
|
+
updateContainerClass();
|
|
486
|
+
onBlur(inputEl.value);
|
|
371
487
|
};
|
|
372
|
-
// Create input or textarea element
|
|
373
|
-
// Only show placeholder when label is floating (focused or has value)
|
|
374
488
|
const getPlaceholder = () => (label && !isFocused && !value ? '' : placeholder);
|
|
375
|
-
|
|
376
|
-
const
|
|
489
|
+
let isFocused = false;
|
|
490
|
+
const inputEl = multiline
|
|
491
|
+
? (jsxRuntime.jsx("textarea", { class: "mui-textfield-input", placeholder: getPlaceholder(), value: value, disabled: disabled, readOnly: readonly, required: required, rows: rows, "on:input": handleInput, "on:change": handleChange, "on:focus": handleFocus, "on:blur": handleBlur }))
|
|
492
|
+
: (jsxRuntime.jsx("input", { type: type, class: "mui-textfield-input", placeholder: getPlaceholder(), value: value, disabled: disabled, readOnly: readonly, required: required, "on:input": handleInput, "on:change": handleChange, "on:focus": handleFocus, "on:blur": handleBlur }));
|
|
493
|
+
const helperTextEl = jsxRuntime.jsx("p", { class: "mui-textfield-helper-text", children: helperText });
|
|
494
|
+
const wrapperRef = createRedrawable(() => (jsxRuntime.jsxs("div", { class: "mui-textfield-wrapper", children: [jsxRuntime.jsxs("label", { "k-if": label, class: "mui-textfield-label", children: [label, required && jsxRuntime.jsx("span", { class: "mui-textfield-required", children: "*" })] }), jsxRuntime.jsx("div", { class: "mui-textfield-input-wrapper", children: inputEl }), jsxRuntime.jsx("fieldset", { class: "mui-textfield-fieldset", children: jsxRuntime.jsx("legend", { "k-if": label, class: "mui-textfield-legend", children: jsxRuntime.jsxs("span", { children: [label, required && '*'] }) }) })] })));
|
|
495
|
+
const container = (jsxRuntime.jsxs("div", { class: 'mui-textfield-root ' + (props.class ? props.class : ''), style: props.style ? props.style : '', children: [wrapperRef, helperTextEl] }));
|
|
377
496
|
// Initialize classes
|
|
378
|
-
setTimeout(() =>
|
|
379
|
-
Object.
|
|
380
|
-
|
|
381
|
-
|
|
497
|
+
setTimeout(() => updateContainerClass(), 0);
|
|
498
|
+
Object.defineProperties(container, {
|
|
499
|
+
value: {
|
|
500
|
+
get() {
|
|
501
|
+
return inputEl.value;
|
|
502
|
+
},
|
|
503
|
+
set(newValue) {
|
|
504
|
+
inputEl.value = newValue;
|
|
505
|
+
updateContainerClass();
|
|
506
|
+
},
|
|
382
507
|
},
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
508
|
+
label: {
|
|
509
|
+
get() {
|
|
510
|
+
return label;
|
|
511
|
+
},
|
|
512
|
+
set(newLabel) {
|
|
513
|
+
label = newLabel;
|
|
514
|
+
wrapperRef.value.redraw(); // label takes too much and should be redrawn
|
|
515
|
+
updateContainerClass();
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
placeholder: {
|
|
519
|
+
get() {
|
|
520
|
+
return placeholder;
|
|
521
|
+
},
|
|
522
|
+
set(newPlaceholder) {
|
|
523
|
+
placeholder = newPlaceholder;
|
|
524
|
+
inputEl.placeholder = getPlaceholder();
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
type: {
|
|
528
|
+
get() {
|
|
529
|
+
return type;
|
|
530
|
+
},
|
|
531
|
+
set(newType) {
|
|
532
|
+
type = newType || 'text';
|
|
533
|
+
inputEl.type = type;
|
|
534
|
+
},
|
|
535
|
+
},
|
|
536
|
+
disabled: {
|
|
537
|
+
get() {
|
|
538
|
+
return disabled;
|
|
539
|
+
},
|
|
540
|
+
set(val) {
|
|
541
|
+
disabled = !!val;
|
|
542
|
+
inputEl.disabled = disabled;
|
|
543
|
+
container.classList.toggle('mui-textfield-disabled', disabled);
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
readonly: {
|
|
547
|
+
get() {
|
|
548
|
+
return readonly;
|
|
549
|
+
},
|
|
550
|
+
set(val) {
|
|
551
|
+
readonly = Boolean(val);
|
|
552
|
+
inputEl.readOnly = readonly;
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
error: {
|
|
556
|
+
get() {
|
|
557
|
+
return error;
|
|
558
|
+
},
|
|
559
|
+
set(val) {
|
|
560
|
+
error = Boolean(val);
|
|
561
|
+
container.classList.toggle('mui-textfield-error', error);
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
helperText: {
|
|
565
|
+
get() {
|
|
566
|
+
return helperText;
|
|
567
|
+
},
|
|
568
|
+
set(text) {
|
|
569
|
+
helperTextEl.textContent = text;
|
|
570
|
+
helperTextEl.style.display = text ? 'block' : 'none';
|
|
571
|
+
},
|
|
386
572
|
},
|
|
387
573
|
});
|
|
388
574
|
return container;
|
|
@@ -406,7 +592,7 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
|
|
|
406
592
|
toggleIcon(checked);
|
|
407
593
|
onChange(checked, value);
|
|
408
594
|
};
|
|
409
|
-
const { checked: initChecked = false, value = '', text = '', size = 'small', '
|
|
595
|
+
const { checked: initChecked = false, value = '', text = '', size = 'small', 'kt:change': onChange = emptyFn$1, disabled: initDisabled = false, color = 'primary', } = props;
|
|
410
596
|
const inputRef = kt_js.ref();
|
|
411
597
|
let checked = initChecked;
|
|
412
598
|
let disabled = initDisabled;
|
|
@@ -426,7 +612,7 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
|
|
|
426
612
|
* RadioGroup component - groups multiple radios together
|
|
427
613
|
*/
|
|
428
614
|
function RadioGroup(props) {
|
|
429
|
-
const { value = '', size = 'small', '
|
|
615
|
+
const { value = '', size = 'small', 'kt:change': onChange = emptyFn$1, row = false } = props;
|
|
430
616
|
const changeHandler = (checked, value) => {
|
|
431
617
|
if (checked) {
|
|
432
618
|
onChange(value);
|
|
@@ -436,15 +622,15 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
|
|
|
436
622
|
const radios = props.options.map((o) => {
|
|
437
623
|
o.size = size;
|
|
438
624
|
o.checked = value === o.value;
|
|
439
|
-
const originalChange = o['
|
|
625
|
+
const originalChange = o['kt:change'];
|
|
440
626
|
if (originalChange) {
|
|
441
|
-
o['
|
|
627
|
+
o['kt:change'] = (checked, newValue) => {
|
|
442
628
|
originalChange(checked, newValue);
|
|
443
629
|
changeHandler(checked, newValue);
|
|
444
630
|
};
|
|
445
631
|
}
|
|
446
632
|
else {
|
|
447
|
-
o['
|
|
633
|
+
o['kt:change'] = changeHandler;
|
|
448
634
|
}
|
|
449
635
|
return Radio(o);
|
|
450
636
|
});
|
|
@@ -456,7 +642,7 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
|
|
|
456
642
|
* Select component - mimics MUI Select appearance and behavior
|
|
457
643
|
*/
|
|
458
644
|
function Select(props) {
|
|
459
|
-
let { value = '', options = [], label = '', placeholder = '', size = 'medium', '
|
|
645
|
+
let { value = '', options = [], label = '', placeholder = '', size = 'medium', 'kt:change': onChange = emptyFn, fullWidth = false, disabled = false, } = props;
|
|
460
646
|
let isOpen = false;
|
|
461
647
|
let isFocused = false;
|
|
462
648
|
const selectRef = kt_js.ref();
|
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'kt.js/jsx-runtime';
|
|
2
|
-
import { ref as ref$1, createRedrawable } from 'kt.js';
|
|
2
|
+
import { ref as ref$1, createRedrawable as createRedrawable$1 } from 'kt.js';
|
|
3
3
|
|
|
4
4
|
/**s
|
|
5
5
|
* Alert component - mimics MUI Alert appearance and behavior
|
|
6
6
|
*/
|
|
7
7
|
function Alert(props) {
|
|
8
|
-
const { children, severity = 'info', variant = 'standard', icon, '
|
|
8
|
+
const { children, severity = 'info', variant = 'standard', icon, 'kt:close': onClose, sx } = props;
|
|
9
9
|
const classes = `mui-alert mui-alert-${severity} mui-alert-${variant} ${props.class ? props.class : ''}`;
|
|
10
10
|
// Convert sx object to style string
|
|
11
11
|
let styleString = props.style || '';
|
|
@@ -44,12 +44,23 @@ function Alert(props) {
|
|
|
44
44
|
return alert;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
const emptyFn$
|
|
47
|
+
const emptyFn$3 = () => { };
|
|
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$3;
|
|
57
|
+
};
|
|
58
|
+
|
|
48
59
|
/**
|
|
49
60
|
* Button component - mimics MUI Button appearance and behavior
|
|
50
61
|
*/
|
|
51
62
|
function Button(props) {
|
|
52
|
-
const { children, variant = 'text', color = 'primary', size = 'medium', disabled = false, fullWidth = false, iconOnly = false, startIcon, endIcon, type = 'button', 'on:click': onClick = emptyFn$
|
|
63
|
+
const { children, variant = 'text', color = 'primary', size = 'medium', disabled = false, fullWidth = false, iconOnly = false, startIcon, endIcon, type = 'button', 'on:click': onClick = emptyFn$3, } = props;
|
|
53
64
|
const classes = [
|
|
54
65
|
'mui-button',
|
|
55
66
|
`mui-button-${variant}`,
|
|
@@ -91,7 +102,7 @@ function Button(props) {
|
|
|
91
102
|
return (jsxs("button", { class: classes, style: props.style ? 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 }), jsx("span", { class: "mui-button-ripple" })] }));
|
|
92
103
|
}
|
|
93
104
|
|
|
94
|
-
const emptyFn$
|
|
105
|
+
const emptyFn$2 = () => { };
|
|
95
106
|
/**
|
|
96
107
|
* Checkbox component - mimics MUI Checkbox appearance and behavior
|
|
97
108
|
*/
|
|
@@ -113,13 +124,13 @@ function Checkbox(props) {
|
|
|
113
124
|
if (disabled) {
|
|
114
125
|
return;
|
|
115
126
|
}
|
|
116
|
-
checked =
|
|
127
|
+
checked = inputEl.checked;
|
|
117
128
|
indeterminate = false;
|
|
118
129
|
toggleIcon(checked, indeterminate);
|
|
119
130
|
onChange(checked, value);
|
|
120
131
|
};
|
|
121
|
-
let { checked = false, value = '', label = '', size = 'medium', '
|
|
122
|
-
const
|
|
132
|
+
let { checked = false, value = '', label = '', size = 'medium', 'kt:change': onChange = emptyFn$2, disabled = false, color = 'primary', indeterminate = false, } = props;
|
|
133
|
+
const inputEl = (jsx("input", { type: "checkbox", class: "mui-checkbox-input", checked: checked, value: value, disabled: disabled, "on:change": handleChange }));
|
|
123
134
|
// Unchecked icon
|
|
124
135
|
const uncheckedIcon = (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" }) }) }));
|
|
125
136
|
// Checked icon
|
|
@@ -128,26 +139,47 @@ function Checkbox(props) {
|
|
|
128
139
|
const indeterminateIcon = (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" }) }) }));
|
|
129
140
|
// Initialize icon state
|
|
130
141
|
toggleIcon(checked, indeterminate);
|
|
131
|
-
const container = (jsxs("label", { class: `mui-checkbox-wrapper mui-checkbox-size-${size} ${disabled ? 'mui-checkbox-disabled' : ''} mui-checkbox-color-${color}`, children: [
|
|
132
|
-
Object.
|
|
133
|
-
|
|
134
|
-
|
|
142
|
+
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 })] }));
|
|
143
|
+
Object.defineProperties(container, {
|
|
144
|
+
checked: {
|
|
145
|
+
get() {
|
|
146
|
+
return checked;
|
|
147
|
+
},
|
|
148
|
+
set(newChecked) {
|
|
149
|
+
checked = newChecked;
|
|
150
|
+
indeterminate = false;
|
|
151
|
+
inputEl.checked = checked;
|
|
152
|
+
toggleIcon(checked, indeterminate);
|
|
153
|
+
},
|
|
135
154
|
},
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
155
|
+
value: {
|
|
156
|
+
get() {
|
|
157
|
+
return value;
|
|
158
|
+
},
|
|
159
|
+
set(newValue) {
|
|
160
|
+
value = newValue;
|
|
161
|
+
inputEl.value = value;
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
disabled: {
|
|
165
|
+
get() {
|
|
166
|
+
return disabled;
|
|
167
|
+
},
|
|
168
|
+
set(newDisabled) {
|
|
169
|
+
disabled = Boolean(newDisabled);
|
|
170
|
+
inputEl.disabled = disabled;
|
|
171
|
+
container.classList.toggle('mui-checkbox-disabled', disabled);
|
|
172
|
+
},
|
|
141
173
|
},
|
|
142
174
|
});
|
|
143
|
-
container.value = value;
|
|
144
175
|
return container;
|
|
145
176
|
}
|
|
146
177
|
/**
|
|
147
178
|
* CheckboxGroup component - groups multiple checkboxes together
|
|
148
179
|
*/
|
|
149
180
|
function CheckboxGroup(props) {
|
|
150
|
-
let { value = [], size = 'medium',
|
|
181
|
+
let { value = [], size = 'medium', row = false } = props;
|
|
182
|
+
const onChange = generateHandler(props, 'kt:change');
|
|
151
183
|
let selectedValues = new Set(value);
|
|
152
184
|
const changeHandler = (checked, checkboxValue) => {
|
|
153
185
|
if (checked) {
|
|
@@ -161,29 +193,56 @@ function CheckboxGroup(props) {
|
|
|
161
193
|
const checkboxes = props.options.map((o) => {
|
|
162
194
|
o.size = size;
|
|
163
195
|
o.checked = selectedValues.has(o.value);
|
|
164
|
-
const originalChange = o['
|
|
196
|
+
const originalChange = o['kt:change'];
|
|
165
197
|
if (originalChange) {
|
|
166
|
-
o['
|
|
198
|
+
o['kt:change'] = (checked, value) => {
|
|
167
199
|
originalChange(checked, value);
|
|
168
200
|
changeHandler(checked, value);
|
|
169
201
|
};
|
|
170
202
|
}
|
|
171
203
|
else {
|
|
172
|
-
o['
|
|
204
|
+
o['kt:change'] = changeHandler;
|
|
173
205
|
}
|
|
174
206
|
return Checkbox(o);
|
|
175
207
|
});
|
|
176
208
|
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 }));
|
|
177
|
-
Object.
|
|
178
|
-
|
|
179
|
-
|
|
209
|
+
Object.defineProperties(container, {
|
|
210
|
+
value: {
|
|
211
|
+
get() {
|
|
212
|
+
return Array.from(selectedValues);
|
|
213
|
+
},
|
|
214
|
+
set(newValues) {
|
|
215
|
+
selectedValues = new Set(newValues);
|
|
216
|
+
for (let i = 0; i < checkboxes.length; i++) {
|
|
217
|
+
const checkbox = checkboxes[i];
|
|
218
|
+
checkbox.checked = selectedValues.has(checkbox.value);
|
|
219
|
+
}
|
|
220
|
+
},
|
|
180
221
|
},
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
222
|
+
disabled: {
|
|
223
|
+
get() {
|
|
224
|
+
return checkboxes.map((cb) => cb.disabled);
|
|
225
|
+
},
|
|
226
|
+
set(newDisabled) {
|
|
227
|
+
for (let i = 0; i < checkboxes.length; i++) {
|
|
228
|
+
const checkbox = checkboxes[i];
|
|
229
|
+
checkbox.disabled = Boolean(newDisabled);
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
disableAll: {
|
|
234
|
+
value: () => {
|
|
235
|
+
for (let i = 0; i < checkboxes.length; i++) {
|
|
236
|
+
checkboxes[i].disabled = true;
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
enableAll: {
|
|
241
|
+
value: () => {
|
|
242
|
+
for (let i = 0; i < checkboxes.length; i++) {
|
|
243
|
+
checkboxes[i].disabled = false;
|
|
244
|
+
}
|
|
245
|
+
},
|
|
187
246
|
},
|
|
188
247
|
});
|
|
189
248
|
return container;
|
|
@@ -195,7 +254,7 @@ const noop = () => { };
|
|
|
195
254
|
* Only handles open/close state, title and content are passed as props
|
|
196
255
|
*/
|
|
197
256
|
function Dialog(props) {
|
|
198
|
-
let { open = false, '
|
|
257
|
+
let { open = false, 'kt:close': onClose = noop, title, children, actions, maxWidth = 'sm', fullWidth = false, } = props;
|
|
199
258
|
// Handle ESC key - store handler for cleanup
|
|
200
259
|
const keyDownHandler = (e) => {
|
|
201
260
|
if (e.key === 'Escape') {
|
|
@@ -280,8 +339,67 @@ document.createElement('div');
|
|
|
280
339
|
* - can alse be used to store normal values, but it is not reactive.
|
|
281
340
|
* @param value mostly an HTMLElement
|
|
282
341
|
*/
|
|
283
|
-
function ref(value) {
|
|
284
|
-
|
|
342
|
+
function ref(value, onChange) {
|
|
343
|
+
let _value = value;
|
|
344
|
+
let _onChanges = [];
|
|
345
|
+
return {
|
|
346
|
+
isKT: true,
|
|
347
|
+
get value() {
|
|
348
|
+
return _value;
|
|
349
|
+
},
|
|
350
|
+
set value(newValue) {
|
|
351
|
+
if (newValue === _value) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
// replace the old node with the new one in the DOM if both are nodes
|
|
355
|
+
if (_value instanceof Node && newValue instanceof Node) {
|
|
356
|
+
if (newValue.contains(_value)) {
|
|
357
|
+
_value.remove();
|
|
358
|
+
}
|
|
359
|
+
_value.replaceWith(newValue);
|
|
360
|
+
}
|
|
361
|
+
const oldValue = _value;
|
|
362
|
+
_value = newValue;
|
|
363
|
+
for (let i = 0; i < _onChanges.length; i++) {
|
|
364
|
+
_onChanges[i](newValue, oldValue);
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
addOnChange: (callback) => _onChanges.push(callback),
|
|
368
|
+
removeOnChange: (callback) => {
|
|
369
|
+
for (let i = _onChanges.length - 1; i >= 0; i--) {
|
|
370
|
+
if (_onChanges[i] === callback) {
|
|
371
|
+
_onChanges.splice(i, 1);
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return false;
|
|
376
|
+
},
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* A helper to create redrawable elements
|
|
381
|
+
* ```tsx
|
|
382
|
+
* export function MyComponent() {
|
|
383
|
+
* let aa = 10;
|
|
384
|
+
* // ...
|
|
385
|
+
* // aa might be changed
|
|
386
|
+
* return createRedrawable(() => <div>{aa}</div>);
|
|
387
|
+
* }
|
|
388
|
+
* ```
|
|
389
|
+
* Then the returned element has a `redraw` method to redraw itself with new values.
|
|
390
|
+
* @param creator a simple creator function that returns an element
|
|
391
|
+
* @returns created element's ref
|
|
392
|
+
*/
|
|
393
|
+
function createRedrawable(creator) {
|
|
394
|
+
const elRef = ref();
|
|
395
|
+
elRef.value = creator();
|
|
396
|
+
const redraw = () => {
|
|
397
|
+
elRef.value = creator(); // ref setter automatically calls replaceWith
|
|
398
|
+
elRef.value.redraw = redraw;
|
|
399
|
+
return elRef.value;
|
|
400
|
+
};
|
|
401
|
+
elRef.value.redraw = redraw;
|
|
402
|
+
return elRef;
|
|
285
403
|
}
|
|
286
404
|
|
|
287
405
|
/**
|
|
@@ -325,64 +443,132 @@ function LinearProgress(props) {
|
|
|
325
443
|
return container;
|
|
326
444
|
}
|
|
327
445
|
|
|
328
|
-
const emptyFn$2 = () => { };
|
|
329
446
|
/**
|
|
330
447
|
* TextField component - mimics MUI TextField appearance and behavior
|
|
331
448
|
*/
|
|
332
449
|
function TextField(props) {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
|
|
450
|
+
let { label = '', placeholder = '', value = '', type = 'text', disabled = false, readonly = false, required = false, error = false, helperText = '', fullWidth = false, multiline = false, rows = 3, size = 'medium', } = props;
|
|
451
|
+
const onInput = generateHandler(props, 'kt:input');
|
|
452
|
+
const onInputTrim = generateHandler(props, 'kt-trim:input');
|
|
453
|
+
const onChange = generateHandler(props, 'kt:change');
|
|
454
|
+
const onChangeTrim = generateHandler(props, 'kt-trim:change');
|
|
455
|
+
const onBlur = generateHandler(props, 'kt:blur');
|
|
456
|
+
const onFocus = generateHandler(props, 'kt:focus');
|
|
457
|
+
const updateContainerClass = () => {
|
|
458
|
+
container.className = [
|
|
340
459
|
'mui-textfield-root',
|
|
341
460
|
`mui-textfield-size-${size}`,
|
|
342
461
|
isFocused ? 'mui-textfield-focused' : '',
|
|
343
462
|
error ? 'mui-textfield-error' : '',
|
|
344
463
|
disabled ? 'mui-textfield-disabled' : '',
|
|
345
464
|
fullWidth ? 'mui-textfield-fullwidth' : '',
|
|
346
|
-
label &&
|
|
465
|
+
label && isFocused && inputEl.value ? 'mui-textfield-has-value' : '',
|
|
347
466
|
label ? '' : 'mui-textfield-no-label',
|
|
348
|
-
];
|
|
349
|
-
container.className = classes.join(' ');
|
|
467
|
+
].join(' ');
|
|
350
468
|
};
|
|
351
|
-
const handleInput = (
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
469
|
+
const handleInput = () => {
|
|
470
|
+
updateContainerClass();
|
|
471
|
+
onInput(inputEl.value);
|
|
472
|
+
onInputTrim(inputEl.value.trim());
|
|
355
473
|
};
|
|
356
|
-
const handleChange = (
|
|
357
|
-
|
|
358
|
-
|
|
474
|
+
const handleChange = () => {
|
|
475
|
+
onChange(inputEl.value);
|
|
476
|
+
onChangeTrim(inputEl.value.trim());
|
|
359
477
|
};
|
|
360
|
-
const handleFocus = (
|
|
478
|
+
const handleFocus = () => {
|
|
361
479
|
isFocused = true;
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
onFocus(target.value, e);
|
|
480
|
+
updateContainerClass();
|
|
481
|
+
onFocus(inputEl.value);
|
|
365
482
|
};
|
|
366
|
-
const handleBlur = (
|
|
483
|
+
const handleBlur = () => {
|
|
367
484
|
isFocused = false;
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
onBlur(target.value, e);
|
|
485
|
+
updateContainerClass();
|
|
486
|
+
onBlur(inputEl.value);
|
|
371
487
|
};
|
|
372
|
-
// Create input or textarea element
|
|
373
|
-
// Only show placeholder when label is floating (focused or has value)
|
|
374
488
|
const getPlaceholder = () => (label && !isFocused && !value ? '' : placeholder);
|
|
375
|
-
|
|
376
|
-
const
|
|
489
|
+
let isFocused = false;
|
|
490
|
+
const inputEl = multiline
|
|
491
|
+
? (jsx("textarea", { class: "mui-textfield-input", placeholder: getPlaceholder(), value: value, disabled: disabled, readOnly: readonly, required: required, rows: rows, "on:input": handleInput, "on:change": handleChange, "on:focus": handleFocus, "on:blur": handleBlur }))
|
|
492
|
+
: (jsx("input", { type: type, class: "mui-textfield-input", placeholder: getPlaceholder(), value: value, disabled: disabled, readOnly: readonly, required: required, "on:input": handleInput, "on:change": handleChange, "on:focus": handleFocus, "on:blur": handleBlur }));
|
|
493
|
+
const helperTextEl = jsx("p", { class: "mui-textfield-helper-text", children: helperText });
|
|
494
|
+
const wrapperRef = createRedrawable(() => (jsxs("div", { class: "mui-textfield-wrapper", children: [jsxs("label", { "k-if": label, class: "mui-textfield-label", children: [label, required && jsx("span", { class: "mui-textfield-required", children: "*" })] }), jsx("div", { class: "mui-textfield-input-wrapper", children: inputEl }), jsx("fieldset", { class: "mui-textfield-fieldset", children: jsx("legend", { "k-if": label, class: "mui-textfield-legend", children: jsxs("span", { children: [label, required && '*'] }) }) })] })));
|
|
495
|
+
const container = (jsxs("div", { class: 'mui-textfield-root ' + (props.class ? props.class : ''), style: props.style ? props.style : '', children: [wrapperRef, helperTextEl] }));
|
|
377
496
|
// Initialize classes
|
|
378
|
-
setTimeout(() =>
|
|
379
|
-
Object.
|
|
380
|
-
|
|
381
|
-
|
|
497
|
+
setTimeout(() => updateContainerClass(), 0);
|
|
498
|
+
Object.defineProperties(container, {
|
|
499
|
+
value: {
|
|
500
|
+
get() {
|
|
501
|
+
return inputEl.value;
|
|
502
|
+
},
|
|
503
|
+
set(newValue) {
|
|
504
|
+
inputEl.value = newValue;
|
|
505
|
+
updateContainerClass();
|
|
506
|
+
},
|
|
382
507
|
},
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
508
|
+
label: {
|
|
509
|
+
get() {
|
|
510
|
+
return label;
|
|
511
|
+
},
|
|
512
|
+
set(newLabel) {
|
|
513
|
+
label = newLabel;
|
|
514
|
+
wrapperRef.value.redraw(); // label takes too much and should be redrawn
|
|
515
|
+
updateContainerClass();
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
placeholder: {
|
|
519
|
+
get() {
|
|
520
|
+
return placeholder;
|
|
521
|
+
},
|
|
522
|
+
set(newPlaceholder) {
|
|
523
|
+
placeholder = newPlaceholder;
|
|
524
|
+
inputEl.placeholder = getPlaceholder();
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
type: {
|
|
528
|
+
get() {
|
|
529
|
+
return type;
|
|
530
|
+
},
|
|
531
|
+
set(newType) {
|
|
532
|
+
type = newType || 'text';
|
|
533
|
+
inputEl.type = type;
|
|
534
|
+
},
|
|
535
|
+
},
|
|
536
|
+
disabled: {
|
|
537
|
+
get() {
|
|
538
|
+
return disabled;
|
|
539
|
+
},
|
|
540
|
+
set(val) {
|
|
541
|
+
disabled = !!val;
|
|
542
|
+
inputEl.disabled = disabled;
|
|
543
|
+
container.classList.toggle('mui-textfield-disabled', disabled);
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
readonly: {
|
|
547
|
+
get() {
|
|
548
|
+
return readonly;
|
|
549
|
+
},
|
|
550
|
+
set(val) {
|
|
551
|
+
readonly = Boolean(val);
|
|
552
|
+
inputEl.readOnly = readonly;
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
error: {
|
|
556
|
+
get() {
|
|
557
|
+
return error;
|
|
558
|
+
},
|
|
559
|
+
set(val) {
|
|
560
|
+
error = Boolean(val);
|
|
561
|
+
container.classList.toggle('mui-textfield-error', error);
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
helperText: {
|
|
565
|
+
get() {
|
|
566
|
+
return helperText;
|
|
567
|
+
},
|
|
568
|
+
set(text) {
|
|
569
|
+
helperTextEl.textContent = text;
|
|
570
|
+
helperTextEl.style.display = text ? 'block' : 'none';
|
|
571
|
+
},
|
|
386
572
|
},
|
|
387
573
|
});
|
|
388
574
|
return container;
|
|
@@ -406,7 +592,7 @@ function Radio(props) {
|
|
|
406
592
|
toggleIcon(checked);
|
|
407
593
|
onChange(checked, value);
|
|
408
594
|
};
|
|
409
|
-
const { checked: initChecked = false, value = '', text = '', size = 'small', '
|
|
595
|
+
const { checked: initChecked = false, value = '', text = '', size = 'small', 'kt:change': onChange = emptyFn$1, disabled: initDisabled = false, color = 'primary', } = props;
|
|
410
596
|
const inputRef = ref$1();
|
|
411
597
|
let checked = initChecked;
|
|
412
598
|
let disabled = initDisabled;
|
|
@@ -426,7 +612,7 @@ function Radio(props) {
|
|
|
426
612
|
* RadioGroup component - groups multiple radios together
|
|
427
613
|
*/
|
|
428
614
|
function RadioGroup(props) {
|
|
429
|
-
const { value = '', size = 'small', '
|
|
615
|
+
const { value = '', size = 'small', 'kt:change': onChange = emptyFn$1, row = false } = props;
|
|
430
616
|
const changeHandler = (checked, value) => {
|
|
431
617
|
if (checked) {
|
|
432
618
|
onChange(value);
|
|
@@ -436,15 +622,15 @@ function RadioGroup(props) {
|
|
|
436
622
|
const radios = props.options.map((o) => {
|
|
437
623
|
o.size = size;
|
|
438
624
|
o.checked = value === o.value;
|
|
439
|
-
const originalChange = o['
|
|
625
|
+
const originalChange = o['kt:change'];
|
|
440
626
|
if (originalChange) {
|
|
441
|
-
o['
|
|
627
|
+
o['kt:change'] = (checked, newValue) => {
|
|
442
628
|
originalChange(checked, newValue);
|
|
443
629
|
changeHandler(checked, newValue);
|
|
444
630
|
};
|
|
445
631
|
}
|
|
446
632
|
else {
|
|
447
|
-
o['
|
|
633
|
+
o['kt:change'] = changeHandler;
|
|
448
634
|
}
|
|
449
635
|
return Radio(o);
|
|
450
636
|
});
|
|
@@ -456,7 +642,7 @@ const emptyFn = () => { };
|
|
|
456
642
|
* Select component - mimics MUI Select appearance and behavior
|
|
457
643
|
*/
|
|
458
644
|
function Select(props) {
|
|
459
|
-
let { value = '', options = [], label = '', placeholder = '', size = 'medium', '
|
|
645
|
+
let { value = '', options = [], label = '', placeholder = '', size = 'medium', 'kt:change': onChange = emptyFn, fullWidth = false, disabled = false, } = props;
|
|
460
646
|
let isOpen = false;
|
|
461
647
|
let isFocused = false;
|
|
462
648
|
const selectRef = ref$1();
|
|
@@ -528,7 +714,7 @@ function Select(props) {
|
|
|
528
714
|
}
|
|
529
715
|
}
|
|
530
716
|
};
|
|
531
|
-
const valueDisplay = createRedrawable(() => {
|
|
717
|
+
const valueDisplay = createRedrawable$1(() => {
|
|
532
718
|
const o = options.find((opt) => opt.value === value);
|
|
533
719
|
let inner;
|
|
534
720
|
if (o === undefined) {
|
|
@@ -539,7 +725,7 @@ function Select(props) {
|
|
|
539
725
|
}
|
|
540
726
|
return jsx("div", { class: "mui-select-display", children: inner });
|
|
541
727
|
});
|
|
542
|
-
const menu = createRedrawable(() => {
|
|
728
|
+
const menu = createRedrawable$1(() => {
|
|
543
729
|
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 }))) }));
|
|
544
730
|
});
|
|
545
731
|
// Create container
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ktjs/mui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.1",
|
|
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,7 @@
|
|
|
35
35
|
"directory": "packages/mui"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@ktjs/core": "0.18.
|
|
38
|
+
"@ktjs/core": "0.18.6"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "rollup -c rollup.config.mjs",
|