Merge remote-tracking branch 'origin/dev' into charting
This commit is contained in:
commit
26e3ea917c
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"vue.server.hybridMode": true,
|
||||
"eslint.experimental.useFlatConfig": true,
|
||||
"prettier.enable": false,
|
||||
"editor.formatOnSave": false,
|
||||
|
|
|
|||
|
|
@ -32,12 +32,12 @@ packages
|
|||
└── cli
|
||||
```
|
||||
|
||||
| Path | Description |
|
||||
| --------------------- | ---------------------------------------- |
|
||||
| `apps/www/app` | The Next.js application for the website. |
|
||||
| `apps/www/content` | The content for the website. |
|
||||
| `apps/www/registry` | The registry for the components. |
|
||||
| `packages/cli` | The `shadcn-vue` package. |
|
||||
| Path | Description |
|
||||
| ----------------------------| -------------------------------------------|
|
||||
| `apps/www/.vitepress` | The Vitepress application for the website. |
|
||||
| `apps/www/src/content` | The content for the website. |
|
||||
| `apps/www/src/lib/registry` | The registry for the components. |
|
||||
| `packages/cli` | The `shadcn-vue` package. |
|
||||
|
||||
## Development
|
||||
|
||||
|
|
@ -79,22 +79,24 @@ The documentation for this project is located in the `www` workspace. You can ru
|
|||
pnpm dev
|
||||
```
|
||||
|
||||
Documentation is written using [md](https://vitepress.dev/guide/markdown). You can find the documentation files in the `apps/www/content/docs` directory.
|
||||
Documentation is written using [md](https://vitepress.dev/guide/markdown). You can find the documentation files in the `apps/www/src/content` directory.
|
||||
|
||||
## Components
|
||||
|
||||
We use a registry system for developing components. You can find the source code for the components under `apps/www/registry`. The components are organized by styles.
|
||||
We use a registry system for developing components. You can find the source code for the components under `apps/www/src/lib/registry`. The components are organized by styles.
|
||||
|
||||
```bash
|
||||
apps
|
||||
└── www
|
||||
└── registry
|
||||
├── default
|
||||
│ ├── example
|
||||
│ └── ui
|
||||
└── new-york
|
||||
├── example
|
||||
└── ui
|
||||
└── src
|
||||
└── lib
|
||||
└── registry
|
||||
├── default
|
||||
│ ├── example
|
||||
│ └── ui
|
||||
└── new-york
|
||||
├── example
|
||||
└── ui
|
||||
```
|
||||
|
||||
When adding or modifying components, please ensure that:
|
||||
|
|
@ -130,13 +132,10 @@ the following categories:
|
|||
|
||||
e.g. `feat(components): add new prop to the avatar component`
|
||||
|
||||
|
||||
If you are interested in the detailed specification you can visit
|
||||
https://www.conventionalcommits.org/ or check out the
|
||||
[Angular Commit Message Guidelines](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines).
|
||||
|
||||
|
||||
|
||||
## Requests for new components
|
||||
|
||||
If you have a request for a new component, please open a discussion on GitHub. We'll be happy to help you out.
|
||||
|
|
|
|||
|
|
@ -3,16 +3,12 @@ import { defineConfig } from 'vitepress'
|
|||
import Icons from 'unplugin-icons/vite'
|
||||
import tailwind from 'tailwindcss'
|
||||
import autoprefixer from 'autoprefixer'
|
||||
import { createCssVariablesTheme } from 'shiki'
|
||||
import { cssVariables } from './theme/config/shiki'
|
||||
|
||||
// import { transformerMetaWordHighlight, transformerNotationWordHighlight } from '@shikijs/transformers'
|
||||
import { siteConfig } from './theme/config/site'
|
||||
import ComponentPreviewPlugin from './theme/plugins/previewer'
|
||||
|
||||
const cssVariables = createCssVariablesTheme({
|
||||
variablePrefix: '--shiki-',
|
||||
variableDefaults: {},
|
||||
})
|
||||
import CodeWrapperPlugin from './theme/plugins/codewrapper'
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
|
|
@ -65,6 +61,7 @@ export default defineConfig({
|
|||
],
|
||||
config(md) {
|
||||
md.use(ComponentPreviewPlugin)
|
||||
md.use(CodeWrapperPlugin)
|
||||
},
|
||||
},
|
||||
rewrites: {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
<script lang="ts" setup>
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import * as z from 'zod'
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import { Input } from '@/lib/registry/new-york/ui/input'
|
||||
import { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/lib/registry/new-york/ui/form'
|
||||
import { Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from '@/lib/registry/new-york/ui/sheet'
|
||||
import RadixIconsGear from '~icons/radix-icons/gear'
|
||||
|
||||
const { codeConfig, setCodeConfig } = useConfigStore()
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
prefix: z.string().default(''),
|
||||
componentsPath: z.string().default('@/components'),
|
||||
utilsPath: z.string().default('@/utils'),
|
||||
}))
|
||||
|
||||
const { handleSubmit, setValues } = useForm({
|
||||
validationSchema: formSchema,
|
||||
initialValues: codeConfig.value,
|
||||
})
|
||||
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
setCodeConfig(values)
|
||||
setValues(values)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Sheet
|
||||
@update:open="(open) => {
|
||||
if (open) setValues(codeConfig)
|
||||
}"
|
||||
>
|
||||
<SheetTrigger as-child>
|
||||
<Button
|
||||
class="w-9 h-9"
|
||||
:variant="'ghost'"
|
||||
:size="'icon'"
|
||||
>
|
||||
<RadixIconsGear class="w-5 h-5" />
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent>
|
||||
<form @submit="onSubmit">
|
||||
<SheetHeader>
|
||||
<SheetTitle>Edit code config</SheetTitle>
|
||||
<SheetDescription>
|
||||
Configure how the CodeBlock should render on the site.
|
||||
</SheetDescription>
|
||||
</SheetHeader>
|
||||
|
||||
<div class="my-4">
|
||||
<!-- <FormField v-slot="{ componentField }" name="prefix">
|
||||
<FormItem>
|
||||
<FormLabel>Prefix</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="" v-bind="componentField" />
|
||||
</FormControl>
|
||||
<FormDescription />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField> -->
|
||||
<FormField v-slot="{ componentField }" name="componentsPath">
|
||||
<FormItem>
|
||||
<FormLabel>Components Path</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="@/components" v-bind="componentField" />
|
||||
</FormControl>
|
||||
<FormDescription />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
<FormField v-slot="{ componentField }" name="utilsPath">
|
||||
<FormItem>
|
||||
<FormLabel>Utils Path</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="@/utils" v-bind="componentField" />
|
||||
</FormControl>
|
||||
<FormDescription />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</div>
|
||||
|
||||
<SheetFooter>
|
||||
<SheetClose as-child>
|
||||
<Button type="submit">
|
||||
Save changes
|
||||
</Button>
|
||||
</SheetClose>
|
||||
</SheetFooter>
|
||||
</form>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
</template>
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { ref, toRefs, watch } from 'vue'
|
||||
import { Icon } from '@iconify/vue'
|
||||
import { makeCodeSandboxParams } from '../utils/codeeditor'
|
||||
import Tooltip from './Tooltip.vue'
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import { type Style } from '@/lib/registry/styles'
|
||||
import type { Style } from '@/lib/registry/styles'
|
||||
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
|
|
@ -12,11 +12,12 @@ const props = defineProps<{
|
|||
style: Style
|
||||
}>()
|
||||
|
||||
const { code } = toRefs(props)
|
||||
const sources = ref<Record<string, string>>({})
|
||||
|
||||
onMounted(() => {
|
||||
sources.value['App.vue'] = props.code
|
||||
})
|
||||
watch(code, () => {
|
||||
sources.value['App.vue'] = code.value
|
||||
}, { immediate: true })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
46
apps/www/.vitepress/theme/components/CodeWrapper.ts
Normal file
46
apps/www/.vitepress/theme/components/CodeWrapper.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import { type VNode, type VNodeArrayChildren, cloneVNode, defineComponent } from 'vue'
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
|
||||
function crawlSpan(children: VNodeArrayChildren, cb: (vnode: VNode) => void) {
|
||||
children.forEach((childNode) => {
|
||||
if (!Array.isArray(childNode) && typeof childNode === 'object') {
|
||||
if (typeof childNode?.children === 'string')
|
||||
cb(childNode)
|
||||
else
|
||||
crawlSpan(childNode?.children as VNodeArrayChildren ?? [], cb)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default defineComponent(
|
||||
(props, { slots }) => {
|
||||
const { codeConfig } = useConfigStore()
|
||||
|
||||
return () => {
|
||||
const clonedVNode = slots.default?.()?.[0]
|
||||
? cloneVNode(slots.default?.()?.[0], {
|
||||
key: JSON.stringify(codeConfig.value),
|
||||
})
|
||||
: undefined
|
||||
|
||||
// @ts-expect-error cloneVNode
|
||||
const preVNode = [...clonedVNode?.children].find((node: VNode) => node.type === 'pre') as VNode
|
||||
// @ts-expect-error cloneVNode
|
||||
const codeVNode = preVNode.children?.at(0) as VNode
|
||||
|
||||
if (codeVNode) {
|
||||
crawlSpan(codeVNode.children as VNodeArrayChildren, (vnode) => {
|
||||
if (typeof vnode.children === 'string') {
|
||||
vnode.children = vnode.children.replaceAll('@/components', codeConfig.value.componentsPath)
|
||||
vnode.children = vnode.children.replaceAll('@/libs', codeConfig.value.utilsPath)
|
||||
}
|
||||
})
|
||||
|
||||
return clonedVNode
|
||||
}
|
||||
else {
|
||||
return slots.default?.()
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
@ -1,4 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { codeToHtml } from 'shiki'
|
||||
import MagicString from 'magic-string'
|
||||
import { cssVariables } from '../config/shiki'
|
||||
import StyleSwitcher from './StyleSwitcher.vue'
|
||||
import ComponentLoader from './ComponentLoader.vue'
|
||||
import Stackblitz from './Stackblitz.vue'
|
||||
|
|
@ -11,14 +15,35 @@ defineOptions({
|
|||
inheritAttrs: false,
|
||||
})
|
||||
|
||||
withDefaults(defineProps<{
|
||||
const props = withDefaults(defineProps<{
|
||||
name: string
|
||||
align?: 'center' | 'start' | 'end'
|
||||
sfcTsCode?: string
|
||||
sfcTsHtml?: string
|
||||
}>(), { align: 'center' })
|
||||
|
||||
const { style } = useConfigStore()
|
||||
const { style, codeConfig } = useConfigStore()
|
||||
|
||||
const rawString = ref('')
|
||||
const codeHtml = ref('')
|
||||
|
||||
function transformImportPath(code: string) {
|
||||
const s = new MagicString(code)
|
||||
s.replaceAll(`@/lib/registry/${style.value}`, codeConfig.value.componentsPath)
|
||||
s.replaceAll(`@/lib/utils`, codeConfig.value.utilsPath)
|
||||
return s.toString()
|
||||
}
|
||||
|
||||
watch([style, codeConfig], async () => {
|
||||
try {
|
||||
rawString.value = await import(`../../../src/lib/registry/${style.value}/example/${props.name}.vue?raw`).then(res => res.default.trim())
|
||||
codeHtml.value = await codeToHtml(transformImportPath(rawString.value), {
|
||||
lang: 'vue',
|
||||
theme: cssVariables,
|
||||
})
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}, { immediate: true, deep: true })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -47,8 +72,8 @@ const { style } = useConfigStore()
|
|||
<StyleSwitcher />
|
||||
|
||||
<div class="flex items-center gap-x-1">
|
||||
<Stackblitz :key="style" :style="style" :name="name" :code="decodeURIComponent(sfcTsCode ?? '')" />
|
||||
<CodeSandbox :key="style" :style="style" :name="name" :code="decodeURIComponent(sfcTsCode ?? '')" />
|
||||
<Stackblitz :key="style" :style="style" :name="name" :code="rawString" />
|
||||
<CodeSandbox :key="style" :style="style" :name="name" :code="rawString" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
|
@ -62,7 +87,7 @@ const { style } = useConfigStore()
|
|||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="code">
|
||||
<div v-if="sfcTsHtml" class="language-vue" style="flex: 1;" v-html="decodeURIComponent(sfcTsHtml)" />
|
||||
<div v-if="codeHtml" class="language-vue" style="flex: 1;" v-html="codeHtml" />
|
||||
<slot v-else />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<a href="/" class="mr-4 md:mr-2 xl:mr-6 flex items-center lg:space-x1 xl:space-x-2">
|
||||
<a href="/" class="mr-4 md:mr-2 lg:mr-6 flex items-center lg:space-x1 xl:space-x-2">
|
||||
<svg class="h-6 w-6" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_102_1338)">
|
||||
<path d="M208 128L128 208" stroke="#41B883" stroke-width="16" stroke-linecap="round" stroke-linejoin="round" />
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { ref, toRefs, watch } from 'vue'
|
||||
import { Icon } from '@iconify/vue'
|
||||
import { makeStackblitzParams } from '../utils/codeeditor'
|
||||
import Tooltip from './Tooltip.vue'
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import { type Style } from '@/lib/registry/styles'
|
||||
import type { Style } from '@/lib/registry/styles'
|
||||
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
|
|
@ -12,11 +12,12 @@ const props = defineProps<{
|
|||
style: Style
|
||||
}>()
|
||||
|
||||
const { code } = toRefs(props)
|
||||
const sources = ref<Record<string, string>>({})
|
||||
|
||||
onMounted(() => {
|
||||
sources.value['App.vue'] = props.code
|
||||
})
|
||||
watch(code, () => {
|
||||
sources.value['App.vue'] = code.value
|
||||
}, { immediate: true })
|
||||
|
||||
function handleClick() {
|
||||
makeStackblitzParams(props.name, props.style, sources.value)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { type SelectTriggerProps } from 'radix-vue'
|
||||
import type { SelectTriggerProps } from 'radix-vue'
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { useSlots } from 'vue'
|
||||
import { TabsContent, TabsTrigger } from '@/lib/registry/default/ui/tabs'
|
||||
import { TabsContent } from '@/lib/registry/default/ui/tabs'
|
||||
|
||||
withDefaults(defineProps<{
|
||||
title?: string
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, useSlots } from 'vue'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/lib/registry/default/ui/tabs'
|
||||
import { Tabs, TabsList, TabsTrigger } from '@/lib/registry/default/ui/tabs'
|
||||
|
||||
const slots = useSlots()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
export { default as CodeWrapper } from './CodeWrapper'
|
||||
export { default as ComponentPreview } from './ComponentPreview.vue'
|
||||
export { default as TabPreview } from './TabPreview.vue'
|
||||
export { default as TabMarkdown } from './TabMarkdown.vue'
|
||||
|
|
|
|||
|
|
@ -89,6 +89,12 @@ export const docsConfig: DocsConfig = {
|
|||
title: 'About',
|
||||
href: '/docs/about',
|
||||
},
|
||||
{
|
||||
title: 'Contribution',
|
||||
href: '/docs/contribution',
|
||||
items: [],
|
||||
label: 'New',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -161,6 +167,12 @@ export const docsConfig: DocsConfig = {
|
|||
title: 'Badge',
|
||||
href: '/docs/components/badge',
|
||||
},
|
||||
{
|
||||
title: 'Breadcrumb',
|
||||
href: '/docs/components/breadcrumb',
|
||||
items: [],
|
||||
label: 'New',
|
||||
},
|
||||
{
|
||||
title: 'Button',
|
||||
href: '/docs/components/button',
|
||||
|
|
|
|||
6
apps/www/.vitepress/theme/config/shiki.ts
Normal file
6
apps/www/.vitepress/theme/config/shiki.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import { createCssVariablesTheme } from 'shiki'
|
||||
|
||||
export const cssVariables = createCssVariablesTheme({
|
||||
variablePrefix: '--shiki-',
|
||||
variableDefaults: {},
|
||||
})
|
||||
|
|
@ -4,7 +4,6 @@ import { docsConfig } from '../config/docs'
|
|||
import TableOfContentVue from '../components/TableOfContent.vue'
|
||||
import EditLink from '../components/EditLink.vue'
|
||||
import { ScrollArea } from '@/lib/registry/default/ui/scroll-area'
|
||||
import { Badge } from '@/lib/registry/default/ui/badge'
|
||||
import RadixIconsCode from '~icons/radix-icons/code'
|
||||
import RadixIconsExternalLink from '~icons/radix-icons/external-link'
|
||||
import ChevronRightIcon from '~icons/lucide/chevron-right'
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
import { useMagicKeys, useToggle } from '@vueuse/core'
|
||||
import { onMounted, ref, watch } from 'vue'
|
||||
import { Content, useData, useRoute, useRouter } from 'vitepress'
|
||||
import { SearchIcon } from 'lucide-vue-next'
|
||||
import { type NavItem, docsConfig } from '../config/docs'
|
||||
import Logo from '../components/Logo.vue'
|
||||
import MobileNav from '../components/MobileNav.vue'
|
||||
import CodeConfigCustomizer from '../components/CodeConfigCustomizer.vue'
|
||||
|
||||
import Kbd from '../components/Kbd.vue'
|
||||
import ThemePopover from '../components/ThemePopover.vue'
|
||||
|
|
@ -94,7 +94,7 @@ watch(() => $route.path, (n) => {
|
|||
<Logo />
|
||||
|
||||
<nav
|
||||
class="flex items-center space-x-6 text-sm font-medium"
|
||||
class="flex items-center max-lg:space-x-4 space-x-6 text-sm font-medium"
|
||||
>
|
||||
<a
|
||||
v-for="route in docsConfig.mainNav"
|
||||
|
|
@ -120,38 +120,42 @@ watch(() => $route.path, (n) => {
|
|||
class="relative h-8 w-full justify-start rounded-[0.5rem] bg-background text-sm font-normal text-muted-foreground shadow-none sm:pr-12 md:w-40 lg:w-64"
|
||||
@click="isOpen = true"
|
||||
>
|
||||
<span className="hidden lg:inline-flex">Search documentation...</span>
|
||||
<span className="inline-flex lg:hidden">Search...</span>
|
||||
<kbd className="pointer-events-none absolute right-[0.3rem] top-[0.3rem] hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex">
|
||||
<span className="text-xs">⌘</span>K
|
||||
</kbd>
|
||||
<span class="hidden lg:inline-flex">Search documentation...</span>
|
||||
<span class="inline-flex lg:hidden">Search...</span>
|
||||
<Kbd class="pointer-events-none absolute right-[0.3rem] top-[0.3rem] hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex">
|
||||
<span class="text-xs">⌘</span>K
|
||||
</Kbd>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<nav class="flex items-center gap-x-1">
|
||||
<nav class="flex items-center">
|
||||
<ThemePopover />
|
||||
|
||||
<CodeConfigCustomizer />
|
||||
|
||||
<Button
|
||||
v-for="link in links"
|
||||
:key="link.name"
|
||||
as="a"
|
||||
class="w-9 h-9"
|
||||
:href="link.href" target="_blank"
|
||||
:variant="'ghost'"
|
||||
:size="'sm'"
|
||||
:size="'icon'"
|
||||
>
|
||||
<component :is="link.icon" class="w-[20px] h-5" />
|
||||
<component :is="link.icon" class="w-5 h-5" />
|
||||
</Button>
|
||||
|
||||
<ClientOnly>
|
||||
<Button
|
||||
class="flex items-center justify-center"
|
||||
class="w-9 h-9"
|
||||
aria-label="Toggle dark mode"
|
||||
:variant="'ghost'"
|
||||
:size="'icon'" @click="toggleDark()"
|
||||
:size="'icon'"
|
||||
@click="toggleDark()"
|
||||
>
|
||||
<component
|
||||
:is="isDark ? RadixIconsSun : RadixIconsMoon"
|
||||
class="w-[20px] h-5 text-foreground"
|
||||
class="w-5 h-5 text-foreground"
|
||||
/>
|
||||
</Button>
|
||||
</ClientOnly>
|
||||
|
|
@ -297,4 +301,4 @@ watch(() => $route.path, (n) => {
|
|||
<NewYorkSonner :theme="'system'" />
|
||||
<NewYorkToaster />
|
||||
</div>
|
||||
</template>
|
||||
</template>../components/CodeConfigCustomizer.vue
|
||||
|
|
|
|||
20
apps/www/.vitepress/theme/plugins/codewrapper.ts
Normal file
20
apps/www/.vitepress/theme/plugins/codewrapper.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import type { MarkdownRenderer } from 'vitepress'
|
||||
|
||||
export default function (md: MarkdownRenderer) {
|
||||
const defaultFenceRenderer = md.renderer.rules.fence
|
||||
if (!defaultFenceRenderer)
|
||||
return
|
||||
|
||||
md.renderer.rules.fence = function (tokens, idx, options, env, self) {
|
||||
// Check if this is a code block
|
||||
const token = tokens[idx]
|
||||
const isAllowedExtension = (token.info.includes('vue') || token.info.includes('astro') || token.info.includes('ts'))
|
||||
if (token && token.tag === 'code' && isAllowedExtension) {
|
||||
// Wrap the code block in CodeWrapper
|
||||
return `<CodeWrapper>${defaultFenceRenderer(tokens, idx, options, env, self)}</CodeWrapper>`
|
||||
}
|
||||
|
||||
// If not a code block, return the default rendering
|
||||
return defaultFenceRenderer(tokens, idx, options, env, self)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
import { dirname, resolve } from 'node:path'
|
||||
import fs from 'node:fs'
|
||||
import type { MarkdownEnv, MarkdownRenderer } from 'vitepress'
|
||||
import { generateDemoComponent, parseProps } from './utils'
|
||||
import type { MarkdownRenderer } from 'vitepress'
|
||||
import { parseProps } from './utils'
|
||||
|
||||
export default function (md: MarkdownRenderer) {
|
||||
function addRenderRule(type: string) {
|
||||
|
|
@ -12,31 +10,9 @@ export default function (md: MarkdownRenderer) {
|
|||
if (!content.match(/^<ComponentPreview\s/) || !content.endsWith('/>'))
|
||||
return defaultRender!(tokens, idx, options, env, self)
|
||||
|
||||
const { path } = env as MarkdownEnv
|
||||
const props = parseProps(content)
|
||||
|
||||
const { name, attrs } = props
|
||||
const pluginPath = dirname(__dirname)
|
||||
const srcPath = resolve(pluginPath, '../../src/lib/registry/default/example/', `${name}.vue`).replace(/\\/g, '/')
|
||||
|
||||
if (!fs.existsSync(srcPath)) {
|
||||
console.error(`rendering ${path}: ${srcPath} does not exist`)
|
||||
return defaultRender!(tokens, idx, options, env, self)
|
||||
}
|
||||
|
||||
let code = fs.readFileSync(srcPath, 'utf-8')
|
||||
code = code.replaceAll(
|
||||
'@/lib/registry/default/',
|
||||
'@/components/',
|
||||
)
|
||||
|
||||
const demoScripts = generateDemoComponent(md, env, {
|
||||
attrs,
|
||||
props,
|
||||
code,
|
||||
path: srcPath,
|
||||
})
|
||||
|
||||
const { attrs } = props
|
||||
const demoScripts = `<ComponentPreview ${attrs ?? ''} v-bind='${JSON.stringify(props)}'></ComponentPreview>`.trim()
|
||||
return demoScripts
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
// Credit to @hairyf https://github.com/hairyf/markdown-it-vitepress-demo
|
||||
|
||||
import type { MarkdownEnv, MarkdownRenderer } from 'vitepress'
|
||||
import { baseParse } from '@vue/compiler-core'
|
||||
import type { AttributeNode, ElementNode } from '@vue/compiler-core'
|
||||
|
||||
|
|
@ -11,36 +10,6 @@ export interface GenerateOptions {
|
|||
code: string
|
||||
}
|
||||
|
||||
export function parse(
|
||||
md: MarkdownRenderer,
|
||||
env: MarkdownEnv,
|
||||
{ code, attrs: _attrs, props }: GenerateOptions,
|
||||
) {
|
||||
const highlightedHtml = md.options.highlight!(code, 'vue', _attrs || '')
|
||||
const sfcTsHtml = highlightedHtml
|
||||
|
||||
const attrs
|
||||
= `sfcTsCode="${encodeURIComponent(code)}"\n`
|
||||
+ `sfcTsHtml="${encodeURIComponent(sfcTsHtml)}"\n`
|
||||
+ `v-bind='${JSON.stringify(props)}'\n`
|
||||
|
||||
return {
|
||||
attrs,
|
||||
highlightedHtml,
|
||||
sfcTsCode: code,
|
||||
sfcTsHtml,
|
||||
}
|
||||
}
|
||||
|
||||
export function generateDemoComponent(
|
||||
md: MarkdownRenderer,
|
||||
env: MarkdownEnv,
|
||||
options: GenerateOptions,
|
||||
) {
|
||||
const { attrs } = parse(md, env, options)
|
||||
return `<ComponentPreview \n${attrs}></ComponentPreview>`.trim()
|
||||
}
|
||||
|
||||
export function isUndefined(v: any): v is undefined {
|
||||
return v === undefined || v === null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export function makeCodeSandboxParams(componentName: string, style: Style, sourc
|
|||
export function makeStackblitzParams(componentName: string, style: Style, sources: Record<string, string>) {
|
||||
const files: Record<string, string> = {}
|
||||
Object.entries(constructFiles(componentName, style, sources)).forEach(([k, v]) => (files[`${k}`] = typeof v.content === 'object' ? JSON.stringify(v.content, null, 2) : v.content))
|
||||
|
||||
return sdk.openProject({
|
||||
title: `${componentName} - Radix Vue`,
|
||||
files,
|
||||
|
|
@ -91,6 +92,7 @@ function constructFiles(componentName: string, style: Style, sources: Record<str
|
|||
'shadcn-vue': 'latest',
|
||||
'typescript': 'latest',
|
||||
'vaul-vue': 'latest',
|
||||
'vue-sonner': 'latest',
|
||||
'@unovis/vue': 'latest',
|
||||
'@unovis/ts': 'latest',
|
||||
}
|
||||
|
|
@ -104,6 +106,7 @@ function constructFiles(componentName: string, style: Style, sources: Record<str
|
|||
'autoprefixer': 'latest',
|
||||
}
|
||||
|
||||
// We have static replace here as this is only showing for code reproduction, doesn't need dynamic codeConfig
|
||||
const transformImportPath = (code: string) => {
|
||||
let parsed = code
|
||||
parsed = parsed.replaceAll(`@/lib/registry/${style}`, '@/components')
|
||||
|
|
|
|||
|
|
@ -80,12 +80,47 @@ export const Index = {
|
|||
component: () => import("../src/lib/registry/default/example/BadgeSecondaryDemo.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/example/BadgeSecondaryDemo.vue"],
|
||||
},
|
||||
"BarChartDemo": {
|
||||
name: "BarChartDemo",
|
||||
"BreadcrumbDemo": {
|
||||
name: "BreadcrumbDemo",
|
||||
type: "components:example",
|
||||
registryDependencies: ["chart-bar"],
|
||||
component: () => import("../src/lib/registry/default/example/BarChartDemo.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/example/BarChartDemo.vue"],
|
||||
registryDependencies: ["breadcrumb","dropdown-menu"],
|
||||
component: () => import("../src/lib/registry/default/example/BreadcrumbDemo.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/example/BreadcrumbDemo.vue"],
|
||||
},
|
||||
"BreadcrumbDropdown": {
|
||||
name: "BreadcrumbDropdown",
|
||||
type: "components:example",
|
||||
registryDependencies: ["breadcrumb","dropdown-menu"],
|
||||
component: () => import("../src/lib/registry/default/example/BreadcrumbDropdown.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/example/BreadcrumbDropdown.vue"],
|
||||
},
|
||||
"BreadcrumbEllipsisDemo": {
|
||||
name: "BreadcrumbEllipsisDemo",
|
||||
type: "components:example",
|
||||
registryDependencies: ["breadcrumb"],
|
||||
component: () => import("../src/lib/registry/default/example/BreadcrumbEllipsisDemo.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/example/BreadcrumbEllipsisDemo.vue"],
|
||||
},
|
||||
"BreadcrumbLinkDemo": {
|
||||
name: "BreadcrumbLinkDemo",
|
||||
type: "components:example",
|
||||
registryDependencies: ["breadcrumb"],
|
||||
component: () => import("../src/lib/registry/default/example/BreadcrumbLinkDemo.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/example/BreadcrumbLinkDemo.vue"],
|
||||
},
|
||||
"BreadcrumbResponsive": {
|
||||
name: "BreadcrumbResponsive",
|
||||
type: "components:example",
|
||||
registryDependencies: ["breadcrumb","button","drawer","dropdown-menu"],
|
||||
component: () => import("../src/lib/registry/default/example/BreadcrumbResponsive.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/example/BreadcrumbResponsive.vue"],
|
||||
},
|
||||
"BreadcrumbSeparatorDemo": {
|
||||
name: "BreadcrumbSeparatorDemo",
|
||||
type: "components:example",
|
||||
registryDependencies: ["breadcrumb"],
|
||||
component: () => import("../src/lib/registry/default/example/BreadcrumbSeparatorDemo.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/example/BreadcrumbSeparatorDemo.vue"],
|
||||
},
|
||||
"ButtonAsChildDemo": {
|
||||
name: "ButtonAsChildDemo",
|
||||
|
|
@ -1159,12 +1194,47 @@ export const Index = {
|
|||
component: () => import("../src/lib/registry/new-york/example/BadgeSecondaryDemo.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/example/BadgeSecondaryDemo.vue"],
|
||||
},
|
||||
"BarChartDemo": {
|
||||
name: "BarChartDemo",
|
||||
"BreadcrumbDemo": {
|
||||
name: "BreadcrumbDemo",
|
||||
type: "components:example",
|
||||
registryDependencies: ["chart-bar"],
|
||||
component: () => import("../src/lib/registry/new-york/example/BarChartDemo.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/example/BarChartDemo.vue"],
|
||||
registryDependencies: ["breadcrumb","dropdown-menu"],
|
||||
component: () => import("../src/lib/registry/new-york/example/BreadcrumbDemo.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/example/BreadcrumbDemo.vue"],
|
||||
},
|
||||
"BreadcrumbDropdown": {
|
||||
name: "BreadcrumbDropdown",
|
||||
type: "components:example",
|
||||
registryDependencies: ["breadcrumb","dropdown-menu"],
|
||||
component: () => import("../src/lib/registry/new-york/example/BreadcrumbDropdown.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/example/BreadcrumbDropdown.vue"],
|
||||
},
|
||||
"BreadcrumbEllipsisDemo": {
|
||||
name: "BreadcrumbEllipsisDemo",
|
||||
type: "components:example",
|
||||
registryDependencies: ["breadcrumb"],
|
||||
component: () => import("../src/lib/registry/new-york/example/BreadcrumbEllipsisDemo.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/example/BreadcrumbEllipsisDemo.vue"],
|
||||
},
|
||||
"BreadcrumbLinkDemo": {
|
||||
name: "BreadcrumbLinkDemo",
|
||||
type: "components:example",
|
||||
registryDependencies: ["breadcrumb"],
|
||||
component: () => import("../src/lib/registry/new-york/example/BreadcrumbLinkDemo.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/example/BreadcrumbLinkDemo.vue"],
|
||||
},
|
||||
"BreadcrumbResponsive": {
|
||||
name: "BreadcrumbResponsive",
|
||||
type: "components:example",
|
||||
registryDependencies: ["breadcrumb","button","drawer","dropdown-menu"],
|
||||
component: () => import("../src/lib/registry/new-york/example/BreadcrumbResponsive.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/example/BreadcrumbResponsive.vue"],
|
||||
},
|
||||
"BreadcrumbSeparatorDemo": {
|
||||
name: "BreadcrumbSeparatorDemo",
|
||||
type: "components:example",
|
||||
registryDependencies: ["breadcrumb"],
|
||||
component: () => import("../src/lib/registry/new-york/example/BreadcrumbSeparatorDemo.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/example/BreadcrumbSeparatorDemo.vue"],
|
||||
},
|
||||
"ButtonAsChildDemo": {
|
||||
name: "ButtonAsChildDemo",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "www",
|
||||
"type": "module",
|
||||
"version": "0.10.1",
|
||||
"version": "0.10.2",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
|
|
@ -18,20 +18,21 @@
|
|||
"@formkit/auto-animate": "^0.8.1",
|
||||
"@radix-icons/vue": "^1.0.0",
|
||||
"@stackblitz/sdk": "^1.9.0",
|
||||
"@tanstack/vue-table": "^8.13.2",
|
||||
"@tanstack/vue-table": "^8.14.0",
|
||||
"@unovis/ts": "^1.3.5",
|
||||
"@unovis/vue": "^1.3.5",
|
||||
"@vee-validate/zod": "^4.12.5",
|
||||
"@vee-validate/zod": "^4.12.6",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.0",
|
||||
"codesandbox": "^2.2.3",
|
||||
"date-fns": "^3.3.1",
|
||||
"date-fns": "^3.6.0",
|
||||
"embla-carousel": "^8.0.0",
|
||||
"embla-carousel-autoplay": "^8.0.0",
|
||||
"embla-carousel-vue": "^8.0.0",
|
||||
"lucide-vue-next": "^0.350.0",
|
||||
"radix-vue": "^1.5.0",
|
||||
"lucide-vue-next": "^0.359.0",
|
||||
"magic-string": "^0.30.8",
|
||||
"radix-vue": "^1.5.3",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"v-calendar": "^3.1.2",
|
||||
"vaul-vue": "^0.1.0",
|
||||
|
|
@ -47,9 +48,9 @@
|
|||
"@iconify-json/tabler": "^1.1.106",
|
||||
"@iconify/json": "^2.2.189",
|
||||
"@iconify/vue": "^4.1.1",
|
||||
"@shikijs/transformers": "^1.1.7",
|
||||
"@shikijs/transformers": "^1.2.0",
|
||||
"@types/lodash.template": "^4.5.3",
|
||||
"@types/node": "^20.11.25",
|
||||
"@types/node": "^20.11.30",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"@vue/compiler-core": "^3.4.21",
|
||||
|
|
@ -60,14 +61,14 @@
|
|||
"oxc-parser": "^0.8.0",
|
||||
"pathe": "^1.1.2",
|
||||
"rimraf": "^5.0.5",
|
||||
"shiki": "^1.1.7",
|
||||
"tailwind-merge": "^2.2.1",
|
||||
"shiki": "^1.2.0",
|
||||
"tailwind-merge": "^2.2.2",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"tsx": "^4.7.1",
|
||||
"typescript": "^5.4.2",
|
||||
"unplugin-icons": "^0.18.5",
|
||||
"vite": "^5.1.5",
|
||||
"vite": "^5.2.2",
|
||||
"vitepress": "^1.0.0-rc.45",
|
||||
"vue-tsc": "^2.0.6"
|
||||
"vue-tsc": "^2.0.7"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
176
apps/www/src/assets/diagrams.drawio
Normal file
176
apps/www/src/assets/diagrams.drawio
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
<mxfile host="app.diagrams.net" modified="2024-03-15T08:14:00.888Z" agent="Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0" etag="eUNOuIh_rCPXdI6LG0BE" version="24.0.6" type="device">
|
||||
<diagram name="Page-1" id="10a91c8b-09ff-31b1-d368-03940ed4cc9e">
|
||||
<mxGraphModel dx="1636" dy="971" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="850" background="none" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-41" value="" style="rounded=0;whiteSpace=wrap;html=1;fontColor=none;noLabel=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
|
||||
<mxGeometry x="30" y="70" width="1010" height="680" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="62893188c0fa7362-1" value="Shadcn/Vue" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" parent="1" vertex="1">
|
||||
<mxGeometry x="380" y="130" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="62893188c0fa7362-2" value="Packages" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" parent="1" vertex="1">
|
||||
<mxGeometry x="160" y="250" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="62893188c0fa7362-3" value="Apps/www" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" parent="1" vertex="1">
|
||||
<mxGeometry x="630" y="250" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="62893188c0fa7362-4" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" parent="1" source="PaMXV6_IjdSjTMUUNi7L-27" target="62893188c0fa7362-3" edge="1">
|
||||
<mxGeometry x="-0.3002" y="13" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="62893188c0fa7362-5" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" parent="1" source="62893188c0fa7362-1" target="62893188c0fa7362-2" edge="1">
|
||||
<mxGeometry x="-0.359" y="-11" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="62893188c0fa7362-8" value="Module" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" parent="1" vertex="1">
|
||||
<mxGeometry x="80" y="360" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="62893188c0fa7362-9" value="CLI" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" parent="1" vertex="1">
|
||||
<mxGeometry x="220" y="360" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="62893188c0fa7362-14" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" parent="1" source="62893188c0fa7362-2" target="62893188c0fa7362-8" edge="1">
|
||||
<mxGeometry x="-0.2" y="-14" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="62893188c0fa7362-15" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" parent="1" source="62893188c0fa7362-2" target="62893188c0fa7362-9" edge="1">
|
||||
<mxGeometry x="-0.2" y="14" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="62893188c0fa7362-16" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.75;entryY=0;entryDx=0;entryDy=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" parent="1" source="62893188c0fa7362-3" target="PaMXV6_IjdSjTMUUNi7L-2" edge="1">
|
||||
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
<mxPoint x="644.5454545454545" y="360" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="62893188c0fa7362-17" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.25;entryY=0;entryDx=0;entryDy=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" parent="1" source="62893188c0fa7362-3" target="PaMXV6_IjdSjTMUUNi7L-1" edge="1">
|
||||
<mxGeometry x="-0.1294" y="17" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
<mxPoint x="782.7272727272725" y="360" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-1" value="Registry" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="720" y="370" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-2" value=".vitepress" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="420" y="370" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-3" value="Scripts" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="870" y="370" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-4" value="Src" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="570" y="370" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-7" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.333;entryY=0.017;entryDx=0;entryDy=0;exitX=1;exitY=1;exitDx=0;exitDy=0;entryPerimeter=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="62893188c0fa7362-3" target="PaMXV6_IjdSjTMUUNi7L-3">
|
||||
<mxGeometry x="-0.1294" y="17" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
<mxPoint x="841" y="270" as="sourcePoint" />
|
||||
<mxPoint x="910" y="320" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-9" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.358;exitY=1.017;exitDx=0;exitDy=0;exitPerimeter=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="62893188c0fa7362-3" target="PaMXV6_IjdSjTMUUNi7L-4">
|
||||
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
<mxPoint x="720" y="540" as="sourcePoint" />
|
||||
<mxPoint x="613" y="600" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-11" value="Content" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="420" y="500" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-12" value="Examples" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="570" y="500" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-13" value="Lib/Registry" style="whiteSpace=wrap;html=1;rounded=1;shadow=0;labelBackgroundColor=none;strokeWidth=1;fontFamily=Garamond;fontSize=17;align=center;sketch=1;curveFitting=1;jiggle=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="720" y="500" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-14" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.308;exitY=1.033;exitDx=0;exitDy=0;exitPerimeter=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="PaMXV6_IjdSjTMUUNi7L-4" target="PaMXV6_IjdSjTMUUNi7L-11">
|
||||
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
<mxPoint x="560" y="470" as="sourcePoint" />
|
||||
<mxPoint x="507" y="529" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-15" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="PaMXV6_IjdSjTMUUNi7L-4" target="PaMXV6_IjdSjTMUUNi7L-12">
|
||||
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
<mxPoint x="657" y="442" as="sourcePoint" />
|
||||
<mxPoint x="540" y="560" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-16" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.75;exitY=1;exitDx=0;exitDy=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="PaMXV6_IjdSjTMUUNi7L-4" target="PaMXV6_IjdSjTMUUNi7L-13">
|
||||
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
<mxPoint x="660" y="435" as="sourcePoint" />
|
||||
<mxPoint x="660" y="555" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-20" value="Default" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="650" y="630" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-21" value="New York" style="rounded=1;whiteSpace=wrap;html=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="800" y="630" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-22" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="PaMXV6_IjdSjTMUUNi7L-13" target="PaMXV6_IjdSjTMUUNi7L-20">
|
||||
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
<mxPoint x="730" y="670" as="sourcePoint" />
|
||||
<mxPoint x="530" y="818" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-23" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="PaMXV6_IjdSjTMUUNi7L-13" target="PaMXV6_IjdSjTMUUNi7L-21">
|
||||
<mxGeometry x="-0.2614" y="-13" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
<mxPoint x="790" y="670" as="sourcePoint" />
|
||||
<mxPoint x="750" y="820" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-26" value="1" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||
<mxGeometry x="140" y="230" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-28" value="3" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||
<mxGeometry x="400" y="350" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-29" value="4" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||
<mxGeometry x="550" y="350" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-30" value="5" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||
<mxGeometry x="700" y="350" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-31" value="6" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||
<mxGeometry x="850" y="350" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-32" value="7" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||
<mxGeometry x="400" y="480" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-33" value="8" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||
<mxGeometry x="550" y="480" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-34" value="9" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||
<mxGeometry x="700" y="480" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-36" value="10" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||
<mxGeometry x="630" y="610" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-38" value="11" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||
<mxGeometry x="780" y="610" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-39" value="" style="rounded=0;html=1;labelBackgroundColor=none;startArrow=none;startFill=0;startSize=5;endArrow=none;endFill=0;endSize=5;jettySize=auto;orthogonalLoop=1;strokeWidth=1;fontFamily=Garamond;fontSize=17;sketch=1;curveFitting=1;jiggle=2;shadow=0;" edge="1" parent="1" source="62893188c0fa7362-1" target="PaMXV6_IjdSjTMUUNi7L-27">
|
||||
<mxGeometry x="-0.3002" y="13" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
<mxPoint x="500" y="189" as="sourcePoint" />
|
||||
<mxPoint x="630" y="251" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="PaMXV6_IjdSjTMUUNi7L-27" value="2" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;sketch=1;curveFitting=1;jiggle=2;fontFamily=Garamond;fontSize=21;" vertex="1" parent="1">
|
||||
<mxGeometry x="610" y="230" width="40" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
|
@ -89,7 +89,6 @@ This is used to generate the default color palette for your components. **This c
|
|||
}
|
||||
```
|
||||
|
||||
|
||||
### tailwind.cssVariables
|
||||
|
||||
You can choose between using CSS variables or Tailwind CSS utility classes for theming.
|
||||
|
|
@ -109,7 +108,6 @@ For more information, see the [theming docs](/docs/theming).
|
|||
|
||||
**This cannot be changed after initialization.** To switch between CSS variables and utility classes, you'll have to delete and re-install your components.
|
||||
|
||||
|
||||
## aliases
|
||||
|
||||
The CLI uses these values and the `paths` config from your `tsconfig.json` or `jsconfig.json` file to place generated components in the correct location.
|
||||
|
|
@ -118,7 +116,6 @@ Path aliases have to be set up in your `tsconfig.json` or `jsconfig.json` file.
|
|||
|
||||
> A fallback to `tsconfig.app.json` if no `paths` were found in `tsconfig.json`
|
||||
|
||||
|
||||
<Callout class="mt-6">
|
||||
|
||||
**Important:** If you're using the `src` directory, make sure it is included
|
||||
|
|
@ -126,7 +123,6 @@ Path aliases have to be set up in your `tsconfig.json` or `jsconfig.json` file.
|
|||
|
||||
</Callout>
|
||||
|
||||
|
||||
### aliases.utils
|
||||
|
||||
Import alias for your utility functions.
|
||||
|
|
|
|||
|
|
@ -5,12 +5,10 @@ source: apps/www/src/lib/registry/default/ui/accordion
|
|||
primitive: https://www.radix-vue.com/components/accordion.html
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="AccordionDemo" class="sm:max-w-[70%]" />
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
<Steps>
|
||||
|
||||
### Run the following command
|
||||
|
|
@ -49,7 +47,6 @@ module.exports = {
|
|||
|
||||
</Steps>
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```vue
|
||||
|
|
@ -68,4 +65,3 @@ import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/
|
|||
</Accordion>
|
||||
</template>
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,10 @@ source: apps/www/src/lib/registry/default/ui/alert-dialog
|
|||
primitive: https://www.radix-vue.com/components/alert-dialog.html
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="AlertDialogDemo" />
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add alert-dialog
|
||||
```
|
||||
|
|
|
|||
|
|
@ -3,12 +3,10 @@ title: Alert
|
|||
description: Displays a callout for user attention.
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="AlertDemo" />
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add alert
|
||||
```
|
||||
|
|
@ -36,9 +34,6 @@ import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
|
|||
|
||||
<ComponentPreview name="AlertDemo" />
|
||||
|
||||
|
||||
### Destructive
|
||||
|
||||
<ComponentPreview name="AlertDestructiveDemo" />
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ source: apps/www/src/lib/registry/default/ui/aspect-ratio
|
|||
primitive: https://www.radix-vue.com/components/aspect-ratio.html
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="AspectRatioDemo" />
|
||||
|
||||
## Installation
|
||||
|
|
|
|||
|
|
@ -5,13 +5,10 @@ source: apps/www/src/lib/registry/default/ui/avatar
|
|||
primitive: https://www.radix-vue.com/components/avatar.html
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="AvatarDemo" />
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add avatar
|
||||
```
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ title: Badge
|
|||
description: Displays a badge or a component that looks like a badge.
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="BadgeDemo" />
|
||||
|
||||
## Installation
|
||||
|
|
@ -80,14 +79,12 @@ import { Badge } from '@/components/ui/badge'
|
|||
</template>
|
||||
```
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
### Default
|
||||
|
||||
<ComponentPreview name="BadgeDemo" />
|
||||
|
||||
|
||||
### Secondary
|
||||
|
||||
<ComponentPreview name="BadgeSecondaryDemo" />
|
||||
|
|
|
|||
205
apps/www/src/content/docs/components/breadcrumb.md
Normal file
205
apps/www/src/content/docs/components/breadcrumb.md
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
---
|
||||
title: Breadcrumb
|
||||
description: Displays the path to the current resource using a hierarchy of links.
|
||||
---
|
||||
|
||||
<ComponentPreview name="BreadcrumbDemo" class="[&_.preview]:p-2" />
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add breadcrumb
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from '@/lib/components/ui/breadcrumb'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/">
|
||||
Home
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/components">
|
||||
Components
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</template>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Custom separator
|
||||
|
||||
Use a custom component as `slot` for `<BreadcrumbSeparator />` to create a custom separator.
|
||||
|
||||
<ComponentPreview name="BreadcrumbSeparatorDemo" />
|
||||
|
||||
```vue showLineNumbers {2,20-22}
|
||||
<script setup lang="ts">
|
||||
import { Slash } from 'lucide-react'
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbSeparator,
|
||||
} from '@/lib/components/ui/breadcrumb'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/">
|
||||
Home
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator>
|
||||
<Slash />
|
||||
</BreadcrumbSeparator>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/components">
|
||||
Components
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Dropdown
|
||||
|
||||
You can compose `<BreadcrumbItem />` with a `<DropdownMenu />` to create a dropdown in the breadcrumb.
|
||||
|
||||
<ComponentPreview name="BreadcrumbDropdown" class="[&_.preview]:p-2" />
|
||||
|
||||
```vue showLineNumbers {2-7,16-26}
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/lib/components/ui/dropdown-menu'
|
||||
|
||||
import { BreadcrumbItem } from '@/lib/components/ui/breadcrumb'
|
||||
|
||||
import ChevronDownIcon from '~icons/radix-icons/chevron-down'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BreadcrumbItem>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger class="flex items-center gap-1">
|
||||
Components
|
||||
<ChevronDownIcon />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start">
|
||||
<DropdownMenuItem>Documentation</DropdownMenuItem>
|
||||
<DropdownMenuItem>Themes</DropdownMenuItem>
|
||||
<DropdownMenuItem>GitHub</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</BreadcrumbItem>
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Collapsed
|
||||
|
||||
We provide a `<BreadcrumbEllipsis />` component to show a collapsed state when the breadcrumb is too long.
|
||||
|
||||
<ComponentPreview name="BreadcrumbEllipsisDemo" class="[&_.preview]:p-2" />
|
||||
|
||||
```vue showLineNumbers {3,15}
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbEllipsis,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbList,
|
||||
} from '@/lib/components/ui/breadcrumb'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<!-- ... -->
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbEllipsis />
|
||||
</BreadcrumbItem>
|
||||
<!-- ... -->
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Link component
|
||||
|
||||
To use a custom link component from your routing library, you can use the `asChild` prop on `<BreadcrumbLink />`.
|
||||
|
||||
<ComponentPreview name="BreadcrumbLinkDemo" />
|
||||
|
||||
```vue showLineNumbers {15-19}
|
||||
<script setup lang="ts">
|
||||
import { RouterLink } from 'vue-router'
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
} from '@/lib/components/ui/breadcrumb'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink as-child>
|
||||
<RouterLink to="/">
|
||||
Home
|
||||
</RouterLink>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<!-- -->
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</template>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Responsive
|
||||
|
||||
Here's an example of a responsive breadcrumb that composes `<BreadcrumbItem />` with `<BreadcrumbEllipsis />`, `<DropdownMenu />`, and `<Drawer />`.
|
||||
|
||||
It displays a dropdown on desktop and a drawer on mobile.
|
||||
|
||||
<ComponentPreview name="BreadcrumbResponsive" class="[&_.preview]:p-2" />
|
||||
|
|
@ -3,7 +3,6 @@ title: Button
|
|||
description: Displays a button or a component that looks like a button.
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="ButtonDemo" />
|
||||
|
||||
## Installation
|
||||
|
|
@ -94,24 +93,20 @@ import { Button } from '@/components/ui/button'
|
|||
</template>
|
||||
```
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
### Primary
|
||||
|
||||
<ComponentPreview name="ButtonDemo" />
|
||||
|
||||
|
||||
### Secondary
|
||||
|
||||
<ComponentPreview name="ButtonSecondaryDemo" />
|
||||
|
||||
|
||||
### Destructive
|
||||
|
||||
<ComponentPreview name="ButtonDestructiveDemo" />
|
||||
|
||||
|
||||
### Outline
|
||||
|
||||
<ComponentPreview name="ButtonOutlineDemo" />
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ source: apps/www/src/lib/registry/default/ui/calendar
|
|||
primitive: https://vcalendar.io/
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="CalendarDemo" />
|
||||
|
||||
## About
|
||||
|
|
@ -34,13 +33,10 @@ npm install v-calendar
|
|||
|
||||
### Copy and paste the following code into your project
|
||||
|
||||
|
||||
<<< @/lib/registry/default/ui/calendar/Calendar.vue
|
||||
|
||||
|
||||
</Steps>
|
||||
|
||||
|
||||
</template>
|
||||
</TabPreview>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,13 +3,10 @@ title: Card
|
|||
description: Displays a card with header, content, and footer.
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="CardFormDemo" />
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add card
|
||||
```
|
||||
|
|
|
|||
|
|
@ -5,13 +5,10 @@ source: apps/www/src/lib/registry/default/ui/checkbox
|
|||
primitive: https://www.radix-vue.com/components/checkbox.html
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="CheckboxDemo" />
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add checkbox
|
||||
```
|
||||
|
|
|
|||
|
|
@ -5,12 +5,10 @@ source: apps/www/src/lib/registry/default/ui/collapsible
|
|||
primitive: https://www.radix-vue.com/components/collapsible.html
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="CollapsibleDemo" />
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
<Steps>
|
||||
|
||||
### Run the following command
|
||||
|
|
@ -49,7 +47,6 @@ module.exports = {
|
|||
|
||||
</Steps>
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```vue
|
||||
|
|
|
|||
|
|
@ -5,14 +5,10 @@ source: apps/www/src/lib/registry/default/ui/command
|
|||
primitive: https://www.radix-vue.com/components/combobox.html
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="CommandDemo" />
|
||||
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add command
|
||||
```
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ source: apps/www/src/lib/registry/default/ui/context-menu
|
|||
primitive: https://www.radix-vue.com/components/context-menu.html
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="ContextMenuDemo" />
|
||||
|
||||
## Installation
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ title: Date Picker
|
|||
description: A date picker component with range and presets.
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="DatePickerDemo" />
|
||||
|
||||
## Installation
|
||||
|
|
@ -53,7 +52,6 @@ const date = ref<Date>()
|
|||
</template>
|
||||
```
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
### Date Picker
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ source: apps/www/src/lib/registry/default/ui/dialog
|
|||
primitive: https://www.radix-vue.com/components/dialog.html
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="DialogDemo" />
|
||||
|
||||
## Installation
|
||||
|
|
@ -67,7 +66,6 @@ import {
|
|||
|
||||
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).
|
||||
|
||||
|
||||
```js:line-numbers showLineNumber{14-25}
|
||||
<Dialog>
|
||||
<ContextMenu>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ source: apps/www/src/lib/registry/default/ui/hover-card
|
|||
primitive: https://www.radix-vue.com/components/hover-card.html
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="HoverCardDemo" />
|
||||
|
||||
## Installation
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ primitive: https://www.radix-vue.com/components/label.html
|
|||
|
||||
<ComponentPreview name="LabelDemo" />
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
<TabPreview name="CLI">
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ primitive: https://www.radix-vue.com/components/menubar.html
|
|||
|
||||
## Installation
|
||||
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add menubar
|
||||
```
|
||||
|
|
|
|||
|
|
@ -64,4 +64,3 @@ import { navigationMenuTriggerStyle } from '@/components/ui/navigation-menu'
|
|||
</NavigationMenuItem>
|
||||
</template>
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ primitive: https://www.radix-vue.com/components/pagination.html
|
|||
|
||||
## Installation
|
||||
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add pagination
|
||||
```
|
||||
|
|
|
|||
|
|
@ -5,12 +5,10 @@ source: apps/www/src/lib/registry/default/ui/popover
|
|||
primitive: https://www.radix-vue.com/components/popover.html
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="PopoverDemo" />
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add popover
|
||||
```
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ primitive: https://www.radix-vue.com/components/progress.html
|
|||
|
||||
<ComponentPreview name="ProgressDemo" />
|
||||
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
<TabPreview name="CLI">
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ primitive: https://www.radix-vue.com/components/radio-group.html
|
|||
|
||||
## Installation
|
||||
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add radio-group
|
||||
```
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ import {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<ResizablePanelGroup direction="horizontal">
|
||||
<ResizablePanelGroup direction="vertical">
|
||||
<ResizablePanel>One</ResizablePanel>
|
||||
<ResizableHandle />
|
||||
<ResizablePanel>Two</ResizablePanel>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ primitive: https://www.radix-vue.com/components/scroll-area.html
|
|||
|
||||
## Installation
|
||||
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add scroll-area
|
||||
```
|
||||
|
|
@ -37,4 +36,3 @@ import { ScrollArea } from '@/components/ui/scroll-area'
|
|||
### Horizontal Scrolling
|
||||
|
||||
<ComponentPreview name="ScrollAreaHorizontalDemo" />
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ primitive: https://www.radix-vue.com/components/separator.html
|
|||
|
||||
<ComponentPreview name="SeparatorDemo" />
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
<TabPreview name="CLI">
|
||||
|
|
@ -32,7 +31,6 @@ npm install radix-vue
|
|||
|
||||
<<< @/lib/registry/default/ui/separator/Separator.vue
|
||||
|
||||
|
||||
</Steps>
|
||||
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ primitive: https://www.radix-vue.com/components/dialog.html
|
|||
|
||||
<ComponentPreview name="SheetDemo" />
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
|
|
@ -52,7 +51,6 @@ Use the `side` property to `<SheetContent />` to indicate the edge of the screen
|
|||
|
||||
<ComponentPreview name="SheetSideDemo" />
|
||||
|
||||
|
||||
### Size
|
||||
|
||||
You can adjust the size of the sheet using CSS classes:
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ primitive: https://www.radix-vue.com/components/switch.html
|
|||
|
||||
<ComponentPreview name="SwitchDemo" />
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
<TabPreview name="CLI">
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ description: A responsive table component.
|
|||
|
||||
<ComponentPreview name="TableDemo" />
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -7,11 +7,8 @@ primitive: https://www.radix-vue.com/components/tabs.html
|
|||
|
||||
<ComponentPreview name="TabsDemo" />
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add tabs
|
||||
```
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ primitive: https://www.radix-vue.com/components/tags-input.html
|
|||
npx shadcn-vue@latest add tags-input
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
### Tags with Combobox
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ description: Displays a form textarea or a component that looks like a textarea.
|
|||
|
||||
<ComponentPreview name="TextareaDemo" />
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
<TabPreview name="CLI">
|
||||
|
|
|
|||
|
|
@ -5,12 +5,10 @@ source: apps/www/src/lib/registry/default/ui/toast
|
|||
primitive: https://www.radix-vue.com/components/toast.html
|
||||
---
|
||||
|
||||
|
||||
<ComponentPreview name="ToastDemo" />
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
<Steps>
|
||||
|
||||
### Run the following command
|
||||
|
|
@ -35,7 +33,6 @@ import Toaster from '@/components/ui/toast/Toaster.vue'
|
|||
|
||||
</Steps>
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
The `useToast` hook returns a `toast` function that you can use to display a toast.
|
||||
|
|
|
|||
|
|
@ -64,30 +64,22 @@ import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
|
|||
|
||||
<ComponentPreview name="ToggleGroupDemo" />
|
||||
|
||||
|
||||
### Outline
|
||||
|
||||
<ComponentPreview name="ToggleGroupOutlineDemo" />
|
||||
|
||||
|
||||
### Single
|
||||
|
||||
<ComponentPreview name="ToggleGroupSingleDemo" />
|
||||
|
||||
|
||||
### Small
|
||||
|
||||
<ComponentPreview name="ToggleGroupSmallDemo" />
|
||||
|
||||
|
||||
### Large
|
||||
|
||||
<ComponentPreview name="ToggleGroupLargeDemo" />
|
||||
|
||||
|
||||
### Disabled
|
||||
|
||||
<ComponentPreview name="ToggleGroupDisabledDemo" />
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ primitive: https://www.radix-vue.com/components/toggle.html
|
|||
|
||||
<ComponentPreview name="ToggleDemo" />
|
||||
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
<TabPreview name="CLI">
|
||||
|
|
@ -56,30 +54,22 @@ import { Toggle } from '@/components/ui/toggle'
|
|||
|
||||
<ComponentPreview name="ToggleDemo" />
|
||||
|
||||
|
||||
### Outline
|
||||
|
||||
<ComponentPreview name="ToggleItalicDemo" />
|
||||
|
||||
|
||||
### With Text
|
||||
|
||||
<ComponentPreview name="ToggleItalicWithTextDemo" />
|
||||
|
||||
|
||||
### Small
|
||||
|
||||
<ComponentPreview name="ToggleSmallDemo" />
|
||||
|
||||
|
||||
### Large
|
||||
|
||||
<ComponentPreview name="ToggleLargeDemo" />
|
||||
|
||||
|
||||
### Disabled
|
||||
|
||||
<ComponentPreview name="ToggleDisabledDemo" />
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ primitive: https://www.radix-vue.com/components/tooltip.html
|
|||
|
||||
<ComponentPreview name="TooltipDemo" />
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
|
|
|
|||
341
apps/www/src/content/docs/contribution.md
Normal file
341
apps/www/src/content/docs/contribution.md
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
---
|
||||
title: Contribution
|
||||
description: Learn on how to contribute to shadcn/vue.
|
||||
---
|
||||
## Introduction
|
||||
|
||||
Thanks for your interest in contributing to shadcn-vue.com. We're happy to have you here.
|
||||
|
||||
Please take a moment to review this document before submitting your first pull request. We also strongly recommend that you check for open issues and pull requests to see if someone else is working on something similar.
|
||||
|
||||
If you need any help, feel free to reach out to the core team on [Discord](https://chat.radix-vue.com/).
|
||||
|
||||
This guide provides detailed information to help new contributors.
|
||||
|
||||
## About this repository
|
||||
|
||||
This repository is a monorepo.
|
||||
|
||||
- We use [pnpm](https://pnpm.io) and [`workspaces`](https://pnpm.io/workspaces) for development.
|
||||
|
||||
## Project Structure
|
||||
|
||||
The GitHub repository consists of the several folders. here's a quick view.
|
||||
|
||||
<VPImage
|
||||
alt="folder-structure"
|
||||
class="block" :image="{
|
||||
dark: '/diagrams/structure-dark.svg',
|
||||
light: '/diagrams/structure-light.svg',
|
||||
}"
|
||||
/>
|
||||
|
||||
1. **packages** -
|
||||
Contains source code for supporting `nuxt` as a module and the `cli` to add new components.
|
||||
|
||||
2. **apps/www** -
|
||||
The main folder that holds the source code for the website and every `shadcn/vue` component. This folder contains important sub-folders and is a subproject with its own `package.json`.
|
||||
|
||||
3. **.vitepress** -
|
||||
Contains the configuration and source code for `vitepress` and the `shadcn/vue` website.
|
||||
|
||||
4. **src** -
|
||||
Hosts the main source code for every `shadcn/vue` component or demo and their documentation on the website.
|
||||
|
||||
5. **\_\_registry\_\_** -
|
||||
Holds the registry file generated by `scripts/build-registry.ts` to serve components for the `cli`. This folder's content is auto-generated and should not be edited manually.
|
||||
|
||||
6. **scripts** -
|
||||
Contains various helper scripts, such as `build-registry.ts`, which automatically generates the `__registry__` folder.
|
||||
|
||||
7. **content** -
|
||||
This folder holds all the documentation for the `/docs` route. Each component has one `.md` file documenting the installation and usage of the component.
|
||||
|
||||
8. **examples** -
|
||||
Holds all examples not part of `/docs`, like the [main page](/).
|
||||
|
||||
9. **lib/registry** -
|
||||
The main folder hosts the source code for different styles of every component. This is likely the main folder you'll be changing.
|
||||
|
||||
We support two different styles for every component in `shadcn/vue`:
|
||||
|
||||
1. Default
|
||||
2. New York
|
||||
|
||||
Every component added to the repository must support both versions, including the main source code and associated demos.
|
||||
|
||||
When adding or modifying components, please ensure that:
|
||||
|
||||
1. You make the changes for every style.
|
||||
2. You update the documentation.
|
||||
3. You run `pnpm build:registry` to update the registry.
|
||||
|
||||
## Development
|
||||
|
||||
Start by cloning the repository:
|
||||
|
||||
```bash
|
||||
git clone git@github.com:radix-vue/shadcn-vue.git
|
||||
```
|
||||
|
||||
### Install dependencies
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
### Run a workspace
|
||||
|
||||
You can use the `pnpm --filter=[WORKSPACE]` command to start the development process for a workspace or some of the shortcut command that we have setup.
|
||||
|
||||
#### Examples
|
||||
|
||||
1. To run the `shadcn-vue.com` website:
|
||||
|
||||
```
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
2. To run the `shadcn-vue` cli package:
|
||||
|
||||
```
|
||||
pnpm dev:cli
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
The documentation for this project is located in the `www` workspace. You can run the documentation locally by running the following command:
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
Documentation is written using [md](https://vitepress.dev/guide/markdown). You can find the documentation files in the `apps/www/src/content` directory.
|
||||
|
||||
## CLI
|
||||
|
||||
The `shadcn-vue` package is a CLI for adding components to your project. You can find the documentation for the CLI [here](https://shadcn-vue.com/docs/cli).
|
||||
|
||||
Any changes to the CLI should be made in the `packages/cli` directory. If you can, it would be great if you could add tests for your changes.
|
||||
|
||||
## Testing
|
||||
|
||||
Tests are written using [Vitest](https://vitest.dev). You can run all the tests from the root of the repository.
|
||||
|
||||
```bash
|
||||
pnpm test
|
||||
```
|
||||
|
||||
Please ensure that the tests are passing when submitting a pull request. If you're adding new features, please include tests.
|
||||
|
||||
## Commit Convention
|
||||
|
||||
Before you create a Pull Request, please check whether your commits comply with
|
||||
the commit conventions used in this repository.
|
||||
|
||||
When you create a commit we kindly ask you to follow the convention
|
||||
`category(scope or module): message` in your commit message while using one of
|
||||
the following categories:
|
||||
|
||||
- `feat / feature`: all changes that introduce completely new code or new
|
||||
features
|
||||
- `fix`: changes that fix a bug (ideally you will additionally reference an
|
||||
issue if present)
|
||||
- `refactor`: any code related change that is not a fix nor a feature
|
||||
- `docs`: changing existing or creating new documentation (i.e. README, docs for
|
||||
usage of a lib or cli usage)
|
||||
- `build`: all changes regarding the build of the software, changes to
|
||||
dependencies or the addition of new dependencies
|
||||
- `test`: all changes regarding tests (adding new tests or changing existing
|
||||
ones)
|
||||
- `ci`: all changes regarding the configuration of continuous integration (i.e.
|
||||
github actions, ci system)
|
||||
- `chore`: all changes to the repository that do not fit into any of the above
|
||||
categories
|
||||
|
||||
e.g. `feat(components): add new prop to the avatar component`
|
||||
|
||||
If you are interested in the detailed specification you can visit [Conventional Commits](https://www.conventionalcommits.org/).
|
||||
|
||||
## SFC - Single File Components
|
||||
|
||||
Multiple components are integrated into one file in `shadcn/ui` - the React version of `shadcn` - while Vue only supports one component per file, hence the name Single File Component (SFC). In such cases, you need to create separate files for each component part and then export them all in an `index.ts` file.
|
||||
|
||||
See the [`Accordion`](https://github.com/radix-vue/shadcn-vue/tree/v0.10.2/apps/www/src/lib/registry/default/ui/accordion) source code as an example.
|
||||
|
||||
## Wrapping Radix-Vue Components
|
||||
|
||||
[Radix-Vue](https://www.radix-vue.com) hosts many low-level UI components that are used to build reusable components.
|
||||
There are many cases that you need to wrap `Radix-Vue` components.
|
||||
|
||||
### Props & Events
|
||||
All of the `Radix-Vue` compoennts expose their prop and emit types. We need to forward any props/events that are coming from outside to the `Radix-Vue` component.
|
||||
|
||||
To do so, we have a helper function named [`useForwardPropsEmits`](https://www.radix-vue.com/utilities/use-forward-props-emits.html) that combines props and events that must be binded to the child radix component.
|
||||
|
||||
To be more clear, the function `useForwardPropsEmits` takes in props and an optional emit function, and returns a
|
||||
computed object that combines the parsed props and emits as props.
|
||||
|
||||
Here's an example from `Accordian` root component.
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
AccordionRoot,
|
||||
type AccordionRootEmits,
|
||||
type AccordionRootProps,
|
||||
useForwardPropsEmits,
|
||||
} from 'radix-vue'
|
||||
|
||||
const props = defineProps<AccordionRootProps>()
|
||||
const emits = defineEmits<AccordionRootEmits>()
|
||||
|
||||
const forwarded = useForwardPropsEmits(props, emits)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AccordionRoot v-bind="forwarded">
|
||||
<slot />
|
||||
</AccordionRoot>
|
||||
</template>
|
||||
```
|
||||
|
||||
As you can see, `AccordionRootEmits` and `AccordionRootProps` types are imported from radix, combined with `useForwardPropsEmits` and then are binded using `v-bind` syntaxt.
|
||||
|
||||
### CSS Classes
|
||||
There are cases when we want to accept `class` as a prop in our `shadcn/vue` component and then combine it with a default tailwind class on our `radix-vue` component via `cn` utility function.
|
||||
|
||||
In these cases, we can not use `v-bind`, because this would lead in [double class binding](https://github.com/radix-vue/shadcn-vue/pull/241).
|
||||
|
||||
Take a look at `DrawerDescription.vue`.
|
||||
|
||||
```vue
|
||||
<script lang="ts" setup>
|
||||
import type { DrawerDescriptionProps } from 'vaul-vue'
|
||||
import { DrawerDescription } from 'vaul-vue'
|
||||
import { type HtmlHTMLAttributes, computed } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DrawerDescriptionProps & { class?: HtmlHTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DrawerDescription v-bind="delegatedProps" :class="cn('text-sm text-muted-foreground', props.class)">
|
||||
<slot />
|
||||
</DrawerDescription>
|
||||
</template>
|
||||
```
|
||||
|
||||
As you can see, we have created a computed property named `delegatedProps` to remove `class` from props, and only then bind
|
||||
the returned value to our radix component (`DrawerDescription` in this case).
|
||||
|
||||
As for our class, we first declared it as type of `HtmlHTMLAttributes['class']` and used `cn` to merge tailwind classes from `class` prop and our own classes.
|
||||
|
||||
This pattern only needs to be applied when the `cn` utility is required. For instances where there are no default Tailwind classes that need to be merged with user-provided classes, this pattern is not necessary. A good example of this is the `SelectValue.vue` component.
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { SelectValue, type SelectValueProps } from 'radix-vue'
|
||||
|
||||
const props = defineProps<SelectValueProps>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SelectValue v-bind="props">
|
||||
<slot />
|
||||
</SelectValue>
|
||||
</template>
|
||||
```
|
||||
|
||||
### Boolean Props
|
||||
When you are building a wrapper for a component, in some cases you want to ignore Vue [Props Boolean Casting](https://vuejs.org/guide/components/props.html#boolean-casting).
|
||||
You can either set default value as undefined for all the boolean field, or you can use [`useForwardProps`](https://www.radix-vue.com/utilities/use-forward-props.html) composable.
|
||||
|
||||
Take a look at `AccordionItem.vue`
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { type HTMLAttributes, computed } from 'vue'
|
||||
import { AccordionItem, type AccordionItemProps, useForwardProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<AccordionItemProps & { class?: HTMLAttributes['class'] }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
||||
return delegated
|
||||
})
|
||||
|
||||
const forwardedProps = useForwardProps(delegatedProps)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AccordionItem
|
||||
v-bind="forwardedProps"
|
||||
:class="cn('border-b', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</AccordionItem>
|
||||
</template>
|
||||
```
|
||||
|
||||
Since `AccordionItemProps` type has atleast one boolean property, we need to use `useForwardProps` on the entire props object.
|
||||
|
||||
Note that `useForwardPropsEmits` use `useForwardProps` under the hood.
|
||||
|
||||
### Component as Root
|
||||
Whenever your root component is a `Component` Primitive from vue, it's easier to use [`Primitive`](https://www.radix-vue.com/utilities/primitive.html) instead.
|
||||
|
||||
Let's take a look at `Button.vue`
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { Primitive, type PrimitiveProps } from 'radix-vue'
|
||||
import { type ButtonVariants, buttonVariants } from '.'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface Props extends PrimitiveProps {
|
||||
variant?: ButtonVariants['variant']
|
||||
size?: ButtonVariants['size']
|
||||
class?: HTMLAttributes['class']
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
as: 'button',
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Primitive
|
||||
:as="as"
|
||||
:as-child="asChild"
|
||||
:class="cn(buttonVariants({ variant, size }), props.class)"
|
||||
>
|
||||
<slot />
|
||||
</Primitive>
|
||||
</template>
|
||||
```
|
||||
|
||||
You'll need to extend `PrimitiveProps` in your props to support `Primitive` component. In most cases you would also need a default value for [`as`](https://www.radix-vue.com/utilities/primitive.html#changing-as-value) property.
|
||||
|
||||
## Debugging
|
||||
Here are some tools and techniques that can help you debug more effectively while contributing to `shadcn/vue` or developing your own projects.
|
||||
|
||||
### Install Vue Dev Tools
|
||||
To easily inspect component props, attributes, events, and more, you can leverage the [`Vue DevTools`](https://devtools.vuejs.org/) extension for browsers. This extension provides a user-friendly interface for debugging Vue components and can improve your development experience.
|
||||
|
||||
### Enable Custom Formmaters
|
||||
Vue wraps values stored in a `ref` in a way that, when logged, results in a nested object and requires manual inspection to access the value stored in the ref.
|
||||
|
||||
You can enable Custom Formatters in your browser to automate this process.
|
||||
|
||||
- [Firefox](https://firefox-source-docs.mozilla.org/devtools-user/custom_formatters/index.html)
|
||||
- Chrome, Edge, Brave and other Chromium based [browsers](https://www.google.com/search?q=how+to+enable+custom++formatter+chrome)
|
||||
|
|
@ -56,8 +56,6 @@ description: How to install dependencies and structure your app.
|
|||
</LinkedCard>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
## TypeScript
|
||||
|
||||
This project and the components are written in TypeScript. We recommend using TypeScript for your project as well.
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ npm install -D @nuxtjs/tailwindcss
|
|||
|
||||
</TabMarkdown>
|
||||
|
||||
|
||||
<TabMarkdown title="manual">
|
||||
|
||||
Add the following code to `modules/shadcn.ts`.
|
||||
|
|
@ -148,7 +147,6 @@ declare module '@nuxt/schema' {
|
|||
</TabMarkdown>
|
||||
</TabsMarkdown>
|
||||
|
||||
|
||||
### Configure `nuxt.config.ts`
|
||||
|
||||
```ts
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ _Use this as a reference to build your own component libraries._
|
|||
|
||||
## FAQ
|
||||
|
||||
|
||||
<Accordion type="multiple">
|
||||
|
||||
<AccordionItem value="faq-1">
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ title: Theming
|
|||
description: Use CSS Variables to customize the look and feel of your application.
|
||||
---
|
||||
|
||||
|
||||
You can choose between using CSS variables or Tailwind CSS utility classes for theming.
|
||||
|
||||
## Utility classes
|
||||
|
|
@ -38,7 +37,6 @@ To use utility classes for theming set `tailwind.cssVariables` to `false` in you
|
|||
|
||||
To use CSS variables for theming set `tailwind.cssVariables` to `true` in your `components.json` file.
|
||||
|
||||
|
||||
```json {7} title="components.json"
|
||||
{
|
||||
"style": "default",
|
||||
|
|
@ -201,9 +199,6 @@ I recommend using [HSL colors](https://www.smashingmagazine.com/2021/07/hsl-colo
|
|||
|
||||
See the [Tailwind CSS documentation](https://tailwindcss.com/docs/customizing-colors#using-css-variables) for more information on using `rgb`, `rgba` or `hsl` colors.
|
||||
|
||||
|
||||
|
||||
|
||||
## Hex -> Color Channel
|
||||
|
||||
You can use this tool to convert your HEX color to HSL without the color space function. Simply add your color in hex format, copy one of the generated values, then add them to the CSS variable.
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ const debouncedSearch = refDebounced(searchValue, 250)
|
|||
|
||||
const filteredMailList = computed(() => {
|
||||
let output: Mail[] = []
|
||||
const serachValue = debouncedSearch.value?.trim()
|
||||
if (!serachValue) {
|
||||
const searchValue = debouncedSearch.value?.trim()
|
||||
if (!searchValue) {
|
||||
output = props.mails
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ const table = useVueTable({
|
|||
|
||||
<TableRow v-else>
|
||||
<TableCell
|
||||
col-span="{columns.length}"
|
||||
:colspan="columns.length"
|
||||
class="h-24 text-center"
|
||||
>
|
||||
No results.
|
||||
|
|
|
|||
53
apps/www/src/lib/registry/default/example/BreadcrumbDemo.vue
Normal file
53
apps/www/src/lib/registry/default/example/BreadcrumbDemo.vue
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<script lang="ts" setup>
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbEllipsis,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from '@/lib/registry/default/ui/breadcrumb'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/lib/registry/default/ui/dropdown-menu'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/">
|
||||
Home
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger class="flex items-center gap-1">
|
||||
<BreadcrumbEllipsis class="h-4 w-4" />
|
||||
<span class="sr-only">Toggle menu</span>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start">
|
||||
<DropdownMenuItem>Documentation</DropdownMenuItem>
|
||||
<DropdownMenuItem>Themes</DropdownMenuItem>
|
||||
<DropdownMenuItem>GitHub</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/docs/components/accordion.html">
|
||||
Components
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<script lang="ts" setup>
|
||||
import { ChevronDown, Slash } from 'lucide-vue-next'
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from '@/lib/registry/default/ui/breadcrumb'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/lib/registry/default/ui/dropdown-menu'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/">
|
||||
Home
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator>
|
||||
<Slash />
|
||||
</BreadcrumbSeparator>
|
||||
<BreadcrumbItem>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger class="flex items-center gap-1">
|
||||
Components
|
||||
<ChevronDown class="h-4 w-4" />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start">
|
||||
<DropdownMenuItem>Documentation</DropdownMenuItem>
|
||||
<DropdownMenuItem>Themes</DropdownMenuItem>
|
||||
<DropdownMenuItem>GitHub</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator>
|
||||
<Slash />
|
||||
</BreadcrumbSeparator>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<script lang="ts" setup>
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbEllipsis,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from '@/lib/registry/default/ui/breadcrumb'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink as-child>
|
||||
<a href="/">
|
||||
Home
|
||||
</a>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbEllipsis />
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink as-child>
|
||||
<a href="/docs/components/accordion.html">
|
||||
Components
|
||||
</a>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<script lang="ts" setup>
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from '@/lib/registry/default/ui/breadcrumb'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink>
|
||||
<a href="/">
|
||||
Home
|
||||
</a>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink>
|
||||
<a href="/docs/components/accordion.html">
|
||||
Components
|
||||
</a>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
<script lang="ts" setup>
|
||||
import { useMediaQuery } from '@vueuse/core'
|
||||
import { computed, ref } from 'vue'
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbEllipsis,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from '@/lib/registry/default/ui/breadcrumb'
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import {
|
||||
Drawer,
|
||||
DrawerClose,
|
||||
DrawerContent,
|
||||
DrawerDescription,
|
||||
DrawerFooter,
|
||||
DrawerHeader,
|
||||
DrawerTitle,
|
||||
DrawerTrigger,
|
||||
} from '@/lib/registry/default/ui/drawer'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/lib/registry/default/ui/dropdown-menu'
|
||||
|
||||
const isDesktop = useMediaQuery('(min-width: 768px)')
|
||||
const isOpen = ref(false)
|
||||
const items = ref([
|
||||
{ href: '#', label: 'Home' },
|
||||
{ href: '#', label: 'Documentation' },
|
||||
{ href: '#', label: 'Building Your Application' },
|
||||
{ href: '#', label: 'Data Fetching' },
|
||||
{ label: 'Caching and Revalidating' },
|
||||
])
|
||||
|
||||
const itemsToDisplay = 3
|
||||
const firstLabel = computed(() => items.value[0]?.label)
|
||||
|
||||
const allButLastTwoItems = computed(() => items.value.slice(1, -2))
|
||||
const remainingItems = computed(() => items.value.slice(-itemsToDisplay + 1))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="{items[0].href}">
|
||||
{{ firstLabel }}
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<template v-if="items.length > itemsToDisplay">
|
||||
<BreadcrumbItem>
|
||||
<DropdownMenu v-if="isDesktop" v-model:open="isOpen">
|
||||
<DropdownMenuTrigger
|
||||
class="flex items-center gap-1"
|
||||
aria-label="Toggle menu"
|
||||
>
|
||||
<BreadcrumbEllipsis class="h-4 w-4" />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="start">
|
||||
<DropdownMenuItem v-for="item of allButLastTwoItems" :key="item.label">
|
||||
<a :href="item.href || '#'">
|
||||
{{ item.label }}
|
||||
</a>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<Drawer v-else v-model:open="isOpen">
|
||||
<DrawerTrigger aria-label="Toggle Menu">
|
||||
<BreadcrumbEllipsis class="h-4 w-4" />
|
||||
</DrawerTrigger>
|
||||
<DrawerContent>
|
||||
<DrawerHeader class="text-left">
|
||||
<DrawerTitle>Navigate to</DrawerTitle>
|
||||
<DrawerDescription>
|
||||
Select a page to navigate to.
|
||||
</DrawerDescription>
|
||||
</DrawerHeader>
|
||||
<div class="grid gap-1 px-4">
|
||||
<a
|
||||
v-for="item of allButLastTwoItems"
|
||||
:key="item.label"
|
||||
:href="item.href"
|
||||
class="py-1 text-sm"
|
||||
>
|
||||
{{ item.label }}
|
||||
</a>
|
||||
</div>
|
||||
<DrawerFooter class="pt-4">
|
||||
<DrawerClose as-child>
|
||||
<Button variant="outline">
|
||||
Close
|
||||
</Button>
|
||||
</DrawerClose>
|
||||
</DrawerFooter>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
</template>
|
||||
<BreadcrumbItem v-for=" item of remainingItems" :key="item.label">
|
||||
<template v-if="item.href">
|
||||
<BreadcrumbLink
|
||||
as-child
|
||||
class="max-w-20 truncate md:max-w-none"
|
||||
>
|
||||
<a :href="item.href">
|
||||
{{ item.label }}
|
||||
</a>
|
||||
</BreadcrumbLink>
|
||||
<BreadcrumbSeparator />
|
||||
</template>
|
||||
<BreadcrumbPage v-else class="max-w-20 truncate md:max-w-none">
|
||||
{{ item.label }}
|
||||
</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<script lang="ts" setup>
|
||||
import { Slash } from 'lucide-vue-next'
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from '@/lib/registry/default/ui/breadcrumb'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/">
|
||||
Home
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator>
|
||||
<Slash />
|
||||
</BreadcrumbSeparator>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/docs/components/accordion.html">
|
||||
Components
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator>
|
||||
<Slash />
|
||||
</BreadcrumbSeparator>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</template>
|
||||
|
|
@ -221,7 +221,7 @@ const table = useVueTable({
|
|||
|
||||
<TableRow v-else>
|
||||
<TableCell
|
||||
:col-span="columns.length"
|
||||
:colspan="columns.length"
|
||||
class="h-24 text-center"
|
||||
>
|
||||
No results.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import type {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
|
|
@ -233,7 +232,7 @@ const table = useVueTable({
|
|||
|
||||
<TableRow v-else>
|
||||
<TableCell
|
||||
col-span="{columns.length}"
|
||||
:colspan="columns.length"
|
||||
class="h-24 text-center"
|
||||
>
|
||||
No results.
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ const table = useVueTable({
|
|||
|
||||
<TableRow v-else>
|
||||
<TableCell
|
||||
col-span="{columns.length}"
|
||||
:colspan="columns.length"
|
||||
class="h-24 text-center"
|
||||
>
|
||||
No results.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { MagnifyingGlassIcon } from '@radix-icons/vue'
|
||||
import { Search } from 'lucide-vue-next'
|
||||
import { Input } from '@/lib/registry/default/ui/input'
|
||||
</script>
|
||||
|
||||
|
|
@ -7,7 +7,7 @@ import { Input } from '@/lib/registry/default/ui/input'
|
|||
<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" />
|
||||
<Search class="size-6 text-muted-foreground" />
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {
|
|||
navigationMenuTriggerStyle,
|
||||
} from '@/lib/registry/default/ui/navigation-menu'
|
||||
|
||||
const components: { title: string; href: string; description: string }[] = [
|
||||
const components: { title: string, href: string, description: string }[] = [
|
||||
{
|
||||
title: 'Alert Dialog',
|
||||
href: '/docs/primitives/alert-dialog',
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import {
|
|||
NavigationMenuLink,
|
||||
} from '@/lib/registry/default/ui/navigation-menu'
|
||||
|
||||
defineProps<{ title?: string; href?: string }>()
|
||||
defineProps<{ title?: string, href?: string }>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -42,12 +42,13 @@ const handleComplete = (e: string[]) => console.log(e.join(''))
|
|||
|
||||
<template>
|
||||
<form class="w-2/3 space-y-6 mx-auto" @submit="onSubmit">
|
||||
<FormField v-slot="{ componentField }" name="pin">
|
||||
<FormField v-slot="{ componentField, value }" name="pin">
|
||||
<FormItem>
|
||||
<FormLabel>OTP</FormLabel>
|
||||
<FormControl>
|
||||
<PinInput
|
||||
id="pin-input"
|
||||
v-model="value!"
|
||||
placeholder="○"
|
||||
class="flex gap-2 items-center mt-1"
|
||||
otp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
<script lang="ts" setup>
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav aria-label="breadcrumb" :class="props.class">
|
||||
<slot />
|
||||
</nav>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<script lang="ts" setup>
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { MoreHorizontal } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span
|
||||
role="presentation"
|
||||
aria-hidden="true"
|
||||
:class="cn('flex h-9 w-9 items-center justify-center', props.class)"
|
||||
>
|
||||
<slot>
|
||||
<MoreHorizontal class="h-4 w-4" />
|
||||
</slot>
|
||||
<span class="sr-only">More</span>
|
||||
</span>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<script lang="ts" setup>
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<li
|
||||
:class="cn('inline-flex items-center gap-1.5', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</li>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<script lang="ts" setup>
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { Primitive, type PrimitiveProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = withDefaults(defineProps<PrimitiveProps & { class?: HTMLAttributes['class'] }>(), {
|
||||
as: 'a',
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Primitive
|
||||
:as="as"
|
||||
:as-child="asChild"
|
||||
:class="cn('transition-colors hover:text-foreground', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</Primitive>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<script lang="ts" setup>
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ol
|
||||
:class="cn('flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</ol>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<script lang="ts" setup>
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span
|
||||
role="link"
|
||||
aria-disabled="true"
|
||||
aria-current="page"
|
||||
:class="cn('font-normal text-foreground', props.class)"
|
||||
>
|
||||
<slot />
|
||||
</span>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<script lang="ts" setup>
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { ChevronRight } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<li
|
||||
role="presentation"
|
||||
aria-hidden="true"
|
||||
:class="cn('[&>svg]:size-3.5', props.class)"
|
||||
>
|
||||
<slot>
|
||||
<ChevronRight />
|
||||
</slot>
|
||||
</li>
|
||||
</template>
|
||||
7
apps/www/src/lib/registry/default/ui/breadcrumb/index.ts
Normal file
7
apps/www/src/lib/registry/default/ui/breadcrumb/index.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export { default as Breadcrumb } from './Breadcrumb.vue'
|
||||
export { default as BreadcrumbEllipsis } from './BreadcrumbEllipsis.vue'
|
||||
export { default as BreadcrumbItem } from './BreadcrumbItem.vue'
|
||||
export { default as BreadcrumbLink } from './BreadcrumbLink.vue'
|
||||
export { default as BreadcrumbList } from './BreadcrumbList.vue'
|
||||
export { default as BreadcrumbPage } from './BreadcrumbPage.vue'
|
||||
export { default as BreadcrumbSeparator } from './BreadcrumbSeparator.vue'
|
||||
|
|
@ -7,7 +7,6 @@ import { cn } from '@/lib/utils'
|
|||
interface Props extends PrimitiveProps {
|
||||
variant?: ButtonVariants['variant']
|
||||
size?: ButtonVariants['size']
|
||||
as?: string
|
||||
class?: HTMLAttributes['class']
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ import type { CarouselEmits, CarouselProps } from './interface'
|
|||
|
||||
const [useProvideCarousel, useInjectCarousel] = createInjectionState(
|
||||
({
|
||||
opts, orientation, plugins,
|
||||
opts,
|
||||
orientation,
|
||||
plugins,
|
||||
}: CarouselProps, emits: CarouselEmits) => {
|
||||
const [emblaNode, emblaApi] = emblaCarouselVue({
|
||||
...opts,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
} from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ContextMenuItemProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
|
||||
const props = defineProps<ContextMenuItemProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
|
||||
const emits = defineEmits<ContextMenuItemEmits>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue'
|
|||
import { ContextMenuLabel, type ContextMenuLabelProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ContextMenuLabelProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
|
||||
const props = defineProps<ContextMenuLabelProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
import { ChevronRight } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<ContextMenuSubTriggerProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
|
||||
const props = defineProps<ContextMenuSubTriggerProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue'
|
|||
import { DropdownMenuItem, type DropdownMenuItemProps, useForwardProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DropdownMenuItemProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
|
||||
const props = defineProps<DropdownMenuItemProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue'
|
|||
import { DropdownMenuLabel, type DropdownMenuLabelProps, useForwardProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<DropdownMenuLabelProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
|
||||
const props = defineProps<DropdownMenuLabelProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
} from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<MenubarItemProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
|
||||
const props = defineProps<MenubarItemProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
|
||||
|
||||
const emits = defineEmits<MenubarItemEmits>()
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import type { HTMLAttributes } from 'vue'
|
|||
import { MenubarLabel, type MenubarLabelProps } from 'radix-vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<MenubarLabelProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
|
||||
const props = defineProps<MenubarLabelProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { MenubarSubTrigger, type MenubarSubTriggerProps, useForwardProps } from
|
|||
import { ChevronRight } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<MenubarSubTriggerProps & { class?: HTMLAttributes['class']; inset?: boolean }>()
|
||||
const props = defineProps<MenubarSubTriggerProps & { class?: HTMLAttributes['class'], inset?: boolean }>()
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _, ...delegated } = props
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user