@minidev.fun/ui 1.0.1 → 1.0.2

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.
@@ -0,0 +1,9 @@
1
+ import { ColorModeInitializer } from "../../../src/components/minidev.fun/color-mode/color-mode-initializer.js";
2
+ import { ColorModeToggle } from "../../../src/components/minidev.fun/color-mode/color-mode-toggle.js";
3
+ import { useColorMode } from "../../../src/components/minidev.fun/color-mode/use-color-mode.js";
4
+ export {
5
+ ColorModeInitializer,
6
+ ColorModeToggle,
7
+ useColorMode
8
+ };
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import "react";
3
3
  import { cn } from "../../../../../lib/utils.js";
4
- import { menuItemVariants } from "../../../../../lib/variants.js";
4
+ import { menuItemVariants } from "../../../../../src/lib/variants.js";
5
5
  import Check from "../../../../../node_modules/lucide-react/dist/esm/icons/check.js";
6
6
  import ChevronRight from "../../../../../node_modules/lucide-react/dist/esm/icons/chevron-right.js";
7
7
  import { ContextMenuRoot } from "../../../../../node_modules/@base-ui/react/esm/context-menu/root/ContextMenuRoot.js";
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import "react";
3
3
  import { cn } from "../../../../../lib/utils.js";
4
- import { menuItemVariants } from "../../../../../lib/variants.js";
4
+ import { menuItemVariants } from "../../../../../src/lib/variants.js";
5
5
  import Check from "../../../../../node_modules/lucide-react/dist/esm/icons/check.js";
6
6
  import ChevronRight from "../../../../../node_modules/lucide-react/dist/esm/icons/chevron-right.js";
7
7
  import { MenuRoot } from "../../../../../node_modules/@base-ui/react/esm/menu/root/MenuRoot.js";
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import "react";
3
3
  import { cn } from "../../../../../lib/utils.js";
4
- import { menuItemVariants } from "../../../../../lib/variants.js";
4
+ import { menuItemVariants } from "../../../../../src/lib/variants.js";
5
5
  import { DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenu, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "./dropdown-menu.js";
6
6
  import { Menubar as Menubar$1 } from "../../../../../node_modules/@base-ui/react/esm/menubar/Menubar.js";
7
7
  import Check from "../../../../../node_modules/lucide-react/dist/esm/icons/check.js";
@@ -0,0 +1,12 @@
1
+ import createLucideIcon from "../createLucideIcon.js";
2
+ const __iconNode = [
3
+ ["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
4
+ ["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
5
+ ["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
6
+ ];
7
+ const Monitor = createLucideIcon("monitor", __iconNode);
8
+ export {
9
+ __iconNode,
10
+ Monitor as default
11
+ };
12
+ //# sourceMappingURL=monitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitor.js","sources":["../../../../../../node_modules/lucide-react/dist/esm/icons/monitor.js"],"sourcesContent":["/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"20\", height: \"14\", x: \"2\", y: \"3\", rx: \"2\", key: \"48i651\" }],\n [\"line\", { x1: \"8\", x2: \"16\", y1: \"21\", y2: \"21\", key: \"1svkeh\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"17\", y2: \"21\", key: \"vw1qmm\" }]\n];\nconst Monitor = createLucideIcon(\"monitor\", __iconNode);\n\nexport { __iconNode, Monitor as default };\n//# sourceMappingURL=monitor.js.map\n"],"names":[],"mappings":";AASK,MAAC,aAAa;AAAA,EACjB,CAAC,QAAQ,EAAE,OAAO,MAAM,QAAQ,MAAM,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,KAAK,SAAQ,CAAE;AAAA,EAC9E,CAAC,QAAQ,EAAE,IAAI,KAAK,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,KAAK,SAAQ,CAAE;AAAA,EACjE,CAAC,QAAQ,EAAE,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,KAAK,SAAQ,CAAE;AACpE;AACK,MAAC,UAAU,iBAAiB,WAAW,UAAU;","x_google_ignoreList":[0]}
@@ -0,0 +1,16 @@
1
+ import createLucideIcon from "../createLucideIcon.js";
2
+ const __iconNode = [
3
+ [
4
+ "path",
5
+ {
6
+ d: "M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401",
7
+ key: "kfwtm"
8
+ }
9
+ ]
10
+ ];
11
+ const Moon = createLucideIcon("moon", __iconNode);
12
+ export {
13
+ __iconNode,
14
+ Moon as default
15
+ };
16
+ //# sourceMappingURL=moon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moon.js","sources":["../../../../../../node_modules/lucide-react/dist/esm/icons/moon.js"],"sourcesContent":["/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401\",\n key: \"kfwtm\"\n }\n ]\n];\nconst Moon = createLucideIcon(\"moon\", __iconNode);\n\nexport { __iconNode, Moon as default };\n//# sourceMappingURL=moon.js.map\n"],"names":[],"mappings":";AASK,MAAC,aAAa;AAAA,EACjB;AAAA,IACE;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,KAAK;AAAA,IACX;AAAA,EACA;AACA;AACK,MAAC,OAAO,iBAAiB,QAAQ,UAAU;","x_google_ignoreList":[0]}
@@ -0,0 +1,18 @@
1
+ import createLucideIcon from "../createLucideIcon.js";
2
+ const __iconNode = [
3
+ ["circle", { cx: "12", cy: "12", r: "4", key: "4exip2" }],
4
+ ["path", { d: "M12 2v2", key: "tus03m" }],
5
+ ["path", { d: "M12 20v2", key: "1lh1kg" }],
6
+ ["path", { d: "m4.93 4.93 1.41 1.41", key: "149t6j" }],
7
+ ["path", { d: "m17.66 17.66 1.41 1.41", key: "ptbguv" }],
8
+ ["path", { d: "M2 12h2", key: "1t8f8n" }],
9
+ ["path", { d: "M20 12h2", key: "1q8mjw" }],
10
+ ["path", { d: "m6.34 17.66-1.41 1.41", key: "1m8zz5" }],
11
+ ["path", { d: "m19.07 4.93-1.41 1.41", key: "1shlcs" }]
12
+ ];
13
+ const Sun = createLucideIcon("sun", __iconNode);
14
+ export {
15
+ __iconNode,
16
+ Sun as default
17
+ };
18
+ //# sourceMappingURL=sun.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sun.js","sources":["../../../../../../node_modules/lucide-react/dist/esm/icons/sun.js"],"sourcesContent":["/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"4\", key: \"4exip2\" }],\n [\"path\", { d: \"M12 2v2\", key: \"tus03m\" }],\n [\"path\", { d: \"M12 20v2\", key: \"1lh1kg\" }],\n [\"path\", { d: \"m4.93 4.93 1.41 1.41\", key: \"149t6j\" }],\n [\"path\", { d: \"m17.66 17.66 1.41 1.41\", key: \"ptbguv\" }],\n [\"path\", { d: \"M2 12h2\", key: \"1t8f8n\" }],\n [\"path\", { d: \"M20 12h2\", key: \"1q8mjw\" }],\n [\"path\", { d: \"m6.34 17.66-1.41 1.41\", key: \"1m8zz5\" }],\n [\"path\", { d: \"m19.07 4.93-1.41 1.41\", key: \"1shlcs\" }]\n];\nconst Sun = createLucideIcon(\"sun\", __iconNode);\n\nexport { __iconNode, Sun as default };\n//# sourceMappingURL=sun.js.map\n"],"names":[],"mappings":";AASK,MAAC,aAAa;AAAA,EACjB,CAAC,UAAU,EAAE,IAAI,MAAM,IAAI,MAAM,GAAG,KAAK,KAAK,UAAU;AAAA,EACxD,CAAC,QAAQ,EAAE,GAAG,WAAW,KAAK,SAAQ,CAAE;AAAA,EACxC,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAAA,EACzC,CAAC,QAAQ,EAAE,GAAG,wBAAwB,KAAK,SAAQ,CAAE;AAAA,EACrD,CAAC,QAAQ,EAAE,GAAG,0BAA0B,KAAK,SAAQ,CAAE;AAAA,EACvD,CAAC,QAAQ,EAAE,GAAG,WAAW,KAAK,SAAQ,CAAE;AAAA,EACxC,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAAA,EACzC,CAAC,QAAQ,EAAE,GAAG,yBAAyB,KAAK,SAAQ,CAAE;AAAA,EACtD,CAAC,QAAQ,EAAE,GAAG,yBAAyB,KAAK,SAAQ,CAAE;AACxD;AACK,MAAC,MAAM,iBAAiB,OAAO,UAAU;","x_google_ignoreList":[0]}
@@ -0,0 +1,30 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useColorMode } from "./use-color-mode.js";
4
+ const colorModeScript = `(function() {
5
+ try {
6
+ var cookie = document.cookie.match(/color-mode=([^;]*)/) || document.cookie.match(/theme=([^;]*)/);
7
+ var stored = cookie ? JSON.parse(decodeURIComponent(cookie[1])) : null;
8
+ var preference = stored ? stored.preference : 'system';
9
+ var mode = preference === 'system'
10
+ ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
11
+ : preference;
12
+ if (mode === 'dark') {
13
+ document.documentElement.classList.add('dark');
14
+ } else {
15
+ document.documentElement.classList.remove('dark');
16
+ }
17
+ document.documentElement.style.colorScheme = mode;
18
+ } catch (e) {
19
+ document.documentElement.classList.remove('dark');
20
+ document.documentElement.style.colorScheme = 'light';
21
+ }
22
+ })();`;
23
+ function ColorModeInitializer() {
24
+ useColorMode();
25
+ return /* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: colorModeScript } });
26
+ }
27
+ export {
28
+ ColorModeInitializer
29
+ };
30
+ //# sourceMappingURL=color-mode-initializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-mode-initializer.js","sources":["../../../../../src/components/minidev.fun/color-mode/color-mode-initializer.tsx"],"sourcesContent":["\"use client\";\n\nimport { useColorMode } from \"./use-color-mode\";\n\n/**\n * Color mode initialization script (internal).\n *\n * For Vite/static HTML apps, copy this script into your index.html <head>.\n * See docs/integrations/vite.md for the full script to copy.\n */\nconst colorModeScript = `(function() {\n try {\n var cookie = document.cookie.match(/color-mode=([^;]*)/) || document.cookie.match(/theme=([^;]*)/);\n var stored = cookie ? JSON.parse(decodeURIComponent(cookie[1])) : null;\n var preference = stored ? stored.preference : 'system';\n var mode = preference === 'system'\n ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')\n : preference;\n if (mode === 'dark') {\n document.documentElement.classList.add('dark');\n } else {\n document.documentElement.classList.remove('dark');\n }\n document.documentElement.style.colorScheme = mode;\n } catch (e) {\n document.documentElement.classList.remove('dark');\n document.documentElement.style.colorScheme = 'light';\n }\n})();`;\n\n/**\n * ColorModeInitializer - Prevents flash of unstyled content (FOUC) during color mode initialization\n *\n * A React component that injects the color mode initialization script into the page.\n * Use this in SSR frameworks like Next.js where React controls the document.\n *\n * **For Vite/static HTML apps:** This component won't prevent FOUC because React\n * renders after first paint. Instead, copy the initialization script directly into\n * your `index.html` `<head>`. See the Vite integration guide for the full script.\n *\n * @component\n * @example Next.js App Router\n * ```tsx\n * // app/layout.tsx\n * import { ColorModeInitializer } from \"@minidev.fun/ui/color-mode\";\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html lang=\"en\" suppressHydrationWarning>\n * <head>\n * <ColorModeInitializer />\n * </head>\n * <body>{children}</body>\n * </html>\n * );\n * }\n * ```\n *\n * @example Vite - copy script to index.html instead\n * ```html\n * <!-- See docs/integrations/vite.md for the full script to copy -->\n * <head>\n * <script>\n * (function() {\n * // ... color mode initialization script\n * })();\n * </script>\n * </head>\n * ```\n *\n * @see {@link useColorMode} - Hook for runtime color mode management\n * @see {@link ColorModeToggle} - UI component for user color mode switching\n * @since 1.0.0\n */\nexport function ColorModeInitializer() {\n useColorMode();\n return <script dangerouslySetInnerHTML={{ __html: colorModeScript }} />;\n}\n"],"names":[],"mappings":";;;AAUA;AAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgEjB;AACL;AACA;AACF;;;;"}
@@ -0,0 +1,88 @@
1
+ "use client";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import { useState, useEffect } from "react";
4
+ import { Button } from "../../../../components/ui/src/components/ui/button.js";
5
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "../../../../components/ui/src/components/ui/dropdown-menu.js";
6
+ import { useColorMode } from "./use-color-mode.js";
7
+ import { cn } from "../../../../lib/utils.js";
8
+ import Monitor from "../../../../node_modules/lucide-react/dist/esm/icons/monitor.js";
9
+ import Sun from "../../../../node_modules/lucide-react/dist/esm/icons/sun.js";
10
+ import Moon from "../../../../node_modules/lucide-react/dist/esm/icons/moon.js";
11
+ const iconSizeMap = {
12
+ xs: "icon-xs",
13
+ sm: "icon-sm",
14
+ default: "icon",
15
+ lg: "icon-lg"
16
+ };
17
+ const iconClassMap = {
18
+ xs: "size-3",
19
+ sm: "size-3.5",
20
+ default: "size-4",
21
+ lg: "size-5"
22
+ };
23
+ const textClassMap = {
24
+ xs: "text-xs",
25
+ sm: "text-sm",
26
+ default: "text-base",
27
+ lg: "text-lg"
28
+ };
29
+ function ColorModeToggle({
30
+ variant = "outline",
31
+ size = "default",
32
+ className,
33
+ showLabel = false,
34
+ align = "end",
35
+ ...props
36
+ }) {
37
+ const buttonSize = showLabel ? size : iconSizeMap[size];
38
+ const iconClass = iconClassMap[size];
39
+ const textClass = textClassMap[size];
40
+ const { preference, setPreference } = useColorMode();
41
+ const [mounted, setMounted] = useState(false);
42
+ useEffect(() => setMounted(true), []);
43
+ const items = [
44
+ { mode: "system", Icon: Monitor, label: "System" },
45
+ { mode: "light", Icon: Sun, label: "Light" },
46
+ { mode: "dark", Icon: Moon, label: "Dark" }
47
+ ];
48
+ const currentItem = mounted ? items.find((item) => item.mode === preference) || items[0] : items[0];
49
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
50
+ /* @__PURE__ */ jsx(
51
+ DropdownMenuTrigger,
52
+ {
53
+ render: /* @__PURE__ */ jsxs(
54
+ Button,
55
+ {
56
+ variant,
57
+ size: buttonSize,
58
+ className: cn(className),
59
+ suppressHydrationWarning: true,
60
+ ...props,
61
+ children: [
62
+ currentItem && /* @__PURE__ */ jsx(currentItem.Icon, { className: iconClass }),
63
+ showLabel && /* @__PURE__ */ jsx("span", { className: textClass, children: currentItem?.label }),
64
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Toggle color mode" })
65
+ ]
66
+ }
67
+ )
68
+ }
69
+ ),
70
+ /* @__PURE__ */ jsx(DropdownMenuContent, { align, children: items.map((item) => /* @__PURE__ */ jsxs(
71
+ DropdownMenuItem,
72
+ {
73
+ onClick: () => setPreference(item.mode),
74
+ className: "flex items-center gap-2",
75
+ children: [
76
+ /* @__PURE__ */ jsx(item.Icon, { className: "size-4" }),
77
+ /* @__PURE__ */ jsx("span", { children: item.label }),
78
+ preference === item.mode && /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs opacity-60", children: "✓" })
79
+ ]
80
+ },
81
+ item.mode
82
+ )) })
83
+ ] });
84
+ }
85
+ export {
86
+ ColorModeToggle
87
+ };
88
+ //# sourceMappingURL=color-mode-toggle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-mode-toggle.js","sources":["../../../../../src/components/minidev.fun/color-mode/color-mode-toggle.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { Monitor, Moon, Sun } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { useColorMode } from \"./use-color-mode\";\nimport { cn } from \"@/lib/utils\";\n\n// Map regular sizes to icon sizes for when showLabel is false\nconst iconSizeMap = {\n xs: \"icon-xs\",\n sm: \"icon-sm\",\n default: \"icon\",\n lg: \"icon-lg\",\n} as const;\n\n// Icon sizes that scale with button size\nconst iconClassMap = {\n xs: \"size-3\",\n sm: \"size-3.5\",\n default: \"size-4\",\n lg: \"size-5\",\n} as const;\n\n// Text sizes that scale with button size\nconst textClassMap = {\n xs: \"text-xs\",\n sm: \"text-sm\",\n default: \"text-base\",\n lg: \"text-lg\",\n} as const;\n\ntype ColorModeToggleSize = \"xs\" | \"sm\" | \"default\" | \"lg\";\n\ntype ColorModeToggleProps = {\n /**\n * Button size - when showLabel is false, renders as a square icon button\n * @default \"default\"\n */\n size?: ColorModeToggleSize;\n /**\n * Whether to show the current color mode name as text next to the icon\n * @default false\n */\n showLabel?: boolean;\n /**\n * Alignment of the dropdown menu relative to the trigger button\n * @default \"end\"\n */\n align?: \"start\" | \"center\" | \"end\";\n} & Omit<React.ComponentProps<typeof Button>, \"size\">;\n\n/**\n * ColorModeToggle - A zero-configuration color mode switcher with system, light, and dark modes\n *\n * A completely self-contained color mode toggle component that provides an intuitive dropdown\n * interface for switching between system preference, light mode, and dark mode. Works\n * immediately without any provider setup, context configuration, or additional dependencies.\n *\n * Built on top of Base UI components (Button + DropdownMenu) with the Minidev useColorMode\n * hook for state management. Handles color mode persistence via cookies, system preference\n * detection, real-time system changes, and synchronization across multiple instances.\n *\n * **Zero Configuration Design:**\n * Just import and use - no providers, no setup, no configuration required. The component\n * handles all color mode management internally and provides a complete solution out of the box.\n *\n * @example Basic usage (most common - icon button)\n * ```tsx\n * import { ColorModeToggle } from \"@minidev.fun/ui/color-mode\";\n *\n * // Just drop it in! Works immediately with zero setup\n * function Header() {\n * return (\n * <header className=\"flex items-center justify-between p-4\">\n * <Logo />\n * <ColorModeToggle />\n * </header>\n * );\n * }\n * ```\n *\n * @example With text labels for better UX\n * ```tsx\n * // Show current color mode name next to icon\n * <ColorModeToggle size=\"default\" showLabel />\n *\n * // In a settings panel\n * <div className=\"space-y-4\">\n * <h3>Appearance</h3>\n * <div className=\"flex items-center justify-between\">\n * <span>Color Mode</span>\n * <ColorModeToggle size=\"sm\" showLabel />\n * </div>\n * </div>\n * ```\n *\n * @example Different visual variants\n * ```tsx\n * // Ghost button for minimalist toolbars\n * <ColorModeToggle variant=\"ghost\" />\n *\n * // Secondary style for subtle integration\n * <ColorModeToggle variant=\"secondary\" size=\"sm\" />\n *\n * // Outline style (default) for clear boundaries\n * <ColorModeToggle variant=\"outline\" size=\"lg\" />\n * ```\n *\n * @param variant - Visual style variant inherited from Button component (default: \"outline\")\n * @param size - Button size: xs, sm, default, lg. Renders as icon button when showLabel is false (default: \"default\")\n * @param className - Additional CSS classes for custom styling\n * @param showLabel - Whether to show color mode name text. When false, renders as square icon button (default: false)\n * @param align - Dropdown menu alignment relative to trigger button (default: \"end\")\n *\n * @features\n * - **Zero Configuration**: Import and use immediately - no setup required\n * - **System Detection**: Automatically follows OS dark/light preference changes\n * - **Perfect Persistence**: Color mode choice saved via cookies for SSR compatibility\n * - **Multi-Instance Sync**: Multiple toggles stay perfectly synchronized\n * - **Real-Time Updates**: Responds to system color mode changes while app is running\n * - **Smooth Transitions**: CSS-based mode switching with no flash of wrong content\n * - **Accessibility First**: Full keyboard navigation and screen reader support\n * - **Touch Optimized**: Works perfectly on mobile and tablet devices\n * - **Framework Agnostic**: Works with Next.js, Vite, Create React App, etc.\n *\n * @accessibility\n * - **Keyboard Navigation**: Full support for Enter, Space, and Arrow keys\n * - **Screen Reader Support**: Proper ARIA labels and role announcements\n * - **Focus Management**: Visible focus indicators meeting WCAG 2.1 AA standards\n * - **State Communication**: Current selection clearly indicated with checkmarks\n *\n * @see {@link useColorMode} - The underlying color mode management hook with event-driven architecture\n * @see {@link ColorModeScript} - Component for FOUC prevention (required in root layout)\n * @since 1.0.0\n */\nfunction ColorModeToggle({\n variant = \"outline\",\n size = \"default\",\n className,\n showLabel = false,\n align = \"end\",\n ...props\n}: ColorModeToggleProps) {\n // Use icon size when no label, regular size when label is shown\n const buttonSize = showLabel ? size : iconSizeMap[size];\n const iconClass = iconClassMap[size];\n const textClass = textClassMap[size];\n\n const { preference, setPreference } = useColorMode();\n\n // Track hydration to prevent mismatch between server/client rendering.\n // This runs once after hydration to signal we can show client-specific values.\n const [mounted, setMounted] = useState(false);\n // eslint-disable-next-line react-hooks/set-state-in-effect -- Intentional: standard hydration detection pattern\n useEffect(() => setMounted(true), []);\n\n // Simple icons and labels - no configuration needed\n const items = [\n { mode: \"system\" as const, Icon: Monitor, label: \"System\" },\n { mode: \"light\" as const, Icon: Sun, label: \"Light\" },\n { mode: \"dark\" as const, Icon: Moon, label: \"Dark\" },\n ];\n\n // Get current item based on preference, not resolved mode\n // Before hydration, always show \"system\" to match server render\n const currentItem = mounted\n ? items.find((item) => item.mode === preference) || items[0]\n : items[0]; // Always \"system\" on server\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button\n variant={variant}\n size={buttonSize}\n className={cn(className)}\n suppressHydrationWarning\n {...props}\n >\n {currentItem && <currentItem.Icon className={iconClass} />}\n {showLabel && (\n <span className={textClass}>{currentItem?.label}</span>\n )}\n <span className=\"sr-only\">Toggle color mode</span>\n </Button>\n }\n />\n <DropdownMenuContent align={align}>\n {items.map((item) => (\n <DropdownMenuItem\n key={item.mode}\n onClick={() => setPreference(item.mode)}\n className=\"flex items-center gap-2\"\n >\n <item.Icon className=\"size-4\" />\n <span>{item.label}</span>\n {preference === item.mode && (\n <span className=\"ml-auto text-xs opacity-60\">✓</span>\n )}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport { ColorModeToggle, type ColorModeToggleProps, type ColorModeToggleSize };\n"],"names":[],"mappings":";;;;;;;;;;AAeA;AAAoB;AACd;AACA;AACK;AAEX;AAGA;AAAqB;AACf;AACA;AACK;AAEX;AAGA;AAAqB;AACf;AACA;AACK;AAEX;AA0GA;AAAyB;AACb;AACH;AACP;AACY;AACJ;AAEV;AAEE;AACA;AACA;AAEA;AAIA;AAEA;AAGA;AAAc;AACqC;AACL;AACA;AAK9C;AAIA;AAEI;AAAA;AAAC;AAAA;AAEG;AAAC;AAAA;AACC;AACM;AACiB;AACC;AACpB;AAEH;AAAuD;AAEN;AAEP;AAAA;AAAA;AAAA;AAC7C;AAAA;AAKA;AAAC;AAAA;AAEuC;AAC5B;AAEV;AAA8B;AACZ;AAE8B;AAAA;AAAA;AAPtC;AAWhB;AAGN;;;;"}
@@ -0,0 +1,106 @@
1
+ "use client";
2
+ import { useState, useEffect } from "react";
3
+ let systemListenerInitialized = false;
4
+ const COOKIE_NAME = "color-mode";
5
+ const COOKIE_OPTIONS = {
6
+ path: "/",
7
+ maxAge: 60 * 60 * 24 * 365,
8
+ // 1 year
9
+ sameSite: "lax"
10
+ };
11
+ function getColorModeFromCookie() {
12
+ if (typeof document === "undefined") return null;
13
+ let match = document.cookie.match(
14
+ new RegExp(`(?:^|; )${COOKIE_NAME}=([^;]*)`)
15
+ );
16
+ if (!match) {
17
+ match = document.cookie.match(/(?:^|; )theme=([^;]*)/);
18
+ }
19
+ if (!match) return null;
20
+ try {
21
+ const decoded = decodeURIComponent(match[1] || "");
22
+ return JSON.parse(decoded);
23
+ } catch {
24
+ return null;
25
+ }
26
+ }
27
+ function setColorModeCookie(state) {
28
+ if (typeof document === "undefined") return;
29
+ const value = JSON.stringify(state);
30
+ let cookieString = `${COOKIE_NAME}=${encodeURIComponent(value)}`;
31
+ cookieString += `; path=${COOKIE_OPTIONS.path}`;
32
+ cookieString += `; max-age=${COOKIE_OPTIONS.maxAge}`;
33
+ cookieString += `; samesite=${COOKIE_OPTIONS.sameSite}`;
34
+ document.cookie = cookieString;
35
+ }
36
+ function getSystemColorMode() {
37
+ if (typeof window === "undefined") return "light";
38
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
39
+ }
40
+ function applyColorMode(mode) {
41
+ if (typeof document === "undefined") return;
42
+ if (mode === "dark") {
43
+ document.documentElement.classList.add("dark");
44
+ } else {
45
+ document.documentElement.classList.remove("dark");
46
+ }
47
+ document.documentElement.style.colorScheme = mode;
48
+ }
49
+ function setupSystemListener() {
50
+ if (systemListenerInitialized || typeof window === "undefined") return;
51
+ systemListenerInitialized = true;
52
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
53
+ mediaQuery.addEventListener("change", () => {
54
+ const stored = getColorModeFromCookie();
55
+ if (stored?.preference !== "system") return;
56
+ const mode = mediaQuery.matches ? "dark" : "light";
57
+ const newState = { preference: "system", mode };
58
+ setColorModeCookie(newState);
59
+ applyColorMode(mode);
60
+ window.dispatchEvent(
61
+ new CustomEvent("color-mode-change", { detail: newState })
62
+ );
63
+ });
64
+ }
65
+ function useColorMode() {
66
+ const [state, setState] = useState(() => {
67
+ const saved = getColorModeFromCookie();
68
+ if (saved) return saved;
69
+ const mode = getSystemColorMode();
70
+ return { preference: "system", mode };
71
+ });
72
+ function setPreference(newPreference) {
73
+ const mode = newPreference === "system" ? getSystemColorMode() : newPreference;
74
+ const newState = { preference: newPreference, mode };
75
+ setColorModeCookie(newState);
76
+ applyColorMode(mode);
77
+ window.dispatchEvent(
78
+ new CustomEvent("color-mode-change", {
79
+ detail: newState
80
+ })
81
+ );
82
+ }
83
+ useEffect(() => {
84
+ setupSystemListener();
85
+ const handleColorModeChange = (event) => {
86
+ setState(event.detail);
87
+ };
88
+ window.addEventListener(
89
+ "color-mode-change",
90
+ handleColorModeChange
91
+ );
92
+ return () => window.removeEventListener(
93
+ "color-mode-change",
94
+ handleColorModeChange
95
+ );
96
+ }, []);
97
+ return {
98
+ preference: state.preference,
99
+ mode: state.mode,
100
+ setPreference
101
+ };
102
+ }
103
+ export {
104
+ useColorMode
105
+ };
106
+ //# sourceMappingURL=use-color-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-color-mode.js","sources":["../../../../../src/components/minidev.fun/color-mode/use-color-mode.ts"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\n/**\n * Module-level flag to ensure the system color mode listener is set up only once.\n *\n * This is a pragmatic tradeoff: module-level mutable state is generally a code smell\n * in React (SSR issues, test leakage, not idiomatic), but the alternative would be\n * requiring users to wrap their app in a <ColorModeProvider>. Since we want zero-config\n * \"just works\" behavior, we accept this pattern here.\n *\n * It's safe because:\n * - Only runs client-side (window check in setupSystemListener)\n * - The listener is truly global (system color scheme is one per browser)\n * - It's idempotent and stateless (reads from cookie each time)\n */\nlet systemListenerInitialized = false;\n\n/**\n * Color mode preference options for the color mode system\n *\n * Controls how the application determines the active color mode:\n * - `\"system\"` - Automatically follows the user's OS preference\n * - `\"light\"` - Forces light mode regardless of system preference\n * - `\"dark\"` - Forces dark mode regardless of system preference\n *\n * @example\n * ```tsx\n * const { preference, setPreference } = useColorMode();\n *\n * // Switch to dark mode\n * setPreference(\"dark\");\n *\n * // Follow system preference\n * setPreference(\"system\");\n * ```\n *\n * @since 1.0.0\n */\nexport type ColorModePreference = \"system\" | \"light\" | \"dark\";\n\n/**\n * Internal color mode state structure stored in cookies\n *\n * Maintains both the user's preference and the actual mode value\n * to handle system color mode changes efficiently.\n *\n * @internal\n */\ntype ColorModeState = {\n /** User's selected color mode preference */\n preference: ColorModePreference;\n /** Actual mode applied to the DOM */\n mode: \"light\" | \"dark\";\n};\n\n/**\n * Cookie configuration for color mode persistence\n *\n * Uses secure defaults for cross-site compatibility and long-term storage.\n *\n * @internal\n */\nconst COOKIE_NAME = \"color-mode\";\nconst COOKIE_OPTIONS = {\n path: \"/\",\n maxAge: 60 * 60 * 24 * 365, // 1 year\n sameSite: \"lax\" as const,\n};\n\n/**\n * Retrieves the stored color mode preference from browser cookies\n *\n * Safely parses the cookie value and handles malformed data gracefully.\n * Returns null if no valid color mode data is found or if running server-side.\n *\n * @returns The stored color mode state or null if unavailable\n * @internal\n */\nfunction getColorModeFromCookie(): ColorModeState | null {\n if (typeof document === \"undefined\") return null;\n\n // Try new cookie name first, then fall back to legacy \"theme\" cookie\n let match = document.cookie.match(\n new RegExp(`(?:^|; )${COOKIE_NAME}=([^;]*)`),\n );\n if (!match) {\n match = document.cookie.match(/(?:^|; )theme=([^;]*)/);\n }\n if (!match) return null;\n\n try {\n const decoded = decodeURIComponent(match[1] || \"\");\n return JSON.parse(decoded);\n } catch {\n return null;\n }\n}\n\n/**\n * Persists the current color mode state to browser cookies\n *\n * Stores the complete color mode state as a JSON string with appropriate\n * cookie settings for security and longevity. Safe for server-side rendering.\n *\n * @param state - The color mode state to persist\n * @internal\n */\nfunction setColorModeCookie(state: ColorModeState) {\n if (typeof document === \"undefined\") return;\n\n const value = JSON.stringify(state);\n let cookieString = `${COOKIE_NAME}=${encodeURIComponent(value)}`;\n\n cookieString += `; path=${COOKIE_OPTIONS.path}`;\n cookieString += `; max-age=${COOKIE_OPTIONS.maxAge}`;\n cookieString += `; samesite=${COOKIE_OPTIONS.sameSite}`;\n\n document.cookie = cookieString;\n}\n\n/**\n * Detects the user's system color mode preference\n *\n * Uses the CSS media query `prefers-color-scheme` to determine if the user\n * has configured their OS to prefer dark or light modes. Falls back to\n * light mode for server-side rendering or unsupported browsers.\n *\n * @returns The system's preferred color mode\n * @internal\n */\nfunction getSystemColorMode(): \"light\" | \"dark\" {\n if (typeof window === \"undefined\") return \"light\";\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? \"dark\"\n : \"light\";\n}\n\n/**\n * Applies the specified color mode to the document\n *\n * Updates the document's class list and color-scheme CSS property to reflect\n * the chosen mode. This triggers CSS-based mode switching throughout the\n * application and ensures native elements respect the mode choice.\n *\n * @param mode - The color mode to apply (\"light\" or \"dark\")\n * @internal\n */\nfunction applyColorMode(mode: \"light\" | \"dark\") {\n if (typeof document === \"undefined\") return;\n\n // For light mode, remove dark class (light is default)\n // For dark mode, add dark class\n if (mode === \"dark\") {\n document.documentElement.classList.add(\"dark\");\n } else {\n document.documentElement.classList.remove(\"dark\");\n }\n\n // Set color-scheme for native elements\n document.documentElement.style.colorScheme = mode;\n}\n\n/**\n * Sets up a global listener for system color mode changes.\n * Only runs once per module load, regardless of how many hook instances exist.\n *\n * @internal\n */\nfunction setupSystemListener() {\n if (systemListenerInitialized || typeof window === \"undefined\") return;\n systemListenerInitialized = true;\n\n const mediaQuery = window.matchMedia(\"(prefers-color-scheme: dark)\");\n mediaQuery.addEventListener(\"change\", () => {\n // Only respond if current preference is \"system\"\n const stored = getColorModeFromCookie();\n if (stored?.preference !== \"system\") return;\n\n const mode: \"light\" | \"dark\" = mediaQuery.matches ? \"dark\" : \"light\";\n const newState: ColorModeState = { preference: \"system\", mode };\n\n setColorModeCookie(newState);\n applyColorMode(mode);\n window.dispatchEvent(\n new CustomEvent(\"color-mode-change\", { detail: newState }),\n );\n });\n}\n\n/**\n * Hook for managing application color mode with automatic system preference detection\n *\n * A complete color mode management solution that handles persistence, system preference\n * detection, and DOM manipulation without requiring any context providers. Designed\n * for applications that need simple light/dark mode switching with optional system\n * preference following.\n *\n * This hook works in conjunction with the {@link ColorModeScript} component to provide\n * a complete color mode solution with FOUC prevention and perfect synchronization\n * across multiple instances.\n *\n * Features:\n * - **Perfect synchronization**: Multiple hook instances stay in sync via custom events\n * - **Automatic persistence**: Color mode preference saved to cookies across sessions\n * - **System preference detection**: Automatically follows OS dark/light mode when set to \"system\"\n * - **Live system updates**: Responds to system color mode changes in real-time\n * - **SSR compatible**: Works safely during server-side rendering\n * - **Type safe**: Full TypeScript support with proper type definitions\n * - **No provider required**: Self-contained hook that works out of the box\n *\n * @example Basic color mode switching\n * ```tsx\n * function ColorModeToggle() {\n * const { preference, mode, setPreference } = useColorMode();\n *\n * const toggleMode = () => {\n * setPreference(mode === \"dark\" ? \"light\" : \"dark\");\n * };\n *\n * return (\n * <button onClick={toggleMode}>\n * Switch to {mode === \"dark\" ? \"light\" : \"dark\"} mode\n * </button>\n * );\n * }\n * ```\n *\n * @example Color mode selector dropdown\n * ```tsx\n * function ColorModeSelector() {\n * const { preference, setPreference } = useColorMode();\n *\n * return (\n * <select value={preference} onChange={(e) => setPreference(e.target.value as ColorModePreference)}>\n * <option value=\"system\">Follow system</option>\n * <option value=\"light\">Light mode</option>\n * <option value=\"dark\">Dark mode</option>\n * </select>\n * );\n * }\n * ```\n *\n * @returns Object containing current color mode state and setter function\n * @returns returns.preference - The user's selected color mode preference\n * @returns returns.mode - The actual color mode currently applied (always \"light\" or \"dark\")\n * @returns returns.setPreference - Function to change the color mode preference\n *\n * @see {@link ColorModePreference} - Available color mode preference options\n * @see {@link ColorModeScript} - Component for FOUC prevention\n * @see {@link ColorModeToggle} - UI component for color mode switching\n * @since 1.0.0\n */\nexport function useColorMode() {\n // Initialize state from cookie or default to system\n const [state, setState] = useState<ColorModeState>(() => {\n const saved = getColorModeFromCookie();\n if (saved) return saved;\n\n const mode = getSystemColorMode();\n return { preference: \"system\", mode };\n });\n\n // Set color mode preference - dispatch event, let event handler update state\n function setPreference(newPreference: ColorModePreference) {\n const mode =\n newPreference === \"system\" ? getSystemColorMode() : newPreference;\n const newState = { preference: newPreference, mode };\n\n // Update cookie and DOM immediately\n setColorModeCookie(newState);\n applyColorMode(mode);\n\n // Broadcast change - ALL instances (including this one) will update state from this event\n window.dispatchEvent(\n new CustomEvent(\"color-mode-change\", {\n detail: newState,\n }),\n );\n }\n\n // Set up global system listener once (idempotent) and listen for color mode changes\n useEffect(() => {\n setupSystemListener();\n\n const handleColorModeChange = (event: CustomEvent) => {\n setState(event.detail);\n };\n\n window.addEventListener(\n \"color-mode-change\",\n handleColorModeChange as EventListener,\n );\n return () =>\n window.removeEventListener(\n \"color-mode-change\",\n handleColorModeChange as EventListener,\n );\n }, []);\n\n return {\n preference: state.preference,\n mode: state.mode,\n setPreference,\n };\n}\n"],"names":[],"mappings":";;AAiBA;AA+CA;AACA;AAAuB;AACf;AACiB;AAAA;AAEzB;AAWA;AACE;AAGA;AAA4B;AACiB;AAE7C;AACE;AAAqD;AAEvD;AAEA;AACE;AACA;AAAyB;AAEzB;AAAO;AAEX;AAWA;AACE;AAEA;AACA;AAEA;AACA;AACA;AAEA;AACF;AAYA;AACE;AACA;AAGF;AAYA;AACE;AAIA;AACE;AAA6C;AAE7C;AAAgD;AAIlD;AACF;AAQA;AACE;AACA;AAEA;AACA;AAEE;AACA;AAEA;AACA;AAEA;AACA;AACA;AAAO;AACoD;AAAA;AAG/D;AAiEO;AAEL;AACE;AACA;AAEA;AACA;AAA+B;AAIjC;AACE;AAEA;AAGA;AACA;AAGA;AAAO;AACgC;AAC3B;AACT;AAAA;AAKL;AACE;AAEA;AACE;AAAqB;AAGvB;AAAO;AACL;AACA;AAEF;AACS;AACL;AACA;AAAA;AAIN;AAAO;AACa;AACN;AACZ;AAEJ;;;;"}
@@ -1,4 +1,4 @@
1
- import { cva } from "../node_modules/class-variance-authority/dist/index.js";
1
+ import { cva } from "../../node_modules/class-variance-authority/dist/index.js";
2
2
  const menuItemVariants = cva(
3
3
  "gap-2 rounded-sm px-2 py-1.5 text-sm [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
4
4
  {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variants.js","sources":["../../../src/lib/variants.ts"],"sourcesContent":["/**\n * @internal\n * Shared CVA variants used by menu and typography components.\n * Not exported publicly - use component props instead:\n * - Menu styling: <DropdownMenuItem variant=\"destructive\">\n * - Typography: <Text color=\"muted\" size=\"sm\">\n */\n\nimport { cva } from \"class-variance-authority\";\n\n/**\n * Shared menu item variants for DropdownMenuItem, ContextMenuItem, and MenubarItem.\n * Provides consistent styling across all menu-style components.\n */\nexport const menuItemVariants = cva(\n \"gap-2 rounded-sm px-2 py-1.5 text-sm [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default:\n \"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground\",\n destructive:\n \"text-destructive focus:bg-destructive/10 dark:focus:bg-destructive/20 focus:text-destructive *:[svg]:text-destructive\",\n success:\n \"text-success focus:bg-success/10 dark:focus:bg-success/20 focus:text-success *:[svg]:text-success\",\n warning:\n \"text-warning focus:bg-warning/10 dark:focus:bg-warning/20 focus:text-warning *:[svg]:text-warning\",\n info: \"text-info focus:bg-info/10 dark:focus:bg-info/20 focus:text-info *:[svg]:text-info\",\n },\n inset: {\n true: \"pl-8\",\n false: \"\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n inset: false,\n },\n },\n);\n\n/** Variant options for menu items: default, destructive, success, warning, info */\nexport type MenuItemVariant =\n | \"default\"\n | \"destructive\"\n | \"success\"\n | \"warning\"\n | \"info\";\n\n/**\n * Typography color variants shared across Title, Text, Code, ListItem, and Blockquote components.\n * Provides semantic color options for consistent text styling.\n *\n * @example\n * ```tsx\n * import { typographyColorVariants } from \"@minidev.fun/ui/lib/variants\"\n * import { cn } from \"@minidev.fun/ui/lib/utils\"\n *\n * <span className={cn(typographyColorVariants({ color: \"muted\" }))}>\n * Secondary text\n * </span>\n * ```\n */\nexport const typographyColorVariants = cva(\"\", {\n variants: {\n color: {\n primary: \"text-primary\",\n default: \"text-foreground\",\n muted: \"text-muted-foreground\",\n subtle: \"text-subtle-foreground\",\n destructive: \"text-destructive\",\n success: \"text-success\",\n warning: \"text-warning\",\n info: \"text-info\",\n },\n },\n defaultVariants: {\n color: \"default\",\n },\n});\n\n/** Semantic color options for typography: default, muted, subtle, destructive, success, warning, info */\nexport type TypographyColor =\n | \"default\"\n | \"primary\"\n | \"muted\"\n | \"subtle\"\n | \"destructive\"\n | \"success\"\n | \"warning\"\n | \"info\";\n\n/**\n * Title order-based size defaults (only used when size prop is not specified).\n * Maps heading levels (h1-h6) to responsive font sizes.\n *\n * @example\n * ```tsx\n * // order: 1 → \"text-3xl md:text-4xl lg:text-5xl\"\n * // order: 6 → \"text-sm md:text-base lg:text-lg\"\n * ```\n */\nexport const titleOrderSizeVariants = cva(\"\", {\n variants: {\n order: {\n 1: \"text-3xl md:text-4xl lg:text-5xl\",\n 2: \"text-2xl md:text-3xl lg:text-4xl\",\n 3: \"text-xl md:text-2xl lg:text-3xl\",\n 4: \"text-lg md:text-xl lg:text-2xl\",\n 5: \"text-base md:text-lg lg:text-xl\",\n 6: \"text-sm md:text-base lg:text-lg\",\n },\n },\n});\n\n/**\n * Title order-based style defaults (weight, tracking, leading).\n * Provides appropriate font-weight and line-height for each heading level.\n *\n * @example\n * ```tsx\n * // order: 1 → \"font-bold tracking-tight leading-[1.1]\"\n * // order: 6 → \"font-medium leading-normal\"\n * ```\n */\nexport const titleOrderStyleVariants = cva(\"\", {\n variants: {\n order: {\n 1: \"font-bold tracking-tight leading-[1.1]\",\n 2: \"font-semibold tracking-tight leading-[1.2]\",\n 3: \"font-semibold tracking-tight leading-[1.25]\",\n 4: \"font-semibold leading-[1.3]\",\n 5: \"font-medium leading-[1.4]\",\n 6: \"font-medium leading-normal\",\n },\n },\n defaultVariants: {\n order: 2,\n },\n});\n\n/**\n * Title component variants for explicit size and weight overrides.\n * Use when you need to override the order-based defaults.\n *\n * @example\n * ```tsx\n * import { titleVariants } from \"@minidev.fun/ui/lib/variants\"\n * import { cn } from \"@minidev.fun/ui/lib/utils\"\n *\n * <h2 className={cn(titleVariants({ size: \"4xl\", weight: \"bold\" }))}>\n * Large Bold Title\n * </h2>\n * ```\n */\nexport const titleVariants = cva(\"\", {\n variants: {\n size: {\n xs: \"text-xs leading-4\",\n sm: \"text-sm leading-5\",\n base: \"text-base leading-6\",\n lg: \"text-lg leading-7\",\n xl: \"text-xl leading-7 tracking-tight\",\n \"2xl\": \"text-2xl leading-8 tracking-tight\",\n \"3xl\": \"text-3xl leading-9 tracking-tight\",\n \"4xl\": \"text-4xl leading-10 tracking-tighter\",\n \"5xl\": \"text-5xl leading-[1.1] tracking-tighter\",\n \"6xl\": \"text-6xl leading-[1.1] tracking-tighter\",\n },\n weight: {\n normal: \"font-normal\",\n medium: \"font-medium\",\n semibold: \"font-semibold\",\n bold: \"font-bold\",\n },\n },\n});\n\n/** Heading level 1-6, maps to h1-h6 elements */\nexport type TitleOrder = 1 | 2 | 3 | 4 | 5 | 6;\n\n/** Font size options from xs to 6xl */\nexport type TitleSize =\n | \"xs\"\n | \"sm\"\n | \"base\"\n | \"lg\"\n | \"xl\"\n | \"2xl\"\n | \"3xl\"\n | \"4xl\"\n | \"5xl\"\n | \"6xl\";\n\n/** Font weight options: normal, medium, semibold, bold */\nexport type TitleWeight = \"normal\" | \"medium\" | \"semibold\" | \"bold\";\n\n/**\n * Text component variants with auto-scaling line-height and letter-spacing.\n * Provides consistent paragraph and body text styling.\n *\n * @example\n * ```tsx\n * import { textVariants } from \"@minidev.fun/ui/lib/variants\"\n * import { cn } from \"@minidev.fun/ui/lib/utils\"\n *\n * <p className={cn(textVariants({ size: \"lg\", weight: \"medium\", align: \"center\" }))}>\n * Centered large text\n * </p>\n * ```\n */\nexport const textVariants = cva(\"\", {\n variants: {\n size: {\n xs: \"text-xs leading-4\",\n sm: \"text-sm leading-5\",\n base: \"text-base leading-6\",\n lg: \"text-lg leading-7\",\n xl: \"text-xl leading-7 tracking-tight\",\n \"2xl\": \"text-2xl leading-8 tracking-tighter\",\n },\n weight: {\n normal: \"font-normal\",\n medium: \"font-medium\",\n semibold: \"font-semibold\",\n bold: \"font-bold\",\n },\n align: {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n },\n transform: {\n uppercase: \"uppercase tracking-wider\",\n lowercase: \"lowercase\",\n capitalize: \"capitalize\",\n },\n },\n defaultVariants: {\n size: \"base\",\n },\n});\n"],"names":[],"mappings":";AAcO,MAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SACE;AAAA,QACF,aACE;AAAA,QACF,SACE;AAAA,QACF,SACE;AAAA,QACF,MAAM;AAAA,MAAA;AAAA,MAER,OAAO;AAAA,QACL,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,IAEF,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,OAAO;AAAA,IAAA;AAAA,EACT;AAEJ;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minidev.fun/ui",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "license": "MIT",
5
5
  "author": "Tokenfi Inc.",
6
6
  "description": "AI-first React component library for coding agents. LLM-optimized docs, sensible defaults, zero config. Built on shadcn patterns, Base UI, and Tailwind CSS v4.",
@@ -238,6 +238,10 @@
238
238
  "types": "./dist/components/ui/accordion.d.ts",
239
239
  "import": "./dist/components/ui/accordion.js"
240
240
  },
241
+ "./undefined": {
242
+ "types": "./dist/components/minidev.fun/undefined/index.d.ts",
243
+ "import": "./dist/components/minidev.fun/undefined/index.js"
244
+ },
241
245
  "./utils": {
242
246
  "types": "./dist/lib/utils.d.ts",
243
247
  "import": "./dist/lib/utils.js"
@@ -1 +0,0 @@
1
- {"version":3,"file":"variants.js","sources":["../../src/lib/variants.ts"],"sourcesContent":["/**\n * @internal\n * Shared CVA variants used by menu and typography components.\n * Not exported publicly - use component props instead:\n * - Menu styling: <DropdownMenuItem variant=\"destructive\">\n * - Typography: <Text color=\"muted\" size=\"sm\">\n */\n\nimport { cva } from \"class-variance-authority\";\n\n/**\n * Shared menu item variants for DropdownMenuItem, ContextMenuItem, and MenubarItem.\n * Provides consistent styling across all menu-style components.\n */\nexport const menuItemVariants = cva(\n \"gap-2 rounded-sm px-2 py-1.5 text-sm [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default:\n \"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground\",\n destructive:\n \"text-destructive focus:bg-destructive/10 dark:focus:bg-destructive/20 focus:text-destructive *:[svg]:text-destructive\",\n success:\n \"text-success focus:bg-success/10 dark:focus:bg-success/20 focus:text-success *:[svg]:text-success\",\n warning:\n \"text-warning focus:bg-warning/10 dark:focus:bg-warning/20 focus:text-warning *:[svg]:text-warning\",\n info: \"text-info focus:bg-info/10 dark:focus:bg-info/20 focus:text-info *:[svg]:text-info\",\n },\n inset: {\n true: \"pl-8\",\n false: \"\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n inset: false,\n },\n },\n);\n\n/** Variant options for menu items: default, destructive, success, warning, info */\nexport type MenuItemVariant =\n | \"default\"\n | \"destructive\"\n | \"success\"\n | \"warning\"\n | \"info\";\n\n/**\n * Typography color variants shared across Title, Text, Code, ListItem, and Blockquote components.\n * Provides semantic color options for consistent text styling.\n *\n * @example\n * ```tsx\n * import { typographyColorVariants } from \"@minidev.fun/ui/lib/variants\"\n * import { cn } from \"@minidev.fun/ui/lib/utils\"\n *\n * <span className={cn(typographyColorVariants({ color: \"muted\" }))}>\n * Secondary text\n * </span>\n * ```\n */\nexport const typographyColorVariants = cva(\"\", {\n variants: {\n color: {\n primary: \"text-primary\",\n default: \"text-foreground\",\n muted: \"text-muted-foreground\",\n subtle: \"text-subtle-foreground\",\n destructive: \"text-destructive\",\n success: \"text-success\",\n warning: \"text-warning\",\n info: \"text-info\",\n },\n },\n defaultVariants: {\n color: \"default\",\n },\n});\n\n/** Semantic color options for typography: default, muted, subtle, destructive, success, warning, info */\nexport type TypographyColor =\n | \"default\"\n | \"primary\"\n | \"muted\"\n | \"subtle\"\n | \"destructive\"\n | \"success\"\n | \"warning\"\n | \"info\";\n\n/**\n * Title order-based size defaults (only used when size prop is not specified).\n * Maps heading levels (h1-h6) to responsive font sizes.\n *\n * @example\n * ```tsx\n * // order: 1 → \"text-3xl md:text-4xl lg:text-5xl\"\n * // order: 6 → \"text-sm md:text-base lg:text-lg\"\n * ```\n */\nexport const titleOrderSizeVariants = cva(\"\", {\n variants: {\n order: {\n 1: \"text-3xl md:text-4xl lg:text-5xl\",\n 2: \"text-2xl md:text-3xl lg:text-4xl\",\n 3: \"text-xl md:text-2xl lg:text-3xl\",\n 4: \"text-lg md:text-xl lg:text-2xl\",\n 5: \"text-base md:text-lg lg:text-xl\",\n 6: \"text-sm md:text-base lg:text-lg\",\n },\n },\n});\n\n/**\n * Title order-based style defaults (weight, tracking, leading).\n * Provides appropriate font-weight and line-height for each heading level.\n *\n * @example\n * ```tsx\n * // order: 1 → \"font-bold tracking-tight leading-[1.1]\"\n * // order: 6 → \"font-medium leading-normal\"\n * ```\n */\nexport const titleOrderStyleVariants = cva(\"\", {\n variants: {\n order: {\n 1: \"font-bold tracking-tight leading-[1.1]\",\n 2: \"font-semibold tracking-tight leading-[1.2]\",\n 3: \"font-semibold tracking-tight leading-[1.25]\",\n 4: \"font-semibold leading-[1.3]\",\n 5: \"font-medium leading-[1.4]\",\n 6: \"font-medium leading-normal\",\n },\n },\n defaultVariants: {\n order: 2,\n },\n});\n\n/**\n * Title component variants for explicit size and weight overrides.\n * Use when you need to override the order-based defaults.\n *\n * @example\n * ```tsx\n * import { titleVariants } from \"@minidev.fun/ui/lib/variants\"\n * import { cn } from \"@minidev.fun/ui/lib/utils\"\n *\n * <h2 className={cn(titleVariants({ size: \"4xl\", weight: \"bold\" }))}>\n * Large Bold Title\n * </h2>\n * ```\n */\nexport const titleVariants = cva(\"\", {\n variants: {\n size: {\n xs: \"text-xs leading-4\",\n sm: \"text-sm leading-5\",\n base: \"text-base leading-6\",\n lg: \"text-lg leading-7\",\n xl: \"text-xl leading-7 tracking-tight\",\n \"2xl\": \"text-2xl leading-8 tracking-tight\",\n \"3xl\": \"text-3xl leading-9 tracking-tight\",\n \"4xl\": \"text-4xl leading-10 tracking-tighter\",\n \"5xl\": \"text-5xl leading-[1.1] tracking-tighter\",\n \"6xl\": \"text-6xl leading-[1.1] tracking-tighter\",\n },\n weight: {\n normal: \"font-normal\",\n medium: \"font-medium\",\n semibold: \"font-semibold\",\n bold: \"font-bold\",\n },\n },\n});\n\n/** Heading level 1-6, maps to h1-h6 elements */\nexport type TitleOrder = 1 | 2 | 3 | 4 | 5 | 6;\n\n/** Font size options from xs to 6xl */\nexport type TitleSize =\n | \"xs\"\n | \"sm\"\n | \"base\"\n | \"lg\"\n | \"xl\"\n | \"2xl\"\n | \"3xl\"\n | \"4xl\"\n | \"5xl\"\n | \"6xl\";\n\n/** Font weight options: normal, medium, semibold, bold */\nexport type TitleWeight = \"normal\" | \"medium\" | \"semibold\" | \"bold\";\n\n/**\n * Text component variants with auto-scaling line-height and letter-spacing.\n * Provides consistent paragraph and body text styling.\n *\n * @example\n * ```tsx\n * import { textVariants } from \"@minidev.fun/ui/lib/variants\"\n * import { cn } from \"@minidev.fun/ui/lib/utils\"\n *\n * <p className={cn(textVariants({ size: \"lg\", weight: \"medium\", align: \"center\" }))}>\n * Centered large text\n * </p>\n * ```\n */\nexport const textVariants = cva(\"\", {\n variants: {\n size: {\n xs: \"text-xs leading-4\",\n sm: \"text-sm leading-5\",\n base: \"text-base leading-6\",\n lg: \"text-lg leading-7\",\n xl: \"text-xl leading-7 tracking-tight\",\n \"2xl\": \"text-2xl leading-8 tracking-tighter\",\n },\n weight: {\n normal: \"font-normal\",\n medium: \"font-medium\",\n semibold: \"font-semibold\",\n bold: \"font-bold\",\n },\n align: {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n },\n transform: {\n uppercase: \"uppercase tracking-wider\",\n lowercase: \"lowercase\",\n capitalize: \"capitalize\",\n },\n },\n defaultVariants: {\n size: \"base\",\n },\n});\n"],"names":[],"mappings":";AAcO,MAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SACE;AAAA,QACF,aACE;AAAA,QACF,SACE;AAAA,QACF,SACE;AAAA,QACF,MAAM;AAAA,MAAA;AAAA,MAER,OAAO;AAAA,QACL,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,IAEF,iBAAiB;AAAA,MACf,SAAS;AAAA,MACT,OAAO;AAAA,IAAA;AAAA,EACT;AAEJ;"}