Merge branch 'main', remote-tracking branch 'upstream' into fix/issue/62
This commit is contained in:
commit
0a56308294
35
apps/www/.vitepress/theme/components/CodeSandbox.vue
Normal file
35
apps/www/.vitepress/theme/components/CodeSandbox.vue
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, ref } 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'
|
||||
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
code: string
|
||||
style: Style
|
||||
}>()
|
||||
|
||||
const sources = ref<Record<string, string>>({})
|
||||
|
||||
onMounted(() => {
|
||||
sources.value['App.vue'] = props.code
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form action="https://codesandbox.io/api/v1/sandboxes/define" method="POST" target="_blank">
|
||||
<input type="hidden" name="query" value="file=src/App.vue">
|
||||
<input type="hidden" name="environment" value="server">
|
||||
<input type="hidden" name="hidedevtools" value="1">
|
||||
<input type="hidden" name="parameters" :value="makeCodeSandboxParams(name, style, sources)">
|
||||
|
||||
<Tooltip :content="`Open ${name} in CodeSandbox`">
|
||||
<Button :variant="'ghost'" :size="'icon'" type="submit">
|
||||
<Icon icon="ph-codesandbox-logo" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</form>
|
||||
</template>
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import StyleSwitcher from './StyleSwitcher.vue'
|
||||
import ComponentLoader from './ComponentLoader.vue'
|
||||
import Stackblitz from './Stackblitz.vue'
|
||||
import CodeSandbox from './CodeSandbox.vue'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/lib/registry/default/ui/tabs'
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
|
@ -39,6 +41,11 @@ const { style } = useConfigStore()
|
|||
<TabsContent value="preview" class="relative rounded-md border">
|
||||
<div class="flex items-center justify-between p-4">
|
||||
<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 ?? '')" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
:class="cn('preview flex min-h-[350px] w-full justify-center p-6 lg:p-10', {
|
||||
|
|
|
|||
|
|
@ -23,32 +23,32 @@ async function copyCode() {
|
|||
<div class="relative">
|
||||
<pre class="max-h-[450px] overflow-x-auto rounded-lg border bg-zinc-950 !py-0 dark:bg-zinc-900">
|
||||
<code ref="codeRef" class="relative block rounded font-mono text-sm">
|
||||
<span class="line">@layer base {</span>
|
||||
<span class="line">:root {</span>
|
||||
<span class="line"> --background: {{ activeTheme?.cssVars.light.background }};</span>
|
||||
<span class="line"> --foreground: {{ activeTheme?.cssVars.light.foreground }};</span>
|
||||
<span class="line text-white">@layer base {</span>
|
||||
<span class="line text-white">:root {</span>
|
||||
<span class="line text-white"> --background: {{ activeTheme?.cssVars.light.background }};</span>
|
||||
<span class="line text-white"> --foreground: {{ activeTheme?.cssVars.light.foreground }};</span>
|
||||
<template v-for="prefix in (['card', 'popover', 'primary', 'secondary', 'muted', 'accent', 'destructive'] as const)" :key="prefix">
|
||||
<span class="line">--{{ prefix }}: {{ activeTheme?.cssVars.light[prefix] }};</span>
|
||||
<span class="line">--{{ prefix }}-foreground: {{ activeTheme?.cssVars.light[ `${prefix}-foreground`] }};</span>
|
||||
<span class="line text-white">--{{ prefix }}: {{ activeTheme?.cssVars.light[prefix] }};</span>
|
||||
<span class="line text-white">--{{ prefix }}-foreground: {{ activeTheme?.cssVars.light[ `${prefix}-foreground`] }};</span>
|
||||
</template>
|
||||
<span class="line"> --border:{{ activeTheme?.cssVars.light.border }};</span>
|
||||
<span class="line"> --input:{{ activeTheme?.cssVars.light.input }};</span>
|
||||
<span class="line"> --ring:{{ activeTheme?.cssVars.light.ring }};</span>
|
||||
<span class="line"> --radius: {{ config.radius }}rem;</span>
|
||||
<span class="line">}</span>
|
||||
<span class="line"> </span>
|
||||
<span class="line">.dark {</span>
|
||||
<span class="line"> --background:{{ activeTheme?.cssVars.dark.background }};</span>
|
||||
<span class="line"> --foreground:{{ activeTheme?.cssVars.dark.foreground }};</span>
|
||||
<span class="line text-white"> --border:{{ activeTheme?.cssVars.light.border }};</span>
|
||||
<span class="line text-white"> --input:{{ activeTheme?.cssVars.light.input }};</span>
|
||||
<span class="line text-white"> --ring:{{ activeTheme?.cssVars.light.ring }};</span>
|
||||
<span class="line text-white"> --radius: {{ config.radius }}rem;</span>
|
||||
<span class="line text-white">}</span>
|
||||
<span class="line text-white"> </span>
|
||||
<span class="line text-white">.dark {</span>
|
||||
<span class="line text-white"> --background:{{ activeTheme?.cssVars.dark.background }};</span>
|
||||
<span class="line text-white"> --foreground:{{ activeTheme?.cssVars.dark.foreground }};</span>
|
||||
<template v-for="prefix in (['card', 'popover', 'primary', 'secondary', 'muted', 'accent', 'destructive'] as const)" :key="prefix">
|
||||
<span class="line">--{{ prefix }}:{{ activeTheme?.cssVars.dark[ prefix] }};</span>
|
||||
<span class="line">--{{ prefix }}-foreground:{{ activeTheme?.cssVars.dark[ `${prefix}-foreground`] }};</span>
|
||||
<span class="line text-white">--{{ prefix }}:{{ activeTheme?.cssVars.dark[ prefix] }};</span>
|
||||
<span class="line text-white">--{{ prefix }}-foreground:{{ activeTheme?.cssVars.dark[ `${prefix}-foreground`] }};</span>
|
||||
</template>
|
||||
<span class="line"> --border:{{ activeTheme?.cssVars.dark.border }};</span>
|
||||
<span class="line"> --input:{{ activeTheme?.cssVars.dark.input }};</span>
|
||||
<span class="line"> --ring:{{ activeTheme?.cssVars.dark.ring }};</span>
|
||||
<span class="line">}</span>
|
||||
<span class="line">}</span>
|
||||
<span class="line text-white"> --border:{{ activeTheme?.cssVars.dark.border }};</span>
|
||||
<span class="line text-white"> --input:{{ activeTheme?.cssVars.dark.input }};</span>
|
||||
<span class="line text-white"> --ring:{{ activeTheme?.cssVars.dark.ring }};</span>
|
||||
<span class="line text-white">}</span>
|
||||
<span class="line text-white">}</span>
|
||||
</code>
|
||||
</pre>
|
||||
<Button size="sm" class="absolute right-4 top-4 bg-muted text-muted-foreground hover:bg-muted hover:text-muted-foreground" @click="copyCode">
|
||||
|
|
|
|||
34
apps/www/.vitepress/theme/components/Stackblitz.vue
Normal file
34
apps/www/.vitepress/theme/components/Stackblitz.vue
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, ref } 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'
|
||||
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
code: string
|
||||
style: Style
|
||||
}>()
|
||||
|
||||
const sources = ref<Record<string, string>>({})
|
||||
|
||||
onMounted(() => {
|
||||
sources.value['App.vue'] = props.code
|
||||
})
|
||||
|
||||
function handleClick() {
|
||||
makeStackblitzParams(props.name, props.style, sources.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<Tooltip :content="`Open ${name} in Stackblitz`">
|
||||
<Button :variant="'ghost'" :size="'icon'" @click="handleClick">
|
||||
<Icon icon="simple-icons:stackblitz" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</template>
|
||||
26
apps/www/.vitepress/theme/components/Tooltip.vue
Normal file
26
apps/www/.vitepress/theme/components/Tooltip.vue
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<script setup lang="ts">
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from '@/lib/registry/default/ui/tooltip'
|
||||
|
||||
defineProps<{
|
||||
content: string
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<slot />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{{ content }}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</template>
|
||||
|
|
@ -108,11 +108,11 @@ export const docsConfig: DocsConfig = {
|
|||
href: '/docs/installation/nuxt',
|
||||
items: [],
|
||||
},
|
||||
// {
|
||||
// title: 'Astro',
|
||||
// href: '/docs/installation/astro',
|
||||
// items: [],
|
||||
// },
|
||||
{
|
||||
title: 'Astro',
|
||||
href: '/docs/installation/astro',
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
title: 'Laravel',
|
||||
href: '/docs/installation/laravel',
|
||||
|
|
@ -244,6 +244,12 @@ export const docsConfig: DocsConfig = {
|
|||
href: '/docs/components/navigation-menu',
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
title: 'Pagination',
|
||||
href: '/docs/components/pagination',
|
||||
label: 'New',
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
title: 'Popover',
|
||||
href: '/docs/components/popover',
|
||||
|
|
|
|||
|
|
@ -119,26 +119,29 @@ watch(() => $route.path, (n) => {
|
|||
</div>
|
||||
</Button>
|
||||
|
||||
<div
|
||||
v-for="link in links"
|
||||
:key="link.name"
|
||||
class="flex items-center space-x-1"
|
||||
>
|
||||
<a :href="link.href" target="_blank" class="text-foreground">
|
||||
<component :is="link.icon" class="w-5 h-5" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="flex items-center gap-x-1">
|
||||
<Button
|
||||
v-for="link in links"
|
||||
:key="link.name"
|
||||
as="a"
|
||||
:href="link.href" target="_blank"
|
||||
:variant="'ghost'" :size="'icon'"
|
||||
>
|
||||
<component :is="link.icon" class="w-[20px] h-[20px]" />
|
||||
</Button>
|
||||
|
||||
<button
|
||||
class="flex items-center justify-center"
|
||||
aria-label="Toggle dark mode"
|
||||
@click="toggleDark()"
|
||||
>
|
||||
<component
|
||||
:is="isDark ? RadixIconsSun : RadixIconsMoon"
|
||||
class="w-5 h-5 text-foreground"
|
||||
/>
|
||||
</button>
|
||||
<Button
|
||||
class="flex items-center justify-center"
|
||||
aria-label="Toggle dark mode"
|
||||
:variant="'ghost'"
|
||||
:size="'icon'" @click="toggleDark()"
|
||||
>
|
||||
<component
|
||||
:is="isDark ? RadixIconsSun : RadixIconsMoon"
|
||||
class="w-[20px] h-[20px] text-foreground"
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
|
|
|||
212
apps/www/.vitepress/theme/utils/codeeditor.ts
Normal file
212
apps/www/.vitepress/theme/utils/codeeditor.ts
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
import { getParameters } from 'codesandbox/lib/api/define'
|
||||
import sdk from '@stackblitz/sdk'
|
||||
import { dependencies as deps } from '../../../package.json'
|
||||
import { Index as demoIndex } from '../../../../www/__registry__'
|
||||
import tailwindConfigRaw from '../../../tailwind.config?raw'
|
||||
import cssRaw from '../../../../../packages/cli/test/fixtures/nuxt/assets/css/tailwind.css?raw'
|
||||
import { type Style } from '@/lib/registry/styles'
|
||||
|
||||
export function makeCodeSandboxParams(componentName: string, style: Style, sources: Record<string, string>) {
|
||||
let files = {}
|
||||
files = constructFiles(componentName, style, sources)
|
||||
return getParameters({ files, template: 'node' })
|
||||
}
|
||||
|
||||
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,
|
||||
template: 'node',
|
||||
}, {
|
||||
newWindow: true,
|
||||
openFile: ['src/App.vue'],
|
||||
})
|
||||
}
|
||||
|
||||
const viteConfig = {
|
||||
'vite.config.js': {
|
||||
content: `import path from "path"
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
},
|
||||
},
|
||||
})`,
|
||||
isBinary: false,
|
||||
},
|
||||
'index.html': {
|
||||
content: `<!DOCTYPE html>
|
||||
<html class="dark" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + Vue + TS</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
isBinary: false,
|
||||
},
|
||||
}
|
||||
|
||||
function constructFiles(componentName: string, style: Style, sources: Record<string, string>) {
|
||||
const componentsJson = {
|
||||
style,
|
||||
tailwind: {
|
||||
config: 'tailwind.config.js',
|
||||
css: 'src/assets/index.css',
|
||||
baseColor: 'zinc',
|
||||
cssVariables: true,
|
||||
},
|
||||
aliases: {
|
||||
utils: '@/utils',
|
||||
components: '@/components',
|
||||
},
|
||||
}
|
||||
|
||||
const iconPackage = style === 'default' ? 'lucide-vue-next' : '@radix-icons/vue'
|
||||
const dependencies = {
|
||||
'vue': 'latest',
|
||||
'radix-vue': deps['radix-vue'],
|
||||
'@radix-ui/colors': 'latest',
|
||||
'clsx': 'latest',
|
||||
'class-variance-authority': 'latest',
|
||||
'tailwind-merge': 'latest',
|
||||
'tailwindcss-animate': 'latest',
|
||||
[iconPackage]: 'latest',
|
||||
'shadcn-vue': 'latest',
|
||||
'typescript': 'latest',
|
||||
}
|
||||
|
||||
const devDependencies = {
|
||||
'vite': 'latest',
|
||||
'@vitejs/plugin-vue': 'latest',
|
||||
'vue-tsc': 'latest',
|
||||
'tailwindcss': 'latest',
|
||||
'postcss': 'latest',
|
||||
'autoprefixer': 'latest',
|
||||
}
|
||||
|
||||
const transformImportPath = (code: string) => {
|
||||
let parsed = code
|
||||
parsed = parsed.replaceAll(`@/lib/registry/${style}`, '@/components')
|
||||
parsed = parsed.replaceAll('@/lib/utils', '@/utils')
|
||||
return parsed
|
||||
}
|
||||
|
||||
const componentFiles = Object.keys(sources).filter(key => key.endsWith('.vue') && key !== 'index.vue')
|
||||
const components: Record<string, any> = {}
|
||||
componentFiles.forEach((i) => {
|
||||
components[`src/${i}`] = {
|
||||
isBinary: false,
|
||||
content: transformImportPath(sources[i]),
|
||||
}
|
||||
})
|
||||
|
||||
// @ts-expect-error componentName migth not exist in Index
|
||||
const registryDependencies = demoIndex[style][componentName as any]?.registryDependencies?.filter(i => i !== 'utils')
|
||||
|
||||
const files = {
|
||||
'package.json': {
|
||||
content: {
|
||||
name: `shadcn-vue-${componentName.toLowerCase().replace(/ /g, '-')}`,
|
||||
scripts: { start: `shadcn-vue add ${registryDependencies.join(' ')} -y && vite` },
|
||||
dependencies,
|
||||
devDependencies,
|
||||
},
|
||||
isBinary: false,
|
||||
},
|
||||
'components.json': {
|
||||
content: componentsJson,
|
||||
isBinary: false,
|
||||
},
|
||||
...viteConfig,
|
||||
'tailwind.config.js': {
|
||||
content: tailwindConfigRaw,
|
||||
isBinary: false,
|
||||
},
|
||||
'postcss.config.js': {
|
||||
content: `module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
}
|
||||
}`,
|
||||
isBinary: false,
|
||||
},
|
||||
'tsconfig.json': {
|
||||
content: `{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}`,
|
||||
isBinary: false,
|
||||
},
|
||||
'src/utils.ts': {
|
||||
isBinary: false,
|
||||
content: `import { type ClassValue, clsx } from 'clsx'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { camelize, getCurrentInstance, toHandlerKey } from 'vue'
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}`,
|
||||
},
|
||||
'src/assets/index.css': {
|
||||
content: cssRaw,
|
||||
isBinary: false,
|
||||
},
|
||||
'src/main.ts': {
|
||||
content: `import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
import './assets/global.css';
|
||||
import './assets/index.css';
|
||||
|
||||
createApp(App).mount('#app')`,
|
||||
isBinary: false,
|
||||
},
|
||||
'src/App.vue': {
|
||||
isBinary: false,
|
||||
content: sources['index.vue'],
|
||||
},
|
||||
...components,
|
||||
'src/assets/global.css': {
|
||||
content: `body {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
padding-top: 120px;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: hsl(var(--background));
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
color: hsl(var(--foreground));
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-feature-settings: "rlig" 1, "calt" 1;
|
||||
}
|
||||
|
||||
#app {
|
||||
@apply w-full flex items-center justify-center px-12;
|
||||
}`,
|
||||
isBinary: false,
|
||||
},
|
||||
}
|
||||
|
||||
return files
|
||||
}
|
||||
|
|
@ -261,6 +261,13 @@ export const Index = {
|
|||
component: () => import('../src/lib/registry/default/example/InputForm.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/default/example/InputForm.vue'],
|
||||
},
|
||||
InputFormAutoAnimate: {
|
||||
name: 'InputFormAutoAnimate',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['button', 'form', 'input'],
|
||||
component: () => import('../src/lib/registry/default/example/InputFormAutoAnimate.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/default/example/InputFormAutoAnimate.vue'],
|
||||
},
|
||||
InputWithButton: {
|
||||
name: 'InputWithButton',
|
||||
type: 'components:example',
|
||||
|
|
@ -303,6 +310,13 @@ export const Index = {
|
|||
component: () => import('../src/lib/registry/default/example/NavigationMenuDemoItem.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/default/example/NavigationMenuDemoItem.vue'],
|
||||
},
|
||||
PaginationDemo: {
|
||||
name: 'PaginationDemo',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['pagination', 'button'],
|
||||
component: () => import('../src/lib/registry/default/example/PaginationDemo.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/default/example/PaginationDemo.vue'],
|
||||
},
|
||||
PopoverDemo: {
|
||||
name: 'PopoverDemo',
|
||||
type: 'components:example',
|
||||
|
|
@ -562,27 +576,7 @@ export const Index = {
|
|||
component: () => import('../src/lib/registry/default/example/TypographyTable.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/default/example/TypographyTable.vue'],
|
||||
},
|
||||
ActivityGoal: {
|
||||
name: 'ActivityGoal',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['button', 'card', 'themes', 'config'],
|
||||
component: () => import('../src/lib/registry/default/example/ActivityGoal.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/default/example/ActivityGoal.vue'],
|
||||
},
|
||||
DataTable: {
|
||||
name: 'DataTable',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['button', 'checkbox', 'dropdown-menu', 'input', 'table', 'card', 'utils'],
|
||||
component: () => import('../src/lib/registry/default/example/DataTable.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/default/example/DataTable.vue'],
|
||||
},
|
||||
Metric: {
|
||||
name: 'Metric',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['card', 'config'],
|
||||
component: () => import('../src/lib/registry/default/example/Metric.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/default/example/Metric.vue'],
|
||||
},
|
||||
|
||||
},
|
||||
'new-york': {
|
||||
AccordionDemo: {
|
||||
|
|
@ -844,6 +838,13 @@ export const Index = {
|
|||
component: () => import('../src/lib/registry/new-york/example/InputForm.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/new-york/example/InputForm.vue'],
|
||||
},
|
||||
InputFormAutoAnimate: {
|
||||
name: 'InputFormAutoAnimate',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['button', 'form', 'input'],
|
||||
component: () => import('../src/lib/registry/new-york/example/InputFormAutoAnimate.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/new-york/example/InputFormAutoAnimate.vue'],
|
||||
},
|
||||
InputWithButton: {
|
||||
name: 'InputWithButton',
|
||||
type: 'components:example',
|
||||
|
|
@ -886,6 +887,13 @@ export const Index = {
|
|||
component: () => import('../src/lib/registry/new-york/example/NavigationMenuDemoItem.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/new-york/example/NavigationMenuDemoItem.vue'],
|
||||
},
|
||||
PaginationDemo: {
|
||||
name: 'PaginationDemo',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['pagination', 'button'],
|
||||
component: () => import('../src/lib/registry/new-york/example/PaginationDemo.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/new-york/example/PaginationDemo.vue'],
|
||||
},
|
||||
PopoverDemo: {
|
||||
name: 'PopoverDemo',
|
||||
type: 'components:example',
|
||||
|
|
@ -1145,26 +1153,5 @@ export const Index = {
|
|||
component: () => import('../src/lib/registry/new-york/example/TypographyTable.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/new-york/example/TypographyTable.vue'],
|
||||
},
|
||||
ActivityGoal: {
|
||||
name: 'ActivityGoal',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['button', 'card', 'themes', 'config'],
|
||||
component: () => import('../src/lib/registry/new-york/example/ActivityGoal.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/new-york/example/ActivityGoal.vue'],
|
||||
},
|
||||
DataTable: {
|
||||
name: 'DataTable',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['button', 'checkbox', 'dropdown-menu', 'input', 'table', 'card', 'utils'],
|
||||
component: () => import('../src/lib/registry/new-york/example/DataTable.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/new-york/example/DataTable.vue'],
|
||||
},
|
||||
Metric: {
|
||||
name: 'Metric',
|
||||
type: 'components:example',
|
||||
registryDependencies: ['card', 'config'],
|
||||
component: () => import('../src/lib/registry/new-york/example/Metric.vue').then(m => m.default),
|
||||
files: ['../src/lib/registry/new-york/example/Metric.vue'],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,10 @@
|
|||
"build:registry": "tsx ./scripts/build-registry.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@formkit/auto-animate": "^0.8.0",
|
||||
"@morev/vue-transitions": "^2.3.6",
|
||||
"@radix-icons/vue": "^1.0.0",
|
||||
"@stackblitz/sdk": "^1.9.0",
|
||||
"@tanstack/vue-table": "^8.10.3",
|
||||
"@unovis/ts": "^1.2.1",
|
||||
"@unovis/vue": "1.3.0-alpha.3",
|
||||
|
|
@ -21,8 +23,10 @@
|
|||
"@vueuse/core": "^10.4.1",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.0.0",
|
||||
"codesandbox": "^2.2.3",
|
||||
"date-fns": "^2.30.0",
|
||||
"lucide-vue-next": "^0.276.0",
|
||||
"radix-vue": "^0.4.1",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"v-calendar": "^3.1.0",
|
||||
"vee-validate": "4.11.7",
|
||||
|
|
@ -43,7 +47,6 @@
|
|||
"@vue/compiler-dom": "^3.3.4",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"lodash.template": "^4.5.0",
|
||||
"radix-vue": "^0.4.1",
|
||||
"rimraf": "^5.0.1",
|
||||
"tailwind-merge": "^1.14.0",
|
||||
"tailwindcss": "^3.3.3",
|
||||
|
|
|
|||
|
|
@ -329,3 +329,10 @@ See the following links for more examples on how to use the `vee-validate` featu
|
|||
- [Switch](/docs/components/switch#form)
|
||||
- [Textarea](/docs/components/textarea#form)
|
||||
- [Combobox](/docs/components/combobox#form)
|
||||
|
||||
|
||||
## Extras
|
||||
|
||||
This example shows how to add motion to your forms with [Formkit AutoAnimate](https://auto-animate.formkit.com/)
|
||||
|
||||
<ComponentPreview name="InputFormAutoAnimate" />
|
||||
|
|
|
|||
57
apps/www/src/content/docs/components/pagination.md
Normal file
57
apps/www/src/content/docs/components/pagination.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
title: Pagination
|
||||
description: Displays data in paged format and provides navigation between pages.
|
||||
source: apps/www/src/lib/registry/default/ui/pagination
|
||||
primitive: https://www.radix-vue.com/components/pagination.html
|
||||
---
|
||||
|
||||
<ComponentPreview name="PaginationDemo" />
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
```bash
|
||||
npx shadcn-vue@latest add pagination
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
Pagination,
|
||||
PaginationEllipsis,
|
||||
PaginationFirst,
|
||||
PaginationLast,
|
||||
PaginationList,
|
||||
PaginationListItem,
|
||||
PaginationNext,
|
||||
PaginationPrev,
|
||||
} from '@/components/ui/pagination'
|
||||
|
||||
import {
|
||||
Button,
|
||||
} from '@/components/ui/button'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Pagination v-slot="{ page }" :total="100" :sibling-count="1" show-edges :default-page="2">
|
||||
<PaginationList v-slot="{ items }" class="flex items-center gap-1">
|
||||
<PaginationFirst />
|
||||
<PaginationPrev />
|
||||
|
||||
<template v-for="(item, index) in items">
|
||||
<PaginationListItem v-if="item.type === 'page'" :key="index" :value="item.value" as-child>
|
||||
<Button class="w-10 h-10 p-0" :variant="item.value === page ? 'default' : 'outline'">
|
||||
{{ item.value }}
|
||||
</Button>
|
||||
</PaginationListItem>
|
||||
<PaginationEllipsis v-else :key="item.type" :index="index" />
|
||||
</template>
|
||||
|
||||
<PaginationNext />
|
||||
<PaginationLast />
|
||||
</PaginationList>
|
||||
</Pagination>
|
||||
</template>
|
||||
```
|
||||
|
|
@ -5,7 +5,7 @@ description: How to install dependencies and structure your app.
|
|||
|
||||
## Frameworks
|
||||
|
||||
<div class="grid sm:grid-cols-2 gap-4 mt-8 sm:gap-6 not-docs">
|
||||
<div class="grid gap-4 mt-8 sm:grid-cols-2 sm:gap-6 not-docs">
|
||||
<LinkedCard href="/docs/installation/vite">
|
||||
<svg
|
||||
role="img"
|
||||
|
|
@ -17,16 +17,16 @@ description: How to install dependencies and structure your app.
|
|||
<title>Vite</title>
|
||||
<path d="m8.286 10.578.512-8.657a.306.306 0 0 1 .247-.282L17.377.006a.306.306 0 0 1 .353.385l-1.558 5.403a.306.306 0 0 0 .352.385l2.388-.46a.306.306 0 0 1 .332.438l-6.79 13.55-.123.19a.294.294 0 0 1-.252.14c-.177 0-.35-.152-.305-.369l1.095-5.301a.306.306 0 0 0-.388-.355l-1.433.435a.306.306 0 0 1-.389-.354l.69-3.375a.306.306 0 0 0-.37-.36l-2.32.536a.306.306 0 0 1-.374-.316zm14.976-7.926L17.284 3.74l-.544 1.887 2.077-.4a.8.8 0 0 1 .84.369.8.8 0 0 1 .034.783L12.9 19.93l-.013.025-.015.023-.122.19a.801.801 0 0 1-.672.37.826.826 0 0 1-.634-.302.8.8 0 0 1-.16-.67l1.029-4.981-1.12.34a.81.81 0 0 1-.86-.262.802.802 0 0 1-.165-.67l.63-3.08-2.027.468a.808.808 0 0 1-.768-.233.81.81 0 0 1-.217-.6l.389-6.57-7.44-1.33a.612.612 0 0 0-.64.906L11.58 23.691a.612.612 0 0 0 1.066-.004l11.26-20.135a.612.612 0 0 0-.644-.9z" />
|
||||
</svg>
|
||||
<p class="font-medium mt-2">Vite</p>
|
||||
<p class="mt-2 font-medium">Vite</p>
|
||||
</LinkedCard>
|
||||
<LinkedCard href="/docs/installation/nuxt">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-12 h-12" viewBox="0 0 900 900" fill="none">
|
||||
<title>Nuxt</title>
|
||||
<path d="M504.908 750H839.476C850.103 750.001 860.542 747.229 869.745 741.963C878.948 736.696 886.589 729.121 891.9 719.999C897.211 710.876 900.005 700.529 900 689.997C899.995 679.465 897.193 669.12 891.873 660.002L667.187 274.289C661.876 265.169 654.237 257.595 645.036 252.329C635.835 247.064 625.398 244.291 614.773 244.291C604.149 244.291 593.711 247.064 584.511 252.329C575.31 257.595 567.67 265.169 562.36 274.289L504.908 372.979L392.581 179.993C387.266 170.874 379.623 163.301 370.42 158.036C361.216 152.772 350.777 150 340.151 150C329.525 150 319.086 152.772 309.883 158.036C300.679 163.301 293.036 170.874 287.721 179.993L8.12649 660.002C2.80743 669.12 0.00462935 679.465 5.72978e-06 689.997C-0.00461789 700.529 2.78909 710.876 8.10015 719.999C13.4112 729.121 21.0523 736.696 30.255 741.963C39.4576 747.229 49.8973 750.001 60.524 750H270.538C353.748 750 415.112 713.775 457.336 643.101L559.849 467.145L614.757 372.979L779.547 655.834H559.849L504.908 750ZM267.114 655.737L120.551 655.704L340.249 278.586L449.87 467.145L376.474 593.175C348.433 639.03 316.577 655.737 267.114 655.737Z" fill="white"/>
|
||||
</svg>
|
||||
<p class="font-medium mt-2">Nuxt</p>
|
||||
<p class="mt-2 font-medium">Nuxt</p>
|
||||
</LinkedCard>
|
||||
<!-- <LinkedCard href="/docs/installation/astro">
|
||||
<LinkedCard href="/docs/installation/astro">
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
|
|
@ -40,8 +40,8 @@ description: How to install dependencies and structure your app.
|
|||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<p class="font-medium mt-2">Astro</p>
|
||||
</LinkedCard> -->
|
||||
<p class="mt-2 font-medium">Astro</p>
|
||||
</LinkedCard>
|
||||
<LinkedCard href="/docs/installation/laravel">
|
||||
<svg
|
||||
role="img"
|
||||
|
|
@ -52,7 +52,7 @@ description: How to install dependencies and structure your app.
|
|||
>
|
||||
<path d="M61.8548 14.6253C61.8778 14.7102 61.8895 14.7978 61.8897 14.8858V28.5615C61.8898 28.737 61.8434 28.9095 61.7554 29.0614C61.6675 29.2132 61.5409 29.3392 61.3887 29.4265L49.9104 36.0351V49.1337C49.9104 49.4902 49.7209 49.8192 49.4118 49.9987L25.4519 63.7916C25.3971 63.8227 25.3372 63.8427 25.2774 63.8639C25.255 63.8714 25.2338 63.8851 25.2101 63.8913C25.0426 63.9354 24.8666 63.9354 24.6991 63.8913C24.6716 63.8838 24.6467 63.8689 24.6205 63.8589C24.5657 63.8389 24.5084 63.8215 24.456 63.7916L0.501061 49.9987C0.348882 49.9113 0.222437 49.7853 0.134469 49.6334C0.0465019 49.4816 0.000120578 49.3092 0 49.1337L0 8.10652C0 8.01678 0.0124642 7.92953 0.0348998 7.84477C0.0423783 7.8161 0.0598282 7.78993 0.0697995 7.76126C0.0884958 7.70891 0.105946 7.65531 0.133367 7.6067C0.152063 7.5743 0.179485 7.54812 0.20192 7.51821C0.230588 7.47832 0.256763 7.43719 0.290416 7.40229C0.319084 7.37362 0.356476 7.35243 0.388883 7.32751C0.425029 7.29759 0.457436 7.26518 0.498568 7.2415L12.4779 0.345059C12.6296 0.257786 12.8015 0.211853 12.9765 0.211853C13.1515 0.211853 13.3234 0.257786 13.475 0.345059L25.4531 7.2415H25.4556C25.4955 7.26643 25.5292 7.29759 25.5653 7.32626C25.5977 7.35119 25.6339 7.37362 25.6625 7.40104C25.6974 7.43719 25.7224 7.47832 25.7523 7.51821C25.7735 7.54812 25.8021 7.5743 25.8196 7.6067C25.8483 7.65656 25.8645 7.70891 25.8844 7.76126C25.8944 7.78993 25.9118 7.8161 25.9193 7.84602C25.9423 7.93096 25.954 8.01853 25.9542 8.10652V33.7317L35.9355 27.9844V14.8846C35.9355 14.7973 35.948 14.7088 35.9704 14.6253C35.9792 14.5954 35.9954 14.5692 36.0053 14.5405C36.0253 14.4882 36.0427 14.4346 36.0702 14.386C36.0888 14.3536 36.1163 14.3274 36.1375 14.2975C36.1674 14.2576 36.1923 14.2165 36.2272 14.1816C36.2559 14.1529 36.292 14.1317 36.3244 14.1068C36.3618 14.0769 36.3942 14.0445 36.4341 14.0208L48.4147 7.12434C48.5663 7.03694 48.7383 6.99094 48.9133 6.99094C49.0883 6.99094 49.2602 7.03694 49.4118 7.12434L61.3899 14.0208C61.4323 14.0457 61.4647 14.0769 61.5021 14.1055C61.5333 14.1305 61.5694 14.1529 61.5981 14.1803C61.633 14.2165 61.6579 14.2576 61.6878 14.2975C61.7103 14.3274 61.7377 14.3536 61.7551 14.386C61.7838 14.4346 61.8 14.4882 61.8199 14.5405C61.8312 14.5692 61.8474 14.5954 61.8548 14.6253ZM59.893 27.9844V16.6121L55.7013 19.0252L49.9104 22.3593V33.7317L59.8942 27.9844H59.893ZM47.9149 48.5566V37.1768L42.2187 40.4299L25.953 49.7133V61.2003L47.9149 48.5566ZM1.99677 9.83281V48.5566L23.9562 61.199V49.7145L12.4841 43.2219L12.4804 43.2194L12.4754 43.2169C12.4368 43.1945 12.4044 43.1621 12.3682 43.1347C12.3371 43.1097 12.3009 43.0898 12.2735 43.0624L12.271 43.0586C12.2386 43.0275 12.2162 42.9888 12.1887 42.9539C12.1638 42.9203 12.1339 42.8916 12.114 42.8567L12.1127 42.853C12.0903 42.8156 12.0766 42.7707 12.0604 42.7283C12.0442 42.6909 12.023 42.656 12.013 42.6161C12.0005 42.5688 11.998 42.5177 11.9931 42.4691C11.9881 42.4317 11.9781 42.3943 11.9781 42.3569V15.5801L6.18848 12.2446L1.99677 9.83281ZM12.9777 2.36177L2.99764 8.10652L12.9752 13.8513L22.9541 8.10527L12.9752 2.36177H12.9777ZM18.1678 38.2138L23.9574 34.8809V9.83281L19.7657 12.2459L13.9749 15.5801V40.6281L18.1678 38.2138ZM48.9133 9.14105L38.9344 14.8858L48.9133 20.6305L58.8909 14.8846L48.9133 9.14105ZM47.9149 22.3593L42.124 19.0252L37.9323 16.6121V27.9844L43.7219 31.3174L47.9149 33.7317V22.3593ZM24.9533 47.987L39.59 39.631L46.9065 35.4555L36.9352 29.7145L25.4544 36.3242L14.9907 42.3482L24.9533 47.987Z" />
|
||||
</svg>
|
||||
<p class="font-medium mt-2">Laravel</p>
|
||||
<p class="mt-2 font-medium">Laravel</p>
|
||||
</LinkedCard>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -32,20 +32,30 @@ Strict
|
|||
Yes/No
|
||||
```
|
||||
|
||||
### Add React to your project
|
||||
### Add Vue to your project
|
||||
|
||||
Install React using the Astro CLI:
|
||||
Install Vue using the Astro CLI:
|
||||
|
||||
```bash
|
||||
npx astro add react
|
||||
npx astro add vue
|
||||
```
|
||||
|
||||
<Callout class="mt-4">
|
||||
|
||||
Answer `Yes` to all the question prompted by the CLI when installing React.
|
||||
Answer `Yes` to all the question prompted by the CLI when installing Vue.
|
||||
|
||||
</Callout>
|
||||
|
||||
This will install `vue` and `@astrojs/vue` as dependencies and automatically set them up in the `astro.config.mjs` file.
|
||||
|
||||
### Install TypeScript
|
||||
|
||||
If you encounter the error `Cannot find module 'typescript'`, please proceed to install TypeScript as a dev dependency, as discussed [here](https://github.com/radix-vue/shadcn-vue/pull/118)
|
||||
|
||||
```bash
|
||||
npm install -D typescript
|
||||
```
|
||||
|
||||
### Add Tailwind CSS to your project
|
||||
|
||||
Install Tailwind CSS using the Astro CLI:
|
||||
|
|
@ -60,6 +70,8 @@ Answer `Yes` to all the question prompted by the CLI when installing Tailwind CS
|
|||
|
||||
</Callout>
|
||||
|
||||
This will install `tailwindcss` and `@astrojs/tailwind` as dependencies and set them up in your `astro.config.mjs` file. It will also create a `tailwind.config.mjs` file with the needed configurations.
|
||||
|
||||
### Edit tsconfig.json file
|
||||
|
||||
Add the code below to the tsconfig.json file to resolve paths:
|
||||
|
|
@ -77,10 +89,10 @@ Add the code below to the tsconfig.json file to resolve paths:
|
|||
|
||||
### Run the CLI
|
||||
|
||||
Run the `shadcn-ui` init command to setup your project:
|
||||
Run the `shadcn-vue` init command to setup your project:
|
||||
|
||||
```bash
|
||||
npx shadcn-ui@latest init
|
||||
npx shadcn-vue@latest init
|
||||
```
|
||||
|
||||
### Configure components.json
|
||||
|
|
@ -89,14 +101,15 @@ You will be asked a few questions to configure `components.json`:
|
|||
|
||||
```txt showLineNumbers
|
||||
Would you like to use TypeScript (recommended)? no / yes
|
||||
Which framework are you using? Astro
|
||||
Which style would you like to use? › Default
|
||||
Which color would you like to use as base color? › Slate
|
||||
Where is your global CSS file? › › ./src/styles/globals.css
|
||||
Where is your global CSS file? › src/styles/globals.css
|
||||
Do you want to use CSS variables for colors? › no / yes
|
||||
Where is your tailwind.config.js located? › tailwind.config.cjs
|
||||
Where is your tailwind.config located? › tailwind.config.mjs
|
||||
Configure the import alias for components: › @/components
|
||||
Configure the import alias for utils: › @/lib/utils
|
||||
Are you using React Server Components? › no
|
||||
Write configuration to components.json. Proceed? > Y/n
|
||||
```
|
||||
|
||||
### Import the globals.css file
|
||||
|
|
@ -126,7 +139,7 @@ export default defineConfig({
|
|||
You can now start adding components to your project.
|
||||
|
||||
```bash
|
||||
npx shadcn-ui@latest add button
|
||||
npx shadcn-vue@latest add button
|
||||
```
|
||||
|
||||
The command above will add the `Button` component to your project. You can then import it like this:
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ Start by creating a new Vue project using `vite`:
|
|||
|
||||
```bash
|
||||
# npm 6.x
|
||||
npm create vite@latest my-vue-app --template vue
|
||||
npm create vite@latest my-vue-app --template vue-ts
|
||||
|
||||
# npm 7+, extra double-dash is needed:
|
||||
npm create vite@latest my-vue-app -- --template vue
|
||||
npm create vite@latest my-vue-app -- --template vue-ts
|
||||
```
|
||||
|
||||
### Add Tailwind and its configuration
|
||||
|
|
@ -103,4 +103,4 @@ import { Button } from '@/components/ui/button'
|
|||
</template>
|
||||
```
|
||||
|
||||
</Steps>
|
||||
</Steps>
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ const onSubmit = handleSubmit((values) => {
|
|||
<FormControl>
|
||||
<Input type="url" v-bind="componentField" />
|
||||
</FormControl>
|
||||
<button class="absolute py-2 pe-3 end-0 text-muted-foreground" @click="remove(index)">
|
||||
<button type="button" class="absolute py-2 pe-3 end-0 text-muted-foreground" @click="remove(index)">
|
||||
<Cross1Icon class="w-3" />
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
<script setup lang="ts">
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import * as z from 'zod'
|
||||
import { vAutoAnimate } from '@formkit/auto-animate/vue'
|
||||
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/lib/registry/default/ui/form'
|
||||
import { Input } from '@/lib/registry/default/ui/input'
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
username: z.string().min(2).max(50),
|
||||
}))
|
||||
|
||||
const { handleSubmit } = useForm({
|
||||
validationSchema: formSchema,
|
||||
})
|
||||
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
console.log('Form submitted!', values)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form class="w-2/3 space-y-6" @submit="onSubmit">
|
||||
<FormField v-slot="{ componentField }" name="username">
|
||||
<FormItem v-auto-animate>
|
||||
<FormLabel>Username</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="text" placeholder="shadcn" v-bind="componentField" />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
This is your public display name.
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
<Button type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Form>
|
||||
</template>
|
||||
37
apps/www/src/lib/registry/default/example/PaginationDemo.vue
Normal file
37
apps/www/src/lib/registry/default/example/PaginationDemo.vue
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<script setup lang="ts">
|
||||
import {
|
||||
Pagination,
|
||||
PaginationEllipsis,
|
||||
PaginationFirst,
|
||||
PaginationLast,
|
||||
PaginationList,
|
||||
PaginationListItem,
|
||||
PaginationNext,
|
||||
PaginationPrev,
|
||||
} from '@/lib/registry/default/ui/pagination'
|
||||
|
||||
import {
|
||||
Button,
|
||||
} from '@/lib/registry/default/ui/button'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Pagination v-slot="{ page }" :total="100" :sibling-count="1" show-edges :default-page="2">
|
||||
<PaginationList v-slot="{ items }" class="flex items-center gap-1">
|
||||
<PaginationFirst />
|
||||
<PaginationPrev />
|
||||
|
||||
<template v-for="(item, index) in items">
|
||||
<PaginationListItem v-if="item.type === 'page'" :key="index" :value="item.value" as-child>
|
||||
<Button class="w-10 h-10 p-0" :variant="item.value === page ? 'default' : 'outline'">
|
||||
{{ item.value }}
|
||||
</Button>
|
||||
</PaginationListItem>
|
||||
<PaginationEllipsis v-else :key="item.type" :index="index" />
|
||||
</template>
|
||||
|
||||
<PaginationNext />
|
||||
<PaginationLast />
|
||||
</PaginationList>
|
||||
</Pagination>
|
||||
</template>
|
||||
|
|
@ -7,7 +7,11 @@ import { computed, nextTick, onMounted, ref } from 'vue'
|
|||
import { buttonVariants } from '../button'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = withDefaults(defineProps< {
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
})
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
modelValue?: string | number | Date | Partial<{
|
||||
start: Date
|
||||
end: Date
|
||||
|
|
@ -41,7 +45,6 @@ function handleNav(direction: 'prev' | 'next') {
|
|||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick()
|
||||
await nextTick()
|
||||
if (modelValue.value instanceof Date && calendarRef.value)
|
||||
calendarRef.value.focusDate(modelValue.value)
|
||||
|
|
@ -59,7 +62,16 @@ onMounted(async () => {
|
|||
</button>
|
||||
</div>
|
||||
|
||||
<DatePicker ref="datePicker" v-model="modelValue" :model-modifiers="modelModifiers" class="calendar" trim-weeks :transition="'none'" :columns="columns" />
|
||||
<DatePicker
|
||||
ref="datePicker"
|
||||
v-model="modelValue"
|
||||
v-bind="$attrs"
|
||||
:model-modifiers="modelModifiers"
|
||||
class="calendar"
|
||||
trim-weeks
|
||||
:transition="'none'"
|
||||
:columns="columns"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { type InjectionKey } from 'vue'
|
||||
|
||||
export const FORMI_TEM_INJECTION_KEY
|
||||
export const FORM_ITEM_INJECTION_KEY
|
||||
= Symbol() as InjectionKey<string>
|
||||
</script>
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ defineOptions({
|
|||
})
|
||||
|
||||
const id = useId()
|
||||
provide(FORMI_TEM_INJECTION_KEY, id)
|
||||
provide(FORM_ITEM_INJECTION_KEY, id)
|
||||
|
||||
const { class: className, ...rest } = useAttrs()
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { FieldContextKey, useFieldError, useIsFieldDirty, useIsFieldTouched, useIsFieldValid } from 'vee-validate'
|
||||
import { inject } from 'vue'
|
||||
import { FORMI_TEM_INJECTION_KEY } from './FormItem.vue'
|
||||
import { FORM_ITEM_INJECTION_KEY } from './FormItem.vue'
|
||||
|
||||
export function useFormField() {
|
||||
const fieldContext = inject(FieldContextKey)
|
||||
const fieldItemContext = inject(FORMI_TEM_INJECTION_KEY)
|
||||
const fieldItemContext = inject(FORM_ITEM_INJECTION_KEY)
|
||||
|
||||
const fieldState = {
|
||||
valid: useIsFieldValid(),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { useAttrs } from 'vue'
|
||||
import { PaginationEllipsis, type PaginationEllipsisProps, useForwardProps } from 'radix-vue'
|
||||
import { MoreHorizontal } from 'lucide-vue-next'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
})
|
||||
|
||||
const props = defineProps<PaginationEllipsisProps>()
|
||||
const forwarded = useForwardProps(props)
|
||||
const { class: className, ...rest } = useAttrs()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PaginationEllipsis :class="cn('w-9 h-9 flex items-center justify-center', className ?? '')" v-bind="{ ...forwarded, ...rest }">
|
||||
<slot>
|
||||
<MoreHorizontal />
|
||||
</slot>
|
||||
</PaginationEllipsis>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { PaginationFirst, type PaginationFirstProps, useForwardProps } from 'radix-vue'
|
||||
import { ChevronsLeft } from 'lucide-vue-next'
|
||||
import {
|
||||
Button,
|
||||
} from '@/lib/registry/default/ui/button'
|
||||
|
||||
const props = withDefaults(defineProps<PaginationFirstProps>(), {
|
||||
asChild: true,
|
||||
})
|
||||
const forwarded = useForwardProps(props)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PaginationFirst v-bind="forwarded">
|
||||
<Button class="w-10 h-10 p-0" variant="outline">
|
||||
<slot>
|
||||
<ChevronsLeft class="h-4 w-4" />
|
||||
</slot>
|
||||
</Button>
|
||||
</PaginationFirst>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { PaginationLast, type PaginationLastProps, useForwardProps } from 'radix-vue'
|
||||
import { ChevronsRight } from 'lucide-vue-next'
|
||||
import {
|
||||
Button,
|
||||
} from '@/lib/registry/default/ui/button'
|
||||
|
||||
const props = withDefaults(defineProps<PaginationLastProps>(), {
|
||||
asChild: true,
|
||||
})
|
||||
const forwarded = useForwardProps(props)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PaginationLast v-bind="forwarded">
|
||||
<Button class="w-10 h-10 p-0" variant="outline">
|
||||
<slot>
|
||||
<ChevronsRight class="h-4 w-4" />
|
||||
</slot>
|
||||
</Button>
|
||||
</PaginationLast>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { PaginationNext, type PaginationNextProps, useForwardProps } from 'radix-vue'
|
||||
import { ChevronRight } from 'lucide-vue-next'
|
||||
import {
|
||||
Button,
|
||||
} from '@/lib/registry/default/ui/button'
|
||||
|
||||
const props = withDefaults(defineProps<PaginationNextProps>(), {
|
||||
asChild: true,
|
||||
})
|
||||
const forwarded = useForwardProps(props)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PaginationNext v-bind="forwarded">
|
||||
<Button class="w-10 h-10 p-0" variant="outline">
|
||||
<slot>
|
||||
<ChevronRight class="h-4 w-4" />
|
||||
</slot>
|
||||
</Button>
|
||||
</PaginationNext>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { PaginationPrev, type PaginationPrevProps, useForwardProps } from 'radix-vue'
|
||||
import { ChevronLeft } from 'lucide-vue-next'
|
||||
import {
|
||||
Button,
|
||||
} from '@/lib/registry/default/ui/button'
|
||||
|
||||
const props = withDefaults(defineProps<PaginationPrevProps>(), {
|
||||
asChild: true,
|
||||
})
|
||||
const forwarded = useForwardProps(props)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PaginationPrev v-bind="forwarded">
|
||||
<Button class="w-10 h-10 p-0" variant="outline">
|
||||
<slot>
|
||||
<ChevronLeft class="h-4 w-4" />
|
||||
</slot>
|
||||
</Button>
|
||||
</PaginationPrev>
|
||||
</template>
|
||||
10
apps/www/src/lib/registry/default/ui/pagination/index.ts
Normal file
10
apps/www/src/lib/registry/default/ui/pagination/index.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
export {
|
||||
PaginationRoot as Pagination,
|
||||
PaginationList,
|
||||
PaginationListItem,
|
||||
} from 'radix-vue'
|
||||
export { default as PaginationEllipsis } from './PaginationEllipsis.vue'
|
||||
export { default as PaginationFirst } from './PaginationFirst.vue'
|
||||
export { default as PaginationLast } from './PaginationLast.vue'
|
||||
export { default as PaginationNext } from './PaginationNext.vue'
|
||||
export { default as PaginationPrev } from './PaginationPrev.vue'
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<script setup lang="ts">
|
||||
import { useForm } from 'vee-validate'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import * as z from 'zod'
|
||||
import { vAutoAnimate } from '@formkit/auto-animate/vue'
|
||||
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import {
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/lib/registry/new-york/ui/form'
|
||||
import { Input } from '@/lib/registry/new-york/ui/input'
|
||||
|
||||
const formSchema = toTypedSchema(z.object({
|
||||
username: z.string().min(2).max(50),
|
||||
}))
|
||||
|
||||
const { isFieldDirty, handleSubmit } = useForm({
|
||||
validationSchema: formSchema,
|
||||
})
|
||||
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
console.log('Form submitted!', values)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form class="w-2/3 space-y-6" @submit="onSubmit">
|
||||
<FormField v-slot="{ componentField }" name="username" :validate-on-blur="!isFieldDirty">
|
||||
<FormItem v-auto-animate>
|
||||
<FormLabel>Username</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="text" placeholder="shadcn" v-bind="componentField" />
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
This is your public display name.
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
<Button type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Form>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<script setup lang="ts">
|
||||
import {
|
||||
Pagination,
|
||||
PaginationEllipsis,
|
||||
PaginationFirst,
|
||||
PaginationLast,
|
||||
PaginationList,
|
||||
PaginationListItem,
|
||||
PaginationNext,
|
||||
PaginationPrev,
|
||||
} from '@/lib/registry/new-york/ui/pagination'
|
||||
|
||||
import {
|
||||
Button,
|
||||
} from '@/lib/registry/new-york/ui/button'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Pagination v-slot="{ page }" :total="100" :sibling-count="1" show-edges :default-page="2">
|
||||
<PaginationList v-slot="{ items }" class="flex items-center gap-1">
|
||||
<PaginationFirst />
|
||||
<PaginationPrev />
|
||||
|
||||
<template v-for="(item, index) in items">
|
||||
<PaginationListItem v-if="item.type === 'page'" :key="index" :value="item.value" as-child>
|
||||
<Button class="w-9 h-9 p-0" :variant="item.value === page ? 'default' : 'outline'">
|
||||
{{ item.value }}
|
||||
</Button>
|
||||
</PaginationListItem>
|
||||
<PaginationEllipsis v-else :key="item.type" :index="index" />
|
||||
</template>
|
||||
|
||||
<PaginationNext />
|
||||
<PaginationLast />
|
||||
</PaginationList>
|
||||
</Pagination>
|
||||
</template>
|
||||
|
|
@ -7,6 +7,10 @@ import { computed, nextTick, onMounted, ref } from 'vue'
|
|||
import { buttonVariants } from '../button'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
})
|
||||
|
||||
const props = withDefaults(defineProps< {
|
||||
modelValue?: string | number | Date | Partial<{
|
||||
start: Date
|
||||
|
|
@ -41,7 +45,6 @@ function handleNav(direction: 'prev' | 'next') {
|
|||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick()
|
||||
await nextTick()
|
||||
if (modelValue.value instanceof Date && calendarRef.value)
|
||||
calendarRef.value.focusDate(modelValue.value)
|
||||
|
|
@ -59,7 +62,16 @@ onMounted(async () => {
|
|||
</button>
|
||||
</div>
|
||||
|
||||
<DatePicker ref="datePicker" v-model="modelValue" :model-modifiers="modelModifiers" class="calendar" trim-weeks :transition="'none'" :columns="columns" />
|
||||
<DatePicker
|
||||
ref="datePicker"
|
||||
v-bind="$attrs"
|
||||
v-model="modelValue"
|
||||
:model-modifiers="modelModifiers"
|
||||
class="calendar"
|
||||
trim-weeks
|
||||
:transition="'none'"
|
||||
:columns="columns"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { type InjectionKey } from 'vue'
|
||||
|
||||
export const FORMI_TEM_INJECTION_KEY
|
||||
export const FORM_ITEM_INJECTION_KEY
|
||||
= Symbol() as InjectionKey<string>
|
||||
</script>
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ import { useId } from 'radix-vue'
|
|||
import { cn } from '@/lib/utils'
|
||||
|
||||
const id = useId()
|
||||
provide(FORMI_TEM_INJECTION_KEY, id)
|
||||
provide(FORM_ITEM_INJECTION_KEY, id)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { FieldContextKey, useFieldError, useIsFieldDirty, useIsFieldTouched, useIsFieldValid } from 'vee-validate'
|
||||
import { inject } from 'vue'
|
||||
import { FORMI_TEM_INJECTION_KEY } from './FormItem.vue'
|
||||
import { FORM_ITEM_INJECTION_KEY } from './FormItem.vue'
|
||||
|
||||
export function useFormField() {
|
||||
const fieldContext = inject(FieldContextKey)
|
||||
const fieldItemContext = inject(FORMI_TEM_INJECTION_KEY)
|
||||
const fieldItemContext = inject(FORM_ITEM_INJECTION_KEY)
|
||||
|
||||
const fieldState = {
|
||||
valid: useIsFieldValid(),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { useAttrs } from 'vue'
|
||||
import { PaginationEllipsis, type PaginationEllipsisProps, useForwardProps } from 'radix-vue'
|
||||
import { DotsHorizontalIcon } from '@radix-icons/vue'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
})
|
||||
|
||||
const props = defineProps<PaginationEllipsisProps>()
|
||||
const forwarded = useForwardProps(props)
|
||||
const { class: className, ...rest } = useAttrs()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PaginationEllipsis :class="cn('w-9 h-9 flex items-center justify-center', className ?? '')" v-bind="{ ...forwarded, ...rest }">
|
||||
<slot>
|
||||
<DotsHorizontalIcon />
|
||||
</slot>
|
||||
</PaginationEllipsis>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { PaginationFirst, type PaginationFirstProps, useForwardProps } from 'radix-vue'
|
||||
import { DoubleArrowLeftIcon } from '@radix-icons/vue'
|
||||
import {
|
||||
Button,
|
||||
} from '@/lib/registry/new-york/ui/button'
|
||||
|
||||
const props = withDefaults(defineProps<PaginationFirstProps>(), {
|
||||
asChild: true,
|
||||
})
|
||||
const forwarded = useForwardProps(props)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PaginationFirst v-bind="forwarded">
|
||||
<Button class="w-9 h-9 p-0" variant="outline">
|
||||
<slot>
|
||||
<DoubleArrowLeftIcon />
|
||||
</slot>
|
||||
</Button>
|
||||
</PaginationFirst>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { PaginationLast, type PaginationLastProps, useForwardProps } from 'radix-vue'
|
||||
import { DoubleArrowRightIcon } from '@radix-icons/vue'
|
||||
import {
|
||||
Button,
|
||||
} from '@/lib/registry/new-york/ui/button'
|
||||
|
||||
const props = withDefaults(defineProps<PaginationLastProps>(), {
|
||||
asChild: true,
|
||||
})
|
||||
const forwarded = useForwardProps(props)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PaginationLast v-bind="forwarded">
|
||||
<Button class="w-9 h-9 p-0" variant="outline">
|
||||
<slot>
|
||||
<DoubleArrowRightIcon />
|
||||
</slot>
|
||||
</Button>
|
||||
</PaginationLast>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { PaginationNext, type PaginationNextProps, useForwardProps } from 'radix-vue'
|
||||
import { ChevronRightIcon } from '@radix-icons/vue'
|
||||
import {
|
||||
Button,
|
||||
} from '@/lib/registry/new-york/ui/button'
|
||||
|
||||
const props = withDefaults(defineProps<PaginationNextProps>(), {
|
||||
asChild: true,
|
||||
})
|
||||
const forwarded = useForwardProps(props)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PaginationNext v-bind="forwarded">
|
||||
<Button class="w-9 h-9 p-0" variant="outline">
|
||||
<slot>
|
||||
<ChevronRightIcon />
|
||||
</slot>
|
||||
</Button>
|
||||
</PaginationNext>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import { PaginationPrev, type PaginationPrevProps, useForwardProps } from 'radix-vue'
|
||||
import { ChevronLeftIcon } from '@radix-icons/vue'
|
||||
import {
|
||||
Button,
|
||||
} from '@/lib/registry/new-york/ui/button'
|
||||
|
||||
const props = withDefaults(defineProps<PaginationPrevProps>(), {
|
||||
asChild: true,
|
||||
})
|
||||
const forwarded = useForwardProps(props)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PaginationPrev v-bind="forwarded">
|
||||
<Button class="w-9 h-9 p-0" variant="outline">
|
||||
<slot>
|
||||
<ChevronLeftIcon />
|
||||
</slot>
|
||||
</Button>
|
||||
</PaginationPrev>
|
||||
</template>
|
||||
10
apps/www/src/lib/registry/new-york/ui/pagination/index.ts
Normal file
10
apps/www/src/lib/registry/new-york/ui/pagination/index.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
export {
|
||||
PaginationRoot as Pagination,
|
||||
PaginationList,
|
||||
PaginationListItem,
|
||||
} from 'radix-vue'
|
||||
export { default as PaginationEllipsis } from './PaginationEllipsis.vue'
|
||||
export { default as PaginationFirst } from './PaginationFirst.vue'
|
||||
export { default as PaginationLast } from './PaginationLast.vue'
|
||||
export { default as PaginationNext } from './PaginationNext.vue'
|
||||
export { default as PaginationPrev } from './PaginationPrev.vue'
|
||||
|
|
@ -9,4 +9,4 @@ export const styles = [
|
|||
},
|
||||
] as const
|
||||
|
||||
export type Style = (typeof styles)[number]
|
||||
export type Style = typeof styles[number]['name']
|
||||
|
|
|
|||
|
|
@ -375,6 +375,25 @@
|
|||
],
|
||||
"type": "components:ui"
|
||||
},
|
||||
{
|
||||
"name": "pagination",
|
||||
"dependencies": [
|
||||
"radix-vue"
|
||||
],
|
||||
"registryDependencies": [
|
||||
"utils",
|
||||
"button"
|
||||
],
|
||||
"files": [
|
||||
"ui/pagination/PaginationEllipsis.vue",
|
||||
"ui/pagination/PaginationFirst.vue",
|
||||
"ui/pagination/PaginationLast.vue",
|
||||
"ui/pagination/PaginationNext.vue",
|
||||
"ui/pagination/PaginationPrev.vue",
|
||||
"ui/pagination/index.ts"
|
||||
],
|
||||
"type": "components:ui"
|
||||
},
|
||||
{
|
||||
"name": "popover",
|
||||
"dependencies": [
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"files": [
|
||||
{
|
||||
"name": "Calendar.vue",
|
||||
"content": "<script setup lang=\"ts\">\nimport { useVModel } from '@vueuse/core'\nimport type { Calendar } from 'v-calendar'\nimport { DatePicker } from 'v-calendar'\nimport { ChevronLeft, ChevronRight } from 'lucide-vue-next'\nimport { computed, nextTick, onMounted, ref } from 'vue'\nimport { buttonVariants } from '../button'\nimport { cn } from '@/lib/utils'\n\nconst props = withDefaults(defineProps< {\n modelValue?: string | number | Date | Partial<{\n start: Date\n end: Date\n }>\n modelModifiers?: object\n columns?: number\n type?: 'single' | 'range'\n}>(), {\n type: 'single',\n columns: 1,\n})\nconst emits = defineEmits<{\n (e: 'update:modelValue', payload: typeof props.modelValue): void\n}>()\n\nconst modelValue = useVModel(props, 'modelValue', emits, {\n passive: true,\n})\n\nconst datePicker = ref<InstanceType<typeof DatePicker>>()\n// @ts-expect-error in this current version of v-calendar has the calendaRef instance, which is required to handle arrow nav.\nconst calendarRef = computed<InstanceType<typeof Calendar>>(() => datePicker.value.calendarRef)\n\nfunction handleNav(direction: 'prev' | 'next') {\n if (!calendarRef.value)\n return\n\n if (direction === 'prev')\n calendarRef.value.movePrev()\n else calendarRef.value.moveNext()\n}\n\nonMounted(async () => {\n await nextTick()\n await nextTick()\n if (modelValue.value instanceof Date && calendarRef.value)\n calendarRef.value.focusDate(modelValue.value)\n})\n</script>\n\n<template>\n <div class=\"relative\">\n <div class=\"absolute top-3 flex justify-between w-full px-4\">\n <button :class=\"cn(buttonVariants({ variant: 'outline' }), 'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100')\" @click=\"handleNav('prev')\">\n <ChevronLeft class=\"w-4 h-4\" />\n </button>\n <button :class=\"cn(buttonVariants({ variant: 'outline' }), 'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100')\" @click=\"handleNav('next')\">\n <ChevronRight class=\"w-4 h-4\" />\n </button>\n </div>\n\n <DatePicker ref=\"datePicker\" v-model=\"modelValue\" :model-modifiers=\"modelModifiers\" class=\"calendar\" trim-weeks :transition=\"'none'\" :columns=\"columns\" />\n </div>\n</template>\n\n<style lang=\"postcss\">\n.calendar {\n @apply p-3 text-center;\n}\n.calendar .vc-pane-layout {\n @apply grid gap-4;\n}\n.calendar .vc-title {\n @apply text-sm font-medium pointer-events-none;\n}\n.calendar .vc-pane-header-wrapper {\n @apply hidden;\n}\n.calendar .vc-weeks {\n @apply mt-4;\n}\n.calendar .vc-weekdays {\n @apply flex;\n}\n.calendar .vc-weekday {\n @apply text-muted-foreground rounded-md w-9 font-normal text-[0.8rem];\n}\n.calendar .vc-weeks {\n @apply w-full space-y-2 flex flex-col [&>_div]:grid [&>_div]:grid-cols-7;\n}\n.calendar .vc-day:has(.vc-highlights) {\n @apply bg-accent first:rounded-l-md last:rounded-r-md overflow-hidden;\n}\n.calendar .vc-day-content {\n @apply text-center text-sm p-0 relative focus-within:relative focus-within:z-20 inline-flex items-center justify-center ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 hover:bg-accent hover:text-accent-foreground h-9 w-9 font-normal aria-selected:opacity-100 select-none;\n}\n.calendar .vc-day-content:not(.vc-highlight-content-light) {\n @apply rounded-md;\n}\n.calendar .is-not-in-month:not(:has(.vc-highlight-content-solid)):not(:has(.vc-highlight-content-light)):not(:has(.vc-highlight-content-outline)),\n.calendar .vc-disabled {\n @apply text-muted-foreground opacity-50;\n}\n.calendar .vc-highlight-content-solid, .calendar .vc-highlight-content-outline {\n @apply bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground;\n}\n.calendar .vc-highlight-content-light {\n @apply bg-accent text-accent-foreground;\n}\n</style>\n"
|
||||
"content": "<script setup lang=\"ts\">\nimport { useVModel } from '@vueuse/core'\nimport type { Calendar } from 'v-calendar'\nimport { DatePicker } from 'v-calendar'\nimport { ChevronLeft, ChevronRight } from 'lucide-vue-next'\nimport { computed, nextTick, onMounted, ref } from 'vue'\nimport { buttonVariants } from '../button'\nimport { cn } from '@/lib/utils'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst props = withDefaults(defineProps<{\n modelValue?: string | number | Date | Partial<{\n start: Date\n end: Date\n }>\n modelModifiers?: object\n columns?: number\n type?: 'single' | 'range'\n}>(), {\n type: 'single',\n columns: 1,\n})\nconst emits = defineEmits<{\n (e: 'update:modelValue', payload: typeof props.modelValue): void\n}>()\n\nconst modelValue = useVModel(props, 'modelValue', emits, {\n passive: true,\n})\n\nconst datePicker = ref<InstanceType<typeof DatePicker>>()\n// @ts-expect-error in this current version of v-calendar has the calendaRef instance, which is required to handle arrow nav.\nconst calendarRef = computed<InstanceType<typeof Calendar>>(() => datePicker.value.calendarRef)\n\nfunction handleNav(direction: 'prev' | 'next') {\n if (!calendarRef.value)\n return\n\n if (direction === 'prev')\n calendarRef.value.movePrev()\n else calendarRef.value.moveNext()\n}\n\nonMounted(async () => {\n await nextTick()\n if (modelValue.value instanceof Date && calendarRef.value)\n calendarRef.value.focusDate(modelValue.value)\n})\n</script>\n\n<template>\n <div class=\"relative\">\n <div class=\"absolute top-3 flex justify-between w-full px-4\">\n <button :class=\"cn(buttonVariants({ variant: 'outline' }), 'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100')\" @click=\"handleNav('prev')\">\n <ChevronLeft class=\"w-4 h-4\" />\n </button>\n <button :class=\"cn(buttonVariants({ variant: 'outline' }), 'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100')\" @click=\"handleNav('next')\">\n <ChevronRight class=\"w-4 h-4\" />\n </button>\n </div>\n\n <DatePicker\n ref=\"datePicker\"\n v-model=\"modelValue\"\n v-bind=\"$attrs\"\n :model-modifiers=\"modelModifiers\"\n class=\"calendar\"\n trim-weeks\n :transition=\"'none'\"\n :columns=\"columns\"\n />\n </div>\n</template>\n\n<style lang=\"postcss\">\n.calendar {\n @apply p-3 text-center;\n}\n.calendar .vc-pane-layout {\n @apply grid gap-4;\n}\n.calendar .vc-title {\n @apply text-sm font-medium pointer-events-none;\n}\n.calendar .vc-pane-header-wrapper {\n @apply hidden;\n}\n.calendar .vc-weeks {\n @apply mt-4;\n}\n.calendar .vc-weekdays {\n @apply flex;\n}\n.calendar .vc-weekday {\n @apply text-muted-foreground rounded-md w-9 font-normal text-[0.8rem];\n}\n.calendar .vc-weeks {\n @apply w-full space-y-2 flex flex-col [&>_div]:grid [&>_div]:grid-cols-7;\n}\n.calendar .vc-day:has(.vc-highlights) {\n @apply bg-accent first:rounded-l-md last:rounded-r-md overflow-hidden;\n}\n.calendar .vc-day-content {\n @apply text-center text-sm p-0 relative focus-within:relative focus-within:z-20 inline-flex items-center justify-center ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 hover:bg-accent hover:text-accent-foreground h-9 w-9 font-normal aria-selected:opacity-100 select-none;\n}\n.calendar .vc-day-content:not(.vc-highlight-content-light) {\n @apply rounded-md;\n}\n.calendar .is-not-in-month:not(:has(.vc-highlight-content-solid)):not(:has(.vc-highlight-content-light)):not(:has(.vc-highlight-content-outline)),\n.calendar .vc-disabled {\n @apply text-muted-foreground opacity-50;\n}\n.calendar .vc-highlight-content-solid, .calendar .vc-highlight-content-outline {\n @apply bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground;\n}\n.calendar .vc-highlight-content-light {\n @apply bg-accent text-accent-foreground;\n}\n</style>\n"
|
||||
},
|
||||
{
|
||||
"name": "index.ts",
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
},
|
||||
{
|
||||
"name": "FormItem.vue",
|
||||
"content": "<script lang=\"ts\">\nimport { type InjectionKey } from 'vue'\n\nexport const FORMI_TEM_INJECTION_KEY\n = Symbol() as InjectionKey<string>\n</script>\n\n<script lang=\"ts\" setup>\nimport { provide, useAttrs } from 'vue'\nimport { useId } from 'radix-vue'\nimport { cn } from '@/lib/utils'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst id = useId()\nprovide(FORMI_TEM_INJECTION_KEY, id)\n\nconst { class: className, ...rest } = useAttrs()\n</script>\n\n<template>\n <div :class=\"cn('space-y-2', className ?? '')\" v-bind=\"rest\">\n <slot />\n </div>\n</template>\n"
|
||||
"content": "<script lang=\"ts\">\nimport { type InjectionKey } from 'vue'\n\nexport const FORM_ITEM_INJECTION_KEY\n = Symbol() as InjectionKey<string>\n</script>\n\n<script lang=\"ts\" setup>\nimport { provide, useAttrs } from 'vue'\nimport { useId } from 'radix-vue'\nimport { cn } from '@/lib/utils'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst id = useId()\nprovide(FORM_ITEM_INJECTION_KEY, id)\n\nconst { class: className, ...rest } = useAttrs()\n</script>\n\n<template>\n <div :class=\"cn('space-y-2', className ?? '')\" v-bind=\"rest\">\n <slot />\n </div>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "FormLabel.vue",
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
},
|
||||
{
|
||||
"name": "useFormField.ts",
|
||||
"content": "import { FieldContextKey, useFieldError, useIsFieldDirty, useIsFieldTouched, useIsFieldValid } from 'vee-validate'\nimport { inject } from 'vue'\nimport { FORMI_TEM_INJECTION_KEY } from './FormItem.vue'\n\nexport function useFormField() {\n const fieldContext = inject(FieldContextKey)\n const fieldItemContext = inject(FORMI_TEM_INJECTION_KEY)\n\n const fieldState = {\n valid: useIsFieldValid(),\n isDirty: useIsFieldDirty(),\n isTouched: useIsFieldTouched(),\n error: useFieldError(),\n }\n\n if (!fieldContext)\n throw new Error('useFormField should be used within <FormField>')\n\n const { name } = fieldContext\n const id = fieldItemContext\n\n return {\n id,\n name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n }\n}\n"
|
||||
"content": "import { FieldContextKey, useFieldError, useIsFieldDirty, useIsFieldTouched, useIsFieldValid } from 'vee-validate'\nimport { inject } from 'vue'\nimport { FORM_ITEM_INJECTION_KEY } from './FormItem.vue'\n\nexport function useFormField() {\n const fieldContext = inject(FieldContextKey)\n const fieldItemContext = inject(FORM_ITEM_INJECTION_KEY)\n\n const fieldState = {\n valid: useIsFieldValid(),\n isDirty: useIsFieldDirty(),\n isTouched: useIsFieldTouched(),\n error: useFieldError(),\n }\n\n if (!fieldContext)\n throw new Error('useFormField should be used within <FormField>')\n\n const { name } = fieldContext\n const id = fieldItemContext\n\n return {\n id,\n name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n }\n}\n"
|
||||
}
|
||||
],
|
||||
"type": "components:ui"
|
||||
|
|
|
|||
37
apps/www/src/public/registry/styles/default/pagination.json
Normal file
37
apps/www/src/public/registry/styles/default/pagination.json
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"name": "pagination",
|
||||
"dependencies": [
|
||||
"radix-vue"
|
||||
],
|
||||
"registryDependencies": [
|
||||
"utils",
|
||||
"button"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"name": "PaginationEllipsis.vue",
|
||||
"content": "<script setup lang=\"ts\">\nimport { useAttrs } from 'vue'\nimport { PaginationEllipsis, type PaginationEllipsisProps, useForwardProps } from 'radix-vue'\nimport { MoreHorizontal } from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst props = defineProps<PaginationEllipsisProps>()\nconst forwarded = useForwardProps(props)\nconst { class: className, ...rest } = useAttrs()\n</script>\n\n<template>\n <PaginationEllipsis :class=\"cn('w-9 h-9 flex items-center justify-center', className ?? '')\" v-bind=\"{ ...forwarded, ...rest }\">\n <slot>\n <MoreHorizontal />\n </slot>\n </PaginationEllipsis>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "PaginationFirst.vue",
|
||||
"content": "<script setup lang=\"ts\">\nimport { PaginationFirst, type PaginationFirstProps, useForwardProps } from 'radix-vue'\nimport { ChevronsLeft } from 'lucide-vue-next'\nimport {\n Button,\n} from '@/lib/registry/default/ui/button'\n\nconst props = withDefaults(defineProps<PaginationFirstProps>(), {\n asChild: true,\n})\nconst forwarded = useForwardProps(props)\n</script>\n\n<template>\n <PaginationFirst v-bind=\"forwarded\">\n <Button class=\"w-10 h-10 p-0\" variant=\"outline\">\n <slot>\n <ChevronsLeft class=\"h-4 w-4\" />\n </slot>\n </Button>\n </PaginationFirst>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "PaginationLast.vue",
|
||||
"content": "<script setup lang=\"ts\">\nimport { PaginationLast, type PaginationLastProps, useForwardProps } from 'radix-vue'\nimport { ChevronsRight } from 'lucide-vue-next'\nimport {\n Button,\n} from '@/lib/registry/default/ui/button'\n\nconst props = withDefaults(defineProps<PaginationLastProps>(), {\n asChild: true,\n})\nconst forwarded = useForwardProps(props)\n</script>\n\n<template>\n <PaginationLast v-bind=\"forwarded\">\n <Button class=\"w-10 h-10 p-0\" variant=\"outline\">\n <slot>\n <ChevronsRight class=\"h-4 w-4\" />\n </slot>\n </Button>\n </PaginationLast>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "PaginationNext.vue",
|
||||
"content": "<script setup lang=\"ts\">\nimport { PaginationNext, type PaginationNextProps, useForwardProps } from 'radix-vue'\nimport { ChevronRight } from 'lucide-vue-next'\nimport {\n Button,\n} from '@/lib/registry/default/ui/button'\n\nconst props = withDefaults(defineProps<PaginationNextProps>(), {\n asChild: true,\n})\nconst forwarded = useForwardProps(props)\n</script>\n\n<template>\n <PaginationNext v-bind=\"forwarded\">\n <Button class=\"w-10 h-10 p-0\" variant=\"outline\">\n <slot>\n <ChevronRight class=\"h-4 w-4\" />\n </slot>\n </Button>\n </PaginationNext>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "PaginationPrev.vue",
|
||||
"content": "<script setup lang=\"ts\">\nimport { PaginationPrev, type PaginationPrevProps, useForwardProps } from 'radix-vue'\nimport { ChevronLeft } from 'lucide-vue-next'\nimport {\n Button,\n} from '@/lib/registry/default/ui/button'\n\nconst props = withDefaults(defineProps<PaginationPrevProps>(), {\n asChild: true,\n})\nconst forwarded = useForwardProps(props)\n</script>\n\n<template>\n <PaginationPrev v-bind=\"forwarded\">\n <Button class=\"w-10 h-10 p-0\" variant=\"outline\">\n <slot>\n <ChevronLeft class=\"h-4 w-4\" />\n </slot>\n </Button>\n </PaginationPrev>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "index.ts",
|
||||
"content": "export {\n PaginationRoot as Pagination,\n PaginationList,\n PaginationListItem,\n} from 'radix-vue'\nexport { default as PaginationEllipsis } from './PaginationEllipsis.vue'\nexport { default as PaginationFirst } from './PaginationFirst.vue'\nexport { default as PaginationLast } from './PaginationLast.vue'\nexport { default as PaginationNext } from './PaginationNext.vue'\nexport { default as PaginationPrev } from './PaginationPrev.vue'\n"
|
||||
}
|
||||
],
|
||||
"type": "components:ui"
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
"files": [
|
||||
{
|
||||
"name": "Calendar.vue",
|
||||
"content": "<script setup lang=\"ts\">\nimport { useVModel } from '@vueuse/core'\nimport type { Calendar } from 'v-calendar'\nimport { DatePicker } from 'v-calendar'\nimport { ChevronLeft, ChevronRight } from 'lucide-vue-next'\nimport { computed, nextTick, onMounted, ref } from 'vue'\nimport { buttonVariants } from '../button'\nimport { cn } from '@/lib/utils'\n\nconst props = withDefaults(defineProps< {\n modelValue?: string | number | Date | Partial<{\n start: Date\n end: Date\n }>\n modelModifiers?: object\n columns?: number\n type?: 'single' | 'range'\n}>(), {\n type: 'single',\n columns: 1,\n})\nconst emits = defineEmits<{\n (e: 'update:modelValue', payload: typeof props.modelValue): void\n}>()\n\nconst modelValue = useVModel(props, 'modelValue', emits, {\n passive: true,\n})\n\nconst datePicker = ref<InstanceType<typeof DatePicker>>()\n// @ts-expect-error in this current version of v-calendar has the calendaRef instance, which is required to handle arrow nav.\nconst calendarRef = computed<InstanceType<typeof Calendar>>(() => datePicker.value.calendarRef)\n\nfunction handleNav(direction: 'prev' | 'next') {\n if (!calendarRef.value)\n return\n\n if (direction === 'prev')\n calendarRef.value.movePrev()\n else calendarRef.value.moveNext()\n}\n\nonMounted(async () => {\n await nextTick()\n await nextTick()\n if (modelValue.value instanceof Date && calendarRef.value)\n calendarRef.value.focusDate(modelValue.value)\n})\n</script>\n\n<template>\n <div class=\"relative\">\n <div class=\"absolute top-3 flex justify-between w-full px-4\">\n <button :class=\"cn(buttonVariants({ variant: 'outline' }), 'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100')\" @click=\"handleNav('prev')\">\n <ChevronLeft class=\"w-4 h-4\" />\n </button>\n <button :class=\"cn(buttonVariants({ variant: 'outline' }), 'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100')\" @click=\"handleNav('next')\">\n <ChevronRight class=\"w-4 h-4\" />\n </button>\n </div>\n\n <DatePicker ref=\"datePicker\" v-model=\"modelValue\" :model-modifiers=\"modelModifiers\" class=\"calendar\" trim-weeks :transition=\"'none'\" :columns=\"columns\" />\n </div>\n</template>\n\n<style lang=\"postcss\">\n.calendar {\n @apply p-3 text-center;\n}\n.calendar .vc-pane-layout {\n @apply grid gap-4;\n}\n.calendar .vc-title {\n @apply text-sm font-medium pointer-events-none;\n}\n.calendar .vc-pane-header-wrapper {\n @apply hidden;\n}\n.calendar .vc-weeks {\n @apply mt-4;\n}\n.calendar .vc-weekdays {\n @apply flex;\n}\n.calendar .vc-weekday {\n @apply text-muted-foreground rounded-md w-8 font-normal text-[0.8rem];\n}\n.calendar .vc-weeks {\n @apply w-full space-y-2 flex flex-col [&>_div]:grid [&>_div]:grid-cols-7;\n}\n.calendar .vc-day:has(.vc-highlights) {\n @apply bg-accent first:rounded-l-md last:rounded-r-md overflow-hidden;\n}\n.calendar .vc-day-content {\n @apply text-center text-sm p-0 relative focus-within:relative focus-within:z-20 inline-flex items-center justify-center ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 hover:bg-accent hover:text-accent-foreground h-8 w-8 font-normal aria-selected:opacity-100 select-none;\n}\n.calendar .vc-day-content:not(.vc-highlight-content-light) {\n @apply rounded-md;\n}\n.calendar .is-not-in-month:not(:has(.vc-highlight-content-solid)):not(:has(.vc-highlight-content-light)):not(:has(.vc-highlight-content-outline)),\n.calendar .vc-disabled {\n @apply text-muted-foreground opacity-50;\n}\n.calendar .vc-highlight-content-solid, .calendar .vc-highlight-content-outline {\n @apply bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground;\n}\n.calendar .vc-highlight-content-light {\n @apply bg-accent text-accent-foreground;\n}\n</style>\n"
|
||||
"content": "<script setup lang=\"ts\">\nimport { useVModel } from '@vueuse/core'\nimport type { Calendar } from 'v-calendar'\nimport { DatePicker } from 'v-calendar'\nimport { ChevronLeft, ChevronRight } from 'lucide-vue-next'\nimport { computed, nextTick, onMounted, ref } from 'vue'\nimport { buttonVariants } from '../button'\nimport { cn } from '@/lib/utils'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst props = withDefaults(defineProps< {\n modelValue?: string | number | Date | Partial<{\n start: Date\n end: Date\n }>\n modelModifiers?: object\n columns?: number\n type?: 'single' | 'range'\n}>(), {\n type: 'single',\n columns: 1,\n})\nconst emits = defineEmits<{\n (e: 'update:modelValue', payload: typeof props.modelValue): void\n}>()\n\nconst modelValue = useVModel(props, 'modelValue', emits, {\n passive: true,\n})\n\nconst datePicker = ref<InstanceType<typeof DatePicker>>()\n// @ts-expect-error in this current version of v-calendar has the calendaRef instance, which is required to handle arrow nav.\nconst calendarRef = computed<InstanceType<typeof Calendar>>(() => datePicker.value.calendarRef)\n\nfunction handleNav(direction: 'prev' | 'next') {\n if (!calendarRef.value)\n return\n\n if (direction === 'prev')\n calendarRef.value.movePrev()\n else calendarRef.value.moveNext()\n}\n\nonMounted(async () => {\n await nextTick()\n if (modelValue.value instanceof Date && calendarRef.value)\n calendarRef.value.focusDate(modelValue.value)\n})\n</script>\n\n<template>\n <div class=\"relative\">\n <div class=\"absolute top-3 flex justify-between w-full px-4\">\n <button :class=\"cn(buttonVariants({ variant: 'outline' }), 'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100')\" @click=\"handleNav('prev')\">\n <ChevronLeft class=\"w-4 h-4\" />\n </button>\n <button :class=\"cn(buttonVariants({ variant: 'outline' }), 'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100')\" @click=\"handleNav('next')\">\n <ChevronRight class=\"w-4 h-4\" />\n </button>\n </div>\n\n <DatePicker\n ref=\"datePicker\"\n v-bind=\"$attrs\"\n v-model=\"modelValue\"\n :model-modifiers=\"modelModifiers\"\n class=\"calendar\"\n trim-weeks\n :transition=\"'none'\"\n :columns=\"columns\"\n />\n </div>\n</template>\n\n<style lang=\"postcss\">\n.calendar {\n @apply p-3 text-center;\n}\n.calendar .vc-pane-layout {\n @apply grid gap-4;\n}\n.calendar .vc-title {\n @apply text-sm font-medium pointer-events-none;\n}\n.calendar .vc-pane-header-wrapper {\n @apply hidden;\n}\n.calendar .vc-weeks {\n @apply mt-4;\n}\n.calendar .vc-weekdays {\n @apply flex;\n}\n.calendar .vc-weekday {\n @apply text-muted-foreground rounded-md w-8 font-normal text-[0.8rem];\n}\n.calendar .vc-weeks {\n @apply w-full space-y-2 flex flex-col [&>_div]:grid [&>_div]:grid-cols-7;\n}\n.calendar .vc-day:has(.vc-highlights) {\n @apply bg-accent first:rounded-l-md last:rounded-r-md overflow-hidden;\n}\n.calendar .vc-day-content {\n @apply text-center text-sm p-0 relative focus-within:relative focus-within:z-20 inline-flex items-center justify-center ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 hover:bg-accent hover:text-accent-foreground h-8 w-8 font-normal aria-selected:opacity-100 select-none;\n}\n.calendar .vc-day-content:not(.vc-highlight-content-light) {\n @apply rounded-md;\n}\n.calendar .is-not-in-month:not(:has(.vc-highlight-content-solid)):not(:has(.vc-highlight-content-light)):not(:has(.vc-highlight-content-outline)),\n.calendar .vc-disabled {\n @apply text-muted-foreground opacity-50;\n}\n.calendar .vc-highlight-content-solid, .calendar .vc-highlight-content-outline {\n @apply bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground;\n}\n.calendar .vc-highlight-content-light {\n @apply bg-accent text-accent-foreground;\n}\n</style>\n"
|
||||
},
|
||||
{
|
||||
"name": "index.ts",
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
},
|
||||
{
|
||||
"name": "FormItem.vue",
|
||||
"content": "<script lang=\"ts\">\nimport { type InjectionKey } from 'vue'\n\nexport const FORMI_TEM_INJECTION_KEY\n = Symbol() as InjectionKey<string>\n</script>\n\n<script lang=\"ts\" setup>\nimport { provide } from 'vue'\nimport { useId } from 'radix-vue'\nimport { cn } from '@/lib/utils'\n\nconst id = useId()\nprovide(FORMI_TEM_INJECTION_KEY, id)\n</script>\n\n<template>\n <div :class=\"cn('space-y-2', $attrs.class ?? '')\">\n <slot />\n </div>\n</template>\n"
|
||||
"content": "<script lang=\"ts\">\nimport { type InjectionKey } from 'vue'\n\nexport const FORM_ITEM_INJECTION_KEY\n = Symbol() as InjectionKey<string>\n</script>\n\n<script lang=\"ts\" setup>\nimport { provide } from 'vue'\nimport { useId } from 'radix-vue'\nimport { cn } from '@/lib/utils'\n\nconst id = useId()\nprovide(FORM_ITEM_INJECTION_KEY, id)\n</script>\n\n<template>\n <div :class=\"cn('space-y-2', $attrs.class ?? '')\">\n <slot />\n </div>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "FormLabel.vue",
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
},
|
||||
{
|
||||
"name": "useFormField.ts",
|
||||
"content": "import { FieldContextKey, useFieldError, useIsFieldDirty, useIsFieldTouched, useIsFieldValid } from 'vee-validate'\nimport { inject } from 'vue'\nimport { FORMI_TEM_INJECTION_KEY } from './FormItem.vue'\n\nexport function useFormField() {\n const fieldContext = inject(FieldContextKey)\n const fieldItemContext = inject(FORMI_TEM_INJECTION_KEY)\n\n const fieldState = {\n valid: useIsFieldValid(),\n isDirty: useIsFieldDirty(),\n isTouched: useIsFieldTouched(),\n error: useFieldError(),\n }\n\n if (!fieldContext)\n throw new Error('useFormField should be used within <FormField>')\n\n const { name } = fieldContext\n const id = fieldItemContext\n\n return {\n id,\n name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n }\n}\n"
|
||||
"content": "import { FieldContextKey, useFieldError, useIsFieldDirty, useIsFieldTouched, useIsFieldValid } from 'vee-validate'\nimport { inject } from 'vue'\nimport { FORM_ITEM_INJECTION_KEY } from './FormItem.vue'\n\nexport function useFormField() {\n const fieldContext = inject(FieldContextKey)\n const fieldItemContext = inject(FORM_ITEM_INJECTION_KEY)\n\n const fieldState = {\n valid: useIsFieldValid(),\n isDirty: useIsFieldDirty(),\n isTouched: useIsFieldTouched(),\n error: useFieldError(),\n }\n\n if (!fieldContext)\n throw new Error('useFormField should be used within <FormField>')\n\n const { name } = fieldContext\n const id = fieldItemContext\n\n return {\n id,\n name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n }\n}\n"
|
||||
}
|
||||
],
|
||||
"type": "components:ui"
|
||||
|
|
|
|||
37
apps/www/src/public/registry/styles/new-york/pagination.json
Normal file
37
apps/www/src/public/registry/styles/new-york/pagination.json
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"name": "pagination",
|
||||
"dependencies": [
|
||||
"radix-vue"
|
||||
],
|
||||
"registryDependencies": [
|
||||
"utils",
|
||||
"button"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"name": "PaginationEllipsis.vue",
|
||||
"content": "<script setup lang=\"ts\">\nimport { useAttrs } from 'vue'\nimport { PaginationEllipsis, type PaginationEllipsisProps, useForwardProps } from 'radix-vue'\nimport { DotsHorizontalIcon } from '@radix-icons/vue'\nimport { cn } from '@/lib/utils'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst props = defineProps<PaginationEllipsisProps>()\nconst forwarded = useForwardProps(props)\nconst { class: className, ...rest } = useAttrs()\n</script>\n\n<template>\n <PaginationEllipsis :class=\"cn('w-9 h-9 flex items-center justify-center', className ?? '')\" v-bind=\"{ ...forwarded, ...rest }\">\n <slot>\n <DotsHorizontalIcon />\n </slot>\n </PaginationEllipsis>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "PaginationFirst.vue",
|
||||
"content": "<script setup lang=\"ts\">\nimport { PaginationFirst, type PaginationFirstProps, useForwardProps } from 'radix-vue'\nimport { DoubleArrowLeftIcon } from '@radix-icons/vue'\nimport {\n Button,\n} from '@/lib/registry/new-york/ui/button'\n\nconst props = withDefaults(defineProps<PaginationFirstProps>(), {\n asChild: true,\n})\nconst forwarded = useForwardProps(props)\n</script>\n\n<template>\n <PaginationFirst v-bind=\"forwarded\">\n <Button class=\"w-9 h-9 p-0\" variant=\"outline\">\n <slot>\n <DoubleArrowLeftIcon />\n </slot>\n </Button>\n </PaginationFirst>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "PaginationLast.vue",
|
||||
"content": "<script setup lang=\"ts\">\nimport { PaginationLast, type PaginationLastProps, useForwardProps } from 'radix-vue'\nimport { DoubleArrowRightIcon } from '@radix-icons/vue'\nimport {\n Button,\n} from '@/lib/registry/new-york/ui/button'\n\nconst props = withDefaults(defineProps<PaginationLastProps>(), {\n asChild: true,\n})\nconst forwarded = useForwardProps(props)\n</script>\n\n<template>\n <PaginationLast v-bind=\"forwarded\">\n <Button class=\"w-9 h-9 p-0\" variant=\"outline\">\n <slot>\n <DoubleArrowRightIcon />\n </slot>\n </Button>\n </PaginationLast>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "PaginationNext.vue",
|
||||
"content": "<script setup lang=\"ts\">\nimport { PaginationNext, type PaginationNextProps, useForwardProps } from 'radix-vue'\nimport { ChevronRightIcon } from '@radix-icons/vue'\nimport {\n Button,\n} from '@/lib/registry/new-york/ui/button'\n\nconst props = withDefaults(defineProps<PaginationNextProps>(), {\n asChild: true,\n})\nconst forwarded = useForwardProps(props)\n</script>\n\n<template>\n <PaginationNext v-bind=\"forwarded\">\n <Button class=\"w-9 h-9 p-0\" variant=\"outline\">\n <slot>\n <ChevronRightIcon />\n </slot>\n </Button>\n </PaginationNext>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "PaginationPrev.vue",
|
||||
"content": "<script setup lang=\"ts\">\nimport { PaginationPrev, type PaginationPrevProps, useForwardProps } from 'radix-vue'\nimport { ChevronLeftIcon } from '@radix-icons/vue'\nimport {\n Button,\n} from '@/lib/registry/new-york/ui/button'\n\nconst props = withDefaults(defineProps<PaginationPrevProps>(), {\n asChild: true,\n})\nconst forwarded = useForwardProps(props)\n</script>\n\n<template>\n <PaginationPrev v-bind=\"forwarded\">\n <Button class=\"w-9 h-9 p-0\" variant=\"outline\">\n <slot>\n <ChevronLeftIcon />\n </slot>\n </Button>\n </PaginationPrev>\n</template>\n"
|
||||
},
|
||||
{
|
||||
"name": "index.ts",
|
||||
"content": "export {\n PaginationRoot as Pagination,\n PaginationList,\n PaginationListItem,\n} from 'radix-vue'\nexport { default as PaginationEllipsis } from './PaginationEllipsis.vue'\nexport { default as PaginationFirst } from './PaginationFirst.vue'\nexport { default as PaginationLast } from './PaginationLast.vue'\nexport { default as PaginationNext } from './PaginationNext.vue'\nexport { default as PaginationPrev } from './PaginationPrev.vue'\n"
|
||||
}
|
||||
],
|
||||
"type": "components:ui"
|
||||
}
|
||||
|
|
@ -2,12 +2,12 @@ import { computed } from 'vue'
|
|||
import { useSessionStorage } from '@vueuse/core'
|
||||
import { useData } from 'vitepress'
|
||||
import { type Theme, themes } from './../lib/registry/themes'
|
||||
import { styles } from '@/lib/registry/styles'
|
||||
import { type Style, styles } from '@/lib/registry/styles'
|
||||
|
||||
interface Config {
|
||||
theme: Theme['name']
|
||||
radius: number
|
||||
style: string
|
||||
style: Style
|
||||
}
|
||||
|
||||
export const RADII = [0, 0.25, 0.5, 0.75, 1]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "shadcn-vue",
|
||||
"version": "0.4.0",
|
||||
"version": "0.6.1",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@8.8.0",
|
||||
"license": "MIT",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "shadcn-vue",
|
||||
"type": "module",
|
||||
"version": "0.4.0",
|
||||
"version": "0.6.1",
|
||||
"description": "Add components to your apps.",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
|
@ -49,6 +49,7 @@
|
|||
"@babel/core": "^7.22.17",
|
||||
"@babel/parser": "^7.22.16",
|
||||
"@babel/plugin-transform-typescript": "^7.22.15",
|
||||
"@vue/compiler-sfc": "^3.3.6",
|
||||
"chalk": "5.3.0",
|
||||
"commander": "^11.0.0",
|
||||
"cosmiconfig": "^8.3.6",
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import {
|
|||
rawConfigSchema,
|
||||
resolveConfigPaths,
|
||||
} from '../utils/get-config'
|
||||
import { transformCJSToESM } from '../utils/transformers/transform-cjs-to-esm'
|
||||
|
||||
const PROJECT_DEPENDENCIES = {
|
||||
base: [
|
||||
|
|
@ -110,6 +111,7 @@ export async function promptForConfig(
|
|||
{ title: 'Vite', value: 'vite' },
|
||||
{ title: 'Nuxt', value: 'nuxt' },
|
||||
{ title: 'Laravel', value: 'laravel' },
|
||||
{ title: 'Astro', value: 'astro' },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -136,7 +138,7 @@ export async function promptForConfig(
|
|||
type: 'text',
|
||||
name: 'tailwindCss',
|
||||
message: `Where is your ${highlight('Tailwind CSS')} file?`,
|
||||
initial: (prev, values) => defaultConfig?.tailwind.css ?? TAILWIND_CSS_PATH[values.framework as 'vite' | 'nuxt' | 'laravel'],
|
||||
initial: (prev, values) => defaultConfig?.tailwind.css ?? TAILWIND_CSS_PATH[values.framework as 'vite' | 'nuxt' | 'laravel' | 'astro'],
|
||||
},
|
||||
{
|
||||
type: 'toggle',
|
||||
|
|
@ -151,8 +153,14 @@ export async function promptForConfig(
|
|||
{
|
||||
type: 'text',
|
||||
name: 'tailwindConfig',
|
||||
message: `Where is your ${highlight('tailwind.config.js')} located?`,
|
||||
initial: defaultConfig?.tailwind.config ?? DEFAULT_TAILWIND_CONFIG,
|
||||
message: `Where is your ${highlight('tailwind.config')} located?`,
|
||||
initial: (prev, values) => {
|
||||
if (defaultConfig?.tailwind.config)
|
||||
return defaultConfig?.tailwind.config
|
||||
if (values.framework === 'astro')
|
||||
return 'tailwind.config.mjs'
|
||||
else return DEFAULT_TAILWIND_CONFIG
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
|
|
@ -235,9 +243,12 @@ export async function runInit(cwd: string, config: Config) {
|
|||
// Write tailwind config.
|
||||
await fs.writeFile(
|
||||
config.resolvedPaths.tailwindConfig,
|
||||
config.tailwind.cssVariables
|
||||
? template(templates.TAILWIND_CONFIG_WITH_VARIABLES)({ extension, framework: config.framework })
|
||||
: template(templates.TAILWIND_CONFIG)({ extension, framework: config.framework }),
|
||||
transformCJSToESM(
|
||||
config.resolvedPaths.tailwindConfig,
|
||||
config.tailwind.cssVariables
|
||||
? template(templates.TAILWIND_CONFIG_WITH_VARIABLES)({ extension, framework: config.framework })
|
||||
: template(templates.TAILWIND_CONFIG)({ extension, framework: config.framework }),
|
||||
),
|
||||
'utf8',
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export const TAILWIND_CSS_PATH = {
|
|||
nuxt: 'assets/css/tailwind.css',
|
||||
vite: 'src/assets/index.css',
|
||||
laravel: 'resources/css/app.css',
|
||||
astro: 'src/styles/globals.css',
|
||||
}
|
||||
|
||||
// TODO: Figure out if we want to support all cosmiconfig formats.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ export function cn(...inputs: ClassValue[]) {
|
|||
}
|
||||
`
|
||||
|
||||
export const TAILWIND_CONFIG = `/** @type {import('tailwindcss').Config} */
|
||||
export const TAILWIND_CONFIG = `const animate = require("tailwindcss-animate")
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
|
|
@ -41,10 +43,12 @@ module.exports = {
|
|||
},
|
||||
},
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
plugins: [animate],
|
||||
}`
|
||||
|
||||
export const TAILWIND_CONFIG_WITH_VARIABLES = `/** @type {import('tailwindcss').Config} */
|
||||
export const TAILWIND_CONFIG_WITH_VARIABLES = `const animate = require("tailwindcss-animate")
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
darkMode: ["class"],
|
||||
<% if (framework === 'vite') { %>
|
||||
|
|
@ -61,6 +65,10 @@ module.exports = {
|
|||
"./resources/views/**/*.blade.php",
|
||||
"./resources/js/**/*.{<%- extension %>,<%- extension %>x,vue}",
|
||||
],
|
||||
<% } else if (framework === 'astro') { %>
|
||||
content: [
|
||||
'./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}',
|
||||
],
|
||||
<% } %>
|
||||
theme: {
|
||||
container: {
|
||||
|
|
@ -127,5 +135,5 @@ module.exports = {
|
|||
},
|
||||
},
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
plugins: [animate],
|
||||
}`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
export function transformCJSToESM(filename: string, code: string) {
|
||||
if (filename.endsWith('.mjs')) {
|
||||
return code
|
||||
.replace(/const\s([\w\d_]+)\s*=\s*require\((.*)\);?/g, 'import $1 from $2')
|
||||
.replace(/module\.exports = /g, 'export default ')
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
import { SyntaxKind } from 'ts-morph'
|
||||
import type * as z from 'zod'
|
||||
import MagicString from 'magic-string'
|
||||
import { parse, walk } from '@vue/compiler-sfc'
|
||||
import { SyntaxKind } from 'ts-morph'
|
||||
import type { registryBaseColorSchema } from '@/src/utils/registry/schema'
|
||||
import type { Transformer } from '@/src/utils/transformers'
|
||||
|
||||
|
|
@ -9,22 +11,32 @@ export const transformCssVars: Transformer = async ({
|
|||
baseColor,
|
||||
}) => {
|
||||
// No transform if using css variables.
|
||||
if (config.tailwind?.cssVariables || !baseColor?.inlineColors)
|
||||
if (config.tailwind?.cssVariables || !baseColor?.inlineColors || sourceFile.getFilePath().endsWith('ts'))
|
||||
return sourceFile
|
||||
|
||||
const parsed = parse(sourceFile.getText())
|
||||
const template = parsed.descriptor.template
|
||||
|
||||
if (!template)
|
||||
return sourceFile
|
||||
|
||||
sourceFile.getDescendantsOfKind(SyntaxKind.StringLiteral).forEach((node) => {
|
||||
if (template.loc.start.offset >= node.getPos())
|
||||
return sourceFile
|
||||
|
||||
const value = node.getText()
|
||||
|
||||
if (value.includes('cn(')) {
|
||||
const splitted = value.split('\'').map(i => applyColorMapping(i, baseColor.inlineColors))
|
||||
node.replaceWithText(`${splitted.join('\'')}`)
|
||||
const hasClosingDoubleQuote = value.match(/"/g)?.length === 2
|
||||
if (value.search('\'') === -1 && hasClosingDoubleQuote) {
|
||||
const mapped = applyColorMapping(value.replace(/"/g, ''), baseColor.inlineColors)
|
||||
node.replaceWithText(`"${mapped}"`)
|
||||
}
|
||||
else if (value) {
|
||||
const valueWithColorMapping = applyColorMapping(
|
||||
value.replace(/"/g, ''),
|
||||
baseColor.inlineColors,
|
||||
)
|
||||
node.replaceWithText(`"${valueWithColorMapping.trim()}"`)
|
||||
else {
|
||||
const s = new MagicString(value)
|
||||
s.replace(/'(.*?)'/g, (substring) => {
|
||||
return `'${applyColorMapping(substring.replace(/\'/g, ''), baseColor.inlineColors)}'`
|
||||
})
|
||||
node.replaceWithText(s.toString())
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -103,6 +115,6 @@ export function applyColorMapping(
|
|||
if (!lightMode.includes(className))
|
||||
lightMode.push(className)
|
||||
}
|
||||
|
||||
return `${lightMode.join(' ')} ${darkMode.join(' ').trim()}`
|
||||
const combined = `${lightMode.join(' ').replace(/\'/g, '')} ${darkMode.join(' ').trim()}`.trim()
|
||||
return `${combined}`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,68 +5,64 @@
|
|||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 46.9%;
|
||||
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 222.2 84% 4.9%;
|
||||
--foreground: 240 10% 3.9%;
|
||||
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 222.2 84% 4.9%;
|
||||
--card-foreground: 240 10% 3.9%;
|
||||
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 240 10% 3.9%;
|
||||
|
||||
--primary: 222.2 47.4% 11.2%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
--primary: 240 5.9% 10%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
|
||||
--accent: 210 40% 96.1%;
|
||||
--accent-foreground: 222.2 47.4% 11.2%;
|
||||
--secondary: 240 4.8% 95.9%;
|
||||
--secondary-foreground: 240 5.9% 10%;
|
||||
--muted: 240 4.8% 95.9%;
|
||||
--muted-foreground: 240 3.8% 46.1%;
|
||||
--accent: 240 4.8% 95.9%;
|
||||
--accent-foreground: 240 5.9% 10%;
|
||||
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
|
||||
--ring: 222.2 84% 4.9%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
|
||||
--border:240 5.9% 90%;
|
||||
--input:240 5.9% 90%;
|
||||
--ring:240 5.9% 10%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 222.2 84% 4.9%;
|
||||
--foreground: 210 40% 98%;
|
||||
--background:240 10% 3.9%;
|
||||
--foreground:0 0% 98%;
|
||||
|
||||
--muted: 217.2 32.6% 17.5%;
|
||||
--muted-foreground: 215 20.2% 65.1%;
|
||||
--card:240 10% 3.9%;
|
||||
--card-foreground:0 0% 98%;
|
||||
|
||||
--popover: 222.2 84% 4.9%;
|
||||
--popover-foreground: 210 40% 98%;
|
||||
--popover:240 10% 3.9%;
|
||||
--popover-foreground:0 0% 98%;
|
||||
|
||||
--card: 222.2 84% 4.9%;
|
||||
--card-foreground: 210 40% 98%;
|
||||
--primary:0 0% 98%;
|
||||
--primary-foreground:240 5.9% 10%;
|
||||
|
||||
--border: 217.2 32.6% 17.5%;
|
||||
--input: 217.2 32.6% 17.5%;
|
||||
--secondary:240 3.7% 15.9%;
|
||||
--secondary-foreground:0 0% 98%;
|
||||
|
||||
--primary: 210 40% 98%;
|
||||
--primary-foreground: 222.2 47.4% 11.2%;
|
||||
--muted:240 3.7% 15.9%;
|
||||
--muted-foreground:240 5% 64.9%;
|
||||
|
||||
--secondary: 217.2 32.6% 17.5%;
|
||||
--secondary-foreground: 210 40% 98%;
|
||||
--accent:240 3.7% 15.9%;
|
||||
--accent-foreground:0 0% 98%;
|
||||
|
||||
--accent: 217.2 32.6% 17.5%;
|
||||
--accent-foreground: 210 40% 98%;
|
||||
--destructive:0 62.8% 30.6%;
|
||||
--destructive-foreground:0 0% 98%;
|
||||
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
|
||||
--ring: 212.7 26.8% 83.9%;
|
||||
--border:240 3.7% 15.9%;
|
||||
--input:240 3.7% 15.9%;
|
||||
--ring:240 4.9% 83.9%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,136 @@
|
|||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`handle tailwind config template correctly 1`] = `
|
||||
"import animate from \\"tailwindcss-animate\\"
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
darkMode: [\\"class\\"],
|
||||
content: [
|
||||
'./pages/**/*.{<%- extension %>,<%- extension %>x,vue}',
|
||||
'./components/**/*.{<%- extension %>,<%- extension %>x,vue}',
|
||||
'./app/**/*.{<%- extension %>,<%- extension %>x,vue}',
|
||||
'./src/**/*.{<%- extension %>,<%- extension %>x,vue}',
|
||||
],
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
padding: \\"2rem\\",
|
||||
screens: {
|
||||
\\"2xl\\": \\"1400px\\",
|
||||
},
|
||||
},
|
||||
extend: {
|
||||
keyframes: {
|
||||
\\"accordion-down\\": {
|
||||
from: { height: 0 },
|
||||
to: { height: \\"var(--radix-accordion-content-height)\\" },
|
||||
},
|
||||
\\"accordion-up\\": {
|
||||
from: { height: \\"var(--radix-accordion-content-height)\\" },
|
||||
to: { height: 0 },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
\\"accordion-down\\": \\"accordion-down 0.2s ease-out\\",
|
||||
\\"accordion-up\\": \\"accordion-up 0.2s ease-out\\",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [animate],
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`handle tailwind config template correctly 2`] = `
|
||||
"import animate from \\"tailwindcss-animate\\"
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
darkMode: [\\"class\\"],
|
||||
<% if (framework === 'vite') { %>
|
||||
content: [
|
||||
'./pages/**/*.{<%- extension %>,<%- extension %>x,vue}',
|
||||
'./components/**/*.{<%- extension %>,<%- extension %>x,vue}',
|
||||
'./app/**/*.{<%- extension %>,<%- extension %>x,vue}',
|
||||
'./src/**/*.{<%- extension %>,<%- extension %>x,vue}',
|
||||
],
|
||||
<% } else if (framework === 'laravel') { %>
|
||||
content: [
|
||||
\\"./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php\\",
|
||||
\\"./storage/framework/views/*.php\\",
|
||||
\\"./resources/views/**/*.blade.php\\",
|
||||
\\"./resources/js/**/*.{<%- extension %>,<%- extension %>x,vue}\\",
|
||||
],
|
||||
<% } else if (framework === 'astro') { %>
|
||||
content: [
|
||||
'./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}',
|
||||
],
|
||||
<% } %>
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
padding: \\"2rem\\",
|
||||
screens: {
|
||||
\\"2xl\\": \\"1400px\\",
|
||||
},
|
||||
},
|
||||
extend: {
|
||||
colors: {
|
||||
border: \\"hsl(var(--border))\\",
|
||||
input: \\"hsl(var(--input))\\",
|
||||
ring: \\"hsl(var(--ring))\\",
|
||||
background: \\"hsl(var(--background))\\",
|
||||
foreground: \\"hsl(var(--foreground))\\",
|
||||
primary: {
|
||||
DEFAULT: \\"hsl(var(--primary))\\",
|
||||
foreground: \\"hsl(var(--primary-foreground))\\",
|
||||
},
|
||||
secondary: {
|
||||
DEFAULT: \\"hsl(var(--secondary))\\",
|
||||
foreground: \\"hsl(var(--secondary-foreground))\\",
|
||||
},
|
||||
destructive: {
|
||||
DEFAULT: \\"hsl(var(--destructive))\\",
|
||||
foreground: \\"hsl(var(--destructive-foreground))\\",
|
||||
},
|
||||
muted: {
|
||||
DEFAULT: \\"hsl(var(--muted))\\",
|
||||
foreground: \\"hsl(var(--muted-foreground))\\",
|
||||
},
|
||||
accent: {
|
||||
DEFAULT: \\"hsl(var(--accent))\\",
|
||||
foreground: \\"hsl(var(--accent-foreground))\\",
|
||||
},
|
||||
popover: {
|
||||
DEFAULT: \\"hsl(var(--popover))\\",
|
||||
foreground: \\"hsl(var(--popover-foreground))\\",
|
||||
},
|
||||
card: {
|
||||
DEFAULT: \\"hsl(var(--card))\\",
|
||||
foreground: \\"hsl(var(--card-foreground))\\",
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
lg: \\"var(--radius)\\",
|
||||
md: \\"calc(var(--radius) - 2px)\\",
|
||||
sm: \\"calc(var(--radius) - 4px)\\",
|
||||
},
|
||||
keyframes: {
|
||||
\\"accordion-down\\": {
|
||||
from: { height: 0 },
|
||||
to: { height: \\"var(--radix-accordion-content-height)\\" },
|
||||
},
|
||||
\\"accordion-up\\": {
|
||||
from: { height: \\"var(--radix-accordion-content-height)\\" },
|
||||
to: { height: 0 },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
\\"accordion-down\\": \\"accordion-down 0.2s ease-out\\",
|
||||
\\"accordion-up\\": \\"accordion-up 0.2s ease-out\\",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [animate],
|
||||
}"
|
||||
`;
|
||||
|
|
@ -17,6 +17,6 @@ exports[`transform css vars 2`] = `
|
|||
exports[`transform css vars 3`] = `
|
||||
"<script setup lang=\\"ts\\"></script>
|
||||
<template>
|
||||
<div :class=\\"cn( 'bg-white hover:bg-stone-100 dark:bg-stone-950 dark:hover:bg-stone-800', true && 'text-stone-50 sm:focus:text-stone-900 dark:text-stone-900 dark:sm:focus:text-stone-50')\\" >foo</div>
|
||||
<div :class=\\"cn('bg-white hover:bg-stone-100 dark:bg-stone-950 dark:hover:bg-stone-800', true && 'text-stone-50 sm:focus:text-stone-900 dark:text-stone-900 dark:sm:focus:text-stone-50')\\">foo</div>
|
||||
</template>\\""
|
||||
`;
|
||||
|
|
|
|||
8
packages/cli/test/utils/transform-cjs-to-esm.test.ts
Normal file
8
packages/cli/test/utils/transform-cjs-to-esm.test.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { expect, test } from 'vitest'
|
||||
import { TAILWIND_CONFIG, TAILWIND_CONFIG_WITH_VARIABLES } from '../../src/utils/templates'
|
||||
import { transformCJSToESM } from '../../src/utils/transformers/transform-cjs-to-esm'
|
||||
|
||||
test('handle tailwind config template correctly', () => {
|
||||
expect(transformCJSToESM('.mjs', TAILWIND_CONFIG)).toMatchSnapshot()
|
||||
expect(transformCJSToESM('.mjs', TAILWIND_CONFIG_WITH_VARIABLES)).toMatchSnapshot()
|
||||
})
|
||||
1550
pnpm-lock.yaml
1550
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user