
3D Extruded Buildings & Urban Footprints
Real-world 3D building extrusions with dynamic sunlight shadows, terrain DEM elevations, and pitch/bearing camera controls.
calendaruiSingle-month calendar grid for date selection (reka-ui + @internationalized/date). Use inline or in a custom popover. For form fields, use Date Picker. Supports min/max, disabled dates, multi-month, and locale.
Also available for React ->Calendar is the always-visible month grid. Date Picker is the form field with popover. Range Calendar manages multi-month spans, and Event Calendar is the multi-view scheduling engine.
| Component | Role | Use when |
|---|---|---|
| Calendarcurrent Embedded dashboard views or scheduling pages where the month grid stays continuously visible. | Grid Primitive | |
| RangeCalendar Contiguous multi-month booking ranges, check-in / check-out spans, and date windows. | Range Primitive | |
| DatePicker Forms, filter bars, and dialogs where space is tight and the calendar opens inside a popover. | Form Control | |
| EventCalendar Full calendar interfaces with month/week/day views, timed hourly intervals, and overlap collision lanes. | Scheduling Engine |
$pnpm dlx shadcn-vue@latest add https://uipkge.dev/r/vue/calendar.json$npx shadcn-vue@latest add https://uipkge.dev/r/vue/calendar.json$yarn dlx shadcn-vue@latest add https://uipkge.dev/r/vue/calendar.json$bunx shadcn-vue@latest add https://uipkge.dev/r/vue/calendar.jsonnpx shadcn-vue@latest add @uipkge/calendarInstalls to:app/components/ui/calendar/Complete scheduling suite composing calendar date navigation, category color-coding, upcoming agenda side-rail, and dynamic modal workflows.
| Name | Type / Values | Default | Required |
|---|---|---|---|
class | HTMLAttributes['class']; layout?: LayoutTypes; yearRange?: DateValue[] | — | optional |
<script lang="ts" setup>
import type { CalendarRootEmits, CalendarRootProps, DateValue } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import type { LayoutTypes } from '.'
import { getLocalTimeZone, today } from '@internationalized/date'
import { createReusableTemplate, reactiveOmit } from '@vueuse/core'
import { CalendarRoot, useDateFormatter, useForwardPropsEmits } from 'reka-ui'
import { createYear, toDate } from 'reka-ui/date'
import { computed, ref, toRaw } from 'vue'
import { ChevronDown } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
import {
CalendarCell,
CalendarCellTrigger,
CalendarGrid,
CalendarGridBody,
CalendarGridHead,
CalendarGridRow,
CalendarHeadCell,
CalendarHeader,
CalendarHeading,
CalendarNextButton,
CalendarPrevButton,
NativeSelect,
NativeSelectOption,
} from '.'
const props = withDefaults(
defineProps<CalendarRootProps & { class?: HTMLAttributes['class']; layout?: LayoutTypes; yearRange?: DateValue[] }>(),
{
modelValue: undefined,
layout: undefined,
},
)
const emits = defineEmits<CalendarRootEmits>()
// Fix: Don't pass defaultValue or defaultPlaceholder to reka-ui to avoid .copy() errors
// Only pass the props that reka-ui needs
const delegatedProps = reactiveOmit(props, ['class', 'layout', 'placeholder', 'defaultValue', 'defaultPlaceholder'])
const forwarded = useForwardPropsEmits(delegatedProps, emits)
const formatter = useDateFormatter(props.locale ?? 'en')
const yearRange = computed(() => {
if (props.yearRange) return props.yearRange
const base = toRaw(props.placeholder) ?? today(getLocalTimeZone())
const start = props?.minValue ?? base.add({ years: -100 })
const end = props?.maxValue ?? base.add({ years: 10 })
const years: DateValue[] = []
let current = start
while (current.compare(end) <= 0) {
years.push(current)
current = current.add({ years: 1 })
}
return years
})
const [DefineMonthTemplate, ReuseMonthTemplate] = createReusableTemplate<{ date: DateValue }>()
const [DefineYearTemplate, ReuseYearTemplate] = createReusableTemplate<{ date: DateValue }>()
// Fix: Use simple ref for placeholder, not useVModel, to avoid .copy() error in reka-ui
const internalPlaceholder = ref(props.placeholder ?? today(getLocalTimeZone()))
function setMonth(e: Event) {
const v = Number((e?.target as HTMLSelectElement | null)?.value)
internalPlaceholder.value = (internalPlaceholder.value as DateValue).set({ month: v })
}
function setYear(e: Event) {
const v = Number((e?.target as HTMLSelectElement | null)?.value)
internalPlaceholder.value = (internalPlaceholder.value as DateValue).set({ year: v })
}
</script>
<template>
<DefineMonthTemplate v-slot="{ date }">
<div class="relative inline-flex items-center">
<select
data-uipkge
data-slot="calendar-month-select"
class="border-input hover:bg-accent/60 text-foreground focus-visible:ring-ring h-8 cursor-pointer appearance-none rounded-md border bg-transparent pr-6 pl-2.5 text-xs font-medium transition-colors focus-visible:ring-1 focus-visible:outline-none"
:value="date.month"
@change="setMonth"
>
<option
v-for="month in createYear({ dateObj: date })"
:key="month.toString()"
:value="month.month"
:selected="date.month === month.month"
class="bg-popover text-popover-foreground"
>
{{ formatter.custom(toDate(month), { month: 'short' }) }}
</option>
</select>
<ChevronDown class="text-muted-foreground pointer-events-none absolute right-1.5 size-3.5 opacity-60" />
</div>
</DefineMonthTemplate>
<DefineYearTemplate v-slot="{ date }">
<div class="relative inline-flex items-center">
<select
data-uipkge
data-slot="calendar-year-select"
class="border-input hover:bg-accent/60 text-foreground focus-visible:ring-ring h-8 cursor-pointer appearance-none rounded-md border bg-transparent pr-6 pl-2.5 text-xs font-medium transition-colors focus-visible:ring-1 focus-visible:outline-none"
:value="date.year"
@change="setYear"
>
<option
v-for="year in yearRange"
:key="year.toString()"
:value="year.year"
:selected="date.year === year.year"
class="bg-popover text-popover-foreground"
>
{{ formatter.custom(toDate(year), { year: 'numeric' }) }}
</option>
</select>
<ChevronDown class="text-muted-foreground pointer-events-none absolute right-1.5 size-3.5 opacity-60" />
</div>
</DefineYearTemplate>
<CalendarRoot
v-slot="{ grid, weekDays, date }"
v-bind="forwarded"
:placeholder="internalPlaceholder as DateValue"
data-uipkge
data-slot="calendar"
:class="cn('p-3', props.class)"
@update:placeholder="
(val) => {
internalPlaceholder = val
}
"
>
<CalendarHeader class="pt-0">
<nav class="absolute inset-x-0 top-0 flex items-center justify-between gap-1">
<CalendarPrevButton>
<slot name="calendar-prev-icon" />
</CalendarPrevButton>
<CalendarNextButton>
<slot name="calendar-next-icon" />
</CalendarNextButton>
</nav>
<slot name="calendar-heading" :date="date" :month="ReuseMonthTemplate" :year="ReuseYearTemplate">
<template v-if="layout === 'month-and-year'">
<div class="flex items-center justify-center gap-1">
<ReuseMonthTemplate :date="date" />
<ReuseYearTemplate :date="date" />
</div>
</template>
<template v-else-if="layout === 'month-only'">
<div class="flex items-center justify-center gap-1">
<ReuseMonthTemplate :date="date" />
{{ formatter.custom(toDate(date), { year: 'numeric' }) }}
</div>
</template>
<template v-else-if="layout === 'year-only'">
<div class="flex items-center justify-center gap-1">
{{ formatter.custom(toDate(date), { month: 'short' }) }}
<ReuseYearTemplate :date="date" />
</div>
</template>
<template v-else>
<CalendarHeading />
</template>
</slot>
</CalendarHeader>
<div class="mt-4 flex flex-col gap-y-4 sm:flex-row sm:gap-x-4 sm:gap-y-0">
<CalendarGrid
v-for="month in grid"
:key="month.value.toString()"
class="motion-safe:animate-[calendar-month-in_220ms_cubic-bezier(0.22,1,0.36,1)_both]"
>
<CalendarGridHead>
<CalendarGridRow>
<CalendarHeadCell v-for="day in weekDays" :key="day">
{{ day }}
</CalendarHeadCell>
</CalendarGridRow>
</CalendarGridHead>
<CalendarGridBody>
<CalendarGridRow v-for="(weekDates, index) in month.rows" :key="`weekDate-${index}`" class="mt-2 w-full">
<CalendarCell v-for="weekDate in weekDates" :key="weekDate.toString()" :date="weekDate">
<CalendarCellTrigger :day="weekDate" :month="month.value">
<slot name="cell" :day="weekDate" :month="month.value">
{{ weekDate.day }}
</slot>
</CalendarCellTrigger>
</CalendarCell>
</CalendarGridRow>
</CalendarGridBody>
</CalendarGrid>
</div>
</CalendarRoot>
</template>
<style>
@keyframes calendar-month-in {
from {
opacity: 0;
transform: translateY(4px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (prefers-reduced-motion: reduce) {
[data-slot='calendar'] [class*='animate-\\[calendar-month'] {
animation: none !important;
}
}
</style>
<script lang="ts" setup>
import type { CalendarCellProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { CalendarCell, useForwardProps } from 'reka-ui'
import { cn } from '@/lib/utils'
const props = defineProps<CalendarCellProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = reactiveOmit(props, 'class')
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<CalendarCell
data-uipkge
data-slot="calendar-cell"
:class="cn('relative flex-1 p-0 text-center text-sm focus-within:relative focus-within:z-20', props.class)"
v-bind="forwardedProps"
>
<slot />
</CalendarCell>
</template>
<script lang="ts" setup>
import type { CalendarCellTriggerProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { CalendarCellTrigger, useForwardProps } from 'reka-ui'
import { cn } from '@/lib/utils'
import { buttonVariants } from '@/components/ui/button'
const props = withDefaults(defineProps<CalendarCellTriggerProps & { class?: HTMLAttributes['class'] }>(), {
as: 'button',
})
const delegatedProps = reactiveOmit(props, 'class')
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<CalendarCellTrigger
data-uipkge
data-slot="calendar-cell-trigger"
:class="
cn(
buttonVariants({ variant: 'ghost' }),
'size-9 cursor-pointer p-0 font-normal transition-[color,background-color,transform,box-shadow] duration-150 aria-selected:opacity-100',
'[&[data-today]:not([data-selected])]:bg-accent [&[data-today]:not([data-selected])]:text-accent-foreground',
// Selected
'data-[selected]:bg-primary data-[selected]:text-primary-foreground data-[selected]:hover:bg-primary data-[selected]:hover:text-primary-foreground data-[selected]:focus:bg-primary data-[selected]:focus:text-primary-foreground data-[selected]:opacity-100 data-[selected]:shadow-sm motion-safe:data-[selected]:animate-[calendar-day-pop_220ms_cubic-bezier(0.22,1.4,0.36,1)_both]',
// Disabled
'data-[disabled]:text-muted-foreground data-[disabled]:opacity-50',
// Unavailable
'data-[unavailable]:text-destructive-foreground data-[unavailable]:line-through',
// Outside months
'data-[outside-view]:text-muted-foreground',
props.class,
)
"
v-bind="forwardedProps"
>
<slot />
</CalendarCellTrigger>
</template>
<style>
@keyframes calendar-day-pop {
0% {
transform: scale(0.86);
}
70% {
transform: scale(1.06);
}
100% {
transform: scale(1);
}
}
@media (prefers-reduced-motion: reduce) {
[data-slot='calendar-cell-trigger'] {
animation: none !important;
transition: none !important;
}
}
</style>
<script lang="ts" setup>
import type { CalendarGridProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { CalendarGrid, useForwardProps } from 'reka-ui'
import { cn } from '@/lib/utils'
const props = defineProps<CalendarGridProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = reactiveOmit(props, 'class')
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<CalendarGrid
data-uipkge
data-slot="calendar-grid"
:class="cn('w-full border-collapse', props.class)"
v-bind="forwardedProps"
>
<slot />
</CalendarGrid>
</template>
<script lang="ts" setup>
import type { CalendarGridBodyProps } from 'reka-ui'
import { CalendarGridBody } from 'reka-ui'
const props = defineProps<CalendarGridBodyProps>()
</script>
<template>
<CalendarGridBody data-uipkge data-slot="calendar-grid-body" v-bind="props">
<slot />
</CalendarGridBody>
</template>
<script lang="ts" setup>
import type { CalendarGridHeadProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { CalendarGridHead } from 'reka-ui'
const props = defineProps<CalendarGridHeadProps & { class?: HTMLAttributes['class'] }>()
</script>
<template>
<CalendarGridHead data-uipkge data-slot="calendar-grid-head" v-bind="props">
<slot />
</CalendarGridHead>
</template>
<script lang="ts" setup>
import type { CalendarGridRowProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { CalendarGridRow, useForwardProps } from 'reka-ui'
import { cn } from '@/lib/utils'
const props = defineProps<CalendarGridRowProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = reactiveOmit(props, 'class')
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<CalendarGridRow data-uipkge data-slot="calendar-grid-row" :class="cn('flex', props.class)" v-bind="forwardedProps">
<slot />
</CalendarGridRow>
</template>
<script lang="ts" setup>
import type { CalendarHeadCellProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { CalendarHeadCell, useForwardProps } from 'reka-ui'
import { cn } from '@/lib/utils'
const props = defineProps<CalendarHeadCellProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = reactiveOmit(props, 'class')
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<CalendarHeadCell
data-uipkge
data-slot="calendar-head-cell"
:class="cn('text-muted-foreground flex-1 rounded-md text-xs font-normal', props.class)"
v-bind="forwardedProps"
>
<slot />
</CalendarHeadCell>
</template>
<script lang="ts" setup>
import type { CalendarHeaderProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { CalendarHeader, useForwardProps } from 'reka-ui'
import { cn } from '@/lib/utils'
const props = defineProps<CalendarHeaderProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = reactiveOmit(props, 'class')
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<CalendarHeader
data-uipkge
data-slot="calendar-header"
:class="cn('relative flex w-full items-center justify-center px-8 pt-1', props.class)"
v-bind="forwardedProps"
>
<slot />
</CalendarHeader>
</template>
<script lang="ts" setup>
import type { CalendarHeadingProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { CalendarHeading, useForwardProps } from 'reka-ui'
import { cn } from '@/lib/utils'
const props = defineProps<CalendarHeadingProps & { class?: HTMLAttributes['class'] }>()
defineSlots<{
default: (props: { headingValue: string }) => any
}>()
const delegatedProps = reactiveOmit(props, 'class')
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<CalendarHeading
v-slot="{ headingValue }"
data-uipkge
data-slot="calendar-heading"
:class="cn('text-sm font-medium', props.class)"
v-bind="forwardedProps"
>
<slot :heading-value>
{{ headingValue }}
</slot>
</CalendarHeading>
</template>
<script lang="ts" setup>
import type { CalendarNextProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { ChevronRight } from 'lucide-vue-next'
import { CalendarNext, useForwardProps } from 'reka-ui'
import { cn } from '@/lib/utils'
import { buttonVariants } from '@/components/ui/button'
const props = defineProps<CalendarNextProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = reactiveOmit(props, 'class')
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<CalendarNext
data-uipkge
data-slot="calendar-next-button"
:class="
cn(
buttonVariants({ variant: 'outline' }),
'size-9 bg-transparent p-0 opacity-70 hover:opacity-100 focus-visible:opacity-100',
props.class,
)
"
v-bind="forwardedProps"
>
<slot>
<ChevronRight class="size-4" aria-hidden="true" />
</slot>
</CalendarNext>
</template>
<script lang="ts" setup>
import type { CalendarPrevProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { ChevronLeft } from 'lucide-vue-next'
import { CalendarPrev, useForwardProps } from 'reka-ui'
import { cn } from '@/lib/utils'
import { buttonVariants } from '@/components/ui/button'
const props = defineProps<CalendarPrevProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = reactiveOmit(props, 'class')
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<CalendarPrev
data-uipkge
data-slot="calendar-prev-button"
:class="
cn(
buttonVariants({ variant: 'outline' }),
'size-9 bg-transparent p-0 opacity-70 hover:opacity-100 focus-visible:opacity-100',
props.class,
)
"
v-bind="forwardedProps"
>
<slot>
<ChevronLeft class="size-4" aria-hidden="true" />
</slot>
</CalendarPrev>
</template>
<script setup lang="ts">
import type { AcceptableValue } from 'reka-ui'
import { computed } from 'vue'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { ChevronDownIcon } from 'lucide-vue-next'
import { cn } from '@/lib/utils'
defineOptions({
inheritAttrs: false,
})
interface Props {
modelValue?: AcceptableValue | AcceptableValue[]
class?: HTMLAttributes['class']
label?: string
placeholder?: string
disabled?: boolean
readonly?: boolean
error?: boolean
errorMessages?: string | string[]
successMessages?: string | string[]
hint?: string
variant?: 'outlined' | 'filled' | 'solo' | 'underlined'
density?: 'compact' | 'default' | 'comfortable'
color?: 'primary' | 'secondary' | 'error' | 'success' | 'warning' | 'info'
hideDetails?: boolean
bgColor?: string
}
const props = withDefaults(defineProps<Props>(), {
modelValue: undefined,
label: '',
placeholder: '',
disabled: false,
readonly: false,
error: false,
errorMessages: () => [],
successMessages: () => [],
hint: '',
variant: 'outlined',
density: 'default',
color: 'primary',
hideDetails: false,
})
const emit = defineEmits<{
'update:modelValue': AcceptableValue
}>()
const modelValue = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
},
})
const delegatedProps = reactiveOmit(
props,
'class',
'label',
'placeholder',
'disabled',
'readonly',
'error',
'errorMessages',
'successMessages',
'hint',
'variant',
'density',
'color',
'hideDetails',
'bgColor',
'modelValue',
)
const hasError = computed(
() => props.error || (Array.isArray(props.errorMessages) ? props.errorMessages.length > 0 : !!props.errorMessages),
)
const hasSuccess = computed(
() =>
!hasError.value &&
(Array.isArray(props.successMessages) ? props.successMessages.length > 0 : !!props.successMessages),
)
const densityClasses = {
compact: 'h-8 text-xs',
default: 'h-9 text-sm',
comfortable: 'h-10 text-base',
}
const variantClasses = {
outlined: 'border bg-transparent',
filled: 'border-b-2 bg-muted/30 border-transparent',
solo: 'border bg-card shadow-md',
underlined: 'border-b bg-transparent rounded-none border-x-0 border-t-0',
}
const stateClasses = computed(() => {
if (hasError.value) return 'border-destructive focus-visible:ring-destructive/20'
if (hasSuccess.value) return 'border-success focus-visible:border-success'
return 'border-input focus-visible:border-ring focus-visible:ring-ring/20 focus-visible:ring-[3px]'
})
</script>
<template>
<div class="relative w-full" :class="densityClasses[density]">
<!-- Label -->
<label v-if="label" class="mb-1 block text-sm font-medium" :class="{ 'text-destructive': hasError }">
{{ label }}
</label>
<!-- Select Wrapper -->
<div class="group/native-select relative w-full" :class="props.class">
<select
v-bind="{ ...$attrs, ...delegatedProps }"
v-model="modelValue"
data-uipkge
data-slot="native-select"
:disabled="disabled"
:readonly="readonly"
:class="
cn(
'border-input placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 dark:hover:bg-input/50',
variantClasses[variant],
stateClasses,
densityClasses[density],
'w-full min-w-0 appearance-none rounded-md border bg-transparent px-3 pr-9 shadow-xs transition-[color,box-shadow] outline-none disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',
bgColor,
)
"
>
<slot />
</select>
<ChevronDownIcon
class="text-muted-foreground pointer-events-none absolute top-1/2 right-3.5 size-4 -translate-y-1/2 opacity-50 select-none"
:class="{
'top-1/2': density === 'default' || density === 'compact' || density === 'comfortable',
}"
aria-hidden="true"
data-uipkge
data-slot="native-select-icon"
/>
</div>
<!-- Details: hint, error, success -->
<div
v-if="!hideDetails"
class="mt-1 text-xs"
:class="{
'text-destructive': hasError,
'text-success': hasSuccess,
'text-muted-foreground': !hasError && !hasSuccess,
}"
>
<template v-if="hasError">
<span v-if="typeof errorMessages === 'string'">{{ errorMessages }}</span>
<span v-else>{{ errorMessages[0] }}</span>
</template>
<template v-else-if="hasSuccess">
<span v-if="typeof successMessages === 'string'">{{ successMessages }}</span>
<span v-else>{{ successMessages[0] }}</span>
</template>
<template v-else>{{ hint }}</template>
</div>
</div>
</template>
<!-- @fallthroughAttributes true -->
<!-- @strictTemplates true -->
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
const props = defineProps<{ class?: HTMLAttributes['class'] }>()
const dataAttrs = { 'data-slot': 'native-select-option' }
</script>
<template>
<option v-bind="dataAttrs" :class="cn('bg-popover text-popover-foreground', props.class)">
<slot />
</option>
</template>
export { default as Calendar } from './Calendar.vue'
export { default as CalendarCell } from './CalendarCell.vue'
export { default as CalendarCellTrigger } from './CalendarCellTrigger.vue'
export { default as CalendarGrid } from './CalendarGrid.vue'
export { default as CalendarGridBody } from './CalendarGridBody.vue'
export { default as CalendarGridHead } from './CalendarGridHead.vue'
export { default as CalendarGridRow } from './CalendarGridRow.vue'
export { default as CalendarHeadCell } from './CalendarHeadCell.vue'
export { default as CalendarHeader } from './CalendarHeader.vue'
export { default as CalendarHeading } from './CalendarHeading.vue'
export { default as CalendarNextButton } from './CalendarNextButton.vue'
export { default as CalendarPrevButton } from './CalendarPrevButton.vue'
export { default as NativeSelect } from './NativeSelect.vue'
export { default as NativeSelectOption } from './NativeSelectOption.vue'
export type LayoutTypes = 'month-and-year' | 'month-only' | 'year-only' | undefined
Raw manifest:https://uipkge.dev/r/vue/calendar.json