├── .cursor └── rules │ ├── api-patterns.mdc │ ├── coding-standards.mdc │ ├── component-patterns.mdc │ ├── deployment-and-infrastructure.mdc │ ├── development-guidelines.mdc │ └── project-overview.mdc ├── .editorconfig ├── .env.example ├── .github └── FUNDING.yml ├── .gitignore ├── .node-version ├── .npmrc ├── .vscode ├── extensions.json └── settings.json ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── app ├── app.config.ts ├── app.vue ├── assets │ ├── css │ │ └── tailwind.css │ └── images │ │ ├── 404.svg │ │ ├── cloudflare.png │ │ ├── hero.svg │ │ └── nuxtjs.png ├── components │ ├── SwitchLanguage.vue │ ├── SwitchTheme.vue │ ├── dashboard │ │ ├── Breadcrumb.vue │ │ ├── DatePicker.vue │ │ ├── Filters.vue │ │ ├── Logout.vue │ │ ├── Nav.vue │ │ ├── TimePicker.vue │ │ ├── analysis │ │ │ ├── Counters.vue │ │ │ ├── Index.vue │ │ │ ├── Views.vue │ │ │ └── metrics │ │ │ │ ├── Group.vue │ │ │ │ ├── Index.vue │ │ │ │ ├── List.vue │ │ │ │ ├── Locations.vue │ │ │ │ ├── Metric.vue │ │ │ │ └── name │ │ │ │ ├── Icon.vue │ │ │ │ ├── Index.vue │ │ │ │ ├── Referer.vue │ │ │ │ └── Slug.vue │ │ ├── links │ │ │ ├── Delete.vue │ │ │ ├── Editor.vue │ │ │ ├── Index.vue │ │ │ ├── Link.vue │ │ │ ├── QRCode.vue │ │ │ ├── Search.vue │ │ │ └── Sort.vue │ │ └── realtime │ │ │ ├── Chart.vue │ │ │ ├── Globe.vue │ │ │ ├── Index.vue │ │ │ └── Logs.vue │ ├── home │ │ ├── Cta.vue │ │ ├── Features.vue │ │ ├── Hero.vue │ │ ├── Link.vue │ │ ├── Logos.vue │ │ └── Twitter.vue │ ├── layouts │ │ ├── Footer.vue │ │ └── Header.vue │ ├── login │ │ └── index.vue │ ├── spark-ui │ │ ├── AnimatedList.vue │ │ └── Notification.vue │ └── ui │ │ ├── accordion │ │ ├── Accordion.vue │ │ ├── AccordionContent.vue │ │ ├── AccordionItem.vue │ │ ├── AccordionTrigger.vue │ │ └── index.ts │ │ ├── alert-dialog │ │ ├── AlertDialog.vue │ │ ├── AlertDialogAction.vue │ │ ├── AlertDialogCancel.vue │ │ ├── AlertDialogContent.vue │ │ ├── AlertDialogDescription.vue │ │ ├── AlertDialogFooter.vue │ │ ├── AlertDialogHeader.vue │ │ ├── AlertDialogTitle.vue │ │ ├── AlertDialogTrigger.vue │ │ └── index.ts │ │ ├── alert │ │ ├── Alert.vue │ │ ├── AlertDescription.vue │ │ ├── AlertTitle.vue │ │ └── index.ts │ │ ├── aspect-ratio │ │ ├── AspectRatio.vue │ │ └── index.ts │ │ ├── auto-form │ │ ├── AutoForm.vue │ │ ├── AutoFormField.vue │ │ ├── AutoFormFieldArray.vue │ │ ├── AutoFormFieldBoolean.vue │ │ ├── AutoFormFieldDate.vue │ │ ├── AutoFormFieldEnum.vue │ │ ├── AutoFormFieldFile.vue │ │ ├── AutoFormFieldInput.vue │ │ ├── AutoFormFieldNumber.vue │ │ ├── AutoFormFieldObject.vue │ │ ├── AutoFormLabel.vue │ │ ├── constant.ts │ │ ├── dependencies.ts │ │ ├── index.ts │ │ ├── interface.ts │ │ └── utils.ts │ │ ├── avatar │ │ ├── Avatar.vue │ │ ├── AvatarFallback.vue │ │ ├── AvatarImage.vue │ │ └── index.ts │ │ ├── badge │ │ ├── Badge.vue │ │ └── index.ts │ │ ├── breadcrumb │ │ ├── Breadcrumb.vue │ │ ├── BreadcrumbEllipsis.vue │ │ ├── BreadcrumbItem.vue │ │ ├── BreadcrumbLink.vue │ │ ├── BreadcrumbList.vue │ │ ├── BreadcrumbPage.vue │ │ ├── BreadcrumbSeparator.vue │ │ └── index.ts │ │ ├── button │ │ ├── Button.vue │ │ └── index.ts │ │ ├── calendar │ │ ├── Calendar.vue │ │ ├── CalendarCell.vue │ │ ├── CalendarCellTrigger.vue │ │ ├── CalendarGrid.vue │ │ ├── CalendarGridBody.vue │ │ ├── CalendarGridHead.vue │ │ ├── CalendarGridRow.vue │ │ ├── CalendarHeadCell.vue │ │ ├── CalendarHeader.vue │ │ ├── CalendarHeading.vue │ │ ├── CalendarNextButton.vue │ │ ├── CalendarPrevButton.vue │ │ └── index.ts │ │ ├── card │ │ ├── Card.vue │ │ ├── CardContent.vue │ │ ├── CardDescription.vue │ │ ├── CardFooter.vue │ │ ├── CardHeader.vue │ │ ├── CardTitle.vue │ │ └── index.ts │ │ ├── chart-area │ │ ├── AreaChart.vue │ │ └── index.ts │ │ ├── chart-bar │ │ ├── BarChart.vue │ │ └── index.ts │ │ ├── chart │ │ ├── ChartCrosshair.vue │ │ ├── ChartLegend.vue │ │ ├── ChartSingleTooltip.vue │ │ ├── ChartTooltip.vue │ │ ├── index.ts │ │ └── interface.ts │ │ ├── checkbox │ │ ├── Checkbox.vue │ │ └── index.ts │ │ ├── command │ │ ├── Command.vue │ │ ├── CommandDialog.vue │ │ ├── CommandEmpty.vue │ │ ├── CommandGroup.vue │ │ ├── CommandInput.vue │ │ ├── CommandItem.vue │ │ ├── CommandList.vue │ │ ├── CommandSeparator.vue │ │ ├── CommandShortcut.vue │ │ └── index.ts │ │ ├── dialog │ │ ├── Dialog.vue │ │ ├── DialogClose.vue │ │ ├── DialogContent.vue │ │ ├── DialogDescription.vue │ │ ├── DialogFooter.vue │ │ ├── DialogHeader.vue │ │ ├── DialogScrollContent.vue │ │ ├── DialogTitle.vue │ │ ├── DialogTrigger.vue │ │ └── index.ts │ │ ├── drawer │ │ ├── Drawer.vue │ │ ├── DrawerContent.vue │ │ ├── DrawerDescription.vue │ │ ├── DrawerFooter.vue │ │ ├── DrawerHeader.vue │ │ ├── DrawerOverlay.vue │ │ ├── DrawerTitle.vue │ │ └── index.ts │ │ ├── dropdown-menu │ │ ├── DropdownMenu.vue │ │ ├── DropdownMenuCheckboxItem.vue │ │ ├── DropdownMenuContent.vue │ │ ├── DropdownMenuGroup.vue │ │ ├── DropdownMenuItem.vue │ │ ├── DropdownMenuLabel.vue │ │ ├── DropdownMenuRadioGroup.vue │ │ ├── DropdownMenuRadioItem.vue │ │ ├── DropdownMenuSeparator.vue │ │ ├── DropdownMenuShortcut.vue │ │ ├── DropdownMenuSub.vue │ │ ├── DropdownMenuSubContent.vue │ │ ├── DropdownMenuSubTrigger.vue │ │ ├── DropdownMenuTrigger.vue │ │ └── index.ts │ │ ├── form │ │ ├── FormControl.vue │ │ ├── FormDescription.vue │ │ ├── FormItem.vue │ │ ├── FormLabel.vue │ │ ├── FormMessage.vue │ │ ├── index.ts │ │ └── useFormField.ts │ │ ├── hover-card │ │ ├── HoverCard.vue │ │ ├── HoverCardContent.vue │ │ ├── HoverCardTrigger.vue │ │ └── index.ts │ │ ├── input │ │ ├── Input.vue │ │ └── index.ts │ │ ├── label │ │ ├── Label.vue │ │ └── index.ts │ │ ├── menubar │ │ ├── Menubar.vue │ │ ├── MenubarCheckboxItem.vue │ │ ├── MenubarContent.vue │ │ ├── MenubarGroup.vue │ │ ├── MenubarItem.vue │ │ ├── MenubarLabel.vue │ │ ├── MenubarMenu.vue │ │ ├── MenubarRadioGroup.vue │ │ ├── MenubarRadioItem.vue │ │ ├── MenubarSeparator.vue │ │ ├── MenubarShortcut.vue │ │ ├── MenubarSub.vue │ │ ├── MenubarSubContent.vue │ │ ├── MenubarSubTrigger.vue │ │ ├── MenubarTrigger.vue │ │ └── index.ts │ │ ├── navigation-menu │ │ ├── NavigationMenu.vue │ │ ├── NavigationMenuContent.vue │ │ ├── NavigationMenuIndicator.vue │ │ ├── NavigationMenuItem.vue │ │ ├── NavigationMenuLink.vue │ │ ├── NavigationMenuList.vue │ │ ├── NavigationMenuTrigger.vue │ │ ├── NavigationMenuViewport.vue │ │ └── index.ts │ │ ├── popover │ │ ├── Popover.vue │ │ ├── PopoverContent.vue │ │ ├── PopoverTrigger.vue │ │ └── index.ts │ │ ├── progress │ │ ├── Progress.vue │ │ └── index.ts │ │ ├── radio-group │ │ ├── RadioGroup.vue │ │ ├── RadioGroupItem.vue │ │ └── index.ts │ │ ├── range-calendar │ │ ├── RangeCalendar.vue │ │ ├── RangeCalendarCell.vue │ │ ├── RangeCalendarCellTrigger.vue │ │ ├── RangeCalendarGrid.vue │ │ ├── RangeCalendarGridBody.vue │ │ ├── RangeCalendarGridHead.vue │ │ ├── RangeCalendarGridRow.vue │ │ ├── RangeCalendarHeadCell.vue │ │ ├── RangeCalendarHeader.vue │ │ ├── RangeCalendarHeading.vue │ │ ├── RangeCalendarNextButton.vue │ │ ├── RangeCalendarPrevButton.vue │ │ └── index.ts │ │ ├── select │ │ ├── Select.vue │ │ ├── SelectContent.vue │ │ ├── SelectGroup.vue │ │ ├── SelectItem.vue │ │ ├── SelectItemText.vue │ │ ├── SelectLabel.vue │ │ ├── SelectScrollDownButton.vue │ │ ├── SelectScrollUpButton.vue │ │ ├── SelectSeparator.vue │ │ ├── SelectTrigger.vue │ │ ├── SelectValue.vue │ │ └── index.ts │ │ ├── separator │ │ ├── Separator.vue │ │ └── index.ts │ │ ├── skeleton │ │ ├── Skeleton.vue │ │ └── index.ts │ │ ├── sonner │ │ ├── Sonner.vue │ │ └── index.ts │ │ ├── switch │ │ ├── Switch.vue │ │ └── index.ts │ │ ├── table │ │ ├── Table.vue │ │ ├── TableBody.vue │ │ ├── TableCaption.vue │ │ ├── TableCell.vue │ │ ├── TableEmpty.vue │ │ ├── TableFooter.vue │ │ ├── TableHead.vue │ │ ├── TableHeader.vue │ │ ├── TableRow.vue │ │ └── index.ts │ │ ├── tabs │ │ ├── Tabs.vue │ │ ├── TabsContent.vue │ │ ├── TabsList.vue │ │ ├── TabsTrigger.vue │ │ └── index.ts │ │ ├── textarea │ │ ├── Textarea.vue │ │ └── index.ts │ │ └── tooltip │ │ ├── Tooltip.vue │ │ ├── TooltipContent.vue │ │ ├── TooltipProvider.vue │ │ ├── TooltipTrigger.vue │ │ └── index.ts ├── composables │ └── index.ts ├── error.vue ├── layouts │ └── default.vue ├── middleware │ └── auth.global.ts ├── pages │ ├── dashboard │ │ ├── analysis.vue │ │ ├── link.vue │ │ ├── links.vue │ │ ├── login.vue │ │ └── realtime.vue │ └── index.vue └── utils │ ├── api.ts │ ├── color.ts │ ├── events.ts │ ├── flag.ts │ ├── index.ts │ ├── number.ts │ └── time.ts ├── components.json ├── docs ├── api.md ├── configuration.md ├── deployment │ ├── pages.md │ └── workers.md ├── faqs.md └── images │ ├── faqs-Analytics_engine.png │ ├── faqs-kv.png │ ├── sink.cool_dashboard.png │ ├── sink.cool_dashboard_link_slug.png │ └── sink.cool_dashboard_links.png ├── eslint.config.mjs ├── i18n ├── i18n.config.ts ├── i18n.ts └── locales │ ├── de-DE.json │ ├── en-US.json │ ├── fr-FR.json │ ├── vi-VN.json │ ├── zh-CN.json │ └── zh-TW.json ├── nuxt.config.ts ├── package.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── public ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── apple-touch-icon-precomposed.png ├── apple-touch-icon.png ├── banner.png ├── colos.json ├── countries.geojson ├── favicon.ico ├── icon-192-maskable.png ├── icon-192.png ├── icon.png ├── image.png ├── sink-1024.png ├── sink.png └── site.webmanifest ├── renovate.json ├── schemas ├── link.ts └── query.ts ├── scripts ├── build-colo.js └── build-map.js ├── server ├── api │ ├── link │ │ ├── ai.get.ts │ │ ├── create.post.ts │ │ ├── delete.post.ts │ │ ├── edit.put.ts │ │ ├── list.get.ts │ │ ├── query.get.ts │ │ ├── search.get.ts │ │ └── upsert.post.ts │ ├── location.ts │ ├── logs │ │ ├── events.ts │ │ └── locations.ts │ ├── stats │ │ ├── counters.get.ts │ │ ├── metrics.get.ts │ │ └── views.get.ts │ └── verify.ts ├── middleware │ ├── 1.redirect.ts │ └── 2.auth.ts ├── tsconfig.json └── utils │ ├── access-log.ts │ ├── cloudflare.ts │ ├── query-filter.ts │ ├── sql-bricks.ts │ └── time.ts ├── tailwind.config.js ├── tsconfig.json └── wrangler.jsonc /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | NUXT_PUBLIC_PREVIEW_MODE=true 2 | NUXT_PUBLIC_SLUG_DEFAULT_LENGTH=5 3 | NUXT_SITE_TOKEN=SinkCool 4 | NUXT_REDIRECT_STATUS_CODE=308 5 | NUXT_LINK_CACHE_TTL=60 6 | NUXT_REDIRECT_WITH_QUERY=false 7 | NUXT_HOME_URL="https://sink.cool" 8 | NUXT_CF_ACCOUNT_ID=123456 9 | NUXT_CF_API_TOKEN=CloudflareAPIToken 10 | NUXT_DATASET=sink 11 | NUXT_AI_MODEL="@cf/meta/llama-3-8b-instruct" 12 | NUXT_AI_PROMPT="You are a URL shortening assistant......" 13 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: ccbikai 2 | buy_me_a_coffee: miantiao 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Nuxt dev/build outputs 2 | .output 3 | .data 4 | .nuxt 5 | .nitro 6 | .cache 7 | dist 8 | 9 | # Node dependencies 10 | node_modules 11 | 12 | # Logs 13 | ./logs 14 | *.log 15 | 16 | # Misc 17 | .DS_Store 18 | .fleet 19 | .idea 20 | 21 | # Local env files 22 | .env 23 | .env.* 24 | !.env.example 25 | .wrangler 26 | site 27 | cache 28 | public/world.json 29 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 22.15.1 -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "vue.volar" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /app/app.config.ts: -------------------------------------------------------------------------------- 1 | export default defineAppConfig({ 2 | title: 'Sink', 3 | email: 'sink.cool@miantiao.me', 4 | github: 'https://github.com/ccbikai/sink', 5 | twitter: 'https://sink.cool/kai', 6 | telegram: 'https://sink.cool/telegram', 7 | mastodon: 'https://sink.cool/mastodon', 8 | blog: 'https://sink.cool/blog', 9 | description: 'A Simple / Speedy / Secure Link Shortener with Analytics, 100% run on Cloudflare.', 10 | image: 'https://sink.cool/banner.png', 11 | previewTTL: 300, // 5 minutes 12 | slugRegex: /^[a-z0-9]+(?:-[a-z0-9]+)*$/i, 13 | reserveSlug: [ 14 | 'dashboard', 15 | ], 16 | }) 17 | -------------------------------------------------------------------------------- /app/app.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 50 | -------------------------------------------------------------------------------- /app/assets/images/cloudflare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccbikai/Sink/3438170d954a2a5bc513fc4d0aa5f687e36d0f34/app/assets/images/cloudflare.png -------------------------------------------------------------------------------- /app/assets/images/nuxtjs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccbikai/Sink/3438170d954a2a5bc513fc4d0aa5f687e36d0f34/app/assets/images/nuxtjs.png -------------------------------------------------------------------------------- /app/components/SwitchLanguage.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 40 | -------------------------------------------------------------------------------- /app/components/SwitchTheme.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 48 | -------------------------------------------------------------------------------- /app/components/dashboard/Breadcrumb.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 39 | -------------------------------------------------------------------------------- /app/components/dashboard/Logout.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 33 | -------------------------------------------------------------------------------- /app/components/dashboard/Nav.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 32 | -------------------------------------------------------------------------------- /app/components/dashboard/analysis/metrics/Group.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 42 | -------------------------------------------------------------------------------- /app/components/dashboard/analysis/metrics/name/Referer.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 33 | -------------------------------------------------------------------------------- /app/components/dashboard/analysis/metrics/name/Slug.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /app/components/dashboard/links/Delete.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 46 | -------------------------------------------------------------------------------- /app/components/dashboard/realtime/Logs.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 51 | -------------------------------------------------------------------------------- /app/components/home/Cta.vue: -------------------------------------------------------------------------------- 1 | 22 | -------------------------------------------------------------------------------- /app/components/home/Link.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 53 | -------------------------------------------------------------------------------- /app/components/home/Logos.vue: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /app/components/home/Twitter.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 24 | -------------------------------------------------------------------------------- /app/components/ui/accordion/Accordion.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /app/components/ui/accordion/AccordionContent.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 25 | -------------------------------------------------------------------------------- /app/components/ui/accordion/AccordionItem.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /app/components/ui/accordion/AccordionTrigger.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 40 | -------------------------------------------------------------------------------- /app/components/ui/accordion/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Accordion } from './Accordion.vue' 2 | export { default as AccordionContent } from './AccordionContent.vue' 3 | export { default as AccordionItem } from './AccordionItem.vue' 4 | export { default as AccordionTrigger } from './AccordionTrigger.vue' 5 | -------------------------------------------------------------------------------- /app/components/ui/alert-dialog/AlertDialog.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/alert-dialog/AlertDialogAction.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | -------------------------------------------------------------------------------- /app/components/ui/alert-dialog/AlertDialogCancel.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | -------------------------------------------------------------------------------- /app/components/ui/alert-dialog/AlertDialogDescription.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 26 | -------------------------------------------------------------------------------- /app/components/ui/alert-dialog/AlertDialogFooter.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 22 | -------------------------------------------------------------------------------- /app/components/ui/alert-dialog/AlertDialogHeader.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /app/components/ui/alert-dialog/AlertDialogTitle.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 23 | -------------------------------------------------------------------------------- /app/components/ui/alert-dialog/AlertDialogTrigger.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/alert-dialog/index.ts: -------------------------------------------------------------------------------- 1 | export { default as AlertDialog } from './AlertDialog.vue' 2 | export { default as AlertDialogTrigger } from './AlertDialogTrigger.vue' 3 | export { default as AlertDialogContent } from './AlertDialogContent.vue' 4 | export { default as AlertDialogHeader } from './AlertDialogHeader.vue' 5 | export { default as AlertDialogTitle } from './AlertDialogTitle.vue' 6 | export { default as AlertDialogDescription } from './AlertDialogDescription.vue' 7 | export { default as AlertDialogFooter } from './AlertDialogFooter.vue' 8 | export { default as AlertDialogAction } from './AlertDialogAction.vue' 9 | export { default as AlertDialogCancel } from './AlertDialogCancel.vue' 10 | -------------------------------------------------------------------------------- /app/components/ui/alert/Alert.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /app/components/ui/alert/AlertDescription.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/alert/AlertTitle.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/alert/index.ts: -------------------------------------------------------------------------------- 1 | import { type VariantProps, cva } from 'class-variance-authority' 2 | 3 | export { default as Alert } from './Alert.vue' 4 | export { default as AlertTitle } from './AlertTitle.vue' 5 | export { default as AlertDescription } from './AlertDescription.vue' 6 | 7 | export const alertVariants = cva( 8 | 'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground', 9 | { 10 | variants: { 11 | variant: { 12 | default: 'bg-background text-foreground', 13 | destructive: 14 | 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive', 15 | }, 16 | }, 17 | defaultVariants: { 18 | variant: 'default', 19 | }, 20 | }, 21 | ) 22 | 23 | export type AlertVariants = VariantProps 24 | -------------------------------------------------------------------------------- /app/components/ui/aspect-ratio/AspectRatio.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/aspect-ratio/index.ts: -------------------------------------------------------------------------------- 1 | export { default as AspectRatio } from './AspectRatio.vue' 2 | -------------------------------------------------------------------------------- /app/components/ui/auto-form/AutoFormField.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 46 | -------------------------------------------------------------------------------- /app/components/ui/auto-form/AutoFormFieldInput.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 37 | -------------------------------------------------------------------------------- /app/components/ui/auto-form/AutoFormFieldNumber.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 33 | -------------------------------------------------------------------------------- /app/components/ui/auto-form/AutoFormLabel.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 15 | -------------------------------------------------------------------------------- /app/components/ui/auto-form/constant.ts: -------------------------------------------------------------------------------- 1 | import AutoFormFieldArray from './AutoFormFieldArray.vue' 2 | import AutoFormFieldBoolean from './AutoFormFieldBoolean.vue' 3 | import AutoFormFieldDate from './AutoFormFieldDate.vue' 4 | import AutoFormFieldEnum from './AutoFormFieldEnum.vue' 5 | import AutoFormFieldFile from './AutoFormFieldFile.vue' 6 | import AutoFormFieldInput from './AutoFormFieldInput.vue' 7 | import AutoFormFieldNumber from './AutoFormFieldNumber.vue' 8 | import AutoFormFieldObject from './AutoFormFieldObject.vue' 9 | 10 | export const INPUT_COMPONENTS = { 11 | date: AutoFormFieldDate, 12 | select: AutoFormFieldEnum, 13 | radio: AutoFormFieldEnum, 14 | checkbox: AutoFormFieldBoolean, 15 | switch: AutoFormFieldBoolean, 16 | textarea: AutoFormFieldInput, 17 | number: AutoFormFieldNumber, 18 | string: AutoFormFieldInput, 19 | file: AutoFormFieldFile, 20 | array: AutoFormFieldArray, 21 | object: AutoFormFieldObject, 22 | } 23 | 24 | /** 25 | * Define handlers for specific Zod types. 26 | * You can expand this object to support more types. 27 | */ 28 | export const DEFAULT_ZOD_HANDLERS: { 29 | [key: string]: keyof typeof INPUT_COMPONENTS 30 | } = { 31 | ZodString: 'string', 32 | ZodBoolean: 'checkbox', 33 | ZodDate: 'date', 34 | ZodEnum: 'select', 35 | ZodNativeEnum: 'select', 36 | ZodNumber: 'number', 37 | ZodArray: 'array', 38 | ZodObject: 'object', 39 | } 40 | -------------------------------------------------------------------------------- /app/components/ui/auto-form/index.ts: -------------------------------------------------------------------------------- 1 | export { getObjectFormSchema, getBaseSchema, getBaseType } from './utils' 2 | export type { Config, ConfigItem, FieldProps } from './interface' 3 | 4 | export { default as AutoForm } from './AutoForm.vue' 5 | export { default as AutoFormField } from './AutoFormField.vue' 6 | export { default as AutoFormLabel } from './AutoFormLabel.vue' 7 | 8 | export { default as AutoFormFieldArray } from './AutoFormFieldArray.vue' 9 | export { default as AutoFormFieldBoolean } from './AutoFormFieldBoolean.vue' 10 | export { default as AutoFormFieldDate } from './AutoFormFieldDate.vue' 11 | export { default as AutoFormFieldEnum } from './AutoFormFieldEnum.vue' 12 | export { default as AutoFormFieldFile } from './AutoFormFieldFile.vue' 13 | export { default as AutoFormFieldInput } from './AutoFormFieldInput.vue' 14 | export { default as AutoFormFieldNumber } from './AutoFormFieldNumber.vue' 15 | export { default as AutoFormFieldObject } from './AutoFormFieldObject.vue' 16 | -------------------------------------------------------------------------------- /app/components/ui/avatar/Avatar.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /app/components/ui/avatar/AvatarFallback.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/avatar/AvatarImage.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /app/components/ui/avatar/index.ts: -------------------------------------------------------------------------------- 1 | import { type VariantProps, cva } from 'class-variance-authority' 2 | 3 | export { default as Avatar } from './Avatar.vue' 4 | export { default as AvatarImage } from './AvatarImage.vue' 5 | export { default as AvatarFallback } from './AvatarFallback.vue' 6 | 7 | export const avatarVariant = cva( 8 | 'inline-flex items-center justify-center font-normal text-foreground select-none shrink-0 bg-secondary overflow-hidden', 9 | { 10 | variants: { 11 | size: { 12 | sm: 'h-10 w-10 text-xs', 13 | base: 'h-16 w-16 text-2xl', 14 | lg: 'h-32 w-32 text-5xl', 15 | }, 16 | shape: { 17 | circle: 'rounded-full', 18 | square: 'rounded-md', 19 | }, 20 | }, 21 | }, 22 | ) 23 | 24 | export type AvatarVariants = VariantProps 25 | -------------------------------------------------------------------------------- /app/components/ui/badge/Badge.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /app/components/ui/badge/index.ts: -------------------------------------------------------------------------------- 1 | import { cva, type VariantProps } from 'class-variance-authority' 2 | 3 | export { default as Badge } from './Badge.vue' 4 | 5 | export const badgeVariants = cva( 6 | 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', 7 | { 8 | variants: { 9 | variant: { 10 | default: 11 | 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80', 12 | secondary: 13 | 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80', 14 | destructive: 15 | 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80', 16 | outline: 'text-foreground', 17 | }, 18 | }, 19 | defaultVariants: { 20 | variant: 'default', 21 | }, 22 | }, 23 | ) 24 | 25 | export type BadgeVariants = VariantProps 26 | -------------------------------------------------------------------------------- /app/components/ui/breadcrumb/Breadcrumb.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /app/components/ui/breadcrumb/BreadcrumbEllipsis.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 23 | -------------------------------------------------------------------------------- /app/components/ui/breadcrumb/BreadcrumbItem.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /app/components/ui/breadcrumb/BreadcrumbLink.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 20 | -------------------------------------------------------------------------------- /app/components/ui/breadcrumb/BreadcrumbList.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /app/components/ui/breadcrumb/BreadcrumbPage.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 20 | -------------------------------------------------------------------------------- /app/components/ui/breadcrumb/BreadcrumbSeparator.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 22 | -------------------------------------------------------------------------------- /app/components/ui/breadcrumb/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Breadcrumb } from './Breadcrumb.vue' 2 | export { default as BreadcrumbEllipsis } from './BreadcrumbEllipsis.vue' 3 | export { default as BreadcrumbItem } from './BreadcrumbItem.vue' 4 | export { default as BreadcrumbLink } from './BreadcrumbLink.vue' 5 | export { default as BreadcrumbList } from './BreadcrumbList.vue' 6 | export { default as BreadcrumbPage } from './BreadcrumbPage.vue' 7 | export { default as BreadcrumbSeparator } from './BreadcrumbSeparator.vue' 8 | -------------------------------------------------------------------------------- /app/components/ui/button/Button.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 27 | -------------------------------------------------------------------------------- /app/components/ui/button/index.ts: -------------------------------------------------------------------------------- 1 | import { type VariantProps, cva } from 'class-variance-authority' 2 | 3 | export { default as Button } from './Button.vue' 4 | 5 | export const buttonVariants = cva( 6 | 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50', 7 | { 8 | variants: { 9 | variant: { 10 | default: 'bg-primary text-primary-foreground hover:bg-primary/90', 11 | destructive: 12 | 'bg-destructive text-destructive-foreground hover:bg-destructive/90', 13 | outline: 14 | 'border border-input bg-background hover:bg-accent hover:text-accent-foreground', 15 | secondary: 16 | 'bg-secondary text-secondary-foreground hover:bg-secondary/80', 17 | ghost: 'hover:bg-accent hover:text-accent-foreground', 18 | link: 'text-primary underline-offset-4 hover:underline', 19 | }, 20 | size: { 21 | default: 'h-10 px-4 py-2', 22 | xs: 'h-7 rounded px-2', 23 | sm: 'h-9 rounded-md px-3', 24 | lg: 'h-11 rounded-md px-8', 25 | icon: 'h-10 w-10', 26 | }, 27 | }, 28 | defaultVariants: { 29 | variant: 'default', 30 | size: 'default', 31 | }, 32 | }, 33 | ) 34 | 35 | export type ButtonVariants = VariantProps 36 | -------------------------------------------------------------------------------- /app/components/ui/calendar/CalendarCell.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /app/components/ui/calendar/CalendarGrid.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /app/components/ui/calendar/CalendarGridBody.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/calendar/CalendarGridHead.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/calendar/CalendarGridRow.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /app/components/ui/calendar/CalendarHeadCell.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /app/components/ui/calendar/CalendarHeader.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /app/components/ui/calendar/CalendarHeading.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 28 | -------------------------------------------------------------------------------- /app/components/ui/calendar/CalendarNextButton.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 33 | -------------------------------------------------------------------------------- /app/components/ui/calendar/CalendarPrevButton.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 33 | -------------------------------------------------------------------------------- /app/components/ui/calendar/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Calendar } from './Calendar.vue' 2 | export { default as CalendarCell } from './CalendarCell.vue' 3 | export { default as CalendarCellTrigger } from './CalendarCellTrigger.vue' 4 | export { default as CalendarGrid } from './CalendarGrid.vue' 5 | export { default as CalendarGridBody } from './CalendarGridBody.vue' 6 | export { default as CalendarGridHead } from './CalendarGridHead.vue' 7 | export { default as CalendarGridRow } from './CalendarGridRow.vue' 8 | export { default as CalendarHeadCell } from './CalendarHeadCell.vue' 9 | export { default as CalendarHeader } from './CalendarHeader.vue' 10 | export { default as CalendarHeading } from './CalendarHeading.vue' 11 | export { default as CalendarNextButton } from './CalendarNextButton.vue' 12 | export { default as CalendarPrevButton } from './CalendarPrevButton.vue' 13 | -------------------------------------------------------------------------------- /app/components/ui/card/Card.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 22 | -------------------------------------------------------------------------------- /app/components/ui/card/CardContent.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/card/CardDescription.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/card/CardFooter.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/card/CardHeader.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/card/CardTitle.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 19 | -------------------------------------------------------------------------------- /app/components/ui/card/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Card } from './Card.vue' 2 | export { default as CardHeader } from './CardHeader.vue' 3 | export { default as CardTitle } from './CardTitle.vue' 4 | export { default as CardDescription } from './CardDescription.vue' 5 | export { default as CardContent } from './CardContent.vue' 6 | export { default as CardFooter } from './CardFooter.vue' 7 | -------------------------------------------------------------------------------- /app/components/ui/chart-area/index.ts: -------------------------------------------------------------------------------- 1 | export { default as AreaChart } from './AreaChart.vue' 2 | -------------------------------------------------------------------------------- /app/components/ui/chart-bar/index.ts: -------------------------------------------------------------------------------- 1 | export { default as BarChart } from './BarChart.vue' 2 | -------------------------------------------------------------------------------- /app/components/ui/chart/ChartTooltip.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 52 | -------------------------------------------------------------------------------- /app/components/ui/chart/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ChartTooltip } from './ChartTooltip.vue' 2 | export { default as ChartSingleTooltip } from './ChartSingleTooltip.vue' 3 | export { default as ChartLegend } from './ChartLegend.vue' 4 | export { default as ChartCrosshair } from './ChartCrosshair.vue' 5 | 6 | export function defaultColors(count: number = 3) { 7 | const quotient = Math.floor(count / 2) 8 | const remainder = count % 2 9 | 10 | const primaryCount = quotient + remainder 11 | const secondaryCount = quotient 12 | return [ 13 | ...Array.from(Array(primaryCount).keys()).map(i => `hsl(var(--vis-primary-color) / ${1 - (1 / primaryCount) * i})`), 14 | ...Array.from(Array(secondaryCount).keys()).map(i => `hsl(var(--vis-secondary-color) / ${1 - (1 / secondaryCount) * i})`), 15 | ] 16 | } 17 | 18 | export * from './interface' 19 | -------------------------------------------------------------------------------- /app/components/ui/checkbox/Checkbox.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 34 | -------------------------------------------------------------------------------- /app/components/ui/checkbox/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Checkbox } from './Checkbox.vue' 2 | -------------------------------------------------------------------------------- /app/components/ui/command/Command.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 31 | -------------------------------------------------------------------------------- /app/components/ui/command/CommandDialog.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 22 | -------------------------------------------------------------------------------- /app/components/ui/command/CommandEmpty.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | -------------------------------------------------------------------------------- /app/components/ui/command/CommandGroup.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 30 | -------------------------------------------------------------------------------- /app/components/ui/command/CommandInput.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 34 | -------------------------------------------------------------------------------- /app/components/ui/command/CommandItem.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 27 | -------------------------------------------------------------------------------- /app/components/ui/command/CommandList.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 28 | -------------------------------------------------------------------------------- /app/components/ui/command/CommandSeparator.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 24 | -------------------------------------------------------------------------------- /app/components/ui/command/CommandShortcut.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/command/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Command } from './Command.vue' 2 | export { default as CommandDialog } from './CommandDialog.vue' 3 | export { default as CommandEmpty } from './CommandEmpty.vue' 4 | export { default as CommandGroup } from './CommandGroup.vue' 5 | export { default as CommandInput } from './CommandInput.vue' 6 | export { default as CommandItem } from './CommandItem.vue' 7 | export { default as CommandList } from './CommandList.vue' 8 | export { default as CommandSeparator } from './CommandSeparator.vue' 9 | export { default as CommandShortcut } from './CommandShortcut.vue' 10 | -------------------------------------------------------------------------------- /app/components/ui/dialog/Dialog.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/dialog/DialogClose.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/dialog/DialogDescription.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /app/components/ui/dialog/DialogFooter.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | -------------------------------------------------------------------------------- /app/components/ui/dialog/DialogHeader.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /app/components/ui/dialog/DialogTitle.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 30 | -------------------------------------------------------------------------------- /app/components/ui/dialog/DialogTrigger.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/dialog/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Dialog } from './Dialog.vue' 2 | export { default as DialogClose } from './DialogClose.vue' 3 | export { default as DialogTrigger } from './DialogTrigger.vue' 4 | export { default as DialogHeader } from './DialogHeader.vue' 5 | export { default as DialogTitle } from './DialogTitle.vue' 6 | export { default as DialogDescription } from './DialogDescription.vue' 7 | export { default as DialogContent } from './DialogContent.vue' 8 | export { default as DialogScrollContent } from './DialogScrollContent.vue' 9 | export { default as DialogFooter } from './DialogFooter.vue' 10 | -------------------------------------------------------------------------------- /app/components/ui/drawer/Drawer.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /app/components/ui/drawer/DrawerContent.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 29 | -------------------------------------------------------------------------------- /app/components/ui/drawer/DrawerDescription.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /app/components/ui/drawer/DrawerFooter.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/drawer/DrawerHeader.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/drawer/DrawerOverlay.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 20 | -------------------------------------------------------------------------------- /app/components/ui/drawer/DrawerTitle.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /app/components/ui/drawer/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Drawer } from './Drawer.vue' 2 | export { default as DrawerContent } from './DrawerContent.vue' 3 | export { default as DrawerDescription } from './DrawerDescription.vue' 4 | export { default as DrawerFooter } from './DrawerFooter.vue' 5 | export { default as DrawerHeader } from './DrawerHeader.vue' 6 | export { default as DrawerOverlay } from './DrawerOverlay.vue' 7 | export { default as DrawerTitle } from './DrawerTitle.vue' 8 | export { DrawerClose, DrawerPortal, DrawerTrigger } from 'vaul-vue' 9 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenu.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 41 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenuContent.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 39 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenuGroup.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenuItem.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 29 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenuLabel.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenuRadioItem.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 42 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenuSeparator.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 23 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenuShortcut.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenuSub.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenuSubContent.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 31 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 34 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/DropdownMenuTrigger.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /app/components/ui/dropdown-menu/index.ts: -------------------------------------------------------------------------------- 1 | export { DropdownMenuPortal } from 'radix-vue' 2 | 3 | export { default as DropdownMenu } from './DropdownMenu.vue' 4 | export { default as DropdownMenuTrigger } from './DropdownMenuTrigger.vue' 5 | export { default as DropdownMenuContent } from './DropdownMenuContent.vue' 6 | export { default as DropdownMenuGroup } from './DropdownMenuGroup.vue' 7 | export { default as DropdownMenuRadioGroup } from './DropdownMenuRadioGroup.vue' 8 | export { default as DropdownMenuItem } from './DropdownMenuItem.vue' 9 | export { default as DropdownMenuCheckboxItem } from './DropdownMenuCheckboxItem.vue' 10 | export { default as DropdownMenuRadioItem } from './DropdownMenuRadioItem.vue' 11 | export { default as DropdownMenuShortcut } from './DropdownMenuShortcut.vue' 12 | export { default as DropdownMenuSeparator } from './DropdownMenuSeparator.vue' 13 | export { default as DropdownMenuLabel } from './DropdownMenuLabel.vue' 14 | export { default as DropdownMenuSub } from './DropdownMenuSub.vue' 15 | export { default as DropdownMenuSubTrigger } from './DropdownMenuSubTrigger.vue' 16 | export { default as DropdownMenuSubContent } from './DropdownMenuSubContent.vue' 17 | -------------------------------------------------------------------------------- /app/components/ui/form/FormControl.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 17 | -------------------------------------------------------------------------------- /app/components/ui/form/FormDescription.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 21 | -------------------------------------------------------------------------------- /app/components/ui/form/FormItem.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 18 | 19 | 24 | -------------------------------------------------------------------------------- /app/components/ui/form/FormLabel.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 24 | -------------------------------------------------------------------------------- /app/components/ui/form/FormMessage.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | -------------------------------------------------------------------------------- /app/components/ui/form/index.ts: -------------------------------------------------------------------------------- 1 | export { Form, Field as FormField } from 'vee-validate' 2 | export { default as FormItem } from './FormItem.vue' 3 | export { default as FormLabel } from './FormLabel.vue' 4 | export { default as FormControl } from './FormControl.vue' 5 | export { default as FormMessage } from './FormMessage.vue' 6 | export { default as FormDescription } from './FormDescription.vue' 7 | -------------------------------------------------------------------------------- /app/components/ui/form/useFormField.ts: -------------------------------------------------------------------------------- 1 | import { FieldContextKey, useFieldError, useIsFieldDirty, useIsFieldTouched, useIsFieldValid } from 'vee-validate' 2 | import { inject } from 'vue' 3 | import { FORM_ITEM_INJECTION_KEY } from '~/composables' 4 | 5 | export function useFormField() { 6 | const fieldContext = inject(FieldContextKey) 7 | const fieldItemContext = inject(FORM_ITEM_INJECTION_KEY) 8 | 9 | const fieldState = { 10 | valid: useIsFieldValid(), 11 | isDirty: useIsFieldDirty(), 12 | isTouched: useIsFieldTouched(), 13 | error: useFieldError(), 14 | } 15 | 16 | if (!fieldContext) 17 | throw new Error('useFormField should be used within ') 18 | 19 | const { name } = fieldContext 20 | const id = fieldItemContext 21 | 22 | return { 23 | id, 24 | name, 25 | formItemId: `${id}-form-item`, 26 | formDescriptionId: `${id}-form-item-description`, 27 | formMessageId: `${id}-form-item-message`, 28 | ...fieldState, 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/components/ui/hover-card/HoverCard.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/hover-card/HoverCardContent.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 42 | -------------------------------------------------------------------------------- /app/components/ui/hover-card/HoverCardTrigger.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/hover-card/index.ts: -------------------------------------------------------------------------------- 1 | export { default as HoverCard } from './HoverCard.vue' 2 | export { default as HoverCardTrigger } from './HoverCardTrigger.vue' 3 | export { default as HoverCardContent } from './HoverCardContent.vue' 4 | -------------------------------------------------------------------------------- /app/components/ui/input/Input.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 25 | -------------------------------------------------------------------------------- /app/components/ui/input/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Input } from './Input.vue' 2 | -------------------------------------------------------------------------------- /app/components/ui/label/Label.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 28 | -------------------------------------------------------------------------------- /app/components/ui/label/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Label } from './Label.vue' 2 | -------------------------------------------------------------------------------- /app/components/ui/menubar/Menubar.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 36 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarCheckboxItem.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 41 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarContent.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 44 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarGroup.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarItem.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 36 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarLabel.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarMenu.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarRadioGroup.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 21 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarRadioItem.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 41 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarSeparator.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 20 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarShortcut.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarSub.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarSubContent.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 40 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarSubTrigger.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 31 | -------------------------------------------------------------------------------- /app/components/ui/menubar/MenubarTrigger.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 30 | -------------------------------------------------------------------------------- /app/components/ui/menubar/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Menubar } from './Menubar.vue' 2 | export { default as MenubarItem } from './MenubarItem.vue' 3 | export { default as MenubarContent } from './MenubarContent.vue' 4 | export { default as MenubarGroup } from './MenubarGroup.vue' 5 | export { default as MenubarMenu } from './MenubarMenu.vue' 6 | export { default as MenubarRadioGroup } from './MenubarRadioGroup.vue' 7 | export { default as MenubarRadioItem } from './MenubarRadioItem.vue' 8 | export { default as MenubarCheckboxItem } from './MenubarCheckboxItem.vue' 9 | export { default as MenubarSeparator } from './MenubarSeparator.vue' 10 | export { default as MenubarSub } from './MenubarSub.vue' 11 | export { default as MenubarSubContent } from './MenubarSubContent.vue' 12 | export { default as MenubarSubTrigger } from './MenubarSubTrigger.vue' 13 | export { default as MenubarTrigger } from './MenubarTrigger.vue' 14 | export { default as MenubarShortcut } from './MenubarShortcut.vue' 15 | export { default as MenubarLabel } from './MenubarLabel.vue' 16 | -------------------------------------------------------------------------------- /app/components/ui/navigation-menu/NavigationMenu.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 34 | -------------------------------------------------------------------------------- /app/components/ui/navigation-menu/NavigationMenuContent.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 35 | -------------------------------------------------------------------------------- /app/components/ui/navigation-menu/NavigationMenuIndicator.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /app/components/ui/navigation-menu/NavigationMenuItem.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/navigation-menu/NavigationMenuLink.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /app/components/ui/navigation-menu/NavigationMenuList.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 30 | -------------------------------------------------------------------------------- /app/components/ui/navigation-menu/NavigationMenuTrigger.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 35 | -------------------------------------------------------------------------------- /app/components/ui/navigation-menu/NavigationMenuViewport.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 34 | -------------------------------------------------------------------------------- /app/components/ui/navigation-menu/index.ts: -------------------------------------------------------------------------------- 1 | import { cva } from 'class-variance-authority' 2 | 3 | export { default as NavigationMenu } from './NavigationMenu.vue' 4 | export { default as NavigationMenuList } from './NavigationMenuList.vue' 5 | export { default as NavigationMenuItem } from './NavigationMenuItem.vue' 6 | export { default as NavigationMenuTrigger } from './NavigationMenuTrigger.vue' 7 | export { default as NavigationMenuContent } from './NavigationMenuContent.vue' 8 | export { default as NavigationMenuLink } from './NavigationMenuLink.vue' 9 | 10 | export const navigationMenuTriggerStyle = cva( 11 | 'group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50', 12 | ) 13 | -------------------------------------------------------------------------------- /app/components/ui/popover/Popover.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /app/components/ui/popover/PopoverTrigger.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/popover/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Popover } from './Popover.vue' 2 | export { default as PopoverTrigger } from './PopoverTrigger.vue' 3 | export { default as PopoverContent } from './PopoverContent.vue' 4 | -------------------------------------------------------------------------------- /app/components/ui/progress/Progress.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 40 | -------------------------------------------------------------------------------- /app/components/ui/progress/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Progress } from './Progress.vue' 2 | -------------------------------------------------------------------------------- /app/components/ui/radio-group/RadioGroup.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 26 | -------------------------------------------------------------------------------- /app/components/ui/radio-group/RadioGroupItem.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 40 | -------------------------------------------------------------------------------- /app/components/ui/radio-group/index.ts: -------------------------------------------------------------------------------- 1 | export { default as RadioGroup } from './RadioGroup.vue' 2 | export { default as RadioGroupItem } from './RadioGroupItem.vue' 3 | -------------------------------------------------------------------------------- /app/components/ui/range-calendar/RangeCalendarCell.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /app/components/ui/range-calendar/RangeCalendarGrid.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /app/components/ui/range-calendar/RangeCalendarGridBody.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/range-calendar/RangeCalendarGridHead.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/range-calendar/RangeCalendarGridRow.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /app/components/ui/range-calendar/RangeCalendarHeadCell.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /app/components/ui/range-calendar/RangeCalendarHeader.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /app/components/ui/range-calendar/RangeCalendarHeading.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 28 | -------------------------------------------------------------------------------- /app/components/ui/range-calendar/RangeCalendarNextButton.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 33 | -------------------------------------------------------------------------------- /app/components/ui/range-calendar/RangeCalendarPrevButton.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 33 | -------------------------------------------------------------------------------- /app/components/ui/range-calendar/index.ts: -------------------------------------------------------------------------------- 1 | export { default as RangeCalendar } from './RangeCalendar.vue' 2 | export { default as RangeCalendarCell } from './RangeCalendarCell.vue' 3 | export { default as RangeCalendarCellTrigger } from './RangeCalendarCellTrigger.vue' 4 | export { default as RangeCalendarGrid } from './RangeCalendarGrid.vue' 5 | export { default as RangeCalendarGridBody } from './RangeCalendarGridBody.vue' 6 | export { default as RangeCalendarGridHead } from './RangeCalendarGridHead.vue' 7 | export { default as RangeCalendarGridRow } from './RangeCalendarGridRow.vue' 8 | export { default as RangeCalendarHeadCell } from './RangeCalendarHeadCell.vue' 9 | export { default as RangeCalendarHeader } from './RangeCalendarHeader.vue' 10 | export { default as RangeCalendarHeading } from './RangeCalendarHeading.vue' 11 | export { default as RangeCalendarNextButton } from './RangeCalendarNextButton.vue' 12 | export { default as RangeCalendarPrevButton } from './RangeCalendarPrevButton.vue' 13 | -------------------------------------------------------------------------------- /app/components/ui/select/Select.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /app/components/ui/select/SelectGroup.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /app/components/ui/select/SelectItem.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 45 | -------------------------------------------------------------------------------- /app/components/ui/select/SelectItemText.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/select/SelectLabel.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /app/components/ui/select/SelectScrollDownButton.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 25 | -------------------------------------------------------------------------------- /app/components/ui/select/SelectScrollUpButton.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 25 | -------------------------------------------------------------------------------- /app/components/ui/select/SelectSeparator.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 18 | -------------------------------------------------------------------------------- /app/components/ui/select/SelectTrigger.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 32 | -------------------------------------------------------------------------------- /app/components/ui/select/SelectValue.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /app/components/ui/select/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Select } from './Select.vue' 2 | export { default as SelectValue } from './SelectValue.vue' 3 | export { default as SelectTrigger } from './SelectTrigger.vue' 4 | export { default as SelectContent } from './SelectContent.vue' 5 | export { default as SelectGroup } from './SelectGroup.vue' 6 | export { default as SelectItem } from './SelectItem.vue' 7 | export { default as SelectItemText } from './SelectItemText.vue' 8 | export { default as SelectLabel } from './SelectLabel.vue' 9 | export { default as SelectSeparator } from './SelectSeparator.vue' 10 | export { default as SelectScrollUpButton } from './SelectScrollUpButton.vue' 11 | export { default as SelectScrollDownButton } from './SelectScrollDownButton.vue' 12 | -------------------------------------------------------------------------------- /app/components/ui/separator/Separator.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 21 | -------------------------------------------------------------------------------- /app/components/ui/separator/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Separator } from './Separator.vue' 2 | -------------------------------------------------------------------------------- /app/components/ui/skeleton/Skeleton.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 15 | -------------------------------------------------------------------------------- /app/components/ui/skeleton/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Skeleton } from './Skeleton.vue' 2 | -------------------------------------------------------------------------------- /app/components/ui/sonner/Sonner.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 24 | -------------------------------------------------------------------------------- /app/components/ui/sonner/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Toaster } from './Sonner.vue' 2 | -------------------------------------------------------------------------------- /app/components/ui/switch/Switch.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 38 | -------------------------------------------------------------------------------- /app/components/ui/switch/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Switch } from './Switch.vue' 2 | -------------------------------------------------------------------------------- /app/components/ui/table/Table.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /app/components/ui/table/TableBody.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/table/TableCaption.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/table/TableCell.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 22 | -------------------------------------------------------------------------------- /app/components/ui/table/TableEmpty.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 38 | -------------------------------------------------------------------------------- /app/components/ui/table/TableFooter.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/table/TableHead.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/table/TableHeader.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/table/TableRow.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /app/components/ui/table/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Table } from './Table.vue' 2 | export { default as TableBody } from './TableBody.vue' 3 | export { default as TableCell } from './TableCell.vue' 4 | export { default as TableHead } from './TableHead.vue' 5 | export { default as TableHeader } from './TableHeader.vue' 6 | export { default as TableRow } from './TableRow.vue' 7 | export { default as TableCaption } from './TableCaption.vue' 8 | export { default as TableEmpty } from './TableEmpty.vue' 9 | -------------------------------------------------------------------------------- /app/components/ui/tabs/Tabs.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /app/components/ui/tabs/TabsContent.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 23 | -------------------------------------------------------------------------------- /app/components/ui/tabs/TabsList.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 26 | -------------------------------------------------------------------------------- /app/components/ui/tabs/TabsTrigger.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 28 | -------------------------------------------------------------------------------- /app/components/ui/tabs/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Tabs } from './Tabs.vue' 2 | export { default as TabsTrigger } from './TabsTrigger.vue' 3 | export { default as TabsList } from './TabsList.vue' 4 | export { default as TabsContent } from './TabsContent.vue' 5 | -------------------------------------------------------------------------------- /app/components/ui/textarea/Textarea.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 |