diff --git a/.github/workflows/deploy.yml b/.github/workflows/api-deploy.yml similarity index 100% rename from .github/workflows/deploy.yml rename to .github/workflows/api-deploy.yml diff --git a/apps/web/app/globals.css b/apps/docs/app/globals.css similarity index 100% rename from apps/web/app/globals.css rename to apps/docs/app/globals.css diff --git a/apps/web/app/layout.tsx b/apps/docs/app/layout.tsx similarity index 78% rename from apps/web/app/layout.tsx rename to apps/docs/app/layout.tsx index 146de38..5d38aa4 100644 --- a/apps/web/app/layout.tsx +++ b/apps/docs/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from 'next'; import { Geist, Geist_Mono } from 'next/font/google'; import './globals.css'; +import { Providers } from '@/components/providers'; import { cn } from '@/lib/utils'; const geistSans = Geist({ @@ -14,8 +15,8 @@ const geistMono = Geist_Mono({ }); export const metadata: Metadata = { - title: 'Create Next App', - description: 'Generated by create next app', + title: 'CMD Api | EspocaBot', + description: 'A set of APIs for streamers', }; export default function RootLayout({ @@ -28,7 +29,7 @@ export default function RootLayout({ - {children} + {children} ); diff --git a/apps/web/app/page.tsx b/apps/docs/app/page.tsx similarity index 100% rename from apps/web/app/page.tsx rename to apps/docs/app/page.tsx diff --git a/apps/web/components.json b/apps/docs/components.json similarity index 100% rename from apps/web/components.json rename to apps/docs/components.json diff --git a/apps/docs/components/providers.tsx b/apps/docs/components/providers.tsx new file mode 100644 index 0000000..bfc3f55 --- /dev/null +++ b/apps/docs/components/providers.tsx @@ -0,0 +1,14 @@ +'use client'; + +import type { ReactNode } from 'react'; +import { Toaster } from './ui/sonner'; +import { TooltipProvider } from './ui/tooltip'; + +export function Providers({ children }: { children: ReactNode }) { + return ( + + {children} + + + ); +} diff --git a/apps/docs/components/ui/badge.tsx b/apps/docs/components/ui/badge.tsx new file mode 100644 index 0000000..894f310 --- /dev/null +++ b/apps/docs/components/ui/badge.tsx @@ -0,0 +1,45 @@ +import { cva, type VariantProps } from 'class-variance-authority'; +import { Slot } from 'radix-ui'; +import type { ComponentProps } from 'react'; +import { cn } from '@/lib/utils'; + +export const badgeVariants = cva( + 'inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden whitespace-nowrap rounded-full border border-transparent px-2 py-0.5 font-medium text-xs transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3', + { + variants: { + variant: { + default: 'bg-primary text-primary-foreground [a&]:hover:bg-primary/90', + secondary: + 'bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90', + destructive: + 'bg-destructive text-white focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90', + outline: + 'border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground', + ghost: '[a&]:hover:bg-accent [a&]:hover:text-accent-foreground', + link: 'text-primary underline-offset-4 [a&]:hover:underline', + }, + }, + defaultVariants: { + variant: 'default', + }, + }, +); + +export function Badge({ + className, + variant = 'default', + asChild = false, + ...props +}: ComponentProps<'span'> & + VariantProps & { asChild?: boolean }) { + const Comp = asChild ? Slot.Root : 'span'; + + return ( + + ); +} diff --git a/apps/docs/components/ui/button.tsx b/apps/docs/components/ui/button.tsx new file mode 100644 index 0000000..cbbe884 --- /dev/null +++ b/apps/docs/components/ui/button.tsx @@ -0,0 +1,61 @@ +import { cva, type VariantProps } from 'class-variance-authority'; +import { Slot } from 'radix-ui'; +import type { ComponentProps } from 'react'; +import { cn } from '@/lib/utils'; + +export const buttonVariants = cva( + "inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-sm outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0", + { + variants: { + variant: { + default: 'bg-primary text-primary-foreground hover:bg-primary/90', + destructive: + 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40', + outline: + 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50', + secondary: + 'bg-secondary text-secondary-foreground hover:bg-secondary/80', + ghost: + 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50', + link: 'text-primary underline-offset-4 hover:underline', + }, + size: { + default: 'h-9 px-4 py-2 has-[>svg]:px-3', + xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3", + sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5', + lg: 'h-10 rounded-md px-6 has-[>svg]:px-4', + icon: 'size-9', + 'icon-xs': "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3", + 'icon-sm': 'size-8', + 'icon-lg': 'size-10', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + }, +); + +export function Button({ + className, + variant = 'default', + size = 'default', + asChild = false, + ...props +}: ComponentProps<'button'> & + VariantProps & { + asChild?: boolean; + }) { + const Comp = asChild ? Slot.Root : 'button'; + + return ( + + ); +} diff --git a/apps/docs/components/ui/collapsible.tsx b/apps/docs/components/ui/collapsible.tsx new file mode 100644 index 0000000..834ee6d --- /dev/null +++ b/apps/docs/components/ui/collapsible.tsx @@ -0,0 +1,32 @@ +'use client'; + +import { Collapsible as CollapsiblePrimitive } from 'radix-ui'; +import type { ComponentProps } from 'react'; + +export function Collapsible({ + ...props +}: ComponentProps) { + return ; +} + +export function CollapsibleTrigger({ + ...props +}: ComponentProps) { + return ( + + ); +} + +export function CollapsibleContent({ + ...props +}: ComponentProps) { + return ( + + ); +} diff --git a/apps/docs/components/ui/field.tsx b/apps/docs/components/ui/field.tsx new file mode 100644 index 0000000..44b2cdd --- /dev/null +++ b/apps/docs/components/ui/field.tsx @@ -0,0 +1,234 @@ +'use client'; + +import { cva, type VariantProps } from 'class-variance-authority'; +import { type ComponentProps, useMemo } from 'react'; +import { Label } from '@/components/ui/label'; +import { Separator } from '@/components/ui/separator'; +import { cn } from '@/lib/utils'; + +export function FieldSet({ className, ...props }: ComponentProps<'fieldset'>) { + return ( +
[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3', + className, + )} + {...props} + /> + ); +} + +export function FieldLegend({ + className, + variant = 'legend', + ...props +}: ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) { + return ( + + ); +} + +export function FieldGroup({ className, ...props }: ComponentProps<'div'>) { + return ( +
[data-slot=field-group]]:gap-4', + className, + )} + {...props} + /> + ); +} + +const fieldVariants = cva( + 'group/field flex w-full gap-3 data-[invalid=true]:text-destructive', + { + variants: { + orientation: { + vertical: ['flex-col [&>*]:w-full [&>.sr-only]:w-auto'], + horizontal: [ + 'flex-row items-center', + '[&>[data-slot=field-label]]:flex-auto', + 'has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px', + ], + responsive: [ + '@md/field-group:flex-row flex-col @md/field-group:items-center @md/field-group:[&>*]:w-auto [&>*]:w-full [&>.sr-only]:w-auto', + '@md/field-group:[&>[data-slot=field-label]]:flex-auto', + '@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px', + ], + }, + }, + defaultVariants: { + orientation: 'vertical', + }, + }, +); + +export function Field({ + className, + orientation = 'vertical', + ...props +}: ComponentProps<'div'> & VariantProps) { + return ( +
+ ); +} + +export function FieldContent({ className, ...props }: ComponentProps<'div'>) { + return ( +
+ ); +} + +export function FieldLabel({ + className, + ...props +}: ComponentProps) { + return ( +