Merge branch 'dev' into feature/command-custom-filter
This commit is contained in:
commit
f9c7e15dfe
|
|
@ -1,19 +0,0 @@
|
||||||
// const process = require('node:process')
|
|
||||||
// process.env.ESLINT_TSCONFIG = 'tsconfig.json'
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
extends: '@antfu',
|
|
||||||
|
|
||||||
rules: {
|
|
||||||
'vue/one-component-per-file': 'off',
|
|
||||||
'vue/no-reserved-component-names': 'off',
|
|
||||||
'vue/no-useless-v-bind': 'off',
|
|
||||||
'symbol-description': 'off',
|
|
||||||
'no-console': 'warn',
|
|
||||||
'no-tabs': 'off',
|
|
||||||
'no-invalid-character': 'off',
|
|
||||||
'import/first': 'off',
|
|
||||||
'@stylistic/js/no-tabs': 'off',
|
|
||||||
'n/prefer-global/process': 'off',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
77
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
77
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
|
|
@ -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
|
||||||
|
|
|
||||||
5
.github/workflows/publish.yaml
vendored
5
.github/workflows/publish.yaml
vendored
|
|
@ -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
|
||||||
|
|
|
||||||
14
.vscode/settings.json
vendored
14
.vscode/settings.json
vendored
|
|
@ -1,11 +1,23 @@
|
||||||
{
|
{
|
||||||
|
"eslint.experimental.useFlatConfig": true,
|
||||||
"prettier.enable": false,
|
"prettier.enable": false,
|
||||||
"editor.formatOnSave": false,
|
"editor.formatOnSave": false,
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": "explicit",
|
"source.fixAll.eslint": "explicit",
|
||||||
"source.organizeImports": "never"
|
"source.organizeImports": "never"
|
||||||
},
|
},
|
||||||
|
"eslint.rules.customizations": [
|
||||||
|
{ "rule": "style/*", "severity": "off" },
|
||||||
|
{ "rule": "format/*", "severity": "off" },
|
||||||
|
{ "rule": "*-indent", "severity": "off" },
|
||||||
|
{ "rule": "*-spacing", "severity": "off" },
|
||||||
|
{ "rule": "*-spaces", "severity": "off" },
|
||||||
|
{ "rule": "*-order", "severity": "off" },
|
||||||
|
{ "rule": "*-dangle", "severity": "off" },
|
||||||
|
{ "rule": "*-newline", "severity": "off" },
|
||||||
|
{ "rule": "*quotes", "severity": "off" },
|
||||||
|
{ "rule": "*semi", "severity": "off" }
|
||||||
|
],
|
||||||
"eslint.validate": [
|
"eslint.validate": [
|
||||||
"javascript",
|
"javascript",
|
||||||
"javascriptreact",
|
"javascriptreact",
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,15 @@ 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, 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'
|
||||||
|
|
||||||
const cssVariables = createCssVariablesTheme({
|
const cssVariables = createCssVariablesTheme({
|
||||||
name: 'css-variables',
|
|
||||||
variablePrefix: '--shiki-',
|
variablePrefix: '--shiki-',
|
||||||
variableDefaults: {},
|
variableDefaults: {},
|
||||||
fontStyle: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// https://vitepress.dev/reference/site-config
|
// https://vitepress.dev/reference/site-config
|
||||||
|
|
@ -59,6 +59,10 @@ export default defineConfig({
|
||||||
srcDir: path.resolve(__dirname, '../src'),
|
srcDir: path.resolve(__dirname, '../src'),
|
||||||
markdown: {
|
markdown: {
|
||||||
theme: cssVariables,
|
theme: cssVariables,
|
||||||
|
codeTransformers: [
|
||||||
|
// transformerMetaWordHighlight(),
|
||||||
|
// transformerNotationWordHighlight(),
|
||||||
|
],
|
||||||
config(md) {
|
config(md) {
|
||||||
md.use(ComponentPreviewPlugin)
|
md.use(ComponentPreviewPlugin)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import PageHeader from '../components/PageHeader.vue'
|
import PageHeader from '../components/PageHeader.vue'
|
||||||
import PageHeaderHeading from '../components/PageHeaderHeading.vue'
|
import PageHeaderHeading from '../components/PageHeaderHeading.vue'
|
||||||
import PageHeaderDescription from '../components/PageHeaderDescription.vue'
|
import PageHeaderDescription from '../components/PageHeaderDescription.vue'
|
||||||
|
import PageAction from '../components/PageAction.vue'
|
||||||
import ExamplesNav from '../components/ExamplesNav.vue'
|
import ExamplesNav from '../components/ExamplesNav.vue'
|
||||||
import { announcementConfig } from '../config/site'
|
import { announcementConfig } from '../config/site'
|
||||||
import GitHubIcon from '~icons/radix-icons/github-logo'
|
import GitHubIcon from '~icons/radix-icons/github-logo'
|
||||||
|
|
@ -31,7 +32,7 @@ import DashboardExample from '@/examples/dashboard/Example.vue'
|
||||||
apps. Accessible. Customizable. Open Source.
|
apps. Accessible. Customizable. Open Source.
|
||||||
</PageHeaderDescription>
|
</PageHeaderDescription>
|
||||||
|
|
||||||
<section class="flex w-full items-center space-x-4 pb-8 pt-4 md:pb-10">
|
<PageAction>
|
||||||
<a
|
<a
|
||||||
href="/docs/introduction"
|
href="/docs/introduction"
|
||||||
:class="cn(buttonVariants(), 'rounded-[6px]')"
|
:class="cn(buttonVariants(), 'rounded-[6px]')"
|
||||||
|
|
@ -49,7 +50,7 @@ import DashboardExample from '@/examples/dashboard/Example.vue'
|
||||||
<GitHubIcon class="mr-2 h-4 w-4" />
|
<GitHubIcon class="mr-2 h-4 w-4" />
|
||||||
GitHub
|
GitHub
|
||||||
</a>
|
</a>
|
||||||
</section>
|
</PageAction>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
<ExamplesNav />
|
<ExamplesNav />
|
||||||
<section class="space-y-8 overflow-hidden rounded-lg border-2 border-primary dark:border-muted md:hidden">
|
<section class="space-y-8 overflow-hidden rounded-lg border-2 border-primary dark:border-muted md:hidden">
|
||||||
|
|
|
||||||
14
apps/www/.vitepress/theme/components/PageAction.vue
Normal file
14
apps/www/.vitepress/theme/components/PageAction.vue
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<section
|
||||||
|
:class="cn(
|
||||||
|
'flex w-full items-center justify-center space-x-4 py-4 md:pb-10',
|
||||||
|
$attrs.class ?? '',
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
@ -7,7 +7,7 @@ import { cn } from '@/lib/utils'
|
||||||
<template>
|
<template>
|
||||||
<section
|
<section
|
||||||
:class="cn(
|
:class="cn(
|
||||||
'flex max-w-[980px] flex-col items-start gap-2 px-4 pt-8 md:pt-12',
|
'mx-auto flex max-w-[980px] flex-col items-center gap-2 py-8 md:py-12 md:pb-8 lg:py-24 lg:pb-20',
|
||||||
$attrs.class ?? '',
|
$attrs.class ?? '',
|
||||||
)"
|
)"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { cn } from '@/lib/utils'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<WrapBalancer :class="cn('max-w-[750px] text-lg text-muted-foreground sm:text-xl', $attrs.class ?? '')" :prefer-native="false">
|
<WrapBalancer :class="cn('max-w-[750px] text-center text-lg text-muted-foreground sm:text-xl', $attrs.class ?? '')" :prefer-native="false">
|
||||||
<slot />
|
<slot />
|
||||||
</WrapBalancer>
|
</WrapBalancer>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { cn } from '@/lib/utils'
|
||||||
<template>
|
<template>
|
||||||
<h1
|
<h1
|
||||||
:class="cn(
|
:class="cn(
|
||||||
'text-3xl font-bold leading-tight tracking-tighter md:text-5xl lg:leading-[1.1]',
|
'text-center text-3xl font-bold leading-tight tracking-tighter md:text-6xl lg:leading-[1.1]',
|
||||||
$attrs.class ?? '',
|
$attrs.class ?? '',
|
||||||
)"
|
)"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -254,6 +254,12 @@ export const docsConfig: DocsConfig = {
|
||||||
href: '/docs/components/pagination',
|
href: '/docs/components/pagination',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Pin Input',
|
||||||
|
href: '/docs/components/pin-input',
|
||||||
|
label: 'New',
|
||||||
|
items: [],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Popover',
|
title: 'Popover',
|
||||||
href: '/docs/components/popover',
|
href: '/docs/components/popover',
|
||||||
|
|
@ -299,6 +305,12 @@ export const docsConfig: DocsConfig = {
|
||||||
href: '/docs/components/slider',
|
href: '/docs/components/slider',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Sonner',
|
||||||
|
href: '/docs/components/sonner',
|
||||||
|
label: 'New',
|
||||||
|
items: [],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Switch',
|
title: 'Switch',
|
||||||
href: '/docs/components/switch',
|
href: '/docs/components/switch',
|
||||||
|
|
@ -314,6 +326,12 @@ export const docsConfig: DocsConfig = {
|
||||||
href: '/docs/components/tabs',
|
href: '/docs/components/tabs',
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Tags Input',
|
||||||
|
href: '/docs/components/tags-input',
|
||||||
|
label: 'New',
|
||||||
|
items: [],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Textarea',
|
title: 'Textarea',
|
||||||
href: '/docs/components/textarea',
|
href: '/docs/components/textarea',
|
||||||
|
|
@ -322,7 +340,6 @@ export const docsConfig: DocsConfig = {
|
||||||
{
|
{
|
||||||
title: 'Toast',
|
title: 'Toast',
|
||||||
href: '/docs/components/toast',
|
href: '/docs/components/toast',
|
||||||
label: 'New',
|
|
||||||
items: [],
|
items: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,6 @@ export const siteConfig = {
|
||||||
|
|
||||||
export const announcementConfig = {
|
export const announcementConfig = {
|
||||||
icon: '✨',
|
icon: '✨',
|
||||||
title: 'VSCode extension',
|
title: 'New components!',
|
||||||
link: '/docs/installation.html#vscode-extension',
|
link: '/docs/components/carousel.html',
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import EditLink from '../components/EditLink.vue'
|
||||||
import { ScrollArea } from '@/lib/registry/default/ui/scroll-area'
|
import { ScrollArea } from '@/lib/registry/default/ui/scroll-area'
|
||||||
import { Badge } from '@/lib/registry/default/ui/badge'
|
import { Badge } from '@/lib/registry/default/ui/badge'
|
||||||
import RadixIconsCode from '~icons/radix-icons/code'
|
import RadixIconsCode from '~icons/radix-icons/code'
|
||||||
|
import RadixIconsExternalLink from '~icons/radix-icons/external-link'
|
||||||
import ChevronRightIcon from '~icons/lucide/chevron-right'
|
import ChevronRightIcon from '~icons/lucide/chevron-right'
|
||||||
|
|
||||||
const $route = useRoute()
|
const $route = useRoute()
|
||||||
|
|
@ -20,7 +21,7 @@ const sourceLink = 'https://github.com/radix-vue/shadcn-vue/tree/dev/'
|
||||||
<aside
|
<aside
|
||||||
class="fixed top-14 z-30 -ml-2 hidden h-[calc(100vh-3.5rem)] w-full shrink-0 md:sticky md:block overflow-y-auto"
|
class="fixed top-14 z-30 -ml-2 hidden h-[calc(100vh-3.5rem)] w-full shrink-0 md:sticky md:block overflow-y-auto"
|
||||||
>
|
>
|
||||||
<ScrollArea orientation="vertical" class="h-full py-6 pl-8 pr-6 lg:py-8" :type="'auto'">
|
<ScrollArea orientation="vertical" class="relative overflow-hidden h-full py-6 pr-6 lg:py-8" :type="'auto'">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div v-for="docsGroup in docsConfig.sidebarNav" :key="docsGroup.title" class="pb-4">
|
<div v-for="docsGroup in docsConfig.sidebarNav" :key="docsGroup.title" class="pb-4">
|
||||||
<h4
|
<h4
|
||||||
|
|
@ -45,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>
|
||||||
|
|
@ -81,6 +82,10 @@ const sourceLink = 'https://github.com/radix-vue/shadcn-vue/tree/dev/'
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center space-x-2 pt-4">
|
<div class="flex items-center space-x-2 pt-4">
|
||||||
|
<a v-if="frontmatter.docs" :href="frontmatter.docs" target="_blank" class="inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 select-none border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80">
|
||||||
|
<RadixIconsExternalLink class="mr-1" />
|
||||||
|
Docs
|
||||||
|
</a>
|
||||||
<a v-if="frontmatter.source" :href="sourceLink + frontmatter.source" target="_blank" class="inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 select-none border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80">
|
<a v-if="frontmatter.source" :href="sourceLink + frontmatter.source" target="_blank" class="inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 select-none border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80">
|
||||||
<RadixIconsCode class="mr-1" />
|
<RadixIconsCode class="mr-1" />
|
||||||
Component Source
|
Component Source
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import PageHeader from '../components/PageHeader.vue'
|
import PageHeader from '../components/PageHeader.vue'
|
||||||
import PageHeaderHeading from '../components/PageHeaderHeading.vue'
|
import PageHeaderHeading from '../components/PageHeaderHeading.vue'
|
||||||
import PageHeaderDescription from '../components/PageHeaderDescription.vue'
|
import PageHeaderDescription from '../components/PageHeaderDescription.vue'
|
||||||
|
import PageAction from '../components/PageAction.vue'
|
||||||
import ExamplesNav from '../components/ExamplesNav.vue'
|
import ExamplesNav from '../components/ExamplesNav.vue'
|
||||||
import { announcementConfig } from '../config/site'
|
import { announcementConfig } from '../config/site'
|
||||||
import ArrowRightIcon from '~icons/radix-icons/arrow-right'
|
import ArrowRightIcon from '~icons/radix-icons/arrow-right'
|
||||||
|
|
@ -36,7 +37,7 @@ import { cn } from '@/lib/utils'
|
||||||
components. Use this as a guide to build your own.
|
components. Use this as a guide to build your own.
|
||||||
</PageHeaderDescription>
|
</PageHeaderDescription>
|
||||||
|
|
||||||
<section class="flex w-full items-center space-x-4 pb-8 pt-4 md:pb-10">
|
<PageAction>
|
||||||
<a
|
<a
|
||||||
href="/docs/introduction"
|
href="/docs/introduction"
|
||||||
:class="cn(buttonVariants(), 'rounded-[6px]')"
|
:class="cn(buttonVariants(), 'rounded-[6px]')"
|
||||||
|
|
@ -52,7 +53,7 @@ import { cn } from '@/lib/utils'
|
||||||
>
|
>
|
||||||
Components
|
Components
|
||||||
</a>
|
</a>
|
||||||
</section>
|
</PageAction>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
<section>
|
<section>
|
||||||
<ExamplesNav />
|
<ExamplesNav />
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import RadixIconsSun from '~icons/radix-icons/sun'
|
||||||
import { useConfigStore } from '@/stores/config'
|
import { useConfigStore } from '@/stores/config'
|
||||||
import { Dialog, DialogContent } from '@/lib/registry/default/ui/dialog'
|
import { Dialog, DialogContent } from '@/lib/registry/default/ui/dialog'
|
||||||
import { Toaster as DefaultToaster } from '@/lib/registry/default/ui/toast'
|
import { Toaster as DefaultToaster } from '@/lib/registry/default/ui/toast'
|
||||||
|
import { Toaster as NewYorkSonner } from '@/lib/registry/new-york/ui/sonner'
|
||||||
import { Toaster as NewYorkToaster } from '@/lib/registry/new-york/ui/toast'
|
import { Toaster as NewYorkToaster } from '@/lib/registry/new-york/ui/toast'
|
||||||
|
|
||||||
import File from '~icons/radix-icons/file'
|
import File from '~icons/radix-icons/file'
|
||||||
|
|
@ -86,7 +87,7 @@ watch(() => $route.path, (n) => {
|
||||||
<div class="flex min-h-screen flex-col bg-background">
|
<div class="flex min-h-screen flex-col bg-background">
|
||||||
<header class="sticky z-40 top-0 bg-background/80 backdrop-blur-lg border-b border-border">
|
<header class="sticky z-40 top-0 bg-background/80 backdrop-blur-lg border-b border-border">
|
||||||
<div
|
<div
|
||||||
class="container flex justify-between h-14 items-center"
|
class="container flex justify-between h-14 max-w-screen-2xl items-center"
|
||||||
>
|
>
|
||||||
<MobileNav />
|
<MobileNav />
|
||||||
|
|
||||||
|
|
@ -134,20 +135,22 @@ 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
|
<ClientOnly>
|
||||||
class="flex items-center justify-center"
|
<Button
|
||||||
aria-label="Toggle dark mode"
|
class="flex items-center justify-center"
|
||||||
:variant="'ghost'"
|
aria-label="Toggle dark mode"
|
||||||
:size="'icon'" @click="toggleDark()"
|
:variant="'ghost'"
|
||||||
>
|
:size="'icon'" @click="toggleDark()"
|
||||||
<component
|
>
|
||||||
:is="isDark ? RadixIconsSun : RadixIconsMoon"
|
<component
|
||||||
class="w-[20px] h-[20px] text-foreground"
|
:is="isDark ? RadixIconsSun : RadixIconsMoon"
|
||||||
/>
|
class="w-[20px] h-5 text-foreground"
|
||||||
</Button>
|
/>
|
||||||
|
</Button>
|
||||||
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -287,6 +290,9 @@ watch(() => $route.path, (n) => {
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
<DefaultToaster />
|
<DefaultToaster />
|
||||||
|
<ClientOnly>
|
||||||
|
<NewYorkSonner :theme="isDark ? 'dark' : 'light'" />
|
||||||
|
</ClientOnly>
|
||||||
<NewYorkToaster />
|
<NewYorkToaster />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,53 +1,55 @@
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap");
|
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: 0 0% 100%;
|
--font-geist-sans: "geist-sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||||
--foreground: 240 10% 3.9%;
|
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
--card: 0 0% 100%;
|
|
||||||
--card-foreground: 240 10% 3.9%;
|
--background: 0 0% 100%;
|
||||||
--popover: 0 0% 100%;
|
--foreground: 240 10% 3.9%;
|
||||||
--popover-foreground: 240 10% 3.9%;
|
--card: 0 0% 100%;
|
||||||
--primary: 240 5.9% 10%;
|
--card-foreground: 240 10% 3.9%;
|
||||||
--primary-foreground: 0 0% 98%;
|
--popover: 0 0% 100%;
|
||||||
--secondary: 240 4.8% 95.9%;
|
--popover-foreground: 240 10% 3.9%;
|
||||||
--secondary-foreground: 240 5.9% 10%;
|
--primary: 240 5.9% 10%;
|
||||||
--muted: 240 4.8% 95.9%;
|
--primary-foreground: 0 0% 98%;
|
||||||
--muted-foreground: 240 3.8% 46.1%;
|
--secondary: 240 4.8% 95.9%;
|
||||||
--accent: 240 4.8% 95.9%;
|
--secondary-foreground: 240 5.9% 10%;
|
||||||
--accent-foreground: 240 5.9% 10%;
|
--muted: 240 4.8% 95.9%;
|
||||||
--destructive: 0 84.2% 60.2%;
|
--muted-foreground: 240 3.8% 46.1%;
|
||||||
--destructive-foreground: 0 0% 98%;
|
--accent: 240 4.8% 95.9%;
|
||||||
--border: 240 5.9% 90%;
|
--accent-foreground: 240 5.9% 10%;
|
||||||
--input: 240 5.9% 90%;
|
--destructive: 0 72.22% 50.59%;
|
||||||
--ring: 240 5% 64.9%;
|
--destructive-foreground: 0 0% 98%;
|
||||||
--radius: 0.5rem;
|
--border: 240 5.9% 90%;
|
||||||
}
|
--input: 240 5.9% 90%;
|
||||||
|
--ring: 240 5% 64.9%;
|
||||||
|
--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%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
|
@ -68,6 +70,16 @@
|
||||||
-webkit-tap-highlight-color: rgba(128, 128, 128, 0.5);
|
-webkit-tap-highlight-color: rgba(128, 128, 128, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Font face Geist font */
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "geist-sans";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100 900;
|
||||||
|
font-display: swap;
|
||||||
|
src: url("/fonts/Geist/GeistVariableVF.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
/* === Scrollbars === */
|
/* === Scrollbars === */
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
|
|
@ -116,7 +128,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 +151,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 +161,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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
:root {
|
:root {
|
||||||
--shiki-foreground: #EEEEEE;
|
--shiki-foreground: #FFF8;
|
||||||
--shiki-color-background: #ffffff;
|
--shiki-color-background: #ffffff;
|
||||||
--shiki-token-constant: #ffffff;
|
--shiki-token-constant: #ffffff;
|
||||||
--shiki-token-string: #ffffff88;
|
--shiki-token-string: #ffffff88;
|
||||||
|
|
@ -7,7 +7,14 @@
|
||||||
--shiki-token-keyword: #ffffff88;
|
--shiki-token-keyword: #ffffff88;
|
||||||
--shiki-token-parameter: #AA0000;
|
--shiki-token-parameter: #AA0000;
|
||||||
--shiki-token-function: #ffffff;
|
--shiki-token-function: #ffffff;
|
||||||
--shiki-token-string-expression: #ffffff88;
|
--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;
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E");
|
--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E");
|
||||||
--vp-code-bg: hsl(var(--muted));
|
--vp-code-bg: hsl(var(--muted));
|
||||||
--vp-c-divider: hsl(var(--muted));
|
--vp-c-divider: hsl(var(--muted));
|
||||||
|
--vp-code-block-color: #fff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -414,7 +415,7 @@
|
||||||
|
|
||||||
.vp-doc div[class*='language-'].line-numbers-mode {
|
.vp-doc div[class*='language-'].line-numbers-mode {
|
||||||
/*rtl:ignore*/
|
/*rtl:ignore*/
|
||||||
padding-left: 32px;
|
padding-left: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vp-doc .line-numbers-wrapper {
|
.vp-doc .line-numbers-wrapper {
|
||||||
|
|
@ -566,4 +567,12 @@
|
||||||
|
|
||||||
.vp-external-link-icon::after {
|
.vp-external-link-icon::after {
|
||||||
content: '';
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
.vp-doc [class*=language-] code {
|
||||||
|
color: var(--vp-code-block-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-numbers-mode pre code .line {
|
||||||
|
padding-left: 3rem !important;
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
// This file is autogenerated by scripts/build-registry.ts
|
// This file is autogenerated by scripts/build-registry.ts
|
||||||
// Do not edit this file directly.
|
// Do not edit this file directly.
|
||||||
export const Index = {
|
export const Index = {
|
||||||
|
|
@ -324,6 +325,13 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/default/example/ContextMenuDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/default/example/ContextMenuDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/default/example/ContextMenuDemo.vue'],
|
files: ['../src/lib/registry/default/example/ContextMenuDemo.vue'],
|
||||||
},
|
},
|
||||||
|
DataTableColumnPinningDemo: {
|
||||||
|
name: 'DataTableColumnPinningDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['button', 'checkbox', 'dropdown-menu', 'input', 'table', 'utils'],
|
||||||
|
component: () => import('../src/lib/registry/default/example/DataTableColumnPinningDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/default/example/DataTableColumnPinningDemo.vue'],
|
||||||
|
},
|
||||||
DataTableDemo: {
|
DataTableDemo: {
|
||||||
name: 'DataTableDemo',
|
name: 'DataTableDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -387,6 +395,20 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/default/example/DialogDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/default/example/DialogDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/default/example/DialogDemo.vue'],
|
files: ['../src/lib/registry/default/example/DialogDemo.vue'],
|
||||||
},
|
},
|
||||||
|
DialogScrollBodyDemo: {
|
||||||
|
name: 'DialogScrollBodyDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['button', 'dialog'],
|
||||||
|
component: () => import('../src/lib/registry/default/example/DialogScrollBodyDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/default/example/DialogScrollBodyDemo.vue'],
|
||||||
|
},
|
||||||
|
DialogScrollOverlayDemo: {
|
||||||
|
name: 'DialogScrollOverlayDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['button', 'dialog'],
|
||||||
|
component: () => import('../src/lib/registry/default/example/DialogScrollOverlayDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/default/example/DialogScrollOverlayDemo.vue'],
|
||||||
|
},
|
||||||
DropdownMenuDemo: {
|
DropdownMenuDemo: {
|
||||||
name: 'DropdownMenuDemo',
|
name: 'DropdownMenuDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -443,6 +465,13 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/default/example/InputWithButton.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/default/example/InputWithButton.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/default/example/InputWithButton.vue'],
|
files: ['../src/lib/registry/default/example/InputWithButton.vue'],
|
||||||
},
|
},
|
||||||
|
InputWithIcon: {
|
||||||
|
name: 'InputWithIcon',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['input'],
|
||||||
|
component: () => import('../src/lib/registry/default/example/InputWithIcon.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/default/example/InputWithIcon.vue'],
|
||||||
|
},
|
||||||
InputWithLabel: {
|
InputWithLabel: {
|
||||||
name: 'InputWithLabel',
|
name: 'InputWithLabel',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -485,6 +514,20 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/default/example/PaginationDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/default/example/PaginationDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/default/example/PaginationDemo.vue'],
|
files: ['../src/lib/registry/default/example/PaginationDemo.vue'],
|
||||||
},
|
},
|
||||||
|
PinInputDemo: {
|
||||||
|
name: 'PinInputDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['pin-input'],
|
||||||
|
component: () => import('../src/lib/registry/default/example/PinInputDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/default/example/PinInputDemo.vue'],
|
||||||
|
},
|
||||||
|
PinInputFormDemo: {
|
||||||
|
name: 'PinInputFormDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['pin-input', 'button', 'form', 'toast'],
|
||||||
|
component: () => import('../src/lib/registry/default/example/PinInputFormDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/default/example/PinInputFormDemo.vue'],
|
||||||
|
},
|
||||||
PopoverDemo: {
|
PopoverDemo: {
|
||||||
name: 'PopoverDemo',
|
name: 'PopoverDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -513,6 +556,13 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/default/example/RadioGroupForm.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/default/example/RadioGroupForm.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/default/example/RadioGroupForm.vue'],
|
files: ['../src/lib/registry/default/example/RadioGroupForm.vue'],
|
||||||
},
|
},
|
||||||
|
RangePickerWithSlot: {
|
||||||
|
name: 'RangePickerWithSlot',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['utils', 'button', 'calendar', 'popover'],
|
||||||
|
component: () => import('../src/lib/registry/default/example/RangePickerWithSlot.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/default/example/RangePickerWithSlot.vue'],
|
||||||
|
},
|
||||||
ScrollAreaDemo: {
|
ScrollAreaDemo: {
|
||||||
name: 'ScrollAreaDemo',
|
name: 'ScrollAreaDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -576,6 +626,13 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/default/example/SliderDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/default/example/SliderDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/default/example/SliderDemo.vue'],
|
files: ['../src/lib/registry/default/example/SliderDemo.vue'],
|
||||||
},
|
},
|
||||||
|
SonnerDemo: {
|
||||||
|
name: 'SonnerDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['button'],
|
||||||
|
component: () => import('../src/lib/registry/default/example/SonnerDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/default/example/SonnerDemo.vue'],
|
||||||
|
},
|
||||||
SwitchDemo: {
|
SwitchDemo: {
|
||||||
name: 'SwitchDemo',
|
name: 'SwitchDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -604,6 +661,20 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/default/example/TabsDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/default/example/TabsDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TabsDemo.vue'],
|
files: ['../src/lib/registry/default/example/TabsDemo.vue'],
|
||||||
},
|
},
|
||||||
|
TagsInputComboboxDemo: {
|
||||||
|
name: 'TagsInputComboboxDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['command', 'tags-input'],
|
||||||
|
component: () => import('../src/lib/registry/default/example/TagsInputComboboxDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/default/example/TagsInputComboboxDemo.vue'],
|
||||||
|
},
|
||||||
|
TagsInputDemo: {
|
||||||
|
name: 'TagsInputDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['tags-input'],
|
||||||
|
component: () => import('../src/lib/registry/default/example/TagsInputDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/default/example/TagsInputDemo.vue'],
|
||||||
|
},
|
||||||
TextareaDemo: {
|
TextareaDemo: {
|
||||||
name: 'TextareaDemo',
|
name: 'TextareaDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -776,96 +847,96 @@ export const Index = {
|
||||||
name: 'TypographyBlockquote',
|
name: 'TypographyBlockquote',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographyBlockquote.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/default/example/TypographyBlockquote.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographyBlockquote.vue'],
|
files: ["../src/lib/registry/default/example/TypographyBlockquote.vue"],
|
||||||
},
|
},
|
||||||
TypographyDemo: {
|
"TypographyDemo": {
|
||||||
name: 'TypographyDemo',
|
name: "TypographyDemo",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographyDemo.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/default/example/TypographyDemo.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographyDemo.vue'],
|
files: ["../src/lib/registry/default/example/TypographyDemo.vue"],
|
||||||
},
|
},
|
||||||
TypographyH1: {
|
"TypographyH1": {
|
||||||
name: 'TypographyH1',
|
name: "TypographyH1",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographyH1.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/default/example/TypographyH1.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographyH1.vue'],
|
files: ["../src/lib/registry/default/example/TypographyH1.vue"],
|
||||||
},
|
},
|
||||||
TypographyH2: {
|
"TypographyH2": {
|
||||||
name: 'TypographyH2',
|
name: "TypographyH2",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographyH2.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/default/example/TypographyH2.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographyH2.vue'],
|
files: ["../src/lib/registry/default/example/TypographyH2.vue"],
|
||||||
},
|
},
|
||||||
TypographyH3: {
|
"TypographyH3": {
|
||||||
name: 'TypographyH3',
|
name: "TypographyH3",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographyH3.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/default/example/TypographyH3.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographyH3.vue'],
|
files: ["../src/lib/registry/default/example/TypographyH3.vue"],
|
||||||
},
|
},
|
||||||
TypographyH4: {
|
"TypographyH4": {
|
||||||
name: 'TypographyH4',
|
name: "TypographyH4",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographyH4.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/default/example/TypographyH4.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographyH4.vue'],
|
files: ["../src/lib/registry/default/example/TypographyH4.vue"],
|
||||||
},
|
},
|
||||||
TypographyInlineCode: {
|
"TypographyInlineCode": {
|
||||||
name: 'TypographyInlineCode',
|
name: "TypographyInlineCode",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographyInlineCode.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/default/example/TypographyInlineCode.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographyInlineCode.vue'],
|
files: ["../src/lib/registry/default/example/TypographyInlineCode.vue"],
|
||||||
},
|
},
|
||||||
TypographyLarge: {
|
"TypographyLarge": {
|
||||||
name: 'TypographyLarge',
|
name: "TypographyLarge",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographyLarge.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/default/example/TypographyLarge.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographyLarge.vue'],
|
files: ["../src/lib/registry/default/example/TypographyLarge.vue"],
|
||||||
},
|
},
|
||||||
TypographyLead: {
|
"TypographyLead": {
|
||||||
name: 'TypographyLead',
|
name: "TypographyLead",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographyLead.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/default/example/TypographyLead.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographyLead.vue'],
|
files: ["../src/lib/registry/default/example/TypographyLead.vue"],
|
||||||
},
|
},
|
||||||
TypographyList: {
|
"TypographyList": {
|
||||||
name: 'TypographyList',
|
name: "TypographyList",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographyList.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/default/example/TypographyList.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographyList.vue'],
|
files: ["../src/lib/registry/default/example/TypographyList.vue"],
|
||||||
},
|
},
|
||||||
TypographyMuted: {
|
"TypographyMuted": {
|
||||||
name: 'TypographyMuted',
|
name: "TypographyMuted",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographyMuted.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/default/example/TypographyMuted.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographyMuted.vue'],
|
files: ["../src/lib/registry/default/example/TypographyMuted.vue"],
|
||||||
},
|
},
|
||||||
TypographyP: {
|
"TypographyP": {
|
||||||
name: 'TypographyP',
|
name: "TypographyP",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographyP.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/default/example/TypographyP.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographyP.vue'],
|
files: ["../src/lib/registry/default/example/TypographyP.vue"],
|
||||||
},
|
},
|
||||||
TypographySmall: {
|
"TypographySmall": {
|
||||||
name: 'TypographySmall',
|
name: "TypographySmall",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographySmall.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/default/example/TypographySmall.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographySmall.vue'],
|
files: ["../src/lib/registry/default/example/TypographySmall.vue"],
|
||||||
},
|
},
|
||||||
TypographyTable: {
|
"TypographyTable": {
|
||||||
name: 'TypographyTable',
|
name: "TypographyTable",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/default/example/TypographyTable.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/default/example/TypographyTable.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TypographyTable.vue'],
|
files: ['../src/lib/registry/default/example/TypographyTable.vue'],
|
||||||
|
|
@ -1215,6 +1286,13 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/new-york/example/ContextMenuDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/new-york/example/ContextMenuDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/ContextMenuDemo.vue'],
|
files: ['../src/lib/registry/new-york/example/ContextMenuDemo.vue'],
|
||||||
},
|
},
|
||||||
|
DataTableColumnPinningDemo: {
|
||||||
|
name: 'DataTableColumnPinningDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['button', 'checkbox', 'dropdown-menu', 'input', 'table', 'utils'],
|
||||||
|
component: () => import('../src/lib/registry/new-york/example/DataTableColumnPinningDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/new-york/example/DataTableColumnPinningDemo.vue'],
|
||||||
|
},
|
||||||
DataTableDemo: {
|
DataTableDemo: {
|
||||||
name: 'DataTableDemo',
|
name: 'DataTableDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -1278,6 +1356,20 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/new-york/example/DialogDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/new-york/example/DialogDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/DialogDemo.vue'],
|
files: ['../src/lib/registry/new-york/example/DialogDemo.vue'],
|
||||||
},
|
},
|
||||||
|
DialogScrollBodyDemo: {
|
||||||
|
name: 'DialogScrollBodyDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['button', 'dialog'],
|
||||||
|
component: () => import('../src/lib/registry/new-york/example/DialogScrollBodyDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/new-york/example/DialogScrollBodyDemo.vue'],
|
||||||
|
},
|
||||||
|
DialogScrollOverlayDemo: {
|
||||||
|
name: 'DialogScrollOverlayDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['button', 'dialog'],
|
||||||
|
component: () => import('../src/lib/registry/new-york/example/DialogScrollOverlayDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/new-york/example/DialogScrollOverlayDemo.vue'],
|
||||||
|
},
|
||||||
DropdownMenuDemo: {
|
DropdownMenuDemo: {
|
||||||
name: 'DropdownMenuDemo',
|
name: 'DropdownMenuDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -1334,6 +1426,13 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/new-york/example/InputWithButton.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/new-york/example/InputWithButton.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/InputWithButton.vue'],
|
files: ['../src/lib/registry/new-york/example/InputWithButton.vue'],
|
||||||
},
|
},
|
||||||
|
InputWithIcon: {
|
||||||
|
name: 'InputWithIcon',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['input'],
|
||||||
|
component: () => import('../src/lib/registry/new-york/example/InputWithIcon.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/new-york/example/InputWithIcon.vue'],
|
||||||
|
},
|
||||||
InputWithLabel: {
|
InputWithLabel: {
|
||||||
name: 'InputWithLabel',
|
name: 'InputWithLabel',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -1376,6 +1475,20 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/new-york/example/PaginationDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/new-york/example/PaginationDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/PaginationDemo.vue'],
|
files: ['../src/lib/registry/new-york/example/PaginationDemo.vue'],
|
||||||
},
|
},
|
||||||
|
PinInputDemo: {
|
||||||
|
name: 'PinInputDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['pin-input'],
|
||||||
|
component: () => import('../src/lib/registry/new-york/example/PinInputDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/new-york/example/PinInputDemo.vue'],
|
||||||
|
},
|
||||||
|
PinInputFormDemo: {
|
||||||
|
name: 'PinInputFormDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['pin-input', 'button', 'form', 'toast'],
|
||||||
|
component: () => import('../src/lib/registry/new-york/example/PinInputFormDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/new-york/example/PinInputFormDemo.vue'],
|
||||||
|
},
|
||||||
PopoverDemo: {
|
PopoverDemo: {
|
||||||
name: 'PopoverDemo',
|
name: 'PopoverDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -1404,6 +1517,13 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/new-york/example/RadioGroupForm.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/new-york/example/RadioGroupForm.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/RadioGroupForm.vue'],
|
files: ['../src/lib/registry/new-york/example/RadioGroupForm.vue'],
|
||||||
},
|
},
|
||||||
|
RangePickerWithSlot: {
|
||||||
|
name: 'RangePickerWithSlot',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['utils', 'button', 'calendar', 'popover'],
|
||||||
|
component: () => import('../src/lib/registry/new-york/example/RangePickerWithSlot.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/new-york/example/RangePickerWithSlot.vue'],
|
||||||
|
},
|
||||||
ScrollAreaDemo: {
|
ScrollAreaDemo: {
|
||||||
name: 'ScrollAreaDemo',
|
name: 'ScrollAreaDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -1467,6 +1587,13 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/new-york/example/SliderDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/new-york/example/SliderDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/SliderDemo.vue'],
|
files: ['../src/lib/registry/new-york/example/SliderDemo.vue'],
|
||||||
},
|
},
|
||||||
|
SonnerDemo: {
|
||||||
|
name: 'SonnerDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['button'],
|
||||||
|
component: () => import('../src/lib/registry/new-york/example/SonnerDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/new-york/example/SonnerDemo.vue'],
|
||||||
|
},
|
||||||
SwitchDemo: {
|
SwitchDemo: {
|
||||||
name: 'SwitchDemo',
|
name: 'SwitchDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -1495,6 +1622,20 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/new-york/example/TabsDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/new-york/example/TabsDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TabsDemo.vue'],
|
files: ['../src/lib/registry/new-york/example/TabsDemo.vue'],
|
||||||
},
|
},
|
||||||
|
TagsInputComboboxDemo: {
|
||||||
|
name: 'TagsInputComboboxDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['command', 'tags-input'],
|
||||||
|
component: () => import('../src/lib/registry/new-york/example/TagsInputComboboxDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/new-york/example/TagsInputComboboxDemo.vue'],
|
||||||
|
},
|
||||||
|
TagsInputDemo: {
|
||||||
|
name: 'TagsInputDemo',
|
||||||
|
type: 'components:example',
|
||||||
|
registryDependencies: ['tags-input'],
|
||||||
|
component: () => import('../src/lib/registry/new-york/example/TagsInputDemo.vue').then(m => m.default),
|
||||||
|
files: ['../src/lib/registry/new-york/example/TagsInputDemo.vue'],
|
||||||
|
},
|
||||||
TextareaDemo: {
|
TextareaDemo: {
|
||||||
name: 'TextareaDemo',
|
name: 'TextareaDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
|
|
@ -1667,120 +1808,120 @@ export const Index = {
|
||||||
name: 'TypographyBlockquote',
|
name: 'TypographyBlockquote',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographyBlockquote.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographyBlockquote.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographyBlockquote.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographyBlockquote.vue"],
|
||||||
},
|
},
|
||||||
TypographyDemo: {
|
"TypographyDemo": {
|
||||||
name: 'TypographyDemo',
|
name: "TypographyDemo",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographyDemo.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographyDemo.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographyDemo.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographyDemo.vue"],
|
||||||
},
|
},
|
||||||
TypographyH1: {
|
"TypographyH1": {
|
||||||
name: 'TypographyH1',
|
name: "TypographyH1",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographyH1.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographyH1.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographyH1.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographyH1.vue"],
|
||||||
},
|
},
|
||||||
TypographyH2: {
|
"TypographyH2": {
|
||||||
name: 'TypographyH2',
|
name: "TypographyH2",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographyH2.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographyH2.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographyH2.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographyH2.vue"],
|
||||||
},
|
},
|
||||||
TypographyH3: {
|
"TypographyH3": {
|
||||||
name: 'TypographyH3',
|
name: "TypographyH3",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographyH3.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographyH3.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographyH3.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographyH3.vue"],
|
||||||
},
|
},
|
||||||
TypographyH4: {
|
"TypographyH4": {
|
||||||
name: 'TypographyH4',
|
name: "TypographyH4",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographyH4.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographyH4.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographyH4.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographyH4.vue"],
|
||||||
},
|
},
|
||||||
TypographyInlineCode: {
|
"TypographyInlineCode": {
|
||||||
name: 'TypographyInlineCode',
|
name: "TypographyInlineCode",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographyInlineCode.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographyInlineCode.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographyInlineCode.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographyInlineCode.vue"],
|
||||||
},
|
},
|
||||||
TypographyLarge: {
|
"TypographyLarge": {
|
||||||
name: 'TypographyLarge',
|
name: "TypographyLarge",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographyLarge.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographyLarge.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographyLarge.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographyLarge.vue"],
|
||||||
},
|
},
|
||||||
TypographyLead: {
|
"TypographyLead": {
|
||||||
name: 'TypographyLead',
|
name: "TypographyLead",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographyLead.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographyLead.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographyLead.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographyLead.vue"],
|
||||||
},
|
},
|
||||||
TypographyList: {
|
"TypographyList": {
|
||||||
name: 'TypographyList',
|
name: "TypographyList",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographyList.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographyList.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographyList.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographyList.vue"],
|
||||||
},
|
},
|
||||||
TypographyMuted: {
|
"TypographyMuted": {
|
||||||
name: 'TypographyMuted',
|
name: "TypographyMuted",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographyMuted.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographyMuted.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographyMuted.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographyMuted.vue"],
|
||||||
},
|
},
|
||||||
TypographyP: {
|
"TypographyP": {
|
||||||
name: 'TypographyP',
|
name: "TypographyP",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographyP.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographyP.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographyP.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographyP.vue"],
|
||||||
},
|
},
|
||||||
TypographySmall: {
|
"TypographySmall": {
|
||||||
name: 'TypographySmall',
|
name: "TypographySmall",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographySmall.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographySmall.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographySmall.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographySmall.vue"],
|
||||||
},
|
},
|
||||||
TypographyTable: {
|
"TypographyTable": {
|
||||||
name: 'TypographyTable',
|
name: "TypographyTable",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: [],
|
registryDependencies: [],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TypographyTable.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/TypographyTable.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TypographyTable.vue'],
|
files: ["../src/lib/registry/new-york/example/TypographyTable.vue"],
|
||||||
},
|
},
|
||||||
ActivityGoal: {
|
"ActivityGoal": {
|
||||||
name: 'ActivityGoal',
|
name: "ActivityGoal",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: ['button', 'card', 'themes', 'config'],
|
registryDependencies: ["button","card","themes","config"],
|
||||||
component: () => import('../src/lib/registry/new-york/example/Cards/ActivityGoal.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/Cards/ActivityGoal.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/Cards/ActivityGoal.vue'],
|
files: ["../src/lib/registry/new-york/example/Cards/ActivityGoal.vue"],
|
||||||
},
|
},
|
||||||
DataTable: {
|
"DataTable": {
|
||||||
name: 'DataTable',
|
name: "DataTable",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: ['button', 'checkbox', 'dropdown-menu', 'input', 'table', 'card', 'utils'],
|
registryDependencies: ["button","checkbox","dropdown-menu","input","table","card","utils"],
|
||||||
component: () => import('../src/lib/registry/new-york/example/Cards/DataTable.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/Cards/DataTable.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/Cards/DataTable.vue'],
|
files: ["../src/lib/registry/new-york/example/Cards/DataTable.vue"],
|
||||||
},
|
},
|
||||||
Metric: {
|
"Metric": {
|
||||||
name: 'Metric',
|
name: "Metric",
|
||||||
type: 'components:example',
|
type: "components:example",
|
||||||
registryDependencies: ['card', 'config'],
|
registryDependencies: ["card","config"],
|
||||||
component: () => import('../src/lib/registry/new-york/example/Cards/Metric.vue').then(m => m.default),
|
component: () => import("../src/lib/registry/new-york/example/Cards/Metric.vue").then((m) => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/Cards/Metric.vue'],
|
files: ["../src/lib/registry/new-york/example/Cards/Metric.vue"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,26 +19,26 @@
|
||||||
"@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.6",
|
"@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",
|
||||||
"@vueuse/integrations": "^10.7.2",
|
"@vueuse/integrations": "^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",
|
||||||
"fuse.js": "^7.0.0",
|
|
||||||
"lucide-vue-next": "^0.276.0",
|
"lucide-vue-next": "^0.276.0",
|
||||||
"radix-vue": "^1.3.2",
|
"radix-vue": "^1.4.6",
|
||||||
"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.14",
|
"vue": "^3.4.15",
|
||||||
|
"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"
|
||||||
},
|
},
|
||||||
|
|
@ -47,25 +47,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.2",
|
"shiki": "^1.0.0-beta.3",
|
||||||
"tailwind-merge": "^2.2.0",
|
"tailwind-merge": "^2.2.1",
|
||||||
"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.11",
|
"vite": "^5.0.12",
|
||||||
"vitepress": "^1.0.0-rc.37",
|
"vitepress": "^1.0.0-rc.41",
|
||||||
"vue-tsc": "^1.8.27"
|
"vue-tsc": "^1.8.27"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,5 +56,40 @@ import { Calendar } from '@/components/ui/calendar'
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
|
||||||
See the [VCalendar](https://vcalendar.io/getting-started/installation.html) documentation for more information.
|
The API is essentially the same, i.e. props and slots. See the [VCalendar](https://vcalendar.io/getting-started/installation.html) documentation for more information.
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
The slots available are [those currently supported](https://github.com/nathanreyes/v-calendar/blob/v3.1.2/src/components/Calendar/CalendarSlot.vue#L16-L28) by VCalendar, namely :
|
||||||
|
|
||||||
|
- `day-content`
|
||||||
|
- `day-popover`
|
||||||
|
- `dp-footer`
|
||||||
|
- `footer`
|
||||||
|
- `header-title-wrapper`
|
||||||
|
- `header-title`
|
||||||
|
- `header-prev-button`
|
||||||
|
- `header-next-button`
|
||||||
|
- `nav`
|
||||||
|
- `nav-prev-button`
|
||||||
|
- `nav-next-button`
|
||||||
|
- `page`
|
||||||
|
- `time-header`
|
||||||
|
|
||||||
|
Example using the `day-content` slot:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Calendar } from '@/components/ui/calendar'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Calendar>
|
||||||
|
<template #day-content="{ day, dayProps, dayEvents }">
|
||||||
|
<div v-bind="dayProps" v-on="dayEvents">
|
||||||
|
{{ day.label }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Calendar>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
@ -57,7 +57,7 @@ To set the size of the items, you can use the `basis` utility class on the `<Car
|
||||||
|
|
||||||
Example
|
Example
|
||||||
|
|
||||||
```vue title="Example" showLineNumbers {4-6}
|
```vue:line-numbers title="Example" {4-6}
|
||||||
// 33% of the carousel width.
|
// 33% of the carousel width.
|
||||||
<Carousel>
|
<Carousel>
|
||||||
<CarouselContent>
|
<CarouselContent>
|
||||||
|
|
@ -71,7 +71,7 @@ Example
|
||||||
|
|
||||||
Responsive
|
Responsive
|
||||||
|
|
||||||
```vue title="Responsive" showLineNumbers {4-6}
|
```vue:line-numbers title="Responsive" {4-6}
|
||||||
// 50% on small screens and 33% on larger screens.
|
// 50% on small screens and 33% on larger screens.
|
||||||
<Carousel>
|
<Carousel>
|
||||||
<CarouselContent>
|
<CarouselContent>
|
||||||
|
|
@ -101,7 +101,7 @@ You can always adjust this in your own project if you need to.
|
||||||
|
|
||||||
Example
|
Example
|
||||||
|
|
||||||
```vue showLineNumbers /-ml-4/ /pl-4/
|
```vue:line-numbers /-ml-4/ /pl-4/
|
||||||
<template>
|
<template>
|
||||||
<Carousel>
|
<Carousel>
|
||||||
<CarouselContent class="-ml-4">
|
<CarouselContent class="-ml-4">
|
||||||
|
|
@ -121,7 +121,7 @@ Example
|
||||||
|
|
||||||
Responsive
|
Responsive
|
||||||
|
|
||||||
```vue showLineNumbers /-ml-2/ /pl-2/ /md:-ml-4/ /md:pl-4/
|
```vue:line-numbers /-ml-2/ /pl-2/ /md:-ml-4/ /md:pl-4/
|
||||||
<template>
|
<template>
|
||||||
<Carousel>
|
<Carousel>
|
||||||
<CarouselContent class="-ml-2 md:-ml-4">
|
<CarouselContent class="-ml-2 md:-ml-4">
|
||||||
|
|
@ -155,7 +155,7 @@ Use the `orientation` prop to set the orientation of the carousel.
|
||||||
|
|
||||||
You can pass options to the carousel using the `opts` prop. See the [Embla Carousel docs](https://www.embla-carousel.com/api/options/) for more information.
|
You can pass options to the carousel using the `opts` prop. See the [Embla Carousel docs](https://www.embla-carousel.com/api/options/) for more information.
|
||||||
|
|
||||||
```vue showLineNumbers {3-6}
|
```vue:line-numbers {3-6}
|
||||||
<template>
|
<template>
|
||||||
<Carousel
|
<Carousel
|
||||||
:opts="{
|
:opts="{
|
||||||
|
|
@ -184,7 +184,7 @@ Use the `@init-api` emit method on `<Carousel />` component to set the instance
|
||||||
|
|
||||||
You can access it through setting a template ref on the `<Carousel />` component.
|
You can access it through setting a template ref on the `<Carousel />` component.
|
||||||
|
|
||||||
```vue showLineNumbers {2,5,9}
|
```vue:line-numbers {2,5,9}
|
||||||
<script setup>
|
<script setup>
|
||||||
const carouselContainerRef = ref<InstanceType<typeof Carousel> | null>(null)
|
const carouselContainerRef = ref<InstanceType<typeof Carousel> | null>(null)
|
||||||
|
|
||||||
|
|
@ -204,7 +204,7 @@ function accessApi() {
|
||||||
|
|
||||||
You can listen to events using the API. To get the API instance use the `@init-api` emit method on the `<Carousel />` component
|
You can listen to events using the API. To get the API instance use the `@init-api` emit method on the `<Carousel />` component
|
||||||
|
|
||||||
```vue showLineNumbers {5,7-9,25}
|
```vue:line-numbers {5,7-9,25}
|
||||||
<script setup>
|
<script setup>
|
||||||
import { nextTick, ref, watch } from 'vue'
|
import { nextTick, ref, watch } from 'vue'
|
||||||
import { useCarousel } from '@/components/ui/carousel'
|
import { useCarousel } from '@/components/ui/carousel'
|
||||||
|
|
@ -241,7 +241,7 @@ See the [Embla Carousel docs](https://www.embla-carousel.com/api/events/) for mo
|
||||||
|
|
||||||
You can get the reactive slot props like `carouselRef, canScrollNext..Prev, scrollNext..Prev` using the `v-slot` directive in the `<Carousel v-slot="slotProps" />` component to extend the functionality.
|
You can get the reactive slot props like `carouselRef, canScrollNext..Prev, scrollNext..Prev` using the `v-slot` directive in the `<Carousel v-slot="slotProps" />` component to extend the functionality.
|
||||||
|
|
||||||
```vue showLineNumbers {2}
|
```vue:line-numbers {2}
|
||||||
<template>
|
<template>
|
||||||
<Carousel v-slot="{ canScrollNext, canScrollPrev }">
|
<Carousel v-slot="{ canScrollNext, canScrollPrev }">
|
||||||
...
|
...
|
||||||
|
|
@ -260,7 +260,7 @@ npm i embla-carousel-autoplay
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
```vue showLineNumbers {2,8-10}
|
```vue:line-numbers {2,8-10}
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Autoplay from 'embla-carousel-autoplay'
|
import Autoplay from 'embla-carousel-autoplay'
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ primitive: https://tanstack.com/table/v8/docs/guide/introduction
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
<ComponentPreview name="DataTableDemo" />
|
<ComponentPreview name="DataTableDemo" />
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -50,6 +50,13 @@ npx shadcn-vue@latest add table
|
||||||
npm install @tanstack/vue-table
|
npm install @tanstack/vue-table
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Column Pinning
|
||||||
|
|
||||||
|
<ComponentPreview name="DataTableColumnPinningDemo" />
|
||||||
|
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
We are going to build a table to show recent payments. Here's what our data looks like:
|
We are going to build a table to show recent payments. Here's what our data looks like:
|
||||||
|
|
@ -109,31 +116,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 +148,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 +224,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 showLineNumbers{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"
|
||||||
|
|
@ -272,7 +271,7 @@ Let's format the amount cell to display the dollar amount. We'll also align the
|
||||||
Update the `header` and `cell` definitions for amount as follows:
|
Update the `header` and `cell` definitions for amount as follows:
|
||||||
|
|
||||||
|
|
||||||
```ts:line-numbers showLineNumbers title="components/payments/columns.ts" {5-17}
|
```ts:line-numbers title="components/payments/columns.ts" {5-17}
|
||||||
import { h } from 'vue'
|
import { h } from 'vue'
|
||||||
|
|
||||||
export const columns: ColumnDef<Payment>[] = [
|
export const columns: ColumnDef<Payment>[] = [
|
||||||
|
|
@ -302,7 +301,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'
|
||||||
|
|
@ -380,7 +379,7 @@ Next, we'll add pagination to our table.
|
||||||
|
|
||||||
### Update `<DataTable>`
|
### Update `<DataTable>`
|
||||||
|
|
||||||
```ts:line-numbers showLineNumbers{4,12}
|
```ts:line-numbers {4,12}
|
||||||
import {
|
import {
|
||||||
FlexRender,
|
FlexRender,
|
||||||
getCoreRowModel,
|
getCoreRowModel,
|
||||||
|
|
@ -402,8 +401,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 showLineNumbers{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"
|
||||||
|
|
||||||
|
|
@ -458,7 +456,7 @@ Let's make the email column sortable.
|
||||||
|
|
||||||
### Add the following into your `utils` file:
|
### Add the following into your `utils` file:
|
||||||
|
|
||||||
```ts:line-numbers showLineNumbers{5,6,12-17}
|
```ts:line-numbers {5,6,12-17}
|
||||||
import { type ClassValue, clsx } from 'clsx'
|
import { type ClassValue, clsx } from 'clsx'
|
||||||
import { twMerge } from 'tailwind-merge'
|
import { twMerge } from 'tailwind-merge'
|
||||||
import { camelize, getCurrentInstance, toHandlerKey } from 'vue'
|
import { camelize, getCurrentInstance, toHandlerKey } from 'vue'
|
||||||
|
|
@ -482,7 +480,7 @@ The `valueUpdater` function updates a Vue `ref` object's value. It handles both
|
||||||
|
|
||||||
### Update `<DataTable>`
|
### Update `<DataTable>`
|
||||||
|
|
||||||
```ts:line-numbers showLineNumbers{4,7,16,34,41-44}
|
```vue:line-numbers {4,7,16,34,41-44}
|
||||||
<script setup lang="ts" generic="TData, TValue">
|
<script setup lang="ts" generic="TData, TValue">
|
||||||
import type {
|
import type {
|
||||||
ColumnDef,
|
ColumnDef,
|
||||||
|
|
@ -545,7 +543,7 @@ const table = useVueTable({
|
||||||
|
|
||||||
We can now update the `email` header cell to add sorting controls.
|
We can now update the `email` header cell to add sorting controls.
|
||||||
|
|
||||||
```ts:line-numbers showLineNumbers{5,10-17}
|
```ts:line-numbers {5,10-17}
|
||||||
// components/payments/columns.ts
|
// components/payments/columns.ts
|
||||||
import type {
|
import type {
|
||||||
ColumnDef,
|
ColumnDef,
|
||||||
|
|
@ -579,7 +577,7 @@ Let's add a search input to filter emails in our table.
|
||||||
|
|
||||||
### Update `<DataTable>`
|
### Update `<DataTable>`
|
||||||
|
|
||||||
```ts:line-numbers showLineNumbers{4,11,19,39,48-49,52,60-64}
|
```vue:line-numbers {4,11,19,39,48-49,52,60-64}
|
||||||
<script setup lang="ts" generic="TData, TValue">
|
<script setup lang="ts" generic="TData, TValue">
|
||||||
import type {
|
import type {
|
||||||
ColumnDef,
|
ColumnDef,
|
||||||
|
|
@ -664,7 +662,7 @@ Adding column visibility is fairly simple using `@tanstack/vue-table` visibility
|
||||||
|
|
||||||
### Update `<DataTable>`
|
### Update `<DataTable>`
|
||||||
|
|
||||||
```ts:line-numbers showLineNumbers{6,9-14,48,59,63,75-91}
|
```vue:line-numbers {6,9-14,48,59,63,75-91}
|
||||||
<script setup lang="ts" generic="TData, TValue">
|
<script setup lang="ts" generic="TData, TValue">
|
||||||
import type {
|
import type {
|
||||||
ColumnDef,
|
ColumnDef,
|
||||||
|
|
@ -803,7 +801,7 @@ Next, we're going to add row selection to our table.
|
||||||
|
|
||||||
### Update column definitions
|
### Update column definitions
|
||||||
|
|
||||||
```ts:line-numbers showLineNumbers{3,6-20}
|
```ts:line-numbers {3,6-20}
|
||||||
import type { ColumnDef } from '@tanstack/vue-table'
|
import type { ColumnDef } from '@tanstack/vue-table'
|
||||||
|
|
||||||
import { Checkbox } from '@/components/ui/checkbox'
|
import { Checkbox } from '@/components/ui/checkbox'
|
||||||
|
|
@ -829,7 +827,7 @@ export const columns: ColumnDef<Payment>[] = [
|
||||||
|
|
||||||
### Update `<DataTable>`
|
### Update `<DataTable>`
|
||||||
|
|
||||||
```ts:line-numbers showLineNumbers{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 +893,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 +986,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 +1091,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'
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,10 @@ const date = ref<Date>()
|
||||||
|
|
||||||
<ComponentPreview name="DatePickerWithPresets" />
|
<ComponentPreview name="DatePickerWithPresets" />
|
||||||
|
|
||||||
|
### With Slot
|
||||||
|
|
||||||
|
<ComponentPreview name="RangePickerWithSlot" />
|
||||||
|
|
||||||
### Form
|
### Form
|
||||||
|
|
||||||
<ComponentPreview name="DatePickerForm" />
|
<ComponentPreview name="DatePickerForm" />
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,14 @@ import {
|
||||||
|
|
||||||
<ComponentPreview name="DialogCustomCloseButton" />
|
<ComponentPreview name="DialogCustomCloseButton" />
|
||||||
|
|
||||||
|
### Scroll body
|
||||||
|
|
||||||
|
<ComponentPreview name="DialogScrollBodyDemo" />
|
||||||
|
|
||||||
|
### Scroll overlay
|
||||||
|
|
||||||
|
<ComponentPreview name="DialogScrollOverlayDemo" />
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
To activate the `Dialog` component from within a `Context Menu` or `Dropdown Menu`, you must encase the `Context Menu` or `Dropdown Menu` component in the `Dialog` component. For more information, refer to the linked issue [here](https://github.com/radix-ui/primitives/issues/1836).
|
To activate the `Dialog` component from within a `Context Menu` or `Dropdown Menu`, you must encase the `Context Menu` or `Dropdown Menu` component in the `Dialog` component. For more information, refer to the linked issue [here](https://github.com/radix-ui/primitives/issues/1836).
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,7 @@ Use `@vee-validate/zod` to integrate Zod schema validation with `vee-validate`
|
||||||
|
|
||||||
`toTypedSchema` also makes the form values and submitted values typed automatically and caters for both input and output types of that schema.
|
`toTypedSchema` also makes the form values and submitted values typed automatically and caters for both input and output types of that schema.
|
||||||
|
|
||||||
```vue showLineNumbers {2-3,5-7}
|
```vue:line-numbers {2-3,5-7}
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { toTypedSchema } from '@vee-validate/zod'
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
import * as z from 'zod'
|
import * as z from 'zod'
|
||||||
|
|
@ -179,7 +179,7 @@ Use the `useForm` composable from `vee-validate` or use `<Form />` component to
|
||||||
<TabPreview name="Composition" :names="['Composition', 'Component']">
|
<TabPreview name="Composition" :names="['Composition', 'Component']">
|
||||||
<template #Composition>
|
<template #Composition>
|
||||||
|
|
||||||
```vue showLineNumbers {2,19-21}
|
```vue:line-numbers {2,19-21}
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useForm } from 'vee-validate'
|
import { useForm } from 'vee-validate'
|
||||||
import { toTypedSchema } from '@vee-validate/zod'
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
|
|
@ -218,7 +218,7 @@ const onSubmit = form.handleSubmit((values) => {
|
||||||
|
|
||||||
<template #Component>
|
<template #Component>
|
||||||
|
|
||||||
```vue showLineNumbers {5,24-26}
|
```vue:line-numbers {5,24-26}
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { toTypedSchema } from '@vee-validate/zod'
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
import * as z from 'zod'
|
import * as z from 'zod'
|
||||||
|
|
@ -256,7 +256,7 @@ function onSubmit(values) {
|
||||||
Based on last step we can either use `<Form />` component or `useForm` composable
|
Based on last step we can either use `<Form />` component or `useForm` composable
|
||||||
`useForm` is recommended cause values are typed automatically
|
`useForm` is recommended cause values are typed automatically
|
||||||
|
|
||||||
```vue showLineNumbers {2}
|
```vue:line-numbers {2}
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useForm } from 'vee-validate'
|
import { useForm } from 'vee-validate'
|
||||||
import { toTypedSchema } from '@vee-validate/zod'
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,10 @@ import { Input } from '@/components/ui/input'
|
||||||
|
|
||||||
<ComponentPreview name="InputWithButton" class="max-w-xs" />
|
<ComponentPreview name="InputWithButton" class="max-w-xs" />
|
||||||
|
|
||||||
|
### With Icon
|
||||||
|
|
||||||
|
<ComponentPreview name="InputWithIcon" class="max-w-xs" />
|
||||||
|
|
||||||
### Form
|
### Form
|
||||||
|
|
||||||
<ComponentPreview name="InputForm" />
|
<ComponentPreview name="InputForm" />
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
21
apps/www/src/content/docs/components/pin-input.md
Normal file
21
apps/www/src/content/docs/components/pin-input.md
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
title: PIN Input
|
||||||
|
description: Allows users to input a sequence of one-character alphanumeric inputs.
|
||||||
|
source: apps/www/src/lib/registry/default/ui/pin-input
|
||||||
|
primitive: https://www.radix-vue.com/components/pin-input.html
|
||||||
|
---
|
||||||
|
|
||||||
|
<ComponentPreview name="PinInputDemo" />
|
||||||
|
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx shadcn-vue@latest add pin-input
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Form
|
||||||
|
|
||||||
|
<ComponentPreview name="PinInputFormDemo" />
|
||||||
|
|
@ -57,7 +57,7 @@ Use the `side` property to `<SheetContent />` to indicate the edge of the screen
|
||||||
|
|
||||||
You can adjust the size of the sheet using CSS classes:
|
You can adjust the size of the sheet using CSS classes:
|
||||||
|
|
||||||
```vue:line-numbers showLineNumbers{4}
|
```vue:line-numbers {4}
|
||||||
<template>
|
<template>
|
||||||
<Sheet>
|
<Sheet>
|
||||||
<SheetTrigger>Open</SheetTrigger>
|
<SheetTrigger>Open</SheetTrigger>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
```
|
```
|
||||||
|
|
|
||||||
63
apps/www/src/content/docs/components/sonner.md
Normal file
63
apps/www/src/content/docs/components/sonner.md
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
---
|
||||||
|
title: Sonner
|
||||||
|
description: An opinionated toast component for Vue.
|
||||||
|
docs: https://vue-sonner.vercel.app
|
||||||
|
source: apps/www/src/lib/registry/default/ui/sonner
|
||||||
|
---
|
||||||
|
|
||||||
|
<ComponentPreview name="SonnerDemo" />
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
The Sonner component is provided by [vue-sonner](https://vue-sonner.vercel.app/), which is a Vue port of Sonner, originally created by [Emil Kowalski](https://twitter.com/emilkowalski_) for React.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
|
||||||
|
### Run the following command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx shadcn-vue@latest add sonner
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add the Toaster component
|
||||||
|
|
||||||
|
Add the following `Toaster` component to your `App.vue` file:
|
||||||
|
|
||||||
|
```vue title="App.vue" {2,6}
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Toaster } from '@/components/ui/sonner'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Toaster />
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { toast } from 'vue-sonner'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Button
|
||||||
|
variant="outline" @click="() => {
|
||||||
|
toast('Event has been created', {
|
||||||
|
description: 'Sunday, December 03, 2023 at 9:00 AM',
|
||||||
|
action: {
|
||||||
|
label: 'Undo',
|
||||||
|
onClick: () => console.log('Undo'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
Add to calendar
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
21
apps/www/src/content/docs/components/tags-input.md
Normal file
21
apps/www/src/content/docs/components/tags-input.md
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
title: Tags Input
|
||||||
|
description: Tag inputs render tags inside an input, followed by an actual text input.
|
||||||
|
source: apps/www/src/lib/registry/default/ui/tags-input
|
||||||
|
primitive: https://www.radix-vue.com/components/tags-input.html
|
||||||
|
---
|
||||||
|
|
||||||
|
<ComponentPreview name="TagsInputDemo" />
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx shadcn-vue@latest add tags-input
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Tags with Combobox
|
||||||
|
|
||||||
|
<ComponentPreview name="TagsInputComboboxDemo" />
|
||||||
|
|
@ -61,7 +61,7 @@ const { toast } = useToast()
|
||||||
});
|
});
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
Add to calander
|
Add to calendar
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ npm create astro@latest
|
||||||
|
|
||||||
You will be asked a few questions to configure your project:
|
You will be asked a few questions to configure your project:
|
||||||
|
|
||||||
```txt showLineNumbers
|
```txt:line-numbers
|
||||||
- Where should we create your new project?
|
- Where should we create your new project?
|
||||||
./your-app-name
|
./your-app-name
|
||||||
- How would you like to start your new project?
|
- How would you like to start your new project?
|
||||||
|
|
@ -76,7 +76,7 @@ This will install `tailwindcss` and `@astrojs/tailwind` as dependencies and set
|
||||||
|
|
||||||
Add the code below to the tsconfig.json file to resolve paths:
|
Add the code below to the tsconfig.json file to resolve paths:
|
||||||
|
|
||||||
```json {2-7} showLineNumbers
|
```json:line-numbers {2-7}
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
|
|
@ -99,7 +99,7 @@ npx shadcn-vue@latest init
|
||||||
|
|
||||||
You will be asked a few questions to configure `components.json`:
|
You will be asked a few questions to configure `components.json`:
|
||||||
|
|
||||||
```txt showLineNumbers
|
```txt:line-numbers
|
||||||
Would you like to use TypeScript (recommended)? no / yes
|
Would you like to use TypeScript (recommended)? no / yes
|
||||||
Which framework are you using? Astro
|
Which framework are you using? Astro
|
||||||
Which style would you like to use? › Default
|
Which style would you like to use? › Default
|
||||||
|
|
@ -116,15 +116,17 @@ Write configuration to components.json. Proceed? > Y/n
|
||||||
|
|
||||||
Import the `globals.css` file in the `src/index.astro` file:
|
Import the `globals.css` file in the `src/index.astro` file:
|
||||||
|
|
||||||
```ts {2} showLineNumbers
|
```ts:line-numbers {2}
|
||||||
|
---
|
||||||
import '@/styles/globals.css'
|
import '@/styles/globals.css'
|
||||||
|
---
|
||||||
```
|
```
|
||||||
|
|
||||||
### Update astro tailwind config
|
### Update astro tailwind config
|
||||||
|
|
||||||
To prevent serving the Tailwind base styles twice, we need to tell Astro not to apply the base styles, since we already include them in our own `globals.css` file. To do this, set the `applyBaseStyles` config option for the tailwind plugin in `astro.config.mjs` to `false`.
|
To prevent serving the Tailwind base styles twice, we need to tell Astro not to apply the base styles, since we already include them in our own `globals.css` file. To do this, set the `applyBaseStyles` config option for the tailwind plugin in `astro.config.mjs` to `false`.
|
||||||
|
|
||||||
```ts {3-5} showLineNumbers
|
```ts:line-numbers {3-5}
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
integrations: [
|
integrations: [
|
||||||
tailwind({
|
tailwind({
|
||||||
|
|
@ -144,7 +146,7 @@ npx shadcn-vue@latest add button
|
||||||
|
|
||||||
The command above will add the `Button` component to your project. You can then import it like this:
|
The command above will add the `Button` component to your project. You can then import it like this:
|
||||||
|
|
||||||
```astro {2,10} showLineNumbers
|
```astro:line-numbers {2,10}
|
||||||
---
|
---
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ npx shadcn-vue@latest init
|
||||||
|
|
||||||
You will be asked a few questions to configure `components.json`:
|
You will be asked a few questions to configure `components.json`:
|
||||||
|
|
||||||
```txt showLineNumbers
|
```txt:line-numbers
|
||||||
Would you like to use TypeScript (recommended)? no / yes
|
Would you like to use TypeScript (recommended)? no / yes
|
||||||
Which framework are you using? Vite / Nuxt / Laravel
|
Which framework are you using? Vite / Nuxt / Laravel
|
||||||
Which style would you like to use? › Default
|
Which style would you like to use? › Default
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ npx shadcn-vue@latest init
|
||||||
|
|
||||||
You will be asked a few questions to configure `components.json`:
|
You will be asked a few questions to configure `components.json`:
|
||||||
|
|
||||||
```txt showLineNumbers
|
```txt:line-numbers
|
||||||
Would you like to use TypeScript (recommended)? no / yes
|
Would you like to use TypeScript (recommended)? no / yes
|
||||||
Which framework are you using? Vite / Nuxt / Laravel
|
Which framework are you using? Vite / Nuxt / Laravel
|
||||||
Which style would you like to use? › Default
|
Which style would you like to use? › Default
|
||||||
|
|
|
||||||
|
|
@ -19,22 +19,82 @@ npm create vite@latest my-vue-app -- --template vue-ts
|
||||||
|
|
||||||
### Add Tailwind and its configuration
|
### Add Tailwind and its configuration
|
||||||
|
|
||||||
Install `tailwindcss` and its peer dependencies, then generate your `tailwind.config.js` and `postcss.config.js` files:
|
Install `tailwindcss` and its peer dependencies, then generate your `tailwind.config.js` and configure `postcss` plugins
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install -D tailwindcss postcss autoprefixer
|
|
||||||
|
|
||||||
npx tailwindcss init -p
|
|
||||||
```
|
<TabsMarkdown>
|
||||||
|
<TabMarkdown title="vite.config">
|
||||||
|
|
||||||
|
Vite already has [`postcss`](https://github.com/vitejs/vite/blob/main/packages/vite/package.json#L78) dependency so you don't have to install it again in your package.json
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install -D tailwindcss autoprefixer
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `vite.config`
|
||||||
|
|
||||||
|
```typescript {5,6,9-13}
|
||||||
|
import path from "path"
|
||||||
|
import { defineConfig } from "vite"
|
||||||
|
import vue from "@vitejs/plugin-vue"
|
||||||
|
|
||||||
|
import tailwind from "tailwindcss"
|
||||||
|
import autoprefixer from "autoprefixer"
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
css: {
|
||||||
|
postcss: {
|
||||||
|
plugins: [tailwind(), autoprefixer()],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [vue()],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@": path.resolve(__dirname, "./src"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabMarkdown>
|
||||||
|
|
||||||
|
|
||||||
|
<TabMarkdown title="postcss.config.js">
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install -D tailwindcss autoprefixer postcss
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `postcss.config.js`
|
||||||
|
|
||||||
|
```js
|
||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</TabMarkdown>
|
||||||
|
</TabsMarkdown>
|
||||||
|
|
||||||
|
|
||||||
### Edit tsconfig.json
|
### Edit tsconfig.json
|
||||||
|
|
||||||
Add the code below to the compilerOptions of your tsconfig.json so your app can resolve paths without error
|
Add the code below to the compilerOptions of your tsconfig.json so your app can resolve paths without error
|
||||||
|
|
||||||
```typescript
|
```json {4-7}
|
||||||
"baseUrl": ".",
|
{
|
||||||
"paths": {
|
"compilerOptions": {
|
||||||
"@/*": ["./src/*"]
|
// ...
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
// ...
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -42,12 +102,22 @@ Add the code below to the compilerOptions of your tsconfig.json so your app can
|
||||||
|
|
||||||
Add the code below to the vite.config.ts so your app can resolve paths without error
|
Add the code below to the vite.config.ts so your app can resolve paths without error
|
||||||
|
|
||||||
```typescript
|
```bash
|
||||||
|
# (so you can import "path" without error)
|
||||||
|
npm i -D @types/node
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript {12-16}
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import vue from "@vitejs/plugin-vue"
|
import vue from "@vitejs/plugin-vue"
|
||||||
import { defineConfig } from "vite"
|
import { defineConfig } from "vite"
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
css: {
|
||||||
|
postcss: {
|
||||||
|
plugins: [tailwind(), autoprefixer()],
|
||||||
|
},
|
||||||
|
},
|
||||||
plugins: [vue()],
|
plugins: [vue()],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
|
|
@ -69,7 +139,7 @@ npx shadcn-vue@latest init
|
||||||
|
|
||||||
You will be asked a few questions to configure `components.json`:
|
You will be asked a few questions to configure `components.json`:
|
||||||
|
|
||||||
```txt showLineNumbers
|
```txt:line-numbers
|
||||||
Would you like to use TypeScript (recommended)? no / yes
|
Would you like to use TypeScript (recommended)? no / yes
|
||||||
Which framework are you using? Vite / Nuxt / Laravel
|
Which framework are you using? Vite / Nuxt / Laravel
|
||||||
Which style would you like to use? › Default
|
Which style would you like to use? › Default
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import type { Column } from '@tanstack/vue-table'
|
import type { Column } from '@tanstack/vue-table'
|
||||||
import type { Component } from 'vue'
|
import type { Component } from 'vue'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { type Task } from '../data/schema'
|
import type { Task } from '../data/schema'
|
||||||
import PlusCircledIcon from '~icons/radix-icons/plus-circled'
|
import PlusCircledIcon from '~icons/radix-icons/plus-circled'
|
||||||
import CheckIcon from '~icons/radix-icons/check'
|
import CheckIcon from '~icons/radix-icons/check'
|
||||||
|
|
||||||
|
|
@ -84,7 +84,8 @@ const selectedValues = computed(() => new Set(props.column?.getFilterValue() as
|
||||||
v-for="option in options"
|
v-for="option in options"
|
||||||
:key="option.value"
|
:key="option.value"
|
||||||
:value="option"
|
:value="option"
|
||||||
@select="() => {
|
@select="(e) => {
|
||||||
|
console.log(e.detail.value)
|
||||||
const isSelected = selectedValues.has(option.value)
|
const isSelected = selectedValues.has(option.value)
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
selectedValues.delete(option.value)
|
selectedValues.delete(option.value)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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(${
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,273 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type {
|
||||||
|
ColumnDef,
|
||||||
|
ColumnFiltersState,
|
||||||
|
SortingState,
|
||||||
|
VisibilityState,
|
||||||
|
} from '@tanstack/vue-table'
|
||||||
|
import {
|
||||||
|
FlexRender,
|
||||||
|
createColumnHelper,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
|
||||||
|
useVueTable,
|
||||||
|
} from '@tanstack/vue-table'
|
||||||
|
import { ArrowUpDown, ChevronDown } from 'lucide-vue-next'
|
||||||
|
|
||||||
|
import { h, ref } from 'vue'
|
||||||
|
import DropdownAction from './DataTableDemoColumn.vue'
|
||||||
|
import { Button } from '@/lib/registry/default/ui/button'
|
||||||
|
import { Checkbox } from '@/lib/registry/default/ui/checkbox'
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuCheckboxItem,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@/lib/registry/default/ui/dropdown-menu'
|
||||||
|
import { Input } from '@/lib/registry/default/ui/input'
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from '@/lib/registry/default/ui/table'
|
||||||
|
import { cn, valueUpdater } from '@/lib/utils'
|
||||||
|
|
||||||
|
export interface Payment {
|
||||||
|
id: string
|
||||||
|
amount: number
|
||||||
|
status: 'pending' | 'processing' | 'success' | 'failed'
|
||||||
|
email: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const data: Payment[] = [
|
||||||
|
{
|
||||||
|
id: 'm5gr84i9',
|
||||||
|
amount: 316,
|
||||||
|
status: 'success',
|
||||||
|
email: 'ken99@yahoo.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3u1reuv4',
|
||||||
|
amount: 242,
|
||||||
|
status: 'success',
|
||||||
|
email: 'Abe45@gmail.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'derv1ws0',
|
||||||
|
amount: 837,
|
||||||
|
status: 'processing',
|
||||||
|
email: 'Monserrat44@gmail.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '5kma53ae',
|
||||||
|
amount: 874,
|
||||||
|
status: 'success',
|
||||||
|
email: 'Silas22@gmail.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'bhqecj4p',
|
||||||
|
amount: 721,
|
||||||
|
status: 'failed',
|
||||||
|
email: 'carmella@hotmail.com',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const columnHelper = createColumnHelper<Payment>()
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
columnHelper.display({
|
||||||
|
id: 'select',
|
||||||
|
header: ({ table }) => h(Checkbox, {
|
||||||
|
'checked': table.getIsAllPageRowsSelected(),
|
||||||
|
'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value),
|
||||||
|
'ariaLabel': 'Select all',
|
||||||
|
}),
|
||||||
|
cell: ({ row, column }) => {
|
||||||
|
return h(Checkbox, {
|
||||||
|
'checked': row.getIsSelected(),
|
||||||
|
'onUpdate:checked': value => row.toggleSelected(!!value),
|
||||||
|
'ariaLabel': 'Select row',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
enableSorting: false,
|
||||||
|
enableHiding: false,
|
||||||
|
}),
|
||||||
|
columnHelper.accessor('status', {
|
||||||
|
enablePinning: true,
|
||||||
|
header: 'Status',
|
||||||
|
cell: ({ row }) => h('div', { class: 'capitalize' }, row.getValue('status')),
|
||||||
|
}),
|
||||||
|
columnHelper.accessor('email', {
|
||||||
|
header: ({ column }) => {
|
||||||
|
return h(Button, {
|
||||||
|
variant: 'ghost',
|
||||||
|
onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'),
|
||||||
|
}, () => ['Email', h(ArrowUpDown, { class: 'ml-2 h-4 w-4' })])
|
||||||
|
},
|
||||||
|
cell: ({ row }) => h('div', { class: 'lowercase' }, row.getValue('email')),
|
||||||
|
}),
|
||||||
|
columnHelper.accessor('amount', {
|
||||||
|
header: () => h('div', { class: 'text-right' }, 'Amount'),
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const amount = Number.parseFloat(row.getValue('amount'))
|
||||||
|
|
||||||
|
// Format the amount as a dollar amount
|
||||||
|
const formatted = new Intl.NumberFormat('en-US', {
|
||||||
|
style: 'currency',
|
||||||
|
currency: 'USD',
|
||||||
|
}).format(amount)
|
||||||
|
|
||||||
|
return h('div', { class: 'text-right font-medium' }, formatted)
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
columnHelper.display({
|
||||||
|
id: 'actions',
|
||||||
|
enableHiding: false,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const payment = row.original
|
||||||
|
|
||||||
|
return h('div', { class: 'relative' }, h(DropdownAction, {
|
||||||
|
payment,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
|
||||||
|
const sorting = ref<SortingState>([])
|
||||||
|
const columnFilters = ref<ColumnFiltersState>([])
|
||||||
|
const columnVisibility = ref<VisibilityState>({})
|
||||||
|
const rowSelection = ref({})
|
||||||
|
|
||||||
|
const table = useVueTable({
|
||||||
|
data,
|
||||||
|
columns,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
onSortingChange: updaterOrValue => valueUpdater(updaterOrValue, sorting),
|
||||||
|
onColumnFiltersChange: updaterOrValue => valueUpdater(updaterOrValue, columnFilters),
|
||||||
|
onColumnVisibilityChange: updaterOrValue => valueUpdater(updaterOrValue, columnVisibility),
|
||||||
|
onRowSelectionChange: updaterOrValue => valueUpdater(updaterOrValue, rowSelection),
|
||||||
|
state: {
|
||||||
|
get sorting() { return sorting.value },
|
||||||
|
get columnFilters() { return columnFilters.value },
|
||||||
|
get columnVisibility() { return columnVisibility.value },
|
||||||
|
get rowSelection() { return rowSelection.value },
|
||||||
|
columnPinning: {
|
||||||
|
left: ['status'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const getState = table.getState()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="w-full">
|
||||||
|
<div class="flex gap-2 items-center py-4">
|
||||||
|
<Input
|
||||||
|
class="max-w-sm"
|
||||||
|
placeholder="Filter emails..."
|
||||||
|
:model-value="table.getColumn('email')?.getFilterValue() as string"
|
||||||
|
@update:model-value=" table.getColumn('email')?.setFilterValue($event)"
|
||||||
|
/>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger as-child>
|
||||||
|
<Button variant="outline" class="ml-auto">
|
||||||
|
Columns <ChevronDown class="ml-2 h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end">
|
||||||
|
<DropdownMenuCheckboxItem
|
||||||
|
v-for="column in table.getAllColumns().filter((column) => column.getCanHide())"
|
||||||
|
:key="column.id"
|
||||||
|
class="capitalize"
|
||||||
|
:checked="column.getIsVisible()"
|
||||||
|
@update:checked="(value) => {
|
||||||
|
column.toggleVisibility(!!value)
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ column.id }}
|
||||||
|
</DropdownMenuCheckboxItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
|
<div class="rounded-md border">
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow v-for="headerGroup in table.getHeaderGroups()" :key="headerGroup.id">
|
||||||
|
<TableHead
|
||||||
|
v-for="header in headerGroup.headers" :key="header.id" :data-pinned="header.column.getIsPinned()"
|
||||||
|
:class="cn(
|
||||||
|
{ 'sticky bg-background/95': header.column.getIsPinned() },
|
||||||
|
header.column.getIsPinned() === 'left' ? 'left-0' : 'right-0',
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<FlexRender v-if="!header.isPlaceholder" :render="header.column.columnDef.header" :props="header.getContext()" />
|
||||||
|
</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
<template v-if="table.getRowModel().rows?.length">
|
||||||
|
<TableRow
|
||||||
|
v-for="row in table.getRowModel().rows"
|
||||||
|
:key="row.id"
|
||||||
|
:data-state="row.getIsSelected() && 'selected'"
|
||||||
|
>
|
||||||
|
<TableCell
|
||||||
|
v-for="cell in row.getVisibleCells()" :key="cell.id" :data-pinned="cell.column.getIsPinned()"
|
||||||
|
:class="cn(
|
||||||
|
{ 'sticky bg-background/95': cell.column.getIsPinned() },
|
||||||
|
cell.column.getIsPinned() === 'left' ? 'left-0' : 'right-0',
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<TableRow v-else>
|
||||||
|
<TableCell
|
||||||
|
col-span="{columns.length}"
|
||||||
|
class="h-24 text-center"
|
||||||
|
>
|
||||||
|
No results.
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-end space-x-2 py-4">
|
||||||
|
<div class="flex-1 text-sm text-muted-foreground">
|
||||||
|
{{ table.getFilteredSelectedRowModel().rows.length }} of
|
||||||
|
{{ table.getFilteredRowModel().rows.length }} row(s) selected.
|
||||||
|
</div>
|
||||||
|
<div class="space-x-2">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
:disabled="!table.getCanPreviousPage()"
|
||||||
|
@click="table.previousPage()"
|
||||||
|
>
|
||||||
|
Previous
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
:disabled="!table.getCanNextPage()"
|
||||||
|
@click="table.nextPage()"
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Button } from '@/lib/registry/default/ui/button'
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from '@/lib/registry/default/ui/dialog'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Dialog>
|
||||||
|
<DialogTrigger as-child>
|
||||||
|
<Button variant="outline">
|
||||||
|
Edit Profile
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent class="sm:max-w-[425px] grid-rows-[auto_minmax(0,1fr)_auto] p-0 max-h-[90dvh]">
|
||||||
|
<DialogHeader class="p-6 pb-0">
|
||||||
|
<DialogTitle>Edit profile</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Make changes to your profile here. Click save when you're done.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div class="grid gap-4 py-4 overflow-y-auto px-6">
|
||||||
|
<div class="flex flex-col justify-between h-[300dvh]">
|
||||||
|
<p>
|
||||||
|
This is some placeholder content to show the scrolling behavior for modals. We use repeated line breaks to demonstrate how content can exceed minimum inner height, thereby showing inner scrolling. When content becomes longer than the predefined max-height of modal, content will be cropped and scrollable within the modal.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>This content should appear at the bottom after you scroll.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<DialogFooter class="p-6 pt-0">
|
||||||
|
<Button type="submit">
|
||||||
|
Save changes
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Button } from '@/lib/registry/default/ui/button'
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogScrollContent,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from '@/lib/registry/default/ui/dialog'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Dialog>
|
||||||
|
<DialogTrigger as-child>
|
||||||
|
<Button variant="outline">
|
||||||
|
Edit Profile
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogScrollContent class="sm:max-w-[425px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Modal title</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Here is modal with overlay scroll
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div class="grid gap-4 py-4 h-[300dvh]">
|
||||||
|
<p>
|
||||||
|
This is some placeholder content to show the scrolling behavior for modals. Instead of repeating the text in the modal, we use an inline style to set a minimum height, thereby extending the length of the overall modal and demonstrating the overflow scrolling. When content becomes longer than the height of the viewport, scrolling will move the modal as needed.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button type="submit">
|
||||||
|
Save changes
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogScrollContent>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
13
apps/www/src/lib/registry/default/example/InputWithIcon.vue
Normal file
13
apps/www/src/lib/registry/default/example/InputWithIcon.vue
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { MagnifyingGlassIcon } from '@radix-icons/vue'
|
||||||
|
import { Input } from '@/lib/registry/default/ui/input'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="relative w-full max-w-sm items-center">
|
||||||
|
<Input id="search" type="text" placeholder="Search..." class="pl-10" />
|
||||||
|
<span class="absolute start-0 inset-y-0 flex items-center justify-center px-2">
|
||||||
|
<MagnifyingGlassIcon class="size-6 text-muted-foreground" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
28
apps/www/src/lib/registry/default/example/PinInputDemo.vue
Normal file
28
apps/www/src/lib/registry/default/example/PinInputDemo.vue
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import {
|
||||||
|
PinInput,
|
||||||
|
PinInputInput,
|
||||||
|
} from '@/lib/registry/default/ui/pin-input'
|
||||||
|
|
||||||
|
const value = ref<string[]>([])
|
||||||
|
const handleComplete = (e: string[]) => alert(e.join(''))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<PinInput
|
||||||
|
id="pin-input"
|
||||||
|
v-model="value"
|
||||||
|
placeholder="○"
|
||||||
|
class="flex gap-2 items-center mt-1"
|
||||||
|
@complete="handleComplete"
|
||||||
|
>
|
||||||
|
<PinInputInput
|
||||||
|
v-for="(id, index) in 5"
|
||||||
|
:key="id"
|
||||||
|
:index="index"
|
||||||
|
/>
|
||||||
|
</PinInput>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { h } from 'vue'
|
||||||
|
import { useForm } from 'vee-validate'
|
||||||
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
|
import * as z from 'zod'
|
||||||
|
import {
|
||||||
|
PinInput,
|
||||||
|
PinInputInput,
|
||||||
|
} from '@/lib/registry/new-york/ui/pin-input'
|
||||||
|
import { Button } from '@/lib/registry/default/ui/button'
|
||||||
|
import {
|
||||||
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from '@/lib/registry/default/ui/form'
|
||||||
|
import { toast } from '@/lib/registry/default/ui/toast'
|
||||||
|
|
||||||
|
const formSchema = toTypedSchema(z.object({
|
||||||
|
pin: z.array(z.coerce.string()).length(5, { message: 'Invalid input' }),
|
||||||
|
}))
|
||||||
|
|
||||||
|
const { handleSubmit, setValues } = useForm({
|
||||||
|
validationSchema: formSchema,
|
||||||
|
initialValues: {
|
||||||
|
pin: [],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const onSubmit = handleSubmit(({ pin }) => {
|
||||||
|
toast({
|
||||||
|
title: 'You submitted the following values:',
|
||||||
|
description: h('pre', { class: 'mt-2 w-[340px] rounded-md bg-slate-950 p-4' }, h('code', { class: 'text-white' }, JSON.stringify(pin.join(''), null, 2))),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleComplete = (e: string[]) => console.log(e.join(''))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<form class="w-2/3 space-y-6 mx-auto" @submit="onSubmit">
|
||||||
|
<FormField v-slot="{ componentField }" name="pin">
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>OTP</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<PinInput
|
||||||
|
id="pin-input"
|
||||||
|
placeholder="○"
|
||||||
|
class="flex gap-2 items-center mt-1"
|
||||||
|
otp
|
||||||
|
type="number"
|
||||||
|
:name="componentField.name"
|
||||||
|
@complete="handleComplete"
|
||||||
|
@update:model-value="(arrStr) => {
|
||||||
|
setValues({
|
||||||
|
pin: arrStr.filter(Boolean),
|
||||||
|
})
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<PinInputInput
|
||||||
|
v-for="(id, index) in 5"
|
||||||
|
:key="id"
|
||||||
|
:index="index"
|
||||||
|
/>
|
||||||
|
</PinInput>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
Allows users to input a sequence of one-character alphanumeric inputs.
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<Button>Submit</Button>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { addDays, format } from 'date-fns'
|
||||||
|
import { Calendar as CalendarIcon } from 'lucide-vue-next'
|
||||||
|
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
import { Button } from '@/lib/registry/default/ui/button'
|
||||||
|
import { Calendar } from '@/lib/registry/default/ui/calendar'
|
||||||
|
import {
|
||||||
|
Popover,
|
||||||
|
PopoverContent,
|
||||||
|
PopoverTrigger,
|
||||||
|
} from '@/lib/registry/default/ui/popover'
|
||||||
|
|
||||||
|
const date = ref({
|
||||||
|
start: new Date(2022, 0, 20),
|
||||||
|
end: addDays(new Date(2022, 0, 20), 20),
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div :class="cn('grid gap-2', $attrs.class ?? '')">
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger as-child>
|
||||||
|
<Button
|
||||||
|
id="date"
|
||||||
|
:variant="'outline'"
|
||||||
|
:class="cn(
|
||||||
|
'w-[300px] justify-start text-left font-normal',
|
||||||
|
!date && 'text-muted-foreground',
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<CalendarIcon class="mr-2 h-4 w-4" />
|
||||||
|
|
||||||
|
<span>
|
||||||
|
{{ date.start ? (
|
||||||
|
date.end ? `${format(date.start, 'LLL dd, y')} - ${format(date.end, 'LLL dd, y')}`
|
||||||
|
: format(date.start, 'LLL dd, y')
|
||||||
|
) : 'Pick a date' }}
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent class="w-auto p-0" align="start">
|
||||||
|
<Calendar
|
||||||
|
v-model.range="date"
|
||||||
|
mode="date"
|
||||||
|
:columns="2"
|
||||||
|
>
|
||||||
|
<template #footer>
|
||||||
|
<div class="w-full px-3 pb-3">
|
||||||
|
Entry time
|
||||||
|
<Calendar
|
||||||
|
v-model="date.start"
|
||||||
|
mode="time"
|
||||||
|
hide-time-header
|
||||||
|
/>
|
||||||
|
Exit time
|
||||||
|
<Calendar
|
||||||
|
v-model="date.end"
|
||||||
|
mode="time"
|
||||||
|
hide-time-header
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Calendar>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
20
apps/www/src/lib/registry/default/example/SonnerDemo.vue
Normal file
20
apps/www/src/lib/registry/default/example/SonnerDemo.vue
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { toast } from 'vue-sonner'
|
||||||
|
import { Button } from '@/lib/registry/default/ui/button'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Button
|
||||||
|
variant="outline" @click="() => {
|
||||||
|
toast('Event has been created', {
|
||||||
|
description: 'Sunday, December 03, 2023 at 9:00 AM',
|
||||||
|
action: {
|
||||||
|
label: 'Undo',
|
||||||
|
onClick: () => console.log('Undo'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
Add to calendar
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import { ComboboxAnchor, ComboboxInput, ComboboxPortal, ComboboxRoot } from 'radix-vue'
|
||||||
|
import { CommandEmpty, CommandGroup, CommandItem, CommandList } from '@/lib/registry/default/ui/command'
|
||||||
|
import { TagsInput, TagsInputInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText } from '@/lib/registry/default/ui/tags-input'
|
||||||
|
|
||||||
|
const frameworks = [
|
||||||
|
{ value: 'next.js', label: 'Next.js' },
|
||||||
|
{ value: 'sveltekit', label: 'SvelteKit' },
|
||||||
|
{ value: 'nuxt.js', label: 'Nuxt.js' },
|
||||||
|
{ value: 'remix', label: 'Remix' },
|
||||||
|
{ value: 'astro', label: 'Astro' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const modelValue = ref<string[]>([])
|
||||||
|
const open = ref(false)
|
||||||
|
const searchTerm = ref('')
|
||||||
|
|
||||||
|
const filteredFrameworks = computed(() => frameworks.filter(i => !modelValue.value.includes(i.label)))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<TagsInput class="px-0 gap-0 w-80" :model-value="modelValue">
|
||||||
|
<div class="flex gap-2 flex-wrap items-center px-3">
|
||||||
|
<TagsInputItem v-for="item in modelValue" :key="item" :value="item">
|
||||||
|
<TagsInputItemText />
|
||||||
|
<TagsInputItemDelete />
|
||||||
|
</TagsInputItem>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ComboboxRoot v-model="modelValue" v-model:open="open" v-model:searchTerm="searchTerm" class="w-full">
|
||||||
|
<ComboboxAnchor as-child>
|
||||||
|
<ComboboxInput placeholder="Framework..." as-child>
|
||||||
|
<TagsInputInput class="w-full px-3" :class="modelValue.length > 0 ? 'mt-2' : ''" @keydown.enter.prevent />
|
||||||
|
</ComboboxInput>
|
||||||
|
</ComboboxAnchor>
|
||||||
|
|
||||||
|
<ComboboxPortal>
|
||||||
|
<CommandList
|
||||||
|
position="popper"
|
||||||
|
class="w-[--radix-popper-anchor-width] rounded-md mt-2 border bg-popover text-popover-foreground shadow-md outline-none 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"
|
||||||
|
>
|
||||||
|
<CommandEmpty />
|
||||||
|
<CommandGroup>
|
||||||
|
<CommandItem
|
||||||
|
v-for="framework in filteredFrameworks" :key="framework.value" :value="framework.label"
|
||||||
|
@select.prevent="(ev) => {
|
||||||
|
if (typeof ev.detail.value === 'string') {
|
||||||
|
searchTerm = ''
|
||||||
|
modelValue.push(ev.detail.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filteredFrameworks.length === 0) {
|
||||||
|
open = false
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ framework.label }}
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</ComboboxPortal>
|
||||||
|
</ComboboxRoot>
|
||||||
|
</TagsInput>
|
||||||
|
</template>
|
||||||
17
apps/www/src/lib/registry/default/example/TagsInputDemo.vue
Normal file
17
apps/www/src/lib/registry/default/example/TagsInputDemo.vue
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { TagsInput, TagsInputInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText } from '@/lib/registry/default/ui/tags-input'
|
||||||
|
|
||||||
|
const modelValue = ref(['Apple', 'Banana'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<TagsInput v-model="modelValue">
|
||||||
|
<TagsInputItem v-for="item in modelValue" :key="item" :value="item">
|
||||||
|
<TagsInputItemText />
|
||||||
|
<TagsInputItemDelete />
|
||||||
|
</TagsInputItem>
|
||||||
|
|
||||||
|
<TagsInputInput placeholder="Fruits..." />
|
||||||
|
</TagsInput>
|
||||||
|
</template>
|
||||||
|
|
@ -14,6 +14,6 @@ const { toast } = useToast()
|
||||||
});
|
});
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
Add to calander
|
Add to calendar
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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',
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +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 } from 'vue'
|
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
|
||||||
|
|
@ -28,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
|
||||||
|
|
@ -64,6 +64,16 @@ onMounted(async () => {
|
||||||
if (modelValue.value instanceof Date && calendarRef.value)
|
if (modelValue.value instanceof Date && calendarRef.value)
|
||||||
calendarRef.value.focusDate(modelValue.value)
|
calendarRef.value.focusDate(modelValue.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const $slots = useSlots()
|
||||||
|
const vCalendarSlots = computed(() => {
|
||||||
|
return Object.keys($slots)
|
||||||
|
.filter(name => isVCalendarSlot(name))
|
||||||
|
.reduce((obj: Record<string, any>, key: string) => {
|
||||||
|
obj[key] = $slots[key]
|
||||||
|
return obj
|
||||||
|
}, {})
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -79,18 +89,30 @@ onMounted(async () => {
|
||||||
|
|
||||||
<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
|
||||||
:transition="'none'"
|
:transition="'none'"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
/>
|
>
|
||||||
|
<template v-for="(_, slot) of vCalendarSlots" #[slot]="scope">
|
||||||
|
<slot :name="slot" v-bind="scope" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #nav-prev-button>
|
||||||
|
<ChevronLeft />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #nav-next-button>
|
||||||
|
<ChevronRight />
|
||||||
|
</template>
|
||||||
|
</DatePicker>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="postcss">
|
<style lang="css">
|
||||||
.calendar {
|
.calendar {
|
||||||
@apply p-3 text-center;
|
@apply p-3 text-center;
|
||||||
}
|
}
|
||||||
|
|
@ -98,7 +120,25 @@ onMounted(async () => {
|
||||||
@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;
|
||||||
|
|
@ -107,19 +147,19 @@ onMounted(async () => {
|
||||||
@apply mt-4;
|
@apply mt-4;
|
||||||
}
|
}
|
||||||
.calendar .vc-weekdays {
|
.calendar .vc-weekdays {
|
||||||
@apply flex;
|
@apply justify-items-center;
|
||||||
}
|
}
|
||||||
.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 font-normal text-[0.8rem];
|
||||||
}
|
}
|
||||||
.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;
|
||||||
|
|
@ -131,7 +171,7 @@ onMounted(async () => {
|
||||||
@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;
|
||||||
|
|
@ -157,6 +197,7 @@ onMounted(async () => {
|
||||||
--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,
|
||||||
|
|
@ -183,6 +224,7 @@ onMounted(async () => {
|
||||||
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,
|
||||||
|
|
@ -192,6 +234,7 @@ onMounted(async () => {
|
||||||
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,
|
||||||
|
|
@ -208,6 +251,7 @@ onMounted(async () => {
|
||||||
.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,
|
||||||
|
|
@ -215,6 +259,7 @@ onMounted(async () => {
|
||||||
-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,
|
||||||
|
|
@ -222,6 +267,7 @@ onMounted(async () => {
|
||||||
-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,
|
||||||
|
|
@ -229,6 +275,7 @@ onMounted(async () => {
|
||||||
-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,
|
||||||
|
|
|
||||||
|
|
@ -1 +1,22 @@
|
||||||
export { default as Calendar } from './Calendar.vue'
|
export { default as Calendar } from './Calendar.vue'
|
||||||
|
import type { CalendarSlotName } from 'v-calendar/dist/types/src/components/Calendar/CalendarSlot.vue.d.ts'
|
||||||
|
|
||||||
|
export function isVCalendarSlot(slotName: string): slotName is CalendarSlotName {
|
||||||
|
const validSlots: CalendarSlotName[] = [
|
||||||
|
'day-content',
|
||||||
|
'day-popover',
|
||||||
|
'dp-footer',
|
||||||
|
'footer',
|
||||||
|
'header-title-wrapper',
|
||||||
|
'header-title',
|
||||||
|
'header-prev-button',
|
||||||
|
'header-next-button',
|
||||||
|
'nav',
|
||||||
|
'nav-prev-button',
|
||||||
|
'nav-next-button',
|
||||||
|
'page',
|
||||||
|
'time-header',
|
||||||
|
]
|
||||||
|
|
||||||
|
return validSlots.includes(slotName as CalendarSlotName)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
<script setup lang="ts">
|
<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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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 />
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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({
|
||||||
|
|
|
||||||
|
|
@ -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>()
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user