Merge branch 'dev' into cli-nypm-and-other-improves

This commit is contained in:
Sadegh Barati 2024-02-04 18:45:26 +03:30
commit 64e8930f38
434 changed files with 5931 additions and 5722 deletions

View File

@ -6,62 +6,27 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | 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 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: or are unsure if this is really a bug, make sure to:
- Read the [docs](https://radix-vue.com/) - Read the [docs](https://radix-vue.com/)
- Ask on [Discord Chat](https://chat.radix-vue.com/) - Ask on [Discord Chat](https://chat.radix-vue.com/)
- Ask on [GitHub Discussions](https://github.com/shadcn-vue/shadcn-vue/discussions) - 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 - type: input
id: reproduction-link id: reproduction
attributes: attributes:
label: Link to minimal reproduction label: Reproduction
description: | description: |
Please provide a link to a minimal reproduction of the bug. 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)
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
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. or use template presets
placeholder: Reproduction Link https://vite.new
validations: https://nuxt.new
required: true placeholder: Reproduction
- 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
validations: validations:
required: true required: true
- type: textarea - type: textarea
@ -73,14 +38,18 @@ body:
validations: validations:
required: true required: true
- type: textarea - type: textarea
id: expected-behavior id: system-info
attributes: attributes:
label: Expected behavior label: System Info
description: A clear and concise description of what you expected to happen. description: Output of `npx envinfo --system --npmPackages vue,@vueuse/core,radix-vue,nuxt,shadcn-vue,shadcn-nuxt,unplugin-auto-import --binaries --browsers`
- type: textarea render: bash
id: screenshots placeholder: System, Binaries, Browsers
validations:
required: true
- type: checkboxes
id: contributes
attributes: attributes:
label: Conext & Screenshots (if applicable) label: Contributes
description: | options:
If applicable, provide any additional context or screenshots of the bug. - label: I am willing to submit a PR to fix this issue
You can drag and drop images here to add them to the issue. - label: I am willing to submit a PR with failing tests

View File

@ -17,8 +17,6 @@ on:
- opened - opened
# When a labeled '🚀request-deploy' pull request from forked repo, it will be deploy to Cloudflare Pages # When a labeled '🚀request-deploy' pull request from forked repo, it will be deploy to Cloudflare Pages
- labeled - labeled
paths:
- 'apps/www/**'
# Allows you to run this workflow manually from the Actions tab # Allows you to run this workflow manually from the Actions tab
# eslint-disable-next-line yml/no-empty-mapping-value # eslint-disable-next-line yml/no-empty-mapping-value
workflow_dispatch: workflow_dispatch:
@ -52,9 +50,6 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
fetch-depth: 0
# Run a build step here # Run a build step here
- name: Setup Node.js environment - name: Setup Node.js environment

View File

@ -3,9 +3,9 @@ import { defineConfig } from 'vitepress'
import Icons from 'unplugin-icons/vite' import Icons from 'unplugin-icons/vite'
import tailwind from 'tailwindcss' import tailwind from 'tailwindcss'
import autoprefixer from 'autoprefixer' import autoprefixer from 'autoprefixer'
import { createCssVariablesTheme } from 'shikiji' import { createCssVariablesTheme } from 'shiki'
// import { transformerMetaWordHighlight } from 'shikiji-transformers' // import { transformerMetaWordHighlight, transformerNotationWordHighlight } from '@shikijs/transformers'
import { siteConfig } from './theme/config/site' import { siteConfig } from './theme/config/site'
import ComponentPreviewPlugin from './theme/plugins/previewer' import ComponentPreviewPlugin from './theme/plugins/previewer'
@ -61,6 +61,7 @@ export default defineConfig({
theme: cssVariables, theme: cssVariables,
codeTransformers: [ codeTransformers: [
// transformerMetaWordHighlight(), // transformerMetaWordHighlight(),
// transformerNotationWordHighlight(),
], ],
config(md) { config(md) {
md.use(ComponentPreviewPlugin) md.use(ComponentPreviewPlugin)
@ -86,8 +87,5 @@ export default defineConfig({
'@': path.resolve(__dirname, '../src'), '@': path.resolve(__dirname, '../src'),
}, },
}, },
ssr: {
noExternal: ['vue-sonner'],
},
}, },
}) })

View File

@ -18,9 +18,9 @@ const kbdClass = computed(() => {
{ {
variants: { variants: {
size: { size: {
xs: 'min-h-[16px] text-[10px] h-4 px-1', xs: 'min-h-4 text-[10px] h-4 px-1',
sm: 'min-h-[20px] text-[11px] h-5 px-1', sm: 'min-h-5 text-[11px] h-5 px-1',
md: 'min-h-[24px] text-[12px] h-6 px-1.5', md: 'min-h-6 text-[12px] h-6 px-1.5',
}, },
}, },
}, },

View File

@ -328,7 +328,6 @@ export const docsConfig: DocsConfig = {
{ {
title: 'Toast', title: 'Toast',
href: '/docs/components/toast', href: '/docs/components/toast',
label: 'New',
items: [], items: [],
}, },
{ {

View File

@ -46,9 +46,9 @@ const sourceLink = 'https://github.com/radix-vue/shadcn-vue/tree/dev/'
> >
{{ doc.title }} {{ 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 }} {{ doc.label }}
</Badge> </span>
</a> </a>
</div> </div>
</div> </div>

View File

@ -135,7 +135,7 @@ watch(() => $route.path, (n) => {
:href="link.href" target="_blank" :href="link.href" target="_blank"
:variant="'ghost'" :size="'icon'" :variant="'ghost'" :size="'icon'"
> >
<component :is="link.icon" class="w-[20px] h-[20px]" /> <component :is="link.icon" class="w-[20px] h-5" />
</Button> </Button>
<Button <Button
@ -146,7 +146,7 @@ watch(() => $route.path, (n) => {
> >
<component <component
:is="isDark ? RadixIconsSun : RadixIconsMoon" :is="isDark ? RadixIconsSun : RadixIconsMoon"
class="w-[20px] h-[20px] text-foreground" class="w-[20px] h-5 text-foreground"
/> />
</Button> </Button>
</div> </div>
@ -288,7 +288,9 @@ watch(() => $route.path, (n) => {
</DialogContent> </DialogContent>
</Dialog> </Dialog>
<DefaultToaster /> <DefaultToaster />
<NewYorkSonner :theme="isDark ? 'dark' : 'light'" /> <ClientOnly>
<NewYorkSonner :theme="isDark ? 'dark' : 'light'" />
</ClientOnly>
<NewYorkToaster /> <NewYorkToaster />
</div> </div>
</template> </template>

View File

@ -5,49 +5,49 @@
@layer base { @layer base {
:root { :root {
--background: 0 0% 100%; --background: 0 0% 100%;
--foreground: 240 10% 3.9%; --foreground: 240 10% 3.9%;
--card: 0 0% 100%; --card: 0 0% 100%;
--card-foreground: 240 10% 3.9%; --card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%; --popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%; --popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%; --primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%; --primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%; --secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%; --secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%; --muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%; --muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%; --accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%; --accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%; --destructive: 0 72.22% 50.59%;
--destructive-foreground: 0 0% 98%; --destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%; --border: 240 5.9% 90%;
--input: 240 5.9% 90%; --input: 240 5.9% 90%;
--ring: 240 5% 64.9%; --ring: 240 5% 64.9%;
--radius: 0.5rem; --radius: 0.5rem;
} }
.dark { .dark {
--background: 240 10% 3.9%; --background: 240 10% 3.9%;
--foreground: 0 0% 98%; --foreground: 0 0% 98%;
--card: 240 10% 3.9%; --card: 240 10% 3.9%;
--card-foreground: 0 0% 98%; --card-foreground: 0 0% 98%;
--popover: 240 10% 3.9%; --popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%; --popover-foreground: 0 0% 98%;
--primary: 0 0% 98%; --primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%; --primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%; --secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%; --secondary-foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%; --muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%; --muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%; --accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%; --accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%; --destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 85.7% 97.3%; --destructive-foreground: 0 85.7% 97.3%;
--border: 240 3.7% 15.9%; --border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%; --input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%; --ring: 240 4.9% 83.9%;
} }
* { * {
@ -116,7 +116,7 @@
.step:before { .step:before {
@apply absolute w-9 h-9 bg-muted rounded-full font-mono font-medium text-center text-base inline-flex items-center justify-center -indent-px border-4 border-background; @apply absolute w-9 h-9 bg-muted rounded-full font-mono font-medium text-center text-base inline-flex items-center justify-center -indent-px border-4 border-background;
@apply ml-[-50px] mt-[-4px]; @apply -ml-[50px] -mt-1;
content: counter(step); content: counter(step);
} }
} }
@ -139,7 +139,7 @@ pre code {
} }
pre code .line { pre code .line {
@apply px-4 min-h-[1.5rem] !py-0.5 w-full inline-block; @apply px-4 min-h-6 !py-0.5 w-full inline-block;
} }
.line-number { .line-number {
@ -149,4 +149,4 @@ pre code .line {
::view-transition-old(root), ::view-transition-old(root),
::view-transition-new(root) { ::view-transition-new(root) {
animation-duration: 0.3s; animation-duration: 0.3s;
} }

View File

@ -10,4 +10,11 @@
--shiki-token-string-expression: #ebebeb; --shiki-token-string-expression: #ebebeb;
--shiki-token-punctuation: #ffffff; --shiki-token-punctuation: #ffffff;
--shiki-token-link: #EE0000; --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;
} }

View File

@ -1,7 +1,7 @@
{ {
"name": "www", "name": "www",
"type": "module", "type": "module",
"version": "0.8.7", "version": "0.9.0",
"files": [ "files": [
"dist" "dist"
], ],
@ -19,25 +19,25 @@
"@morev/vue-transitions": "^2.3.6", "@morev/vue-transitions": "^2.3.6",
"@radix-icons/vue": "^1.0.0", "@radix-icons/vue": "^1.0.0",
"@stackblitz/sdk": "^1.9.0", "@stackblitz/sdk": "^1.9.0",
"@tanstack/vue-table": "^8.11.7", "@tanstack/vue-table": "^8.11.8",
"@unovis/ts": "^1.3.1", "@unovis/ts": "^1.3.3",
"@unovis/vue": "^1.3.1", "@unovis/vue": "^1.3.3",
"@vee-validate/zod": "^4.12.4", "@vee-validate/zod": "^4.12.5",
"@vueuse/core": "^10.7.2", "@vueuse/core": "^10.7.2",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"clsx": "^2.1.0", "clsx": "^2.1.0",
"codesandbox": "^2.2.3", "codesandbox": "^2.2.3",
"date-fns": "^2.30.0", "date-fns": "^2.30.0",
"embla-carousel": "8.0.0-rc19", "embla-carousel": "^8.0.0-rc22",
"embla-carousel-autoplay": "8.0.0-rc19", "embla-carousel-autoplay": "^8.0.0-rc22",
"embla-carousel-vue": "8.0.0-rc19", "embla-carousel-vue": "^8.0.0-rc22",
"lucide-vue-next": "^0.276.0", "lucide-vue-next": "^0.276.0",
"radix-vue": "^1.3.2", "radix-vue": "^1.4.0",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"v-calendar": "^3.1.2", "v-calendar": "^3.1.2",
"vee-validate": "4.12.4", "vee-validate": "4.12.5",
"vue": "^3.4.15", "vue": "^3.4.15",
"vue-sonner": "^1.0.2", "vue-sonner": "^1.0.3",
"vue-wrap-balancer": "^1.1.3", "vue-wrap-balancer": "^1.1.3",
"zod": "^3.22.4" "zod": "^3.22.4"
}, },
@ -46,26 +46,27 @@
"@iconify-json/tabler": "^1.1.89", "@iconify-json/tabler": "^1.1.89",
"@iconify/json": "^2.2.108", "@iconify/json": "^2.2.108",
"@iconify/vue": "^4.1.1", "@iconify/vue": "^4.1.1",
"@shikijs/transformers": "^1.0.0-beta.3",
"@types/lodash.template": "^4.5.2", "@types/lodash.template": "^4.5.2",
"@types/node": "^20.8.10", "@types/node": "^20.8.10",
"@vitejs/plugin-vue": "^5.0.3", "@vitejs/plugin-vue": "^5.0.3",
"@vitejs/plugin-vue-jsx": "^3.1.0", "@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/compiler-core": "^3.4.14", "@vue/compiler-core": "^3.4.15",
"@vue/compiler-dom": "^3.4.14", "@vue/compiler-dom": "^3.4.15",
"@vue/tsconfig": "^0.5.1", "@vue/tsconfig": "^0.5.1",
"autoprefixer": "^10.4.16", "autoprefixer": "^10.4.17",
"lodash.template": "^4.5.0", "lodash.template": "^4.5.0",
"oxc-parser": "^0.2.0",
"pathe": "^1.1.2", "pathe": "^1.1.2",
"rimraf": "^5.0.5", "rimraf": "^5.0.5",
"shikiji": "^0.10.0-beta.9", "shiki": "^1.0.0-beta.3",
"shikiji-transformers": "^0.10.0-beta.9", "tailwind-merge": "^2.2.1",
"tailwind-merge": "^2.2.0",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"tsx": "^4.7.0", "tsx": "^4.7.0",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"unplugin-icons": "^0.17.1", "unplugin-icons": "^0.18.3",
"vite": "^5.0.12", "vite": "^5.0.12",
"vitepress": "^1.0.0-rc.39", "vitepress": "^1.0.0-rc.41",
"vue-tsc": "^1.8.27" "vue-tsc": "^1.8.27"
} }
} }

View File

@ -25,7 +25,7 @@ We'll start with the basic `<Table />` component and build a complex data table
## Table of Contents ## 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) - [Basic Table](#basic-table)
- [Row Actions](#row-actions) - [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. First, we'll define our columns in the `columns.ts` file.
```ts:line-numbers title="components/payments/columns.ts" {1,12-27} ```ts:line-numbers {1,12-27}
import type { ColumnDef } from '@tanstack/vue-table' import { h } from 'vue'
// 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
}
export const columns: ColumnDef<Payment>[] = [ export const columns: ColumnDef<Payment>[] = [
{
accessorKey: 'status',
header: 'Status',
},
{
accessorKey: 'email',
header: 'Email',
},
{ {
accessorKey: 'amount', 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. Next, we'll create a `<DataTable />` component to render our table.
```ts:line-numbers ```vue:line-numbers
<script setup lang="ts" generic="TData, TValue"> <script setup lang="ts" generic="TData, TValue">
import type { ColumnDef } from '@tanstack/vue-table' import type { ColumnDef } from '@tanstack/vue-table'
import { import {
@ -225,7 +217,7 @@ const table = useVueTable({
Finally, we'll render our table in our index component. Finally, we'll render our table in our index component.
```ts:line-numbers {28} ```vue:line-numbers {28}
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import { columns } from "./components/columns" import { columns } from "./components/columns"
@ -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: ### Add the following into your `DataTableDropDown.vue` component:
```ts:line-numbers ```vue:line-numbers
// DataTableDropDown.vue // DataTableDropDown.vue
<script setup lang="ts"> <script setup lang="ts">
import { MoreHorizontal } from 'lucide-vue-next' import { MoreHorizontal } from 'lucide-vue-next'
@ -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. We can add pagination controls to our table using the `<Button />` component and the `table.previousPage()`, `table.nextPage()` API methods.
```ts:line-numbers {3,15,21-39} ```vue:line-numbers {3,15,21-39}
// components/payments/DataTable.vue
<script lang="ts" generic="TData, TValue"> <script lang="ts" generic="TData, TValue">
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
@ -482,7 +473,7 @@ The `valueUpdater` function updates a Vue `ref` object's value. It handles both
### Update `<DataTable>` ### Update `<DataTable>`
```ts:line-numbers {4,7,16,34,41-44} ```vue:line-numbers {4,7,16,34,41-44}
<script setup lang="ts" generic="TData, TValue"> <script setup lang="ts" generic="TData, TValue">
import type { import type {
ColumnDef, ColumnDef,
@ -579,7 +570,7 @@ Let's add a search input to filter emails in our table.
### Update `<DataTable>` ### Update `<DataTable>`
```ts:line-numbers {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"> <script setup lang="ts" generic="TData, TValue">
import type { import type {
ColumnDef, ColumnDef,
@ -664,7 +655,7 @@ Adding column visibility is fairly simple using `@tanstack/vue-table` visibility
### Update `<DataTable>` ### Update `<DataTable>`
```ts:line-numbers {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"> <script setup lang="ts" generic="TData, TValue">
import type { import type {
ColumnDef, ColumnDef,
@ -829,7 +820,7 @@ export const columns: ColumnDef<Payment>[] = [
### Update `<DataTable>` ### Update `<DataTable>`
```ts:line-numbers {10,22,27} ```vue:line-numbers {10,22,27}
<script setup lang="ts" generic="TData, TValue"> <script setup lang="ts" generic="TData, TValue">
const props = defineProps<{ const props = defineProps<{
columns: ColumnDef<TData, TValue>[] 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. Make any column header sortable and hideable.
```ts:line-numbers ```vue:line-numbers
<script setup lang="ts"> <script setup lang="ts">
import type { Column } from '@tanstack/vue-table' import type { Column } from '@tanstack/vue-table'
import { type Task } from '../data/schema' 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. Add pagination controls to your table including page size and selection count.
```ts:line-numbers ```vue:line-numbers
<script setup lang="ts"> <script setup lang="ts">
import { type Table } from '@tanstack/vue-table' import { type Table } from '@tanstack/vue-table'
import { type Task } from '../data/schema' import { type Task } from '../data/schema'
@ -1093,8 +1084,7 @@ defineProps<DataTablePaginationProps>()
A component to toggle column visibility. A component to toggle column visibility.
```ts:line-numbers ```vue:line-numbers
<script setup lang="ts"> <script setup lang="ts">
import type { Table } from '@tanstack/vue-table' import type { Table } from '@tanstack/vue-table'
import { computed } from 'vue' import { computed } from 'vue'

View File

@ -47,7 +47,7 @@ import {
### Link Component ### 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 ```ts
import { navigationMenuTriggerStyle } from '@/components/ui/navigation-menu' import { navigationMenuTriggerStyle } from '@/components/ui/navigation-menu'

View File

@ -37,6 +37,6 @@ import { Skeleton } from '@/components/ui/skeleton'
</script> </script>
<template> <template>
<Skeleton class="w-[100px] h-[20px] rounded-full" /> <Skeleton class="w-[100px] h-5 rounded-full" />
</template> </template>
``` ```

View File

@ -26,7 +26,7 @@ import { Separator } from '@/lib/registry/new-york/ui/separator'
<template> <template>
<Card> <Card>
<CardHeader class="grid grid-cols-[1fr_110px] items-start gap-4 space-y-0"> <CardHeader class="grid grid-cols-[minmax(0,1fr)_110px] items-start gap-4 space-y-0">
<div class="space-y-1"> <div class="space-y-1">
<CardTitle>shadcn/ui</CardTitle> <CardTitle>shadcn/ui</CardTitle>
<CardDescription> <CardDescription>
@ -39,7 +39,7 @@ import { Separator } from '@/lib/registry/new-york/ui/separator'
<StarIcon class="mr-2 h-4 w-4" /> <StarIcon class="mr-2 h-4 w-4" />
Star Star
</Button> </Button>
<Separator orientation="vertical" class="h-[20px]" /> <Separator orientation="vertical" class="h-5" />
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger as-child> <DropdownMenuTrigger as-child>
<Button variant="secondary" class="px-2 shadow-none"> <Button variant="secondary" class="px-2 shadow-none">

View File

@ -40,7 +40,7 @@ const date = ref({
</span> </span>
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent class="w-auto p-0" :align="'end'" :avoid-collisions="true"> <PopoverContent class="w-auto p-0" :align="'end'">
<Calendar <Calendar
v-model.range="date" v-model.range="date"
:columns="2" :columns="2"

View File

@ -95,7 +95,7 @@ async function onSubmit(values: any) {
</FormField> </FormField>
<FormField v-slot="{ componentField, value }" name="dob"> <FormField v-slot="{ componentField, value }" name="dob">
<FormItem> <FormItem class="flex flex-col">
<FormLabel>Date of birth</FormLabel> <FormLabel>Date of birth</FormLabel>
<Popover> <Popover>
<PopoverTrigger as-child> <PopoverTrigger as-child>
@ -123,7 +123,7 @@ async function onSubmit(values: any) {
</FormField> </FormField>
<FormField v-slot="{ value }" name="language"> <FormField v-slot="{ value }" name="language">
<FormItem> <FormItem class="flex flex-col">
<FormLabel>Language</FormLabel> <FormLabel>Language</FormLabel>
<Popover v-model:open="open"> <Popover v-model:open="open">

View File

@ -101,7 +101,7 @@ const onSubmit = handleSubmit((values) => {
<div class="items-center rounded-md border-2 border-muted p-1 hover:border-accent"> <div class="items-center rounded-md border-2 border-muted p-1 hover:border-accent">
<div class="space-y-2 rounded-sm bg-[#ecedef] p-2"> <div class="space-y-2 rounded-sm bg-[#ecedef] p-2">
<div class="space-y-2 rounded-md bg-white p-2 shadow-sm"> <div class="space-y-2 rounded-md bg-white p-2 shadow-sm">
<div class="h-2 w-[80px] rounded-lg bg-[#ecedef]" /> <div class="h-2 w-20 rounded-lg bg-[#ecedef]" />
<div class="h-2 w-[100px] rounded-lg bg-[#ecedef]" /> <div class="h-2 w-[100px] rounded-lg bg-[#ecedef]" />
</div> </div>
<div class="flex items-center space-x-2 rounded-md bg-white p-2 shadow-sm"> <div class="flex items-center space-x-2 rounded-md bg-white p-2 shadow-sm">
@ -127,7 +127,7 @@ const onSubmit = handleSubmit((values) => {
<div class="items-center rounded-md border-2 border-muted bg-popover p-1 hover:bg-accent hover:text-accent-foreground"> <div class="items-center rounded-md border-2 border-muted bg-popover p-1 hover:bg-accent hover:text-accent-foreground">
<div class="space-y-2 rounded-sm bg-slate-950 p-2"> <div class="space-y-2 rounded-sm bg-slate-950 p-2">
<div class="space-y-2 rounded-md bg-slate-800 p-2 shadow-sm"> <div class="space-y-2 rounded-md bg-slate-800 p-2 shadow-sm">
<div class="h-2 w-[80px] rounded-lg bg-slate-400" /> <div class="h-2 w-20 rounded-lg bg-slate-400" />
<div class="h-2 w-[100px] rounded-lg bg-slate-400" /> <div class="h-2 w-[100px] rounded-lg bg-slate-400" />
</div> </div>
<div class="flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-sm"> <div class="flex items-center space-x-2 rounded-md bg-slate-800 p-2 shadow-sm">

View File

@ -57,7 +57,7 @@ import CounterClockwiseClockIcon from '~icons/radix-icons/counter-clockwise-cloc
<Separator /> <Separator />
<Tabs default-value="complete" class="flex-1"> <Tabs default-value="complete" class="flex-1">
<div class="container h-full py-6"> <div class="container h-full py-6">
<div class="grid h-full items-stretch gap-6 md:grid-cols-[1fr_200px]"> <div class="grid h-full items-stretch gap-6 md:grid-cols-[minmax(0,1fr)_200px]">
<div class="hidden flex-col space-y-4 sm:flex md:order-2"> <div class="hidden flex-col space-y-4 sm:flex md:order-2">
<div class="grid gap-2"> <div class="grid gap-2">
<HoverCard :open-delay="200"> <HoverCard :open-delay="200">

View File

@ -12,16 +12,16 @@ export const columns: ColumnDef<Task>[] = [
{ {
id: 'select', id: 'select',
header: ({ table }) => h(Checkbox, header: ({ table }) => h(Checkbox,
{ 'checked': table.getIsAllPageRowsSelected(), 'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value), 'ariaLabel': 'Select all', 'class': 'translate-y-[2px]' }), { 'checked': table.getIsAllPageRowsSelected(), 'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value), 'ariaLabel': 'Select all', 'class': 'translate-y-0.5' }),
cell: ({ row }) => h(Checkbox, cell: ({ row }) => h(Checkbox,
{ 'checked': row.getIsSelected(), 'onUpdate:checked': value => row.toggleSelected(!!value), 'ariaLabel': 'Select row', 'class': 'translate-y-[2px]' }), { 'checked': row.getIsSelected(), 'onUpdate:checked': value => row.toggleSelected(!!value), 'ariaLabel': 'Select row', 'class': 'translate-y-0.5' }),
enableSorting: false, enableSorting: false,
enableHiding: false, enableHiding: false,
}, },
{ {
accessorKey: 'id', accessorKey: 'id',
header: ({ column }) => h(DataTableColumnHeader, { column, title: 'Task' }), header: ({ column }) => h(DataTableColumnHeader, { column, title: 'Task' }),
cell: ({ row }) => h('div', { class: 'w-[80px]' }, row.getValue('id')), cell: ({ row }) => h('div', { class: 'w-20' }, row.getValue('id')),
enableSorting: false, enableSorting: false,
enableHiding: false, enableHiding: false,
}, },

View File

@ -51,7 +51,7 @@ const notifications = [
<div> <div>
<div <div
v-for="(notification, index) in notifications" :key="index" v-for="(notification, index) in notifications" :key="index"
class="mb-4 grid grid-cols-[25px_1fr] items-start pb-4 last:mb-0 last:pb-0" class="mb-4 grid grid-cols-[25px_minmax(0,1fr)] items-start pb-4 last:mb-0 last:pb-0"
> >
<span class="flex h-2 w-2 translate-y-1 rounded-full bg-sky-500" /> <span class="flex h-2 w-2 translate-y-1 rounded-full bg-sky-500" />
<div class="space-y-1"> <div class="space-y-1">

View File

@ -1,5 +1,12 @@
<script setup lang='ts'> <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 { import {
Select, Select,
SelectContent, SelectContent,

View File

@ -43,7 +43,7 @@ const lineY = (d: Data) => d.revenue
+20.1% from last month +20.1% from last month
</p> </p>
<div class="h-[80px]"> <div class="h-20">
<VisXYContainer <VisXYContainer
height="80px" height="80px"
:data="data" :margin="{ :data="data" :margin="{
@ -79,7 +79,7 @@ const lineY = (d: Data) => d.revenue
+54.8% from last month +54.8% from last month
</p> </p>
<div class="mt-4 h-[80px]"> <div class="mt-4 h-20">
<VisXYContainer <VisXYContainer
height="80px" :data="data" :style="{ height="80px" :data="data" :style="{
'--theme-primary': `hsl(${ '--theme-primary': `hsl(${

View File

@ -14,7 +14,7 @@ import {
useVueTable, useVueTable,
} from '@tanstack/vue-table' } from '@tanstack/vue-table'
import { h, ref } from 'vue' 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 DropdownAction from '../DataTableDemoColumn.vue'
import { Button } from '@/lib/registry/default/ui/button' import { Button } from '@/lib/registry/default/ui/button'
@ -104,7 +104,7 @@ const columns: ColumnDef<Payment>[] = [
return h(Button, { return h(Button, {
variant: 'ghost', variant: 'ghost',
onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'), 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')), cell: ({ row }) => h('div', { class: 'lowercase' }, row.getValue('email')),
}, },
@ -179,7 +179,7 @@ const table = useVueTable({
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger as-child> <DropdownMenuTrigger as-child>
<Button variant="outline" class="ml-auto"> <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> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end"> <DropdownMenuContent align="end">

View File

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { ref } from 'vue'
import { CaretSortIcon, CheckIcon } from '@radix-icons/vue' import { Check, ChevronsUpDown } from 'lucide-vue-next'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { Button } from '@/lib/registry/default/ui/button' import { Button } from '@/lib/registry/default/ui/button'
@ -44,7 +44,7 @@ const value = ref<string>('')
{{ value {{ value
? frameworks.find((framework) => framework.value === value)?.label ? frameworks.find((framework) => framework.value === value)?.label
: "Select framework..." }} : "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> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent class="w-[200px] p-0"> <PopoverContent class="w-[200px] p-0">
@ -65,7 +65,7 @@ const value = ref<string>('')
}" }"
> >
{{ framework.label }} {{ framework.label }}
<CheckIcon <Check
:class="cn( :class="cn(
'ml-auto h-4 w-4', 'ml-auto h-4 w-4',
value === framework.value ? 'opacity-100' : 'opacity-0', value === framework.value ? 'opacity-100' : 'opacity-0',

View File

@ -40,7 +40,7 @@ const date = ref({
</span> </span>
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent class="w-auto p-0" align="start" :avoid-collisions="true"> <PopoverContent class="w-auto p-0" align="start">
<Calendar <Calendar
v-model.range="date" v-model.range="date"
:columns="2" :columns="2"

View File

@ -55,7 +55,7 @@ const components: { title: string; href: string; description: string }[] = [
<NavigationMenuItem> <NavigationMenuItem>
<NavigationMenuTrigger>Getting started</NavigationMenuTrigger> <NavigationMenuTrigger>Getting started</NavigationMenuTrigger>
<NavigationMenuContent> <NavigationMenuContent>
<ul class="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]"> <ul class="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[minmax(0,.75fr)_minmax(0,1fr)]">
<li class="row-span-3"> <li class="row-span-3">
<NavigationMenuLink as-child> <NavigationMenuLink as-child>
<a <a

View File

@ -11,5 +11,5 @@ watchEffect((cleanupFn) => {
</script> </script>
<template> <template>
<Progress v-model="progress" class="w-[60%]" /> <Progress v-model="progress" class="w-3/5" />
</template> </template>

View File

@ -40,7 +40,7 @@ const date = ref({
</span> </span>
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent class="w-auto p-0" align="start" :avoid-collisions="true"> <PopoverContent class="w-auto p-0" align="start">
<Calendar <Calendar
v-model.range="date" v-model.range="date"
mode="date" mode="date"

View File

@ -11,6 +11,6 @@ const modelValue = ref([50])
v-model="modelValue" v-model="modelValue"
:max="100" :max="100"
:step="1" :step="1"
:class="cn('w-[60%]', $attrs.class ?? '')" :class="cn('w-3/5', $attrs.class ?? '')"
/> />
</template> </template>

View File

@ -3,15 +3,17 @@ import {
AccordionRoot, AccordionRoot,
type AccordionRootEmits, type AccordionRootEmits,
type AccordionRootProps, type AccordionRootProps,
useEmitAsProps, useForwardPropsEmits,
} from 'radix-vue' } from 'radix-vue'
const props = defineProps<AccordionRootProps>() const props = defineProps<AccordionRootProps>()
const emits = defineEmits<AccordionRootEmits>() const emits = defineEmits<AccordionRootEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script> </script>
<template> <template>
<AccordionRoot v-bind="{ ...props, ...useEmitAsProps(emits) }"> <AccordionRoot v-bind="forwarded">
<slot /> <slot />
</AccordionRoot> </AccordionRoot>
</template> </template>

View File

@ -1,21 +1,23 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { AccordionContent, type AccordionContentProps } from 'radix-vue' import { AccordionContent, type AccordionContentProps } from 'radix-vue'
import { cn } from '@/lib/utils' 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> </script>
<template> <template>
<AccordionContent <AccordionContent
v-bind="props" v-bind="delegatedProps"
:class=" class="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
cn(
'overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down',
props.class,
)
"
> >
<div class="pb-4 pt-0"> <div :class="cn('pb-4 pt-0', props.class)">
<slot /> <slot />
</div> </div>
</AccordionContent> </AccordionContent>

View File

@ -1,14 +1,23 @@
<script setup lang="ts"> <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' 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> </script>
<template> <template>
<AccordionItem <AccordionItem
v-bind="props" v-bind="forwardedProps"
:class="cn('border-b', props.class ?? '')" :class="cn('border-b', props.class)"
> >
<slot /> <slot />
</AccordionItem> </AccordionItem>

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
AccordionHeader, AccordionHeader,
AccordionTrigger, AccordionTrigger,
@ -7,13 +8,19 @@ import {
import { ChevronDown } from 'lucide-vue-next' import { ChevronDown } from 'lucide-vue-next'
import { cn } from '@/lib/utils' 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> </script>
<template> <template>
<AccordionHeader class="flex" as="div"> <AccordionHeader class="flex">
<AccordionTrigger <AccordionTrigger
v-bind="props" v-bind="delegatedProps"
:class=" :class="
cn( cn(
'flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180', '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 /> <slot />
<ChevronDown <slot name="icon">
class="h-4 w-4 shrink-0 transition-transform duration-200" <ChevronDown
/> class="h-4 w-4 shrink-0 transition-transform duration-200"
/>
</slot>
</AccordionTrigger> </AccordionTrigger>
</AccordionHeader> </AccordionHeader>
</template> </template>

View File

@ -1,13 +1,20 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { AlertDialogAction, type AlertDialogActionProps } from 'radix-vue' import { AlertDialogAction, type AlertDialogActionProps } from 'radix-vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { buttonVariants } from '@/lib/registry/default/ui/button' 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> </script>
<template> <template>
<AlertDialogAction v-bind="props" :class="cn(buttonVariants(), $attrs.class ?? '')"> <AlertDialogAction v-bind="delegatedProps" :class="cn(buttonVariants(), props.class)">
<slot /> <slot />
</AlertDialogAction> </AlertDialogAction>
</template> </template>

View File

@ -1,13 +1,20 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { AlertDialogCancel, type AlertDialogCancelProps } from 'radix-vue' import { AlertDialogCancel, type AlertDialogCancelProps } from 'radix-vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { buttonVariants } from '@/lib/registry/default/ui/button' 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> </script>
<template> <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 /> <slot />
</AlertDialogCancel> </AlertDialogCancel>
</template> </template>

View File

@ -1,30 +1,37 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
AlertDialogContent, AlertDialogContent,
type AlertDialogContentEmits, type AlertDialogContentEmits,
type AlertDialogContentProps, type AlertDialogContentProps,
AlertDialogOverlay, AlertDialogOverlay,
AlertDialogPortal, AlertDialogPortal,
useEmitAsProps, useForwardPropsEmits,
} from 'radix-vue' } from 'radix-vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<AlertDialogContentProps & { class?: string }>() const props = defineProps<AlertDialogContentProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<AlertDialogContentEmits>() const emits = defineEmits<AlertDialogContentEmits>()
const emitsAsProps = useEmitAsProps(emits) const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
<AlertDialogPortal> <AlertDialogPortal>
<AlertDialogOverlay <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 <AlertDialogContent
v-bind="{ ...props, ...emitsAsProps }" v-bind="forwarded"
:class=" :class="
cn( cn(
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] 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, props.class,
) )
" "

View File

@ -1,17 +1,24 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
AlertDialogDescription, AlertDialogDescription,
type AlertDialogDescriptionProps, type AlertDialogDescriptionProps,
} from 'radix-vue' } from 'radix-vue'
import { cn } from '@/lib/utils' 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> </script>
<template> <template>
<AlertDialogDescription <AlertDialogDescription
:class="cn('text-muted-foreground text-sm', props.class)" v-bind="delegatedProps"
:as-child="props.asChild" :class="cn('text-sm text-muted-foreground', props.class)"
> >
<slot /> <slot />
</AlertDialogDescription> </AlertDialogDescription>

View File

@ -1,19 +1,17 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps({ const props = defineProps<{
class: { class?: HTMLAttributes['class']
type: String, }>()
default: '',
},
})
</script> </script>
<template> <template>
<div <div
:class=" :class="
cn( 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, props.class,
) )
" "

View File

@ -1,17 +1,15 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps({ const props = defineProps<{
class: { class?: HTMLAttributes['class']
type: String, }>()
default: '',
},
})
</script> </script>
<template> <template>
<div <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 /> <slot />
</div> </div>

View File

@ -1,14 +1,21 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { AlertDialogTitle, type AlertDialogTitleProps } from 'radix-vue' import { AlertDialogTitle, type AlertDialogTitleProps } from 'radix-vue'
import { cn } from '@/lib/utils' 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> </script>
<template> <template>
<AlertDialogTitle <AlertDialogTitle
:as-child="props.asChild" v-bind="delegatedProps"
:class="cn('text-lg text-foreground font-semibold', props.class)" :class="cn('text-lg font-semibold', props.class)"
> >
<slot /> <slot />
</AlertDialogTitle> </AlertDialogTitle>

View File

@ -1,17 +1,16 @@
<script setup lang="ts"> <script setup lang="ts">
import { alertVariants } from '.' import type { HTMLAttributes } from 'vue'
import { type AlertVariants, alertVariants } from '.'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
interface Props { const props = defineProps<{
variant?: NonNullable<Parameters<typeof alertVariants>[0]>['variant'] class?: HTMLAttributes['class']
class?: string variant?: AlertVariants['variant']
} }>()
const props = defineProps<Props>()
</script> </script>
<template> <template>
<div :class="cn(alertVariants({ variant }), props.class ?? '')"> <div :class="cn(alertVariants({ variant }), props.class)" role="alert">
<slot /> <slot />
</div> </div>
</template> </template>

View File

@ -1,9 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps({ const props = defineProps<{
class: String, class?: HTMLAttributes['class']
}) }>()
</script> </script>
<template> <template>

View File

@ -1,9 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script> </script>
<template> <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 /> <slot />
</h5> </h5>
</template> </template>

View File

@ -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 Alert } from './Alert.vue'
export { default as AlertTitle } from './AlertTitle.vue' export { default as AlertTitle } from './AlertTitle.vue'
@ -19,3 +19,5 @@ export const alertVariants = cva(
}, },
}, },
) )
export type AlertVariants = VariantProps<typeof alertVariants>

View File

@ -1,15 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { AvatarRoot } from 'radix-vue' import { AvatarRoot } from 'radix-vue'
import { avatarVariant } from '.' import { type AvatarVariants, avatarVariant } from '.'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
interface Props { const props = withDefaults(defineProps<{
size?: NonNullable<Parameters<typeof avatarVariant>[0]>['size'] class?: HTMLAttributes['class']
shape?: NonNullable<Parameters<typeof avatarVariant>[0]>['shape'] size?: AvatarVariants['size']
class?: string shape?: AvatarVariants['shape']
} }>(), {
const props = withDefaults(defineProps<Props>(), {
size: 'sm', size: 'sm',
shape: 'circle', shape: 'circle',
}) })

View File

@ -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 Avatar } from './Avatar.vue'
export { default as AvatarImage } from './AvatarImage.vue' export { default as AvatarImage } from './AvatarImage.vue'
@ -20,3 +20,5 @@ export const avatarVariant = cva(
}, },
}, },
) )
export type AvatarVariants = VariantProps<typeof avatarVariant>

View File

@ -1,18 +1,16 @@
<script setup lang="ts"> <script setup lang="ts">
import type { VariantProps } from 'class-variance-authority' import type { HTMLAttributes } from 'vue'
import { badgeVariants } from '.' import { type BadgeVariants, badgeVariants } from '.'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
interface BadgeVariantProps extends VariantProps<typeof badgeVariants> {} const props = defineProps<{
variant?: BadgeVariants['variant']
interface Props { class?: HTMLAttributes['class']
variant?: BadgeVariantProps['variant'] }>()
}
defineProps<Props>()
</script> </script>
<template> <template>
<div :class="cn(badgeVariants({ variant }), $attrs.class ?? '')"> <div :class="cn(badgeVariants({ variant }), props.class)">
<slot /> <slot />
</div> </div>
</template> </template>

View File

@ -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' export { default as Badge } from './Badge.vue'
@ -21,3 +21,5 @@ export const badgeVariants = cva(
}, },
}, },
) )
export type BadgeVariants = VariantProps<typeof badgeVariants>

View File

@ -1,20 +1,17 @@
<script setup lang="ts"> <script setup lang="ts">
import type { VariantProps } from 'class-variance-authority' import type { HTMLAttributes } from 'vue'
import { Primitive, type PrimitiveProps } from 'radix-vue' import { Primitive, type PrimitiveProps } from 'radix-vue'
import { buttonVariants } from '.' import { type ButtonVariants, buttonVariants } from '.'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
interface ButtonVariantProps extends VariantProps<typeof buttonVariants> {}
interface Props extends PrimitiveProps { interface Props extends PrimitiveProps {
variant?: ButtonVariantProps['variant'] variant?: ButtonVariants['variant']
size?: ButtonVariantProps['size'] size?: ButtonVariants['size']
as?: string as?: string
class?: HTMLAttributes['class']
} }
withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
variant: 'default',
size: 'default',
as: 'button', as: 'button',
}) })
</script> </script>
@ -23,7 +20,7 @@ withDefaults(defineProps<Props>(), {
<Primitive <Primitive
:as="as" :as="as"
:as-child="asChild" :as-child="asChild"
:class="cn(buttonVariants({ variant, size }), $attrs.class ?? '')" :class="cn(buttonVariants({ variant, size }), props.class)"
> >
<slot /> <slot />
</Primitive> </Primitive>

View File

@ -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 { default as Button } from './Button.vue'
export const buttonVariants = cva( 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: { variants: {
variant: { variant: {
@ -30,3 +30,5 @@ export const buttonVariants = cva(
}, },
}, },
) )
export type ButtonVariants = VariantProps<typeof buttonVariants>

View File

@ -1,12 +1,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { useVModel } from '@vueuse/core' import { useVModel } from '@vueuse/core'
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
import type { Calendar } from 'v-calendar' import type { Calendar } from 'v-calendar'
import { DatePicker } from 'v-calendar' import { DatePicker } from 'v-calendar'
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
import { computed, nextTick, onMounted, ref, useSlots } from 'vue' import { computed, nextTick, onMounted, ref, useSlots } from 'vue'
import { isVCalendarSlot } from '.' import { isVCalendarSlot } from '.'
import { buttonVariants } from '@/lib/registry/default/ui/button'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { buttonVariants } from '@/lib/registry/default/ui/button'
/* Extracted from v-calendar */ /* Extracted from v-calendar */
type DatePickerModel = DatePickerDate | DatePickerRangeObject type DatePickerModel = DatePickerDate | DatePickerRangeObject
@ -29,8 +29,7 @@ interface SimpleDateParts {
defineOptions({ defineOptions({
inheritAttrs: false, inheritAttrs: false,
}) })
const props = withDefaults(defineProps< {
const props = withDefaults(defineProps<{
modelValue?: string | number | Date | DatePickerModel modelValue?: string | number | Date | DatePickerModel
modelModifiers?: object modelModifiers?: object
columns?: number columns?: number
@ -90,8 +89,8 @@ const vCalendarSlots = computed(() => {
<DatePicker <DatePicker
ref="datePicker" ref="datePicker"
v-model="modelValue"
v-bind="$attrs" v-bind="$attrs"
v-model="modelValue"
:model-modifiers="modelModifiers" :model-modifiers="modelModifiers"
class="calendar" class="calendar"
trim-weeks trim-weeks
@ -101,11 +100,19 @@ const vCalendarSlots = computed(() => {
<template v-for="(_, slot) of vCalendarSlots" #[slot]="scope"> <template v-for="(_, slot) of vCalendarSlots" #[slot]="scope">
<slot :name="slot" v-bind="scope" /> <slot :name="slot" v-bind="scope" />
</template> </template>
<template #nav-prev-button>
<ChevronLeft />
</template>
<template #nav-next-button>
<ChevronRight />
</template>
</DatePicker> </DatePicker>
</div> </div>
</template> </template>
<style lang="postcss"> <style lang="css">
.calendar { .calendar {
@apply p-3 text-center; @apply p-3 text-center;
} }
@ -113,7 +120,25 @@ const vCalendarSlots = computed(() => {
@apply grid gap-4; @apply grid gap-4;
} }
.calendar .vc-title { .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 { .calendar .vc-pane-header-wrapper {
@apply hidden; @apply hidden;
@ -125,16 +150,22 @@ const vCalendarSlots = computed(() => {
@apply flex; @apply flex;
} }
.calendar .vc-weekday { .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 { .calendar .vc-weeks {
@apply w-full space-y-2 flex flex-col [&>_div]:grid [&>_div]:grid-cols-7; @apply w-full space-y-2 flex flex-col [&>_div]:grid [&>_div]:grid-cols-7;
} }
.calendar .vc-day:has(.vc-highlights) { .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)) { .calendar .vc-day.is-today:not(:has(.vc-day-layer)) .vc-day-content {
@apply bg-secondary rounded-md; @apply bg-secondary text-primary rounded-md;
} }
.calendar .vc-day:has(.vc-highlight-base-start) { .calendar .vc-day:has(.vc-highlight-base-start) {
@apply rounded-l-md; @apply rounded-l-md;
@ -146,7 +177,7 @@ const vCalendarSlots = computed(() => {
@apply rounded-md; @apply rounded-md;
} }
.calendar .vc-day-content { .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) { .calendar .vc-day-content:not(.vc-highlight-content-light) {
@apply rounded-md; @apply rounded-md;
@ -172,6 +203,7 @@ const vCalendarSlots = computed(() => {
--vc-slide-duration: 0.15s; --vc-slide-duration: 0.15s;
--vc-slide-timing: ease; --vc-slide-timing: ease;
} }
.calendar .vc-fade-enter-active, .calendar .vc-fade-enter-active,
.calendar .vc-fade-leave-active, .calendar .vc-fade-leave-active,
.calendar .vc-slide-left-enter-active, .calendar .vc-slide-left-enter-active,
@ -198,6 +230,7 @@ const vCalendarSlots = computed(() => {
backface-visibility: hidden; backface-visibility: hidden;
pointer-events: none; pointer-events: none;
} }
.calendar .vc-none-leave-active, .calendar .vc-none-leave-active,
.calendar .vc-fade-leave-active, .calendar .vc-fade-leave-active,
.calendar .vc-slide-left-leave-active, .calendar .vc-slide-left-leave-active,
@ -207,6 +240,7 @@ const vCalendarSlots = computed(() => {
position: absolute !important; position: absolute !important;
width: 100%; width: 100%;
} }
.calendar .vc-none-enter-from, .calendar .vc-none-enter-from,
.calendar .vc-none-leave-to, .calendar .vc-none-leave-to,
.calendar .vc-fade-enter-from, .calendar .vc-fade-enter-from,
@ -223,6 +257,7 @@ const vCalendarSlots = computed(() => {
.calendar .vc-slide-fade-leave-to { .calendar .vc-slide-fade-leave-to {
opacity: 0; opacity: 0;
} }
.calendar .vc-slide-left-enter-from, .calendar .vc-slide-left-enter-from,
.calendar .vc-slide-right-leave-to, .calendar .vc-slide-right-leave-to,
.calendar .vc-slide-fade-enter-from.direction-left, .calendar .vc-slide-fade-enter-from.direction-left,
@ -230,6 +265,7 @@ const vCalendarSlots = computed(() => {
-webkit-transform: translateX(var(--vc-slide-translate)); -webkit-transform: translateX(var(--vc-slide-translate));
transform: translateX(var(--vc-slide-translate)); transform: translateX(var(--vc-slide-translate));
} }
.calendar .vc-slide-right-enter-from, .calendar .vc-slide-right-enter-from,
.calendar .vc-slide-left-leave-to, .calendar .vc-slide-left-leave-to,
.calendar .vc-slide-fade-enter-from.direction-right, .calendar .vc-slide-fade-enter-from.direction-right,
@ -237,6 +273,7 @@ const vCalendarSlots = computed(() => {
-webkit-transform: translateX(calc(-1 * var(--vc-slide-translate))); -webkit-transform: translateX(calc(-1 * var(--vc-slide-translate)));
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-up-enter-from,
.calendar .vc-slide-down-leave-to, .calendar .vc-slide-down-leave-to,
.calendar .vc-slide-fade-enter-from.direction-top, .calendar .vc-slide-fade-enter-from.direction-top,
@ -244,6 +281,7 @@ const vCalendarSlots = computed(() => {
-webkit-transform: translateY(var(--vc-slide-translate)); -webkit-transform: translateY(var(--vc-slide-translate));
transform: translateY(var(--vc-slide-translate)); transform: translateY(var(--vc-slide-translate));
} }
.calendar .vc-slide-down-enter-from, .calendar .vc-slide-down-enter-from,
.calendar .vc-slide-up-leave-to, .calendar .vc-slide-up-leave-to,
.calendar .vc-slide-fade-enter-from.direction-bottom, .calendar .vc-slide-fade-enter-from.direction-bottom,

View File

@ -1,12 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps({ const props = defineProps<{
class: { class?: HTMLAttributes['class']
type: String, }>()
default: '',
},
})
</script> </script>
<template> <template>

View File

@ -1,12 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps({ const props = defineProps<{
class: { class?: HTMLAttributes['class']
type: String, }>()
default: '',
},
})
</script> </script>
<template> <template>

View File

@ -1,12 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps({ const props = defineProps<{
class: { class?: HTMLAttributes['class']
type: String, }>()
default: '',
},
})
</script> </script>
<template> <template>

View File

@ -1,16 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps({ const props = defineProps<{
class: { class?: HTMLAttributes['class']
type: String, }>()
default: '',
},
})
</script> </script>
<template> <template>
<div :class="cn('p-6 pt-0', props.class)"> <div :class="cn('flex items-center p-6 pt-0', props.class)">
<slot /> <slot />
</div> </div>
</template> </template>

View File

@ -1,16 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps({ const props = defineProps<{
class: { class?: HTMLAttributes['class']
type: String, }>()
default: '',
},
})
</script> </script>
<template> <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 /> <slot />
</div> </div>
</template> </template>

View File

@ -1,18 +1,16 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps({ const props = defineProps<{
class: { class?: HTMLAttributes['class']
type: String, }>()
default: '',
},
})
</script> </script>
<template> <template>
<h3 <h3
:class=" :class="
cn('text-2xl font-semibold leading-none tracking-tighter', props.class) cn('text-2xl font-semibold leading-none tracking-tight', props.class)
" "
> >
<slot /> <slot />

View File

@ -1,5 +1,4 @@
<script setup lang="ts"> <script setup lang="ts">
import emblaCarouselVue from 'embla-carousel-vue'
import { useProvideCarousel } from './useCarousel' import { useProvideCarousel } from './useCarousel'
import type { CarouselEmits, CarouselProps, WithClassAsProps } from './interface' import type { CarouselEmits, CarouselProps, WithClassAsProps } from './interface'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'

View File

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { WithClassAsProps } from './interface'
import { useCarousel } from './useCarousel' import { useCarousel } from './useCarousel'
import type { WithClassAsProps } from './interface'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
defineOptions({ defineOptions({

View File

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { WithClassAsProps } from './interface'
import { useCarousel } from './useCarousel' import { useCarousel } from './useCarousel'
import type { WithClassAsProps } from './interface'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<WithClassAsProps>() const props = defineProps<WithClassAsProps>()

View File

@ -1,13 +1,20 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import type { CheckboxRootEmits, CheckboxRootProps } from 'radix-vue' import type { CheckboxRootEmits, CheckboxRootProps } from 'radix-vue'
import { CheckboxIndicator, CheckboxRoot, useForwardPropsEmits } from 'radix-vue' import { CheckboxIndicator, CheckboxRoot, useForwardPropsEmits } from 'radix-vue'
import { Check } from 'lucide-vue-next' import { Check } from 'lucide-vue-next'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<CheckboxRootProps>() const props = defineProps<CheckboxRootProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<CheckboxRootEmits>() const emits = defineEmits<CheckboxRootEmits>()
const forwarded = useForwardPropsEmits(props, emits) const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
@ -15,10 +22,12 @@ const forwarded = useForwardPropsEmits(props, emits)
v-bind="forwarded" v-bind="forwarded"
:class=" :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', 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"> <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> </CheckboxIndicator>
</CheckboxRoot> </CheckboxRoot>
</template> </template>

View File

@ -1,13 +1,15 @@
<script setup lang="ts"> <script setup lang="ts">
import { CollapsibleRoot, useEmitAsProps } from 'radix-vue' import { CollapsibleRoot, useForwardPropsEmits } from 'radix-vue'
import type { CollapsibleRootEmits, CollapsibleRootProps } from 'radix-vue' import type { CollapsibleRootEmits, CollapsibleRootProps } from 'radix-vue'
const props = defineProps<CollapsibleRootProps>() const props = defineProps<CollapsibleRootProps>()
const emits = defineEmits<CollapsibleRootEmits>() const emits = defineEmits<CollapsibleRootEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script> </script>
<template> <template>
<CollapsibleRoot v-slot="{ open }" v-bind="{ ...props, ...useEmitAsProps(emits) }"> <CollapsibleRoot v-slot="{ open }" v-bind="forwarded">
<slot :open="open" /> <slot :open="open" />
</CollapsibleRoot> </CollapsibleRoot>
</template> </template>

View File

@ -1,20 +1,29 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import type { ComboboxRootEmits, ComboboxRootProps } from 'radix-vue' import type { ComboboxRootEmits, ComboboxRootProps } from 'radix-vue'
import { ComboboxRoot, useForwardPropsEmits } from 'radix-vue' import { ComboboxRoot, useForwardPropsEmits } from 'radix-vue'
import { cn } from '@/lib/utils' 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 emits = defineEmits<ComboboxRootEmits>()
const forwarded = useForwardPropsEmits(props, emits) const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
<ComboboxRoot <ComboboxRoot
v-bind="forwarded" v-bind="forwarded"
:open="true" :class="cn('flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground', props.class)"
:model-value="''"
:class="cn('flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground', $attrs.class ?? '')"
> >
<slot /> <slot />
</ComboboxRoot> </ComboboxRoot>

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { useEmitAsProps } from 'radix-vue' import { useForwardPropsEmits } from 'radix-vue'
import type { DialogRootEmits, DialogRootProps } from 'radix-vue' import type { DialogRootEmits, DialogRootProps } from 'radix-vue'
import Command from './Command.vue' import Command from './Command.vue'
import { Dialog, DialogContent } from '@/lib/registry/default/ui/dialog' 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 props = defineProps<DialogRootProps>()
const emits = defineEmits<DialogRootEmits>() const emits = defineEmits<DialogRootEmits>()
const emitsAsProps = useEmitAsProps(emits) const forwarded = useForwardPropsEmits(props, emits)
</script> </script>
<template> <template>
<Dialog v-bind="{ ...props, ...emitsAsProps }"> <Dialog v-bind="forwarded">
<DialogContent class="p-0 overflow-hidden shadow-lg"> <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"> <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 /> <slot />
</Command> </Command>

View File

@ -1,13 +1,20 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import type { ComboboxEmptyProps } from 'radix-vue' import type { ComboboxEmptyProps } from 'radix-vue'
import { ComboboxEmpty } from 'radix-vue' import { ComboboxEmpty } from 'radix-vue'
import { cn } from '@/lib/utils' 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> </script>
<template> <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 /> <slot />
</ComboboxEmpty> </ComboboxEmpty>
</template> </template>

View File

@ -1,17 +1,25 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import type { ComboboxGroupProps } from 'radix-vue' import type { ComboboxGroupProps } from 'radix-vue'
import { ComboboxGroup, ComboboxLabel } from 'radix-vue' import { ComboboxGroup, ComboboxLabel } from 'radix-vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<ComboboxGroupProps & { const props = defineProps<ComboboxGroupProps & {
class?: HTMLAttributes['class']
heading?: string heading?: string
}>() }>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
</script> </script>
<template> <template>
<ComboboxGroup <ComboboxGroup
v-bind="props" v-bind="delegatedProps"
:class="cn('overflow-hidden p-1 text-foreground', $attrs.class ?? '')" :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"> <ComboboxLabel v-if="heading" class="px-2 py-1.5 text-xs font-medium text-muted-foreground">
{{ heading }} {{ heading }}

View File

@ -1,24 +1,33 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { Search } from 'lucide-vue-next' 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' import { cn } from '@/lib/utils'
const props = defineProps<ComboboxInputProps>() defineOptions({
</script>
<script lang="ts">
export default {
inheritAttrs: false, inheritAttrs: false,
} })
const props = defineProps<ComboboxInputProps & {
class?: HTMLAttributes['class']
}>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script> </script>
<template> <template>
<div class="flex items-center border-b px-3" cmdk-input-wrapper> <div class="flex items-center border-b px-3" cmdk-input-wrapper>
<Search class="mr-2 h-4 w-4 shrink-0 opacity-50" /> <Search class="mr-2 h-4 w-4 shrink-0 opacity-50" />
<ComboboxInput <ComboboxInput
v-bind="{ ...props, ...$attrs }" v-bind="{ ...forwardedProps, ...$attrs }"
auto-focus 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> </div>
</template> </template>

View File

@ -1,18 +1,25 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import type { ComboboxItemEmits, ComboboxItemProps } from 'radix-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' import { cn } from '@/lib/utils'
const props = defineProps<ComboboxItemProps>() const props = defineProps<ComboboxItemProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<ComboboxItemEmits>() const emits = defineEmits<ComboboxItemEmits>()
const emitsAsProps = useEmitAsProps(emits) const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
<ComboboxItem <ComboboxItem
v-bind="{ ...props, ...emitsAsProps }" v-bind="forwarded"
: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 ?? '')" :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 @select.prevent
> >
<slot /> <slot />

View File

@ -1,16 +1,23 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import type { ComboboxContentEmits, ComboboxContentProps } from 'radix-vue' import type { ComboboxContentEmits, ComboboxContentProps } from 'radix-vue'
import { ComboboxContent, useForwardPropsEmits } from 'radix-vue' import { ComboboxContent, useForwardPropsEmits } from 'radix-vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<ComboboxContentProps>() const props = defineProps<ComboboxContentProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<ComboboxContentEmits>() const emits = defineEmits<ComboboxContentEmits>()
const forwarded = useForwardPropsEmits(props, emits) const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <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"> <div role="presentation">
<slot /> <slot />
</div> </div>

View File

@ -1,15 +1,22 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import type { ComboboxSeparatorProps } from 'radix-vue' import type { ComboboxSeparatorProps } from 'radix-vue'
import { ComboboxSeparator } from 'radix-vue' import { ComboboxSeparator } from 'radix-vue'
import { cn } from '@/lib/utils' 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> </script>
<template> <template>
<ComboboxSeparator <ComboboxSeparator
v-bind="props" v-bind="delegatedProps"
:class="cn('-mx-1 h-px bg-border', $attrs.class ?? '')" :class="cn('-mx-1 h-px bg-border', props.class)"
> >
<slot /> <slot />
</ComboboxSeparator> </ComboboxSeparator>

View File

@ -1,9 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script> </script>
<template> <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 /> <slot />
</span> </span>
</template> </template>

View File

@ -1,33 +1,38 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
ContextMenuCheckboxItem, ContextMenuCheckboxItem,
type ContextMenuCheckboxItemEmits, type ContextMenuCheckboxItemEmits,
type ContextMenuCheckboxItemProps, type ContextMenuCheckboxItemProps,
ContextMenuItemIndicator, ContextMenuItemIndicator,
useEmitAsProps, useForwardPropsEmits,
} from 'radix-vue' } from 'radix-vue'
import { Check } from 'lucide-vue-next' import { Check } from 'lucide-vue-next'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<ContextMenuCheckboxItemProps & { class?: string }>() const props = defineProps<ContextMenuCheckboxItemProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<ContextMenuCheckboxItemEmits>() const emits = defineEmits<ContextMenuCheckboxItemEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
<ContextMenuCheckboxItem <ContextMenuCheckboxItem
v-bind="{ ...props, ...useEmitAsProps(emits) }" v-bind="forwarded"
:class="[ :class="cn(
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',
'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,
props.class, )"
),
]"
> >
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<ContextMenuItemIndicator <ContextMenuItemIndicator>
class="absolute left-1.5 inline-flex w-4 h-4 items-center justify-center" <Check class="h-4 w-4" />
>
<Check class="h-4 h-w" />
</ContextMenuItemIndicator> </ContextMenuItemIndicator>
</span> </span>
<slot /> <slot />

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
ContextMenuContent, ContextMenuContent,
type ContextMenuContentEmits, type ContextMenuContentEmits,
@ -8,23 +9,26 @@ import {
} from 'radix-vue' } from 'radix-vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<ContextMenuContentProps & { class?: string }>() const props = defineProps<ContextMenuContentProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<ContextMenuContentEmits>() const emits = defineEmits<ContextMenuContentEmits>()
const forwarded = useForwardPropsEmits(props, emits) const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
<ContextMenuPortal> <ContextMenuPortal>
<ContextMenuContent <ContextMenuContent
:align-offset="props.alignOffset"
:class="[
cn(
'z-50 min-w-[8rem] 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" 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 /> <slot />
</ContextMenuContent> </ContextMenuContent>

View File

@ -1,26 +1,33 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
ContextMenuItem, ContextMenuItem,
type ContextMenuItemEmits, type ContextMenuItemEmits,
type ContextMenuItemProps, type ContextMenuItemProps,
useEmitAsProps, useForwardPropsEmits,
} from 'radix-vue' } from 'radix-vue'
import { cn } from '@/lib/utils' 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 emits = defineEmits<ContextMenuItemEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
<ContextMenuItem <ContextMenuItem
v-bind="{ ...props, ...useEmitAsProps(emits) }" v-bind="forwarded"
:class="[ :class="cn(
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',
'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',
inset && 'pl-8', props.class,
props.class, )"
),
]"
> >
<slot /> <slot />
</ContextMenuItem> </ContextMenuItem>

View File

@ -1,16 +1,23 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { ContextMenuLabel, type ContextMenuLabelProps } from 'radix-vue' import { ContextMenuLabel, type ContextMenuLabelProps } from 'radix-vue'
import { cn } from '@/lib/utils' 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> </script>
<template> <template>
<ContextMenuLabel <ContextMenuLabel
v-bind="props" v-bind="delegatedProps"
:class=" :class="
cn('px-2 py-1.5 text-sm font-semibold text-foreground', cn('px-2 py-1.5 text-sm font-semibold text-foreground',
inset && 'pl-8', props.class ?? '', inset && 'pl-8', props.class,
)" )"
> >
<slot /> <slot />

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
ContextMenuItemIndicator, ContextMenuItemIndicator,
ContextMenuRadioItem, ContextMenuRadioItem,
@ -9,21 +10,25 @@ import {
import { Circle } from 'lucide-vue-next' import { Circle } from 'lucide-vue-next'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<ContextMenuRadioItemProps & { class?: string }>() const props = defineProps<ContextMenuRadioItemProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<ContextMenuRadioItemEmits>() const emits = defineEmits<ContextMenuRadioItemEmits>()
const forwarded = useForwardPropsEmits(props, emits) const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
<ContextMenuRadioItem <ContextMenuRadioItem
v-bind="forwarded" v-bind="forwarded"
:class="[ :class="cn(
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',
'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,
props.class, )"
),
]"
> >
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<ContextMenuItemIndicator> <ContextMenuItemIndicator>

View File

@ -1,13 +1,20 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
ContextMenuSeparator, ContextMenuSeparator,
type ContextMenuSeparatorProps, type ContextMenuSeparatorProps,
} from 'radix-vue' } from 'radix-vue'
import { cn } from '@/lib/utils' 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> </script>
<template> <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> </template>

View File

@ -1,9 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script> </script>
<template> <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 /> <slot />
</span> </span>
</template> </template>

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
ContextMenuSubContent, ContextMenuSubContent,
type DropdownMenuSubContentEmits, type DropdownMenuSubContentEmits,
@ -7,10 +8,16 @@ import {
} from 'radix-vue' } from 'radix-vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<DropdownMenuSubContentProps & { class?: string }>() const props = defineProps<DropdownMenuSubContentProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<DropdownMenuSubContentEmits>() const emits = defineEmits<DropdownMenuSubContentEmits>()
const forwarded = useForwardPropsEmits(props, emits) const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
@ -18,7 +25,7 @@ const forwarded = useForwardPropsEmits(props, emits)
v-bind="forwarded" v-bind="forwarded"
:class=" :class="
cn( cn(
'z-50 min-w-[8rem] 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', '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, props.class,
) )
" "

View File

@ -1,24 +1,32 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
ContextMenuSubTrigger, ContextMenuSubTrigger,
type ContextMenuSubTriggerProps, type ContextMenuSubTriggerProps,
useForwardProps,
} from 'radix-vue' } from 'radix-vue'
import { ChevronRight } from 'lucide-vue-next' import { ChevronRight } from 'lucide-vue-next'
import { cn } from '@/lib/utils' 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> </script>
<template> <template>
<ContextMenuSubTrigger <ContextMenuSubTrigger
v-bind="props" v-bind="forwardedProps"
:class="[ :class="cn(
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',
'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',
inset && 'pl-8', props.class,
props.class, )"
),
]"
> >
<slot /> <slot />
<ChevronRight class="ml-auto h-4 w-4" /> <ChevronRight class="ml-auto h-4 w-4" />

View File

@ -1,11 +1,13 @@
<script setup lang="ts"> <script setup lang="ts">
import { ContextMenuTrigger, type ContextMenuTriggerProps } from 'radix-vue' import { ContextMenuTrigger, type ContextMenuTriggerProps, useForwardProps } from 'radix-vue'
const props = defineProps<ContextMenuTriggerProps>() const props = defineProps<ContextMenuTriggerProps>()
const forwardedProps = useForwardProps(props)
</script> </script>
<template> <template>
<ContextMenuTrigger v-bind="props"> <ContextMenuTrigger v-bind="forwardedProps">
<slot /> <slot />
</ContextMenuTrigger> </ContextMenuTrigger>
</template> </template>

View File

@ -1,14 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { DialogRoot, type DialogRootEmits, type DialogRootProps, useForwardPropsEmits } from 'radix-vue' import { DialogRoot, type DialogRootEmits, type DialogRootProps, useForwardPropsEmits } from 'radix-vue'
const props = defineProps<DialogRootProps>() const props = defineProps<DialogRootProps>()
const emits = defineEmits<DialogRootEmits>() const emits = defineEmits<DialogRootEmits>()
const forwarded = useForwardPropsEmits(props, emits) const forwarded = useForwardPropsEmits(props, emits)
</script> </script>
<template> <template>
<DialogRoot v-bind="forwarded"> <DialogRoot v-bind="forwarded">
<slot /> <slot />
</DialogRoot> </DialogRoot>
</template> </template>

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
DialogClose, DialogClose,
DialogContent, DialogContent,
@ -6,35 +7,40 @@ import {
type DialogContentProps, type DialogContentProps,
DialogOverlay, DialogOverlay,
DialogPortal, DialogPortal,
useEmitAsProps, useForwardPropsEmits,
} from 'radix-vue' } from 'radix-vue'
import { X } from 'lucide-vue-next' import { X } from 'lucide-vue-next'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<DialogContentProps & { class?: string }>() const props = defineProps<DialogContentProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<DialogContentEmits>() const emits = defineEmits<DialogContentEmits>()
const emitsAsProps = useEmitAsProps(emits) const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
<DialogPortal> <DialogPortal>
<DialogOverlay <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 <DialogContent
v-bind="forwarded"
:class=" :class="
cn( cn(
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] 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, props.class,
) )"
"
v-bind="{ ...props, ...emitsAsProps }"
> >
<slot /> <slot />
<DialogClose <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" /> <X class="w-4 h-4" />
<span class="sr-only">Close</span> <span class="sr-only">Close</span>

View File

@ -1,14 +1,23 @@
<script setup lang="ts"> <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' 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> </script>
<template> <template>
<DialogDescription <DialogDescription
v-bind="props" v-bind="forwardedProps"
:class="cn('text-muted-foreground text-sm', props.class)" :class="cn('text-sm text-muted-foreground', props.class)"
> >
<slot /> <slot />
</DialogDescription> </DialogDescription>

View File

@ -1,18 +1,15 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
interface DialogFooterProps { const props = defineProps<{ class?: HTMLAttributes['class'] }>()
class?: string
}
const props = defineProps<DialogFooterProps>()
</script> </script>
<template> <template>
<div <div
:class=" :class="
cn( 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, props.class,
) )
" "

View File

@ -1,16 +1,15 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
interface DialogHeaderProps { const props = defineProps<{
class?: string class?: HTMLAttributes['class']
} }>()
const props = defineProps<DialogHeaderProps>()
</script> </script>
<template> <template>
<div <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 /> <slot />
</div> </div>

View File

@ -1,16 +1,25 @@
<script setup lang="ts"> <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' 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> </script>
<template> <template>
<DialogTitle <DialogTitle
v-bind="props" v-bind="forwardedProps"
:class=" :class="
cn( cn(
'text-lg text-foreground font-semibold leading-none tracking-tight', 'text-lg font-semibold leading-none tracking-tight',
props.class, props.class,
) )
" "

View File

@ -1,21 +1,30 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
DropdownMenuCheckboxItem, DropdownMenuCheckboxItem,
type DropdownMenuCheckboxItemEmits, type DropdownMenuCheckboxItemEmits,
type DropdownMenuCheckboxItemProps, type DropdownMenuCheckboxItemProps,
DropdownMenuItemIndicator, DropdownMenuItemIndicator,
useEmitAsProps, useForwardPropsEmits,
} from 'radix-vue' } from 'radix-vue'
import { Check } from 'lucide-vue-next' import { Check } from 'lucide-vue-next'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<DropdownMenuCheckboxItemProps & { class?: string }>() const props = defineProps<DropdownMenuCheckboxItemProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<DropdownMenuCheckboxItemEmits>() const emits = defineEmits<DropdownMenuCheckboxItemEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
<DropdownMenuCheckboxItem <DropdownMenuCheckboxItem
v-bind="{ ...props, ...useEmitAsProps(emits) }" v-bind="forwarded"
:class=" cn( :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', '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, props.class,

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
DropdownMenuContent, DropdownMenuContent,
type DropdownMenuContentEmits, type DropdownMenuContentEmits,
@ -9,26 +10,27 @@ import {
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = withDefaults( const props = withDefaults(
defineProps<DropdownMenuContentProps & { class?: string }>(), defineProps<DropdownMenuContentProps & { class?: HTMLAttributes['class'] }>(),
{ {
sideOffset: 4, sideOffset: 4,
}, },
) )
const emits = defineEmits<DropdownMenuContentEmits>() const emits = defineEmits<DropdownMenuContentEmits>()
const forwarded = useForwardPropsEmits(props, emits) const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
<DropdownMenuPortal> <DropdownMenuPortal>
<DropdownMenuContent <DropdownMenuContent
:class="[
cn(
'z-50 min-w-[8rem] 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" 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 /> <slot />
</DropdownMenuContent> </DropdownMenuContent>

View File

@ -1,20 +1,27 @@
<script setup lang="ts"> <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' 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> </script>
<template> <template>
<DropdownMenuItem <DropdownMenuItem
v-bind="props" v-bind="forwardedProps"
:class="[ :class="cn(
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',
'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',
inset && 'pl-8', props.class,
props.class, )"
),
]"
> >
<slot /> <slot />
</DropdownMenuItem> </DropdownMenuItem>

View File

@ -1,19 +1,23 @@
<script setup lang="ts"> <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' import { cn } from '@/lib/utils'
const props = defineProps<DropdownMenuLabelProps & { const props = defineProps<DropdownMenuLabelProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
inset?: boolean
class?: string const delegatedProps = computed(() => {
}>() const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script> </script>
<template> <template>
<DropdownMenuLabel <DropdownMenuLabel
v-bind="props" v-bind="forwardedProps"
:class=" :class="cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', props.class)"
cn('px-2 py-1.5 text-sm font-semibold',
inset && 'pl-8', props.class)"
> >
<slot /> <slot />
</DropdownMenuLabel> </DropdownMenuLabel>

View File

@ -3,18 +3,17 @@ import {
DropdownMenuRadioGroup, DropdownMenuRadioGroup,
type DropdownMenuRadioGroupEmits, type DropdownMenuRadioGroupEmits,
type DropdownMenuRadioGroupProps, type DropdownMenuRadioGroupProps,
useForwardPropsEmits,
} from 'radix-vue' } from 'radix-vue'
const props = defineProps<DropdownMenuRadioGroupProps>() const props = defineProps<DropdownMenuRadioGroupProps>()
const emits = defineEmits<DropdownMenuRadioGroupEmits>() const emits = defineEmits<DropdownMenuRadioGroupEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script> </script>
<template> <template>
<DropdownMenuRadioGroup <DropdownMenuRadioGroup v-bind="forwarded">
v-bind="props"
@update:model-value="emits('update:modelValue', $event)"
>
<slot /> <slot />
</DropdownMenuRadioGroup> </DropdownMenuRadioGroup>
</template> </template>

View File

@ -1,29 +1,37 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
DropdownMenuItemIndicator, DropdownMenuItemIndicator,
DropdownMenuRadioItem, DropdownMenuRadioItem,
type DropdownMenuRadioItemEmits, type DropdownMenuRadioItemEmits,
type DropdownMenuRadioItemProps, type DropdownMenuRadioItemProps,
useEmitAsProps, useForwardPropsEmits,
} from 'radix-vue' } from 'radix-vue'
import { Circle } from 'lucide-vue-next' import { Circle } from 'lucide-vue-next'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<DropdownMenuRadioItemProps & { class?: string }>() const props = defineProps<DropdownMenuRadioItemProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<DropdownMenuRadioItemEmits>() const emits = defineEmits<DropdownMenuRadioItemEmits>()
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
<DropdownMenuRadioItem <DropdownMenuRadioItem
v-bind="{ ...props, ...useEmitAsProps(emits) }" v-bind="forwarded"
:class="cn( :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, props.class,
)" )"
> >
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuItemIndicator> <DropdownMenuItemIndicator>
<Circle class="h-2 w-2 fill-current" /> <Circle class="h-2 w-2 fill-current" />
</DropdownMenuItemIndicator> </DropdownMenuItemIndicator>

View File

@ -1,12 +1,22 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
DropdownMenuSeparator, DropdownMenuSeparator,
type DropdownMenuSeparatorProps, type DropdownMenuSeparatorProps,
} from 'radix-vue' } 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> </script>
<template> <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> </template>

View File

@ -1,9 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script> </script>
<template> <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 /> <slot />
</span> </span>
</template> </template>

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
DropdownMenuSubContent, DropdownMenuSubContent,
type DropdownMenuSubContentEmits, type DropdownMenuSubContentEmits,
@ -7,16 +8,22 @@ import {
} from 'radix-vue' } from 'radix-vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
const props = defineProps<DropdownMenuSubContentProps>() const props = defineProps<DropdownMenuSubContentProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<DropdownMenuSubContentEmits>() const emits = defineEmits<DropdownMenuSubContentEmits>()
const forwarded = useForwardPropsEmits(props, emits) const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script> </script>
<template> <template>
<DropdownMenuSubContent <DropdownMenuSubContent
v-bind="forwarded" v-bind="forwarded"
:class="cn('z-50 min-w-[8rem] 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 /> <slot />
</DropdownMenuSubContent> </DropdownMenuSubContent>

View File

@ -1,23 +1,31 @@
<script setup lang="ts"> <script setup lang="ts">
import { type HTMLAttributes, computed } from 'vue'
import { import {
DropdownMenuSubTrigger, DropdownMenuSubTrigger,
type DropdownMenuSubTriggerProps, type DropdownMenuSubTriggerProps,
useForwardProps,
} from 'radix-vue' } from 'radix-vue'
import { ChevronRight } from 'lucide-vue-next' import { ChevronRight } from 'lucide-vue-next'
import { cn } from '@/lib/utils' 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> </script>
<template> <template>
<DropdownMenuSubTrigger <DropdownMenuSubTrigger
v-bind="props" v-bind="forwardedProps"
:class="[ :class="cn(
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',
'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,
props.class, )"
),
]"
> >
<slot /> <slot />
<ChevronRight class="ml-auto h-4 w-4" /> <ChevronRight class="ml-auto h-4 w-4" />

View File

@ -1,11 +1,13 @@
<script setup lang="ts"> <script setup lang="ts">
import { DropdownMenuTrigger, type DropdownMenuTriggerProps } from 'radix-vue' import { DropdownMenuTrigger, type DropdownMenuTriggerProps, useForwardProps } from 'radix-vue'
const props = defineProps<DropdownMenuTriggerProps>() const props = defineProps<DropdownMenuTriggerProps>()
const forwardedProps = useForwardProps(props)
</script> </script>
<template> <template>
<DropdownMenuTrigger class="outline-none" v-bind="props"> <DropdownMenuTrigger class="outline-none" v-bind="forwardedProps">
<slot /> <slot />
</DropdownMenuTrigger> </DropdownMenuTrigger>
</template> </template>

View File

@ -1,21 +1,19 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useAttrs } from 'vue' import type { HTMLAttributes } from 'vue'
import { useFormField } from './useFormField' import { useFormField } from './useFormField'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
defineOptions({ const props = defineProps<{
inheritAttrs: false, class?: HTMLAttributes['class']
}) }>()
const { formDescriptionId } = useFormField() const { formDescriptionId } = useFormField()
const { class: className, ...rest } = useAttrs()
</script> </script>
<template> <template>
<p <p
:id="formDescriptionId" :id="formDescriptionId"
:class="cn('text-sm text-muted-foreground', className ?? '')" :class="cn('text-sm text-muted-foreground', props.class)"
v-bind="rest"
> >
<slot /> <slot />
</p> </p>

View File

@ -1,27 +1,25 @@
<script lang="ts"> <script lang="ts">
import { type InjectionKey } from 'vue' import type { HTMLAttributes, InjectionKey } from 'vue'
export const FORM_ITEM_INJECTION_KEY export const FORM_ITEM_INJECTION_KEY
= Symbol() as InjectionKey<string> = Symbol() as InjectionKey<string>
</script> </script>
<script lang="ts" setup> <script lang="ts" setup>
import { provide, useAttrs } from 'vue' import { provide } from 'vue'
import { useId } from 'radix-vue' import { useId } from 'radix-vue'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
defineOptions({ const props = defineProps<{
inheritAttrs: false, class?: HTMLAttributes['class']
}) }>()
const id = useId() const id = useId()
provide(FORM_ITEM_INJECTION_KEY, id) provide(FORM_ITEM_INJECTION_KEY, id)
const { class: className, ...rest } = useAttrs()
</script> </script>
<template> <template>
<div :class="cn('space-y-2', className ?? '')" v-bind="rest"> <div :class="cn('space-y-2', props.class)">
<slot /> <slot />
</div> </div>
</template> </template>

Some files were not shown because too many files have changed in this diff Show More