You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
65 lines
2.6 KiB
65 lines
2.6 KiB
<script lang="ts">
|
|
/**
|
|
* Eidos `<Calendar.MonthSelect>` — month chooser. A NON-MODAL popover whose
|
|
* trigger shows the current month + a chevron and whose content is the reused
|
|
* `MonthGrid` (12 month cells). Picking a month sets the calendar month and
|
|
* closes. Replaces the former native `<select>`; staying non-modal means it
|
|
* also works opened inside the date-picker's own popover (no nested trap).
|
|
*
|
|
* No `value` is passed to the grid — a controlled value would make the grid
|
|
* fire a select on mount and slam the popover shut as it opens.
|
|
*/
|
|
import { CalendarProvider } from '$soma/components/calendar';
|
|
import { ChevronDown } from '$uix/eidos/components/icon';
|
|
import { Button } from '$uix/eidos/components/button';
|
|
import Popover from '../popover';
|
|
import MonthGrid from '../month-grid';
|
|
import type { MonthValue, MonthGridProviderSnippetProps } from '$soma/components/month-grid';
|
|
|
|
const provider = CalendarProvider.require();
|
|
let open = $state(false);
|
|
|
|
const placeholderYear = $derived(provider.opts.placeholder.current.year);
|
|
const placeholderMonth = $derived(provider.opts.placeholder.current.month);
|
|
// Abbreviated month (matches the grid) so the trigger stays compact and never
|
|
// grows the header.
|
|
const monthLabel = $derived(
|
|
new Intl.DateTimeFormat(provider.effectiveLocale, { month: 'short' }).format(
|
|
new Date(2000, placeholderMonth - 1, 1)
|
|
)
|
|
);
|
|
const placeholder = $derived<MonthValue>({ year: placeholderYear, month: placeholderMonth });
|
|
// Highlight the viewed month with the SELECTED style (filled), like the grid.
|
|
const value = $derived<MonthValue>({ year: placeholderYear, month: placeholderMonth });
|
|
|
|
function onValueChange(next: MonthValue | undefined): void {
|
|
if (!next) return;
|
|
provider.setMonth(next.month);
|
|
open = false;
|
|
}
|
|
</script>
|
|
|
|
<Popover bind:open modal={false}>
|
|
<Popover.Trigger data-calendar-month-select>
|
|
{#snippet child({ props }: { props: Record<string, unknown> })}
|
|
<Button {...props} variant="ghost" size="sm">
|
|
<span data-calendar-select-label>{monthLabel}</span>
|
|
<ChevronDown data-calendar-select-chevron aria-hidden="true" />
|
|
</Button>
|
|
{/snippet}
|
|
</Popover.Trigger>
|
|
<Popover.Portal>
|
|
<Popover.Content data-calendar-select-popover>
|
|
<MonthGrid {placeholder} {value} locale={provider.effectiveLocale} {onValueChange}>
|
|
{#snippet children({ months }: MonthGridProviderSnippetProps)}
|
|
<MonthGrid.Grid>
|
|
{#each months as month (month)}
|
|
<MonthGrid.Cell {month} />
|
|
{/each}
|
|
</MonthGrid.Grid>
|
|
{/snippet}
|
|
</MonthGrid>
|
|
</Popover.Content>
|
|
</Popover.Portal>
|
|
</Popover>
|