superdesk-ui-framework 3.0.1-beta.4 → 3.0.1-beta.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.
- package/app-typescript/components/DurationInput.tsx +83 -61
- package/app-typescript/components/Form/InputNew.tsx +3 -1
- package/dist/examples.bundle.js +129 -109
- package/dist/superdesk-ui.bundle.js +117 -97
- package/package.json +1 -1
- package/patches/@superdesk+primereact+5.0.2-4.patch +10 -1
- package/react/components/DurationInput.d.ts +5 -2
- package/react/components/DurationInput.js +74 -56
- package/react/components/Form/InputNew.js +3 -1
@@ -2,6 +2,7 @@ import * as React from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
3
3
|
import moment from 'moment';
|
4
4
|
import nextId from "react-id-generator";
|
5
|
+
import { InputWrapper } from './Form';
|
5
6
|
|
6
7
|
interface IProps {
|
7
8
|
hours?: number;
|
@@ -24,60 +25,72 @@ interface IState {
|
|
24
25
|
hours?: any;
|
25
26
|
minutes?: any;
|
26
27
|
seconds?: any;
|
27
|
-
invalid?: any;
|
28
28
|
}
|
29
29
|
|
30
30
|
export class DurationInput extends React.PureComponent<IProps, IState> {
|
31
31
|
hourRef: React.RefObject<HTMLInputElement>;
|
32
32
|
minuteRef: React.RefObject<HTMLInputElement>;
|
33
33
|
secondRef: React.RefObject<HTMLInputElement>;
|
34
|
+
private htmlId = nextId();
|
34
35
|
constructor(props: IProps) {
|
35
36
|
super(props);
|
36
37
|
this.state = {
|
37
|
-
hours: this.props.hours
|
38
|
-
minutes: this.
|
39
|
-
seconds: this.
|
40
|
-
invalid: this.props.invalid ?? false,
|
38
|
+
hours: this.stateUpdate('hours', this.props.hours, this.props.minutes, this.props.seconds),
|
39
|
+
minutes: this.stateUpdate('minutes', this.props.minutes, this.props.seconds),
|
40
|
+
seconds: this.stateUpdate('seconds', this.props.seconds),
|
41
41
|
};
|
42
42
|
|
43
43
|
this.hourRef = React.createRef();
|
44
44
|
this.minuteRef = React.createRef();
|
45
45
|
this.secondRef = React.createRef();
|
46
46
|
this.handleKeyDown = this.handleKeyDown.bind(this);
|
47
|
-
this.
|
47
|
+
this.zeroPad = this.zeroPad.bind(this);
|
48
48
|
this.handleChange = this.handleChange.bind(this);
|
49
49
|
this.handleFocusOnKeyUp = this.handleFocusOnKeyUp.bind(this);
|
50
50
|
this.handleKeyValue = this.handleKeyValue.bind(this);
|
51
|
+
this.valueUpdate = this.valueUpdate.bind(this);
|
52
|
+
this.stateUpdate = this.stateUpdate.bind(this);
|
53
|
+
}
|
51
54
|
|
55
|
+
stateUpdate(state: string, parametar1?: number, parametar2?: number, parametar3?: number) {
|
56
|
+
let value;
|
57
|
+
if (state === 'hours') {
|
58
|
+
value = parametar1
|
59
|
+
? parametar1 + Math.floor((parametar2 || 0) / 60) + Math.floor((parametar3 || 0) / 3600)
|
60
|
+
: Math.floor((parametar2 || 0) / 60) + Math.floor((parametar3 || 0) / 3600);
|
61
|
+
} else if (state === 'minutes') {
|
62
|
+
value = parametar1
|
63
|
+
? (parametar1 % 60) + Math.floor((parametar2 || 0) % 3600 / 60)
|
64
|
+
: Math.floor((parametar2 || 0) % 3600 / 60);
|
65
|
+
} else {
|
66
|
+
value = parametar1 ? parametar1 % 60 : 0;
|
67
|
+
}
|
68
|
+
return this.zeroPad(value);
|
52
69
|
}
|
53
70
|
|
54
71
|
componentDidUpdate(_: any, prevState: IState) {
|
55
|
-
if (this.props.onChange) {
|
56
|
-
this.props.onChange(moment.duration(`${this.state.hours}:${this.state.minutes}:${this.state.seconds}`)
|
57
|
-
.asSeconds());
|
58
|
-
}
|
59
72
|
if (!this.hourRef.current || !this.minuteRef.current || !this.secondRef.current ) {
|
60
73
|
return;
|
61
74
|
}
|
62
75
|
if (this.state.hours !== prevState.hours) {
|
63
76
|
if (Number(this.hourRef.current.value) > 99) {
|
64
77
|
this.setState({
|
65
|
-
hours: this.
|
78
|
+
hours: this.zeroPad(99),
|
66
79
|
});
|
67
80
|
}
|
68
81
|
}
|
69
82
|
if (this.state.minutes !== prevState.minutes) {
|
70
83
|
if (Number(this.minuteRef.current.value) > 59) {
|
71
84
|
this.setState({
|
72
|
-
hours: this.
|
73
|
-
minutes: this.
|
85
|
+
hours: this.zeroPad(Number(this.state.hours) + 1),
|
86
|
+
minutes: this.zeroPad(this.state.minutes % 60),
|
74
87
|
});
|
75
88
|
}
|
76
89
|
if (Number(this.minuteRef.current.value) < 0) {
|
77
90
|
this.setState({
|
78
|
-
hours: this.
|
79
|
-
? this.
|
80
|
-
: this.
|
91
|
+
hours: this.zeroPad(Number(this.state.hours)) > 0
|
92
|
+
? this.zeroPad(Number(this.state.hours) - 1)
|
93
|
+
: this.zeroPad(Number(this.state.hours)),
|
81
94
|
minutes: 59,
|
82
95
|
});
|
83
96
|
}
|
@@ -85,19 +98,26 @@ export class DurationInput extends React.PureComponent<IProps, IState> {
|
|
85
98
|
if (this.state.seconds !== prevState.seconds) {
|
86
99
|
if (Number(this.secondRef.current.value) > 59) {
|
87
100
|
this.setState({
|
88
|
-
minutes: this.
|
89
|
-
seconds: this.
|
101
|
+
minutes: this.zeroPad(Number(this.state.minutes) + 1),
|
102
|
+
seconds: this.zeroPad(this.state.seconds % 60),
|
90
103
|
});
|
91
104
|
}
|
92
105
|
if (Number(this.secondRef.current.value) < 0) {
|
93
106
|
this.setState({
|
94
|
-
minutes: this.
|
107
|
+
minutes: this.zeroPad(Number(this.state.minutes) - 1),
|
95
108
|
seconds: 59,
|
96
109
|
});
|
97
110
|
}
|
98
111
|
}
|
99
112
|
}
|
100
113
|
|
114
|
+
valueUpdate() {
|
115
|
+
if (this.props.onChange) {
|
116
|
+
this.props.onChange(moment.duration(`${this.state.hours}:${this.state.minutes}:${this.state.seconds}`)
|
117
|
+
.asSeconds());
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
101
121
|
handleKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {
|
102
122
|
if (!(event.target instanceof HTMLInputElement)) {
|
103
123
|
return;
|
@@ -140,6 +160,12 @@ export class DurationInput extends React.PureComponent<IProps, IState> {
|
|
140
160
|
}
|
141
161
|
if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
|
142
162
|
this.handleKeyValue(event, event.target.id as 'hours' | 'minutes' | 'seconds');
|
163
|
+
setTimeout(this.valueUpdate);
|
164
|
+
}
|
165
|
+
if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {
|
166
|
+
if (!this.state.hours || !this.state.minutes || !this.state.seconds) {
|
167
|
+
setTimeout(this.valueUpdate);
|
168
|
+
}
|
143
169
|
}
|
144
170
|
}
|
145
171
|
|
@@ -157,22 +183,24 @@ export class DurationInput extends React.PureComponent<IProps, IState> {
|
|
157
183
|
if (event.key === 'ArrowUp') {
|
158
184
|
if (event.target.id === 'hours') {
|
159
185
|
stateClone[state] = this.state[state] < 99
|
160
|
-
? this.
|
161
|
-
: this.
|
186
|
+
? this.zeroPad(Number(this.state[state]) + 1)
|
187
|
+
: this.zeroPad(99);
|
162
188
|
} else {
|
163
|
-
stateClone[state] = this.
|
189
|
+
stateClone[state] = this.zeroPad(Number(this.state[state]) + 1);
|
164
190
|
}
|
165
191
|
} else if (event.key === 'ArrowDown') {
|
166
192
|
if (event.target.id === 'hours') {
|
167
|
-
stateClone[state] = this.state[state] > 0
|
193
|
+
stateClone[state] = this.state[state] > 0
|
194
|
+
? this.zeroPad(Number(this.state[state]) - 1)
|
195
|
+
: this.zeroPad(0);
|
168
196
|
} else {
|
169
|
-
stateClone[state] = this.
|
197
|
+
stateClone[state] = this.zeroPad(Number(this.state[state]) - 1);
|
170
198
|
}
|
171
199
|
}
|
172
200
|
this.setState(stateClone);
|
173
201
|
}
|
174
202
|
|
175
|
-
|
203
|
+
zeroPad(value: number | string) {
|
176
204
|
if (value.toString().length === 1 || value === 0) {
|
177
205
|
return `0${value}`;
|
178
206
|
} else if (!value) {
|
@@ -190,6 +218,7 @@ export class DurationInput extends React.PureComponent<IProps, IState> {
|
|
190
218
|
stateClone[state] = event.target.value;
|
191
219
|
}
|
192
220
|
this.setState(stateClone);
|
221
|
+
setTimeout(this.valueUpdate);
|
193
222
|
}
|
194
223
|
|
195
224
|
handleFocus(ref: HTMLInputElement | null, state: 'hours' | 'minutes' | 'seconds') {
|
@@ -198,18 +227,20 @@ export class DurationInput extends React.PureComponent<IProps, IState> {
|
|
198
227
|
ref?.setSelectionRange(0, 2);
|
199
228
|
});
|
200
229
|
let stateClone: IState = {};
|
201
|
-
stateClone[state] = this.
|
230
|
+
stateClone[state] = this.zeroPad(this.state[state]);
|
202
231
|
this.setState(stateClone);
|
203
232
|
}
|
204
233
|
|
205
234
|
handleFocusOnKeyUp(event: React.KeyboardEvent<HTMLInputElement>, ref: HTMLInputElement | null) {
|
206
235
|
if (event.key !== 'ArrowRight' && event.key !== 'ArrowLeft' && event.key !== 'ArrowUp' && event.key !== 'ArrowDown' && event.key !== 'Backspace') {
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
236
|
+
if ((event.keyCode > 46 && event.keyCode < 58) || (event.keyCode > 95 && event.keyCode < 106)) {
|
237
|
+
const target = event.target as HTMLInputElement;
|
238
|
+
if (target.value.length >= 2) {
|
239
|
+
ref?.focus();
|
240
|
+
setTimeout(() => {
|
241
|
+
ref?.setSelectionRange(0, 2);
|
242
|
+
});
|
243
|
+
}
|
213
244
|
}
|
214
245
|
}
|
215
246
|
}
|
@@ -217,25 +248,19 @@ export class DurationInput extends React.PureComponent<IProps, IState> {
|
|
217
248
|
render() {
|
218
249
|
let InputClasses = classNames('sd-input__duration-input');
|
219
250
|
|
220
|
-
const classes = classNames('sd-input', {
|
221
|
-
'sd-input--inline-label': this.props.inlineLabel,
|
222
|
-
'sd-input--required': this.props.required,
|
223
|
-
'sd-input--disabled': this.props.disabled,
|
224
|
-
'sd-input--full-width': this.props.fullWidth,
|
225
|
-
'sd-input--invalid': this.props.invalid || this.state.invalid,
|
226
|
-
});
|
227
|
-
const labelClasses = classNames('sd-input__label', {
|
228
|
-
'a11y-only': this.props.labelHidden,
|
229
|
-
});
|
230
|
-
|
231
|
-
let htmlId = nextId();
|
232
|
-
|
233
251
|
return (
|
234
|
-
<
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
252
|
+
<InputWrapper
|
253
|
+
label={this.props.label}
|
254
|
+
error={this.props.error}
|
255
|
+
required={this.props.required}
|
256
|
+
disabled={this.props.disabled}
|
257
|
+
invalid={this.props.invalid}
|
258
|
+
info={this.props.info}
|
259
|
+
inlineLabel={this.props.inlineLabel}
|
260
|
+
labelHidden={this.props.labelHidden}
|
261
|
+
fullWidth={this.props.fullWidth}
|
262
|
+
htmlId={this.htmlId}
|
263
|
+
tabindex={this.props.tabindex}>
|
239
264
|
<div className={InputClasses}>
|
240
265
|
<input
|
241
266
|
className='duration-input'
|
@@ -249,7 +274,7 @@ export class DurationInput extends React.PureComponent<IProps, IState> {
|
|
249
274
|
onKeyDown={(event) => this.handleKeyDown(event)}
|
250
275
|
onKeyUp={(event) => this.handleFocusOnKeyUp(event, this.minuteRef.current)}
|
251
276
|
onChange={(event) => { this.handleChange(event, 'hours'); }}
|
252
|
-
onBlur={(event) => this.setState({hours: this.
|
277
|
+
onBlur={(event) => this.setState({hours: this.zeroPad(event.target.value)})}
|
253
278
|
onKeyPress={(event) => {
|
254
279
|
if (!/[0-9]/.test(event.key)) {
|
255
280
|
event.preventDefault();
|
@@ -267,7 +292,7 @@ export class DurationInput extends React.PureComponent<IProps, IState> {
|
|
267
292
|
onKeyDown={(event) => this.handleKeyDown(event)}
|
268
293
|
onKeyUp={(event) => this.handleFocusOnKeyUp(event, this.secondRef.current)}
|
269
294
|
onChange={(event) => { this.handleChange(event, 'minutes'); }}
|
270
|
-
onBlur={(event) => this.setState({minutes: this.
|
295
|
+
onBlur={(event) => this.setState({minutes: this.zeroPad(event.target.value)})}
|
271
296
|
onKeyPress={(event) => {
|
272
297
|
if (!/[0-9]/.test(event.key)) {
|
273
298
|
event.preventDefault();
|
@@ -285,7 +310,7 @@ export class DurationInput extends React.PureComponent<IProps, IState> {
|
|
285
310
|
onKeyDown={(event) => this.handleKeyDown(event)}
|
286
311
|
onKeyUp={(event) => this.handleFocusOnKeyUp(event, this.hourRef.current)}
|
287
312
|
onChange={(event) => { this.handleChange(event, 'seconds'); }}
|
288
|
-
onBlur={(event) => this.setState({seconds: this.
|
313
|
+
onBlur={(event) => this.setState({seconds: this.zeroPad(event.target.value)})}
|
289
314
|
onKeyPress={(event) => {
|
290
315
|
if (!/[0-9]/.test(event.key)) {
|
291
316
|
event.preventDefault();
|
@@ -293,14 +318,11 @@ export class DurationInput extends React.PureComponent<IProps, IState> {
|
|
293
318
|
}} />
|
294
319
|
<span className='sd-input__suffix'>s</span>
|
295
320
|
</div>
|
296
|
-
|
297
|
-
{this.props.info && !this.props.invalid && !this.state.invalid ?
|
298
|
-
<div className='sd-input__hint'>{this.props.info}</div> : null}
|
299
|
-
{this.props.invalid || this.state.invalid ?
|
300
|
-
<div className='sd-input__message'>{this.props.error}</div>
|
301
|
-
: null}
|
302
|
-
</div>
|
303
|
-
</div>
|
321
|
+
</InputWrapper>
|
304
322
|
);
|
305
323
|
}
|
306
324
|
}
|
325
|
+
|
326
|
+
export function getDurationString(seconds: number) {
|
327
|
+
return moment.utc(seconds * 1000).format("HH:mm:ss");
|
328
|
+
}
|
@@ -90,7 +90,9 @@ export class InputNew extends React.PureComponent<IProps, IState> {
|
|
90
90
|
type="text"
|
91
91
|
onChange={(value: string) => {
|
92
92
|
this.setState({ value: value });
|
93
|
-
this.setState({ invalid: this.props.maxLength
|
93
|
+
this.setState({ invalid: this.props.maxLength
|
94
|
+
? (value as string).length > this.props.maxLength
|
95
|
+
: false });
|
94
96
|
this.props.onChange(value as string);
|
95
97
|
}}
|
96
98
|
disabled={this.props.disabled}
|