diff --git a/docs-site/src/components/Examples/config.tsx b/docs-site/src/components/Examples/config.tsx index 4baac1b7f..f92645ea5 100644 --- a/docs-site/src/components/Examples/config.tsx +++ b/docs-site/src/components/Examples/config.tsx @@ -62,6 +62,7 @@ import Inline from "../../examples/ts/inline?raw"; import InlineDisabled from "../../examples/ts/disabledInline?raw"; import InlineVisible from "../../examples/ts/inlineVisible?raw"; import TimeInput from "../../examples/ts/timeInput?raw"; +import RangeTimeInputLabels from "../../examples/ts/rangeTimeInputLabels?raw"; import Locale from "../../examples/ts/locale?raw"; import LocaleWithTime from "../../examples/ts/localeWithTime?raw"; import LocaleWithoutGlobalVariable from "../../examples/ts/localeWithoutGlobalVariable?raw"; @@ -370,6 +371,10 @@ export const EXAMPLE_CONFIG: IExampleConfig[] = [ title: "Input Time", component: TimeInput, }, + { + title: "Input Time with Range (custom start/end labels)", + component: RangeTimeInputLabels, + }, { title: "Locale", component: Locale, diff --git a/docs-site/src/examples/ts/rangeTimeInputLabels.tsx b/docs-site/src/examples/ts/rangeTimeInputLabels.tsx new file mode 100644 index 000000000..7ddd31162 --- /dev/null +++ b/docs-site/src/examples/ts/rangeTimeInputLabels.tsx @@ -0,0 +1,26 @@ +const RangeTimeInputLabels = () => { + const [startDate, setStartDate] = useState(new Date()); + const [endDate, setEndDate] = useState(null); + + const onChange = (dates: [Date | null, Date | null]) => { + const [start, end] = dates; + setStartDate(start); + setEndDate(end); + }; + + return ( + + ); +}; + +render(RangeTimeInputLabels); diff --git a/src/calendar.tsx b/src/calendar.tsx index 4bedbdc06..643778f35 100644 --- a/src/calendar.tsx +++ b/src/calendar.tsx @@ -223,6 +223,8 @@ type CalendarProps = React.PropsWithChildren< onTimeChange?: (time: Date, modifyDateType?: "start" | "end") => void; timeFormat?: TimeProps["format"]; timeIntervals?: TimeProps["intervals"]; + timeInputStartLabel?: string; + timeInputEndLabel?: string; } & ( | ({ showMonthYearDropdown: true; @@ -1212,7 +1214,10 @@ export default class Calendar extends Component { onChange={(time: Date) => { this.props.onTimeChange?.(time, "start"); }} - timeInputLabel={(this.props.timeInputLabel ?? "Time") + " (Start)"} + timeInputLabel={ + this.props.timeInputStartLabel ?? + (this.props.timeInputLabel ?? "Time") + " (Start)" + } /> { onChange={(time: Date) => { this.props.onTimeChange?.(time, "end"); }} - timeInputLabel={(this.props.timeInputLabel ?? "Time") + " (End)"} + timeInputLabel={ + this.props.timeInputEndLabel ?? + (this.props.timeInputLabel ?? "Time") + " (End)" + } /> ); diff --git a/src/test/datepicker_test.test.tsx b/src/test/datepicker_test.test.tsx index 31b239b37..2e4ebdf95 100644 --- a/src/test/datepicker_test.test.tsx +++ b/src/test/datepicker_test.test.tsx @@ -6821,6 +6821,124 @@ describe("DatePicker", () => { expect(timeInputs[0]?.value).toBe(""); expect(timeInputs[1]?.value).toBe(""); }); + + describe("timeInputStartLabel / timeInputEndLabel props (#6280)", () => { + const rangeStart = newDate("2024-01-15 09:00:00"); + const rangeEnd = newDate("2024-01-20 14:30:00"); + + const captionsOf = (container: HTMLElement) => + Array.from( + container.querySelectorAll(".react-datepicker-time__caption"), + ).map((n) => n.textContent); + + it("defaults to the hardcoded English suffixes", () => { + const { container } = render( + , + ); + expect(captionsOf(container)).toEqual(["Time (Start)", "Time (End)"]); + }); + + it("appends the suffixes to a custom timeInputLabel (existing behavior)", () => { + const { container } = render( + , + ); + expect(captionsOf(container)).toEqual([ + "Uhrzeit (Start)", + "Uhrzeit (End)", + ]); + }); + + it("replaces each caption entirely when the new props are provided", () => { + const { container } = render( + , + ); + expect(captionsOf(container)).toEqual(["Startzeit", "Endzeit"]); + }); + + it("overrides timeInputLabel + suffix when both are set", () => { + const { container } = render( + , + ); + expect(captionsOf(container)).toEqual(["Von", "Bis"]); + }); + + it("falls back per-side when only one of the two props is set", () => { + const { container: c1 } = render( + , + ); + expect(captionsOf(c1)).toEqual(["Von", "Time (End)"]); + + const { container: c2 } = render( + , + ); + expect(captionsOf(c2)).toEqual(["Time (Start)", "Bis"]); + }); + + it("does not affect single (non-range) mode", () => { + const { container } = render( + , + ); + expect(captionsOf(container)).toEqual(["Uhrzeit"]); + }); + }); }); describe("Critical functions coverage - best in class", () => {