jsDelivr Package Stats Example 02

PreviousNext

Display jsDelivr packages from a provided namespace and package names with real-time stats, rankings, and bandwidth usage.

Docs
phucbmcomponent

Preview

Loading preview…
registry/phucbm/blocks/jsdelivr/example-02.transformed.tsx
'use client'

import { useEffect, useState } from 'react'
import { JsDelivrPackages, JsDelivrPackage } from '@/components/phucbm/jsdelivr'
import { getPublicGithubRepos } from '@/registry/phucbm/lib/getPublicGithubRepos'
import { getJsDelivrPackages } from '@/lib/getJsDelivrPackages'

export default function Example02() {
    const [username, setUsername] = useState('phucbm')
    const [packages, setPackages] = useState<JsDelivrPackage[]>([])
    const [loading, setLoading] = useState(false)
    const [error, setError] = useState<string | null>(null)
    const [reposFound, setReposFound] = useState(0)
    const [packagesFound, setPackagesFound] = useState(0)

    useEffect(() => {
        // Debounce timer
        const timer = setTimeout(async () => {
            if (!username.trim()) {
                setPackages([])
                setReposFound(0)
                setPackagesFound(0)
                setError(null)
                return
            }

            setLoading(true)
            setError(null)
            setPackages([])

            try {
                // Fetch public repos from GitHub
                const repos = await getPublicGithubRepos(username, 50, 36)
                setReposFound(repos.length)

                if (repos.length === 0) {
                    setPackagesFound(0)
                    setLoading(false)
                    return
                }

                // Extract package names from repo names
                const packageNames = repos.map((repo: any) => repo.name)

                // Fetch jsDelivr stats for those packages
                // Only show packages with actual hits (minHits: 1)
                const jsDelivrPackages = await getJsDelivrPackages(packageNames, username, 'month', 1)
                setPackagesFound(jsDelivrPackages.length)
                setPackages(jsDelivrPackages)
            } catch (err) {
                setError(err instanceof Error ? err.message : 'Failed to load packages')
                setPackagesFound(0)
            } finally {
                setLoading(false)
            }
        }, 1000) // 1 second debounce

        return () => clearTimeout(timer)
    }, [username])

    return (
        <div className="bg-slate-50">
            {/* Sticky Header */}
            <div className="sticky top-0 bg-white border-b border-slate-200 p-4 z-10">
                <div className="flex items-end gap-4">
                    {/* Input Section */}
                    <div className="flex-1 relative">
                        <label className="text-xs font-semibold text-slate-700 block mb-1">GitHub Username</label>
                        <input
                            type="text"
                            value={username}
                            onChange={(e) => setUsername(e.target.value)}
                            placeholder="Enter username..."
                            className="w-full px-3 py-2 text-sm border border-slate-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
                        />
                        <p className="text-xs text-slate-500 mt-1">
                            Shows repos with CDN downloads on jsDelivr
                        </p>

                        {/* Loading Indicator - Absolute to prevent CLS */}
                        {loading && (
                            <div className="absolute right-3 top-8 text-slate-500 text-xs whitespace-nowrap">
                                Loading...
                            </div>
                        )}
                    </div>

                    {/* Stats Section */}
                    {(reposFound > 0 || packagesFound > 0) && (
                        <div className="flex gap-3">
                            <div className="bg-blue-50 px-3 py-2 rounded border border-blue-200">
                                <p className="text-blue-600 font-semibold text-sm">{reposFound}</p>
                                <p className="text-blue-700 text-xs whitespace-nowrap">Repos</p>
                            </div>
                            <div className="bg-green-50 px-3 py-2 rounded border border-green-200">
                                <p className="text-green-600 font-semibold text-sm">{packagesFound}</p>
                                <p className="text-green-700 text-xs whitespace-nowrap">Downloads</p>
                            </div>
                        </div>
                    )}
                </div>
            </div>

            {/* Scrollable Content */}
            <div className="flex-1 p-6 space-y-4">
                {/* Error State */}
                {error && (
                    <div className="bg-red-50 border border-red-200 rounded p-4">
                        <p className="text-red-600 text-sm font-semibold">Error</p>
                        <p className="text-red-700 text-sm">{error}</p>
                    </div>
                )}

                {/* Results Section */}
                {!loading && !error && packages.length > 0 && (
                    <div className="space-y-4">
                        <div className="text-sm font-semibold text-slate-700">
                            jsDelivr Packages ({packages.length})
                        </div>
                        <JsDelivrPackages packages={packages} statsPeriod="month" showBandwidth={true} />
                    </div>
                )}

                {/* No Results */}
                {!loading && !error && reposFound > 0 && packages.length === 0 && (
                    <div className="bg-yellow-50 border border-yellow-200 rounded p-4">
                        <p className="text-yellow-700 text-sm">
                            Found {reposFound} repositories, but none have actual CDN downloads on jsDelivr.
                            Repos need distributed files and active downloads to appear here.
                        </p>
                    </div>
                )}

                {/* Empty State */}
                {!loading && !error && reposFound === 0 && username.trim() && (
                    <div className="bg-slate-100 border border-slate-300 rounded p-4">
                        <p className="text-slate-600 text-sm">
                            No public repositories found for "{username}"
                        </p>
                    </div>
                )}
            </div>
        </div>
    )
}

Installation

npx shadcn@latest add @phucbm/jsdelivr-example-02

Usage

import { JsdelivrExample02 } from "@/components/jsdelivr-example-02"
<JsdelivrExample02 />