mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-08 14:43:54 -05:00
feat(contributors): added contributors page (#444)
* added contributors page * added debounce to prefetch, acked PR comments
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
'use server'
|
||||
|
||||
import { env } from '@/lib/env'
|
||||
|
||||
/**
|
||||
* Format a number to a human-readable format (e.g., 1000 -> 1k, 1100 -> 1.1k)
|
||||
*/
|
||||
@@ -8,10 +10,8 @@ function formatNumber(num: number): string {
|
||||
return num.toString()
|
||||
}
|
||||
|
||||
// Convert to one decimal place and remove trailing 0
|
||||
const formatted = (Math.round(num / 100) / 10).toFixed(1)
|
||||
|
||||
// Remove .0 if the decimal is 0
|
||||
return formatted.endsWith('.0') ? `${formatted.slice(0, -2)}k` : `${formatted}k`
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ function formatNumber(num: number): string {
|
||||
*/
|
||||
export async function getFormattedGitHubStars(): Promise<string> {
|
||||
try {
|
||||
const token = process.env.GITHUB_TOKEN
|
||||
const token = env.GITHUB_TOKEN
|
||||
|
||||
const response = await fetch('https://api.github.com/repos/simstudioai/sim', {
|
||||
headers: {
|
||||
@@ -29,18 +29,176 @@ export async function getFormattedGitHubStars(): Promise<string> {
|
||||
'User-Agent': 'SimStudio/1.0',
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||
},
|
||||
next: { revalidate: 3600 }, // Revalidate every hour
|
||||
next: { revalidate: 3600 },
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
console.error(`GitHub API error: ${response.status} ${response.statusText}`)
|
||||
return formatNumber(1200)
|
||||
return formatNumber(3867)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return formatNumber(data.stargazers_count || 1200)
|
||||
return formatNumber(data.stargazers_count || 3867)
|
||||
} catch (error) {
|
||||
console.error('Error fetching GitHub stars:', error)
|
||||
return formatNumber(1200)
|
||||
return formatNumber(3867)
|
||||
}
|
||||
}
|
||||
|
||||
interface Contributor {
|
||||
login: string
|
||||
avatar_url: string
|
||||
contributions: number
|
||||
html_url: string
|
||||
}
|
||||
|
||||
interface CommitData {
|
||||
sha: string
|
||||
commit: {
|
||||
author: {
|
||||
name: string
|
||||
email: string
|
||||
date: string
|
||||
}
|
||||
message: string
|
||||
}
|
||||
html_url: string
|
||||
}
|
||||
|
||||
interface RepoStats {
|
||||
stars: number
|
||||
forks: number
|
||||
watchers: number
|
||||
openIssues: number
|
||||
openPRs: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Server action to fetch repository statistics
|
||||
*/
|
||||
export async function getRepositoryStats(): Promise<RepoStats> {
|
||||
try {
|
||||
const token = env.GITHUB_TOKEN
|
||||
|
||||
const headers = {
|
||||
Accept: 'application/vnd.github+json',
|
||||
'X-GitHub-Api-Version': '2022-11-28',
|
||||
'User-Agent': 'SimStudio/1.0',
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||
}
|
||||
|
||||
const repoResponse = await fetch('https://api.github.com/repos/simstudioai/sim', {
|
||||
headers,
|
||||
next: { revalidate: 3600 },
|
||||
})
|
||||
|
||||
const prsResponse = await fetch(
|
||||
'https://api.github.com/repos/simstudioai/sim/pulls?state=open',
|
||||
{
|
||||
headers,
|
||||
next: { revalidate: 3600 },
|
||||
}
|
||||
)
|
||||
|
||||
if (!repoResponse.ok || !prsResponse.ok) {
|
||||
console.error('GitHub API error fetching repo stats')
|
||||
return {
|
||||
stars: 3867,
|
||||
forks: 581,
|
||||
watchers: 26,
|
||||
openIssues: 23,
|
||||
openPRs: 3,
|
||||
}
|
||||
}
|
||||
|
||||
const repoData = await repoResponse.json()
|
||||
const prsData = await prsResponse.json()
|
||||
|
||||
return {
|
||||
stars: repoData.stargazers_count || 3867,
|
||||
forks: repoData.forks_count || 581,
|
||||
watchers: repoData.subscribers_count || 26,
|
||||
openIssues: (repoData.open_issues_count || 26) - prsData.length,
|
||||
openPRs: prsData.length || 3,
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching repository stats:', error)
|
||||
return {
|
||||
stars: 3867,
|
||||
forks: 581,
|
||||
watchers: 26,
|
||||
openIssues: 23,
|
||||
openPRs: 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Server action to fetch contributors
|
||||
*/
|
||||
export async function getContributors(): Promise<Contributor[]> {
|
||||
try {
|
||||
const token = env.GITHUB_TOKEN
|
||||
|
||||
const headers = {
|
||||
Accept: 'application/vnd.github+json',
|
||||
'X-GitHub-Api-Version': '2022-11-28',
|
||||
'User-Agent': 'SimStudio/1.0',
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
'https://api.github.com/repos/simstudioai/sim/contributors?per_page=100',
|
||||
{
|
||||
headers,
|
||||
next: { revalidate: 3600 },
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
console.error('GitHub API error fetching contributors')
|
||||
return []
|
||||
}
|
||||
|
||||
const contributors = await response.json()
|
||||
return contributors || []
|
||||
} catch (error) {
|
||||
console.error('Error fetching contributors:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Server action to fetch recent commits for timeline data
|
||||
*/
|
||||
export async function getCommitsData(): Promise<CommitData[]> {
|
||||
try {
|
||||
const token = env.GITHUB_TOKEN
|
||||
|
||||
const headers = {
|
||||
Accept: 'application/vnd.github+json',
|
||||
'X-GitHub-Api-Version': '2022-11-28',
|
||||
'User-Agent': 'SimStudio/1.0',
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
'https://api.github.com/repos/simstudioai/sim/commits?per_page=100',
|
||||
{
|
||||
headers,
|
||||
next: { revalidate: 3600 },
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
console.error('GitHub API error fetching commits')
|
||||
return []
|
||||
}
|
||||
|
||||
const commits = await response.json()
|
||||
return commits || []
|
||||
} catch (error) {
|
||||
console.error('Error fetching commits:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,7 @@ import {
|
||||
SheetTitle,
|
||||
SheetTrigger,
|
||||
} from '@/components/ui/sheet'
|
||||
import { createLogger } from '@/lib/logs/console-logger'
|
||||
|
||||
const _logger = createLogger('NavClient')
|
||||
import { usePrefetchOnHover } from '../utils/prefetch'
|
||||
|
||||
// --- Framer Motion Variants ---
|
||||
const desktopNavContainerVariants = {
|
||||
@@ -90,9 +88,11 @@ const NavLinks = ({
|
||||
...(currentPath !== '/' ? [{ href: '/', label: 'Home' }] : []),
|
||||
{ href: 'https://docs.simstudio.ai/', label: 'Docs', external: true },
|
||||
// { href: '/', label: 'Blog' },
|
||||
{ href: 'https://github.com/simstudioai/sim', label: 'Contributors', external: true },
|
||||
{ href: '/contributors', label: 'Contributors' },
|
||||
]
|
||||
|
||||
const handleContributorsHover = usePrefetchOnHover()
|
||||
|
||||
// Common CSS class for navigation items
|
||||
const navItemClass = `text-white/60 hover:text-white/100 text-base ${
|
||||
mobile ? 'p-2.5 text-lg font-medium text-left' : 'p-1.5'
|
||||
@@ -106,6 +106,7 @@ const NavLinks = ({
|
||||
<Link
|
||||
href={link.href}
|
||||
className={navItemClass}
|
||||
onMouseEnter={link.label === 'Contributors' ? handleContributorsHover : undefined}
|
||||
{...(link.external ? { target: '_blank', rel: 'noopener noreferrer' } : {})}
|
||||
>
|
||||
{link.label}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useRouter } from 'next/navigation'
|
||||
import { DiscordIcon, GithubIcon, xIcon as XIcon } from '@/components/icons'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { useSession } from '@/lib/auth-client'
|
||||
import { usePrefetchOnHover } from '../../utils/prefetch'
|
||||
import useIsMobile from '../hooks/use-is-mobile'
|
||||
|
||||
function Footer() {
|
||||
@@ -14,6 +15,8 @@ function Footer() {
|
||||
const { data: session, isPending } = useSession()
|
||||
const isAuthenticated = !isPending && !!session?.user
|
||||
|
||||
const handleContributorsHover = usePrefetchOnHover()
|
||||
|
||||
const handleNavigate = () => {
|
||||
if (typeof window !== 'undefined') {
|
||||
// Check if user has an active session
|
||||
@@ -95,10 +98,9 @@ function Footer() {
|
||||
Docs
|
||||
</Link>
|
||||
<Link
|
||||
href={'https://github.com/simstudioai/sim'}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
href={'/contributors'}
|
||||
className='font-light text-[#9E91AA] text-xl transition-all duration-500 hover:text-[#bdaecb] md:text-2xl'
|
||||
onMouseEnter={handleContributorsHover}
|
||||
>
|
||||
Contributors
|
||||
</Link>
|
||||
@@ -274,10 +276,9 @@ function Footer() {
|
||||
Docs
|
||||
</Link>
|
||||
<Link
|
||||
href={'https://github.com/simstudioai/sim'}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
href={'/contributors'}
|
||||
className='font-light text-[#9E91AA] text-xl transition-all duration-500 hover:text-[#bdaecb] md:text-2xl'
|
||||
onMouseEnter={handleContributorsHover}
|
||||
>
|
||||
Contributors
|
||||
</Link>
|
||||
|
||||
614
apps/sim/app/(landing)/contributors/page.tsx
Normal file
614
apps/sim/app/(landing)/contributors/page.tsx
Normal file
@@ -0,0 +1,614 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { motion } from 'framer-motion'
|
||||
import {
|
||||
ChartAreaIcon,
|
||||
GitFork,
|
||||
GitGraph,
|
||||
Github,
|
||||
GitPullRequest,
|
||||
LayoutGrid,
|
||||
MessageCircle,
|
||||
Star,
|
||||
} from 'lucide-react'
|
||||
import Image from 'next/image'
|
||||
import {
|
||||
Area,
|
||||
AreaChart,
|
||||
Bar,
|
||||
BarChart,
|
||||
ResponsiveContainer,
|
||||
Tooltip,
|
||||
XAxis,
|
||||
YAxis,
|
||||
} from 'recharts'
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||
import { GridPattern } from '../components/grid-pattern'
|
||||
import NavWrapper from '../components/nav-wrapper'
|
||||
import Footer from '../components/sections/footer'
|
||||
import { getCachedContributorsData, prefetchContributorsData } from '../utils/prefetch'
|
||||
|
||||
interface Contributor {
|
||||
login: string
|
||||
avatar_url: string
|
||||
contributions: number
|
||||
html_url: string
|
||||
}
|
||||
|
||||
interface RepoStats {
|
||||
stars: number
|
||||
forks: number
|
||||
watchers: number
|
||||
openIssues: number
|
||||
openPRs: number
|
||||
}
|
||||
|
||||
interface CommitTimelineData {
|
||||
date: string
|
||||
commits: number
|
||||
additions: number
|
||||
deletions: number
|
||||
}
|
||||
|
||||
interface ActivityData {
|
||||
date: string
|
||||
commits: number
|
||||
issues: number
|
||||
pullRequests: number
|
||||
}
|
||||
|
||||
const excludedUsernames = ['dependabot[bot]', 'github-actions']
|
||||
|
||||
const ChartControls = ({
|
||||
showAll,
|
||||
setShowAll,
|
||||
total,
|
||||
}: {
|
||||
showAll: boolean
|
||||
setShowAll: (show: boolean) => void
|
||||
total: number
|
||||
}) => (
|
||||
<div className='mb-4 flex items-center justify-between'>
|
||||
<span className='text-neutral-400 text-sm'>
|
||||
Showing {showAll ? 'all' : 'top 10'} contributors
|
||||
</span>
|
||||
<Button
|
||||
variant='outline'
|
||||
size='sm'
|
||||
onClick={() => setShowAll(!showAll)}
|
||||
className='border-[#606060]/30 bg-[#0f0f0f] text-neutral-300 text-xs backdrop-blur-sm hover:bg-neutral-700/50 hover:text-white'
|
||||
>
|
||||
Show {showAll ? 'less' : 'all'} ({total})
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
|
||||
export default function ContributorsPage() {
|
||||
const [repoStats, setRepoStats] = useState<RepoStats>({
|
||||
stars: 0,
|
||||
forks: 0,
|
||||
watchers: 0,
|
||||
openIssues: 0,
|
||||
openPRs: 0,
|
||||
})
|
||||
const [timelineData, setTimelineData] = useState<CommitTimelineData[]>([])
|
||||
const [activityData, setActivityData] = useState<ActivityData[]>([])
|
||||
const [showAllContributors, setShowAllContributors] = useState(false)
|
||||
const [allContributors, setAllContributors] = useState<Contributor[]>([])
|
||||
|
||||
const handleOpenTypeformLink = () => {
|
||||
window.open('https://form.typeform.com/to/jqCO12pF', '_blank')
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
// First, try to get cached data
|
||||
const cachedData = getCachedContributorsData()
|
||||
|
||||
if (cachedData) {
|
||||
// Use cached data immediately
|
||||
setAllContributors(cachedData.contributors)
|
||||
setRepoStats(cachedData.repoStats)
|
||||
setTimelineData(cachedData.timelineData)
|
||||
setActivityData(cachedData.activityData)
|
||||
} else {
|
||||
// If no cached data, fetch it
|
||||
try {
|
||||
const data = await prefetchContributorsData()
|
||||
setAllContributors(data.contributors)
|
||||
setRepoStats(data.repoStats)
|
||||
setTimelineData(data.timelineData)
|
||||
setActivityData(data.activityData)
|
||||
} catch (err) {
|
||||
console.error('Error fetching data:', err)
|
||||
// Set default values if fetch fails
|
||||
setAllContributors([])
|
||||
setRepoStats({
|
||||
stars: 3867,
|
||||
forks: 581,
|
||||
watchers: 26,
|
||||
openIssues: 23,
|
||||
openPRs: 3,
|
||||
})
|
||||
setTimelineData([])
|
||||
setActivityData([])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loadData()
|
||||
}, [])
|
||||
|
||||
const filteredContributors = useMemo(
|
||||
() =>
|
||||
allContributors
|
||||
?.filter((contributor) => !excludedUsernames.includes(contributor.login))
|
||||
.sort((a, b) => b.contributions - a.contributions),
|
||||
[allContributors]
|
||||
)
|
||||
|
||||
return (
|
||||
<main className='relative min-h-screen bg-[#0C0C0C] font-geist-sans text-white'>
|
||||
{/* Grid pattern background */}
|
||||
<div className='absolute inset-0 bottom-[400px] z-0'>
|
||||
<GridPattern
|
||||
x={-5}
|
||||
y={-5}
|
||||
className='absolute inset-0 stroke-[#ababab]/5'
|
||||
width={90}
|
||||
height={90}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Header/Navigation */}
|
||||
<NavWrapper onOpenTypeformLink={handleOpenTypeformLink} />
|
||||
|
||||
{/* Content */}
|
||||
<div className='relative z-10'>
|
||||
{/* Hero Section with Integrated Stats */}
|
||||
<section className='px-4 pt-20 pb-12 sm:px-8 sm:pt-28 sm:pb-16 md:px-16 md:pt-40 md:pb-24 lg:px-28 xl:px-32'>
|
||||
<div className='mx-auto max-w-6xl'>
|
||||
{/* Main Hero Content */}
|
||||
<div className='mb-12 text-center sm:mb-16'>
|
||||
<motion.h1
|
||||
className='font-medium text-4xl text-white tracking-tight sm:text-5xl'
|
||||
initial={{ opacity: 0, y: 40 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.7, ease: 'easeOut' }}
|
||||
>
|
||||
Contributors
|
||||
</motion.h1>
|
||||
<motion.p
|
||||
className='mx-auto mt-3 max-w-2xl font-light text-lg text-neutral-400 sm:mt-4 sm:text-xl'
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.2 }}
|
||||
>
|
||||
Meet the amazing people who have helped build and improve Sim Studio
|
||||
</motion.p>
|
||||
</div>
|
||||
|
||||
{/* Integrated Project Stats */}
|
||||
<motion.div
|
||||
className='overflow-hidden rounded-2xl border border-[#606060]/30 bg-[#0f0f0f] p-4 backdrop-blur-sm sm:rounded-3xl sm:p-8'
|
||||
initial={{ opacity: 0, y: 40 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, amount: 0.2 }}
|
||||
transition={{ duration: 0.7, delay: 0.1 }}
|
||||
>
|
||||
{/* Project Header */}
|
||||
<div className='mb-6 flex flex-col items-start justify-between gap-3 sm:mb-8 sm:flex-row sm:items-center sm:gap-4'>
|
||||
<div className='space-y-1'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<div className='relative h-6 w-6 sm:h-8 sm:w-8'>
|
||||
<Image
|
||||
src='/favicon.ico'
|
||||
alt='Sim Studio Logo'
|
||||
className='object-contain'
|
||||
width={32}
|
||||
height={32}
|
||||
/>
|
||||
</div>
|
||||
<h2 className='font-semibold text-lg text-white sm:text-xl'>Sim Studio</h2>
|
||||
</div>
|
||||
<p className='text-neutral-400 text-xs sm:text-sm'>
|
||||
An open source platform for building, testing, and optimizing agentic workflows
|
||||
</p>
|
||||
</div>
|
||||
<div className='flex gap-2 self-end sm:self-auto'>
|
||||
<Button
|
||||
asChild
|
||||
variant='outline'
|
||||
size='sm'
|
||||
className='gap-1 border-[#606060]/30 bg-[#0f0f0f] text-neutral-300 text-xs backdrop-blur-sm hover:bg-neutral-700/50 hover:text-white sm:gap-2 sm:text-sm'
|
||||
>
|
||||
<a href='https://github.com/simstudioai/sim' target='_blank' rel='noopener'>
|
||||
<Github className='h-3 w-3 sm:h-4 sm:w-4' />
|
||||
<span className='hidden sm:inline'>View on GitHub</span>
|
||||
<span className='sm:hidden'>GitHub</span>
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Stats Grid - Mobile: 1 column, Tablet: 2 columns, Desktop: 5 columns */}
|
||||
<div className='mb-6 grid grid-cols-1 gap-3 sm:mb-8 sm:grid-cols-2 sm:gap-4 lg:grid-cols-5'>
|
||||
<div className='rounded-lg border border-[#606060]/20 bg-neutral-800/30 p-3 text-center sm:rounded-xl sm:p-4'>
|
||||
<div className='mb-1 flex items-center justify-center sm:mb-2'>
|
||||
<Star className='h-4 w-4 text-[#701ffc] sm:h-5 sm:w-5' />
|
||||
</div>
|
||||
<div className='font-bold text-lg text-white sm:text-xl'>{repoStats.stars}</div>
|
||||
<div className='text-neutral-400 text-xs'>Stars</div>
|
||||
</div>
|
||||
|
||||
<div className='rounded-lg border border-[#606060]/20 bg-neutral-800/30 p-3 text-center sm:rounded-xl sm:p-4'>
|
||||
<div className='mb-1 flex items-center justify-center sm:mb-2'>
|
||||
<GitFork className='h-4 w-4 text-[#701ffc] sm:h-5 sm:w-5' />
|
||||
</div>
|
||||
<div className='font-bold text-lg text-white sm:text-xl'>{repoStats.forks}</div>
|
||||
<div className='text-neutral-400 text-xs'>Forks</div>
|
||||
</div>
|
||||
|
||||
<div className='rounded-lg border border-[#606060]/20 bg-neutral-800/30 p-3 text-center sm:rounded-xl sm:p-4'>
|
||||
<div className='mb-1 flex items-center justify-center sm:mb-2'>
|
||||
<GitGraph className='h-4 w-4 text-[#701ffc] sm:h-5 sm:w-5' />
|
||||
</div>
|
||||
<div className='font-bold text-lg text-white sm:text-xl'>
|
||||
{filteredContributors?.length || 0}
|
||||
</div>
|
||||
<div className='text-neutral-400 text-xs'>Contributors</div>
|
||||
</div>
|
||||
|
||||
<div className='rounded-lg border border-[#606060]/20 bg-neutral-800/30 p-3 text-center sm:rounded-xl sm:p-4'>
|
||||
<div className='mb-1 flex items-center justify-center sm:mb-2'>
|
||||
<MessageCircle className='h-4 w-4 text-[#701ffc] sm:h-5 sm:w-5' />
|
||||
</div>
|
||||
<div className='font-bold text-lg text-white sm:text-xl'>
|
||||
{repoStats.openIssues}
|
||||
</div>
|
||||
<div className='text-neutral-400 text-xs'>Open Issues</div>
|
||||
</div>
|
||||
|
||||
<div className='rounded-lg border border-[#606060]/20 bg-neutral-800/30 p-3 text-center sm:rounded-xl sm:p-4'>
|
||||
<div className='mb-1 flex items-center justify-center sm:mb-2'>
|
||||
<GitPullRequest className='h-4 w-4 text-[#701ffc] sm:h-5 sm:w-5' />
|
||||
</div>
|
||||
<div className='font-bold text-lg text-white sm:text-xl'>{repoStats.openPRs}</div>
|
||||
<div className='text-neutral-400 text-xs'>Pull Requests</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Activity Chart - Mobile responsive */}
|
||||
<div className='rounded-xl border border-[#606060]/30 bg-[#0f0f0f] p-4 sm:rounded-2xl sm:p-6'>
|
||||
<h3 className='mb-3 font-medium text-base text-white sm:mb-4 sm:text-lg'>
|
||||
Commit Activity
|
||||
</h3>
|
||||
<ResponsiveContainer width='100%' height={150} className='sm:!h-[200px]'>
|
||||
<AreaChart data={timelineData} className='-mx-2 sm:-mx-5 mt-1 sm:mt-2'>
|
||||
<defs>
|
||||
<linearGradient id='commits' x1='0' y1='0' x2='0' y2='1'>
|
||||
<stop offset='5%' stopColor='#701ffc' stopOpacity={0.3} />
|
||||
<stop offset='95%' stopColor='#701ffc' stopOpacity={0} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<XAxis
|
||||
dataKey='date'
|
||||
stroke='currentColor'
|
||||
fontSize={10}
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
className='text-neutral-400 sm:text-xs'
|
||||
interval={4}
|
||||
/>
|
||||
<YAxis
|
||||
stroke='currentColor'
|
||||
fontSize={10}
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
tickFormatter={(value) => `${value}`}
|
||||
className='text-neutral-400 sm:text-xs'
|
||||
width={30}
|
||||
/>
|
||||
<Tooltip
|
||||
content={({ active, payload }) => {
|
||||
if (active && payload && payload.length) {
|
||||
return (
|
||||
<div className='rounded-lg border border-[#606060]/30 bg-[#0f0f0f] p-2 shadow-lg backdrop-blur-sm sm:p-3'>
|
||||
<div className='grid gap-1 sm:gap-2'>
|
||||
<div className='flex items-center gap-1 sm:gap-2'>
|
||||
<GitGraph className='h-3 w-3 text-[#701ffc] sm:h-4 sm:w-4' />
|
||||
<span className='text-neutral-400 text-xs sm:text-sm'>
|
||||
Commits:
|
||||
</span>
|
||||
<span className='font-medium text-white text-xs sm:text-sm'>
|
||||
{payload[0]?.value}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return null
|
||||
}}
|
||||
/>
|
||||
<Area
|
||||
type='monotone'
|
||||
dataKey='commits'
|
||||
stroke='#701ffc'
|
||||
strokeWidth={2}
|
||||
fill='url(#commits)'
|
||||
/>
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contributors Display */}
|
||||
<section className='px-4 py-12 sm:px-8 sm:py-16 md:px-16 lg:px-28 xl:px-32'>
|
||||
<div className='mx-auto max-w-6xl'>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 40 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, amount: 0.2 }}
|
||||
transition={{ duration: 0.7, delay: 0.2 }}
|
||||
>
|
||||
<Tabs defaultValue='grid' className='w-full'>
|
||||
<div className='mb-6 flex justify-center sm:mb-8'>
|
||||
<TabsList className='grid h-full w-full max-w-[300px] grid-cols-2 border border-[#606060]/30 bg-[#0f0f0f] p-1 backdrop-blur-sm sm:w-[200px]'>
|
||||
<TabsTrigger
|
||||
value='grid'
|
||||
className='flex items-center gap-1 text-neutral-400 text-xs data-[state=active]:bg-neutral-700/50 data-[state=active]:text-white data-[state=active]:shadow-sm sm:gap-2 sm:text-sm'
|
||||
>
|
||||
<LayoutGrid className='h-3 w-3 sm:h-4 sm:w-4' />
|
||||
Grid
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
value='chart'
|
||||
className='flex items-center gap-1 text-neutral-400 text-xs data-[state=active]:bg-neutral-700/50 data-[state=active]:text-white data-[state=active]:shadow-sm sm:gap-2 sm:text-sm'
|
||||
>
|
||||
<ChartAreaIcon className='h-3 w-3 sm:h-4 sm:w-4' />
|
||||
Chart
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</div>
|
||||
|
||||
<TabsContent value='grid'>
|
||||
{/* Mobile: 2 columns, Small: 3 columns, Large: 4 columns, XL: 6 columns */}
|
||||
<div className='grid grid-cols-2 gap-3 sm:grid-cols-3 sm:gap-4 lg:grid-cols-4 xl:grid-cols-6'>
|
||||
{filteredContributors?.map((contributor, index) => (
|
||||
<motion.a
|
||||
key={contributor.login}
|
||||
href={contributor.html_url}
|
||||
target='_blank'
|
||||
className='group relative flex flex-col items-center rounded-lg border border-[#606060]/30 bg-[#0f0f0f] p-3 backdrop-blur-sm transition-all hover:bg-neutral-700/50 sm:rounded-xl sm:p-4'
|
||||
whileHover={{ scale: 1.02, y: -2 }}
|
||||
transition={{ type: 'spring', stiffness: 300, damping: 20 }}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
style={{ animationDelay: `${index * 50}ms` }}
|
||||
>
|
||||
<Avatar className='h-12 w-12 ring-2 ring-[#606060]/30 transition-transform group-hover:scale-105 group-hover:ring-[#701ffc]/60 sm:h-16 sm:w-16'>
|
||||
<AvatarImage
|
||||
src={contributor.avatar_url}
|
||||
alt={contributor.login}
|
||||
className='object-cover'
|
||||
/>
|
||||
<AvatarFallback className='bg-[#0f0f0f] text-[10px] sm:text-xs'>
|
||||
{contributor.login.slice(0, 2).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
|
||||
<div className='mt-2 text-center sm:mt-3'>
|
||||
<span className='block font-medium text-white text-xs transition-colors group-hover:text-[#701ffc] sm:text-sm'>
|
||||
{contributor.login.length > 12
|
||||
? `${contributor.login.slice(0, 12)}...`
|
||||
: contributor.login}
|
||||
</span>
|
||||
<div className='mt-1 flex items-center justify-center gap-1 sm:mt-2'>
|
||||
<GitGraph className='h-2 w-2 text-neutral-400 transition-colors group-hover:text-[#701ffc] sm:h-3 sm:w-3' />
|
||||
<span className='font-medium text-neutral-300 text-xs transition-colors group-hover:text-white sm:text-sm'>
|
||||
{contributor.contributions}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</motion.a>
|
||||
))}
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value='chart'>
|
||||
<div className='rounded-2xl border border-[#606060]/30 bg-[#0f0f0f] p-4 backdrop-blur-sm sm:rounded-3xl sm:p-6'>
|
||||
<ChartControls
|
||||
showAll={showAllContributors}
|
||||
setShowAll={setShowAllContributors}
|
||||
total={filteredContributors?.length || 0}
|
||||
/>
|
||||
|
||||
<ResponsiveContainer width='100%' height={300} className='sm:!h-[400px]'>
|
||||
<BarChart
|
||||
data={filteredContributors?.slice(0, showAllContributors ? undefined : 10)}
|
||||
margin={{ top: 10, right: 5, bottom: 50, left: 5 }}
|
||||
className='sm:!mx-2.5 sm:!mb-2.5'
|
||||
>
|
||||
<XAxis
|
||||
dataKey='login'
|
||||
interval={0}
|
||||
tick={(props) => {
|
||||
const { x, y, payload } = props
|
||||
const contributor = allContributors?.find(
|
||||
(c) => c.login === payload.value
|
||||
)
|
||||
|
||||
return (
|
||||
<g transform={`translate(${x},${y})`}>
|
||||
<foreignObject
|
||||
x='-12'
|
||||
y='6'
|
||||
width='24'
|
||||
height='24'
|
||||
className='sm:!x-[-16] sm:!y-[8] sm:!w-[32] sm:!h-[32]'
|
||||
>
|
||||
<Avatar className='h-6 w-6 ring-1 ring-[#606060]/30 sm:h-8 sm:w-8'>
|
||||
<AvatarImage src={contributor?.avatar_url} />
|
||||
<AvatarFallback className='bg-[#0f0f0f] text-[6px] sm:text-[8px]'>
|
||||
{payload.value.slice(0, 2).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
</foreignObject>
|
||||
<text
|
||||
x='0'
|
||||
y='40'
|
||||
textAnchor='middle'
|
||||
className='fill-neutral-400 text-[10px] sm:text-xs'
|
||||
>
|
||||
{payload.value.length > 6
|
||||
? `${payload.value.slice(0, 6)}...`
|
||||
: payload.value}
|
||||
</text>
|
||||
</g>
|
||||
)
|
||||
}}
|
||||
height={60}
|
||||
className='sm:!h-[80px] text-neutral-400'
|
||||
/>
|
||||
<YAxis
|
||||
stroke='currentColor'
|
||||
fontSize={10}
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
tickFormatter={(value) => `${value}`}
|
||||
className='text-neutral-400 sm:text-xs'
|
||||
width={25}
|
||||
/>
|
||||
<Tooltip
|
||||
cursor={{ fill: 'rgb(255 255 255 / 0.05)' }}
|
||||
content={({ active, payload }) => {
|
||||
if (active && payload && payload.length) {
|
||||
const data = payload[0]?.payload
|
||||
return (
|
||||
<div className='rounded-lg border border-[#606060]/30 bg-[#0f0f0f] p-2 shadow-lg backdrop-blur-sm sm:p-3'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Avatar className='h-6 w-6 ring-1 ring-[#606060]/30 sm:h-8 sm:w-8'>
|
||||
<AvatarImage src={data.avatar_url} />
|
||||
<AvatarFallback className='bg-[#0f0f0f] text-[8px] sm:text-xs'>
|
||||
{data.login.slice(0, 2).toUpperCase()}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div>
|
||||
<div className='font-medium text-white text-xs sm:text-sm'>
|
||||
{data.login}
|
||||
</div>
|
||||
<div className='flex items-center gap-1 text-[10px] text-neutral-400 sm:text-xs'>
|
||||
<GitGraph className='h-2 w-2 sm:h-3 sm:w-3' />
|
||||
<span>{data.contributions} commits</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return null
|
||||
}}
|
||||
/>
|
||||
<Bar
|
||||
dataKey='contributions'
|
||||
className='fill-[#701ffc]'
|
||||
radius={[4, 4, 0, 0]}
|
||||
/>
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Call to Action */}
|
||||
<section className='px-4 py-8 sm:px-8 sm:py-10 md:px-16 md:py-16 lg:px-28 xl:px-32'>
|
||||
<div className='mx-auto max-w-6xl'>
|
||||
<motion.div
|
||||
className='relative overflow-hidden rounded-2xl border border-[#606060]/30 bg-[#0f0f0f] sm:rounded-3xl'
|
||||
initial={{ opacity: 0, y: 40 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, amount: 0.2 }}
|
||||
transition={{ duration: 0.7, delay: 0.3 }}
|
||||
>
|
||||
<div className='relative p-6 sm:p-8 md:p-12 lg:p-16'>
|
||||
<div className='text-center'>
|
||||
<div className='mb-4 inline-flex items-center rounded-full border border-[#701ffc]/20 bg-[#701ffc]/10 px-3 py-1 font-medium text-[#701ffc] text-xs sm:mb-6 sm:px-4 sm:py-2 sm:text-sm'>
|
||||
<Github className='mr-1 h-3 w-3 sm:mr-2 sm:h-4 sm:w-4' />
|
||||
Apache-2.0 Licensed
|
||||
</div>
|
||||
|
||||
<h3 className='font-medium text-2xl text-white leading-[1.1] tracking-tight sm:text-[42px] md:text-5xl'>
|
||||
Want to contribute?
|
||||
</h3>
|
||||
|
||||
<p className='mx-auto mt-3 max-w-2xl font-light text-base text-neutral-400 sm:mt-4 sm:text-xl'>
|
||||
Whether you're fixing bugs, adding features, or improving documentation,
|
||||
every contribution helps build the future of AI workflows.
|
||||
</p>
|
||||
|
||||
<div className='mt-6 flex flex-col gap-3 sm:mt-8 sm:flex-row sm:flex-wrap sm:justify-center sm:gap-4'>
|
||||
<Button
|
||||
asChild
|
||||
size='lg'
|
||||
className='bg-[#701ffc] text-white transition-colors duration-500 hover:bg-[#802FFF]'
|
||||
>
|
||||
<a
|
||||
href='https://github.com/simstudioai/sim/blob/main/.github/CONTRIBUTING.md'
|
||||
target='_blank'
|
||||
rel='noopener'
|
||||
>
|
||||
<GitGraph className='mr-2 h-4 w-4 sm:h-5 sm:w-5' />
|
||||
Start Contributing
|
||||
</a>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
asChild
|
||||
variant='outline'
|
||||
size='lg'
|
||||
className='border-[#606060]/30 bg-transparent text-neutral-300 transition-colors duration-500 hover:bg-neutral-700/50 hover:text-white'
|
||||
>
|
||||
<a href='https://github.com/simstudioai/sim' target='_blank' rel='noopener'>
|
||||
<Github className='mr-2 h-4 w-4 sm:h-5 sm:w-5' />
|
||||
View Repository
|
||||
</a>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
asChild
|
||||
variant='outline'
|
||||
size='lg'
|
||||
className='border-[#606060]/30 bg-transparent text-neutral-300 transition-colors duration-500 hover:bg-neutral-700/50 hover:text-white'
|
||||
>
|
||||
<a
|
||||
href='https://github.com/simstudioai/sim/issues'
|
||||
target='_blank'
|
||||
rel='noopener'
|
||||
>
|
||||
<MessageCircle className='mr-2 h-4 w-4 sm:h-5 sm:w-5' />
|
||||
Open Issues
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{/* Footer */}
|
||||
<Footer />
|
||||
</main>
|
||||
)
|
||||
}
|
||||
100
apps/sim/app/(landing)/utils/github.ts
Normal file
100
apps/sim/app/(landing)/utils/github.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
interface RepoStats {
|
||||
stars: number
|
||||
forks: number
|
||||
watchers: number
|
||||
openIssues: number
|
||||
openPRs: number
|
||||
}
|
||||
|
||||
interface CommitTimelineData {
|
||||
date: string
|
||||
commits: number
|
||||
additions: number
|
||||
deletions: number
|
||||
}
|
||||
|
||||
interface ActivityData {
|
||||
date: string
|
||||
commits: number
|
||||
issues: number
|
||||
pullRequests: number
|
||||
}
|
||||
|
||||
interface CommitData {
|
||||
sha: string
|
||||
commit: {
|
||||
author: {
|
||||
name: string
|
||||
email: string
|
||||
date: string
|
||||
}
|
||||
message: string
|
||||
}
|
||||
html_url: string
|
||||
stats?: {
|
||||
additions: number
|
||||
deletions: number
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate commit timeline data for the last 30 days using real commit data
|
||||
*/
|
||||
export function generateCommitTimelineData(commitsData: CommitData[]): CommitTimelineData[] {
|
||||
return Array.from({ length: 30 }, (_, i) => {
|
||||
const date = new Date()
|
||||
date.setDate(date.getDate() - (29 - i))
|
||||
const dateStr = date.toISOString().split('T')[0]
|
||||
|
||||
const dayCommits = commitsData.filter((commit) => commit.commit.author.date.startsWith(dateStr))
|
||||
|
||||
const stats = dayCommits.reduce(
|
||||
(acc, commit) => {
|
||||
if (commit.stats) {
|
||||
acc.additions += commit.stats.additions || 0
|
||||
acc.deletions += commit.stats.deletions || 0
|
||||
}
|
||||
return acc
|
||||
},
|
||||
{ additions: 0, deletions: 0 }
|
||||
)
|
||||
|
||||
return {
|
||||
date: date.toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
}),
|
||||
commits: dayCommits.length,
|
||||
additions: stats.additions,
|
||||
deletions: stats.deletions,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate activity data for the last 7 days using actual commit data
|
||||
*/
|
||||
export function generateActivityData(
|
||||
commitsData: CommitData[],
|
||||
repoStats?: RepoStats
|
||||
): ActivityData[] {
|
||||
return Array.from({ length: 7 }, (_, i) => {
|
||||
const date = new Date()
|
||||
const today = date.getDay()
|
||||
const daysToSubtract = today + (6 - i)
|
||||
date.setDate(date.getDate() - daysToSubtract)
|
||||
|
||||
const dateStr = date.toISOString().split('T')[0]
|
||||
|
||||
const dayCommits = commitsData.filter((commit) =>
|
||||
commit.commit.author.date.startsWith(dateStr)
|
||||
).length
|
||||
|
||||
return {
|
||||
date: date.toLocaleDateString('en-US', { weekday: 'short' }),
|
||||
commits: dayCommits,
|
||||
issues: repoStats ? Math.floor(repoStats.openIssues / 7) : 0,
|
||||
pullRequests: repoStats ? Math.floor(repoStats.openPRs / 7) : 0,
|
||||
}
|
||||
})
|
||||
}
|
||||
133
apps/sim/app/(landing)/utils/prefetch.ts
Normal file
133
apps/sim/app/(landing)/utils/prefetch.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
// Utility for prefetching and caching contributors page data
|
||||
import { getCommitsData, getContributors, getRepositoryStats } from '../actions/github'
|
||||
import { generateActivityData, generateCommitTimelineData } from './github'
|
||||
|
||||
interface Contributor {
|
||||
login: string
|
||||
avatar_url: string
|
||||
contributions: number
|
||||
html_url: string
|
||||
}
|
||||
|
||||
interface RepoStats {
|
||||
stars: number
|
||||
forks: number
|
||||
watchers: number
|
||||
openIssues: number
|
||||
openPRs: number
|
||||
}
|
||||
|
||||
interface CommitTimelineData {
|
||||
date: string
|
||||
commits: number
|
||||
additions: number
|
||||
deletions: number
|
||||
}
|
||||
|
||||
interface ActivityData {
|
||||
date: string
|
||||
commits: number
|
||||
issues: number
|
||||
pullRequests: number
|
||||
}
|
||||
|
||||
interface ContributorsPageData {
|
||||
contributors: Contributor[]
|
||||
repoStats: RepoStats
|
||||
timelineData: CommitTimelineData[]
|
||||
activityData: ActivityData[]
|
||||
}
|
||||
|
||||
// Debounce utility function
|
||||
function debounce<T extends (...args: any[]) => any>(
|
||||
func: T,
|
||||
wait: number
|
||||
): (...args: Parameters<T>) => void {
|
||||
let timeout: NodeJS.Timeout | null = null
|
||||
return (...args: Parameters<T>) => {
|
||||
if (timeout) clearTimeout(timeout)
|
||||
timeout = setTimeout(() => func(...args), wait)
|
||||
}
|
||||
}
|
||||
|
||||
// Cache for the prefetched data
|
||||
let cachedData: ContributorsPageData | null = null
|
||||
let isPreFetching = false
|
||||
let prefetchPromise: Promise<ContributorsPageData> | null = null
|
||||
|
||||
// Create a debounced version of the prefetch function
|
||||
const debouncedPrefetchContributorsData = debounce(() => {
|
||||
prefetchContributorsData().catch((err: unknown) => {
|
||||
console.error('Failed to prefetch contributors data:', err)
|
||||
})
|
||||
}, 100)
|
||||
|
||||
/**
|
||||
* Debounced prefetch function for use in hover handlers
|
||||
* Only triggers after 100ms of stable hover to prevent rapid API calls
|
||||
*/
|
||||
export function usePrefetchOnHover(): () => void {
|
||||
return debouncedPrefetchContributorsData
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefetch contributors page data
|
||||
*/
|
||||
export async function prefetchContributorsData(): Promise<ContributorsPageData> {
|
||||
// If data is already cached, return it
|
||||
if (cachedData) {
|
||||
return cachedData
|
||||
}
|
||||
|
||||
// If already prefetching, return the existing promise
|
||||
if (isPreFetching && prefetchPromise) {
|
||||
return prefetchPromise
|
||||
}
|
||||
|
||||
// Start prefetching
|
||||
prefetchPromise = fetchContributorsData()
|
||||
isPreFetching = true
|
||||
|
||||
try {
|
||||
const data = await prefetchPromise
|
||||
cachedData = data
|
||||
return data
|
||||
} finally {
|
||||
isPreFetching = false
|
||||
prefetchPromise = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached contributors data if available
|
||||
*/
|
||||
export function getCachedContributorsData(): ContributorsPageData | null {
|
||||
return cachedData
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cached data (useful for refreshing)
|
||||
*/
|
||||
export function clearContributorsCache(): void {
|
||||
cachedData = null
|
||||
isPreFetching = false
|
||||
prefetchPromise = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function to fetch all contributors data
|
||||
*/
|
||||
async function fetchContributorsData(): Promise<ContributorsPageData> {
|
||||
const [contributors, stats, commits] = await Promise.all([
|
||||
getContributors(),
|
||||
getRepositoryStats(),
|
||||
getCommitsData(),
|
||||
])
|
||||
|
||||
return {
|
||||
contributors,
|
||||
repoStats: stats,
|
||||
timelineData: generateCommitTimelineData(commits),
|
||||
activityData: generateActivityData(commits),
|
||||
}
|
||||
}
|
||||
46
apps/sim/components/ui/avatar.tsx
Normal file
46
apps/sim/components/ui/avatar.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import * as AvatarPrimitive from '@radix-ui/react-avatar'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const Avatar = React.forwardRef<
|
||||
React.ElementRef<typeof AvatarPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AvatarPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn('relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Avatar.displayName = AvatarPrimitive.Root.displayName
|
||||
|
||||
const AvatarImage = React.forwardRef<
|
||||
React.ElementRef<typeof AvatarPrimitive.Image>,
|
||||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AvatarPrimitive.Image
|
||||
ref={ref}
|
||||
className={cn('aspect-square h-full w-full', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AvatarImage.displayName = AvatarPrimitive.Image.displayName
|
||||
|
||||
const AvatarFallback = React.forwardRef<
|
||||
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
||||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AvatarPrimitive.Fallback
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'flex h-full w-full items-center justify-center rounded-full bg-muted',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
|
||||
|
||||
export { Avatar, AvatarImage, AvatarFallback }
|
||||
@@ -138,7 +138,7 @@ const nextConfig: NextConfig = {
|
||||
},
|
||||
{
|
||||
key: 'Content-Security-Policy',
|
||||
value: `default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.google.com https://apis.google.com https://*.vercel-scripts.com https://*.vercel-insights.com https://vercel.live https://*.vercel.live https://vercel.com https://*.vercel.app; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https://*.googleusercontent.com https://*.google.com https://*.atlassian.com https://cdn.discordapp.com; media-src 'self' blob:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' ${env.OLLAMA_URL || 'http://localhost:11434'} https://api.browser-use.com https://*.googleapis.com https://*.amazonaws.com https://*.s3.amazonaws.com https://*.vercel-insights.com https://*.atlassian.com https://vercel.live https://*.vercel.live https://vercel.com https://*.vercel.app; frame-src https://drive.google.com https://*.google.com; frame-ancestors 'self'; form-action 'self'; base-uri 'self'; object-src 'none'`,
|
||||
value: `default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.google.com https://apis.google.com https://*.vercel-scripts.com https://*.vercel-insights.com https://vercel.live https://*.vercel.live https://vercel.com https://*.vercel.app; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https://*.googleusercontent.com https://*.google.com https://*.atlassian.com https://cdn.discordapp.com https://*.githubusercontent.com; media-src 'self' blob:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' ${env.OLLAMA_URL || 'http://localhost:11434'} https://api.browser-use.com https://*.googleapis.com https://*.amazonaws.com https://*.s3.amazonaws.com https://*.vercel-insights.com https://*.atlassian.com https://vercel.live https://*.vercel.live https://vercel.com https://*.vercel.app; frame-src https://drive.google.com https://*.google.com; frame-ancestors 'self'; form-action 'self'; base-uri 'self'; object-src 'none'`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
"@opentelemetry/sdk-trace-web": "^2.0.0",
|
||||
"@opentelemetry/semantic-conventions": "^1.32.0",
|
||||
"@radix-ui/react-alert-dialog": "^1.1.5",
|
||||
"@radix-ui/react-avatar": "1.1.10",
|
||||
"@radix-ui/react-checkbox": "^1.1.3",
|
||||
"@radix-ui/react-collapsible": "^1.1.3",
|
||||
"@radix-ui/react-dialog": "^1.1.5",
|
||||
@@ -98,6 +99,7 @@
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-simple-code-editor": "^0.14.1",
|
||||
"reactflow": "^11.11.4",
|
||||
"recharts": "2.15.3",
|
||||
"resend": "^4.1.2",
|
||||
"stripe": "^17.7.0",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
|
||||
64
bun.lock
64
bun.lock
@@ -73,6 +73,7 @@
|
||||
"@opentelemetry/sdk-trace-web": "^2.0.0",
|
||||
"@opentelemetry/semantic-conventions": "^1.32.0",
|
||||
"@radix-ui/react-alert-dialog": "^1.1.5",
|
||||
"@radix-ui/react-avatar": "1.1.10",
|
||||
"@radix-ui/react-checkbox": "^1.1.3",
|
||||
"@radix-ui/react-collapsible": "^1.1.3",
|
||||
"@radix-ui/react-dialog": "^1.1.5",
|
||||
@@ -129,6 +130,7 @@
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-simple-code-editor": "^0.14.1",
|
||||
"reactflow": "^11.11.4",
|
||||
"recharts": "2.15.3",
|
||||
"resend": "^4.1.2",
|
||||
"stripe": "^17.7.0",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
@@ -745,6 +747,8 @@
|
||||
|
||||
"@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.6", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-2JMfHJf/eVnwq+2dewT3C0acmCWD3XiVA1Da+jTDqo342UlU13WvXtqHhG+yJw5JeQmu4ue2eMy6gcEArLBlcw=="],
|
||||
|
||||
"@radix-ui/react-avatar": ["@radix-ui/react-avatar@1.1.10", "", { "dependencies": { "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog=="],
|
||||
|
||||
"@radix-ui/react-checkbox": ["@radix-ui/react-checkbox@1.3.1", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.2", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-xTaLKAO+XXMPK/BpVTSaAAhlefmvMSACjIhK9mGsImvX2ljcTDm8VGR1CuS1uYcNdR5J+oiOhoJZc5un6bh3VQ=="],
|
||||
|
||||
"@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.2", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-O2mcG3gZNkJ/Ena34HurA3llPOEA/M4dJtIRMa6y/cknRDC8XY5UZBInKTsUwW5cUue9A4k0wi1XU5fKBzKe1w=="],
|
||||
@@ -817,6 +821,8 @@
|
||||
|
||||
"@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="],
|
||||
|
||||
"@radix-ui/react-use-is-hydrated": ["@radix-ui/react-use-is-hydrated@0.1.0", "", { "dependencies": { "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA=="],
|
||||
|
||||
"@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
|
||||
|
||||
"@radix-ui/react-use-previous": ["@radix-ui/react-use-previous@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ=="],
|
||||
@@ -1597,6 +1603,8 @@
|
||||
|
||||
"csv-parser": ["csv-parser@3.2.0", "", { "bin": { "csv-parser": "bin/csv-parser" } }, "sha512-fgKbp+AJbn1h2dcAHKIdKNSSjfp43BZZykXsCjzALjKy80VXQNHPFJ6T9Afwdzoj24aMkq8GwDS7KGcDPpejrA=="],
|
||||
|
||||
"d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="],
|
||||
|
||||
"d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="],
|
||||
|
||||
"d3-dispatch": ["d3-dispatch@3.0.1", "", {}, "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="],
|
||||
@@ -1605,10 +1613,22 @@
|
||||
|
||||
"d3-ease": ["d3-ease@3.0.1", "", {}, "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="],
|
||||
|
||||
"d3-format": ["d3-format@3.1.0", "", {}, "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA=="],
|
||||
|
||||
"d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="],
|
||||
|
||||
"d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="],
|
||||
|
||||
"d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="],
|
||||
|
||||
"d3-selection": ["d3-selection@3.0.0", "", {}, "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ=="],
|
||||
|
||||
"d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="],
|
||||
|
||||
"d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="],
|
||||
|
||||
"d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="],
|
||||
|
||||
"d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="],
|
||||
|
||||
"d3-transition": ["d3-transition@3.0.1", "", { "dependencies": { "d3-color": "1 - 3", "d3-dispatch": "1 - 3", "d3-ease": "1 - 3", "d3-interpolate": "1 - 3", "d3-timer": "1 - 3" }, "peerDependencies": { "d3-selection": "2 - 3" } }, "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w=="],
|
||||
@@ -1627,6 +1647,8 @@
|
||||
|
||||
"decimal.js": ["decimal.js@10.5.0", "", {}, "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw=="],
|
||||
|
||||
"decimal.js-light": ["decimal.js-light@2.5.1", "", {}, "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="],
|
||||
|
||||
"decode-named-character-reference": ["decode-named-character-reference@1.1.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w=="],
|
||||
|
||||
"deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="],
|
||||
@@ -1663,6 +1685,8 @@
|
||||
|
||||
"dom-accessibility-api": ["dom-accessibility-api@0.6.3", "", {}, "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w=="],
|
||||
|
||||
"dom-helpers": ["dom-helpers@5.2.1", "", { "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" } }, "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA=="],
|
||||
|
||||
"dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="],
|
||||
|
||||
"domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
|
||||
@@ -1761,7 +1785,7 @@
|
||||
|
||||
"event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
|
||||
|
||||
"eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="],
|
||||
"eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="],
|
||||
|
||||
"events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="],
|
||||
|
||||
@@ -1777,6 +1801,8 @@
|
||||
|
||||
"fast-deep-equal": ["fast-deep-equal@2.0.1", "", {}, "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w=="],
|
||||
|
||||
"fast-equals": ["fast-equals@5.2.2", "", {}, "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw=="],
|
||||
|
||||
"fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
|
||||
|
||||
"fast-redact": ["fast-redact@3.5.0", "", {}, "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A=="],
|
||||
@@ -1941,6 +1967,8 @@
|
||||
|
||||
"inquirer": ["inquirer@8.2.6", "", { "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.1", "cli-cursor": "^3.1.0", "cli-width": "^3.0.0", "external-editor": "^3.0.3", "figures": "^3.0.0", "lodash": "^4.17.21", "mute-stream": "0.0.8", "ora": "^5.4.1", "run-async": "^2.4.0", "rxjs": "^7.5.5", "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6", "wrap-ansi": "^6.0.1" } }, "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg=="],
|
||||
|
||||
"internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="],
|
||||
|
||||
"ioredis": ["ioredis@5.6.1", "", { "dependencies": { "@ioredis/commands": "^1.1.1", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-UxC0Yv1Y4WRJiGQxQkP0hfdL0/5/6YvdfOOClRgJ0qppSarkhneSa6UvkMkms0AkdGimSH3Ikqm+6mkMmX7vGA=="],
|
||||
|
||||
"is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="],
|
||||
@@ -2105,6 +2133,8 @@
|
||||
|
||||
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
|
||||
|
||||
"loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
|
||||
|
||||
"lop": ["lop@0.4.2", "", { "dependencies": { "duck": "^0.1.12", "option": "~0.2.1", "underscore": "^1.13.1" } }, "sha512-RefILVDQ4DKoRZsJ4Pj22TxE3omDO47yFpkIBoDKzkqPRISs5U1cnAdg/5583YPkWPaLIYHOKRMQSvjFsO26cw=="],
|
||||
|
||||
"loupe": ["loupe@3.1.3", "", {}, "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug=="],
|
||||
@@ -2457,6 +2487,8 @@
|
||||
|
||||
"progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="],
|
||||
|
||||
"prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
|
||||
|
||||
"property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
|
||||
|
||||
"protobufjs": ["protobufjs@7.5.2", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-f2ls6rpO6G153Cy+o2XQ+Y0sARLOZ17+OGVLHrc3VUKcLHYKEKWbkSujdBWQXM7gKn5NTfp0XnRPZn1MIu8n9w=="],
|
||||
@@ -2493,7 +2525,7 @@
|
||||
|
||||
"react-hook-form": ["react-hook-form@7.56.4", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-Rob7Ftz2vyZ/ZGsQZPaRdIefkgOSrQSPXfqBdvOPwJfoGnjwRJUs7EM7Kc1mcoDv3NOtqBzPGbcMB8CGn9CKgw=="],
|
||||
|
||||
"react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
|
||||
"react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
||||
|
||||
"react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="],
|
||||
|
||||
@@ -2509,8 +2541,12 @@
|
||||
|
||||
"react-simple-code-editor": ["react-simple-code-editor@0.14.1", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-BR5DtNRy+AswWJECyA17qhUDvrrCZ6zXOCfkQY5zSmb96BVUbpVAv03WpcjcwtCwiLbIANx3gebHOcXYn1EHow=="],
|
||||
|
||||
"react-smooth": ["react-smooth@4.0.4", "", { "dependencies": { "fast-equals": "^5.0.1", "prop-types": "^15.8.1", "react-transition-group": "^4.4.5" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q=="],
|
||||
|
||||
"react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
|
||||
|
||||
"react-transition-group": ["react-transition-group@4.4.5", "", { "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", "loose-envify": "^1.4.0", "prop-types": "^15.6.2" }, "peerDependencies": { "react": ">=16.6.0", "react-dom": ">=16.6.0" } }, "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g=="],
|
||||
|
||||
"reactflow": ["reactflow@11.11.4", "", { "dependencies": { "@reactflow/background": "11.3.14", "@reactflow/controls": "11.2.14", "@reactflow/core": "11.11.4", "@reactflow/minimap": "11.7.14", "@reactflow/node-resizer": "2.2.14", "@reactflow/node-toolbar": "1.3.14" }, "peerDependencies": { "react": ">=17", "react-dom": ">=17" } }, "sha512-70FOtJkUWH3BAOsN+LU9lCrKoKbtOPnz2uq0CV2PLdNSwxTXOhCbsZr50GmZ+Rtw3jx8Uv7/vBFtCGixLfd4Og=="],
|
||||
|
||||
"read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="],
|
||||
@@ -2521,6 +2557,10 @@
|
||||
|
||||
"real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="],
|
||||
|
||||
"recharts": ["recharts@2.15.3", "", { "dependencies": { "clsx": "^2.0.0", "eventemitter3": "^4.0.1", "lodash": "^4.17.21", "react-is": "^18.3.1", "react-smooth": "^4.0.4", "recharts-scale": "^0.4.4", "tiny-invariant": "^1.3.1", "victory-vendor": "^36.6.8" }, "peerDependencies": { "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-EdOPzTwcFSuqtvkDoaM5ws/Km1+WTAO2eizL7rqiG0V2UVhTnz0m7J2i0CjVPUCdEkZImaWvXLbZDS2H5t6GFQ=="],
|
||||
|
||||
"recharts-scale": ["recharts-scale@0.4.5", "", { "dependencies": { "decimal.js-light": "^2.4.1" } }, "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w=="],
|
||||
|
||||
"recma-build-jsx": ["recma-build-jsx@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-build-jsx": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew=="],
|
||||
|
||||
"recma-jsx": ["recma-jsx@1.0.0", "", { "dependencies": { "acorn-jsx": "^5.0.0", "estree-util-to-js": "^2.0.0", "recma-parse": "^1.0.0", "recma-stringify": "^1.0.0", "unified": "^11.0.0" } }, "sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q=="],
|
||||
@@ -2759,6 +2799,8 @@
|
||||
|
||||
"tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="],
|
||||
|
||||
"tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
|
||||
|
||||
"tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
|
||||
|
||||
"tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
|
||||
@@ -2863,6 +2905,8 @@
|
||||
|
||||
"vfile-message": ["vfile-message@4.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw=="],
|
||||
|
||||
"victory-vendor": ["victory-vendor@36.9.2", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ=="],
|
||||
|
||||
"vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="],
|
||||
|
||||
"vite-node": ["vite-node@3.1.3", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-uHV4plJ2IxCl4u1up1FQRrqclylKAogbtBfOTwcuJ28xFi+89PZ57BRh+naIRvH70HPwxy5QHYzg1OrEaC7AbA=="],
|
||||
@@ -3151,6 +3195,8 @@
|
||||
|
||||
"@prisma/instrumentation/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.57.2", "", { "dependencies": { "@opentelemetry/api-logs": "0.57.2", "@types/shimmer": "^1.2.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", "semver": "^7.5.2", "shimmer": "^1.2.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg=="],
|
||||
|
||||
"@radix-ui/react-avatar/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
|
||||
|
||||
"@react-email/code-block/prismjs": ["prismjs@1.29.0", "", {}, "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q=="],
|
||||
|
||||
"@react-email/render/prettier": ["prettier@3.4.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ=="],
|
||||
@@ -3287,6 +3333,8 @@
|
||||
|
||||
"lint-staged/listr2": ["listr2@8.3.3", "", { "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ=="],
|
||||
|
||||
"listr2/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="],
|
||||
|
||||
"listr2/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
|
||||
|
||||
"log-update/ansi-escapes": ["ansi-escapes@5.0.0", "", { "dependencies": { "type-fest": "^1.0.2" } }, "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA=="],
|
||||
@@ -3331,6 +3379,10 @@
|
||||
|
||||
"pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
|
||||
|
||||
"pretty-format/react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
|
||||
|
||||
"prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||
|
||||
"protobufjs/long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
||||
|
||||
"react-day-picker/date-fns": ["date-fns@3.6.0", "", {}, "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww=="],
|
||||
@@ -3527,6 +3579,8 @@
|
||||
|
||||
"@prisma/instrumentation/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.57.2", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A=="],
|
||||
|
||||
"@radix-ui/react-avatar/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
||||
|
||||
"@sentry/bundler-plugin-core/glob/minimatch": ["minimatch@8.0.4", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA=="],
|
||||
|
||||
"@sentry/bundler-plugin-core/glob/minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="],
|
||||
@@ -3543,6 +3597,8 @@
|
||||
|
||||
"@sentry/node/@opentelemetry/sdk-trace-base/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="],
|
||||
|
||||
"@types/jest/pretty-format/react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
|
||||
|
||||
"accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||
|
||||
"cli-truncate/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||
@@ -3561,8 +3617,12 @@
|
||||
|
||||
"inquirer/ora/log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="],
|
||||
|
||||
"jest-diff/pretty-format/react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
|
||||
|
||||
"lint-staged/listr2/cli-truncate": ["cli-truncate@4.0.0", "", { "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" } }, "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA=="],
|
||||
|
||||
"lint-staged/listr2/eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="],
|
||||
|
||||
"lint-staged/listr2/log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="],
|
||||
|
||||
"lint-staged/listr2/wrap-ansi": ["wrap-ansi@9.0.0", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q=="],
|
||||
|
||||
Reference in New Issue
Block a user