@pixpilot/shadcn-ui 0.28.0 → 0.30.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.
- package/dist/icon-selector/IconPicker.cjs +70 -39
- package/dist/icon-selector/IconPicker.d.cts +3 -0
- package/dist/icon-selector/IconPicker.d.ts +3 -0
- package/dist/icon-selector/IconPicker.js +69 -40
- package/dist/theme-toggle/ThemeModeDropdown.cjs +9 -9
- package/dist/theme-toggle/ThemeModeDropdown.d.cts +8 -8
- package/dist/theme-toggle/ThemeModeDropdown.d.ts +6 -6
- package/dist/theme-toggle/ThemeModeDropdown.js +9 -9
- package/dist/theme-toggle/ThemeModeSwitchInside.cjs +6 -6
- package/dist/theme-toggle/ThemeModeSwitchInside.d.cts +6 -6
- package/dist/theme-toggle/ThemeModeSwitchInside.d.ts +4 -4
- package/dist/theme-toggle/ThemeModeSwitchInside.js +6 -6
- package/dist/theme-toggle/ThemeModeSwitchOutside.cjs +4 -4
- package/dist/theme-toggle/ThemeModeSwitchOutside.d.cts +4 -4
- package/dist/theme-toggle/ThemeModeSwitchOutside.d.ts +4 -4
- package/dist/theme-toggle/ThemeModeSwitchOutside.js +4 -4
- package/dist/theme-toggle/ThemeModeToggleButton.cjs +5 -5
- package/dist/theme-toggle/ThemeModeToggleButton.d.cts +3 -3
- package/dist/theme-toggle/ThemeModeToggleButton.d.ts +3 -3
- package/dist/theme-toggle/ThemeModeToggleButton.js +5 -5
- package/package.json +2 -2
|
@@ -5,6 +5,10 @@ require('../hooks/index.cjs');
|
|
|
5
5
|
const require_constants = require('./constants.cjs');
|
|
6
6
|
const require_icon_picker_container = require('./icon-picker-container.cjs');
|
|
7
7
|
const require_icon_picker_content = require('./icon-picker-content.cjs');
|
|
8
|
+
let __pixpilot_shadcn = require("@pixpilot/shadcn");
|
|
9
|
+
__pixpilot_shadcn = require_rolldown_runtime.__toESM(__pixpilot_shadcn);
|
|
10
|
+
let lucide_react = require("lucide-react");
|
|
11
|
+
lucide_react = require_rolldown_runtime.__toESM(lucide_react);
|
|
8
12
|
let react = require("react");
|
|
9
13
|
react = require_rolldown_runtime.__toESM(react);
|
|
10
14
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -13,7 +17,7 @@ let __iconify_react = require("@iconify/react");
|
|
|
13
17
|
__iconify_react = require_rolldown_runtime.__toESM(__iconify_react);
|
|
14
18
|
|
|
15
19
|
//#region src/icon-selector/IconPicker.tsx
|
|
16
|
-
const IconPicker = ({ value, onChange, onOpenChange, pickerMode = "dialog", popover, variant = "default", providers: providersProp }) => {
|
|
20
|
+
const IconPicker = ({ value, onChange, onOpenChange, pickerMode = "dialog", popover, variant = "default", providers: providersProp, showValueText = true, emptyText = "+", showClearButton = true }) => {
|
|
17
21
|
const [isOpen, setIsOpen] = (0, react.useState)(false);
|
|
18
22
|
const isMobile = require_use_media_query.useMediaQuery({ maxWidth: 768 });
|
|
19
23
|
const handleSelectIcon = (0, react.useCallback)((iconName) => {
|
|
@@ -21,15 +25,25 @@ const IconPicker = ({ value, onChange, onOpenChange, pickerMode = "dialog", popo
|
|
|
21
25
|
setIsOpen(false);
|
|
22
26
|
onOpenChange?.(false);
|
|
23
27
|
}, [onChange, onOpenChange]);
|
|
28
|
+
const handleClearIcon = (0, react.useCallback)(() => {
|
|
29
|
+
onChange?.("");
|
|
30
|
+
setIsOpen(false);
|
|
31
|
+
onOpenChange?.(false);
|
|
32
|
+
}, [onChange, onOpenChange]);
|
|
24
33
|
const hasValue = typeof value === "string" && value.length > 0;
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
const renderIconDisplay = (emptyClassName, ariaHidden) => {
|
|
35
|
+
if (hasValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__iconify_react.Icon, {
|
|
36
|
+
icon: value,
|
|
37
|
+
width: "20",
|
|
38
|
+
height: "20"
|
|
39
|
+
});
|
|
40
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
41
|
+
"aria-hidden": ariaHidden,
|
|
42
|
+
className: (0, __pixpilot_shadcn.cn)("min-w-6 text-muted-foreground flex items-center justify-center", emptyClassName),
|
|
43
|
+
children: emptyText
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
const displayIcon = renderIconDisplay("text-sm");
|
|
33
47
|
const selectorContent = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icon_picker_content.default, {
|
|
34
48
|
providers: providersProp,
|
|
35
49
|
onChange: handleSelectIcon,
|
|
@@ -42,50 +56,67 @@ const IconPicker = ({ value, onChange, onOpenChange, pickerMode = "dialog", popo
|
|
|
42
56
|
else effectiveMode = pickerMode;
|
|
43
57
|
const isIconButtonVariant = variant === "icon-button";
|
|
44
58
|
const iconButtonLabel = hasValue ? `Change selected icon (${value})` : "Select an icon";
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
width: "20",
|
|
48
|
-
height: "20"
|
|
49
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
50
|
-
"aria-hidden": "true",
|
|
51
|
-
className: "text-muted-foreground text-lg",
|
|
52
|
-
children: "+"
|
|
53
|
-
});
|
|
59
|
+
const shouldShowClearButton = showClearButton && hasValue;
|
|
60
|
+
const iconButtonContent = renderIconDisplay("text-lg", true);
|
|
54
61
|
if (isIconButtonVariant) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icon_picker_container.IconPickerContainer, {
|
|
55
62
|
effectiveMode,
|
|
56
63
|
isOpen,
|
|
57
64
|
setIsOpen,
|
|
58
65
|
selectorContent,
|
|
59
66
|
popover,
|
|
60
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
68
|
+
className: "relative inline-flex",
|
|
69
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.Button, {
|
|
70
|
+
type: "button",
|
|
71
|
+
variant: "outline",
|
|
72
|
+
className: "p-2",
|
|
73
|
+
"aria-label": iconButtonLabel,
|
|
74
|
+
children: iconButtonContent
|
|
75
|
+
}), shouldShowClearButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.Button, {
|
|
76
|
+
type: "button",
|
|
77
|
+
title: "Clear selected icon",
|
|
78
|
+
className: (0, __pixpilot_shadcn.cn)("absolute -right-1 -top-1 inline-flex h-4 w-4 items-center justify-center rounded-full !p-1", "border border-border bg-background text-foreground", "hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"),
|
|
79
|
+
"aria-label": "Clear icon",
|
|
80
|
+
onClick: (event) => {
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
event.stopPropagation();
|
|
83
|
+
handleClearIcon();
|
|
84
|
+
},
|
|
85
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, { className: "!h-3 !w-3" })
|
|
86
|
+
})]
|
|
66
87
|
})
|
|
67
88
|
});
|
|
68
89
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
69
90
|
className: "flex items-center gap-2",
|
|
70
|
-
children: [
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
91
|
+
children: [
|
|
92
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
93
|
+
className: "flex items-center gap-2 rounded-md border border-input bg-background px-3 py-2",
|
|
94
|
+
children: [displayIcon, showValueText && hasValue && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
95
|
+
className: "text-sm text-muted-foreground",
|
|
96
|
+
children: value
|
|
97
|
+
})]
|
|
98
|
+
}),
|
|
99
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icon_picker_container.IconPickerContainer, {
|
|
100
|
+
effectiveMode,
|
|
101
|
+
isOpen,
|
|
102
|
+
setIsOpen,
|
|
103
|
+
selectorContent,
|
|
104
|
+
popover,
|
|
105
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.Button, {
|
|
106
|
+
type: "button",
|
|
107
|
+
variant: "outline",
|
|
108
|
+
className: "whitespace-nowrap",
|
|
109
|
+
children: hasValue ? "Change Icon" : "Select Icon"
|
|
110
|
+
})
|
|
111
|
+
}),
|
|
112
|
+
shouldShowClearButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button.Button, {
|
|
83
113
|
type: "button",
|
|
84
114
|
variant: "outline",
|
|
85
115
|
className: "whitespace-nowrap",
|
|
86
|
-
|
|
116
|
+
onClick: handleClearIcon,
|
|
117
|
+
children: "Clear"
|
|
87
118
|
})
|
|
88
|
-
|
|
119
|
+
]
|
|
89
120
|
});
|
|
90
121
|
};
|
|
91
122
|
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { Button } from "../Button.js";
|
|
1
|
+
import { Button as Button$1 } from "../Button.js";
|
|
2
2
|
import { useMediaQuery } from "../hooks/use-media-query.js";
|
|
3
3
|
import "../hooks/index.js";
|
|
4
4
|
import { ICON_SELECTOR_ERROR_MESSAGE } from "./constants.js";
|
|
5
5
|
import { IconPickerContainer } from "./icon-picker-container.js";
|
|
6
6
|
import icon_picker_content_default from "./icon-picker-content.js";
|
|
7
|
+
import { cn } from "@pixpilot/shadcn";
|
|
8
|
+
import { X } from "lucide-react";
|
|
7
9
|
import { useCallback, useState } from "react";
|
|
8
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
11
|
import { Icon } from "@iconify/react";
|
|
10
12
|
|
|
11
13
|
//#region src/icon-selector/IconPicker.tsx
|
|
12
|
-
const IconPicker = ({ value, onChange, onOpenChange, pickerMode = "dialog", popover, variant = "default", providers: providersProp }) => {
|
|
14
|
+
const IconPicker = ({ value, onChange, onOpenChange, pickerMode = "dialog", popover, variant = "default", providers: providersProp, showValueText = true, emptyText = "+", showClearButton = true }) => {
|
|
13
15
|
const [isOpen, setIsOpen] = useState(false);
|
|
14
16
|
const isMobile = useMediaQuery({ maxWidth: 768 });
|
|
15
17
|
const handleSelectIcon = useCallback((iconName) => {
|
|
@@ -17,15 +19,25 @@ const IconPicker = ({ value, onChange, onOpenChange, pickerMode = "dialog", popo
|
|
|
17
19
|
setIsOpen(false);
|
|
18
20
|
onOpenChange?.(false);
|
|
19
21
|
}, [onChange, onOpenChange]);
|
|
22
|
+
const handleClearIcon = useCallback(() => {
|
|
23
|
+
onChange?.("");
|
|
24
|
+
setIsOpen(false);
|
|
25
|
+
onOpenChange?.(false);
|
|
26
|
+
}, [onChange, onOpenChange]);
|
|
20
27
|
const hasValue = typeof value === "string" && value.length > 0;
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
const renderIconDisplay = (emptyClassName, ariaHidden) => {
|
|
29
|
+
if (hasValue) return /* @__PURE__ */ jsx(Icon, {
|
|
30
|
+
icon: value,
|
|
31
|
+
width: "20",
|
|
32
|
+
height: "20"
|
|
33
|
+
});
|
|
34
|
+
return /* @__PURE__ */ jsx("span", {
|
|
35
|
+
"aria-hidden": ariaHidden,
|
|
36
|
+
className: cn("min-w-6 text-muted-foreground flex items-center justify-center", emptyClassName),
|
|
37
|
+
children: emptyText
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
const displayIcon = renderIconDisplay("text-sm");
|
|
29
41
|
const selectorContent = /* @__PURE__ */ jsx(icon_picker_content_default, {
|
|
30
42
|
providers: providersProp,
|
|
31
43
|
onChange: handleSelectIcon,
|
|
@@ -37,50 +49,67 @@ const IconPicker = ({ value, onChange, onOpenChange, pickerMode = "dialog", popo
|
|
|
37
49
|
else effectiveMode = pickerMode;
|
|
38
50
|
const isIconButtonVariant = variant === "icon-button";
|
|
39
51
|
const iconButtonLabel = hasValue ? `Change selected icon (${value})` : "Select an icon";
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
width: "20",
|
|
43
|
-
height: "20"
|
|
44
|
-
}) : /* @__PURE__ */ jsx("span", {
|
|
45
|
-
"aria-hidden": "true",
|
|
46
|
-
className: "text-muted-foreground text-lg",
|
|
47
|
-
children: "+"
|
|
48
|
-
});
|
|
52
|
+
const shouldShowClearButton = showClearButton && hasValue;
|
|
53
|
+
const iconButtonContent = renderIconDisplay("text-lg", true);
|
|
49
54
|
if (isIconButtonVariant) return /* @__PURE__ */ jsx(IconPickerContainer, {
|
|
50
55
|
effectiveMode,
|
|
51
56
|
isOpen,
|
|
52
57
|
setIsOpen,
|
|
53
58
|
selectorContent,
|
|
54
59
|
popover,
|
|
55
|
-
children: /* @__PURE__ */
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
children: /* @__PURE__ */ jsxs("span", {
|
|
61
|
+
className: "relative inline-flex",
|
|
62
|
+
children: [/* @__PURE__ */ jsx(Button$1, {
|
|
63
|
+
type: "button",
|
|
64
|
+
variant: "outline",
|
|
65
|
+
className: "p-2",
|
|
66
|
+
"aria-label": iconButtonLabel,
|
|
67
|
+
children: iconButtonContent
|
|
68
|
+
}), shouldShowClearButton && /* @__PURE__ */ jsx(Button$1, {
|
|
69
|
+
type: "button",
|
|
70
|
+
title: "Clear selected icon",
|
|
71
|
+
className: cn("absolute -right-1 -top-1 inline-flex h-4 w-4 items-center justify-center rounded-full !p-1", "border border-border bg-background text-foreground", "hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"),
|
|
72
|
+
"aria-label": "Clear icon",
|
|
73
|
+
onClick: (event) => {
|
|
74
|
+
event.preventDefault();
|
|
75
|
+
event.stopPropagation();
|
|
76
|
+
handleClearIcon();
|
|
77
|
+
},
|
|
78
|
+
children: /* @__PURE__ */ jsx(X, { className: "!h-3 !w-3" })
|
|
79
|
+
})]
|
|
61
80
|
})
|
|
62
81
|
});
|
|
63
82
|
return /* @__PURE__ */ jsxs("div", {
|
|
64
83
|
className: "flex items-center gap-2",
|
|
65
|
-
children: [
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
84
|
+
children: [
|
|
85
|
+
/* @__PURE__ */ jsxs("div", {
|
|
86
|
+
className: "flex items-center gap-2 rounded-md border border-input bg-background px-3 py-2",
|
|
87
|
+
children: [displayIcon, showValueText && hasValue && /* @__PURE__ */ jsx("span", {
|
|
88
|
+
className: "text-sm text-muted-foreground",
|
|
89
|
+
children: value
|
|
90
|
+
})]
|
|
91
|
+
}),
|
|
92
|
+
/* @__PURE__ */ jsx(IconPickerContainer, {
|
|
93
|
+
effectiveMode,
|
|
94
|
+
isOpen,
|
|
95
|
+
setIsOpen,
|
|
96
|
+
selectorContent,
|
|
97
|
+
popover,
|
|
98
|
+
children: /* @__PURE__ */ jsx(Button$1, {
|
|
99
|
+
type: "button",
|
|
100
|
+
variant: "outline",
|
|
101
|
+
className: "whitespace-nowrap",
|
|
102
|
+
children: hasValue ? "Change Icon" : "Select Icon"
|
|
103
|
+
})
|
|
104
|
+
}),
|
|
105
|
+
shouldShowClearButton && /* @__PURE__ */ jsx(Button$1, {
|
|
78
106
|
type: "button",
|
|
79
107
|
variant: "outline",
|
|
80
108
|
className: "whitespace-nowrap",
|
|
81
|
-
|
|
109
|
+
onClick: handleClearIcon,
|
|
110
|
+
children: "Clear"
|
|
82
111
|
})
|
|
83
|
-
|
|
112
|
+
]
|
|
84
113
|
});
|
|
85
114
|
};
|
|
86
115
|
|
|
@@ -15,11 +15,11 @@ react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
|
|
|
15
15
|
/**
|
|
16
16
|
* Theme mode selector dropdown.
|
|
17
17
|
* Provides Light / Dark / System options.
|
|
18
|
-
* Pure component - requires
|
|
18
|
+
* Pure component - requires themeValue and onChange props.
|
|
19
19
|
*/
|
|
20
20
|
function ThemeModeDropdown(props) {
|
|
21
|
-
const { align = "end", className,
|
|
22
|
-
const isDark =
|
|
21
|
+
const { align = "end", className, themeValue, onChange, value, disabled } = props;
|
|
22
|
+
const isDark = value === "dark";
|
|
23
23
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuTrigger, {
|
|
24
24
|
asChild: true,
|
|
25
25
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Button, {
|
|
@@ -40,36 +40,36 @@ function ThemeModeDropdown(props) {
|
|
|
40
40
|
align,
|
|
41
41
|
children: [
|
|
42
42
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DropdownMenuItem, {
|
|
43
|
-
onClick: () =>
|
|
43
|
+
onClick: () => onChange?.("light"),
|
|
44
44
|
children: [
|
|
45
45
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Sun, { className: "h-4 w-4 mr-2" }),
|
|
46
46
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47
47
|
className: "flex-1",
|
|
48
48
|
children: "Light"
|
|
49
49
|
}),
|
|
50
|
-
|
|
50
|
+
themeValue === "light" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "h-4 w-4 ml-2" })
|
|
51
51
|
]
|
|
52
52
|
}),
|
|
53
53
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DropdownMenuItem, {
|
|
54
|
-
onClick: () =>
|
|
54
|
+
onClick: () => onChange?.("dark"),
|
|
55
55
|
children: [
|
|
56
56
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Moon, { className: "h-4 w-4 mr-2" }),
|
|
57
57
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
58
58
|
className: "flex-1",
|
|
59
59
|
children: "Dark"
|
|
60
60
|
}),
|
|
61
|
-
|
|
61
|
+
themeValue === "dark" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "h-4 w-4 ml-2" })
|
|
62
62
|
]
|
|
63
63
|
}),
|
|
64
64
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DropdownMenuItem, {
|
|
65
|
-
onClick: () =>
|
|
65
|
+
onClick: () => onChange?.("system"),
|
|
66
66
|
children: [
|
|
67
67
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Monitor, { className: "h-4 w-4 mr-2" }),
|
|
68
68
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
69
69
|
className: "flex-1",
|
|
70
70
|
children: "System"
|
|
71
71
|
}),
|
|
72
|
-
|
|
72
|
+
themeValue === "system" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "h-4 w-4 ml-2" })
|
|
73
73
|
]
|
|
74
74
|
})
|
|
75
75
|
]
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime11 from "react/jsx-runtime";
|
|
2
2
|
|
|
3
3
|
//#region src/theme-toggle/ThemeModeDropdown.d.ts
|
|
4
4
|
interface ThemeModeDropdownProps {
|
|
5
5
|
align?: 'start' | 'center' | 'end';
|
|
6
6
|
className?: string;
|
|
7
|
-
/** Current theme
|
|
8
|
-
|
|
7
|
+
/** Current theme selection ("light" | "dark" | "system") */
|
|
8
|
+
themeValue?: string;
|
|
9
9
|
/** Function to change the theme */
|
|
10
|
-
|
|
11
|
-
/** The resolved theme ("light" | "dark") */
|
|
12
|
-
|
|
10
|
+
onChange?: (theme: string) => void;
|
|
11
|
+
/** The resolved theme value ("light" | "dark") */
|
|
12
|
+
value?: string;
|
|
13
13
|
disabled?: boolean;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* Theme mode selector dropdown.
|
|
17
17
|
* Provides Light / Dark / System options.
|
|
18
|
-
* Pure component - requires
|
|
18
|
+
* Pure component - requires themeValue and onChange props.
|
|
19
19
|
*/
|
|
20
|
-
declare function ThemeModeDropdown(props: ThemeModeDropdownProps):
|
|
20
|
+
declare function ThemeModeDropdown(props: ThemeModeDropdownProps): react_jsx_runtime11.JSX.Element;
|
|
21
21
|
declare namespace ThemeModeDropdown {
|
|
22
22
|
var displayName: string;
|
|
23
23
|
}
|
|
@@ -4,18 +4,18 @@ import * as react_jsx_runtime10 from "react/jsx-runtime";
|
|
|
4
4
|
interface ThemeModeDropdownProps {
|
|
5
5
|
align?: 'start' | 'center' | 'end';
|
|
6
6
|
className?: string;
|
|
7
|
-
/** Current theme
|
|
8
|
-
|
|
7
|
+
/** Current theme selection ("light" | "dark" | "system") */
|
|
8
|
+
themeValue?: string;
|
|
9
9
|
/** Function to change the theme */
|
|
10
|
-
|
|
11
|
-
/** The resolved theme ("light" | "dark") */
|
|
12
|
-
|
|
10
|
+
onChange?: (theme: string) => void;
|
|
11
|
+
/** The resolved theme value ("light" | "dark") */
|
|
12
|
+
value?: string;
|
|
13
13
|
disabled?: boolean;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* Theme mode selector dropdown.
|
|
17
17
|
* Provides Light / Dark / System options.
|
|
18
|
-
* Pure component - requires
|
|
18
|
+
* Pure component - requires themeValue and onChange props.
|
|
19
19
|
*/
|
|
20
20
|
declare function ThemeModeDropdown(props: ThemeModeDropdownProps): react_jsx_runtime10.JSX.Element;
|
|
21
21
|
declare namespace ThemeModeDropdown {
|
|
@@ -10,11 +10,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
/**
|
|
11
11
|
* Theme mode selector dropdown.
|
|
12
12
|
* Provides Light / Dark / System options.
|
|
13
|
-
* Pure component - requires
|
|
13
|
+
* Pure component - requires themeValue and onChange props.
|
|
14
14
|
*/
|
|
15
15
|
function ThemeModeDropdown(props) {
|
|
16
|
-
const { align = "end", className,
|
|
17
|
-
const isDark =
|
|
16
|
+
const { align = "end", className, themeValue, onChange, value, disabled } = props;
|
|
17
|
+
const isDark = value === "dark";
|
|
18
18
|
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
|
|
19
19
|
asChild: true,
|
|
20
20
|
children: /* @__PURE__ */ jsxs(Button, {
|
|
@@ -35,36 +35,36 @@ function ThemeModeDropdown(props) {
|
|
|
35
35
|
align,
|
|
36
36
|
children: [
|
|
37
37
|
/* @__PURE__ */ jsxs(DropdownMenuItem, {
|
|
38
|
-
onClick: () =>
|
|
38
|
+
onClick: () => onChange?.("light"),
|
|
39
39
|
children: [
|
|
40
40
|
/* @__PURE__ */ jsx(Sun, { className: "h-4 w-4 mr-2" }),
|
|
41
41
|
/* @__PURE__ */ jsx("span", {
|
|
42
42
|
className: "flex-1",
|
|
43
43
|
children: "Light"
|
|
44
44
|
}),
|
|
45
|
-
|
|
45
|
+
themeValue === "light" && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 ml-2" })
|
|
46
46
|
]
|
|
47
47
|
}),
|
|
48
48
|
/* @__PURE__ */ jsxs(DropdownMenuItem, {
|
|
49
|
-
onClick: () =>
|
|
49
|
+
onClick: () => onChange?.("dark"),
|
|
50
50
|
children: [
|
|
51
51
|
/* @__PURE__ */ jsx(Moon, { className: "h-4 w-4 mr-2" }),
|
|
52
52
|
/* @__PURE__ */ jsx("span", {
|
|
53
53
|
className: "flex-1",
|
|
54
54
|
children: "Dark"
|
|
55
55
|
}),
|
|
56
|
-
|
|
56
|
+
themeValue === "dark" && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 ml-2" })
|
|
57
57
|
]
|
|
58
58
|
}),
|
|
59
59
|
/* @__PURE__ */ jsxs(DropdownMenuItem, {
|
|
60
|
-
onClick: () =>
|
|
60
|
+
onClick: () => onChange?.("system"),
|
|
61
61
|
children: [
|
|
62
62
|
/* @__PURE__ */ jsx(Monitor, { className: "h-4 w-4 mr-2" }),
|
|
63
63
|
/* @__PURE__ */ jsx("span", {
|
|
64
64
|
className: "flex-1",
|
|
65
65
|
children: "System"
|
|
66
66
|
}),
|
|
67
|
-
|
|
67
|
+
themeValue === "system" && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 ml-2" })
|
|
68
68
|
]
|
|
69
69
|
})
|
|
70
70
|
]
|
|
@@ -16,9 +16,9 @@ const ICON_CLASS_NAME = (0, __pixpilot_shadcn.cn)("pointer-events-none rounded-f
|
|
|
16
16
|
const SWITCH_OVERLAY_CLASS_NAME = (0, __pixpilot_shadcn.cn)("absolute inset-0 h-full w-full opacity-0 cursor-pointer rounded-full", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", "ring-offset-background disabled:cursor-not-allowed");
|
|
17
17
|
const SIZE_STYLES = {
|
|
18
18
|
sm: {
|
|
19
|
-
wrapper: "h-
|
|
19
|
+
wrapper: "h-7",
|
|
20
20
|
iconPadding: "p-1",
|
|
21
|
-
defaultIconSize:
|
|
21
|
+
defaultIconSize: 20
|
|
22
22
|
},
|
|
23
23
|
md: {
|
|
24
24
|
wrapper: "h-8/5",
|
|
@@ -34,15 +34,15 @@ const SIZE_STYLES = {
|
|
|
34
34
|
/**
|
|
35
35
|
* Light/Dark theme switch with icons inside the switch.
|
|
36
36
|
* Icons are embedded within the switch control.
|
|
37
|
-
* Pure component - requires
|
|
37
|
+
* Pure component - requires value and onChange props.
|
|
38
38
|
*/
|
|
39
39
|
function ThemeModeSwitchInside(props) {
|
|
40
|
-
const { showIcons = true, size = "md", iconSize: iconSizeProp, className, switchClassName, disabled, ariaLabel = "Toggle theme",
|
|
40
|
+
const { showIcons = true, size = "md", iconSize: iconSizeProp, className, switchClassName, disabled, ariaLabel = "Toggle theme", value, onChange } = props;
|
|
41
41
|
const sizeStyles = SIZE_STYLES[size];
|
|
42
42
|
const iconSize = iconSizeProp ?? sizeStyles.defaultIconSize ?? DEFAULT_ICON_SIZE;
|
|
43
|
-
const isDark =
|
|
43
|
+
const isDark = value === "dark";
|
|
44
44
|
const onCheckedChange = (checked) => {
|
|
45
|
-
|
|
45
|
+
onChange?.(checked ? "dark" : "light");
|
|
46
46
|
};
|
|
47
47
|
if (!showIcons) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Switch, {
|
|
48
48
|
checked: isDark,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react_jsx_runtime10 from "react/jsx-runtime";
|
|
2
2
|
|
|
3
3
|
//#region src/theme-toggle/ThemeModeSwitchInside.d.ts
|
|
4
4
|
type ThemeModeSwitchInsideSize = 'sm' | 'md' | 'lg';
|
|
@@ -15,17 +15,17 @@ interface ThemeModeSwitchInsideProps {
|
|
|
15
15
|
switchClassName?: string;
|
|
16
16
|
disabled?: boolean;
|
|
17
17
|
ariaLabel?: string;
|
|
18
|
-
/** The resolved theme ("light" | "dark") */
|
|
19
|
-
|
|
18
|
+
/** The resolved theme value ("light" | "dark") */
|
|
19
|
+
value?: string;
|
|
20
20
|
/** Function to change the theme */
|
|
21
|
-
|
|
21
|
+
onChange?: (theme: string) => void;
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
24
|
* Light/Dark theme switch with icons inside the switch.
|
|
25
25
|
* Icons are embedded within the switch control.
|
|
26
|
-
* Pure component - requires
|
|
26
|
+
* Pure component - requires value and onChange props.
|
|
27
27
|
*/
|
|
28
|
-
declare function ThemeModeSwitchInside(props: ThemeModeSwitchInsideProps):
|
|
28
|
+
declare function ThemeModeSwitchInside(props: ThemeModeSwitchInsideProps): react_jsx_runtime10.JSX.Element;
|
|
29
29
|
declare namespace ThemeModeSwitchInside {
|
|
30
30
|
var displayName: string;
|
|
31
31
|
}
|
|
@@ -15,15 +15,15 @@ interface ThemeModeSwitchInsideProps {
|
|
|
15
15
|
switchClassName?: string;
|
|
16
16
|
disabled?: boolean;
|
|
17
17
|
ariaLabel?: string;
|
|
18
|
-
/** The resolved theme ("light" | "dark") */
|
|
19
|
-
|
|
18
|
+
/** The resolved theme value ("light" | "dark") */
|
|
19
|
+
value?: string;
|
|
20
20
|
/** Function to change the theme */
|
|
21
|
-
|
|
21
|
+
onChange?: (theme: string) => void;
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
24
|
* Light/Dark theme switch with icons inside the switch.
|
|
25
25
|
* Icons are embedded within the switch control.
|
|
26
|
-
* Pure component - requires
|
|
26
|
+
* Pure component - requires value and onChange props.
|
|
27
27
|
*/
|
|
28
28
|
declare function ThemeModeSwitchInside(props: ThemeModeSwitchInsideProps): react_jsx_runtime11.JSX.Element;
|
|
29
29
|
declare namespace ThemeModeSwitchInside {
|
|
@@ -12,9 +12,9 @@ const ICON_CLASS_NAME = cn("pointer-events-none rounded-full transition-colors")
|
|
|
12
12
|
const SWITCH_OVERLAY_CLASS_NAME = cn("absolute inset-0 h-full w-full opacity-0 cursor-pointer rounded-full", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", "ring-offset-background disabled:cursor-not-allowed");
|
|
13
13
|
const SIZE_STYLES = {
|
|
14
14
|
sm: {
|
|
15
|
-
wrapper: "h-
|
|
15
|
+
wrapper: "h-7",
|
|
16
16
|
iconPadding: "p-1",
|
|
17
|
-
defaultIconSize:
|
|
17
|
+
defaultIconSize: 20
|
|
18
18
|
},
|
|
19
19
|
md: {
|
|
20
20
|
wrapper: "h-8/5",
|
|
@@ -30,15 +30,15 @@ const SIZE_STYLES = {
|
|
|
30
30
|
/**
|
|
31
31
|
* Light/Dark theme switch with icons inside the switch.
|
|
32
32
|
* Icons are embedded within the switch control.
|
|
33
|
-
* Pure component - requires
|
|
33
|
+
* Pure component - requires value and onChange props.
|
|
34
34
|
*/
|
|
35
35
|
function ThemeModeSwitchInside(props) {
|
|
36
|
-
const { showIcons = true, size = "md", iconSize: iconSizeProp, className, switchClassName, disabled, ariaLabel = "Toggle theme",
|
|
36
|
+
const { showIcons = true, size = "md", iconSize: iconSizeProp, className, switchClassName, disabled, ariaLabel = "Toggle theme", value, onChange } = props;
|
|
37
37
|
const sizeStyles = SIZE_STYLES[size];
|
|
38
38
|
const iconSize = iconSizeProp ?? sizeStyles.defaultIconSize ?? DEFAULT_ICON_SIZE;
|
|
39
|
-
const isDark =
|
|
39
|
+
const isDark = value === "dark";
|
|
40
40
|
const onCheckedChange = (checked) => {
|
|
41
|
-
|
|
41
|
+
onChange?.(checked ? "dark" : "light");
|
|
42
42
|
};
|
|
43
43
|
if (!showIcons) return /* @__PURE__ */ jsx(Switch, {
|
|
44
44
|
checked: isDark,
|
|
@@ -16,13 +16,13 @@ const DEFAULT_ICON_SIZE = 16;
|
|
|
16
16
|
/**
|
|
17
17
|
* Light/Dark theme switch with icons outside the switch.
|
|
18
18
|
* Icons flank the switch control on either side.
|
|
19
|
-
* Pure component - requires
|
|
19
|
+
* Pure component - requires value and onChange props.
|
|
20
20
|
*/
|
|
21
21
|
function ThemeModeSwitchOutside(props) {
|
|
22
|
-
const { showIcons = true, iconSize = DEFAULT_ICON_SIZE, className, switchClassName, disabled, ariaLabel = "Toggle theme",
|
|
23
|
-
const isDark =
|
|
22
|
+
const { showIcons = true, iconSize = DEFAULT_ICON_SIZE, className, switchClassName, disabled, ariaLabel = "Toggle theme", value, onChange } = props;
|
|
23
|
+
const isDark = value === "dark";
|
|
24
24
|
const onCheckedChange = (checked) => {
|
|
25
|
-
|
|
25
|
+
onChange?.(checked ? "dark" : "light");
|
|
26
26
|
};
|
|
27
27
|
if (!showIcons) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Switch, {
|
|
28
28
|
checked: isDark,
|
|
@@ -12,15 +12,15 @@ interface ThemeModeSwitchOutsideProps {
|
|
|
12
12
|
switchClassName?: string;
|
|
13
13
|
disabled?: boolean;
|
|
14
14
|
ariaLabel?: string;
|
|
15
|
-
/** The resolved theme ("light" | "dark") */
|
|
16
|
-
|
|
15
|
+
/** The resolved theme value ("light" | "dark") */
|
|
16
|
+
value?: string;
|
|
17
17
|
/** Function to change the theme */
|
|
18
|
-
|
|
18
|
+
onChange?: (theme: string) => void;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Light/Dark theme switch with icons outside the switch.
|
|
22
22
|
* Icons flank the switch control on either side.
|
|
23
|
-
* Pure component - requires
|
|
23
|
+
* Pure component - requires value and onChange props.
|
|
24
24
|
*/
|
|
25
25
|
declare function ThemeModeSwitchOutside(props: ThemeModeSwitchOutsideProps): react_jsx_runtime12.JSX.Element;
|
|
26
26
|
declare namespace ThemeModeSwitchOutside {
|
|
@@ -12,15 +12,15 @@ interface ThemeModeSwitchOutsideProps {
|
|
|
12
12
|
switchClassName?: string;
|
|
13
13
|
disabled?: boolean;
|
|
14
14
|
ariaLabel?: string;
|
|
15
|
-
/** The resolved theme ("light" | "dark") */
|
|
16
|
-
|
|
15
|
+
/** The resolved theme value ("light" | "dark") */
|
|
16
|
+
value?: string;
|
|
17
17
|
/** Function to change the theme */
|
|
18
|
-
|
|
18
|
+
onChange?: (theme: string) => void;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Light/Dark theme switch with icons outside the switch.
|
|
22
22
|
* Icons flank the switch control on either side.
|
|
23
|
-
* Pure component - requires
|
|
23
|
+
* Pure component - requires value and onChange props.
|
|
24
24
|
*/
|
|
25
25
|
declare function ThemeModeSwitchOutside(props: ThemeModeSwitchOutsideProps): react_jsx_runtime12.JSX.Element;
|
|
26
26
|
declare namespace ThemeModeSwitchOutside {
|
|
@@ -11,13 +11,13 @@ const DEFAULT_ICON_SIZE = 16;
|
|
|
11
11
|
/**
|
|
12
12
|
* Light/Dark theme switch with icons outside the switch.
|
|
13
13
|
* Icons flank the switch control on either side.
|
|
14
|
-
* Pure component - requires
|
|
14
|
+
* Pure component - requires value and onChange props.
|
|
15
15
|
*/
|
|
16
16
|
function ThemeModeSwitchOutside(props) {
|
|
17
|
-
const { showIcons = true, iconSize = DEFAULT_ICON_SIZE, className, switchClassName, disabled, ariaLabel = "Toggle theme",
|
|
18
|
-
const isDark =
|
|
17
|
+
const { showIcons = true, iconSize = DEFAULT_ICON_SIZE, className, switchClassName, disabled, ariaLabel = "Toggle theme", value, onChange } = props;
|
|
18
|
+
const isDark = value === "dark";
|
|
19
19
|
const onCheckedChange = (checked) => {
|
|
20
|
-
|
|
20
|
+
onChange?.(checked ? "dark" : "light");
|
|
21
21
|
};
|
|
22
22
|
if (!showIcons) return /* @__PURE__ */ jsx(Switch, {
|
|
23
23
|
checked: isDark,
|
|
@@ -17,14 +17,14 @@ react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
|
|
|
17
17
|
* Pure component - toggles between light and dark.
|
|
18
18
|
*/
|
|
19
19
|
function ThemeModeToggleButton(props) {
|
|
20
|
-
const { className,
|
|
20
|
+
const { className, value, onChange, disabled } = props;
|
|
21
21
|
const toggleTheme = react.default.useCallback(() => {
|
|
22
|
-
if (
|
|
23
|
-
|
|
22
|
+
if (value === "dark") {
|
|
23
|
+
onChange?.("light");
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
}, [
|
|
26
|
+
onChange?.("dark");
|
|
27
|
+
}, [value, onChange]);
|
|
28
28
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Button, {
|
|
29
29
|
variant: "secondary",
|
|
30
30
|
size: "icon",
|
|
@@ -3,10 +3,10 @@ import * as react_jsx_runtime9 from "react/jsx-runtime";
|
|
|
3
3
|
//#region src/theme-toggle/ThemeModeToggleButton.d.ts
|
|
4
4
|
interface ThemeModeToggleButtonProps {
|
|
5
5
|
className?: string;
|
|
6
|
-
/** The resolved theme ("light" | "dark") */
|
|
7
|
-
|
|
6
|
+
/** The resolved theme value ("light" | "dark") */
|
|
7
|
+
value?: string;
|
|
8
8
|
/** Function to change the theme */
|
|
9
|
-
|
|
9
|
+
onChange?: (theme: string) => void;
|
|
10
10
|
disabled?: boolean;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
@@ -3,10 +3,10 @@ import * as react_jsx_runtime9 from "react/jsx-runtime";
|
|
|
3
3
|
//#region src/theme-toggle/ThemeModeToggleButton.d.ts
|
|
4
4
|
interface ThemeModeToggleButtonProps {
|
|
5
5
|
className?: string;
|
|
6
|
-
/** The resolved theme ("light" | "dark") */
|
|
7
|
-
|
|
6
|
+
/** The resolved theme value ("light" | "dark") */
|
|
7
|
+
value?: string;
|
|
8
8
|
/** Function to change the theme */
|
|
9
|
-
|
|
9
|
+
onChange?: (theme: string) => void;
|
|
10
10
|
disabled?: boolean;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
@@ -12,14 +12,14 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
12
12
|
* Pure component - toggles between light and dark.
|
|
13
13
|
*/
|
|
14
14
|
function ThemeModeToggleButton(props) {
|
|
15
|
-
const { className,
|
|
15
|
+
const { className, value, onChange, disabled } = props;
|
|
16
16
|
const toggleTheme = React.useCallback(() => {
|
|
17
|
-
if (
|
|
18
|
-
|
|
17
|
+
if (value === "dark") {
|
|
18
|
+
onChange?.("light");
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
|
-
|
|
22
|
-
}, [
|
|
21
|
+
onChange?.("dark");
|
|
22
|
+
}, [value, onChange]);
|
|
23
23
|
return /* @__PURE__ */ jsxs(Button, {
|
|
24
24
|
variant: "secondary",
|
|
25
25
|
size: "icon",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixpilot/shadcn-ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.30.0",
|
|
5
5
|
"description": "Custom UI components and utilities built with shadcn/ui.",
|
|
6
6
|
"author": "m.doaie <m.doaie@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
"tsdown": "^0.15.12",
|
|
59
59
|
"typescript": "^5.9.3",
|
|
60
60
|
"@internal/eslint-config": "0.3.0",
|
|
61
|
-
"@internal/hooks": "0.0.0",
|
|
62
61
|
"@internal/prettier-config": "0.0.1",
|
|
62
|
+
"@internal/hooks": "0.0.0",
|
|
63
63
|
"@internal/tsconfig": "0.1.0",
|
|
64
64
|
"@internal/tsdown-config": "0.1.0",
|
|
65
65
|
"@internal/vitest-config": "0.1.0"
|