Merge branch 'dev' into refactor/update-tailwind-classes
This commit is contained in:
commit
ec2b606dec
77
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
77
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
|
|
@ -6,62 +6,27 @@ body:
|
|||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Before You Start...**
|
||||
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
This form is only for submitting bug reports. If you have a usage question
|
||||
or are unsure if this is really a bug, make sure to:
|
||||
|
||||
- Read the [docs](https://radix-vue.com/)
|
||||
- Ask on [Discord Chat](https://chat.radix-vue.com/)
|
||||
- Ask on [GitHub Discussions](https://github.com/shadcn-vue/shadcn-vue/discussions)
|
||||
|
||||
Also try to search for your issue - it may have already been answered or even fixed.
|
||||
However, if you find that an old, closed issue still persists in the latest version,
|
||||
you should open a new issue using the form below instead of commenting on the old issue.
|
||||
- type: textarea
|
||||
id: bug-env
|
||||
attributes:
|
||||
label: Environment
|
||||
description: Please provide the following information about your environment.
|
||||
value: |
|
||||
Developement/Production OS: Windows 10 19043.1110
|
||||
Node version: 16.0.0
|
||||
Package manager: pnpm@8.6.0
|
||||
Radix Vue version: 1.0.0
|
||||
Shadcn Vue version: 1.0.0
|
||||
Vue version: 3.0.0
|
||||
Nuxt version: 3.0.0
|
||||
Nuxt mode: universal
|
||||
Nuxt target: server
|
||||
CSS framework: tailwindcss@3.3.3
|
||||
Client OS: Windows 10 19043.1110
|
||||
Browser: Chrome 90.0.4430.212
|
||||
render: bash
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: reproduction-link
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Link to minimal reproduction
|
||||
label: Reproduction
|
||||
description: |
|
||||
Please provide a link to a minimal reproduction of the bug.
|
||||
A minimal reproduction is a CodeSandbox, CodePen, or a StackBlitz that contains the bare minimum amount of code needed to show the bug.
|
||||
A minimal reproduction is required unless you are absolutely sure that the issue is obvious and the provided information is enough to understand the problem
|
||||
A [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) is **required**, otherwise the issue might be closed without further notice. [**Why?**](https://antfu.me/posts/why-reproductions-are-required)
|
||||
|
||||
This is **required** for us to be able to triage your issue in a timely manner.
|
||||
To get started, you can use the StackBlitz and CodeSandbox playgrounds in shadcn-vue demos:
|
||||
https://www.shadcn-vue.com/docs/components/accordion.html
|
||||
|
||||
Please do not just fill in a random link. The issue will be closed if no valid reproduction is provided.
|
||||
placeholder: Reproduction Link
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps-to-reproduce
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: |
|
||||
How do you trigger this bug? Please walk us through it step by step.
|
||||
Note that you can use [Markdown](https://guides.github.com/features/mastering-markdown/) to format lists and code.
|
||||
placeholder: Steps to reproduce
|
||||
or use template presets
|
||||
https://vite.new
|
||||
https://nuxt.new
|
||||
placeholder: Reproduction
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
|
@ -73,14 +38,18 @@ body:
|
|||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
id: system-info
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
label: System Info
|
||||
description: Output of `npx envinfo --system --npmPackages vue,@vueuse/core,radix-vue,nuxt,shadcn-vue,shadcn-nuxt,unplugin-auto-import --binaries --browsers`
|
||||
render: bash
|
||||
placeholder: System, Binaries, Browsers
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: contributes
|
||||
attributes:
|
||||
label: Conext & Screenshots (if applicable)
|
||||
description: |
|
||||
If applicable, provide any additional context or screenshots of the bug.
|
||||
You can drag and drop images here to add them to the issue.
|
||||
label: Contributes
|
||||
options:
|
||||
- label: I am willing to submit a PR to fix this issue
|
||||
- label: I am willing to submit a PR with failing tests
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@ import { defineConfig } from 'vitepress'
|
|||
import Icons from 'unplugin-icons/vite'
|
||||
import tailwind from 'tailwindcss'
|
||||
import autoprefixer from 'autoprefixer'
|
||||
import { createCssVariablesTheme } from 'shikiji'
|
||||
import { createCssVariablesTheme } from 'shiki'
|
||||
|
||||
// import { transformerMetaWordHighlight, transformerNotationWordHighlight } from '@shikijs/transformers'
|
||||
import { siteConfig } from './theme/config/site'
|
||||
import ComponentPreviewPlugin from './theme/plugins/previewer'
|
||||
|
||||
const cssVariables = createCssVariablesTheme({
|
||||
name: 'css-variables',
|
||||
variablePrefix: '--shiki-',
|
||||
variableDefaults: {},
|
||||
fontStyle: true,
|
||||
})
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
|
|
@ -59,6 +59,10 @@ export default defineConfig({
|
|||
srcDir: path.resolve(__dirname, '../src'),
|
||||
markdown: {
|
||||
theme: cssVariables,
|
||||
codeTransformers: [
|
||||
// transformerMetaWordHighlight(),
|
||||
// transformerNotationWordHighlight(),
|
||||
],
|
||||
config(md) {
|
||||
md.use(ComponentPreviewPlugin)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -299,6 +299,12 @@ export const docsConfig: DocsConfig = {
|
|||
href: '/docs/components/slider',
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
title: 'Sonner',
|
||||
href: '/docs/components/sonner',
|
||||
label: 'New',
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
title: 'Switch',
|
||||
href: '/docs/components/switch',
|
||||
|
|
@ -322,7 +328,6 @@ export const docsConfig: DocsConfig = {
|
|||
{
|
||||
title: 'Toast',
|
||||
href: '/docs/components/toast',
|
||||
label: 'New',
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import EditLink from '../components/EditLink.vue'
|
|||
import { ScrollArea } from '@/lib/registry/default/ui/scroll-area'
|
||||
import { Badge } from '@/lib/registry/default/ui/badge'
|
||||
import RadixIconsCode from '~icons/radix-icons/code'
|
||||
import RadixIconsExternalLink from '~icons/radix-icons/external-link'
|
||||
import ChevronRightIcon from '~icons/lucide/chevron-right'
|
||||
|
||||
const $route = useRoute()
|
||||
|
|
@ -20,7 +21,7 @@ const sourceLink = 'https://github.com/radix-vue/shadcn-vue/tree/dev/'
|
|||
<aside
|
||||
class="fixed top-14 z-30 -ml-2 hidden h-[calc(100vh-3.5rem)] w-full shrink-0 md:sticky md:block overflow-y-auto"
|
||||
>
|
||||
<ScrollArea orientation="vertical" class="h-full py-6 pl-8 pr-6 lg:py-8" :type="'auto'">
|
||||
<ScrollArea orientation="vertical" class="relative overflow-hidden h-full py-6 pr-6 lg:py-8" :type="'auto'">
|
||||
<div class="w-full">
|
||||
<div v-for="docsGroup in docsConfig.sidebarNav" :key="docsGroup.title" class="pb-4">
|
||||
<h4
|
||||
|
|
@ -45,9 +46,9 @@ const sourceLink = 'https://github.com/radix-vue/shadcn-vue/tree/dev/'
|
|||
>
|
||||
{{ doc.title }}
|
||||
|
||||
<Badge v-if="doc.label" class="ml-2" :variant="'secondary'">
|
||||
<span v-if="doc.label" class="ml-2 rounded-md bg-[#adfa1d] px-1.5 py-0.5 text-xs leading-none text-[#000000] no-underline group-hover:no-underline">
|
||||
{{ doc.label }}
|
||||
</Badge>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -81,6 +82,10 @@ const sourceLink = 'https://github.com/radix-vue/shadcn-vue/tree/dev/'
|
|||
</div>
|
||||
|
||||
<div class="flex items-center space-x-2 pt-4">
|
||||
<a v-if="frontmatter.docs" :href="frontmatter.docs" target="_blank" class="inline-flex items-center rounded-md 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 select-none border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80">
|
||||
<RadixIconsExternalLink class="mr-1" />
|
||||
Docs
|
||||
</a>
|
||||
<a v-if="frontmatter.source" :href="sourceLink + frontmatter.source" target="_blank" class="inline-flex items-center rounded-md 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 select-none border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80">
|
||||
<RadixIconsCode class="mr-1" />
|
||||
Component Source
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import RadixIconsSun from '~icons/radix-icons/sun'
|
|||
import { useConfigStore } from '@/stores/config'
|
||||
import { Dialog, DialogContent } from '@/lib/registry/default/ui/dialog'
|
||||
import { Toaster as DefaultToaster } from '@/lib/registry/default/ui/toast'
|
||||
import { Toaster as NewYorkSonner } from '@/lib/registry/new-york/ui/sonner'
|
||||
import { Toaster as NewYorkToaster } from '@/lib/registry/new-york/ui/toast'
|
||||
|
||||
import File from '~icons/radix-icons/file'
|
||||
|
|
@ -86,7 +87,7 @@ watch(() => $route.path, (n) => {
|
|||
<div 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 items-center"
|
||||
class="container flex justify-between h-14 max-w-screen-2xl items-center"
|
||||
>
|
||||
<MobileNav />
|
||||
|
||||
|
|
@ -287,6 +288,9 @@ watch(() => $route.path, (n) => {
|
|||
</DialogContent>
|
||||
</Dialog>
|
||||
<DefaultToaster />
|
||||
<ClientOnly>
|
||||
<NewYorkSonner :theme="isDark ? 'dark' : 'light'" />
|
||||
</ClientOnly>
|
||||
<NewYorkToaster />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -5,49 +5,49 @@
|
|||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 240 10% 3.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 240 10% 3.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 240 10% 3.9%;
|
||||
--primary: 240 5.9% 10%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 240 4.8% 95.9%;
|
||||
--secondary-foreground: 240 5.9% 10%;
|
||||
--muted: 240 4.8% 95.9%;
|
||||
--muted-foreground: 240 3.8% 46.1%;
|
||||
--accent: 240 4.8% 95.9%;
|
||||
--accent-foreground: 240 5.9% 10%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 240 5.9% 90%;
|
||||
--input: 240 5.9% 90%;
|
||||
--ring: 240 5% 64.9%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 240 10% 3.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 240 10% 3.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 240 10% 3.9%;
|
||||
--primary: 240 5.9% 10%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 240 4.8% 95.9%;
|
||||
--secondary-foreground: 240 5.9% 10%;
|
||||
--muted: 240 4.8% 95.9%;
|
||||
--muted-foreground: 240 3.8% 46.1%;
|
||||
--accent: 240 4.8% 95.9%;
|
||||
--accent-foreground: 240 5.9% 10%;
|
||||
--destructive: 0 72.22% 50.59%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 240 5.9% 90%;
|
||||
--input: 240 5.9% 90%;
|
||||
--ring: 240 5% 64.9%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 240 10% 3.9%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 240 10% 3.9%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 240 10% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 0% 98%;
|
||||
--primary-foreground: 240 5.9% 10%;
|
||||
--secondary: 240 3.7% 15.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 240 3.7% 15.9%;
|
||||
--muted-foreground: 240 5% 64.9%;
|
||||
--accent: 240 3.7% 15.9%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 85.7% 97.3%;
|
||||
--border: 240 3.7% 15.9%;
|
||||
--input: 240 3.7% 15.9%;
|
||||
--ring: 240 4.9% 83.9%;
|
||||
}
|
||||
.dark {
|
||||
--background: 240 10% 3.9%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 240 10% 3.9%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 240 10% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 0% 98%;
|
||||
--primary-foreground: 240 5.9% 10%;
|
||||
--secondary: 240 3.7% 15.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 240 3.7% 15.9%;
|
||||
--muted-foreground: 240 5% 64.9%;
|
||||
--accent: 240 3.7% 15.9%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 85.7% 97.3%;
|
||||
--border: 240 3.7% 15.9%;
|
||||
--input: 240 3.7% 15.9%;
|
||||
--ring: 240 4.9% 83.9%;
|
||||
}
|
||||
|
||||
|
||||
* {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
:root {
|
||||
--shiki-foreground: #EEEEEE;
|
||||
--shiki-foreground: #FFF8;
|
||||
--shiki-color-background: #ffffff;
|
||||
--shiki-token-constant: #ffffff;
|
||||
--shiki-token-string: #ffffff88;
|
||||
|
|
@ -7,7 +7,14 @@
|
|||
--shiki-token-keyword: #ffffff88;
|
||||
--shiki-token-parameter: #AA0000;
|
||||
--shiki-token-function: #ffffff;
|
||||
--shiki-token-string-expression: #ffffff88;
|
||||
--shiki-token-string-expression: #ebebeb;
|
||||
--shiki-token-punctuation: #ffffff;
|
||||
--shiki-token-link: #EE0000;
|
||||
}
|
||||
|
||||
.shiki .highlighted-word {
|
||||
border-radius: calc(var(--radius) - 2px);
|
||||
border-color: rgba(63,63,70,.7);
|
||||
background-color: rgba(63,63,70,.5);
|
||||
padding: 0.25rem;
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E");
|
||||
--vp-code-bg: hsl(var(--muted));
|
||||
--vp-c-divider: hsl(var(--muted));
|
||||
--vp-code-block-color: #fff
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -414,7 +415,7 @@
|
|||
|
||||
.vp-doc div[class*='language-'].line-numbers-mode {
|
||||
/*rtl:ignore*/
|
||||
padding-left: 32px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.vp-doc .line-numbers-wrapper {
|
||||
|
|
@ -566,4 +567,12 @@
|
|||
|
||||
.vp-external-link-icon::after {
|
||||
content: '';
|
||||
}
|
||||
|
||||
.vp-doc [class*=language-] code {
|
||||
color: var(--vp-code-block-color);
|
||||
}
|
||||
|
||||
.line-numbers-mode pre code .line {
|
||||
padding-left: 3rem !important;
|
||||
}
|
||||
|
|
@ -506,6 +506,13 @@ export const Index = {
|
|||
component: () => import('../src/lib/registry/default/example/RadioGroupForm.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/default/example/RadioGroupForm.vue'],
|
||||
},
|
||||
RangePickerWithSlot: {
|
||||
name: 'RangePickerWithSlot',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['utils', 'button', 'calendar', 'popover'],
|
||||
component: () => import('../src/lib/registry/default/example/RangePickerWithSlot.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/default/example/RangePickerWithSlot.vue'],
|
||||
},
|
||||
ScrollAreaDemo: {
|
||||
name: 'ScrollAreaDemo',
|
||||
type: 'components:example',
|
||||
|
|
@ -569,6 +576,13 @@ export const Index = {
|
|||
component: () => import('../src/lib/registry/default/example/SliderDemo.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/default/example/SliderDemo.vue'],
|
||||
},
|
||||
SonnerDemo: {
|
||||
name: 'SonnerDemo',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['button'],
|
||||
component: () => import('../src/lib/registry/default/example/SonnerDemo.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/default/example/SonnerDemo.vue'],
|
||||
},
|
||||
SwitchDemo: {
|
||||
name: 'SwitchDemo',
|
||||
type: 'components:example',
|
||||
|
|
@ -1390,6 +1404,13 @@ export const Index = {
|
|||
component: () => import('../src/lib/registry/new-york/example/RadioGroupForm.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/new-york/example/RadioGroupForm.vue'],
|
||||
},
|
||||
RangePickerWithSlot: {
|
||||
name: 'RangePickerWithSlot',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['utils', 'button', 'calendar', 'popover'],
|
||||
component: () => import('../src/lib/registry/new-york/example/RangePickerWithSlot.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/new-york/example/RangePickerWithSlot.vue'],
|
||||
},
|
||||
ScrollAreaDemo: {
|
||||
name: 'ScrollAreaDemo',
|
||||
type: 'components:example',
|
||||
|
|
@ -1453,6 +1474,13 @@ export const Index = {
|
|||
component: () => import('../src/lib/registry/new-york/example/SliderDemo.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/new-york/example/SliderDemo.vue'],
|
||||
},
|
||||
SonnerDemo: {
|
||||
name: 'SonnerDemo',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['button'],
|
||||
component: () => import('../src/lib/registry/new-york/example/SonnerDemo.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/new-york/example/SonnerDemo.vue'],
|
||||
},
|
||||
SwitchDemo: {
|
||||
name: 'SwitchDemo',
|
||||
type: 'components:example',
|
||||
|
|
|
|||
|
|
@ -19,24 +19,25 @@
|
|||
"@morev/vue-transitions": "^2.3.6",
|
||||
"@radix-icons/vue": "^1.0.0",
|
||||
"@stackblitz/sdk": "^1.9.0",
|
||||
"@tanstack/vue-table": "^8.11.6",
|
||||
"@unovis/ts": "^1.3.1",
|
||||
"@unovis/vue": "^1.3.1",
|
||||
"@vee-validate/zod": "^4.12.4",
|
||||
"@tanstack/vue-table": "^8.11.8",
|
||||
"@unovis/ts": "^1.3.3",
|
||||
"@unovis/vue": "^1.3.3",
|
||||
"@vee-validate/zod": "^4.12.5",
|
||||
"@vueuse/core": "^10.7.2",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.0",
|
||||
"codesandbox": "^2.2.3",
|
||||
"date-fns": "^2.30.0",
|
||||
"embla-carousel": "8.0.0-rc19",
|
||||
"embla-carousel-autoplay": "8.0.0-rc19",
|
||||
"embla-carousel-vue": "8.0.0-rc19",
|
||||
"embla-carousel": "^8.0.0-rc22",
|
||||
"embla-carousel-autoplay": "^8.0.0-rc22",
|
||||
"embla-carousel-vue": "^8.0.0-rc22",
|
||||
"lucide-vue-next": "^0.276.0",
|
||||
"radix-vue": "^1.3.2",
|
||||
"radix-vue": "^1.4.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"v-calendar": "^3.1.2",
|
||||
"vee-validate": "4.12.4",
|
||||
"vue": "^3.4.14",
|
||||
"vee-validate": "4.12.5",
|
||||
"vue": "^3.4.15",
|
||||
"vue-sonner": "^1.0.3",
|
||||
"vue-wrap-balancer": "^1.1.3",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
|
|
@ -45,26 +46,27 @@
|
|||
"@iconify-json/tabler": "^1.1.89",
|
||||
"@iconify/json": "^2.2.108",
|
||||
"@iconify/vue": "^4.1.1",
|
||||
"@shikijs/transformers": "^1.0.0-beta.3",
|
||||
"@types/lodash.template": "^4.5.2",
|
||||
"@types/node": "^20.8.10",
|
||||
"@vitejs/plugin-vue": "^5.0.3",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"@vue/compiler-core": "^3.4.14",
|
||||
"@vue/compiler-dom": "^3.4.14",
|
||||
"@vue/compiler-core": "^3.4.15",
|
||||
"@vue/compiler-dom": "^3.4.15",
|
||||
"@vue/tsconfig": "^0.5.1",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"lodash.template": "^4.5.0",
|
||||
"oxc-parser": "^0.2.0",
|
||||
"pathe": "^1.1.2",
|
||||
"rimraf": "^5.0.5",
|
||||
"shikiji": "^0.10.0-beta.2",
|
||||
"tailwind-merge": "^2.2.0",
|
||||
"shiki": "^1.0.0-beta.3",
|
||||
"tailwind-merge": "^2.2.1",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"tsx": "^4.7.0",
|
||||
"typescript": "^5.3.3",
|
||||
"unplugin-icons": "^0.17.1",
|
||||
"vite": "^5.0.11",
|
||||
"vitepress": "^1.0.0-rc.37",
|
||||
"unplugin-icons": "^0.18.3",
|
||||
"vite": "^5.0.12",
|
||||
"vitepress": "^1.0.0-rc.41",
|
||||
"vue-tsc": "^1.8.27"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,5 +56,40 @@ import { Calendar } from '@/components/ui/calendar'
|
|||
</template>
|
||||
```
|
||||
|
||||
See the [VCalendar](https://vcalendar.io/getting-started/installation.html) documentation for more information.
|
||||
The API is essentially the same, i.e. props and slots. See the [VCalendar](https://vcalendar.io/getting-started/installation.html) documentation for more information.
|
||||
|
||||
### Slots
|
||||
|
||||
The slots available are [those currently supported](https://github.com/nathanreyes/v-calendar/blob/v3.1.2/src/components/Calendar/CalendarSlot.vue#L16-L28) by VCalendar, namely :
|
||||
|
||||
- `day-content`
|
||||
- `day-popover`
|
||||
- `dp-footer`
|
||||
- `footer`
|
||||
- `header-title-wrapper`
|
||||
- `header-title`
|
||||
- `header-prev-button`
|
||||
- `header-next-button`
|
||||
- `nav`
|
||||
- `nav-prev-button`
|
||||
- `nav-next-button`
|
||||
- `page`
|
||||
- `time-header`
|
||||
|
||||
Example using the `day-content` slot:
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { Calendar } from '@/components/ui/calendar'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Calendar>
|
||||
<template #day-content="{ day, dayProps, dayEvents }">
|
||||
<div v-bind="dayProps" v-on="dayEvents">
|
||||
{{ day.label }}
|
||||
</div>
|
||||
</template>
|
||||
</Calendar>
|
||||
</template>
|
||||
```
|
||||
|
|
@ -57,7 +57,7 @@ To set the size of the items, you can use the `basis` utility class on the `<Car
|
|||
|
||||
Example
|
||||
|
||||
```vue title="Example" showLineNumbers {4-6}
|
||||
```vue:line-numbers title="Example" {4-6}
|
||||
// 33% of the carousel width.
|
||||
<Carousel>
|
||||
<CarouselContent>
|
||||
|
|
@ -71,7 +71,7 @@ Example
|
|||
|
||||
Responsive
|
||||
|
||||
```vue title="Responsive" showLineNumbers {4-6}
|
||||
```vue:line-numbers title="Responsive" {4-6}
|
||||
// 50% on small screens and 33% on larger screens.
|
||||
<Carousel>
|
||||
<CarouselContent>
|
||||
|
|
@ -101,7 +101,7 @@ You can always adjust this in your own project if you need to.
|
|||
|
||||
Example
|
||||
|
||||
```vue showLineNumbers /-ml-4/ /pl-4/
|
||||
```vue:line-numbers /-ml-4/ /pl-4/
|
||||
<template>
|
||||
<Carousel>
|
||||
<CarouselContent class="-ml-4">
|
||||
|
|
@ -121,7 +121,7 @@ Example
|
|||
|
||||
Responsive
|
||||
|
||||
```vue showLineNumbers /-ml-2/ /pl-2/ /md:-ml-4/ /md:pl-4/
|
||||
```vue:line-numbers /-ml-2/ /pl-2/ /md:-ml-4/ /md:pl-4/
|
||||
<template>
|
||||
<Carousel>
|
||||
<CarouselContent class="-ml-2 md:-ml-4">
|
||||
|
|
@ -155,7 +155,7 @@ Use the `orientation` prop to set the orientation of the carousel.
|
|||
|
||||
You can pass options to the carousel using the `opts` prop. See the [Embla Carousel docs](https://www.embla-carousel.com/api/options/) for more information.
|
||||
|
||||
```vue showLineNumbers {3-6}
|
||||
```vue:line-numbers {3-6}
|
||||
<template>
|
||||
<Carousel
|
||||
:opts="{
|
||||
|
|
@ -184,7 +184,7 @@ Use the `@init-api` emit method on `<Carousel />` component to set the instance
|
|||
|
||||
You can access it through setting a template ref on the `<Carousel />` component.
|
||||
|
||||
```vue showLineNumbers {2,5,9}
|
||||
```vue:line-numbers {2,5,9}
|
||||
<script setup>
|
||||
const carouselContainerRef = ref<InstanceType<typeof Carousel> | null>(null)
|
||||
|
||||
|
|
@ -204,7 +204,7 @@ function accessApi() {
|
|||
|
||||
You can listen to events using the API. To get the API instance use the `@init-api` emit method on the `<Carousel />` component
|
||||
|
||||
```vue showLineNumbers {5,7-9,25}
|
||||
```vue:line-numbers {5,7-9,25}
|
||||
<script setup>
|
||||
import { nextTick, ref, watch } from 'vue'
|
||||
import { useCarousel } from '@/components/ui/carousel'
|
||||
|
|
@ -241,7 +241,7 @@ See the [Embla Carousel docs](https://www.embla-carousel.com/api/events/) for mo
|
|||
|
||||
You can get the reactive slot props like `carouselRef, canScrollNext..Prev, scrollNext..Prev` using the `v-slot` directive in the `<Carousel v-slot="slotProps" />` component to extend the functionality.
|
||||
|
||||
```vue showLineNumbers {2}
|
||||
```vue:line-numbers {2}
|
||||
<template>
|
||||
<Carousel v-slot="{ canScrollNext, canScrollPrev }">
|
||||
...
|
||||
|
|
@ -260,7 +260,7 @@ npm i embla-carousel-autoplay
|
|||
```
|
||||
|
||||
|
||||
```vue showLineNumbers {2,8-10}
|
||||
```vue:line-numbers {2,8-10}
|
||||
<script setup lang="ts">
|
||||
import Autoplay from 'embla-carousel-autoplay'
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ We'll start with the basic `<Table />` component and build a complex data table
|
|||
|
||||
## Table of Contents
|
||||
|
||||
This guide will show you how to use [TanStack Table](https://tanstack.com/table/v8) and the <Table /> component to build your own custom data table. We'll cover the following topics:
|
||||
This guide will show you how to use [TanStack Table](https://tanstack.com/table/v8) and the `<Table />` component to build your own custom data table. We'll cover the following topics:
|
||||
|
||||
- [Basic Table](#basic-table)
|
||||
- [Row Actions](#row-actions)
|
||||
|
|
@ -109,31 +109,23 @@ Let's start by building a basic table.
|
|||
|
||||
First, we'll define our columns in the `columns.ts` file.
|
||||
|
||||
```ts:line-numbers title="components/payments/columns.ts" {1,12-27}
|
||||
import type { ColumnDef } from '@tanstack/vue-table'
|
||||
|
||||
// This type is used to define the shape of our data.
|
||||
// You can use a Zod schema here if you want.
|
||||
export interface Payment {
|
||||
id: string
|
||||
amount: number
|
||||
status: 'pending' | 'processing' | 'success' | 'failed'
|
||||
email: string
|
||||
}
|
||||
```ts:line-numbers {1,12-27}
|
||||
import { h } from 'vue'
|
||||
|
||||
export const columns: ColumnDef<Payment>[] = [
|
||||
{
|
||||
accessorKey: 'status',
|
||||
header: 'Status',
|
||||
},
|
||||
{
|
||||
accessorKey: 'email',
|
||||
header: 'Email',
|
||||
},
|
||||
{
|
||||
accessorKey: 'amount',
|
||||
header: 'Amount',
|
||||
},
|
||||
header: () => h('div', { class: 'text-right' }, 'Amount'),
|
||||
cell: ({ row }) => {
|
||||
const amount = Number.parseFloat(row.getValue('amount'))
|
||||
const formatted = new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: 'USD',
|
||||
}).format(amount)
|
||||
|
||||
return h('div', { class: 'text-right font-medium' }, formatted)
|
||||
},
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
|
|
@ -149,7 +141,7 @@ formatted, sorted and filtered.
|
|||
|
||||
Next, we'll create a `<DataTable />` component to render our table.
|
||||
|
||||
```ts:line-numbers
|
||||
```vue:line-numbers
|
||||
<script setup lang="ts" generic="TData, TValue">
|
||||
import type { ColumnDef } from '@tanstack/vue-table'
|
||||
import {
|
||||
|
|
@ -225,7 +217,7 @@ const table = useVueTable({
|
|||
|
||||
Finally, we'll render our table in our index component.
|
||||
|
||||
```ts:line-numbers showLineNumbers{28}
|
||||
```vue:line-numbers {28}
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { columns } from "./components/columns"
|
||||
|
|
@ -272,7 +264,7 @@ Let's format the amount cell to display the dollar amount. We'll also align the
|
|||
Update the `header` and `cell` definitions for amount as follows:
|
||||
|
||||
|
||||
```ts:line-numbers showLineNumbers title="components/payments/columns.ts" {5-17}
|
||||
```ts:line-numbers title="components/payments/columns.ts" {5-17}
|
||||
import { h } from 'vue'
|
||||
|
||||
export const columns: ColumnDef<Payment>[] = [
|
||||
|
|
@ -302,7 +294,7 @@ Let's add row actions to our table. We'll use a `<Dropdown />` component for thi
|
|||
|
||||
### Add the following into your `DataTableDropDown.vue` component:
|
||||
|
||||
```ts:line-numbers
|
||||
```vue:line-numbers
|
||||
// DataTableDropDown.vue
|
||||
<script setup lang="ts">
|
||||
import { MoreHorizontal } from 'lucide-vue-next'
|
||||
|
|
@ -380,7 +372,7 @@ Next, we'll add pagination to our table.
|
|||
|
||||
### Update `<DataTable>`
|
||||
|
||||
```ts:line-numbers showLineNumbers{4,12}
|
||||
```ts:line-numbers {4,12}
|
||||
import {
|
||||
FlexRender,
|
||||
getCoreRowModel,
|
||||
|
|
@ -402,8 +394,7 @@ This will automatically paginate your rows into pages of 10. See the [pagination
|
|||
|
||||
We can add pagination controls to our table using the `<Button />` component and the `table.previousPage()`, `table.nextPage()` API methods.
|
||||
|
||||
```ts:line-numbers showLineNumbers{3,15,21-39}
|
||||
// components/payments/DataTable.vue
|
||||
```vue:line-numbers {3,15,21-39}
|
||||
<script lang="ts" generic="TData, TValue">
|
||||
import { Button } from "@/components/ui/button"
|
||||
|
||||
|
|
@ -458,7 +449,7 @@ Let's make the email column sortable.
|
|||
|
||||
### Add the following into your `utils` file:
|
||||
|
||||
```ts:line-numbers showLineNumbers{5,6,12-17}
|
||||
```ts:line-numbers {5,6,12-17}
|
||||
import { type ClassValue, clsx } from 'clsx'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { camelize, getCurrentInstance, toHandlerKey } from 'vue'
|
||||
|
|
@ -482,7 +473,7 @@ The `valueUpdater` function updates a Vue `ref` object's value. It handles both
|
|||
|
||||
### Update `<DataTable>`
|
||||
|
||||
```ts:line-numbers showLineNumbers{4,7,16,34,41-44}
|
||||
```vue:line-numbers {4,7,16,34,41-44}
|
||||
<script setup lang="ts" generic="TData, TValue">
|
||||
import type {
|
||||
ColumnDef,
|
||||
|
|
@ -545,7 +536,7 @@ const table = useVueTable({
|
|||
|
||||
We can now update the `email` header cell to add sorting controls.
|
||||
|
||||
```ts:line-numbers showLineNumbers{5,10-17}
|
||||
```ts:line-numbers {5,10-17}
|
||||
// components/payments/columns.ts
|
||||
import type {
|
||||
ColumnDef,
|
||||
|
|
@ -579,7 +570,7 @@ Let's add a search input to filter emails in our table.
|
|||
|
||||
### Update `<DataTable>`
|
||||
|
||||
```ts:line-numbers showLineNumbers{4,11,19,39,48-49,52,60-64}
|
||||
```vue:line-numbers {4,11,19,39,48-49,52,60-64}
|
||||
<script setup lang="ts" generic="TData, TValue">
|
||||
import type {
|
||||
ColumnDef,
|
||||
|
|
@ -664,7 +655,7 @@ Adding column visibility is fairly simple using `@tanstack/vue-table` visibility
|
|||
|
||||
### Update `<DataTable>`
|
||||
|
||||
```ts:line-numbers showLineNumbers{6,9-14,48,59,63,75-91}
|
||||
```vue:line-numbers {6,9-14,48,59,63,75-91}
|
||||
<script setup lang="ts" generic="TData, TValue">
|
||||
import type {
|
||||
ColumnDef,
|
||||
|
|
@ -803,7 +794,7 @@ Next, we're going to add row selection to our table.
|
|||
|
||||
### Update column definitions
|
||||
|
||||
```ts:line-numbers showLineNumbers{3,6-20}
|
||||
```ts:line-numbers {3,6-20}
|
||||
import type { ColumnDef } from '@tanstack/vue-table'
|
||||
|
||||
import { Checkbox } from '@/components/ui/checkbox'
|
||||
|
|
@ -829,7 +820,7 @@ export const columns: ColumnDef<Payment>[] = [
|
|||
|
||||
### Update `<DataTable>`
|
||||
|
||||
```ts:line-numbers showLineNumbers{10,22,27}
|
||||
```vue:line-numbers {10,22,27}
|
||||
<script setup lang="ts" generic="TData, TValue">
|
||||
const props = defineProps<{
|
||||
columns: ColumnDef<TData, TValue>[]
|
||||
|
|
@ -895,7 +886,7 @@ Here are some components you can use to build your data tables. This is from the
|
|||
|
||||
Make any column header sortable and hideable.
|
||||
|
||||
```ts:line-numbers
|
||||
```vue:line-numbers
|
||||
<script setup lang="ts">
|
||||
import type { Column } from '@tanstack/vue-table'
|
||||
import { type Task } from '../data/schema'
|
||||
|
|
@ -988,7 +979,7 @@ export const columns = [
|
|||
|
||||
Add pagination controls to your table including page size and selection count.
|
||||
|
||||
```ts:line-numbers
|
||||
```vue:line-numbers
|
||||
<script setup lang="ts">
|
||||
import { type Table } from '@tanstack/vue-table'
|
||||
import { type Task } from '../data/schema'
|
||||
|
|
@ -1093,8 +1084,7 @@ defineProps<DataTablePaginationProps>()
|
|||
|
||||
A component to toggle column visibility.
|
||||
|
||||
```ts:line-numbers
|
||||
|
||||
```vue:line-numbers
|
||||
<script setup lang="ts">
|
||||
import type { Table } from '@tanstack/vue-table'
|
||||
import { computed } from 'vue'
|
||||
|
|
|
|||
|
|
@ -72,6 +72,10 @@ const date = ref<Date>()
|
|||
|
||||
<ComponentPreview name="DatePickerWithPresets" />
|
||||
|
||||
### With Slot
|
||||
|
||||
<ComponentPreview name="RangePickerWithSlot" />
|
||||
|
||||
### Form
|
||||
|
||||
<ComponentPreview name="DatePickerForm" />
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ Use `@vee-validate/zod` to integrate Zod schema validation with `vee-validate`
|
|||
|
||||
`toTypedSchema` also makes the form values and submitted values typed automatically and caters for both input and output types of that schema.
|
||||
|
||||
```vue showLineNumbers {2-3,5-7}
|
||||
```vue:line-numbers {2-3,5-7}
|
||||
<script setup lang="ts">
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import * as z from 'zod'
|
||||
|
|
@ -179,7 +179,7 @@ Use the `useForm` composable from `vee-validate` or use `<Form />` component to
|
|||
<TabPreview name="Composition" :names="['Composition', 'Component']">
|
||||
<template #Composition>
|
||||
|
||||
```vue showLineNumbers {2,19-21}
|
||||
```vue:line-numbers {2,19-21}
|
||||
<script setup lang="ts">
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
|
|
@ -218,7 +218,7 @@ const onSubmit = form.handleSubmit((values) => {
|
|||
|
||||
<template #Component>
|
||||
|
||||
```vue showLineNumbers {5,24-26}
|
||||
```vue:line-numbers {5,24-26}
|
||||
<script setup lang="ts">
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import * as z from 'zod'
|
||||
|
|
@ -256,7 +256,7 @@ function onSubmit(values) {
|
|||
Based on last step we can either use `<Form />` component or `useForm` composable
|
||||
`useForm` is recommended cause values are typed automatically
|
||||
|
||||
```vue showLineNumbers {2}
|
||||
```vue:line-numbers {2}
|
||||
<script setup lang="ts">
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ import {
|
|||
|
||||
### Link Component
|
||||
|
||||
When using the Nuxt.js <NuxtLink /> component, you can use `navigationMenuTriggerStyle()` to apply the correct styles to the trigger.
|
||||
When using the Nuxt.js `<NuxtLink />` component, you can use `navigationMenuTriggerStyle()` to apply the correct styles to the trigger.
|
||||
|
||||
```ts
|
||||
import { navigationMenuTriggerStyle } from '@/components/ui/navigation-menu'
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ Use the `side` property to `<SheetContent />` to indicate the edge of the screen
|
|||
|
||||
You can adjust the size of the sheet using CSS classes:
|
||||
|
||||
```vue:line-numbers showLineNumbers{4}
|
||||
```vue:line-numbers {4}
|
||||
<template>
|
||||
<Sheet>
|
||||
<SheetTrigger>Open</SheetTrigger>
|
||||
|
|
|
|||
63
apps/www/src/content/docs/components/sonner.md
Normal file
63
apps/www/src/content/docs/components/sonner.md
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
title: Sonner
|
||||
description: An opinionated toast component for Vue.
|
||||
docs: https://vue-sonner.vercel.app
|
||||
source: apps/www/src/lib/registry/default/ui/sonner
|
||||
---
|
||||
|
||||
<ComponentPreview name="SonnerDemo" />
|
||||
|
||||
## About
|
||||
|
||||
The Sonner component is provided by [vue-sonner](https://vue-sonner.vercel.app/), which is a Vue port of Sonner, originally created by [Emil Kowalski](https://twitter.com/emilkowalski_) for React.
|
||||
|
||||
## Installation
|
||||
|
||||
<Steps>
|
||||
|
||||
### Run the following command
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add sonner
|
||||
```
|
||||
|
||||
### Add the Toaster component
|
||||
|
||||
Add the following `Toaster` component to your `App.vue` file:
|
||||
|
||||
```vue title="App.vue" {2,6}
|
||||
<script setup lang="ts">
|
||||
import { Toaster } from '@/components/ui/sonner'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Toaster />
|
||||
</template>
|
||||
```
|
||||
|
||||
</Steps>
|
||||
|
||||
## Usage
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { toast } from 'vue-sonner'
|
||||
import { Button } from '@/components/ui/button'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Button
|
||||
variant="outline" @click="() => {
|
||||
toast('Event has been created', {
|
||||
description: 'Sunday, December 03, 2023 at 9:00 AM',
|
||||
action: {
|
||||
label: 'Undo',
|
||||
onClick: () => console.log('Undo'),
|
||||
},
|
||||
})
|
||||
}"
|
||||
>
|
||||
Add to calander
|
||||
</Button>
|
||||
</template>
|
||||
```
|
||||
|
|
@ -17,7 +17,7 @@ npm create astro@latest
|
|||
|
||||
You will be asked a few questions to configure your project:
|
||||
|
||||
```txt showLineNumbers
|
||||
```txt:line-numbers
|
||||
- Where should we create your new project?
|
||||
./your-app-name
|
||||
- How would you like to start your new project?
|
||||
|
|
@ -76,7 +76,7 @@ This will install `tailwindcss` and `@astrojs/tailwind` as dependencies and set
|
|||
|
||||
Add the code below to the tsconfig.json file to resolve paths:
|
||||
|
||||
```json {2-7} showLineNumbers
|
||||
```json:line-numbers {2-7}
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
|
|
@ -99,7 +99,7 @@ npx shadcn-vue@latest init
|
|||
|
||||
You will be asked a few questions to configure `components.json`:
|
||||
|
||||
```txt showLineNumbers
|
||||
```txt:line-numbers
|
||||
Would you like to use TypeScript (recommended)? no / yes
|
||||
Which framework are you using? Astro
|
||||
Which style would you like to use? › Default
|
||||
|
|
@ -116,15 +116,17 @@ Write configuration to components.json. Proceed? > Y/n
|
|||
|
||||
Import the `globals.css` file in the `src/index.astro` file:
|
||||
|
||||
```ts {2} showLineNumbers
|
||||
```ts:line-numbers {2}
|
||||
---
|
||||
import '@/styles/globals.css'
|
||||
---
|
||||
```
|
||||
|
||||
### Update astro tailwind config
|
||||
|
||||
To prevent serving the Tailwind base styles twice, we need to tell Astro not to apply the base styles, since we already include them in our own `globals.css` file. To do this, set the `applyBaseStyles` config option for the tailwind plugin in `astro.config.mjs` to `false`.
|
||||
|
||||
```ts {3-5} showLineNumbers
|
||||
```ts:line-numbers {3-5}
|
||||
export default defineConfig({
|
||||
integrations: [
|
||||
tailwind({
|
||||
|
|
@ -144,7 +146,7 @@ npx shadcn-vue@latest add button
|
|||
|
||||
The command above will add the `Button` component to your project. You can then import it like this:
|
||||
|
||||
```astro {2,10} showLineNumbers
|
||||
```astro:line-numbers {2,10}
|
||||
---
|
||||
import { Button } from "@/components/ui/button"
|
||||
---
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ npx shadcn-vue@latest init
|
|||
|
||||
You will be asked a few questions to configure `components.json`:
|
||||
|
||||
```txt showLineNumbers
|
||||
```txt:line-numbers
|
||||
Would you like to use TypeScript (recommended)? no / yes
|
||||
Which framework are you using? Vite / Nuxt / Laravel
|
||||
Which style would you like to use? › Default
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ npx shadcn-vue@latest init
|
|||
|
||||
You will be asked a few questions to configure `components.json`:
|
||||
|
||||
```txt showLineNumbers
|
||||
```txt:line-numbers
|
||||
Would you like to use TypeScript (recommended)? no / yes
|
||||
Which framework are you using? Vite / Nuxt / Laravel
|
||||
Which style would you like to use? › Default
|
||||
|
|
|
|||
|
|
@ -19,13 +19,63 @@ npm create vite@latest my-vue-app -- --template vue-ts
|
|||
|
||||
### Add Tailwind and its configuration
|
||||
|
||||
Install `tailwindcss` and its peer dependencies, then generate your `tailwind.config.js` and `postcss.config.js` files:
|
||||
Install `tailwindcss` and its peer dependencies, then generate your `tailwind.config.js` and configure `postcss` plugins
|
||||
|
||||
```bash
|
||||
npm install -D tailwindcss postcss autoprefixer
|
||||
|
||||
npx tailwindcss init -p
|
||||
```
|
||||
|
||||
<TabsMarkdown>
|
||||
<TabMarkdown title="vite.config.ts">
|
||||
|
||||
Vite already has [`postcss`](https://github.com/vitejs/vite/blob/main/packages/vite/package.json#L78) dependency so you don't have to install it again in your package.json
|
||||
|
||||
```bash
|
||||
npm install -D tailwindcss autoprefixer
|
||||
```
|
||||
|
||||
#### `vite.config`
|
||||
|
||||
```typescript {5,6,10-14}
|
||||
import path from "path"
|
||||
import { defineConfig } from "vite"
|
||||
import vue from "@vitejs/plugin-vue"
|
||||
|
||||
import tailwind from "tailwindcss"
|
||||
import autoprefixer from "autoprefixer"
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
css: {
|
||||
postcss: {
|
||||
plugins: [tailwind(), autoprefixer()],
|
||||
},
|
||||
},
|
||||
resolve: {...}
|
||||
})
|
||||
```
|
||||
|
||||
</TabMarkdown>
|
||||
|
||||
|
||||
<TabMarkdown title="postcss.config.js">
|
||||
|
||||
```bash
|
||||
npm install -D tailwindcss autoprefixer postcss
|
||||
```
|
||||
|
||||
#### `postcss.config.js`
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</TabMarkdown>
|
||||
</TabsMarkdown>
|
||||
|
||||
|
||||
### Edit tsconfig.json
|
||||
|
||||
|
|
@ -42,6 +92,11 @@ Add the code below to the compilerOptions of your tsconfig.json so your app can
|
|||
|
||||
Add the code below to the vite.config.ts so your app can resolve paths without error
|
||||
|
||||
```bash
|
||||
# (so you can import "path" without error)
|
||||
npm i -D @types/node
|
||||
```
|
||||
|
||||
```typescript
|
||||
import path from "path"
|
||||
import vue from "@vitejs/plugin-vue"
|
||||
|
|
@ -69,7 +124,7 @@ npx shadcn-vue@latest init
|
|||
|
||||
You will be asked a few questions to configure `components.json`:
|
||||
|
||||
```txt showLineNumbers
|
||||
```txt:line-numbers
|
||||
Would you like to use TypeScript (recommended)? no / yes
|
||||
Which framework are you using? Vite / Nuxt / Laravel
|
||||
Which style would you like to use? › Default
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ const date = ref({
|
|||
</span>
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="w-auto p-0" :align="'end'" :avoid-collisions="true">
|
||||
<PopoverContent class="w-auto p-0" :align="'end'">
|
||||
<Calendar
|
||||
v-model.range="date"
|
||||
:columns="2"
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ async function onSubmit(values: any) {
|
|||
</FormField>
|
||||
|
||||
<FormField v-slot="{ componentField, value }" name="dob">
|
||||
<FormItem>
|
||||
<FormItem class="flex flex-col">
|
||||
<FormLabel>Date of birth</FormLabel>
|
||||
<Popover>
|
||||
<PopoverTrigger as-child>
|
||||
|
|
@ -123,7 +123,7 @@ async function onSubmit(values: any) {
|
|||
</FormField>
|
||||
|
||||
<FormField v-slot="{ value }" name="language">
|
||||
<FormItem>
|
||||
<FormItem class="flex flex-col">
|
||||
<FormLabel>Language</FormLabel>
|
||||
|
||||
<Popover v-model:open="open">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
<script setup lang='ts'>
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/lib/registry/default/ui/card'
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@/lib/registry/default/ui/card'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
useVueTable,
|
||||
} from '@tanstack/vue-table'
|
||||
import { h, ref } from 'vue'
|
||||
import { CaretSortIcon, ChevronDownIcon } from '@radix-icons/vue'
|
||||
import { ChevronDown, ChevronsUpDown } from 'lucide-vue-next'
|
||||
import DropdownAction from '../DataTableDemoColumn.vue'
|
||||
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
|
|
@ -104,7 +104,7 @@ const columns: ColumnDef<Payment>[] = [
|
|||
return h(Button, {
|
||||
variant: 'ghost',
|
||||
onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'),
|
||||
}, ['Email', h(CaretSortIcon, { class: 'ml-2 h-4 w-4' })])
|
||||
}, ['Email', h(ChevronsUpDown, { class: 'ml-2 h-4 w-4' })])
|
||||
},
|
||||
cell: ({ row }) => h('div', { class: 'lowercase' }, row.getValue('email')),
|
||||
},
|
||||
|
|
@ -179,7 +179,7 @@ const table = useVueTable({
|
|||
<DropdownMenu>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<Button variant="outline" class="ml-auto">
|
||||
Columns <ChevronDownIcon class="ml-2 h-4 w-4" />
|
||||
Columns <ChevronDown class="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { CaretSortIcon, CheckIcon } from '@radix-icons/vue'
|
||||
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
|
|
@ -44,7 +44,7 @@ const value = ref<string>('')
|
|||
{{ value
|
||||
? frameworks.find((framework) => framework.value === value)?.label
|
||||
: "Select framework..." }}
|
||||
<CaretSortIcon class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="w-[200px] p-0">
|
||||
|
|
@ -65,7 +65,7 @@ const value = ref<string>('')
|
|||
}"
|
||||
>
|
||||
{{ framework.label }}
|
||||
<CheckIcon
|
||||
<Check
|
||||
:class="cn(
|
||||
'ml-auto h-4 w-4',
|
||||
value === framework.value ? 'opacity-100' : 'opacity-0',
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ const date = ref({
|
|||
</span>
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="w-auto p-0" align="start" :avoid-collisions="true">
|
||||
<PopoverContent class="w-auto p-0" align="start">
|
||||
<Calendar
|
||||
v-model.range="date"
|
||||
:columns="2"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
<script setup lang="ts">
|
||||
import { addDays, format } from 'date-fns'
|
||||
import { Calendar as CalendarIcon } from 'lucide-vue-next'
|
||||
|
||||
import { ref } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import { Calendar } from '@/lib/registry/default/ui/calendar'
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@/lib/registry/default/ui/popover'
|
||||
|
||||
const date = ref({
|
||||
start: new Date(2022, 0, 20),
|
||||
end: addDays(new Date(2022, 0, 20), 20),
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="cn('grid gap-2', $attrs.class ?? '')">
|
||||
<Popover>
|
||||
<PopoverTrigger as-child>
|
||||
<Button
|
||||
id="date"
|
||||
:variant="'outline'"
|
||||
:class="cn(
|
||||
'w-[300px] justify-start text-left font-normal',
|
||||
!date && 'text-muted-foreground',
|
||||
)"
|
||||
>
|
||||
<CalendarIcon class="mr-2 h-4 w-4" />
|
||||
|
||||
<span>
|
||||
{{ date.start ? (
|
||||
date.end ? `${format(date.start, 'LLL dd, y')} - ${format(date.end, 'LLL dd, y')}`
|
||||
: format(date.start, 'LLL dd, y')
|
||||
) : 'Pick a date' }}
|
||||
</span>
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="w-auto p-0" align="start">
|
||||
<Calendar
|
||||
v-model.range="date"
|
||||
mode="date"
|
||||
:columns="2"
|
||||
>
|
||||
<template #footer>
|
||||
<div class="w-full px-3 pb-3">
|
||||
Entry time
|
||||
<Calendar
|
||||
v-model="date.start"
|
||||
mode="time"
|
||||
hide-time-header
|
||||
/>
|
||||
Exit time
|
||||
<Calendar
|
||||
v-model="date.end"
|
||||
mode="time"
|
||||
hide-time-header
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</Calendar>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
</template>
|
||||
20
apps/www/src/lib/registry/default/example/SonnerDemo.vue
Normal file
20
apps/www/src/lib/registry/default/example/SonnerDemo.vue
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import { toast } from 'vue-sonner'
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Button
|
||||
variant="outline" @click="() => {
|
||||
toast('Event has been created', {
|
||||
description: 'Sunday, December 03, 2023 at 9:00 AM',
|
||||
action: {
|
||||
label: 'Undo',
|
||||
onClick: () => console.log('Undo'),
|
||||
},
|
||||
})
|
||||
}"
|
||||
>
|
||||
Add to calander
|
||||
</Button>
|
||||
</template>
|
||||
|
|
@ -3,15 +3,17 @@ import {
|
|||
AccordionRoot,
|
||||
type AccordionRootEmits,
|
||||
type AccordionRootProps,
|
||||
useEmitAsProps,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue'
|
||||
|
||||
const props = defineProps<AccordionRootProps>()
|
||||
const emits = defineEmits<AccordionRootEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AccordionRoot v-bind="{ ...props, ...useEmitAsProps(emits) }">
|
||||
<AccordionRoot v-bind="forwarded">
|
||||
<slot />
|
||||
</AccordionRoot>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import { AccordionContent, type AccordionContentProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<AccordionContentProps & { class?: string }>()
|
||||
const props = defineProps<AccordionContentProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AccordionContent
|
||||
v-bind="props"
|
||||
:class="
|
||||
cn(
|
||||
'overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
v-bind="delegatedProps"
|
||||
class="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
|
||||
>
|
||||
<div class="pb-4 pt-0">
|
||||
<div :class="cn('pb-4 pt-0', props.class)">
|
||||
<slot />
|
||||
</div>
|
||||
</AccordionContent>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
import { AccordionItem, type AccordionItemProps } from 'radix-vue'
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import { AccordionItem, type AccordionItemProps, useForwardProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<AccordionItemProps & { class?: string }>()
|
||||
const props = defineProps<AccordionItemProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AccordionItem
|
||||
v-bind="props"
|
||||
:class="cn('border-b', props.class ?? '')"
|
||||
v-bind="forwardedProps"
|
||||
:class="cn('border-b', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</AccordionItem>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
AccordionHeader,
|
||||
AccordionTrigger,
|
||||
|
|
@ -7,13 +8,19 @@ import {
|
|||
import { ChevronDown } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<AccordionTriggerProps & { class?: string }>()
|
||||
const props = defineProps<AccordionTriggerProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AccordionHeader class="flex" as="div">
|
||||
<AccordionHeader class="flex">
|
||||
<AccordionTrigger
|
||||
v-bind="props"
|
||||
v-bind="delegatedProps"
|
||||
:class="
|
||||
cn(
|
||||
'flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180',
|
||||
|
|
@ -22,9 +29,11 @@ const props = defineProps<AccordionTriggerProps & { class?: string }>()
|
|||
"
|
||||
>
|
||||
<slot />
|
||||
<ChevronDown
|
||||
class="h-4 w-4 shrink-0 transition-transform duration-200"
|
||||
/>
|
||||
<slot name="icon">
|
||||
<ChevronDown
|
||||
class="h-4 w-4 shrink-0 transition-transform duration-200"
|
||||
/>
|
||||
</slot>
|
||||
</AccordionTrigger>
|
||||
</AccordionHeader>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import { AlertDialogAction, type AlertDialogActionProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { buttonVariants } from '@/lib/registry/default/ui/button'
|
||||
|
||||
const props = defineProps<AlertDialogActionProps>()
|
||||
const props = defineProps<AlertDialogActionProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogAction v-bind="props" :class="cn(buttonVariants(), $attrs.class ?? '')">
|
||||
<AlertDialogAction v-bind="delegatedProps" :class="cn(buttonVariants(), props.class)">
|
||||
<slot />
|
||||
</AlertDialogAction>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import { AlertDialogCancel, type AlertDialogCancelProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { buttonVariants } from '@/lib/registry/default/ui/button'
|
||||
|
||||
const props = defineProps<AlertDialogCancelProps>()
|
||||
const props = defineProps<AlertDialogCancelProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogCancel v-bind="props" :class="cn(buttonVariants({ variant: 'outline' }), 'mt-2 sm:mt-0', $attrs.class ?? '')">
|
||||
<AlertDialogCancel v-bind="delegatedProps" :class="cn(buttonVariants({ variant: 'outline' }), 'mt-2 sm:mt-0', props.class)">
|
||||
<slot />
|
||||
</AlertDialogCancel>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,30 +1,37 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
AlertDialogContent,
|
||||
type AlertDialogContentEmits,
|
||||
type AlertDialogContentProps,
|
||||
AlertDialogOverlay,
|
||||
AlertDialogPortal,
|
||||
useEmitAsProps,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<AlertDialogContentProps & { class?: string }>()
|
||||
const props = defineProps<AlertDialogContentProps & { class?: HTMLAttributes['class'] }>()
|
||||
const emits = defineEmits<AlertDialogContentEmits>()
|
||||
|
||||
const emitsAsProps = useEmitAsProps(emits)
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogPortal>
|
||||
<AlertDialogOverlay
|
||||
class="fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
|
||||
class="fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
|
||||
/>
|
||||
<AlertDialogContent
|
||||
v-bind="{ ...props, ...emitsAsProps }"
|
||||
v-bind="forwarded"
|
||||
:class="
|
||||
cn(
|
||||
'fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border border-border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full',
|
||||
'fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
|
|
|
|||
|
|
@ -1,17 +1,24 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
AlertDialogDescription,
|
||||
type AlertDialogDescriptionProps,
|
||||
} from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<AlertDialogDescriptionProps & { class?: string }>()
|
||||
const props = defineProps<AlertDialogDescriptionProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogDescription
|
||||
:class="cn('text-muted-foreground text-sm', props.class)"
|
||||
:as-child="props.asChild"
|
||||
v-bind="delegatedProps"
|
||||
:class="cn('text-sm text-muted-foreground', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</AlertDialogDescription>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,17 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'flex flex-col space-y-2 sm:space-y-0 mt-3.5 sm:flex-row sm:justify-end sm:space-x-2',
|
||||
'flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-x-2',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="cn('flex flex-col space-y-2 text-center sm:text-left', props.class)"
|
||||
:class="cn('flex flex-col gap-y-2 text-center sm:text-left', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,21 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import { AlertDialogTitle, type AlertDialogTitleProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<AlertDialogTitleProps & { class?: string }>()
|
||||
const props = defineProps<AlertDialogTitleProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AlertDialogTitle
|
||||
:as-child="props.asChild"
|
||||
:class="cn('text-lg text-foreground font-semibold', props.class)"
|
||||
v-bind="delegatedProps"
|
||||
:class="cn('text-lg font-semibold', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</AlertDialogTitle>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
<script setup lang="ts">
|
||||
import { alertVariants } from '.'
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { type AlertVariants, alertVariants } from '.'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface Props {
|
||||
variant?: NonNullable<Parameters<typeof alertVariants>[0]>['variant']
|
||||
class?: string
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
variant?: AlertVariants['variant']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="cn(alertVariants({ variant }), props.class ?? '')">
|
||||
<div :class="cn(alertVariants({ variant }), props.class)" role="alert">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: String,
|
||||
})
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h5 :class="cn('mb-1 font-medium leading-none tracking-tight', $attrs.class ?? '')">
|
||||
<h5 :class="cn('mb-1 font-medium leading-none tracking-tight', props.class)">
|
||||
<slot />
|
||||
</h5>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { cva } from 'class-variance-authority'
|
||||
import { type VariantProps, cva } from 'class-variance-authority'
|
||||
|
||||
export { default as Alert } from './Alert.vue'
|
||||
export { default as AlertTitle } from './AlertTitle.vue'
|
||||
|
|
@ -19,3 +19,5 @@ export const alertVariants = cva(
|
|||
},
|
||||
},
|
||||
)
|
||||
|
||||
export type AlertVariants = VariantProps<typeof alertVariants>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { AvatarRoot } from 'radix-vue'
|
||||
import { avatarVariant } from '.'
|
||||
import { type AvatarVariants, avatarVariant } from '.'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface Props {
|
||||
size?: NonNullable<Parameters<typeof avatarVariant>[0]>['size']
|
||||
shape?: NonNullable<Parameters<typeof avatarVariant>[0]>['shape']
|
||||
class?: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
const props = withDefaults(defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
size?: AvatarVariants['size']
|
||||
shape?: AvatarVariants['shape']
|
||||
}>(), {
|
||||
size: 'sm',
|
||||
shape: 'circle',
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { cva } from 'class-variance-authority'
|
||||
import { type VariantProps, cva } from 'class-variance-authority'
|
||||
|
||||
export { default as Avatar } from './Avatar.vue'
|
||||
export { default as AvatarImage } from './AvatarImage.vue'
|
||||
|
|
@ -20,3 +20,5 @@ export const avatarVariant = cva(
|
|||
},
|
||||
},
|
||||
)
|
||||
|
||||
export type AvatarVariants = VariantProps<typeof avatarVariant>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
<script setup lang="ts">
|
||||
import type { VariantProps } from 'class-variance-authority'
|
||||
import { badgeVariants } from '.'
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { type BadgeVariants, badgeVariants } from '.'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface BadgeVariantProps extends VariantProps<typeof badgeVariants> {}
|
||||
|
||||
interface Props {
|
||||
variant?: BadgeVariantProps['variant']
|
||||
}
|
||||
defineProps<Props>()
|
||||
const props = defineProps<{
|
||||
variant?: BadgeVariants['variant']
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="cn(badgeVariants({ variant }), $attrs.class ?? '')">
|
||||
<div :class="cn(badgeVariants({ variant }), props.class)">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { cva } from 'class-variance-authority'
|
||||
import { type VariantProps, cva } from 'class-variance-authority'
|
||||
|
||||
export { default as Badge } from './Badge.vue'
|
||||
|
||||
|
|
@ -21,3 +21,5 @@ export const badgeVariants = cva(
|
|||
},
|
||||
},
|
||||
)
|
||||
|
||||
export type BadgeVariants = VariantProps<typeof badgeVariants>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,17 @@
|
|||
<script setup lang="ts">
|
||||
import type { VariantProps } from 'class-variance-authority'
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { Primitive, type PrimitiveProps } from 'radix-vue'
|
||||
import { buttonVariants } from '.'
|
||||
import { type ButtonVariants, buttonVariants } from '.'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface ButtonVariantProps extends VariantProps<typeof buttonVariants> {}
|
||||
|
||||
interface Props extends PrimitiveProps {
|
||||
variant?: ButtonVariantProps['variant']
|
||||
size?: ButtonVariantProps['size']
|
||||
variant?: ButtonVariants['variant']
|
||||
size?: ButtonVariants['size']
|
||||
as?: string
|
||||
class?: HTMLAttributes['class']
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
variant: 'default',
|
||||
size: 'default',
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
as: 'button',
|
||||
})
|
||||
</script>
|
||||
|
|
@ -23,7 +20,7 @@ withDefaults(defineProps<Props>(), {
|
|||
<Primitive
|
||||
:as="as"
|
||||
:as-child="asChild"
|
||||
:class="cn(buttonVariants({ variant, size }), $attrs.class ?? '')"
|
||||
:class="cn(buttonVariants({ variant, size }), props.class)"
|
||||
>
|
||||
<slot />
|
||||
</Primitive>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { cva } from 'class-variance-authority'
|
||||
import { type VariantProps, cva } from 'class-variance-authority'
|
||||
|
||||
export { default as Button } from './Button.vue'
|
||||
|
||||
export const buttonVariants = cva(
|
||||
'inline-flex items-center justify-center rounded-md whitespace-nowrap 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',
|
||||
'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',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
|
|
@ -30,3 +30,5 @@ export const buttonVariants = cva(
|
|||
},
|
||||
},
|
||||
)
|
||||
|
||||
export type ButtonVariants = VariantProps<typeof buttonVariants>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
|
||||
import type { Calendar } from 'v-calendar'
|
||||
import { DatePicker } from 'v-calendar'
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
|
||||
import { computed, nextTick, onMounted, ref } from 'vue'
|
||||
import { buttonVariants } from '@/lib/registry/default/ui/button'
|
||||
import { computed, nextTick, onMounted, ref, useSlots } from 'vue'
|
||||
import { isVCalendarSlot } from '.'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { buttonVariants } from '@/lib/registry/default/ui/button'
|
||||
|
||||
/* Extracted from v-calendar */
|
||||
type DatePickerModel = DatePickerDate | DatePickerRangeObject
|
||||
|
|
@ -28,8 +29,7 @@ interface SimpleDateParts {
|
|||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
})
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
const props = withDefaults(defineProps< {
|
||||
modelValue?: string | number | Date | DatePickerModel
|
||||
modelModifiers?: object
|
||||
columns?: number
|
||||
|
|
@ -64,11 +64,21 @@ onMounted(async () => {
|
|||
if (modelValue.value instanceof Date && calendarRef.value)
|
||||
calendarRef.value.focusDate(modelValue.value)
|
||||
})
|
||||
|
||||
const $slots = useSlots()
|
||||
const vCalendarSlots = computed(() => {
|
||||
return Object.keys($slots)
|
||||
.filter(name => isVCalendarSlot(name))
|
||||
.reduce((obj: Record<string, any>, key: string) => {
|
||||
obj[key] = $slots[key]
|
||||
return obj
|
||||
}, {})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative">
|
||||
<div class="absolute flex justify-between w-full px-4 top-3 z-[1]">
|
||||
<div v-if="$attrs.mode !== 'time'" class="absolute flex justify-between w-full px-4 top-3 z-[1]">
|
||||
<button :class="cn(buttonVariants({ variant: 'outline' }), 'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100')" @click="handleNav('prev')">
|
||||
<ChevronLeft class="w-4 h-4" />
|
||||
</button>
|
||||
|
|
@ -79,18 +89,30 @@ onMounted(async () => {
|
|||
|
||||
<DatePicker
|
||||
ref="datePicker"
|
||||
v-model="modelValue"
|
||||
v-bind="$attrs"
|
||||
v-model="modelValue"
|
||||
:model-modifiers="modelModifiers"
|
||||
class="calendar"
|
||||
trim-weeks
|
||||
:transition="'none'"
|
||||
:columns="columns"
|
||||
/>
|
||||
>
|
||||
<template v-for="(_, slot) of vCalendarSlots" #[slot]="scope">
|
||||
<slot :name="slot" v-bind="scope" />
|
||||
</template>
|
||||
|
||||
<template #nav-prev-button>
|
||||
<ChevronLeft />
|
||||
</template>
|
||||
|
||||
<template #nav-next-button>
|
||||
<ChevronRight />
|
||||
</template>
|
||||
</DatePicker>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="postcss">
|
||||
<style lang="css">
|
||||
.calendar {
|
||||
@apply p-3 text-center;
|
||||
}
|
||||
|
|
@ -98,7 +120,25 @@ onMounted(async () => {
|
|||
@apply grid gap-4;
|
||||
}
|
||||
.calendar .vc-title {
|
||||
@apply text-sm font-medium pointer-events-none;
|
||||
@apply text-sm font-medium relative z-20;
|
||||
}
|
||||
.vc-popover-content-wrapper .vc-popover-content {
|
||||
@apply mt-3 rounded-md max-w-xs border bg-background;
|
||||
}
|
||||
.vc-popover-content-wrapper .vc-nav-header {
|
||||
@apply flex justify-between items-center p-2;
|
||||
}
|
||||
.vc-popover-content-wrapper .vc-nav-items {
|
||||
@apply grid grid-cols-4 gap-2 p-2;
|
||||
}
|
||||
.vc-popover-content-wrapper .vc-nav-items .vc-nav-item {
|
||||
@apply rounded-md px-2 py-1;
|
||||
}
|
||||
.vc-popover-content-wrapper .vc-nav-items .vc-nav-item:hover {
|
||||
@apply text-muted-foreground bg-muted;
|
||||
}
|
||||
.vc-popover-content-wrapper .vc-nav-items .vc-nav-item.is-active {
|
||||
@apply bg-primary text-primary-foreground;
|
||||
}
|
||||
.calendar .vc-pane-header-wrapper {
|
||||
@apply hidden;
|
||||
|
|
@ -110,16 +150,22 @@ onMounted(async () => {
|
|||
@apply flex;
|
||||
}
|
||||
.calendar .vc-weekday {
|
||||
@apply text-muted-foreground rounded-md w-9 font-normal text-[0.8rem];
|
||||
@apply text-muted-foreground rounded-md w-full font-normal text-[0.8rem];
|
||||
}
|
||||
.calendar .vc-weekday-1 {
|
||||
@apply pr-3;
|
||||
}
|
||||
.calendar .vc-weekday-7 {
|
||||
@apply pl-3;
|
||||
}
|
||||
.calendar .vc-weeks {
|
||||
@apply w-full space-y-2 flex flex-col [&>_div]:grid [&>_div]:grid-cols-7;
|
||||
}
|
||||
.calendar .vc-day:has(.vc-highlights) {
|
||||
@apply bg-accent first:rounded-l-md last:rounded-r-md overflow-hidden;
|
||||
@apply first:rounded-l-md last:rounded-r-md;
|
||||
}
|
||||
.calendar .vc-day.is-today:not(:has(.vc-day-layer)) {
|
||||
@apply bg-secondary rounded-md;
|
||||
.calendar .vc-day.is-today:not(:has(.vc-day-layer)) .vc-day-content {
|
||||
@apply bg-secondary text-primary rounded-md;
|
||||
}
|
||||
.calendar .vc-day:has(.vc-highlight-base-start) {
|
||||
@apply rounded-l-md;
|
||||
|
|
@ -131,7 +177,7 @@ onMounted(async () => {
|
|||
@apply rounded-md;
|
||||
}
|
||||
.calendar .vc-day-content {
|
||||
@apply text-center text-sm p-0 relative focus-within:relative focus-within:z-20 inline-flex items-center justify-center ring-offset-background hover:transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 hover:bg-accent hover:text-accent-foreground h-9 w-9 font-normal aria-selected:opacity-100 select-none;
|
||||
@apply text-center text-sm p-0 relative focus-within:relative focus-within:z-20 inline-flex items-center justify-center ring-offset-background hover:transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 hover:bg-accent hover:text-accent-foreground h-9 w-9 font-normal aria-selected:opacity-100 select-none;
|
||||
}
|
||||
.calendar .vc-day-content:not(.vc-highlight-content-light) {
|
||||
@apply rounded-md;
|
||||
|
|
@ -157,6 +203,7 @@ onMounted(async () => {
|
|||
--vc-slide-duration: 0.15s;
|
||||
--vc-slide-timing: ease;
|
||||
}
|
||||
|
||||
.calendar .vc-fade-enter-active,
|
||||
.calendar .vc-fade-leave-active,
|
||||
.calendar .vc-slide-left-enter-active,
|
||||
|
|
@ -183,6 +230,7 @@ onMounted(async () => {
|
|||
backface-visibility: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.calendar .vc-none-leave-active,
|
||||
.calendar .vc-fade-leave-active,
|
||||
.calendar .vc-slide-left-leave-active,
|
||||
|
|
@ -192,6 +240,7 @@ onMounted(async () => {
|
|||
position: absolute !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.calendar .vc-none-enter-from,
|
||||
.calendar .vc-none-leave-to,
|
||||
.calendar .vc-fade-enter-from,
|
||||
|
|
@ -208,6 +257,7 @@ onMounted(async () => {
|
|||
.calendar .vc-slide-fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.calendar .vc-slide-left-enter-from,
|
||||
.calendar .vc-slide-right-leave-to,
|
||||
.calendar .vc-slide-fade-enter-from.direction-left,
|
||||
|
|
@ -215,6 +265,7 @@ onMounted(async () => {
|
|||
-webkit-transform: translateX(var(--vc-slide-translate));
|
||||
transform: translateX(var(--vc-slide-translate));
|
||||
}
|
||||
|
||||
.calendar .vc-slide-right-enter-from,
|
||||
.calendar .vc-slide-left-leave-to,
|
||||
.calendar .vc-slide-fade-enter-from.direction-right,
|
||||
|
|
@ -222,6 +273,7 @@ onMounted(async () => {
|
|||
-webkit-transform: translateX(calc(-1 * var(--vc-slide-translate)));
|
||||
transform: translateX(calc(-1 * var(--vc-slide-translate)));
|
||||
}
|
||||
|
||||
.calendar .vc-slide-up-enter-from,
|
||||
.calendar .vc-slide-down-leave-to,
|
||||
.calendar .vc-slide-fade-enter-from.direction-top,
|
||||
|
|
@ -229,6 +281,7 @@ onMounted(async () => {
|
|||
-webkit-transform: translateY(var(--vc-slide-translate));
|
||||
transform: translateY(var(--vc-slide-translate));
|
||||
}
|
||||
|
||||
.calendar .vc-slide-down-enter-from,
|
||||
.calendar .vc-slide-up-leave-to,
|
||||
.calendar .vc-slide-fade-enter-from.direction-bottom,
|
||||
|
|
|
|||
|
|
@ -1 +1,22 @@
|
|||
export { default as Calendar } from './Calendar.vue'
|
||||
import type { CalendarSlotName } from 'v-calendar/dist/types/src/components/Calendar/CalendarSlot.vue.d.ts'
|
||||
|
||||
export function isVCalendarSlot(slotName: string): slotName is CalendarSlotName {
|
||||
const validSlots: CalendarSlotName[] = [
|
||||
'day-content',
|
||||
'day-popover',
|
||||
'dp-footer',
|
||||
'footer',
|
||||
'header-title-wrapper',
|
||||
'header-title',
|
||||
'header-prev-button',
|
||||
'header-next-button',
|
||||
'nav',
|
||||
'nav-prev-button',
|
||||
'nav-next-button',
|
||||
'page',
|
||||
'time-header',
|
||||
]
|
||||
|
||||
return validSlots.includes(slotName as CalendarSlotName)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="cn('p-6 pt-0', props.class)">
|
||||
<div :class="cn('flex items-center p-6 pt-0', props.class)">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="cn('flex flex-col space-y-1.5 p-6', props.class)">
|
||||
<div :class="cn('flex flex-col gap-y-1.5 p-6', props.class)">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps({
|
||||
class: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h3
|
||||
:class="
|
||||
cn('text-2xl font-semibold leading-none tracking-tighter', props.class)
|
||||
cn('text-2xl font-semibold leading-none tracking-tight', props.class)
|
||||
"
|
||||
>
|
||||
<slot />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import type { WithClassAsProps } from './interface'
|
||||
import { useCarousel } from './useCarousel'
|
||||
import type { WithClassAsProps } from './interface'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
defineOptions({
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import type { WithClassAsProps } from './interface'
|
||||
import { useCarousel } from './useCarousel'
|
||||
import type { WithClassAsProps } from './interface'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<WithClassAsProps>()
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import type { CheckboxRootEmits, CheckboxRootProps } from 'radix-vue'
|
||||
import { CheckboxIndicator, CheckboxRoot, useForwardPropsEmits } from 'radix-vue'
|
||||
import { Check } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<CheckboxRootProps>()
|
||||
const props = defineProps<CheckboxRootProps & { class?: HTMLAttributes['class'] }>()
|
||||
const emits = defineEmits<CheckboxRootEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -15,10 +22,12 @@ const forwarded = useForwardPropsEmits(props, emits)
|
|||
v-bind="forwarded"
|
||||
:class="
|
||||
cn('peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',
|
||||
$attrs.class ?? '')"
|
||||
props.class)"
|
||||
>
|
||||
<CheckboxIndicator class="flex h-full w-full items-center justify-center text-current">
|
||||
<Check class="h-4 w-4" />
|
||||
<slot>
|
||||
<Check class="h-4 w-4" />
|
||||
</slot>
|
||||
</CheckboxIndicator>
|
||||
</CheckboxRoot>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import { CollapsibleRoot, useEmitAsProps } from 'radix-vue'
|
||||
import { CollapsibleRoot, useForwardPropsEmits } from 'radix-vue'
|
||||
import type { CollapsibleRootEmits, CollapsibleRootProps } from 'radix-vue'
|
||||
|
||||
const props = defineProps<CollapsibleRootProps>()
|
||||
const emits = defineEmits<CollapsibleRootEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CollapsibleRoot v-slot="{ open }" v-bind="{ ...props, ...useEmitAsProps(emits) }">
|
||||
<CollapsibleRoot v-slot="{ open }" v-bind="forwarded">
|
||||
<slot :open="open" />
|
||||
</CollapsibleRoot>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,29 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import type { ComboboxRootEmits, ComboboxRootProps } from 'radix-vue'
|
||||
import { ComboboxRoot, useForwardPropsEmits } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ComboboxRootProps>()
|
||||
const props = withDefaults(defineProps<ComboboxRootProps & { class?: HTMLAttributes['class'] }>(), {
|
||||
open: true,
|
||||
modelValue: '',
|
||||
})
|
||||
|
||||
const emits = defineEmits<ComboboxRootEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ComboboxRoot
|
||||
v-bind="forwarded"
|
||||
:open="true"
|
||||
:model-value="''"
|
||||
:class="cn('flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground', $attrs.class ?? '')"
|
||||
:class="cn('flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</ComboboxRoot>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { useEmitAsProps } from 'radix-vue'
|
||||
import { useForwardPropsEmits } from 'radix-vue'
|
||||
import type { DialogRootEmits, DialogRootProps } from 'radix-vue'
|
||||
import Command from './Command.vue'
|
||||
import { Dialog, DialogContent } from '@/lib/registry/default/ui/dialog'
|
||||
|
|
@ -7,12 +7,12 @@ import { Dialog, DialogContent } from '@/lib/registry/default/ui/dialog'
|
|||
const props = defineProps<DialogRootProps>()
|
||||
const emits = defineEmits<DialogRootEmits>()
|
||||
|
||||
const emitsAsProps = useEmitAsProps(emits)
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Dialog v-bind="{ ...props, ...emitsAsProps }">
|
||||
<DialogContent class="p-0 overflow-hidden shadow-lg">
|
||||
<Dialog v-bind="forwarded">
|
||||
<DialogContent class="overflow-hidden p-0 shadow-lg">
|
||||
<Command class="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
||||
<slot />
|
||||
</Command>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import type { ComboboxEmptyProps } from 'radix-vue'
|
||||
import { ComboboxEmpty } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ComboboxEmptyProps>()
|
||||
const props = defineProps<ComboboxEmptyProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ComboboxEmpty v-bind="props" :class="cn('py-6 text-center text-sm', $attrs.class ?? '')">
|
||||
<ComboboxEmpty v-bind="delegatedProps" :class="cn('py-6 text-center text-sm', props.class)">
|
||||
<slot />
|
||||
</ComboboxEmpty>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,25 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import type { ComboboxGroupProps } from 'radix-vue'
|
||||
import { ComboboxGroup, ComboboxLabel } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ComboboxGroupProps & {
|
||||
class?: HTMLAttributes['class']
|
||||
heading?: string
|
||||
}>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ComboboxGroup
|
||||
v-bind="props"
|
||||
:class="cn('overflow-hidden p-1 text-foreground', $attrs.class ?? '')"
|
||||
v-bind="delegatedProps"
|
||||
:class="cn('overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground', props.class)"
|
||||
>
|
||||
<ComboboxLabel v-if="heading" class="px-2 py-1.5 text-xs font-medium text-muted-foreground">
|
||||
{{ heading }}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,33 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import { Search } from 'lucide-vue-next'
|
||||
import { ComboboxInput, type ComboboxInputProps } from 'radix-vue'
|
||||
import { ComboboxInput, type ComboboxInputProps, useForwardProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ComboboxInputProps>()
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
}
|
||||
})
|
||||
|
||||
const props = defineProps<ComboboxInputProps & {
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex items-center border-b px-3" cmdk-input-wrapper>
|
||||
<Search class="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
<ComboboxInput
|
||||
v-bind="{ ...props, ...$attrs }"
|
||||
v-bind="{ ...forwardedProps, ...$attrs }"
|
||||
auto-focus
|
||||
:class="cn('flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50', $attrs.class ?? '')"
|
||||
:class="cn('flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50', props.class)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,25 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import type { ComboboxItemEmits, ComboboxItemProps } from 'radix-vue'
|
||||
import { ComboboxItem, useEmitAsProps } from 'radix-vue'
|
||||
import { ComboboxItem, useForwardPropsEmits } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ComboboxItemProps>()
|
||||
const props = defineProps<ComboboxItemProps & { class?: HTMLAttributes['class'] }>()
|
||||
const emits = defineEmits<ComboboxItemEmits>()
|
||||
|
||||
const emitsAsProps = useEmitAsProps(emits)
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ComboboxItem
|
||||
v-bind="{ ...props, ...emitsAsProps }"
|
||||
:class="cn('relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50', $attrs.class ?? '')"
|
||||
v-bind="forwarded"
|
||||
:class="cn('relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50', props.class)"
|
||||
@select.prevent
|
||||
>
|
||||
<slot />
|
||||
|
|
|
|||
|
|
@ -1,16 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import type { ComboboxContentEmits, ComboboxContentProps } from 'radix-vue'
|
||||
import { ComboboxContent, useForwardPropsEmits } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ComboboxContentProps>()
|
||||
const props = defineProps<ComboboxContentProps & { class?: HTMLAttributes['class'] }>()
|
||||
const emits = defineEmits<ComboboxContentEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ComboboxContent v-bind="forwarded" :class="cn('max-h-[300px] overflow-y-auto overflow-x-hidden', $attrs.class ?? '')">
|
||||
<ComboboxContent v-bind="forwarded" :class="cn('max-h-[300px] overflow-y-auto overflow-x-hidden', props.class)">
|
||||
<div role="presentation">
|
||||
<slot />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import type { ComboboxSeparatorProps } from 'radix-vue'
|
||||
import { ComboboxSeparator } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ComboboxSeparatorProps>()
|
||||
const props = defineProps<ComboboxSeparatorProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ComboboxSeparator
|
||||
v-bind="props"
|
||||
:class="cn('-mx-1 h-px bg-border', $attrs.class ?? '')"
|
||||
v-bind="delegatedProps"
|
||||
:class="cn('-mx-1 h-px bg-border', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</ComboboxSeparator>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span :class="cn('ml-auto text-xs tracking-widest text-muted-foreground', $attrs.class ?? '')">
|
||||
<span :class="cn('ml-auto text-xs tracking-widest text-muted-foreground', props.class)">
|
||||
<slot />
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,33 +1,38 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
ContextMenuCheckboxItem,
|
||||
type ContextMenuCheckboxItemEmits,
|
||||
type ContextMenuCheckboxItemProps,
|
||||
ContextMenuItemIndicator,
|
||||
useEmitAsProps,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue'
|
||||
import { Check } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ContextMenuCheckboxItemProps & { class?: string }>()
|
||||
const props = defineProps<ContextMenuCheckboxItemProps & { class?: HTMLAttributes['class'] }>()
|
||||
const emits = defineEmits<ContextMenuCheckboxItemEmits>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ContextMenuCheckboxItem
|
||||
v-bind="{ ...props, ...useEmitAsProps(emits) }"
|
||||
:class="[
|
||||
cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
props.class,
|
||||
),
|
||||
]"
|
||||
v-bind="forwarded"
|
||||
:class="cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
props.class,
|
||||
)"
|
||||
>
|
||||
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
<ContextMenuItemIndicator
|
||||
class="absolute left-1.5 inline-flex w-4 h-4 items-center justify-center"
|
||||
>
|
||||
<Check class="h-4 h-w" />
|
||||
<ContextMenuItemIndicator>
|
||||
<Check class="h-4 w-4" />
|
||||
</ContextMenuItemIndicator>
|
||||
</span>
|
||||
<slot />
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
ContextMenuContent,
|
||||
type ContextMenuContentEmits,
|
||||
|
|
@ -8,23 +9,26 @@ import {
|
|||
} from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ContextMenuContentProps & { class?: string }>()
|
||||
const props = defineProps<ContextMenuContentProps & { class?: HTMLAttributes['class'] }>()
|
||||
const emits = defineEmits<ContextMenuContentEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ContextMenuPortal>
|
||||
<ContextMenuContent
|
||||
:align-offset="props.alignOffset"
|
||||
:class="[
|
||||
cn(
|
||||
'z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||
props.class,
|
||||
),
|
||||
]"
|
||||
v-bind="forwarded"
|
||||
:class="cn(
|
||||
'z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||
props.class,
|
||||
)"
|
||||
>
|
||||
<slot />
|
||||
</ContextMenuContent>
|
||||
|
|
|
|||
|
|
@ -1,26 +1,33 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
ContextMenuItem,
|
||||
type ContextMenuItemEmits,
|
||||
type ContextMenuItemProps,
|
||||
useEmitAsProps,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ContextMenuItemProps & { class?: string; inset?: boolean }>()
|
||||
const props = defineProps<ContextMenuItemProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
|
||||
const emits = defineEmits<ContextMenuItemEmits>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ContextMenuItem
|
||||
v-bind="{ ...props, ...useEmitAsProps(emits) }"
|
||||
:class="[
|
||||
cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
inset && 'pl-8',
|
||||
props.class,
|
||||
),
|
||||
]"
|
||||
v-bind="forwarded"
|
||||
:class="cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
inset && 'pl-8',
|
||||
props.class,
|
||||
)"
|
||||
>
|
||||
<slot />
|
||||
</ContextMenuItem>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import { ContextMenuLabel, type ContextMenuLabelProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ContextMenuLabelProps & { class?: string; inset?: boolean }>()
|
||||
const props = defineProps<ContextMenuLabelProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ContextMenuLabel
|
||||
v-bind="props"
|
||||
v-bind="delegatedProps"
|
||||
:class="
|
||||
cn('px-2 py-1.5 text-sm font-semibold text-foreground',
|
||||
inset && 'pl-8', props.class ?? '',
|
||||
inset && 'pl-8', props.class,
|
||||
)"
|
||||
>
|
||||
<slot />
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
ContextMenuItemIndicator,
|
||||
ContextMenuRadioItem,
|
||||
|
|
@ -9,21 +10,25 @@ import {
|
|||
import { Circle } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ContextMenuRadioItemProps & { class?: string }>()
|
||||
const props = defineProps<ContextMenuRadioItemProps & { class?: HTMLAttributes['class'] }>()
|
||||
const emits = defineEmits<ContextMenuRadioItemEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ContextMenuRadioItem
|
||||
v-bind="forwarded"
|
||||
:class="[
|
||||
cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
props.class,
|
||||
),
|
||||
]"
|
||||
:class="cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
props.class,
|
||||
)"
|
||||
>
|
||||
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
<ContextMenuItemIndicator>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
ContextMenuSeparator,
|
||||
type ContextMenuSeparatorProps,
|
||||
} from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ContextMenuSeparatorProps>()
|
||||
const props = defineProps<ContextMenuSeparatorProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ContextMenuSeparator v-bind="props" :class="cn('-mx-1 my-1 h-px bg-border', $attrs.class ?? '')" />
|
||||
<ContextMenuSeparator v-bind="delegatedProps" :class="cn('-mx-1 my-1 h-px bg-border', props.class)" />
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span :class="cn('ml-auto text-xs tracking-widest text-muted-foreground', $attrs.class ?? '')">
|
||||
<span :class="cn('ml-auto text-xs tracking-widest text-muted-foreground', props.class)">
|
||||
<slot />
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
ContextMenuSubContent,
|
||||
type DropdownMenuSubContentEmits,
|
||||
|
|
@ -7,10 +8,16 @@ import {
|
|||
} from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DropdownMenuSubContentProps & { class?: string }>()
|
||||
const props = defineProps<DropdownMenuSubContentProps & { class?: HTMLAttributes['class'] }>()
|
||||
const emits = defineEmits<DropdownMenuSubContentEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,24 +1,32 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
ContextMenuSubTrigger,
|
||||
type ContextMenuSubTriggerProps,
|
||||
useForwardProps,
|
||||
} from 'radix-vue'
|
||||
import { ChevronRight } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ContextMenuSubTriggerProps & { class?: string; inset?: boolean }>()
|
||||
const props = defineProps<ContextMenuSubTriggerProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ContextMenuSubTrigger
|
||||
v-bind="props"
|
||||
:class="[
|
||||
cn(
|
||||
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
|
||||
inset && 'pl-8',
|
||||
props.class,
|
||||
),
|
||||
]"
|
||||
v-bind="forwardedProps"
|
||||
:class="cn(
|
||||
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground',
|
||||
inset && 'pl-8',
|
||||
props.class,
|
||||
)"
|
||||
>
|
||||
<slot />
|
||||
<ChevronRight class="ml-auto h-4 w-4" />
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
import { ContextMenuTrigger, type ContextMenuTriggerProps } from 'radix-vue'
|
||||
import { ContextMenuTrigger, type ContextMenuTriggerProps, useForwardProps } from 'radix-vue'
|
||||
|
||||
const props = defineProps<ContextMenuTriggerProps>()
|
||||
|
||||
const forwardedProps = useForwardProps(props)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ContextMenuTrigger v-bind="props">
|
||||
<ContextMenuTrigger v-bind="forwardedProps">
|
||||
<slot />
|
||||
</ContextMenuTrigger>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import { DialogRoot, type DialogRootEmits, type DialogRootProps, useForwardPropsEmits } from 'radix-vue'
|
||||
|
||||
const props = defineProps<DialogRootProps>()
|
||||
const emits = defineEmits<DialogRootEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogRoot v-bind="forwarded">
|
||||
<slot />
|
||||
</DialogRoot>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { DialogRoot, type DialogRootEmits, type DialogRootProps, useForwardPropsEmits } from 'radix-vue'
|
||||
|
||||
const props = defineProps<DialogRootProps>()
|
||||
const emits = defineEmits<DialogRootEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogRoot v-bind="forwarded">
|
||||
<slot />
|
||||
</DialogRoot>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
|
|
@ -6,35 +7,40 @@ import {
|
|||
type DialogContentProps,
|
||||
DialogOverlay,
|
||||
DialogPortal,
|
||||
useEmitAsProps,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue'
|
||||
import { X } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DialogContentProps & { class?: string }>()
|
||||
const props = defineProps<DialogContentProps & { class?: HTMLAttributes['class'] }>()
|
||||
const emits = defineEmits<DialogContentEmits>()
|
||||
|
||||
const emitsAsProps = useEmitAsProps(emits)
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogPortal>
|
||||
<DialogOverlay
|
||||
class="fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
|
||||
class="fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
|
||||
/>
|
||||
<DialogContent
|
||||
v-bind="forwarded"
|
||||
:class="
|
||||
cn(
|
||||
'fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border border-border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full',
|
||||
'fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
v-bind="{ ...props, ...emitsAsProps }"
|
||||
)"
|
||||
>
|
||||
<slot />
|
||||
|
||||
<DialogClose
|
||||
class="absolute top-3 right-3 p-0.5 transition-colors rounded-md hover:bg-secondary"
|
||||
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
|
||||
>
|
||||
<X class="w-4 h-4" />
|
||||
<span class="sr-only">Close</span>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
import { DialogDescription, type DialogDescriptionProps } from 'radix-vue'
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import { DialogDescription, type DialogDescriptionProps, useForwardProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DialogDescriptionProps & { class?: string }>()
|
||||
const props = defineProps<DialogDescriptionProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogDescription
|
||||
v-bind="props"
|
||||
:class="cn('text-muted-foreground text-sm', props.class)"
|
||||
v-bind="forwardedProps"
|
||||
:class="cn('text-sm text-muted-foreground', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</DialogDescription>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface DialogFooterProps {
|
||||
class?: string
|
||||
}
|
||||
|
||||
const props = defineProps<DialogFooterProps>()
|
||||
const props = defineProps<{ class?: HTMLAttributes['class'] }>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
'flex flex-col space-y-2 sm:space-y-0 mt-1.5 sm:flex-row sm:justify-end sm:space-x-2',
|
||||
'flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-x-2',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface DialogHeaderProps {
|
||||
class?: string
|
||||
}
|
||||
|
||||
const props = defineProps<DialogHeaderProps>()
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="cn('flex flex-col space-y-2 text-center sm:text-left', props.class)"
|
||||
:class="cn('flex flex-col gap-y-1.5 text-center sm:text-left', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,25 @@
|
|||
<script setup lang="ts">
|
||||
import { DialogTitle, type DialogTitleProps } from 'radix-vue'
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import { DialogTitle, type DialogTitleProps, useForwardProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DialogTitleProps & { class?: string }>()
|
||||
const props = defineProps<DialogTitleProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DialogTitle
|
||||
v-bind="props"
|
||||
v-bind="forwardedProps"
|
||||
:class="
|
||||
cn(
|
||||
'text-lg text-foreground font-semibold leading-none tracking-tight',
|
||||
'text-lg font-semibold leading-none tracking-tight',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
|
|
|
|||
|
|
@ -1,21 +1,30 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
DropdownMenuCheckboxItem,
|
||||
type DropdownMenuCheckboxItemEmits,
|
||||
type DropdownMenuCheckboxItemProps,
|
||||
DropdownMenuItemIndicator,
|
||||
useEmitAsProps,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue'
|
||||
import { Check } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DropdownMenuCheckboxItemProps & { class?: string }>()
|
||||
const props = defineProps<DropdownMenuCheckboxItemProps & { class?: HTMLAttributes['class'] }>()
|
||||
const emits = defineEmits<DropdownMenuCheckboxItemEmits>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenuCheckboxItem
|
||||
v-bind="{ ...props, ...useEmitAsProps(emits) }"
|
||||
v-bind="forwarded"
|
||||
:class=" cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
props.class,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
DropdownMenuContent,
|
||||
type DropdownMenuContentEmits,
|
||||
|
|
@ -9,26 +10,27 @@ import {
|
|||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<DropdownMenuContentProps & { class?: string }>(),
|
||||
defineProps<DropdownMenuContentProps & { class?: HTMLAttributes['class'] }>(),
|
||||
{
|
||||
sideOffset: 4,
|
||||
},
|
||||
)
|
||||
const emits = defineEmits<DropdownMenuContentEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuContent
|
||||
:class="[
|
||||
cn(
|
||||
'z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
||||
props.class,
|
||||
),
|
||||
]"
|
||||
v-bind="forwarded"
|
||||
:class="cn('z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</DropdownMenuContent>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,27 @@
|
|||
<script setup lang="ts">
|
||||
import { DropdownMenuItem, type DropdownMenuItemProps } from 'radix-vue'
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import { DropdownMenuItem, type DropdownMenuItemProps, useForwardProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DropdownMenuItemProps & { inset?: boolean; class?: string }>()
|
||||
const props = defineProps<DropdownMenuItemProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenuItem
|
||||
v-bind="props"
|
||||
:class="[
|
||||
cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
inset && 'pl-8',
|
||||
props.class,
|
||||
),
|
||||
]"
|
||||
v-bind="forwardedProps"
|
||||
:class="cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
inset && 'pl-8',
|
||||
props.class,
|
||||
)"
|
||||
>
|
||||
<slot />
|
||||
</DropdownMenuItem>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
import { DropdownMenuLabel, type DropdownMenuLabelProps } from 'radix-vue'
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import { DropdownMenuLabel, type DropdownMenuLabelProps, useForwardProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DropdownMenuLabelProps & {
|
||||
inset?: boolean
|
||||
class?: string
|
||||
}>()
|
||||
const props = defineProps<DropdownMenuLabelProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenuLabel
|
||||
v-bind="props"
|
||||
:class="
|
||||
cn('px-2 py-1.5 text-sm font-semibold',
|
||||
inset && 'pl-8', props.class)"
|
||||
v-bind="forwardedProps"
|
||||
:class="cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</DropdownMenuLabel>
|
||||
|
|
|
|||
|
|
@ -3,18 +3,17 @@ import {
|
|||
DropdownMenuRadioGroup,
|
||||
type DropdownMenuRadioGroupEmits,
|
||||
type DropdownMenuRadioGroupProps,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue'
|
||||
|
||||
const props = defineProps<DropdownMenuRadioGroupProps>()
|
||||
|
||||
const emits = defineEmits<DropdownMenuRadioGroupEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenuRadioGroup
|
||||
v-bind="props"
|
||||
@update:model-value="emits('update:modelValue', $event)"
|
||||
>
|
||||
<DropdownMenuRadioGroup v-bind="forwarded">
|
||||
<slot />
|
||||
</DropdownMenuRadioGroup>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,29 +1,37 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
DropdownMenuItemIndicator,
|
||||
DropdownMenuRadioItem,
|
||||
type DropdownMenuRadioItemEmits,
|
||||
type DropdownMenuRadioItemProps,
|
||||
useEmitAsProps,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue'
|
||||
import { Circle } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DropdownMenuRadioItemProps & { class?: string }>()
|
||||
const props = defineProps<DropdownMenuRadioItemProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const emits = defineEmits<DropdownMenuRadioItemEmits>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenuRadioItem
|
||||
v-bind="{ ...props, ...useEmitAsProps(emits) }"
|
||||
v-bind="forwarded"
|
||||
:class="cn(
|
||||
'flex relative items-center rounded-md transition-colors data-[disabled]:opacity-50 data-[disabled]:pointer-events-none data-[highlighted]:bg-outline-hover pl-7 py-1.5 text-sm outline-none select-none cursor-default',
|
||||
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
||||
props.class,
|
||||
)"
|
||||
>
|
||||
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
|
||||
<DropdownMenuItemIndicator>
|
||||
<Circle class="h-2 w-2 fill-current" />
|
||||
</DropdownMenuItemIndicator>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
DropdownMenuSeparator,
|
||||
type DropdownMenuSeparatorProps,
|
||||
} from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DropdownMenuSeparatorProps>()
|
||||
const props = defineProps<DropdownMenuSeparatorProps & {
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenuSeparator v-bind="props" class="-mx-1 my-1 h-px bg-muted" />
|
||||
<DropdownMenuSeparator v-bind="delegatedProps" :class="cn('-mx-1 my-1 h-px bg-muted', props.class)" />
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span :class="cn('ml-auto text-xs tracking-widest opacity-60', $attrs.class ?? '')">
|
||||
<span :class="cn('ml-auto text-xs tracking-widest opacity-60', props.class)">
|
||||
<slot />
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
DropdownMenuSubContent,
|
||||
type DropdownMenuSubContentEmits,
|
||||
|
|
@ -7,16 +8,22 @@ import {
|
|||
} from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DropdownMenuSubContentProps>()
|
||||
const props = defineProps<DropdownMenuSubContentProps & { class?: HTMLAttributes['class'] }>()
|
||||
const emits = defineEmits<DropdownMenuSubContentEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenuSubContent
|
||||
v-bind="forwarded"
|
||||
:class="cn('z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', $attrs.class ?? '')"
|
||||
:class="cn('z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</DropdownMenuSubContent>
|
||||
|
|
|
|||
|
|
@ -1,23 +1,31 @@
|
|||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import {
|
||||
DropdownMenuSubTrigger,
|
||||
type DropdownMenuSubTriggerProps,
|
||||
useForwardProps,
|
||||
} from 'radix-vue'
|
||||
import { ChevronRight } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DropdownMenuSubTriggerProps & { class?: string }>()
|
||||
const props = defineProps<DropdownMenuSubTriggerProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenuSubTrigger
|
||||
v-bind="props"
|
||||
:class="[
|
||||
cn(
|
||||
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent',
|
||||
props.class,
|
||||
),
|
||||
]"
|
||||
v-bind="forwardedProps"
|
||||
:class="cn(
|
||||
'flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent',
|
||||
props.class,
|
||||
)"
|
||||
>
|
||||
<slot />
|
||||
<ChevronRight class="ml-auto h-4 w-4" />
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
import { DropdownMenuTrigger, type DropdownMenuTriggerProps } from 'radix-vue'
|
||||
import { DropdownMenuTrigger, type DropdownMenuTriggerProps, useForwardProps } from 'radix-vue'
|
||||
|
||||
const props = defineProps<DropdownMenuTriggerProps>()
|
||||
|
||||
const forwardedProps = useForwardProps(props)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenuTrigger class="outline-none" v-bind="props">
|
||||
<DropdownMenuTrigger class="outline-none" v-bind="forwardedProps">
|
||||
<slot />
|
||||
</DropdownMenuTrigger>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,21 +1,19 @@
|
|||
<script lang="ts" setup>
|
||||
import { useAttrs } from 'vue'
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { useFormField } from './useFormField'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
})
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
|
||||
const { formDescriptionId } = useFormField()
|
||||
const { class: className, ...rest } = useAttrs()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p
|
||||
:id="formDescriptionId"
|
||||
:class="cn('text-sm text-muted-foreground', className ?? '')"
|
||||
v-bind="rest"
|
||||
:class="cn('text-sm text-muted-foreground', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</p>
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user