1
- import { AuButton , AuInput , AuLabel } from ' @appuniversum/ember-appuniversum' ;
2
1
import { fn } from ' @ember/helper' ;
3
2
import { on } from ' @ember/modifier' ;
4
3
import { action } from ' @ember/object' ;
5
4
import { isPresent } from ' @ember/utils' ;
6
5
import Component from ' @glimmer/component' ;
7
6
import { trackedReset } from ' tracked-toolbox' ;
7
+ import AuButton from ' ./au-button' ;
8
+ import AuInput from ' ./au-input' ;
9
+ import type { AuInputSignature } from ' ./au-input' ;
10
+ import AuLabel from ' ./au-label' ;
8
11
9
- export default class AuTimePicker extends Component {
10
- @trackedReset ({
12
+ export interface AuTimePickerSignature {
13
+ Args: {
14
+ hours? : number ;
15
+ hoursLabel? : string ;
16
+ minutes? : number ;
17
+ minutesLabel? : string ;
18
+ nowLabel? : string ;
19
+ onChange? : (data : TimeData ) => void ;
20
+ seconds? : number ;
21
+ secondsLabel? : string ;
22
+ showNow? : boolean ;
23
+ showSeconds? : boolean ;
24
+ };
25
+ }
26
+
27
+ type TimeData = {
28
+ hours: number ;
29
+ minutes: number ;
30
+ seconds: number ;
31
+ };
32
+
33
+ type TimeProperty = ' hours' | ' minutes' | ' seconds' ;
34
+
35
+ export default class AuTimePicker extends Component <AuTimePickerSignature > {
36
+ @trackedReset <AuTimePicker , number >({
11
37
memo: ' args.hours' ,
12
- update () {
13
- if (this .args .hours || this .args .hours == 0 ) {
14
- return this .validateTimeValue (this .args .hours , ' hourValue' );
38
+ update(component : AuTimePicker ) {
39
+ const { hours } = component .args ;
40
+ if (hours || hours == 0 ) {
41
+ return component .normalizeTimeValue (hours , ' hours' );
15
42
} else {
16
43
return 12 ;
17
44
}
18
45
},
19
46
})
20
- hourValue = 12 ;
47
+ hours = 12 ;
21
48
22
- @trackedReset ({
49
+ @trackedReset < AuTimePicker , number > ({
23
50
memo: ' args.minutes' ,
24
- update () {
25
- return this .validateTimeValue (this .args .minutes , ' minuteValue' );
51
+ update(component : AuTimePicker ) {
52
+ let { minutes } = component .args ;
53
+
54
+ if (typeof minutes !== ' number' && typeof minutes !== ' string' ) {
55
+ return 0 ;
56
+ }
57
+
58
+ if (typeof minutes === ' string' ) {
59
+ minutes = parseInt (minutes , 10 );
60
+ }
61
+
62
+ return component .normalizeTimeValue (minutes , ' minutes' );
26
63
},
27
64
})
28
- minuteValue = 0 ;
65
+ minutes = 0 ;
29
66
30
- @trackedReset ({
67
+ @trackedReset < AuTimePicker , number > ({
31
68
memo: ' args.seconds' ,
32
- update () {
33
- return this .validateTimeValue (this .args .seconds , ' secondValue' );
69
+ update(component : AuTimePicker ) {
70
+ let { seconds } = component .args ;
71
+
72
+ if (typeof seconds !== ' number' && typeof seconds !== ' string' ) {
73
+ return 0 ;
74
+ }
75
+
76
+ if (typeof seconds === ' string' ) {
77
+ seconds = parseInt (seconds , 10 );
78
+ }
79
+
80
+ return component .normalizeTimeValue (seconds , ' seconds' );
34
81
},
35
82
})
36
- secondValue = 0 ;
37
-
38
- get hourValueFormatted () {
39
- return this .formatTimeNumber (this .hourValue );
40
- }
41
- get minuteValueFormatted () {
42
- return this .formatTimeNumber (this .minuteValue );
43
- }
44
- get secondValueFormatted () {
45
- return this .formatTimeNumber (this .secondValue );
46
- }
83
+ seconds = 0 ;
47
84
48
- get getTimeObject () {
85
+ get timeData() : TimeData {
49
86
return {
50
- hours: this .hourValue ,
51
- minutes: this .minuteValue ,
52
- seconds: this .secondValue ,
87
+ hours: this .hours ,
88
+ minutes: this .minutes ,
89
+ seconds: this .seconds ,
53
90
};
54
91
}
55
92
@@ -62,19 +99,25 @@ export default class AuTimePicker extends Component {
62
99
}
63
100
64
101
@action
65
- increment (elem ) {
66
- this [elem] = this .validateTimeValue (this [elem] + 1 , elem);
67
- this .callBackParent (this .getTimeObject );
102
+ increment(propertyName : TimeProperty ) {
103
+ this [propertyName ] = this .normalizeTimeValue (
104
+ this [propertyName ] + 1 ,
105
+ propertyName ,
106
+ );
107
+ this .onChange (this .timeData );
68
108
}
69
109
70
110
@action
71
- decrement (elem ) {
72
- this [elem] = this .validateTimeValue (this [elem] - 1 , elem);
73
- this .callBackParent (this .getTimeObject );
111
+ decrement(propertyName : TimeProperty ) {
112
+ this [propertyName ] = this .normalizeTimeValue (
113
+ this [propertyName ] - 1 ,
114
+ propertyName ,
115
+ );
116
+ this .onChange (this .timeData );
74
117
}
75
118
76
119
@action
77
- timeValueKeyPress (type , event ) {
120
+ timeValueKeyPress(type : TimeProperty , event : KeyboardEvent ) {
78
121
switch (event .key ) {
79
122
case ' ArrowUp' :
80
123
this .increment (type );
@@ -86,38 +129,37 @@ export default class AuTimePicker extends Component {
86
129
}
87
130
88
131
@action
89
- validateTime (type , event ) {
90
- this [type] = this .validateTimeValue (event .target .value , type);
91
- this .callBackParent (this .getTimeObject );
132
+ validateTime(type : TimeProperty , event : Event ) {
133
+ const newValue = parseInt (
134
+ // We can't use .valueAsNumber since we're using a type="text" input field, which always returns NaN
135
+ (event .target as AuInputSignature [' Element' ]).value ,
136
+ 10 ,
137
+ );
138
+ this [type ] = this .normalizeTimeValue (newValue , type );
139
+ this .onChange (this .timeData );
92
140
}
93
141
94
- validateTimeValue (value , type ) {
95
- let tempValue = parseInt (value, 10 );
96
- if (isNaN (tempValue)) tempValue = 0 ;
97
- const max = type === ' hourValue' ? 23 : 59 ;
98
- tempValue = tempValue < 0 ? 0 : tempValue;
99
- tempValue = tempValue > max ? max : tempValue;
100
- return tempValue;
142
+ normalizeTimeValue(value : number , type : TimeProperty ) {
143
+ let normalizedValue = ! isNaN (value ) ? value : 0 ;
144
+ const max = type === ' hours' ? 23 : 59 ;
145
+ normalizedValue = normalizedValue < 0 ? 0 : normalizedValue ;
146
+ normalizedValue = normalizedValue > max ? max : normalizedValue ;
147
+ return normalizedValue ;
101
148
}
102
149
103
- @action
104
- callBackParent (value ) {
150
+ onChange(value : TimeData ) {
105
151
if (typeof this .args .onChange === ' function' ) {
106
152
this .args .onChange (value );
107
153
}
108
154
}
109
155
110
156
@action
111
157
setCurrentTime() {
112
- let current = new Date ();
113
- this .hourValue = current .getHours ();
114
- this .minuteValue = current .getMinutes ();
115
- this .secondValue = current .getSeconds ();
116
- this .callBackParent (this .getTimeObject );
117
- }
118
-
119
- formatTimeNumber (number ) {
120
- return number .toString ().padStart (2 , 0 );
158
+ const current = new Date ();
159
+ this .hours = current .getHours ();
160
+ this .minutes = current .getMinutes ();
161
+ this .seconds = current .getSeconds ();
162
+ this .onChange (this .timeData );
121
163
}
122
164
123
165
<template >
@@ -132,10 +174,10 @@ export default class AuTimePicker extends Component {
132
174
class =" au-c-time-picker__input"
133
175
name =" input-hour"
134
176
id =" input-hour"
135
- value ={{this .hourValueFormatted }}
177
+ value ={{formatTime this . hours }}
136
178
data-test-autimepicker-hourinput
137
- {{on " keyup" ( fn this . timeValueKeyPress " hourValue " ) }}
138
- {{on " input" ( fn this . validateTime " hourValue " ) }}
179
+ {{on " keyup" ( fn this . timeValueKeyPress " hours " ) }}
180
+ {{on " input" ( fn this . validateTime " hours " ) }}
139
181
/>
140
182
<div class =" au-c-time-picker__button-wrapper" >
141
183
<button
@@ -144,7 +186,7 @@ export default class AuTimePicker extends Component {
144
186
aria-controls =" input-hour"
145
187
class =" au-c-time-picker__button"
146
188
data-test-autimepicker-hourincrement
147
- {{on " click" ( fn this . increment " hourValue " ) }}
189
+ {{on " click" ( fn this . increment " hours " ) }}
148
190
>
149
191
+
150
192
</button >
@@ -154,7 +196,7 @@ export default class AuTimePicker extends Component {
154
196
aria-controls =" input-hour"
155
197
class =" au-c-time-picker__button"
156
198
data-test-autimepicker-hourdecrement
157
- {{on " click" ( fn this . decrement " hourValue " ) }}
199
+ {{on " click" ( fn this . decrement " hours " ) }}
158
200
>
159
201
-
160
202
</button >
@@ -174,10 +216,10 @@ export default class AuTimePicker extends Component {
174
216
class =" au-c-time-picker__input"
175
217
name =" input-minute"
176
218
id =" input-minute"
177
- value ={{this .minuteValueFormatted }}
219
+ value ={{formatTime this . minutes }}
178
220
data-test-autimepicker-minuteinput
179
- {{on " keyup" ( fn this . timeValueKeyPress " minuteValue " ) }}
180
- {{on " input" ( fn this . validateTime " minuteValue " ) }}
221
+ {{on " keyup" ( fn this . timeValueKeyPress " minutes " ) }}
222
+ {{on " input" ( fn this . validateTime " minutes " ) }}
181
223
/>
182
224
<div class =" au-c-time-picker__button-wrapper" >
183
225
<button
@@ -186,7 +228,7 @@ export default class AuTimePicker extends Component {
186
228
aria-controls =" input-minute"
187
229
class =" au-c-time-picker__button"
188
230
data-test-autimepicker-minuteincrement
189
- {{on " click" ( fn this . increment " minuteValue " ) }}
231
+ {{on " click" ( fn this . increment " minutes " ) }}
190
232
>
191
233
+
192
234
</button >
@@ -196,7 +238,7 @@ export default class AuTimePicker extends Component {
196
238
aria-controls =" input-minute"
197
239
class =" au-c-time-picker__button"
198
240
data-test-autimepicker-minutedecrement
199
- {{on " click" ( fn this . decrement " minuteValue " ) }}
241
+ {{on " click" ( fn this . decrement " minutes " ) }}
200
242
>
201
243
-
202
244
</button >
@@ -217,10 +259,10 @@ export default class AuTimePicker extends Component {
217
259
class =" au-c-time-picker__input"
218
260
name =" input-second"
219
261
id =" input-second"
220
- value ={{this .secondValueFormatted }}
262
+ value ={{formatTime this . seconds }}
221
263
data-test-autimepicker-secondinput
222
- {{on " keyup" ( fn this . timeValueKeyPress " secondValue " ) }}
223
- {{on " input" ( fn this . validateTime " secondValue " ) }}
264
+ {{on " keyup" ( fn this . timeValueKeyPress " seconds " ) }}
265
+ {{on " input" ( fn this . validateTime " seconds " ) }}
224
266
/>
225
267
<div class =" au-c-time-picker__button-wrapper" >
226
268
<button
@@ -229,7 +271,7 @@ export default class AuTimePicker extends Component {
229
271
aria-controls =" input-second"
230
272
class =" au-c-time-picker__button"
231
273
data-test-autimepicker-secondincrement
232
- {{on " click" ( fn this . increment " secondValue " ) }}
274
+ {{on " click" ( fn this . increment " seconds " ) }}
233
275
>
234
276
+
235
277
</button >
@@ -239,7 +281,7 @@ export default class AuTimePicker extends Component {
239
281
aria-controls =" input-second"
240
282
class =" au-c-time-picker__button"
241
283
data-test-autimepicker-seconddecrement
242
- {{on " click" ( fn this . decrement " secondValue " ) }}
284
+ {{on " click" ( fn this . decrement " seconds " ) }}
243
285
>
244
286
-
245
287
</button >
@@ -260,12 +302,16 @@ export default class AuTimePicker extends Component {
260
302
</div >
261
303
{{/if }}
262
304
263
- <span class =" au-u-hidden-visually" >{{this .hourValue }}
305
+ <span class =" au-u-hidden-visually" >{{this .hours }}
264
306
{{@ hoursLabel }} ,
265
- {{this .minuteValue }}
307
+ {{this .minutes }}
266
308
{{@ minutesLabel }} ,
267
- {{this .secondValue }}
309
+ {{this .seconds }}
268
310
{{@ secondsLabel }} .</span >
269
311
</div >
270
312
</template >
271
313
}
314
+
315
+ function formatTime(number : number ): string {
316
+ return number .toString ().padStart (2 , ' 0' );
317
+ }
0 commit comments