@semcore/time-picker 3.0.13 → 3.0.16
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/CHANGELOG.md +18 -0
- package/lib/cjs/TimePicker.js +13 -13
- package/lib/es6/TimePicker.js +13 -13
- package/package.json +1 -1
- package/src/PickerFormat.jsx +0 -21
- package/src/PickerInput.jsx +0 -217
- package/src/TimePicker.jsx +0 -243
- package/src/index.d.ts +0 -47
- package/src/index.js +0 -2
- package/src/style/time-picker.shadow.css +0 -99
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
CHANGELOG.md standards are inspired by [keepachangelog.com](https://keepachangelog.com/en/1.0.0/).
|
|
4
4
|
|
|
5
|
+
## [3.0.16] - 2022-07-21
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Version patch update due to children dependencies update (`@semcore/select` [3.0.13 ~> 3.0.14]).
|
|
10
|
+
|
|
11
|
+
## [3.0.15] - 2022-07-18
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Version patch update due to children dependencies update (`@semcore/select` [3.0.12 ~> 3.0.13]).
|
|
16
|
+
|
|
17
|
+
## [3.0.14] - 2022-07-14
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Version patch update due to children dependencies update (`@semcore/input` [3.0.7 ~> 3.0.8], `@semcore/select` [3.0.11 ~> 3.0.12]).
|
|
22
|
+
|
|
5
23
|
## [3.0.13] - 2022-07-14
|
|
6
24
|
|
|
7
25
|
### Changed
|
package/lib/cjs/TimePicker.js
CHANGED
|
@@ -61,22 +61,22 @@ var style = (
|
|
|
61
61
|
/*__reshadow_css_start__*/
|
|
62
62
|
_core.sstyled.insert(
|
|
63
63
|
/*__inner_css_start__*/
|
|
64
|
-
".
|
|
64
|
+
".___STimePicker_18gcr_gg_{position:relative;width:auto}.___STimePicker_18gcr_gg_.__disabled_18gcr_gg_{color:rgba(25,27,35,.3);cursor:default}.___SPickerInput_18gcr_gg_{box-sizing:content-box;text-align:center;z-index:1}.___SPickerInput_18gcr_gg_.__placeholder_18gcr_gg_{text-overflow:clip}.___SPickerInput_18gcr_gg_._size_m_18gcr_gg_{width:19px}.___SPickerInput_18gcr_gg_._size_l_18gcr_gg_{width:21px}.___SPickerFormat_18gcr_gg_{flex-shrink:0;position:relative;display:inline-flex;padding:0;white-space:nowrap;font-family:inherit;font-weight:500;line-height:normal;text-decoration:none;align-items:center;border:1px solid #c4c7cf;border-radius:0 6px 6px 0;outline:0;box-shadow:none;cursor:pointer;box-sizing:border-box;overflow:visible;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;touch-action:manipulation;-webkit-tap-highlight-color:transparent;color:#6c6e79;background-color:rgba(138,142,155,.1)}.___SPickerFormat_18gcr_gg_:hover{color:#6c6e79;background-color:rgba(138,142,155,.2)}.___SPickerFormat_18gcr_gg_:active,.___SPickerFormat_18gcr_gg_.__active_18gcr_gg_{color:#6c6e79;background-color:rgba(138,142,155,.3)}.___SPickerFormat_18gcr_gg_._size_m_18gcr_gg_{height:28px;font-size:14px;margin:0 -1px 0 0}.___SPickerFormat_18gcr_gg_._size_m_18gcr_gg_ .___SPickerFormatText_18gcr_gg_{margin:0 8px}.___SPickerFormat_18gcr_gg_._size_l_18gcr_gg_{height:40px;font-size:16px;margin:0 -4px 0 0}.___SPickerFormat_18gcr_gg_._size_l_18gcr_gg_ .___SPickerFormatText_18gcr_gg_{margin:0 12px}.___SPickerFormat_18gcr_gg_.__disabled_18gcr_gg_{opacity:0.3;cursor:default;pointer-events:none;border-color:transparent transparent transparent #c4c7cf}.___SPickerFormat_18gcr_gg_.__keyboardFocused_18gcr_gg_{box-shadow:0 0 0 3px rgba(0, 143, 248, 0.2)}.___STimePickerSeparator_18gcr_gg_.__disabled_18gcr_gg_{opacity:0.3;pointer-events:none}"
|
|
65
65
|
/*__inner_css_end__*/
|
|
66
|
-
, "
|
|
66
|
+
, "18gcr_gg_")
|
|
67
67
|
/*__reshadow_css_end__*/
|
|
68
68
|
, {
|
|
69
|
-
"__STimePicker": "
|
|
70
|
-
"_disabled": "
|
|
71
|
-
"__SPickerInput": "
|
|
72
|
-
"_placeholder": "
|
|
73
|
-
"_size_m": "
|
|
74
|
-
"_size_l": "
|
|
75
|
-
"__SPickerFormat": "
|
|
76
|
-
"_active": "
|
|
77
|
-
"__SPickerFormatText": "
|
|
78
|
-
"_keyboardFocused": "
|
|
79
|
-
"__STimePickerSeparator": "
|
|
69
|
+
"__STimePicker": "___STimePicker_18gcr_gg_",
|
|
70
|
+
"_disabled": "__disabled_18gcr_gg_",
|
|
71
|
+
"__SPickerInput": "___SPickerInput_18gcr_gg_",
|
|
72
|
+
"_placeholder": "__placeholder_18gcr_gg_",
|
|
73
|
+
"_size_m": "_size_m_18gcr_gg_",
|
|
74
|
+
"_size_l": "_size_l_18gcr_gg_",
|
|
75
|
+
"__SPickerFormat": "___SPickerFormat_18gcr_gg_",
|
|
76
|
+
"_active": "__active_18gcr_gg_",
|
|
77
|
+
"__SPickerFormatText": "___SPickerFormatText_18gcr_gg_",
|
|
78
|
+
"_keyboardFocused": "__keyboardFocused_18gcr_gg_",
|
|
79
|
+
"__STimePickerSeparator": "___STimePickerSeparator_18gcr_gg_"
|
|
80
80
|
});
|
|
81
81
|
var MAP_MERIDIEM = {
|
|
82
82
|
AM: 'PM',
|
package/lib/es6/TimePicker.js
CHANGED
|
@@ -30,22 +30,22 @@ var style = (
|
|
|
30
30
|
/*__reshadow_css_start__*/
|
|
31
31
|
_sstyled.insert(
|
|
32
32
|
/*__inner_css_start__*/
|
|
33
|
-
".
|
|
33
|
+
".___STimePicker_18gcr_gg_{position:relative;width:auto}.___STimePicker_18gcr_gg_.__disabled_18gcr_gg_{color:rgba(25,27,35,.3);cursor:default}.___SPickerInput_18gcr_gg_{box-sizing:content-box;text-align:center;z-index:1}.___SPickerInput_18gcr_gg_.__placeholder_18gcr_gg_{text-overflow:clip}.___SPickerInput_18gcr_gg_._size_m_18gcr_gg_{width:19px}.___SPickerInput_18gcr_gg_._size_l_18gcr_gg_{width:21px}.___SPickerFormat_18gcr_gg_{flex-shrink:0;position:relative;display:inline-flex;padding:0;white-space:nowrap;font-family:inherit;font-weight:500;line-height:normal;text-decoration:none;align-items:center;border:1px solid #c4c7cf;border-radius:0 6px 6px 0;outline:0;box-shadow:none;cursor:pointer;box-sizing:border-box;overflow:visible;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;touch-action:manipulation;-webkit-tap-highlight-color:transparent;color:#6c6e79;background-color:rgba(138,142,155,.1)}.___SPickerFormat_18gcr_gg_:hover{color:#6c6e79;background-color:rgba(138,142,155,.2)}.___SPickerFormat_18gcr_gg_:active,.___SPickerFormat_18gcr_gg_.__active_18gcr_gg_{color:#6c6e79;background-color:rgba(138,142,155,.3)}.___SPickerFormat_18gcr_gg_._size_m_18gcr_gg_{height:28px;font-size:14px;margin:0 -1px 0 0}.___SPickerFormat_18gcr_gg_._size_m_18gcr_gg_ .___SPickerFormatText_18gcr_gg_{margin:0 8px}.___SPickerFormat_18gcr_gg_._size_l_18gcr_gg_{height:40px;font-size:16px;margin:0 -4px 0 0}.___SPickerFormat_18gcr_gg_._size_l_18gcr_gg_ .___SPickerFormatText_18gcr_gg_{margin:0 12px}.___SPickerFormat_18gcr_gg_.__disabled_18gcr_gg_{opacity:0.3;cursor:default;pointer-events:none;border-color:transparent transparent transparent #c4c7cf}.___SPickerFormat_18gcr_gg_.__keyboardFocused_18gcr_gg_{box-shadow:0 0 0 3px rgba(0, 143, 248, 0.2)}.___STimePickerSeparator_18gcr_gg_.__disabled_18gcr_gg_{opacity:0.3;pointer-events:none}"
|
|
34
34
|
/*__inner_css_end__*/
|
|
35
|
-
, "
|
|
35
|
+
, "18gcr_gg_")
|
|
36
36
|
/*__reshadow_css_end__*/
|
|
37
37
|
, {
|
|
38
|
-
"__STimePicker": "
|
|
39
|
-
"_disabled": "
|
|
40
|
-
"__SPickerInput": "
|
|
41
|
-
"_placeholder": "
|
|
42
|
-
"_size_m": "
|
|
43
|
-
"_size_l": "
|
|
44
|
-
"__SPickerFormat": "
|
|
45
|
-
"_active": "
|
|
46
|
-
"__SPickerFormatText": "
|
|
47
|
-
"_keyboardFocused": "
|
|
48
|
-
"__STimePickerSeparator": "
|
|
38
|
+
"__STimePicker": "___STimePicker_18gcr_gg_",
|
|
39
|
+
"_disabled": "__disabled_18gcr_gg_",
|
|
40
|
+
"__SPickerInput": "___SPickerInput_18gcr_gg_",
|
|
41
|
+
"_placeholder": "__placeholder_18gcr_gg_",
|
|
42
|
+
"_size_m": "_size_m_18gcr_gg_",
|
|
43
|
+
"_size_l": "_size_l_18gcr_gg_",
|
|
44
|
+
"__SPickerFormat": "___SPickerFormat_18gcr_gg_",
|
|
45
|
+
"_active": "__active_18gcr_gg_",
|
|
46
|
+
"__SPickerFormatText": "___SPickerFormatText_18gcr_gg_",
|
|
47
|
+
"_keyboardFocused": "__keyboardFocused_18gcr_gg_",
|
|
48
|
+
"__STimePickerSeparator": "___STimePickerSeparator_18gcr_gg_"
|
|
49
49
|
});
|
|
50
50
|
var MAP_MERIDIEM = {
|
|
51
51
|
AM: 'PM',
|
package/package.json
CHANGED
package/src/PickerFormat.jsx
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Component, sstyled, Root } from '@semcore/core';
|
|
3
|
-
import { Box } from '@semcore/flex-box';
|
|
4
|
-
import keyboardFocusEnhance from '@semcore/utils/lib/enhances/keyboardFocusEnhance';
|
|
5
|
-
|
|
6
|
-
class TimePickerFormat extends Component {
|
|
7
|
-
static enhance = [keyboardFocusEnhance()];
|
|
8
|
-
render() {
|
|
9
|
-
const SPickerFormat = Root;
|
|
10
|
-
const { Children, meridiem, styles } = this.asProps;
|
|
11
|
-
const SPickerFormatText = 'span';
|
|
12
|
-
|
|
13
|
-
return sstyled(styles)(
|
|
14
|
-
<SPickerFormat render={Box} type="button" tag="button">
|
|
15
|
-
{Children.origin ? <Children /> : <SPickerFormatText>{meridiem}</SPickerFormatText>}
|
|
16
|
-
</SPickerFormat>,
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export default TimePickerFormat;
|
package/src/PickerInput.jsx
DELETED
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import Input from '@semcore/input';
|
|
3
|
-
import Select from '@semcore/select';
|
|
4
|
-
import { intOrDefault, nextInput, prevInput, withLeadingZero } from './TimePicker';
|
|
5
|
-
import { Component, sstyled, Root } from '@semcore/core';
|
|
6
|
-
import { callAllEventHandlers } from '@semcore/utils/lib/assignProps';
|
|
7
|
-
|
|
8
|
-
const MAP_FIELD_TO_TIME = {
|
|
9
|
-
hours: 0,
|
|
10
|
-
minutes: 1,
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const MAP_SIZE_SELECT = {
|
|
14
|
-
m: 'm',
|
|
15
|
-
l: 'l',
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
function getOptions(min, max, step = 1) {
|
|
19
|
-
const length = Number(((max + 1 - min) / step).toFixed(0));
|
|
20
|
-
const options = Array(length).fill('');
|
|
21
|
-
let numValue = min;
|
|
22
|
-
return options.map((i, index) => {
|
|
23
|
-
numValue = index === 0 ? numValue : numValue + step;
|
|
24
|
-
const value = withLeadingZero(String(numValue));
|
|
25
|
-
return (
|
|
26
|
-
<Select.Option value={value} key={value}>
|
|
27
|
-
{value}
|
|
28
|
-
</Select.Option>
|
|
29
|
-
);
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
class ItemPicker extends Component {
|
|
34
|
-
static defaultProps = {
|
|
35
|
-
placeholder: '00',
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
$input = React.createRef();
|
|
39
|
-
|
|
40
|
-
minMax() {
|
|
41
|
-
return [];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
state = {
|
|
45
|
-
dirtyValue: undefined,
|
|
46
|
-
visible: false,
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
parseValueWithMinMax = (value) => {
|
|
50
|
-
const [min, max] = this.minMax();
|
|
51
|
-
return String(Math.max(min, Math.min(max, value)));
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
dispatchOnChange(value, event) {
|
|
55
|
-
this.setState({ dirtyValue: undefined });
|
|
56
|
-
this.asProps.$onValueChange(value, this.field, event);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
submitChanges(event) {
|
|
60
|
-
let { dirtyValue } = this.state;
|
|
61
|
-
if (dirtyValue !== undefined) {
|
|
62
|
-
// if changes value
|
|
63
|
-
if (dirtyValue) dirtyValue = this.parseValueWithMinMax(dirtyValue); // if not ""
|
|
64
|
-
this.dispatchOnChange(dirtyValue, event);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
handleChange = (value, e) => {
|
|
69
|
-
/* hide props for bubbling events */
|
|
70
|
-
e.stopPropagation();
|
|
71
|
-
const numberValue = intOrDefault(Number(value), NaN);
|
|
72
|
-
|
|
73
|
-
if (!Number.isNaN(numberValue)) {
|
|
74
|
-
this.setState({ dirtyValue: value.slice(-2) });
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
handleBlur = (e) => this.submitChanges(e);
|
|
79
|
-
|
|
80
|
-
handleFocus = () => {
|
|
81
|
-
this.$input?.current.select();
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
/* rewrite method */
|
|
85
|
-
handleKeyDown = () => {};
|
|
86
|
-
|
|
87
|
-
handleSelect = (value, e) => {
|
|
88
|
-
this.dispatchOnChange(value, e);
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
handleVisibleChange = (visible) => this.setState({ visible });
|
|
92
|
-
|
|
93
|
-
render() {
|
|
94
|
-
const SPickerInput = Root;
|
|
95
|
-
const { styles, step, onSelect, time, size, disabled, onVisibleChange, ...other } =
|
|
96
|
-
this.asProps;
|
|
97
|
-
const { dirtyValue, visible } = this.state;
|
|
98
|
-
const timeValue = time[MAP_FIELD_TO_TIME[this.field]];
|
|
99
|
-
const value = dirtyValue === undefined ? timeValue : dirtyValue;
|
|
100
|
-
const [min, max] = this.minMax();
|
|
101
|
-
|
|
102
|
-
return sstyled(styles)(
|
|
103
|
-
<Select
|
|
104
|
-
{...other}
|
|
105
|
-
interaction="focus"
|
|
106
|
-
size={size ? MAP_SIZE_SELECT[size] : false}
|
|
107
|
-
onChange={callAllEventHandlers(onSelect, this.handleSelect)}
|
|
108
|
-
onVisibleChange={callAllEventHandlers(onVisibleChange, this.handleVisibleChange)}
|
|
109
|
-
visible={visible}
|
|
110
|
-
value={timeValue}
|
|
111
|
-
>
|
|
112
|
-
<SPickerInput
|
|
113
|
-
interaction="focus"
|
|
114
|
-
render={Select.Trigger}
|
|
115
|
-
tag={Input.Value}
|
|
116
|
-
ref={this.$input}
|
|
117
|
-
size={size}
|
|
118
|
-
disabled={disabled}
|
|
119
|
-
neighborLocation={false}
|
|
120
|
-
value={value}
|
|
121
|
-
aria-label={`Search ${this.field}`}
|
|
122
|
-
onChange={this.handleChange}
|
|
123
|
-
onBlur={this.handleBlur}
|
|
124
|
-
onFocus={this.handleFocus}
|
|
125
|
-
onKeyDown={this.handleKeyDown}
|
|
126
|
-
/>
|
|
127
|
-
<Select.Menu hMax={180}>{getOptions(min, max, step)}</Select.Menu>
|
|
128
|
-
</Select>,
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
class Hours extends ItemPicker {
|
|
134
|
-
field = 'hours';
|
|
135
|
-
|
|
136
|
-
minMax() {
|
|
137
|
-
const { is12Hour } = this.asProps;
|
|
138
|
-
if (is12Hour) {
|
|
139
|
-
return [1, 12];
|
|
140
|
-
} else {
|
|
141
|
-
return [0, 23];
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
nextInput() {
|
|
146
|
-
if (this.$input.current) {
|
|
147
|
-
const $input = nextInput(this.$input.current);
|
|
148
|
-
if ($input) {
|
|
149
|
-
this.setState({ visible: false });
|
|
150
|
-
$input.focus();
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
handleKeyDown = (e) => {
|
|
156
|
-
const { currentTarget } = e;
|
|
157
|
-
if (e.keyCode === 13) this.submitChanges(e);
|
|
158
|
-
if (e.keyCode === 39) {
|
|
159
|
-
if (
|
|
160
|
-
currentTarget.selectionStart >= currentTarget.value.length &&
|
|
161
|
-
currentTarget.selectionStart === currentTarget.selectionEnd
|
|
162
|
-
) {
|
|
163
|
-
e.preventDefault();
|
|
164
|
-
this.nextInput();
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
componentDidUpdate(prevProps, prevState) {
|
|
170
|
-
const { dirtyValue } = this.state;
|
|
171
|
-
if (prevState.dirtyValue === undefined || dirtyValue === undefined) return;
|
|
172
|
-
|
|
173
|
-
if (prevState.dirtyValue.length === 1 && dirtyValue.length === 2) {
|
|
174
|
-
this.nextInput();
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
class Minutes extends ItemPicker {
|
|
180
|
-
field = 'minutes';
|
|
181
|
-
|
|
182
|
-
minMax() {
|
|
183
|
-
return [0, 59];
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
prevFocus() {
|
|
187
|
-
if (this.$input.current) {
|
|
188
|
-
const $input = prevInput(this.$input.current);
|
|
189
|
-
if ($input) {
|
|
190
|
-
this.setState({ visible: false });
|
|
191
|
-
$input.focus();
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
handleKeyDown = (e) => {
|
|
197
|
-
const { currentTarget } = e;
|
|
198
|
-
if (e.keyCode === 13) this.submitChanges(e);
|
|
199
|
-
if (e.keyCode === 37) {
|
|
200
|
-
if (
|
|
201
|
-
currentTarget.selectionStart <= 0 &&
|
|
202
|
-
currentTarget.selectionStart === currentTarget.selectionEnd
|
|
203
|
-
) {
|
|
204
|
-
e.preventDefault();
|
|
205
|
-
this.prevFocus();
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
if (e.keyCode === 8) {
|
|
209
|
-
if (currentTarget.value.length === 0) {
|
|
210
|
-
e.preventDefault();
|
|
211
|
-
this.prevFocus();
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
export { Hours, Minutes };
|
package/src/TimePicker.jsx
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import createComponent, { Component, sstyled, Root } from '@semcore/core';
|
|
3
|
-
import Input from '@semcore/input';
|
|
4
|
-
import { Box } from '@semcore/flex-box';
|
|
5
|
-
import { Hours, Minutes } from './PickerInput';
|
|
6
|
-
import Format from './PickerFormat';
|
|
7
|
-
|
|
8
|
-
import style from './style/time-picker.shadow.css';
|
|
9
|
-
|
|
10
|
-
const MAP_MERIDIEM = {
|
|
11
|
-
AM: 'PM',
|
|
12
|
-
PM: 'AM',
|
|
13
|
-
};
|
|
14
|
-
const MAP_FIELD_TO_TIME = {
|
|
15
|
-
hours: 0,
|
|
16
|
-
minutes: 1,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export function nextInput(element) {
|
|
20
|
-
do {
|
|
21
|
-
element = element.nextElementSibling;
|
|
22
|
-
} while (element && element.tagName !== 'INPUT');
|
|
23
|
-
return element;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function prevInput(element) {
|
|
27
|
-
do {
|
|
28
|
-
element = element.previousElementSibling;
|
|
29
|
-
} while (element && element.tagName !== 'INPUT');
|
|
30
|
-
return element;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function intOrDefault(value, def = 0) {
|
|
34
|
-
const number = Number.parseInt(value);
|
|
35
|
-
return Number.isNaN(number) ? def : number;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function withLeadingZero(value) {
|
|
39
|
-
value = String(value);
|
|
40
|
-
if (value.length === 1) return `0${value}`;
|
|
41
|
-
return String(value);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function meridiemByHours(hours) {
|
|
45
|
-
return hours >= 12 ? 'PM' : 'AM';
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function formatHoursTo12(hours /* hours by 24 */) {
|
|
49
|
-
const nHours = intOrDefault(hours, NaN); // if not (:00)
|
|
50
|
-
if (Number.isNaN(nHours)) return hours;
|
|
51
|
-
|
|
52
|
-
// if not (HH:00)
|
|
53
|
-
if (nHours === 0) return 12; // 0 => 12 PM
|
|
54
|
-
if (nHours > 12) return nHours - 12; // 22 => 12 PM
|
|
55
|
-
|
|
56
|
-
return hours;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function formatHoursTo24(hours /* hours by 12 */, meridiem) {
|
|
60
|
-
const nHours = intOrDefault(hours, NaN); // if not (:00)
|
|
61
|
-
|
|
62
|
-
if (Number.isNaN(nHours)) return hours;
|
|
63
|
-
|
|
64
|
-
if (meridiem === 'AM') {
|
|
65
|
-
if (nHours === 12) return 0; // 12 AM => 0
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (meridiem === 'PM') {
|
|
69
|
-
if (nHours < 12) return nHours + 12; // 10 PM => 22
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return hours;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
class TimePickerRoot extends Component {
|
|
76
|
-
static displayName = 'TimePicker';
|
|
77
|
-
static style = style;
|
|
78
|
-
static defaultProps = ({ is12Hour }) => ({
|
|
79
|
-
defaultValue: '',
|
|
80
|
-
size: 'm',
|
|
81
|
-
children: (
|
|
82
|
-
<>
|
|
83
|
-
<TimePicker.Hours />
|
|
84
|
-
<TimePicker.Separator />
|
|
85
|
-
<TimePicker.Minutes />
|
|
86
|
-
{is12Hour && <TimePicker.Format />}
|
|
87
|
-
</>
|
|
88
|
-
),
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
_lastMeridiem = 'AM'; // default AM
|
|
92
|
-
|
|
93
|
-
uncontrolledProps() {
|
|
94
|
-
return {
|
|
95
|
-
value: null,
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
get value() {
|
|
100
|
-
const { value } = this.asProps;
|
|
101
|
-
return value === null || value === undefined ? ':' : value;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
get meridiem() {
|
|
105
|
-
const { value } = this.asProps;
|
|
106
|
-
const [hours = ''] = value.split(':');
|
|
107
|
-
|
|
108
|
-
const nHours = intOrDefault(hours, NaN);
|
|
109
|
-
|
|
110
|
-
if (!Number.isNaN(nHours)) {
|
|
111
|
-
this._lastMeridiem = meridiemByHours(nHours);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return this._lastMeridiem;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
valueToTime(value) {
|
|
118
|
-
const { is12Hour } = this.asProps;
|
|
119
|
-
let [hours = '', minutes = ''] = value.split(':');
|
|
120
|
-
|
|
121
|
-
if (is12Hour) hours = formatHoursTo12(hours);
|
|
122
|
-
|
|
123
|
-
hours = withLeadingZero(hours);
|
|
124
|
-
minutes = withLeadingZero(minutes);
|
|
125
|
-
|
|
126
|
-
return [hours, minutes];
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
timeToValue(time, meridiem) {
|
|
130
|
-
const { is12Hour } = this.asProps;
|
|
131
|
-
let [hours = '', minutes = ''] = time;
|
|
132
|
-
|
|
133
|
-
hours = intOrDefault(hours, hours); // 03 => 3
|
|
134
|
-
minutes = intOrDefault(minutes, minutes); // MM => MM
|
|
135
|
-
|
|
136
|
-
if (is12Hour) hours = formatHoursTo24(hours, meridiem); // 12 PM -> 0
|
|
137
|
-
|
|
138
|
-
return `${hours}:${minutes}`;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
handleValueChange = (value, field, event) => {
|
|
142
|
-
const { is12Hour } = this.asProps;
|
|
143
|
-
const { meridiem } = this;
|
|
144
|
-
|
|
145
|
-
let time;
|
|
146
|
-
if (field) {
|
|
147
|
-
time = this.value.split(':');
|
|
148
|
-
time[MAP_FIELD_TO_TIME[field]] = value;
|
|
149
|
-
} else {
|
|
150
|
-
time = value.split(':');
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
let [hours = '', minutes = ''] = time;
|
|
154
|
-
|
|
155
|
-
if (is12Hour) hours = String(formatHoursTo12(hours));
|
|
156
|
-
|
|
157
|
-
value = this.timeToValue([hours, minutes], meridiem);
|
|
158
|
-
this.handlers.value(value, event);
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
handleMeridiemClick = (event) => {
|
|
162
|
-
const { is12Hour } = this.asProps;
|
|
163
|
-
let { value, meridiem } = this;
|
|
164
|
-
let [hours = '', minutes = ''] = value.split(':');
|
|
165
|
-
|
|
166
|
-
if (is12Hour) hours = String(formatHoursTo12(hours));
|
|
167
|
-
|
|
168
|
-
value = this.timeToValue([hours, minutes], MAP_MERIDIEM[meridiem]);
|
|
169
|
-
this.handlers.value(value, event);
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
_getHoursAndMinutesProps = () => {
|
|
173
|
-
const { is12Hour, size, disabled } = this.asProps;
|
|
174
|
-
const time = this.valueToTime(this.value);
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
time,
|
|
178
|
-
size,
|
|
179
|
-
is12Hour,
|
|
180
|
-
disabled,
|
|
181
|
-
$onValueChange: this.handleValueChange,
|
|
182
|
-
};
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
getHoursProps = this._getHoursAndMinutesProps;
|
|
186
|
-
getMinutesProps = this._getHoursAndMinutesProps;
|
|
187
|
-
|
|
188
|
-
getSeparatorProps() {
|
|
189
|
-
return {
|
|
190
|
-
disabled: this.asProps.disabled,
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
getFormatProps() {
|
|
195
|
-
const { size, disabled, disablePortal } = this.asProps;
|
|
196
|
-
return {
|
|
197
|
-
size,
|
|
198
|
-
disabled,
|
|
199
|
-
disablePortal,
|
|
200
|
-
meridiem: this.meridiem,
|
|
201
|
-
onClick: this.handleMeridiemClick,
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
render() {
|
|
206
|
-
const STimePicker = Root;
|
|
207
|
-
const { styles, Children } = this.asProps;
|
|
208
|
-
|
|
209
|
-
return sstyled(styles)(
|
|
210
|
-
<STimePicker render={Input}>
|
|
211
|
-
<Children />
|
|
212
|
-
</STimePicker>,
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
class Separator extends Component {
|
|
218
|
-
static defaultProps = {
|
|
219
|
-
children: ':',
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
$el = React.createRef();
|
|
223
|
-
|
|
224
|
-
handlerClick = () => {
|
|
225
|
-
if (this.$el.current) {
|
|
226
|
-
prevInput(this.$el.current)?.focus();
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
render() {
|
|
231
|
-
const STimePickerSeparator = Root;
|
|
232
|
-
return <STimePickerSeparator render={Box} ref={this.$el} onClick={this.handlerClick} />;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
const TimePicker = createComponent(TimePickerRoot, {
|
|
237
|
-
Hours,
|
|
238
|
-
Minutes,
|
|
239
|
-
Separator,
|
|
240
|
-
Format,
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
export default TimePicker;
|
package/src/index.d.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { CProps, PropGetterFn, ReturnEl } from '@semcore/core';
|
|
3
|
-
import { IInputProps, IInputValueProps } from '@semcore/input';
|
|
4
|
-
import { Box, IBoxProps } from '@semcore/flex-box';
|
|
5
|
-
import { IKeyboardFocusProps } from '@semcore/utils/lib/enhances/keyboardFocusEnhance';
|
|
6
|
-
|
|
7
|
-
export interface ITimePickerProps extends Omit<IInputProps, 'size'> {
|
|
8
|
-
/** Time in the hh:mm format */
|
|
9
|
-
value?: string;
|
|
10
|
-
/** The event responses upon time changing */
|
|
11
|
-
onChange?: (time: string, event?: React.SyntheticEvent) => void;
|
|
12
|
-
/** In charge of the component blocking */
|
|
13
|
-
disabled?: boolean;
|
|
14
|
-
/** Control size
|
|
15
|
-
* @default m */
|
|
16
|
-
size?: 'm' | 'l';
|
|
17
|
-
/** 12-hour time format */
|
|
18
|
-
is12Hour?: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface ITimePickerItemProps extends IInputValueProps {
|
|
22
|
-
/** Step for changing of the values in the dropdown list */
|
|
23
|
-
step?: number;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface ITimePickerFormatProps extends IBoxProps, IKeyboardFocusProps {}
|
|
27
|
-
|
|
28
|
-
export interface ITimePickerContext {
|
|
29
|
-
getHoursProps: PropGetterFn;
|
|
30
|
-
getFormatProps: PropGetterFn;
|
|
31
|
-
getMinutesProps: PropGetterFn;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface ITimePickerHandlers {
|
|
35
|
-
value: (value: string) => void;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
declare const TimePicker: (<T>(
|
|
39
|
-
props: CProps<ITimePickerProps & T, ITimePickerContext, ITimePickerHandlers>,
|
|
40
|
-
) => ReturnEl) & {
|
|
41
|
-
Hours: <T>(props: ITimePickerItemProps & T) => ReturnEl;
|
|
42
|
-
Minutes: <T>(props: ITimePickerItemProps & T) => ReturnEl;
|
|
43
|
-
Separator: typeof Box;
|
|
44
|
-
Format: <T>(props: ITimePickerFormatProps & T) => ReturnEl;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export default TimePicker;
|
package/src/index.js
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
@import '@semcore/utils/style/var.css';
|
|
2
|
-
|
|
3
|
-
STimePicker {
|
|
4
|
-
position: relative;
|
|
5
|
-
width: auto;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
STimePicker[disabled] {
|
|
9
|
-
color: color-mod(var(--gray-800) a(30%));
|
|
10
|
-
cursor: default;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
SPickerInput {
|
|
14
|
-
box-sizing: content-box;
|
|
15
|
-
text-align: center;
|
|
16
|
-
z-index: 1;
|
|
17
|
-
|
|
18
|
-
&[placeholder] {
|
|
19
|
-
text-overflow: initial;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
SPickerInput[size='m'] {
|
|
24
|
-
width: 19px;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
SPickerInput[size='l'] {
|
|
28
|
-
width: 21px;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
SPickerFormat {
|
|
32
|
-
flex-shrink: 0;
|
|
33
|
-
position: relative;
|
|
34
|
-
display: inline-flex;
|
|
35
|
-
padding: 0;
|
|
36
|
-
white-space: nowrap;
|
|
37
|
-
font-family: inherit;
|
|
38
|
-
font-weight: 500;
|
|
39
|
-
line-height: normal;
|
|
40
|
-
text-decoration: none;
|
|
41
|
-
align-items: center;
|
|
42
|
-
border: 1px solid var(--gray-200);
|
|
43
|
-
border-radius: 0 var(--rounded-m) var(--rounded-m) 0;
|
|
44
|
-
outline: 0;
|
|
45
|
-
box-shadow: none;
|
|
46
|
-
cursor: pointer;
|
|
47
|
-
box-sizing: border-box;
|
|
48
|
-
overflow: visible;
|
|
49
|
-
user-select: none;
|
|
50
|
-
touch-action: manipulation;
|
|
51
|
-
-webkit-tap-highlight-color: transparent;
|
|
52
|
-
color: var(--gray-500);
|
|
53
|
-
background-color: color-mod(var(--gray-400) a(10%));
|
|
54
|
-
|
|
55
|
-
&:hover {
|
|
56
|
-
color: var(--gray-500);
|
|
57
|
-
background-color: color-mod(var(--gray-400) a(20%));
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
&:active,
|
|
61
|
-
&[active] {
|
|
62
|
-
color: var(--gray-500);
|
|
63
|
-
background-color: color-mod(var(--gray-400) a(30%));
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
SPickerFormat[size='m'] {
|
|
68
|
-
height: var(--form-control-m);
|
|
69
|
-
font-size: var(--fs-200);
|
|
70
|
-
margin: 0 -1px 0 0;
|
|
71
|
-
& SPickerFormatText {
|
|
72
|
-
margin: 0 8px;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
SPickerFormat[size='l'] {
|
|
77
|
-
height: var(--form-control-l);
|
|
78
|
-
font-size: var(--fs-300);
|
|
79
|
-
margin: 0 -4px 0 0;
|
|
80
|
-
& SPickerFormatText {
|
|
81
|
-
margin: 0 12px;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
SPickerFormat[disabled] {
|
|
86
|
-
opacity: var(--disabled-opacity);
|
|
87
|
-
cursor: default;
|
|
88
|
-
pointer-events: none;
|
|
89
|
-
border-color: transparent transparent transparent var(--gray-200);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
SPickerFormat[keyboardFocused] {
|
|
93
|
-
box-shadow: var(--keyboard-focus);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
STimePickerSeparator[disabled] {
|
|
97
|
-
opacity: var(--disabled-opacity);
|
|
98
|
-
pointer-events: none;
|
|
99
|
-
}
|