virtual-ui-lib 1.0.22 → 1.0.24

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
@@ -38,7 +38,9 @@ __export(index_exports, {
38
38
  FormInput: () => FormInput,
39
39
  GridLayout: () => GridLayout,
40
40
  ImageUploadPreview: () => ImageUploadPreview,
41
- Navbar: () => Navbar
41
+ Loader: () => Loader,
42
+ Navbar: () => Navbar,
43
+ OTPInput: () => OTPInput
42
44
  });
43
45
  module.exports = __toCommonJS(index_exports);
44
46
 
@@ -597,6 +599,128 @@ var CopyButton = ({
597
599
  copied ? "Copied!" : text
598
600
  );
599
601
  };
602
+
603
+ // src/components/Loader/Loader.jsx
604
+ var import_react11 = __toESM(require("react"));
605
+ var Loader = ({
606
+ size = "medium",
607
+ fullScreen = false,
608
+ color = "#7c3aed",
609
+ backgroundColor = "#0f172a",
610
+ duration = "1s"
611
+ }) => {
612
+ const sizes = { small: "40px", medium: "60px", large: "80px" };
613
+ const [fadeIn, setFadeIn] = (0, import_react11.useState)(false);
614
+ (0, import_react11.useEffect)(() => {
615
+ setFadeIn(true);
616
+ }, []);
617
+ return /* @__PURE__ */ import_react11.default.createElement(
618
+ "div",
619
+ {
620
+ style: {
621
+ display: "flex",
622
+ justifyContent: "center",
623
+ alignItems: "center",
624
+ height: fullScreen ? "100vh" : "auto",
625
+ background: fullScreen ? backgroundColor : "transparent",
626
+ transition: "opacity 0.5s",
627
+ opacity: fadeIn ? 1 : 0
628
+ }
629
+ },
630
+ /* @__PURE__ */ import_react11.default.createElement(
631
+ "div",
632
+ {
633
+ style: {
634
+ width: sizes[size],
635
+ height: sizes[size],
636
+ border: `8px solid ${color}`,
637
+ borderTop: `8px solid transparent`,
638
+ borderRadius: "50%",
639
+ animation: `spin ${duration} linear infinite`
640
+ }
641
+ }
642
+ ),
643
+ /* @__PURE__ */ import_react11.default.createElement("style", null, `
644
+ @keyframes spin {
645
+ 0% { transform: rotate(0deg); }
646
+ 100% { transform: rotate(360deg); }
647
+ }
648
+ `)
649
+ );
650
+ };
651
+
652
+ // src/components/OTPInput/OTPInput.jsx
653
+ var import_react12 = __toESM(require("react"));
654
+ var OTPInput = ({
655
+ length = 4,
656
+ bg = "#0f172a",
657
+ borderColorDefault = "#4b5563",
658
+ borderColorFocus = "#2563eb",
659
+ borderColorError = "#e11d48",
660
+ borderColorSuccess = "#059669",
661
+ color = "#f1f5f9",
662
+ radius = "8px",
663
+ onChange,
664
+ error = false,
665
+ success = false
666
+ }) => {
667
+ const [otp, setOtp] = (0, import_react12.useState)(Array(length).fill(""));
668
+ const inputRefs = (0, import_react12.useRef)(Array(length).fill().map(() => import_react12.default.createRef()));
669
+ (0, import_react12.useEffect)(() => {
670
+ inputRefs.current[0].current.focus();
671
+ }, []);
672
+ const handleChange = (index, value) => {
673
+ if (/[^0-9]/.test(value)) return;
674
+ const newOtp = [...otp];
675
+ newOtp[index] = value;
676
+ setOtp(newOtp);
677
+ onChange(newOtp.join(""));
678
+ if (value && index < length - 1) {
679
+ inputRefs.current[index + 1].current.focus();
680
+ }
681
+ };
682
+ const handleKeyDown = (index, event) => {
683
+ if (event.key === "Backspace" && !otp[index] && index > 0) {
684
+ inputRefs.current[index - 1].current.focus();
685
+ }
686
+ };
687
+ const handlePaste = (event) => {
688
+ const pastedData = event.clipboardData.getData("text").split("").slice(0, length);
689
+ const newOtp = pastedData.map((char, index) => char.match(/\d/) ? char : "");
690
+ setOtp(newOtp);
691
+ newOtp.forEach((_, index) => {
692
+ if (inputRefs.current[index]) {
693
+ inputRefs.current[index].current.focus();
694
+ }
695
+ });
696
+ onChange(newOtp.join(""));
697
+ event.preventDefault();
698
+ };
699
+ 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(
700
+ "input",
701
+ {
702
+ key: index,
703
+ ref: inputRefs.current[index],
704
+ value,
705
+ onChange: (e) => handleChange(index, e.target.value),
706
+ onKeyDown: (event) => handleKeyDown(index, event),
707
+ style: {
708
+ width: "40px",
709
+ height: "50px",
710
+ borderRadius: radius,
711
+ border: `2px solid ${error ? borderColorError : success ? borderColorSuccess : index === otp.findIndex((v) => v !== "") ? borderColorFocus : borderColorDefault}`,
712
+ background: bg,
713
+ color,
714
+ fontSize: "20px",
715
+ textAlign: "center",
716
+ outline: "none",
717
+ transition: "border-color 0.3s ease, transform 0.2s ease",
718
+ transform: `scale(${index === otp.findIndex((v) => v !== "") ? 1.05 : 1})`
719
+ },
720
+ autoFocus: index === 0
721
+ }
722
+ )));
723
+ };
600
724
  // Annotate the CommonJS export names for ESM import in node:
601
725
  0 && (module.exports = {
602
726
  AlertBanner,
@@ -608,5 +732,7 @@ var CopyButton = ({
608
732
  FormInput,
609
733
  GridLayout,
610
734
  ImageUploadPreview,
611
- Navbar
735
+ Loader,
736
+ Navbar,
737
+ OTPInput
612
738
  });
package/dist/index.mjs CHANGED
@@ -553,6 +553,128 @@ var CopyButton = ({
553
553
  copied ? "Copied!" : text
554
554
  );
555
555
  };
556
+
557
+ // src/components/Loader/Loader.jsx
558
+ import React11, { useEffect as useEffect5, useState as useState8 } from "react";
559
+ var Loader = ({
560
+ size = "medium",
561
+ fullScreen = false,
562
+ color = "#7c3aed",
563
+ backgroundColor = "#0f172a",
564
+ duration = "1s"
565
+ }) => {
566
+ const sizes = { small: "40px", medium: "60px", large: "80px" };
567
+ const [fadeIn, setFadeIn] = useState8(false);
568
+ useEffect5(() => {
569
+ setFadeIn(true);
570
+ }, []);
571
+ return /* @__PURE__ */ React11.createElement(
572
+ "div",
573
+ {
574
+ style: {
575
+ display: "flex",
576
+ justifyContent: "center",
577
+ alignItems: "center",
578
+ height: fullScreen ? "100vh" : "auto",
579
+ background: fullScreen ? backgroundColor : "transparent",
580
+ transition: "opacity 0.5s",
581
+ opacity: fadeIn ? 1 : 0
582
+ }
583
+ },
584
+ /* @__PURE__ */ React11.createElement(
585
+ "div",
586
+ {
587
+ style: {
588
+ width: sizes[size],
589
+ height: sizes[size],
590
+ border: `8px solid ${color}`,
591
+ borderTop: `8px solid transparent`,
592
+ borderRadius: "50%",
593
+ animation: `spin ${duration} linear infinite`
594
+ }
595
+ }
596
+ ),
597
+ /* @__PURE__ */ React11.createElement("style", null, `
598
+ @keyframes spin {
599
+ 0% { transform: rotate(0deg); }
600
+ 100% { transform: rotate(360deg); }
601
+ }
602
+ `)
603
+ );
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
+ };
556
678
  export {
557
679
  AlertBanner,
558
680
  Button,
@@ -563,5 +685,7 @@ export {
563
685
  FormInput,
564
686
  GridLayout,
565
687
  ImageUploadPreview,
566
- Navbar
688
+ Loader,
689
+ Navbar,
690
+ OTPInput
567
691
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "virtual-ui-lib",
3
- "version": "1.0.22",
3
+ "version": "1.0.24",
4
4
  "description": "Virtual UI React Component Library",
5
5
  "author": "Ankush",
6
6
  "license": "ISC",