updated datepicker dependency
This commit is contained in:
@@ -10,8 +10,9 @@ import {
|
|||||||
fromDate,
|
fromDate,
|
||||||
getLocalTimeZone,
|
getLocalTimeZone,
|
||||||
parseDate,
|
parseDate,
|
||||||
|
today,
|
||||||
} from "@internationalized/date"
|
} from "@internationalized/date"
|
||||||
import type { DateRange } from "reka-ui"
|
import type { DateRange, DateValue } from "reka-ui"
|
||||||
import type { Ref } from "vue"
|
import type { Ref } from "vue"
|
||||||
import Popover from "@/components/ui/popover/Popover.vue";
|
import Popover from "@/components/ui/popover/Popover.vue";
|
||||||
import PopoverTrigger from "@/components/ui/popover/PopoverTrigger.vue";
|
import PopoverTrigger from "@/components/ui/popover/PopoverTrigger.vue";
|
||||||
@@ -84,6 +85,11 @@ onMounted(async () => {
|
|||||||
console.log(currentMember.value);
|
console.log(currentMember.value);
|
||||||
resetForm({ values: { member_id: currentMember.value?.member_id } });
|
resetForm({ values: { member_id: currentMember.value?.member_id } });
|
||||||
});
|
});
|
||||||
|
import type { LayoutTypes } from '@/components/ui/calendar'
|
||||||
|
|
||||||
|
const defaultPlaceholder = today(getLocalTimeZone())
|
||||||
|
const date = ref(today(getLocalTimeZone())) as Ref<DateValue>
|
||||||
|
const layout = ref<LayoutTypes>('month-and-year')
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -175,7 +181,7 @@ onMounted(async () => {
|
|||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent class="w-auto p-0">
|
<PopoverContent class="w-auto p-0">
|
||||||
<Calendar
|
<Calendar
|
||||||
:model-value="field.value ? fromDate(field.value, getLocalTimeZone()) : null"
|
:model-value="field.value ? fromDate(field.value, getLocalTimeZone()) : null"
|
||||||
@update:model-value="(val: CalendarDate) => field.onChange(val.toDate(getLocalTimeZone()))"
|
@update:model-value="(val: CalendarDate) => field.onChange(val.toDate(getLocalTimeZone()))"
|
||||||
layout="month-and-year" />
|
layout="month-and-year" />
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
@@ -204,7 +210,8 @@ onMounted(async () => {
|
|||||||
<Calendar
|
<Calendar
|
||||||
:model-value="field.value ? new CalendarDate(field.value.getFullYear(), field.value.getMonth() + 1, field.value.getDate()) : null"
|
:model-value="field.value ? new CalendarDate(field.value.getFullYear(), field.value.getMonth() + 1, field.value.getDate()) : null"
|
||||||
@update:model-value="(val: CalendarDate) => field.onChange(val.toDate(getLocalTimeZone()))"
|
@update:model-value="(val: CalendarDate) => field.onChange(val.toDate(getLocalTimeZone()))"
|
||||||
layout="month-and-year" />
|
:default-placeholder="defaultPlaceholder" layout="month-and-year">
|
||||||
|
</Calendar>
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
@@ -233,5 +240,11 @@ onMounted(async () => {
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-4 w-min">
|
||||||
|
<Calendar v-model="date" :default-placeholder="defaultPlaceholder" class="rounded-md border shadow-sm"
|
||||||
|
layout="month-and-year" disable-days-outside-current-view />
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -1,7 +1,14 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { reactiveOmit } from "@vueuse/core";
|
import { getLocalTimeZone, today } from "@internationalized/date";
|
||||||
import { CalendarRoot, useForwardPropsEmits } from "reka-ui";
|
import { createReusableTemplate, reactiveOmit, useVModel } from "@vueuse/core";
|
||||||
|
import { CalendarRoot, useDateFormatter, useForwardPropsEmits } from "reka-ui";
|
||||||
|
import { createYear, createYearRange, toDate } from "reka-ui/date";
|
||||||
|
import { computed, toRaw } from "vue";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import {
|
||||||
|
NativeSelect,
|
||||||
|
NativeSelectOption,
|
||||||
|
} from '@/components/ui/native-select';
|
||||||
import {
|
import {
|
||||||
CalendarCell,
|
CalendarCell,
|
||||||
CalendarCellTrigger,
|
CalendarCellTrigger,
|
||||||
@@ -38,34 +45,165 @@ const props = defineProps({
|
|||||||
dir: { type: String, required: false },
|
dir: { type: String, required: false },
|
||||||
nextPage: { type: Function, required: false },
|
nextPage: { type: Function, required: false },
|
||||||
prevPage: { type: Function, required: false },
|
prevPage: { type: Function, required: false },
|
||||||
modelValue: { type: null, required: false },
|
modelValue: { type: null, required: false, default: undefined },
|
||||||
multiple: { type: Boolean, required: false },
|
multiple: { type: Boolean, required: false },
|
||||||
disableDaysOutsideCurrentView: { type: Boolean, required: false },
|
disableDaysOutsideCurrentView: { type: Boolean, required: false },
|
||||||
asChild: { type: Boolean, required: false },
|
asChild: { type: Boolean, required: false },
|
||||||
as: { type: [String, Object, Function], required: false },
|
as: { type: null, required: false },
|
||||||
class: { type: null, required: false },
|
class: { type: null, required: false },
|
||||||
|
layout: { type: null, required: false, default: undefined },
|
||||||
|
yearRange: { type: Array, required: false },
|
||||||
});
|
});
|
||||||
const emits = defineEmits(["update:modelValue", "update:placeholder"]);
|
const emits = defineEmits(["update:modelValue", "update:placeholder"]);
|
||||||
|
|
||||||
const delegatedProps = reactiveOmit(props, "class");
|
const delegatedProps = reactiveOmit(props, "class", "layout", "placeholder");
|
||||||
|
|
||||||
|
const placeholder = useVModel(props, "placeholder", emits, {
|
||||||
|
passive: true,
|
||||||
|
defaultValue: props.defaultPlaceholder ?? today(getLocalTimeZone()),
|
||||||
|
});
|
||||||
|
|
||||||
|
const formatter = useDateFormatter(props.locale ?? "en");
|
||||||
|
|
||||||
|
const yearRange = computed(() => {
|
||||||
|
return (
|
||||||
|
props.yearRange ??
|
||||||
|
createYearRange({
|
||||||
|
start:
|
||||||
|
props?.minValue ??
|
||||||
|
(
|
||||||
|
toRaw(props.placeholder) ??
|
||||||
|
props.defaultPlaceholder ??
|
||||||
|
today(getLocalTimeZone())
|
||||||
|
).cycle("year", -100),
|
||||||
|
|
||||||
|
end:
|
||||||
|
props?.maxValue ??
|
||||||
|
(
|
||||||
|
toRaw(props.placeholder) ??
|
||||||
|
props.defaultPlaceholder ??
|
||||||
|
today(getLocalTimeZone())
|
||||||
|
).cycle("year", 10),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const [DefineMonthTemplate, ReuseMonthTemplate] = createReusableTemplate();
|
||||||
|
const [DefineYearTemplate, ReuseYearTemplate] = createReusableTemplate();
|
||||||
|
|
||||||
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<DefineMonthTemplate v-slot="{ date }">
|
||||||
|
<div class="**:data-[slot=native-select-icon]:right-1">
|
||||||
|
<div class="relative">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 flex h-full items-center text-sm pl-2 pointer-events-none"
|
||||||
|
>
|
||||||
|
{{ formatter.custom(toDate(date), { month: "short" }) }}
|
||||||
|
</div>
|
||||||
|
<NativeSelect
|
||||||
|
class="text-xs h-8 pr-6 pl-2 text-transparent relative"
|
||||||
|
@change="
|
||||||
|
(e) => {
|
||||||
|
placeholder = placeholder.set({
|
||||||
|
month: Number(e?.target?.value),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<NativeSelectOption
|
||||||
|
v-for="month in createYear({ dateObj: date })"
|
||||||
|
:key="month.toString()"
|
||||||
|
:value="month.month"
|
||||||
|
:selected="date.month === month.month"
|
||||||
|
>
|
||||||
|
{{ formatter.custom(toDate(month), { month: "short" }) }}
|
||||||
|
</NativeSelectOption>
|
||||||
|
</NativeSelect>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DefineMonthTemplate>
|
||||||
|
|
||||||
|
<DefineYearTemplate v-slot="{ date }">
|
||||||
|
<div class="**:data-[slot=native-select-icon]:right-1">
|
||||||
|
<div class="relative">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 flex h-full items-center text-sm pl-2 pointer-events-none"
|
||||||
|
>
|
||||||
|
{{ formatter.custom(toDate(date), { year: "numeric" }) }}
|
||||||
|
</div>
|
||||||
|
<NativeSelect
|
||||||
|
class="text-xs h-8 pr-6 pl-2 text-transparent relative"
|
||||||
|
@change="
|
||||||
|
(e) => {
|
||||||
|
placeholder = placeholder.set({
|
||||||
|
year: Number(e?.target?.value),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<NativeSelectOption
|
||||||
|
v-for="year in yearRange"
|
||||||
|
:key="year.toString()"
|
||||||
|
:value="year.year"
|
||||||
|
:selected="date.year === year.year"
|
||||||
|
>
|
||||||
|
{{ formatter.custom(toDate(year), { year: "numeric" }) }}
|
||||||
|
</NativeSelectOption>
|
||||||
|
</NativeSelect>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DefineYearTemplate>
|
||||||
|
|
||||||
<CalendarRoot
|
<CalendarRoot
|
||||||
v-slot="{ grid, weekDays }"
|
v-slot="{ grid, weekDays, date }"
|
||||||
|
v-bind="forwarded"
|
||||||
|
v-model:placeholder="placeholder"
|
||||||
data-slot="calendar"
|
data-slot="calendar"
|
||||||
:class="cn('p-3', props.class)"
|
:class="cn('p-3', props.class)"
|
||||||
v-bind="forwarded"
|
|
||||||
>
|
>
|
||||||
<CalendarHeader>
|
<CalendarHeader class="pt-0">
|
||||||
<CalendarHeading />
|
<nav
|
||||||
|
class="flex items-center gap-1 absolute top-0 inset-x-0 justify-between"
|
||||||
|
>
|
||||||
|
<CalendarPrevButton>
|
||||||
|
<slot name="calendar-prev-icon" />
|
||||||
|
</CalendarPrevButton>
|
||||||
|
<CalendarNextButton>
|
||||||
|
<slot name="calendar-next-icon" />
|
||||||
|
</CalendarNextButton>
|
||||||
|
</nav>
|
||||||
|
|
||||||
<div class="flex items-center gap-1">
|
<slot
|
||||||
<CalendarPrevButton />
|
name="calendar-heading"
|
||||||
<CalendarNextButton />
|
:date="date"
|
||||||
</div>
|
: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>
|
</CalendarHeader>
|
||||||
|
|
||||||
<div class="flex flex-col gap-y-4 mt-4 sm:flex-row sm:gap-x-4 sm:gap-y-0">
|
<div class="flex flex-col gap-y-4 mt-4 sm:flex-row sm:gap-x-4 sm:gap-y-0">
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { cn } from "@/lib/utils";
|
|||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
date: { type: null, required: true },
|
date: { type: null, required: true },
|
||||||
asChild: { type: Boolean, required: false },
|
asChild: { type: Boolean, required: false },
|
||||||
as: { type: [String, Object, Function], required: false },
|
as: { type: null, required: false },
|
||||||
class: { type: null, required: false },
|
class: { type: null, required: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const props = defineProps({
|
|||||||
day: { type: null, required: true },
|
day: { type: null, required: true },
|
||||||
month: { type: null, required: true },
|
month: { type: null, required: true },
|
||||||
asChild: { type: Boolean, required: false },
|
asChild: { type: Boolean, required: false },
|
||||||
as: { type: [String, Object, Function], required: false, default: "button" },
|
as: { type: null, required: false, default: "button" },
|
||||||
class: { type: null, required: false },
|
class: { type: null, required: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { cn } from "@/lib/utils";
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
asChild: { type: Boolean, required: false },
|
asChild: { type: Boolean, required: false },
|
||||||
as: { type: [String, Object, Function], required: false },
|
as: { type: null, required: false },
|
||||||
class: { type: null, required: false },
|
class: { type: null, required: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { CalendarGridBody } from "reka-ui";
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
asChild: { type: Boolean, required: false },
|
asChild: { type: Boolean, required: false },
|
||||||
as: { type: [String, Object, Function], required: false },
|
as: { type: null, required: false },
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { CalendarGridHead } from "reka-ui";
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
asChild: { type: Boolean, required: false },
|
asChild: { type: Boolean, required: false },
|
||||||
as: { type: [String, Object, Function], required: false },
|
as: { type: null, required: false },
|
||||||
class: { type: null, required: false },
|
class: { type: null, required: false },
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { cn } from "@/lib/utils";
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
asChild: { type: Boolean, required: false },
|
asChild: { type: Boolean, required: false },
|
||||||
as: { type: [String, Object, Function], required: false },
|
as: { type: null, required: false },
|
||||||
class: { type: null, required: false },
|
class: { type: null, required: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { cn } from "@/lib/utils";
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
asChild: { type: Boolean, required: false },
|
asChild: { type: Boolean, required: false },
|
||||||
as: { type: [String, Object, Function], required: false },
|
as: { type: null, required: false },
|
||||||
class: { type: null, required: false },
|
class: { type: null, required: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ const forwardedProps = useForwardProps(delegatedProps);
|
|||||||
data-slot="calendar-head-cell"
|
data-slot="calendar-head-cell"
|
||||||
:class="
|
:class="
|
||||||
cn(
|
cn(
|
||||||
'text-muted-foreground rounded-md w-8 font-normal text-[0.8rem]',
|
'text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem]',
|
||||||
props.class,
|
props.class,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { cn } from "@/lib/utils";
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
asChild: { type: Boolean, required: false },
|
asChild: { type: Boolean, required: false },
|
||||||
as: { type: [String, Object, Function], required: false },
|
as: { type: null, required: false },
|
||||||
class: { type: null, required: false },
|
class: { type: null, required: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -18,7 +18,10 @@ const forwardedProps = useForwardProps(delegatedProps);
|
|||||||
<CalendarHeader
|
<CalendarHeader
|
||||||
data-slot="calendar-header"
|
data-slot="calendar-header"
|
||||||
:class="
|
:class="
|
||||||
cn('flex justify-center pt-1 relative items-center w-full', props.class)
|
cn(
|
||||||
|
'flex justify-center pt-1 relative items-center w-full px-8',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
"
|
"
|
||||||
v-bind="forwardedProps"
|
v-bind="forwardedProps"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { cn } from "@/lib/utils";
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
asChild: { type: Boolean, required: false },
|
asChild: { type: Boolean, required: false },
|
||||||
as: { type: [String, Object, Function], required: false },
|
as: { type: null, required: false },
|
||||||
class: { type: null, required: false },
|
class: { type: null, required: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { buttonVariants } from '@/components/ui/button';
|
|||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
nextPage: { type: Function, required: false },
|
nextPage: { type: Function, required: false },
|
||||||
asChild: { type: Boolean, required: false },
|
asChild: { type: Boolean, required: false },
|
||||||
as: { type: [String, Object, Function], required: false },
|
as: { type: null, required: false },
|
||||||
class: { type: null, required: false },
|
class: { type: null, required: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -23,7 +23,6 @@ const forwardedProps = useForwardProps(delegatedProps);
|
|||||||
:class="
|
:class="
|
||||||
cn(
|
cn(
|
||||||
buttonVariants({ variant: 'outline' }),
|
buttonVariants({ variant: 'outline' }),
|
||||||
'absolute right-1',
|
|
||||||
'size-7 bg-transparent p-0 opacity-50 hover:opacity-100',
|
'size-7 bg-transparent p-0 opacity-50 hover:opacity-100',
|
||||||
props.class,
|
props.class,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { buttonVariants } from '@/components/ui/button';
|
|||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
prevPage: { type: Function, required: false },
|
prevPage: { type: Function, required: false },
|
||||||
asChild: { type: Boolean, required: false },
|
asChild: { type: Boolean, required: false },
|
||||||
as: { type: [String, Object, Function], required: false },
|
as: { type: null, required: false },
|
||||||
class: { type: null, required: false },
|
class: { type: null, required: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -23,7 +23,6 @@ const forwardedProps = useForwardProps(delegatedProps);
|
|||||||
:class="
|
:class="
|
||||||
cn(
|
cn(
|
||||||
buttonVariants({ variant: 'outline' }),
|
buttonVariants({ variant: 'outline' }),
|
||||||
'absolute left-1',
|
|
||||||
'size-7 bg-transparent p-0 opacity-50 hover:opacity-100',
|
'size-7 bg-transparent p-0 opacity-50 hover:opacity-100',
|
||||||
props.class,
|
props.class,
|
||||||
)
|
)
|
||||||
|
|||||||
51
ui/src/components/ui/native-select/NativeSelect.vue
Normal file
51
ui/src/components/ui/native-select/NativeSelect.vue
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<script setup>
|
||||||
|
import { reactiveOmit, useVModel } from "@vueuse/core";
|
||||||
|
import { ChevronDownIcon } from "lucide-vue-next";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
inheritAttrs: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: { type: null, required: false },
|
||||||
|
class: { type: null, required: false },
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:modelValue"]);
|
||||||
|
|
||||||
|
const modelValue = useVModel(props, "modelValue", emit, {
|
||||||
|
passive: true,
|
||||||
|
defaultValue: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const delegatedProps = reactiveOmit(props, "class");
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="group/native-select relative w-fit has-[select:disabled]:opacity-50"
|
||||||
|
data-slot="native-select-wrapper"
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
v-bind="{ ...$attrs, ...delegatedProps }"
|
||||||
|
v-model="modelValue"
|
||||||
|
data-slot="native-select"
|
||||||
|
:class="
|
||||||
|
cn(
|
||||||
|
'border-input placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 dark:hover:bg-input/50 h-9 w-full min-w-0 appearance-none rounded-md border bg-transparent px-3 py-2 pr-9 text-sm shadow-xs transition-[color,box-shadow] outline-none disabled:pointer-events-none disabled:cursor-not-allowed',
|
||||||
|
'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
|
||||||
|
'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
|
||||||
|
props.class,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<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"
|
||||||
|
aria-hidden="true"
|
||||||
|
data-slot="native-select-icon"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
19
ui/src/components/ui/native-select/NativeSelectOptGroup.vue
Normal file
19
ui/src/components/ui/native-select/NativeSelectOptGroup.vue
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!-- @fallthroughAttributes true -->
|
||||||
|
<!-- @strictTemplates true -->
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
class: { type: null, required: false },
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<optgroup
|
||||||
|
data-slot="native-select-optgroup"
|
||||||
|
:class="cn('bg-popover text-popover-foreground', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</optgroup>
|
||||||
|
</template>
|
||||||
19
ui/src/components/ui/native-select/NativeSelectOption.vue
Normal file
19
ui/src/components/ui/native-select/NativeSelectOption.vue
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!-- @fallthroughAttributes true -->
|
||||||
|
<!-- @strictTemplates true -->
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
class: { type: null, required: false },
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<option
|
||||||
|
data-slot="native-select-option"
|
||||||
|
:class="cn('bg-popover text-popover-foreground', props.class)"
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</option>
|
||||||
|
</template>
|
||||||
3
ui/src/components/ui/native-select/index.js
Normal file
3
ui/src/components/ui/native-select/index.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export { default as NativeSelect } from "./NativeSelect.vue";
|
||||||
|
export { default as NativeSelectOptGroup } from "./NativeSelectOptGroup.vue";
|
||||||
|
export { default as NativeSelectOption } from "./NativeSelectOption.vue";
|
||||||
Reference in New Issue
Block a user