import { useState } from "react";
import { Text } from "react-native";
import { DatePicker, DateRangePicker, DateTimePicker, type DateRange } from "@/component-lib/date-picker";
import { useKitTheme } from "@/component-lib/shared/native";
import { Section } from "./layout"; // Section and Row: page layout for the demo
const addDays = (days: number) => {
const d = new Date();
d.setHours(0, 0, 0, 0);
d.setDate(d.getDate() + days);
return d;
};
const weekend = (date: Date) => date.getDay() === 0 || date.getDay() === 6;
export function DatePickerDemo() {
const { tokens } = useKitTheme();
const [single, setSingle] = useState<Date | null>(null);
const [range, setRange] = useState<DateRange>({ start: null, end: null });
const [moment, setMoment] = useState<Date | null>(null);
const note = { color: tokens.muted, fontSize: tokens.fontSize - 2 };
return (
<>
<Section title="DatePicker · locales">
<DatePicker
label="Invoice date (en-IN, week starts Sunday)"
locale="en-IN"
value={single}
onChange={setSingle}
description="Tap to open the calendar; swipe sideways to change month."
/>
<Text style={note}>Value: {single ? single.toDateString() : "none"}</Text>
<DatePicker label="تاريخ الفاتورة (ar-EG, Saturday start)" locale="ar-EG" defaultValue={new Date()} />
<DatePicker label="Rechnungsdatum (de-DE, Monday start)" locale="de-DE" showWeekNumbers />
</Section>
<Section title="DatePicker · limits and errors">
<DatePicker
label="Delivery (next 30 days, weekdays only)"
locale="en-IN"
min={addDays(1)}
max={addDays(30)}
isDateDisabled={weekend}
/>
<DatePicker label="Date of birth" required error="Enter your date of birth." locale="en-IN" />
<DatePicker label="Locked" locale="en-IN" defaultValue={new Date()} readOnly />
<DatePicker label="Disabled" locale="en-IN" disabled />
</Section>
<Section title="DateRangePicker">
<DateRangePicker
label="Stay"
locale="en-IN"
value={range}
onChange={(next) => setRange(next)}
min={addDays(0)}
presets={[
{ label: "This weekend", range: { start: addDays(6 - new Date().getDay()), end: addDays(7 - new Date().getDay()) } },
{ label: "Next 7 days", range: { start: addDays(0), end: addDays(6) } },
{ label: "Next 30 days", range: { start: addDays(0), end: addDays(29) } },
]}
/>
<Text style={note}>
Range: {range.start?.toDateString() ?? "–"} → {range.end?.toDateString() ?? "–"}
</Text>
</Section>
<Section title="DateTimePicker">
<DateTimePicker
label="Meeting (12-hour, 15-minute steps)"
locale="en-IN"
hourCycle={12}
minuteStep={15}
defaultTime="09:00"
value={moment}
onChange={setMoment}
/>
<Text style={note}>Value: {moment ? moment.toString() : "none"}</Text>
<DateTimePicker label="Abfahrt (24-hour, seconds)" locale="de-DE" showSeconds />
<DateTimePicker label="موعد (ar-EG)" locale="ar-EG" />
</Section>
</>
);
}Install
npx @grampro/kit@native add DatePickerUsage
import { DatePicker, DateRangePicker, DateTimePicker } from "@/component-lib/date-picker";
<DatePicker label="Due date" locale="en-IN" min={new Date()} onChange={setDue} />
<DateTimePicker label="Reminder" hourCycle={12} minuteStep={15} />Props
DatePickerProps
| Prop | Type | Description |
|---|---|---|
value | DateInput | null | |
defaultValue | DateInput | null | |
onChange | (date: Date | null) => void | The chosen day as a Date at local midnight, or null once cleared. |
closeOnSelect | boolean | Close the calendar after choosing a date. Default true. |
min | DateInput | null | |
max | DateInput | null | |
isDateDisabled | (date: Date) => boolean | |
locale | string | BCP-47 tag for month names, digits and the first day of the week. |
weekStartsOn | number | 0 = Sunday. Defaults to the locale's first day of the week. |
format | DateFormat | |
numberOfMonths | number | Months shown, stacked. Default 1 on native, for every picker. |
showWeekNumbers | boolean | |
showToday | boolean | "Today" in the footer. |
fixedWeeks | boolean | Always six week rows, so the panel never changes height. Default true. |
label | ReactNode | |
description | ReactNode | |
error | ReactNode | |
placeholder | string | |
required | boolean | |
disabled | boolean | |
readOnly | boolean | |
clearable | boolean | Show the clear button. Default true. |
size | DatePickerSize | Default md. |
presentation | "auto" | "sheet" | "popover" | Sheet on phones, anchored panel on tablets. Default auto. |
style | StyleProp<ViewStyle> | |
styles | DatePickerStyles | |
localeText | Partial<DatePickerLocaleText> | |
onOpenChange | (open: boolean) => void |
DateRangePickerProps
| Prop | Type | Description |
|---|---|---|
value | DateRangeInput | null | |
defaultValue | DateRangeInput | null | |
onChange | (range: DateRange, complete: boolean) => void | complete is false on the first of the two taps. |
presets | readonly DatePreset[] | |
closeOnSelect | boolean | Close once both ends are chosen. Default true. |
min | DateInput | null | |
max | DateInput | null | |
isDateDisabled | (date: Date) => boolean | |
locale | string | BCP-47 tag for month names, digits and the first day of the week. |
weekStartsOn | number | 0 = Sunday. Defaults to the locale's first day of the week. |
format | DateFormat | |
numberOfMonths | number | Months shown, stacked. Default 1 on native, for every picker. |
showWeekNumbers | boolean | |
showToday | boolean | "Today" in the footer. |
fixedWeeks | boolean | Always six week rows, so the panel never changes height. Default true. |
label | ReactNode | |
description | ReactNode | |
error | ReactNode | |
placeholder | string | |
required | boolean | |
disabled | boolean | |
readOnly | boolean | |
clearable | boolean | Show the clear button. Default true. |
size | DatePickerSize | Default md. |
presentation | "auto" | "sheet" | "popover" | Sheet on phones, anchored panel on tablets. Default auto. |
style | StyleProp<ViewStyle> | |
styles | DatePickerStyles | |
localeText | Partial<DatePickerLocaleText> | |
onOpenChange | (open: boolean) => void |
DateTimePickerProps
| Prop | Type | Description |
|---|---|---|
value | DateInput | null | |
defaultValue | DateInput | null | |
onChange | (date: Date | null) => void | The chosen moment as a local Date, or null once cleared. Fires on Done. |
min | DateInput | null | Earliest moment: earlier days cannot be picked, an earlier time on that day is moved up. |
max | DateInput | null | Latest moment, applied the same way. |
hourCycle | HourCycle | 12 shows an AM/PM switch. Defaults to the locale's clock. |
showSeconds | boolean | A seconds part as well. Default false. |
minuteStep | number | How far the minutes move per step. Default 1. |
defaultTime | string | Time used when a day is picked before any time is set, HH:mm. Default 00:00. |
showNow | boolean | "Now" in the footer. Default true. |
isDateDisabled | (date: Date) => boolean | |
locale | string | BCP-47 tag for month names, digits and the first day of the week. |
weekStartsOn | number | 0 = Sunday. Defaults to the locale's first day of the week. |
format | DateFormat | |
numberOfMonths | number | Months shown, stacked. Default 1 on native, for every picker. |
showWeekNumbers | boolean | |
showToday | boolean | "Today" in the footer. |
fixedWeeks | boolean | Always six week rows, so the panel never changes height. Default true. |
label | ReactNode | |
description | ReactNode | |
error | ReactNode | |
placeholder | string | |
required | boolean | |
disabled | boolean | |
readOnly | boolean | |
clearable | boolean | Show the clear button. Default true. |
size | DatePickerSize | Default md. |
presentation | "auto" | "sheet" | "popover" | Sheet on phones, anchored panel on tablets. Default auto. |
style | StyleProp<ViewStyle> | |
styles | DatePickerStyles | |
localeText | Partial<DatePickerLocaleText> | |
onOpenChange | (open: boolean) => void |
Native and web
- The week starts per locale (Sunday for en-IN, Saturday for ar-EG) even though Hermes has no
Intl.Locale. - Tap-only for now: no typed dates. DateTimePicker commits on Done.
- Web version: DatePicker on the web.