@pixpilot/shadcn 0.7.0 → 0.8.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/components/index.cjs +1 -0
- package/dist/components/index.d.cts +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/ui/alert.d.cts +4 -4
- package/dist/components/ui/index.cjs +1 -0
- package/dist/components/ui/index.d.cts +1 -0
- package/dist/components/ui/index.d.ts +1 -0
- package/dist/components/ui/index.js +1 -0
- package/dist/components/ui/rating.cjs +160 -0
- package/dist/components/ui/rating.d.cts +112 -0
- package/dist/components/ui/rating.d.ts +112 -0
- package/dist/components/ui/rating.js +153 -0
- package/dist/components/ui/select.d.cts +11 -11
- package/dist/components/ui/select.d.ts +11 -11
- package/dist/components/ui/separator.d.cts +2 -2
- package/dist/components/ui/separator.d.ts +2 -2
- package/dist/components/ui/shadcn-io/tags/index.d.cts +9 -9
- package/dist/components/ui/shadcn-io/tags/index.d.ts +9 -9
- package/dist/components/ui/shadcn-io/tags-input-inline/index.d.cts +7 -7
- package/dist/components/ui/shadcn-io/tags-input-inline/index.d.ts +7 -7
- package/dist/components/ui/sheet.d.cts +9 -9
- package/dist/components/ui/sheet.d.ts +9 -9
- package/dist/components/ui/slider.d.cts +2 -2
- package/dist/components/ui/slider.d.ts +2 -2
- package/dist/components/ui/switch.d.cts +2 -2
- package/dist/components/ui/switch.d.ts +2 -2
- package/dist/components/ui/tabs.d.cts +8 -8
- package/dist/components/ui/tabs.d.ts +8 -8
- package/dist/components/ui/textarea.d.cts +2 -2
- package/dist/components/ui/textarea.d.ts +2 -2
- package/dist/components/ui/tooltip.d.cts +5 -5
- package/dist/index.cjs +5 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/package.json +2 -2
|
@@ -22,6 +22,7 @@ const require_separator = require('./ui/separator.cjs');
|
|
|
22
22
|
const require_OrContinueWithSeparator = require('./ui/OrContinueWithSeparator.cjs');
|
|
23
23
|
const require_pagination = require('./ui/pagination.cjs');
|
|
24
24
|
const require_radio_group = require('./ui/radio-group.cjs');
|
|
25
|
+
const require_rating = require('./ui/rating.cjs');
|
|
25
26
|
const require_index = require('./ui/shadcn-io/tags/index.cjs');
|
|
26
27
|
const require_index$1 = require('./ui/shadcn-io/tags-input-inline/index.cjs');
|
|
27
28
|
const require_sheet = require('./ui/sheet.cjs');
|
|
@@ -20,6 +20,7 @@ import { Label } from "./ui/label.cjs";
|
|
|
20
20
|
import { OrContinueWithSeparator } from "./ui/OrContinueWithSeparator.cjs";
|
|
21
21
|
import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from "./ui/pagination.cjs";
|
|
22
22
|
import { RadioGroup, RadioGroupItem } from "./ui/radio-group.cjs";
|
|
23
|
+
import { Rating, RatingButton, RatingButtonProps, RatingProps, useRating } from "./ui/rating.cjs";
|
|
23
24
|
import { Separator } from "./ui/separator.cjs";
|
|
24
25
|
import { Tags, TagsContent, TagsContentProps, TagsEmpty, TagsEmptyProps, TagsGroup, TagsGroupProps, TagsInput, TagsInputProps, TagsItem, TagsItemProps, TagsList, TagsListProps, TagsProps, TagsTrigger, TagsTriggerProps, TagsValue, TagsValueProps } from "./ui/shadcn-io/tags/index.cjs";
|
|
25
26
|
import { TagsInputInLineClear, TagsInputInLineInput, TagsInputInLineItem, TagsInputInLineLabel, TagsInputInLineList, TagsInputInLineRoot } from "./ui/shadcn-io/tags-input-inline/index.cjs";
|
|
@@ -20,6 +20,7 @@ import { Label } from "./ui/label.js";
|
|
|
20
20
|
import { OrContinueWithSeparator } from "./ui/OrContinueWithSeparator.js";
|
|
21
21
|
import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from "./ui/pagination.js";
|
|
22
22
|
import { RadioGroup, RadioGroupItem } from "./ui/radio-group.js";
|
|
23
|
+
import { Rating, RatingButton, RatingButtonProps, RatingProps, useRating } from "./ui/rating.js";
|
|
23
24
|
import { Separator } from "./ui/separator.js";
|
|
24
25
|
import { Tags, TagsContent, TagsContentProps, TagsEmpty, TagsEmptyProps, TagsGroup, TagsGroupProps, TagsInput, TagsInputProps, TagsItem, TagsItemProps, TagsList, TagsListProps, TagsProps, TagsTrigger, TagsTriggerProps, TagsValue, TagsValueProps } from "./ui/shadcn-io/tags/index.js";
|
|
25
26
|
import { TagsInputInLineClear, TagsInputInLineInput, TagsInputInLineItem, TagsInputInLineLabel, TagsInputInLineList, TagsInputInLineRoot } from "./ui/shadcn-io/tags-input-inline/index.js";
|
package/dist/components/index.js
CHANGED
|
@@ -22,6 +22,7 @@ import { Separator } from "./ui/separator.js";
|
|
|
22
22
|
import { OrContinueWithSeparator } from "./ui/OrContinueWithSeparator.js";
|
|
23
23
|
import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from "./ui/pagination.js";
|
|
24
24
|
import { RadioGroup, RadioGroupItem } from "./ui/radio-group.js";
|
|
25
|
+
import { Rating, RatingButton, useRating } from "./ui/rating.js";
|
|
25
26
|
import { Tags, TagsContent, TagsEmpty, TagsGroup, TagsInput, TagsItem, TagsList, TagsTrigger, TagsValue } from "./ui/shadcn-io/tags/index.js";
|
|
26
27
|
import { TagsInputInLineClear, TagsInputInLineInput, TagsInputInLineItem, TagsInputInLineLabel, TagsInputInLineList, TagsInputInLineRoot } from "./ui/shadcn-io/tags-input-inline/index.js";
|
|
27
28
|
import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from "./ui/sheet.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as class_variance_authority_types0 from "class-variance-authority/types";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
3
|
import { VariantProps } from "class-variance-authority";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
|
|
@@ -11,14 +11,14 @@ declare function Alert({
|
|
|
11
11
|
className,
|
|
12
12
|
variant,
|
|
13
13
|
...props
|
|
14
|
-
}: React.ComponentProps<'div'> & VariantProps<typeof alertVariants>):
|
|
14
|
+
}: React.ComponentProps<'div'> & VariantProps<typeof alertVariants>): react_jsx_runtime0.JSX.Element;
|
|
15
15
|
declare function AlertTitle({
|
|
16
16
|
className,
|
|
17
17
|
...props
|
|
18
|
-
}: React.ComponentProps<'div'>):
|
|
18
|
+
}: React.ComponentProps<'div'>): react_jsx_runtime0.JSX.Element;
|
|
19
19
|
declare function AlertDescription({
|
|
20
20
|
className,
|
|
21
21
|
...props
|
|
22
|
-
}: React.ComponentProps<'div'>):
|
|
22
|
+
}: React.ComponentProps<'div'>): react_jsx_runtime0.JSX.Element;
|
|
23
23
|
//#endregion
|
|
24
24
|
export { Alert, AlertDescription, AlertTitle };
|
|
@@ -22,6 +22,7 @@ const require_separator = require('./separator.cjs');
|
|
|
22
22
|
const require_OrContinueWithSeparator = require('./OrContinueWithSeparator.cjs');
|
|
23
23
|
const require_pagination = require('./pagination.cjs');
|
|
24
24
|
const require_radio_group = require('./radio-group.cjs');
|
|
25
|
+
const require_rating = require('./rating.cjs');
|
|
25
26
|
const require_index = require('./shadcn-io/tags/index.cjs');
|
|
26
27
|
const require_index$1 = require('./shadcn-io/tags-input-inline/index.cjs');
|
|
27
28
|
const require_sheet = require('./sheet.cjs');
|
|
@@ -20,6 +20,7 @@ import { Label } from "./label.cjs";
|
|
|
20
20
|
import { OrContinueWithSeparator } from "./OrContinueWithSeparator.cjs";
|
|
21
21
|
import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from "./pagination.cjs";
|
|
22
22
|
import { RadioGroup, RadioGroupItem } from "./radio-group.cjs";
|
|
23
|
+
import { Rating, RatingButton, RatingButtonProps, RatingProps, useRating } from "./rating.cjs";
|
|
23
24
|
import { Separator } from "./separator.cjs";
|
|
24
25
|
import { Tags, TagsContent, TagsContentProps, TagsEmpty, TagsEmptyProps, TagsGroup, TagsGroupProps, TagsInput, TagsInputProps, TagsItem, TagsItemProps, TagsList, TagsListProps, TagsProps, TagsTrigger, TagsTriggerProps, TagsValue, TagsValueProps } from "./shadcn-io/tags/index.cjs";
|
|
25
26
|
import { TagsInputInLineClear, TagsInputInLineInput, TagsInputInLineItem, TagsInputInLineLabel, TagsInputInLineList, TagsInputInLineRoot } from "./shadcn-io/tags-input-inline/index.cjs";
|
|
@@ -20,6 +20,7 @@ import { Label } from "./label.js";
|
|
|
20
20
|
import { OrContinueWithSeparator } from "./OrContinueWithSeparator.js";
|
|
21
21
|
import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from "./pagination.js";
|
|
22
22
|
import { RadioGroup, RadioGroupItem } from "./radio-group.js";
|
|
23
|
+
import { Rating, RatingButton, RatingButtonProps, RatingProps, useRating } from "./rating.js";
|
|
23
24
|
import { Separator } from "./separator.js";
|
|
24
25
|
import { Tags, TagsContent, TagsContentProps, TagsEmpty, TagsEmptyProps, TagsGroup, TagsGroupProps, TagsInput, TagsInputProps, TagsItem, TagsItemProps, TagsList, TagsListProps, TagsProps, TagsTrigger, TagsTriggerProps, TagsValue, TagsValueProps } from "./shadcn-io/tags/index.js";
|
|
25
26
|
import { TagsInputInLineClear, TagsInputInLineInput, TagsInputInLineItem, TagsInputInLineLabel, TagsInputInLineList, TagsInputInLineRoot } from "./shadcn-io/tags-input-inline/index.js";
|
|
@@ -22,6 +22,7 @@ import { Separator } from "./separator.js";
|
|
|
22
22
|
import { OrContinueWithSeparator } from "./OrContinueWithSeparator.js";
|
|
23
23
|
import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from "./pagination.js";
|
|
24
24
|
import { RadioGroup, RadioGroupItem } from "./radio-group.js";
|
|
25
|
+
import { Rating, RatingButton, useRating } from "./rating.js";
|
|
25
26
|
import { Tags, TagsContent, TagsEmpty, TagsGroup, TagsInput, TagsItem, TagsList, TagsTrigger, TagsValue } from "./shadcn-io/tags/index.js";
|
|
26
27
|
import { TagsInputInLineClear, TagsInputInLineInput, TagsInputInLineItem, TagsInputInLineLabel, TagsInputInLineList, TagsInputInLineRoot } from "./shadcn-io/tags-input-inline/index.js";
|
|
27
28
|
import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from "./sheet.js";
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_utils = require('../../lib/utils.cjs');
|
|
3
|
+
require('../../lib/index.cjs');
|
|
4
|
+
let class_variance_authority = require("class-variance-authority");
|
|
5
|
+
class_variance_authority = require_rolldown_runtime.__toESM(class_variance_authority);
|
|
6
|
+
let react = require("react");
|
|
7
|
+
react = require_rolldown_runtime.__toESM(react);
|
|
8
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
|
+
react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
|
|
10
|
+
let lucide_react = require("lucide-react");
|
|
11
|
+
lucide_react = require_rolldown_runtime.__toESM(lucide_react);
|
|
12
|
+
|
|
13
|
+
//#region src/components/ui/rating.tsx
|
|
14
|
+
const ratingVariants = (0, class_variance_authority.cva)("inline-flex items-center gap-1", {
|
|
15
|
+
variants: { size: {
|
|
16
|
+
sm: "[&_svg]:size-4",
|
|
17
|
+
default: "[&_svg]:size-5",
|
|
18
|
+
lg: "[&_svg]:size-6",
|
|
19
|
+
xl: "[&_svg]:size-8"
|
|
20
|
+
} },
|
|
21
|
+
defaultVariants: { size: "default" }
|
|
22
|
+
});
|
|
23
|
+
const RatingContext = react.createContext(void 0);
|
|
24
|
+
function useRating() {
|
|
25
|
+
const context = react.use(RatingContext);
|
|
26
|
+
if (!context) throw new Error("Rating components must be used within a Rating provider");
|
|
27
|
+
return context;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Rating component for displaying and collecting star/circle ratings
|
|
31
|
+
*/
|
|
32
|
+
function Rating({ value: controlledValue, defaultValue = 0, onValueChange, max = 5, iconType = "star", labels, readOnly = false, disabled = false, name, required = false, size = "default", className, children }) {
|
|
33
|
+
const [uncontrolledValue, setUncontrolledValue] = react.useState(defaultValue);
|
|
34
|
+
const [hoverValue, setHoverValue] = react.useState(0);
|
|
35
|
+
const isControlled = controlledValue !== void 0;
|
|
36
|
+
const value = isControlled ? controlledValue : uncontrolledValue;
|
|
37
|
+
const handleValueChange = react.useCallback((newValue) => {
|
|
38
|
+
if (readOnly || disabled) return;
|
|
39
|
+
if (!isControlled) setUncontrolledValue(newValue);
|
|
40
|
+
onValueChange?.(newValue);
|
|
41
|
+
}, [
|
|
42
|
+
readOnly,
|
|
43
|
+
disabled,
|
|
44
|
+
isControlled,
|
|
45
|
+
onValueChange
|
|
46
|
+
]);
|
|
47
|
+
const handleHoverChange = react.useCallback((newHoverValue) => {
|
|
48
|
+
if (readOnly || disabled) return;
|
|
49
|
+
setHoverValue(newHoverValue);
|
|
50
|
+
}, [readOnly, disabled]);
|
|
51
|
+
const contextValue = react.useMemo(() => ({
|
|
52
|
+
value,
|
|
53
|
+
hoverValue,
|
|
54
|
+
max,
|
|
55
|
+
readOnly,
|
|
56
|
+
disabled,
|
|
57
|
+
size: size === "sm" ? 16 : size === "lg" ? 24 : size === "xl" ? 32 : 20,
|
|
58
|
+
iconType,
|
|
59
|
+
labels,
|
|
60
|
+
onValueChange: handleValueChange,
|
|
61
|
+
onHoverChange: handleHoverChange
|
|
62
|
+
}), [
|
|
63
|
+
value,
|
|
64
|
+
hoverValue,
|
|
65
|
+
max,
|
|
66
|
+
readOnly,
|
|
67
|
+
disabled,
|
|
68
|
+
size,
|
|
69
|
+
iconType,
|
|
70
|
+
labels,
|
|
71
|
+
handleValueChange,
|
|
72
|
+
handleHoverChange
|
|
73
|
+
]);
|
|
74
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RatingContext.Provider, {
|
|
75
|
+
value: contextValue,
|
|
76
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
77
|
+
className: require_utils.cn(ratingVariants({ size }), className),
|
|
78
|
+
role: "radiogroup",
|
|
79
|
+
"aria-label": "Rating",
|
|
80
|
+
"aria-required": required,
|
|
81
|
+
tabIndex: 0,
|
|
82
|
+
onMouseLeave: () => handleHoverChange(0),
|
|
83
|
+
children: [children, name && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
84
|
+
type: "hidden",
|
|
85
|
+
name,
|
|
86
|
+
value,
|
|
87
|
+
required
|
|
88
|
+
})]
|
|
89
|
+
})
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Individual rating item button component
|
|
94
|
+
*/
|
|
95
|
+
function RatingButton({ index, className,...props }) {
|
|
96
|
+
const { value, hoverValue, max, readOnly, disabled, size, iconType, labels, onValueChange, onHoverChange } = useRating();
|
|
97
|
+
const isFilled = index <= (hoverValue || value);
|
|
98
|
+
const label = labels?.[index - 1];
|
|
99
|
+
const Icon = iconType === "circle" ? lucide_react.Circle : lucide_react.Star;
|
|
100
|
+
const handleClick = () => {
|
|
101
|
+
if (!readOnly && !disabled) onValueChange?.(index);
|
|
102
|
+
};
|
|
103
|
+
const handleMouseEnter = () => {
|
|
104
|
+
if (!readOnly && !disabled) onHoverChange(index);
|
|
105
|
+
};
|
|
106
|
+
const handleKeyDown = (e) => {
|
|
107
|
+
if (readOnly || disabled) return;
|
|
108
|
+
switch (e.key) {
|
|
109
|
+
case "ArrowRight":
|
|
110
|
+
case "ArrowUp":
|
|
111
|
+
e.preventDefault();
|
|
112
|
+
onHoverChange(Math.min(index + 1, max));
|
|
113
|
+
break;
|
|
114
|
+
case "ArrowLeft":
|
|
115
|
+
case "ArrowDown":
|
|
116
|
+
e.preventDefault();
|
|
117
|
+
onHoverChange(Math.max(index - 1, 1));
|
|
118
|
+
break;
|
|
119
|
+
case "Home":
|
|
120
|
+
e.preventDefault();
|
|
121
|
+
onHoverChange(1);
|
|
122
|
+
break;
|
|
123
|
+
case "End":
|
|
124
|
+
e.preventDefault();
|
|
125
|
+
onHoverChange(max);
|
|
126
|
+
break;
|
|
127
|
+
case " ":
|
|
128
|
+
case "Enter":
|
|
129
|
+
e.preventDefault();
|
|
130
|
+
handleClick();
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
135
|
+
type: "button",
|
|
136
|
+
role: "radio",
|
|
137
|
+
"aria-checked": index === value,
|
|
138
|
+
"aria-label": label || `Rate ${index}`,
|
|
139
|
+
title: label,
|
|
140
|
+
disabled: disabled || readOnly,
|
|
141
|
+
onClick: handleClick,
|
|
142
|
+
onMouseEnter: handleMouseEnter,
|
|
143
|
+
onKeyDown: handleKeyDown,
|
|
144
|
+
className: require_utils.cn("inline-flex items-center justify-center transition-all outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-sm", readOnly && "cursor-default", !readOnly && !disabled && "cursor-pointer hover:scale-110", disabled && "opacity-50 cursor-not-allowed", className),
|
|
145
|
+
...props,
|
|
146
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
|
|
147
|
+
className: require_utils.cn("transition-all", isFilled ? "fill-yellow-400 text-yellow-400 dark:fill-yellow-500 dark:text-yellow-500" : "fill-transparent text-muted-foreground"),
|
|
148
|
+
size,
|
|
149
|
+
"aria-hidden": "true"
|
|
150
|
+
}), label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
151
|
+
className: "sr-only",
|
|
152
|
+
children: label
|
|
153
|
+
})]
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
//#endregion
|
|
158
|
+
exports.Rating = Rating;
|
|
159
|
+
exports.RatingButton = RatingButton;
|
|
160
|
+
exports.useRating = useRating;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import * as class_variance_authority_types4 from "class-variance-authority/types";
|
|
2
|
+
import * as react_jsx_runtime114 from "react/jsx-runtime";
|
|
3
|
+
import { VariantProps } from "class-variance-authority";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
|
|
6
|
+
//#region src/components/ui/rating.d.ts
|
|
7
|
+
declare const ratingVariants: (props?: ({
|
|
8
|
+
size?: "default" | "sm" | "lg" | "xl" | null | undefined;
|
|
9
|
+
} & class_variance_authority_types4.ClassProp) | undefined) => string;
|
|
10
|
+
interface RatingContextValue {
|
|
11
|
+
value: number;
|
|
12
|
+
hoverValue: number;
|
|
13
|
+
max: number;
|
|
14
|
+
readOnly: boolean;
|
|
15
|
+
disabled: boolean;
|
|
16
|
+
size: number;
|
|
17
|
+
iconType: 'star' | 'circle';
|
|
18
|
+
labels?: string[];
|
|
19
|
+
onValueChange?: (value: number) => void;
|
|
20
|
+
onHoverChange: (value: number) => void;
|
|
21
|
+
}
|
|
22
|
+
declare function useRating(): RatingContextValue;
|
|
23
|
+
interface RatingProps extends VariantProps<typeof ratingVariants> {
|
|
24
|
+
/**
|
|
25
|
+
* Current rating value for controlled mode
|
|
26
|
+
*/
|
|
27
|
+
value?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Initial rating value for uncontrolled mode
|
|
30
|
+
* @default 0
|
|
31
|
+
*/
|
|
32
|
+
defaultValue?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Callback when rating value changes
|
|
35
|
+
*/
|
|
36
|
+
onValueChange?: (value: number) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Maximum rating value (number of items)
|
|
39
|
+
* @default 5
|
|
40
|
+
*/
|
|
41
|
+
max?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Icon type to display
|
|
44
|
+
* @default 'star'
|
|
45
|
+
*/
|
|
46
|
+
iconType?: 'star' | 'circle';
|
|
47
|
+
/**
|
|
48
|
+
* Labels for each rating level (displayed on hover)
|
|
49
|
+
*/
|
|
50
|
+
labels?: string[];
|
|
51
|
+
/**
|
|
52
|
+
* Disables interaction and shows display-only mode
|
|
53
|
+
* @default false
|
|
54
|
+
*/
|
|
55
|
+
readOnly?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Disables all rating interactions
|
|
58
|
+
* @default false
|
|
59
|
+
*/
|
|
60
|
+
disabled?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Form input name for form integration
|
|
63
|
+
*/
|
|
64
|
+
name?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Makes rating selection required for forms
|
|
67
|
+
* @default false
|
|
68
|
+
*/
|
|
69
|
+
required?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Additional CSS classes for container
|
|
72
|
+
*/
|
|
73
|
+
className?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Children components (RatingButton)
|
|
76
|
+
*/
|
|
77
|
+
children?: React.ReactNode;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Rating component for displaying and collecting star/circle ratings
|
|
81
|
+
*/
|
|
82
|
+
declare function Rating({
|
|
83
|
+
value: controlledValue,
|
|
84
|
+
defaultValue,
|
|
85
|
+
onValueChange,
|
|
86
|
+
max,
|
|
87
|
+
iconType,
|
|
88
|
+
labels,
|
|
89
|
+
readOnly,
|
|
90
|
+
disabled,
|
|
91
|
+
name,
|
|
92
|
+
required,
|
|
93
|
+
size,
|
|
94
|
+
className,
|
|
95
|
+
children
|
|
96
|
+
}: RatingProps): react_jsx_runtime114.JSX.Element;
|
|
97
|
+
interface RatingButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
98
|
+
/**
|
|
99
|
+
* The rating value this button represents (1-based index)
|
|
100
|
+
*/
|
|
101
|
+
index: number;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Individual rating item button component
|
|
105
|
+
*/
|
|
106
|
+
declare function RatingButton({
|
|
107
|
+
index,
|
|
108
|
+
className,
|
|
109
|
+
...props
|
|
110
|
+
}: RatingButtonProps): react_jsx_runtime114.JSX.Element;
|
|
111
|
+
//#endregion
|
|
112
|
+
export { Rating, RatingButton, RatingButtonProps, RatingProps, useRating };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { VariantProps } from "class-variance-authority";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import * as react_jsx_runtime114 from "react/jsx-runtime";
|
|
4
|
+
import * as class_variance_authority_types4 from "class-variance-authority/types";
|
|
5
|
+
|
|
6
|
+
//#region src/components/ui/rating.d.ts
|
|
7
|
+
declare const ratingVariants: (props?: ({
|
|
8
|
+
size?: "default" | "sm" | "lg" | "xl" | null | undefined;
|
|
9
|
+
} & class_variance_authority_types4.ClassProp) | undefined) => string;
|
|
10
|
+
interface RatingContextValue {
|
|
11
|
+
value: number;
|
|
12
|
+
hoverValue: number;
|
|
13
|
+
max: number;
|
|
14
|
+
readOnly: boolean;
|
|
15
|
+
disabled: boolean;
|
|
16
|
+
size: number;
|
|
17
|
+
iconType: 'star' | 'circle';
|
|
18
|
+
labels?: string[];
|
|
19
|
+
onValueChange?: (value: number) => void;
|
|
20
|
+
onHoverChange: (value: number) => void;
|
|
21
|
+
}
|
|
22
|
+
declare function useRating(): RatingContextValue;
|
|
23
|
+
interface RatingProps extends VariantProps<typeof ratingVariants> {
|
|
24
|
+
/**
|
|
25
|
+
* Current rating value for controlled mode
|
|
26
|
+
*/
|
|
27
|
+
value?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Initial rating value for uncontrolled mode
|
|
30
|
+
* @default 0
|
|
31
|
+
*/
|
|
32
|
+
defaultValue?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Callback when rating value changes
|
|
35
|
+
*/
|
|
36
|
+
onValueChange?: (value: number) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Maximum rating value (number of items)
|
|
39
|
+
* @default 5
|
|
40
|
+
*/
|
|
41
|
+
max?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Icon type to display
|
|
44
|
+
* @default 'star'
|
|
45
|
+
*/
|
|
46
|
+
iconType?: 'star' | 'circle';
|
|
47
|
+
/**
|
|
48
|
+
* Labels for each rating level (displayed on hover)
|
|
49
|
+
*/
|
|
50
|
+
labels?: string[];
|
|
51
|
+
/**
|
|
52
|
+
* Disables interaction and shows display-only mode
|
|
53
|
+
* @default false
|
|
54
|
+
*/
|
|
55
|
+
readOnly?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Disables all rating interactions
|
|
58
|
+
* @default false
|
|
59
|
+
*/
|
|
60
|
+
disabled?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Form input name for form integration
|
|
63
|
+
*/
|
|
64
|
+
name?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Makes rating selection required for forms
|
|
67
|
+
* @default false
|
|
68
|
+
*/
|
|
69
|
+
required?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Additional CSS classes for container
|
|
72
|
+
*/
|
|
73
|
+
className?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Children components (RatingButton)
|
|
76
|
+
*/
|
|
77
|
+
children?: React.ReactNode;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Rating component for displaying and collecting star/circle ratings
|
|
81
|
+
*/
|
|
82
|
+
declare function Rating({
|
|
83
|
+
value: controlledValue,
|
|
84
|
+
defaultValue,
|
|
85
|
+
onValueChange,
|
|
86
|
+
max,
|
|
87
|
+
iconType,
|
|
88
|
+
labels,
|
|
89
|
+
readOnly,
|
|
90
|
+
disabled,
|
|
91
|
+
name,
|
|
92
|
+
required,
|
|
93
|
+
size,
|
|
94
|
+
className,
|
|
95
|
+
children
|
|
96
|
+
}: RatingProps): react_jsx_runtime114.JSX.Element;
|
|
97
|
+
interface RatingButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
98
|
+
/**
|
|
99
|
+
* The rating value this button represents (1-based index)
|
|
100
|
+
*/
|
|
101
|
+
index: number;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Individual rating item button component
|
|
105
|
+
*/
|
|
106
|
+
declare function RatingButton({
|
|
107
|
+
index,
|
|
108
|
+
className,
|
|
109
|
+
...props
|
|
110
|
+
}: RatingButtonProps): react_jsx_runtime114.JSX.Element;
|
|
111
|
+
//#endregion
|
|
112
|
+
export { Rating, RatingButton, RatingButtonProps, RatingProps, useRating };
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { cn } from "../../lib/utils.js";
|
|
2
|
+
import "../../lib/index.js";
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { Circle, Star } from "lucide-react";
|
|
7
|
+
|
|
8
|
+
//#region src/components/ui/rating.tsx
|
|
9
|
+
const ratingVariants = cva("inline-flex items-center gap-1", {
|
|
10
|
+
variants: { size: {
|
|
11
|
+
sm: "[&_svg]:size-4",
|
|
12
|
+
default: "[&_svg]:size-5",
|
|
13
|
+
lg: "[&_svg]:size-6",
|
|
14
|
+
xl: "[&_svg]:size-8"
|
|
15
|
+
} },
|
|
16
|
+
defaultVariants: { size: "default" }
|
|
17
|
+
});
|
|
18
|
+
const RatingContext = React.createContext(void 0);
|
|
19
|
+
function useRating() {
|
|
20
|
+
const context = React.use(RatingContext);
|
|
21
|
+
if (!context) throw new Error("Rating components must be used within a Rating provider");
|
|
22
|
+
return context;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Rating component for displaying and collecting star/circle ratings
|
|
26
|
+
*/
|
|
27
|
+
function Rating({ value: controlledValue, defaultValue = 0, onValueChange, max = 5, iconType = "star", labels, readOnly = false, disabled = false, name, required = false, size = "default", className, children }) {
|
|
28
|
+
const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue);
|
|
29
|
+
const [hoverValue, setHoverValue] = React.useState(0);
|
|
30
|
+
const isControlled = controlledValue !== void 0;
|
|
31
|
+
const value = isControlled ? controlledValue : uncontrolledValue;
|
|
32
|
+
const handleValueChange = React.useCallback((newValue) => {
|
|
33
|
+
if (readOnly || disabled) return;
|
|
34
|
+
if (!isControlled) setUncontrolledValue(newValue);
|
|
35
|
+
onValueChange?.(newValue);
|
|
36
|
+
}, [
|
|
37
|
+
readOnly,
|
|
38
|
+
disabled,
|
|
39
|
+
isControlled,
|
|
40
|
+
onValueChange
|
|
41
|
+
]);
|
|
42
|
+
const handleHoverChange = React.useCallback((newHoverValue) => {
|
|
43
|
+
if (readOnly || disabled) return;
|
|
44
|
+
setHoverValue(newHoverValue);
|
|
45
|
+
}, [readOnly, disabled]);
|
|
46
|
+
const contextValue = React.useMemo(() => ({
|
|
47
|
+
value,
|
|
48
|
+
hoverValue,
|
|
49
|
+
max,
|
|
50
|
+
readOnly,
|
|
51
|
+
disabled,
|
|
52
|
+
size: size === "sm" ? 16 : size === "lg" ? 24 : size === "xl" ? 32 : 20,
|
|
53
|
+
iconType,
|
|
54
|
+
labels,
|
|
55
|
+
onValueChange: handleValueChange,
|
|
56
|
+
onHoverChange: handleHoverChange
|
|
57
|
+
}), [
|
|
58
|
+
value,
|
|
59
|
+
hoverValue,
|
|
60
|
+
max,
|
|
61
|
+
readOnly,
|
|
62
|
+
disabled,
|
|
63
|
+
size,
|
|
64
|
+
iconType,
|
|
65
|
+
labels,
|
|
66
|
+
handleValueChange,
|
|
67
|
+
handleHoverChange
|
|
68
|
+
]);
|
|
69
|
+
return /* @__PURE__ */ jsx(RatingContext.Provider, {
|
|
70
|
+
value: contextValue,
|
|
71
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
72
|
+
className: cn(ratingVariants({ size }), className),
|
|
73
|
+
role: "radiogroup",
|
|
74
|
+
"aria-label": "Rating",
|
|
75
|
+
"aria-required": required,
|
|
76
|
+
tabIndex: 0,
|
|
77
|
+
onMouseLeave: () => handleHoverChange(0),
|
|
78
|
+
children: [children, name && /* @__PURE__ */ jsx("input", {
|
|
79
|
+
type: "hidden",
|
|
80
|
+
name,
|
|
81
|
+
value,
|
|
82
|
+
required
|
|
83
|
+
})]
|
|
84
|
+
})
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Individual rating item button component
|
|
89
|
+
*/
|
|
90
|
+
function RatingButton({ index, className,...props }) {
|
|
91
|
+
const { value, hoverValue, max, readOnly, disabled, size, iconType, labels, onValueChange, onHoverChange } = useRating();
|
|
92
|
+
const isFilled = index <= (hoverValue || value);
|
|
93
|
+
const label = labels?.[index - 1];
|
|
94
|
+
const Icon = iconType === "circle" ? Circle : Star;
|
|
95
|
+
const handleClick = () => {
|
|
96
|
+
if (!readOnly && !disabled) onValueChange?.(index);
|
|
97
|
+
};
|
|
98
|
+
const handleMouseEnter = () => {
|
|
99
|
+
if (!readOnly && !disabled) onHoverChange(index);
|
|
100
|
+
};
|
|
101
|
+
const handleKeyDown = (e) => {
|
|
102
|
+
if (readOnly || disabled) return;
|
|
103
|
+
switch (e.key) {
|
|
104
|
+
case "ArrowRight":
|
|
105
|
+
case "ArrowUp":
|
|
106
|
+
e.preventDefault();
|
|
107
|
+
onHoverChange(Math.min(index + 1, max));
|
|
108
|
+
break;
|
|
109
|
+
case "ArrowLeft":
|
|
110
|
+
case "ArrowDown":
|
|
111
|
+
e.preventDefault();
|
|
112
|
+
onHoverChange(Math.max(index - 1, 1));
|
|
113
|
+
break;
|
|
114
|
+
case "Home":
|
|
115
|
+
e.preventDefault();
|
|
116
|
+
onHoverChange(1);
|
|
117
|
+
break;
|
|
118
|
+
case "End":
|
|
119
|
+
e.preventDefault();
|
|
120
|
+
onHoverChange(max);
|
|
121
|
+
break;
|
|
122
|
+
case " ":
|
|
123
|
+
case "Enter":
|
|
124
|
+
e.preventDefault();
|
|
125
|
+
handleClick();
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
130
|
+
type: "button",
|
|
131
|
+
role: "radio",
|
|
132
|
+
"aria-checked": index === value,
|
|
133
|
+
"aria-label": label || `Rate ${index}`,
|
|
134
|
+
title: label,
|
|
135
|
+
disabled: disabled || readOnly,
|
|
136
|
+
onClick: handleClick,
|
|
137
|
+
onMouseEnter: handleMouseEnter,
|
|
138
|
+
onKeyDown: handleKeyDown,
|
|
139
|
+
className: cn("inline-flex items-center justify-center transition-all outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-sm", readOnly && "cursor-default", !readOnly && !disabled && "cursor-pointer hover:scale-110", disabled && "opacity-50 cursor-not-allowed", className),
|
|
140
|
+
...props,
|
|
141
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
142
|
+
className: cn("transition-all", isFilled ? "fill-yellow-400 text-yellow-400 dark:fill-yellow-500 dark:text-yellow-500" : "fill-transparent text-muted-foreground"),
|
|
143
|
+
size,
|
|
144
|
+
"aria-hidden": "true"
|
|
145
|
+
}), label && /* @__PURE__ */ jsx("span", {
|
|
146
|
+
className: "sr-only",
|
|
147
|
+
children: label
|
|
148
|
+
})]
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
//#endregion
|
|
153
|
+
export { Rating, RatingButton, useRating };
|