chore: docs stuff (#400)

This commit is contained in:
Sadegh Barati 2024-03-09 20:21:24 +03:30 committed by GitHub
parent f530e3e4a7
commit f2f5641b33
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 296 additions and 109 deletions

View File

@ -15,7 +15,7 @@ const { copy, copied } = useClipboard()
const codeRef = ref<HTMLElement>() const codeRef = ref<HTMLElement>()
async function copyCode() { async function copyCode() {
await copy(codeRef.value?.innerText.replace(/\u00A0/g, " ") ?? '') await copy(codeRef.value?.textContent?.replace(/\u00A0/g, ' ') ?? '')
} }
</script> </script>

View File

@ -2,7 +2,7 @@
</script> </script>
<template> <template>
<a href="/" class="mr-6 flex items-center space-x-2"> <a href="/" class="mr-4 md:mr-2 xl:mr-6 flex items-center lg:space-x1 xl:space-x-2">
<svg class="h-6 w-6" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg class="h-6 w-6" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_102_1338)"> <g clip-path="url(#clip0_102_1338)">
<path d="M208 128L128 208" stroke="#41B883" stroke-width="16" stroke-linecap="round" stroke-linejoin="round" /> <path d="M208 128L128 208" stroke="#41B883" stroke-width="16" stroke-linecap="round" stroke-linejoin="round" />
@ -15,7 +15,7 @@
</defs> </defs>
</svg> </svg>
<span class="font-bold "> <span class="font-bold">
shadcn-vue shadcn-vue
</span> </span>
</a> </a>

View File

@ -5,7 +5,6 @@ import Logo from './Logo.vue'
import { Sheet, SheetContent, SheetTrigger } from '@/lib/registry/default/ui/sheet' import { Sheet, SheetContent, SheetTrigger } from '@/lib/registry/default/ui/sheet'
import { Button } from '@/lib/registry/default/ui/button' import { Button } from '@/lib/registry/default/ui/button'
import { ScrollArea } from '@/lib/registry/default/ui/scroll-area' import { ScrollArea } from '@/lib/registry/default/ui/scroll-area'
import ViewVerticalIcon from '~icons/radix-icons/view-vertical'
const open = ref(false) const open = ref(false)
</script> </script>
@ -17,7 +16,35 @@ const open = ref(false)
variant="ghost" variant="ghost"
class="mr-2 px-2 text-base flex-shrink-0 hover:bg-transparent focus-visible:bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 md:hidden" class="mr-2 px-2 text-base flex-shrink-0 hover:bg-transparent focus-visible:bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 md:hidden"
> >
<ViewVerticalIcon class="h-5 w-5" /> <svg
strokeWidth="1.5"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
>
<path
d="M3 5H11"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M3 12H16"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M3 19H21"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
<span class="sr-only">Toggle Menu</span> <span class="sr-only">Toggle Menu</span>
</Button> </Button>
</SheetTrigger> </SheetTrigger>

View File

@ -14,15 +14,13 @@ import CardChat from '@/lib/registry/new-york/example/CardChat.vue'
import ActivityGoal from '@/lib/registry/new-york/example/Cards/ActivityGoal.vue' import ActivityGoal from '@/lib/registry/new-york/example/Cards/ActivityGoal.vue'
import Metric from '@/lib/registry/new-york/example/Cards/Metric.vue' import Metric from '@/lib/registry/new-york/example/Cards/Metric.vue'
import DataTable from '@/lib/registry/new-york/example/Cards/DataTable.vue' import DataTable from '@/lib/registry/new-york/example/Cards/DataTable.vue'
import CardStats from '@/lib/registry/default/example/CardStats.vue' import CardStats from '@/lib/registry/new-york/example/CardStats.vue'
import { import {
Card, Card,
} from '@/lib/registry/new-york/ui/card' } from '@/lib/registry/new-york/ui/card'
import { Calendar } from '@/lib/registry/new-york/ui/calendar' import { Calendar } from '@/lib/registry/new-york/ui/calendar'
const goal = ref(350)
const range = ref({ const range = ref({
start: startOfToday(), start: startOfToday(),
end: addDays(startOfToday(), 8), end: addDays(startOfToday(), 8),

View File

@ -87,11 +87,9 @@ watch(() => $route.path, (n) => {
<div vaul-drawer-wrapper class="flex min-h-screen flex-col bg-background"> <div vaul-drawer-wrapper class="flex min-h-screen flex-col bg-background">
<header class="sticky z-40 top-0 bg-background/80 backdrop-blur-lg border-b border-border"> <header class="sticky z-40 top-0 bg-background/80 backdrop-blur-lg border-b border-border">
<div <div
class="container flex justify-between h-14 max-w-screen-2xl items-center" class="container flex h-14 max-w-screen-2xl items-center"
> >
<MobileNav /> <div class="mr-4 md:mr-1 hidden md:flex">
<div class="mr-4 hidden md:flex">
<Logo /> <Logo />
<nav <nav
@ -105,29 +103,31 @@ watch(() => $route.path, (n) => {
class="transition-colors hover:text-foreground/80 text-foreground/60" class="transition-colors hover:text-foreground/80 text-foreground/60"
:class="{ :class="{
'font-semibold !text-foreground': $route.path === `${route.href}.html`, 'font-semibold !text-foreground': $route.path === `${route.href}.html`,
'hidden lg:block': route?.href?.includes('github'),
}" }"
> >
{{ route.title }} {{ route.title }}
</a> </a>
</nav> </nav>
</div> </div>
<MobileNav />
<div class=" flex items-center justify-end space-x-4 "> <div class="flex flex-1 items-center justify-between space-x-2 md:justify-end">
<Button <div class="w-full flex-1 md:w-auto md:flex-none">
variant="outline" <Button
class="w-72 h-8 px-3 hidden lg:flex lg:justify-between lg:items-center" variant="outline"
@click="isOpen = true" class="relative h-8 w-full justify-start rounded-[0.5rem] bg-background text-sm font-normal text-muted-foreground shadow-none sm:pr-12 md:w-40 lg:w-64"
> @click="isOpen = true"
<div class="flex items-center"> >
<SearchIcon class="w-4 h-4 mr-2 text-muted-foreground" /> <span className="hidden lg:inline-flex">Search documentation...</span>
<span class="text-muted-foreground"> Search documentation... </span> <span className="inline-flex lg:hidden">Search...</span>
</div> <kbd className="pointer-events-none absolute right-[0.3rem] top-[0.3rem] hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex">
<div class="flex items-center gap-x-1"> <span className="text-xs"></span>K
<Kbd> <span></span>K </Kbd> </kbd>
</div> </Button>
</Button> </div>
<div class="flex items-center gap-x-1"> <nav class="flex items-center gap-x-1">
<Button <Button
v-for="link in links" v-for="link in links"
:key="link.name" :key="link.name"
@ -151,7 +151,7 @@ watch(() => $route.path, (n) => {
/> />
</Button> </Button>
</ClientOnly> </ClientOnly>
</div> </nav>
</div> </div>
</div> </div>
</header> </header>

View File

@ -7,26 +7,26 @@
--font-geist-sans: "geist-sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, --font-geist-sans: "geist-sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
--background: 0 0% 100%; --background: 0 0% 100%;
--foreground: 240 10% 3.9%; --foreground: 240 10% 3.9%;
--card: 0 0% 100%; --card: 0 0% 100%;
--card-foreground: 240 10% 3.9%; --card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%; --popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%; --popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%; --primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%; --primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%; --secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%; --secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%; --muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%; --muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%; --accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%; --accent-foreground: 240 5.9% 10%;
--destructive: 0 72.22% 50.59%; --destructive: 0 72.22% 50.59%;
--destructive-foreground: 0 0% 98%; --destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%; --border: 240 5.9% 90%;
--input: 240 5.9% 90%; --input: 240 5.9% 90%;
--ring: 240 5% 64.9%; --ring: 240 5% 64.9%;
--radius: 0.5rem; --radius: 0.5rem;
} }
.dark { .dark {
@ -61,7 +61,9 @@
} }
body { body {
@apply bg-background text-foreground min-h-screen antialiased font-sans; @apply bg-background text-foreground min-h-screen antialiased font-sans;
font-feature-settings: "rlig" 1, "calt" 1; /* font-feature-settings: "rlig" 1, "calt" 1; */
font-synthesis-weight: none;
text-rendering: optimizeLegibility;
} }
/* Mobile tap highlight */ /* Mobile tap highlight */

View File

@ -227,6 +227,13 @@ export const Index = {
component: () => import("../src/lib/registry/default/example/CarouselSpacing.vue").then((m) => m.default), component: () => import("../src/lib/registry/default/example/CarouselSpacing.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/CarouselSpacing.vue"], files: ["../src/lib/registry/default/example/CarouselSpacing.vue"],
}, },
"CarouselThumbnails": {
name: "CarouselThumbnails",
type: "components:example",
registryDependencies: ["carousel","card"],
component: () => import("../src/lib/registry/default/example/CarouselThumbnails.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/CarouselThumbnails.vue"],
},
"CheckboxDemo": { "CheckboxDemo": {
name: "CheckboxDemo", name: "CheckboxDemo",
type: "components:example", type: "components:example",
@ -1257,6 +1264,13 @@ export const Index = {
component: () => import("../src/lib/registry/new-york/example/CarouselSpacing.vue").then((m) => m.default), component: () => import("../src/lib/registry/new-york/example/CarouselSpacing.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/CarouselSpacing.vue"], files: ["../src/lib/registry/new-york/example/CarouselSpacing.vue"],
}, },
"CarouselThumbnails": {
name: "CarouselThumbnails",
type: "components:example",
registryDependencies: ["carousel","card"],
component: () => import("../src/lib/registry/new-york/example/CarouselThumbnails.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/CarouselThumbnails.vue"],
},
"CheckboxDemo": { "CheckboxDemo": {
name: "CheckboxDemo", name: "CheckboxDemo",
type: "components:example", type: "components:example",

View File

@ -5,17 +5,14 @@ source: apps/www/src/lib/registry/default/ui/carousel
primitive: https://www.embla-carousel.com/api primitive: https://www.embla-carousel.com/api
--- ---
<ComponentPreview name="CarouselDemo" /> <ComponentPreview name="CarouselDemo" />
## About ## About
The carousel component is built using the [Embla Carousel](https://www.embla-carousel.com/) library. The carousel component is built using the [Embla Carousel](https://www.embla-carousel.com/) library.
## Installation ## Installation
```bash ```bash
npx shadcn-vue@latest add carousel npx shadcn-vue@latest add carousel
``` ```
@ -54,7 +51,6 @@ To set the size of the items, you can use the `basis` utility class on the `<Car
<ComponentPreview name="CarouselSize" /> <ComponentPreview name="CarouselSize" />
Example Example
```vue:line-numbers title="Example" {4-6} ```vue:line-numbers title="Example" {4-6}
@ -68,7 +64,6 @@ Example
</Carousel> </Carousel>
``` ```
Responsive Responsive
```vue:line-numbers title="Responsive" {4-6} ```vue:line-numbers title="Responsive" {4-6}
@ -151,6 +146,10 @@ Use the `orientation` prop to set the orientation of the carousel.
</Carousel> </Carousel>
``` ```
### Thumbnails
<ComponentPreview name="CarouselThumbnails" />
## Options ## Options
You can pass options to the carousel using the `opts` prop. See the [Embla Carousel docs](https://www.embla-carousel.com/api/options/) for more information. You can pass options to the carousel using the `opts` prop. See the [Embla Carousel docs](https://www.embla-carousel.com/api/options/) for more information.
@ -259,7 +258,6 @@ You can use the `plugins` prop to add plugins to the carousel.
npm i embla-carousel-autoplay npm i embla-carousel-autoplay
``` ```
```vue:line-numbers {2,8-10} ```vue:line-numbers {2,8-10}
<script setup lang="ts"> <script setup lang="ts">
import Autoplay from 'embla-carousel-autoplay' import Autoplay from 'embla-carousel-autoplay'

View File

@ -72,7 +72,7 @@ const onSubmit = handleSubmit((values) => {
</option> </option>
</select> </select>
</FormControl> </FormControl>
<ChevronDownIcon class="absolute right-3 top-2.5 h-4 w-4 opacity-50" /> <ChevronDownIcon class="pointer-events-none absolute right-3 top-2.5 h-4 w-4 opacity-50" />
</div> </div>
<FormDescription> <FormDescription>
Set the font you want to use in the dashboard. Set the font you want to use in the dashboard.

View File

@ -17,7 +17,7 @@ import {
} from '@tanstack/vue-table' } from '@tanstack/vue-table'
import { ref } from 'vue' import { ref } from 'vue'
import { type Task } from '../data/schema' import type { Task } from '../data/schema'
import DataTablePagination from './DataTablePagination.vue' import DataTablePagination from './DataTablePagination.vue'
import DataTableToolbar from './DataTableToolbar.vue' import DataTableToolbar from './DataTableToolbar.vue'
import { valueUpdater } from '@/lib/utils' import { valueUpdater } from '@/lib/utils'

View File

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Column } from '@tanstack/vue-table' import type { Column } from '@tanstack/vue-table'
import { type Task } from '../data/schema' import type { Task } from '../data/schema'
import ArrowDownIcon from '~icons/radix-icons/arrow-down' import ArrowDownIcon from '~icons/radix-icons/arrow-down'
import ArrowUpIcon from '~icons/radix-icons/arrow-up' import ArrowUpIcon from '~icons/radix-icons/arrow-up'
import CaretSortIcon from '~icons/radix-icons/caret-sort' import CaretSortIcon from '~icons/radix-icons/caret-sort'

View File

@ -109,7 +109,7 @@ const selectedValues = computed(() => new Set(props.column?.getFilterValue() as
> >
<CheckIcon :class="cn('h-4 w-4')" /> <CheckIcon :class="cn('h-4 w-4')" />
</div> </div>
<option.icon v-if="option.icon" class="mr-2 h-4 w-4 text-muted-foreground" /> <component :is="option.icon" v-if="option.icon" class="mr-2 h-4 w-4 text-muted-foreground" />
<span>{{ option.label }}</span> <span>{{ option.label }}</span>
<span v-if="facets?.get(option.value)" class="ml-auto flex h-4 w-4 items-center justify-center font-mono text-xs"> <span v-if="facets?.get(option.value)" class="ml-auto flex h-4 w-4 items-center justify-center font-mono text-xs">
{{ facets.get(option.value) }} {{ facets.get(option.value) }}

View File

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { type Table } from '@tanstack/vue-table' import type { Table } from '@tanstack/vue-table'
import { type Task } from '../data/schema' import type { Task } from '../data/schema'
import ChevronLeftIcon from '~icons/radix-icons/chevron-left' import ChevronLeftIcon from '~icons/radix-icons/chevron-left'
import ChevronRightIcon from '~icons/radix-icons/chevron-right' import ChevronRightIcon from '~icons/radix-icons/chevron-right'
import DoubleArrowLeftIcon from '~icons/radix-icons/double-arrow-left' import DoubleArrowLeftIcon from '~icons/radix-icons/double-arrow-left'

View File

@ -3,7 +3,7 @@ import type { Row } from '@tanstack/vue-table'
import { computed } from 'vue' import { computed } from 'vue'
import { labels } from '../data/data' import { labels } from '../data/data'
import { taskSchema } from '../data/schema' import { taskSchema } from '../data/schema'
import { type Task } from '../data/schema' import type { Task } from '../data/schema'
import DotsHorizontalIcon from '~icons/radix-icons/dots-horizontal' import DotsHorizontalIcon from '~icons/radix-icons/dots-horizontal'
import { Button } from '@/lib/registry/new-york/ui/button' import { Button } from '@/lib/registry/new-york/ui/button'

View File

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { type Table } from '@tanstack/vue-table' import type { Table } from '@tanstack/vue-table'
import { computed } from 'vue' import { computed } from 'vue'
import { type Task } from '../data/schema' import type { Task } from '../data/schema'
import { priorities, statuses } from '../data/data' import { priorities, statuses } from '../data/data'
import DataTableFacetedFilter from './DataTableFacetedFilter.vue' import DataTableFacetedFilter from './DataTableFacetedFilter.vue'

View File

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import type { Table } from '@tanstack/vue-table' import type { Table } from '@tanstack/vue-table'
import { computed } from 'vue' import { computed } from 'vue'
import { type Task } from '../data/schema' import type { Task } from '../data/schema'
import MixerHorizontalIcon from '~icons/radix-icons/mixer-horizontal' import MixerHorizontalIcon from '~icons/radix-icons/mixer-horizontal'
import { Button } from '@/lib/registry/new-york/ui/button' import { Button } from '@/lib/registry/new-york/ui/button'

View File

@ -11,10 +11,13 @@ import { Badge } from '@/lib/registry/new-york/ui/badge'
export const columns: ColumnDef<Task>[] = [ export const columns: ColumnDef<Task>[] = [
{ {
id: 'select', id: 'select',
header: ({ table }) => h(Checkbox, header: ({ table }) => h(Checkbox, {
{ 'checked': table.getIsAllPageRowsSelected(), 'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value), 'ariaLabel': 'Select all', 'class': 'translate-y-0.5' }), 'checked': table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate'),
cell: ({ row }) => h(Checkbox, 'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value),
{ 'checked': row.getIsSelected(), 'onUpdate:checked': value => row.toggleSelected(!!value), 'ariaLabel': 'Select row', 'class': 'translate-y-0.5' }), 'ariaLabel': 'Select all',
'class': 'translate-y-0.5',
}),
cell: ({ row }) => h(Checkbox, { 'checked': row.getIsSelected(), 'onUpdate:checked': value => row.toggleSelected(!!value), 'ariaLabel': 'Select row', 'class': 'translate-y-0.5' }),
enableSorting: false, enableSorting: false,
enableHiding: false, enableHiding: false,
}, },
@ -33,7 +36,7 @@ export const columns: ColumnDef<Task>[] = [
const label = labels.find(label => label.value === row.original.label) const label = labels.find(label => label.value === row.original.label)
return h('div', { class: 'flex space-x-2' }, [ return h('div', { class: 'flex space-x-2' }, [
label && h(Badge, { variant: 'outline' }, label.label), label ? h(Badge, { variant: 'outline' }, () => label.label) : null,
h('span', { class: 'max-w-[500px] truncate font-medium' }, row.getValue('title')), h('span', { class: 'max-w-[500px] truncate font-medium' }, row.getValue('title')),
]) ])
}, },
@ -72,7 +75,7 @@ export const columns: ColumnDef<Task>[] = [
return h('div', { class: 'flex items-center' }, [ return h('div', { class: 'flex items-center' }, [
priority.icon && h(priority.icon, { class: 'mr-2 h-4 w-4 text-muted-foreground' }), priority.icon && h(priority.icon, { class: 'mr-2 h-4 w-4 text-muted-foreground' }),
h('span', priority.label), h('span', {}, priority.label),
]) ])
}, },
filterFn: (row, id, value) => { filterFn: (row, id, value) => {

View File

@ -81,7 +81,7 @@ const columns: ColumnDef<Payment>[] = [
{ {
id: 'select', id: 'select',
header: ({ table }) => h(Checkbox, { header: ({ table }) => h(Checkbox, {
'checked': table.getIsAllPageRowsSelected(), 'checked': table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate'),
'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value), 'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value),
'ariaLabel': 'Select all', 'ariaLabel': 'Select all',
}), }),

View File

@ -0,0 +1,72 @@
<script setup lang="ts">
import { ref } from 'vue'
import { watchOnce } from '@vueuse/core'
import { Carousel, type CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from '@/lib/registry/default/ui/carousel'
import { Card, CardContent } from '@/lib/registry/default/ui/card'
const emblaMainApi = ref<CarouselApi>()
const emblaThumbnailApi = ref<CarouselApi>()
const selectedIndex = ref(0)
function onSelect() {
if (!emblaMainApi.value || !emblaThumbnailApi.value)
return
selectedIndex.value = emblaMainApi.value.selectedScrollSnap()
emblaThumbnailApi.value.scrollTo(emblaMainApi.value.selectedScrollSnap())
}
function onThumbClick(index: number) {
if (!emblaMainApi.value || !emblaThumbnailApi.value)
return
emblaMainApi.value.scrollTo(index)
}
watchOnce(emblaMainApi, (emblaMainApi) => {
if (!emblaMainApi)
return
onSelect()
emblaMainApi.on('select', onSelect)
emblaMainApi.on('reInit', onSelect)
})
</script>
<template>
<div class="w-full sm:w-auto">
<Carousel
class="relative w-full max-w-xs"
@init-api="(val) => emblaMainApi = val"
>
<CarouselContent>
<CarouselItem v-for="(_, index) in 10" :key="index">
<div class="p-1">
<Card>
<CardContent class="flex aspect-square items-center justify-center p-6">
<span class="text-4xl font-semibold">{{ index + 1 }}</span>
</CardContent>
</Card>
</div>
</CarouselItem>
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
<Carousel
class="relative w-full max-w-xs"
@init-api="(val) => emblaThumbnailApi = val"
>
<CarouselContent class="flex gap-1 ml-0">
<CarouselItem v-for="(_, index) in 10" :key="index" class="pl-0 basis-1/4 cursor-pointer" @click="onThumbClick(index)">
<div class="p-1" :class="index === selectedIndex ? '' : 'opacity-50'">
<Card>
<CardContent class="flex aspect-square items-center justify-center p-6">
<span class="text-4xl font-semibold">{{ index + 1 }}</span>
</CardContent>
</Card>
</div>
</CarouselItem>
</CarouselContent>
</Carousel>
</div>
</template>

View File

@ -84,11 +84,11 @@ const columns = [
columnHelper.display({ columnHelper.display({
id: 'select', id: 'select',
header: ({ table }) => h(Checkbox, { header: ({ table }) => h(Checkbox, {
'checked': table.getIsAllPageRowsSelected(), 'checked': table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate'),
'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value), 'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value),
'ariaLabel': 'Select all', 'ariaLabel': 'Select all',
}), }),
cell: ({ row, column }) => { cell: ({ row }) => {
return h(Checkbox, { return h(Checkbox, {
'checked': row.getIsSelected(), 'checked': row.getIsSelected(),
'onUpdate:checked': value => row.toggleSelected(!!value), 'onUpdate:checked': value => row.toggleSelected(!!value),
@ -165,8 +165,6 @@ const table = useVueTable({
}, },
}, },
}) })
const getState = table.getState()
</script> </script>
<template> <template>

View File

@ -80,7 +80,7 @@ const columns: ColumnDef<Payment>[] = [
{ {
id: 'select', id: 'select',
header: ({ table }) => h(Checkbox, { header: ({ table }) => h(Checkbox, {
'checked': table.getIsAllPageRowsSelected(), 'checked': table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate'),
'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value), 'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value),
'ariaLabel': 'Select all', 'ariaLabel': 'Select all',
}), }),

View File

@ -6,7 +6,7 @@ import * as z from 'zod'
import { import {
PinInput, PinInput,
PinInputInput, PinInputInput,
} from '@/lib/registry/new-york/ui/pin-input' } from '@/lib/registry/default/ui/pin-input'
import { Button } from '@/lib/registry/default/ui/button' import { Button } from '@/lib/registry/default/ui/button'
import { import {
FormControl, FormControl,

View File

@ -24,6 +24,9 @@ const formSchema = toTypedSchema(z.object({
const { handleSubmit } = useForm({ const { handleSubmit } = useForm({
validationSchema: formSchema, validationSchema: formSchema,
initialValues: {
duration: [30],
},
}) })
const onSubmit = handleSubmit((values) => { const onSubmit = handleSubmit((values) => {
@ -36,20 +39,20 @@ const onSubmit = handleSubmit((values) => {
<template> <template>
<form class="w-2/3 space-y-6" @submit="onSubmit"> <form class="w-2/3 space-y-6" @submit="onSubmit">
<FormField v-slot="{ componentField }" name="duration"> <FormField v-slot="{ componentField, value }" name="duration">
<FormItem> <FormItem>
<FormLabel>Duration</FormLabel> <FormLabel>Duration</FormLabel>
<FormControl> <FormControl>
<Slider <Slider
v-bind="componentField" v-bind="componentField"
:default-value="[30]" :default-value="[30]"
:max="60" :max="100"
:min="5" :min="0"
:step="5" :step="5"
/> />
<FormDescription class="flex justify-between"> <FormDescription class="flex justify-between">
<span>How many minutes are you available?</span> <span>How many minutes are you available?</span>
<span>{{ componentField.modelValue?.[0] ?? "30" }} min</span> <span>{{ value?.[0] }} min</span>
</FormDescription> </FormDescription>
</FormControl> </FormControl>
<FormMessage /> <FormMessage />

View File

@ -81,7 +81,7 @@ const columns: ColumnDef<Payment>[] = [
{ {
id: 'select', id: 'select',
header: ({ table }) => h(Checkbox, { header: ({ table }) => h(Checkbox, {
'checked': table.getIsAllPageRowsSelected(), 'checked': table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate'),
'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value), 'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value),
'ariaLabel': 'Select all', 'ariaLabel': 'Select all',
}), }),
@ -104,7 +104,7 @@ const columns: ColumnDef<Payment>[] = [
return h(Button, { return h(Button, {
variant: 'ghost', variant: 'ghost',
onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'), onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'),
}, ['Email', h(CaretSortIcon, { class: 'ml-2 h-4 w-4' })]) }, () => ['Email', h(CaretSortIcon, { class: 'ml-2 h-4 w-4' })])
}, },
cell: ({ row }) => h('div', { class: 'lowercase' }, row.getValue('email')), cell: ({ row }) => h('div', { class: 'lowercase' }, row.getValue('email')),
}, },

View File

@ -0,0 +1,72 @@
<script setup lang="ts">
import { ref } from 'vue'
import { watchOnce } from '@vueuse/core'
import { Carousel, type CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from '@/lib/registry/new-york/ui/carousel'
import { Card, CardContent } from '@/lib/registry/new-york/ui/card'
const emblaMainApi = ref<CarouselApi>()
const emblaThumbnailApi = ref<CarouselApi>()
const selectedIndex = ref(0)
function onSelect() {
if (!emblaMainApi.value || !emblaThumbnailApi.value)
return
selectedIndex.value = emblaMainApi.value.selectedScrollSnap()
emblaThumbnailApi.value.scrollTo(emblaMainApi.value.selectedScrollSnap())
}
function onThumbClick(index: number) {
if (!emblaMainApi.value || !emblaThumbnailApi.value)
return
emblaMainApi.value.scrollTo(index)
}
watchOnce(emblaMainApi, (emblaMainApi) => {
if (!emblaMainApi)
return
onSelect()
emblaMainApi.on('select', onSelect)
emblaMainApi.on('reInit', onSelect)
})
</script>
<template>
<div class="w-full sm:w-auto">
<Carousel
class="relative w-full max-w-xs"
@init-api="(val) => emblaMainApi = val"
>
<CarouselContent>
<CarouselItem v-for="(_, index) in 10" :key="index">
<div class="p-1">
<Card>
<CardContent class="flex aspect-square items-center justify-center p-6">
<span class="text-4xl font-semibold">{{ index + 1 }}</span>
</CardContent>
</Card>
</div>
</CarouselItem>
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
<Carousel
class="relative w-full max-w-xs"
@init-api="(val) => emblaThumbnailApi = val"
>
<CarouselContent class="flex gap-1 ml-0">
<CarouselItem v-for="(_, index) in 10" :key="index" class="pl-0 basis-1/4 cursor-pointer" @click="onThumbClick(index)">
<div class="p-1" :class="index === selectedIndex ? '' : 'opacity-50'">
<Card>
<CardContent class="flex aspect-square items-center justify-center p-6">
<span class="text-4xl font-semibold">{{ index + 1 }}</span>
</CardContent>
</Card>
</div>
</CarouselItem>
</CarouselContent>
</Carousel>
</div>
</template>

View File

@ -84,11 +84,11 @@ const columns = [
columnHelper.display({ columnHelper.display({
id: 'select', id: 'select',
header: ({ table }) => h(Checkbox, { header: ({ table }) => h(Checkbox, {
'checked': table.getIsAllPageRowsSelected(), 'checked': table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate'),
'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value), 'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value),
'ariaLabel': 'Select all', 'ariaLabel': 'Select all',
}), }),
cell: ({ row, column }) => { cell: ({ row }) => {
return h(Checkbox, { return h(Checkbox, {
'checked': row.getIsSelected(), 'checked': row.getIsSelected(),
'onUpdate:checked': value => row.toggleSelected(!!value), 'onUpdate:checked': value => row.toggleSelected(!!value),
@ -165,8 +165,6 @@ const table = useVueTable({
}, },
}, },
}) })
const getState = table.getState()
</script> </script>
<template> <template>

View File

@ -80,7 +80,7 @@ const columns: ColumnDef<Payment>[] = [
{ {
id: 'select', id: 'select',
header: ({ table }) => h(Checkbox, { header: ({ table }) => h(Checkbox, {
'checked': table.getIsAllPageRowsSelected(), 'checked': table.getIsAllPageRowsSelected() || (table.getIsSomePageRowsSelected() && 'indeterminate'),
'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value), 'onUpdate:checked': value => table.toggleAllPageRowsSelected(!!value),
'ariaLabel': 'Select all', 'ariaLabel': 'Select all',
}), }),

View File

@ -2,7 +2,7 @@
import { ref } from 'vue' import { ref } from 'vue'
import { Minus, Plus } from 'lucide-vue-next' import { Minus, Plus } from 'lucide-vue-next'
import { VisStackedBar, VisXYContainer } from '@unovis/vue' import { VisStackedBar, VisXYContainer } from '@unovis/vue'
import { Button } from '@/lib/registry/default/ui/button' import { Button } from '@/lib/registry/new-york/ui/button'
import { import {
Drawer, Drawer,
DrawerClose, DrawerClose,
@ -12,7 +12,7 @@ import {
DrawerHeader, DrawerHeader,
DrawerTitle, DrawerTitle,
DrawerTrigger, DrawerTrigger,
} from '@/lib/registry/default/ui/drawer' } from '@/lib/registry/new-york/ui/drawer'
const goal = ref(350) const goal = ref(350)

View File

@ -1,7 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue' import { ref } from 'vue'
import { createReusableTemplate, useMediaQuery } from '@vueuse/core' import { createReusableTemplate, useMediaQuery } from '@vueuse/core'
import { Button } from '@/lib/registry/default/ui/button' import { Button } from '@/lib/registry/new-york/ui/button'
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@ -9,7 +9,7 @@ import {
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from '@/lib/registry/default/ui/dialog' } from '@/lib/registry/new-york/ui/dialog'
import { import {
Drawer, Drawer,
DrawerClose, DrawerClose,
@ -19,9 +19,9 @@ import {
DrawerHeader, DrawerHeader,
DrawerTitle, DrawerTitle,
DrawerTrigger, DrawerTrigger,
} from '@/lib/registry/default/ui/drawer' } from '@/lib/registry/new-york/ui/drawer'
import { Label } from '@/lib/registry/default/ui/label' import { Label } from '@/lib/registry/new-york/ui/label'
import { Input } from '@/lib/registry/default/ui/input' import { Input } from '@/lib/registry/new-york/ui/input'
// Reuse `form` section // Reuse `form` section
const [UseTemplate, GridForm] = createReusableTemplate() const [UseTemplate, GridForm] = createReusableTemplate()

View File

@ -24,6 +24,9 @@ const formSchema = toTypedSchema(z.object({
const { handleSubmit } = useForm({ const { handleSubmit } = useForm({
validationSchema: formSchema, validationSchema: formSchema,
initialValues: {
duration: [30],
},
}) })
const onSubmit = handleSubmit((values) => { const onSubmit = handleSubmit((values) => {
@ -36,20 +39,20 @@ const onSubmit = handleSubmit((values) => {
<template> <template>
<form class="w-2/3 space-y-6" @submit="onSubmit"> <form class="w-2/3 space-y-6" @submit="onSubmit">
<FormField v-slot="{ componentField }" name="duration"> <FormField v-slot="{ componentField, value }" name="duration">
<FormItem> <FormItem>
<FormLabel>Duration</FormLabel> <FormLabel>Duration</FormLabel>
<FormControl> <FormControl>
<Slider <Slider
v-bind="componentField" v-bind="componentField"
:default-value="[30]" :default-value="[30]"
:max="60" :max="100"
:min="5" :min="0"
:step="5" :step="5"
/> />
<FormDescription class="flex justify-between"> <FormDescription class="flex justify-between">
<span>How many minutes are you available?</span> <span>How many minutes are you available?</span>
<span>{{ componentField.modelValue?.[0] ?? "30" }} min</span> <span>{{ value?.[0] }} min</span>
</FormDescription> </FormDescription>
</FormControl> </FormControl>
<FormMessage /> <FormMessage />

View File

@ -103,11 +103,11 @@ const vCalendarSlots = computed(() => {
</template> </template>
<template #nav-prev-button> <template #nav-prev-button>
<ChevronLeft /> <ChevronLeftIcon />
</template> </template>
<template #nav-next-button> <template #nav-next-button>
<ChevronRight /> <ChevronRightIcon />
</template> </template>
</DatePicker> </DatePicker>
</div> </div>

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@ import { type Theme, themes } from './../lib/registry/themes'
import { type Style, styles } from '@/lib/registry/styles' import { type Style, styles } from '@/lib/registry/styles'
interface Config { interface Config {
theme: Theme['name'] theme?: Theme['name']
radius: number radius: number
style: Style style: Style
} }
@ -15,7 +15,6 @@ export const RADII = [0, 0.25, 0.5, 0.75, 1]
export function useConfigStore() { export function useConfigStore() {
const { isDark } = useData() const { isDark } = useData()
const config = useSessionStorage<Config>('config', { const config = useSessionStorage<Config>('config', {
theme: 'zinc',
radius: 0.5, radius: 0.5,
style: styles[0].name, style: styles[0].name,
}) })