Skip to content

Commit b08fef0

Browse files
committed
Time picker now preselects values when any value is selected
1 parent d913839 commit b08fef0

5 files changed

Lines changed: 77 additions & 103 deletions

File tree

packages/lib/src/time-input/TimeInput.stories.tsx

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,10 @@ const TimePickerExamples = () => {
119119
<ExampleContainer>
120120
<Title title="Time Picker 24h format" theme="light" level={3} />
121121
<DxcContainer width="250px">
122-
<TimePicker onSelectMinutes={() => {}} onSelectHours={() => {}} timeFormat="24" id="testId" tabIndex={0} />
122+
<TimePicker onPickTime={() => {}} timeFormat="24" id="testId" tabIndex={0} />
123+
<TimePicker onPickTime={() => {}} timeFormat="24" id="testId" tabIndex={0} hourValue={15} minuteValue={30} />
123124
<TimePicker
124-
onSelectMinutes={() => {}}
125-
onSelectHours={() => {}}
126-
timeFormat="24"
127-
id="testId"
128-
tabIndex={0}
129-
hourValue={15}
130-
minuteValue={30}
131-
/>
132-
<TimePicker
133-
onSelectMinutes={() => {}}
134-
onSelectHours={() => {}}
125+
onPickTime={() => {}}
135126
timeFormat="24"
136127
id="testId"
137128
tabIndex={0}
@@ -145,10 +136,9 @@ const TimePickerExamples = () => {
145136
<ExampleContainer>
146137
<Title title="Time Picker 12h format" theme="light" level={3} />
147138
<DxcContainer width="250px">
148-
<TimePicker onSelectMinutes={() => {}} onSelectHours={() => {}} timeFormat="12" id="testId" tabIndex={0} />
139+
<TimePicker onPickTime={() => {}} timeFormat="12" id="testId" tabIndex={0} />
149140
<TimePicker
150-
onSelectMinutes={() => {}}
151-
onSelectHours={() => {}}
141+
onPickTime={() => {}}
152142
timeFormat="12"
153143
id="testId"
154144
tabIndex={0}
@@ -157,8 +147,7 @@ const TimePickerExamples = () => {
157147
dayPeriod={1}
158148
/>
159149
<TimePicker
160-
onSelectMinutes={() => {}}
161-
onSelectHours={() => {}}
150+
onPickTime={() => {}}
162151
timeFormat="12"
163152
id="testId"
164153
tabIndex={0}
@@ -173,10 +162,9 @@ const TimePickerExamples = () => {
173162
<ExampleContainer pseudoState={"pseudo-hover"}>
174163
<Title title="hover" theme="light" level={3} />
175164
<DxcContainer width="250px">
176-
<TimePicker onSelectMinutes={() => {}} onSelectHours={() => {}} timeFormat="12" id="testId" tabIndex={0} />
165+
<TimePicker onPickTime={() => {}} timeFormat="12" id="testId" tabIndex={0} />
177166
<TimePicker
178-
onSelectMinutes={() => {}}
179-
onSelectHours={() => {}}
167+
onPickTime={() => {}}
180168
timeFormat="12"
181169
id="testId"
182170
tabIndex={0}
@@ -185,8 +173,7 @@ const TimePickerExamples = () => {
185173
dayPeriod={1}
186174
/>
187175
<TimePicker
188-
onSelectMinutes={() => {}}
189-
onSelectHours={() => {}}
176+
onPickTime={() => {}}
190177
timeFormat="12"
191178
id="testId"
192179
tabIndex={0}
@@ -201,10 +188,9 @@ const TimePickerExamples = () => {
201188
<ExampleContainer pseudoState={"pseudo-focus"}>
202189
<Title title="focus" theme="light" level={3} />
203190
<DxcContainer width="250px">
204-
<TimePicker onSelectMinutes={() => {}} onSelectHours={() => {}} timeFormat="12" id="testId" tabIndex={0} />
191+
<TimePicker onPickTime={() => {}} timeFormat="12" id="testId" tabIndex={0} />
205192
<TimePicker
206-
onSelectMinutes={() => {}}
207-
onSelectHours={() => {}}
193+
onPickTime={() => {}}
208194
timeFormat="12"
209195
id="testId"
210196
tabIndex={0}
@@ -213,8 +199,7 @@ const TimePickerExamples = () => {
213199
dayPeriod={1}
214200
/>
215201
<TimePicker
216-
onSelectMinutes={() => {}}
217-
onSelectHours={() => {}}
202+
onPickTime={() => {}}
218203
timeFormat="12"
219204
id="testId"
220205
tabIndex={0}
@@ -229,10 +214,9 @@ const TimePickerExamples = () => {
229214
<ExampleContainer pseudoState={"pseudo-active"}>
230215
<Title title="active" theme="light" level={3} />
231216
<DxcContainer width="250px">
232-
<TimePicker onSelectMinutes={() => {}} onSelectHours={() => {}} timeFormat="12" id="testId" tabIndex={0} />
217+
<TimePicker onPickTime={() => {}} timeFormat="12" id="testId" tabIndex={0} />
233218
<TimePicker
234-
onSelectMinutes={() => {}}
235-
onSelectHours={() => {}}
219+
onPickTime={() => {}}
236220
timeFormat="12"
237221
id="testId"
238222
tabIndex={0}
@@ -241,8 +225,7 @@ const TimePickerExamples = () => {
241225
dayPeriod={1}
242226
/>
243227
<TimePicker
244-
onSelectMinutes={() => {}}
245-
onSelectHours={() => {}}
228+
onPickTime={() => {}}
246229
timeFormat="12"
247230
id="testId"
248231
tabIndex={0}

packages/lib/src/time-input/TimeInput.test.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,13 @@ describe("DxcTimeInput rendering", () => {
110110
expect(getByText("AM")).toBeTruthy();
111111
const hourbutton = getAllByText("07");
112112
if (hourbutton[0]) userEvent.click(hourbutton[0]);
113-
expect(mockOnChange).toHaveBeenCalledWith("07: ");
113+
expect(mockOnChange).toHaveBeenCalledWith("07:00 AM");
114114
const minuteButton = getAllByText("30");
115115
if (minuteButton[0]) userEvent.click(minuteButton[0]);
116-
expect(mockOnChange).toHaveBeenCalledWith("07:30 ");
117-
const amButton = getByText("AM");
116+
expect(mockOnChange).toHaveBeenCalledWith("07:30 AM");
117+
const amButton = getAllByText("AM")[0];
118118
expect(amButton).toBeTruthy();
119-
userEvent.click(amButton);
119+
if (amButton) userEvent.click(amButton);
120120
expect(mockOnChange).toHaveBeenCalledWith("07:30 AM");
121121
});
122122

@@ -130,14 +130,14 @@ describe("DxcTimeInput rendering", () => {
130130
userEvent.keyboard("{ArrowDown}");
131131
userEvent.keyboard("{ArrowDown}");
132132
userEvent.keyboard("{Enter}");
133-
expect(mockOnChange).toHaveBeenCalledWith("03: ");
133+
expect(mockOnChange).toHaveBeenCalledWith("03:00 AM");
134134
userEvent.tab();
135135
userEvent.keyboard("{ArrowUp}");
136136
userEvent.keyboard("{Enter}");
137-
expect(mockOnChange).toHaveBeenCalledWith("03:55 ");
137+
expect(mockOnChange).toHaveBeenCalledWith("03:55 AM");
138138
userEvent.keyboard("{ArrowDown}");
139139
userEvent.keyboard(" ");
140-
expect(mockOnChange).toHaveBeenCalledWith("03:00 ");
140+
expect(mockOnChange).toHaveBeenCalledWith("03:00 AM");
141141
userEvent.tab();
142142
userEvent.keyboard("{ArrowDown}");
143143
userEvent.keyboard("{Enter}");

packages/lib/src/time-input/TimeInput.tsx

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ const ColonContainer = styled.span`
5252
padding: 0;
5353
color: var(--color-fg-neutral-dark);
5454
`;
55+
// number can be 2 digit or 1 digit
56+
const isNumber = (value: string) => /^\d{1,2}$/.test(value);
5557

5658
const DxcTimeInput = forwardRef<RefType, TimeInputPropsType>(
5759
(
@@ -95,10 +97,10 @@ const DxcTimeInput = forwardRef<RefType, TimeInputPropsType>(
9597
if (time) {
9698
const numberPart = timeFormat === "12" ? time.split(" ")[0] : time;
9799
if (numberPart) {
98-
const [hour, minute, second] = numberPart.split(":").map(Number);
99-
setHourValue(hour || hour === 0 ? hour : undefined);
100-
setMinuteValue(minute || minute === 0 ? minute : undefined);
101-
setSecondValue(second || second === 0 ? second : undefined);
100+
const [hourStr, minuteStr, secondStr] = numberPart.split(":").map(String);
101+
setHourValue(hourStr && isNumber(hourStr) ? Number(hourStr) : undefined);
102+
setMinuteValue(minuteStr && isNumber(minuteStr) ? Number(minuteStr) : undefined);
103+
setSecondValue(secondStr && isNumber(secondStr) ? Number(secondStr) : undefined);
102104
}
103105
if (timeFormat === "12" && time.includes(" ")) {
104106
const dayPeriodValue = time.split(" ")[1] === "AM" ? 0 : time.split(" ")[1] === "PM" ? 1 : undefined;
@@ -343,44 +345,15 @@ const DxcTimeInput = forwardRef<RefType, TimeInputPropsType>(
343345
<DxcPopover
344346
popoverContent={
345347
<TimePicker
346-
onSelectHours={(value) => {
348+
onPickTime={(hour, minute, second, dayPeriod) => {
347349
if (!isControlled) {
348-
setHourValue(value);
350+
setDayPeriodValue(dayPeriod);
351+
setSecondValue(second);
352+
setMinuteValue(minute);
353+
setHourValue(hour);
349354
}
350355
if (typeof onChange === "function") {
351-
onChange(
352-
generateEventValue(value, minuteValue, secondValue, dayPeriodValue, showSeconds, timeFormat)
353-
);
354-
}
355-
}}
356-
onSelectMinutes={(value) => {
357-
if (!isControlled) {
358-
setMinuteValue(value);
359-
}
360-
if (typeof onChange === "function") {
361-
onChange(
362-
generateEventValue(hourValue, value, secondValue, dayPeriodValue, showSeconds, timeFormat)
363-
);
364-
}
365-
}}
366-
onSelectSeconds={(value) => {
367-
if (!isControlled) {
368-
setSecondValue(value);
369-
}
370-
if (typeof onChange === "function") {
371-
onChange(
372-
generateEventValue(hourValue, minuteValue, value, dayPeriodValue, showSeconds, timeFormat)
373-
);
374-
}
375-
}}
376-
onSelectDayPeriod={(value: number) => {
377-
if (!isControlled) {
378-
setDayPeriodValue(value);
379-
}
380-
if (typeof onChange === "function") {
381-
onChange(
382-
generateEventValue(hourValue, minuteValue, secondValue, value, showSeconds, timeFormat)
383-
);
356+
onChange(generateEventValue(hour, minute, second, dayPeriod, showSeconds, timeFormat));
384357
}
385358
}}
386359
timeFormat={timeFormat}

packages/lib/src/time-input/TimePicker.tsx

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { TimePickerPropsType } from "./types";
33
import { useEffect, useState } from "react";
44
import TimePickerColumn from "./TimePickerColumn";
55
import { handleColumnKeyDown } from "./utils";
6-
76
// Array to be used in seconds and minutes.
87
const STEP = 5;
98
const ARRAY_OF_60 = Array.from({ length: 60 / STEP }, (_, index) => index * STEP);
@@ -15,10 +14,7 @@ const TimePickerContainer = styled.div`
1514
`;
1615

1716
const TimePicker = ({
18-
onSelectHours,
19-
onSelectMinutes,
20-
onSelectSeconds,
21-
onSelectDayPeriod,
17+
onPickTime,
2218
timeFormat,
2319
showSeconds,
2420
hourValue,
@@ -34,6 +30,19 @@ const TimePicker = ({
3430
const [dayPeriodToFocus, setDayPeriodToFocus] = useState(dayPeriod || 0);
3531
const totalHours = timeFormat === "12" ? 12 : 24;
3632

33+
const onPickerSelect = (value: number, type: "hour" | "minute" | "second" | "dayPeriod") => {
34+
const hourVal = type === "hour" ? value : hourValue || 0;
35+
const minuteVal = type === "minute" ? value : minuteValue || 0;
36+
const secondVal = type === "second" ? value : secondValue || 0;
37+
const dayPeriodVal = type === "dayPeriod" ? value : dayPeriod || 0;
38+
39+
setDayPeriodToFocus(dayPeriodVal);
40+
setSecondToFocus(secondVal);
41+
setMinuteToFocus(minuteVal);
42+
setHourToFocus(hourVal);
43+
onPickTime(hourVal, minuteVal, secondVal, dayPeriodVal);
44+
};
45+
3746
useEffect(() => {
3847
if (dayPeriodToFocus !== undefined && id) {
3948
document.getElementById(`${id}-dayPeriod-${dayPeriodToFocus}`)?.focus();
@@ -65,11 +74,12 @@ const TimePicker = ({
6574
tabIndex={tabIndex}
6675
dataType="hour"
6776
onClick={(value: number) => {
68-
onSelectHours(value);
69-
setHourToFocus(value);
77+
onPickerSelect(value, "hour");
7078
}}
7179
onKeyboardEvent={(event: React.KeyboardEvent, value: number) =>
72-
handleColumnKeyDown(event, "hour", value, totalHours, setHourToFocus, onSelectHours)
80+
handleColumnKeyDown(event, "hour", value, totalHours, setHourToFocus, (value) =>
81+
onPickerSelect(value, "hour")
82+
)
7383
}
7484
/>
7585
<TimePickerColumn
@@ -80,11 +90,18 @@ const TimePicker = ({
8090
tabIndex={tabIndex}
8191
dataType="minute"
8292
onClick={(value: number) => {
83-
onSelectMinutes(value);
84-
setMinuteToFocus(value);
93+
onPickerSelect(value, "minute");
8594
}}
8695
onKeyboardEvent={(event: React.KeyboardEvent, value: number) =>
87-
handleColumnKeyDown(event, "minute", value, 60, setMinuteToFocus, onSelectMinutes, STEP)
96+
handleColumnKeyDown(
97+
event,
98+
"minute",
99+
value,
100+
60,
101+
setMinuteToFocus,
102+
(value) => onPickerSelect(value, "minute"),
103+
STEP
104+
)
88105
}
89106
/>
90107
{showSeconds && (
@@ -96,13 +113,18 @@ const TimePicker = ({
96113
tabIndex={tabIndex}
97114
dataType="second"
98115
onClick={(value: number) => {
99-
if (typeof onSelectSeconds === "function") {
100-
onSelectSeconds(value);
101-
setSecondToFocus(value);
102-
}
116+
onPickerSelect(value, "second");
103117
}}
104118
onKeyboardEvent={(event: React.KeyboardEvent, value: number) =>
105-
handleColumnKeyDown(event, "second", value, 60, setSecondToFocus, onSelectSeconds, STEP)
119+
handleColumnKeyDown(
120+
event,
121+
"second",
122+
value,
123+
60,
124+
setSecondToFocus,
125+
(value) => onPickerSelect(value, "second"),
126+
STEP
127+
)
106128
}
107129
/>
108130
)}
@@ -115,13 +137,12 @@ const TimePicker = ({
115137
tabIndex={tabIndex}
116138
dataType="dayPeriod"
117139
onClick={(value: number) => {
118-
if (typeof onSelectDayPeriod === "function") {
119-
onSelectDayPeriod(value);
120-
setDayPeriodToFocus(value);
121-
}
140+
onPickerSelect(value, "dayPeriod");
122141
}}
123142
onKeyboardEvent={(event: React.KeyboardEvent, value: number) =>
124-
handleColumnKeyDown(event, "dayPeriod", value, 2, setDayPeriodToFocus, onSelectDayPeriod)
143+
handleColumnKeyDown(event, "dayPeriod", value, 2, setDayPeriodToFocus, (value) =>
144+
onPickerSelect(value, "dayPeriod")
145+
)
125146
}
126147
/>
127148
)}

packages/lib/src/time-input/types.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,7 @@ export type TimeSpinButtonPropsType = {
104104
};
105105

106106
export type TimePickerPropsType = {
107-
onSelectHours: (hours: number) => void;
108-
onSelectMinutes: (minutes: number) => void;
109-
onSelectSeconds?: (seconds: number) => void;
110-
onSelectDayPeriod?: (isPM: number) => void;
107+
onPickTime: (hours: number, minutes: number, seconds?: number, dayPeriod?: number) => void;
111108
timeFormat: "12" | "24";
112109
showSeconds?: boolean;
113110
hourValue?: number;

0 commit comments

Comments
 (0)