@mhome/ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +188 -0
  2. package/dist/index.cjs.js +9 -0
  3. package/dist/index.cjs.js.map +1 -0
  4. package/dist/index.css +2 -0
  5. package/dist/index.esm.js +9 -0
  6. package/dist/index.esm.js.map +1 -0
  7. package/package.json +54 -0
  8. package/src/common/adaptive-theme-provider.js +19 -0
  9. package/src/components/accordion.jsx +306 -0
  10. package/src/components/alert.jsx +137 -0
  11. package/src/components/app-bar.jsx +105 -0
  12. package/src/components/autocomplete.jsx +347 -0
  13. package/src/components/avatar.jsx +160 -0
  14. package/src/components/box.jsx +165 -0
  15. package/src/components/button.jsx +104 -0
  16. package/src/components/card.jsx +156 -0
  17. package/src/components/checkbox.jsx +63 -0
  18. package/src/components/chip.jsx +137 -0
  19. package/src/components/collapse.jsx +188 -0
  20. package/src/components/container.jsx +67 -0
  21. package/src/components/date-picker.jsx +528 -0
  22. package/src/components/dialog-content-text.jsx +27 -0
  23. package/src/components/dialog.jsx +584 -0
  24. package/src/components/divider.jsx +192 -0
  25. package/src/components/drawer.jsx +255 -0
  26. package/src/components/form-control-label.jsx +89 -0
  27. package/src/components/form-group.jsx +32 -0
  28. package/src/components/form-label.jsx +54 -0
  29. package/src/components/grid.jsx +135 -0
  30. package/src/components/icon-button.jsx +101 -0
  31. package/src/components/index.js +78 -0
  32. package/src/components/input-adornment.jsx +43 -0
  33. package/src/components/input-label.jsx +55 -0
  34. package/src/components/list.jsx +239 -0
  35. package/src/components/menu.jsx +370 -0
  36. package/src/components/paper.jsx +173 -0
  37. package/src/components/radio-group.jsx +76 -0
  38. package/src/components/radio.jsx +108 -0
  39. package/src/components/select.jsx +308 -0
  40. package/src/components/slider.jsx +382 -0
  41. package/src/components/stack.jsx +110 -0
  42. package/src/components/table.jsx +243 -0
  43. package/src/components/tabs.jsx +363 -0
  44. package/src/components/text-field.jsx +289 -0
  45. package/src/components/toggle-button.jsx +209 -0
  46. package/src/components/toolbar.jsx +48 -0
  47. package/src/components/tooltip.jsx +127 -0
  48. package/src/components/typography.jsx +77 -0
  49. package/src/global-state.js +29 -0
  50. package/src/index.css +110 -0
  51. package/src/index.js +6 -0
  52. package/src/lib/useMediaQuery.js +37 -0
  53. package/src/lib/utils.js +113 -0
@@ -0,0 +1,77 @@
1
+ import * as React from "react";
2
+ import { cva } from "class-variance-authority";
3
+ import { cn } from "../lib/utils";
4
+
5
+ const typographyVariants = cva("", {
6
+ variants: {
7
+ variant: {
8
+ h1: "scroll-m-20 text-4xl font-extralight tracking-tight lg:text-5xl",
9
+ h2: "scroll-m-20 border-b pb-2 text-3xl font-semibold tracking-tight first:mt-0",
10
+ h3: "scroll-m-20 text-2xl font-semibold tracking-tight",
11
+ h4: "scroll-m-20 text-xl font-semibold tracking-tight",
12
+ h5: "scroll-m-20 text-lg font-semibold tracking-tight",
13
+ h6: "scroll-m-20 text-base font-semibold tracking-tight",
14
+ p: "leading-7 [&:not(:first-child)]:mt-6",
15
+ blockquote: "mt-6 border-l-2 pl-6 italic",
16
+ list: "my-6 ml-6 list-disc [&>li]:mt-2",
17
+ inlineCode:
18
+ "relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold",
19
+ lead: "text-xl text-muted-foreground",
20
+ largeText: "text-lg font-semibold",
21
+ smallText: "text-sm font-medium leading-none",
22
+ mutedText: "text-sm text-muted-foreground",
23
+ // MUI compatibility variants
24
+ body1: "text-base leading-normal",
25
+ body2: "text-sm leading-normal",
26
+ subtitle1: "text-base font-normal leading-normal",
27
+ subtitle2: "text-sm font-medium leading-normal",
28
+ caption: "text-xs leading-normal",
29
+ overline: "text-xs font-normal uppercase leading-normal tracking-wide",
30
+ },
31
+ color: {
32
+ default: "text-foreground",
33
+ primary: "text-primary",
34
+ secondary: "text-secondary-foreground",
35
+ muted: "text-muted-foreground",
36
+ destructive: "text-destructive",
37
+ error: "text-destructive",
38
+ inherit: "text-inherit",
39
+ },
40
+ },
41
+ defaultVariants: {
42
+ variant: "body1",
43
+ color: "default",
44
+ },
45
+ });
46
+
47
+ const Typography = React.forwardRef(
48
+ (
49
+ { className, variant = "body1", component, style, color, ...props },
50
+ ref
51
+ ) => {
52
+ // Map MUI color props to shadcn colors
53
+ const mappedColor =
54
+ color === "text.secondary" || color === "textSecondary"
55
+ ? "muted"
56
+ : color === "text.primary" || color === "textPrimary"
57
+ ? "default"
58
+ : color;
59
+
60
+ const Component = component || (variant.startsWith("h") ? variant : "p");
61
+
62
+ return (
63
+ <Component
64
+ ref={ref}
65
+ className={cn(
66
+ typographyVariants({ variant, color: mappedColor }),
67
+ className
68
+ )}
69
+ style={style}
70
+ {...props}
71
+ />
72
+ );
73
+ }
74
+ );
75
+ Typography.displayName = "Typography";
76
+
77
+ export { Typography, typographyVariants };
@@ -0,0 +1,29 @@
1
+ // Simplified version for examples project
2
+ // In the real project, this would use Recoil for state management
3
+ // For examples, we'll use a simple React context or just return default values
4
+
5
+ import React from "react";
6
+
7
+ // Create a simple context for background type
8
+ const BackgroundTypeContext = React.createContext("solid");
9
+
10
+ export const BackgroundTypeProvider = ({ children, value = "solid" }) => {
11
+ return (
12
+ <BackgroundTypeContext.Provider value={value}>
13
+ {children}
14
+ </BackgroundTypeContext.Provider>
15
+ );
16
+ };
17
+
18
+ // Mock Recoil atom for background type
19
+ export const backgroundTypeState = {
20
+ key: "backgroundType",
21
+ default: "solid",
22
+ };
23
+
24
+ // Mock useRecoilValue hook
25
+ export const useRecoilValue = (atom) => {
26
+ const context = React.useContext(BackgroundTypeContext);
27
+ return context || atom.default || "solid";
28
+ };
29
+
package/src/index.css ADDED
@@ -0,0 +1,110 @@
1
+ /* Tailwind CSS will be imported here */
2
+ @tailwind base;
3
+ @tailwind components;
4
+ @tailwind utilities;
5
+
6
+ @layer base {
7
+ :root {
8
+ --background: 0 0% 100%;
9
+ --foreground: 222.2 84% 4.9%;
10
+ --card: 0 0% 100%;
11
+ --card-foreground: 222.2 84% 4.9%;
12
+ --popover: 0 0% 100%;
13
+ --popover-foreground: 222.2 84% 4.9%;
14
+ --primary: 221.2 83.2% 53.3%;
15
+ --primary-foreground: 210 40% 98%;
16
+ --secondary: 210 40% 96.1%;
17
+ --secondary-foreground: 222.2 47.4% 11.2%;
18
+ --muted: 210 40% 96.1%;
19
+ --muted-foreground: 215.4 16.3% 46.9%;
20
+ --accent: 210 40% 96.1%;
21
+ --accent-foreground: 222.2 47.4% 11.2%;
22
+ --destructive: 0 84.2% 60.2%;
23
+ --destructive-foreground: 210 40% 98%;
24
+ --success: 142.1 76.2% 36.3%;
25
+ --success-foreground: 210 40% 98%;
26
+ --warning: 38.9 92% 50%;
27
+ --warning-foreground: 210 40% 98%;
28
+ --info: 199.1 89.1% 48.2%;
29
+ --info-foreground: 210 40% 98%;
30
+ --border: 214.3 31.8% 91.4%;
31
+ --input: 214.3 31.8% 91.4%;
32
+ --ring: 222.2 84% 4.9%;
33
+ --radius: 0.5rem;
34
+
35
+ /* Z-index variables */
36
+ --z-index-mobile-stepper: 1000;
37
+ --z-index-fab: 1050;
38
+ --z-index-speed-dial: 1050;
39
+ --z-index-app-bar: 1100;
40
+ --z-index-drawer: 1200;
41
+ --z-index-modal: 1300;
42
+ --z-index-snackbar: 1400;
43
+ --z-index-tooltip: 1500;
44
+ --z-index-automation-drawer: 1200;
45
+ --z-index-automation-input: 1300;
46
+ --z-index-important-toast: 1400;
47
+ --z-index-dashboard-input: 1300;
48
+ --z-index-dashboard-drag: 1300;
49
+ --z-index-snackbar-input: 1400;
50
+
51
+ /* Background level colors (simplified) */
52
+ --color-background-logo1: #ffffff;
53
+ --color-background-logo2: #000000;
54
+ --color-background-l0: hsl(var(--background));
55
+ --color-background-l1: hsl(var(--card));
56
+ --color-background-l2: hsl(var(--muted));
57
+ --color-background-l3: hsl(var(--accent));
58
+ --color-background-l4: hsl(var(--muted));
59
+ --color-background-l5: hsl(var(--muted));
60
+ --color-background-l6: hsl(var(--muted));
61
+ --color-background-c0: hsl(var(--background));
62
+ --color-background-c1: hsl(var(--card));
63
+ --color-background-c2: hsl(var(--muted));
64
+ --color-background-c3: hsl(var(--accent));
65
+ }
66
+
67
+ .dark {
68
+ --background: 222.2 84% 4.9%;
69
+ --foreground: 210 40% 98%;
70
+ --card: 222.2 84% 4.9%;
71
+ --card-foreground: 210 40% 98%;
72
+ --popover: 222.2 84% 4.9%;
73
+ --popover-foreground: 210 40% 98%;
74
+ --primary: 221.2 83.2% 53.3%;
75
+ --primary-foreground: 210 40% 98%;
76
+ --secondary: 217.2 32.6% 17.5%;
77
+ --secondary-foreground: 210 40% 98%;
78
+ --muted: 217.2 32.6% 17.5%;
79
+ --muted-foreground: 215 20.2% 65.1%;
80
+ --accent: 217.2 32.6% 17.5%;
81
+ --accent-foreground: 210 40% 98%;
82
+ --destructive: 0 62.8% 30.6%;
83
+ --destructive-foreground: 210 40% 98%;
84
+ --success: 142.1 70.6% 45.3%;
85
+ --success-foreground: 210 40% 98%;
86
+ --warning: 38.9 92% 50%;
87
+ --warning-foreground: 210 40% 98%;
88
+ --info: 199.1 89.1% 48.2%;
89
+ --info-foreground: 210 40% 98%;
90
+ --border: 217.2 32.6% 17.5%;
91
+ --input: 217.2 32.6% 17.5%;
92
+ --ring: 212.7 26.8% 83.9%;
93
+
94
+ /* Background level colors for dark mode */
95
+ --color-background-logo1: #000000;
96
+ --color-background-logo2: #ffffff;
97
+ --color-background-l0: hsl(var(--background));
98
+ --color-background-l1: hsl(var(--card));
99
+ --color-background-l2: hsl(var(--muted));
100
+ --color-background-l3: hsl(var(--accent));
101
+ --color-background-l4: hsl(var(--muted));
102
+ --color-background-l5: hsl(var(--muted));
103
+ --color-background-l6: hsl(var(--muted));
104
+ --color-background-c0: hsl(var(--background));
105
+ --color-background-c1: hsl(var(--card));
106
+ --color-background-c2: hsl(var(--muted));
107
+ --color-background-c3: hsl(var(--accent));
108
+ }
109
+ }
110
+
package/src/index.js ADDED
@@ -0,0 +1,6 @@
1
+ // Import CSS
2
+ import "./index.css";
3
+
4
+ // Export all components
5
+ export * from "./components";
6
+
@@ -0,0 +1,37 @@
1
+ import { useState, useEffect } from "react";
2
+
3
+ // Simplified useMediaQuery hook to replace @mui/material's useMediaQuery
4
+ export const useMediaQuery = (query) => {
5
+ const [matches, setMatches] = useState(false);
6
+
7
+ useEffect(() => {
8
+ // Extract media query from MUI format or use directly
9
+ let mediaQueryString = query;
10
+
11
+ // Handle MUI format: "@media (max-width:599px)"
12
+ if (query.startsWith("@media")) {
13
+ mediaQueryString = query.replace("@media", "").trim();
14
+ }
15
+
16
+ const mediaQuery = window.matchMedia(mediaQueryString);
17
+
18
+ // Set initial value
19
+ setMatches(mediaQuery.matches);
20
+
21
+ // Create event listener
22
+ const handler = (event) => {
23
+ setMatches(event.matches);
24
+ };
25
+
26
+ // Add listener
27
+ mediaQuery.addEventListener("change", handler);
28
+
29
+ // Cleanup
30
+ return () => {
31
+ mediaQuery.removeEventListener("change", handler);
32
+ };
33
+ }, [query]);
34
+
35
+ return matches;
36
+ };
37
+
@@ -0,0 +1,113 @@
1
+ import React from "react";
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+
5
+ export function cn(...inputs) {
6
+ return twMerge(clsx(inputs));
7
+ }
8
+
9
+ // Convert MUI spacing unit to pixels (MUI spacing unit = 8px)
10
+ export function spacingToPx(value) {
11
+ if (typeof value === "number") {
12
+ return `${value * 8}px`;
13
+ }
14
+ return value;
15
+ }
16
+
17
+ // Helper function to convert MUI sx prop to style object
18
+ export const convertSxToStyle = (sx) => {
19
+ if (!sx) return {};
20
+ const style = {};
21
+ for (const key in sx) {
22
+ if (Object.prototype.hasOwnProperty.call(sx, key)) {
23
+ const value = sx[key];
24
+ // Handle spacing values
25
+ if (
26
+ typeof value === "number" &&
27
+ [
28
+ "p",
29
+ "px",
30
+ "py",
31
+ "pt",
32
+ "pb",
33
+ "pl",
34
+ "pr",
35
+ "m",
36
+ "mx",
37
+ "my",
38
+ "mt",
39
+ "mb",
40
+ "ml",
41
+ "mr",
42
+ "gap",
43
+ ].includes(key)
44
+ ) {
45
+ const cssProp = {
46
+ p: "padding",
47
+ px: ["paddingLeft", "paddingRight"],
48
+ py: ["paddingTop", "paddingBottom"],
49
+ pt: "paddingTop",
50
+ pb: "paddingBottom",
51
+ pl: "paddingLeft",
52
+ pr: "paddingRight",
53
+ m: "margin",
54
+ mx: ["marginLeft", "marginRight"],
55
+ my: ["marginTop", "marginBottom"],
56
+ mt: "marginTop",
57
+ mb: "marginBottom",
58
+ ml: "marginLeft",
59
+ mr: "marginRight",
60
+ gap: "gap",
61
+ }[key];
62
+
63
+ if (Array.isArray(cssProp)) {
64
+ cssProp.forEach((prop) => (style[prop] = spacingToPx(value)));
65
+ } else {
66
+ style[cssProp] = spacingToPx(value);
67
+ }
68
+ } else if (key === "bgcolor") {
69
+ // Handle bgcolor - convert theme paths to CSS variables
70
+ if (typeof value === "string" && value.includes(".")) {
71
+ const bgcolorMap = {
72
+ "background.paper": "hsl(var(--card))",
73
+ "background.default": "hsl(var(--background))",
74
+ "background.card": "hsl(var(--card))",
75
+ };
76
+ style.backgroundColor = bgcolorMap[value] || value;
77
+ } else {
78
+ style.backgroundColor = value;
79
+ }
80
+ } else {
81
+ style[key] = value;
82
+ }
83
+ }
84
+ }
85
+ return style;
86
+ };
87
+
88
+ // Hook to detect dark mode by checking document class
89
+ export const useIsDarkMode = () => {
90
+ const [isDark, setIsDark] = React.useState(() => {
91
+ if (typeof document !== "undefined") {
92
+ return document.documentElement.classList.contains("dark");
93
+ }
94
+ return false;
95
+ });
96
+
97
+ React.useEffect(() => {
98
+ if (typeof document === "undefined") return;
99
+
100
+ const observer = new MutationObserver(() => {
101
+ setIsDark(document.documentElement.classList.contains("dark"));
102
+ });
103
+
104
+ observer.observe(document.documentElement, {
105
+ attributes: true,
106
+ attributeFilter: ["class"],
107
+ });
108
+
109
+ return () => observer.disconnect();
110
+ }, []);
111
+
112
+ return isDark ? "dark" : "light";
113
+ };