virtual-ui-lib 1.0.73 → 1.0.74

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
+ ProgressBar: () => ProgressBar,
47
48
  RatingStars: () => RatingStars,
48
49
  Sidebar: () => Sidebar,
49
50
  StatCard: () => StatCard
@@ -3327,6 +3328,253 @@ var StatCard = ({
3327
3328
  ))
3328
3329
  ));
3329
3330
  };
3331
+
3332
+ // src/components/ProgressBar/ProgressBar.jsx
3333
+ var import_react19 = __toESM(require("react"));
3334
+ var ProgressBar = ({
3335
+ label = "Progress",
3336
+ percentage = 75,
3337
+ accent = "#6366f1",
3338
+ bg = "#ffffff",
3339
+ height = 12,
3340
+ showLabel = true,
3341
+ showPercent = true,
3342
+ type = "default",
3343
+ // "default" | "striped" | "circular" | "gradient" | "steps"
3344
+ steps = 5
3345
+ // only for type="steps"
3346
+ }) => {
3347
+ const [filled, setFilled] = (0, import_react19.useState)(0);
3348
+ const [visible, setVisible] = (0, import_react19.useState)(false);
3349
+ const ref = (0, import_react19.useRef)(null);
3350
+ (0, import_react19.useEffect)(() => {
3351
+ const obs = new IntersectionObserver(
3352
+ ([e]) => {
3353
+ if (e.isIntersecting) {
3354
+ setVisible(true);
3355
+ obs.disconnect();
3356
+ }
3357
+ },
3358
+ { threshold: 0.3 }
3359
+ );
3360
+ if (ref.current) obs.observe(ref.current);
3361
+ return () => obs.disconnect();
3362
+ }, []);
3363
+ (0, import_react19.useEffect)(() => {
3364
+ if (!visible) return;
3365
+ const duration = 1200;
3366
+ const start = performance.now();
3367
+ const target = Math.min(100, Math.max(0, percentage));
3368
+ const tick = (now) => {
3369
+ const p = Math.min((now - start) / duration, 1);
3370
+ const eased = 1 - Math.pow(1 - p, 4);
3371
+ setFilled(Math.round(eased * target));
3372
+ if (p < 1) requestAnimationFrame(tick);
3373
+ };
3374
+ requestAnimationFrame(tick);
3375
+ }, [visible, percentage]);
3376
+ const alpha = (hex, op) => {
3377
+ const r = parseInt(hex.slice(1, 3), 16);
3378
+ const g = parseInt(hex.slice(3, 5), 16);
3379
+ const b = parseInt(hex.slice(5, 7), 16);
3380
+ return `rgba(${r},${g},${b},${op})`;
3381
+ };
3382
+ const uid = (accent + label + type).replace(/[^a-z0-9]/gi, "x");
3383
+ const badgeColor = filled >= 80 ? "#16a34a" : filled >= 50 ? "#d97706" : "#dc2626";
3384
+ const badgeBg = filled >= 80 ? "#dcfce7" : filled >= 50 ? "#fef3c7" : "#fee2e2";
3385
+ const wrapStyle = {
3386
+ fontFamily: "'Sora', sans-serif",
3387
+ background: bg,
3388
+ borderRadius: "14px",
3389
+ padding: "20px 22px",
3390
+ display: "flex",
3391
+ flexDirection: "column",
3392
+ gap: "10px",
3393
+ border: "1px solid rgba(0,0,0,0.07)",
3394
+ boxShadow: "0 2px 12px rgba(0,0,0,0.05)",
3395
+ opacity: visible ? 1 : 0,
3396
+ transform: visible ? "translateY(0)" : "translateY(16px)",
3397
+ transition: "opacity 0.45s ease, transform 0.45s ease"
3398
+ };
3399
+ const rowStyle = { display: "flex", justifyContent: "space-between", alignItems: "center" };
3400
+ const labelEl = showLabel && /* @__PURE__ */ import_react19.default.createElement("span", { style: { fontSize: "0.85rem", fontWeight: 600, color: "#334155" } }, label);
3401
+ const badgeEl = showPercent && /* @__PURE__ */ import_react19.default.createElement("span", { style: {
3402
+ fontSize: "0.72rem",
3403
+ fontWeight: 700,
3404
+ color: badgeColor,
3405
+ background: badgeBg,
3406
+ padding: "3px 10px",
3407
+ borderRadius: "999px",
3408
+ transition: "color 0.4s,background 0.4s",
3409
+ fontVariantNumeric: "tabular-nums"
3410
+ } }, filled, "%");
3411
+ if (type === "default") return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("style", null, `
3412
+ @import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;600;700&display=swap');
3413
+ @keyframes pb-pulse-${uid} {
3414
+ 0%,100%{opacity:.9;transform:translateY(-50%) scale(1)}
3415
+ 50%{opacity:.4;transform:translateY(-50%) scale(1.5)}
3416
+ }
3417
+ `), /* @__PURE__ */ import_react19.default.createElement("div", { ref, style: wrapStyle }, /* @__PURE__ */ import_react19.default.createElement("div", { style: rowStyle }, labelEl, badgeEl), /* @__PURE__ */ import_react19.default.createElement("div", { style: { width: "100%", height, borderRadius: "999px", background: "#f1f5f9", overflow: "hidden", position: "relative" } }, /* @__PURE__ */ import_react19.default.createElement("div", { style: {
3418
+ height: "100%",
3419
+ width: `${filled}%`,
3420
+ borderRadius: "999px",
3421
+ background: `linear-gradient(90deg,${alpha(accent, 0.7)},${accent})`,
3422
+ boxShadow: `0 0 10px ${alpha(accent, 0.35)}`,
3423
+ position: "relative",
3424
+ transition: "width 0.05s linear"
3425
+ } }, /* @__PURE__ */ import_react19.default.createElement("div", { style: {
3426
+ position: "absolute",
3427
+ right: 0,
3428
+ top: "50%",
3429
+ width: height + 4,
3430
+ height: height + 4,
3431
+ borderRadius: "50%",
3432
+ background: accent,
3433
+ boxShadow: `0 0 8px 2px ${alpha(accent, 0.5)}`,
3434
+ animation: `pb-pulse-${uid} 1.5s ease-in-out infinite`
3435
+ } }))), /* @__PURE__ */ import_react19.default.createElement("div", { style: rowStyle }, /* @__PURE__ */ import_react19.default.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled < 100 ? `${filled} of 100 completed` : "Completed \u2713"), /* @__PURE__ */ import_react19.default.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled >= 80 ? "Almost there!" : filled >= 50 ? "Halfway done" : "Just started"))));
3436
+ if (type === "striped") return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("style", null, `
3437
+ @import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;600;700&display=swap');
3438
+ @keyframes pb-stripe-${uid} { from{background-position:0 0} to{background-position:32px 0} }
3439
+ @keyframes pb-pulse-${uid} {
3440
+ 0%,100%{opacity:.9;transform:translateY(-50%) scale(1)}
3441
+ 50%{opacity:.4;transform:translateY(-50%) scale(1.5)}
3442
+ }
3443
+ `), /* @__PURE__ */ import_react19.default.createElement("div", { ref, style: wrapStyle }, /* @__PURE__ */ import_react19.default.createElement("div", { style: rowStyle }, labelEl, badgeEl), /* @__PURE__ */ import_react19.default.createElement("div", { style: { width: "100%", height, borderRadius: "999px", background: "#f1f5f9", overflow: "hidden", position: "relative" } }, /* @__PURE__ */ import_react19.default.createElement("div", { style: {
3444
+ height: "100%",
3445
+ width: `${filled}%`,
3446
+ borderRadius: "999px",
3447
+ background: `linear-gradient(90deg,${alpha(accent, 0.7)},${accent})`,
3448
+ boxShadow: `0 0 10px ${alpha(accent, 0.35)}`,
3449
+ position: "relative",
3450
+ transition: "width 0.05s linear"
3451
+ } }, /* @__PURE__ */ import_react19.default.createElement("div", { style: {
3452
+ position: "absolute",
3453
+ inset: 0,
3454
+ borderRadius: "999px",
3455
+ background: "repeating-linear-gradient(45deg,transparent,transparent 8px,rgba(255,255,255,0.18) 8px,rgba(255,255,255,0.18) 16px)",
3456
+ animation: `pb-stripe-${uid} 0.7s linear infinite`
3457
+ } }), /* @__PURE__ */ import_react19.default.createElement("div", { style: {
3458
+ position: "absolute",
3459
+ right: 0,
3460
+ top: "50%",
3461
+ width: height + 4,
3462
+ height: height + 4,
3463
+ borderRadius: "50%",
3464
+ background: accent,
3465
+ boxShadow: `0 0 8px 2px ${alpha(accent, 0.5)}`,
3466
+ animation: `pb-pulse-${uid} 1.5s ease-in-out infinite`
3467
+ } }))), /* @__PURE__ */ import_react19.default.createElement("div", { style: rowStyle }, /* @__PURE__ */ import_react19.default.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled < 100 ? `${filled} of 100 completed` : "Completed \u2713"), /* @__PURE__ */ import_react19.default.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled >= 80 ? "Almost there!" : filled >= 50 ? "Halfway done" : "Just started"))));
3468
+ if (type === "circular") {
3469
+ const r = 54;
3470
+ const cx = 70;
3471
+ const cy = 70;
3472
+ const circ = 2 * Math.PI * r;
3473
+ const offset = circ - filled / 100 * circ;
3474
+ return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("style", null, `
3475
+ @import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;600;700;800&display=swap');
3476
+ @keyframes pb-spin-${uid} { from{stroke-dashoffset:${circ}} to{stroke-dashoffset:${offset}} }
3477
+ `), /* @__PURE__ */ import_react19.default.createElement("div", { ref, style: { ...wrapStyle, alignItems: "center", gap: 16 } }, /* @__PURE__ */ import_react19.default.createElement("svg", { width: "140", height: "140", viewBox: "0 0 140 140" }, /* @__PURE__ */ import_react19.default.createElement("circle", { cx, cy, r, fill: "none", stroke: "#f1f5f9", strokeWidth: "10" }), /* @__PURE__ */ import_react19.default.createElement(
3478
+ "circle",
3479
+ {
3480
+ cx,
3481
+ cy,
3482
+ r,
3483
+ fill: "none",
3484
+ stroke: accent,
3485
+ strokeWidth: "10",
3486
+ strokeLinecap: "round",
3487
+ strokeDasharray: circ,
3488
+ strokeDashoffset: offset,
3489
+ transform: `rotate(-90 ${cx} ${cy})`,
3490
+ style: { transition: "stroke-dashoffset 0.05s linear", filter: `drop-shadow(0 0 6px ${alpha(accent, 0.5)})` }
3491
+ }
3492
+ ), /* @__PURE__ */ import_react19.default.createElement(
3493
+ "text",
3494
+ {
3495
+ x: cx,
3496
+ y: cy - 8,
3497
+ textAnchor: "middle",
3498
+ dominantBaseline: "middle",
3499
+ style: { fontFamily: "'Sora',sans-serif", fontSize: "1.5rem", fontWeight: 800, fill: "#0f172a" }
3500
+ },
3501
+ filled,
3502
+ "%"
3503
+ ), /* @__PURE__ */ import_react19.default.createElement(
3504
+ "text",
3505
+ {
3506
+ x: cx,
3507
+ y: cy + 14,
3508
+ textAnchor: "middle",
3509
+ dominantBaseline: "middle",
3510
+ style: { fontFamily: "'Sora',sans-serif", fontSize: "0.68rem", fontWeight: 600, fill: "#94a3b8", letterSpacing: "0.05em" }
3511
+ },
3512
+ filled >= 80 ? "GREAT" : filled >= 50 ? "GOOD" : "LOW"
3513
+ )), showLabel && /* @__PURE__ */ import_react19.default.createElement("span", { style: { fontSize: "0.85rem", fontWeight: 600, color: "#334155" } }, label)));
3514
+ }
3515
+ if (type === "gradient") {
3516
+ const colors = ["#ef4444", "#f97316", "#eab308", "#22c55e", "#6366f1"];
3517
+ const gradStr = colors.map((c, i) => `${c} ${i * 25}%`).join(",");
3518
+ return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("style", null, `
3519
+ @import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;600;700&display=swap');
3520
+ @keyframes pb-pulse-${uid} {
3521
+ 0%,100%{opacity:.9;transform:translateY(-50%) scale(1)}
3522
+ 50%{opacity:.4;transform:translateY(-50%) scale(1.5)}
3523
+ }
3524
+ `), /* @__PURE__ */ import_react19.default.createElement("div", { ref, style: wrapStyle }, /* @__PURE__ */ import_react19.default.createElement("div", { style: rowStyle }, labelEl, badgeEl), /* @__PURE__ */ import_react19.default.createElement("div", { style: { width: "100%", height, borderRadius: "999px", background: "#f1f5f9", overflow: "hidden", position: "relative" } }, /* @__PURE__ */ import_react19.default.createElement("div", { style: { position: "absolute", inset: 0, background: `linear-gradient(90deg,${gradStr})`, opacity: 0.15 } }), /* @__PURE__ */ import_react19.default.createElement("div", { style: {
3525
+ height: "100%",
3526
+ width: `${filled}%`,
3527
+ borderRadius: "999px",
3528
+ background: `linear-gradient(90deg,${gradStr})`,
3529
+ transition: "width 0.05s linear",
3530
+ position: "relative"
3531
+ } }, /* @__PURE__ */ import_react19.default.createElement("div", { style: {
3532
+ position: "absolute",
3533
+ right: 0,
3534
+ top: "50%",
3535
+ width: height + 4,
3536
+ height: height + 4,
3537
+ borderRadius: "50%",
3538
+ background: "#fff",
3539
+ border: `2px solid ${accent}`,
3540
+ animation: `pb-pulse-${uid} 1.5s ease-in-out infinite`
3541
+ } }))), /* @__PURE__ */ import_react19.default.createElement("div", { style: rowStyle }, /* @__PURE__ */ import_react19.default.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled < 100 ? `${filled} of 100` : "Completed \u2713"), /* @__PURE__ */ import_react19.default.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled >= 80 ? "Almost there!" : filled >= 50 ? "Halfway done" : "Just started"))));
3542
+ }
3543
+ if (type === "steps") {
3544
+ const completedSteps = Math.round(filled / 100 * steps);
3545
+ return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("style", null, `
3546
+ @import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;600;700&display=swap');
3547
+ @keyframes pb-popin-${uid} {
3548
+ from{transform:scale(0.5);opacity:0}
3549
+ to{transform:scale(1);opacity:1}
3550
+ }
3551
+ `), /* @__PURE__ */ import_react19.default.createElement("div", { ref, style: wrapStyle }, /* @__PURE__ */ import_react19.default.createElement("div", { style: rowStyle }, labelEl, badgeEl), /* @__PURE__ */ import_react19.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: 0 } }, Array.from({ length: steps }, (_, i) => {
3552
+ const done = i < completedSteps;
3553
+ const active = i === completedSteps - 1;
3554
+ return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, { key: i }, /* @__PURE__ */ import_react19.default.createElement("div", { style: {
3555
+ width: 32,
3556
+ height: 32,
3557
+ borderRadius: "50%",
3558
+ background: done ? accent : "#f1f5f9",
3559
+ border: active ? `2px solid ${accent}` : done ? "none" : "2px solid #e2e8f0",
3560
+ display: "flex",
3561
+ alignItems: "center",
3562
+ justifyContent: "center",
3563
+ flexShrink: 0,
3564
+ boxShadow: active ? `0 0 12px ${alpha(accent, 0.4)}` : "none",
3565
+ transition: "background 0.3s,box-shadow 0.3s",
3566
+ animation: done ? `pb-popin-${uid} 0.3s ease ${i * 0.08}s both` : "none"
3567
+ } }, done ? /* @__PURE__ */ import_react19.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none" }, /* @__PURE__ */ import_react19.default.createElement("path", { d: "M2.5 7l3.5 3.5 5.5-6", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })) : /* @__PURE__ */ import_react19.default.createElement("span", { style: { fontSize: "0.7rem", fontWeight: 700, color: "#cbd5e1" } }, i + 1)), i < steps - 1 && /* @__PURE__ */ import_react19.default.createElement("div", { style: {
3568
+ flex: 1,
3569
+ height: 3,
3570
+ borderRadius: "999px",
3571
+ background: i < completedSteps - 1 ? accent : "#f1f5f9",
3572
+ transition: "background 0.3s"
3573
+ } }));
3574
+ })), /* @__PURE__ */ import_react19.default.createElement("div", { style: rowStyle }, /* @__PURE__ */ import_react19.default.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, "Step ", completedSteps, " of ", steps), /* @__PURE__ */ import_react19.default.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled >= 80 ? "Almost there!" : filled >= 50 ? "Halfway done" : "Just started"))));
3575
+ }
3576
+ return null;
3577
+ };
3330
3578
  // Annotate the CommonJS export names for ESM import in node:
3331
3579
  0 && (module.exports = {
3332
3580
  AvatarCard,
@@ -3344,6 +3592,7 @@ var StatCard = ({
3344
3592
  OTPInput,
3345
3593
  PageLoader,
3346
3594
  PricingCard,
3595
+ ProgressBar,
3347
3596
  RatingStars,
3348
3597
  Sidebar,
3349
3598
  StatCard
package/dist/index.mjs CHANGED
@@ -3275,6 +3275,253 @@ var StatCard = ({
3275
3275
  ))
3276
3276
  ));
3277
3277
  };
3278
+
3279
+ // src/components/ProgressBar/ProgressBar.jsx
3280
+ import React19, { useEffect as useEffect8, useRef as useRef4, useState as useState17 } from "react";
3281
+ var ProgressBar = ({
3282
+ label = "Progress",
3283
+ percentage = 75,
3284
+ accent = "#6366f1",
3285
+ bg = "#ffffff",
3286
+ height = 12,
3287
+ showLabel = true,
3288
+ showPercent = true,
3289
+ type = "default",
3290
+ // "default" | "striped" | "circular" | "gradient" | "steps"
3291
+ steps = 5
3292
+ // only for type="steps"
3293
+ }) => {
3294
+ const [filled, setFilled] = useState17(0);
3295
+ const [visible, setVisible] = useState17(false);
3296
+ const ref = useRef4(null);
3297
+ useEffect8(() => {
3298
+ const obs = new IntersectionObserver(
3299
+ ([e]) => {
3300
+ if (e.isIntersecting) {
3301
+ setVisible(true);
3302
+ obs.disconnect();
3303
+ }
3304
+ },
3305
+ { threshold: 0.3 }
3306
+ );
3307
+ if (ref.current) obs.observe(ref.current);
3308
+ return () => obs.disconnect();
3309
+ }, []);
3310
+ useEffect8(() => {
3311
+ if (!visible) return;
3312
+ const duration = 1200;
3313
+ const start = performance.now();
3314
+ const target = Math.min(100, Math.max(0, percentage));
3315
+ const tick = (now) => {
3316
+ const p = Math.min((now - start) / duration, 1);
3317
+ const eased = 1 - Math.pow(1 - p, 4);
3318
+ setFilled(Math.round(eased * target));
3319
+ if (p < 1) requestAnimationFrame(tick);
3320
+ };
3321
+ requestAnimationFrame(tick);
3322
+ }, [visible, percentage]);
3323
+ const alpha = (hex, op) => {
3324
+ const r = parseInt(hex.slice(1, 3), 16);
3325
+ const g = parseInt(hex.slice(3, 5), 16);
3326
+ const b = parseInt(hex.slice(5, 7), 16);
3327
+ return `rgba(${r},${g},${b},${op})`;
3328
+ };
3329
+ const uid = (accent + label + type).replace(/[^a-z0-9]/gi, "x");
3330
+ const badgeColor = filled >= 80 ? "#16a34a" : filled >= 50 ? "#d97706" : "#dc2626";
3331
+ const badgeBg = filled >= 80 ? "#dcfce7" : filled >= 50 ? "#fef3c7" : "#fee2e2";
3332
+ const wrapStyle = {
3333
+ fontFamily: "'Sora', sans-serif",
3334
+ background: bg,
3335
+ borderRadius: "14px",
3336
+ padding: "20px 22px",
3337
+ display: "flex",
3338
+ flexDirection: "column",
3339
+ gap: "10px",
3340
+ border: "1px solid rgba(0,0,0,0.07)",
3341
+ boxShadow: "0 2px 12px rgba(0,0,0,0.05)",
3342
+ opacity: visible ? 1 : 0,
3343
+ transform: visible ? "translateY(0)" : "translateY(16px)",
3344
+ transition: "opacity 0.45s ease, transform 0.45s ease"
3345
+ };
3346
+ const rowStyle = { display: "flex", justifyContent: "space-between", alignItems: "center" };
3347
+ const labelEl = showLabel && /* @__PURE__ */ React19.createElement("span", { style: { fontSize: "0.85rem", fontWeight: 600, color: "#334155" } }, label);
3348
+ const badgeEl = showPercent && /* @__PURE__ */ React19.createElement("span", { style: {
3349
+ fontSize: "0.72rem",
3350
+ fontWeight: 700,
3351
+ color: badgeColor,
3352
+ background: badgeBg,
3353
+ padding: "3px 10px",
3354
+ borderRadius: "999px",
3355
+ transition: "color 0.4s,background 0.4s",
3356
+ fontVariantNumeric: "tabular-nums"
3357
+ } }, filled, "%");
3358
+ if (type === "default") return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("style", null, `
3359
+ @import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;600;700&display=swap');
3360
+ @keyframes pb-pulse-${uid} {
3361
+ 0%,100%{opacity:.9;transform:translateY(-50%) scale(1)}
3362
+ 50%{opacity:.4;transform:translateY(-50%) scale(1.5)}
3363
+ }
3364
+ `), /* @__PURE__ */ React19.createElement("div", { ref, style: wrapStyle }, /* @__PURE__ */ React19.createElement("div", { style: rowStyle }, labelEl, badgeEl), /* @__PURE__ */ React19.createElement("div", { style: { width: "100%", height, borderRadius: "999px", background: "#f1f5f9", overflow: "hidden", position: "relative" } }, /* @__PURE__ */ React19.createElement("div", { style: {
3365
+ height: "100%",
3366
+ width: `${filled}%`,
3367
+ borderRadius: "999px",
3368
+ background: `linear-gradient(90deg,${alpha(accent, 0.7)},${accent})`,
3369
+ boxShadow: `0 0 10px ${alpha(accent, 0.35)}`,
3370
+ position: "relative",
3371
+ transition: "width 0.05s linear"
3372
+ } }, /* @__PURE__ */ React19.createElement("div", { style: {
3373
+ position: "absolute",
3374
+ right: 0,
3375
+ top: "50%",
3376
+ width: height + 4,
3377
+ height: height + 4,
3378
+ borderRadius: "50%",
3379
+ background: accent,
3380
+ boxShadow: `0 0 8px 2px ${alpha(accent, 0.5)}`,
3381
+ animation: `pb-pulse-${uid} 1.5s ease-in-out infinite`
3382
+ } }))), /* @__PURE__ */ React19.createElement("div", { style: rowStyle }, /* @__PURE__ */ React19.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled < 100 ? `${filled} of 100 completed` : "Completed \u2713"), /* @__PURE__ */ React19.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled >= 80 ? "Almost there!" : filled >= 50 ? "Halfway done" : "Just started"))));
3383
+ if (type === "striped") return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("style", null, `
3384
+ @import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;600;700&display=swap');
3385
+ @keyframes pb-stripe-${uid} { from{background-position:0 0} to{background-position:32px 0} }
3386
+ @keyframes pb-pulse-${uid} {
3387
+ 0%,100%{opacity:.9;transform:translateY(-50%) scale(1)}
3388
+ 50%{opacity:.4;transform:translateY(-50%) scale(1.5)}
3389
+ }
3390
+ `), /* @__PURE__ */ React19.createElement("div", { ref, style: wrapStyle }, /* @__PURE__ */ React19.createElement("div", { style: rowStyle }, labelEl, badgeEl), /* @__PURE__ */ React19.createElement("div", { style: { width: "100%", height, borderRadius: "999px", background: "#f1f5f9", overflow: "hidden", position: "relative" } }, /* @__PURE__ */ React19.createElement("div", { style: {
3391
+ height: "100%",
3392
+ width: `${filled}%`,
3393
+ borderRadius: "999px",
3394
+ background: `linear-gradient(90deg,${alpha(accent, 0.7)},${accent})`,
3395
+ boxShadow: `0 0 10px ${alpha(accent, 0.35)}`,
3396
+ position: "relative",
3397
+ transition: "width 0.05s linear"
3398
+ } }, /* @__PURE__ */ React19.createElement("div", { style: {
3399
+ position: "absolute",
3400
+ inset: 0,
3401
+ borderRadius: "999px",
3402
+ background: "repeating-linear-gradient(45deg,transparent,transparent 8px,rgba(255,255,255,0.18) 8px,rgba(255,255,255,0.18) 16px)",
3403
+ animation: `pb-stripe-${uid} 0.7s linear infinite`
3404
+ } }), /* @__PURE__ */ React19.createElement("div", { style: {
3405
+ position: "absolute",
3406
+ right: 0,
3407
+ top: "50%",
3408
+ width: height + 4,
3409
+ height: height + 4,
3410
+ borderRadius: "50%",
3411
+ background: accent,
3412
+ boxShadow: `0 0 8px 2px ${alpha(accent, 0.5)}`,
3413
+ animation: `pb-pulse-${uid} 1.5s ease-in-out infinite`
3414
+ } }))), /* @__PURE__ */ React19.createElement("div", { style: rowStyle }, /* @__PURE__ */ React19.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled < 100 ? `${filled} of 100 completed` : "Completed \u2713"), /* @__PURE__ */ React19.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled >= 80 ? "Almost there!" : filled >= 50 ? "Halfway done" : "Just started"))));
3415
+ if (type === "circular") {
3416
+ const r = 54;
3417
+ const cx = 70;
3418
+ const cy = 70;
3419
+ const circ = 2 * Math.PI * r;
3420
+ const offset = circ - filled / 100 * circ;
3421
+ return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("style", null, `
3422
+ @import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;600;700;800&display=swap');
3423
+ @keyframes pb-spin-${uid} { from{stroke-dashoffset:${circ}} to{stroke-dashoffset:${offset}} }
3424
+ `), /* @__PURE__ */ React19.createElement("div", { ref, style: { ...wrapStyle, alignItems: "center", gap: 16 } }, /* @__PURE__ */ React19.createElement("svg", { width: "140", height: "140", viewBox: "0 0 140 140" }, /* @__PURE__ */ React19.createElement("circle", { cx, cy, r, fill: "none", stroke: "#f1f5f9", strokeWidth: "10" }), /* @__PURE__ */ React19.createElement(
3425
+ "circle",
3426
+ {
3427
+ cx,
3428
+ cy,
3429
+ r,
3430
+ fill: "none",
3431
+ stroke: accent,
3432
+ strokeWidth: "10",
3433
+ strokeLinecap: "round",
3434
+ strokeDasharray: circ,
3435
+ strokeDashoffset: offset,
3436
+ transform: `rotate(-90 ${cx} ${cy})`,
3437
+ style: { transition: "stroke-dashoffset 0.05s linear", filter: `drop-shadow(0 0 6px ${alpha(accent, 0.5)})` }
3438
+ }
3439
+ ), /* @__PURE__ */ React19.createElement(
3440
+ "text",
3441
+ {
3442
+ x: cx,
3443
+ y: cy - 8,
3444
+ textAnchor: "middle",
3445
+ dominantBaseline: "middle",
3446
+ style: { fontFamily: "'Sora',sans-serif", fontSize: "1.5rem", fontWeight: 800, fill: "#0f172a" }
3447
+ },
3448
+ filled,
3449
+ "%"
3450
+ ), /* @__PURE__ */ React19.createElement(
3451
+ "text",
3452
+ {
3453
+ x: cx,
3454
+ y: cy + 14,
3455
+ textAnchor: "middle",
3456
+ dominantBaseline: "middle",
3457
+ style: { fontFamily: "'Sora',sans-serif", fontSize: "0.68rem", fontWeight: 600, fill: "#94a3b8", letterSpacing: "0.05em" }
3458
+ },
3459
+ filled >= 80 ? "GREAT" : filled >= 50 ? "GOOD" : "LOW"
3460
+ )), showLabel && /* @__PURE__ */ React19.createElement("span", { style: { fontSize: "0.85rem", fontWeight: 600, color: "#334155" } }, label)));
3461
+ }
3462
+ if (type === "gradient") {
3463
+ const colors = ["#ef4444", "#f97316", "#eab308", "#22c55e", "#6366f1"];
3464
+ const gradStr = colors.map((c, i) => `${c} ${i * 25}%`).join(",");
3465
+ return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("style", null, `
3466
+ @import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;600;700&display=swap');
3467
+ @keyframes pb-pulse-${uid} {
3468
+ 0%,100%{opacity:.9;transform:translateY(-50%) scale(1)}
3469
+ 50%{opacity:.4;transform:translateY(-50%) scale(1.5)}
3470
+ }
3471
+ `), /* @__PURE__ */ React19.createElement("div", { ref, style: wrapStyle }, /* @__PURE__ */ React19.createElement("div", { style: rowStyle }, labelEl, badgeEl), /* @__PURE__ */ React19.createElement("div", { style: { width: "100%", height, borderRadius: "999px", background: "#f1f5f9", overflow: "hidden", position: "relative" } }, /* @__PURE__ */ React19.createElement("div", { style: { position: "absolute", inset: 0, background: `linear-gradient(90deg,${gradStr})`, opacity: 0.15 } }), /* @__PURE__ */ React19.createElement("div", { style: {
3472
+ height: "100%",
3473
+ width: `${filled}%`,
3474
+ borderRadius: "999px",
3475
+ background: `linear-gradient(90deg,${gradStr})`,
3476
+ transition: "width 0.05s linear",
3477
+ position: "relative"
3478
+ } }, /* @__PURE__ */ React19.createElement("div", { style: {
3479
+ position: "absolute",
3480
+ right: 0,
3481
+ top: "50%",
3482
+ width: height + 4,
3483
+ height: height + 4,
3484
+ borderRadius: "50%",
3485
+ background: "#fff",
3486
+ border: `2px solid ${accent}`,
3487
+ animation: `pb-pulse-${uid} 1.5s ease-in-out infinite`
3488
+ } }))), /* @__PURE__ */ React19.createElement("div", { style: rowStyle }, /* @__PURE__ */ React19.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled < 100 ? `${filled} of 100` : "Completed \u2713"), /* @__PURE__ */ React19.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled >= 80 ? "Almost there!" : filled >= 50 ? "Halfway done" : "Just started"))));
3489
+ }
3490
+ if (type === "steps") {
3491
+ const completedSteps = Math.round(filled / 100 * steps);
3492
+ return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("style", null, `
3493
+ @import url('https://fonts.googleapis.com/css2?family=Sora:wght@400;600;700&display=swap');
3494
+ @keyframes pb-popin-${uid} {
3495
+ from{transform:scale(0.5);opacity:0}
3496
+ to{transform:scale(1);opacity:1}
3497
+ }
3498
+ `), /* @__PURE__ */ React19.createElement("div", { ref, style: wrapStyle }, /* @__PURE__ */ React19.createElement("div", { style: rowStyle }, labelEl, badgeEl), /* @__PURE__ */ React19.createElement("div", { style: { display: "flex", alignItems: "center", gap: 0 } }, Array.from({ length: steps }, (_, i) => {
3499
+ const done = i < completedSteps;
3500
+ const active = i === completedSteps - 1;
3501
+ return /* @__PURE__ */ React19.createElement(React19.Fragment, { key: i }, /* @__PURE__ */ React19.createElement("div", { style: {
3502
+ width: 32,
3503
+ height: 32,
3504
+ borderRadius: "50%",
3505
+ background: done ? accent : "#f1f5f9",
3506
+ border: active ? `2px solid ${accent}` : done ? "none" : "2px solid #e2e8f0",
3507
+ display: "flex",
3508
+ alignItems: "center",
3509
+ justifyContent: "center",
3510
+ flexShrink: 0,
3511
+ boxShadow: active ? `0 0 12px ${alpha(accent, 0.4)}` : "none",
3512
+ transition: "background 0.3s,box-shadow 0.3s",
3513
+ animation: done ? `pb-popin-${uid} 0.3s ease ${i * 0.08}s both` : "none"
3514
+ } }, done ? /* @__PURE__ */ React19.createElement("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none" }, /* @__PURE__ */ React19.createElement("path", { d: "M2.5 7l3.5 3.5 5.5-6", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })) : /* @__PURE__ */ React19.createElement("span", { style: { fontSize: "0.7rem", fontWeight: 700, color: "#cbd5e1" } }, i + 1)), i < steps - 1 && /* @__PURE__ */ React19.createElement("div", { style: {
3515
+ flex: 1,
3516
+ height: 3,
3517
+ borderRadius: "999px",
3518
+ background: i < completedSteps - 1 ? accent : "#f1f5f9",
3519
+ transition: "background 0.3s"
3520
+ } }));
3521
+ })), /* @__PURE__ */ React19.createElement("div", { style: rowStyle }, /* @__PURE__ */ React19.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, "Step ", completedSteps, " of ", steps), /* @__PURE__ */ React19.createElement("span", { style: { fontSize: "0.7rem", color: "#94a3b8" } }, filled >= 80 ? "Almost there!" : filled >= 50 ? "Halfway done" : "Just started"))));
3522
+ }
3523
+ return null;
3524
+ };
3278
3525
  export {
3279
3526
  AvatarCard,
3280
3527
  BackgoundImageSlider,
@@ -3291,6 +3538,7 @@ export {
3291
3538
  OTPInput,
3292
3539
  PageLoader,
3293
3540
  PricingCard,
3541
+ ProgressBar,
3294
3542
  RatingStars,
3295
3543
  Sidebar,
3296
3544
  StatCard
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "virtual-ui-lib",
3
- "version": "1.0.73",
3
+ "version": "1.0.74",
4
4
  "description": "Virtual UI React Component Library",
5
5
  "author": "Ankush",
6
6
  "license": "ISC",