Usage
DateTimePicker from @prepared911/ui-calendar pairs a DatePicker with one or two native <input type="time"> fields. It ships in two modes—single and range—and supports deferred commits via onApply. Use it when a workflow commits a specific date-and-time (scheduling, appointment booking) rather than describing a query constraint.
For queries that need Before / After or half-open ranges, use AdvancedDateTimeRangePicker instead; DateTimePicker is designed for contiguous, "specific point or span" values.
| Su | Mo | Tu | We | Th | Fr | Sa |
|---|---|---|---|---|---|---|
maxRange enforcement. Shift-length constraints and other "no more than N days" rules are enforced by the component when maxRange is set.AdvancedDateRangePicker / AdvancedDateTimeRangePicker: inequality semantics and committed ranges have different UX.DatePicker or DateInput: the time input adds cognitive load.TimePicker.EventRecurrencePicker.DatePicker in Single mode stacked with a TimePicker (<input type="time">).DatePicker in Range mode paired with TimeRangeInputs (a matched TimePicker pair with maxRange enforcement).onApply defers commits; without it, every change emits onChange.onApply, internal state tracks date and time drafts; Apply emits the committed value. Without it, onChange fires on every date or time change.maxRange (range mode). When a range exceeds maxRange days, the component clamps the end to start + maxRange. Surface the limit in helper copy so the clamp is predictable.Date objects. Convert at the boundary (convertLocalToUTC / convertUTCToLocal from @prepared911/util-helpers) so you store UTC and display local.onChange payload uses { start: Date | null; end: Date | null } so callers can observe mid-selection state; onApply is only dispatched on a full commit.Do
onApply with deferred commits so mid-edit state does not fan out to network calls or dependent UI.maxRange limits in helper copy ("Shift length cannot exceed 12 hours") so the clamp feels intentional.Don't
DateTimePicker for time-only changes to an existing date: a standalone TimePicker is less invasive.Single pickers; the component handles end-before-start correction and the maxRange clamp in Range mode.DateTimePicker with a separate time selector bound to the same state: the internal TimePicker already owns time-of-day.DateTimePicker inherits the date grid's keyboard semantics and the native time input's platform picker. The app owns the visible label for the time input (via TimePicker's label / hideLabel pattern), the Apply / Reset announcement if present, and distinct ids when multiple pickers share a screen. See the Accessibility page for the full contract.