From 43c516a005c31f263dcedab144ee5ce26dd85b88 Mon Sep 17 00:00:00 2001 From: Arkaprabha Chakraborty Date: Sun, 14 Dec 2025 05:33:05 +0530 Subject: [PATCH] overhaul --- backend/.gitignore | 11 + backend/Dockerfile | 24 +- backend/go.mod | 15 +- backend/go.sum | 20 +- backend/main.go | 97 ++-- backend/store.go | 34 ++ database/Dockerfile | 4 - docker-compose.yml | 25 +- frontend/.eslintrc.json | 3 - frontend/.gitignore | 43 +- frontend/Dockerfile | 21 +- frontend/README.md | 43 +- frontend/app/api/redirect/[id]/route.js | 22 - frontend/app/error/page.js | 25 - frontend/app/favicon.ico | Bin 15406 -> 0 bytes frontend/app/globals.css | 33 -- frontend/app/layout.js | 62 --- frontend/app/page.js | 116 ----- frontend/bun.lock | 581 ++++++++++++++++++++++++ frontend/index.html | 13 + frontend/jsconfig.json | 7 - frontend/next.config.mjs | 14 - frontend/package.json | 41 +- frontend/postcss.config.js | 6 + frontend/postcss.config.mjs | 8 - frontend/public/next.svg | 1 - frontend/public/og-image.png | Bin 21249 -> 0 bytes frontend/public/vercel.svg | 1 - frontend/src/App.tsx | 16 + frontend/src/index.css | 9 + frontend/src/main.tsx | 10 + frontend/src/pages/Home.tsx | 138 ++++++ frontend/src/pages/Redirect.tsx | 62 +++ frontend/src/vite-env.d.ts | 1 + frontend/tailwind.config.js | 23 +- frontend/tsconfig.json | 20 + frontend/vite.config.ts | 11 + 37 files changed, 1037 insertions(+), 523 deletions(-) create mode 100644 backend/.gitignore create mode 100644 backend/store.go delete mode 100644 database/Dockerfile delete mode 100644 frontend/.eslintrc.json delete mode 100644 frontend/app/api/redirect/[id]/route.js delete mode 100644 frontend/app/error/page.js delete mode 100644 frontend/app/favicon.ico delete mode 100644 frontend/app/globals.css delete mode 100644 frontend/app/layout.js delete mode 100644 frontend/app/page.js create mode 100644 frontend/bun.lock create mode 100644 frontend/index.html delete mode 100644 frontend/jsconfig.json delete mode 100644 frontend/next.config.mjs create mode 100644 frontend/postcss.config.js delete mode 100644 frontend/postcss.config.mjs delete mode 100644 frontend/public/next.svg delete mode 100644 frontend/public/og-image.png delete mode 100644 frontend/public/vercel.svg create mode 100644 frontend/src/App.tsx create mode 100644 frontend/src/index.css create mode 100644 frontend/src/main.tsx create mode 100644 frontend/src/pages/Home.tsx create mode 100644 frontend/src/pages/Redirect.tsx create mode 100644 frontend/src/vite-env.d.ts create mode 100644 frontend/tsconfig.json create mode 100644 frontend/vite.config.ts diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 0000000..812b73c --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1,11 @@ +# Go +bin/ +pkg/ +*.exe +*.dll +*.so +*.test +*.prof +.env +# Local database (if applicable) +reduce.db diff --git a/backend/Dockerfile b/backend/Dockerfile index 2c795a3..392a17b 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,23 +1,23 @@ -# Use the official Golang image -FROM golang:1.20-alpine +FROM golang:1.21-alpine AS builder + +RUN apk add --no-cache gcc musl-dev -# Set the Current Working Directory inside the container WORKDIR /app -# Copy go mod and sum files COPY go.mod go.sum ./ - -# Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed RUN go mod download -# Copy the source code into the container COPY . . -# Build the Go app -RUN go build -o main . +RUN CGO_ENABLED=1 \ + CGO_CFLAGS="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE" \ + CGO_LDFLAGS="-lm" \ + go build -ldflags="-s -w" . + +FROM alpine:latest + +COPY --from=builder /app/reduce /reduce -# Expose port 8080 to the outside world EXPOSE 8080 -# Command to run the executable -CMD ["./main"] +CMD ["/reduce"] diff --git a/backend/go.mod b/backend/go.mod index 99dd1d8..68405b3 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -1,25 +1,24 @@ -module url-shortener-backend +module reduce go 1.20 +require ( + github.com/jinzhu/gorm v1.9.16 + github.com/labstack/echo v3.3.10+incompatible +) + require ( github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect - github.com/golang-jwt/jwt v3.2.2+incompatible // indirect - github.com/gorilla/mux v1.8.1 // indirect - github.com/jinzhu/gorm v1.9.16 // indirect github.com/jinzhu/inflection v1.0.0 // indirect - github.com/labstack/echo v3.3.10+incompatible // indirect - github.com/labstack/echo/v4 v4.12.0 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/lib/pq v1.10.9 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/rs/xid v1.5.0 // indirect + github.com/mattn/go-sqlite3 v1.14.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect golang.org/x/crypto v0.22.0 // indirect golang.org/x/net v0.24.0 // indirect golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.5.0 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index eced652..a1d8f47 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,24 +1,24 @@ github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= -github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= -github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o= github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg= github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= -github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0= -github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -29,9 +29,10 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= -github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= @@ -57,5 +58,4 @@ golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/backend/main.go b/backend/main.go index e10755b..7981c44 100644 --- a/backend/main.go +++ b/backend/main.go @@ -4,61 +4,18 @@ import ( "log" "math/rand" "net/http" - "os" "time" - "fmt" + "os" "errors" - + "strconv" "github.com/jinzhu/gorm" - _ "github.com/jinzhu/gorm/dialects/postgres" + _ "github.com/jinzhu/gorm/dialects/sqlite" + "github.com/labstack/echo" "github.com/labstack/echo/middleware" ) -var db *gorm.DB - -type URL struct { - ID string `gorm:"primary_key" json:"id"` - LongURL string `json:"long_url"` - ShortURL string `json:"short_url"` - CreatedAt time.Time `json:"created_at"` -} - -func init() { - var err error - dbHost := os.Getenv("DB_HOST") - dbPort := os.Getenv("DB_PORT") - dbUser := os.Getenv("DB_USER") - dbName := os.Getenv("DB_NAME") - dbPassword := os.Getenv("DB_PASSWORD") - - dsn := "host=" + dbHost + " port=" + dbPort + " user=" + dbUser + " dbname=" + dbName + " password=" + dbPassword + " sslmode=disable" - - maxRetries := 5 - retryDelay := 2 * time.Second - - for i := 0; i < maxRetries; i++ { - db, err = gorm.Open("postgres", dsn) - if err == nil { - // Connection successful, break out of the loop - break - } - - // Log the error and wait before retrying - fmt.Printf("Failed to connect to database (attempt %d/%d): %v\n", i+1, maxRetries, err) - time.Sleep(retryDelay) - } - - if err != nil { - // Panic if the final attempt also fails - panic(fmt.Sprintf("Failed to connect to database after %d attempts: %v", maxRetries, err)) - } - - // Auto-migrate database - db.AutoMigrate(&URL{}) -} - -func generateRandomString(length int) string { +func codegen(length int) string { const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" bytes := make([]byte, length) for i := range bytes { @@ -70,7 +27,7 @@ func generateRandomString(length int) string { func shortenURL(c echo.Context) error { // Define a struct for binding the request body type RequestBody struct { - LongURL string `json:"long_url"` + LURL string `json:"lurl"` BaseURL string `json:"base_url"` // Expect base URL in the request } @@ -90,23 +47,31 @@ func shortenURL(c echo.Context) error { } // Check if the long URL already exists in the database - var existingURL URL - if err := db.Where("long_url = ?", reqBody.LongURL).First(&existingURL).Error; err == nil { + var existingURL CodeURLMap + if err := db.Where("lurl = ?", reqBody.LURL).First(&existingURL).Error; err == nil { // If the long URL exists, return the existing short URL - return c.JSON(http.StatusOK, existingURL) + return c.JSON(http.StatusOK, map[string]string{ + "surl": reqBody.BaseURL + "/" + existingURL.Code, + }) } else if !errors.Is(err, gorm.ErrRecordNotFound) { // If there's an error other than record not found, return an error return echo.NewHTTPError(http.StatusInternalServerError, "Failed to check existing URL") } - // Generate a unique ID - id := generateRandomString(6) + // Generate a unique code + codelen := 6 + if os.Getenv("CODE_LENGTH") != "" && os.Getenv("CODE_LENGTH") != "0" { + t, err := strconv.Atoi(os.Getenv("CODE_LENGTH")) + if err == nil { + codelen = t + } + } + code := codegen(codelen) // Create URL record - url := &URL{ - ID: id, - LongURL: reqBody.LongURL, - ShortURL: reqBody.BaseURL + "/" + id, + url := &CodeURLMap{ + Code: code, + LURL: reqBody.LURL, CreatedAt: time.Now(), } @@ -115,17 +80,19 @@ func shortenURL(c echo.Context) error { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create URL record") } - return c.JSON(http.StatusCreated, url) + return c.JSON(http.StatusCreated, map[string]string{ + "surl": reqBody.BaseURL + "/" + code, + }) } -func fetchLongURL(c echo.Context) error { - id := c.Param("id") - var url URL - if err := db.Where("id = ?", id).First(&url).Error; err != nil { +func fetchLURL(c echo.Context) error { + code := c.Param("code") + var url CodeURLMap + if err := db.Where("code = ?", code).First(&url).Error; err != nil { log.Println("Error retrieving URL:", err) return echo.NewHTTPError(http.StatusNotFound, "URL not found") } - return c.JSON(http.StatusOK, map[string]string{"long_url": url.LongURL}) + return c.JSON(http.StatusOK, map[string]string{"lurl": url.LURL}) } @@ -148,7 +115,7 @@ func main() { }) e.POST("/reduce/shorten", shortenURL) - e.GET("/reduce/:id", fetchLongURL) + e.GET("/reduce/:code", fetchLURL) e.Logger.Fatal(e.Start(":8080")) } diff --git a/backend/store.go b/backend/store.go new file mode 100644 index 0000000..e64ddb2 --- /dev/null +++ b/backend/store.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "time" + "github.com/jinzhu/gorm" + _ "github.com/jinzhu/gorm/dialects/sqlite" + + "os" +) + +type CodeURLMap struct { + Code string `gorm:"primary_key" json:"code"` + LURL string `json:"lurl" gorm:"column:lurl"` + CreatedAt time.Time `json:"created_at"` +} + +var db *gorm.DB + +func init() { + var err error + dbPath := os.Getenv("DB_PATH") + if dbPath == "" { + dbPath = "reduce.db" + } + + db, err = gorm.Open("sqlite3", dbPath) + if err != nil { + panic(fmt.Sprintf("Failed to connect to database: %v", err)) + } + + // Auto-migrate database + db.AutoMigrate(&CodeURLMap{}) +} diff --git a/database/Dockerfile b/database/Dockerfile deleted file mode 100644 index 89cd218..0000000 --- a/database/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -# Use the official PostgreSQL image -FROM postgres:latest - -EXPOSE 5432 diff --git a/docker-compose.yml b/docker-compose.yml index 15d2ebf..241e495 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,34 +2,19 @@ services: backend: build: ./backend environment: - DB_HOST: postgres - DB_PORT: 5432 - DB_USER: user - DB_NAME: urlshortener - DB_PASSWORD: password + DB_PATH: /data/reduce.db ports: - "8080:8080" - depends_on: - - postgres - networks: - - docker - - postgres: - image: postgres:latest - build: ./database - environment: - POSTGRES_DB: urlshortener - POSTGRES_USER: user - POSTGRES_PASSWORD: password - ports: - - "5432:5432" + volumes: + - ./data:/data networks: - docker frontend: build: ./frontend environment: - NEXT_PUBLIC_BACKEND_URL: http://backend:8080 + PUBLIC_BACKEND_URL: http://localhost:8080 + INTERNAL_BACKEND_URL: http://backend:8080 ports: - "3000:3000" depends_on: diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json deleted file mode 100644 index bffb357..0000000 --- a/frontend/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "next/core-web-vitals" -} diff --git a/frontend/.gitignore b/frontend/.gitignore index fd3dbb5..b1a6255 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -1,36 +1,11 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js -.yarn/install-state.gz - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc +# Node.js +node_modules/ +dist/ +build/ +.env .DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript +*.log +coverage/ +.vite/ *.tsbuildinfo -next-env.d.ts +bun.lockb diff --git a/frontend/Dockerfile b/frontend/Dockerfile index d886264..549564e 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,26 +1,13 @@ -# Use a Node.js image with at least version 18.17.0 -FROM node:18.17.0 +FROM oven/bun:latest -# Set the working directory -WORKDIR /app +WORKDIR /site -# Install bun -RUN curl -fsSL https://bun.sh/install | bash +COPY package*.json ./ -# Set bun's binary path -ENV PATH="/root/.bun/bin:${PATH}" - -# Copy the package.json and bun.lockb if available -COPY package*.json bun.lockb* ./ - -# Install dependencies using bun RUN bun install -# Copy the rest of the application files COPY . . -# Expose the port the app runs on EXPOSE 3000 -# Command to run the application -CMD ["bun", "run", "dev"] +CMD ["bun", "run", "dev", "--", "--host"] diff --git a/frontend/README.md b/frontend/README.md index 0dc9ea2..a587aa9 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,36 +1,19 @@ -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). +# Reduce Frontend -## Getting Started +This is the frontend for the Reduce URL shortener, built with React, Vite, TypeScript, Tailwind CSS, and Chakra UI. -First, run the development server: +## Development -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` +1. Install dependencies: + ```bash + npm install + ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +2. Run the development server: + ```bash + npm run dev + ``` -You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file. +## Docker -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. +The frontend is set up to run with Docker Compose. diff --git a/frontend/app/api/redirect/[id]/route.js b/frontend/app/api/redirect/[id]/route.js deleted file mode 100644 index eec9b30..0000000 --- a/frontend/app/api/redirect/[id]/route.js +++ /dev/null @@ -1,22 +0,0 @@ -import { NextResponse } from "next/server"; -import axios from "axios"; -import dotenv from "dotenv"; - -dotenv.config(); - -export async function GET(request, { params }) { - const { id } = params; - - try { - const response = await axios.get( - `${process.env.NEXT_PUBLIC_BACKEND_URL}/reduce/${id}` - ); - if (response.status === 200) { - return NextResponse.redirect(response.data.long_url); - } else { - return new NextResponse("URL not found", { status: 404 }); - } - } catch (error) { - return NextResponse.redirect("/error"); - } -} diff --git a/frontend/app/error/page.js b/frontend/app/error/page.js deleted file mode 100644 index 949024a..0000000 --- a/frontend/app/error/page.js +++ /dev/null @@ -1,25 +0,0 @@ -"use client"; - -import { MdError } from "react-icons/md"; -import Link from "next/link"; - -export default function ServerErrorPage() { - return ( -
-
-
- -
-

Server Error

-

- Oops! Something went wrong on our end. Please try again later. -

- - - Go Back to Home - - -
-
- ); -} diff --git a/frontend/app/favicon.ico b/frontend/app/favicon.ico deleted file mode 100644 index c4ba568fe12badb34cd77d55c86e3cea3421d134..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15406 zcmeHOUq}^M7@vE!dZ<7{TPg^**tV#4&D8!7vGo#(SlC8H1tRU$2%m}`dXjzV$=-Si z+SqPH1VurFJwzt5K^h1VA!bFG7^z*A3RCa5-|w86d*{xdd*_Zbqu4!goH=vPcfQ~E z`@ZvM&KVUYq~s|D1qxqFl*W8TsZ{H(N8{e7LH{8y|f>$wh#u!MZh z7n>9!{(+QGSYG))6ykE2uXrvp*WusAbFHkX^@W^z&oYo>pdv#aIV@ywpU3T?F1Lqz zcrJ9Q7(_k&eG)@h)KC2lvUx%VZH9%O;-X@zEU%z7Yt|%m{JwcJZL6%LqM{;+1v*(S ztg~6e5{X0z=~^@@+Wd9hFElkZMPI*urB$m|N%^n=2ik&7j6ujx6Ger*LeXnc;v!va zxhQP~UY1XCt75@(#&z;!gyJmm@L?+*s5w9rlan+)K2Al;mvj44FZk55^p9)<`u~bF z&{RAwY@q3BZj0#s`}efzw@s{9@}$`cAAmn_E87cEq(R!>_T&ludH66jH~&p>Zm+Me zkNwa7)BJ|3daq%DO_IMjMgNU5zrYouv9U3MXZcUXT$Z{LalmE04JW}r6V}nuK_`wM zrwbP@u&$;lh-oKYKA-)RVpqvNa>)JvrNW1y5`-E|(g!3PqF+Qb9slF4oOIuhbfZtU61JUKDJ@ds5 zKRKGcwvBy1nArBl-XlkjP*YP=BClS(+SD(rs;Uydqwb+YhfH-c+APN%lU!FOR0nT8*`yPH8wV;)XAtjP5-ynpB#tfT$I%Q=FJ;guwa4D`lWASyEcz%2a-C;J~2Ggur(3sfiTvo%Bbwy3 zus$Is-Ef~+HyL8r$iH#?!Ptkju$E%6SoR#)jD1%28}*}3e}BKGUR*b9*kH+ln|UZ< zKVDckS?M1b7!bdyRj8t(!cxB*za;bv4QBo5^ZEo|tXQ$aH~r6_Kj-(bhaz`&cJk|# zX0?ogr%#`HrWYaXv;}1A!ZEYoU+}VwX&eyBP^@n~fa_ZD6 zs;Q~*)ZcDmbl%9M8HeVLjfU|(tzB8HlhU@6jZWX{a$lT#_AqTfZo)nZZ_z4soP*mZ zaX$7kEKlc>AFsWcbM0o$7AVhidd`?R|ABIu>u?j3k;_kmm=_rpIscI=>g z_wLc-$B$F;rAwE@nJIKy%}uqnwJG&A`TO_p)0Qn;ME_2a^Jz_5U0qF|K7BI2A`{-v zSFT)XInFFuvV>m0er=M$gJ;j4(c;C6E#>^+U*i90!jcaE*|TR&_3_~Q_wTfS|Ng+R zgO6^pGUjz=WfQeZ17{>_sp3y^zGX>6a1l}Au2B~_n3RTeHEs+~Vg_bT|YJ=asPcrqHZ1_KR?3igE7`A-={F(Od-D`tg zzT3EojZE0HiGPeay}i9g>P7j%g9ntKpPv@L6D(QR;WfQe{t@?9DK0+%u)FE>+RdOYVH$doT2N_u{0Y#eE8t$ zd5#n8sAGp8=d647?4gYtHzxAdty`&~p}~6nz{fH-ZrpI$7u?639e%s@8`coJckj0J z0en_aP>`h!>DCCD?aCIv=2yG93_jE91aWnX{|SHNXqB+W@E>>5XKwMMZ(F5c@F(Lc zTl`q(9OiFJtrEtiojZ31z<*}^FJ8P5XO6(5WvnsJojXVG-o3MePlJPlfxbH;PVM-| z_Yzna4-XF~GRl~9ljDE#dj=TP+}s=}_v!Fk5^VDj?=Sdf7~g37-*;2jO?Ld-Ks7yv zFWTDLX#4iUTl{;? fL9V^o@o(_`Xm;$(#aE8^EMkDG=2DIUcMSXw5G{w% diff --git a/frontend/app/globals.css b/frontend/app/globals.css deleted file mode 100644 index 875c01e..0000000 --- a/frontend/app/globals.css +++ /dev/null @@ -1,33 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -:root { - --foreground-rgb: 0, 0, 0; - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; -} - -@media (prefers-color-scheme: dark) { - :root { - --foreground-rgb: 255, 255, 255; - --background-start-rgb: 0, 0, 0; - --background-end-rgb: 0, 0, 0; - } -} - -body { - color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); -} - -@layer utilities { - .text-balance { - text-wrap: balance; - } -} diff --git a/frontend/app/layout.js b/frontend/app/layout.js deleted file mode 100644 index ccc3e60..0000000 --- a/frontend/app/layout.js +++ /dev/null @@ -1,62 +0,0 @@ -import { Inter } from "next/font/google"; -import "./globals.css"; -import dotenv from "dotenv"; - -dotenv.config(); - -const inter = Inter({ subsets: ["latin"] }); - -export const metadata = { - title: "Reduce", - description: "A simple URL shortening service.", - icons: { - icon: "/favicon.ico", - }, - openGraph: { - type: "website", - locale: "en_US", - url: "https://r.webark.in", - title: "Reduce - Simple URL Shortener", - description: "A simple URL shortening service to make your links concise.", - siteName: "Reduce", - images: [ - { - url: "/og-image.png", - width: 1200, - height: 630, - alt: "Reduce - URL Shortening Service", - }, - ], - }, -}; - -export default function RootLayout({ children }) { - return ( - - - {/* Basic SEO Meta Tags */} - - - - - - - {/* Open Graph Meta Tags */} - - - - - - - - - - - - {/* Favicon */} - - - {children} - - ); -} diff --git a/frontend/app/page.js b/frontend/app/page.js deleted file mode 100644 index b6de162..0000000 --- a/frontend/app/page.js +++ /dev/null @@ -1,116 +0,0 @@ -"use client"; - -import { useState } from "react"; -import axios from "axios"; -import { MdContentCopy } from "react-icons/md"; -import Link from "next/link"; -import QRCode from "react-qr-code"; - -export default function Home() { - const [longUrl, setLongUrl] = useState(""); - const [shortUrl, setShortUrl] = useState(""); - const [copied, setCopied] = useState(false); - const [prevLongUrl, setPrevLongUrl] = useState(""); - - const handleSubmit = async (e) => { - e.preventDefault(); - - if (longUrl === prevLongUrl && shortUrl) { - return; - } - - const baseURL = window.location.origin; - try { - const response = await axios.post( - `${process.env.NEXT_PUBLIC_BACKEND_URL}/reduce/shorten`, - { - long_url: longUrl, - base_url: baseURL, - }, - ); - - setShortUrl(response.data.short_url); - setPrevLongUrl(longUrl); - } catch (error) { - console.error("Error shortening URL:", error); - } - }; - - const handleCopy = () => { - navigator.clipboard.writeText(shortUrl); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - }; - - return ( - <> - -
-
-

- Reduce -

-
- setLongUrl(e.target.value)} - className="border border-gray-300 bg-inherit rounded-lg p-3 text-white focus:outline-none focus:ring-2 focus:ring-blue-500" - /> - -
- {shortUrl && ( -
-
- - {shortUrl} - - -
-
- -
-
- )} -
-
- - ); -} diff --git a/frontend/bun.lock b/frontend/bun.lock new file mode 100644 index 0000000..2ab9c90 --- /dev/null +++ b/frontend/bun.lock @@ -0,0 +1,581 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "reduce-frontend", + "dependencies": { + "@chakra-ui/react": "^2.8.2", + "@emotion/react": "^11.11.3", + "@emotion/styled": "^11.11.0", + "axios": "^1.6.7", + "framer-motion": "^11.0.3", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-icons": "^5.0.1", + "react-qr-code": "^2.0.12", + "react-router-dom": "^6.22.0", + }, + "devDependencies": { + "@types/react": "^18.2.55", + "@types/react-dom": "^18.2.19", + "@vitejs/plugin-react": "^4.2.1", + "autoprefixer": "^10.4.17", + "postcss": "^8.4.35", + "tailwindcss": "^3.4.1", + "typescript": "^5.3.3", + "vite": "^5.1.0", + }, + }, + }, + "packages": { + "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], + + "@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + + "@babel/compat-data": ["@babel/compat-data@7.28.5", "", {}, "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA=="], + + "@babel/core": ["@babel/core@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw=="], + + "@babel/generator": ["@babel/generator@7.28.5", "", { "dependencies": { "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ=="], + + "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="], + + "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="], + + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="], + + "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.28.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="], + + "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], + + "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], + + "@babel/helpers": ["@babel/helpers@7.28.4", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.4" } }, "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w=="], + + "@babel/parser": ["@babel/parser@7.28.5", "", { "dependencies": { "@babel/types": "^7.28.5" }, "bin": "./bin/babel-parser.js" }, "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ=="], + + "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="], + + "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="], + + "@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="], + + "@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], + + "@babel/traverse": ["@babel/traverse@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/types": "^7.28.5", "debug": "^4.3.1" } }, "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ=="], + + "@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="], + + "@chakra-ui/anatomy": ["@chakra-ui/anatomy@2.3.6", "", {}, "sha512-TjmjyQouIZzha/l8JxdBZN1pKZTj7sLpJ0YkFnQFyqHcbfWggW9jKWzY1E0VBnhtFz/xF3KC6UAVuZVSJx+y0g=="], + + "@chakra-ui/hooks": ["@chakra-ui/hooks@2.4.5", "", { "dependencies": { "@chakra-ui/utils": "2.2.5", "@zag-js/element-size": "0.31.1", "copy-to-clipboard": "3.3.3", "framesync": "6.1.2" }, "peerDependencies": { "react": ">=18" } }, "sha512-601fWfHE2i7UjaxK/9lDLlOni6vk/I+04YDbM0BrelJy+eqxdlOmoN8Z6MZ3PzFh7ofERUASor+vL+/HaCaZ7w=="], + + "@chakra-ui/react": ["@chakra-ui/react@2.10.9", "", { "dependencies": { "@chakra-ui/hooks": "2.4.5", "@chakra-ui/styled-system": "2.12.4", "@chakra-ui/theme": "3.4.9", "@chakra-ui/utils": "2.2.5", "@popperjs/core": "^2.11.8", "@zag-js/focus-visible": "^0.31.1", "aria-hidden": "^1.2.3", "react-fast-compare": "3.2.2", "react-focus-lock": "^2.9.6", "react-remove-scroll": "^2.5.7" }, "peerDependencies": { "@emotion/react": ">=11", "@emotion/styled": ">=11", "framer-motion": ">=4.0.0", "react": ">=18", "react-dom": ">=18" } }, "sha512-lhdcgoocOiURwBNR3L8OioCNIaGCZqRfuKioLyaQLjOanl4jr0PQclsGb+w0cmito252vEWpsz2xRqF7y+Flrw=="], + + "@chakra-ui/styled-system": ["@chakra-ui/styled-system@2.12.4", "", { "dependencies": { "@chakra-ui/utils": "2.2.5", "csstype": "^3.1.2" } }, "sha512-oa07UG7Lic5hHSQtGRiMEnYjuhIa8lszyuVhZjZqR2Ap3VMF688y1MVPJ1pK+8OwY5uhXBgVd5c0+rI8aBZlwg=="], + + "@chakra-ui/theme": ["@chakra-ui/theme@3.4.9", "", { "dependencies": { "@chakra-ui/anatomy": "2.3.6", "@chakra-ui/theme-tools": "2.2.9", "@chakra-ui/utils": "2.2.5" }, "peerDependencies": { "@chakra-ui/styled-system": ">=2.8.0" } }, "sha512-GAom2SjSdRWTcX76/2yJOFJsOWHQeBgaynCUNBsHq62OafzvELrsSHDUw0bBqBb1c2ww0CclIvGilPup8kXBFA=="], + + "@chakra-ui/theme-tools": ["@chakra-ui/theme-tools@2.2.9", "", { "dependencies": { "@chakra-ui/anatomy": "2.3.6", "@chakra-ui/utils": "2.2.5", "color2k": "^2.0.2" }, "peerDependencies": { "@chakra-ui/styled-system": ">=2.0.0" } }, "sha512-PcbYL19lrVvEc7Oydy//jsy/MO/rZz1DvLyO6AoI+bI/+Kwz9WfOKsspbulEhRg5COayE0R/IZPsskXZ7Mp4bA=="], + + "@chakra-ui/utils": ["@chakra-ui/utils@2.2.5", "", { "dependencies": { "@types/lodash.mergewith": "4.6.9", "lodash.mergewith": "4.6.2" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-KTBCK+M5KtXH6p54XS39ImQUMVtAx65BoZDoEms3LuObyTo1+civ1sMm4h3nRT320U6H5H7D35WnABVQjqU/4g=="], + + "@emotion/babel-plugin": ["@emotion/babel-plugin@11.13.5", "", { "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/serialize": "^1.3.3", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", "find-root": "^1.1.0", "source-map": "^0.5.7", "stylis": "4.2.0" } }, "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ=="], + + "@emotion/cache": ["@emotion/cache@11.14.0", "", { "dependencies": { "@emotion/memoize": "^0.9.0", "@emotion/sheet": "^1.4.0", "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } }, "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA=="], + + "@emotion/hash": ["@emotion/hash@0.9.2", "", {}, "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="], + + "@emotion/is-prop-valid": ["@emotion/is-prop-valid@1.4.0", "", { "dependencies": { "@emotion/memoize": "^0.9.0" } }, "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw=="], + + "@emotion/memoize": ["@emotion/memoize@0.9.0", "", {}, "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="], + + "@emotion/react": ["@emotion/react@11.14.0", "", { "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", "@emotion/cache": "^11.14.0", "@emotion/serialize": "^1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "hoist-non-react-statics": "^3.3.1" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA=="], + + "@emotion/serialize": ["@emotion/serialize@1.3.3", "", { "dependencies": { "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/unitless": "^0.10.0", "@emotion/utils": "^1.4.2", "csstype": "^3.0.2" } }, "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA=="], + + "@emotion/sheet": ["@emotion/sheet@1.4.0", "", {}, "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg=="], + + "@emotion/styled": ["@emotion/styled@11.14.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", "@emotion/is-prop-valid": "^1.3.0", "@emotion/serialize": "^1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", "@emotion/utils": "^1.4.2" }, "peerDependencies": { "@emotion/react": "^11.0.0-rc.0", "react": ">=16.8.0" } }, "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw=="], + + "@emotion/unitless": ["@emotion/unitless@0.10.0", "", {}, "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg=="], + + "@emotion/use-insertion-effect-with-fallbacks": ["@emotion/use-insertion-effect-with-fallbacks@1.2.0", "", { "peerDependencies": { "react": ">=16.8.0" } }, "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg=="], + + "@emotion/utils": ["@emotion/utils@1.4.2", "", {}, "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA=="], + + "@emotion/weak-memoize": ["@emotion/weak-memoize@0.4.0", "", {}, "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], + + "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@popperjs/core": ["@popperjs/core@2.11.8", "", {}, "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="], + + "@remix-run/router": ["@remix-run/router@1.23.1", "", {}, "sha512-vDbaOzF7yT2Qs4vO6XV1MHcJv+3dgR1sT+l3B8xxOVhUC336prMvqrvsLL/9Dnw2xr6Qhz4J0dmS0llNAbnUmQ=="], + + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.53.3", "", { "os": "android", "cpu": "arm" }, "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.53.3", "", { "os": "android", "cpu": "arm64" }, "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.53.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.53.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.53.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.53.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.53.3", "", { "os": "linux", "cpu": "arm" }, "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.53.3", "", { "os": "linux", "cpu": "arm" }, "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.53.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.53.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A=="], + + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g=="], + + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.53.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.53.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.53.3", "", { "os": "linux", "cpu": "x64" }, "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.53.3", "", { "os": "linux", "cpu": "x64" }, "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q=="], + + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.53.3", "", { "os": "none", "cpu": "arm64" }, "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.53.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.53.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA=="], + + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.53.3", "", { "os": "win32", "cpu": "x64" }, "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.53.3", "", { "os": "win32", "cpu": "x64" }, "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ=="], + + "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], + + "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="], + + "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="], + + "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/lodash": ["@types/lodash@4.17.21", "", {}, "sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ=="], + + "@types/lodash.mergewith": ["@types/lodash.mergewith@4.6.9", "", { "dependencies": { "@types/lodash": "*" } }, "sha512-fgkoCAOF47K7sxrQ7Mlud2TH023itugZs2bUg8h/KzT+BnZNrR2jAOmaokbLunHNnobXVWOezAeNn/lZqwxkcw=="], + + "@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="], + + "@types/prop-types": ["@types/prop-types@15.7.15", "", {}, "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="], + + "@types/react": ["@types/react@18.3.27", "", { "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" } }, "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w=="], + + "@types/react-dom": ["@types/react-dom@18.3.7", "", { "peerDependencies": { "@types/react": "^18.0.0" } }, "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ=="], + + "@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="], + + "@zag-js/dom-query": ["@zag-js/dom-query@0.31.1", "", {}, "sha512-oiuohEXAXhBxpzzNm9k2VHGEOLC1SXlXSbRPcfBZ9so5NRQUA++zCE7cyQJqGLTZR0t3itFLlZqDbYEXRrefwg=="], + + "@zag-js/element-size": ["@zag-js/element-size@0.31.1", "", {}, "sha512-4T3yvn5NqqAjhlP326Fv+w9RqMIBbNN9H72g5q2ohwzhSgSfZzrKtjL4rs9axY/cw9UfMfXjRjEE98e5CMq7WQ=="], + + "@zag-js/focus-visible": ["@zag-js/focus-visible@0.31.1", "", { "dependencies": { "@zag-js/dom-query": "0.31.1" } }, "sha512-dbLksz7FEwyFoANbpIlNnd3bVm0clQSUsnP8yUVQucStZPsuWjCrhL2jlAbGNrTrahX96ntUMXHb/sM68TibFg=="], + + "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], + + "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + + "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], + + "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], + + "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], + + "autoprefixer": ["autoprefixer@10.4.22", "", { "dependencies": { "browserslist": "^4.27.0", "caniuse-lite": "^1.0.30001754", "fraction.js": "^5.3.4", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg=="], + + "axios": ["axios@1.13.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA=="], + + "babel-plugin-macros": ["babel-plugin-macros@3.1.0", "", { "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", "resolve": "^1.19.0" } }, "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg=="], + + "baseline-browser-mapping": ["baseline-browser-mapping@2.9.7", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-k9xFKplee6KIio3IDbwj+uaCLpqzOwakOgmqzPezM0sFJlFKcg30vk2wOiAJtkTSfx0SSQDSe8q+mWA/fSH5Zg=="], + + "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + + "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001760", "", {}, "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw=="], + + "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + + "color2k": ["color2k@2.0.3", "", {}, "sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog=="], + + "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], + + "commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], + + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + + "copy-to-clipboard": ["copy-to-clipboard@3.3.3", "", { "dependencies": { "toggle-selection": "^1.0.6" } }, "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA=="], + + "cosmiconfig": ["cosmiconfig@7.1.0", "", { "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" } }, "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA=="], + + "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], + + "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], + + "didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="], + + "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "electron-to-chromium": ["electron-to-chromium@1.5.267", "", {}, "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw=="], + + "error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], + + "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], + + "esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "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=="], + + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], + + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="], + + "focus-lock": ["focus-lock@1.3.6", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-Ik/6OCk9RQQ0T5Xw+hKNLWrjSMtv51dD4GRmJjbD5a58TIEpI5a5iXagKVl3Z5UuyslMCA8Xwnu76jQob62Yhg=="], + + "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="], + + "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="], + + "fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="], + + "framer-motion": ["framer-motion@11.18.2", "", { "dependencies": { "motion-dom": "^11.18.1", "motion-utils": "^11.18.1", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w=="], + + "framesync": ["framesync@6.1.2", "", { "dependencies": { "tslib": "2.4.0" } }, "sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + + "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="], + + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + + "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], + + "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], + + "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + + "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], + + "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + + "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], + + "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + + "lodash.mergewith": ["lodash.mergewith@4.6.2", "", {}, "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ=="], + + "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=="], + + "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "motion-dom": ["motion-dom@11.18.1", "", { "dependencies": { "motion-utils": "^11.18.1" } }, "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw=="], + + "motion-utils": ["motion-utils@11.18.1", "", {}, "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], + + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="], + + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + + "normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], + + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + + "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], + + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + + "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="], + + "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="], + + "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + + "postcss-import": ["postcss-import@15.1.0", "", { "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "peerDependencies": { "postcss": "^8.0.0" } }, "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="], + + "postcss-js": ["postcss-js@4.1.0", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw=="], + + "postcss-load-config": ["postcss-load-config@6.0.1", "", { "dependencies": { "lilconfig": "^3.1.1" }, "peerDependencies": { "jiti": ">=1.21.0", "postcss": ">=8.0.9", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["jiti", "postcss", "tsx", "yaml"] }, "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g=="], + + "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="], + + "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], + + "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], + + "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=="], + + "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + + "qr.js": ["qr.js@0.0.0", "", {}, "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="], + + "react-clientside-effect": ["react-clientside-effect@1.2.8", "", { "dependencies": { "@babel/runtime": "^7.12.13" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-ma2FePH0z3px2+WOu6h+YycZcEvFmmxIlAb62cF52bG86eMySciO/EQZeQMXd07kPCYB0a1dWDT5J+KE9mCDUw=="], + + "react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="], + + "react-fast-compare": ["react-fast-compare@3.2.2", "", {}, "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="], + + "react-focus-lock": ["react-focus-lock@2.13.7", "", { "dependencies": { "@babel/runtime": "^7.0.0", "focus-lock": "^1.3.6", "prop-types": "^15.6.2", "react-clientside-effect": "^1.2.7", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-20lpZHEQrXPb+pp1tzd4ULL6DyO5D2KnR0G69tTDdydrmNhU7pdFmbQUYVyHUgp+xN29IuFR0PVuhOmvaZL9Og=="], + + "react-icons": ["react-icons@5.5.0", "", { "peerDependencies": { "react": "*" } }, "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw=="], + + "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], + + "react-qr-code": ["react-qr-code@2.0.18", "", { "dependencies": { "prop-types": "^15.8.1", "qr.js": "0.0.0" }, "peerDependencies": { "react": "*" } }, "sha512-v1Jqz7urLMhkO6jkgJuBYhnqvXagzceg3qJUWayuCK/c6LTIonpWbwxR1f1APGd4xrW/QcQEovNrAojbUz65Tg=="], + + "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="], + + "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="], + + "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], + + "react-router": ["react-router@6.30.2", "", { "dependencies": { "@remix-run/router": "1.23.1" }, "peerDependencies": { "react": ">=16.8" } }, "sha512-H2Bm38Zu1bm8KUE5NVWRMzuIyAV8p/JrOaBJAwVmp37AXG72+CZJlEBw6pdn9i5TBgLMhNDgijS4ZlblpHyWTA=="], + + "react-router-dom": ["react-router-dom@6.30.2", "", { "dependencies": { "@remix-run/router": "1.23.1", "react-router": "6.30.2" }, "peerDependencies": { "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-l2OwHn3UUnEVUqc6/1VMmR1cvZryZ3j3NzapC2eUXO1dB0sYp5mvwdjiXhpUbRb21eFow3qSxpP8Yv6oAU824Q=="], + + "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=="], + + "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="], + + "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], + + "resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], + + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "rollup": ["rollup@4.53.3", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.53.3", "@rollup/rollup-android-arm64": "4.53.3", "@rollup/rollup-darwin-arm64": "4.53.3", "@rollup/rollup-darwin-x64": "4.53.3", "@rollup/rollup-freebsd-arm64": "4.53.3", "@rollup/rollup-freebsd-x64": "4.53.3", "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", "@rollup/rollup-linux-arm-musleabihf": "4.53.3", "@rollup/rollup-linux-arm64-gnu": "4.53.3", "@rollup/rollup-linux-arm64-musl": "4.53.3", "@rollup/rollup-linux-loong64-gnu": "4.53.3", "@rollup/rollup-linux-ppc64-gnu": "4.53.3", "@rollup/rollup-linux-riscv64-gnu": "4.53.3", "@rollup/rollup-linux-riscv64-musl": "4.53.3", "@rollup/rollup-linux-s390x-gnu": "4.53.3", "@rollup/rollup-linux-x64-gnu": "4.53.3", "@rollup/rollup-linux-x64-musl": "4.53.3", "@rollup/rollup-openharmony-arm64": "4.53.3", "@rollup/rollup-win32-arm64-msvc": "4.53.3", "@rollup/rollup-win32-ia32-msvc": "4.53.3", "@rollup/rollup-win32-x64-gnu": "4.53.3", "@rollup/rollup-win32-x64-msvc": "4.53.3", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], + + "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "stylis": ["stylis@4.2.0", "", {}, "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="], + + "sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="], + + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + + "tailwindcss": ["tailwindcss@3.4.19", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.7", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ=="], + + "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], + + "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], + + "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "toggle-selection": ["toggle-selection@1.0.6", "", {}, "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="], + + "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + + "update-browserslist-db": ["update-browserslist-db@1.2.2", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA=="], + + "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "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-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], + + "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.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-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "vite": ["vite@5.4.21", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw=="], + + "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + + "yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], + + "@emotion/babel-plugin/convert-source-map": ["convert-source-map@1.9.0", "", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="], + + "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "framesync/tslib": ["tslib@2.4.0", "", {}, "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="], + + "tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + } +} diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..29890f1 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + Reduce - URL Shortener + + +
+ + + diff --git a/frontend/jsconfig.json b/frontend/jsconfig.json deleted file mode 100644 index 2a2e4b3..0000000 --- a/frontend/jsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "compilerOptions": { - "paths": { - "@/*": ["./*"] - } - } -} diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs deleted file mode 100644 index 0a5aecb..0000000 --- a/frontend/next.config.mjs +++ /dev/null @@ -1,14 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { - async redirects() { - return [ - { - source: "/:id([a-zA-Z0-9]{6})", // Match only 6-character IDs - destination: `/api/redirect/:id`, - permanent: false, - }, - ]; - }, -}; - -export default nextConfig; diff --git a/frontend/package.json b/frontend/package.json index 26fc9ba..7da6bb7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,27 +1,34 @@ { - "name": "my-nextjs13-app", - "version": "0.1.0", + "name": "reduce-frontend", "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint" + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" }, "dependencies": { - "@types/react": "^18.3.3", - "axios": "^1.7.3", - "dotenv": "^16.4.5", - "next": "14.2.5", - "react": "^18", - "react-dom": "^18", - "react-icons": "^5.2.1", - "react-qr-code": "^2.0.15" + "@chakra-ui/react": "^2.8.2", + "@emotion/react": "^11.11.3", + "@emotion/styled": "^11.11.0", + "axios": "^1.6.7", + "framer-motion": "^11.0.3", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-icons": "^5.0.1", + "react-qr-code": "^2.0.12", + "react-router-dom": "^6.22.0" }, "devDependencies": { - "postcss": "^8", + "@types/react": "^18.2.55", + "@types/react-dom": "^18.2.19", + "@vitejs/plugin-react": "^4.2.1", + "autoprefixer": "^10.4.17", + "postcss": "^8.4.35", "tailwindcss": "^3.4.1", - "eslint": "^8", - "eslint-config-next": "14.2.5" + "typescript": "^5.3.3", + "vite": "^5.1.0" } } diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/frontend/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/frontend/postcss.config.mjs b/frontend/postcss.config.mjs deleted file mode 100644 index 1a69fd2..0000000 --- a/frontend/postcss.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -/** @type {import('postcss-load-config').Config} */ -const config = { - plugins: { - tailwindcss: {}, - }, -}; - -export default config; diff --git a/frontend/public/next.svg b/frontend/public/next.svg deleted file mode 100644 index 5174b28..0000000 --- a/frontend/public/next.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/public/og-image.png b/frontend/public/og-image.png deleted file mode 100644 index 87d0370420ca0984138ec7afbc58892e4a1e4b50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21249 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 \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx new file mode 100644 index 0000000..727186c --- /dev/null +++ b/frontend/src/App.tsx @@ -0,0 +1,16 @@ +import { BrowserRouter, Routes, Route } from 'react-router-dom'; +import Home from './pages/Home'; +import Redirect from './pages/Redirect'; + +function App() { + return ( + + + } /> + } /> + + + ); +} + +export default App; diff --git a/frontend/src/index.css b/frontend/src/index.css new file mode 100644 index 0000000..1d5e457 --- /dev/null +++ b/frontend/src/index.css @@ -0,0 +1,9 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + body { + @apply bg-zinc-950 text-zinc-300 font-mono antialiased; + } +} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx new file mode 100644 index 0000000..3d7150d --- /dev/null +++ b/frontend/src/main.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.tsx' +import './index.css' + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx new file mode 100644 index 0000000..6047a87 --- /dev/null +++ b/frontend/src/pages/Home.tsx @@ -0,0 +1,138 @@ +import { useState } from 'react'; +import axios from 'axios'; +import { MdContentCopy, MdCheck, MdRefresh } from 'react-icons/md'; +import QRCode from 'react-qr-code'; + +export default function Home() { + const [longUrl, setLongUrl] = useState(""); + const [shortUrl, setShortUrl] = useState(""); + const [copied, setCopied] = useState(false); + const [prevLongUrl, setPrevLongUrl] = useState(""); + const [status, setStatus] = useState<{ type: 'error' | 'success' | 'idle', msg: string }>({ type: 'idle', msg: '' }); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setStatus({ type: 'idle', msg: '' }); + + if (longUrl === prevLongUrl && shortUrl) { + return; + } + + if (longUrl.trim() === "") { + return; + } + + try { + new URL(longUrl); + } catch (_) { + setStatus({ type: 'error', msg: 'Invalid URL' }); + return; + } + + const baseURL = window.location.origin; + const backendUrl = import.meta.env.VITE_BACKEND_URL || 'http://localhost:8080'; + + try { + const response = await axios.post( + `${backendUrl}/reduce/shorten`, + { + lurl: longUrl, + base_url: baseURL, + }, + ); + + setShortUrl(response.data.surl); + setPrevLongUrl(longUrl); + setStatus({ type: 'success', msg: '' }); + } catch (error) { + console.error("Error shortening URL:", error); + setStatus({ type: 'error', msg: 'Error' }); + } + }; + + const handleCopy = () => { + navigator.clipboard.writeText(shortUrl); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }; + + const handleReset = () => { + setLongUrl(""); + setShortUrl(""); + setPrevLongUrl(""); + setStatus({ type: 'idle', msg: '' }); + setCopied(false); + }; + + return ( +
+
+ {/* Header */} +
+

+ Reduce +

+
+ + {/* Main Interface */} +
+ {!shortUrl ? ( + <> +
+ setLongUrl(e.target.value)} + className="w-full bg-zinc-950 border border-zinc-700 p-3 text-zinc-300 placeholder-zinc-700 focus:outline-none focus:border-zinc-400 focus:ring-1 focus:ring-zinc-400 transition-all font-mono text-sm" + /> + + +
+ + {/* Error Indicator */} + {status.msg && status.type === 'error' && ( +
+ {status.msg} +
+ )} + + ) : ( +
+
+ + +
+ +
+ +
+ + +
+ )} +
+
+
+ ); +} diff --git a/frontend/src/pages/Redirect.tsx b/frontend/src/pages/Redirect.tsx new file mode 100644 index 0000000..d499a65 --- /dev/null +++ b/frontend/src/pages/Redirect.tsx @@ -0,0 +1,62 @@ +import { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; +import axios from 'axios'; +import { MdErrorOutline } from "react-icons/md"; + +export default function Redirect() { + const { code } = useParams(); + const [error, setError] = useState(false); + + useEffect(() => { + const fetchUrl = async () => { + if (!code) return; + + const backendUrl = import.meta.env.VITE_BACKEND_URL || 'http://localhost:8080'; + + try { + const response = await axios.get( + `${backendUrl}/reduce/${code}` + ); + if (response.status === 200 && response.data.lurl) { + window.location.replace(response.data.lurl); + } else { + setError(true); + } + } catch (err) { + console.error("Redirect error:", err); + setError(true); + } + }; + + fetchUrl(); + }, [code]); + + if (error) { + return ( +
+
+
+ +
+

404 Not Found

+

+ Link invalid or expired. +

+ + + Go Home + + +
+
+ ); + } + + return ( +
+
+ Redirecting... +
+
+ ); +} diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index ef60c8b..dca8ba0 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -1,16 +1,11 @@ /** @type {import('tailwindcss').Config} */ -export const content = [ - "./pages/**/*.{js,ts,jsx,tsx,mdx}", - "./components/**/*.{js,ts,jsx,tsx,mdx}", - "./app/**/*.{js,ts,jsx,tsx,mdx}", -]; -export const theme = { - extend: { - backgroundImage: { - "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", - "gradient-conic": - "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", - }, +export default { + content: [ + "./index.html", + "./src/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: {}, }, -}; -export const plugins = []; + plugins: [], +} diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 0000000..a4c834a --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts new file mode 100644 index 0000000..aad7f71 --- /dev/null +++ b/frontend/vite.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + server: { + host: true, + port: 3000, + } +})