@tangle-network/sandbox-ui 0.20.2 → 0.21.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.
@@ -127,8 +127,8 @@ function resolveModelBrandIdentity(model) {
127
127
  const labKey = normalizeBrandKey(model.logos?.lab ?? model.modelLab ?? inferModelLab(model, canonical, hostKey));
128
128
  const hostBase = brandInfo(hostKey);
129
129
  const labBase = brandInfo(labKey);
130
- const host = { ...hostBase, logoUrl: model.logos?.hostUrl ?? hostBase.logoUrl };
131
- const lab = { ...labBase, logoUrl: model.logos?.labUrl ?? labBase.logoUrl };
130
+ const host = model.logos?.hostUrl ? { ...hostBase, logoUrl: model.logos.hostUrl, monochrome: false } : hostBase;
131
+ const lab = model.logos?.labUrl ? { ...labBase, logoUrl: model.logos.labUrl, monochrome: false } : labBase;
132
132
  return {
133
133
  host,
134
134
  lab,
@@ -468,13 +468,33 @@ function BrandLogo({ brand, size, className }) {
468
468
  size === "md" && "h-7 w-7",
469
469
  className
470
470
  ),
471
- children: brand.logo === "tangle" ? /* @__PURE__ */ jsx(TangleKnot, { size: pixelSize, className: "h-full w-full" }) : brand.logoUrl ? /* @__PURE__ */ jsx("img", { src: brand.logoUrl, alt: "", className: "h-[72%] w-[72%] object-contain" }) : null
471
+ children: brand.logo === "tangle" ? /* @__PURE__ */ jsx(TangleKnot, { size: pixelSize, className: "h-full w-full" }) : brand.logoUrl && brand.monochrome ? /* @__PURE__ */ jsx(
472
+ "span",
473
+ {
474
+ "aria-hidden": true,
475
+ className: "h-[72%] w-[72%]",
476
+ style: {
477
+ backgroundColor: "hsl(var(--foreground))",
478
+ maskImage: cssUrl(brand.logoUrl),
479
+ maskSize: "contain",
480
+ maskRepeat: "no-repeat",
481
+ maskPosition: "center",
482
+ WebkitMaskImage: cssUrl(brand.logoUrl),
483
+ WebkitMaskSize: "contain",
484
+ WebkitMaskRepeat: "no-repeat",
485
+ WebkitMaskPosition: "center"
486
+ }
487
+ }
488
+ ) : brand.logoUrl ? /* @__PURE__ */ jsx("img", { src: brand.logoUrl, alt: "", className: "h-[72%] w-[72%] object-contain" }) : null
472
489
  }
473
490
  );
474
491
  }
475
492
  function hasRealLogo(brand) {
476
493
  return Boolean(brand.logoUrl || brand.logo);
477
494
  }
495
+ function cssUrl(url) {
496
+ return `url("${url.replace(/[\\"'#\n]/g, (char) => encodeURIComponent(char))}")`;
497
+ }
478
498
  function modelLogo(path) {
479
499
  return path;
480
500
  }
@@ -548,7 +568,7 @@ function brandLogo(key) {
548
568
  function brandMark(key) {
549
569
  if (key === "tangle" || key === "tcloud") return { logo: "tangle" };
550
570
  const logoUrl = brandLogo(key);
551
- return logoUrl ? { logoUrl } : {};
571
+ return logoUrl ? { logoUrl, monochrome: true } : {};
552
572
  }
553
573
  function inferModelLab(model, canonical, hostKey) {
554
574
  const name = model.name ?? "";
@@ -638,550 +658,9 @@ var BRAND_INFO = {
638
658
  unknown: { key: "unknown", label: "Unknown" }
639
659
  };
640
660
 
641
- // src/dashboard/billing-dashboard.tsx
642
- import { Button } from "@tangle-network/ui/primitives";
643
- import { Badge } from "@tangle-network/ui/primitives";
644
- import {
645
- Card,
646
- CardContent,
647
- CardDescription,
648
- CardHeader,
649
- CardTitle
650
- } from "@tangle-network/ui/primitives";
651
- import { Progress } from "@tangle-network/ui/primitives";
652
- import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
653
- var variantColors = {
654
- sandbox: {
655
- accent: "text-[var(--accent-text)]",
656
- accentBg: "bg-[var(--accent-surface-soft)]",
657
- border: "border-[var(--border-accent)]",
658
- progress: "bg-[image:var(--accent-gradient-strong)]"
659
- }
660
- };
661
- function formatCredits(value) {
662
- if (value >= 1e6) {
663
- return `${(value / 1e6).toFixed(1)}M`;
664
- }
665
- if (value >= 1e3) {
666
- return `${(value / 1e3).toFixed(1)}K`;
667
- }
668
- return value.toLocaleString();
669
- }
670
- function formatDate(dateStr) {
671
- const date = new Date(dateStr);
672
- return date.toLocaleDateString("en-US", {
673
- month: "long",
674
- day: "numeric",
675
- year: "numeric"
676
- });
677
- }
678
- function getStatusBadgeVariant(status) {
679
- switch (status.toLowerCase()) {
680
- case "active":
681
- return "success";
682
- case "trialing":
683
- case "past_due":
684
- return "warning";
685
- case "canceled":
686
- case "unpaid":
687
- return "error";
688
- default:
689
- return "secondary";
690
- }
691
- }
692
- function CreditCardIcon({ className }) {
693
- return /* @__PURE__ */ jsxs2(
694
- "svg",
695
- {
696
- xmlns: "http://www.w3.org/2000/svg",
697
- viewBox: "0 0 24 24",
698
- fill: "none",
699
- stroke: "currentColor",
700
- strokeWidth: "2",
701
- strokeLinecap: "round",
702
- strokeLinejoin: "round",
703
- className: cn("h-5 w-5", className),
704
- children: [
705
- /* @__PURE__ */ jsx2("title", { children: "Credit card icon" }),
706
- /* @__PURE__ */ jsx2("rect", { width: "20", height: "14", x: "2", y: "5", rx: "2" }),
707
- /* @__PURE__ */ jsx2("line", { x1: "2", x2: "22", y1: "10", y2: "10" })
708
- ]
709
- }
710
- );
711
- }
712
- function CoinsIcon({ className }) {
713
- return /* @__PURE__ */ jsxs2(
714
- "svg",
715
- {
716
- xmlns: "http://www.w3.org/2000/svg",
717
- viewBox: "0 0 24 24",
718
- fill: "none",
719
- stroke: "currentColor",
720
- strokeWidth: "2",
721
- strokeLinecap: "round",
722
- strokeLinejoin: "round",
723
- className: cn("h-5 w-5", className),
724
- children: [
725
- /* @__PURE__ */ jsx2("title", { children: "Coins icon" }),
726
- /* @__PURE__ */ jsx2("circle", { cx: "8", cy: "8", r: "6" }),
727
- /* @__PURE__ */ jsx2("path", { d: "M18.09 10.37A6 6 0 1 1 10.34 18" }),
728
- /* @__PURE__ */ jsx2("path", { d: "M7 6h1v4" }),
729
- /* @__PURE__ */ jsx2("path", { d: "m16.71 13.88.7.71-2.82 2.82" })
730
- ]
731
- }
732
- );
733
- }
734
- function ChartIcon({ className }) {
735
- return /* @__PURE__ */ jsxs2(
736
- "svg",
737
- {
738
- xmlns: "http://www.w3.org/2000/svg",
739
- viewBox: "0 0 24 24",
740
- fill: "none",
741
- stroke: "currentColor",
742
- strokeWidth: "2",
743
- strokeLinecap: "round",
744
- strokeLinejoin: "round",
745
- className: cn("h-5 w-5", className),
746
- children: [
747
- /* @__PURE__ */ jsx2("title", { children: "Chart icon" }),
748
- /* @__PURE__ */ jsx2("path", { d: "M3 3v18h18" }),
749
- /* @__PURE__ */ jsx2("path", { d: "m19 9-5 5-4-4-3 3" })
750
- ]
751
- }
752
- );
753
- }
754
- function BillingDashboard({
755
- subscription,
756
- balance,
757
- usage,
758
- onManageSubscription,
759
- onAddCredits,
760
- variant = "sandbox",
761
- className,
762
- cardClassName
763
- }) {
764
- const colors2 = variantColors[variant];
765
- const totalCredits = balance.available + balance.used;
766
- const usagePercent = totalCredits > 0 ? balance.used / totalCredits * 100 : 0;
767
- const sortedModels = Object.entries(usage.byModel).sort(
768
- ([, a], [, b]) => b - a
769
- );
770
- return /* @__PURE__ */ jsxs2("div", { className: cn("grid gap-6 lg:grid-cols-3", className), children: [
771
- /* @__PURE__ */ jsxs2(Card, { variant, className: cn("lg:col-span-1", cardClassName), children: [
772
- /* @__PURE__ */ jsx2(CardHeader, { children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between", children: [
773
- /* @__PURE__ */ jsxs2(CardTitle, { className: "flex items-center gap-2 text-base", children: [
774
- /* @__PURE__ */ jsx2(CreditCardIcon, { className: colors2.accent }),
775
- "Current Plan"
776
- ] }),
777
- subscription && /* @__PURE__ */ jsx2(Badge, { variant: getStatusBadgeVariant(subscription.status), children: subscription.status })
778
- ] }) }),
779
- /* @__PURE__ */ jsx2(CardContent, { className: "space-y-4", children: subscription ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
780
- /* @__PURE__ */ jsxs2("div", { children: [
781
- /* @__PURE__ */ jsx2("p", { className: cn("font-bold text-2xl", colors2.accent), children: subscription.tierName }),
782
- /* @__PURE__ */ jsxs2("p", { className: "text-muted-foreground text-sm", children: [
783
- "Renews ",
784
- formatDate(subscription.renewsAt)
785
- ] })
786
- ] }),
787
- /* @__PURE__ */ jsx2(
788
- Button,
789
- {
790
- variant: "outline",
791
- className: "w-full",
792
- onClick: onManageSubscription,
793
- children: "Manage Subscription"
794
- }
795
- )
796
- ] }) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
797
- /* @__PURE__ */ jsxs2("div", { children: [
798
- /* @__PURE__ */ jsx2("p", { className: "font-bold text-2xl text-muted-foreground", children: "No Active Plan" }),
799
- /* @__PURE__ */ jsx2("p", { className: "text-muted-foreground text-sm", children: "Subscribe to get started" })
800
- ] }),
801
- /* @__PURE__ */ jsx2(
802
- Button,
803
- {
804
- variant,
805
- className: "w-full",
806
- onClick: onManageSubscription,
807
- children: "View Plans"
808
- }
809
- )
810
- ] }) })
811
- ] }),
812
- /* @__PURE__ */ jsxs2(Card, { variant, className: cn("lg:col-span-1", cardClassName), children: [
813
- /* @__PURE__ */ jsxs2(CardHeader, { children: [
814
- /* @__PURE__ */ jsxs2(CardTitle, { className: "flex items-center gap-2 text-base", children: [
815
- /* @__PURE__ */ jsx2(CoinsIcon, { className: colors2.accent }),
816
- "Credit Balance"
817
- ] }),
818
- /* @__PURE__ */ jsxs2(CardDescription, { children: [
819
- formatCredits(balance.available),
820
- " credits remaining"
821
- ] })
822
- ] }),
823
- /* @__PURE__ */ jsxs2(CardContent, { className: "space-y-4", children: [
824
- /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
825
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between text-sm", children: [
826
- /* @__PURE__ */ jsx2("span", { className: "text-muted-foreground", children: "Used" }),
827
- /* @__PURE__ */ jsx2("span", { className: "font-medium", children: formatCredits(balance.used) })
828
- ] }),
829
- /* @__PURE__ */ jsx2(Progress, { value: usagePercent, variant, className: "h-3" }),
830
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between text-sm", children: [
831
- /* @__PURE__ */ jsx2("span", { className: "text-muted-foreground", children: "Available" }),
832
- /* @__PURE__ */ jsx2("span", { className: cn("font-medium", colors2.accent), children: formatCredits(balance.available) })
833
- ] })
834
- ] }),
835
- /* @__PURE__ */ jsx2(Button, { variant, className: "w-full", onClick: onAddCredits, children: "Add Credits" })
836
- ] })
837
- ] }),
838
- /* @__PURE__ */ jsxs2(Card, { variant, className: cn("lg:col-span-1", cardClassName), children: [
839
- /* @__PURE__ */ jsxs2(CardHeader, { children: [
840
- /* @__PURE__ */ jsxs2(CardTitle, { className: "flex items-center gap-2 text-base", children: [
841
- /* @__PURE__ */ jsx2(ChartIcon, { className: colors2.accent }),
842
- "Usage Breakdown"
843
- ] }),
844
- /* @__PURE__ */ jsx2(CardDescription, { children: usage.period })
845
- ] }),
846
- /* @__PURE__ */ jsxs2(CardContent, { className: "space-y-4", children: [
847
- /* @__PURE__ */ jsxs2("div", { className: "flex items-baseline justify-between", children: [
848
- /* @__PURE__ */ jsx2("span", { className: "text-muted-foreground text-sm", children: "Total Usage" }),
849
- /* @__PURE__ */ jsx2("span", { className: cn("font-bold text-2xl", colors2.accent), children: formatCredits(usage.total) })
850
- ] }),
851
- /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
852
- /* @__PURE__ */ jsx2("p", { className: "font-medium text-muted-foreground text-xs uppercase tracking-wider", children: "By Model" }),
853
- /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
854
- sortedModels.slice(0, 5).map(([model, credits]) => {
855
- const modelPercent = usage.total > 0 ? credits / usage.total * 100 : 0;
856
- return /* @__PURE__ */ jsxs2("div", { className: "space-y-1", children: [
857
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between text-sm", children: [
858
- /* @__PURE__ */ jsx2("span", { className: "truncate text-muted-foreground", children: model }),
859
- /* @__PURE__ */ jsx2("span", { className: "ml-2 font-medium", children: formatCredits(credits) })
860
- ] }),
861
- /* @__PURE__ */ jsx2("div", { className: "h-1.5 w-full overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx2(
862
- "div",
863
- {
864
- className: cn(
865
- "h-full rounded-full transition-all",
866
- variant === "sandbox" && colors2.progress
867
- ),
868
- style: { width: `${modelPercent}%` }
869
- }
870
- ) })
871
- ] }, model);
872
- }),
873
- sortedModels.length > 5 && /* @__PURE__ */ jsxs2("p", { className: "text-muted-foreground text-xs", children: [
874
- "+",
875
- sortedModels.length - 5,
876
- " more models"
877
- ] }),
878
- sortedModels.length === 0 && /* @__PURE__ */ jsx2("p", { className: "text-muted-foreground text-sm", children: "No usage this period" })
879
- ] })
880
- ] })
881
- ] })
882
- ] })
883
- ] });
884
- }
885
-
886
- // src/dashboard/pricing-page.tsx
887
- import { Check, Zap } from "lucide-react";
888
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
889
- function formatPrice(cents) {
890
- if (!Number.isFinite(cents) || cents < 0) return "$0";
891
- return cents % 100 === 0 ? `$${cents / 100}` : `$${(cents / 100).toFixed(2)}`;
892
- }
893
- function PricingPage({
894
- tiers,
895
- currentTierId,
896
- billingPeriod,
897
- onBillingPeriodChange,
898
- onSelectTier,
899
- loading = false,
900
- className
901
- }) {
902
- const tiersWithRecommended = tiers.map((tier, i) => ({
903
- ...tier,
904
- recommended: tier.recommended ?? (tiers.length === 3 && i === 1)
905
- }));
906
- return /* @__PURE__ */ jsxs3("div", { className: cn("w-full space-y-10", className), children: [
907
- /* @__PURE__ */ jsx3("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxs3("div", { className: "inline-flex items-center rounded-full border border-border bg-muted/50 p-1", children: [
908
- /* @__PURE__ */ jsx3(
909
- "button",
910
- {
911
- type: "button",
912
- onClick: () => onBillingPeriodChange("monthly"),
913
- className: cn(
914
- "rounded-full px-5 py-2 text-sm font-medium transition-all",
915
- billingPeriod === "monthly" ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
916
- ),
917
- children: "Monthly"
918
- }
919
- ),
920
- /* @__PURE__ */ jsxs3(
921
- "button",
922
- {
923
- type: "button",
924
- onClick: () => onBillingPeriodChange("yearly"),
925
- className: cn(
926
- "rounded-full px-5 py-2 text-sm font-medium transition-all",
927
- billingPeriod === "yearly" ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
928
- ),
929
- children: [
930
- "Yearly",
931
- /* @__PURE__ */ jsx3("span", { className: "ml-2 rounded-full bg-[var(--surface-success-bg)] px-2 py-0.5 text-[10px] font-bold text-[var(--surface-success-text)]", children: "Save 20%" })
932
- ]
933
- }
934
- )
935
- ] }) }),
936
- /* @__PURE__ */ jsx3("div", { className: "grid grid-cols-1 gap-6 lg:grid-cols-3 items-start", children: tiersWithRecommended.map((tier) => {
937
- const isCurrentTier = tier.id === currentTierId;
938
- const isRecommended = tier.recommended;
939
- const isFree = tier.monthlyPriceCents === 0;
940
- const price = billingPeriod === "yearly" && tier.yearlyPriceCents !== void 0 ? tier.yearlyPriceCents : tier.monthlyPriceCents;
941
- const displayPrice = billingPeriod === "yearly" ? Math.round(price / 12) : price;
942
- return /* @__PURE__ */ jsxs3(
943
- "div",
944
- {
945
- className: cn(
946
- "relative flex flex-col rounded-2xl border transition-all",
947
- isRecommended ? "border-primary shadow-[var(--shadow-glow)] scale-[1.02] z-10" : "border-border hover:border-primary/30"
948
- ),
949
- children: [
950
- isRecommended && /* @__PURE__ */ jsx3("div", { className: "absolute -top-4 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ jsxs3("span", { className: "inline-flex items-center gap-1.5 rounded-full bg-primary px-4 py-1.5 text-xs font-bold text-primary-foreground shadow-sm", children: [
951
- /* @__PURE__ */ jsx3(Zap, { className: "h-3 w-3" }),
952
- "Most Popular"
953
- ] }) }),
954
- isCurrentTier && !isRecommended && /* @__PURE__ */ jsx3("div", { className: "absolute -top-4 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ jsx3("span", { className: "inline-flex items-center rounded-full bg-muted border border-border px-4 py-1.5 text-xs font-bold text-foreground", children: "Current Plan" }) }),
955
- /* @__PURE__ */ jsxs3("div", { className: cn("flex flex-col p-8", isRecommended && "pt-10"), children: [
956
- /* @__PURE__ */ jsxs3("div", { className: "mb-6", children: [
957
- /* @__PURE__ */ jsx3("h3", { className: "text-lg font-bold text-foreground", children: tier.name }),
958
- /* @__PURE__ */ jsx3("p", { className: "mt-1 text-sm text-muted-foreground", children: tier.description })
959
- ] }),
960
- /* @__PURE__ */ jsxs3("div", { className: "mb-8", children: [
961
- /* @__PURE__ */ jsxs3("div", { className: "flex items-baseline gap-1", children: [
962
- /* @__PURE__ */ jsx3("span", { className: cn("text-5xl font-extrabold tracking-tight", isRecommended ? "text-primary" : "text-foreground"), children: isFree ? "Free" : formatPrice(displayPrice) }),
963
- !isFree && /* @__PURE__ */ jsx3("span", { className: "text-muted-foreground text-sm font-medium", children: "/mo" })
964
- ] }),
965
- billingPeriod === "yearly" && tier.yearlyPriceCents !== void 0 && !isFree && /* @__PURE__ */ jsxs3("p", { className: "mt-1 text-xs text-muted-foreground", children: [
966
- formatPrice(tier.yearlyPriceCents),
967
- " billed annually"
968
- ] })
969
- ] }),
970
- /* @__PURE__ */ jsx3(
971
- "button",
972
- {
973
- type: "button",
974
- onClick: () => onSelectTier(tier.id),
975
- disabled: isCurrentTier || loading,
976
- className: cn(
977
- "w-full rounded-xl py-3 text-sm font-bold transition-all active:scale-[0.98] disabled:opacity-50",
978
- isRecommended ? "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm" : isCurrentTier ? "bg-muted text-muted-foreground border border-border cursor-default" : "bg-card text-foreground border border-border hover:border-primary/50 hover:bg-muted"
979
- ),
980
- children: isCurrentTier ? "Current Plan" : isFree ? "Get Started" : "Subscribe"
981
- }
982
- ),
983
- /* @__PURE__ */ jsx3("div", { className: "my-8 border-t border-border" }),
984
- /* @__PURE__ */ jsx3("ul", { className: "space-y-3.5 flex-1", children: tier.features.map((feature) => /* @__PURE__ */ jsxs3("li", { className: "flex items-start gap-3", children: [
985
- /* @__PURE__ */ jsx3("div", { className: cn(
986
- "mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full",
987
- isRecommended ? "bg-primary/10 text-primary" : "bg-muted text-muted-foreground"
988
- ), children: /* @__PURE__ */ jsx3(Check, { className: "h-3 w-3" }) }),
989
- /* @__PURE__ */ jsx3("span", { className: "text-sm text-foreground/80", children: feature })
990
- ] }, feature)) })
991
- ] })
992
- ]
993
- },
994
- tier.id
995
- );
996
- }) })
997
- ] });
998
- }
999
-
1000
- // src/dashboard/usage-chart.tsx
1001
- import * as React2 from "react";
1002
- import { Card as Card2, CardContent as CardContent2, CardHeader as CardHeader2, CardTitle as CardTitle2 } from "@tangle-network/ui/primitives";
1003
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1004
- var colors = {
1005
- bar: "bg-[image:var(--accent-gradient-strong)]",
1006
- barHover: "hover:brightness-110",
1007
- text: "text-[var(--accent-text)]"
1008
- };
1009
- function formatDate2(dateStr) {
1010
- const date = new Date(dateStr);
1011
- return date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
1012
- }
1013
- function formatValue(value) {
1014
- if (value >= 1e6) {
1015
- return `${(value / 1e6).toFixed(1)}M`;
1016
- }
1017
- if (value >= 1e3) {
1018
- return `${(value / 1e3).toFixed(1)}K`;
1019
- }
1020
- return value.toLocaleString();
1021
- }
1022
- function UsageChart({ data, title, unit, className }) {
1023
- const maxValue = Math.max(...data.map((d) => d.value), 1);
1024
- const total = data.reduce((sum, d) => sum + d.value, 0);
1025
- const [hoveredIndex, setHoveredIndex] = React2.useState(null);
1026
- return /* @__PURE__ */ jsxs4(Card2, { className, children: [
1027
- /* @__PURE__ */ jsxs4(CardHeader2, { className: "flex flex-row items-center justify-between pb-2", children: [
1028
- /* @__PURE__ */ jsx4(CardTitle2, { className: "font-medium text-base", children: title }),
1029
- /* @__PURE__ */ jsxs4("div", { className: "text-right", children: [
1030
- /* @__PURE__ */ jsx4("span", { className: cn("font-bold text-2xl", colors.text), children: formatValue(total) }),
1031
- /* @__PURE__ */ jsx4("span", { className: "ml-1 text-muted-foreground text-sm", children: unit })
1032
- ] })
1033
- ] }),
1034
- /* @__PURE__ */ jsxs4(CardContent2, { children: [
1035
- /* @__PURE__ */ jsxs4("div", { className: "relative", children: [
1036
- /* @__PURE__ */ jsxs4("div", { className: "absolute top-0 left-0 flex h-48 flex-col justify-between text-muted-foreground text-xs", children: [
1037
- /* @__PURE__ */ jsx4("span", { children: formatValue(maxValue) }),
1038
- /* @__PURE__ */ jsx4("span", { children: formatValue(Math.round(maxValue / 2)) }),
1039
- /* @__PURE__ */ jsx4("span", { children: "0" })
1040
- ] }),
1041
- /* @__PURE__ */ jsx4("div", { className: "ml-10 flex h-48 items-end gap-1", children: data.map((point, index) => {
1042
- const heightPercent = point.value / maxValue * 100;
1043
- const isHovered = hoveredIndex === index;
1044
- return (
1045
- // biome-ignore lint/a11y/noStaticElementInteractions: chart bar uses hover for tooltip display
1046
- /* @__PURE__ */ jsxs4(
1047
- "div",
1048
- {
1049
- className: "group relative flex flex-1 flex-col items-center",
1050
- onMouseEnter: () => setHoveredIndex(index),
1051
- onMouseLeave: () => setHoveredIndex(null),
1052
- children: [
1053
- isHovered && /* @__PURE__ */ jsxs4("div", { className: "absolute -top-12 z-10 rounded-lg bg-popover px-3 py-1.5 text-sm shadow-lg", children: [
1054
- /* @__PURE__ */ jsxs4("p", { className: "font-medium", children: [
1055
- formatValue(point.value),
1056
- " ",
1057
- unit
1058
- ] }),
1059
- /* @__PURE__ */ jsx4("p", { className: "text-muted-foreground text-xs", children: formatDate2(point.date) })
1060
- ] }),
1061
- /* @__PURE__ */ jsx4(
1062
- "div",
1063
- {
1064
- className: cn(
1065
- "min-h-[2px] w-full rounded-t-sm transition-all duration-200",
1066
- colors.bar,
1067
- colors.barHover,
1068
- isHovered && "opacity-80"
1069
- ),
1070
- style: { height: `${Math.max(heightPercent, 1)}%` }
1071
- }
1072
- )
1073
- ]
1074
- },
1075
- point.date
1076
- )
1077
- );
1078
- }) }),
1079
- /* @__PURE__ */ jsx4("div", { className: "mt-2 ml-10 flex gap-1", children: data.map((point, index) => /* @__PURE__ */ jsx4(
1080
- "div",
1081
- {
1082
- className: cn(
1083
- "flex-1 truncate text-center text-muted-foreground text-xs",
1084
- hoveredIndex === index && colors.text
1085
- ),
1086
- children: data.length <= 7 || index % Math.ceil(data.length / 7) === 0 ? formatDate2(point.date) : ""
1087
- },
1088
- point.date
1089
- )) })
1090
- ] }),
1091
- /* @__PURE__ */ jsxs4("div", { className: "mt-4 grid grid-cols-3 gap-4 border-border border-t pt-4", children: [
1092
- /* @__PURE__ */ jsxs4("div", { className: "text-center", children: [
1093
- /* @__PURE__ */ jsx4("p", { className: "text-muted-foreground text-xs", children: "Average" }),
1094
- /* @__PURE__ */ jsxs4("p", { className: "font-medium", children: [
1095
- formatValue(Math.round(total / data.length)),
1096
- " ",
1097
- unit
1098
- ] })
1099
- ] }),
1100
- /* @__PURE__ */ jsxs4("div", { className: "text-center", children: [
1101
- /* @__PURE__ */ jsx4("p", { className: "text-muted-foreground text-xs", children: "Peak" }),
1102
- /* @__PURE__ */ jsxs4("p", { className: "font-medium", children: [
1103
- formatValue(maxValue),
1104
- " ",
1105
- unit
1106
- ] })
1107
- ] }),
1108
- /* @__PURE__ */ jsxs4("div", { className: "text-center", children: [
1109
- /* @__PURE__ */ jsx4("p", { className: "text-muted-foreground text-xs", children: "Total" }),
1110
- /* @__PURE__ */ jsxs4("p", { className: cn("font-medium", colors.text), children: [
1111
- formatValue(total),
1112
- " ",
1113
- unit
1114
- ] })
1115
- ] })
1116
- ] })
1117
- ] })
1118
- ] });
1119
- }
1120
-
1121
- // src/dashboard/template-card.tsx
1122
- import { ArrowRight } from "lucide-react";
1123
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1124
- function TemplateCard({ template, onUseTemplate, className }) {
1125
- return /* @__PURE__ */ jsxs5(
1126
- "div",
1127
- {
1128
- className: cn(
1129
- "group relative flex flex-col justify-between rounded-2xl border border-border bg-card p-6 transition-all hover:border-primary/30 hover:shadow-md",
1130
- className
1131
- ),
1132
- children: [
1133
- /* @__PURE__ */ jsxs5("div", { children: [
1134
- /* @__PURE__ */ jsx5("div", { className: "mb-4 flex h-12 w-12 items-center justify-center rounded-xl bg-muted border border-border", children: template.icon ?? /* @__PURE__ */ jsx5("span", { className: "text-lg font-bold text-primary", children: template.name.charAt(0).toUpperCase() }) }),
1135
- /* @__PURE__ */ jsx5("h3", { className: "mb-1 text-base font-bold text-foreground", children: template.name }),
1136
- /* @__PURE__ */ jsx5("p", { className: "text-sm text-muted-foreground leading-relaxed line-clamp-2", children: template.description }),
1137
- template.tags && template.tags.length > 0 && /* @__PURE__ */ jsx5("div", { className: "mt-3 flex flex-wrap gap-1.5", children: template.tags.map((tag, i) => /* @__PURE__ */ jsx5(
1138
- "span",
1139
- {
1140
- className: "rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground",
1141
- children: tag
1142
- },
1143
- `${tag}-${i}`
1144
- )) })
1145
- ] }),
1146
- /* @__PURE__ */ jsxs5(
1147
- "button",
1148
- {
1149
- type: "button",
1150
- onClick: () => onUseTemplate(template.id),
1151
- className: "mt-5 inline-flex w-full items-center justify-center gap-2 rounded-xl bg-primary/10 border border-primary/20 px-4 py-2.5 text-sm font-bold text-primary transition-colors hover:bg-primary hover:text-primary-foreground active:scale-[0.98]",
1152
- children: [
1153
- "Use Template",
1154
- /* @__PURE__ */ jsx5(ArrowRight, { className: "h-4 w-4 transition-transform group-hover:translate-x-0.5" })
1155
- ]
1156
- }
1157
- )
1158
- ]
1159
- }
1160
- );
1161
- }
1162
-
1163
- // src/dashboard/info-panel.tsx
1164
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1165
- function InfoPanel({ label, title, description, className }) {
1166
- return /* @__PURE__ */ jsxs6("div", { className: cn("rounded-lg bg-[var(--brand-strong)] p-5 text-[var(--brand-strong-text)] relative overflow-hidden", className), children: [
1167
- /* @__PURE__ */ jsxs6("div", { className: "relative z-10", children: [
1168
- /* @__PURE__ */ jsx6("p", { className: "text-[10px] font-bold uppercase tracking-widest text-[var(--brand-strong-text-dim)]", children: label }),
1169
- /* @__PURE__ */ jsx6("h3", { className: "mt-1 text-lg font-bold", children: title }),
1170
- /* @__PURE__ */ jsx6("p", { className: "mt-1 text-sm text-[var(--brand-strong-text-muted)]", children: description })
1171
- ] }),
1172
- /* @__PURE__ */ jsx6("div", { className: "absolute right-0 top-0 h-full w-1/3 bg-white/5 -skew-x-12 translate-x-12 pointer-events-none" })
1173
- ] });
1174
- }
1175
-
1176
661
  export {
1177
662
  canonicalModelId,
1178
663
  formatPricing,
1179
664
  formatContext,
1180
- ModelPicker,
1181
- BillingDashboard,
1182
- formatPrice,
1183
- PricingPage,
1184
- UsageChart,
1185
- TemplateCard,
1186
- InfoPanel
665
+ ModelPicker
1187
666
  };