diff --git a/packages/bits-ui/src/lib/bits/calendar/calendar.svelte.ts b/packages/bits-ui/src/lib/bits/calendar/calendar.svelte.ts index d9220cef0..a9d1294f4 100644 --- a/packages/bits-ui/src/lib/bits/calendar/calendar.svelte.ts +++ b/packages/bits-ui/src/lib/bits/calendar/calendar.svelte.ts @@ -36,7 +36,7 @@ import { type CalendarParts, } from "$lib/shared/date/calendar-helpers.svelte.js"; import { createFormatter, type Formatter } from "$lib/shared/date/formatter.js"; -import type { Month } from "$lib/shared/date/types.js"; +import type { DateMatcher, Month } from "$lib/shared/date/types.js"; import { isBefore, toDate } from "$lib/shared/date/utils.js"; import { getLocalTimeZone, @@ -64,8 +64,8 @@ type CalendarRootStateProps = WithRefProps< pagedNavigation: boolean; weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6; weekdayFormat: Intl.DateTimeFormatOptions["weekday"]; - isDateDisabled: (date: DateValue) => boolean; - isDateUnavailable: (date: DateValue) => boolean; + isDateDisabled: DateMatcher; + isDateUnavailable: DateMatcher; fixedWeeks: boolean; numberOfMonths: number; locale: string; @@ -73,6 +73,11 @@ type CalendarRootStateProps = WithRefProps< type: "single" | "multiple"; readonly: boolean; disableDaysOutsideMonth: boolean; + /** + * This is strictly used by the `DatePicker` component to close the popover when a date + * is selected. It is not intended to be used by the user. + */ + onDateSelect?: () => void; }> >; @@ -97,6 +102,7 @@ export class CalendarRootState { type: CalendarRootStateProps["type"]; readonly: CalendarRootStateProps["readonly"]; disableDaysOutsideMonth: CalendarRootStateProps["disableDaysOutsideMonth"]; + onDateSelect: CalendarRootStateProps["onDateSelect"]; months: Month[] = $state([]); visibleMonths = $derived.by(() => this.months.map((month) => month.value)); announcer: Announcer; @@ -124,6 +130,7 @@ export class CalendarRootState { this.id = props.id; this.ref = props.ref; this.disableDaysOutsideMonth = props.disableDaysOutsideMonth; + this.onDateSelect = props.onDateSelect; this.announcer = getAnnouncer(); this.formatter = createFormatter(this.locale.value); @@ -382,6 +389,9 @@ export class CalendarRootState { ); } this.value.value = next; + if (next !== undefined) { + this.onDateSelect?.value?.(); + } } } }; diff --git a/packages/bits-ui/src/lib/bits/calendar/types.ts b/packages/bits-ui/src/lib/bits/calendar/types.ts index bff6a1ccd..544085ed4 100644 --- a/packages/bits-ui/src/lib/bits/calendar/types.ts +++ b/packages/bits-ui/src/lib/bits/calendar/types.ts @@ -12,7 +12,7 @@ import type { WithAsChild, Without, } from "$lib/internal/types.js"; -import type { DateMatcher, Month } from "$lib/shared/date/types.js"; +import type { DateMatcher, Month, WeekStartsOn } from "$lib/shared/date/types.js"; import type { DateValue } from "@internationalized/date"; import type { Snippet } from "svelte"; @@ -85,7 +85,7 @@ type CalendarBaseRootPropsWithoutHTML = Omit< * * @defaultValue 0 (Sunday) */ - weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6; + weekStartsOn?: WeekStartsOn; /** * How the string representation of the weekdays provided via the `weekdays` state store diff --git a/packages/bits-ui/src/lib/bits/date-field/date-field.svelte.ts b/packages/bits-ui/src/lib/bits/date-field/date-field.svelte.ts index 6dbe8f32c..b3dfed04d 100644 --- a/packages/bits-ui/src/lib/bits/date-field/date-field.svelte.ts +++ b/packages/bits-ui/src/lib/bits/date-field/date-field.svelte.ts @@ -52,7 +52,7 @@ import { DATE_SEGMENT_PARTS, TIME_SEGMENT_PARTS } from "$lib/shared/date/field/p import { onDestroy, onMount, untrack } from "svelte"; import { createContext } from "$lib/internal/createContext.js"; import { useId } from "$lib/internal/useId.svelte.js"; -import type { Granularity, DateMatcher } from "$lib/shared/date/types.js"; +import type { Granularity, DateMatcher, HourCycle } from "$lib/shared/date/types.js"; import type { DateRangeFieldRootState } from "../date-range-field/date-range-field.svelte.js"; export type DateFieldRootStateProps = WritableBoxedValues<{ @@ -67,7 +67,7 @@ export type DateFieldRootStateProps = WritableBoxedValues<{ disabled: boolean; readonly: boolean; granularity: Granularity | undefined; - hourCycle: 12 | 24 | undefined; + hourCycle: HourCycle | undefined; locale: string; hideTimeZone: boolean; name: string; @@ -600,6 +600,7 @@ class DateFieldInputState { "aria-disabled": getAriaDisabled(this.root.disabled.value), "data-invalid": this.root.isInvalid ? "" : undefined, "data-disabled": getDataDisabled(this.root.disabled.value), + "data-date-field-input": "", }) as const ); } diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-arrow.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-arrow.svelte deleted file mode 100644 index f6f5b1360..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-arrow.svelte +++ /dev/null @@ -1,30 +0,0 @@ - - -{#if asChild} - -{:else} -
-{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-calendar.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-calendar.svelte index 320076dd4..e513edfd1 100644 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-calendar.svelte +++ b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-calendar.svelte @@ -1,41 +1,56 @@ {#if asChild} - + {@render child?.({ props: mergedProps, ...calendarState.snippetProps })} {:else} -
- +
+ {@render children?.(calendarState.snippetProps)}
{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-cell.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-cell.svelte deleted file mode 100644 index e95297d5a..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-cell.svelte +++ /dev/null @@ -1,30 +0,0 @@ - - -{#if asChild} - -{:else} - - - -{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-close.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-close.svelte deleted file mode 100644 index 318be8a50..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-close.svelte +++ /dev/null @@ -1,38 +0,0 @@ - - -{#if asChild} - -{:else} - -{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-content.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-content.svelte index 69992ad75..69cca883e 100644 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-content.svelte +++ b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-content.svelte @@ -1,103 +1,14 @@ -{#if asChild && $open} - -{:else if transition && $open} -
- -
-{:else if inTransition && outTransition && $open} -
- -
-{:else if inTransition && $open} -
- -
-{:else if outTransition && $open} -
- -
-{:else if $open} -
- -
-{/if} + diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-day.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-day.svelte deleted file mode 100644 index 07cad338f..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-day.svelte +++ /dev/null @@ -1,40 +0,0 @@ - - -{#if asChild} - -{:else} -
- - {date.day} - -
-{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-field.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-field.svelte deleted file mode 100644 index f94bd6634..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-field.svelte +++ /dev/null @@ -1,122 +0,0 @@ - - - diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-grid-body.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-grid-body.svelte deleted file mode 100644 index 7d43c8453..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-grid-body.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - -{#if asChild} - -{:else} - - - -{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-grid-head.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-grid-head.svelte deleted file mode 100644 index ce177e54a..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-grid-head.svelte +++ /dev/null @@ -1,23 +0,0 @@ - - -{#if asChild} - -{:else} - - - -{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-grid-row.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-grid-row.svelte deleted file mode 100644 index fe58147bd..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-grid-row.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - -{#if asChild} - -{:else} - - - -{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-grid.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-grid.svelte deleted file mode 100644 index 909fe2b21..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-grid.svelte +++ /dev/null @@ -1,28 +0,0 @@ - - -{#if asChild} - -{:else} - - -
-{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-head-cell.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-head-cell.svelte deleted file mode 100644 index ae0a9319d..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-head-cell.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - -{#if asChild} - -{:else} - - - -{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-header.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-header.svelte deleted file mode 100644 index 6ed8de837..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-header.svelte +++ /dev/null @@ -1,20 +0,0 @@ - - -{#if asChild} - -{:else} -
- -
-{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-heading.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-heading.svelte deleted file mode 100644 index e36b5c5c3..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-heading.svelte +++ /dev/null @@ -1,30 +0,0 @@ - - -{#if asChild} - -{:else} -
- - {$headingValue} - -
-{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-input.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-input.svelte deleted file mode 100644 index 2d3a7a9cb..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-input.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - -{#if asChild} - -{:else} -
- -
-{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-label.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-label.svelte deleted file mode 100644 index d7e696b42..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-label.svelte +++ /dev/null @@ -1,34 +0,0 @@ - - -{#if asChild} - -{:else} - - - -{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-next-button.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-next-button.svelte deleted file mode 100644 index 1cd381d27..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-next-button.svelte +++ /dev/null @@ -1,31 +0,0 @@ - - -{#if asChild} - -{:else} - -{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-prev-button.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-prev-button.svelte deleted file mode 100644 index dcbc18f13..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-prev-button.svelte +++ /dev/null @@ -1,31 +0,0 @@ - - -{#if asChild} - -{:else} - -{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-segment.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-segment.svelte deleted file mode 100644 index 9a75a593e..000000000 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-segment.svelte +++ /dev/null @@ -1,45 +0,0 @@ - - -{#if asChild} - -{:else} -
- -
-{/if} diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-trigger.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-trigger.svelte index c113a0b9b..b71d74d20 100644 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-trigger.svelte +++ b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker-trigger.svelte @@ -1,44 +1,21 @@ -{#if asChild} - -{:else} - -{/if} + diff --git a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker.svelte b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker.svelte index 6a252b5a2..01ab5099f 100644 --- a/packages/bits-ui/src/lib/bits/date-picker/components/date-picker.svelte +++ b/packages/bits-ui/src/lib/bits/date-picker/components/date-picker.svelte @@ -1,172 +1,135 @@ - + + {@render children?.()} + diff --git a/packages/bits-ui/src/lib/bits/date-picker/date-picker.svelte.ts b/packages/bits-ui/src/lib/bits/date-picker/date-picker.svelte.ts new file mode 100644 index 000000000..a9b6cb3d2 --- /dev/null +++ b/packages/bits-ui/src/lib/bits/date-picker/date-picker.svelte.ts @@ -0,0 +1,46 @@ +import type { ReadableBoxedValues, WritableBoxedValues } from "$lib/internal/box.svelte.js"; +import { createContext } from "$lib/internal/createContext.js"; +import type { DateMatcher, Granularity, HourCycle, WeekStartsOn } from "$lib/shared/date/types.js"; +import type { SegmentPart } from "$lib/shared/index.js"; +import type { DateValue } from "@internationalized/date"; + +type DatePickerRootStateProps = WritableBoxedValues<{ + value: DateValue | undefined; + open: boolean; + placeholder: DateValue; +}> & + ReadableBoxedValues<{ + readonlySegments: SegmentPart[]; + isDateUnavailable: DateMatcher; + isDateDisabled: DateMatcher; + minValue: DateValue | undefined; + maxValue: DateValue | undefined; + disabled: boolean; + readonly: boolean; + granularity: Granularity | undefined; + hourCycle: HourCycle | undefined; + locale: string; + hideTimeZone: boolean; + name: string; + required: boolean; + preventDeselect: boolean; + pagedNavigation: boolean; + weekStartsOn: WeekStartsOn; + weekdayFormat: Intl.DateTimeFormatOptions["weekday"]; + fixedWeeks: boolean; + numberOfMonths: number; + calendarLabel: string; + disableDaysOutsideMonth: boolean; + onDateSelect?: () => void; + }>; + +class DatePickerRootState { + constructor(readonly props: DatePickerRootStateProps) {} +} + +export const [setDatePickerRootContext, getDatePickerRootContext] = + createContext("DatePicker.Root"); + +export function useDatePickerRoot(props: DatePickerRootStateProps) { + return setDatePickerRootContext(new DatePickerRootState(props)); +} diff --git a/packages/bits-ui/src/lib/bits/date-picker/index.ts b/packages/bits-ui/src/lib/bits/date-picker/index.ts index f0c9409b7..8a746e0e1 100644 --- a/packages/bits-ui/src/lib/bits/date-picker/index.ts +++ b/packages/bits-ui/src/lib/bits/date-picker/index.ts @@ -1,52 +1,43 @@ -// export { default as Arrow } from "./components/date-picker-arrow.svelte"; -// export { default as Calendar } from "./components/date-picker-calendar.svelte"; -// export { default as Close } from "./components/date-picker-close.svelte"; -// export { default as Content } from "./components/date-picker-content.svelte"; -// export { default as Field } from "./components/date-picker-field.svelte"; -// export { default as Input } from "./components/date-picker-input.svelte"; -// export { default as Label } from "./components/date-picker-label.svelte"; -// export { default as Segment } from "./components/date-picker-segment.svelte"; -// export { default as Trigger } from "./components/date-picker-trigger.svelte"; -// export { default as Root } from "./components/date-picker.svelte"; -// export { default as GridBody } from "./components/date-picker-grid-body.svelte"; -// export { default as GridHead } from "./components/date-picker-grid-head.svelte"; -// export { default as GridRow } from "./components/date-picker-grid-row.svelte"; -// export { default as HeadCell } from "./components/date-picker-head-cell.svelte"; -// export { default as Header } from "./components/date-picker-header.svelte"; -// export { default as Cell } from "./components/date-picker-cell.svelte"; -// export { default as Day } from "./components/date-picker-day.svelte"; -// export { default as Grid } from "./components/date-picker-grid.svelte"; +export { default as Root } from "./components/date-picker.svelte"; +export { default as Calendar } from "./components/date-picker-calendar.svelte"; +export { default as Content } from "./components/date-picker-content.svelte"; +export { default as Trigger } from "./components/date-picker-trigger.svelte"; +export { Arrow } from "$lib/bits/popover/index.js"; +export { default as Close } from "$lib/bits/popover/components/popover-close.svelte"; +export { default as Input } from "$lib/bits/date-field/components/date-field-input.svelte"; +export { default as Label } from "$lib/bits/date-field/components/date-field-label.svelte"; +export { default as Segment } from "$lib/bits/date-field/components/date-field-segment.svelte"; +export { default as GridBody } from "$lib/bits/calendar/components/calendar-grid-body.svelte"; +export { default as GridHead } from "$lib/bits/calendar/components/calendar-grid-head.svelte"; +export { default as GridRow } from "$lib/bits/calendar/components/calendar-grid-row.svelte"; +export { default as Grid } from "$lib/bits/calendar/components/calendar-grid.svelte"; +export { default as HeadCell } from "$lib/bits/calendar/components/calendar-head-cell.svelte"; +export { default as Header } from "$lib/bits/calendar/components/calendar-header.svelte"; +export { default as Heading } from "$lib/bits/calendar/components/calendar-heading.svelte"; +export { default as NextButton } from "$lib/bits/calendar/components/calendar-next-button.svelte"; +export { default as PrevButton } from "$lib/bits/calendar/components/calendar-prev-button.svelte"; +export { default as Cell } from "$lib/bits/calendar/components/calendar-cell.svelte"; +export { default as Day } from "$lib/bits/calendar/components/calendar-day.svelte"; -// export { default as Heading } from "./components/date-picker-heading.svelte"; -// export { default as NextButton } from "./components/date-picker-next-button.svelte"; -// export { default as PrevButton } from "./components/date-picker-prev-button.svelte"; - -// export type { -// DatePickerProps as Props, -// DatePickerLabelProps as LabelProps, -// DatePickerInputProps as InputProps, -// DatePickerSegmentProps as SegmentProps, -// DatePickerArrowProps as ArrowProps, -// DatePickerCloseEvents as CloseEvents, -// DatePickerCloseProps as CloseProps, -// DatePickerContentProps as ContentProps, -// DatePickerTriggerEvents as TriggerEvents, -// DatePickerTriggerProps as TriggerProps, -// DatePickerCalendarEvents as CalendarEvents, -// DatePickerCalendarProps as CalendarProps, -// DatePickerCellProps as CellProps, -// DatePickerDayEvents as DayEvents, -// DatePickerDayProps as DayProps, -// DatePickerGridBodyProps as GridBodyProps, -// DatePickerGridHeadProps as GridHeadProps, -// DatePickerGridProps as GridProps, -// DatePickerGridRowProps as GridRowProps, -// DatePickerHeadCellProps as HeadCellProps, -// DatePickerHeaderProps as HeaderProps, -// DatePickerHeadingProps as HeadingProps, -// DatePickerNextButtonEvents as NextButtonEvents, -// DatePickerNextButtonProps as NextButtonProps, -// DatePickerPrevButtonEvents as PrevButtonEvents, -// DatePickerPrevButtonProps as PrevButtonProps, -// DatePickerSegmentEvents as SegmentEvents, -// } from "./types.js"; +export type { + DatePickerRootProps as RootProps, + DatePickerLabelProps as LabelProps, + DatePickerInputProps as InputProps, + DatePickerSegmentProps as SegmentProps, + DatePickerArrowProps as ArrowProps, + DatePickerCloseProps as CloseProps, + DatePickerContentProps as ContentProps, + DatePickerTriggerProps as TriggerProps, + DatePickerCalendarProps as CalendarProps, + DatePickerCellProps as CellProps, + DatePickerDayProps as DayProps, + DatePickerGridBodyProps as GridBodyProps, + DatePickerGridHeadProps as GridHeadProps, + DatePickerGridProps as GridProps, + DatePickerGridRowProps as GridRowProps, + DatePickerHeadCellProps as HeadCellProps, + DatePickerHeaderProps as HeaderProps, + DatePickerHeadingProps as HeadingProps, + DatePickerNextButtonProps as NextButtonProps, + DatePickerPrevButtonProps as PrevButtonProps, +} from "./types.js"; diff --git a/packages/bits-ui/src/lib/bits/date-picker/types.ts b/packages/bits-ui/src/lib/bits/date-picker/types.ts index d3c8c7852..34b45f4f9 100644 --- a/packages/bits-ui/src/lib/bits/date-picker/types.ts +++ b/packages/bits-ui/src/lib/bits/date-picker/types.ts @@ -1,116 +1,308 @@ -import type { DateValue } from "@internationalized/date"; -import type { CreateDatePickerProps as MeltDatePickerProps } from "@melt-ui/svelte"; import type { - DOMElement, - Expand, - HTMLDivAttributes, - HTMLSpanAttributes, - OmitDates, - OmitFloating, OnChangeFn, -} from "$lib/internal/index.js"; + PrimitiveDivAttributes, + WithAsChild, + Without, +} from "$lib/internal/types.js"; +import type { EditableSegmentPart } from "$lib/shared/date/field/types.js"; +import type { DateMatcher, Granularity, WeekStartsOn } from "$lib/shared/date/types.js"; +import type { CalendarRootSnippetProps } from "$lib/types.js"; +import type { DateValue } from "@internationalized/date"; +import type { Snippet } from "svelte"; + +export type DatePickerRootPropsWithoutHTML = { + /** + * The value of the date picker. + * + * @bindable + */ + value?: DateValue; + + /** + * A callback function called when the value changes. + */ + onValueChange?: OnChangeFn; + + /** + * The placeholder value of the date field. This determines the format + * and what date the field starts at when it is empty. + * @bindable + */ + placeholder?: DateValue; + + /** + * A callback function called when the placeholder value changes. + */ + onPlaceholderChange?: OnChangeFn; + + /** + * The open state of the date picker popover. + * + * @bindable + */ + open?: boolean; + + /** + * A callback function called when the open state changes. + */ + onOpenChange?: OnChangeFn; + + /** + * A function that returns true if the given date is unavailable, + * where if selected, the date field will be marked as invalid. + */ + isDateUnavailable?: DateMatcher; + + /** + * A function that returns true if the given date is disabled, + * which makes the date unable to be selected in the calendar. + */ + isDateDisabled?: DateMatcher; + + /** + * The minimum acceptable date. When provided, the date field + * will be marked as invalid if the user enters a date before this date. + */ + minValue?: DateValue | undefined; + + /** + * The maximum acceptable date. When provided, the date field + * will be marked as invalid if the user enters a date after this date. + */ + maxValue?: DateValue | undefined; + + /** + * If true, the date field will be disabled and users will not be able + * to interact with it. This also disables the hidden input element if + * the date field is used in a form. + * + * @defaultValue false + */ + disabled?: boolean; + + /** + * If true, the date field will be readonly, and users will not be able to + * edit the values of any of the individual segments. + * + * @defaultValue false + */ + readonly?: boolean; + + /** + * An array of segment names that should be readonly. If provided, only the + * segments not in this array will be editable. + */ + readonlySegments?: EditableSegmentPart[]; + + /** + * The format to use for displaying the time in the input. + * If using a 12 hour clock, ensure you also include the `dayPeriod` + * segment in your input to ensure the user can select AM/PM. + * + * @defaultValue the locale's default time format + */ + hourCycle?: 12 | 24; + + /** + * The locale to use for formatting the date field. + * + * @defaultValue 'en' + */ + locale?: string; + + /** + * The granularity of the date field. This determines which + * segments will be includes in the segments array used to + * build the date field. + * + * By default, when a `CalendarDate` value is used, the granularity + * will default to `'day'`, and when a `CalendarDateTime` or `ZonedDateTime` + * value is used, the granularity will default to `'minute'`. + * + * Granularity is only used for visual purposes, and does not impact + * the value of the date field. You can have the same value synced + * between multiple date fields with different granularities and they + * will all contain the same value. + * + * @defaultValue 'day' + */ + granularity?: Granularity; + + /** + * Whether or not to hide the timeZoneName segment from the date field. + * + * @defaultValue false; + */ + hideTimeZone?: boolean; + + /** + * The name to use for the hidden input element of the date field, + * which is used to submit the ISO string value of the date field + * to a server. If not provided, the hidden input element will not + * be rendered. + */ + name?: string; + + /** + * Whether or not the hidden input of the date field requires a value + * to be submitted. + * + * @defaultValue false + */ + required?: boolean; + + /** + * Applicable only when `numberOfMonths` is greater than 1. + * + * Controls whether to use paged navigation for the next and previous buttons in the + * date picker. With paged navigation set to `true`, clicking the next/prev buttons + * changes all months in view. When set to `false`, it shifts the view by a single month. + * + * For example, with `pagedNavigation` set to `true` and 2 months displayed (January and + * February), clicking the next button changes the view to March and April. If `pagedNavigation` + * is `false`, the view shifts to February and March. + * + * @defaultValue false + */ + pagedNavigation?: boolean; + + /** + * The day of the week to start the calendar on, which must + * be a number between 0 and 6, where 0 is Sunday and 6 is + * Saturday. + * + * @defaultValue 0 (Sunday) + */ + weekStartsOn?: WeekStartsOn; + + /** + * How the string representation of the weekdays provided via the `weekdays` state store + * should be formatted. + * + * ```md + * - "long": "Sunday", "Monday", "Tuesday", etc. + * - "short": "Sun", "Mon", "Tue", etc. + * - "narrow": "S", "M", "T", etc. + *``` + * + * @defaultValue "narrow" + * + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#weekday + */ + weekdayFormat?: Intl.DateTimeFormatOptions["weekday"]; + + /** + * Display 6 weeks per month, regardless the month's number of weeks. + * This is useful for displaying a consistent calendar, where the size + * of the calendar doesn't change month to month. + * + * To display 6 weeks per month, you will need to render out the previous + * and next month's dates in the calendar as well. + * + * @defaultValue false + */ + fixedWeeks?: boolean; + + /** + * Determines the number of months to display on the calendar simultaneously. + * For navigation between months, refer to the `pagedNavigation` prop. + * + * @defaultValue 1 + */ + numberOfMonths?: number; + + /** + * This label is exclusively used for accessibility, remaining hidden from the page. + * It's read by screen readers when the calendar is opened. The current month and year + * are automatically appended to the label, so you only need to provide the base label. + * + * For instance: + * - 'Date of birth' will be read as 'Date of birth, January 2021' if the current month is January 2021. + * - 'Appointment date' will be read as 'Appointment date, January 2021' if the current month is January 2021. + * - 'Booking date' will be read as 'Booking date, January 2021' if the current month is January 2021. + */ + calendarLabel?: string; + + /** + * Whether to disable the selection of days outside the current month. By default, + * days outside the current month are rendered to fill the calendar grid, but they + * are not selectable. Setting this prop to `true` will disable this behavior. + * + * @defaultValue false + */ + disableDaysOutsideMonth?: boolean; + + /** + * Whether or not users can deselect a date once selected + * without selecting another date. + * + * @defaultValue false + */ + preventDeselect?: boolean; + + /** + * Whether to close the popover when a date is selected. + * + * @defaultValue true + */ + closeOnDateSelect?: boolean; + + children?: Snippet; +}; + +export type DatePickerRootProps = DatePickerRootPropsWithoutHTML; -import type { SegmentPart } from "$lib/shared/index.js"; export type { - ArrowProps as DatePickerArrowProps, - CloseEvents as DatePickerCloseEvents, - CloseProps as DatePickerCloseProps, - ContentProps as DatePickerContentProps, - TriggerEvents as DatePickerTriggerEvents, - TriggerProps as DatePickerTriggerProps, -} from "../popover/index.js"; + PopoverTriggerPropsWithoutHTML as DatePickerTriggerPropsWithoutHTML, + PopoverTriggerProps as DatePickerTriggerProps, + PopoverContentPropsWithoutHTML as DatePickerContentPropsWithoutHTML, + PopoverContentProps as DatePickerContentProps, + PopoverArrowPropsWithoutHTML as DatePickerArrowPropsWithoutHTML, + PopoverArrowProps as DatePickerArrowProps, + PopoverClosePropsWithoutHTML as DatePickerClosePropsWithoutHTML, + PopoverCloseProps as DatePickerCloseProps, +} from "$lib/bits/popover/types.js"; + +export type { + DateFieldInputPropsWithoutHTML as DatePickerInputPropsWithoutHTML, + DateFieldInputProps as DatePickerInputProps, + DateFieldLabelPropsWithoutHTML as DatePickerLabelPropsWithoutHTML, + DateFieldLabelProps as DatePickerLabelProps, + DateFieldSegmentPropsWithoutHTML as DatePickerSegmentPropsWithoutHTML, + DateFieldSegmentProps as DatePickerSegmentProps, +} from "$lib/bits/date-field/types.js"; + +export type DatePickerCalendarPropsWithoutHTML = Omit< + WithAsChild<{}, CalendarRootSnippetProps>, + "children" +> & { + children?: Snippet<[CalendarRootSnippetProps]>; +}; + +export type DatePickerCalendarProps = DatePickerCalendarPropsWithoutHTML & + Without; export type { - Events as DatePickerCalendarEvents, - CellProps as DatePickerCellProps, - DayEvents as DatePickerDayEvents, - DayProps as DatePickerDayProps, - GridBodyProps as DatePickerGridBodyProps, - GridHeadProps as DatePickerGridHeadProps, - GridProps as DatePickerGridProps, - GridRowProps as DatePickerGridRowProps, - HeadCellProps as DatePickerHeadCellProps, - HeaderProps as DatePickerHeaderProps, - HeadingProps as DatePickerHeadingProps, - NextButtonEvents as DatePickerNextButtonEvents, - NextButtonProps as DatePickerNextButtonProps, - PrevButtonEvents as DatePickerPrevButtonEvents, - PrevButtonProps as DatePickerPrevButtonProps, -} from "../calendar/index.js"; - -export type { SegmentEvents as DatePickerSegmentEvents } from "../date-field/index.js"; - -export type DatePickerPropsWithoutHTML = Expand< - Omit< - OmitFloating>, - "required" | "name" | "calendarIds" | "dateFieldIds" | "popoverIds" - > & { - /** - * The open state of the popover. - * You can bind this to a boolean value to programmatically control the open state. - * - * @default false - */ - open?: boolean; - - /** - * A callback function called when the open state changes. - */ - onOpenChange?: OnChangeFn; - - /** - * The value of the date field. - * You can bind this to a `DateValue` object to programmatically control the value. - */ - value?: DateValue; - - /** - * A callback function called when the value changes. - */ - onValueChange?: OnChangeFn; - - /** - * The placeholder date used to start the field. - */ - placeholder?: DateValue; - - /** - * A callback function called when the placeholder changes. - */ - onPlaceholderChange?: OnChangeFn; - - /** - * The id of the validation message element which is used to apply the - * appropriate `aria-describedby` attribute to the input. - */ - validationId?: string; - - /** - * The id of the description element which is used to describe the input. - * This is used to apply the appropriate `aria-describedby` attribute to the input. - */ - descriptionId?: string; - } ->; - -export type DatePickerInputPropsWithoutHTML = DOMElement; - -export type DatePickerDescriptionPropsWithoutHTML = DOMElement; - -export type DatePickerLabelPropsWithoutHTML = DOMElement; - -export type DatePickerCalendarPropsWithoutHTML = DOMElement; - -export type DatePickerSegmentPropsWithoutHTML = Expand< - { - part: SegmentPart; - } & DOMElement ->; -// - -export type DatePickerProps = DatePickerPropsWithoutHTML; -export type DatePickerLabelProps = DatePickerLabelPropsWithoutHTML & HTMLSpanAttributes; -export type DatePickerSegmentProps = DatePickerSegmentPropsWithoutHTML & HTMLDivAttributes; -export type DatePickerInputProps = DatePickerInputPropsWithoutHTML & HTMLDivAttributes; -export type DatePickerDescriptionProps = DatePickerDescriptionPropsWithoutHTML & HTMLDivAttributes; -export type DatePickerCalendarProps = DatePickerCalendarPropsWithoutHTML & HTMLDivAttributes; + CalendarCellPropsWithoutHTML as DatePickerCellPropsWithoutHTML, + CalendarCellProps as DatePickerCellProps, + CalendarDayPropsWithoutHTML as DatePickerDayPropsWithoutHTML, + CalendarDayProps as DatePickerDayProps, + CalendarGridPropsWithoutHTML as DatePickerGridPropsWithoutHTML, + CalendarGridProps as DatePickerGridProps, + CalendarGridBodyPropsWithoutHTML as DatePickerGridBodyPropsWithoutHTML, + CalendarGridBodyProps as DatePickerGridBodyProps, + CalendarGridHeadPropsWithoutHTML as DatePickerGridHeadPropsWithoutHTML, + CalendarGridHeadProps as DatePickerGridHeadProps, + CalendarGridRowPropsWithoutHTML as DatePickerGridRowPropsWithoutHTML, + CalendarGridRowProps as DatePickerGridRowProps, + CalendarHeadCellPropsWithoutHTML as DatePickerHeadCellPropsWithoutHTML, + CalendarHeadCellProps as DatePickerHeadCellProps, + CalendarHeaderPropsWithoutHTML as DatePickerHeaderPropsWithoutHTML, + CalendarHeaderProps as DatePickerHeaderProps, + CalendarHeadingPropsWithoutHTML as DatePickerHeadingPropsWithoutHTML, + CalendarHeadingProps as DatePickerHeadingProps, + CalendarNextButtonPropsWithoutHTML as DatePickerNextButtonPropsWithoutHTML, + CalendarNextButtonProps as DatePickerNextButtonProps, + CalendarPrevButtonPropsWithoutHTML as DatePickerPrevButtonPropsWithoutHTML, + CalendarPrevButtonProps as DatePickerPrevButtonProps, +} from "$lib/bits/calendar/types.js"; diff --git a/packages/bits-ui/src/lib/bits/index.ts b/packages/bits-ui/src/lib/bits/index.ts index 2905b49d7..4408dd56c 100644 --- a/packages/bits-ui/src/lib/bits/index.ts +++ b/packages/bits-ui/src/lib/bits/index.ts @@ -11,7 +11,7 @@ export * as Collapsible from "./collapsible/index.js"; export * as Combobox from "./combobox/index.js"; export * as ContextMenu from "./context-menu/index.js"; export * as DateField from "./date-field/index.js"; -// export * as DatePicker from "./date-picker/index.js"; +export * as DatePicker from "./date-picker/index.js"; export * as DateRangeField from "./date-range-field/index.js"; // export * as DateRangePicker from "./date-range-picker/index.js"; export * as Dialog from "./dialog/index.js"; diff --git a/packages/bits-ui/src/lib/bits/menu/components/menu-arrow.svelte b/packages/bits-ui/src/lib/bits/menu/components/menu-arrow.svelte index 6199664b7..f41a96249 100644 --- a/packages/bits-ui/src/lib/bits/menu/components/menu-arrow.svelte +++ b/packages/bits-ui/src/lib/bits/menu/components/menu-arrow.svelte @@ -4,7 +4,7 @@ import { FloatingLayer } from "$lib/bits/utilities/floating-layer/index.js"; import { mergeProps } from "$lib/internal/mergeProps.js"; - let { ref = $bindable(), ...restProps }: ArrowProps = $props(); + let { ref = $bindable(null), ...restProps }: ArrowProps = $props(); const arrowState = useMenuArrow(); diff --git a/packages/bits-ui/src/lib/bits/popover/components/popover-arrow.svelte b/packages/bits-ui/src/lib/bits/popover/components/popover-arrow.svelte index 115f984e5..df0044481 100644 --- a/packages/bits-ui/src/lib/bits/popover/components/popover-arrow.svelte +++ b/packages/bits-ui/src/lib/bits/popover/components/popover-arrow.svelte @@ -2,7 +2,7 @@ import type { ArrowProps } from "../index.js"; import { FloatingLayer } from "$lib/bits/utilities/floating-layer/index.js"; - let { ref = $bindable(), ...restProps }: ArrowProps = $props(); + let { ref = $bindable(null), ...restProps }: ArrowProps = $props(); diff --git a/packages/bits-ui/src/lib/bits/popover/components/popover-content.svelte b/packages/bits-ui/src/lib/bits/popover/components/popover-content.svelte index 159b92367..ef5c32cee 100644 --- a/packages/bits-ui/src/lib/bits/popover/components/popover-content.svelte +++ b/packages/bits-ui/src/lib/bits/popover/components/popover-content.svelte @@ -26,18 +26,26 @@ (v) => (ref = v) ), }); + + const mergedProps = $derived(mergeProps(restProps, contentState.props)) + + $effect(() => { + console.log("open", contentState.root.open.value); + }); { + console.log("interactoutside"); onInteractOutside(e); if (e.defaultPrevented) return; contentState.root.close(); }} onEscapeKeydown={(e) => { + console.log("escape keydown"); // TODO: users should be able to cancel this onEscapeKeydown(e); contentState.root.close(); @@ -50,13 +58,14 @@ }} trapped {loop} + {forceMount} > {#snippet popper({ props })} - {@const mergedProps = mergeProps(restProps, contentState.props, props)} + {@const finalProps = mergeProps(props, mergedProps)} {#if asChild} - {@render child?.({ props: mergedProps })} + {@render child?.({ props: finalProps })} {:else} -
+
{@render children?.()}
{/if} diff --git a/packages/bits-ui/src/lib/bits/popover/popover.svelte.ts b/packages/bits-ui/src/lib/bits/popover/popover.svelte.ts index 5b587117f..d0ec502e7 100644 --- a/packages/bits-ui/src/lib/bits/popover/popover.svelte.ts +++ b/packages/bits-ui/src/lib/bits/popover/popover.svelte.ts @@ -1,5 +1,4 @@ -import { box } from "svelte-toolbelt"; -import type { ReadableBoxedValues, WritableBoxedValues } from "$lib/internal/box.svelte.js"; +import type { WritableBoxedValues } from "$lib/internal/box.svelte.js"; import { useRefById } from "$lib/internal/useRefById.svelte.js"; import { kbd } from "$lib/internal/kbd.js"; import { getAriaExpanded, getDataOpenClosed } from "$lib/internal/attrs.js"; @@ -19,26 +18,26 @@ class PopoverRootState { this.open = props.open; } - toggleOpen() { + toggleOpen = () => { this.open.value = !this.open.value; - } + }; close = () => { if (!this.open.value) return; this.open.value = false; }; - createTrigger(props: PopoverTriggerStateProps) { + createTrigger = (props: PopoverTriggerStateProps) => { return new PopoverTriggerState(props, this); - } + }; - createContent(props: PopoverContentStateProps) { + createContent = (props: PopoverContentStateProps) => { return new PopoverContentState(props, this); - } + }; - createClose(props: PopoverCloseStateProps) { + createClose = (props: PopoverCloseStateProps) => { return new PopoverCloseState(props, this); - } + }; } type PopoverTriggerStateProps = WithRefProps; @@ -72,12 +71,12 @@ class PopoverTriggerState { this.#root.toggleOpen(); }; - #getAriaControls() { + #getAriaControls = () => { if (this.#root.open.value && this.#root.contentNode?.id) { return this.#root.contentNode.id; } return undefined; - } + }; props = $derived.by( () => diff --git a/packages/bits-ui/src/lib/bits/popover/types.ts b/packages/bits-ui/src/lib/bits/popover/types.ts index 85eb21905..89c5b4dcd 100644 --- a/packages/bits-ui/src/lib/bits/popover/types.ts +++ b/packages/bits-ui/src/lib/bits/popover/types.ts @@ -9,7 +9,6 @@ import type { WithAsChild, Without, } from "$lib/internal/index.js"; -import type { CustomEventHandler } from "$lib/index.js"; export type PopoverRootPropsWithoutHTML = { /** @@ -53,10 +52,3 @@ export type PopoverCloseProps = PopoverClosePropsWithoutHTML & export type PopoverArrowPropsWithoutHTML = ArrowPropsWithoutHTML; export type PopoverArrowProps = ArrowProps; - -export type PopoverTriggerEvents = { - click: CustomEventHandler; - keydown: CustomEventHandler; -}; - -export type PopoverCloseEvents = PopoverTriggerEvents; diff --git a/packages/bits-ui/src/lib/bits/utilities/dismissable-layer/dismissable-layer.svelte b/packages/bits-ui/src/lib/bits/utilities/dismissable-layer/dismissable-layer.svelte index b2ffe9183..34dde0b69 100644 --- a/packages/bits-ui/src/lib/bits/utilities/dismissable-layer/dismissable-layer.svelte +++ b/packages/bits-ui/src/lib/bits/utilities/dismissable-layer/dismissable-layer.svelte @@ -22,6 +22,10 @@ enabled: box.with(() => enabled), onFocusOutside: box.with(() => onFocusOutside), }); + + $effect(() => { + console.log("dismissable layer enabled", enabled); + }); {@render children?.({ props: dismissableLayerState.props })} diff --git a/packages/bits-ui/src/lib/shared/date/calendar-helpers.svelte.ts b/packages/bits-ui/src/lib/shared/date/calendar-helpers.svelte.ts index 940fe2c5a..06abb9aca 100644 --- a/packages/bits-ui/src/lib/shared/date/calendar-helpers.svelte.ts +++ b/packages/bits-ui/src/lib/shared/date/calendar-helpers.svelte.ts @@ -723,3 +723,11 @@ export function getCalendarBitsAttr( const prefix = isRange ? "data-range-calendar-" : "data-calendar-"; return `${prefix}${part}`; } + +export function pickerOpenFocus(e: Event) { + const nodeToFocus = document.querySelector("[data-bits-day][data-focused]"); + if (nodeToFocus) { + e.preventDefault(); + nodeToFocus?.focus(); + } +} diff --git a/packages/bits-ui/src/lib/shared/date/types.ts b/packages/bits-ui/src/lib/shared/date/types.ts index c4b135932..fdffa7a68 100644 --- a/packages/bits-ui/src/lib/shared/date/types.ts +++ b/packages/bits-ui/src/lib/shared/date/types.ts @@ -1,6 +1,8 @@ import type { DateValue } from "@internationalized/date"; export type Granularity = "day" | "hour" | "minute" | "second"; +export type HourCycle = 12 | 24; +export type WeekStartsOn = 0 | 1 | 2 | 3 | 4 | 5 | 6; // Days of the week, starting with Sunday const daysOfWeek = [0, 1, 2, 3, 4, 5, 6] as const; diff --git a/packages/bits-ui/src/tests/popover/Popover.spec.ts b/packages/bits-ui/src/tests/popover/Popover.spec.ts index 861db936c..b96949db3 100644 --- a/packages/bits-ui/src/tests/popover/Popover.spec.ts +++ b/packages/bits-ui/src/tests/popover/Popover.spec.ts @@ -2,14 +2,14 @@ import { render, waitFor } from "@testing-library/svelte/svelte5"; import { userEvent } from "@testing-library/user-event"; import { axe } from "jest-axe"; import { describe, it } from "vitest"; -import { getTestKbd } from "../utils.js"; +import { getTestKbd, setupUserEvents } from "../utils.js"; import PopoverTest, { type PopoverTestProps } from "./PopoverTest.svelte"; import { sleep } from "$lib/internal/sleep.js"; const kbd = getTestKbd(); function setup(props: PopoverTestProps = {}) { - const user = userEvent.setup({ pointerEventsCheck: 0 }); + const user = setupUserEvents(); const returned = render(PopoverTest, { ...props }); const { getByTestId } = returned; const trigger = getByTestId("trigger"); @@ -67,9 +67,7 @@ describe("popover", () => { it("closes on outside click by default", async () => { const { user, queryByTestId, getByTestId } = await open(); const outside = getByTestId("outside"); - await sleep(100); await user.click(outside); - await sleep(100); expect(queryByTestId("content")).toBeNull(); }); diff --git a/sites/docs/content/components/calendar.md b/sites/docs/content/components/calendar.md index 300a85557..6d8202595 100644 --- a/sites/docs/content/components/calendar.md +++ b/sites/docs/content/components/calendar.md @@ -21,37 +21,39 @@ description: Displays dates and days of the week, facilitating date-related inte import { Calendar } from "bits-ui"; - - - - - - - - {#each months as month} - - - - {#each weekdays as day} - - {day} - - {/each} - - - - {#each month.weeks as weekDates} + + {#snippet children({ months, weekdays })} + + + + + + + {#each months as month} + + - {#each weekDates as date} - - - + {#each weekdays as day} + + {day} + {/each} - {/each} - - - {/each} + + + {#each month.weeks as weekDates} + + {#each weekDates as date} + + + + {/each} + + {/each} + + + {/each} + {/snippet} ``` diff --git a/sites/docs/content/components/date-field.md b/sites/docs/content/components/date-field.md index 1dc8c020d..a32671ecd 100644 --- a/sites/docs/content/components/date-field.md +++ b/sites/docs/content/components/date-field.md @@ -25,12 +25,14 @@ description: Enables users to input specific dates within a designated field. Check-in date - - {#each segments as { part, value }} - - {value} - - {/each} + + {#snippet children({ segments })} + {#each segments as { part, value }} + + {value} + + {/each} + {/snippet} ``` diff --git a/sites/docs/content/components/date-picker.md b/sites/docs/content/components/date-picker.md index 54f77fba3..d06a70d8a 100644 --- a/sites/docs/content/components/date-picker.md +++ b/sites/docs/content/components/date-picker.md @@ -23,45 +23,49 @@ description: Facilitates the selection of dates through an input and calendar-ba - - {#each segments as { part, value }} - - {value} - - {/each} + + {#snippet children({ segments })} + {#each segments as { part, value }} + + {value} + + {/each} + {/snippet} - - - - - - - {#each months as month} - - - - {#each weekdays as day} - - {day} - - {/each} - - - - {#each month.weeks as weekDates} + + {#snippet children({ months, weekdays })} + + + + + + {#each months as month} + + - {#each weekDates as date} - - - + {#each weekdays as day} + + {day} + {/each} - {/each} - - - {/each} + + + {#each month.weeks as weekDates} + + {#each weekDates as date} + + + + {/each} + + {/each} + + + {/each} + {/snippet} diff --git a/sites/docs/content/components/date-range-field.md b/sites/docs/content/components/date-range-field.md index 072c3334a..a8131981e 100644 --- a/sites/docs/content/components/date-range-field.md +++ b/sites/docs/content/components/date-range-field.md @@ -21,16 +21,20 @@ description: Allows users to input a range of dates within a designated field. import { DateField } from "$lib"; - - Check-in date - - {#each segments as { part, value }} - - {value} - - {/each} - - + + Check-in date + {#each ["start", "end"] as const as type} + + {#snippet children({ segments })} + {#each segments as { part, value }} + + {value} + + {/each} + {/snippet} + + {/each} + ``` diff --git a/sites/docs/content/components/range-calendar.md b/sites/docs/content/components/range-calendar.md index ae951cf9f..c5d2192c5 100644 --- a/sites/docs/content/components/range-calendar.md +++ b/sites/docs/content/components/range-calendar.md @@ -21,36 +21,38 @@ description: Presents a calendar view tailored for selecting date ranges. import { RangeCalendar } from "bits-ui"; - - - - - - - {#each months as month} - - - - {#each weekdays as day} - - {day} - - {/each} - - - - {#each month.weeks as weekDates} + + {#snippet children({ months, weekdays })} + + + + + + {#each months as month} + + - {#each weekDates as date} - - - + {#each weekdays as day} + + {day} + {/each} - {/each} - - - {/each} + + + {#each month.weeks as weekDates} + + {#each weekDates as date} + + + + {/each} + + {/each} + + + {/each} + {/snippet} ``` diff --git a/sites/docs/src/lib/components/demos/date-picker-demo.svelte b/sites/docs/src/lib/components/demos/date-picker-demo.svelte index ed820f90a..5d2a8d57f 100644 --- a/sites/docs/src/lib/components/demos/date-picker-demo.svelte +++ b/sites/docs/src/lib/components/demos/date-picker-demo.svelte @@ -1,103 +1,97 @@ - + diff --git a/sites/docs/src/lib/components/icons/index.ts b/sites/docs/src/lib/components/icons/index.ts index 99939e1f2..303252e7c 100644 --- a/sites/docs/src/lib/components/icons/index.ts +++ b/sites/docs/src/lib/components/icons/index.ts @@ -1,5 +1,4 @@ import type { HTMLAttributes } from "svelte/elements"; - export { default as GitHub } from "./github.svelte"; export { default as Xcom } from "./x-com.svelte"; export { default as Tailwind } from "./tailwind.svelte";