virtual-ui-lib 1.0.71 → 1.0.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -44,6 +44,7 @@ __export(index_exports, {
44
44
  OTPInput: () => OTPInput,
45
45
  PageLoader: () => PageLoader,
46
46
  PricingCard: () => PricingCard,
47
+ RatingStars: () => RatingStars,
47
48
  Sidebar: () => Sidebar
48
49
  });
49
50
  module.exports = __toCommonJS(index_exports);
@@ -2993,6 +2994,122 @@ var ColorPicker = ({
2993
2994
  alignItems: "center"
2994
2995
  } }, /* @__PURE__ */ import_react16.default.createElement("span", { style: { fontSize: "10px", color: "rgba(255,255,255,0.25)", fontWeight: "600", textTransform: "uppercase", letterSpacing: "0.5px" } }, "RGBA"), /* @__PURE__ */ import_react16.default.createElement("span", { style: { fontSize: "10px", fontFamily: "monospace", color: "rgba(255,255,255,0.5)" } }, alpha(color, opacity / 100))));
2995
2996
  };
2997
+
2998
+ // src/components/RatingStars/RatingStars.jsx
2999
+ var import_react17 = __toESM(require("react"));
3000
+ var RatingStars = ({
3001
+ defaultRating = 0,
3002
+ total = 5,
3003
+ size = 32,
3004
+ allowHalf = true,
3005
+ showLabel = true,
3006
+ showCount = true,
3007
+ reviewCount = 0,
3008
+ readOnly = false,
3009
+ accent = "#f59e0b",
3010
+ bg = "#0f172a",
3011
+ radius = "14px",
3012
+ onChange = () => {
3013
+ }
3014
+ }) => {
3015
+ const [rating, setRating] = (0, import_react17.useState)(defaultRating);
3016
+ const [hovered, setHovered] = (0, import_react17.useState)(0);
3017
+ const labels = ["", "Terrible", "Bad", "Okay", "Good", "Excellent"];
3018
+ const halfLabels = { 0.5: "Awful", 1: "Terrible", 1.5: "Very Bad", 2: "Bad", 2.5: "Below Average", 3: "Okay", 3.5: "Above Average", 4: "Good", 4.5: "Great", 5: "Excellent" };
3019
+ const alpha = (hex, op) => {
3020
+ const r = parseInt(hex.slice(1, 3), 16);
3021
+ const g = parseInt(hex.slice(3, 5), 16);
3022
+ const b = parseInt(hex.slice(5, 7), 16);
3023
+ return `rgba(${r},${g},${b},${op})`;
3024
+ };
3025
+ const active = hovered || rating;
3026
+ const handleMouseMove = (e, i) => {
3027
+ if (readOnly) return;
3028
+ if (allowHalf) {
3029
+ const rect = e.currentTarget.getBoundingClientRect();
3030
+ const half = e.clientX - rect.left < rect.width / 2;
3031
+ setHovered(half ? i - 0.5 : i);
3032
+ } else {
3033
+ setHovered(i);
3034
+ }
3035
+ };
3036
+ const handleClick = (e, i) => {
3037
+ if (readOnly) return;
3038
+ let val;
3039
+ if (allowHalf) {
3040
+ const rect = e.currentTarget.getBoundingClientRect();
3041
+ val = e.clientX - rect.left < rect.width / 2 ? i - 0.5 : i;
3042
+ } else {
3043
+ val = i;
3044
+ }
3045
+ setRating(val);
3046
+ onChange(val);
3047
+ };
3048
+ const StarIcon = ({ index }) => {
3049
+ const fill = active >= index ? "full" : active >= index - 0.5 ? "half" : "empty";
3050
+ const id = `half-${index}`;
3051
+ return /* @__PURE__ */ import_react17.default.createElement(
3052
+ "svg",
3053
+ {
3054
+ width: size,
3055
+ height: size,
3056
+ viewBox: "0 0 24 24",
3057
+ style: { cursor: readOnly ? "default" : "pointer", transition: "transform 0.1s", flexShrink: 0 },
3058
+ onMouseMove: (e) => handleMouseMove(e, index),
3059
+ onMouseLeave: () => !readOnly && setHovered(0),
3060
+ onClick: (e) => handleClick(e, index),
3061
+ onMouseEnter: (e) => {
3062
+ if (!readOnly) e.currentTarget.style.transform = "scale(1.15)";
3063
+ }
3064
+ },
3065
+ /* @__PURE__ */ import_react17.default.createElement("defs", null, /* @__PURE__ */ import_react17.default.createElement("linearGradient", { id }, /* @__PURE__ */ import_react17.default.createElement("stop", { offset: "50%", stopColor: accent }), /* @__PURE__ */ import_react17.default.createElement("stop", { offset: "50%", stopColor: "transparent" }))),
3066
+ /* @__PURE__ */ import_react17.default.createElement(
3067
+ "polygon",
3068
+ {
3069
+ points: "12,2 15.09,8.26 22,9.27 17,14.14 18.18,21.02 12,17.77 5.82,21.02 7,14.14 2,9.27 8.91,8.26",
3070
+ fill: fill === "full" ? accent : fill === "half" ? `url(#${id})` : "transparent",
3071
+ stroke: fill === "empty" ? "rgba(255,255,255,0.15)" : accent,
3072
+ strokeWidth: "1.5"
3073
+ }
3074
+ )
3075
+ );
3076
+ };
3077
+ return /* @__PURE__ */ import_react17.default.createElement("div", { style: {
3078
+ background: bg,
3079
+ borderRadius: radius,
3080
+ padding: "20px 22px",
3081
+ display: "inline-flex",
3082
+ flexDirection: "column",
3083
+ alignItems: "center",
3084
+ gap: "12px",
3085
+ fontFamily: "system-ui, sans-serif",
3086
+ border: "1px solid rgba(255,255,255,0.07)",
3087
+ boxShadow: "0 10px 40px rgba(0,0,0,0.4)"
3088
+ } }, /* @__PURE__ */ import_react17.default.createElement("div", { style: { display: "flex", gap: "4px", alignItems: "center" } }, Array.from({ length: total }, (_, i) => /* @__PURE__ */ import_react17.default.createElement(StarIcon, { key: i + 1, index: i + 1 }))), showLabel && /* @__PURE__ */ import_react17.default.createElement("div", { style: {
3089
+ fontSize: "14px",
3090
+ fontWeight: "700",
3091
+ minHeight: "20px",
3092
+ color: active > 0 ? accent : "rgba(255,255,255,0.2)",
3093
+ transition: "color 0.2s"
3094
+ } }, active > 0 ? allowHalf ? halfLabels[active] : labels[Math.round(active)] : readOnly ? "Not rated" : "Rate this"), (rating > 0 || readOnly) && showCount && /* @__PURE__ */ import_react17.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: "8px" } }, /* @__PURE__ */ import_react17.default.createElement("span", { style: {
3095
+ fontSize: "28px",
3096
+ fontWeight: "800",
3097
+ color: "#fff",
3098
+ lineHeight: 1
3099
+ } }, rating.toFixed(1)), /* @__PURE__ */ import_react17.default.createElement("div", null, /* @__PURE__ */ import_react17.default.createElement("div", { style: { display: "flex", gap: "1px", marginBottom: "3px" } }, Array.from({ length: total }, (_, i) => {
3100
+ const fill = rating >= i + 1 ? "full" : rating >= i + 0.5 ? "half" : "empty";
3101
+ const gid = `sm-${i}`;
3102
+ return /* @__PURE__ */ import_react17.default.createElement("svg", { key: i, width: "12", height: "12", viewBox: "0 0 24 24" }, /* @__PURE__ */ import_react17.default.createElement("defs", null, /* @__PURE__ */ import_react17.default.createElement("linearGradient", { id: gid }, /* @__PURE__ */ import_react17.default.createElement("stop", { offset: "50%", stopColor: accent }), /* @__PURE__ */ import_react17.default.createElement("stop", { offset: "50%", stopColor: "transparent" }))), /* @__PURE__ */ import_react17.default.createElement(
3103
+ "polygon",
3104
+ {
3105
+ points: "12,2 15.09,8.26 22,9.27 17,14.14 18.18,21.02 12,17.77 5.82,21.02 7,14.14 2,9.27 8.91,8.26",
3106
+ fill: fill === "full" ? accent : fill === "half" ? `url(#${gid})` : "transparent",
3107
+ stroke: fill === "empty" ? "rgba(255,255,255,0.15)" : accent,
3108
+ strokeWidth: "1.5"
3109
+ }
3110
+ ));
3111
+ })), reviewCount > 0 && /* @__PURE__ */ import_react17.default.createElement("span", { style: { fontSize: "11px", color: "rgba(255,255,255,0.3)" } }, reviewCount.toLocaleString(), " reviews"))), !readOnly && rating === 0 && /* @__PURE__ */ import_react17.default.createElement("p", { style: { fontSize: "11px", color: "rgba(255,255,255,0.2)", margin: 0 } }, allowHalf ? "Hover to rate \u2022 Half stars supported" : "Click to rate"));
3112
+ };
2996
3113
  // Annotate the CommonJS export names for ESM import in node:
2997
3114
  0 && (module.exports = {
2998
3115
  AvatarCard,
@@ -3010,5 +3127,6 @@ var ColorPicker = ({
3010
3127
  OTPInput,
3011
3128
  PageLoader,
3012
3129
  PricingCard,
3130
+ RatingStars,
3013
3131
  Sidebar
3014
3132
  });
package/dist/index.mjs CHANGED
@@ -2943,6 +2943,122 @@ var ColorPicker = ({
2943
2943
  alignItems: "center"
2944
2944
  } }, /* @__PURE__ */ React16.createElement("span", { style: { fontSize: "10px", color: "rgba(255,255,255,0.25)", fontWeight: "600", textTransform: "uppercase", letterSpacing: "0.5px" } }, "RGBA"), /* @__PURE__ */ React16.createElement("span", { style: { fontSize: "10px", fontFamily: "monospace", color: "rgba(255,255,255,0.5)" } }, alpha(color, opacity / 100))));
2945
2945
  };
2946
+
2947
+ // src/components/RatingStars/RatingStars.jsx
2948
+ import React17, { useState as useState15 } from "react";
2949
+ var RatingStars = ({
2950
+ defaultRating = 0,
2951
+ total = 5,
2952
+ size = 32,
2953
+ allowHalf = true,
2954
+ showLabel = true,
2955
+ showCount = true,
2956
+ reviewCount = 0,
2957
+ readOnly = false,
2958
+ accent = "#f59e0b",
2959
+ bg = "#0f172a",
2960
+ radius = "14px",
2961
+ onChange = () => {
2962
+ }
2963
+ }) => {
2964
+ const [rating, setRating] = useState15(defaultRating);
2965
+ const [hovered, setHovered] = useState15(0);
2966
+ const labels = ["", "Terrible", "Bad", "Okay", "Good", "Excellent"];
2967
+ const halfLabels = { 0.5: "Awful", 1: "Terrible", 1.5: "Very Bad", 2: "Bad", 2.5: "Below Average", 3: "Okay", 3.5: "Above Average", 4: "Good", 4.5: "Great", 5: "Excellent" };
2968
+ const alpha = (hex, op) => {
2969
+ const r = parseInt(hex.slice(1, 3), 16);
2970
+ const g = parseInt(hex.slice(3, 5), 16);
2971
+ const b = parseInt(hex.slice(5, 7), 16);
2972
+ return `rgba(${r},${g},${b},${op})`;
2973
+ };
2974
+ const active = hovered || rating;
2975
+ const handleMouseMove = (e, i) => {
2976
+ if (readOnly) return;
2977
+ if (allowHalf) {
2978
+ const rect = e.currentTarget.getBoundingClientRect();
2979
+ const half = e.clientX - rect.left < rect.width / 2;
2980
+ setHovered(half ? i - 0.5 : i);
2981
+ } else {
2982
+ setHovered(i);
2983
+ }
2984
+ };
2985
+ const handleClick = (e, i) => {
2986
+ if (readOnly) return;
2987
+ let val;
2988
+ if (allowHalf) {
2989
+ const rect = e.currentTarget.getBoundingClientRect();
2990
+ val = e.clientX - rect.left < rect.width / 2 ? i - 0.5 : i;
2991
+ } else {
2992
+ val = i;
2993
+ }
2994
+ setRating(val);
2995
+ onChange(val);
2996
+ };
2997
+ const StarIcon = ({ index }) => {
2998
+ const fill = active >= index ? "full" : active >= index - 0.5 ? "half" : "empty";
2999
+ const id = `half-${index}`;
3000
+ return /* @__PURE__ */ React17.createElement(
3001
+ "svg",
3002
+ {
3003
+ width: size,
3004
+ height: size,
3005
+ viewBox: "0 0 24 24",
3006
+ style: { cursor: readOnly ? "default" : "pointer", transition: "transform 0.1s", flexShrink: 0 },
3007
+ onMouseMove: (e) => handleMouseMove(e, index),
3008
+ onMouseLeave: () => !readOnly && setHovered(0),
3009
+ onClick: (e) => handleClick(e, index),
3010
+ onMouseEnter: (e) => {
3011
+ if (!readOnly) e.currentTarget.style.transform = "scale(1.15)";
3012
+ }
3013
+ },
3014
+ /* @__PURE__ */ React17.createElement("defs", null, /* @__PURE__ */ React17.createElement("linearGradient", { id }, /* @__PURE__ */ React17.createElement("stop", { offset: "50%", stopColor: accent }), /* @__PURE__ */ React17.createElement("stop", { offset: "50%", stopColor: "transparent" }))),
3015
+ /* @__PURE__ */ React17.createElement(
3016
+ "polygon",
3017
+ {
3018
+ points: "12,2 15.09,8.26 22,9.27 17,14.14 18.18,21.02 12,17.77 5.82,21.02 7,14.14 2,9.27 8.91,8.26",
3019
+ fill: fill === "full" ? accent : fill === "half" ? `url(#${id})` : "transparent",
3020
+ stroke: fill === "empty" ? "rgba(255,255,255,0.15)" : accent,
3021
+ strokeWidth: "1.5"
3022
+ }
3023
+ )
3024
+ );
3025
+ };
3026
+ return /* @__PURE__ */ React17.createElement("div", { style: {
3027
+ background: bg,
3028
+ borderRadius: radius,
3029
+ padding: "20px 22px",
3030
+ display: "inline-flex",
3031
+ flexDirection: "column",
3032
+ alignItems: "center",
3033
+ gap: "12px",
3034
+ fontFamily: "system-ui, sans-serif",
3035
+ border: "1px solid rgba(255,255,255,0.07)",
3036
+ boxShadow: "0 10px 40px rgba(0,0,0,0.4)"
3037
+ } }, /* @__PURE__ */ React17.createElement("div", { style: { display: "flex", gap: "4px", alignItems: "center" } }, Array.from({ length: total }, (_, i) => /* @__PURE__ */ React17.createElement(StarIcon, { key: i + 1, index: i + 1 }))), showLabel && /* @__PURE__ */ React17.createElement("div", { style: {
3038
+ fontSize: "14px",
3039
+ fontWeight: "700",
3040
+ minHeight: "20px",
3041
+ color: active > 0 ? accent : "rgba(255,255,255,0.2)",
3042
+ transition: "color 0.2s"
3043
+ } }, active > 0 ? allowHalf ? halfLabels[active] : labels[Math.round(active)] : readOnly ? "Not rated" : "Rate this"), (rating > 0 || readOnly) && showCount && /* @__PURE__ */ React17.createElement("div", { style: { display: "flex", alignItems: "center", gap: "8px" } }, /* @__PURE__ */ React17.createElement("span", { style: {
3044
+ fontSize: "28px",
3045
+ fontWeight: "800",
3046
+ color: "#fff",
3047
+ lineHeight: 1
3048
+ } }, rating.toFixed(1)), /* @__PURE__ */ React17.createElement("div", null, /* @__PURE__ */ React17.createElement("div", { style: { display: "flex", gap: "1px", marginBottom: "3px" } }, Array.from({ length: total }, (_, i) => {
3049
+ const fill = rating >= i + 1 ? "full" : rating >= i + 0.5 ? "half" : "empty";
3050
+ const gid = `sm-${i}`;
3051
+ return /* @__PURE__ */ React17.createElement("svg", { key: i, width: "12", height: "12", viewBox: "0 0 24 24" }, /* @__PURE__ */ React17.createElement("defs", null, /* @__PURE__ */ React17.createElement("linearGradient", { id: gid }, /* @__PURE__ */ React17.createElement("stop", { offset: "50%", stopColor: accent }), /* @__PURE__ */ React17.createElement("stop", { offset: "50%", stopColor: "transparent" }))), /* @__PURE__ */ React17.createElement(
3052
+ "polygon",
3053
+ {
3054
+ points: "12,2 15.09,8.26 22,9.27 17,14.14 18.18,21.02 12,17.77 5.82,21.02 7,14.14 2,9.27 8.91,8.26",
3055
+ fill: fill === "full" ? accent : fill === "half" ? `url(#${gid})` : "transparent",
3056
+ stroke: fill === "empty" ? "rgba(255,255,255,0.15)" : accent,
3057
+ strokeWidth: "1.5"
3058
+ }
3059
+ ));
3060
+ })), reviewCount > 0 && /* @__PURE__ */ React17.createElement("span", { style: { fontSize: "11px", color: "rgba(255,255,255,0.3)" } }, reviewCount.toLocaleString(), " reviews"))), !readOnly && rating === 0 && /* @__PURE__ */ React17.createElement("p", { style: { fontSize: "11px", color: "rgba(255,255,255,0.2)", margin: 0 } }, allowHalf ? "Hover to rate \u2022 Half stars supported" : "Click to rate"));
3061
+ };
2946
3062
  export {
2947
3063
  AvatarCard,
2948
3064
  BackgoundImageSlider,
@@ -2959,5 +3075,6 @@ export {
2959
3075
  OTPInput,
2960
3076
  PageLoader,
2961
3077
  PricingCard,
3078
+ RatingStars,
2962
3079
  Sidebar
2963
3080
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "virtual-ui-lib",
3
- "version": "1.0.71",
3
+ "version": "1.0.72",
4
4
  "description": "Virtual UI React Component Library",
5
5
  "author": "Ankush",
6
6
  "license": "ISC",