diff --git a/mobile/app/admin/index.tsx b/mobile/app/admin/index.tsx
index 1f0d0b3..634fb70 100644
--- a/mobile/app/admin/index.tsx
+++ b/mobile/app/admin/index.tsx
@@ -1,9 +1,10 @@
import React, { useCallback, useState } from 'react';
-import { ActivityIndicator, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
+import { ActivityIndicator, Pressable, ScrollView, StyleSheet, Text, View, Dimensions } from 'react-native';
import { useFocusEffect, useRouter } from 'expo-router';
import { ChevronRight, Flag, Package, ShoppingCart, Users } from 'lucide-react-native';
import { palette, radius, spacing, type } from '@/theme';
import { Screen, AppHeader, Card } from '@/components/ui';
+import { LineChart, BarChart } from 'react-native-chart-kit';
import { adminApi } from '@/lib/api';
import type { AdminStats } from '@/lib/types';
@@ -64,6 +65,52 @@ export default function AdminDashboard() {
/>
+
+ User Growth (Last 6 Months)
+ palette.accent,
+ labelColor: (opacity = 1) => palette.muted,
+ propsForDots: { r: '4', strokeWidth: '2', stroke: palette.accent },
+ }}
+ bezier
+ style={{ borderRadius: radius.md, marginVertical: spacing.xs }}
+ />
+
+
+
+ Listings by Category
+ palette.warning,
+ labelColor: (opacity = 1) => palette.muted,
+ }}
+ style={{ borderRadius: radius.md, marginVertical: spacing.xs }}
+ />
+
+
router.push('/admin/users' as any)} />
diff --git a/mobile/app/chat/[conversationId].tsx b/mobile/app/chat/[conversationId].tsx
index 2d319db..7101a01 100644
--- a/mobile/app/chat/[conversationId].tsx
+++ b/mobile/app/chat/[conversationId].tsx
@@ -14,13 +14,18 @@ import * as ImagePicker from 'expo-image-picker';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useLocalSearchParams, useRouter } from 'expo-router';
import { useUser } from '@clerk/clerk-expo';
-import { ImagePlus, Send } from 'lucide-react-native';
+import { ImagePlus, Send, MoreVertical, ChevronLeft } from 'lucide-react-native';
import { palette, radius, spacing, type } from '@/theme';
import { AppHeader, Input, Avatar } from '@/components/ui';
+import { ImageViewerModal } from '@/components/ImageViewerModal';
import { chatApi, getImageUrl } from '@/lib/api';
import { formatRelative } from '@/lib/format';
import { getSocket } from '@/lib/socket';
import type { Message, User } from '@/lib/types';
+import { LinkPreview } from '@/components/LinkPreview';
+import { SharedMediaModal } from '@/components/SharedMediaModal';
+import { SellerVerificationModal } from '@/components/SellerVerificationModal';
+import { BuyerPurchasesModal } from '@/components/BuyerPurchasesModal';
export default function Thread() {
const { conversationId } = useLocalSearchParams<{ conversationId: string }>();
@@ -32,6 +37,11 @@ export default function Thread() {
const [other, setOther] = useState();
const [draft, setDraft] = useState('');
const [busy, setBusy] = useState(false);
+ const [showSharedMedia, setShowSharedMedia] = useState(false);
+ const [showSellerModal, setShowSellerModal] = useState(false);
+ const [showBuyerModal, setShowBuyerModal] = useState(false);
+ const [enlargedImage, setEnlargedImage] = useState(null);
+
const listRef = useRef>(null);
const load = useCallback(async () => {
@@ -104,23 +114,47 @@ export default function Thread() {
}
};
+ // Determine active listing and roles based on the latest message that references a listing
+ const activeListingMessage = [...messages].reverse().find(m => m.listingId && m.listing);
+ const activeListingId = activeListingMessage?.listingId;
+ const isSeller = activeListingMessage && activeListingMessage.listing?.sellerId === user?.id;
+ const isBuyer = activeListingMessage && activeListingMessage.listing?.sellerId !== user?.id;
+
return (
- router.push(`/profile/${other.clerkUserId}` as any)}>
-
+
+ router.back()} style={styles.backBtn} hitSlop={8}>
+
+
+ other && router.push(`/profile/${other.clerkUserId}` as any)}
+ style={styles.headerProfile}
+ >
+ {other && }
+
+ {other?.name ?? other?.username ?? 'Conversation'}
+
+
+
+ {isSeller && (
+ setShowSellerModal(true)} style={styles.actionBtn}>
+ Verify
- ) : null
- }
- />
+ )}
+ {isBuyer && (
+ setShowBuyerModal(true)} style={[styles.actionBtn, { backgroundColor: palette.surfaceElevated, borderWidth: 1, borderColor: palette.hairline }]}>
+ Purchases
+
+ )}
+ setShowSharedMedia(true)} hitSlop={8}>
+
+
+
+
{loading ? (
@@ -131,7 +165,9 @@ export default function Thread() {
data={messages}
keyExtractor={(m) => m.id}
contentContainerStyle={styles.list}
- renderItem={({ item }) => }
+ renderItem={({ item }) => (
+
+ )}
ItemSeparatorComponent={() => }
onContentSizeChange={() => listRef.current?.scrollToEnd({ animated: false })}
/>
@@ -161,11 +197,32 @@ export default function Thread() {
/>
+
+ setShowSharedMedia(false)}
+ messages={messages}
+ />
+ setShowSellerModal(false)}
+ buyerId={other?.id}
+ />
+ setShowBuyerModal(false)}
+ sellerId={other?.id}
+ />
+ setEnlargedImage(null)}
+ imageUrl={enlargedImage ? getImageUrl(enlargedImage) : null}
+ />
);
}
-function Bubble({ message, myClerkId }: { message: Message; myClerkId?: string }) {
+function Bubble({ message, myClerkId, onImagePress }: { message: Message; myClerkId?: string; onImagePress: (url: string) => void }) {
const mine = message.sender?.clerkUserId === myClerkId;
return (
@@ -191,12 +248,13 @@ function Bubble({ message, myClerkId }: { message: Message; myClerkId?: string }
{message.imageUrls && message.imageUrls.length > 0 ? (
{message.imageUrls.map(url => (
-
+ onImagePress(url)}>
+
+
))}
) : null}
@@ -206,6 +264,11 @@ function Bubble({ message, myClerkId }: { message: Message; myClerkId?: string }
{message.content}
) : null}
+
+ {message.content ? (() => {
+ const match = message.content.match(/https?:\/\/[^\s]+/);
+ return match ? : null;
+ })() : null}
();
@@ -33,6 +34,7 @@ export default function ListingDetail() {
const [saved, setSaved] = useState(false);
const [busy, setBusy] = useState(false);
const [existingOffer, setExistingOffer] = useState(null);
+ const [enlargedImage, setEnlargedImage] = useState(null);
const load = useCallback(async () => {
if (!id) return;
@@ -249,12 +251,13 @@ export default function ListingDetail() {
style={{ height: width * 0.88 }}
>
{(images.length > 0 ? images : [{ url: '' }]).map((img, i) => (
-
+ setEnlargedImage(img.url)}>
+
+
))}
@@ -452,6 +455,12 @@ export default function ListingDetail() {
) : null}
+
+ setEnlargedImage(null)}
+ imageUrl={enlargedImage ? getImageUrl(enlargedImage) : null}
+ />
);
}
diff --git a/mobile/components/BuyerPurchasesModal.tsx b/mobile/components/BuyerPurchasesModal.tsx
new file mode 100644
index 0000000..3c18ed3
--- /dev/null
+++ b/mobile/components/BuyerPurchasesModal.tsx
@@ -0,0 +1,220 @@
+import React, { useCallback, useEffect, useState } from 'react';
+import { Modal, View, Text, StyleSheet, Pressable, FlatList, ActivityIndicator } from 'react-native';
+import { Image } from 'expo-image';
+import { X, AlertTriangle } from 'lucide-react-native';
+import { palette, radius, spacing, type } from '@/theme';
+import { transactionsApi, getImageUrl } from '@/lib/api';
+import type { Transaction } from '@/lib/types';
+
+interface BuyerPurchasesModalProps {
+ visible: boolean;
+ onClose: () => void;
+ sellerId: string | undefined;
+}
+
+export function BuyerPurchasesModal({ visible, onClose, sellerId }: BuyerPurchasesModalProps) {
+ const [transactions, setTransactions] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [activeCode, setActiveCode] = useState(null);
+
+ const fetchTransactions = useCallback(async () => {
+ if (!visible || !sellerId) return;
+ setLoading(true);
+ try {
+ const data = await transactionsApi.activeAsBuyer();
+ const filtered = data.filter((t) => t.sellerId === sellerId);
+ setTransactions(filtered);
+
+ if (filtered.length > 0) {
+ // Just fetch the active code for the first listing in the context
+ const codeRes = await transactionsApi.activeMeetupCode(filtered[0].listingId, sellerId);
+ if (codeRes && codeRes.activeCode) {
+ setActiveCode(codeRes.activeCode);
+ }
+ }
+ } catch (e) {
+ console.warn('Failed to fetch buyer transactions', e);
+ } finally {
+ setLoading(false);
+ }
+ }, [visible, sellerId]);
+
+ useEffect(() => {
+ fetchTransactions();
+ }, [fetchTransactions]);
+
+ return (
+
+
+
+
+
+ My Purchases
+ Manage your active purchases from this seller.
+
+
+
+
+
+
+ {loading ? (
+
+
+
+ ) : transactions.length === 0 ? (
+
+
+ No Active Purchases
+
+ You don't have any pending purchases with this seller.
+
+
+ ) : (
+ item.id}
+ contentContainerStyle={styles.list}
+ ItemSeparatorComponent={() => }
+ renderItem={({ item }) => (
+
+
+
+
+
+ {item.listing?.title || 'Unknown Item'}
+
+
+ ${(item.amount / 100).toFixed(2)}
+
+
+
+ {item.paymentMethod}
+
+
+ {item.orderStatus.replace(/_/g, ' ')}
+
+
+
+
+
+ {item.paymentMethod === 'STRIPE' && item.orderStatus !== 'COMPLETED_BY_SELLER' && (
+
+
+ Show this 6-digit code to the seller:
+
+
+ {activeCode || '------'}
+
+
+ )}
+ {item.paymentMethod === 'DIRECT' && item.orderStatus !== 'COMPLETED_BY_SELLER' && (
+
+
+ Direct Payment
+
+
+ Pay the seller directly (Cash, Zelle, etc.) when you meet. The seller will mark the item as sold.
+
+
+ )}
+
+ )}
+ />
+ )}
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ overlay: {
+ flex: 1,
+ backgroundColor: 'rgba(0,0,0,0.5)',
+ justifyContent: 'flex-end',
+ },
+ content: {
+ backgroundColor: palette.background,
+ borderTopLeftRadius: radius.xl,
+ borderTopRightRadius: radius.xl,
+ height: '70%',
+ },
+ header: {
+ flexDirection: 'row',
+ alignItems: 'flex-start',
+ justifyContent: 'space-between',
+ padding: spacing.base,
+ borderBottomWidth: 1,
+ borderBottomColor: palette.hairline,
+ },
+ center: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ padding: spacing.xl,
+ },
+ list: {
+ padding: spacing.base,
+ paddingBottom: spacing.xxl,
+ },
+ card: {
+ backgroundColor: palette.surfaceElevated,
+ borderRadius: radius.lg,
+ padding: spacing.sm,
+ borderWidth: 1,
+ borderColor: palette.hairline,
+ },
+ cardHeader: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: spacing.sm,
+ },
+ image: {
+ width: 60,
+ height: 60,
+ borderRadius: radius.md,
+ backgroundColor: palette.card,
+ },
+ info: {
+ flex: 1,
+ },
+ badge: {
+ backgroundColor: palette.card,
+ paddingHorizontal: 6,
+ paddingVertical: 2,
+ borderRadius: radius.sm,
+ borderWidth: 1,
+ borderColor: palette.hairline,
+ },
+ badgeText: {
+ fontSize: 10,
+ fontWeight: '800',
+ color: palette.muted,
+ },
+ codeContainer: {
+ marginTop: spacing.md,
+ padding: spacing.sm,
+ backgroundColor: palette.accent + '10',
+ borderRadius: radius.md,
+ alignItems: 'center',
+ },
+ codeText: {
+ fontSize: 32,
+ fontWeight: '900',
+ color: palette.accent,
+ letterSpacing: 8,
+ marginTop: 4,
+ },
+ directContainer: {
+ marginTop: spacing.md,
+ padding: spacing.sm,
+ backgroundColor: palette.surface,
+ borderRadius: radius.md,
+ borderWidth: 1,
+ borderColor: palette.hairlineSoft,
+ }
+});
diff --git a/mobile/components/ImageViewerModal.tsx b/mobile/components/ImageViewerModal.tsx
new file mode 100644
index 0000000..4145ad1
--- /dev/null
+++ b/mobile/components/ImageViewerModal.tsx
@@ -0,0 +1,103 @@
+import React from 'react';
+import { Modal, View, StyleSheet, Pressable, ScrollView, Dimensions, Platform } from 'react-native';
+import { Image } from 'expo-image';
+import { X } from 'lucide-react-native';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import { palette, radius, hitSlop } from '@/theme';
+
+interface ImageViewerModalProps {
+ visible: boolean;
+ onClose: () => void;
+ imageUrl: string | null;
+}
+
+const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get('window');
+
+export function ImageViewerModal({ visible, onClose, imageUrl }: ImageViewerModalProps) {
+ const insets = useSafeAreaInsets();
+
+ if (!visible || !imageUrl) return null;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ {Platform.OS === 'ios' ? (
+
+
+
+ ) : (
+
+
+
+ )}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ overlay: {
+ flex: 1,
+ backgroundColor: 'rgba(0,0,0,0.9)',
+ },
+ header: {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ right: 0,
+ zIndex: 10,
+ flexDirection: 'row',
+ justifyContent: 'flex-end',
+ paddingHorizontal: 20,
+ paddingBottom: 20,
+ },
+ closeBtn: {
+ padding: 8,
+ },
+ closeBtnBg: {
+ backgroundColor: 'rgba(255,255,255,0.2)',
+ borderRadius: 20,
+ width: 40,
+ height: 40,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ scrollContainer: {
+ flex: 1,
+ width: SCREEN_WIDTH,
+ height: SCREEN_HEIGHT,
+ },
+ scrollContent: {
+ flexGrow: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ image: {
+ width: SCREEN_WIDTH,
+ height: SCREEN_HEIGHT,
+ },
+});
diff --git a/mobile/components/LinkPreview.tsx b/mobile/components/LinkPreview.tsx
new file mode 100644
index 0000000..fe45046
--- /dev/null
+++ b/mobile/components/LinkPreview.tsx
@@ -0,0 +1,84 @@
+import React, { useEffect, useState } from 'react';
+import { View, Text, StyleSheet, Pressable, Linking } from 'react-native';
+import { Image } from 'expo-image';
+import { getLinkPreview } from 'link-preview-js';
+import { palette, radius, spacing, type } from '@/theme';
+
+interface LinkPreviewProps {
+ url: string;
+}
+
+export function LinkPreview({ url }: LinkPreviewProps) {
+ const [data, setData] = useState(null);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ let mounted = true;
+ getLinkPreview(url)
+ .then((preview) => {
+ if (mounted) {
+ setData(preview);
+ setLoading(false);
+ }
+ })
+ .catch((e) => {
+ console.warn('Link preview failed:', e);
+ if (mounted) setLoading(false);
+ });
+
+ return () => {
+ mounted = false;
+ };
+ }, [url]);
+
+ if (loading || !data) {
+ return null; // Fail silently if it can't fetch metadata
+ }
+
+ const handlePress = () => {
+ Linking.openURL(url).catch(() => {});
+ };
+
+ const imageUrl = data.images?.[0] || data.favicons?.[0];
+
+ return (
+
+ {imageUrl && (
+
+ )}
+
+
+ {data.title || data.siteName || new URL(url).hostname}
+
+ {data.description && (
+
+ {data.description}
+
+ )}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ marginTop: spacing.xs,
+ backgroundColor: palette.surfaceElevated,
+ borderRadius: radius.md,
+ overflow: 'hidden',
+ borderWidth: 1,
+ borderColor: palette.hairline,
+ },
+ image: {
+ width: '100%',
+ height: 120,
+ backgroundColor: palette.card,
+ },
+ content: {
+ padding: spacing.sm,
+ },
+});
diff --git a/mobile/components/SellerVerificationModal.tsx b/mobile/components/SellerVerificationModal.tsx
new file mode 100644
index 0000000..ccffac0
--- /dev/null
+++ b/mobile/components/SellerVerificationModal.tsx
@@ -0,0 +1,245 @@
+import React, { useCallback, useEffect, useState } from 'react';
+import { Modal, View, Text, StyleSheet, Pressable, FlatList, ActivityIndicator, TextInput, KeyboardAvoidingView, Platform } from 'react-native';
+import { Image } from 'expo-image';
+import { X, AlertTriangle } from 'lucide-react-native';
+import { palette, radius, spacing, type } from '@/theme';
+import { transactionsApi, getImageUrl } from '@/lib/api';
+import type { Transaction } from '@/lib/types';
+import { Button } from '@/components/ui';
+
+interface SellerVerificationModalProps {
+ visible: boolean;
+ onClose: () => void;
+ buyerId: string | undefined;
+}
+
+export function SellerVerificationModal({ visible, onClose, buyerId }: SellerVerificationModalProps) {
+ const [transactions, setTransactions] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [actionLoading, setActionLoading] = useState>({});
+ const [codes, setCodes] = useState>({});
+
+ const fetchTransactions = useCallback(async () => {
+ if (!visible || !buyerId) return;
+ setLoading(true);
+ try {
+ const data = await transactionsApi.activeAsSeller();
+ // Filter only transactions with this specific buyer
+ const filtered = data.filter((t) => t.buyerId === buyerId);
+ setTransactions(filtered);
+ } catch (e) {
+ console.warn('Failed to fetch seller transactions', e);
+ } finally {
+ setLoading(false);
+ }
+ }, [visible, buyerId]);
+
+ useEffect(() => {
+ fetchTransactions();
+ }, [fetchTransactions]);
+
+ const handleMarkAsSold = async (id: string) => {
+ setActionLoading((prev) => ({ ...prev, [id]: true }));
+ try {
+ await transactionsApi.markAsSold(id);
+ await fetchTransactions(); // Refresh
+ } catch (e) {
+ console.warn('Failed to mark as sold', e);
+ } finally {
+ setActionLoading((prev) => ({ ...prev, [id]: false }));
+ }
+ };
+
+ const handleVerifyCode = async (id: string) => {
+ const code = codes[id];
+ if (!code || code.length !== 6) return;
+ setActionLoading((prev) => ({ ...prev, [id]: true }));
+ try {
+ await transactionsApi.verifyMeetupCode(id, code);
+ await fetchTransactions(); // Refresh
+ } catch (e) {
+ console.warn('Failed to verify code', e);
+ } finally {
+ setActionLoading((prev) => ({ ...prev, [id]: false }));
+ }
+ };
+
+ return (
+
+
+
+
+
+ Verify Meetups
+ Manage your active transactions with this buyer.
+
+
+
+
+
+
+ {loading ? (
+
+
+
+ ) : transactions.length === 0 ? (
+
+
+ No Active Meetups
+
+ You don't have any pending transactions with this buyer.
+
+
+ ) : (
+ item.id}
+ contentContainerStyle={styles.list}
+ ItemSeparatorComponent={() => }
+ renderItem={({ item }) => (
+
+
+
+
+
+ {item.listing?.title || 'Unknown Item'}
+
+
+ ${(item.amount / 100).toFixed(2)}
+
+
+
+ {item.paymentMethod}
+
+
+ {item.orderStatus.replace(/_/g, ' ')}
+
+
+
+
+
+
+ {item.paymentMethod === 'DIRECT' && item.orderStatus !== 'COMPLETED_BY_SELLER' && (
+
+
+ )}
+ />
+ )}
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ overlay: {
+ flex: 1,
+ backgroundColor: 'rgba(0,0,0,0.5)',
+ justifyContent: 'flex-end',
+ },
+ content: {
+ backgroundColor: palette.background,
+ borderTopLeftRadius: radius.xl,
+ borderTopRightRadius: radius.xl,
+ height: '70%',
+ },
+ header: {
+ flexDirection: 'row',
+ alignItems: 'flex-start',
+ justifyContent: 'space-between',
+ padding: spacing.base,
+ borderBottomWidth: 1,
+ borderBottomColor: palette.hairline,
+ },
+ center: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ padding: spacing.xl,
+ },
+ list: {
+ padding: spacing.base,
+ paddingBottom: spacing.xxl,
+ },
+ card: {
+ backgroundColor: palette.surfaceElevated,
+ borderRadius: radius.lg,
+ padding: spacing.sm,
+ borderWidth: 1,
+ borderColor: palette.hairline,
+ },
+ cardHeader: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: spacing.sm,
+ },
+ image: {
+ width: 60,
+ height: 60,
+ borderRadius: radius.md,
+ backgroundColor: palette.card,
+ },
+ info: {
+ flex: 1,
+ },
+ badge: {
+ backgroundColor: palette.card,
+ paddingHorizontal: 6,
+ paddingVertical: 2,
+ borderRadius: radius.sm,
+ borderWidth: 1,
+ borderColor: palette.hairline,
+ },
+ badgeText: {
+ fontSize: 10,
+ fontWeight: '800',
+ color: palette.muted,
+ },
+ actions: {
+ marginTop: spacing.sm,
+ },
+ codeRow: {
+ flexDirection: 'row',
+ gap: spacing.sm,
+ },
+ input: {
+ flex: 1,
+ height: 48,
+ borderRadius: radius.md,
+ borderWidth: 1,
+ borderColor: palette.hairlineStrong,
+ color: palette.foreground,
+ paddingHorizontal: spacing.md,
+ fontSize: 16,
+ },
+});
diff --git a/mobile/components/SharedMediaModal.tsx b/mobile/components/SharedMediaModal.tsx
new file mode 100644
index 0000000..5c2763e
--- /dev/null
+++ b/mobile/components/SharedMediaModal.tsx
@@ -0,0 +1,170 @@
+import React, { useMemo, useState } from 'react';
+import { Modal, View, Text, StyleSheet, Pressable, FlatList, Linking } from 'react-native';
+import { Image } from 'expo-image';
+import { X, ExternalLink, Image as ImageIcon } from 'lucide-react-native';
+import { palette, radius, spacing, type } from '@/theme';
+import { getImageUrl } from '@/lib/api';
+import type { Message } from '@/lib/types';
+import { ImageViewerModal } from '@/components/ImageViewerModal';
+
+interface SharedMediaModalProps {
+ visible: boolean;
+ onClose: () => void;
+ messages: Message[];
+}
+
+export function SharedMediaModal({ visible, onClose, messages }: SharedMediaModalProps) {
+ const { images, links } = useMemo(() => {
+ const imgs: string[] = [];
+ const lnks: string[] = [];
+ messages.forEach((m) => {
+ if (m.imageUrls) {
+ m.imageUrls.forEach((url) => imgs.push(url));
+ }
+ if (m.content) {
+ const matches = m.content.match(/https?:\/\/[^\s]+/g);
+ if (matches) {
+ matches.forEach((match) => lnks.push(match));
+ }
+ }
+ });
+ return { images: imgs, links: lnks };
+ }, [messages]);
+
+ const [activeTab, setActiveTab] = useState<'media' | 'links'>('media');
+ const [enlargedImage, setEnlargedImage] = useState(null);
+
+ return (
+
+
+
+
+ Shared Media
+
+
+
+
+
+
+ setActiveTab('media')}
+ >
+
+ Pictures ({images.length})
+
+
+ setActiveTab('links')}
+ >
+
+ URLs ({links.length})
+
+
+
+
+ `${item}-${index}`}
+ renderItem={({ item }) => {
+ if (activeTab === 'media') {
+ return (
+ setEnlargedImage(item)}>
+
+
+ );
+ }
+ if (activeTab === 'links') {
+ return (
+ Linking.openURL(item).catch(() => {})} style={styles.linkRow}>
+
+
+ {item}
+
+
+ );
+ }
+ return null;
+ }}
+ contentContainerStyle={styles.list}
+ />
+
+
+
+ setEnlargedImage(null)}
+ imageUrl={enlargedImage ? getImageUrl(enlargedImage) : null}
+ />
+
+ );
+}
+
+const styles = StyleSheet.create({
+ overlay: {
+ flex: 1,
+ backgroundColor: 'rgba(0,0,0,0.5)',
+ justifyContent: 'flex-end',
+ },
+ content: {
+ backgroundColor: palette.background,
+ borderTopLeftRadius: radius.xl,
+ borderTopRightRadius: radius.xl,
+ height: '85%',
+ },
+ header: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ padding: spacing.base,
+ borderBottomWidth: 1,
+ borderBottomColor: palette.hairline,
+ },
+ tabs: {
+ flexDirection: 'row',
+ borderBottomWidth: 1,
+ borderBottomColor: palette.hairline,
+ },
+ tab: {
+ flex: 1,
+ paddingVertical: spacing.md,
+ alignItems: 'center',
+ borderBottomWidth: 2,
+ borderBottomColor: 'transparent',
+ },
+ tabActive: {
+ borderBottomColor: palette.foreground,
+ },
+ tabText: {
+ ...type.body,
+ fontWeight: '600',
+ color: palette.muted,
+ },
+ tabTextActive: {
+ color: palette.foreground,
+ },
+ list: {
+ paddingHorizontal: spacing.base,
+ paddingTop: spacing.base,
+ paddingBottom: spacing.xxl,
+ },
+ image: {
+ width: '100%',
+ height: 200,
+ borderRadius: radius.md,
+ marginBottom: spacing.sm,
+ backgroundColor: palette.card,
+ },
+ linkRow: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingVertical: spacing.sm,
+ borderBottomWidth: 1,
+ borderBottomColor: palette.hairlineSoft,
+ },
+});
diff --git a/mobile/components/magicui/Globe.tsx b/mobile/components/magicui/Globe.tsx
index 99398c6..1c94e3f 100644
--- a/mobile/components/magicui/Globe.tsx
+++ b/mobile/components/magicui/Globe.tsx
@@ -1,20 +1,7 @@
-import React, { useEffect } from 'react';
+import React, { useEffect, useState } from 'react';
import { StyleSheet, View } from 'react-native';
-import Animated, {
- Easing,
- useAnimatedProps,
- useSharedValue,
- withRepeat,
- withTiming,
- type SharedValue,
-} from 'react-native-reanimated';
-import Svg, { Circle, Ellipse } from 'react-native-svg';
-import { palette } from '@/theme';
-
-const AnimatedEllipse = Animated.createAnimatedComponent(Ellipse);
-const AnimatedCircle = Animated.createAnimatedComponent(Circle);
-
-/** Marker locations as [latitude, longitude] — same cities as the web cobe globe. */
+import Svg, { Circle, Ellipse, Defs, RadialGradient, Stop } from 'react-native-svg';
+
const MARKERS: Array<[number, number, number]> = [
[14.6, 120.98, 3],
[19.08, 72.88, 5],
@@ -26,60 +13,74 @@ const MARKERS: Array<[number, number, number]> = [
[41.0, 28.98, 3.5],
];
-const MERIDIAN_COUNT = 5;
-const PARALLELS = [-50, -25, 0, 25, 50];
+const MERIDIAN_COUNT = 7;
+const PARALLELS = [-60, -40, -20, 0, 20, 40, 60];
-/**
- * React Native stand-in for `frontend/components/ui/globe.tsx` (cobe/WebGL).
- * A slowly spinning orthographic wireframe globe: static parallels, meridians
- * whose apparent width breathes with the rotation, and Cursor-Orange markers
- * that traverse the surface and fade behind the horizon.
- */
export function Globe({ size = 320 }: { size?: number }) {
- const spin = useSharedValue(0);
+ const [spin, setSpin] = useState(0);
useEffect(() => {
- spin.value = withRepeat(
- withTiming(1, { duration: 24000, easing: Easing.linear }),
- -1,
- false,
- );
- }, [spin]);
-
- const r = size / 2 - 4;
+ let animationFrameId: number;
+ let start: number;
+ const animate = (time: number) => {
+ if (!start) start = time;
+ const progress = ((time - start) % 18000) / 18000;
+ setSpin(progress);
+ animationFrameId = requestAnimationFrame(animate);
+ };
+ animationFrameId = requestAnimationFrame(animate);
+ return () => cancelAnimationFrame(animationFrameId);
+ }, []);
+
+ const r = size / 2 - 8;
const c = size / 2;
return (
@@ -55,9 +62,9 @@ const styles = StyleSheet.create({
borderBottomWidth: 1,
borderBottomColor: palette.hairline,
},
- left: { width: 44, alignItems: 'flex-start' },
- center: { flex: 1, alignItems: 'center' },
- right: { width: 44, alignItems: 'flex-end' },
+ left: { flex: 1, alignItems: 'flex-start' },
+ center: { flex: 2, alignItems: 'center', justifyContent: 'center' },
+ right: { flex: 1, alignItems: 'flex-end' },
backBtn: {
width: 44,
height: 44,
diff --git a/mobile/package-lock.json b/mobile/package-lock.json
index e92f574..0512f93 100644
--- a/mobile/package-lock.json
+++ b/mobile/package-lock.json
@@ -31,10 +31,12 @@
"expo-status-bar": "~1.12.1",
"expo-system-ui": "~3.0.7",
"expo-web-browser": "~13.0.3",
+ "link-preview-js": "^4.0.4",
"lucide-react-native": "^0.469.0",
"react": "18.2.0",
"react-dom": "^18.2.0",
"react-native": "0.74.5",
+ "react-native-chart-kit": "^7.0.2",
"react-native-gesture-handler": "~2.16.1",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-reanimated": "~3.10.1",
@@ -467,107 +469,6 @@
"node": ">=6.0.0"
}
},
- "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz",
- "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7",
- "@babel/traverse": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz",
- "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz",
- "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz",
- "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz",
- "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7",
- "@babel/plugin-transform-optional-chaining": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.13.0"
- }
- },
- "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz",
- "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7",
- "@babel/traverse": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
"node_modules/@babel/plugin-proposal-async-generator-functions": {
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz",
@@ -742,19 +643,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-private-property-in-object": {
- "version": "7.21.0-placeholder-for-preset-env.2",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
- "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-syntax-async-generators": {
"version": "7.8.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
@@ -824,38 +712,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-import-assertions": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz",
- "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-import-attributes": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz",
- "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-syntax-jsx": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz",
@@ -958,23 +814,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-unicode-sets-regex": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
- "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.18.6",
- "@babel/helper-plugin-utils": "^7.18.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
"node_modules/@babel/plugin-transform-arrow-functions": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz",
@@ -990,24 +829,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-async-generator-functions": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz",
- "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7",
- "@babel/helper-remap-async-to-generator": "^7.29.7",
- "@babel/traverse": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-async-to-generator": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz",
@@ -1025,22 +846,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-block-scoped-functions": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz",
- "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-block-scoping": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz",
@@ -1056,40 +861,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-class-properties": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz",
- "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.29.7",
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-class-static-block": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz",
- "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.29.7",
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.12.0"
- }
- },
"node_modules/@babel/plugin-transform-classes": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz",
@@ -1142,105 +913,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-dotall-regex": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz",
- "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.29.7",
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-duplicate-keys": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz",
- "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz",
- "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.29.7",
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-transform-dynamic-import": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz",
- "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-explicit-resource-management": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz",
- "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7",
- "@babel/plugin-transform-destructuring": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-exponentiation-operator": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz",
- "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-export-namespace-from": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz",
@@ -1272,23 +944,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-for-of": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz",
- "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-function-name": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz",
@@ -1306,22 +961,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-json-strings": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz",
- "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-literals": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz",
@@ -1337,55 +976,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-logical-assignment-operators": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz",
- "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-member-expression-literals": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz",
- "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-modules-amd": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz",
- "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-module-transforms": "^7.29.7",
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-modules-commonjs": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz",
@@ -1402,42 +992,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-modules-systemjs": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz",
- "integrity": "sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-module-transforms": "^7.29.7",
- "@babel/helper-plugin-utils": "^7.29.7",
- "@babel/helper-validator-identifier": "^7.29.7",
- "@babel/traverse": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-modules-umd": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz",
- "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-module-transforms": "^7.29.7",
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz",
@@ -1454,22 +1008,6 @@
"@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-transform-new-target": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz",
- "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz",
@@ -1485,22 +1023,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-numeric-separator": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz",
- "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-object-rest-spread": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz",
@@ -1511,40 +1033,7 @@
"@babel/helper-plugin-utils": "^7.29.7",
"@babel/plugin-transform-destructuring": "^7.29.7",
"@babel/plugin-transform-parameters": "^7.29.7",
- "@babel/traverse": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-object-super": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz",
- "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7",
- "@babel/helper-replace-supers": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-optional-catch-binding": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz",
- "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
+ "@babel/traverse": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
@@ -1617,22 +1106,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-property-literals": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz",
- "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-react-display-name": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.29.7.tgz",
@@ -1728,55 +1201,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-regenerator": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.7.tgz",
- "integrity": "sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-regexp-modifiers": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz",
- "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.29.7",
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-transform-reserved-words": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz",
- "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-runtime": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.29.7.tgz",
@@ -1858,22 +1282,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-typeof-symbol": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz",
- "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-typescript": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.29.7.tgz",
@@ -1893,39 +1301,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-unicode-escapes": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz",
- "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-unicode-property-regex": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz",
- "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.29.7",
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-unicode-regex": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz",
@@ -1942,123 +1317,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-unicode-sets-regex": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz",
- "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.29.7",
- "@babel/helper-plugin-utils": "^7.29.7"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/preset-env": {
- "version": "7.29.7",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.7.tgz",
- "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/compat-data": "^7.29.7",
- "@babel/helper-compilation-targets": "^7.29.7",
- "@babel/helper-plugin-utils": "^7.29.7",
- "@babel/helper-validator-option": "^7.29.7",
- "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7",
- "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7",
- "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7",
- "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7",
- "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7",
- "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7",
- "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
- "@babel/plugin-syntax-import-assertions": "^7.29.7",
- "@babel/plugin-syntax-import-attributes": "^7.29.7",
- "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
- "@babel/plugin-transform-arrow-functions": "^7.29.7",
- "@babel/plugin-transform-async-generator-functions": "^7.29.7",
- "@babel/plugin-transform-async-to-generator": "^7.29.7",
- "@babel/plugin-transform-block-scoped-functions": "^7.29.7",
- "@babel/plugin-transform-block-scoping": "^7.29.7",
- "@babel/plugin-transform-class-properties": "^7.29.7",
- "@babel/plugin-transform-class-static-block": "^7.29.7",
- "@babel/plugin-transform-classes": "^7.29.7",
- "@babel/plugin-transform-computed-properties": "^7.29.7",
- "@babel/plugin-transform-destructuring": "^7.29.7",
- "@babel/plugin-transform-dotall-regex": "^7.29.7",
- "@babel/plugin-transform-duplicate-keys": "^7.29.7",
- "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7",
- "@babel/plugin-transform-dynamic-import": "^7.29.7",
- "@babel/plugin-transform-explicit-resource-management": "^7.29.7",
- "@babel/plugin-transform-exponentiation-operator": "^7.29.7",
- "@babel/plugin-transform-export-namespace-from": "^7.29.7",
- "@babel/plugin-transform-for-of": "^7.29.7",
- "@babel/plugin-transform-function-name": "^7.29.7",
- "@babel/plugin-transform-json-strings": "^7.29.7",
- "@babel/plugin-transform-literals": "^7.29.7",
- "@babel/plugin-transform-logical-assignment-operators": "^7.29.7",
- "@babel/plugin-transform-member-expression-literals": "^7.29.7",
- "@babel/plugin-transform-modules-amd": "^7.29.7",
- "@babel/plugin-transform-modules-commonjs": "^7.29.7",
- "@babel/plugin-transform-modules-systemjs": "^7.29.7",
- "@babel/plugin-transform-modules-umd": "^7.29.7",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7",
- "@babel/plugin-transform-new-target": "^7.29.7",
- "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7",
- "@babel/plugin-transform-numeric-separator": "^7.29.7",
- "@babel/plugin-transform-object-rest-spread": "^7.29.7",
- "@babel/plugin-transform-object-super": "^7.29.7",
- "@babel/plugin-transform-optional-catch-binding": "^7.29.7",
- "@babel/plugin-transform-optional-chaining": "^7.29.7",
- "@babel/plugin-transform-parameters": "^7.29.7",
- "@babel/plugin-transform-private-methods": "^7.29.7",
- "@babel/plugin-transform-private-property-in-object": "^7.29.7",
- "@babel/plugin-transform-property-literals": "^7.29.7",
- "@babel/plugin-transform-regenerator": "^7.29.7",
- "@babel/plugin-transform-regexp-modifiers": "^7.29.7",
- "@babel/plugin-transform-reserved-words": "^7.29.7",
- "@babel/plugin-transform-shorthand-properties": "^7.29.7",
- "@babel/plugin-transform-spread": "^7.29.7",
- "@babel/plugin-transform-sticky-regex": "^7.29.7",
- "@babel/plugin-transform-template-literals": "^7.29.7",
- "@babel/plugin-transform-typeof-symbol": "^7.29.7",
- "@babel/plugin-transform-unicode-escapes": "^7.29.7",
- "@babel/plugin-transform-unicode-property-regex": "^7.29.7",
- "@babel/plugin-transform-unicode-regex": "^7.29.7",
- "@babel/plugin-transform-unicode-sets-regex": "^7.29.7",
- "@babel/preset-modules": "0.1.6-no-external-plugins",
- "babel-plugin-polyfill-corejs2": "^0.4.15",
- "babel-plugin-polyfill-corejs3": "^0.14.0",
- "babel-plugin-polyfill-regenerator": "^0.6.6",
- "core-js-compat": "^3.48.0",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": {
- "version": "0.14.2",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz",
- "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.6.8",
- "core-js-compat": "^3.48.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
- }
- },
"node_modules/@babel/preset-flow": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.29.7.tgz",
@@ -2076,21 +1334,6 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/preset-modules": {
- "version": "0.1.6-no-external-plugins",
- "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
- "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/types": "^7.4.4",
- "esutils": "^2.0.2"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
- }
- },
"node_modules/@babel/preset-react": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.29.7.tgz",
@@ -6888,44 +6131,6 @@
}
}
},
- "node_modules/@solana/buffer-layout": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz",
- "integrity": "sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "buffer": "~6.0.3"
- },
- "engines": {
- "node": ">=5.10"
- }
- },
- "node_modules/@solana/buffer-layout/node_modules/buffer": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
- "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.2.1"
- }
- },
"node_modules/@solana/codecs": {
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/@solana/codecs/-/codecs-6.10.0.tgz",
@@ -8019,138 +7224,6 @@
"react": "*"
}
},
- "node_modules/@solana/web3.js": {
- "version": "1.98.4",
- "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.98.4.tgz",
- "integrity": "sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@babel/runtime": "^7.25.0",
- "@noble/curves": "^1.4.2",
- "@noble/hashes": "^1.4.0",
- "@solana/buffer-layout": "^4.0.1",
- "@solana/codecs-numbers": "^2.1.0",
- "agentkeepalive": "^4.5.0",
- "bn.js": "^5.2.1",
- "borsh": "^0.7.0",
- "bs58": "^4.0.1",
- "buffer": "6.0.3",
- "fast-stable-stringify": "^1.0.0",
- "jayson": "^4.1.1",
- "node-fetch": "^2.7.0",
- "rpc-websockets": "^9.0.2",
- "superstruct": "^2.0.2"
- }
- },
- "node_modules/@solana/web3.js/node_modules/@solana/codecs-core": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.3.0.tgz",
- "integrity": "sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@solana/errors": "2.3.0"
- },
- "engines": {
- "node": ">=20.18.0"
- },
- "peerDependencies": {
- "typescript": ">=5.3.3"
- }
- },
- "node_modules/@solana/web3.js/node_modules/@solana/codecs-numbers": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.3.0.tgz",
- "integrity": "sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@solana/codecs-core": "2.3.0",
- "@solana/errors": "2.3.0"
- },
- "engines": {
- "node": ">=20.18.0"
- },
- "peerDependencies": {
- "typescript": ">=5.3.3"
- }
- },
- "node_modules/@solana/web3.js/node_modules/@solana/errors": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.3.0.tgz",
- "integrity": "sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "chalk": "^5.4.1",
- "commander": "^14.0.0"
- },
- "bin": {
- "errors": "bin/cli.mjs"
- },
- "engines": {
- "node": ">=20.18.0"
- },
- "peerDependencies": {
- "typescript": ">=5.3.3"
- }
- },
- "node_modules/@solana/web3.js/node_modules/base-x": {
- "version": "3.0.11",
- "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz",
- "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/@solana/web3.js/node_modules/bs58": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
- "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "base-x": "^3.0.2"
- }
- },
- "node_modules/@solana/web3.js/node_modules/buffer": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
- "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.2.1"
- }
- },
- "node_modules/@solana/web3.js/node_modules/commander": {
- "version": "14.0.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
- "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=20"
- }
- },
"node_modules/@stripe/stripe-js": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-5.6.0.tgz",
@@ -8195,16 +7268,6 @@
"url": "https://github.com/sponsors/tannerlinsley"
}
},
- "node_modules/@types/connect": {
- "version": "3.4.38",
- "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
- "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@types/node": "*"
- }
- },
"node_modules/@types/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
@@ -8282,14 +7345,14 @@
"version": "15.7.15",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
"integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
- "devOptional": true,
+ "dev": true,
"license": "MIT"
},
"node_modules/@types/react": {
"version": "18.2.79",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.79.tgz",
"integrity": "sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==",
- "devOptional": true,
+ "dev": true,
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
@@ -8302,23 +7365,6 @@
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
"license": "MIT"
},
- "node_modules/@types/uuid": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
- "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/@types/ws": {
- "version": "7.4.7",
- "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz",
- "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@types/node": "*"
- }
- },
"node_modules/@types/yargs": {
"version": "13.0.12",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz",
@@ -8554,19 +7600,6 @@
"node": ">= 6.0.0"
}
},
- "node_modules/agentkeepalive": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
- "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "humanize-ms": "^1.2.1"
- },
- "engines": {
- "node": ">= 8.0.0"
- }
- },
"node_modules/aggregate-error": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
@@ -9081,15 +8114,8 @@
"node_modules/base-64": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
- "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==",
- "license": "MIT"
- },
- "node_modules/base-x": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.1.tgz",
- "integrity": "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==",
- "license": "MIT",
- "peer": true
+ "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==",
+ "license": "MIT"
},
"node_modules/base64-js": {
"version": "1.5.1",
@@ -9169,51 +8195,12 @@
"node": ">= 6"
}
},
- "node_modules/bn.js": {
- "version": "5.2.4",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.4.tgz",
- "integrity": "sha512-QL7sb18rJ1PbdsKsqPA0guxL563vIMwRHgzNrW/uzQuRGN1Cjqd/wonUBAVqHox9KwzHA6vCbM0lXx3k4iQMow==",
- "license": "MIT",
- "peer": true
- },
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"license": "ISC"
},
- "node_modules/borsh": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/borsh/-/borsh-0.7.0.tgz",
- "integrity": "sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA==",
- "license": "Apache-2.0",
- "peer": true,
- "dependencies": {
- "bn.js": "^5.2.0",
- "bs58": "^4.0.0",
- "text-encoding-utf-8": "^1.0.2"
- }
- },
- "node_modules/borsh/node_modules/base-x": {
- "version": "3.0.11",
- "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz",
- "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/borsh/node_modules/bs58": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
- "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "base-x": "^3.0.2"
- }
- },
"node_modules/bplist-creator": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.7.tgz",
@@ -9300,16 +8287,6 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
- "node_modules/bs58": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz",
- "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "base-x": "^5.0.0"
- }
- },
"node_modules/bser": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
@@ -9371,21 +8348,6 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"license": "MIT"
},
- "node_modules/bufferutil": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.1.0.tgz",
- "integrity": "sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw==",
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "peer": true,
- "dependencies": {
- "node-gyp-build": "^4.3.0"
- },
- "engines": {
- "node": ">=6.14.2"
- }
- },
"node_modules/builtins": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz",
@@ -9617,6 +8579,45 @@
"node": "*"
}
},
+ "node_modules/cheerio": {
+ "version": "1.0.0-rc.11",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.11.tgz",
+ "integrity": "sha512-bQwNaDIBKID5ts/DsdhxrjqFXYfLw4ste+wMKqWA8DyKcS4qwsPP4Bk8ZNaTJjvpiX/qW3BT4sU7d6Bh5i+dag==",
+ "license": "MIT",
+ "dependencies": {
+ "cheerio-select": "^2.1.0",
+ "dom-serializer": "^2.0.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1",
+ "htmlparser2": "^8.0.1",
+ "parse5": "^7.0.0",
+ "parse5-htmlparser2-tree-adapter": "^7.0.0",
+ "tslib": "^2.4.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
+ }
+ },
+ "node_modules/cheerio-select": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
+ "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-select": "^5.1.0",
+ "css-what": "^6.1.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
"node_modules/chownr": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
@@ -10370,19 +9371,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/delay": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz",
- "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==",
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -10835,23 +9823,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/es6-promise": {
- "version": "4.2.8",
- "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
- "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/es6-promisify": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
- "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "es6-promise": "^4.0.3"
- }
- },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -10892,16 +9863,6 @@
"node": ">=4"
}
},
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "license": "BSD-2-Clause",
- "peer": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -11404,15 +10365,6 @@
"integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==",
"license": "Apache-2.0"
},
- "node_modules/eyes": {
- "version": "0.1.8",
- "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
- "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==",
- "peer": true,
- "engines": {
- "node": "> 0.1.90"
- }
- },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -11435,13 +10387,6 @@
"node": ">=8.6.0"
}
},
- "node_modules/fast-stable-stringify": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz",
- "integrity": "sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag==",
- "license": "MIT",
- "peer": true
- },
"node_modules/fast-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz",
@@ -12236,6 +11181,25 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"license": "ISC"
},
+ "node_modules/htmlparser2": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
+ "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1",
+ "entities": "^4.4.0"
+ }
+ },
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
@@ -12283,16 +11247,6 @@
"node": ">=10.17.0"
}
},
- "node_modules/humanize-ms": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
- "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "ms": "^2.0.0"
- }
- },
"node_modules/idb-keyval": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz",
@@ -13063,16 +12017,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/isomorphic-ws": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz",
- "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==",
- "license": "MIT",
- "peer": true,
- "peerDependencies": {
- "ws": "*"
- }
- },
"node_modules/isows": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz",
@@ -13103,69 +12047,6 @@
"@pkgjs/parseargs": "^0.11.0"
}
},
- "node_modules/jayson": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.3.0.tgz",
- "integrity": "sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@types/connect": "^3.4.33",
- "@types/node": "^12.12.54",
- "@types/ws": "^7.4.4",
- "commander": "^2.20.3",
- "delay": "^5.0.0",
- "es6-promisify": "^5.0.0",
- "eyes": "^0.1.8",
- "isomorphic-ws": "^4.0.1",
- "json-stringify-safe": "^5.0.1",
- "stream-json": "^1.9.1",
- "uuid": "^8.3.2",
- "ws": "^7.5.10"
- },
- "bin": {
- "jayson": "bin/jayson.js"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/jayson/node_modules/@types/node": {
- "version": "12.20.55",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
- "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/jayson/node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/jayson/node_modules/ws": {
- "version": "7.5.11",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.11.tgz",
- "integrity": "sha512-zS54Oen9bITtp7kp2XM3AydrCIq1D+HwJOuH+c+e4LfpL/lotP5osijd+UoMnxwAam1GN8R4KtLAyIrIcBNpiA==",
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=8.3.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": "^5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
"node_modules/jest-environment-node": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
@@ -13942,13 +12823,6 @@
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"license": "MIT"
},
- "node_modules/json-stringify-safe": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
- "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
- "license": "ISC",
- "peer": true
- },
"node_modules/json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
@@ -14226,6 +13100,18 @@
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"license": "MIT"
},
+ "node_modules/link-preview-js": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/link-preview-js/-/link-preview-js-4.0.4.tgz",
+ "integrity": "sha512-hJ2UlkFtwCihTtx8y5zBH6iuMYwz+W5v06GY7owDfFvTdAtMZMBfKzg7TjKegL+ehHw4CDIzZClJNKhwAD6Q0Q==",
+ "license": "MIT",
+ "dependencies": {
+ "cheerio": "1.0.0-rc.11"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -15349,19 +14235,6 @@
"node": ">= 6.13.0"
}
},
- "node_modules/node-gyp-build": {
- "version": "4.8.4",
- "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
- "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
- "license": "MIT",
- "optional": true,
- "peer": true,
- "bin": {
- "node-gyp-build": "bin.js",
- "node-gyp-build-optional": "optional.js",
- "node-gyp-build-test": "build-test.js"
- }
- },
"node_modules/node-int64": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
@@ -15839,6 +14712,43 @@
"node": ">=10"
}
},
+ "node_modules/parse5": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+ "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^6.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5-htmlparser2-tree-adapter": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
+ "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
+ "license": "MIT",
+ "dependencies": {
+ "domhandler": "^5.0.3",
+ "parse5": "^7.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5/node_modules/entities": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
+ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -15912,6 +14822,15 @@
"node": ">=8"
}
},
+ "node_modules/paths-js": {
+ "version": "0.4.11",
+ "resolved": "https://registry.npmjs.org/paths-js/-/paths-js-0.4.11.tgz",
+ "integrity": "sha512-3mqcLomDBXOo7Fo+UlaenG6f71bk1ZezPQy2JCmYHy2W2k5VKpP+Jbin9H0bjXynelTbglCqdFhSEkeIkKTYUA==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=0.11.0"
+ }
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -16494,6 +15413,27 @@
}
}
},
+ "node_modules/react-native-chart-kit": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/react-native-chart-kit/-/react-native-chart-kit-7.0.2.tgz",
+ "integrity": "sha512-rN2Q7Dak8FFC1clbkkTu7eF9gWBovYD45Fnb64hFmlxn0bYmWFv9MwG+KlNGXsmfrxZ3oU4EUbf5gOTjHtcpoQ==",
+ "license": "MIT",
+ "workspaces": [
+ "packages/*",
+ "apps/site"
+ ],
+ "dependencies": {
+ "paths-js": "^0.4.11"
+ },
+ "engines": {
+ "node": ">=20.19.4"
+ },
+ "peerDependencies": {
+ "react": ">=19.1.0 <20",
+ "react-native": ">=0.81 <1",
+ "react-native-svg": ">=15.12.1 <16"
+ }
+ },
"node_modules/react-native-gesture-handler": {
"version": "2.16.2",
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.16.2.tgz",
@@ -17162,79 +16102,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/rpc-websockets": {
- "version": "9.3.9",
- "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-9.3.9.tgz",
- "integrity": "sha512-2iQDaTB4g5fDB2ihrTFSJSibCEuxaRi1q7qTW7ZO9/M5/TC+ToHA4D9/ffNLEbAoHNNrcdeP05oATNk44SKZXA==",
- "license": "LGPL-3.0-only",
- "peer": true,
- "dependencies": {
- "@swc/helpers": "^0.5.11",
- "@types/uuid": "^10.0.0",
- "@types/ws": "^8.2.2",
- "buffer": "^6.0.3",
- "eventemitter3": "^5.0.1",
- "uuid": "^14.0.0",
- "ws": "^8.5.0"
- },
- "funding": {
- "type": "paypal",
- "url": "https://paypal.me/kozjak"
- },
- "optionalDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": "^6.0.0"
- }
- },
- "node_modules/rpc-websockets/node_modules/@types/ws": {
- "version": "8.18.1",
- "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
- "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/rpc-websockets/node_modules/buffer": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
- "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.2.1"
- }
- },
- "node_modules/rpc-websockets/node_modules/uuid": {
- "version": "14.0.1",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz",
- "integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==",
- "funding": [
- "https://github.com/sponsors/broofa",
- "https://github.com/sponsors/ctavan"
- ],
- "license": "MIT",
- "peer": true,
- "bin": {
- "uuid": "dist-node/bin/uuid"
- }
- },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -18050,23 +16917,6 @@
"node": ">= 0.10.0"
}
},
- "node_modules/stream-chain": {
- "version": "2.2.5",
- "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz",
- "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==",
- "license": "BSD-3-Clause",
- "peer": true
- },
- "node_modules/stream-json": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz",
- "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==",
- "license": "BSD-3-Clause",
- "peer": true,
- "dependencies": {
- "stream-chain": "^2.2.5"
- }
- },
"node_modules/stream-slice": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/stream-slice/-/stream-slice-0.1.2.tgz",
@@ -18387,16 +17237,6 @@
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
"license": "MIT"
},
- "node_modules/superstruct": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-2.0.2.tgz",
- "integrity": "sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==",
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=14.0.0"
- }
- },
"node_modules/supports-color": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
@@ -18642,12 +17482,6 @@
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"license": "MIT"
},
- "node_modules/text-encoding-utf-8": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz",
- "integrity": "sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==",
- "peer": true
- },
"node_modules/text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@@ -18892,6 +17726,7 @@
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
+ "dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
@@ -19108,21 +17943,6 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
- "node_modules/utf-8-validate": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.6.tgz",
- "integrity": "sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA==",
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "peer": true,
- "dependencies": {
- "node-gyp-build": "^4.3.0"
- },
- "engines": {
- "node": ">=6.14.2"
- }
- },
"node_modules/util": {
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
diff --git a/mobile/package.json b/mobile/package.json
index aaa4746..7567ca2 100644
--- a/mobile/package.json
+++ b/mobile/package.json
@@ -34,10 +34,12 @@
"expo-status-bar": "~1.12.1",
"expo-system-ui": "~3.0.7",
"expo-web-browser": "~13.0.3",
+ "link-preview-js": "^4.0.4",
"lucide-react-native": "^0.469.0",
"react": "18.2.0",
"react-dom": "^18.2.0",
"react-native": "0.74.5",
+ "react-native-chart-kit": "^7.0.2",
"react-native-gesture-handler": "~2.16.1",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-reanimated": "~3.10.1",