├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .gitignore
├── .prettierignore
├── LICENSE
├── README.md
├── atoms
└── index.ts
├── components
├── dropzone.tsx
├── file-select.tsx
├── icons.tsx
├── key-popover.tsx
├── layout.tsx
├── main-nav.tsx
├── site-header.tsx
├── theme-toggle.tsx
├── transcription-loader.tsx
└── ui
│ ├── accordion.tsx
│ ├── alert-dialog.tsx
│ ├── aspect-ratio.tsx
│ ├── avatar.tsx
│ ├── button.tsx
│ ├── checkbox.tsx
│ ├── collapsible.tsx
│ ├── command.tsx
│ ├── context-menu.tsx
│ ├── dialog.tsx
│ ├── dropdown-menu.tsx
│ ├── hover-card.tsx
│ ├── input.tsx
│ ├── label.tsx
│ ├── menubar.tsx
│ ├── navigation-menu.tsx
│ ├── popover.tsx
│ ├── progress.tsx
│ ├── radio-group.tsx
│ ├── scroll-area.tsx
│ ├── select.tsx
│ ├── separator.tsx
│ ├── sheet.tsx
│ ├── slider.tsx
│ ├── switch.tsx
│ ├── tabs.tsx
│ ├── textarea.tsx
│ ├── toast.tsx
│ ├── toaster.tsx
│ ├── toggle.tsx
│ └── tooltip.tsx
├── config
└── site.ts
├── hooks
└── use-toast.ts
├── lib
├── openai.ts
└── utils.ts
├── next-env.d.ts
├── next.config.mjs
├── package-lock.json
├── package.json
├── pages
├── _app.tsx
├── _document.tsx
├── api
│ └── transcribe.ts
├── index.tsx
├── video.tsx
└── youtube.tsx
├── postcss.config.js
├── prettier.config.js
├── public
├── favicon.ico
├── next.svg
├── robot-loading-animation.json
├── thirteen.svg
└── vercel.svg
├── styles
└── globals.css
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.tsbuildinfo
└── types
└── nav.ts
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | indent_size = 2
8 | indent_style = space
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist/*
2 | .cache
3 | public
4 | node_modules
5 | *.esm.js
6 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/eslintrc",
3 | "root": true,
4 | "extends": [
5 | "next/core-web-vitals",
6 | "prettier",
7 | "plugin:tailwindcss/recommended"
8 | ],
9 | "plugins": ["tailwindcss"],
10 | "rules": {
11 | "@next/next/no-html-link-for-pages": "off",
12 | "react/jsx-key": "off",
13 | "tailwindcss/no-custom-classname": "off"
14 | },
15 | "settings": {
16 | "tailwindcss": {
17 | "callees": ["cn"]
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 | .pnp
6 | .pnp.js
7 |
8 | # testing
9 | coverage
10 |
11 | # next.js
12 | .next/
13 | out/
14 | build
15 |
16 | # misc
17 | .DS_Store
18 | *.pem
19 |
20 | # debug
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 | .pnpm-debug.log*
25 |
26 | # local env files
27 | .env.local
28 | .env.development.local
29 | .env.test.local
30 | .env.production.local
31 |
32 | # turbo
33 | .turbo
34 |
35 | .contentlayer
36 | .env
37 |
38 | .vscode/*
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | cache
2 | .cache
3 | package.json
4 | package-lock.json
5 | public
6 | CHANGELOG.md
7 | .yarn
8 | dist
9 | node_modules
10 | .next
11 | build
12 | .contentlayer
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Sully Omar
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Videoscribe
2 |
3 | Transcribe your videos using OpenAI's whisper api.
4 |
5 | Code is free and 100% open source. You will need an api key from openai.
6 |
7 | ## Features
8 |
9 | - Youtube transcriber
10 | - Uploaded file transcriber
11 |
12 | ## Built with
13 |
14 | - TailwindCSS
15 | - Next13
16 |
17 | ## Components & UI
18 |
19 | This project was boostrapped using this [template](https://ui.shadcn.com/)
20 |
21 | ### Usage
22 |
23 | Simply add your api key, then select whether you want to transcribe a youtube video or your own file. Note: you will be charged based on OpenAI's pricing found [here](https://openai.com/pricing)
24 |
25 | ### Additional notes
26 |
27 | I tried to make this as simple as possible, so yes, there could be several improvements, specifically in making the components more reusable.
28 |
29 | ## License
30 |
31 | Licensed under the [MIT license](https://github.com/shadcn/ui/blob/main/LICENSE.md).
32 |
--------------------------------------------------------------------------------
/atoms/index.ts:
--------------------------------------------------------------------------------
1 | import { atomWithStorage } from "jotai/utils";
2 |
3 | export const apiKeyAtom = atomWithStorage("apiKey", "");
4 |
--------------------------------------------------------------------------------
/components/dropzone.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from "react";
2 | import { useDropzone } from "react-dropzone";
3 |
4 | import { cn } from "@/lib/utils";
5 | import { Icons } from "./icons";
6 | import { Button } from "./ui/button";
7 |
8 | interface DropzoneProps {
9 | files: File[];
10 | setFiles: (files: File[]) => void;
11 | }
12 |
13 | const Dropzone = ({ setFiles, files }: DropzoneProps) => {
14 | const onDrop = useCallback(
15 | (acceptedFiles: File[]) => {
16 | setFiles(acceptedFiles);
17 | },
18 | [setFiles]
19 | );
20 | const { getRootProps, getInputProps, isDragActive } = useDropzone({
21 | onDrop,
22 | multiple: false,
23 | accept: {
24 | "video/mp4": [".mp4", ".m4a"],
25 | "video/mpeg": [".mpeg"],
26 | "audio/mpeg": [".mp3"],
27 | "audio/webm": [".webm"],
28 | "audio/wav": [".wav"],
29 | },
30 | });
31 |
32 | return (
33 |
42 |
43 |
44 |
45 |
or drag and drop
46 |
47 | );
48 | };
49 |
50 | export default Dropzone;
51 |
--------------------------------------------------------------------------------
/components/file-select.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Select,
3 | SelectContent,
4 | SelectItem,
5 | SelectTrigger,
6 | SelectValue,
7 | } from "@/components/ui/select";
8 |
9 | export default function FileSelect({
10 | format,
11 | setFileFormat,
12 | }: {
13 | format: string;
14 | setFileFormat: (format: string) => void;
15 | }) {
16 | return (
17 |
30 | );
31 | }
32 |
--------------------------------------------------------------------------------
/components/icons.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Laptop,
3 | LucideFileDown,
4 | LucideProps,
5 | Moon,
6 | Settings2Icon,
7 | SunMedium,
8 | Twitter,
9 | UploadCloud,
10 | type Icon as LucideIcon,
11 | } from "lucide-react";
12 |
13 | export type Icon = LucideIcon;
14 |
15 | export const Icons = {
16 | sun: SunMedium,
17 | moon: Moon,
18 | laptop: Laptop,
19 | twitter: Twitter,
20 | upload: UploadCloud,
21 | download: LucideFileDown,
22 | settings: Settings2Icon,
23 | logo: (props: LucideProps) => (
24 |
30 | ),
31 | gitHub: (props: LucideProps) => (
32 |
38 | ),
39 | };
40 |
--------------------------------------------------------------------------------
/components/key-popover.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { apiKeyAtom } from "@/atoms";
4 | import { useAtom } from "jotai";
5 |
6 | import { Button } from "@/components/ui/button";
7 | import { Input } from "@/components/ui/input";
8 | import { Label } from "@/components/ui/label";
9 | import {
10 | Popover,
11 | PopoverContent,
12 | PopoverTrigger,
13 | } from "@/components/ui/popover";
14 |
15 | export function KeyPopover() {
16 | const [apiKey, setApiKey] = useAtom(apiKeyAtom);
17 |
18 | return (
19 |
20 |
21 |
30 |
31 |
32 |
33 |
34 |
OpenAI API Key
35 |
36 | Add your OpenAI API key to use the whisper API.
37 |
38 |
39 |
40 |
41 |
42 | {
48 | setApiKey(e.target.value);
49 | }}
50 | />
51 |
52 |
53 |
54 |
55 |
56 | );
57 | }
58 |
--------------------------------------------------------------------------------
/components/layout.tsx:
--------------------------------------------------------------------------------
1 | import { SiteHeader } from "@/components/site-header"
2 |
3 | interface LayoutProps {
4 | children: React.ReactNode
5 | }
6 |
7 | export function Layout({ children }: LayoutProps) {
8 | return (
9 | <>
10 |
11 | {children}
12 | >
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/components/main-nav.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import Link from "next/link"
3 |
4 | import { NavItem } from "@/types/nav"
5 | import { siteConfig } from "@/config/site"
6 | import { cn } from "@/lib/utils"
7 | import { Icons } from "@/components/icons"
8 | import { Button } from "@/components/ui/button"
9 | import {
10 | DropdownMenu,
11 | DropdownMenuContent,
12 | DropdownMenuItem,
13 | DropdownMenuLabel,
14 | DropdownMenuSeparator,
15 | DropdownMenuTrigger,
16 | } from "@/components/ui/dropdown-menu"
17 |
18 | interface MainNavProps {
19 | items?: NavItem[]
20 | }
21 |
22 | export function MainNav({ items }: MainNavProps) {
23 | return (
24 |
25 |
26 |
27 |
28 | {siteConfig.name}
29 |
30 |
31 | {items?.length ? (
32 |
49 | ) : null}
50 |
51 |
52 |
59 |
60 |
65 |
66 |
67 | {siteConfig.name}
68 |
69 |
70 |
71 | {items?.map(
72 | (item, index) =>
73 | item.href && (
74 |
75 | {item.title}
76 |
77 | )
78 | )}
79 |
80 |
81 |
82 | )
83 | }
84 |
--------------------------------------------------------------------------------
/components/site-header.tsx:
--------------------------------------------------------------------------------
1 | import Link from "next/link";
2 |
3 | import { siteConfig } from "@/config/site";
4 | import { Icons } from "@/components/icons";
5 | import { KeyPopover } from "@/components/key-popover";
6 | import { MainNav } from "@/components/main-nav";
7 | import { ThemeToggle } from "@/components/theme-toggle";
8 | import { buttonVariants } from "@/components/ui/button";
9 |
10 | export function SiteHeader() {
11 | return (
12 |
13 |
14 |
15 |
16 |
53 |
54 |
55 |
56 | );
57 | }
58 |
--------------------------------------------------------------------------------
/components/theme-toggle.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import { useTheme } from "next-themes"
3 |
4 | import { Icons } from "@/components/icons"
5 | import { Button } from "@/components/ui/button"
6 | import {
7 | DropdownMenu,
8 | DropdownMenuContent,
9 | DropdownMenuItem,
10 | DropdownMenuTrigger,
11 | } from "@/components/ui/dropdown-menu"
12 |
13 | export function ThemeToggle() {
14 | const { setTheme } = useTheme()
15 |
16 | return (
17 |
18 |
19 |
24 |
25 |
26 | setTheme("light")}>
27 |
28 | Light
29 |
30 | setTheme("dark")}>
31 |
32 | Dark
33 |
34 | setTheme("system")}>
35 |
36 | System
37 |
38 |
39 |
40 | )
41 | }
42 |
--------------------------------------------------------------------------------
/components/transcription-loader.tsx:
--------------------------------------------------------------------------------
1 | import { Player } from "@lottiefiles/react-lottie-player";
2 |
3 | export function RobotLoader() {
4 | return (
5 |
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/components/ui/accordion.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as AccordionPrimitive from "@radix-ui/react-accordion";
5 | import { ChevronDown } from "lucide-react";
6 |
7 | import { cn } from "@/lib/utils";
8 |
9 | const Accordion = AccordionPrimitive.Root;
10 |
11 | const AccordionItem = React.forwardRef<
12 | React.ElementRef,
13 | React.ComponentPropsWithoutRef
14 | >(({ className, ...props }, ref) => (
15 |
23 | ));
24 | AccordionItem.displayName = "AccordionItem";
25 |
26 | const AccordionTrigger = React.forwardRef<
27 | React.ElementRef,
28 | React.ComponentPropsWithoutRef
29 | >(({ className, children, ...props }, ref) => (
30 |
31 | svg]:rotate-180",
35 | className
36 | )}
37 | {...props}
38 | >
39 | {children}
40 |
41 |
42 |
43 | ));
44 | AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
45 |
46 | const AccordionContent = React.forwardRef<
47 | React.ElementRef,
48 | React.ComponentPropsWithoutRef
49 | >(({ className, children, ...props }, ref) => (
50 |
58 | {children}
59 |
60 | ));
61 | AccordionContent.displayName = AccordionPrimitive.Content.displayName;
62 |
63 | export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
64 |
--------------------------------------------------------------------------------
/components/ui/alert-dialog.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
5 |
6 | import { cn } from "@/lib/utils";
7 |
8 | const AlertDialog = AlertDialogPrimitive.Root;
9 |
10 | const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
11 |
12 | const AlertDialogPortal = ({
13 | className,
14 | children,
15 | ...props
16 | }: AlertDialogPrimitive.AlertDialogPortalProps) => (
17 |
18 |
19 | {children}
20 |
21 |
22 | );
23 | AlertDialogPortal.displayName = AlertDialogPrimitive.Portal.displayName;
24 |
25 | const AlertDialogOverlay = React.forwardRef<
26 | React.ElementRef,
27 | React.ComponentPropsWithoutRef
28 | >(({ className, children, ...props }, ref) => (
29 |
37 | ));
38 | AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
39 |
40 | const AlertDialogContent = React.forwardRef<
41 | React.ElementRef,
42 | React.ComponentPropsWithoutRef
43 | >(({ className, ...props }, ref) => (
44 |
45 |
46 |
55 |
56 | ));
57 | AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
58 |
59 | const AlertDialogHeader = ({
60 | className,
61 | ...props
62 | }: React.HTMLAttributes) => (
63 |
70 | );
71 | AlertDialogHeader.displayName = "AlertDialogHeader";
72 |
73 | const AlertDialogFooter = ({
74 | className,
75 | ...props
76 | }: React.HTMLAttributes) => (
77 |
84 | );
85 | AlertDialogFooter.displayName = "AlertDialogFooter";
86 |
87 | const AlertDialogTitle = React.forwardRef<
88 | React.ElementRef,
89 | React.ComponentPropsWithoutRef
90 | >(({ className, ...props }, ref) => (
91 |
100 | ));
101 | AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
102 |
103 | const AlertDialogDescription = React.forwardRef<
104 | React.ElementRef,
105 | React.ComponentPropsWithoutRef
106 | >(({ className, ...props }, ref) => (
107 |
112 | ));
113 | AlertDialogDescription.displayName =
114 | AlertDialogPrimitive.Description.displayName;
115 |
116 | const AlertDialogAction = React.forwardRef<
117 | React.ElementRef,
118 | React.ComponentPropsWithoutRef
119 | >(({ className, ...props }, ref) => (
120 |
128 | ));
129 | AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
130 |
131 | const AlertDialogCancel = React.forwardRef<
132 | React.ElementRef,
133 | React.ComponentPropsWithoutRef
134 | >(({ className, ...props }, ref) => (
135 |
143 | ));
144 | AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
145 |
146 | export {
147 | AlertDialog,
148 | AlertDialogTrigger,
149 | AlertDialogContent,
150 | AlertDialogHeader,
151 | AlertDialogFooter,
152 | AlertDialogTitle,
153 | AlertDialogDescription,
154 | AlertDialogAction,
155 | AlertDialogCancel,
156 | };
157 |
--------------------------------------------------------------------------------
/components/ui/aspect-ratio.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
4 |
5 | const AspectRatio = AspectRatioPrimitive.Root
6 |
7 | export { AspectRatio }
8 |
--------------------------------------------------------------------------------
/components/ui/avatar.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as AvatarPrimitive from "@radix-ui/react-avatar";
5 |
6 | import { cn } from "@/lib/utils";
7 |
8 | const Avatar = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, ...props }, ref) => (
12 |
20 | ));
21 | Avatar.displayName = AvatarPrimitive.Root.displayName;
22 |
23 | const AvatarImage = React.forwardRef<
24 | React.ElementRef,
25 | React.ComponentPropsWithoutRef
26 | >(({ className, ...props }, ref) => (
27 |
32 | ));
33 | AvatarImage.displayName = AvatarPrimitive.Image.displayName;
34 |
35 | const AvatarFallback = React.forwardRef<
36 | React.ElementRef,
37 | React.ComponentPropsWithoutRef
38 | >(({ className, ...props }, ref) => (
39 |
47 | ));
48 | AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
49 |
50 | export { Avatar, AvatarImage, AvatarFallback };
51 |
--------------------------------------------------------------------------------
/components/ui/button.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { VariantProps, cva } from "class-variance-authority";
3 |
4 | import { cn } from "@/lib/utils";
5 |
6 | const buttonVariants = cva(
7 | "active:scale-95 inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 dark:hover:bg-slate-800 dark:hover:text-slate-100 disabled:opacity-50 dark:focus:ring-slate-400 disabled:pointer-events-none dark:focus:ring-offset-slate-900 data-[state=open]:bg-slate-100 dark:data-[state=open]:bg-slate-800",
8 | {
9 | variants: {
10 | variant: {
11 | default:
12 | "bg-slate-900 text-white hover:bg-slate-700 dark:bg-slate-50 dark:text-slate-900",
13 | destructive:
14 | "bg-red-500 text-white hover:bg-red-600 dark:hover:bg-red-600",
15 | outline:
16 | "bg-transparent border border-slate-200 hover:bg-slate-100 dark:border-slate-700 dark:text-slate-100",
17 | subtle:
18 | "bg-slate-100 text-slate-900 hover:bg-slate-200 dark:bg-slate-700 dark:text-slate-100",
19 | ghost:
20 | "bg-transparent hover:bg-slate-100 dark:hover:bg-slate-800 dark:text-slate-100 dark:hover:text-slate-100 data-[state=open]:bg-transparent dark:data-[state=open]:bg-transparent",
21 | link: "bg-transparent dark:bg-transparent underline-offset-4 hover:underline text-slate-900 dark:text-slate-100 hover:bg-transparent dark:hover:bg-transparent",
22 | },
23 | size: {
24 | default: "h-10 py-2 px-4",
25 | sm: "h-9 px-2 rounded-md",
26 | lg: "h-11 px-8 rounded-md",
27 | },
28 | },
29 | defaultVariants: {
30 | variant: "default",
31 | size: "default",
32 | },
33 | }
34 | );
35 |
36 | export interface ButtonProps
37 | extends React.ButtonHTMLAttributes,
38 | VariantProps {}
39 |
40 | const Button = React.forwardRef(
41 | ({ className, variant, size, ...props }, ref) => {
42 | return (
43 |
48 | );
49 | }
50 | );
51 | Button.displayName = "Button";
52 |
53 | export { Button, buttonVariants };
54 |
--------------------------------------------------------------------------------
/components/ui/checkbox.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
5 | import { Check } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const Checkbox = React.forwardRef<
10 | React.ElementRef,
11 | React.ComponentPropsWithoutRef
12 | >(({ className, ...props }, ref) => (
13 |
21 |
24 |
25 |
26 |
27 | ))
28 | Checkbox.displayName = CheckboxPrimitive.Root.displayName
29 |
30 | export { Checkbox }
31 |
--------------------------------------------------------------------------------
/components/ui/collapsible.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
4 |
5 | const Collapsible = CollapsiblePrimitive.Root;
6 |
7 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;
8 |
9 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;
10 |
11 | export { Collapsible, CollapsibleTrigger, CollapsibleContent };
12 |
--------------------------------------------------------------------------------
/components/ui/command.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import { DialogProps } from "@radix-ui/react-dialog";
5 | import { Command as CommandPrimitive, useCommandState } from "cmdk";
6 | import { ChevronsUpDown, Search } from "lucide-react";
7 |
8 | import { cn } from "@/lib/utils";
9 | import { Dialog, DialogContent } from "@/components/ui/dialog";
10 |
11 | const Command = React.forwardRef<
12 | React.ElementRef,
13 | React.ComponentPropsWithoutRef
14 | >(({ className, ...props }, ref) => (
15 |
23 | ));
24 | Command.displayName = CommandPrimitive.displayName;
25 |
26 | interface CommandDialogProps extends DialogProps {}
27 |
28 | const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
29 | return (
30 |
37 | );
38 | };
39 |
40 | const CommandInput = React.forwardRef<
41 | React.ElementRef,
42 | React.ComponentPropsWithoutRef
43 | >(({ className, ...props }, ref) => (
44 |
48 |
49 |
57 |
58 | ));
59 |
60 | CommandInput.displayName = CommandPrimitive.Input.displayName;
61 |
62 | const CommandList = React.forwardRef<
63 | React.ElementRef,
64 | React.ComponentPropsWithoutRef
65 | >(({ className, ...props }, ref) => (
66 |
71 | ));
72 |
73 | CommandList.displayName = CommandPrimitive.List.displayName;
74 |
75 | const CommandEmpty = React.forwardRef<
76 | React.ElementRef,
77 | React.ComponentPropsWithoutRef
78 | >((props, ref) => (
79 |
84 | ));
85 |
86 | CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
87 |
88 | const CommandGroup = React.forwardRef<
89 | React.ElementRef,
90 | React.ComponentPropsWithoutRef
91 | >(({ className, ...props }, ref) => (
92 |
100 | ));
101 |
102 | CommandGroup.displayName = CommandPrimitive.Group.displayName;
103 |
104 | const CommandSeparator = React.forwardRef<
105 | React.ElementRef,
106 | React.ComponentPropsWithoutRef
107 | >(({ className, ...props }, ref) => (
108 |
113 | ));
114 | CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
115 |
116 | const CommandItem = React.forwardRef<
117 | React.ElementRef,
118 | React.ComponentPropsWithoutRef
119 | >(({ className, ...props }, ref) => (
120 |
128 | ));
129 |
130 | CommandItem.displayName = CommandPrimitive.Item.displayName;
131 |
132 | const CommandShortcut = ({
133 | className,
134 | ...props
135 | }: React.HTMLAttributes) => {
136 | return (
137 |
144 | );
145 | };
146 | CommandShortcut.displayName = "CommandShortcut";
147 |
148 | export {
149 | Command,
150 | CommandDialog,
151 | CommandInput,
152 | CommandList,
153 | CommandEmpty,
154 | CommandGroup,
155 | CommandItem,
156 | CommandShortcut,
157 | CommandSeparator,
158 | };
159 |
--------------------------------------------------------------------------------
/components/ui/context-menu.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"
5 | import { Check, ChevronRight, Circle } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const ContextMenu = ContextMenuPrimitive.Root
10 |
11 | const ContextMenuTrigger = ContextMenuPrimitive.Trigger
12 |
13 | const ContextMenuGroup = ContextMenuPrimitive.Group
14 |
15 | const ContextMenuPortal = ContextMenuPrimitive.Portal
16 |
17 | const ContextMenuSub = ContextMenuPrimitive.Sub
18 |
19 | const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup
20 |
21 | const ContextMenuSubTrigger = React.forwardRef<
22 | React.ElementRef,
23 | React.ComponentPropsWithoutRef & {
24 | inset?: boolean
25 | }
26 | >(({ className, inset, children, ...props }, ref) => (
27 |
36 | {children}
37 |
38 |
39 | ))
40 | ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName
41 |
42 | const ContextMenuSubContent = React.forwardRef<
43 | React.ElementRef,
44 | React.ComponentPropsWithoutRef
45 | >(({ className, ...props }, ref) => (
46 |
54 | ))
55 | ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName
56 |
57 | const ContextMenuContent = React.forwardRef<
58 | React.ElementRef,
59 | React.ComponentPropsWithoutRef
60 | >(({ className, ...props }, ref) => (
61 |
62 |
70 |
71 | ))
72 | ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName
73 |
74 | const ContextMenuItem = React.forwardRef<
75 | React.ElementRef,
76 | React.ComponentPropsWithoutRef & {
77 | inset?: boolean
78 | }
79 | >(({ className, inset, ...props }, ref) => (
80 |
89 | ))
90 | ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName
91 |
92 | const ContextMenuCheckboxItem = React.forwardRef<
93 | React.ElementRef,
94 | React.ComponentPropsWithoutRef
95 | >(({ className, children, checked, ...props }, ref) => (
96 |
105 |
106 |
107 |
108 |
109 |
110 | {children}
111 |
112 | ))
113 | ContextMenuCheckboxItem.displayName =
114 | ContextMenuPrimitive.CheckboxItem.displayName
115 |
116 | const ContextMenuRadioItem = React.forwardRef<
117 | React.ElementRef,
118 | React.ComponentPropsWithoutRef
119 | >(({ className, children, ...props }, ref) => (
120 |
128 |
129 |
130 |
131 |
132 |
133 | {children}
134 |
135 | ))
136 | ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName
137 |
138 | const ContextMenuLabel = React.forwardRef<
139 | React.ElementRef,
140 | React.ComponentPropsWithoutRef & {
141 | inset?: boolean
142 | }
143 | >(({ className, inset, ...props }, ref) => (
144 |
153 | ))
154 | ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName
155 |
156 | const ContextMenuSeparator = React.forwardRef<
157 | React.ElementRef,
158 | React.ComponentPropsWithoutRef
159 | >(({ className, ...props }, ref) => (
160 |
165 | ))
166 | ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName
167 |
168 | const ContextMenuShortcut = ({
169 | className,
170 | ...props
171 | }: React.HTMLAttributes) => {
172 | return (
173 |
180 | )
181 | }
182 | ContextMenuShortcut.displayName = "ContextMenuShortcut"
183 |
184 | export {
185 | ContextMenu,
186 | ContextMenuTrigger,
187 | ContextMenuContent,
188 | ContextMenuItem,
189 | ContextMenuCheckboxItem,
190 | ContextMenuRadioItem,
191 | ContextMenuLabel,
192 | ContextMenuSeparator,
193 | ContextMenuShortcut,
194 | ContextMenuGroup,
195 | ContextMenuPortal,
196 | ContextMenuSub,
197 | ContextMenuSubContent,
198 | ContextMenuSubTrigger,
199 | ContextMenuRadioGroup,
200 | }
201 |
--------------------------------------------------------------------------------
/components/ui/dialog.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as DialogPrimitive from "@radix-ui/react-dialog";
5 | import { X } from "lucide-react";
6 |
7 | import { cn } from "@/lib/utils";
8 |
9 | const Dialog = DialogPrimitive.Root;
10 |
11 | const DialogTrigger = DialogPrimitive.Trigger;
12 |
13 | const DialogPortal = ({
14 | className,
15 | children,
16 | ...props
17 | }: DialogPrimitive.DialogPortalProps) => (
18 |
19 |
20 | {children}
21 |
22 |
23 | );
24 | DialogPortal.displayName = DialogPrimitive.Portal.displayName;
25 |
26 | const DialogOverlay = React.forwardRef<
27 | React.ElementRef,
28 | React.ComponentPropsWithoutRef
29 | >(({ className, children, ...props }, ref) => (
30 |
38 | ));
39 | DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
40 |
41 | const DialogContent = React.forwardRef<
42 | React.ElementRef,
43 | React.ComponentPropsWithoutRef
44 | >(({ className, children, ...props }, ref) => (
45 |
46 |
47 |
56 | {children}
57 |
58 |
59 | Close
60 |
61 |
62 |
63 | ));
64 | DialogContent.displayName = DialogPrimitive.Content.displayName;
65 |
66 | const DialogHeader = ({
67 | className,
68 | ...props
69 | }: React.HTMLAttributes) => (
70 |
77 | );
78 | DialogHeader.displayName = "DialogHeader";
79 |
80 | const DialogFooter = ({
81 | className,
82 | ...props
83 | }: React.HTMLAttributes) => (
84 |
91 | );
92 | DialogFooter.displayName = "DialogFooter";
93 |
94 | const DialogTitle = React.forwardRef<
95 | React.ElementRef,
96 | React.ComponentPropsWithoutRef
97 | >(({ className, ...props }, ref) => (
98 |
107 | ));
108 | DialogTitle.displayName = DialogPrimitive.Title.displayName;
109 |
110 | const DialogDescription = React.forwardRef<
111 | React.ElementRef,
112 | React.ComponentPropsWithoutRef
113 | >(({ className, ...props }, ref) => (
114 |
119 | ));
120 | DialogDescription.displayName = DialogPrimitive.Description.displayName;
121 |
122 | export {
123 | Dialog,
124 | DialogTrigger,
125 | DialogContent,
126 | DialogHeader,
127 | DialogFooter,
128 | DialogTitle,
129 | DialogDescription,
130 | };
131 |
--------------------------------------------------------------------------------
/components/ui/dropdown-menu.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
5 | import { Check, ChevronRight, Circle } from "lucide-react";
6 |
7 | import { cn } from "@/lib/utils";
8 |
9 | const DropdownMenu = DropdownMenuPrimitive.Root;
10 |
11 | const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
12 |
13 | const DropdownMenuGroup = DropdownMenuPrimitive.Group;
14 |
15 | const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
16 |
17 | const DropdownMenuSub = DropdownMenuPrimitive.Sub;
18 |
19 | const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
20 |
21 | const DropdownMenuSubTrigger = React.forwardRef<
22 | React.ElementRef,
23 | React.ComponentPropsWithoutRef & {
24 | inset?: boolean;
25 | }
26 | >(({ className, inset, children, ...props }, ref) => (
27 |
36 | {children}
37 |
38 |
39 | ));
40 | DropdownMenuSubTrigger.displayName =
41 | DropdownMenuPrimitive.SubTrigger.displayName;
42 |
43 | const DropdownMenuSubContent = React.forwardRef<
44 | React.ElementRef,
45 | React.ComponentPropsWithoutRef
46 | >(({ className, ...props }, ref) => (
47 |
55 | ));
56 | DropdownMenuSubContent.displayName =
57 | DropdownMenuPrimitive.SubContent.displayName;
58 |
59 | const DropdownMenuContent = React.forwardRef<
60 | React.ElementRef,
61 | React.ComponentPropsWithoutRef
62 | >(({ className, sideOffset = 4, ...props }, ref) => (
63 |
64 |
73 |
74 | ));
75 | DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
76 |
77 | const DropdownMenuItem = React.forwardRef<
78 | React.ElementRef,
79 | React.ComponentPropsWithoutRef & {
80 | inset?: boolean;
81 | }
82 | >(({ className, inset, ...props }, ref) => (
83 |
92 | ));
93 | DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
94 |
95 | const DropdownMenuCheckboxItem = React.forwardRef<
96 | React.ElementRef,
97 | React.ComponentPropsWithoutRef
98 | >(({ className, children, checked, ...props }, ref) => (
99 |
108 |
109 |
110 |
111 |
112 |
113 | {children}
114 |
115 | ));
116 | DropdownMenuCheckboxItem.displayName =
117 | DropdownMenuPrimitive.CheckboxItem.displayName;
118 |
119 | const DropdownMenuRadioItem = React.forwardRef<
120 | React.ElementRef,
121 | React.ComponentPropsWithoutRef
122 | >(({ className, children, ...props }, ref) => (
123 |
131 |
132 |
133 |
134 |
135 |
136 | {children}
137 |
138 | ));
139 | DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
140 |
141 | const DropdownMenuLabel = React.forwardRef<
142 | React.ElementRef,
143 | React.ComponentPropsWithoutRef & {
144 | inset?: boolean;
145 | }
146 | >(({ className, inset, ...props }, ref) => (
147 |
156 | ));
157 | DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
158 |
159 | const DropdownMenuSeparator = React.forwardRef<
160 | React.ElementRef,
161 | React.ComponentPropsWithoutRef
162 | >(({ className, ...props }, ref) => (
163 |
168 | ));
169 | DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
170 |
171 | const DropdownMenuShortcut = ({
172 | className,
173 | ...props
174 | }: React.HTMLAttributes) => {
175 | return (
176 |
183 | );
184 | };
185 | DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
186 |
187 | export {
188 | DropdownMenu,
189 | DropdownMenuTrigger,
190 | DropdownMenuContent,
191 | DropdownMenuItem,
192 | DropdownMenuCheckboxItem,
193 | DropdownMenuRadioItem,
194 | DropdownMenuLabel,
195 | DropdownMenuSeparator,
196 | DropdownMenuShortcut,
197 | DropdownMenuGroup,
198 | DropdownMenuPortal,
199 | DropdownMenuSub,
200 | DropdownMenuSubContent,
201 | DropdownMenuSubTrigger,
202 | DropdownMenuRadioGroup,
203 | };
204 |
--------------------------------------------------------------------------------
/components/ui/hover-card.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const HoverCard = HoverCardPrimitive.Root
9 |
10 | const HoverCardTrigger = HoverCardPrimitive.Trigger
11 |
12 | const HoverCardContent = React.forwardRef<
13 | React.ElementRef,
14 | React.ComponentPropsWithoutRef
15 | >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
16 |
26 | ))
27 | HoverCardContent.displayName = HoverCardPrimitive.Content.displayName
28 |
29 | export { HoverCard, HoverCardTrigger, HoverCardContent }
30 |
--------------------------------------------------------------------------------
/components/ui/input.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { cn } from "@/lib/utils"
4 |
5 | export interface InputProps
6 | extends React.InputHTMLAttributes {}
7 |
8 | const Input = React.forwardRef(
9 | ({ className, ...props }, ref) => {
10 | return (
11 |
19 | )
20 | }
21 | )
22 | Input.displayName = "Input"
23 |
24 | export { Input }
25 |
--------------------------------------------------------------------------------
/components/ui/label.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as LabelPrimitive from "@radix-ui/react-label";
5 |
6 | import { cn } from "@/lib/utils";
7 |
8 | const Label = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, ...props }, ref) => (
12 |
20 | ));
21 | Label.displayName = LabelPrimitive.Root.displayName;
22 |
23 | export { Label };
24 |
--------------------------------------------------------------------------------
/components/ui/menubar.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as MenubarPrimitive from "@radix-ui/react-menubar"
5 | import { Check, ChevronRight, Circle } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const MenubarMenu = MenubarPrimitive.Menu
10 |
11 | const MenubarGroup = MenubarPrimitive.Group
12 |
13 | const MenubarPortal = MenubarPrimitive.Portal
14 |
15 | const MenubarSub = MenubarPrimitive.Sub
16 |
17 | const MenubarRadioGroup = MenubarPrimitive.RadioGroup
18 |
19 | const Menubar = React.forwardRef<
20 | React.ElementRef,
21 | React.ComponentPropsWithoutRef
22 | >(({ className, ...props }, ref) => (
23 |
31 | ))
32 | Menubar.displayName = MenubarPrimitive.Root.displayName
33 |
34 | const MenubarTrigger = React.forwardRef<
35 | React.ElementRef,
36 | React.ComponentPropsWithoutRef
37 | >(({ className, ...props }, ref) => (
38 |
46 | ))
47 | MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName
48 |
49 | const MenubarSubTrigger = React.forwardRef<
50 | React.ElementRef,
51 | React.ComponentPropsWithoutRef & {
52 | inset?: boolean
53 | }
54 | >(({ className, inset, children, ...props }, ref) => (
55 |
64 | {children}
65 |
66 |
67 | ))
68 | MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName
69 |
70 | const MenubarSubContent = React.forwardRef<
71 | React.ElementRef,
72 | React.ComponentPropsWithoutRef
73 | >(({ className, ...props }, ref) => (
74 |
82 | ))
83 | MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName
84 |
85 | const MenubarContent = React.forwardRef<
86 | React.ElementRef,
87 | React.ComponentPropsWithoutRef
88 | >(
89 | (
90 | { className, align = "start", alignOffset = -4, sideOffset = 8, ...props },
91 | ref
92 | ) => (
93 |
94 |
105 |
106 | )
107 | )
108 | MenubarContent.displayName = MenubarPrimitive.Content.displayName
109 |
110 | const MenubarItem = React.forwardRef<
111 | React.ElementRef,
112 | React.ComponentPropsWithoutRef & {
113 | inset?: boolean
114 | }
115 | >(({ className, inset, ...props }, ref) => (
116 |
125 | ))
126 | MenubarItem.displayName = MenubarPrimitive.Item.displayName
127 |
128 | const MenubarCheckboxItem = React.forwardRef<
129 | React.ElementRef,
130 | React.ComponentPropsWithoutRef
131 | >(({ className, children, checked, ...props }, ref) => (
132 |
141 |
142 |
143 |
144 |
145 |
146 | {children}
147 |
148 | ))
149 | MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName
150 |
151 | const MenubarRadioItem = React.forwardRef<
152 | React.ElementRef,
153 | React.ComponentPropsWithoutRef
154 | >(({ className, children, ...props }, ref) => (
155 |
163 |
164 |
165 |
166 |
167 |
168 | {children}
169 |
170 | ))
171 | MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName
172 |
173 | const MenubarLabel = React.forwardRef<
174 | React.ElementRef,
175 | React.ComponentPropsWithoutRef & {
176 | inset?: boolean
177 | }
178 | >(({ className, inset, ...props }, ref) => (
179 |
188 | ))
189 | MenubarLabel.displayName = MenubarPrimitive.Label.displayName
190 |
191 | const MenubarSeparator = React.forwardRef<
192 | React.ElementRef,
193 | React.ComponentPropsWithoutRef
194 | >(({ className, ...props }, ref) => (
195 |
200 | ))
201 | MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName
202 |
203 | const MenubarShortcut = ({
204 | className,
205 | ...props
206 | }: React.HTMLAttributes) => {
207 | return (
208 |
215 | )
216 | }
217 | MenubarShortcut.displayname = "MenubarShortcut"
218 |
219 | export {
220 | Menubar,
221 | MenubarMenu,
222 | MenubarTrigger,
223 | MenubarContent,
224 | MenubarItem,
225 | MenubarSeparator,
226 | MenubarLabel,
227 | MenubarCheckboxItem,
228 | MenubarRadioGroup,
229 | MenubarRadioItem,
230 | MenubarPortal,
231 | MenubarSubContent,
232 | MenubarSubTrigger,
233 | MenubarGroup,
234 | MenubarSub,
235 | MenubarShortcut,
236 | }
237 |
--------------------------------------------------------------------------------
/components/ui/navigation-menu.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu";
3 | import { cva } from "class-variance-authority";
4 | import { ChevronDown } from "lucide-react";
5 |
6 | import { cn } from "@/lib/utils";
7 |
8 | const NavigationMenu = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, children, ...props }, ref) => (
12 |
20 | {children}
21 |
22 |
23 | ));
24 | NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName;
25 |
26 | const NavigationMenuList = React.forwardRef<
27 | React.ElementRef,
28 | React.ComponentPropsWithoutRef
29 | >(({ className, ...props }, ref) => (
30 |
38 | ));
39 | NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;
40 |
41 | const NavigationMenuItem = NavigationMenuPrimitive.Item;
42 |
43 | const navigationMenuTriggerStyle = cva(
44 | "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:bg-slate-100 disabled:opacity-50 dark:focus:bg-slate-800 disabled:pointer-events-none bg-transparent hover:bg-slate-100 dark:hover:bg-slate-800 dark:text-slate-100 dark:hover:text-slate-100 data-[state=open]:bg-slate-50 dark:data-[state=open]:bg-slate-800 data-[active]:bg-slate-50 dark:data-[active]:bg-slate-800 h-10 py-2 px-4 group w-max"
45 | );
46 |
47 | const NavigationMenuTrigger = React.forwardRef<
48 | React.ElementRef,
49 | React.ComponentPropsWithoutRef
50 | >(({ className, children, ...props }, ref) => (
51 |
56 | {children}{" "}
57 |
61 |
62 | ));
63 | NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;
64 |
65 | const NavigationMenuContent = React.forwardRef<
66 | React.ElementRef,
67 | React.ComponentPropsWithoutRef
68 | >(({ className, ...props }, ref) => (
69 |
77 | ));
78 | NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName;
79 |
80 | const NavigationMenuLink = NavigationMenuPrimitive.Link;
81 |
82 | const NavigationMenuViewport = React.forwardRef<
83 | React.ElementRef,
84 | React.ComponentPropsWithoutRef
85 | >(({ className, ...props }, ref) => (
86 |
87 |
95 |
96 | ));
97 | NavigationMenuViewport.displayName =
98 | NavigationMenuPrimitive.Viewport.displayName;
99 |
100 | const NavigationMenuIndicator = React.forwardRef<
101 | React.ElementRef,
102 | React.ComponentPropsWithoutRef
103 | >(({ className, ...props }, ref) => (
104 |
112 |
113 |
114 | ));
115 | NavigationMenuIndicator.displayName =
116 | NavigationMenuPrimitive.Indicator.displayName;
117 |
118 | export {
119 | navigationMenuTriggerStyle,
120 | NavigationMenu,
121 | NavigationMenuList,
122 | NavigationMenuItem,
123 | NavigationMenuContent,
124 | NavigationMenuTrigger,
125 | NavigationMenuLink,
126 | NavigationMenuIndicator,
127 | NavigationMenuViewport,
128 | };
129 |
--------------------------------------------------------------------------------
/components/ui/popover.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as PopoverPrimitive from "@radix-ui/react-popover";
5 |
6 | import { cn } from "@/lib/utils";
7 |
8 | const Popover = PopoverPrimitive.Root;
9 |
10 | const PopoverTrigger = PopoverPrimitive.Trigger;
11 |
12 | const PopoverContent = React.forwardRef<
13 | React.ElementRef,
14 | React.ComponentPropsWithoutRef
15 | >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
16 |
17 |
27 |
28 | ));
29 | PopoverContent.displayName = PopoverPrimitive.Content.displayName;
30 |
31 | export { Popover, PopoverTrigger, PopoverContent };
32 |
--------------------------------------------------------------------------------
/components/ui/progress.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as ProgressPrimitive from "@radix-ui/react-progress"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Progress = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, value, ...props }, ref) => (
12 |
20 |
24 |
25 | ))
26 | Progress.displayName = ProgressPrimitive.Root.displayName
27 |
28 | export { Progress }
29 |
--------------------------------------------------------------------------------
/components/ui/radio-group.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
5 | import { Circle } from "lucide-react";
6 |
7 | import { cn } from "@/lib/utils";
8 |
9 | const RadioGroup = React.forwardRef<
10 | React.ElementRef,
11 | React.ComponentPropsWithoutRef
12 | >(({ className, ...props }, ref) => {
13 | return (
14 |
19 | );
20 | });
21 | RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
22 |
23 | const RadioGroupItem = React.forwardRef<
24 | React.ElementRef,
25 | React.ComponentPropsWithoutRef
26 | >(({ className, children, ...props }, ref) => {
27 | return (
28 |
36 |
37 |
38 |
39 |
40 | );
41 | });
42 | RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
43 |
44 | export { RadioGroup, RadioGroupItem };
45 |
--------------------------------------------------------------------------------
/components/ui/scroll-area.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const ScrollArea = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, children, ...props }, ref) => (
12 |
17 |
18 | {children}
19 |
20 |
21 |
22 |
23 | ))
24 | ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
25 |
26 | const ScrollBar = React.forwardRef<
27 | React.ElementRef,
28 | React.ComponentPropsWithoutRef
29 | >(({ className, orientation = "vertical", ...props }, ref) => (
30 |
43 |
44 |
45 | ))
46 | ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
47 |
48 | export { ScrollArea, ScrollBar }
49 |
--------------------------------------------------------------------------------
/components/ui/select.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SelectPrimitive from "@radix-ui/react-select"
5 | import { Check, ChevronDown } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const Select = SelectPrimitive.Root
10 |
11 | const SelectGroup = SelectPrimitive.Group
12 |
13 | const SelectValue = SelectPrimitive.Value
14 |
15 | const SelectTrigger = React.forwardRef<
16 | React.ElementRef,
17 | React.ComponentPropsWithoutRef
18 | >(({ className, children, ...props }, ref) => (
19 |
27 | {children}
28 |
29 |
30 | ))
31 | SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
32 |
33 | const SelectContent = React.forwardRef<
34 | React.ElementRef,
35 | React.ComponentPropsWithoutRef
36 | >(({ className, children, ...props }, ref) => (
37 |
38 |
46 |
47 | {children}
48 |
49 |
50 |
51 | ))
52 | SelectContent.displayName = SelectPrimitive.Content.displayName
53 |
54 | const SelectLabel = React.forwardRef<
55 | React.ElementRef,
56 | React.ComponentPropsWithoutRef
57 | >(({ className, ...props }, ref) => (
58 |
66 | ))
67 | SelectLabel.displayName = SelectPrimitive.Label.displayName
68 |
69 | const SelectItem = React.forwardRef<
70 | React.ElementRef,
71 | React.ComponentPropsWithoutRef
72 | >(({ className, children, ...props }, ref) => (
73 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | {children}
88 |
89 | ))
90 | SelectItem.displayName = SelectPrimitive.Item.displayName
91 |
92 | const SelectSeparator = React.forwardRef<
93 | React.ElementRef,
94 | React.ComponentPropsWithoutRef
95 | >(({ className, ...props }, ref) => (
96 |
101 | ))
102 | SelectSeparator.displayName = SelectPrimitive.Separator.displayName
103 |
104 | export {
105 | Select,
106 | SelectGroup,
107 | SelectValue,
108 | SelectTrigger,
109 | SelectContent,
110 | SelectLabel,
111 | SelectItem,
112 | SelectSeparator,
113 | }
114 |
--------------------------------------------------------------------------------
/components/ui/separator.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SeparatorPrimitive from "@radix-ui/react-separator"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Separator = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(
12 | (
13 | { className, orientation = "horizontal", decorative = true, ...props },
14 | ref
15 | ) => (
16 |
27 | )
28 | )
29 | Separator.displayName = SeparatorPrimitive.Root.displayName
30 |
31 | export { Separator }
32 |
--------------------------------------------------------------------------------
/components/ui/sheet.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as SheetPrimitive from "@radix-ui/react-dialog";
5 | import { VariantProps, cva } from "class-variance-authority";
6 | import { X } from "lucide-react";
7 |
8 | import { cn } from "@/lib/utils";
9 |
10 | const Sheet = SheetPrimitive.Root;
11 |
12 | const SheetTrigger = SheetPrimitive.Trigger;
13 |
14 | const portalVariants = cva("fixed inset-0 z-50 flex", {
15 | variants: {
16 | position: {
17 | top: "items-start",
18 | bottom: "items-end",
19 | left: "justify-start",
20 | right: "justify-end",
21 | },
22 | },
23 | defaultVariants: { position: "right" },
24 | });
25 |
26 | interface SheetPortalProps
27 | extends SheetPrimitive.DialogPortalProps,
28 | VariantProps {}
29 |
30 | const SheetPortal = ({
31 | position,
32 | className,
33 | children,
34 | ...props
35 | }: SheetPortalProps) => (
36 |
37 | {children}
38 |
39 | );
40 | SheetPortal.displayName = SheetPrimitive.Portal.displayName;
41 |
42 | const SheetOverlay = React.forwardRef<
43 | React.ElementRef,
44 | React.ComponentPropsWithoutRef
45 | >(({ className, children, ...props }, ref) => (
46 |
54 | ));
55 | SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
56 |
57 | const sheetVariants = cva(
58 | "fixed z-50 scale-100 gap-4 bg-white p-6 opacity-100 dark:bg-slate-900",
59 | {
60 | variants: {
61 | position: {
62 | top: "animate-in slide-in-from-top w-full duration-300",
63 | bottom: "animate-in slide-in-from-bottom w-full duration-300",
64 | left: "animate-in slide-in-from-left h-full duration-300",
65 | right: "animate-in slide-in-from-right h-full duration-300",
66 | },
67 | size: {
68 | content: "",
69 | default: "",
70 | sm: "",
71 | lg: "",
72 | xl: "",
73 | full: "",
74 | },
75 | },
76 | compoundVariants: [
77 | {
78 | position: ["top", "bottom"],
79 | size: "content",
80 | class: "max-h-screen",
81 | },
82 | {
83 | position: ["top", "bottom"],
84 | size: "default",
85 | class: "h-1/3",
86 | },
87 | {
88 | position: ["top", "bottom"],
89 | size: "sm",
90 | class: "h-1/4",
91 | },
92 | {
93 | position: ["top", "bottom"],
94 | size: "lg",
95 | class: "h-1/2",
96 | },
97 | {
98 | position: ["top", "bottom"],
99 | size: "xl",
100 | class: "h-5/6",
101 | },
102 | {
103 | position: ["top", "bottom"],
104 | size: "full",
105 | class: "h-screen",
106 | },
107 | {
108 | position: ["right", "left"],
109 | size: "content",
110 | class: "max-w-screen",
111 | },
112 | {
113 | position: ["right", "left"],
114 | size: "default",
115 | class: "w-1/3",
116 | },
117 | {
118 | position: ["right", "left"],
119 | size: "sm",
120 | class: "w-1/4",
121 | },
122 | {
123 | position: ["right", "left"],
124 | size: "lg",
125 | class: "w-1/2",
126 | },
127 | {
128 | position: ["right", "left"],
129 | size: "xl",
130 | class: "w-5/6",
131 | },
132 | {
133 | position: ["right", "left"],
134 | size: "full",
135 | class: "w-screen",
136 | },
137 | ],
138 | defaultVariants: {
139 | position: "right",
140 | size: "default",
141 | },
142 | }
143 | );
144 |
145 | export interface DialogContentProps
146 | extends React.ComponentPropsWithoutRef,
147 | VariantProps {}
148 |
149 | const SheetContent = React.forwardRef<
150 | React.ElementRef,
151 | DialogContentProps
152 | >(({ position, size, className, children, ...props }, ref) => (
153 |
154 |
155 |
160 | {children}
161 |
162 |
163 | Close
164 |
165 |
166 |
167 | ));
168 | SheetContent.displayName = SheetPrimitive.Content.displayName;
169 |
170 | const SheetHeader = ({
171 | className,
172 | ...props
173 | }: React.HTMLAttributes) => (
174 |
181 | );
182 | SheetHeader.displayName = "SheetHeader";
183 |
184 | const SheetFooter = ({
185 | className,
186 | ...props
187 | }: React.HTMLAttributes) => (
188 |
195 | );
196 | SheetFooter.displayName = "SheetFooter";
197 |
198 | const SheetTitle = React.forwardRef<
199 | React.ElementRef,
200 | React.ComponentPropsWithoutRef
201 | >(({ className, ...props }, ref) => (
202 |
211 | ));
212 | SheetTitle.displayName = SheetPrimitive.Title.displayName;
213 |
214 | const SheetDescription = React.forwardRef<
215 | React.ElementRef,
216 | React.ComponentPropsWithoutRef
217 | >(({ className, ...props }, ref) => (
218 |
223 | ));
224 | SheetDescription.displayName = SheetPrimitive.Description.displayName;
225 |
226 | export {
227 | Sheet,
228 | SheetTrigger,
229 | SheetContent,
230 | SheetHeader,
231 | SheetFooter,
232 | SheetTitle,
233 | SheetDescription,
234 | };
235 |
--------------------------------------------------------------------------------
/components/ui/slider.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SliderPrimitive from "@radix-ui/react-slider"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Slider = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, ...props }, ref) => (
12 |
20 |
21 |
22 |
23 |
24 |
25 | ))
26 | Slider.displayName = SliderPrimitive.Root.displayName
27 |
28 | export { Slider }
29 |
--------------------------------------------------------------------------------
/components/ui/switch.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SwitchPrimitives from "@radix-ui/react-switch"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Switch = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, ...props }, ref) => (
12 |
20 |
25 |
26 | ))
27 | Switch.displayName = SwitchPrimitives.Root.displayName
28 |
29 | export { Switch }
30 |
--------------------------------------------------------------------------------
/components/ui/tabs.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as TabsPrimitive from "@radix-ui/react-tabs"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Tabs = TabsPrimitive.Root
9 |
10 | const TabsList = React.forwardRef<
11 | React.ElementRef,
12 | React.ComponentPropsWithoutRef
13 | >(({ className, ...props }, ref) => (
14 |
22 | ))
23 | TabsList.displayName = TabsPrimitive.List.displayName
24 |
25 | const TabsTrigger = React.forwardRef<
26 | React.ElementRef,
27 | React.ComponentPropsWithoutRef
28 | >(({ className, ...props }, ref) => (
29 |
37 | ))
38 | TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
39 |
40 | const TabsContent = React.forwardRef<
41 | React.ElementRef,
42 | React.ComponentPropsWithoutRef
43 | >(({ className, ...props }, ref) => (
44 |
52 | ))
53 | TabsContent.displayName = TabsPrimitive.Content.displayName
54 |
55 | export { Tabs, TabsList, TabsTrigger, TabsContent }
56 |
--------------------------------------------------------------------------------
/components/ui/textarea.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { cn } from "@/lib/utils"
4 |
5 | export interface TextareaProps
6 | extends React.TextareaHTMLAttributes {}
7 |
8 | const Textarea = React.forwardRef(
9 | ({ className, ...props }, ref) => {
10 | return (
11 |
19 | )
20 | }
21 | )
22 | Textarea.displayName = "Textarea"
23 |
24 | export { Textarea }
25 |
--------------------------------------------------------------------------------
/components/ui/toast.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as ToastPrimitives from "@radix-ui/react-toast";
3 | import { VariantProps, cva } from "class-variance-authority";
4 | import { X } from "lucide-react";
5 |
6 | import { cn } from "@/lib/utils";
7 |
8 | const ToastProvider = ToastPrimitives.Provider;
9 |
10 | const ToastViewport = React.forwardRef<
11 | React.ElementRef,
12 | React.ComponentPropsWithoutRef
13 | >(({ className, ...props }, ref) => (
14 |
22 | ));
23 | ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
24 |
25 | const toastVariants = cva(
26 | "data-[swipe=move]:transition-none grow-1 group relative pointer-events-auto flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full mt-4 data-[state=closed]:slide-out-to-right-full dark:border-slate-700 last:mt-0 sm:last:mt-4",
27 | {
28 | variants: {
29 | variant: {
30 | default:
31 | "bg-white border-slate-200 dark:bg-slate-800 dark:border-slate-700",
32 | destructive:
33 | "group destructive bg-red-600 text-white border-red-600 dark:border-red-600",
34 | },
35 | },
36 | defaultVariants: {
37 | variant: "default",
38 | },
39 | }
40 | );
41 |
42 | const Toast = React.forwardRef<
43 | React.ElementRef,
44 | React.ComponentPropsWithoutRef &
45 | VariantProps
46 | >(({ className, variant, ...props }, ref) => {
47 | return (
48 |
53 | );
54 | });
55 | Toast.displayName = ToastPrimitives.Root.displayName;
56 |
57 | const ToastAction = React.forwardRef<
58 | React.ElementRef,
59 | React.ComponentPropsWithoutRef
60 | >(({ className, ...props }, ref) => (
61 |
69 | ));
70 | ToastAction.displayName = ToastPrimitives.Action.displayName;
71 |
72 | const ToastClose = React.forwardRef<
73 | React.ElementRef,
74 | React.ComponentPropsWithoutRef
75 | >(({ className, ...props }, ref) => (
76 |
85 |
86 |
87 | ));
88 | ToastClose.displayName = ToastPrimitives.Close.displayName;
89 |
90 | const ToastTitle = React.forwardRef<
91 | React.ElementRef,
92 | React.ComponentPropsWithoutRef
93 | >(({ className, ...props }, ref) => (
94 |
99 | ));
100 | ToastTitle.displayName = ToastPrimitives.Title.displayName;
101 |
102 | const ToastDescription = React.forwardRef<
103 | React.ElementRef,
104 | React.ComponentPropsWithoutRef
105 | >(({ className, ...props }, ref) => (
106 |
111 | ));
112 | ToastDescription.displayName = ToastPrimitives.Description.displayName;
113 |
114 | type ToastProps = React.ComponentPropsWithoutRef;
115 |
116 | type ToastActionElement = React.ReactElement;
117 |
118 | export {
119 | type ToastProps,
120 | type ToastActionElement,
121 | ToastProvider,
122 | ToastViewport,
123 | Toast,
124 | ToastTitle,
125 | ToastDescription,
126 | ToastClose,
127 | ToastAction,
128 | };
129 |
--------------------------------------------------------------------------------
/components/ui/toaster.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { useToast } from "@/hooks/use-toast"
4 |
5 | import {
6 | Toast,
7 | ToastClose,
8 | ToastDescription,
9 | ToastProvider,
10 | ToastTitle,
11 | ToastViewport,
12 | } from "@/components/ui/toast"
13 |
14 | export function Toaster() {
15 | const { toasts } = useToast()
16 |
17 | return (
18 |
19 | {toasts.map(function ({ id, title, description, action, ...props }) {
20 | return (
21 |
22 |
23 | {title && {title}}
24 | {description && (
25 | {description}
26 | )}
27 |
28 | {action}
29 |
30 |
31 | )
32 | })}
33 |
34 |
35 | )
36 | }
37 |
--------------------------------------------------------------------------------
/components/ui/toggle.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as TogglePrimitive from "@radix-ui/react-toggle"
5 | import { VariantProps, cva } from "class-variance-authority"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const toggleVariants = cva(
10 | "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors data-[state=on]:bg-slate-200 dark:hover:bg-slate-800 dark:data-[state=on]:bg-slate-700 focus:outline-none dark:text-slate-100 focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 dark:focus:ring-offset-slate-900 hover:bg-slate-100 dark:hover:text-slate-100 dark:data-[state=on]:text-slate-100",
11 | {
12 | variants: {
13 | variant: {
14 | default: "bg-transparent",
15 | outline:
16 | "bg-transparent border border-slate-200 hover:bg-slate-100 dark:border-slate-700",
17 | },
18 | size: {
19 | default: "h-10 px-3",
20 | sm: "h-9 px-2.5",
21 | lg: "h-11 px-5",
22 | },
23 | },
24 | defaultVariants: {
25 | variant: "default",
26 | size: "default",
27 | },
28 | }
29 | )
30 |
31 | const Toggle = React.forwardRef<
32 | React.ElementRef,
33 | React.ComponentPropsWithoutRef &
34 | VariantProps
35 | >(({ className, variant, size, ...props }, ref) => (
36 |
41 | ))
42 |
43 | Toggle.displayName = TogglePrimitive.Root.displayName
44 |
45 | export { Toggle, toggleVariants }
46 |
--------------------------------------------------------------------------------
/components/ui/tooltip.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as TooltipPrimitive from "@radix-ui/react-tooltip";
5 |
6 | import { cn } from "@/lib/utils";
7 |
8 | const TooltipProvider = TooltipPrimitive.Provider;
9 |
10 | const Tooltip = ({ ...props }) => ;
11 | Tooltip.displayName = TooltipPrimitive.Tooltip.displayName;
12 |
13 | const TooltipTrigger = TooltipPrimitive.Trigger;
14 |
15 | const TooltipContent = React.forwardRef<
16 | React.ElementRef,
17 | React.ComponentPropsWithoutRef
18 | >(({ className, sideOffset = 4, ...props }, ref) => (
19 |
28 | ));
29 | TooltipContent.displayName = TooltipPrimitive.Content.displayName;
30 |
31 | export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
32 |
--------------------------------------------------------------------------------
/config/site.ts:
--------------------------------------------------------------------------------
1 | import { NavItem } from "@/types/nav";
2 |
3 | interface SiteConfig {
4 | name: string;
5 | description: string;
6 | mainNav: NavItem[];
7 | links: {
8 | twitter: string;
9 | github: string;
10 | video: string;
11 | youtube: string;
12 | };
13 | }
14 |
15 | export const siteConfig: SiteConfig = {
16 | name: "videoscribe",
17 | description: "Transcribe any video for free with OpenAI's whisper API",
18 | mainNav: [
19 | {
20 | title: "Home",
21 | href: "/",
22 | },
23 | ],
24 | links: {
25 | twitter: "https://twitter.com/sullyo",
26 | github: "https://github.com/sullyo/videoscribe",
27 | video: "/video",
28 | youtube: "/youtube",
29 | },
30 | };
31 |
--------------------------------------------------------------------------------
/hooks/use-toast.ts:
--------------------------------------------------------------------------------
1 | // Inspired by react-hot-toast library
2 | import * as React from "react"
3 |
4 | import { ToastActionElement, type ToastProps } from "@/components/ui/toast"
5 |
6 | const TOAST_LIMIT = 1
7 | const TOAST_REMOVE_DELAY = 1000
8 |
9 | type ToasterToast = ToastProps & {
10 | id: string
11 | title?: React.ReactNode
12 | description?: React.ReactNode
13 | action?: ToastActionElement
14 | }
15 |
16 | const actionTypes = {
17 | ADD_TOAST: "ADD_TOAST",
18 | UPDATE_TOAST: "UPDATE_TOAST",
19 | DISMISS_TOAST: "DISMISS_TOAST",
20 | REMOVE_TOAST: "REMOVE_TOAST",
21 | } as const
22 |
23 | let count = 0
24 |
25 | function genId() {
26 | count = (count + 1) % Number.MAX_VALUE
27 | return count.toString()
28 | }
29 |
30 | type ActionType = typeof actionTypes
31 |
32 | type Action =
33 | | {
34 | type: ActionType["ADD_TOAST"]
35 | toast: ToasterToast
36 | }
37 | | {
38 | type: ActionType["UPDATE_TOAST"]
39 | toast: Partial
40 | }
41 | | {
42 | type: ActionType["DISMISS_TOAST"]
43 | toastId?: ToasterToast["id"]
44 | }
45 | | {
46 | type: ActionType["REMOVE_TOAST"]
47 | toastId?: ToasterToast["id"]
48 | }
49 |
50 | interface State {
51 | toasts: ToasterToast[]
52 | }
53 |
54 | const toastTimeouts = new Map>()
55 |
56 | const addToRemoveQueue = (toastId: string) => {
57 | if (toastTimeouts.has(toastId)) {
58 | return
59 | }
60 |
61 | const timeout = setTimeout(() => {
62 | toastTimeouts.delete(toastId)
63 | dispatch({
64 | type: "REMOVE_TOAST",
65 | toastId: toastId,
66 | })
67 | }, TOAST_REMOVE_DELAY)
68 |
69 | toastTimeouts.set(toastId, timeout)
70 | }
71 |
72 | export const reducer = (state: State, action: Action): State => {
73 | switch (action.type) {
74 | case "ADD_TOAST":
75 | return {
76 | ...state,
77 | toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
78 | }
79 |
80 | case "UPDATE_TOAST":
81 | return {
82 | ...state,
83 | toasts: state.toasts.map((t) =>
84 | t.id === action.toast.id ? { ...t, ...action.toast } : t
85 | ),
86 | }
87 |
88 | case "DISMISS_TOAST":
89 | const { toastId } = action
90 |
91 | // ! Side effects ! - This could be extracted into a dismissToast() action,
92 | // but I'll keep it here for simplicity
93 | if (toastId) {
94 | addToRemoveQueue(toastId)
95 | } else {
96 | state.toasts.forEach((toast) => {
97 | addToRemoveQueue(toast.id)
98 | })
99 | }
100 |
101 | return {
102 | ...state,
103 | toasts: state.toasts.map((t) =>
104 | t.id === toastId || toastId === undefined
105 | ? {
106 | ...t,
107 | open: false,
108 | }
109 | : t
110 | ),
111 | }
112 | case "REMOVE_TOAST":
113 | if (action.toastId === undefined) {
114 | return {
115 | ...state,
116 | toasts: [],
117 | }
118 | }
119 | return {
120 | ...state,
121 | toasts: state.toasts.filter((t) => t.id !== action.toastId),
122 | }
123 | }
124 | }
125 |
126 | const listeners: Array<(state: State) => void> = []
127 |
128 | let memoryState: State = { toasts: [] }
129 |
130 | function dispatch(action: Action) {
131 | memoryState = reducer(memoryState, action)
132 | listeners.forEach((listener) => {
133 | listener(memoryState)
134 | })
135 | }
136 |
137 | interface Toast extends Omit {}
138 |
139 | function toast({ ...props }: Toast) {
140 | const id = genId()
141 |
142 | const update = (props: ToasterToast) =>
143 | dispatch({
144 | type: "UPDATE_TOAST",
145 | toast: { ...props, id },
146 | })
147 | const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
148 |
149 | dispatch({
150 | type: "ADD_TOAST",
151 | toast: {
152 | ...props,
153 | id,
154 | open: true,
155 | onOpenChange: (open) => {
156 | if (!open) dismiss()
157 | },
158 | },
159 | })
160 |
161 | return {
162 | id: id,
163 | dismiss,
164 | update,
165 | }
166 | }
167 |
168 | function useToast() {
169 | const [state, setState] = React.useState(memoryState)
170 |
171 | React.useEffect(() => {
172 | listeners.push(setState)
173 | return () => {
174 | const index = listeners.indexOf(setState)
175 | if (index > -1) {
176 | listeners.splice(index, 1)
177 | }
178 | }
179 | }, [state])
180 |
181 | return {
182 | ...state,
183 | toast,
184 | dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
185 | }
186 | }
187 |
188 | export { useToast, toast }
189 |
--------------------------------------------------------------------------------
/lib/openai.ts:
--------------------------------------------------------------------------------
1 | import { Configuration, OpenAIApi } from "openai";
2 |
3 | export const OpenAITranscriber = async (file: File, apiKey: string) => {
4 | const configuration = new Configuration({
5 | apiKey,
6 | });
7 | const openai = new OpenAIApi(configuration);
8 | const model = "whisper-1";
9 | const response_format = "srt";
10 | const transcription = await openai.createTranscription(
11 | file,
12 | model,
13 | response_format
14 | );
15 |
16 | if (transcription.status !== 200) {
17 | throw new Error("OpenAI API returned an error");
18 | }
19 | return transcription.data.text;
20 | };
21 |
--------------------------------------------------------------------------------
/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { ClassValue, clsx } from "clsx";
2 | import { twMerge } from "tailwind-merge";
3 |
4 | export function cn(...inputs: ClassValue[]) {
5 | return twMerge(clsx(inputs));
6 | }
7 | export function stripExtension(filename: string): string {
8 | return filename.split(".").slice(0, -1).join(".");
9 | }
10 |
--------------------------------------------------------------------------------
/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/next.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | reactStrictMode: true,
4 | experimental: {
5 | fontLoaders: [
6 | {
7 | loader: "@next/font/google",
8 | options: { subsets: ["latin"] },
9 | },
10 | ],
11 | },
12 | }
13 |
14 | export default nextConfig
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "next-template",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint",
10 | "preview": "next build && next start",
11 | "typecheck": "tsc --noEmit",
12 | "format:write": "prettier --write \"**/*.{ts,tsx,mdx}\" --cache",
13 | "format:check": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache"
14 | },
15 | "dependencies": {
16 | "@lottiefiles/react-lottie-player": "^3.5.2",
17 | "@next/font": "^13.1.6",
18 | "@radix-ui/react-accessible-icon": "^1.0.1",
19 | "@radix-ui/react-accordion": "^1.1.0",
20 | "@radix-ui/react-alert-dialog": "^1.0.2",
21 | "@radix-ui/react-aspect-ratio": "^1.0.1",
22 | "@radix-ui/react-avatar": "^1.0.1",
23 | "@radix-ui/react-checkbox": "^1.0.1",
24 | "@radix-ui/react-collapsible": "^1.0.1",
25 | "@radix-ui/react-context-menu": "^2.1.1",
26 | "@radix-ui/react-dialog": "^1.0.2",
27 | "@radix-ui/react-dropdown-menu": "^2.0.1",
28 | "@radix-ui/react-hover-card": "^1.0.3",
29 | "@radix-ui/react-label": "^2.0.0",
30 | "@radix-ui/react-menubar": "^1.0.0",
31 | "@radix-ui/react-navigation-menu": "^1.1.1",
32 | "@radix-ui/react-popover": "^1.0.2",
33 | "@radix-ui/react-progress": "^1.0.1",
34 | "@radix-ui/react-radio-group": "^1.1.0",
35 | "@radix-ui/react-scroll-area": "^1.0.2",
36 | "@radix-ui/react-select": "^1.2.0",
37 | "@radix-ui/react-separator": "^1.0.1",
38 | "@radix-ui/react-slider": "^1.1.0",
39 | "@radix-ui/react-slot": "^1.0.1",
40 | "@radix-ui/react-switch": "^1.0.1",
41 | "@radix-ui/react-tabs": "^1.0.2",
42 | "@radix-ui/react-toast": "^1.1.2",
43 | "@radix-ui/react-toggle": "^1.0.1",
44 | "@radix-ui/react-toggle-group": "^1.0.1",
45 | "@radix-ui/react-tooltip": "^1.0.3",
46 | "@vercel/analytics": "^0.1.11",
47 | "class-variance-authority": "^0.4.0",
48 | "clsx": "^1.2.1",
49 | "cmdk": "^0.1.21",
50 | "formdata-node": "^5.0.0",
51 | "jotai": "^2.0.3",
52 | "lucide-react": "0.105.0-alpha.4",
53 | "next": "^13.1.6",
54 | "next-themes": "^0.2.1",
55 | "node-fetch": "^3.3.0",
56 | "openai": "^3.2.1",
57 | "react": "^18.2.0",
58 | "react-dom": "^18.2.0",
59 | "react-dropzone": "^14.2.3",
60 | "sharp": "^0.31.3",
61 | "tailwind-merge": "^1.8.0",
62 | "tailwindcss-animate": "^1.0.5",
63 | "ytdl-core": "^4.11.2"
64 | },
65 | "devDependencies": {
66 | "@ianvs/prettier-plugin-sort-imports": "^3.7.1",
67 | "@types/node": "^17.0.12",
68 | "@types/node-fetch": "^2.6.2",
69 | "@types/react": "^18.0.22",
70 | "@types/react-dom": "^18.0.7",
71 | "autoprefixer": "^10.4.13",
72 | "eslint": "^8.31.0",
73 | "eslint-config-next": "13.0.0",
74 | "eslint-config-prettier": "^8.3.0",
75 | "eslint-plugin-react": "^7.31.11",
76 | "eslint-plugin-tailwindcss": "^3.8.0",
77 | "postcss": "^8.4.14",
78 | "prettier": "^2.7.1",
79 | "tailwindcss": "^3.1.7",
80 | "typescript": "^4.5.3"
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import type { AppProps } from "next/app";
2 | import { Inter as FontSans } from "@next/font/google";
3 | import { Analytics } from "@vercel/analytics/react";
4 | import { ThemeProvider } from "next-themes";
5 |
6 | import "@/styles/globals.css";
7 |
8 | const fontSans = FontSans({
9 | subsets: ["latin"],
10 | variable: "--font-sans",
11 | display: "swap",
12 | });
13 |
14 | export default function App({ Component, pageProps }: AppProps) {
15 | return (
16 | <>
17 |
22 |
23 |
24 |
25 |
26 | >
27 | );
28 | }
29 |
--------------------------------------------------------------------------------
/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | import { Head, Html, Main, NextScript } from "next/document";
2 |
3 | export default function Document() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/pages/api/transcribe.ts:
--------------------------------------------------------------------------------
1 | import { randomUUID } from "crypto";
2 | import fs from "fs";
3 | import type { NextApiRequest, NextApiResponse } from "next";
4 | import fetch, { FormData, fileFromSync } from "node-fetch";
5 | import ytdl from "ytdl-core";
6 |
7 | const handler = async (req: NextApiRequest, res: NextApiResponse) => {
8 | if (req.method === "POST") {
9 | const outputFile = `/tmp/${randomUUID()}.mp4`;
10 | const { videoUrl, apiKey, format } = req.body;
11 | try {
12 | const fileStream = ytdl(videoUrl, {
13 | quality: "140",
14 | }).pipe(fs.createWriteStream(outputFile));
15 |
16 | await new Promise((resolve) => {
17 | fileStream.on("finish", resolve);
18 | });
19 | } catch (err: any) {
20 | console.log(`❌ Error message: ${err.message}`);
21 | return res.status(400).send(`Unable to download video: ${err.message}`);
22 | }
23 | try {
24 | const form = new FormData();
25 | const mimetype = "audio/mp4";
26 | const file = fileFromSync(outputFile, mimetype);
27 | form.append("file", file);
28 | form.append("model", "whisper-1");
29 | form.append("response_format", format);
30 |
31 | const response = await fetch(
32 | "https://api.openai.com/v1/audio/transcriptions",
33 | {
34 | method: "POST",
35 | headers: {
36 | Authorization: `Bearer ${apiKey}`,
37 | },
38 | body: form,
39 | }
40 | );
41 | const data = await response.text();
42 |
43 | res.status(200).json({ transcript: data });
44 | } catch (err) {
45 | console.log(`❌ Error message: ${err.message}`);
46 | return res
47 | .status(400)
48 | .send(`Issue with transcribing video from openai: ${err.message}`);
49 | }
50 | } else {
51 | res.setHeader("Allow", "POST");
52 | res.status(405).end("Method Not Allowed");
53 | }
54 | };
55 |
56 | export default handler;
57 |
--------------------------------------------------------------------------------
/pages/index.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/no-unescaped-entities */
2 | import { useState } from "react";
3 | import Head from "next/head";
4 | import Link from "next/link";
5 | import ytdl from "ytdl-core";
6 |
7 | import { siteConfig } from "@/config/site";
8 | import { Layout } from "@/components/layout";
9 | import { Button, buttonVariants } from "@/components/ui/button";
10 | import { Input } from "@/components/ui/input";
11 |
12 | export default function IndexPage() {
13 | return (
14 |
15 |
16 | Videoscribe
17 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | Transcribe any video for free.
28 |
29 |
30 | Turn videos into text in minutes. Whether it's your own files or a
31 | YouTube video, we've got you covered.
32 |
33 |
34 |
35 |
36 |
37 | Upload File
38 |
39 |
43 | Youtube Link
44 |
45 |
46 |
47 |
48 | );
49 | }
50 |
--------------------------------------------------------------------------------
/pages/video.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import Head from "next/head";
3 | import { apiKeyAtom } from "@/atoms";
4 | import { useToast } from "@/hooks/use-toast";
5 | import { useAtom } from "jotai";
6 |
7 | import { stripExtension } from "@/lib/utils";
8 | import Dropzone from "@/components/dropzone";
9 | import FileSelect from "@/components/file-select";
10 | import { Icons } from "@/components/icons";
11 | import { Layout } from "@/components/layout";
12 | import { RobotLoader } from "@/components/transcription-loader";
13 | import { Button } from "@/components/ui/button";
14 | import { ToastAction } from "@/components/ui/toast";
15 |
16 | export default function VideoPage() {
17 | const [loading, setLoading] = useState(false);
18 | const [files, setFiles] = useState([]);
19 | const [format, setFileFormat] = useState("srt");
20 | const [downloadHref, setDownloadHref] = useState("srt");
21 | const [downLoadFile, setDownloadFile] = useState(null);
22 |
23 | const { toast } = useToast();
24 |
25 | const [apiKey] = useAtom(apiKeyAtom);
26 |
27 | const handleTranscribe = async () => {
28 | setLoading(true);
29 | try {
30 | const formData = new FormData();
31 | formData.append("file", files[0]);
32 | formData.append("model", "whisper-1");
33 | formData.append("response_format", format);
34 |
35 | const res = await fetch(
36 | "https://api.openai.com/v1/audio/transcriptions",
37 | {
38 | headers: {
39 | Authorization: `Bearer ${apiKey}`,
40 | },
41 | method: "POST",
42 | body: formData,
43 | }
44 | );
45 |
46 | const transcript = await res.text();
47 |
48 | setLoading(false);
49 |
50 | const file = new Blob([transcript], { type: "text/plain" });
51 | setDownloadFile(file);
52 | setDownloadHref(URL.createObjectURL(file));
53 | } catch (error) {
54 | setLoading(false);
55 | toast({
56 | title: "Error Transcribing ",
57 | variant: "destructive",
58 | description:
59 | "OpenAI had an issue transcribing your file. Either try again or try a different file.",
60 | action: (
61 | window.location.reload()}
64 | >
65 | Try again
66 |
67 | ),
68 | });
69 | console.error(error.message);
70 | }
71 | };
72 |
73 | if (apiKey.length < 51) {
74 | return (
75 |
76 |
77 | Videoscribe
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | Please enter your OpenAI API Key
86 |
87 |
88 |
89 |
90 | );
91 | }
92 |
93 | return (
94 |
95 |
96 | Videoscribe
97 |
98 |
99 |
100 |
101 |
102 | {loading && (
103 |
104 |
105 | Transcribing your file...
106 |
107 |
108 | Do not close this tab.
109 |
110 |
111 |
112 | )}
113 |
114 | {downLoadFile && (
115 |
136 | )}
137 | {!loading && !downLoadFile && (
138 | <>
139 | {files.length > 0 && (
140 |
141 |
142 | File to transcribe:
143 |
144 | {files.map((file) => (
145 |
146 | {file.name}
147 |
148 | ))}
149 |
150 | )}
151 | {files.length === 0 ? (
152 | <>
153 |
154 |
155 | Upload a file and transcribe it.
156 |
157 |
158 | Formats supported: mp3, mp4, mpeg, mpga, m4a, wav, or webm.
159 |
160 |
161 |
162 | >
163 | ) : (
164 |
165 |
168 |
169 |
170 | )}
171 | >
172 | )}
173 |
174 |
175 | );
176 | }
177 |
--------------------------------------------------------------------------------
/pages/youtube.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import Head from "next/head";
3 | import { apiKeyAtom } from "@/atoms";
4 | import { toast } from "@/hooks/use-toast";
5 | import { useAtom } from "jotai";
6 |
7 | import FileSelect from "@/components/file-select";
8 | import { Icons } from "@/components/icons";
9 | import { Layout } from "@/components/layout";
10 | import { RobotLoader } from "@/components/transcription-loader";
11 | import { Button } from "@/components/ui/button";
12 | import { Input } from "@/components/ui/input";
13 | import { ToastAction } from "@/components/ui/toast";
14 |
15 | export default function YoutubePage() {
16 | const [loading, setLoading] = useState(false);
17 | const [videoUrl, setVideoUrl] = useState("");
18 | const [format, setFileFormat] = useState("srt");
19 | const [file, setFile] = useState();
20 | const [downloadHref, setDownloadHref] = useState("");
21 | const [downLoadFile, setDownloadFile] = useState(null);
22 | const [fileName, setFileName] = useState("");
23 | const [apiKey] = useAtom(apiKeyAtom);
24 |
25 | const handleYoutubeDownload = async () => {
26 | setLoading(true);
27 | try {
28 | const response = await fetch("/api/transcribe", {
29 | method: "POST",
30 | headers: { "Content-Type": "application/json" },
31 | body: JSON.stringify({ videoUrl, apiKey, format }),
32 | });
33 |
34 | const { transcript } = await response.json();
35 | const file = new Blob([transcript], { type: "text/plain" });
36 | setDownloadFile(file);
37 | setDownloadHref(URL.createObjectURL(file));
38 | setLoading(false);
39 | } catch (error) {
40 | setLoading(false);
41 | toast({
42 | title: "Error Transcribing ",
43 | variant: "destructive",
44 | description:
45 | "OpenAI had an issue transcribing your file. Either try again or try a different file.",
46 | action: (
47 | window.location.reload()}
50 | >
51 | Try again
52 |
53 | ),
54 | });
55 | console.error(error.message);
56 | }
57 | };
58 |
59 | if (apiKey.length < 51) {
60 | return (
61 |
62 |
63 | Videoscribe
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | Please enter your OpenAI API Key
72 |
73 |
74 |
75 |
76 | );
77 | }
78 |
79 | return (
80 |
81 |
82 | Videoscribe
83 |
84 |
85 |
86 |
87 |
88 | {loading && (
89 |
90 |
91 | Transcribing this youtube video...
92 |
93 |
94 | This may take a few minutes. Do not close this tab.
95 |
96 |
97 |
98 | )}
99 | {downLoadFile && (
100 |
121 | )}
122 | {!loading && !downLoadFile && (
123 | <>
124 |
125 |
126 | Choose a youtube video & transcribe it
127 |
128 |
129 |
130 |
setVideoUrl(e.target.value)}
135 | />
136 |
137 |
143 |
144 |
145 |
146 | >
147 | )}
148 |
149 |
150 | );
151 | }
152 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('prettier').Config} */
2 | module.exports = {
3 | endOfLine: "lf",
4 | singleQuote: false,
5 | tabWidth: 2,
6 | trailingComma: "es5",
7 | importOrder: [
8 | "^(react/(.*)$)|^(react$)",
9 | "^(next/(.*)$)|^(next$)",
10 | "",
11 | "",
12 | "^types$",
13 | "^@/types/(.*)$",
14 | "^@/config/(.*)$",
15 | "^@/lib/(.*)$",
16 | "^@/components/(.*)$",
17 | "^@/styles/(.*)$",
18 | "^[./]",
19 | ],
20 | importOrderSeparation: false,
21 | importOrderSortSpecifiers: true,
22 | importOrderBuiltinModulesToTop: true,
23 | importOrderParserPlugins: ["typescript", "jsx", "decorators-legacy"],
24 | importOrderMergeDuplicateImports: true,
25 | importOrderCombineTypeAndValueImports: true,
26 | plugins: ["@ianvs/prettier-plugin-sort-imports"],
27 | }
28 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sullyo/videoscribe/34245b72d8dd3ceb6ad673018db6b73592a9414b/public/favicon.ico
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/thirteen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | const { fontFamily } = require("tailwindcss/defaultTheme")
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | darkMode: ["class"],
6 | content: ["pages/**/*.{ts,tsx}", "components/**/*.{ts,tsx}"],
7 | theme: {
8 | container: {
9 | center: true,
10 | padding: "1.5rem",
11 | screens: {
12 | "2xl": "1360px",
13 | },
14 | },
15 | extend: {
16 | fontFamily: {
17 | sans: ["var(--font-sans)", ...fontFamily.sans],
18 | },
19 | keyframes: {
20 | "accordion-down": {
21 | from: { height: 0 },
22 | to: { height: "var(--radix-accordion-content-height)" },
23 | },
24 | "accordion-up": {
25 | from: { height: "var(--radix-accordion-content-height)" },
26 | to: { height: 0 },
27 | },
28 | },
29 | animation: {
30 | "accordion-down": "accordion-down 0.2s ease-out",
31 | "accordion-up": "accordion-up 0.2s ease-out",
32 | },
33 | },
34 | },
35 | plugins: [require("tailwindcss-animate")],
36 | }
37 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["dom", "dom.iterable", "esnext"],
4 | "allowJs": true,
5 | "skipLibCheck": true,
6 | "strict": false,
7 | "forceConsistentCasingInFileNames": true,
8 | "noEmit": true,
9 | "incremental": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "baseUrl": ".",
17 | "paths": {
18 | "@/*": ["./*"]
19 | }
20 | },
21 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
22 | "exclude": ["node_modules"]
23 | }
24 |
--------------------------------------------------------------------------------
/tsconfig.tsbuildinfo:
--------------------------------------------------------------------------------
1 | {"program":{"fileNames":["../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2021.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2022.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.esnext.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.dom.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.dom.iterable.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2021.promise.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2021.string.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2021.intl.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2022.array.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2022.error.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2022.intl.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2022.object.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2022.sharedmemory.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.es2022.string.d.ts","../../node_modules/.pnpm/typescript@4.9.4/node_modules/typescript/lib/lib.esnext.intl.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/styled-jsx/types/css.d.ts","../../node_modules/.pnpm/@types+react@18.0.15/node_modules/@types/react/global.d.ts","../../node_modules/.pnpm/csstype@3.1.1/node_modules/csstype/index.d.ts","../../node_modules/.pnpm/@types+prop-types@15.7.5/node_modules/@types/prop-types/index.d.ts","../../node_modules/.pnpm/@types+scheduler@0.16.2/node_modules/@types/scheduler/tracing.d.ts","../../node_modules/.pnpm/@types+react@18.0.15/node_modules/@types/react/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/styled-jsx/types/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/styled-jsx/types/macro.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/styled-jsx/types/style.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/styled-jsx/types/global.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/amp.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/amp.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/assert.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/assert/strict.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/globals.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/async_hooks.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/buffer.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/child_process.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/cluster.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/console.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/constants.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/crypto.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/dgram.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/diagnostics_channel.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/dns.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/dns/promises.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/domain.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/events.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/fs.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/fs/promises.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/http.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/http2.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/https.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/inspector.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/module.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/net.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/os.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/path.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/perf_hooks.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/process.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/punycode.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/querystring.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/readline.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/repl.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/stream.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/stream/promises.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/stream/consumers.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/stream/web.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/string_decoder.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/timers.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/timers/promises.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/tls.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/trace_events.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/tty.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/url.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/util.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/v8.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/vm.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/wasi.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/worker_threads.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/zlib.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/globals.global.d.ts","../../node_modules/.pnpm/@types+node@17.0.45/node_modules/@types/node/index.d.ts","../../node_modules/.pnpm/@types+react@18.0.26/node_modules/@types/react/global.d.ts","../../node_modules/.pnpm/@types+react@18.0.26/node_modules/@types/react/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/get-page-files.d.ts","../../node_modules/.pnpm/@types+react-dom@18.0.9/node_modules/@types/react-dom/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/compiled/webpack/webpack.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/config.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/lib/load-custom-routes.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/image-config.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/build/webpack/plugins/subresource-integrity-plugin.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/config-shared.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/base-http/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/api-utils/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/initialize-require-hook.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/node-polyfill-fetch.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/node-polyfill-web-streams.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/router/utils/route-regex.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/router/utils/route-matcher.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/body-streams.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/request-meta.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/router.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/build/analysis/get-page-static-info.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/build/webpack/loaders/get-module-build-info.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/build/webpack/plugins/middleware-plugin.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/render-result.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/web/next-url.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/web/spec-extension/cookies/types.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/web/spec-extension/cookies/request-cookies.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/web/spec-extension/cookies/response-cookies.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/web/spec-extension/cookies/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/web/spec-extension/request.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/web/spec-extension/fetch-event.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/web/spec-extension/response.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/web/types.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/build/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/build/webpack/plugins/pages-manifest-plugin.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/send-payload/revalidate-headers.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/send-payload/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/base-http/node.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/font-utils.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/load-components.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/build/webpack/plugins/font-loader-manifest-plugin.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/render.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/router/utils/parse-url.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/router/utils/middleware-route-matcher.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/response-cache/types.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/response-cache/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/lib/incremental-cache/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/base-server.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/image-optimizer.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/next-server.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/dev/static-paths-worker.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/dev/next-dev-server.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/next.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/types/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/html-context.d.ts","../../node_modules/.pnpm/@next+env@13.1.6/node_modules/@next/env/types/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/mitt.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/client/with-router.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/client/router.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/client/route-loader.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/client/page-loader.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/router/router.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/constants.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/utils.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/pages/_app.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/app.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/runtime-config.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/config.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/pages/_document.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/document.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/dynamic.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dynamic.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/pages/_error.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/error.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/shared/lib/head.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/head.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/client/image.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/image.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/client/link.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/link.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/router.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/client/script.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/script.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/server/web/spec-extension/user-agent.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/dist/compiled/@edge-runtime/primitives/url.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/server.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/types/global.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/index.d.ts","../../node_modules/.pnpm/next@13.1.6_7xlrwlvvs7cv2obrs6a5y6oxxq/node_modules/next/image-types/global.d.ts","./next-env.d.ts","./types/nav.ts","./config/site.ts","../../node_modules/.pnpm/@radix-ui+react-primitive@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-primitive/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-dismissable-layer@1.0.2_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-dismissable-layer/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-context@1.0.0_react@18.2.0/node_modules/@radix-ui/react-context/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-toast@1.1.2_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-toast/dist/index.d.ts","../../node_modules/.pnpm/class-variance-authority@0.4.0_typescript@4.9.4/node_modules/class-variance-authority/dist/types.d.ts","../../node_modules/.pnpm/class-variance-authority@0.4.0_typescript@4.9.4/node_modules/class-variance-authority/dist/index.d.ts","../../node_modules/.pnpm/lucide-react@0.105.0-alpha.4_react@18.2.0/node_modules/lucide-react/dist/lucide-react.d.ts","../../node_modules/.pnpm/clsx@1.2.1/node_modules/clsx/clsx.d.ts","../../node_modules/.pnpm/tailwind-merge@1.8.0/node_modules/tailwind-merge/dist/lib/tw-join.d.ts","../../node_modules/.pnpm/tailwind-merge@1.8.0/node_modules/tailwind-merge/dist/lib/tw-merge.d.ts","../../node_modules/.pnpm/tailwind-merge@1.8.0/node_modules/tailwind-merge/dist/lib/validators.d.ts","../../node_modules/.pnpm/tailwind-merge@1.8.0/node_modules/tailwind-merge/dist/lib/types.d.ts","../../node_modules/.pnpm/tailwind-merge@1.8.0/node_modules/tailwind-merge/dist/lib/default-config.d.ts","../../node_modules/.pnpm/tailwind-merge@1.8.0/node_modules/tailwind-merge/dist/lib/extend-tailwind-merge.d.ts","../../node_modules/.pnpm/tailwind-merge@1.8.0/node_modules/tailwind-merge/dist/lib/create-tailwind-merge.d.ts","../../node_modules/.pnpm/tailwind-merge@1.8.0/node_modules/tailwind-merge/dist/lib/merge-configs.d.ts","../../node_modules/.pnpm/tailwind-merge@1.8.0/node_modules/tailwind-merge/dist/lib/from-theme.d.ts","../../node_modules/.pnpm/tailwind-merge@1.8.0/node_modules/tailwind-merge/dist/index.d.ts","./lib/utils.ts","./components/ui/toast.tsx","./hooks/use-toast.ts","./components/icons.tsx","./components/ui/button.tsx","../../node_modules/.pnpm/@radix-ui+react-focus-scope@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-focus-scope/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-arrow@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-arrow/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+rect@1.0.0/node_modules/@radix-ui/rect/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-popper@1.0.1_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-popper/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-portal@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-portal/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-roving-focus@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-roving-focus/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-menu@2.0.1_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-menu/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-dropdown-menu@2.0.1_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-dropdown-menu/dist/index.d.ts","./components/ui/dropdown-menu.tsx","./components/main-nav.tsx","../../node_modules/.pnpm/next-themes@0.2.1_3vryta7zmbcsw4rrqf4axjqggm/node_modules/next-themes/dist/types.d.ts","../../node_modules/.pnpm/next-themes@0.2.1_3vryta7zmbcsw4rrqf4axjqggm/node_modules/next-themes/dist/index.d.ts","./components/theme-toggle.tsx","./components/site-header.tsx","./components/layout.tsx","../../node_modules/.pnpm/@radix-ui+react-collapsible@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-collapsible/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-accordion@1.1.0_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-accordion/dist/index.d.ts","./components/ui/accordion.tsx","../../node_modules/.pnpm/@radix-ui+react-dialog@1.0.2_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-dialog/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-alert-dialog@1.0.2_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-alert-dialog/dist/index.d.ts","./components/ui/alert-dialog.tsx","../../node_modules/.pnpm/@radix-ui+react-aspect-ratio@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-aspect-ratio/dist/index.d.ts","./components/ui/aspect-ratio.tsx","../../node_modules/.pnpm/@radix-ui+react-avatar@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-avatar/dist/index.d.ts","./components/ui/avatar.tsx","../../node_modules/.pnpm/@radix-ui+react-checkbox@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-checkbox/dist/index.d.ts","./components/ui/checkbox.tsx","./components/ui/collapsible.tsx","../../node_modules/.pnpm/@radix-ui+react-primitive@1.0.0_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-primitive/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-dismissable-layer@1.0.0_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-dismissable-layer/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-focus-scope@1.0.0_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-focus-scope/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-portal@1.0.0_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-portal/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-dialog@1.0.0_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-dialog/dist/index.d.ts","../../node_modules/.pnpm/cmdk@0.1.21_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/cmdk/dist/index.d.ts","./components/ui/dialog.tsx","./components/ui/command.tsx","../../node_modules/.pnpm/@radix-ui+react-popper@1.1.0_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-popper/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-roving-focus@1.0.2_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-roving-focus/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-menu@2.0.2_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-menu/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-context-menu@2.1.1_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-context-menu/dist/index.d.ts","./components/ui/context-menu.tsx","../../node_modules/.pnpm/@radix-ui+react-hover-card@1.0.3_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-hover-card/dist/index.d.ts","./components/ui/hover-card.tsx","./components/ui/input.tsx","../../node_modules/.pnpm/@radix-ui+react-label@2.0.0_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-label/dist/index.d.ts","./components/ui/label.tsx","../../node_modules/.pnpm/@radix-ui+react-menubar@1.0.0_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-menubar/dist/index.d.ts","./components/ui/menubar.tsx","../../node_modules/.pnpm/@radix-ui+react-visually-hidden@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-visually-hidden/dist/index.d.ts","../../node_modules/.pnpm/@radix-ui+react-navigation-menu@1.1.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-navigation-menu/dist/index.d.ts","./components/ui/navigation-menu.tsx","../../node_modules/.pnpm/@radix-ui+react-popover@1.0.2_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-popover/dist/index.d.ts","./components/ui/popover.tsx","../../node_modules/.pnpm/@radix-ui+react-progress@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-progress/dist/index.d.ts","./components/ui/progress.tsx","../../node_modules/.pnpm/@radix-ui+react-radio-group@1.1.0_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-radio-group/dist/index.d.ts","./components/ui/radio-group.tsx","../../node_modules/.pnpm/@radix-ui+react-scroll-area@1.0.2_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-scroll-area/dist/index.d.ts","./components/ui/scroll-area.tsx","../../node_modules/.pnpm/@radix-ui+react-select@1.2.0_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-select/dist/index.d.ts","./components/ui/select.tsx","../../node_modules/.pnpm/@radix-ui+react-separator@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-separator/dist/index.d.ts","./components/ui/separator.tsx","../../node_modules/.pnpm/@radix-ui+react-slider@1.1.0_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-slider/dist/index.d.ts","./components/ui/slider.tsx","../../node_modules/.pnpm/@radix-ui+react-switch@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-switch/dist/index.d.ts","./components/ui/switch.tsx","../../node_modules/.pnpm/@radix-ui+react-tabs@1.0.2_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-tabs/dist/index.d.ts","./components/ui/tabs.tsx","./components/ui/textarea.tsx","./components/ui/toaster.tsx","../../node_modules/.pnpm/@radix-ui+react-toggle@1.0.1_biqbaboplfbrettd7655fr4n2y/node_modules/@radix-ui/react-toggle/dist/index.d.ts","./components/ui/toggle.tsx","../../node_modules/.pnpm/@radix-ui+react-tooltip@1.0.3_ib3m5ricvtkl2cll7qpr2f6lvq/node_modules/@radix-ui/react-tooltip/dist/index.d.ts","./components/ui/tooltip.tsx","../../node_modules/.pnpm/@next+font@13.1.6/node_modules/@next/font/dist/types.d.ts","../../node_modules/.pnpm/@next+font@13.1.6/node_modules/@next/font/dist/google/index.d.ts","../../node_modules/.pnpm/@next+font@13.1.6/node_modules/@next/font/google/index.d.ts","./pages/_app.tsx","./pages/_document.tsx","./pages/index.tsx"],"fileInfos":[{"version":"8730f4bf322026ff5229336391a18bcaa1f94d4f82416c8b2f3954e2ccaae2ba","affectsGlobalScope":true},"dc47c4fa66b9b9890cf076304de2a9c5201e94b740cffdf09f87296d877d71f6","7a387c58583dfca701b6c85e0adaf43fb17d590fb16d5b2dc0a2fbd89f35c467","8a12173c586e95f4433e0c6dc446bc88346be73ffe9ca6eec7aa63c8f3dca7f9","5f4e733ced4e129482ae2186aae29fde948ab7182844c3a5a51dd346182c7b06","4b421cbfb3a38a27c279dec1e9112c3d1da296f77a1a85ddadf7e7a425d45d18","1fc5ab7a764205c68fa10d381b08417795fc73111d6dd16b5b1ed36badb743d9","746d62152361558ea6d6115cf0da4dd10ede041d14882ede3568bce5dc4b4f1f","d11a03592451da2d1065e09e61f4e2a9bf68f780f4f6623c18b57816a9679d17","aea179452def8a6152f98f63b191b84e7cbd69b0e248c91e61fb2e52328abe8c",{"version":"3aafcb693fe5b5c3bd277bd4c3a617b53db474fe498fc5df067c5603b1eebde7","affectsGlobalScope":true},{"version":"f3d4da15233e593eacb3965cde7960f3fddf5878528d882bcedd5cbaba0193c7","affectsGlobalScope":true},{"version":"adb996790133eb33b33aadb9c09f15c2c575e71fb57a62de8bf74dbf59ec7dfb","affectsGlobalScope":true},{"version":"8cc8c5a3bac513368b0157f3d8b31cfdcfe78b56d3724f30f80ed9715e404af8","affectsGlobalScope":true},{"version":"cdccba9a388c2ee3fd6ad4018c640a471a6c060e96f1232062223063b0a5ac6a","affectsGlobalScope":true},{"version":"c5c05907c02476e4bde6b7e76a79ffcd948aedd14b6a8f56e4674221b0417398","affectsGlobalScope":true},{"version":"5f406584aef28a331c36523df688ca3650288d14f39c5d2e555c95f0d2ff8f6f","affectsGlobalScope":true},{"version":"22f230e544b35349cfb3bd9110b6ef37b41c6d6c43c3314a31bd0d9652fcec72","affectsGlobalScope":true},{"version":"7ea0b55f6b315cf9ac2ad622b0a7813315bb6e97bf4bb3fbf8f8affbca7dc695","affectsGlobalScope":true},{"version":"3013574108c36fd3aaca79764002b3717da09725a36a6fc02eac386593110f93","affectsGlobalScope":true},{"version":"eb26de841c52236d8222f87e9e6a235332e0788af8c87a71e9e210314300410a","affectsGlobalScope":true},{"version":"3be5a1453daa63e031d266bf342f3943603873d890ab8b9ada95e22389389006","affectsGlobalScope":true},{"version":"17bb1fc99591b00515502d264fa55dc8370c45c5298f4a5c2083557dccba5a2a","affectsGlobalScope":true},{"version":"7ce9f0bde3307ca1f944119f6365f2d776d281a393b576a18a2f2893a2d75c98","affectsGlobalScope":true},{"version":"6a6b173e739a6a99629a8594bfb294cc7329bfb7b227f12e1f7c11bc163b8577","affectsGlobalScope":true},{"version":"81cac4cbc92c0c839c70f8ffb94eb61e2d32dc1c3cf6d95844ca099463cf37ea","affectsGlobalScope":true},{"version":"b0124885ef82641903d232172577f2ceb5d3e60aed4da1153bab4221e1f6dd4e","affectsGlobalScope":true},{"version":"0eb85d6c590b0d577919a79e0084fa1744c1beba6fd0d4e951432fa1ede5510a","affectsGlobalScope":true},{"version":"da233fc1c8a377ba9e0bed690a73c290d843c2c3d23a7bd7ec5cd3d7d73ba1e0","affectsGlobalScope":true},{"version":"d154ea5bb7f7f9001ed9153e876b2d5b8f5c2bb9ec02b3ae0d239ec769f1f2ae","affectsGlobalScope":true},{"version":"bb2d3fb05a1d2ffbca947cc7cbc95d23e1d053d6595391bd325deb265a18d36c","affectsGlobalScope":true},{"version":"c80df75850fea5caa2afe43b9949338ce4e2de086f91713e9af1a06f973872b8","affectsGlobalScope":true},{"version":"9d57b2b5d15838ed094aa9ff1299eecef40b190722eb619bac4616657a05f951","affectsGlobalScope":true},{"version":"6c51b5dd26a2c31dbf37f00cfc32b2aa6a92e19c995aefb5b97a3a64f1ac99de","affectsGlobalScope":true},{"version":"6e7997ef61de3132e4d4b2250e75343f487903ddf5370e7ce33cf1b9db9a63ed","affectsGlobalScope":true},{"version":"2ad234885a4240522efccd77de6c7d99eecf9b4de0914adb9a35c0c22433f993","affectsGlobalScope":true},{"version":"5e5e095c4470c8bab227dbbc61374878ecead104c74ab9960d3adcccfee23205","affectsGlobalScope":true},{"version":"09aa50414b80c023553090e2f53827f007a301bc34b0495bfb2c3c08ab9ad1eb","affectsGlobalScope":true},{"version":"d7f680a43f8cd12a6b6122c07c54ba40952b0c8aa140dcfcf32eb9e6cb028596","affectsGlobalScope":true},{"version":"3787b83e297de7c315d55d4a7c546ae28e5f6c0a361b7a1dcec1f1f50a54ef11","affectsGlobalScope":true},{"version":"e7e8e1d368290e9295ef18ca23f405cf40d5456fa9f20db6373a61ca45f75f40","affectsGlobalScope":true},{"version":"faf0221ae0465363c842ce6aa8a0cbda5d9296940a8e26c86e04cc4081eea21e","affectsGlobalScope":true},{"version":"06393d13ea207a1bfe08ec8d7be562549c5e2da8983f2ee074e00002629d1871","affectsGlobalScope":true},{"version":"2768ef564cfc0689a1b76106c421a2909bdff0acbe87da010785adab80efdd5c","affectsGlobalScope":true},{"version":"b248e32ca52e8f5571390a4142558ae4f203ae2f94d5bac38a3084d529ef4e58","affectsGlobalScope":true},{"version":"6c55633c733c8378db65ac3da7a767c3cf2cf3057f0565a9124a16a3a2019e87","affectsGlobalScope":true},{"version":"fb4416144c1bf0323ccbc9afb0ab289c07312214e8820ad17d709498c865a3fe","affectsGlobalScope":true},{"version":"5b0ca94ec819d68d33da516306c15297acec88efeb0ae9e2b39f71dbd9685ef7","affectsGlobalScope":true},{"version":"34c839eaaa6d78c8674ae2c37af2236dee6831b13db7b4ef4df3ec889a04d4f2","affectsGlobalScope":true},{"version":"34478567f8a80171f88f2f30808beb7da15eac0538ae91282dd33dce928d98ed","affectsGlobalScope":true},{"version":"ab7d58e6161a550ff92e5aff755dc37fe896245348332cd5f1e1203479fe0ed1","affectsGlobalScope":true},{"version":"6bda95ea27a59a276e46043b7065b55bd4b316c25e70e29b572958fa77565d43","affectsGlobalScope":true},{"version":"aedb8de1abb2ff1095c153854a6df7deae4a5709c37297f9d6e9948b6806fa66","affectsGlobalScope":true},{"version":"a4da0551fd39b90ca7ce5f68fb55d4dc0c1396d589b612e1902f68ee090aaada","affectsGlobalScope":true},{"version":"11ffe3c281f375fff9ffdde8bbec7669b4dd671905509079f866f2354a788064","affectsGlobalScope":true},{"version":"52d1bb7ab7a3306fd0375c8bff560feed26ed676a5b0457fa8027b563aecb9a4","affectsGlobalScope":true},"0990a7576222f248f0a3b888adcb7389f957928ce2afb1cd5128169086ff4d29",{"version":"bbdf156fea2fabed31a569445835aeedcc33643d404fcbaa54541f06c109df3f","affectsGlobalScope":true},"1c29793071152b207c01ea1954e343be9a44d85234447b2b236acae9e709a383","6a386ff939f180ae8ef064699d8b7b6e62bc2731a62d7fbf5e02589383838dea","f5a8b384f182b3851cec3596ccc96cb7464f8d3469f48c74bf2befb782a19de5",{"version":"e870860b52176fc9c884bbd62b6dbb4982e84a3dd33782333b952653979911eb","affectsGlobalScope":true},"cc69795d9954ee4ad57545b10c7bf1a7260d990231b1685c147ea71a6faa265c","8bc6c94ff4f2af1f4023b7bb2379b08d3d7dd80c698c9f0b07431ea16101f05f","1b61d259de5350f8b1e5db06290d31eaebebc6baafd5f79d314b5af9256d7153","57194e1f007f3f2cbef26fa299d4c6b21f4623a2eddc63dfeef79e38e187a36e","0f6666b58e9276ac3a38fdc80993d19208442d6027ab885580d93aec76b4ef00","05fd364b8ef02fb1e174fbac8b825bdb1e5a36a016997c8e421f5fab0a6da0a0","0cba3a5d7b81356222594442753cf90dd2892e5ccfe1d262aaca6896ba6c1380","a69c09dbea52352f479d3e7ac949fde3d17b195abe90b045d619f747b38d6d1a",{"version":"77f0b5c6a193a699c9f7d7fb0578e64e562d271afa740783665d2a827104a873","affectsGlobalScope":true},"e5979905796fe2740d85fbaf4f11f42b7ee1851421afe750823220813421b1af",{"version":"fcdcb42da18dd98dc286b1876dd425791772036012ae61263c011a76b13a190f","affectsGlobalScope":true},"1dab5ab6bcf11de47ab9db295df8c4f1d92ffa750e8f095e88c71ce4c3299628","f71f46ccd5a90566f0a37b25b23bc4684381ab2180bdf6733f4e6624474e1894",{"version":"54e65985a3ee3cec182e6a555e20974ea936fc8b8d1738c14e8ed8a42bd921d4","affectsGlobalScope":true},"82408ed3e959ddc60d3e9904481b5a8dc16469928257af22a3f7d1a3bc7fd8c4","5b30f550565fd0a7524282c81c27fe8534099e2cd26170ca80852308f07ae68d","34e5de87d983bc6aefef8b17658556e3157003e8d9555d3cb098c6bef0b5fbc8","d97cd8a4a42f557fc62271369ed0461c8e50d47b7f9c8ad0b5462f53306f6060","f27371653aded82b2b160f7a7033fb4a5b1534b6f6081ef7be1468f0f15327d3","c762cd6754b13a461c54b59d0ae0ab7aeef3c292c6cf889873f786ee4d8e75c9","f4ea7d5df644785bd9fbf419930cbaec118f0d8b4160037d2339b8e23c059e79",{"version":"bfea28e6162ed21a0aeed181b623dcf250aa79abf49e24a6b7e012655af36d81","affectsGlobalScope":true},"b8aca9d0c81abb02bec9b7621983ae65bde71da6727580070602bd2500a9ce2a","ae97e20f2e10dbeec193d6a2f9cd9a367a1e293e7d6b33b68bacea166afd7792","10d4796a130577d57003a77b95d8723530bbec84718e364aa2129fa8ffba0378","063f53ff674228c190efa19dd9448bcbd540acdbb48a928f4cf3a1b9f9478e43","bf73c576885408d4a176f44a9035d798827cc5020d58284cb18d7573430d9022","7ae078ca42a670445ae0c6a97c029cb83d143d62abd1730efb33f68f0b2c0e82",{"version":"e8b18c6385ff784228a6f369694fcf1a6b475355ba89090a88de13587a9391d5","affectsGlobalScope":true},"287b21dc1d1b9701c92e15e7dd673dfe6044b15812956377adffb6f08825b1bc","12eea70b5e11e924bb0543aea5eadc16ced318aa26001b453b0d561c2fd0bd1e","08777cd9318d294646b121838574e1dd7acbb22c21a03df84e1f2c87b1ad47f2","08a90bcdc717df3d50a2ce178d966a8c353fd23e5c392fd3594a6e39d9bb6304",{"version":"4cd4cff679c9b3d9239fd7bf70293ca4594583767526916af8e5d5a47d0219c7","affectsGlobalScope":true},"2a12d2da5ac4c4979401a3f6eaafa874747a37c365e4bc18aa2b171ae134d21b","002b837927b53f3714308ecd96f72ee8a053b8aeb28213d8ec6de23ed1608b66","1dc9c847473bb47279e398b22c740c83ea37a5c88bf66629666e3cf4c5b9f99c","a9e4a5a24bf2c44de4c98274975a1a705a0abbaad04df3557c2d3cd8b1727949","00fa7ce8bc8acc560dc341bbfdf37840a8c59e6a67c9bfa3fa5f36254df35db2","1b952304137851e45bc009785de89ada562d9376177c97e37702e39e60c2f1ff",{"version":"806ef4cac3b3d9fa4a48d849c8e084d7c72fcd7b16d76e06049a9ed742ff79c0","affectsGlobalScope":true},"44b8b584a338b190a59f4f6929d072431950c7bd92ec2694821c11bce180c8a5","5f0ed51db151c2cdc4fa3bb0f44ce6066912ad001b607a34e65a96c52eb76248",{"version":"af9771b066ec35ffa1c7db391b018d2469d55e51b98ae95e62b6cbef1b0169ca","affectsGlobalScope":true},"664d8f2d59164f2e08c543981453893bc7e003e4dfd29651ce09db13e9457980","103d70bfbeb3cd3a3f26d1705bf986322d8738c2c143f38ebb743b1e228d7444","f52fbf64c7e480271a9096763c4882d356b05cab05bf56a64e68a95313cd2ce2","59bdb65f28d7ce52ccfc906e9aaf422f8b8534b2d21c32a27d7819be5ad81df7",{"version":"3a2da34079a2567161c1359316a32e712404b56566c45332ac9dcee015ecce9f","affectsGlobalScope":true},"28a2e7383fd898c386ffdcacedf0ec0845e5d1a86b5a43f25b86bc315f556b79","3aff9c8c36192e46a84afe7b926136d520487155154ab9ba982a8b544ea8fc95","a880cf8d85af2e4189c709b0fea613741649c0e40fffb4360ec70762563d5de0","85bbf436a15bbeda4db888be3062d47f99c66fd05d7c50f0f6473a9151b6a070","9f9c49c95ecd25e0cb2587751925976cf64fd184714cb11e213749c80cf0f927","f0c75c08a71f9212c93a719a25fb0320d53f2e50ca89a812640e08f8ad8c408c",{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true},"9cafe917bf667f1027b2bb62e2de454ecd2119c80873ad76fc41d941089753b8",{"version":"bbdf156fea2fabed31a569445835aeedcc33643d404fcbaa54541f06c109df3f","affectsGlobalScope":true},{"version":"ef8a481f9f2205fcc287eef2b4e461d2fc16bc8a0e49a844681f2f742d69747e","affectsGlobalScope":true},"30a1b56068b3820c91a055425a6af2294f8ef2bb10a59dcda413f6437093620d","e4dd91dd4789a109aab51d8a0569a282369fcda9ba6f2b2297bc61bacfb1a042","db6d2d9daad8a6d83f281af12ce4355a20b9a3e71b82b9f57cddcca0a8964a96","5d97586646b92d2c7d8013e7078d7e06662db89d1155d2903e7ef893665dbd16","625e5d5e9e25017d53e65c62ff944d812d48ec1bbaaf7395c8f8cdf6c9218061","dbe7db9a8a34bb2538505d52d7c24e3ea7cecb751a0b43347a4a9e1f5ae1aa5c","39a3fc61a65aee8c90cd81bb2c9b508be6c5cc745cd40eaed95954a07c11bb82","fcf6ce3735ff6b1296e12468f32142a462ab752ef6e856ca79908abdb5b4bfe0","3150ee51540bdf0d4e0ccb05de6f905962dc3505bd28b7385c6924f7d9eeba11","2302818e3723d16f85c3d75de67247a1bacc23f5399b8235fde025737a6cc5b8","8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","6b54d9dc8b614a8112eeea74a5cfc3a6d45e67007d2da94ec96cbcec1bfe6c06","98e00fba67d4b527de2929778f96c7f9453fbbb8c50968ff096dddd29057450b","9f6caa8495de09a303e6290a3ee15650dbcc75af637449b8fc249ca2d2094004","139c4f4b86b2f19fb58ad7043d68032729ae50dc0fad52825e0466becd9c79eb","c10187772095e8fcc648aa8fc643d2357c589ec763f25af043b889efe7ac832b","6c8d48ede5f1fc63b6fe58c61c7cda35794ba05e11be8c1f1ed0780efedf8b28","22082ac39501b626f8b4322d6bd6fb0424de438777b141f663286cf8bd048398","f7c3d9fed586680437235e2ef6f6a1a69fb47d4524679d295355601edd71a18d","cfe1714064aa842b413125bb353c4625ce313fb0318f84e1015ad74c8f1c91f3","61716ffc5c1011548c0691798dbf9e5f4bebebddc3b7da3b83e93615c7cbb265","97023a8ac2c5d9c9cad96a374eceb49ce7df43ccd669c379c97f04fee55c25a0","efbb14c342884141e21966b812a10509167507a1a6dd86e3dce717a2642d6e6a","2631451ef83e2d263bf40de98dff80ac3852871da3d48531c6b71601b767de47","dce67ee42028e07a6801743d82aefc1531d35b2153a21f7764f73d3218c97709","6cad714c085fc87d55e67b3d269014c6722b8477187b366dfcf4cc2f7b1f9b2b","58902668adae2e5eb67efbccb4048afa02308fa684f1a4e4c7d47668ecf58c1b","3d365237792d79384c1315ad7fba7505b4355ba88d2032349ab437bf7b22e2e8","e5b2baacc2ebb20dcb570b5e6f99e60dd35a55ae490b096bce2efc29e3a96ce1","d114431b4eb5571072d8310555f0d937597ecf1935d98c840f56ad86887f5795","5e19d1888ba7d67fa01640154e32378896a8f3198cb227035afef565dd7e1588","17937316a2f7f362dd6375251a9ce9e4960cfdc0aa7ba6cbd00656f7ab92334b","575bc12d93a33c09e803375cd99a77f50c9272d01abe26d5de27af637c7427a3","39a9af32c7cfa9f1f96c5c8599b3e0ff5285edb41247272880aefe0daee5a43a","9b9a846c90d84dce215990a86a8b5ee7ad24ed7bac50d20d095de5d5627b212f","79832350f1a38cab037218ccbc04d5425b0d2cd330bc821db216f3e813457127","11bf67658477b5f9cf859f106e39be5ee8c5f5f63126bb839aedc9c559433e52","cc0edde838d15c6d272b7b610caf73803efc4e5974ab2079a22beb7b5f27f646","6e5f5cee603d67ee1ba6120815497909b73399842254fc1e77a0d5cdc51d8c9c","f6404e7837b96da3ea4d38c4f1a3812c96c9dcdf264e93d5bdb199f983a3ef4b","7a8940a18491e942d59713bdb6693a1df122615c7595f4a52e9bd808afd0228d","2882275baf937ce116e835d72c9248f6ebde5ce23ca9fb7cf82b7bff39f4e4fc","f9d5c11015ecb267eac5ab59606f75f763dc541d0ddc26e86c9f79b8b5810a8d","8e6d18b22da3989e94ed861d07c45e3a484fe88013970e6560203a46c1f0ae1b","5a2d21ca0e2019640e54a03b8768132a168a35e25e5957abce79cf8a4e10cfa8","b80db8060c4e6e67a1785275bdab95dca1a61ae4dcebef1485df4844d003e3b0","2c94dc2a39a7992b055d9c9d15c82a81a80b0f93c8c9ff2b69ea84c4337ce83a","08eaf47ee3150eba5afc0554771e68f01c43f76b8b1fda71367b4f89fa0b132c","5cab8fa167ee711e4dfcd22ed632c60be36bd49dc6eea8cfdd3613c59d00c43d",{"version":"901d4041ce6c4c901cafa0aeb1b511e72b21d6c6631214c5dc34e18ed796099f","affectsGlobalScope":true},"04a29c45b12f113812c7dcebdc2e8558f0775c70d35042f93616300b6b3550ec","00357bb70a10782936bbfdf7c87ad632e5c2694b6714224ea0995299db1885ed","2766dee26ea113e9b491b7842cb44df57c4d79b17057b42607e09fc174bd411d","cb4047ce260c2f4585b2d592d04a1d9a9c2a1ba32679a688523ec314a977989a","0511c61c22d677da1b6bab4d3844aead1d7e27028d2f0ed1ed315e0860ed5357",{"version":"b4610d904ab939109aa8bcee6f795de8da780b6b4a4d8ff2ff9d2e3b699f55b7","affectsGlobalScope":true},{"version":"6707b2ff066e782f676f90ba7abfca7d6f321eececbbecf3d42eebb7a8c28da2","affectsGlobalScope":true},{"version":"a5f9c19af25fd29cf86b61d3775add09ec59b54d635990e285706dace7430c2b","affectsGlobalScope":true},"2d210643aff12f1beee1fe09bf5ebb2fcb1b6ca8d37e5f992299f4a0871d56c7","4d3cb51deb665532219e1011ecd468216e0df99ae3ed9d58a32e4fe07ebe353f","06dfd2ebf571b3df2cc23a70f031417eb77f7702f0ce727cec99a296242d6929","65c24a8baa2cca1de069a0ba9fba82a173690f52d7e2d0f1f7542d59d5eb4db0","b7fff2d004c5879cae335db8f954eb1d61242d9f2d28515e67902032723caeab","8303df69e9d100e3df8f2d67ec77348cb6494dc406356fdd9b56e61aa7c3c758","8de50542d92f9ac659c30ead0a97e9c107dd3404a3b4fd4bf3504589a026221a","4545c1a1ceca170d5d83452dd7c4994644c35cf676a671412601689d9a62da35","bbff899d5b0a6fda33c17d8de7e2599a7d9aa7cda5eb5ba27e2bebf6cf439608","a2d648d333cf67b9aeac5d81a1a379d563a8ffa91ddd61c6179f68de724260ff","c3a905a7fa93ca648349e934fb19356cf7b40e48d65658de3e0c77d67696fd40","a3f41ed1b4f2fc3049394b945a68ae4fdefd49fa1739c32f149d32c0545d67f5","c2489c80994d62e5b51370a6f02f537db4c37af5f914fcb5b2755b81f1906cae","47699512e6d8bebf7be488182427189f999affe3addc1c87c882d36b7f2d0b0e","da5f632f5f82f60322089dc4f73fde31ba4c51d599d920d1cad0eef686c71f7c","42c686ce08bf5576ed178f4a6a62d1b580d941334fb53bdff7054e0980f2dc75","605b66155b4f222c5f5a48bf19224815e4bceb2966dfb1c5704692ed07e5fa0a","cdf21eee8007e339b1b9945abf4a7b44930b1d695cc528459e68a3adc39a622e","1d079c37fa53e3c21ed3fa214a27507bda9991f2a41458705b19ed8c2b61173d","26a451bf3a5f87ebaaa7694c5b664c3d9cec296f3fa8b797b872aee0f302b3a0","5835a6e0d7cd2738e56b671af0e561e7c1b4fb77751383672f4b009f4e161d70","c0eeaaa67c85c3bb6c52b629ebbfd3b2292dc67e8c0ffda2fc6cd2f78dc471e6","4b7f74b772140395e7af67c4841be1ab867c11b3b82a51b1aeb692822b76c872",{"version":"b57b61d9a3f3e4243d1bc307a14f7e678057a86710f2c30ec0cd254a55f36948","affectsGlobalScope":true},{"version":"57ad3ef8cd87e876021acbcabcc6457f21a721cb0c5388de700bd57ea32030c1","affectsGlobalScope":true},"9c00f78ac4e60d1c34d0fb415df6b2fea5f6eea200076dff4d782256a4c2802d","79d056984a8964d3917c7587067447d7565d9da696fcf6ecaa5e8437a214f04e","9269d492817e359123ac64c8205e5d05dab63d71a3a7a229e68b5d9a0e8150bf","fce3be25a64ca64c47d90887b7055580ad97976c00d1e3b9bac188cc381f05a6","355af7b7b0732517c982e2c296e50f717c56c1e7a8d277729720164898ccb025","725d7c13ea07d985981d8d815fcc2de328fb01e7ae7edc1b28f8331764f22ac5","f3095dfa3cf7be7b80dee24765c5213d51ed3f954a925839963da606ee6df74d","bd409b19dd2d7fc2d965e2fe7758d8af696150f3300d7d7f83c1a82eecda9979","2b6897733f5e680e2470e66f19589f7a276ef7f7ffc480b2dea2d926a93c4f94","951a918a753179bf5c018065e3302c8e2d899600ac1e7e5dfc1c2d9867a643c5","842454d0222fa151b62f4f18c893335993829311367f4502270d449bd32c1b72","894711d8c2e76012cc3258ab90fc6339b19a792349f94c16e1b4801709e0eb94","7a129438cedf12b5f1b5f773a3e96242b7569c95243432dcf12618f80fca5cdc","eead9bccaa73110c70b335084a2430431bbb0330d8a25dfa53afc42ed1dd506e","0e000fd63bd08abc96dbd4746c371b8a0368f351629590ee7ba12c9787cdc8e6","be2b61a9ac460b93bfcb3a44cef25609b5fe9a6727f139b5bf424ad177ac6805","687ee3310c7a1999a79d9d0a46873c239a526f076a04e2acd7b377da10918112","7402f4db71ba546b9576c5b4ca73c635c47a91eb16349f2f833f894aa906038f","fc56be7a344782b9933fd96772e63f1498f57131ee9727a6783d5fef82a90caa","10bcfe336e2f0340a2780ce32b4ad76c14fccf9ec44bd83e482905aeb1bda017","3ad4660add51c3c3adf49524d61cc1e3ed57e16274c62c6cfb047b64aab973aa","22f25ec27fa1c1ca03010aa71b8077c742ab5bf6a08a44663a287a296be34481","74ac2c0b3fa70bb0cf47f80fabc73f6b868ba177ced233e294068fc099cf5a06","12c453fe9c994ee8dda079a9af00b41fa48475dc1f8778b34c3680351bdf2ae1",{"version":"10f7303c5c9d5e7f84506dc7d59654d89981b7e3f2e0b6cfd9dadbcbfb551b0c","signature":"2c95d961abc1ba5b24193a89a2334a168757785cde54520df6eb4b96518d947f"},{"version":"14549ce65c076e5176c40d65321426734b105af4c4b3f0a304c2554283f389d0","signature":"eebbb761731a28544a4fd8bfb1d794b67e3c3d2a71525387a786803e817f1fb3"},{"version":"4759f86e98da42013f841ed76abac1289ed1e90fdd3b3c702f5dc409af1846de","signature":"819ca13f6b26b86a13b12f1c67ebd99083435cf3a0bf25784b6d95e04599da08"},{"version":"fa54046738b0193701787b6e11aeb47023337a694682b0609fd29cb55ca33cf6","signature":"3ce9e77ded9780538bb3dfec5032d0d36c03248620af638d4344b7bc9ac853c5"},"1616b4d2596ae32500e2087bd0d80b3a3d9098c808854ec4e4932ae0dcb59469","76b9a2fc8918f9b852911d4c311941581bca1448c6a29b831cfa1f54378dbeb0","f6333512273b449f40a9c1a7809fc9a6abc518c03ab8f2738e8ff8f9ddc41acd","590cea8037720a4592bcb897991660fd9b6ead03e04a6300e23049b1c5e22092","f234afe14bc84b3711e7b4e7efd0e4b73151a0538b62b69b176b01a08141c7d9","cecddf5788045ec4c9c13f16bbccdbcc8b2bdc5a853db61ac4a5fe0d47b84c98","3f5728d498807ba381d003f939754c461fc5b52513b76cc7f8543b979bdac116","5a728b230cad4b68e3c9405c007d656adfb63c7f0f1fbaedecaada1d7bba5fed",{"version":"8ead3a86cb1380ca1fbd9bdb0c9e512ac58f9ed94ed55ca7e9c16a2b4ca6d53c","signature":"6cfe03863384187d6d7989a1888da7f36e434d96cd259540c62cd54004d5c131"},"24907e8a6d9cac42f7f5799deb358202f4a6f9b76f719a5dad3e757443fe71a7","ae0d70b4f8a3a43cb0a5a89859aca3611f2789a3bca6a387f9deab912b7605b0","966b0f7789547bb149ad553f5a8c0d7b4406eceac50991aaad8a12643f3aec71",{"version":"a127eb1948daa48680a5a067ad176d9512b15310338124626279a80cb3e92369","signature":"fe0d466be11feff0318d0e42b1f3e28df18bd0d2c851482ac6bba6cc251ed9d3"},"14d234c1d72fade656abb6d9c77f36fd6a74b2ddcfd163530f754719f2de1724","fa70bdc67035c981fcb92927c0964016a5d731937b51767e12b596dc53c2471d","722d4727af4198e7ce7d3fbebad7aac5df5453c778e924ddcc930f7b79856ade","c99cd6cf0ea5d98aa5b759670f0ca78c74683b391895fb817dd70659b6e057a3","4e17022f8d8921443b432c62323988f0233e93c1182d2ca1f1adb9eb5d0d49a5","da44c89678d93683d56a71e4ea63f968ee1402d81df44d5947fa1be2f99f0341","11c2fcf981188bed6f189f39f4d88e3eced6f6e41df7865e7ad4627f0aa5a281","984f8606a0e69f913d9abc07808958885fec9cb3018030a42c887c38b11be54e","2af6c1ad3c4855fc59900500adb6a5f1c23c42cfe416baeb06ad0c8886960a93","589c299c27e2ad99c2e96c9a90e6ad49051cf99fc88f0c42a13465177379186f","dfe39c95b8bc915ad0243afc79541d408267496502ae69ad9649df589166daeb","6c07f91d5a73d89be10bc8102f469d7a7236215b9e2870a4e9312abc61c31d17","7de7e156bed4a97d5cf802347a97e358f97399e49f187aa9bdfbfa10b1699695","ef43e1b7760d00520608f5f64b04c9b0bef9b4c91a03f12bc85c0e27a9b7b358","f4cdd104de29928bfcd40b865c7d08eed9157a537fbb8b5e6d0921f02b63cc04","d3d4e3df19a693505fdc6440647862718530e2c79ea9ecc9cd6ce5936efe6ef7","f3095dfa3cf7be7b80dee24765c5213d51ed3f954a925839963da606ee6df74d","1616b4d2596ae32500e2087bd0d80b3a3d9098c808854ec4e4932ae0dcb59469","f234afe14bc84b3711e7b4e7efd0e4b73151a0538b62b69b176b01a08141c7d9","da44c89678d93683d56a71e4ea63f968ee1402d81df44d5947fa1be2f99f0341","a9091e2287a0f089251b37293f39673c46936cd87060440ee5dbe6aab78c7744",{"version":"a6e48044d01e14fc148e5d5a4acec77b4c8911fce1fe11fb3685ab10537de602","signature":"b6ddc3cb59edf537dce8aa91a2b51713dd00e00121c8328d812d0cdda11a54d0"},{"version":"0847c5fdb47472194bc07072ada4a23a09832bc8ef5386ab6b086615bf80d0d6","signature":"7b0931419dbaa210a6c0a6044edb714ff0f4e70c14fa2bf93c2a0b9aba06a53f"},"010d7414f0f9d740d26633d45654516e3564e2592b95c4bfa16c0f95f9fe3158","db7a6e485a0b24096dce703b9240b24d84e654f0994984571f3c4ba9b34a3a09","cbc4abab352a457ce794e0621f7d6bf4561debfd212388e8ab5e6a3337eed4e1","a6e6905afb0872e8dbae4b55077dbafb5ee689b15144affbd09b5414e4c13db5","064c6785bddf9e6df36e0cc070c0ce8a0837c15deb93bea082ea36d2abb3d24a","2f15e8e7cfbf830cf96176e23bd802684eb6d96be9cd480d0db008f8eb9ea95f","f02b539bb02f3a54bed0b4ee9b4d08a0055d70d42a0f13c74f83422da654f152","b275fbb95cd37e0e3dcb442681895cb07ca4786bff0d50f562bbb98ae7b62b58","82e7e7faeedffe629d0c088e305814b19011aa84ad1b1b5f6ffc368354dc0a9f","318198880beabb199a9486012ae010ca94801f272c68dd9903139d08c498b1b6","5baf6e1065b60c2ce1c671c6977e2c21f6370a7254754c25b6cb0b42f13cf7f6","abb083409c5f771d2c3d3d5d45fcc494f49e6a13b7c8e32aab63103f4bb8987e","642ff7d2fd4ae85285aec72664b12e0987482104e1218ee16162568fb9a67101","f61a507e024a6f8cbbf133a67d0627aa2c4e118117d439dbead0f84ffceedc45",{"version":"a9e2dbc0cc3875410c006d7fe28bfc1dd9285f53ecbeaab0473fc042cf98295f","signature":"019223c2a31d5a143a0b2b5c5a30dfffa192ca3222e5f2a4d0700a03219e05d0"},"646ba662d9b61b796904dec30fd5fe95b99e9364f16e06a69a49d3053d4e1816",{"version":"b9333522eb150b1a26d1efa4ae79cedefcad4480d5cfc45fdc29ee55451fc603","signature":"8d1fb0ebb776e56fe54a574e67956de3b26758391705a3342bb77fdb00cc1094"},"6f411c82cf7ddb14e75afa3a36f2e515d9ca6cdab60267998ed2f1e63b14123b","bafb2ab1ec591214d46ac9a9c95c7463ddc5f6580c7dc5f34f665c64b59c8630","17e62f03dba75655d5f104b8d48f35c06dbeeb2107dcf42ad7163d400be8b070","8fa3c094a51d23c50cb0def51d1f998941111ac3e43378635f7f11cff0f1da9b","a87f37030562b075f460027fa5af16194451ef1ffe29e0f13c328c84d05bf9e8","ee51dd9753df3e7efcd78d5b0f97252cf1d5d1e794e03970b2bcac7497fa09eb","72a22437a50c66c93e984469dd2a0320acd986b3400d4b32e995221e4f751474","d0d6e792d145cf8b77b9ebcc25b2d2f9e7e4c3d172f3083dbd0495d0fa49a0c7","9ffaf4f9bc289291981a261f341e01fc1e3f66e2687a30ae1b4a7a7769047935","172e340cf037902dd85db632cd829ecb61339d91c64d9a473099ab2d981a6812","369e600fdd358d6e0e0dd611818bbafb24d341f197185f5775b8b91783076b0c","42faf3420a114e9b7a47a8c4d9bfaf8d9c3113d9bf394dd88a1cd0df787df002","0af9a710edac568fecbb213a6a46a48b078ed7605d803faba6325efcf79219eb",{"version":"ab0790e3d9cb3d0068e7df4fefe43ecfb224655ad4ad4d72dabf89b0fb3796ec","signature":"2bfe3bc22c541685f2704de5a6fd5d72dec87a7db5353ad1bb3443b8169044d2"},"e4dc0c1cb9e413990fb37ed3ceb2c957d4071e527372dc6e6926a4ee3c98e7e9",{"version":"826015fb6429d43f4048f2ff73136c102d8d2a85f660e8586cab2c1d1ff81f62","signature":"eb9adb17019110901ed9060df1a3bf71cf4c2bb979b855afadc40c0a12d41348"},"aa8ff9c08b801b74bae8cfd502abf7627313fc12ed002a1ff0b54ef9e36de6e6",{"version":"f2b889469e404111545fe5ed8193b27b2dd20e5333ce4077b1b440c0eb4f1501","signature":"bd3596ec7ca0f1c2e5bd457cd88f6f6404503635f455bce11de94ea0305e3e3a"},"a90ed5d965bf786da5d884691ef334e810c41b0131edd81cf95244a049c49afb",{"version":"a39657973a7d264bc95fdbc24bee64d56f5a07bd093e70f74850551d71930694","signature":"a1cac058ecfd7af2beeeca2dc0d80181f81f0136235262fe40d42c6a44c3dbdf"},"513b53524e6080141f59e27f3f72130412a62446d7aa63efdbf788c0981fc46f","1a8cd63c7657d0e1c936f844cc56f32f660f0fe672e310f04e3e13b2e7704e10","807535f4e95ebccc1eae3d675289b1be5c23e6aaa6fd624f2be485e3e1e6f23d","dbbd4cf7b048fe64f88ee23d0f68a6964ef0d4956913e8ccd58ec1fe57f9d70e","aa11af1f1a0f4a8778ffe02db25d6cd0e571941cf969b29a6ade816d1c4cc1e8","589bc40fe8d104675083737366037c431e047b583b3144399f80693d9075d8b9","defd0db55eef839c8938ac6db43208fa2525e2986c636022b7484dbd2482bee2","c29311bcb8462a83665d95331ac945ddec55b50052fcc21895b817badf1a8aa0"],"options":{"esModuleInterop":true,"jsx":1,"module":99,"skipLibCheck":true,"strict":false},"fileIdsList":[[112],[112,310],[112,311],[62,112,212,214,250],[62,112,212,214,253],[62,112,212],[62,112,212,214],[62,112,212,214,273],[62,112],[62,112,214,263,264,265,266],[62,112,212,213,214,235,239],[62,112,263],[62,112,212,214,241],[62,112,212,213,214,239,271],[62,112,212,213,214,235,238,239,240],[62,112,212,213,214,235,239,271,272],[62,112,212,214,272,273],[62,112,212,213,214,283],[62,112,212,213,214,235,238,239],[62,112,212,214,236,237],[62,112,212,214,240],[62,112,212,213,214,235,239,271],[62,112,212,214,272],[62,112,212,213,214],[69,112],[72,112],[73,78,112],[74,84,85,92,101,111,112],[74,75,84,92,112],[76,112],[77,78,85,93,112],[78,101,108,112],[79,81,84,92,112],[80,112],[81,82,112],[83,84,112],[84,112],[84,85,86,101,111,112],[84,85,86,101,112],[112,116],[87,92,101,111,112],[84,85,87,88,92,101,108,111,112],[87,89,101,108,111,112],[69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118],[84,90,112],[91,111,112],[81,84,92,101,112],[93,112],[94,112],[72,95,112],[96,110,112,116],[97,112],[98,112],[84,99,112],[99,100,112,114],[84,101,102,103,112],[101,103,112],[101,102,112],[104,112],[105,112],[84,106,107,112],[106,107,112],[78,92,101,108,112],[109,112],[92,110,112],[73,87,98,111,112],[78,112],[101,112,113],[112,114],[112,115],[73,78,84,86,95,101,111,112,114,116],[101,112,117],[112,121],[58,59,60,61,112],[59,60,61,112,120],[112,216],[62,112,267],[62,112,121],[62,112,245],[67,112],[112,184],[112,186],[112,126,129,173],[112,131],[112,124,140],[112,124],[112,124,140,141],[62,112,127],[62,111,112,119],[62,112,140,179],[62,112,140],[112,177,181],[62,112,178,183],[112,125],[62,112,174,183],[62,112,183],[87,112,119,130,183],[87,112,119,129,131],[87,101,112,119,130,131,138,173],[87,98,111,112,119,125,126,127,129,130,131,136,138,139,140,143,153,154,156,158,159,160,161,163,165,166,173],[87,101,112,119],[112,124,126,127,128,173,183],[112,129],[98,111,112,119,126,129,130,131,136,139,152,157,159,162,167,169,170],[87,111,112,119,129,138,165],[112,153,165,183],[112,122,173,183],[87,98,111,112,119,126,129,130,132,134,136,138,139,142,143,152,153,154,156,157,158,161,162,165,166,167,168,183],[87,112,119,138,169,171],[62,87,98,112,119,125,127,131,138,143,158,159,160,173],[87,98,111,112,119,130,137],[112,164],[112,119,143],[98,112,119,125,126,130,136,138],[87,112,119,143,155],[87,112,119,130,156],[112,145,146,147],[112,145],[112,149],[112,129,144,148,152],[112,129,144,148],[112,129,137,149,150,151],[62,112,121,122,158,160,173,183],[62,98,111,112,119,125,176,178,180,183],[112,130,136,140],[98,112,119],[112,135],[62,87,98,112,119,125,173,174,175,181,182],[57,62,63,64,65,112,173],[112,188],[112,190],[112,192],[112,194],[112,196],[66,68,112,173,185,187,189,191,193,195,197,199,200,202,205,206],[112,198],[112,178],[112,201],[72,112,149,150,151,152,203,204],[112,119],[62,66,87,98,112,119,121,123,125,131,172,183],[112,220,221,222,223,224,225,226,227,228],[112,220,223],[112,222,223],[112,223],[112,220],[112,218],[112,248],[112,121,199,210,211,230,233,234,243],[112,199,211,233,234,244,247],[112,121,233,234,243,246],[112,121,218,230,251],[112,121,230,254],[112,256],[112,121,230,258],[112,121,217,230],[112,121,218,230,260],[112,250],[112,121,218,230,253,268,269],[112,121,218,230,274],[112,121,218,230,253],[112,121,218,230,242],[112,121,230,276],[112,121,230],[112,121,230,279],[112,121,218,230,281],[112,121,217,218,230,284],[112,121,230,286],[112,121,230,288],[112,121,218,230,290],[112,121,230,292],[112,121,218,230,294],[112,121,230,296],[112,121,230,298],[112,121,230,300],[112,121,230,302],[112,121,215,217,218,230],[112,231,232],[112,121,217,230,306],[112,121,230,308],[112,210],[112,121,231],[112,219,229],[112,207,208],[112,185,246,312],[112,189],[112,195,199,211,234,249],[218],[121,216,217],[62,121,253],[62,121,242],[62,121,216,284],[62,121,286],[62,121,300],[62,121,302],[62,121,215,216,217],[62,121,216,217,306],[121,231]],"referencedMap":[[175,1],[311,2],[310,1],[312,3],[251,4],[254,5],[236,6],[256,6],[258,7],[260,7],[250,7],[274,8],[214,9],[267,10],[253,11],[264,12],[213,6],[242,13],[265,12],[235,6],[276,14],[279,6],[241,15],[273,16],[281,17],[284,18],[286,19],[238,20],[271,20],[266,12],[239,6],[263,9],[212,9],[288,7],[290,21],[240,7],[272,7],[292,7],[294,22],[296,6],[298,7],[300,7],[302,23],[215,24],[306,6],[308,14],[283,6],[237,1],[69,25],[70,25],[72,26],[73,27],[74,28],[75,29],[76,30],[77,31],[78,32],[79,33],[80,34],[81,35],[82,35],[83,36],[84,37],[85,38],[86,39],[71,40],[118,1],[87,41],[88,42],[89,43],[119,44],[90,45],[91,46],[92,47],[93,48],[94,49],[95,50],[96,51],[97,52],[98,53],[99,54],[100,55],[101,56],[103,57],[102,58],[104,59],[105,60],[106,61],[107,62],[108,63],[109,64],[110,65],[111,66],[112,67],[113,68],[114,69],[115,70],[116,71],[117,72],[60,1],[123,73],[58,1],[62,74],[120,1],[121,75],[61,1],[217,76],[216,1],[219,1],[268,77],[59,1],[218,78],[246,79],[245,73],[68,80],[185,81],[187,82],[140,83],[153,84],[141,85],[160,86],[142,87],[154,86],[128,86],[196,88],[198,89],[180,90],[179,91],[178,92],[201,9],[177,93],[204,1],[124,1],[126,94],[184,93],[188,95],[192,96],[131,97],[130,98],[157,99],[167,100],[137,101],[129,102],[125,103],[171,104],[170,103],[158,1],[122,1],[168,105],[132,1],[166,106],[159,107],[169,108],[172,109],[133,1],[134,1],[143,101],[161,110],[138,111],[165,112],[164,113],[139,114],[156,115],[155,116],[144,103],[148,117],[146,118],[147,118],[145,1],[150,119],[149,120],[151,121],[203,1],[152,122],[67,1],[182,1],[190,9],[194,9],[174,123],[127,1],[176,1],[181,124],[163,125],[162,126],[136,127],[135,1],[186,1],[183,128],[57,1],[66,129],[63,9],[64,1],[65,1],[189,130],[191,131],[193,132],[195,133],[208,134],[197,134],[207,135],[199,136],[200,137],[202,138],[205,139],[206,140],[173,141],[229,142],[226,143],[224,144],[225,143],[228,145],[227,145],[220,1],[221,146],[223,1],[222,1],[11,1],[12,1],[14,1],[13,1],[2,1],[15,1],[16,1],[17,1],[18,1],[19,1],[20,1],[21,1],[22,1],[3,1],[4,1],[26,1],[23,1],[24,1],[25,1],[27,1],[28,1],[29,1],[5,1],[30,1],[31,1],[32,1],[33,1],[6,1],[37,1],[34,1],[35,1],[36,1],[38,1],[7,1],[39,1],[44,1],[45,1],[40,1],[41,1],[42,1],[43,1],[8,1],[49,1],[46,1],[47,1],[48,1],[50,1],[9,1],[51,1],[52,1],[53,1],[54,1],[55,1],[1,1],[10,1],[56,1],[233,147],[249,148],[244,149],[248,150],[247,151],[252,152],[255,153],[257,154],[259,155],[234,156],[261,157],[262,158],[270,159],[275,160],[269,161],[243,162],[277,163],[278,164],[280,165],[282,166],[285,167],[287,168],[289,169],[291,170],[293,171],[295,172],[297,173],[299,174],[301,175],[303,176],[304,164],[231,177],[305,178],[307,179],[309,180],[211,181],[232,182],[230,183],[209,184],[313,185],[314,186],[315,187],[210,1]],"exportedModulesMap":[[175,1],[311,2],[310,1],[312,3],[251,4],[254,5],[236,6],[256,6],[258,7],[260,7],[250,7],[274,8],[214,9],[267,10],[253,11],[264,12],[213,6],[242,13],[265,12],[235,6],[276,14],[279,6],[241,15],[273,16],[281,17],[284,18],[286,19],[238,20],[271,20],[266,12],[239,6],[263,9],[212,9],[288,7],[290,21],[240,7],[272,7],[292,7],[294,22],[296,6],[298,7],[300,7],[302,23],[215,24],[306,6],[308,14],[283,6],[237,1],[69,25],[70,25],[72,26],[73,27],[74,28],[75,29],[76,30],[77,31],[78,32],[79,33],[80,34],[81,35],[82,35],[83,36],[84,37],[85,38],[86,39],[71,40],[118,1],[87,41],[88,42],[89,43],[119,44],[90,45],[91,46],[92,47],[93,48],[94,49],[95,50],[96,51],[97,52],[98,53],[99,54],[100,55],[101,56],[103,57],[102,58],[104,59],[105,60],[106,61],[107,62],[108,63],[109,64],[110,65],[111,66],[112,67],[113,68],[114,69],[115,70],[116,71],[117,72],[60,1],[123,73],[58,1],[62,74],[120,1],[121,75],[61,1],[217,76],[216,1],[219,1],[268,77],[59,1],[218,78],[246,79],[245,73],[68,80],[185,81],[187,82],[140,83],[153,84],[141,85],[160,86],[142,87],[154,86],[128,86],[196,88],[198,89],[180,90],[179,91],[178,92],[201,9],[177,93],[204,1],[124,1],[126,94],[184,93],[188,95],[192,96],[131,97],[130,98],[157,99],[167,100],[137,101],[129,102],[125,103],[171,104],[170,103],[158,1],[122,1],[168,105],[132,1],[166,106],[159,107],[169,108],[172,109],[133,1],[134,1],[143,101],[161,110],[138,111],[165,112],[164,113],[139,114],[156,115],[155,116],[144,103],[148,117],[146,118],[147,118],[145,1],[150,119],[149,120],[151,121],[203,1],[152,122],[67,1],[182,1],[190,9],[194,9],[174,123],[127,1],[176,1],[181,124],[163,125],[162,126],[136,127],[135,1],[186,1],[183,128],[57,1],[66,129],[63,9],[64,1],[65,1],[189,130],[191,131],[193,132],[195,133],[208,134],[197,134],[207,135],[199,136],[200,137],[202,138],[205,139],[206,140],[173,141],[229,142],[226,143],[224,144],[225,143],[228,145],[227,145],[220,1],[221,146],[223,1],[222,1],[11,1],[12,1],[14,1],[13,1],[2,1],[15,1],[16,1],[17,1],[18,1],[19,1],[20,1],[21,1],[22,1],[3,1],[4,1],[26,1],[23,1],[24,1],[25,1],[27,1],[28,1],[29,1],[5,1],[30,1],[31,1],[32,1],[33,1],[6,1],[37,1],[34,1],[35,1],[36,1],[38,1],[7,1],[39,1],[44,1],[45,1],[40,1],[41,1],[42,1],[43,1],[8,1],[49,1],[46,1],[47,1],[48,1],[50,1],[9,1],[51,1],[52,1],[53,1],[54,1],[55,1],[1,1],[10,1],[56,1],[233,188],[249,148],[244,149],[248,150],[252,152],[255,153],[257,154],[259,155],[234,189],[261,157],[262,158],[270,190],[275,160],[269,190],[243,191],[277,163],[278,164],[280,165],[282,166],[285,192],[287,193],[289,169],[291,170],[293,171],[295,172],[297,173],[299,174],[301,194],[303,195],[304,164],[231,196],[307,197],[309,180],[211,181],[232,198],[230,183],[209,184],[313,185],[314,186],[315,187],[210,1]],"semanticDiagnosticsPerFile":[175,311,310,312,251,254,236,256,258,260,250,274,214,267,253,264,213,242,265,235,276,279,241,273,281,284,286,238,271,266,239,263,212,288,290,240,272,292,294,296,298,300,302,215,306,308,283,237,69,70,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,71,118,87,88,89,119,90,91,92,93,94,95,96,97,98,99,100,101,103,102,104,105,106,107,108,109,110,111,112,113,114,115,116,117,60,123,58,62,120,121,61,217,216,219,268,59,218,246,245,68,185,187,140,153,141,160,142,154,128,196,198,180,179,178,201,177,204,124,126,184,188,192,131,130,157,167,137,129,125,171,170,158,122,168,132,166,159,169,172,133,134,143,161,138,165,164,139,156,155,144,148,146,147,145,150,149,151,203,152,67,182,190,194,174,127,176,181,163,162,136,135,186,183,57,66,63,64,65,189,191,193,195,208,197,207,199,200,202,205,206,173,229,226,224,225,228,227,220,221,223,222,11,12,14,13,2,15,16,17,18,19,20,21,22,3,4,26,23,24,25,27,28,29,5,30,31,32,33,6,37,34,35,36,38,7,39,44,45,40,41,42,43,8,49,46,47,48,50,9,51,52,53,54,55,1,10,56,233,249,244,248,247,252,255,257,259,234,261,262,270,275,269,243,277,278,280,282,285,287,289,291,293,295,297,299,301,303,304,231,305,307,309,211,232,230,209,313,314,315,210],"affectedFilesPendingEmit":[[175,1],[311,1],[310,1],[312,1],[251,1],[254,1],[236,1],[256,1],[258,1],[260,1],[250,1],[274,1],[214,1],[267,1],[253,1],[264,1],[213,1],[242,1],[265,1],[235,1],[276,1],[279,1],[241,1],[273,1],[281,1],[284,1],[286,1],[238,1],[271,1],[266,1],[239,1],[263,1],[212,1],[288,1],[290,1],[240,1],[272,1],[292,1],[294,1],[296,1],[298,1],[300,1],[302,1],[215,1],[306,1],[308,1],[283,1],[237,1],[69,1],[70,1],[72,1],[73,1],[74,1],[75,1],[76,1],[77,1],[78,1],[79,1],[80,1],[81,1],[82,1],[83,1],[84,1],[85,1],[86,1],[71,1],[118,1],[87,1],[88,1],[89,1],[119,1],[90,1],[91,1],[92,1],[93,1],[94,1],[95,1],[96,1],[97,1],[98,1],[99,1],[100,1],[101,1],[103,1],[102,1],[104,1],[105,1],[106,1],[107,1],[108,1],[109,1],[110,1],[111,1],[112,1],[113,1],[114,1],[115,1],[116,1],[117,1],[60,1],[123,1],[58,1],[62,1],[120,1],[121,1],[61,1],[217,1],[216,1],[219,1],[268,1],[59,1],[218,1],[246,1],[245,1],[68,1],[185,1],[187,1],[140,1],[153,1],[141,1],[160,1],[142,1],[154,1],[128,1],[196,1],[198,1],[180,1],[179,1],[178,1],[201,1],[177,1],[204,1],[124,1],[126,1],[184,1],[188,1],[192,1],[131,1],[130,1],[157,1],[167,1],[137,1],[129,1],[125,1],[171,1],[170,1],[158,1],[122,1],[168,1],[132,1],[166,1],[159,1],[169,1],[172,1],[133,1],[134,1],[143,1],[161,1],[138,1],[165,1],[164,1],[139,1],[156,1],[155,1],[144,1],[148,1],[146,1],[147,1],[145,1],[150,1],[149,1],[151,1],[203,1],[152,1],[67,1],[182,1],[190,1],[194,1],[174,1],[127,1],[176,1],[181,1],[163,1],[162,1],[136,1],[135,1],[186,1],[183,1],[57,1],[66,1],[63,1],[64,1],[65,1],[189,1],[191,1],[193,1],[195,1],[208,1],[197,1],[207,1],[199,1],[200,1],[202,1],[205,1],[206,1],[173,1],[229,1],[226,1],[224,1],[225,1],[228,1],[227,1],[220,1],[221,1],[223,1],[222,1],[2,1],[3,1],[4,1],[5,1],[6,1],[7,1],[8,1],[9,1],[10,1],[233,1],[249,1],[244,1],[248,1],[247,1],[252,1],[255,1],[257,1],[259,1],[234,1],[261,1],[262,1],[270,1],[275,1],[269,1],[243,1],[277,1],[278,1],[280,1],[282,1],[285,1],[287,1],[289,1],[291,1],[293,1],[295,1],[297,1],[299,1],[301,1],[303,1],[304,1],[231,1],[305,1],[307,1],[309,1],[211,1],[232,1],[230,1],[209,1],[313,1],[314,1],[315,1],[210,1]]},"version":"4.9.4"}
--------------------------------------------------------------------------------
/types/nav.ts:
--------------------------------------------------------------------------------
1 | export interface NavItem {
2 | title: string;
3 | href?: string;
4 | disabled?: boolean;
5 | external?: boolean;
6 | }
7 |
--------------------------------------------------------------------------------