Skip to content

Commit 75f1899

Browse files
committed
fix: date picker range
1 parent 71f8a73 commit 75f1899

File tree

4 files changed

+44
-5
lines changed

4 files changed

+44
-5
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@zag-js/date-picker": patch
3+
---
4+
5+
Fix crash in range date picker when typing end date first by adding `null`/`undefined` checks when accessing date
6+
properties.

e2e/date-picker.e2e.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,35 @@ test.describe("datepicker [min-max]", () => {
217217
await I.seeSelectedValue("08/15/2025")
218218
})
219219
})
220+
221+
test.describe("datepicker [range]", () => {
222+
test.beforeEach(async ({ page }) => {
223+
I = new DatePickerModel(page)
224+
await I.goto("/date-picker-range")
225+
})
226+
227+
test("should not crash when typing end date first", async () => {
228+
// Regression test for issue #2809
229+
// Focus the end date input (index 1) first and type a valid date
230+
await I.focusInput(1)
231+
await I.type("06/15/2024", 1)
232+
await I.clickOutsideToBlur()
233+
234+
// Should not crash and the value should be set
235+
await I.seeInputHasValue("06/15/2024", 1)
236+
})
237+
238+
test("should allow selecting dates after typing end date first", async () => {
239+
// Type end date first
240+
await I.focusInput(1)
241+
await I.type("06/20/2024", 1)
242+
await I.clickOutsideToBlur()
243+
await I.seeInputHasValue("06/20/2024", 1)
244+
245+
// Open calendar and select a start date - should not crash
246+
await I.clickTrigger()
247+
await I.seeContent()
248+
await I.clickDayCell(10)
249+
await I.seeInputHasValue("06/10/2024", 0)
250+
})
251+
})

packages/machines/date-picker/src/date-picker.connect.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ export function connect<T extends PropTypes>(
148148
focused: focusedValue.year === props.value,
149149
selectable: isOutsideVisibleRange || isOutsideRange,
150150
outsideRange: isOutsideVisibleRange,
151-
selected: !!selectedValue.find((date) => date.year === value),
151+
selected: !!selectedValue.find((date) => date && date.year === value),
152152
valueText: value.toString(),
153153
inRange:
154154
isRangePicker &&
@@ -168,7 +168,7 @@ export function connect<T extends PropTypes>(
168168
const cellState = {
169169
focused: focusedValue.month === props.value,
170170
selectable: !isDateOutsideRange(dateValue, min, max),
171-
selected: !!selectedValue.find((date) => date.month === value && date.year === focusedValue.year),
171+
selected: !!selectedValue.find((date) => date && date.month === value && date.year === focusedValue.year),
172172
valueText: formatter.format(dateValue.toDate(timeZone)),
173173
inRange:
174174
isRangePicker &&
@@ -270,7 +270,7 @@ export function connect<T extends PropTypes>(
270270
weekDays: getWeekDays(getTodayDate(timeZone), startOfWeek, timeZone, locale),
271271
visibleRangeText: computed("visibleRangeText"),
272272
value: selectedValue,
273-
valueAsDate: selectedValue.map((date) => date.toDate(timeZone)),
273+
valueAsDate: selectedValue.filter((date) => date != null).map((date) => date.toDate(timeZone)),
274274
valueAsString: computed("valueAsString"),
275275
focusedValue,
276276
focusedValueAsDate: focusedValue?.toDate(timeZone),
@@ -870,7 +870,7 @@ export function connect<T extends PropTypes>(
870870

871871
getPresetTriggerProps(props) {
872872
const value = Array.isArray(props.value) ? props.value : getDateRangePreset(props.value, locale, timeZone)
873-
const valueAsString = value.map((item) => item.toDate(timeZone).toDateString())
873+
const valueAsString = value.filter((item) => item != null).map((item) => item.toDate(timeZone).toDateString())
874874
return normalize.button({
875875
...parts.presetTrigger.attrs,
876876
"aria-label": translations.presetTrigger(valueAsString),

packages/machines/date-picker/src/date-picker.utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ export const defaultTranslations: IntlTranslations = {
7979
})
8080
},
8181
presetTrigger(value) {
82-
return Array.isArray(value) ? `select ${value[0].toString()} to ${value[1].toString()}` : `select ${value}`
82+
const [start = "", end = ""] = value
83+
return `select ${start} to ${end}`
8384
},
8485
prevTrigger(view) {
8586
return match(view, {

0 commit comments

Comments
 (0)