@ktjs/mui 0.18.5 → 0.18.8

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 CHANGED
@@ -3,8 +3,7 @@ import { KTHTMLElement as KTHTMLElement$1, KTRef } from '@ktjs/core';
3
3
 
4
4
  interface AlertProps {
5
5
  class?: string;
6
- style?: string;
7
- sx?: Record<string, any>;
6
+ style?: string | Partial<CSSStyleDeclaration>;
8
7
  children: string | HTMLElement | KTHTMLElement | Array<string | HTMLElement | KTHTMLElement>;
9
8
  severity?: 'error' | 'warning' | 'info' | 'success';
10
9
  variant?: 'standard' | 'filled' | 'outlined';
@@ -18,7 +17,7 @@ declare function Alert(props: AlertProps): KTHTMLElement;
18
17
 
19
18
  interface ButtonProps {
20
19
  class?: string;
21
- style?: string;
20
+ style?: string | Partial<CSSStyleDeclaration>;
22
21
  children: string | HTMLElement | KTHTMLElement;
23
22
  variant?: 'contained' | 'outlined' | 'text';
24
23
  color?: 'primary' | 'secondary' | 'error' | 'warning' | 'info' | 'success';
@@ -117,8 +116,7 @@ declare function FormLabel(props: FormLabelProps): KTHTMLElement;
117
116
 
118
117
  interface LinearProgressProps {
119
118
  class?: string;
120
- style?: string;
121
- sx?: Record<string, any>;
119
+ style?: string | Partial<CSSStyleDeclaration>;
122
120
  variant?: 'determinate' | 'indeterminate';
123
121
  progress?: number;
124
122
  color?: 'primary' | 'secondary' | 'error' | 'warning' | 'info' | 'success';
@@ -140,7 +138,7 @@ type InputTypes = 'text' | 'password' | 'email' | 'number' | 'tel' | 'url';
140
138
 
141
139
  interface KTMuiTextFieldProps<T extends InputTypes> {
142
140
  class?: string;
143
- style?: string;
141
+ style?: string | Partial<CSSStyleDeclaration>;
144
142
  label?: string;
145
143
  placeholder?: string;
146
144
  value?: any;
@@ -216,8 +214,10 @@ type KTMuiTextField = KTHTMLElement & {
216
214
  declare function TextField<T extends InputTypes>(props: KTMuiTextFieldProps<T>): KTMuiTextField;
217
215
 
218
216
  interface KTMuiRadioProps {
217
+ class?: string;
218
+ style?: string | Partial<CSSStyleDeclaration>;
219
219
  value: string;
220
- text: string | KTHTMLElement | HTMLElement;
220
+ label: string | KTHTMLElement$1 | HTMLElement;
221
221
  checked?: boolean;
222
222
  size?: 'small' | 'medium';
223
223
  'kt:change'?: (checked: boolean, value: string) => void;
@@ -225,7 +225,19 @@ interface KTMuiRadioProps {
225
225
  color?: 'primary' | 'secondary' | 'default';
226
226
  }
227
227
 
228
- type KTMuiRadio = KTHTMLElement & {
228
+ interface KTMuiRadioGroupProps {
229
+ class?: string;
230
+ style?: string | Partial<CSSStyleDeclaration>;
231
+ value?: string;
232
+ name?: string;
233
+ size?: 'small' | 'medium';
234
+ options: KTMuiRadioProps[];
235
+ 'kt:change'?: ((value: string) => void) | KTRef<string>;
236
+ 'kt:click'?: (checked: boolean) => void;
237
+ row?: boolean;
238
+ }
239
+
240
+ type KTMuiRadio = KTHTMLElement$1 & {
229
241
  /**
230
242
  * The value of the radio button
231
243
  * @readonly
@@ -237,7 +249,7 @@ type KTMuiRadio = KTHTMLElement & {
237
249
  */
238
250
  checked: boolean;
239
251
  };
240
- type KTMuiRadioGroup = KTHTMLElement & {
252
+ type KTMuiRadioGroup = KTHTMLElement$1 & {
241
253
  /**
242
254
  * Reactive checked state of the radio button
243
255
  */
@@ -248,32 +260,21 @@ type KTMuiRadioGroup = KTHTMLElement & {
248
260
  * Radio component - mimics MUI Radio appearance and behavior
249
261
  */
250
262
  declare function Radio(props: KTMuiRadioProps): KTMuiRadio;
251
- interface RadioGroupProps {
252
- class?: string;
253
- style?: string;
254
- value?: string;
255
- name?: string;
256
- size?: 'small' | 'medium';
257
- options: KTMuiRadioProps[];
258
- 'kt:change'?: ((value: string) => void) | KTRef<string>;
259
- 'kt:click'?: (checked: boolean) => void;
260
- row?: boolean;
261
- }
262
263
  /**
263
264
  * RadioGroup component - groups multiple radios together
264
265
  */
265
- declare function RadioGroup(props: RadioGroupProps): KTMuiRadioGroup;
266
+ declare function RadioGroup(props: KTMuiRadioGroupProps): KTMuiRadioGroup;
266
267
 
267
- interface SelectOption {
268
+ interface KTMuiSelectOption {
268
269
  value: string;
269
270
  label: string;
270
271
  }
271
- interface SelectProps {
272
+ interface KTMuiSelectProps {
272
273
  class?: string;
273
- style?: string;
274
+ style?: string | Partial<CSSStyleDeclaration>;
274
275
  size?: 'small' | 'medium';
275
276
  value?: string;
276
- options: SelectOption[];
277
+ options: KTMuiSelectOption[];
277
278
  label?: string;
278
279
  placeholder?: string;
279
280
  'kt:change'?: (value: string) => void;
@@ -283,7 +284,7 @@ interface SelectProps {
283
284
  /**
284
285
  * Select component - mimics MUI Select appearance and behavior
285
286
  */
286
- declare function Select(props: SelectProps): JSX.Element;
287
+ declare function Select(props: KTMuiSelectProps): JSX.Element;
287
288
 
288
289
  declare function DownloadIcon(props: KTAttribute): JSX.Element;
289
290
 
@@ -330,4 +331,4 @@ declare function ContentCopyIcon(props: KTAttribute): JSX.Element;
330
331
  declare function SelectAllIcon(props: KTAttribute): JSX.Element;
331
332
 
332
333
  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 };
333
- export type { KTMuiDialog, KTMuiLinearProgress, KTMuiRadio, KTMuiRadioGroup, KTMuiRadioProps, KTMuiTextField, KTMuiTextFieldProps };
334
+ export type { KTMuiDialog, KTMuiLinearProgress, KTMuiRadio, KTMuiRadioGroup, KTMuiRadioProps, KTMuiSelectProps, KTMuiTextField, KTMuiTextFieldProps };
@@ -5,12 +5,12 @@ 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, 'kt:close': onClose, sx } = props;
8
+ const { children, style = '', severity = 'info', variant = 'standard', icon, 'kt:close': onClose } = 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
- let styleString = props.style || '';
12
- if (sx) {
13
- const sxStyles = Object.entries(sx)
11
+ let styleString = typeof style === 'string' ? style : '';
12
+ if (style && typeof style === 'object') {
13
+ const sxStyles = Object.entries(style)
14
14
  .map(([key, value]) => {
15
15
  // Convert camelCase to kebab-case
16
16
  const cssKey = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
@@ -44,7 +44,7 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
44
44
  return alert;
45
45
  }
46
46
 
47
- const emptyFn$1 = () => { };
47
+ const emptyFn = () => { };
48
48
  const generateHandler = (props, key) => {
49
49
  const handler = props[key];
50
50
  if (typeof handler === 'function') {
@@ -53,14 +53,30 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
53
53
  else if (handler && typeof handler === 'object' && handler.isKT) {
54
54
  return (value) => (handler.value = value);
55
55
  }
56
- return emptyFn$1;
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 '';
57
73
  };
58
74
 
59
75
  /**
60
76
  * Button component - mimics MUI Button appearance and behavior
61
77
  */
62
78
  function Button(props) {
63
- const { children, variant = 'text', color = 'primary', size = 'medium', disabled = false, fullWidth = false, iconOnly = false, startIcon, endIcon, type = 'button', 'on:click': onClick = emptyFn$1, } = 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;
64
80
  const classes = [
65
81
  'mui-button',
66
82
  `mui-button-${variant}`,
@@ -99,7 +115,7 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
99
115
  }
100
116
  onClick(e);
101
117
  };
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" })] }));
118
+ return (jsxRuntime.jsxs("button", { class: classes, style: parseStyle(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" })] }));
103
119
  }
104
120
 
105
121
  /**
@@ -253,7 +269,7 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
253
269
  * Only handles open/close state, title and content are passed as props
254
270
  */
255
271
  function Dialog(props) {
256
- let { open = false, 'kt:close': onClose = emptyFn$1, title, children, actions, maxWidth = 'sm', fullWidth = false, } = props;
272
+ let { open = false, 'kt:close': onClose = emptyFn, title, children, actions, maxWidth = 'sm', fullWidth = false, } = props;
257
273
  // Handle ESC key - store handler for cleanup
258
274
  const keyDownHandler = (e) => {
259
275
  if (e.key === 'Escape') {
@@ -405,25 +421,14 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
405
421
  * LinearProgress component - mimics MUI LinearProgress appearance and behavior
406
422
  */
407
423
  function LinearProgress(props) {
408
- let { variant = 'indeterminate', progress: value = 0, color = 'primary', sx } = props;
424
+ let { variant = 'indeterminate', progress: value = 0, color = 'primary' } = props;
409
425
  const classes = [
410
426
  'mui-linear-progress',
411
427
  `mui-linear-progress-${color}`,
412
428
  `mui-linear-progress-${variant}`,
413
429
  props.class ? props.class : '',
414
430
  ].join(' ');
415
- // Convert sx object to style string
416
- let styleString = props.style || '';
417
- if (sx) {
418
- const sxStyles = Object.entries(sx)
419
- .map(([key, value]) => {
420
- // Convert camelCase to kebab-case
421
- const cssKey = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
422
- return `${cssKey}: ${value}`;
423
- })
424
- .join('; ');
425
- styleString = styleString ? `${styleString}; ${sxStyles}` : sxStyles;
426
- }
431
+ const styleString = parseStyle(props.style);
427
432
  // Calculate progress percentage
428
433
  let progressValue = Math.min(Math.max(value, 0), 100);
429
434
  const barRef = ref();
@@ -506,7 +511,7 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
506
511
  : (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 }));
507
512
  const helperTextEl = jsxRuntime.jsx("p", { class: "mui-textfield-helper-text", children: helperText });
508
513
  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 && '*'] }) }) })] })));
509
- const container = (jsxRuntime.jsxs("div", { class: 'mui-textfield-root ' + (props.class ? props.class : ''), style: props.style ? props.style : '', children: [wrapperRef, helperTextEl] }));
514
+ const container = (jsxRuntime.jsxs("div", { class: 'mui-textfield-root ' + (props.class ? props.class : ''), style: parseStyle(props.style), children: [wrapperRef, helperTextEl] }));
510
515
  // Initialize classes
511
516
  setTimeout(() => updateContainerClass(), 0);
512
517
  Object.defineProperties(container, {
@@ -606,13 +611,13 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
606
611
  toggleIcon(checked);
607
612
  onChange(checked, value);
608
613
  };
609
- let { checked = false, value = '', text = '', size = 'small', disabled = false, color = 'primary' } = props;
614
+ let { checked = false, value = '', label: text = '', size = 'small', disabled = false, color = 'primary' } = props;
610
615
  const input = (jsxRuntime.jsx("input", { type: "radio", class: "mui-radio-input", checked: checked, value: value, disabled: disabled, "on:change": handleChange }));
611
616
  const uncheckedIcon = (jsxRuntime.jsx("span", { class: "mui-radio-icon-unchecked", children: jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", children: jsxRuntime.jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" }) }) }));
612
617
  const checkedIcon = (jsxRuntime.jsx("span", { class: "mui-radio-icon-checked", children: jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", children: jsxRuntime.jsx("path", { d: "M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" }) }) }));
613
618
  // initialize icon state
614
619
  toggleIcon(checked);
615
- const container = (jsxRuntime.jsxs("label", { class: `mui-radio-wrapper mui-radio-size-${size} ${disabled ? 'mui-radio-disabled' : ''} mui-radio-color-${color}`, children: [input, jsxRuntime.jsxs("span", { class: "mui-radio-icon", children: [uncheckedIcon, checkedIcon] }), jsxRuntime.jsx("span", { class: "mui-radio-label", children: text })] }));
620
+ const container = (jsxRuntime.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, jsxRuntime.jsxs("span", { class: "mui-radio-icon", children: [uncheckedIcon, checkedIcon] }), jsxRuntime.jsx("span", { class: "mui-radio-label", children: text })] }));
616
621
  Object.defineProperties(container, {
617
622
  value: {
618
623
  get() {
@@ -659,7 +664,7 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
659
664
  }
660
665
  return Radio(o);
661
666
  });
662
- const container = (jsxRuntime.jsx("div", { class: `mui-radio-group ${row ? 'mui-radio-group-row' : ''} ${props.class ?? ''}`, style: props.style ?? '', role: "radiogroup", children: radios }));
667
+ const container = (jsxRuntime.jsx("div", { class: `mui-radio-group ${row ? 'mui-radio-group-row' : ''} ${props.class ?? ''}`, style: parseStyle(props.style), role: "radiogroup", children: radios }));
663
668
  Object.defineProperties(container, {
664
669
  value: {
665
670
  get() {
@@ -674,12 +679,12 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
674
679
  return container;
675
680
  }
676
681
 
677
- const emptyFn = () => { };
678
682
  /**
679
683
  * Select component - mimics MUI Select appearance and behavior
680
684
  */
681
685
  function Select(props) {
682
- let { value = '', options = [], label = '', placeholder = '', size = 'medium', 'kt:change': onChange = emptyFn, fullWidth = false, disabled = false, } = props;
686
+ let { value = '', options = [], label = '', placeholder = '', size = 'medium', fullWidth = false, disabled = false, } = props;
687
+ const onChange = generateHandler(props, 'kt:change');
683
688
  let isOpen = false;
684
689
  let isFocused = false;
685
690
  const selectRef = kt_js.ref();
@@ -766,7 +771,7 @@ var __ktjs_mui__ = (function (exports, jsxRuntime, kt_js) {
766
771
  return (jsxRuntime.jsx("div", { class: "mui-select-menu", style: { display: 'none' }, children: options.map((option) => (jsxRuntime.jsx("div", { class: `mui-select-option ${option.value === value ? 'selected' : ''}`, "on:click": () => handleOptionClick(option.value), children: option.label }))) }));
767
772
  });
768
773
  // Create container
769
- const container = (jsxRuntime.jsxs("div", { ref: selectRef, class: `mui-select-wrapper mui-select-size-${size} ${props.class ? props.class : ''} ${fullWidth ? 'mui-select-fullWidth' : ''} ${disabled ? 'mui-select-disabled' : ''}`, style: props.style ? props.style : '', children: [label && jsxRuntime.jsx("label", { class: `mui-select-label ${value || isFocused ? 'focused' : ''}`, children: label }), jsxRuntime.jsxs("div", { class: "mui-select-control mui-select-outlined", "on:click": toggleMenu, "on:focus": handleFocus, "on:blur": handleBlur, tabIndex: disabled ? -1 : 0, children: [valueDisplay, jsxRuntime.jsx("input", { type: "hidden", value: value }), jsxRuntime.jsx("fieldset", { class: "mui-select-fieldset", children: jsxRuntime.jsx("legend", { children: jsxRuntime.jsx("span", { children: label }) }) }), jsxRuntime.jsx("svg", { class: "mui-select-icon", focusable: "false", "aria-hidden": "true", viewBox: "0 0 24 24", width: "24", height: "24", children: jsxRuntime.jsx("path", { d: "M7 10l5 5 5-5Z", fill: "currentColor" }) })] }), menu] }));
774
+ const container = (jsxRuntime.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: [label && jsxRuntime.jsx("label", { class: `mui-select-label ${value || isFocused ? 'focused' : ''}`, children: label }), jsxRuntime.jsxs("div", { class: "mui-select-control mui-select-outlined", "on:click": toggleMenu, "on:focus": handleFocus, "on:blur": handleBlur, tabIndex: disabled ? -1 : 0, children: [valueDisplay, jsxRuntime.jsx("input", { type: "hidden", value: value }), jsxRuntime.jsx("fieldset", { class: "mui-select-fieldset", children: jsxRuntime.jsx("legend", { children: jsxRuntime.jsx("span", { children: label }) }) }), jsxRuntime.jsx("svg", { class: "mui-select-icon", focusable: "false", "aria-hidden": "true", viewBox: "0 0 24 24", width: "24", height: "24", children: jsxRuntime.jsx("path", { d: "M7 10l5 5 5-5Z", fill: "currentColor" }) })] }), menu] }));
770
775
  // Add global click listener
771
776
  setTimeout(() => {
772
777
  document.removeEventListener('click', handleClickOutside);
package/dist/index.mjs CHANGED
@@ -5,12 +5,12 @@ import { ref as ref$1, createRedrawable as createRedrawable$1 } from '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, 'kt:close': onClose, sx } = props;
8
+ const { children, style = '', severity = 'info', variant = 'standard', icon, 'kt:close': onClose } = 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
- let styleString = props.style || '';
12
- if (sx) {
13
- const sxStyles = Object.entries(sx)
11
+ let styleString = typeof style === 'string' ? style : '';
12
+ if (style && typeof style === 'object') {
13
+ const sxStyles = Object.entries(style)
14
14
  .map(([key, value]) => {
15
15
  // Convert camelCase to kebab-case
16
16
  const cssKey = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
@@ -44,7 +44,7 @@ function Alert(props) {
44
44
  return alert;
45
45
  }
46
46
 
47
- const emptyFn$1 = () => { };
47
+ const emptyFn = () => { };
48
48
  const generateHandler = (props, key) => {
49
49
  const handler = props[key];
50
50
  if (typeof handler === 'function') {
@@ -53,14 +53,30 @@ const generateHandler = (props, key) => {
53
53
  else if (handler && typeof handler === 'object' && handler.isKT) {
54
54
  return (value) => (handler.value = value);
55
55
  }
56
- return emptyFn$1;
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 '';
57
73
  };
58
74
 
59
75
  /**
60
76
  * Button component - mimics MUI Button appearance and behavior
61
77
  */
62
78
  function Button(props) {
63
- const { children, variant = 'text', color = 'primary', size = 'medium', disabled = false, fullWidth = false, iconOnly = false, startIcon, endIcon, type = 'button', 'on:click': onClick = emptyFn$1, } = 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;
64
80
  const classes = [
65
81
  'mui-button',
66
82
  `mui-button-${variant}`,
@@ -99,7 +115,7 @@ function Button(props) {
99
115
  }
100
116
  onClick(e);
101
117
  };
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" })] }));
118
+ return (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 }), jsx("span", { class: "mui-button-ripple" })] }));
103
119
  }
104
120
 
105
121
  /**
@@ -253,7 +269,7 @@ function CheckboxGroup(props) {
253
269
  * Only handles open/close state, title and content are passed as props
254
270
  */
255
271
  function Dialog(props) {
256
- let { open = false, 'kt:close': onClose = emptyFn$1, title, children, actions, maxWidth = 'sm', fullWidth = false, } = props;
272
+ let { open = false, 'kt:close': onClose = emptyFn, title, children, actions, maxWidth = 'sm', fullWidth = false, } = props;
257
273
  // Handle ESC key - store handler for cleanup
258
274
  const keyDownHandler = (e) => {
259
275
  if (e.key === 'Escape') {
@@ -405,25 +421,14 @@ function createRedrawable(creator) {
405
421
  * LinearProgress component - mimics MUI LinearProgress appearance and behavior
406
422
  */
407
423
  function LinearProgress(props) {
408
- let { variant = 'indeterminate', progress: value = 0, color = 'primary', sx } = props;
424
+ let { variant = 'indeterminate', progress: value = 0, color = 'primary' } = props;
409
425
  const classes = [
410
426
  'mui-linear-progress',
411
427
  `mui-linear-progress-${color}`,
412
428
  `mui-linear-progress-${variant}`,
413
429
  props.class ? props.class : '',
414
430
  ].join(' ');
415
- // Convert sx object to style string
416
- let styleString = props.style || '';
417
- if (sx) {
418
- const sxStyles = Object.entries(sx)
419
- .map(([key, value]) => {
420
- // Convert camelCase to kebab-case
421
- const cssKey = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
422
- return `${cssKey}: ${value}`;
423
- })
424
- .join('; ');
425
- styleString = styleString ? `${styleString}; ${sxStyles}` : sxStyles;
426
- }
431
+ const styleString = parseStyle(props.style);
427
432
  // Calculate progress percentage
428
433
  let progressValue = Math.min(Math.max(value, 0), 100);
429
434
  const barRef = ref();
@@ -506,7 +511,7 @@ function TextField(props) {
506
511
  : (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 }));
507
512
  const helperTextEl = jsx("p", { class: "mui-textfield-helper-text", children: helperText });
508
513
  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 && '*'] }) }) })] })));
509
- const container = (jsxs("div", { class: 'mui-textfield-root ' + (props.class ? props.class : ''), style: props.style ? props.style : '', children: [wrapperRef, helperTextEl] }));
514
+ const container = (jsxs("div", { class: 'mui-textfield-root ' + (props.class ? props.class : ''), style: parseStyle(props.style), children: [wrapperRef, helperTextEl] }));
510
515
  // Initialize classes
511
516
  setTimeout(() => updateContainerClass(), 0);
512
517
  Object.defineProperties(container, {
@@ -606,13 +611,13 @@ function Radio(props) {
606
611
  toggleIcon(checked);
607
612
  onChange(checked, value);
608
613
  };
609
- let { checked = false, value = '', text = '', size = 'small', disabled = false, color = 'primary' } = props;
614
+ let { checked = false, value = '', label: text = '', size = 'small', disabled = false, color = 'primary' } = props;
610
615
  const input = (jsx("input", { type: "radio", class: "mui-radio-input", checked: checked, value: value, disabled: disabled, "on:change": handleChange }));
611
616
  const uncheckedIcon = (jsx("span", { class: "mui-radio-icon-unchecked", children: jsx("svg", { viewBox: "0 0 24 24", children: jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" }) }) }));
612
617
  const checkedIcon = (jsx("span", { class: "mui-radio-icon-checked", children: jsx("svg", { viewBox: "0 0 24 24", children: jsx("path", { d: "M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" }) }) }));
613
618
  // initialize icon state
614
619
  toggleIcon(checked);
615
- const container = (jsxs("label", { class: `mui-radio-wrapper mui-radio-size-${size} ${disabled ? 'mui-radio-disabled' : ''} mui-radio-color-${color}`, children: [input, jsxs("span", { class: "mui-radio-icon", children: [uncheckedIcon, checkedIcon] }), jsx("span", { class: "mui-radio-label", children: text })] }));
620
+ 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 })] }));
616
621
  Object.defineProperties(container, {
617
622
  value: {
618
623
  get() {
@@ -659,7 +664,7 @@ function RadioGroup(props) {
659
664
  }
660
665
  return Radio(o);
661
666
  });
662
- const container = (jsx("div", { class: `mui-radio-group ${row ? 'mui-radio-group-row' : ''} ${props.class ?? ''}`, style: props.style ?? '', role: "radiogroup", children: radios }));
667
+ const container = (jsx("div", { class: `mui-radio-group ${row ? 'mui-radio-group-row' : ''} ${props.class ?? ''}`, style: parseStyle(props.style), role: "radiogroup", children: radios }));
663
668
  Object.defineProperties(container, {
664
669
  value: {
665
670
  get() {
@@ -674,12 +679,12 @@ function RadioGroup(props) {
674
679
  return container;
675
680
  }
676
681
 
677
- const emptyFn = () => { };
678
682
  /**
679
683
  * Select component - mimics MUI Select appearance and behavior
680
684
  */
681
685
  function Select(props) {
682
- let { value = '', options = [], label = '', placeholder = '', size = 'medium', 'kt:change': onChange = emptyFn, fullWidth = false, disabled = false, } = props;
686
+ let { value = '', options = [], label = '', placeholder = '', size = 'medium', fullWidth = false, disabled = false, } = props;
687
+ const onChange = generateHandler(props, 'kt:change');
683
688
  let isOpen = false;
684
689
  let isFocused = false;
685
690
  const selectRef = ref$1();
@@ -766,7 +771,7 @@ function Select(props) {
766
771
  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 }))) }));
767
772
  });
768
773
  // Create container
769
- const container = (jsxs("div", { ref: selectRef, class: `mui-select-wrapper mui-select-size-${size} ${props.class ? props.class : ''} ${fullWidth ? 'mui-select-fullWidth' : ''} ${disabled ? 'mui-select-disabled' : ''}`, style: props.style ? props.style : '', children: [label && jsx("label", { 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] }));
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: [label && jsx("label", { 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] }));
770
775
  // Add global click listener
771
776
  setTimeout(() => {
772
777
  document.removeEventListener('click', handleClickOutside);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ktjs/mui",
3
- "version": "0.18.5",
3
+ "version": "0.18.8",
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.6"
38
+ "@ktjs/core": "0.18.10"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "rollup -c rollup.config.mjs",