feat: vaul-vue integration (#374)

This commit is contained in:
Saeid Zareie 2024-03-04 10:04:28 +03:30 committed by GitHub
parent 0265b48b35
commit 64e2f9c199
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 900 additions and 2 deletions

View File

@ -214,6 +214,12 @@ export const docsConfig: DocsConfig = {
href: '/docs/components/dialog',
items: [],
},
{
title: 'Drawer',
href: '/docs/components/drawer',
items: [],
label: 'New',
},
{
title: 'Dropdown Menu',
href: '/docs/components/dropdown-menu',

View File

@ -84,7 +84,7 @@ watch(() => $route.path, (n) => {
</script>
<template>
<div class="flex min-h-screen flex-col bg-background">
<div vaul-drawer-wrapper class="flex min-h-screen flex-col bg-background">
<header class="sticky z-40 top-0 bg-background/80 backdrop-blur-lg border-b border-border">
<div
class="container flex justify-between h-14 max-w-screen-2xl items-center"

View File

@ -402,6 +402,20 @@ export const Index = {
component: () => import("../src/lib/registry/default/example/DialogScrollOverlayDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/DialogScrollOverlayDemo.vue"],
},
"DrawerDemo": {
name: "DrawerDemo",
type: "components:example",
registryDependencies: ["button","drawer"],
component: () => import("../src/lib/registry/default/example/DrawerDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/DrawerDemo.vue"],
},
"DrawerDialog": {
name: "DrawerDialog",
type: "components:example",
registryDependencies: ["button","dialog","drawer","label","input"],
component: () => import("../src/lib/registry/default/example/DrawerDialog.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/DrawerDialog.vue"],
},
"DropdownMenuDemo": {
name: "DropdownMenuDemo",
type: "components:example",
@ -1355,6 +1369,20 @@ export const Index = {
component: () => import("../src/lib/registry/new-york/example/DialogScrollOverlayDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/DialogScrollOverlayDemo.vue"],
},
"DrawerDemo": {
name: "DrawerDemo",
type: "components:example",
registryDependencies: ["button","drawer"],
component: () => import("../src/lib/registry/new-york/example/DrawerDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/DrawerDemo.vue"],
},
"DrawerDialog": {
name: "DrawerDialog",
type: "components:example",
registryDependencies: ["button","dialog","drawer","label","input"],
component: () => import("../src/lib/registry/new-york/example/DrawerDialog.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/DrawerDialog.vue"],
},
"DropdownMenuDemo": {
name: "DropdownMenuDemo",
type: "components:example",

View File

@ -34,6 +34,7 @@
"radix-vue": "^1.4.9",
"tailwindcss-animate": "^1.0.7",
"v-calendar": "^3.1.2",
"vaul-vue": "^0.1.0",
"vee-validate": "4.12.5",
"vue": "^3.4.21",
"vue-sonner": "^1.1.1",

View File

@ -0,0 +1,63 @@
---
title: Drawer
description: A drawer component for vue.
source: apps/www/src/lib/registry/default/ui/drawer
primitive: https://github.com/radix-vue/vaul-vue
---
<ComponentPreview name="DrawerDemo" />
## About
Drawer is built on top of [Vaul Vue](https://github.com/radix-vue/vaul-vue).
## Installation
```bash
npx shadcn-vue@latest add drawer
```
## Usage
```vue showLineNumbers
<script setup lang="ts">
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/components/ui/drawer'
</script>
<template>
<Drawer>
<DrawerTrigger>Open</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Are you absolutely sure?</DrawerTitle>
<DrawerDescription>This action cannot be undone.</DrawerDescription>
</DrawerHeader>
<DrawerFooter>
<Button>Submit</Button>
<DrawerClose>
<Button variant="outline">
Cancel
</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
</template>
```
## Examples
### Responsive Dialog
You can combine the `Dialog` and `Drawer` components to create a responsive dialog. This renders a `Dialog` component on desktop and a `Drawer` on mobile.
<ComponentPreview name="DrawerDialog" />

View File

@ -0,0 +1,111 @@
<script setup lang="ts">
import { ref } from 'vue'
import { Minus, Plus } from 'lucide-vue-next'
import { VisStackedBar, VisXYContainer } from '@unovis/vue'
import { Button } from '@/lib/registry/default/ui/button'
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/lib/registry/default/ui/drawer'
const goal = ref(350)
type Data = typeof data[number]
const data = [
{ goal: 400 },
{ goal: 300 },
{ goal: 200 },
{ goal: 300 },
{ goal: 200 },
{ goal: 278 },
{ goal: 189 },
{ goal: 239 },
{ goal: 300 },
{ goal: 200 },
{ goal: 278 },
{ goal: 189 },
{ goal: 349 },
]
</script>
<template>
<Drawer>
<DrawerTrigger as-child>
<Button variant="outline">
Open Drawer
</Button>
</DrawerTrigger>
<DrawerContent>
<div class="mx-auto w-full max-w-sm">
<DrawerHeader>
<DrawerTitle>Move Goal</DrawerTitle>
<DrawerDescription>Set your daily activity goal.</DrawerDescription>
</DrawerHeader>
<div class="p-4 pb-0">
<div class="flex items-center justify-center space-x-2">
<Button
variant="outline"
size="icon"
class="h-8 w-8 shrink-0 rounded-full"
:disabled="goal <= 200"
@click="goal -= 10"
>
<Minus class="h-4 w-4" />
<span class="sr-only">Decrease</span>
</Button>
<div class="flex-1 text-center">
<div class="text-7xl font-bold tracking-tighter">
{{ goal }}
</div>
<div class="text-[0.70rem] uppercase text-muted-foreground">
Calories/day
</div>
</div>
<Button
variant="outline"
size="icon"
class="h-8 w-8 shrink-0 rounded-full"
:disabled="goal >= 400"
@click="goal += 10"
>
<Plus class="h-4 w-4" />
<span class="sr-only">Increase</span>
</Button>
</div>
<div class="my-3 px-3 h-[120px]">
<VisXYContainer
:data="data"
class="h-[120px]"
:style="{
'opacity': 0.9,
'--theme-primary': `hsl(var(--foreground))`,
}"
>
<VisStackedBar
:x="(d: Data, i :number) => i"
:y="(d: Data) => d.goal"
color="var(--theme-primary)"
:bar-padding="0.1"
:rounded-corners="0"
/>
</VisXYContainer>
</div>
</div>
<DrawerFooter>
<Button>Submit</Button>
<DrawerClose as-child>
<Button variant="outline">
Cancel
</Button>
</DrawerClose>
</DrawerFooter>
</div>
</DrawerContent>
</Drawer>
</template>

View File

@ -0,0 +1,90 @@
<script lang="ts" setup>
import { ref } from 'vue'
import { createReusableTemplate, useMediaQuery } from '@vueuse/core'
import { Button } from '@/lib/registry/default/ui/button'
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/lib/registry/default/ui/dialog'
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/lib/registry/default/ui/drawer'
import { Label } from '@/lib/registry/default/ui/label'
import { Input } from '@/lib/registry/default/ui/input'
// Reuse `form` section
const [UseTemplate, GridForm] = createReusableTemplate()
const isDesktop = useMediaQuery('(min-width: 768px)')
const isOpen = ref(false)
</script>
<template>
<UseTemplate>
<form class="grid items-start gap-4 px-4">
<div class="grid gap-2">
<Label html-for="email">Email</Label>
<Input id="email" type="email" default-value="shadcn@example.com" />
</div>
<div class="grid gap-2">
<Label html-for="username">Username</Label>
<Input id="username" default-value="@shadcn" />
</div>
<Button type="submit">
Save changes
</Button>
</form>
</UseTemplate>
<Dialog v-if="isDesktop" v-model:open="isOpen">
<DialogTrigger as-child>
<Button variant="outline">
Edit Profile
</Button>
</DialogTrigger>
<DialogContent class="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Click save when you're done.
</DialogDescription>
</DialogHeader>
<GridForm />
</DialogContent>
</Dialog>
<Drawer v-else v-model:open="isOpen">
<DrawerTrigger as-child>
<Button variant="outline">
Edit Profile
</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader class="text-left">
<DrawerTitle>Edit profile</DrawerTitle>
<DrawerDescription>
Make changes to your profile here. Click save when you're done.
</DrawerDescription>
</DrawerHeader>
<GridForm />
<DrawerFooter class="pt-2">
<DrawerClose as-child>
<Button variant="outline">
Cancel
</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
</template>

View File

@ -0,0 +1,19 @@
<script lang="ts" setup>
import type { DrawerRootEmits, DrawerRootProps } from 'vaul-vue'
import { DrawerRoot } from 'vaul-vue'
import { useForwardPropsEmits } from 'radix-vue'
const props = withDefaults(defineProps<DrawerRootProps>(), {
shouldScaleBackground: true,
})
const emits = defineEmits<DrawerRootEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>
<template>
<DrawerRoot v-bind="forwarded">
<slot />
</DrawerRoot>
</template>

View File

@ -0,0 +1,28 @@
<script lang="ts" setup>
import { DrawerContent, DrawerPortal } from 'vaul-vue'
import type { DialogContentEmits, DialogContentProps } from 'radix-vue'
import { useForwardPropsEmits } from 'radix-vue'
import type { HtmlHTMLAttributes } from 'vue'
import DrawerOverlay from './DrawerOverlay.vue'
import { cn } from '@/lib/utils'
const props = defineProps<DialogContentProps & { class?: HtmlHTMLAttributes['class'] }>()
const emits = defineEmits<DialogContentEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>
<template>
<DrawerPortal>
<DrawerOverlay />
<DrawerContent
v-bind="forwarded" :class="cn(
'fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background',
props.class,
)"
>
<div class="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
<slot />
</DrawerContent>
</DrawerPortal>
</template>

View File

@ -0,0 +1,20 @@
<script lang="ts" setup>
import type { DrawerDescriptionProps } from 'vaul-vue'
import { DrawerDescription } from 'vaul-vue'
import { type HtmlHTMLAttributes, computed } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<DrawerDescriptionProps & { class?: HtmlHTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script>
<template>
<DrawerDescription v-bind="delegatedProps" :class="cn('text-sm text-muted-foreground', props.class)">
<slot />
</DrawerDescription>
</template>

View File

@ -0,0 +1,14 @@
<script lang="ts" setup>
import type { HtmlHTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HtmlHTMLAttributes['class']
}>()
</script>
<template>
<div :class="cn('mt-auto flex flex-col gap-2 p-4', props.class)">
<slot />
</div>
</template>

View File

@ -0,0 +1,14 @@
<script lang="ts" setup>
import type { HtmlHTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HtmlHTMLAttributes['class']
}>()
</script>
<template>
<div :class="cn('grid gap-1.5 p-4 text-center sm:text-left', props.class)">
<slot />
</div>
</template>

View File

@ -0,0 +1,18 @@
<script lang="ts" setup>
import { DrawerOverlay } from 'vaul-vue'
import type { DialogOverlayProps } from 'radix-vue'
import { type HtmlHTMLAttributes, computed } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<DialogOverlayProps & { class?: HtmlHTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script>
<template>
<DrawerOverlay v-bind="delegatedProps" :class="cn('fixed inset-0 z-50 bg-black/80', props.class)" />
</template>

View File

@ -0,0 +1,20 @@
<script lang="ts" setup>
import type { DrawerTitleProps } from 'vaul-vue'
import { DrawerTitle } from 'vaul-vue'
import { type HtmlHTMLAttributes, computed } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<DrawerTitleProps & { class?: HtmlHTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script>
<template>
<DrawerTitle v-bind="delegatedProps" :class="cn('text-lg font-semibold leading-none tracking-tight', props.class)">
<slot />
</DrawerTitle>
</template>

View File

@ -0,0 +1,8 @@
export { DrawerPortal, DrawerTrigger, DrawerClose } from 'vaul-vue'
export { default as Drawer } from './Drawer.vue'
export { default as DrawerOverlay } from './DrawerOverlay.vue'
export { default as DrawerContent } from './DrawerContent.vue'
export { default as DrawerHeader } from './DrawerHeader.vue'
export { default as DrawerFooter } from './DrawerFooter.vue'
export { default as DrawerTitle } from './DrawerTitle.vue'
export { default as DrawerDescription } from './DrawerDescription.vue'

View File

@ -0,0 +1,111 @@
<script setup lang="ts">
import { ref } from 'vue'
import { Minus, Plus } from 'lucide-vue-next'
import { VisStackedBar, VisXYContainer } from '@unovis/vue'
import { Button } from '@/lib/registry/default/ui/button'
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/lib/registry/default/ui/drawer'
const goal = ref(350)
type Data = typeof data[number]
const data = [
{ goal: 400 },
{ goal: 300 },
{ goal: 200 },
{ goal: 300 },
{ goal: 200 },
{ goal: 278 },
{ goal: 189 },
{ goal: 239 },
{ goal: 300 },
{ goal: 200 },
{ goal: 278 },
{ goal: 189 },
{ goal: 349 },
]
</script>
<template>
<Drawer>
<DrawerTrigger as-child>
<Button variant="outline">
Open Drawer
</Button>
</DrawerTrigger>
<DrawerContent>
<div class="mx-auto w-full max-w-sm">
<DrawerHeader>
<DrawerTitle>Move Goal</DrawerTitle>
<DrawerDescription>Set your daily activity goal.</DrawerDescription>
</DrawerHeader>
<div class="p-4 pb-0">
<div class="flex items-center justify-center space-x-2">
<Button
variant="outline"
size="icon"
class="h-8 w-8 shrink-0 rounded-full"
:disabled="goal <= 200"
@click="goal -= 10"
>
<Minus class="h-4 w-4" />
<span class="sr-only">Decrease</span>
</Button>
<div class="flex-1 text-center">
<div class="text-7xl font-bold tracking-tighter">
{{ goal }}
</div>
<div class="text-[0.70rem] uppercase text-muted-foreground">
Calories/day
</div>
</div>
<Button
variant="outline"
size="icon"
class="h-8 w-8 shrink-0 rounded-full"
:disabled="goal >= 400"
@click="goal += 10"
>
<Plus class="h-4 w-4" />
<span class="sr-only">Increase</span>
</Button>
</div>
<div class="my-3 px-3 h-[120px]">
<VisXYContainer
:data="data"
class="h-[120px]"
:style="{
'opacity': 0.9,
'--theme-primary': `hsl(var(--foreground))`,
}"
>
<VisStackedBar
:x="(d: Data, i :number) => i"
:y="(d: Data) => d.goal"
color="var(--theme-primary)"
:bar-padding="0.1"
:rounded-corners="0"
/>
</VisXYContainer>
</div>
</div>
<DrawerFooter>
<Button>Submit</Button>
<DrawerClose as-child>
<Button variant="outline">
Cancel
</Button>
</DrawerClose>
</DrawerFooter>
</div>
</DrawerContent>
</Drawer>
</template>

View File

@ -0,0 +1,90 @@
<script lang="ts" setup>
import { ref } from 'vue'
import { createReusableTemplate, useMediaQuery } from '@vueuse/core'
import { Button } from '@/lib/registry/default/ui/button'
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/lib/registry/default/ui/dialog'
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/lib/registry/default/ui/drawer'
import { Label } from '@/lib/registry/default/ui/label'
import { Input } from '@/lib/registry/default/ui/input'
// Reuse `form` section
const [UseTemplate, GridForm] = createReusableTemplate()
const isDesktop = useMediaQuery('(min-width: 768px)')
const isOpen = ref(false)
</script>
<template>
<UseTemplate>
<form class="grid items-start gap-4 px-4">
<div class="grid gap-2">
<Label html-for="email">Email</Label>
<Input id="email" type="email" default-value="shadcn@example.com" />
</div>
<div class="grid gap-2">
<Label html-for="username">Username</Label>
<Input id="username" default-value="@shadcn" />
</div>
<Button type="submit">
Save changes
</Button>
</form>
</UseTemplate>
<Dialog v-if="isDesktop" v-model:open="isOpen">
<DialogTrigger as-child>
<Button variant="outline">
Edit Profile
</Button>
</DialogTrigger>
<DialogContent class="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Click save when you're done.
</DialogDescription>
</DialogHeader>
<GridForm />
</DialogContent>
</Dialog>
<Drawer v-else v-model:open="isOpen">
<DrawerTrigger as-child>
<Button variant="outline">
Edit Profile
</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader class="text-left">
<DrawerTitle>Edit profile</DrawerTitle>
<DrawerDescription>
Make changes to your profile here. Click save when you're done.
</DrawerDescription>
</DrawerHeader>
<GridForm />
<DrawerFooter class="pt-2">
<DrawerClose as-child>
<Button variant="outline">
Cancel
</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
</template>

View File

@ -0,0 +1,19 @@
<script lang="ts" setup>
import type { DrawerRootEmits, DrawerRootProps } from 'vaul-vue'
import { DrawerRoot } from 'vaul-vue'
import { useForwardPropsEmits } from 'radix-vue'
const props = withDefaults(defineProps<DrawerRootProps>(), {
shouldScaleBackground: true,
})
const emits = defineEmits<DrawerRootEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>
<template>
<DrawerRoot v-bind="forwarded">
<slot />
</DrawerRoot>
</template>

View File

@ -0,0 +1,28 @@
<script lang="ts" setup>
import { DrawerContent, DrawerPortal } from 'vaul-vue'
import type { DialogContentEmits, DialogContentProps } from 'radix-vue'
import { useForwardPropsEmits } from 'radix-vue'
import type { HtmlHTMLAttributes } from 'vue'
import DrawerOverlay from './DrawerOverlay.vue'
import { cn } from '@/lib/utils'
const props = defineProps<DialogContentProps & { class?: HtmlHTMLAttributes['class'] }>()
const emits = defineEmits<DialogContentEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>
<template>
<DrawerPortal>
<DrawerOverlay />
<DrawerContent
v-bind="forwarded" :class="cn(
'fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background',
props.class,
)"
>
<div class="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
<slot />
</DrawerContent>
</DrawerPortal>
</template>

View File

@ -0,0 +1,20 @@
<script lang="ts" setup>
import type { DrawerDescriptionProps } from 'vaul-vue'
import { DrawerDescription } from 'vaul-vue'
import { type HtmlHTMLAttributes, computed } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<DrawerDescriptionProps & { class?: HtmlHTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script>
<template>
<DrawerDescription v-bind="delegatedProps" :class="cn('text-sm text-muted-foreground', props.class)">
<slot />
</DrawerDescription>
</template>

View File

@ -0,0 +1,14 @@
<script lang="ts" setup>
import type { HtmlHTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HtmlHTMLAttributes['class']
}>()
</script>
<template>
<div :class="cn('mt-auto flex flex-col gap-2 p-4', props.class)">
<slot />
</div>
</template>

View File

@ -0,0 +1,14 @@
<script lang="ts" setup>
import type { HtmlHTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HtmlHTMLAttributes['class']
}>()
</script>
<template>
<div :class="cn('grid gap-1.5 p-4 text-center sm:text-left', props.class)">
<slot />
</div>
</template>

View File

@ -0,0 +1,18 @@
<script lang="ts" setup>
import { DrawerOverlay } from 'vaul-vue'
import type { DialogOverlayProps } from 'radix-vue'
import { type HtmlHTMLAttributes, computed } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<DialogOverlayProps & { class?: HtmlHTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script>
<template>
<DrawerOverlay v-bind="delegatedProps" :class="cn('fixed inset-0 z-50 bg-black/80', props.class)" />
</template>

View File

@ -0,0 +1,20 @@
<script lang="ts" setup>
import type { DrawerTitleProps } from 'vaul-vue'
import { DrawerTitle } from 'vaul-vue'
import { type HtmlHTMLAttributes, computed } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<DrawerTitleProps & { class?: HtmlHTMLAttributes['class'] }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script>
<template>
<DrawerTitle v-bind="delegatedProps" :class="cn('text-lg font-semibold leading-none tracking-tight', props.class)">
<slot />
</DrawerTitle>
</template>

View File

@ -0,0 +1,8 @@
export { DrawerPortal, DrawerTrigger, DrawerClose } from 'vaul-vue'
export { default as Drawer } from './Drawer.vue'
export { default as DrawerOverlay } from './DrawerOverlay.vue'
export { default as DrawerContent } from './DrawerContent.vue'
export { default as DrawerHeader } from './DrawerHeader.vue'
export { default as DrawerFooter } from './DrawerFooter.vue'
export { default as DrawerTitle } from './DrawerTitle.vue'
export { default as DrawerDescription } from './DrawerDescription.vue'

View File

@ -244,6 +244,24 @@
],
"type": "components:ui"
},
{
"name": "drawer",
"dependencies": [],
"registryDependencies": [
"utils"
],
"files": [
"ui/drawer/Drawer.vue",
"ui/drawer/DrawerContent.vue",
"ui/drawer/DrawerDescription.vue",
"ui/drawer/DrawerFooter.vue",
"ui/drawer/DrawerHeader.vue",
"ui/drawer/DrawerOverlay.vue",
"ui/drawer/DrawerTitle.vue",
"ui/drawer/index.ts"
],
"type": "components:ui"
},
{
"name": "dropdown-menu",
"dependencies": [],
@ -685,4 +703,4 @@
],
"type": "components:ui"
}
]
]

View File

@ -0,0 +1,42 @@
{
"name": "drawer",
"dependencies": [],
"registryDependencies": [
"utils"
],
"files": [
{
"name": "Drawer.vue",
"content": "<script lang=\"ts\" setup>\nimport type { DrawerRootEmits, DrawerRootProps } from 'vaul-vue'\nimport { DrawerRoot } from 'vaul-vue'\nimport { useForwardPropsEmits } from 'radix-vue'\n\nconst props = withDefaults(defineProps<DrawerRootProps>(), {\n shouldScaleBackground: true,\n})\n\nconst emits = defineEmits<DrawerRootEmits>()\n\nconst forwarded = useForwardPropsEmits(props, emits)\n</script>\n\n<template>\n <DrawerRoot v-bind=\"forwarded\">\n <slot />\n </DrawerRoot>\n</template>\n"
},
{
"name": "DrawerContent.vue",
"content": "<script lang=\"ts\" setup>\nimport { DrawerContent, DrawerPortal } from 'vaul-vue'\nimport type { DialogContentEmits, DialogContentProps } from 'radix-vue'\nimport { useForwardPropsEmits } from 'radix-vue'\nimport type { HtmlHTMLAttributes } from 'vue'\nimport DrawerOverlay from './DrawerOverlay.vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<DialogContentProps & { class?: HtmlHTMLAttributes['class'] }>()\nconst emits = defineEmits<DialogContentEmits>()\n\nconst forwarded = useForwardPropsEmits(props, emits)\n</script>\n\n<template>\n <DrawerPortal>\n <DrawerOverlay />\n <DrawerContent\n v-bind=\"forwarded\" :class=\"cn(\n 'fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background',\n props.class,\n )\"\n >\n <div class=\"mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted\" />\n <slot />\n </DrawerContent>\n </DrawerPortal>\n</template>\n"
},
{
"name": "DrawerDescription.vue",
"content": "<script lang=\"ts\" setup>\nimport type { DrawerDescriptionProps } from 'vaul-vue'\nimport { DrawerDescription } from 'vaul-vue'\nimport { type HtmlHTMLAttributes, computed } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<DrawerDescriptionProps & { class?: HtmlHTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <DrawerDescription v-bind=\"delegatedProps\" :class=\"cn('text-sm text-muted-foreground', props.class)\">\n <slot />\n </DrawerDescription>\n</template>\n"
},
{
"name": "DrawerFooter.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HtmlHTMLAttributes } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HtmlHTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <div :class=\"cn('mt-auto flex flex-col gap-2 p-4', props.class)\">\n <slot />\n </div>\n</template>\n"
},
{
"name": "DrawerHeader.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HtmlHTMLAttributes } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HtmlHTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <div :class=\"cn('grid gap-1.5 p-4 text-center sm:text-left', props.class)\">\n <slot />\n </div>\n</template>\n"
},
{
"name": "DrawerOverlay.vue",
"content": "<script lang=\"ts\" setup>\nimport { DrawerOverlay } from 'vaul-vue'\nimport type { DialogOverlayProps } from 'radix-vue'\nimport { type HtmlHTMLAttributes, computed } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<DialogOverlayProps & { class?: HtmlHTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <DrawerOverlay v-bind=\"delegatedProps\" :class=\"cn('fixed inset-0 z-50 bg-black/80', props.class)\" />\n</template>\n"
},
{
"name": "DrawerTitle.vue",
"content": "<script lang=\"ts\" setup>\nimport type { DrawerTitleProps } from 'vaul-vue'\nimport { DrawerTitle } from 'vaul-vue'\nimport { type HtmlHTMLAttributes, computed } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<DrawerTitleProps & { class?: HtmlHTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <DrawerTitle v-bind=\"delegatedProps\" :class=\"cn('text-lg font-semibold leading-none tracking-tight', props.class)\">\n <slot />\n </DrawerTitle>\n</template>\n"
},
{
"name": "index.ts",
"content": "export { DrawerPortal, DrawerTrigger, DrawerClose } from 'vaul-vue'\nexport { default as Drawer } from './Drawer.vue'\nexport { default as DrawerOverlay } from './DrawerOverlay.vue'\nexport { default as DrawerContent } from './DrawerContent.vue'\nexport { default as DrawerHeader } from './DrawerHeader.vue'\nexport { default as DrawerFooter } from './DrawerFooter.vue'\nexport { default as DrawerTitle } from './DrawerTitle.vue'\nexport { default as DrawerDescription } from './DrawerDescription.vue'\n"
}
],
"type": "components:ui"
}

View File

@ -0,0 +1,42 @@
{
"name": "drawer",
"dependencies": [],
"registryDependencies": [
"utils"
],
"files": [
{
"name": "Drawer.vue",
"content": "<script lang=\"ts\" setup>\nimport type { DrawerRootEmits, DrawerRootProps } from 'vaul-vue'\nimport { DrawerRoot } from 'vaul-vue'\nimport { useForwardPropsEmits } from 'radix-vue'\n\nconst props = withDefaults(defineProps<DrawerRootProps>(), {\n shouldScaleBackground: true,\n})\n\nconst emits = defineEmits<DrawerRootEmits>()\n\nconst forwarded = useForwardPropsEmits(props, emits)\n</script>\n\n<template>\n <DrawerRoot v-bind=\"forwarded\">\n <slot />\n </DrawerRoot>\n</template>\n"
},
{
"name": "DrawerContent.vue",
"content": "<script lang=\"ts\" setup>\nimport { DrawerContent, DrawerPortal } from 'vaul-vue'\nimport type { DialogContentEmits, DialogContentProps } from 'radix-vue'\nimport { useForwardPropsEmits } from 'radix-vue'\nimport type { HtmlHTMLAttributes } from 'vue'\nimport DrawerOverlay from './DrawerOverlay.vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<DialogContentProps & { class?: HtmlHTMLAttributes['class'] }>()\nconst emits = defineEmits<DialogContentEmits>()\n\nconst forwarded = useForwardPropsEmits(props, emits)\n</script>\n\n<template>\n <DrawerPortal>\n <DrawerOverlay />\n <DrawerContent\n v-bind=\"forwarded\" :class=\"cn(\n 'fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background',\n props.class,\n )\"\n >\n <div class=\"mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted\" />\n <slot />\n </DrawerContent>\n </DrawerPortal>\n</template>\n"
},
{
"name": "DrawerDescription.vue",
"content": "<script lang=\"ts\" setup>\nimport type { DrawerDescriptionProps } from 'vaul-vue'\nimport { DrawerDescription } from 'vaul-vue'\nimport { type HtmlHTMLAttributes, computed } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<DrawerDescriptionProps & { class?: HtmlHTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <DrawerDescription v-bind=\"delegatedProps\" :class=\"cn('text-sm text-muted-foreground', props.class)\">\n <slot />\n </DrawerDescription>\n</template>\n"
},
{
"name": "DrawerFooter.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HtmlHTMLAttributes } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HtmlHTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <div :class=\"cn('mt-auto flex flex-col gap-2 p-4', props.class)\">\n <slot />\n </div>\n</template>\n"
},
{
"name": "DrawerHeader.vue",
"content": "<script lang=\"ts\" setup>\nimport type { HtmlHTMLAttributes } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<{\n class?: HtmlHTMLAttributes['class']\n}>()\n</script>\n\n<template>\n <div :class=\"cn('grid gap-1.5 p-4 text-center sm:text-left', props.class)\">\n <slot />\n </div>\n</template>\n"
},
{
"name": "DrawerOverlay.vue",
"content": "<script lang=\"ts\" setup>\nimport { DrawerOverlay } from 'vaul-vue'\nimport type { DialogOverlayProps } from 'radix-vue'\nimport { type HtmlHTMLAttributes, computed } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<DialogOverlayProps & { class?: HtmlHTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <DrawerOverlay v-bind=\"delegatedProps\" :class=\"cn('fixed inset-0 z-50 bg-black/80', props.class)\" />\n</template>\n"
},
{
"name": "DrawerTitle.vue",
"content": "<script lang=\"ts\" setup>\nimport type { DrawerTitleProps } from 'vaul-vue'\nimport { DrawerTitle } from 'vaul-vue'\nimport { type HtmlHTMLAttributes, computed } from 'vue'\nimport { cn } from '@/lib/utils'\n\nconst props = defineProps<DrawerTitleProps & { class?: HtmlHTMLAttributes['class'] }>()\n\nconst delegatedProps = computed(() => {\n const { class: _, ...delegated } = props\n\n return delegated\n})\n</script>\n\n<template>\n <DrawerTitle v-bind=\"delegatedProps\" :class=\"cn('text-lg font-semibold leading-none tracking-tight', props.class)\">\n <slot />\n </DrawerTitle>\n</template>\n"
},
{
"name": "index.ts",
"content": "export { DrawerPortal, DrawerTrigger, DrawerClose } from 'vaul-vue'\nexport { default as Drawer } from './Drawer.vue'\nexport { default as DrawerOverlay } from './DrawerOverlay.vue'\nexport { default as DrawerContent } from './DrawerContent.vue'\nexport { default as DrawerHeader } from './DrawerHeader.vue'\nexport { default as DrawerFooter } from './DrawerFooter.vue'\nexport { default as DrawerTitle } from './DrawerTitle.vue'\nexport { default as DrawerDescription } from './DrawerDescription.vue'\n"
}
],
"type": "components:ui"
}

View File

@ -98,6 +98,9 @@ importers:
v-calendar:
specifier: ^3.1.2
version: 3.1.2(@popperjs/core@2.11.8)(vue@3.4.21)
vaul-vue:
specifier: ^0.1.0
version: 0.1.0(typescript@5.3.3)
vee-validate:
specifier: 4.12.5
version: 4.12.5(vue@3.4.21)
@ -13145,6 +13148,17 @@ packages:
builtins: 5.0.1
dev: true
/vaul-vue@0.1.0(typescript@5.3.3):
resolution: {integrity: sha512-3PYWMbN3cSdsciv3fzewskxZFnX61PYq1uNsbvizXDo/8sN4SMrWkYDqWaPdTD3GTEm6wpx7j5flRLg7A5ZXbQ==}
dependencies:
'@vueuse/core': 10.9.0(vue@3.4.21)
radix-vue: 1.4.9(vue@3.4.21)
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- '@vue/composition-api'
- typescript
dev: false
/vee-validate@4.12.5(vue@3.4.21):
resolution: {integrity: sha512-rvaDfLPSLwTk+mf016XWE4drB8yXzOsKXiKHTb9gNXNLTtQSZ0Ww26O0/xbIFQe+n3+u8Wv1Y8uO/aLDX4fxOg==}
peerDependencies: