@turtleclub/ui 0.7.0-beta.32 → 0.7.0-beta.34
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.cjs +10331 -110
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +7652 -47844
- package/dist/index.js.map +1 -1
- package/dist/types/components/features/sidebar-layout.d.ts +2 -0
- package/dist/types/components/features/sidebar-layout.d.ts.map +1 -1
- package/dist/types/components/ui/chart.d.ts +1 -1
- package/dist/types/components/ui/chart.d.ts.map +1 -1
- package/package.json +26 -22
- package/.prettierrc.json +0 -4
- package/.turbo/turbo-build.log +0 -182
- package/CHANGELOG.md +0 -795
- package/components.json +0 -21
- package/src/components/charts/QUICK_REFERENCE.md +0 -323
- package/src/components/charts/README.md +0 -658
- package/src/components/charts/RECHARTS_FEATURES.md +0 -458
- package/src/components/charts/area-chart.tsx +0 -248
- package/src/components/charts/bar-chart.tsx +0 -362
- package/src/components/charts/index.ts +0 -4
- package/src/components/charts/pie-chart.tsx +0 -277
- package/src/components/charts/radial-chart.tsx +0 -312
- package/src/components/features/api-status/index.tsx +0 -23
- package/src/components/features/data-table/data-table.tsx +0 -538
- package/src/components/features/data-table/expand-toggle.tsx +0 -17
- package/src/components/features/data-table/fuzzy-filter.tsx +0 -34
- package/src/components/features/data-table/index.ts +0 -3
- package/src/components/features/data-table/item-info.tsx +0 -19
- package/src/components/features/data-table/skeleton.tsx +0 -23
- package/src/components/features/data-table/sort-dropdown.tsx +0 -118
- package/src/components/features/data-table/sortable-header.tsx +0 -37
- package/src/components/features/index.ts +0 -6
- package/src/components/features/page-heading.tsx +0 -27
- package/src/components/features/search-bar.tsx +0 -55
- package/src/components/features/segmented-navigation.tsx +0 -18
- package/src/components/features/sidebar-layout.tsx +0 -193
- package/src/components/features/turtle-tooltip.tsx +0 -67
- package/src/components/icons/arrow.tsx +0 -23
- package/src/components/icons/beta.tsx +0 -95
- package/src/components/icons/dot.tsx +0 -102
- package/src/components/icons/index.ts +0 -7
- package/src/components/icons/issue.tsx +0 -106
- package/src/components/icons/turtle.tsx +0 -156
- package/src/components/icons/update.tsx +0 -113
- package/src/components/icons/warning.tsx +0 -95
- package/src/components/molecules/index.ts +0 -9
- package/src/components/molecules/opportunity/index.ts +0 -10
- package/src/components/molecules/opportunity/opportunity-apr.tsx +0 -129
- package/src/components/molecules/opportunity/opportunity-disclaimer.tsx +0 -46
- package/src/components/molecules/opportunity/opportunity-rate-estimator.tsx +0 -62
- package/src/components/molecules/opportunity/opportunity-section.tsx +0 -113
- package/src/components/molecules/opportunity/opportunity-selector.tsx +0 -30
- package/src/components/molecules/opportunity/opportunity-type.tsx +0 -16
- package/src/components/molecules/route-details.tsx +0 -112
- package/src/components/molecules/slippage-selector.tsx +0 -200
- package/src/components/molecules/swap-details.tsx +0 -55
- package/src/components/molecules/swap-input.tsx +0 -186
- package/src/components/molecules/tabs.tsx +0 -79
- package/src/components/molecules/token-selector.tsx +0 -180
- package/src/components/molecules/tx-status.tsx +0 -312
- package/src/components/molecules/widget/asset-list/asset-filters.tsx +0 -113
- package/src/components/molecules/widget/asset-list/asset-list.tsx +0 -178
- package/src/components/molecules/widget/asset-list/asset-row.tsx +0 -45
- package/src/components/molecules/widget/asset-list/hooks/index.ts +0 -2
- package/src/components/molecules/widget/asset-list/hooks/use-asset-filtering.ts +0 -44
- package/src/components/molecules/widget/asset-list/hooks/use-asset-grouping.ts +0 -87
- package/src/components/molecules/widget/asset-list/index.ts +0 -3
- package/src/components/molecules/widget/base-selector.tsx +0 -121
- package/src/components/molecules/widget/campaign-item.tsx +0 -82
- package/src/components/molecules/widget/deal-item.tsx +0 -92
- package/src/components/molecules/widget/index.ts +0 -36
- package/src/components/molecules/widget/opportunity-item.tsx +0 -105
- package/src/components/molecules/widget/widget-item-stats.tsx +0 -50
- package/src/components/molecules/widget/widget-item.tsx +0 -139
- package/src/components/molecules/widget/widget-list-items.tsx +0 -86
- package/src/components/ui/alert-dialog.tsx +0 -163
- package/src/components/ui/animated-background/animated-background.tsx +0 -182
- package/src/components/ui/animated-background/index.ts +0 -1
- package/src/components/ui/avatar.tsx +0 -73
- package/src/components/ui/badge.tsx +0 -59
- package/src/components/ui/banner.tsx +0 -84
- package/src/components/ui/button.tsx +0 -100
- package/src/components/ui/card.tsx +0 -119
- package/src/components/ui/chart.tsx +0 -346
- package/src/components/ui/checkbox.tsx +0 -32
- package/src/components/ui/chip.tsx +0 -52
- package/src/components/ui/collapsible.tsx +0 -34
- package/src/components/ui/combobox.tsx +0 -730
- package/src/components/ui/command.tsx +0 -184
- package/src/components/ui/dialog.tsx +0 -129
- package/src/components/ui/dropdown.tsx +0 -316
- package/src/components/ui/field.tsx +0 -244
- package/src/components/ui/heading.tsx +0 -74
- package/src/components/ui/hover-card.tsx +0 -139
- package/src/components/ui/icon-animation.tsx +0 -82
- package/src/components/ui/icon-list.tsx +0 -168
- package/src/components/ui/index.ts +0 -48
- package/src/components/ui/info-card.tsx +0 -110
- package/src/components/ui/input-group.tsx +0 -170
- package/src/components/ui/input.tsx +0 -72
- package/src/components/ui/label-with-icon.tsx +0 -122
- package/src/components/ui/label.tsx +0 -24
- package/src/components/ui/multi-select.tsx +0 -1090
- package/src/components/ui/navigation-bar.tsx +0 -153
- package/src/components/ui/navigation-menu.tsx +0 -188
- package/src/components/ui/opportunity-details-v1.tsx +0 -104
- package/src/components/ui/pagination.tsx +0 -127
- package/src/components/ui/popover.tsx +0 -48
- package/src/components/ui/scroll-area.tsx +0 -64
- package/src/components/ui/segment-control.tsx +0 -146
- package/src/components/ui/select.tsx +0 -199
- package/src/components/ui/separator.tsx +0 -26
- package/src/components/ui/sheet.tsx +0 -139
- package/src/components/ui/sidebar.tsx +0 -728
- package/src/components/ui/skeleton.tsx +0 -14
- package/src/components/ui/slider.tsx +0 -58
- package/src/components/ui/sonner.tsx +0 -24
- package/src/components/ui/switch.tsx +0 -29
- package/src/components/ui/table-shadcn.tsx +0 -110
- package/src/components/ui/table.tsx +0 -117
- package/src/components/ui/textarea.tsx +0 -22
- package/src/components/ui/toggle-group.tsx +0 -71
- package/src/components/ui/toggle.tsx +0 -47
- package/src/components/ui/tooltip.tsx +0 -66
- package/src/hooks/index.ts +0 -1
- package/src/hooks/useIsMobile.ts +0 -77
- package/src/index.ts +0 -16
- package/src/lib/utils.ts +0 -6
- package/src/styles/globals.css +0 -181
- package/src/styles/themes/index.css +0 -9
- package/src/styles/themes/semantic.css +0 -117
- package/src/styles/tokens/colors.css +0 -124
- package/src/styles/tokens/index.css +0 -15
- package/src/styles/tokens/radius.css +0 -18
- package/src/styles/tokens/spacing.css +0 -58
- package/src/styles/tokens/typography.css +0 -87
- package/src/tokens/index.ts +0 -108
- package/tsconfig.json +0 -20
- package/vite.config.js +0 -49
- /package/{src/images/enso.png → dist/enso-22FJ4GNK.png} +0 -0
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import {
|
|
3
|
-
HoverCard,
|
|
4
|
-
HoverCardContent,
|
|
5
|
-
HoverCardTrigger,
|
|
6
|
-
} from "../../ui/hover-card";
|
|
7
|
-
import { InfoIcon } from "lucide-react";
|
|
8
|
-
import { LabelWithIcon, Separator } from "../../ui";
|
|
9
|
-
import NumberFlow, { type Value } from "@number-flow/react";
|
|
10
|
-
|
|
11
|
-
// TODO: Extract aprBreakdown to a type
|
|
12
|
-
interface OpportunityAprProps {
|
|
13
|
-
apr: Value;
|
|
14
|
-
aprBreakdown: {
|
|
15
|
-
iconUrl: string;
|
|
16
|
-
name: string;
|
|
17
|
-
description: string;
|
|
18
|
-
apr: string;
|
|
19
|
-
boost: boolean;
|
|
20
|
-
}[];
|
|
21
|
-
showBoostedRewardsDescription?: boolean;
|
|
22
|
-
showBoostedRewards?: boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const OpportunityApr = ({
|
|
26
|
-
apr,
|
|
27
|
-
aprBreakdown,
|
|
28
|
-
showBoostedRewards = false,
|
|
29
|
-
showBoostedRewardsDescription = false,
|
|
30
|
-
}: OpportunityAprProps) => {
|
|
31
|
-
const boostedRewards = aprBreakdown.filter((item) => item.boost);
|
|
32
|
-
return (
|
|
33
|
-
<HoverCard>
|
|
34
|
-
<HoverCardTrigger asChild>
|
|
35
|
-
<span className="text-accent inline-flex items-center gap-1 text-2xl font-semibold">
|
|
36
|
-
<NumberFlow
|
|
37
|
-
value={apr}
|
|
38
|
-
format={{
|
|
39
|
-
style: "percent",
|
|
40
|
-
minimumFractionDigits: 2,
|
|
41
|
-
maximumFractionDigits: 2,
|
|
42
|
-
}}
|
|
43
|
-
/>
|
|
44
|
-
<InfoIcon
|
|
45
|
-
size={16}
|
|
46
|
-
className="text-muted-foreground cursor-pointer font-bold"
|
|
47
|
-
/>
|
|
48
|
-
</span>
|
|
49
|
-
</HoverCardTrigger>
|
|
50
|
-
<HoverCardContent>
|
|
51
|
-
<h3 className="text-accent text-sm">Rewards</h3>
|
|
52
|
-
<div className="flex flex-col gap-2">
|
|
53
|
-
{aprBreakdown
|
|
54
|
-
.filter((item) => !item.boost)
|
|
55
|
-
.map((item) => (
|
|
56
|
-
<div key={item.name} className="flex justify-between">
|
|
57
|
-
<LabelWithIcon
|
|
58
|
-
textSize="xs"
|
|
59
|
-
icon={item.iconUrl}
|
|
60
|
-
iconSize="sm"
|
|
61
|
-
className="text-muted-foreground"
|
|
62
|
-
>
|
|
63
|
-
{item.name}
|
|
64
|
-
</LabelWithIcon>
|
|
65
|
-
<span className="text-accent text-sm font-semibold">
|
|
66
|
-
<NumberFlow
|
|
67
|
-
value={parseFloat(item.apr) / 100}
|
|
68
|
-
format={{
|
|
69
|
-
style: "percent",
|
|
70
|
-
minimumFractionDigits: 2,
|
|
71
|
-
maximumFractionDigits: 3,
|
|
72
|
-
}}
|
|
73
|
-
/>
|
|
74
|
-
</span>
|
|
75
|
-
</div>
|
|
76
|
-
))}
|
|
77
|
-
<Separator />
|
|
78
|
-
<div className="flex justify-between">
|
|
79
|
-
<span className="text-accent text-sm">Net Reward Rate</span>
|
|
80
|
-
<span className="text-accent text-sm font-semibold">
|
|
81
|
-
<NumberFlow
|
|
82
|
-
value={apr}
|
|
83
|
-
format={{
|
|
84
|
-
style: "percent",
|
|
85
|
-
minimumFractionDigits: 3,
|
|
86
|
-
maximumFractionDigits: 3,
|
|
87
|
-
}}
|
|
88
|
-
/>
|
|
89
|
-
</span>
|
|
90
|
-
</div>
|
|
91
|
-
{showBoostedRewards && boostedRewards.length > 0 && (
|
|
92
|
-
<>
|
|
93
|
-
<Separator />
|
|
94
|
-
<h3 className="text-accent text-sm">Boosted Rewards</h3>
|
|
95
|
-
<div className="flex justify-between">
|
|
96
|
-
<span className="text-accent text-sm font-semibold">
|
|
97
|
-
{boostedRewards.map((item) => (
|
|
98
|
-
<div key={item.name} className="flex flex-col gap-2">
|
|
99
|
-
<LabelWithIcon
|
|
100
|
-
textSize="xs"
|
|
101
|
-
icon={item.iconUrl}
|
|
102
|
-
iconSize="sm"
|
|
103
|
-
className="text-muted-foreground"
|
|
104
|
-
>
|
|
105
|
-
{item.description}
|
|
106
|
-
</LabelWithIcon>
|
|
107
|
-
{showBoostedRewardsDescription && item.description && (
|
|
108
|
-
<span className="text-muted-foreground text-xs">
|
|
109
|
-
{item.description}
|
|
110
|
-
</span>
|
|
111
|
-
)}
|
|
112
|
-
</div>
|
|
113
|
-
))}
|
|
114
|
-
</span>
|
|
115
|
-
</div>
|
|
116
|
-
</>
|
|
117
|
-
)}
|
|
118
|
-
{/* <p className="text-sm text-muted-foreground text-center">
|
|
119
|
-
All reward amounts displayed in this app are the amounts after fees, please note that
|
|
120
|
-
the reward rate is not guaranteed and may change over time. The APR is the annualized
|
|
121
|
-
return on investment for the opportunity.
|
|
122
|
-
</p> */}
|
|
123
|
-
</div>
|
|
124
|
-
</HoverCardContent>
|
|
125
|
-
</HoverCard>
|
|
126
|
-
);
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
export { OpportunityApr };
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BanknoteIcon,
|
|
3
|
-
GiftIcon,
|
|
4
|
-
MessageSquareTextIcon,
|
|
5
|
-
SproutIcon,
|
|
6
|
-
} from "lucide-react";
|
|
7
|
-
import React from "react";
|
|
8
|
-
|
|
9
|
-
const OpportunityDisclaimer = () => {
|
|
10
|
-
const diclaimers = [
|
|
11
|
-
{
|
|
12
|
-
icon: <MessageSquareTextIcon size={16} />,
|
|
13
|
-
description:
|
|
14
|
-
"Lorem ipsum dolor sit, amet consectetur adipisicing elit. Porro expedita amet hic beatae similique vero recusandae necessitatibus",
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
icon: <SproutIcon size={16} />,
|
|
18
|
-
description: "Lend your USDT with Morpho and earn USDT rewards",
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
icon: <GiftIcon size={16} />,
|
|
22
|
-
description:
|
|
23
|
-
"Rewards are automatically distributed every block and accrue to your position",
|
|
24
|
-
},
|
|
25
|
-
// {
|
|
26
|
-
// icon: <BanknoteIcon size={16} />,
|
|
27
|
-
// description: "Request withdraw at anytime and get USDT immediately",
|
|
28
|
-
// },
|
|
29
|
-
];
|
|
30
|
-
return (
|
|
31
|
-
<div className="flex w-full flex-col gap-3">
|
|
32
|
-
{diclaimers.map((disclaimer) => (
|
|
33
|
-
<div key={disclaimer.description} className="flex gap-3">
|
|
34
|
-
<div className="text-muted-foreground flex h-4 w-4 flex-shrink-0 items-center justify-center">
|
|
35
|
-
{disclaimer.icon}
|
|
36
|
-
</div>
|
|
37
|
-
<p className="text-muted-foreground flex-1 text-xs">
|
|
38
|
-
{disclaimer.description}
|
|
39
|
-
</p>
|
|
40
|
-
</div>
|
|
41
|
-
))}
|
|
42
|
-
</div>
|
|
43
|
-
);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export { OpportunityDisclaimer };
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { useMemo } from "react";
|
|
2
|
-
|
|
3
|
-
export interface OpportunityRateEstimatorProps {
|
|
4
|
-
value: {
|
|
5
|
-
symbol: string;
|
|
6
|
-
price: number;
|
|
7
|
-
depositedAmountUsd: number;
|
|
8
|
-
apr: number;
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const OpportunityRateEstimator = ({ value }: OpportunityRateEstimatorProps) => {
|
|
13
|
-
const { depositedAmountUsd, apr, symbol, price } = value;
|
|
14
|
-
|
|
15
|
-
const result = useMemo(() => {
|
|
16
|
-
// Validar que tengamos todos los valores necesarios
|
|
17
|
-
if (!depositedAmountUsd || !apr || !price) {
|
|
18
|
-
return {
|
|
19
|
-
monthlyReward: "0.0000",
|
|
20
|
-
monthlyRewardUsd: "0.00",
|
|
21
|
-
yearlyReward: "0.0000",
|
|
22
|
-
yearlyRewardUsd: "0.00",
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Calcular rewards anuales en USD
|
|
27
|
-
const yearlyRewardsUsd = depositedAmountUsd * (apr / 100);
|
|
28
|
-
|
|
29
|
-
// Convertir rewards USD a cantidad de reward token
|
|
30
|
-
const yearlyRewardsToken = yearlyRewardsUsd / price;
|
|
31
|
-
|
|
32
|
-
// Calcular rewards mensuales
|
|
33
|
-
const monthlyRewardsUsd = yearlyRewardsUsd / 12;
|
|
34
|
-
const monthlyRewardsToken = yearlyRewardsToken / 12;
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
monthlyReward: monthlyRewardsToken.toFixed(4),
|
|
38
|
-
monthlyRewardUsd: monthlyRewardsUsd.toFixed(2),
|
|
39
|
-
yearlyReward: yearlyRewardsToken.toFixed(4),
|
|
40
|
-
yearlyRewardUsd: yearlyRewardsUsd.toFixed(2),
|
|
41
|
-
};
|
|
42
|
-
}, [depositedAmountUsd, apr, price]);
|
|
43
|
-
|
|
44
|
-
return (
|
|
45
|
-
<div className="mx-4 mb-4 space-y-1">
|
|
46
|
-
<div className="flex justify-between">
|
|
47
|
-
<span className="text-muted-foreground text-sm">Monthly</span>
|
|
48
|
-
<span className="text-muted-foreground text-sm">
|
|
49
|
-
{result.monthlyReward || 0} {symbol} (${result.monthlyRewardUsd || 0})
|
|
50
|
-
</span>
|
|
51
|
-
</div>
|
|
52
|
-
<div className="flex justify-between">
|
|
53
|
-
<span className="text-muted-foreground text-sm">Yearly</span>
|
|
54
|
-
<span className="text-muted-foreground text-sm">
|
|
55
|
-
{result.yearlyReward || 0} {symbol} (${result.yearlyRewardUsd || 0})
|
|
56
|
-
</span>
|
|
57
|
-
</div>
|
|
58
|
-
</div>
|
|
59
|
-
);
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export { OpportunityRateEstimator };
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { cn } from "@/lib/utils";
|
|
3
|
-
import { Card } from "@/components/ui/card";
|
|
4
|
-
import { OpportunityApr } from "./opportunity-apr";
|
|
5
|
-
import {
|
|
6
|
-
OpportunityRateEstimator,
|
|
7
|
-
OpportunityRateEstimatorProps,
|
|
8
|
-
} from "./opportunity-rate-estimator";
|
|
9
|
-
import { OpportunityType } from "./opportunity-type";
|
|
10
|
-
import { Separator } from "@/components/ui";
|
|
11
|
-
import { OpportunityDisclaimer } from "./opportunity-disclaimer";
|
|
12
|
-
import { OpportunitySelector } from "./opportunity-selector";
|
|
13
|
-
import { Wallet } from "lucide-react";
|
|
14
|
-
import { BaseSelector, iconUrlToImg } from "../widget";
|
|
15
|
-
|
|
16
|
-
interface OpportunitySectionProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
17
|
-
value: {
|
|
18
|
-
name: string;
|
|
19
|
-
icon: string;
|
|
20
|
-
vaultSymbol: string;
|
|
21
|
-
totalApr: string;
|
|
22
|
-
aprBreakdown: {
|
|
23
|
-
iconUrl: string;
|
|
24
|
-
name: string;
|
|
25
|
-
description: string;
|
|
26
|
-
boost: boolean;
|
|
27
|
-
apr: string;
|
|
28
|
-
}[];
|
|
29
|
-
tvlUsd: string;
|
|
30
|
-
depositDetails: OpportunityRateEstimatorProps["value"];
|
|
31
|
-
type: "Boosted Deal" | "Turtle Campaign";
|
|
32
|
-
};
|
|
33
|
-
opportunitySelector: "old" | "new";
|
|
34
|
-
hideDisclaimer?: boolean;
|
|
35
|
-
onOpportunityClick?: () => void;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const OpportunitySection = React.forwardRef<
|
|
39
|
-
HTMLDivElement,
|
|
40
|
-
OpportunitySectionProps
|
|
41
|
-
>(
|
|
42
|
-
(
|
|
43
|
-
{
|
|
44
|
-
className,
|
|
45
|
-
value,
|
|
46
|
-
onOpportunityClick,
|
|
47
|
-
hideDisclaimer,
|
|
48
|
-
opportunitySelector,
|
|
49
|
-
...props
|
|
50
|
-
},
|
|
51
|
-
ref,
|
|
52
|
-
) => {
|
|
53
|
-
return (
|
|
54
|
-
<div className="text-foreground space-y-2">
|
|
55
|
-
<Card
|
|
56
|
-
variant="shadow"
|
|
57
|
-
gradient="white"
|
|
58
|
-
ref={ref}
|
|
59
|
-
className={cn("space-y-3", className)}
|
|
60
|
-
{...props}
|
|
61
|
-
>
|
|
62
|
-
<div className="flex justify-between p-4">
|
|
63
|
-
<OpportunityApr
|
|
64
|
-
apr={parseFloat(value.totalApr) / 100}
|
|
65
|
-
aprBreakdown={value.aprBreakdown}
|
|
66
|
-
showBoostedRewardsDescription={false}
|
|
67
|
-
showBoostedRewards={true}
|
|
68
|
-
/>
|
|
69
|
-
{opportunitySelector === "new" && (
|
|
70
|
-
<OpportunitySelector
|
|
71
|
-
iconUrl={value.icon}
|
|
72
|
-
name={value.name}
|
|
73
|
-
onClick={onOpportunityClick}
|
|
74
|
-
/>
|
|
75
|
-
)}
|
|
76
|
-
{opportunitySelector === "old" && (
|
|
77
|
-
<BaseSelector
|
|
78
|
-
icon={iconUrlToImg(value.icon, value.vaultSymbol)}
|
|
79
|
-
text={value.name}
|
|
80
|
-
onClick={onOpportunityClick}
|
|
81
|
-
size="sm"
|
|
82
|
-
/>
|
|
83
|
-
)}
|
|
84
|
-
</div>
|
|
85
|
-
{/* <OpportunityRateEstimator value={value.depositDetails} /> */}
|
|
86
|
-
</Card>
|
|
87
|
-
{/* Disclaimer */}
|
|
88
|
-
{!hideDisclaimer && (
|
|
89
|
-
<Card
|
|
90
|
-
ref={ref}
|
|
91
|
-
variant="border"
|
|
92
|
-
gradient="white"
|
|
93
|
-
className={cn("space-y-3", className)}
|
|
94
|
-
{...props}
|
|
95
|
-
>
|
|
96
|
-
<div className="flex flex-col items-center justify-between gap-3">
|
|
97
|
-
<div className="flex w-full justify-between p-1">
|
|
98
|
-
<OpportunityType type={value.type} />
|
|
99
|
-
<span className="text-foreground text-sm font-semibold">
|
|
100
|
-
TVL: {value.tvlUsd}
|
|
101
|
-
</span>
|
|
102
|
-
</div>
|
|
103
|
-
<Separator />
|
|
104
|
-
<OpportunityDisclaimer />
|
|
105
|
-
</div>
|
|
106
|
-
</Card>
|
|
107
|
-
)}
|
|
108
|
-
</div>
|
|
109
|
-
);
|
|
110
|
-
},
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
export { OpportunitySection };
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Card, LabelWithIcon } from "@/components/ui";
|
|
2
|
-
import { ChevronDownIcon } from "lucide-react";
|
|
3
|
-
import React from "react";
|
|
4
|
-
|
|
5
|
-
interface OpportunitySelectorProps {
|
|
6
|
-
iconUrl: string;
|
|
7
|
-
name: string;
|
|
8
|
-
onClick: () => void;
|
|
9
|
-
}
|
|
10
|
-
const OpportunitySelector = ({
|
|
11
|
-
iconUrl,
|
|
12
|
-
name,
|
|
13
|
-
onClick,
|
|
14
|
-
}: OpportunitySelectorProps) => {
|
|
15
|
-
return (
|
|
16
|
-
<Card
|
|
17
|
-
variant="border"
|
|
18
|
-
rounded="full"
|
|
19
|
-
onClick={onClick}
|
|
20
|
-
className="flex cursor-pointer items-center justify-between gap-3"
|
|
21
|
-
>
|
|
22
|
-
<LabelWithIcon icon={iconUrl} textSize="sm" iconSize="base">
|
|
23
|
-
{name}
|
|
24
|
-
</LabelWithIcon>
|
|
25
|
-
<ChevronDownIcon className="text-muted-foreground h-4 w-4" />
|
|
26
|
-
</Card>
|
|
27
|
-
);
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export { OpportunitySelector };
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Badge } from "@/components/ui/badge";
|
|
2
|
-
import { HandCoinsIcon } from "lucide-react";
|
|
3
|
-
import React from "react";
|
|
4
|
-
|
|
5
|
-
interface OpportunityTypeProps {
|
|
6
|
-
type: "Boosted Deal" | "Turtle Campaign";
|
|
7
|
-
}
|
|
8
|
-
const OpportunityType = ({ type }: OpportunityTypeProps) => {
|
|
9
|
-
return (
|
|
10
|
-
<Badge variant="muted" className="gap-2">
|
|
11
|
-
<HandCoinsIcon size={16} /> {type}
|
|
12
|
-
</Badge>
|
|
13
|
-
);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export { OpportunityType };
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { Card, CardContent } from "../ui/card";
|
|
3
|
-
import { LabelWithIcon } from "../ui/label-with-icon";
|
|
4
|
-
import { ScrollArea } from "../ui/scroll-area";
|
|
5
|
-
import { ChevronsRight } from "lucide-react";
|
|
6
|
-
import ensoLogo from "../../images/enso.png";
|
|
7
|
-
import { useMemo } from "react";
|
|
8
|
-
|
|
9
|
-
// Local type definitions (no dependency on @turtleclub/hooks)
|
|
10
|
-
export interface SimpleToken {
|
|
11
|
-
icon?: React.ReactNode | string;
|
|
12
|
-
symbol: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface TokenStep {
|
|
16
|
-
in: SimpleToken;
|
|
17
|
-
out: SimpleToken | null;
|
|
18
|
-
type: "approve" | "swap" | "deposit";
|
|
19
|
-
amount?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface RouteDetailsProps {
|
|
23
|
-
value: {
|
|
24
|
-
steps: TokenStep[];
|
|
25
|
-
};
|
|
26
|
-
className?: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export const RouteDetails = ({ value, className }: RouteDetailsProps) => {
|
|
30
|
-
const { steps } = value;
|
|
31
|
-
|
|
32
|
-
const isLongRoute = useMemo(() => {
|
|
33
|
-
return steps.length > 2;
|
|
34
|
-
}, [steps]);
|
|
35
|
-
|
|
36
|
-
const defaultIcon = (symbol: string) => (
|
|
37
|
-
<div className="bg-primary/20 flex size-3 items-center justify-center rounded-full">
|
|
38
|
-
<span className="text-primary text-xs font-bold">{symbol.charAt(0)}</span>
|
|
39
|
-
</div>
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
const capitalize = (str: string) => {
|
|
43
|
-
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
if (steps.length === 0) return null;
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<div className="text-foreground px-3 pb-3">
|
|
50
|
-
<div className="text-sm font-medium">Swap Route</div>
|
|
51
|
-
<div className="mb-1 flex items-center gap-1 text-[10px]">
|
|
52
|
-
<span className="text-sm opacity-50">Powered by</span>
|
|
53
|
-
<img src={ensoLogo} className="w-10" alt="Enso" />
|
|
54
|
-
</div>
|
|
55
|
-
{/* Route visualization */}
|
|
56
|
-
<ScrollArea className="mt-2 rounded-md whitespace-nowrap">
|
|
57
|
-
<div className="grid w-full auto-cols-fr grid-flow-col items-center gap-2 py-2">
|
|
58
|
-
{steps.map((step, index) => (
|
|
59
|
-
<React.Fragment key={`${step.in.symbol}-${step.type}-${index}`}>
|
|
60
|
-
<Card variant="border" className="border-muted-foreground/60">
|
|
61
|
-
<CardContent className="space-y-2 pt-4">
|
|
62
|
-
{/* Type */}
|
|
63
|
-
<div className="text-secondary-foreground text-sm">
|
|
64
|
-
{capitalize(step.type)}
|
|
65
|
-
</div>
|
|
66
|
-
|
|
67
|
-
<div className="flex flex-row items-center gap-2">
|
|
68
|
-
{/* Token in */}
|
|
69
|
-
<LabelWithIcon
|
|
70
|
-
icon={step.in.icon || defaultIcon(step.in.symbol)}
|
|
71
|
-
textSize="xs"
|
|
72
|
-
iconSize="xs"
|
|
73
|
-
>
|
|
74
|
-
{!isLongRoute && (
|
|
75
|
-
<span className="hidden gap-2 sm:block">
|
|
76
|
-
{step.in.symbol}
|
|
77
|
-
</span>
|
|
78
|
-
)}
|
|
79
|
-
{step.type === "approve" && (
|
|
80
|
-
<span className="gap-2"> {step.amount}</span>
|
|
81
|
-
)}
|
|
82
|
-
</LabelWithIcon>
|
|
83
|
-
|
|
84
|
-
{step.type !== "approve" && (
|
|
85
|
-
<>
|
|
86
|
-
{/* Arrow between tokens */}
|
|
87
|
-
<ChevronsRight className="text-primary size-4 shrink-0" />
|
|
88
|
-
|
|
89
|
-
{/* Token out */}
|
|
90
|
-
<LabelWithIcon
|
|
91
|
-
icon={step.out.icon || defaultIcon(step.out.symbol)}
|
|
92
|
-
textSize="xs"
|
|
93
|
-
iconSize="xs"
|
|
94
|
-
>
|
|
95
|
-
{!isLongRoute && (
|
|
96
|
-
<span className="hidden gap-2 sm:block">
|
|
97
|
-
{step.in.symbol}
|
|
98
|
-
</span>
|
|
99
|
-
)}
|
|
100
|
-
</LabelWithIcon>
|
|
101
|
-
</>
|
|
102
|
-
)}
|
|
103
|
-
</div>
|
|
104
|
-
</CardContent>
|
|
105
|
-
</Card>
|
|
106
|
-
</React.Fragment>
|
|
107
|
-
))}
|
|
108
|
-
</div>
|
|
109
|
-
</ScrollArea>
|
|
110
|
-
</div>
|
|
111
|
-
);
|
|
112
|
-
};
|