feat: better components
This commit is contained in:
76
client/src/lib/ui/daterangepicker/daterangepicker.svelte
Normal file
76
client/src/lib/ui/daterangepicker/daterangepicker.svelte
Normal file
@ -0,0 +1,76 @@
|
||||
<script lang="ts">
|
||||
import CalendarIcon from '@lucide/svelte/icons/calendar';
|
||||
import type { DateRange } from 'bits-ui';
|
||||
import {
|
||||
CalendarDate,
|
||||
DateFormatter,
|
||||
type DateValue,
|
||||
getLocalTimeZone
|
||||
} from '@internationalized/date';
|
||||
import { cn } from '$lib/utils.js';
|
||||
import { buttonVariants } from '$lib/ui/button';
|
||||
import { RangeCalendar } from '$lib/ui/range-calendar';
|
||||
import * as Popover from '$lib/ui/popover';
|
||||
|
||||
let {
|
||||
className,
|
||||
start,
|
||||
end,
|
||||
onchange
|
||||
}: {
|
||||
className?: string;
|
||||
start?: Date;
|
||||
end?: Date;
|
||||
onchange?: (start: Date, end: Date) => void;
|
||||
} = $props();
|
||||
|
||||
let value: DateRange = $state({
|
||||
start: start
|
||||
? new CalendarDate(start.getFullYear(), start.getMonth(), start.getDate())
|
||||
: undefined,
|
||||
end: end ? new CalendarDate(end.getFullYear(), end.getMonth(), end.getDate()) : undefined
|
||||
});
|
||||
|
||||
const df = new DateFormatter('en-US', {
|
||||
dateStyle: 'medium'
|
||||
});
|
||||
|
||||
let startValue: DateValue | undefined = $state(undefined);
|
||||
</script>
|
||||
|
||||
<div class={cn('grid gap-2', className)}>
|
||||
<Popover.Root>
|
||||
<Popover.Trigger
|
||||
class={cn(buttonVariants({ variant: 'input' }), 'bg-based', !value && 'text-subtext')}
|
||||
>
|
||||
<CalendarIcon class="mr-2 size-4" />
|
||||
{#if value && value.start}
|
||||
{#if value.end}
|
||||
{df.format(value.start.toDate(getLocalTimeZone()))} - {df.format(
|
||||
value.end.toDate(getLocalTimeZone())
|
||||
)}
|
||||
{:else}
|
||||
{df.format(value.start.toDate(getLocalTimeZone()))}
|
||||
{/if}
|
||||
{:else if startValue}
|
||||
{df.format(startValue.toDate(getLocalTimeZone()))}
|
||||
{:else}
|
||||
Pick a date range
|
||||
{/if}
|
||||
</Popover.Trigger>
|
||||
<Popover.Content class="w-auto p-0 bg-based" align="start">
|
||||
<RangeCalendar
|
||||
bind:value
|
||||
onStartValueChange={(v) => {
|
||||
startValue = v;
|
||||
}}
|
||||
onValueChange={(v) => {
|
||||
if (v.start && v.end) {
|
||||
onchange?.(v.start.toDate(getLocalTimeZone()), v.end.toDate(getLocalTimeZone()));
|
||||
}
|
||||
}}
|
||||
numberOfMonths={2}
|
||||
/>
|
||||
</Popover.Content>
|
||||
</Popover.Root>
|
||||
</div>
|
6
client/src/lib/ui/daterangepicker/index.ts
Normal file
6
client/src/lib/ui/daterangepicker/index.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import Root from "./daterangepicker.svelte";
|
||||
|
||||
export {
|
||||
Root,
|
||||
Root as DateRangePicker
|
||||
};
|
Reference in New Issue
Block a user