superdesk-ui-framework 4.1.3 → 4.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,7 @@ on:
6
6
  - 'develop'
7
7
  - 'v3'
8
8
  - 'v4'
9
+ - '4.1.5'
9
10
 
10
11
  jobs:
11
12
  publish:
package/.mocharc.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "extension": ["ts", ".tsx"],
3
- "spec": "app-typescript/components/*.spec.*",
3
+ "spec": "app-typescript/**/*.spec.*",
4
4
  "require": ["ts-node/register", "./mocha-setup.ts"]
5
5
  }
@@ -0,0 +1,59 @@
1
+ import {describe, it} from 'mocha';
2
+ import * as assert from 'assert';
3
+ import * as React from 'react';
4
+ import {DateTimePicker} from './DateTimePicker';
5
+
6
+ function makePicker(overrides: Partial<React.ComponentProps<typeof DateTimePicker>> = {}) {
7
+ return new DateTimePicker({
8
+ valueType: 'date',
9
+ dateFormat: 'MM/DD/YYYY',
10
+ value: new Date(2024, 0, 1, 13, 30, 45),
11
+ onChange: () => undefined,
12
+ allowSeconds: true,
13
+ ...overrides,
14
+ } as React.ComponentProps<typeof DateTimePicker>);
15
+ }
16
+
17
+ describe('DateTimePicker', () => {
18
+ it('keeps seconds when formatting date values', () => {
19
+ const picker = makePicker();
20
+
21
+ assert.strictEqual(picker.getTimeValue(), '13:30:45');
22
+ });
23
+
24
+ it('keeps seconds when changing time values', () => {
25
+ let nextValue: Date | null = null;
26
+ const picker = makePicker({
27
+ onChange: (value: Date | null) => {
28
+ nextValue = value;
29
+ },
30
+ });
31
+
32
+ picker.handleTimeChange('09:05:12');
33
+
34
+ assert.notStrictEqual(nextValue, null);
35
+ const timeValue = nextValue as unknown as Date;
36
+
37
+ assert.strictEqual(timeValue.getHours(), 9);
38
+ assert.strictEqual(timeValue.getMinutes(), 5);
39
+ assert.strictEqual(timeValue.getSeconds(), 12);
40
+ });
41
+
42
+ it('keeps seconds when changing the date', () => {
43
+ let nextValue: Date | null = null;
44
+ const picker = makePicker({
45
+ onChange: (value: Date | null) => {
46
+ nextValue = value;
47
+ },
48
+ });
49
+
50
+ picker.handleDateChange(new Date(2024, 0, 2));
51
+
52
+ assert.notStrictEqual(nextValue, null);
53
+ const dateValue = nextValue as unknown as Date;
54
+
55
+ assert.strictEqual(dateValue.getHours(), 13);
56
+ assert.strictEqual(dateValue.getMinutes(), 30);
57
+ assert.strictEqual(dateValue.getSeconds(), 45);
58
+ });
59
+ });
@@ -46,10 +46,10 @@ export class DateTimePicker extends React.PureComponent<IProps> {
46
46
 
47
47
  handleTimeChange = (time: string) => {
48
48
  if (this.props.valueType === 'date') {
49
- const [hours, minutes] = time.split(':').map((x) => defaultTo(parseInt(x, 10), 0));
49
+ const [hours, minutes, seconds] = time.split(':').map((x) => defaultTo(parseInt(x, 10), 0));
50
50
  const origDate = this.props.value ?? new Date();
51
51
 
52
- origDate.setHours(hours, minutes);
52
+ origDate.setHours(hours, minutes, this.props.allowSeconds ? seconds : 0);
53
53
 
54
54
  this.props.onChange(origDate);
55
55
  } else if (this.props.valueType === 'object') {
@@ -72,7 +72,11 @@ export class DateTimePicker extends React.PureComponent<IProps> {
72
72
  const origDate = this.props.value ?? new Date();
73
73
  const selectedDate = new Date(date);
74
74
 
75
- selectedDate.setHours(origDate.getHours(), origDate.getMinutes());
75
+ selectedDate.setHours(
76
+ origDate.getHours(),
77
+ origDate.getMinutes(),
78
+ this.props.allowSeconds ? origDate.getSeconds() : 0,
79
+ );
76
80
 
77
81
  this.props.onChange(selectedDate);
78
82
  } else if (this.props.valueType === 'object') {
@@ -91,9 +95,13 @@ export class DateTimePicker extends React.PureComponent<IProps> {
91
95
 
92
96
  getTimeValue(): string | null {
93
97
  if (this.props.valueType === 'date') {
94
- return this.props.value != null
95
- ? `${this.prepareFormat(this.props.value.getHours())}:${this.prepareFormat(this.props.value.getMinutes())}`
96
- : null;
98
+ if (this.props.value == null) {
99
+ return null;
100
+ }
101
+
102
+ const seconds = this.props.allowSeconds ? `:${this.prepareFormat(this.props.value.getSeconds())}` : '';
103
+
104
+ return `${this.prepareFormat(this.props.value.getHours())}:${this.prepareFormat(this.props.value.getMinutes())}${seconds}`;
97
105
  } else if (this.props.valueType === 'object') {
98
106
  return this.props.value.time ?? null;
99
107
  } else {
@@ -0,0 +1,163 @@
1
+ import {describe, it} from 'mocha';
2
+ import * as assert from 'assert';
3
+ import {convert12HourTo24Hour, convert24HourTo12Hour, toInternalState} from './TimePickerPopover';
4
+
5
+ it('should convert all 12-hour times to 24-hour format', () => {
6
+ // AM times
7
+ assert.strictEqual(convert12HourTo24Hour(12, 'am'), 0);
8
+ assert.strictEqual(convert12HourTo24Hour(1, 'am'), 1);
9
+ assert.strictEqual(convert12HourTo24Hour(2, 'am'), 2);
10
+ assert.strictEqual(convert12HourTo24Hour(3, 'am'), 3);
11
+ assert.strictEqual(convert12HourTo24Hour(4, 'am'), 4);
12
+ assert.strictEqual(convert12HourTo24Hour(5, 'am'), 5);
13
+ assert.strictEqual(convert12HourTo24Hour(6, 'am'), 6);
14
+ assert.strictEqual(convert12HourTo24Hour(7, 'am'), 7);
15
+ assert.strictEqual(convert12HourTo24Hour(8, 'am'), 8);
16
+ assert.strictEqual(convert12HourTo24Hour(9, 'am'), 9);
17
+ assert.strictEqual(convert12HourTo24Hour(10, 'am'), 10);
18
+ assert.strictEqual(convert12HourTo24Hour(11, 'am'), 11);
19
+
20
+ // PM times
21
+ assert.strictEqual(convert12HourTo24Hour(12, 'pm'), 12);
22
+ assert.strictEqual(convert12HourTo24Hour(1, 'pm'), 13);
23
+ assert.strictEqual(convert12HourTo24Hour(2, 'pm'), 14);
24
+ assert.strictEqual(convert12HourTo24Hour(3, 'pm'), 15);
25
+ assert.strictEqual(convert12HourTo24Hour(4, 'pm'), 16);
26
+ assert.strictEqual(convert12HourTo24Hour(5, 'pm'), 17);
27
+ assert.strictEqual(convert12HourTo24Hour(6, 'pm'), 18);
28
+ assert.strictEqual(convert12HourTo24Hour(7, 'pm'), 19);
29
+ assert.strictEqual(convert12HourTo24Hour(8, 'pm'), 20);
30
+ assert.strictEqual(convert12HourTo24Hour(9, 'pm'), 21);
31
+ assert.strictEqual(convert12HourTo24Hour(10, 'pm'), 22);
32
+ assert.strictEqual(convert12HourTo24Hour(11, 'pm'), 23);
33
+ });
34
+
35
+ it('should convert all 24-hour times to 12-hour format', () => {
36
+ assert.strictEqual(convert24HourTo12Hour(0), 12);
37
+ assert.strictEqual(convert24HourTo12Hour(1), 1);
38
+ assert.strictEqual(convert24HourTo12Hour(2), 2);
39
+ assert.strictEqual(convert24HourTo12Hour(3), 3);
40
+ assert.strictEqual(convert24HourTo12Hour(4), 4);
41
+ assert.strictEqual(convert24HourTo12Hour(5), 5);
42
+ assert.strictEqual(convert24HourTo12Hour(6), 6);
43
+ assert.strictEqual(convert24HourTo12Hour(7), 7);
44
+ assert.strictEqual(convert24HourTo12Hour(8), 8);
45
+ assert.strictEqual(convert24HourTo12Hour(9), 9);
46
+ assert.strictEqual(convert24HourTo12Hour(10), 10);
47
+ assert.strictEqual(convert24HourTo12Hour(11), 11);
48
+ assert.strictEqual(convert24HourTo12Hour(12), 12);
49
+ assert.strictEqual(convert24HourTo12Hour(13), 1);
50
+ assert.strictEqual(convert24HourTo12Hour(14), 2);
51
+ assert.strictEqual(convert24HourTo12Hour(15), 3);
52
+ assert.strictEqual(convert24HourTo12Hour(16), 4);
53
+ assert.strictEqual(convert24HourTo12Hour(17), 5);
54
+ assert.strictEqual(convert24HourTo12Hour(18), 6);
55
+ assert.strictEqual(convert24HourTo12Hour(19), 7);
56
+ assert.strictEqual(convert24HourTo12Hour(20), 8);
57
+ assert.strictEqual(convert24HourTo12Hour(21), 9);
58
+ assert.strictEqual(convert24HourTo12Hour(22), 10);
59
+ assert.strictEqual(convert24HourTo12Hour(23), 11);
60
+ });
61
+
62
+ describe('toInternalState', () => {
63
+ describe('null/undefined/empty input', () => {
64
+ it('should return null state for null input', () => {
65
+ assert.deepStrictEqual(toInternalState(null), {
66
+ hours: null,
67
+ minutes: null,
68
+ seconds: null,
69
+ period: null,
70
+ });
71
+ });
72
+
73
+ it('should return null state for undefined input', () => {
74
+ assert.deepStrictEqual(toInternalState(undefined), {
75
+ hours: null,
76
+ minutes: null,
77
+ seconds: null,
78
+ period: null,
79
+ });
80
+ });
81
+
82
+ it('should return null state for empty string', () => {
83
+ assert.deepStrictEqual(toInternalState(' '), {
84
+ hours: null,
85
+ minutes: null,
86
+ seconds: null,
87
+ period: null,
88
+ });
89
+ });
90
+ });
91
+
92
+ it('should convert 00:00:00 to 12:00:00 am', () => {
93
+ assert.deepStrictEqual(toInternalState('00:00:00'), {
94
+ hours: '12',
95
+ minutes: '00',
96
+ seconds: '00',
97
+ period: 'am',
98
+ });
99
+ });
100
+
101
+ it('should convert 01:30:45 to 01:30:45 am', () => {
102
+ assert.deepStrictEqual(toInternalState('01:30:45'), {
103
+ hours: '01',
104
+ minutes: '30',
105
+ seconds: '45',
106
+ period: 'am',
107
+ });
108
+ });
109
+
110
+ it('should convert 11:59:59 to 11:59:59 am', () => {
111
+ assert.deepStrictEqual(toInternalState('11:59:59'), {
112
+ hours: '11',
113
+ minutes: '59',
114
+ seconds: '59',
115
+ period: 'am',
116
+ });
117
+ });
118
+
119
+ it('should convert 12:00:00 to 12:00:00 pm', () => {
120
+ assert.deepStrictEqual(toInternalState('12:00:00'), {
121
+ hours: '12',
122
+ minutes: '00',
123
+ seconds: '00',
124
+ period: 'pm',
125
+ });
126
+ });
127
+
128
+ it('should convert 13:30:15 to 01:30:15 pm', () => {
129
+ assert.deepStrictEqual(toInternalState('13:30:15'), {
130
+ hours: '01',
131
+ minutes: '30',
132
+ seconds: '15',
133
+ period: 'pm',
134
+ });
135
+ });
136
+
137
+ it('should convert 23:59:59 to 11:59:59 pm', () => {
138
+ assert.deepStrictEqual(toInternalState('23:59:59'), {
139
+ hours: '11',
140
+ minutes: '59',
141
+ seconds: '59',
142
+ period: 'pm',
143
+ });
144
+ });
145
+
146
+ it('should handle time without seconds and default to 00', () => {
147
+ assert.deepStrictEqual(toInternalState('14:30'), {
148
+ hours: '02',
149
+ minutes: '30',
150
+ seconds: '00',
151
+ period: 'pm',
152
+ });
153
+ });
154
+
155
+ it('should handle time without seconds in morning', () => {
156
+ assert.deepStrictEqual(toInternalState('09:15'), {
157
+ hours: '09',
158
+ minutes: '15',
159
+ seconds: '00',
160
+ period: 'am',
161
+ });
162
+ });
163
+ });
@@ -0,0 +1,286 @@
1
+ import * as React from 'react';
2
+ import {Spacer} from '@sourcefabric/common';
3
+ import {ContentDivider} from '../ContentDivider';
4
+ import {RadioButtonGroup} from '../RadioButtonGroup';
5
+ import {getOptionsForTimeUnit} from '../../utils/time';
6
+ import {TimeValueHolder} from './TimeValueHolder';
7
+
8
+ export function convert12HourTo24Hour(hour: number, period: 'am' | 'pm'): number {
9
+ if (period === 'am' && hour === 12) {
10
+ return 0; // midnight
11
+ }
12
+
13
+ if (period === 'pm' && hour !== 12) {
14
+ return hour + 12; // PM and not 12
15
+ }
16
+
17
+ return hour; // For 12PM, 1-11AM
18
+ }
19
+
20
+ export function convert24HourTo12Hour(hour: number) {
21
+ const remainder = hour % 12;
22
+
23
+ return remainder === 0 ? 12 : remainder;
24
+ }
25
+
26
+ function isAm(hours: number) {
27
+ return hours < 12;
28
+ }
29
+
30
+ export function toInternalState(
31
+ timeStr: string | undefined | null, // will always be in 24h format
32
+ ): IState {
33
+ if (timeStr == null || (timeStr ?? '').trim().length < 1) {
34
+ return {
35
+ hours: null,
36
+ minutes: null,
37
+ seconds: null,
38
+ period: null,
39
+ };
40
+ }
41
+
42
+ const [hours, minutes, seconds] = timeStr.split(':');
43
+ const secondsDefault = hours != null && minutes != null ? '00' : null;
44
+
45
+ return {
46
+ hours: (() => {
47
+ if (hours == null) {
48
+ return null;
49
+ }
50
+
51
+ if (is12HourFormat) {
52
+ return convert24HourTo12Hour(parseInt(hours, 10)).toString().padStart(2, '0');
53
+ } else {
54
+ return hours;
55
+ }
56
+ })(),
57
+ minutes: minutes ?? null,
58
+ seconds: seconds ?? secondsDefault,
59
+ period: hours == null ? null : isAm(parseInt(hours, 10)) ? 'am' : 'pm',
60
+ };
61
+ }
62
+
63
+ const is12HourFormat: boolean = (() => {
64
+ const hour = new Date().toLocaleTimeString([]);
65
+
66
+ return hour.includes('AM') || hour.includes('PM');
67
+ })();
68
+
69
+ interface IProps {
70
+ headerTemplate?: React.ReactNode;
71
+ footerTemplate?: React.ReactNode;
72
+ allowSeconds?: boolean;
73
+ onChange: (nextValue: string) => void;
74
+ value: string | null;
75
+ }
76
+
77
+ // internal state is needed in order to be able to wait for all inputs to be filled before triggering `props.onChange`
78
+ interface IState {
79
+ hours: string | null;
80
+ minutes: string | null;
81
+ seconds: string | null;
82
+ period: 'am' | 'pm' | null;
83
+ }
84
+
85
+ export class TimePickerPopover extends React.PureComponent<IProps, IState> {
86
+ // hour, minutes, seconds
87
+ private inputRefs: Array<React.RefObject<TimeValueHolder>>;
88
+
89
+ constructor(props: IProps) {
90
+ super(props);
91
+
92
+ this.inputRefs = [React.createRef(), React.createRef(), React.createRef()];
93
+ this.handleChange = this.handleChange.bind(this);
94
+ this.scrollToValues = this.scrollToValues.bind(this);
95
+
96
+ this.state = toInternalState(props.value);
97
+ }
98
+
99
+ private handleChange(nextState: IState) {
100
+ this.setState(nextState, () => {
101
+ let timeParts: Array<string> = [];
102
+
103
+ if (this.state.hours == null) {
104
+ return;
105
+ }
106
+
107
+ if (is12HourFormat) {
108
+ if (this.state.period == null) {
109
+ return;
110
+ }
111
+
112
+ timeParts.push(
113
+ convert12HourTo24Hour(parseInt(this.state.hours, 10), this.state.period)
114
+ .toString()
115
+ .padStart(2, '0'),
116
+ );
117
+ } else {
118
+ timeParts.push(this.state.hours);
119
+ }
120
+
121
+ if (this.state.minutes == null) {
122
+ return;
123
+ } else {
124
+ timeParts.push(this.state.minutes);
125
+ }
126
+
127
+ if (this.props.allowSeconds) {
128
+ if (this.state.seconds == null) {
129
+ return;
130
+ } else {
131
+ timeParts.push(this.state.seconds);
132
+ }
133
+ }
134
+
135
+ this.props.onChange(timeParts.join(':'));
136
+ });
137
+ }
138
+
139
+ scrollToValues() {
140
+ this.inputRefs.forEach((unitOfTime) => unitOfTime?.current?.scrollToValue?.());
141
+ }
142
+
143
+ componentDidMount(): void {
144
+ this.scrollToValues();
145
+ }
146
+
147
+ componentDidUpdate(prevProps: Readonly<IProps>): void {
148
+ if (this.props.value !== prevProps.value) {
149
+ this.setState(toInternalState(this.props.value), () => {
150
+ this.scrollToValues();
151
+ });
152
+ }
153
+ }
154
+
155
+ render(): React.ReactNode {
156
+ const styleForColumnOfUnit: React.CSSProperties = {
157
+ maxHeight: 190,
158
+ overflowY: 'auto',
159
+ scrollbarWidth: 'thin',
160
+ marginTop: 'var(--gap-1)',
161
+ scrollBehavior: 'smooth',
162
+ };
163
+
164
+ return (
165
+ <div className="sd-shadow--z2 radius-md">
166
+ <Spacer
167
+ v
168
+ gap="0"
169
+ style={{
170
+ minWidth: 200,
171
+ maxWidth: 'max-content',
172
+ backgroundColor: 'var(--color-dropdown-menu-Bg)',
173
+ borderRadius: 'var(--b-radius--small)',
174
+ }}
175
+ >
176
+ {this.props.headerTemplate && (
177
+ <div className="px-1-5 py-1" style={{borderBottom: '1px solid var(--color-line-x-light)'}}>
178
+ {this.props.headerTemplate}
179
+ </div>
180
+ )}
181
+
182
+ <Spacer
183
+ h
184
+ gap="4"
185
+ noWrap
186
+ justifyContent="center"
187
+ alignItems="start"
188
+ style={{paddingInline: 'var(--gap-1)'}}
189
+ >
190
+ <Spacer v gap="4" style={styleForColumnOfUnit} alignItems="center" noWrap>
191
+ {getOptionsForTimeUnit('hours', is12HourFormat).map((hour) => {
192
+ const isActiveHour = hour === this.state.hours;
193
+
194
+ return (
195
+ <TimeValueHolder
196
+ key={hour}
197
+ ref={isActiveHour ? this.inputRefs[0] : undefined}
198
+ onClick={() => {
199
+ this.handleChange({...this.state, hours: hour});
200
+ }}
201
+ isActive={isActiveHour}
202
+ value={hour}
203
+ />
204
+ );
205
+ })}
206
+ </Spacer>
207
+
208
+ <ContentDivider align="center" border type="solid" orientation="vertical" margin="none" />
209
+
210
+ <Spacer v gap="4" style={styleForColumnOfUnit} alignItems="center" noWrap>
211
+ {getOptionsForTimeUnit('minutes', is12HourFormat).map((minute) => {
212
+ const isActiveMinute = minute === this.state.minutes;
213
+
214
+ return (
215
+ <TimeValueHolder
216
+ key={minute}
217
+ ref={isActiveMinute ? this.inputRefs[1] : undefined}
218
+ isActive={isActiveMinute}
219
+ value={minute}
220
+ onClick={() => {
221
+ this.handleChange({...this.state, minutes: minute});
222
+ }}
223
+ />
224
+ );
225
+ })}
226
+ </Spacer>
227
+
228
+ {this.props.allowSeconds && (
229
+ <>
230
+ <ContentDivider
231
+ align="center"
232
+ border
233
+ type="solid"
234
+ orientation="vertical"
235
+ margin="none"
236
+ />
237
+ <Spacer v gap="4" style={styleForColumnOfUnit} alignItems="center" noWrap>
238
+ {getOptionsForTimeUnit('seconds', is12HourFormat).map((second) => {
239
+ const isActiveSecond = second === this.state.seconds;
240
+
241
+ return (
242
+ <TimeValueHolder
243
+ key={second}
244
+ ref={isActiveSecond ? this.inputRefs[2] : undefined}
245
+ onClick={() => {
246
+ this.handleChange({...this.state, seconds: second});
247
+ }}
248
+ isActive={isActiveSecond}
249
+ value={second}
250
+ />
251
+ );
252
+ })}
253
+ </Spacer>
254
+ </>
255
+ )}
256
+
257
+ {is12HourFormat && (
258
+ <div
259
+ style={{
260
+ marginTop: 'var(--gap-1)',
261
+ }}
262
+ >
263
+ <RadioButtonGroup
264
+ onChange={(nextValue) => {
265
+ this.handleChange({...this.state, period: nextValue as 'am' | 'pm'});
266
+ }}
267
+ options={[
268
+ {label: 'AM', value: 'am'},
269
+ {label: 'PM', value: 'pm'},
270
+ ]}
271
+ value={this.state.period == null ? '' : this.state.period}
272
+ />
273
+ </div>
274
+ )}
275
+ </Spacer>
276
+
277
+ {this.props.footerTemplate && (
278
+ <div className="px-1-5 py-1" style={{borderTop: '1px solid var(--color-line-x-light)'}}>
279
+ {this.props.footerTemplate}
280
+ </div>
281
+ )}
282
+ </Spacer>
283
+ </div>
284
+ );
285
+ }
286
+ }
@@ -0,0 +1,36 @@
1
+ import * as React from 'react';
2
+ import {classnames} from '@sourcefabric/common';
3
+
4
+ interface IProps {
5
+ isActive?: boolean;
6
+ value: string;
7
+ onClick(event: React.MouseEvent<HTMLSpanElement>): void;
8
+ }
9
+
10
+ export class TimeValueHolder extends React.PureComponent<IProps> {
11
+ private spanEl: React.RefObject<HTMLSpanElement>;
12
+
13
+ constructor(props: IProps) {
14
+ super(props);
15
+
16
+ this.spanEl = React.createRef();
17
+ }
18
+
19
+ public scrollToValue() {
20
+ this.spanEl.current?.scrollIntoView({block: 'start', behavior: 'smooth'});
21
+ }
22
+
23
+ render() {
24
+ return (
25
+ <span
26
+ ref={this.props.isActive ? this.spanEl : undefined}
27
+ onClick={this.props.onClick}
28
+ className={classnames('p-1 time-unit', {
29
+ 'time-unit-highlight': this.props.isActive ?? false,
30
+ })}
31
+ >
32
+ {this.props.value}
33
+ </span>
34
+ );
35
+ }
36
+ }
@@ -1,12 +1,12 @@
1
1
  import * as React from 'react';
2
2
  import nextId from 'react-id-generator';
3
3
  import classNames from 'classnames';
4
- import {InputWrapper} from './Form';
5
- import {IInputWrapper} from './Form/InputWrapper';
4
+ import {InputWrapper} from '../Form';
5
+ import {IInputWrapper} from '../Form/InputWrapper';
6
6
  import {TimePickerPopover} from './TimePickerPopover';
7
- import {PopupPositioner} from './ShowPopup';
8
- import {Icon} from './Icon';
9
- import {IconButton} from './IconButton';
7
+ import {PopupPositioner} from '../ShowPopup';
8
+ import {Icon} from '../Icon';
9
+ import {IconButton} from '../IconButton';
10
10
 
11
11
  interface IProps extends IInputWrapper {
12
12
  value: string | null; // ISO8601 time string(e.g. 16:55) or null if there's no value
@@ -71,11 +71,6 @@ export class TimePicker extends React.PureComponent<IProps, IState> {
71
71
  <TimePickerPopover
72
72
  value={this.props.value}
73
73
  onChange={this.props.onChange}
74
- closePopup={() => {
75
- this.setState({
76
- popupOpen: false,
77
- });
78
- }}
79
74
  allowSeconds={this.props.allowSeconds}
80
75
  headerTemplate={this.props.headerTemplate}
81
76
  footerTemplate={this.props.footerTemplate}
@@ -90,18 +85,12 @@ export class TimePicker extends React.PureComponent<IProps, IState> {
90
85
  ref={this.timeInputRef}
91
86
  value={this.props.value ?? ''}
92
87
  type="time"
93
- onClick={(e) => {
94
- // don't show default popup
95
- e.preventDefault();
96
-
88
+ onClick={() => {
97
89
  this.setState({
98
90
  popupOpen: true,
99
91
  });
100
92
  }}
101
93
  onKeyDown={(event) => {
102
- // don't show default popup
103
- event.preventDefault();
104
-
105
94
  if (event.key === ' ') {
106
95
  this.setState({
107
96
  popupOpen: !this.state.popupOpen,