@mhome/ui 0.1.5 → 0.1.6
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.cjs.js +2 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +2 -2
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/date-picker.jsx +5 -5
- package/src/components/dialog.jsx +5 -65
- package/src/components/icon-button.jsx +2 -1
- package/src/components/select.jsx +10 -3
- package/src/components/tabs.jsx +2 -2
- package/src/components/text-field.jsx +1 -1
- package/src/components/typography.jsx +2 -1
package/package.json
CHANGED
|
@@ -26,6 +26,8 @@ const DatePicker = React.forwardRef(
|
|
|
26
26
|
const inputRef = React.useRef(null);
|
|
27
27
|
const yearPickerRef = React.useRef(null);
|
|
28
28
|
const currentYearButtonRef = React.useRef(null);
|
|
29
|
+
const [viewMode, setViewMode] = React.useState("month"); // "month" or "year"
|
|
30
|
+
const [showYearPicker, setShowYearPicker] = React.useState(false);
|
|
29
31
|
|
|
30
32
|
React.useImperativeHandle(ref, () => inputRef.current);
|
|
31
33
|
|
|
@@ -52,7 +54,7 @@ const DatePicker = React.forwardRef(
|
|
|
52
54
|
}
|
|
53
55
|
};
|
|
54
56
|
|
|
55
|
-
const handleClickOutside = (event) => {
|
|
57
|
+
const handleClickOutside = React.useCallback((event) => {
|
|
56
58
|
if (
|
|
57
59
|
calendarRef.current &&
|
|
58
60
|
!calendarRef.current.contains(event.target) &&
|
|
@@ -65,7 +67,7 @@ const DatePicker = React.forwardRef(
|
|
|
65
67
|
onOpenChange(false);
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
|
-
};
|
|
70
|
+
}, [onOpenChange]);
|
|
69
71
|
|
|
70
72
|
React.useEffect(() => {
|
|
71
73
|
if (open) {
|
|
@@ -74,12 +76,10 @@ const DatePicker = React.forwardRef(
|
|
|
74
76
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
75
77
|
};
|
|
76
78
|
}
|
|
77
|
-
}, [open]);
|
|
79
|
+
}, [open, handleClickOutside]);
|
|
78
80
|
|
|
79
81
|
const textFieldProps = slotProps?.textField || {};
|
|
80
82
|
const displayValue = selectedDate ? selectedDate.format("YYYY-MM-DD") : "";
|
|
81
|
-
const [viewMode, setViewMode] = React.useState("month"); // "month" or "year"
|
|
82
|
-
const [showYearPicker, setShowYearPicker] = React.useState(false);
|
|
83
83
|
|
|
84
84
|
// Scroll to current year when year picker opens
|
|
85
85
|
React.useEffect(() => {
|
|
@@ -363,17 +363,7 @@ DialogFooter.displayName = "DialogFooter";
|
|
|
363
363
|
|
|
364
364
|
const DialogTitle = React.forwardRef(
|
|
365
365
|
({ className, style, sx, ...props }, ref) => {
|
|
366
|
-
|
|
367
|
-
const backgroundType = useRecoilValue(backgroundTypeState);
|
|
368
|
-
const bgColor = getBackground(backgroundType, actualMode === "dark");
|
|
369
|
-
const isGradient =
|
|
370
|
-
bgColor &&
|
|
371
|
-
typeof bgColor === "string" &&
|
|
372
|
-
(bgColor.startsWith("linear-gradient") ||
|
|
373
|
-
bgColor.startsWith("radial-gradient") ||
|
|
374
|
-
bgColor.startsWith("conic-gradient"));
|
|
375
|
-
|
|
376
|
-
// Check if DialogTitle is inside DialogHeader
|
|
366
|
+
// Check if DialogTitle is inside DialogHeader (DialogHeader already has padding)
|
|
377
367
|
const isInsideDialogHeader = React.useContext(DialogHeaderContext);
|
|
378
368
|
|
|
379
369
|
// Convert sx prop to style if provided, handling MUI spacing
|
|
@@ -456,42 +446,6 @@ const DialogTitle = React.forwardRef(
|
|
|
456
446
|
return converted;
|
|
457
447
|
}, [sx]);
|
|
458
448
|
|
|
459
|
-
// Extract padding from style to allow override
|
|
460
|
-
const {
|
|
461
|
-
padding,
|
|
462
|
-
paddingTop,
|
|
463
|
-
paddingBottom,
|
|
464
|
-
paddingLeft,
|
|
465
|
-
paddingRight,
|
|
466
|
-
backgroundColor,
|
|
467
|
-
...restStyle
|
|
468
|
-
} = style || {};
|
|
469
|
-
|
|
470
|
-
// Check if padding is explicitly set in style, sxStyles, or className
|
|
471
|
-
// Check for padding-related Tailwind classes in className
|
|
472
|
-
const hasPaddingInClassName = className && (
|
|
473
|
-
/\b(p|px|py|pt|pb|pl|pr)-\d+/.test(className) ||
|
|
474
|
-
/\bpadding/.test(className)
|
|
475
|
-
);
|
|
476
|
-
|
|
477
|
-
const hasAnyPadding =
|
|
478
|
-
padding !== undefined ||
|
|
479
|
-
paddingTop !== undefined ||
|
|
480
|
-
paddingBottom !== undefined ||
|
|
481
|
-
paddingLeft !== undefined ||
|
|
482
|
-
paddingRight !== undefined ||
|
|
483
|
-
sxStyles.padding !== undefined ||
|
|
484
|
-
sxStyles.paddingTop !== undefined ||
|
|
485
|
-
sxStyles.paddingBottom !== undefined ||
|
|
486
|
-
sxStyles.paddingLeft !== undefined ||
|
|
487
|
-
sxStyles.paddingRight !== undefined ||
|
|
488
|
-
hasPaddingInClassName;
|
|
489
|
-
|
|
490
|
-
// DialogTitle should have default padding when used standalone (not inside DialogHeader)
|
|
491
|
-
// When inside DialogHeader, DialogHeader provides px-6 pt-6, so DialogTitle doesn't need padding
|
|
492
|
-
// When used standalone, DialogTitle should have px-6 pt-6 to match DialogHeader's padding
|
|
493
|
-
const defaultPaddingClass = !isInsideDialogHeader && !hasAnyPadding ? "px-6 pt-6" : "";
|
|
494
|
-
|
|
495
449
|
return (
|
|
496
450
|
<h2
|
|
497
451
|
ref={ref}
|
|
@@ -499,28 +453,14 @@ const DialogTitle = React.forwardRef(
|
|
|
499
453
|
"rounded-t-[inherit]",
|
|
500
454
|
"text-lg font-semibold leading-none tracking-tight",
|
|
501
455
|
"text-foreground",
|
|
502
|
-
"text-left",
|
|
503
|
-
|
|
456
|
+
"text-left",
|
|
457
|
+
!isInsideDialogHeader && "px-6 pt-6", // Default padding only when not inside DialogHeader
|
|
504
458
|
className
|
|
505
459
|
)}
|
|
506
460
|
style={{
|
|
507
|
-
|
|
508
|
-
...(backgroundColor !== undefined
|
|
509
|
-
? backgroundColor.startsWith("linear-gradient") ||
|
|
510
|
-
backgroundColor.startsWith("radial-gradient") ||
|
|
511
|
-
backgroundColor.startsWith("conic-gradient")
|
|
512
|
-
? { background: backgroundColor }
|
|
513
|
-
: { backgroundColor }
|
|
514
|
-
: {}),
|
|
515
|
-
// Allow padding override via style prop (for standalone use)
|
|
516
|
-
padding: padding,
|
|
517
|
-
paddingLeft: paddingLeft,
|
|
518
|
-
paddingRight: paddingRight,
|
|
519
|
-
paddingTop: paddingTop,
|
|
520
|
-
paddingBottom: paddingBottom,
|
|
521
|
-
textAlign: "left", // Ensure left alignment
|
|
461
|
+
textAlign: "left",
|
|
522
462
|
...sxStyles,
|
|
523
|
-
...
|
|
463
|
+
...style,
|
|
524
464
|
}}
|
|
525
465
|
{...props}
|
|
526
466
|
/>
|
|
@@ -70,8 +70,9 @@ const IconButton = React.forwardRef(
|
|
|
70
70
|
}, [children, size]);
|
|
71
71
|
|
|
72
72
|
// Warn if no aria-label is provided (accessibility best practice)
|
|
73
|
+
// Only warn in development mode
|
|
73
74
|
React.useEffect(() => {
|
|
74
|
-
if (!ariaLabel && !props["aria-labelledby"]) {
|
|
75
|
+
if (process.env.NODE_ENV === "development" && !ariaLabel && !props["aria-labelledby"]) {
|
|
75
76
|
console.warn(
|
|
76
77
|
"IconButton: Missing aria-label or aria-labelledby. Icon-only buttons should have accessible labels."
|
|
77
78
|
);
|
|
@@ -28,6 +28,8 @@ const Select = React.forwardRef(
|
|
|
28
28
|
multiple = false,
|
|
29
29
|
sx,
|
|
30
30
|
style,
|
|
31
|
+
menuStyle, // Style for the dropdown menu (the open listbox)
|
|
32
|
+
menuClassName, // ClassName for the dropdown menu
|
|
31
33
|
...props
|
|
32
34
|
},
|
|
33
35
|
ref
|
|
@@ -154,7 +156,7 @@ const Select = React.forwardRef(
|
|
|
154
156
|
paddingRight: endAdornment ? "8px" : "14px",
|
|
155
157
|
paddingTop: "6px",
|
|
156
158
|
paddingBottom: "6px",
|
|
157
|
-
// If borderRadius is provided in props.style, use it; otherwise let Tailwind
|
|
159
|
+
// If borderRadius is provided in props.style, use it; otherwise let Tailwind classes handle it
|
|
158
160
|
...(style?.borderRadius !== undefined
|
|
159
161
|
? { borderRadius: style.borderRadius }
|
|
160
162
|
: {}),
|
|
@@ -194,16 +196,21 @@ const Select = React.forwardRef(
|
|
|
194
196
|
id={`${selectId}-listbox`}
|
|
195
197
|
role="listbox"
|
|
196
198
|
aria-label={label || "Options"}
|
|
197
|
-
className=
|
|
199
|
+
className={cn(
|
|
200
|
+
"absolute z-50 w-full mt-1 shadow-lg",
|
|
201
|
+
menuClassName
|
|
202
|
+
)}
|
|
198
203
|
style={{
|
|
199
204
|
backgroundColor: "hsl(var(--card))",
|
|
200
205
|
boxShadow: isDark
|
|
201
|
-
? "0px 4px 12px rgba(0, 0, 0, 0.4)
|
|
206
|
+
? "0px 4px 12px rgba(0, 0, 0, 0.4)"
|
|
202
207
|
: "0px 4px 12px rgba(0, 0, 0, 0.15)",
|
|
203
208
|
border: isDark
|
|
204
209
|
? "1px solid rgba(255, 255, 255, 0.1)"
|
|
205
210
|
: "1px solid hsl(var(--border))",
|
|
206
211
|
borderRadius: "8px",
|
|
212
|
+
overflow: "hidden",
|
|
213
|
+
...menuStyle,
|
|
207
214
|
}}
|
|
208
215
|
>
|
|
209
216
|
{React.Children.map(children, (child) => {
|
package/src/components/tabs.jsx
CHANGED
|
@@ -218,7 +218,7 @@ const Tab = React.forwardRef(
|
|
|
218
218
|
}
|
|
219
219
|
}}
|
|
220
220
|
className={cn(
|
|
221
|
-
"cursor-pointer transition-all duration-200 text-sm border-none bg-transparent focus:outline-none
|
|
221
|
+
"cursor-pointer transition-all duration-200 text-sm border-none bg-transparent focus:outline-none",
|
|
222
222
|
defaultPaddingClass,
|
|
223
223
|
"min-w-[72px] min-h-[48px] flex-1",
|
|
224
224
|
selected ? "font-semibold" : "font-medium",
|
|
@@ -320,7 +320,7 @@ const Tab = React.forwardRef(
|
|
|
320
320
|
}
|
|
321
321
|
}}
|
|
322
322
|
className={cn(
|
|
323
|
-
"cursor-pointer transition-all duration-200 min-h-[32px] min-w-[100px] rounded-2xl text-sm border-none focus:outline-none
|
|
323
|
+
"cursor-pointer transition-all duration-200 min-h-[32px] min-w-[100px] rounded-2xl text-sm border-none focus:outline-none",
|
|
324
324
|
defaultPaddingClass,
|
|
325
325
|
defaultMarginClass,
|
|
326
326
|
selected ? "font-semibold" : "font-medium",
|
|
@@ -46,7 +46,7 @@ const typographyVariants = cva("", {
|
|
|
46
46
|
|
|
47
47
|
const Typography = React.forwardRef(
|
|
48
48
|
(
|
|
49
|
-
{ className, variant = "body1", component, style, color, noWrap, ...props },
|
|
49
|
+
{ className, variant = "body1", component, style, color, noWrap, gutterBottom, ...props },
|
|
50
50
|
ref
|
|
51
51
|
) => {
|
|
52
52
|
// Map MUI color props to shadcn colors
|
|
@@ -68,6 +68,7 @@ const Typography = React.forwardRef(
|
|
|
68
68
|
)}
|
|
69
69
|
style={{
|
|
70
70
|
...(noWrap && { whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }),
|
|
71
|
+
...(gutterBottom && { marginBottom: "0.35em" }),
|
|
71
72
|
...style,
|
|
72
73
|
}}
|
|
73
74
|
{...props}
|