virtual-ui-lib 1.0.23 → 1.0.25

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
@@ -39,7 +39,9 @@ __export(index_exports, {
39
39
  GridLayout: () => GridLayout,
40
40
  ImageUploadPreview: () => ImageUploadPreview,
41
41
  Loader: () => Loader,
42
- Navbar: () => Navbar
42
+ Navbar: () => Navbar,
43
+ OTPInput: () => OTPInput,
44
+ RatingStars: () => RatingStars
43
45
  });
44
46
  module.exports = __toCommonJS(index_exports);
45
47
 
@@ -647,6 +649,121 @@ var Loader = ({
647
649
  `)
648
650
  );
649
651
  };
652
+
653
+ // src/components/OTPInput/OTPInput.jsx
654
+ var import_react12 = __toESM(require("react"));
655
+ var OTPInput = ({
656
+ length = 4,
657
+ bg = "#0f172a",
658
+ borderColorDefault = "#4b5563",
659
+ borderColorFocus = "#2563eb",
660
+ borderColorError = "#e11d48",
661
+ borderColorSuccess = "#059669",
662
+ color = "#f1f5f9",
663
+ radius = "8px",
664
+ onChange,
665
+ error = false,
666
+ success = false
667
+ }) => {
668
+ const [otp, setOtp] = (0, import_react12.useState)(Array(length).fill(""));
669
+ const inputRefs = (0, import_react12.useRef)(Array(length).fill().map(() => import_react12.default.createRef()));
670
+ (0, import_react12.useEffect)(() => {
671
+ inputRefs.current[0].current.focus();
672
+ }, []);
673
+ const handleChange = (index, value) => {
674
+ if (/[^0-9]/.test(value)) return;
675
+ const newOtp = [...otp];
676
+ newOtp[index] = value;
677
+ setOtp(newOtp);
678
+ onChange(newOtp.join(""));
679
+ if (value && index < length - 1) {
680
+ inputRefs.current[index + 1].current.focus();
681
+ }
682
+ };
683
+ const handleKeyDown = (index, event) => {
684
+ if (event.key === "Backspace" && !otp[index] && index > 0) {
685
+ inputRefs.current[index - 1].current.focus();
686
+ }
687
+ };
688
+ const handlePaste = (event) => {
689
+ const pastedData = event.clipboardData.getData("text").split("").slice(0, length);
690
+ const newOtp = pastedData.map((char, index) => char.match(/\d/) ? char : "");
691
+ setOtp(newOtp);
692
+ newOtp.forEach((_, index) => {
693
+ if (inputRefs.current[index]) {
694
+ inputRefs.current[index].current.focus();
695
+ }
696
+ });
697
+ onChange(newOtp.join(""));
698
+ event.preventDefault();
699
+ };
700
+ return /* @__PURE__ */ import_react12.default.createElement("div", { style: { display: "flex", justifyContent: "center", gap: "10px" }, onPaste: handlePaste }, otp.map((value, index) => /* @__PURE__ */ import_react12.default.createElement(
701
+ "input",
702
+ {
703
+ key: index,
704
+ ref: inputRefs.current[index],
705
+ value,
706
+ onChange: (e) => handleChange(index, e.target.value),
707
+ onKeyDown: (event) => handleKeyDown(index, event),
708
+ style: {
709
+ width: "40px",
710
+ height: "50px",
711
+ borderRadius: radius,
712
+ border: `2px solid ${error ? borderColorError : success ? borderColorSuccess : index === otp.findIndex((v) => v !== "") ? borderColorFocus : borderColorDefault}`,
713
+ background: bg,
714
+ color,
715
+ fontSize: "20px",
716
+ textAlign: "center",
717
+ outline: "none",
718
+ transition: "border-color 0.3s ease, transform 0.2s ease",
719
+ transform: `scale(${index === otp.findIndex((v) => v !== "") ? 1.05 : 1})`
720
+ },
721
+ autoFocus: index === 0
722
+ }
723
+ )));
724
+ };
725
+
726
+ // src/components/RatingStars/RatingStars.jsx
727
+ var import_react13 = __toESM(require("react"));
728
+ var RatingStars = ({
729
+ totalStars = 5,
730
+ selectedColor = "#ffc107",
731
+ defaultColor = "#e4e5e9",
732
+ size = "24px",
733
+ onSelect
734
+ }) => {
735
+ const [hovered, setHovered] = (0, import_react13.useState)(0);
736
+ const [selected, setSelected] = (0, import_react13.useState)(0);
737
+ const handleMouseEnter = (index) => {
738
+ setHovered(index + 1);
739
+ };
740
+ const handleMouseLeave = () => {
741
+ setHovered(0);
742
+ };
743
+ const handleClick = (index) => {
744
+ setSelected(index + 1);
745
+ if (onSelect) onSelect(index + 1);
746
+ };
747
+ return /* @__PURE__ */ import_react13.default.createElement("div", { style: { display: "flex", gap: "4px" } }, [...Array(totalStars)].map((_, index) => /* @__PURE__ */ import_react13.default.createElement(
748
+ "svg",
749
+ {
750
+ key: index,
751
+ width: size,
752
+ height: size,
753
+ viewBox: "0 0 24 24",
754
+ fill: "none",
755
+ stroke: index < (hovered || selected) ? selectedColor : defaultColor,
756
+ strokeWidth: "1.5",
757
+ strokeLinecap: "round",
758
+ strokeLinejoin: "round",
759
+ onMouseEnter: () => handleMouseEnter(index),
760
+ onMouseLeave: handleMouseLeave,
761
+ onClick: () => handleClick(index),
762
+ style: { transition: "color 0.2s ease" }
763
+ },
764
+ /* @__PURE__ */ import_react13.default.createElement("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21 12 17.77 5.82 21 7 14.14 2 9.27 8.91 8.26 12 2" })
765
+ )));
766
+ };
650
767
  // Annotate the CommonJS export names for ESM import in node:
651
768
  0 && (module.exports = {
652
769
  AlertBanner,
@@ -659,5 +776,7 @@ var Loader = ({
659
776
  GridLayout,
660
777
  ImageUploadPreview,
661
778
  Loader,
662
- Navbar
779
+ Navbar,
780
+ OTPInput,
781
+ RatingStars
663
782
  });
package/dist/index.mjs CHANGED
@@ -602,6 +602,121 @@ var Loader = ({
602
602
  `)
603
603
  );
604
604
  };
605
+
606
+ // src/components/OTPInput/OTPInput.jsx
607
+ import React12, { useEffect as useEffect6, useRef as useRef2, useState as useState9 } from "react";
608
+ var OTPInput = ({
609
+ length = 4,
610
+ bg = "#0f172a",
611
+ borderColorDefault = "#4b5563",
612
+ borderColorFocus = "#2563eb",
613
+ borderColorError = "#e11d48",
614
+ borderColorSuccess = "#059669",
615
+ color = "#f1f5f9",
616
+ radius = "8px",
617
+ onChange,
618
+ error = false,
619
+ success = false
620
+ }) => {
621
+ const [otp, setOtp] = useState9(Array(length).fill(""));
622
+ const inputRefs = useRef2(Array(length).fill().map(() => React12.createRef()));
623
+ useEffect6(() => {
624
+ inputRefs.current[0].current.focus();
625
+ }, []);
626
+ const handleChange = (index, value) => {
627
+ if (/[^0-9]/.test(value)) return;
628
+ const newOtp = [...otp];
629
+ newOtp[index] = value;
630
+ setOtp(newOtp);
631
+ onChange(newOtp.join(""));
632
+ if (value && index < length - 1) {
633
+ inputRefs.current[index + 1].current.focus();
634
+ }
635
+ };
636
+ const handleKeyDown = (index, event) => {
637
+ if (event.key === "Backspace" && !otp[index] && index > 0) {
638
+ inputRefs.current[index - 1].current.focus();
639
+ }
640
+ };
641
+ const handlePaste = (event) => {
642
+ const pastedData = event.clipboardData.getData("text").split("").slice(0, length);
643
+ const newOtp = pastedData.map((char, index) => char.match(/\d/) ? char : "");
644
+ setOtp(newOtp);
645
+ newOtp.forEach((_, index) => {
646
+ if (inputRefs.current[index]) {
647
+ inputRefs.current[index].current.focus();
648
+ }
649
+ });
650
+ onChange(newOtp.join(""));
651
+ event.preventDefault();
652
+ };
653
+ return /* @__PURE__ */ React12.createElement("div", { style: { display: "flex", justifyContent: "center", gap: "10px" }, onPaste: handlePaste }, otp.map((value, index) => /* @__PURE__ */ React12.createElement(
654
+ "input",
655
+ {
656
+ key: index,
657
+ ref: inputRefs.current[index],
658
+ value,
659
+ onChange: (e) => handleChange(index, e.target.value),
660
+ onKeyDown: (event) => handleKeyDown(index, event),
661
+ style: {
662
+ width: "40px",
663
+ height: "50px",
664
+ borderRadius: radius,
665
+ border: `2px solid ${error ? borderColorError : success ? borderColorSuccess : index === otp.findIndex((v) => v !== "") ? borderColorFocus : borderColorDefault}`,
666
+ background: bg,
667
+ color,
668
+ fontSize: "20px",
669
+ textAlign: "center",
670
+ outline: "none",
671
+ transition: "border-color 0.3s ease, transform 0.2s ease",
672
+ transform: `scale(${index === otp.findIndex((v) => v !== "") ? 1.05 : 1})`
673
+ },
674
+ autoFocus: index === 0
675
+ }
676
+ )));
677
+ };
678
+
679
+ // src/components/RatingStars/RatingStars.jsx
680
+ import React13, { useState as useState10 } from "react";
681
+ var RatingStars = ({
682
+ totalStars = 5,
683
+ selectedColor = "#ffc107",
684
+ defaultColor = "#e4e5e9",
685
+ size = "24px",
686
+ onSelect
687
+ }) => {
688
+ const [hovered, setHovered] = useState10(0);
689
+ const [selected, setSelected] = useState10(0);
690
+ const handleMouseEnter = (index) => {
691
+ setHovered(index + 1);
692
+ };
693
+ const handleMouseLeave = () => {
694
+ setHovered(0);
695
+ };
696
+ const handleClick = (index) => {
697
+ setSelected(index + 1);
698
+ if (onSelect) onSelect(index + 1);
699
+ };
700
+ return /* @__PURE__ */ React13.createElement("div", { style: { display: "flex", gap: "4px" } }, [...Array(totalStars)].map((_, index) => /* @__PURE__ */ React13.createElement(
701
+ "svg",
702
+ {
703
+ key: index,
704
+ width: size,
705
+ height: size,
706
+ viewBox: "0 0 24 24",
707
+ fill: "none",
708
+ stroke: index < (hovered || selected) ? selectedColor : defaultColor,
709
+ strokeWidth: "1.5",
710
+ strokeLinecap: "round",
711
+ strokeLinejoin: "round",
712
+ onMouseEnter: () => handleMouseEnter(index),
713
+ onMouseLeave: handleMouseLeave,
714
+ onClick: () => handleClick(index),
715
+ style: { transition: "color 0.2s ease" }
716
+ },
717
+ /* @__PURE__ */ React13.createElement("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21 12 17.77 5.82 21 7 14.14 2 9.27 8.91 8.26 12 2" })
718
+ )));
719
+ };
605
720
  export {
606
721
  AlertBanner,
607
722
  Button,
@@ -613,5 +728,7 @@ export {
613
728
  GridLayout,
614
729
  ImageUploadPreview,
615
730
  Loader,
616
- Navbar
731
+ Navbar,
732
+ OTPInput,
733
+ RatingStars
617
734
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "virtual-ui-lib",
3
- "version": "1.0.23",
3
+ "version": "1.0.25",
4
4
  "description": "Virtual UI React Component Library",
5
5
  "author": "Ankush",
6
6
  "license": "ISC",