diff --git a/README.md b/README.md index 01e81b4..76d8b2d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# [Ningowood](http://ningowood) v0.2.0: Add the missing community to the spreadsheet database ecology +# [Ningowood](http://ningowood) v0.2.0: Add the missing all-in-one community to the spreadsheet database ecology -![](./public/static/showcase-20221126.webp) +![](./public/static/showcase-20230604.webp) ## Read the newest artitle -[Ningowood v0.2.0: Add the missing community to the spreadsheet database ecology](./blogs/2023-0618-ningowood-v0_2.md): in writing... +[Ningowood v0.2.0: Add the missing all-in-one community to the spreadsheet database ecology](./blogs/2023-0618-ningowood-v0_2.md): in writing... ## Webinar resource diff --git a/ningowood.com/app/api/auth/[...nextauth]/route.ts b/ningowood.com/app/api/auth/[...nextauth]/route.ts index b39b376..954a547 100644 --- a/ningowood.com/app/api/auth/[...nextauth]/route.ts +++ b/ningowood.com/app/api/auth/[...nextauth]/route.ts @@ -1,7 +1,8 @@ -import NextAuth, { NextAuthOptions } from "next-auth"; -import { PrismaAdapter } from "@next-auth/prisma-adapter"; -import prisma from "@/lib/prisma"; -import GoogleProvider from "next-auth/providers/google"; +import NextAuth, { NextAuthOptions } from "next-auth" +import GoogleProvider from "next-auth/providers/google" +import { PrismaAdapter } from "@next-auth/prisma-adapter" + +import prisma from "@/lib/prisma" export const authOptions: NextAuthOptions = { adapter: PrismaAdapter(prisma), @@ -11,8 +12,8 @@ export const authOptions: NextAuthOptions = { clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, }), ], -}; +} -const handler = NextAuth(authOptions); +const handler = NextAuth(authOptions) -export { handler as GET, handler as POST }; +export { handler as GET, handler as POST } diff --git a/ningowood.com/app/fonts/index.ts b/ningowood.com/app/fonts/index.ts index a5a1cd2..34fc742 100644 --- a/ningowood.com/app/fonts/index.ts +++ b/ningowood.com/app/fonts/index.ts @@ -1,12 +1,12 @@ -import localFont from "next/font/local"; -import { Inter } from "next/font/google"; +import localFont from "next/font/local" +import { Inter } from "next/font/google" export const sfPro = localFont({ src: "./SF-Pro-Display-Medium.otf", variable: "--font-sf", -}); +}) export const inter = Inter({ variable: "--font-inter", subsets: ["latin"], -}); +}) diff --git a/ningowood.com/app/layout.tsx b/ningowood.com/app/layout.tsx index 05728b4..7cb337e 100644 --- a/ningowood.com/app/layout.tsx +++ b/ningowood.com/app/layout.tsx @@ -1,45 +1,46 @@ -import "./globals.css"; -import { Analytics } from "@vercel/analytics/react"; -import cx from "classnames"; -import { sfPro, inter } from "./fonts"; -import Nav from "@/components/layout/nav"; -import Footer from "@/components/layout/footer"; -import { Suspense } from "react"; +import "./globals.css" +import { Analytics } from "@vercel/analytics/react" +import cx from "classnames" +import { sfPro, inter } from "./fonts" +import Nav from "@/components/layout/nav" +import Footer from "@/components/layout/footer" +import { Suspense } from "react" export const metadata = { - title: "Precedent - Building blocks for your Next.js project", + title: + "Ningowood - Add the missing all-in-one community to the spreadsheet database ecology", description: - "Precedent is the all-in-one solution for your Next.js project. It includes a design system, authentication, analytics, and more.", + "Ningowood v0.2 is focus on adding the missing community to the spreadsheet database ecology.", twitter: { card: "summary_large_image", - title: "Precedent - Building blocks for your Next.js project", + title: + "Ningowood - Add the missing all-in-one community to the spreadsheet database ecology", description: - "Precedent is the all-in-one solution for your Next.js project. It includes a design system, authentication, analytics, and more.", - creator: "@steventey", + "Ningowood v0.2 is focus on adding the missing community to the spreadsheet database ecology.", + creator: "@hylerrix", }, - metadataBase: new URL("https://precedent.dev"), + metadataBase: new URL("http://ningowood.com"), themeColor: "#FFF", -}; +} export default async function RootLayout({ children, }: { - children: React.ReactNode; + children: React.ReactNode }) { return ( -
{/* @ts-expect-error Server Component */}
- ); + ) } diff --git a/ningowood.com/components/home/component-grid.tsx b/ningowood.com/components/home/component-grid.tsx index 77fa233..5ea137d 100644 --- a/ningowood.com/components/home/component-grid.tsx +++ b/ningowood.com/components/home/component-grid.tsx @@ -1,14 +1,16 @@ -"use client"; +"use client" -import { useState } from "react"; -import { useDemoModal } from "@/components/home/demo-modal"; -import Popover from "@/components/shared/popover"; -import Tooltip from "@/components/shared/tooltip"; -import { ChevronDown } from "lucide-react"; +import { useState } from "react" +import { ChevronDown } from "lucide-react" + +import { useDemoModal } from "@/components/home/demo-modal" +import Popover from "@/components/shared/popover" +import Tooltip from "@/components/shared/tooltip" export default function ComponentGrid() { - const { DemoModal, setShowDemoModal } = useDemoModal(); - const [openPopover, setOpenPopover] = useState(false); + const { DemoModal, setShowDemoModal } = useDemoModal() + const [openPopover, setOpenPopover] = useState(false) + return (
@@ -53,5 +55,5 @@ export default function ComponentGrid() {
- ); + ) } diff --git a/ningowood.com/components/home/constant.tsx b/ningowood.com/components/home/constant.tsx new file mode 100644 index 0000000..7fdfeeb --- /dev/null +++ b/ningowood.com/components/home/constant.tsx @@ -0,0 +1,105 @@ +import { SupportItem } from "./type" + +export const SupportSsDB: SupportItem[] = [ + { + name: 'Airtable', + logo: '/logo/airtable.webp', + link: 'https://airtable.com/invite/r/40Xexj1v', + }, + { + name: 'Notion', + logo: '/logo/notion.webp', + link: 'https://notion.so/', + }, + { + name: 'Apitable', + logo: '/logo/apitable.webp', + link: 'https://apitable.com/', + }, + { + name: 'Rowy', + logo: '/logo/rowy.webp', + link: 'https://www.rowy.io/', + }, + { + name: 'Baserow', + logo: '/logo/baserow.webp', + link: 'https://baserow.io/', + }, + { + name: 'Jotform', + logo: '/logo/jotform.webp', + link: 'https://www.jotform.com/', + }, + { + name: 'Rows', + logo: '/logo/rows.webp', + link: 'https://rows.com/', + }, + { + name: 'Spreadsheet.com', + logo: '/logo/spreadsheet-com.webp', + link: 'https://www.spreadsheet.com/', + }, + { + name: 'actiondesk', + logo: '/logo/actiondesk.webp', + link: 'https://www.actiondesk.io/', + }, + { + name: 'Mathesar', + logo: '/logo/mathesar.webp', + link: 'https://www.mathesar.org/', + }, + // { + // name: 'Trello', + // logo: '/logo/trello.webp', + // link: 'https://trello.com/', + // }, + // { + // name: 'monday.com', + // logo: '/logo/monday-com.webp', + // link: 'https://monday.com/', + // }, + // { + // name: 'Asana', + // logo: '/logo/asana.webp', + // link: 'https://asana.com', + // }, + // { + // name: 'Lark', + // logo: '/logo/lark.webp', + // link: 'https://www.larksuite.com/en_us/product/creation', + // }, + // wrike.com...s +] + +export const SupportSsDBCN = [] + +// Mainly as XLS file +export const SupportSsFile: SupportItem[] = [ + { + name: 'Google Sheets', + logo: '/logo/google-sheets.webp', + link: 'https://docs.google.com/spreadsheets/', + }, + { + name: 'Microsoft Excel', + logo: '/logo/microsoft-excel.webp', + link: 'https://www.microsoft.com/en-us/microsoft-365/excel', + }, +] + +// Mainly as XLS file +export const SupportWorkflow: SupportItem[] = [ + { + name: 'Zapier', + logo: '/logo/zapier.webp', + link: 'https://zapier.com/', + }, + { + name: 'n8n', + logo: '/logo/n8n.webp', + link: 'https://n8n.io/', + }, +] diff --git a/ningowood.com/components/home/dashboard/components/date-range-picker.tsx b/ningowood.com/components/home/dashboard/components/date-range-picker.tsx new file mode 100644 index 0000000..03d8758 --- /dev/null +++ b/ningowood.com/components/home/dashboard/components/date-range-picker.tsx @@ -0,0 +1,66 @@ +"use client" + +import * as React from "react" +import { addDays, format } from "date-fns" +import { Calendar as CalendarIcon } from "lucide-react" +import { DateRange } from "react-day-picker" + +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" +import { Calendar } from "@/components/ui/calendar" +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover" + +export function CalendarDateRangePicker({ + className, +}: React.HTMLAttributes) { + const [date, setDate] = React.useState({ + from: new Date(2023, 0, 20), + to: addDays(new Date(2023, 0, 20), 20), + }) + + return ( +
+ + + + + + + + +
+ ) +} diff --git a/ningowood.com/components/home/dashboard/components/main-nav.tsx b/ningowood.com/components/home/dashboard/components/main-nav.tsx new file mode 100644 index 0000000..44358e6 --- /dev/null +++ b/ningowood.com/components/home/dashboard/components/main-nav.tsx @@ -0,0 +1,40 @@ +import Link from "next/link" + +import { cn } from "@/lib/utils" + +export function MainNav({ + className, + ...props +}: React.HTMLAttributes) { + return ( + + ) +} diff --git a/ningowood.com/components/home/dashboard/components/overview.tsx b/ningowood.com/components/home/dashboard/components/overview.tsx new file mode 100644 index 0000000..991a43f --- /dev/null +++ b/ningowood.com/components/home/dashboard/components/overview.tsx @@ -0,0 +1,78 @@ +"use client" + +import { Bar, BarChart, ResponsiveContainer, XAxis, YAxis } from "recharts" + +const data = [ + { + name: "Jan", + total: Math.floor(Math.random() * 500) + 100, + }, + { + name: "Feb", + total: Math.floor(Math.random() * 500) + 100, + }, + { + name: "Mar", + total: Math.floor(Math.random() * 500) + 100, + }, + { + name: "Apr", + total: Math.floor(Math.random() * 500) + 100, + }, + { + name: "May", + total: Math.floor(Math.random() * 500) + 100, + }, + { + name: "Jun", + total: Math.floor(Math.random() * 500) + 100, + }, + { + name: "Jul", + total: Math.floor(Math.random() * 500) + 100, + }, + { + name: "Aug", + total: Math.floor(Math.random() * 500) + 100, + }, + { + name: "Sep", + total: Math.floor(Math.random() * 500) + 100, + }, + { + name: "Oct", + total: Math.floor(Math.random() * 500) + 100, + }, + { + name: "Nov", + total: Math.floor(Math.random() * 500) + 100, + }, + { + name: "Dec", + total: Math.floor(Math.random() * 500) + 100, + }, +] + +export function Overview() { + return ( + + + + `${value}`} + /> + + + + ) +} diff --git a/ningowood.com/components/home/dashboard/components/recent-databases.tsx b/ningowood.com/components/home/dashboard/components/recent-databases.tsx new file mode 100644 index 0000000..ea7277a --- /dev/null +++ b/ningowood.com/components/home/dashboard/components/recent-databases.tsx @@ -0,0 +1,78 @@ +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" + +const RECENT_DATABASE_LIST = [ + { + logo: "/logo/airtable.webp", + type: "Airtable", + author: "hylerrix", + name: "All YC Investment case in one place", + description: "The 2023 investment winds reveal the arrival of the new AI era.", + stars: 9999, + }, + { + logo: "/logo/notion.webp", + type: "Notion", + author: "hylerrix", + name: "My favorite game List", + description: "Including PS, XBox, Switch, Steam, GOG, Epic and more.", + stars: 1593, + }, + { + logo: "/logo/jotform.webp", + type: "Jotform", + author: "hylerrix", + name: "Automation workflow example", + description: "The official Ningowood showcase to control all your workflow.", + stars: 8704, + }, + { + logo: "/logo/rowy.webp", + type: "Rowy", + author: "hylerrix", + name: "Cloud Native Tech Stack", + description: "Chose what you need, all in one. Contribution is welcome.", + stars: 7538, + }, + { + logo: "/logo/baserow.webp", + type: "Baserow", + author: "hylerrix", + name: "Awesome Next.js starter", + description: "Oh my God it's too many! Which one?", + stars: 9326, + }, + { + logo: "/logo/apitable.webp", + type: "Apitable", + author: "hylerrix", + name: "The films I watched", + description: "National Theatre Live: The Lehman Trilogy is my favorite!", + stars: 4276, + }, +] + +export function RecentDatabases() { + return ( +
+ { + RECENT_DATABASE_LIST.map((db, index) => { + return ( +
+ + + OM + +
+

{db.name}

+

+ {db.description} +

+
+
+{db.stars}
+
+ ) + }) + } +
+ ) +} diff --git a/ningowood.com/components/home/dashboard/components/search.tsx b/ningowood.com/components/home/dashboard/components/search.tsx new file mode 100644 index 0000000..004b6c3 --- /dev/null +++ b/ningowood.com/components/home/dashboard/components/search.tsx @@ -0,0 +1,13 @@ +import { Input } from "@/components/ui/input" + +export function Search() { + return ( +
+ +
+ ) +} diff --git a/ningowood.com/components/home/dashboard/components/team-switcher.tsx b/ningowood.com/components/home/dashboard/components/team-switcher.tsx new file mode 100644 index 0000000..3de782e --- /dev/null +++ b/ningowood.com/components/home/dashboard/components/team-switcher.tsx @@ -0,0 +1,205 @@ +"use client" + +import * as React from "react" +import { Check, ChevronsUpDown, PlusCircle } from "lucide-react" + +import { cn } from "@/lib/utils" +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { Button } from "@/components/ui/button" +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, + CommandSeparator, +} from "@/components/ui/command" +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" + +const groups = [ + { + label: "Personal Account", + teams: [ + { + label: "Alicia Koch", + value: "personal", + }, + ], + }, + { + label: "Teams", + teams: [ + { + label: "Acme Inc.", + value: "acme-inc", + }, + { + label: "Monsters Inc.", + value: "monsters", + }, + ], + }, +] + +type Team = (typeof groups)[number]["teams"][number] + +type PopoverTriggerProps = React.ComponentPropsWithoutRef + +interface TeamSwitcherProps extends PopoverTriggerProps {} + +export default function TeamSwitcher({ className }: TeamSwitcherProps) { + const [open, setOpen] = React.useState(false) + const [showNewTeamDialog, setShowNewTeamDialog] = React.useState(false) + const [selectedTeam, setSelectedTeam] = React.useState( + groups[0].teams[0], + ) + + return ( + + + + + + + + + + No team found. + {groups.map((group) => ( + + {group.teams.map((team) => ( + { + setSelectedTeam(team) + setOpen(false) + }} + className="text-sm" + > + + + SC + + {team.label} + + + ))} + + ))} + + + + + + { + setOpen(false) + setShowNewTeamDialog(true) + }} + > + + Create Team + + + + + + + + + + Create team + + Add a new team to manage products and customers. + + +
+
+
+ + +
+
+ + +
+
+
+ + + + +
+
+ ) +} diff --git a/ningowood.com/components/home/dashboard/components/user-nav.tsx b/ningowood.com/components/home/dashboard/components/user-nav.tsx new file mode 100644 index 0000000..49256f4 --- /dev/null +++ b/ningowood.com/components/home/dashboard/components/user-nav.tsx @@ -0,0 +1,67 @@ +import { CreditCard, LogOut, PlusCircle, Settings, User } from "lucide-react" + +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" + +export function UserNav() { + return ( + + + + + + +
+

shadcn

+

+ m@example.com +

+
+
+ + + + + Profile + ⇧⌘P + + + + Billing + ⌘B + + + + Settings + ⌘S + + + + New Team + + + + + + Log out + ⇧⌘Q + +
+
+ ) +} diff --git a/ningowood.com/components/home/dashboard/page.tsx b/ningowood.com/components/home/dashboard/page.tsx new file mode 100644 index 0000000..25f2e6d --- /dev/null +++ b/ningowood.com/components/home/dashboard/page.tsx @@ -0,0 +1,126 @@ +import { Metadata } from "next" +import Image from "next/image" +import { + Database, + GitFork, + Star, + Users, +} from "lucide-react" + +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card" + +import { Overview } from "./components/overview" +import { RecentDatabases } from "./components/recent-databases" + +export const metadata: Metadata = { + title: "Dashboard", + description: "Example dashboard app using the components.", +} + +export default function DashboardPage() { + return ( + <> +
+ Dashboard + Dashboard +
+
+
+
+ + + + Total databases + + + + +
9,769
+

+ +20.1% from last month +

+
+
+ + + + Total users + + + + +
+231
+

+ +180.1% from last month +

+
+
+ + + Forks + + + +
+684
+

+ +19% from last month +

+
+
+ + + Stars + + + +
+573
+

+ +201 since last hour +

+
+
+
+
+ + + Overview + + + + + + + + Recent databases + + 265 databases uploaded this month. + + + + + + +
+
+
+ + ) +} diff --git a/ningowood.com/components/home/demo-modal.tsx b/ningowood.com/components/home/demo-modal.tsx index 2bdcc5f..482335b 100644 --- a/ningowood.com/components/home/demo-modal.tsx +++ b/ningowood.com/components/home/demo-modal.tsx @@ -1,19 +1,13 @@ -import Modal from "@/components/shared/modal"; -import { - useState, - Dispatch, - SetStateAction, - useCallback, - useMemo, -} from "react"; -import Image from "next/image"; +import Modal from "@/components/shared/modal" +import { useState, Dispatch, SetStateAction, useCallback, useMemo } from "react" +import Image from "next/image" const DemoModal = ({ showDemoModal, setShowDemoModal, }: { - showDemoModal: boolean; - setShowDemoModal: Dispatch>; + showDemoModal: boolean + setShowDemoModal: Dispatch> }) => { return ( @@ -36,11 +30,11 @@ const DemoModal = ({ - ); -}; + ) +} export function useDemoModal() { - const [showDemoModal, setShowDemoModal] = useState(false); + const [showDemoModal, setShowDemoModal] = useState(false) const DemoModalCallback = useCallback(() => { return ( @@ -48,11 +42,11 @@ export function useDemoModal() { showDemoModal={showDemoModal} setShowDemoModal={setShowDemoModal} /> - ); - }, [showDemoModal, setShowDemoModal]); + ) + }, [showDemoModal, setShowDemoModal]) return useMemo( () => ({ setShowDemoModal, DemoModal: DemoModalCallback }), [setShowDemoModal, DemoModalCallback], - ); + ) } diff --git a/ningowood.com/components/home/future-app-preview.tsx b/ningowood.com/components/home/future-app-preview.tsx new file mode 100644 index 0000000..2ca47e1 --- /dev/null +++ b/ningowood.com/components/home/future-app-preview.tsx @@ -0,0 +1,43 @@ +import Balancer from "react-wrap-balancer" + +export default function HomeIntroHeader() { + return ( +
+

Future App Preview

+ +

+ + Flowchats AI + +

+

+ + Your all-in-one AI chat app in canvas tree, and save it into LifeTable. + +

+ +

+ + Navigator AI + +

+

+ + Web nav manager in AI era, forget about your outdated browser bookmarks. + +

+
+ ) +} diff --git a/ningowood.com/components/home/home-Intro-header.tsx b/ningowood.com/components/home/home-Intro-header.tsx new file mode 100644 index 0000000..3502937 --- /dev/null +++ b/ningowood.com/components/home/home-Intro-header.tsx @@ -0,0 +1,147 @@ +import Balancer from "react-wrap-balancer" +import Image from "next/image" + +import { nFormatter } from "@/lib/utils" +import { DEPLOY_URL } from "@/lib/constants" +import { Github, Twitter } from "@/components/shared/icons" +import { SupportSsDB } from "./constant" +import { SupportItem } from "./type" + +interface SupportItemProps { + db: SupportItem +} + +const SupportItem = ({ db }: SupportItemProps) => { + return ( + + {db.name} + + ) +} + +export default function HomeIntroHeader() { + // const { stargazers_count: stars } = await fetch( + // "https://api.github.com/repos/ningowood/ningowood", + // { + // ...(process.env.GITHUB_OAUTH_TOKEN && { + // headers: { + // Authorization: `Bearer ${process.env.GITHUB_OAUTH_TOKEN}`, + // "Content-Type": "application/json", + // }, + // }), + // // data will revalidate every 60 seconds + // next: { revalidate: 60 }, + // }, + // ) + // .then((res) => res.json()) + // .catch((e) => console.log(e)) + + return ( +
+ + +

+ Introducing Ningowood v0.2 +

+
+ +
+

+ + Introducing 1st CORE APP in micro app market: LifeTable! + +

+

+ + Add the missing all-in-one community to the spreadsheet database ecology + +

+

+ + Make the structured data all together, and sharing as easy as you wish. + +

+
+ { SupportSsDB.map((db, index) => ) } + ... +
+ + +
+ + +
+ ) +} diff --git a/ningowood.com/components/home/type.tsx b/ningowood.com/components/home/type.tsx new file mode 100644 index 0000000..01b62ed --- /dev/null +++ b/ningowood.com/components/home/type.tsx @@ -0,0 +1,5 @@ +export interface SupportItem { + name: string + logo: string + link: string +} diff --git a/ningowood.com/components/home/web-vitals.tsx b/ningowood.com/components/home/web-vitals.tsx deleted file mode 100644 index 662333d..0000000 --- a/ningowood.com/components/home/web-vitals.tsx +++ /dev/null @@ -1,39 +0,0 @@ -"use client"; - -import { motion } from "framer-motion"; -import CountingNumbers from "@/components/shared/counting-numbers"; - -export default function WebVitals() { - return ( -
- - - - -
- ); -} diff --git a/ningowood.com/components/layout/footer.tsx b/ningowood.com/components/layout/footer.tsx index ed7e994..02f1808 100644 --- a/ningowood.com/components/layout/footer.tsx +++ b/ningowood.com/components/layout/footer.tsx @@ -2,16 +2,43 @@ export default function Footer() { return (

- A free template by{" "} + Currently powered by  - Steven Tey + Precedent + + ,  + + Shadcn UI + + ,  + + Taxonomy + +  and  + + Preline UI

- ); + ) } diff --git a/ningowood.com/components/layout/nav.tsx b/ningowood.com/components/layout/nav.tsx index ba62b01..121699a 100644 --- a/ningowood.com/components/layout/nav.tsx +++ b/ningowood.com/components/layout/nav.tsx @@ -1,8 +1,8 @@ -import Navbar from "./navbar"; -import { getServerSession } from "next-auth/next"; -import { authOptions } from "@/app/api/auth/[...nextauth]/route"; +import Navbar from "./navbar" +import { getServerSession } from "next-auth/next" +import { authOptions } from "@/app/api/auth/[...nextauth]/route" export default async function Nav() { - const session = await getServerSession(authOptions); - return ; + const session = await getServerSession(authOptions) + return } diff --git a/ningowood.com/components/layout/navbar.tsx b/ningowood.com/components/layout/navbar.tsx index ea0a512..d7e88f0 100644 --- a/ningowood.com/components/layout/navbar.tsx +++ b/ningowood.com/components/layout/navbar.tsx @@ -1,15 +1,15 @@ -"use client"; +"use client" -import Image from "next/image"; -import Link from "next/link"; -import useScroll from "@/lib/hooks/use-scroll"; -import { useSignInModal } from "./sign-in-modal"; -import UserDropdown from "./user-dropdown"; -import { Session } from "next-auth"; +import Image from "next/image" +import Link from "next/link" +import useScroll from "@/lib/hooks/use-scroll" +import { useSignInModal } from "./sign-in-modal" +import UserDropdown from "./user-dropdown" +import { Session } from "next-auth" export default function NavBar({ session }: { session: Session | null }) { - const { SignInModal, setShowSignInModal } = useSignInModal(); - const scrolled = useScroll(50); + const { SignInModal, setShowSignInModal } = useSignInModal() + const scrolled = useScroll(50) return ( <> @@ -25,12 +25,12 @@ export default function NavBar({ session }: { session: Session | null }) { Precedent logo -

Precedent

+

Ningowood

{session ? ( @@ -47,5 +47,5 @@ export default function NavBar({ session }: { session: Session | null }) {
- ); + ) } diff --git a/ningowood.com/components/layout/sign-in-modal.tsx b/ningowood.com/components/layout/sign-in-modal.tsx index 17b5021..e97454b 100644 --- a/ningowood.com/components/layout/sign-in-modal.tsx +++ b/ningowood.com/components/layout/sign-in-modal.tsx @@ -1,23 +1,17 @@ -import Modal from "@/components/shared/modal"; -import { signIn } from "next-auth/react"; -import { - useState, - Dispatch, - SetStateAction, - useCallback, - useMemo, -} from "react"; -import { LoadingDots, Google } from "@/components/shared/icons"; -import Image from "next/image"; +import Modal from "@/components/shared/modal" +import { signIn } from "next-auth/react" +import { useState, Dispatch, SetStateAction, useCallback, useMemo } from "react" +import { LoadingDots, Google } from "@/components/shared/icons" +import Image from "next/image" const SignInModal = ({ showSignInModal, setShowSignInModal, }: { - showSignInModal: boolean; - setShowSignInModal: Dispatch>; + showSignInModal: boolean + setShowSignInModal: Dispatch> }) => { - const [signInClicked, setSignInClicked] = useState(false); + const [signInClicked, setSignInClicked] = useState(false) return ( @@ -48,8 +42,8 @@ const SignInModal = ({ : "border border-gray-200 bg-white text-black hover:bg-gray-50" } flex h-10 w-full items-center justify-center space-x-3 rounded-md border text-sm shadow-sm transition-all duration-75 focus:outline-none`} onClick={() => { - setSignInClicked(true); - signIn("google"); + setSignInClicked(true) + signIn("google") }} > {signInClicked ? ( @@ -64,11 +58,11 @@ const SignInModal = ({ - ); -}; + ) +} export function useSignInModal() { - const [showSignInModal, setShowSignInModal] = useState(false); + const [showSignInModal, setShowSignInModal] = useState(false) const SignInModalCallback = useCallback(() => { return ( @@ -76,11 +70,11 @@ export function useSignInModal() { showSignInModal={showSignInModal} setShowSignInModal={setShowSignInModal} /> - ); - }, [showSignInModal, setShowSignInModal]); + ) + }, [showSignInModal, setShowSignInModal]) return useMemo( () => ({ setShowSignInModal, SignInModal: SignInModalCallback }), [setShowSignInModal, SignInModalCallback], - ); + ) } diff --git a/ningowood.com/components/layout/user-dropdown.tsx b/ningowood.com/components/layout/user-dropdown.tsx index b9c9c1a..8a53e7e 100644 --- a/ningowood.com/components/layout/user-dropdown.tsx +++ b/ningowood.com/components/layout/user-dropdown.tsx @@ -1,17 +1,17 @@ -"use client"; +"use client" -import { useState } from "react"; -import { signOut } from "next-auth/react"; -import { LayoutDashboard, LogOut } from "lucide-react"; -import Popover from "@/components/shared/popover"; -import Image from "next/image"; -import { Session } from "next-auth"; +import { useState } from "react" +import { signOut } from "next-auth/react" +import { LayoutDashboard, LogOut } from "lucide-react" +import Popover from "@/components/shared/popover" +import Image from "next/image" +import { Session } from "next-auth" export default function UserDropdown({ session }: { session: Session }) { - const { email, image } = session?.user || {}; - const [openPopover, setOpenPopover] = useState(false); + const { email, image } = session?.user || {} + const [openPopover, setOpenPopover] = useState(false) - if (!email) return null; + if (!email) return null return (
@@ -58,5 +58,5 @@ export default function UserDropdown({ session }: { session: Session }) {
- ); + ) } diff --git a/ningowood.com/components/shared/counting-numbers.tsx b/ningowood.com/components/shared/counting-numbers.tsx index bfd3a37..bf6e554 100644 --- a/ningowood.com/components/shared/counting-numbers.tsx +++ b/ningowood.com/components/shared/counting-numbers.tsx @@ -1,6 +1,6 @@ -"use client"; +"use client" -import { useEffect, useState } from "react"; +import { useEffect, useState } from "react" export default function CountingNumbers({ value, @@ -8,33 +8,33 @@ export default function CountingNumbers({ start = 0, duration = 800, }: { - value: number; - className: string; - start?: number; - duration?: number; + value: number + className: string + start?: number + duration?: number }) { - const [count, setCount] = useState(start); + const [count, setCount] = useState(start) useEffect(() => { - let startTime: number | undefined; + let startTime: number | undefined const animateCount = (timestamp: number) => { - if (!startTime) startTime = timestamp; - const timePassed = timestamp - startTime; - const progress = timePassed / duration; - const currentCount = easeOutQuad(progress, 0, value, 1); + if (!startTime) startTime = timestamp + const timePassed = timestamp - startTime + const progress = timePassed / duration + const currentCount = easeOutQuad(progress, 0, value, 1) if (currentCount >= value) { - setCount(value); - return; + setCount(value) + return } - setCount(currentCount); - requestAnimationFrame(animateCount); - }; - requestAnimationFrame(animateCount); - }, [value, duration]); + setCount(currentCount) + requestAnimationFrame(animateCount) + } + requestAnimationFrame(animateCount) + }, [value, duration]) - return

{Intl.NumberFormat().format(count)}

; + return

{Intl.NumberFormat().format(count)}

} const easeOutQuad = (t: number, b: number, c: number, d: number) => { - t = t > d ? d : t / d; - return Math.round(-c * t * (t - 2) + b); -}; + t = t > d ? d : t / d + return Math.round(-c * t * (t - 2) + b) +} diff --git a/ningowood.com/components/shared/icons/expanding-arrow.tsx b/ningowood.com/components/shared/icons/expanding-arrow.tsx index 819fd74..6f44c37 100644 --- a/ningowood.com/components/shared/icons/expanding-arrow.tsx +++ b/ningowood.com/components/shared/icons/expanding-arrow.tsx @@ -32,5 +32,5 @@ export default function ExpandingArrow({ className }: { className?: string }) { > - ); + ) } diff --git a/ningowood.com/components/shared/icons/github.tsx b/ningowood.com/components/shared/icons/github.tsx index ff13f39..c69d76c 100644 --- a/ningowood.com/components/shared/icons/github.tsx +++ b/ningowood.com/components/shared/icons/github.tsx @@ -10,5 +10,5 @@ export default function Github({ className }: { className?: string }) { > - ); + ) } diff --git a/ningowood.com/components/shared/icons/google.tsx b/ningowood.com/components/shared/icons/google.tsx index 660f7b7..33e705b 100644 --- a/ningowood.com/components/shared/icons/google.tsx +++ b/ningowood.com/components/shared/icons/google.tsx @@ -43,5 +43,5 @@ export default function Google({ className }: { className: string }) { d="M50 69.8a19.8 19.8 90 1 0 0-39.6 19.8 19.8 90 0 0 0 39.6z" />{" "} - ); + ) } diff --git a/ningowood.com/components/shared/icons/index.tsx b/ningowood.com/components/shared/icons/index.tsx index 1795504..6edfb53 100644 --- a/ningowood.com/components/shared/icons/index.tsx +++ b/ningowood.com/components/shared/icons/index.tsx @@ -1,7 +1,7 @@ -export { default as LoadingDots } from "./loading-dots"; -export { default as LoadingCircle } from "./loading-circle"; -export { default as LoadingSpinner } from "./loading-spinner"; -export { default as ExpandingArrow } from "./expanding-arrow"; -export { default as Github } from "./github"; -export { default as Twitter } from "./twitter"; -export { default as Google } from "./google"; +export { default as LoadingDots } from "./loading-dots" +export { default as LoadingCircle } from "./loading-circle" +export { default as LoadingSpinner } from "./loading-spinner" +export { default as ExpandingArrow } from "./expanding-arrow" +export { default as Github } from "./github" +export { default as Twitter } from "./twitter" +export { default as Google } from "./google" diff --git a/ningowood.com/components/shared/icons/loading-circle.tsx b/ningowood.com/components/shared/icons/loading-circle.tsx index 4649275..d09642e 100644 --- a/ningowood.com/components/shared/icons/loading-circle.tsx +++ b/ningowood.com/components/shared/icons/loading-circle.tsx @@ -16,5 +16,5 @@ export default function LoadingCircle() { fill="currentFill" /> - ); + ) } diff --git a/ningowood.com/components/shared/icons/loading-dots.tsx b/ningowood.com/components/shared/icons/loading-dots.tsx index 23ebed0..2bc2d72 100644 --- a/ningowood.com/components/shared/icons/loading-dots.tsx +++ b/ningowood.com/components/shared/icons/loading-dots.tsx @@ -1,4 +1,4 @@ -import styles from "./loading-dots.module.css"; +import styles from "./loading-dots.module.css" const LoadingDots = ({ color = "#000" }: { color?: string }) => { return ( @@ -7,7 +7,7 @@ const LoadingDots = ({ color = "#000" }: { color?: string }) => { - ); -}; + ) +} -export default LoadingDots; +export default LoadingDots diff --git a/ningowood.com/components/shared/icons/loading-spinner.tsx b/ningowood.com/components/shared/icons/loading-spinner.tsx index 1c8e704..fb66008 100644 --- a/ningowood.com/components/shared/icons/loading-spinner.tsx +++ b/ningowood.com/components/shared/icons/loading-spinner.tsx @@ -1,4 +1,4 @@ -import styles from "./loading-spinner.module.css"; +import styles from "./loading-spinner.module.css" export default function LoadingSpinner() { return ( @@ -16,5 +16,5 @@ export default function LoadingSpinner() {
- ); + ) } diff --git a/ningowood.com/components/shared/icons/twitter.tsx b/ningowood.com/components/shared/icons/twitter.tsx index 693309d..c41999d 100644 --- a/ningowood.com/components/shared/icons/twitter.tsx +++ b/ningowood.com/components/shared/icons/twitter.tsx @@ -10,5 +10,5 @@ export default function Twitter({ className }: { className?: string }) { d="M221.95 51.29c.15 2.17.15 4.34.15 6.53 0 66.73-50.8 143.69-143.69 143.69v-.04c-27.44.04-54.31-7.82-77.41-22.64 3.99.48 8 .72 12.02.73 22.74.02 44.83-7.61 62.72-21.66-21.61-.41-40.56-14.5-47.18-35.07 7.57 1.46 15.37 1.16 22.8-.87-23.56-4.76-40.51-25.46-40.51-49.5v-.64c7.02 3.91 14.88 6.08 22.92 6.32C11.58 63.31 4.74 33.79 18.14 10.71c25.64 31.55 63.47 50.73 104.08 52.76-4.07-17.54 1.49-35.92 14.61-48.25 20.34-19.12 52.33-18.14 71.45 2.19 11.31-2.23 22.15-6.38 32.07-12.26-3.77 11.69-11.66 21.62-22.2 27.93 10.01-1.18 19.79-3.86 29-7.95-6.78 10.16-15.32 19.01-25.2 26.16z" /> - ); + ) } diff --git a/ningowood.com/components/shared/leaflet.tsx b/ningowood.com/components/shared/leaflet.tsx index e5eaa6d..e921e01 100644 --- a/ningowood.com/components/shared/leaflet.tsx +++ b/ningowood.com/components/shared/leaflet.tsx @@ -1,33 +1,33 @@ -import { useEffect, useRef, ReactNode, Dispatch, SetStateAction } from "react"; -import { AnimatePresence, motion, useAnimation } from "framer-motion"; +import { useEffect, useRef, ReactNode, Dispatch, SetStateAction } from "react" +import { AnimatePresence, motion, useAnimation } from "framer-motion" export default function Leaflet({ setShow, children, }: { - setShow: Dispatch>; - children: ReactNode; + setShow: Dispatch> + children: ReactNode }) { - const leafletRef = useRef(null); - const controls = useAnimation(); - const transitionProps = { type: "spring", stiffness: 500, damping: 30 }; + const leafletRef = useRef(null) + const controls = useAnimation() + const transitionProps = { type: "spring", stiffness: 500, damping: 30 } useEffect(() => { controls.start({ y: 20, transition: transitionProps, - }); + }) // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, []) async function handleDragEnd(_: any, info: any) { - const offset = info.offset.y; - const velocity = info.velocity.y; - const height = leafletRef.current?.getBoundingClientRect().height || 0; + const offset = info.offset.y + const velocity = info.velocity.y + const height = leafletRef.current?.getBoundingClientRect().height || 0 if (offset > height / 2 || velocity > 800) { - await controls.start({ y: "100%", transition: transitionProps }); - setShow(false); + await controls.start({ y: "100%", transition: transitionProps }) + setShow(false) } else { - controls.start({ y: 0, transition: transitionProps }); + controls.start({ y: 0, transition: transitionProps }) } } @@ -64,5 +64,5 @@ export default function Leaflet({ onClick={() => setShow(false)} /> - ); + ) } diff --git a/ningowood.com/components/shared/modal.tsx b/ningowood.com/components/shared/modal.tsx index 409b9d6..019ca0b 100644 --- a/ningowood.com/components/shared/modal.tsx +++ b/ningowood.com/components/shared/modal.tsx @@ -1,43 +1,37 @@ -"use client"; +"use client" -import { - Dispatch, - SetStateAction, - useCallback, - useEffect, - useRef, -} from "react"; -import FocusTrap from "focus-trap-react"; -import { AnimatePresence, motion } from "framer-motion"; -import Leaflet from "./leaflet"; -import useWindowSize from "@/lib/hooks/use-window-size"; +import { Dispatch, SetStateAction, useCallback, useEffect, useRef } from "react" +import FocusTrap from "focus-trap-react" +import { AnimatePresence, motion } from "framer-motion" +import Leaflet from "./leaflet" +import useWindowSize from "@/lib/hooks/use-window-size" export default function Modal({ children, showModal, setShowModal, }: { - children: React.ReactNode; - showModal: boolean; - setShowModal: Dispatch>; + children: React.ReactNode + showModal: boolean + setShowModal: Dispatch> }) { - const desktopModalRef = useRef(null); + const desktopModalRef = useRef(null) const onKeyDown = useCallback( (e: KeyboardEvent) => { if (e.key === "Escape") { - setShowModal(false); + setShowModal(false) } }, [setShowModal], - ); + ) useEffect(() => { - document.addEventListener("keydown", onKeyDown); - return () => document.removeEventListener("keydown", onKeyDown); - }, [onKeyDown]); + document.addEventListener("keydown", onKeyDown) + return () => document.removeEventListener("keydown", onKeyDown) + }, [onKeyDown]) - const { isMobile, isDesktop } = useWindowSize(); + const { isMobile, isDesktop } = useWindowSize() return ( @@ -56,7 +50,7 @@ export default function Modal({ exit={{ scale: 0.95 }} onMouseDown={(e) => { if (desktopModalRef.current === e.target) { - setShowModal(false); + setShowModal(false) } }} > @@ -76,5 +70,5 @@ export default function Modal({ )} - ); + ) } diff --git a/ningowood.com/components/shared/popover.tsx b/ningowood.com/components/shared/popover.tsx index 61a3e9b..d02cded 100644 --- a/ningowood.com/components/shared/popover.tsx +++ b/ningowood.com/components/shared/popover.tsx @@ -1,9 +1,9 @@ -"use client"; +"use client" -import { Dispatch, SetStateAction, ReactNode, useRef } from "react"; -import * as PopoverPrimitive from "@radix-ui/react-popover"; -import useWindowSize from "@/lib/hooks/use-window-size"; -import Leaflet from "./leaflet"; +import { Dispatch, SetStateAction, ReactNode, useRef } from "react" +import * as PopoverPrimitive from "@radix-ui/react-popover" +import useWindowSize from "@/lib/hooks/use-window-size" +import Leaflet from "./leaflet" export default function Popover({ children, @@ -12,14 +12,14 @@ export default function Popover({ openPopover, setOpenPopover, }: { - children: ReactNode; - content: ReactNode | string; - align?: "center" | "start" | "end"; - openPopover: boolean; - setOpenPopover: Dispatch>; + children: ReactNode + content: ReactNode | string + align?: "center" | "start" | "end" + openPopover: boolean + setOpenPopover: Dispatch> }) { - const { isMobile, isDesktop } = useWindowSize(); - if (!isMobile && !isDesktop) return <>{children}; + const { isMobile, isDesktop } = useWindowSize() + if (!isMobile && !isDesktop) return <>{children} return ( <> {isMobile && children} @@ -44,5 +44,5 @@ export default function Popover({ )} - ); + ) } diff --git a/ningowood.com/components/shared/tooltip.tsx b/ningowood.com/components/shared/tooltip.tsx index 2a45919..ae1762e 100644 --- a/ningowood.com/components/shared/tooltip.tsx +++ b/ningowood.com/components/shared/tooltip.tsx @@ -1,22 +1,22 @@ -"use client"; +"use client" -import { ReactNode, useState } from "react"; -import * as TooltipPrimitive from "@radix-ui/react-tooltip"; -import useWindowSize from "@/lib/hooks/use-window-size"; -import Leaflet from "./leaflet"; +import { ReactNode, useState } from "react" +import * as TooltipPrimitive from "@radix-ui/react-tooltip" +import useWindowSize from "@/lib/hooks/use-window-size" +import Leaflet from "./leaflet" export default function Tooltip({ children, content, fullWidth, }: { - children: ReactNode; - content: ReactNode | string; - fullWidth?: boolean; + children: ReactNode + content: ReactNode | string + fullWidth?: boolean }) { - const [openTooltip, setOpenTooltip] = useState(false); + const [openTooltip, setOpenTooltip] = useState(false) - const { isMobile, isDesktop } = useWindowSize(); + const { isMobile, isDesktop } = useWindowSize() return ( <> @@ -67,5 +67,5 @@ export default function Tooltip({ )} - ); + ) } diff --git a/ningowood.com/components/ui/accordion.tsx b/ningowood.com/components/ui/accordion.tsx new file mode 100644 index 0000000..6181f2e --- /dev/null +++ b/ningowood.com/components/ui/accordion.tsx @@ -0,0 +1,60 @@ +"use client" + +import * as React from "react" +import * as AccordionPrimitive from "@radix-ui/react-accordion" +import { ChevronDown } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Accordion = AccordionPrimitive.Root + +const AccordionItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AccordionItem.displayName = "AccordionItem" + +const AccordionTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + svg]:rotate-180", + className, + )} + {...props} + > + {children} + + + +)) +AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName + +const AccordionContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + +
{children}
+
+)) +AccordionContent.displayName = AccordionPrimitive.Content.displayName + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/ningowood.com/components/ui/alert-dialog.tsx b/ningowood.com/components/ui/alert-dialog.tsx new file mode 100644 index 0000000..caca50d --- /dev/null +++ b/ningowood.com/components/ui/alert-dialog.tsx @@ -0,0 +1,150 @@ +"use client" + +import * as React from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +const AlertDialog = AlertDialogPrimitive.Root + +const AlertDialogTrigger = AlertDialogPrimitive.Trigger + +const AlertDialogPortal = ({ + className, + children, + ...props +}: AlertDialogPrimitive.AlertDialogPortalProps) => ( + +
+ {children} +
+
+) +AlertDialogPortal.displayName = AlertDialogPrimitive.Portal.displayName + +const AlertDialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + +)) +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName + +const AlertDialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + +)) +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName + +const AlertDialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogHeader.displayName = "AlertDialogHeader" + +const AlertDialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogFooter.displayName = "AlertDialogFooter" + +const AlertDialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName + +const AlertDialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogDescription.displayName = + AlertDialogPrimitive.Description.displayName + +const AlertDialogAction = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName + +const AlertDialogCancel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName + +export { + AlertDialog, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +} diff --git a/ningowood.com/components/ui/alert.tsx b/ningowood.com/components/ui/alert.tsx new file mode 100644 index 0000000..b04660d --- /dev/null +++ b/ningowood.com/components/ui/alert.tsx @@ -0,0 +1,59 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const alertVariants = cva( + "relative w-full rounded-lg border p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11", + { + variants: { + variant: { + default: "bg-background text-foreground", + destructive: + "text-destructive border-destructive/50 dark:border-destructive [&>svg]:text-destructive text-destructive", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +) + +const Alert = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & VariantProps +>(({ className, variant, ...props }, ref) => ( +
+)) +Alert.displayName = "Alert" + +const AlertTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertTitle.displayName = "AlertTitle" + +const AlertDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertDescription.displayName = "AlertDescription" + +export { Alert, AlertTitle, AlertDescription } diff --git a/ningowood.com/components/ui/aspect-ratio.tsx b/ningowood.com/components/ui/aspect-ratio.tsx new file mode 100644 index 0000000..d6a5226 --- /dev/null +++ b/ningowood.com/components/ui/aspect-ratio.tsx @@ -0,0 +1,7 @@ +"use client" + +import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" + +const AspectRatio = AspectRatioPrimitive.Root + +export { AspectRatio } diff --git a/ningowood.com/components/ui/avatar.tsx b/ningowood.com/components/ui/avatar.tsx new file mode 100644 index 0000000..4fe7e48 --- /dev/null +++ b/ningowood.com/components/ui/avatar.tsx @@ -0,0 +1,50 @@ +"use client" + +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/ningowood.com/components/ui/badge.tsx b/ningowood.com/components/ui/badge.tsx new file mode 100644 index 0000000..4b0b0d4 --- /dev/null +++ b/ningowood.com/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center border rounded-full px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "bg-primary hover:bg-primary/80 border-transparent text-primary-foreground", + secondary: + "bg-secondary hover:bg-secondary/80 border-transparent text-secondary-foreground", + destructive: + "bg-destructive hover:bg-destructive/80 border-transparent text-destructive-foreground", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +) + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ) +} + +export { Badge, badgeVariants } diff --git a/ningowood.com/components/ui/button.tsx b/ningowood.com/components/ui/button.tsx new file mode 100644 index 0000000..9af0374 --- /dev/null +++ b/ningowood.com/components/ui/button.tsx @@ -0,0 +1,55 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "underline-offset-4 hover:underline text-primary", + }, + size: { + default: "h-10 py-2 px-4", + sm: "h-9 px-3 rounded-md", + lg: "h-11 px-8 rounded-md", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + }, +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/ningowood.com/components/ui/calendar.tsx b/ningowood.com/components/ui/calendar.tsx new file mode 100644 index 0000000..9b43a3d --- /dev/null +++ b/ningowood.com/components/ui/calendar.tsx @@ -0,0 +1,64 @@ +"use client" + +import * as React from "react" +import { ChevronLeft, ChevronRight } from "lucide-react" +import { DayPicker } from "react-day-picker" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +export type CalendarProps = React.ComponentProps + +function Calendar({ + className, + classNames, + showOutsideDays = true, + ...props +}: CalendarProps) { + return ( + , + IconRight: ({ ...props }) => , + }} + {...props} + /> + ) +} +Calendar.displayName = "Calendar" + +export { Calendar } diff --git a/ningowood.com/components/ui/card.tsx b/ningowood.com/components/ui/card.tsx new file mode 100644 index 0000000..7cd9edd --- /dev/null +++ b/ningowood.com/components/ui/card.tsx @@ -0,0 +1,79 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/ningowood.com/components/ui/checkbox.tsx b/ningowood.com/components/ui/checkbox.tsx new file mode 100644 index 0000000..99edf93 --- /dev/null +++ b/ningowood.com/components/ui/checkbox.tsx @@ -0,0 +1,30 @@ +"use client" + +import * as React from "react" +import * as CheckboxPrimitive from "@radix-ui/react-checkbox" +import { Check } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Checkbox = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + +)) +Checkbox.displayName = CheckboxPrimitive.Root.displayName + +export { Checkbox } diff --git a/ningowood.com/components/ui/collapsible.tsx b/ningowood.com/components/ui/collapsible.tsx new file mode 100644 index 0000000..9fa4894 --- /dev/null +++ b/ningowood.com/components/ui/collapsible.tsx @@ -0,0 +1,11 @@ +"use client" + +import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" + +const Collapsible = CollapsiblePrimitive.Root + +const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger + +const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent + +export { Collapsible, CollapsibleTrigger, CollapsibleContent } diff --git a/ningowood.com/components/ui/command.tsx b/ningowood.com/components/ui/command.tsx new file mode 100644 index 0000000..2dac0e4 --- /dev/null +++ b/ningowood.com/components/ui/command.tsx @@ -0,0 +1,155 @@ +"use client" + +import * as React from "react" +import { DialogProps } from "@radix-ui/react-dialog" +import { Command as CommandPrimitive } from "cmdk" +import { Search } from "lucide-react" + +import { cn } from "@/lib/utils" +import { Dialog, DialogContent } from "@/components/ui/dialog" + +const Command = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Command.displayName = CommandPrimitive.displayName + +interface CommandDialogProps extends DialogProps {} + +const CommandDialog = ({ children, ...props }: CommandDialogProps) => { + return ( + + + + {children} + + + + ) +} + +const CommandInput = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( +
+ + +
+)) + +CommandInput.displayName = CommandPrimitive.Input.displayName + +const CommandList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandList.displayName = CommandPrimitive.List.displayName + +const CommandEmpty = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>((props, ref) => ( + +)) + +CommandEmpty.displayName = CommandPrimitive.Empty.displayName + +const CommandGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandGroup.displayName = CommandPrimitive.Group.displayName + +const CommandSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +CommandSeparator.displayName = CommandPrimitive.Separator.displayName + +const CommandItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandItem.displayName = CommandPrimitive.Item.displayName + +const CommandShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +CommandShortcut.displayName = "CommandShortcut" + +export { + Command, + CommandDialog, + CommandInput, + CommandList, + CommandEmpty, + CommandGroup, + CommandItem, + CommandShortcut, + CommandSeparator, +} diff --git a/ningowood.com/components/ui/context-menu.tsx b/ningowood.com/components/ui/context-menu.tsx new file mode 100644 index 0000000..12aba44 --- /dev/null +++ b/ningowood.com/components/ui/context-menu.tsx @@ -0,0 +1,200 @@ +"use client" + +import * as React from "react" +import * as ContextMenuPrimitive from "@radix-ui/react-context-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const ContextMenu = ContextMenuPrimitive.Root + +const ContextMenuTrigger = ContextMenuPrimitive.Trigger + +const ContextMenuGroup = ContextMenuPrimitive.Group + +const ContextMenuPortal = ContextMenuPrimitive.Portal + +const ContextMenuSub = ContextMenuPrimitive.Sub + +const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup + +const ContextMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName + +const ContextMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName + +const ContextMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName + +const ContextMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName + +const ContextMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +ContextMenuCheckboxItem.displayName = + ContextMenuPrimitive.CheckboxItem.displayName + +const ContextMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName + +const ContextMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName + +const ContextMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName + +const ContextMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +ContextMenuShortcut.displayName = "ContextMenuShortcut" + +export { + ContextMenu, + ContextMenuTrigger, + ContextMenuContent, + ContextMenuItem, + ContextMenuCheckboxItem, + ContextMenuRadioItem, + ContextMenuLabel, + ContextMenuSeparator, + ContextMenuShortcut, + ContextMenuGroup, + ContextMenuPortal, + ContextMenuSub, + ContextMenuSubContent, + ContextMenuSubTrigger, + ContextMenuRadioGroup, +} diff --git a/ningowood.com/components/ui/dialog.tsx b/ningowood.com/components/ui/dialog.tsx new file mode 100644 index 0000000..1810c92 --- /dev/null +++ b/ningowood.com/components/ui/dialog.tsx @@ -0,0 +1,128 @@ +"use client" + +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = ({ + className, + children, + ...props +}: DialogPrimitive.DialogPortalProps) => ( + +
+ {children} +
+
+) +DialogPortal.displayName = DialogPrimitive.Portal.displayName + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = "DialogHeader" + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = "DialogFooter" + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/ningowood.com/components/ui/dropdown-menu.tsx b/ningowood.com/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..1a2aa8b --- /dev/null +++ b/ningowood.com/components/ui/dropdown-menu.tsx @@ -0,0 +1,200 @@ +"use client" + +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} diff --git a/ningowood.com/components/ui/hover-card.tsx b/ningowood.com/components/ui/hover-card.tsx new file mode 100644 index 0000000..83d606b --- /dev/null +++ b/ningowood.com/components/ui/hover-card.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import * as HoverCardPrimitive from "@radix-ui/react-hover-card" + +import { cn } from "@/lib/utils" + +const HoverCard = HoverCardPrimitive.Root + +const HoverCardTrigger = HoverCardPrimitive.Trigger + +const HoverCardContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( + +)) +HoverCardContent.displayName = HoverCardPrimitive.Content.displayName + +export { HoverCard, HoverCardTrigger, HoverCardContent } diff --git a/ningowood.com/components/ui/input.tsx b/ningowood.com/components/ui/input.tsx new file mode 100644 index 0000000..25abe1b --- /dev/null +++ b/ningowood.com/components/ui/input.tsx @@ -0,0 +1,25 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ) + }, +) +Input.displayName = "Input" + +export { Input } diff --git a/ningowood.com/components/ui/label.tsx b/ningowood.com/components/ui/label.tsx new file mode 100644 index 0000000..afde563 --- /dev/null +++ b/ningowood.com/components/ui/label.tsx @@ -0,0 +1,26 @@ +"use client" + +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", +) + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, ...props }, ref) => ( + +)) +Label.displayName = LabelPrimitive.Root.displayName + +export { Label } diff --git a/ningowood.com/components/ui/menubar.tsx b/ningowood.com/components/ui/menubar.tsx new file mode 100644 index 0000000..5fee850 --- /dev/null +++ b/ningowood.com/components/ui/menubar.tsx @@ -0,0 +1,236 @@ +"use client" + +import * as React from "react" +import * as MenubarPrimitive from "@radix-ui/react-menubar" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const MenubarMenu = MenubarPrimitive.Menu + +const MenubarGroup = MenubarPrimitive.Group + +const MenubarPortal = MenubarPrimitive.Portal + +const MenubarSub = MenubarPrimitive.Sub + +const MenubarRadioGroup = MenubarPrimitive.RadioGroup + +const Menubar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Menubar.displayName = MenubarPrimitive.Root.displayName + +const MenubarTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName + +const MenubarSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName + +const MenubarSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName + +const MenubarContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, align = "start", alignOffset = -4, sideOffset = 8, ...props }, + ref, + ) => ( + + + + ), +) +MenubarContent.displayName = MenubarPrimitive.Content.displayName + +const MenubarItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +MenubarItem.displayName = MenubarPrimitive.Item.displayName + +const MenubarCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName + +const MenubarRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName + +const MenubarLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +MenubarLabel.displayName = MenubarPrimitive.Label.displayName + +const MenubarSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName + +const MenubarShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +MenubarShortcut.displayname = "MenubarShortcut" + +export { + Menubar, + MenubarMenu, + MenubarTrigger, + MenubarContent, + MenubarItem, + MenubarSeparator, + MenubarLabel, + MenubarCheckboxItem, + MenubarRadioGroup, + MenubarRadioItem, + MenubarPortal, + MenubarSubContent, + MenubarSubTrigger, + MenubarGroup, + MenubarSub, + MenubarShortcut, +} diff --git a/ningowood.com/components/ui/navigation-menu.tsx b/ningowood.com/components/ui/navigation-menu.tsx new file mode 100644 index 0000000..6245a94 --- /dev/null +++ b/ningowood.com/components/ui/navigation-menu.tsx @@ -0,0 +1,128 @@ +import * as React from "react" +import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu" +import { cva } from "class-variance-authority" +import { ChevronDown } from "lucide-react" + +import { cn } from "@/lib/utils" + +const NavigationMenu = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children} + + +)) +NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName + +const NavigationMenuList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName + +const NavigationMenuItem = NavigationMenuPrimitive.Item + +const navigationMenuTriggerStyle = cva( + "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:bg-accent focus:text-accent-foreground disabled:opacity-50 disabled:pointer-events-none bg-background hover:bg-accent hover:text-accent-foreground data-[state=open]:bg-accent/50 data-[active]:bg-accent/50 h-10 py-2 px-4 group w-max", +) + +const NavigationMenuTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children}{" "} + +)) +NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName + +const NavigationMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName + +const NavigationMenuLink = NavigationMenuPrimitive.Link + +const NavigationMenuViewport = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( +
+ +
+)) +NavigationMenuViewport.displayName = + NavigationMenuPrimitive.Viewport.displayName + +const NavigationMenuIndicator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +
+ +)) +NavigationMenuIndicator.displayName = + NavigationMenuPrimitive.Indicator.displayName + +export { + navigationMenuTriggerStyle, + NavigationMenu, + NavigationMenuList, + NavigationMenuItem, + NavigationMenuContent, + NavigationMenuTrigger, + NavigationMenuLink, + NavigationMenuIndicator, + NavigationMenuViewport, +} diff --git a/ningowood.com/components/ui/popover.tsx b/ningowood.com/components/ui/popover.tsx new file mode 100644 index 0000000..6dd5736 --- /dev/null +++ b/ningowood.com/components/ui/popover.tsx @@ -0,0 +1,31 @@ +"use client" + +import * as React from "react" +import * as PopoverPrimitive from "@radix-ui/react-popover" + +import { cn } from "@/lib/utils" + +const Popover = PopoverPrimitive.Root + +const PopoverTrigger = PopoverPrimitive.Trigger + +const PopoverContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( + + + +)) +PopoverContent.displayName = PopoverPrimitive.Content.displayName + +export { Popover, PopoverTrigger, PopoverContent } diff --git a/ningowood.com/components/ui/progress.tsx b/ningowood.com/components/ui/progress.tsx new file mode 100644 index 0000000..650d924 --- /dev/null +++ b/ningowood.com/components/ui/progress.tsx @@ -0,0 +1,28 @@ +"use client" + +import * as React from "react" +import * as ProgressPrimitive from "@radix-ui/react-progress" + +import { cn } from "@/lib/utils" + +const Progress = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, value, ...props }, ref) => ( + + + +)) +Progress.displayName = ProgressPrimitive.Root.displayName + +export { Progress } diff --git a/ningowood.com/components/ui/radio-group.tsx b/ningowood.com/components/ui/radio-group.tsx new file mode 100644 index 0000000..3aa7098 --- /dev/null +++ b/ningowood.com/components/ui/radio-group.tsx @@ -0,0 +1,44 @@ +"use client" + +import * as React from "react" +import * as RadioGroupPrimitive from "@radix-ui/react-radio-group" +import { Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const RadioGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + return ( + + ) +}) +RadioGroup.displayName = RadioGroupPrimitive.Root.displayName + +const RadioGroupItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => { + return ( + + + + + + ) +}) +RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName + +export { RadioGroup, RadioGroupItem } diff --git a/ningowood.com/components/ui/scroll-area.tsx b/ningowood.com/components/ui/scroll-area.tsx new file mode 100644 index 0000000..7132989 --- /dev/null +++ b/ningowood.com/components/ui/scroll-area.tsx @@ -0,0 +1,48 @@ +"use client" + +import * as React from "react" +import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" + +import { cn } from "@/lib/utils" + +const ScrollArea = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + {children} + + + + +)) +ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName + +const ScrollBar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, orientation = "vertical", ...props }, ref) => ( + + + +)) +ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName + +export { ScrollArea, ScrollBar } diff --git a/ningowood.com/components/ui/select.tsx b/ningowood.com/components/ui/select.tsx new file mode 100644 index 0000000..ad42c4e --- /dev/null +++ b/ningowood.com/components/ui/select.tsx @@ -0,0 +1,120 @@ +"use client" + +import * as React from "react" +import * as SelectPrimitive from "@radix-ui/react-select" +import { Check, ChevronDown } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Select = SelectPrimitive.Root + +const SelectGroup = SelectPrimitive.Group + +const SelectValue = SelectPrimitive.Value + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children} + + + + +)) +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + {children} + + + +)) +SelectContent.displayName = SelectPrimitive.Content.displayName + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectLabel.displayName = SelectPrimitive.Label.displayName + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + + {children} + +)) +SelectItem.displayName = SelectPrimitive.Item.displayName + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SelectSeparator.displayName = SelectPrimitive.Separator.displayName + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, +} diff --git a/ningowood.com/components/ui/separator.tsx b/ningowood.com/components/ui/separator.tsx new file mode 100644 index 0000000..ca279b1 --- /dev/null +++ b/ningowood.com/components/ui/separator.tsx @@ -0,0 +1,31 @@ +"use client" + +import * as React from "react" +import * as SeparatorPrimitive from "@radix-ui/react-separator" + +import { cn } from "@/lib/utils" + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = "horizontal", decorative = true, ...props }, + ref, + ) => ( + + ), +) +Separator.displayName = SeparatorPrimitive.Root.displayName + +export { Separator } diff --git a/ningowood.com/components/ui/sheet.tsx b/ningowood.com/components/ui/sheet.tsx new file mode 100644 index 0000000..fdb6fca --- /dev/null +++ b/ningowood.com/components/ui/sheet.tsx @@ -0,0 +1,233 @@ +"use client" + +import * as React from "react" +import * as SheetPrimitive from "@radix-ui/react-dialog" +import { cva, type VariantProps } from "class-variance-authority" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Sheet = SheetPrimitive.Root + +const SheetTrigger = SheetPrimitive.Trigger + +const SheetClose = SheetPrimitive.Close + +const portalVariants = cva("fixed inset-0 z-50 flex", { + variants: { + position: { + top: "items-start", + bottom: "items-end", + left: "justify-start", + right: "justify-end", + }, + }, + defaultVariants: { position: "right" }, +}) + +interface SheetPortalProps + extends SheetPrimitive.DialogPortalProps, + VariantProps {} + +const SheetPortal = ({ + position, + className, + children, + ...props +}: SheetPortalProps) => ( + +
{children}
+
+) +SheetPortal.displayName = SheetPrimitive.Portal.displayName + +const SheetOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + +)) +SheetOverlay.displayName = SheetPrimitive.Overlay.displayName + +const sheetVariants = cva( + "fixed z-50 scale-100 gap-4 bg-background p-6 opacity-100 shadow-lg border", + { + variants: { + position: { + top: "animate-in slide-in-from-top w-full duration-300", + bottom: "animate-in slide-in-from-bottom w-full duration-300", + left: "animate-in slide-in-from-left h-full duration-300", + right: "animate-in slide-in-from-right h-full duration-300", + }, + size: { + content: "", + default: "", + sm: "", + lg: "", + xl: "", + full: "", + }, + }, + compoundVariants: [ + { + position: ["top", "bottom"], + size: "content", + class: "max-h-screen", + }, + { + position: ["top", "bottom"], + size: "default", + class: "h-1/3", + }, + { + position: ["top", "bottom"], + size: "sm", + class: "h-1/4", + }, + { + position: ["top", "bottom"], + size: "lg", + class: "h-1/2", + }, + { + position: ["top", "bottom"], + size: "xl", + class: "h-5/6", + }, + { + position: ["top", "bottom"], + size: "full", + class: "h-screen", + }, + { + position: ["right", "left"], + size: "content", + class: "max-w-screen", + }, + { + position: ["right", "left"], + size: "default", + class: "w-1/3", + }, + { + position: ["right", "left"], + size: "sm", + class: "w-1/4", + }, + { + position: ["right", "left"], + size: "lg", + class: "w-1/2", + }, + { + position: ["right", "left"], + size: "xl", + class: "w-5/6", + }, + { + position: ["right", "left"], + size: "full", + class: "w-screen", + }, + ], + defaultVariants: { + position: "right", + size: "default", + }, + }, +) + +export interface DialogContentProps + extends React.ComponentPropsWithoutRef, + VariantProps {} + +const SheetContent = React.forwardRef< + React.ElementRef, + DialogContentProps +>(({ position, size, className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +SheetContent.displayName = SheetPrimitive.Content.displayName + +const SheetHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +SheetHeader.displayName = "SheetHeader" + +const SheetFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +SheetFooter.displayName = "SheetFooter" + +const SheetTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SheetTitle.displayName = SheetPrimitive.Title.displayName + +const SheetDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +SheetDescription.displayName = SheetPrimitive.Description.displayName + +export { + Sheet, + SheetTrigger, + SheetClose, + SheetContent, + SheetHeader, + SheetFooter, + SheetTitle, + SheetDescription, +} diff --git a/ningowood.com/components/ui/skeleton.tsx b/ningowood.com/components/ui/skeleton.tsx new file mode 100644 index 0000000..cb541e0 --- /dev/null +++ b/ningowood.com/components/ui/skeleton.tsx @@ -0,0 +1,15 @@ +import { cn } from "@/lib/utils" + +function Skeleton({ + className, + ...props +}: React.HTMLAttributes) { + return ( +
+ ) +} + +export { Skeleton } diff --git a/ningowood.com/components/ui/slider.tsx b/ningowood.com/components/ui/slider.tsx new file mode 100644 index 0000000..eed0c67 --- /dev/null +++ b/ningowood.com/components/ui/slider.tsx @@ -0,0 +1,28 @@ +"use client" + +import * as React from "react" +import * as SliderPrimitive from "@radix-ui/react-slider" + +import { cn } from "@/lib/utils" + +const Slider = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + + +)) +Slider.displayName = SliderPrimitive.Root.displayName + +export { Slider } diff --git a/ningowood.com/components/ui/switch.tsx b/ningowood.com/components/ui/switch.tsx new file mode 100644 index 0000000..00bef6a --- /dev/null +++ b/ningowood.com/components/ui/switch.tsx @@ -0,0 +1,29 @@ +"use client" + +import * as React from "react" +import * as SwitchPrimitives from "@radix-ui/react-switch" + +import { cn } from "@/lib/utils" + +const Switch = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +Switch.displayName = SwitchPrimitives.Root.displayName + +export { Switch } diff --git a/ningowood.com/components/ui/table.tsx b/ningowood.com/components/ui/table.tsx new file mode 100644 index 0000000..f6e2127 --- /dev/null +++ b/ningowood.com/components/ui/table.tsx @@ -0,0 +1,114 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Table = React.forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+ + +)) +Table.displayName = "Table" + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableHeader.displayName = "TableHeader" + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableBody.displayName = "TableBody" + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableFooter.displayName = "TableFooter" + +const TableRow = React.forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableRow.displayName = "TableRow" + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableHead.displayName = "TableHead" + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableCell.displayName = "TableCell" + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableCaption.displayName = "TableCaption" + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +} diff --git a/ningowood.com/components/ui/tabs.tsx b/ningowood.com/components/ui/tabs.tsx new file mode 100644 index 0000000..0d3d053 --- /dev/null +++ b/ningowood.com/components/ui/tabs.tsx @@ -0,0 +1,55 @@ +"use client" + +import * as React from "react" +import * as TabsPrimitive from "@radix-ui/react-tabs" + +import { cn } from "@/lib/utils" + +const Tabs = TabsPrimitive.Root + +const TabsList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsList.displayName = TabsPrimitive.List.displayName + +const TabsTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName + +const TabsContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsContent.displayName = TabsPrimitive.Content.displayName + +export { Tabs, TabsList, TabsTrigger, TabsContent } diff --git a/ningowood.com/components/ui/textarea.tsx b/ningowood.com/components/ui/textarea.tsx new file mode 100644 index 0000000..72466bb --- /dev/null +++ b/ningowood.com/components/ui/textarea.tsx @@ -0,0 +1,24 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +export interface TextareaProps + extends React.TextareaHTMLAttributes {} + +const Textarea = React.forwardRef( + ({ className, ...props }, ref) => { + return ( +