From 76d63d976d303b7cfba8d07b1d8aa4b0a416c4b3 Mon Sep 17 00:00:00 2001 From: ajnart Date: Thu, 10 Oct 2024 11:56:27 +0900 Subject: [PATCH] Add link preview ```` --- next.config.js | 3 ++ package.json | 9 ++++-- pnpm-lock.yaml | 69 +++++++++++++++++++++++++++++++++++++++++++++- src/app/layout.tsx | 12 +++++--- src/app/page.tsx | 25 ++++++++++++----- 5 files changed, 104 insertions(+), 14 deletions(-) diff --git a/next.config.js b/next.config.js index 4e03590..7275b0d 100644 --- a/next.config.js +++ b/next.config.js @@ -11,6 +11,9 @@ const config = { remotePatterns: [ { hostname: "www.google.com", + }, + { + hostname: "api.microlink.io", } ], } diff --git a/package.json b/package.json index 590140a..7ed7723 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "subs", - "version": "0.3.2", + "version": "0.4.0", "author": { "name": "ajanrt", "email": "thomas@ajnart.dev" @@ -31,7 +31,7 @@ "@radix-ui/react-context-menu": "^2.2.1", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", - "@radix-ui/react-hover-card": "^1.1.1", + "@radix-ui/react-hover-card": "^1.1.2", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-menubar": "^1.1.1", @@ -51,17 +51,22 @@ "@radix-ui/react-toggle-group": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.2", "@t3-oss/env-nextjs": "^0.10.1", + "@tabler/icons-react": "^3.19.0", + "@types/canvas-confetti": "^1.6.4", + "canvas-confetti": "^1.9.3", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cmdk": "1.0.0", "date-fns": "^4.1.0", "drizzle-orm": "^0.33.0", "embla-carousel-react": "^8.3.0", + "framer-motion": "^11.11.7", "geist": "^1.3.0", "input-otp": "^1.2.4", "lucide-react": "^0.446.0", "next": "^14.2.4", "next-themes": "^0.3.0", + "qss": "^3.0.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-hook-form": "^7.53.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fb1bb57..8ecd059 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,7 +42,7 @@ importers: specifier: ^2.1.1 version: 2.1.2(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-hover-card': - specifier: ^1.1.1 + specifier: ^1.1.2 version: 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-icons': specifier: ^1.3.0 @@ -101,6 +101,15 @@ importers: '@t3-oss/env-nextjs': specifier: ^0.10.1 version: 0.10.1(typescript@5.6.3)(zod@3.23.8) + '@tabler/icons-react': + specifier: ^3.19.0 + version: 3.19.0(react@18.3.1) + '@types/canvas-confetti': + specifier: ^1.6.4 + version: 1.6.4 + canvas-confetti: + specifier: ^1.9.3 + version: 1.9.3 class-variance-authority: specifier: ^0.7.0 version: 0.7.0 @@ -119,6 +128,9 @@ importers: embla-carousel-react: specifier: ^8.3.0 version: 8.3.0(react@18.3.1) + framer-motion: + specifier: ^11.11.7 + version: 11.11.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) geist: specifier: ^1.3.0 version: 1.3.1(next@14.2.15(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) @@ -134,6 +146,9 @@ importers: next-themes: specifier: ^0.3.0 version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + qss: + specifier: ^3.0.0 + version: 3.0.0 react: specifier: ^18.3.1 version: 18.3.1 @@ -1556,6 +1571,17 @@ packages: typescript: optional: true + '@tabler/icons-react@3.19.0': + resolution: {integrity: sha512-AqEWGI0tQWgqo6ZjMO5yJ9sYT8oXLuAM/up0hN9iENS6IdtNZryKrkNSiMgpwweNTpl8wFFG/dAZ959S91A/uQ==} + peerDependencies: + react: '>= 16' + + '@tabler/icons@3.19.0': + resolution: {integrity: sha512-A4WEWqpdbTfnpFEtwXqwAe9qf9sp1yRPvzppqAuwcoF0q5YInqB+JkJtSFToCyBpPVeLxJUxxkapLvt2qQgnag==} + + '@types/canvas-confetti@1.6.4': + resolution: {integrity: sha512-fNyZ/Fdw/Y92X0vv7B+BD6ysHL4xVU5dJcgzgxLdGbn8O3PezZNIJpml44lKM0nsGur+o/6+NZbZeNTt00U1uA==} + '@types/d3-array@3.2.1': resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} @@ -1766,6 +1792,9 @@ packages: caniuse-lite@1.0.30001667: resolution: {integrity: sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==} + canvas-confetti@1.9.3: + resolution: {integrity: sha512-rFfTURMvmVEX1gyXFgn5QMn81bYk70qa0HLzcIOSVEyl57n6o9ItHeBtUSWdvKAPY0xlvBHno4/v3QPrT83q9g==} + ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -2167,6 +2196,20 @@ packages: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} engines: {node: '>=12.20.0'} + framer-motion@11.11.7: + resolution: {integrity: sha512-89CgILOXPeG3L7ymOTGrLmf8IiKubYLUN/QkYgQuLvehAHfqgwJbLfCnhuyRI4WTds1TXkUp67A7IJrgRY/j1w==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 + react-dom: ^18.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -2673,6 +2716,10 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + qss@3.0.0: + resolution: {integrity: sha512-ZHoCB3M/3Voev64zhLLUOKDtaEdJ/lymsJJ7R3KBusVZ2ovNiIB7XOq3Xh6V1a8O+Vho+g2B5YElq9zW7D8aQw==} + engines: {node: '>=4'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -4307,6 +4354,15 @@ snapshots: optionalDependencies: typescript: 5.6.3 + '@tabler/icons-react@3.19.0(react@18.3.1)': + dependencies: + '@tabler/icons': 3.19.0 + react: 18.3.1 + + '@tabler/icons@3.19.0': {} + + '@types/canvas-confetti@1.6.4': {} + '@types/d3-array@3.2.1': {} '@types/d3-color@3.1.3': {} @@ -4526,6 +4582,8 @@ snapshots: caniuse-lite@1.0.30001667: {} + canvas-confetti@1.9.3: {} + ccount@2.0.1: {} chalk@4.1.2: @@ -4898,6 +4956,13 @@ snapshots: dependencies: fetch-blob: 3.2.0 + framer-motion@11.11.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + tslib: 2.7.0 + optionalDependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -5525,6 +5590,8 @@ snapshots: punycode@2.3.1: {} + qss@3.0.0: {} + queue-microtask@1.2.3: {} react-dom@18.3.1(react@18.3.1): diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 62ca4ce..53a860f 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,7 +1,7 @@ -import '~/styles/globals.css' - import { GeistSans } from 'geist/font/sans' import type { Metadata } from 'next' +import { ThemeProvider } from 'next-themes' +import '~/styles/globals.css' export const metadata: Metadata = { title: 'Subs - Your subscription tracker', @@ -11,8 +11,12 @@ export const metadata: Metadata = { export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) { return ( - - {children} + + + + {children} + + ) } diff --git a/src/app/page.tsx b/src/app/page.tsx index 5b5e7b8..125e1c8 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -10,9 +10,12 @@ import { DialogTitle, DialogTrigger, } from '@/components/ui/dialog' +import { FloatingDock } from '@/components/ui/floating-dock' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' +import { LinkPreview } from '@/components/ui/link-preview' import { PlusCircle } from 'lucide-react' +import Image from 'next/image' import { useEffect, useState } from 'react' import InstructionsPopup from '~/components/InstructionsPopup' import MadeWithKodu from '~/components/MadeWithKodu' @@ -64,6 +67,12 @@ export default function Component() { setIsOpen(true) } + const dockItems = subscriptions.map((sub) => ({ + title: sub.name, + icon: {`${sub.name}, + href: sub.url, + })) + if (!mounted) { return null // Return null on initial render to avoid hydration mismatch } @@ -143,18 +152,20 @@ export default function Component() {
Total Monthly: ${totalMonthly.toFixed(2)}
-
+
{subscriptions.map((subscription) => ( - + + + ))}
{env.NEXT_PUBLIC_SHOW_KODU === 'true' && } + ) }