@vuu-ui/vuu-ui-controls 4.0.0-alpha.2 → 4.0.0-alpha.20
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/package.json +11 -10
- package/src/index.js +0 -1
- package/src/item-picker/ItemPicker.css.js +0 -4
- package/src/item-picker/ItemPicker.js +69 -60
- package/src/item-picker/useItemPicker.js +2 -5
- package/src/time-input/MaskedInput.js +176 -156
- package/src/time-input/TimeInput.css.js +41 -18
- package/src/time-input/TimeInput.js +25 -14
- package/src/time-input/useTimeInput.js +57 -47
- package/src/vuu-date-picker/VuuDatePicker.js +46 -52
- package/src/vuu-time-picker/VuuTimePicker.js +6 -5
- package/types/index.d.ts +3 -4
- package/types/item-picker/ItemPicker.d.ts +25 -7
- package/types/item-picker/useItemPicker.d.ts +4 -7
- package/types/modal-provider/ModalProvider.d.ts +1 -1
- package/types/time-input/MaskedInput.d.ts +60 -10
- package/types/time-input/TimeInput.d.ts +4 -3
- package/types/time-input/useTimeInput.d.ts +24 -5
- package/types/vuu-date-picker/VuuDatePicker.d.ts +19 -3
- package/types/vuu-time-picker/VuuTimePicker.d.ts +8 -6
- package/src/modal-provider/ModalProvider.js +0 -147
|
@@ -1,35 +1,78 @@
|
|
|
1
|
-
import { EventEmitter, createSyntheticEvent, decrementTimeUnitValue, incrementTimeUnitValue,
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { EventEmitter, createSyntheticEvent, decrementTimeUnitValue, incrementTimeUnitValue, normaliseTimeString, updateTimeString, zeroTime, zeroTimeMillis } from "@vuu-ui/vuu-utils";
|
|
2
|
+
const unitSpec = {
|
|
3
|
+
hours: {
|
|
4
|
+
start: 0,
|
|
5
|
+
length: 2,
|
|
6
|
+
max: 23
|
|
7
|
+
},
|
|
8
|
+
minutes: {
|
|
9
|
+
start: 3,
|
|
10
|
+
length: 2,
|
|
11
|
+
max: 59
|
|
12
|
+
},
|
|
13
|
+
seconds: {
|
|
14
|
+
start: 6,
|
|
15
|
+
length: 2,
|
|
16
|
+
max: 59
|
|
17
|
+
},
|
|
18
|
+
milliseconds: {
|
|
19
|
+
start: 9,
|
|
20
|
+
length: 3,
|
|
21
|
+
max: 999
|
|
22
|
+
}
|
|
9
23
|
};
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
24
|
+
const secondsUnits = [
|
|
25
|
+
"hours",
|
|
26
|
+
"minutes",
|
|
27
|
+
"seconds"
|
|
28
|
+
];
|
|
29
|
+
const millisecondsUnits = [
|
|
30
|
+
...secondsUnits,
|
|
31
|
+
"milliseconds"
|
|
32
|
+
];
|
|
33
|
+
const invalidClassName = "vuuTimeInput-invalid";
|
|
34
|
+
const isValidUnitValue = (unit, value)=>{
|
|
35
|
+
const { length, max } = unitSpec[unit];
|
|
36
|
+
return value.length === length && /^[0-9]+$/.test(value) && parseInt(value) <= max;
|
|
13
37
|
};
|
|
14
38
|
class MaskedInput extends EventEmitter {
|
|
15
39
|
#controlled = false;
|
|
16
40
|
#input = null;
|
|
17
41
|
#isFocused = false;
|
|
18
|
-
#
|
|
42
|
+
#milliseconds;
|
|
19
43
|
#selectionStart = -1;
|
|
20
44
|
#selectionEnd = -1;
|
|
45
|
+
#units;
|
|
21
46
|
#value;
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
constructor(defaultValue, inputEl = null){
|
|
47
|
+
#selectedUnit;
|
|
48
|
+
#digitIndex = 0;
|
|
49
|
+
constructor(defaultValue, inputEl = null, { milliseconds = false } = {}){
|
|
25
50
|
super();
|
|
51
|
+
this.#milliseconds = milliseconds;
|
|
52
|
+
this.#units = milliseconds ? millisecondsUnits : secondsUnits;
|
|
53
|
+
this.#value = this.normalise(defaultValue) ?? this.zeroValue;
|
|
26
54
|
if (inputEl) this.input = inputEl;
|
|
27
|
-
|
|
55
|
+
}
|
|
56
|
+
get milliseconds() {
|
|
57
|
+
return this.#milliseconds;
|
|
58
|
+
}
|
|
59
|
+
get zeroValue() {
|
|
60
|
+
return this.#milliseconds ? zeroTimeMillis : zeroTime;
|
|
61
|
+
}
|
|
62
|
+
get length() {
|
|
63
|
+
return this.#milliseconds ? 12 : 8;
|
|
64
|
+
}
|
|
65
|
+
normalise(value) {
|
|
66
|
+
return normaliseTimeString(value, this.#milliseconds);
|
|
28
67
|
}
|
|
29
68
|
set input(el) {
|
|
30
|
-
if (this.#input)
|
|
69
|
+
if (el === this.#input) return;
|
|
70
|
+
this.#input?.removeEventListener("change", this.emitSyntheticChangeEvent);
|
|
31
71
|
this.#input = el;
|
|
32
|
-
el
|
|
72
|
+
if (el) {
|
|
73
|
+
el.addEventListener("change", this.emitSyntheticChangeEvent);
|
|
74
|
+
if ("" !== el.value && el.value !== this.#value) el.value = this.#value;
|
|
75
|
+
}
|
|
33
76
|
}
|
|
34
77
|
emitSyntheticChangeEvent = (e)=>{
|
|
35
78
|
const syntheticEvent = createSyntheticEvent(e);
|
|
@@ -58,33 +101,46 @@ class MaskedInput extends EventEmitter {
|
|
|
58
101
|
set selectionEnd(value) {
|
|
59
102
|
this.#selectionEnd = value;
|
|
60
103
|
}
|
|
104
|
+
nextUnit(unit) {
|
|
105
|
+
const index = this.#units.indexOf(unit);
|
|
106
|
+
return this.#units[Math.min(index + 1, this.#units.length - 1)];
|
|
107
|
+
}
|
|
108
|
+
previousUnit(unit) {
|
|
109
|
+
const index = this.#units.indexOf(unit);
|
|
110
|
+
return this.#units[Math.max(index - 1, 0)];
|
|
111
|
+
}
|
|
112
|
+
get firstUnit() {
|
|
113
|
+
return this.#units[0];
|
|
114
|
+
}
|
|
115
|
+
get lastUnit() {
|
|
116
|
+
return this.#units[this.#units.length - 1];
|
|
117
|
+
}
|
|
61
118
|
setValue(value) {
|
|
62
|
-
if (!this.#controlled)
|
|
63
|
-
this.#isIncrementalChange = false;
|
|
64
|
-
this.#value = value;
|
|
65
|
-
}
|
|
119
|
+
if (!this.#controlled) this.#value = value;
|
|
66
120
|
if (this.#input) {
|
|
67
121
|
this.#input.value = value;
|
|
68
122
|
this.#input.dispatchEvent(new Event("change", {
|
|
69
123
|
bubbles: true,
|
|
70
124
|
composed: true
|
|
71
125
|
}));
|
|
126
|
+
if (this.#controlled) this.#input.value = this.#value;
|
|
72
127
|
}
|
|
73
128
|
}
|
|
129
|
+
getUnitValue(unit) {
|
|
130
|
+
const { start, length } = unitSpec[unit];
|
|
131
|
+
return this.#value.slice(start, start + length);
|
|
132
|
+
}
|
|
74
133
|
setUnitValue(unit, value) {
|
|
75
|
-
const
|
|
76
|
-
this.setValue(
|
|
134
|
+
const newValue = updateTimeString(this.#value, unit, value);
|
|
135
|
+
this.setValue(newValue);
|
|
77
136
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return this.#value.slice(6, 8);
|
|
86
|
-
default:
|
|
87
|
-
throw Error(`[MaskedInout] invalue unit ${unit}`);
|
|
137
|
+
setInvalid(invalid) {
|
|
138
|
+
if (this.#input) if (invalid) {
|
|
139
|
+
this.#input.classList.add(invalidClassName);
|
|
140
|
+
this.#input.setAttribute("aria-invalid", "true");
|
|
141
|
+
} else {
|
|
142
|
+
this.#input.classList.remove(invalidClassName);
|
|
143
|
+
this.#input.removeAttribute("aria-invalid");
|
|
88
144
|
}
|
|
89
145
|
}
|
|
90
146
|
get value() {
|
|
@@ -92,188 +148,152 @@ class MaskedInput extends EventEmitter {
|
|
|
92
148
|
}
|
|
93
149
|
set value(value) {
|
|
94
150
|
this.#controlled = true;
|
|
95
|
-
|
|
96
|
-
if (this
|
|
97
|
-
|
|
98
|
-
this
|
|
99
|
-
|
|
100
|
-
if (isIncremental) this.restoreSelection();
|
|
101
|
-
else this.advanceSelection();
|
|
151
|
+
const normalisedValue = this.normalise(value);
|
|
152
|
+
if (void 0 !== normalisedValue && normalisedValue !== this.#value) {
|
|
153
|
+
this.#value = normalisedValue;
|
|
154
|
+
if (this.isFocused) requestAnimationFrame(()=>{
|
|
155
|
+
this.restoreSelection();
|
|
102
156
|
});
|
|
103
157
|
}
|
|
104
158
|
}
|
|
105
159
|
clear(unit) {
|
|
106
|
-
if (this.#input)
|
|
107
|
-
let newValue = this.#value;
|
|
108
|
-
if ("hours" === unit) newValue = zeroTimeUnit.concat(this.#value.slice(2));
|
|
109
|
-
else if ("minutes" === unit) newValue = this.#value.slice(0, 3).concat(zeroTimeUnit).concat(this.#value.slice(5));
|
|
110
|
-
else if ("seconds" === unit) newValue = this.#value.slice(0, 6).concat(zeroTimeUnit);
|
|
111
|
-
if (newValue !== this.#value) this.setValue(newValue);
|
|
112
|
-
}
|
|
160
|
+
if (this.#input) this.setUnitValue(unit, "0".repeat(unitSpec[unit].length));
|
|
113
161
|
}
|
|
114
|
-
select(unit,
|
|
115
|
-
if (this.#input) {
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
this.selectionEnd = this.#input.selectionEnd = 2;
|
|
120
|
-
} else if ("minutes" === unit) {
|
|
121
|
-
this.selectionStart = this.#input.selectionStart = 3 + offset;
|
|
122
|
-
this.selectionEnd = this.#input.selectionEnd = 5;
|
|
123
|
-
} else if ("seconds" === unit) {
|
|
124
|
-
this.selectionStart = this.#input.selectionStart = 6 + offset;
|
|
125
|
-
this.selectionEnd = this.#input.selectionEnd = 8;
|
|
126
|
-
}
|
|
162
|
+
select(unit, digitIndex = 0) {
|
|
163
|
+
if (this.#input && this.#units.includes(unit)) {
|
|
164
|
+
const { start, length } = unitSpec[unit];
|
|
165
|
+
this.selectionStart = start + digitIndex;
|
|
166
|
+
this.selectionEnd = start + length;
|
|
127
167
|
this.#input.setSelectionRange(this.selectionStart, this.selectionEnd);
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
this.#unitSelected = void 0;
|
|
131
|
-
} else {
|
|
132
|
-
this.#halfUnitSelected = void 0;
|
|
133
|
-
this.#unitSelected = unit;
|
|
134
|
-
}
|
|
168
|
+
this.#selectedUnit = unit;
|
|
169
|
+
this.#digitIndex = digitIndex;
|
|
135
170
|
}
|
|
136
171
|
}
|
|
137
172
|
removeSelection() {
|
|
138
|
-
this
|
|
139
|
-
this.#
|
|
140
|
-
this.#
|
|
173
|
+
this.selectionStart = this.selectionEnd = this.length;
|
|
174
|
+
this.#selectedUnit = void 0;
|
|
175
|
+
this.#digitIndex = 0;
|
|
141
176
|
}
|
|
142
177
|
restoreSelection() {
|
|
143
|
-
if (this.#
|
|
178
|
+
if (this.#selectedUnit) this.select(this.#selectedUnit, this.#digitIndex);
|
|
144
179
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
else throw Error("unreachable code, in theory");
|
|
180
|
+
selectFirst() {
|
|
181
|
+
this.select(this.firstUnit);
|
|
182
|
+
}
|
|
183
|
+
selectLast() {
|
|
184
|
+
this.select(this.lastUnit);
|
|
151
185
|
}
|
|
152
186
|
moveFocus(direction) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
} else if ("seconds" === this.#unitSelected || "seconds" === this.#halfUnitSelected) this.select("minutes");
|
|
158
|
-
else if ("minutes" === this.#unitSelected || "minutes" === this.#halfUnitSelected) this.select("hours");
|
|
159
|
-
else if ("hours" === this.#unitSelected || "hours" === this.#halfUnitSelected) this.select("hours");
|
|
160
|
-
else {
|
|
161
|
-
const selection = this.getSelection();
|
|
162
|
-
if (selection === CursorAtEnd) this.select("seconds");
|
|
163
|
-
}
|
|
187
|
+
const unit = this.#selectedUnit;
|
|
188
|
+
if (unit) this.select("right" === direction ? this.nextUnit(unit) : this.previousUnit(unit));
|
|
189
|
+
else if ("right" === direction) this.selectFirst();
|
|
190
|
+
else this.selectLast();
|
|
164
191
|
}
|
|
165
192
|
pasteValue(value) {
|
|
166
|
-
|
|
167
|
-
this.#
|
|
168
|
-
|
|
193
|
+
const normalisedValue = this.normalise(value.trim());
|
|
194
|
+
if (this.#input && void 0 !== normalisedValue) {
|
|
195
|
+
this.setInvalid(false);
|
|
196
|
+
if (normalisedValue !== this.#value) this.setValue(normalisedValue);
|
|
197
|
+
this.selectFirst();
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
return false;
|
|
169
201
|
}
|
|
170
202
|
getUnitAtCursorPos(cursorPos = this.cursorPos) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
203
|
+
for(let i = this.#units.length - 1; i > 0; i--){
|
|
204
|
+
const unit = this.#units[i];
|
|
205
|
+
if (cursorPos >= unitSpec[unit].start) return unit;
|
|
206
|
+
}
|
|
207
|
+
return this.firstUnit;
|
|
208
|
+
}
|
|
209
|
+
get activeUnit() {
|
|
210
|
+
return this.#selectedUnit ?? this.getUnitAtCursorPos();
|
|
175
211
|
}
|
|
176
212
|
incrementValue() {
|
|
177
213
|
if (this.#input) {
|
|
178
|
-
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
const newUnitValue = incrementTimeUnitValue(unit, unitValue);
|
|
214
|
+
const unit = this.activeUnit;
|
|
215
|
+
const newUnitValue = incrementTimeUnitValue(unit, this.getUnitValue(unit));
|
|
216
|
+
this.setInvalid(false);
|
|
182
217
|
this.setUnitValue(unit, newUnitValue);
|
|
183
218
|
this.select(unit);
|
|
184
219
|
}
|
|
185
220
|
}
|
|
186
221
|
decrementValue() {
|
|
187
222
|
if (this.#input) {
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
const newUnitValue = decrementTimeUnitValue(unit, unitValue);
|
|
223
|
+
const unit = this.activeUnit;
|
|
224
|
+
const newUnitValue = decrementTimeUnitValue(unit, this.getUnitValue(unit));
|
|
225
|
+
this.setInvalid(false);
|
|
192
226
|
this.setUnitValue(unit, newUnitValue);
|
|
193
227
|
this.select(unit);
|
|
194
228
|
}
|
|
195
229
|
}
|
|
196
230
|
backspace() {
|
|
197
231
|
if (this.#input) {
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
this.clear("minutes");
|
|
204
|
-
this.select("hours");
|
|
205
|
-
} else if ("hours" === this.#unitSelected) {
|
|
206
|
-
this.clear("hours");
|
|
207
|
-
this.select("hours");
|
|
208
|
-
} else if (cursorPos > 0) {
|
|
209
|
-
const offset = 6 === this.selectionStart || 3 === this.selectionStart ? 2 : 1;
|
|
210
|
-
const newValue = this.#value.slice(0, cursorPos - offset).concat(zeroTime.slice(cursorPos - offset, cursorPos)).concat(this.#value.slice(cursorPos));
|
|
211
|
-
this.selectionStart -= offset;
|
|
212
|
-
this.selectionEnd -= offset;
|
|
213
|
-
this.setValue(newValue);
|
|
214
|
-
requestAnimationFrame(()=>{
|
|
215
|
-
this.#input?.setSelectionRange(this.#selectionStart, this.selectionEnd);
|
|
216
|
-
});
|
|
217
|
-
}
|
|
232
|
+
const unit = this.activeUnit;
|
|
233
|
+
const isPartiallyEntered = this.#selectedUnit === unit && this.#digitIndex > 0;
|
|
234
|
+
this.setInvalid(false);
|
|
235
|
+
this.clear(unit);
|
|
236
|
+
this.select(isPartiallyEntered ? unit : this.previousUnit(unit));
|
|
218
237
|
}
|
|
219
238
|
}
|
|
220
239
|
update(key) {
|
|
221
240
|
if (this.#input) {
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
241
|
+
const unit = this.activeUnit;
|
|
242
|
+
const { length, max } = unitSpec[unit];
|
|
243
|
+
const digitIndex = this.#selectedUnit === unit && this.#digitIndex < length ? this.#digitIndex : 0;
|
|
244
|
+
const maxFirstDigit = Math.floor(max / 10 ** (length - 1));
|
|
245
|
+
let newUnitValue;
|
|
246
|
+
let nextDigitIndex;
|
|
247
|
+
if (0 === digitIndex && parseInt(key) > maxFirstDigit) {
|
|
248
|
+
newUnitValue = key.padStart(length, "0");
|
|
249
|
+
nextDigitIndex = length;
|
|
250
|
+
} else {
|
|
251
|
+
const unitValue = this.getUnitValue(unit);
|
|
252
|
+
const head = unitValue.slice(0, digitIndex).concat(key);
|
|
253
|
+
const overwritten = head.concat(unitValue.slice(digitIndex + 1));
|
|
254
|
+
newUnitValue = isValidUnitValue(unit, overwritten) ? overwritten : head.padEnd(length, "0");
|
|
255
|
+
nextDigitIndex = digitIndex + 1;
|
|
256
|
+
}
|
|
257
|
+
if (!isValidUnitValue(unit, newUnitValue)) {
|
|
258
|
+
this.setInvalid(true);
|
|
259
|
+
this.select(unit, digitIndex);
|
|
260
|
+
return;
|
|
235
261
|
}
|
|
262
|
+
this.setInvalid(false);
|
|
263
|
+
this.setUnitValue(unit, newUnitValue);
|
|
264
|
+
if (nextDigitIndex === length) this.select(this.nextUnit(unit));
|
|
265
|
+
else this.select(unit, nextDigitIndex);
|
|
236
266
|
}
|
|
237
267
|
}
|
|
238
268
|
getSelection() {
|
|
239
269
|
if (this.#input) {
|
|
240
270
|
const { selectionEnd, selectionStart } = this.#input;
|
|
241
|
-
|
|
242
|
-
if (0 === selectionStart && 8 === selectionEnd) return FullSelection;
|
|
243
|
-
if (8 === selectionStart && 8 === selectionEnd) return CursorAtEnd;
|
|
244
|
-
else return {
|
|
271
|
+
return {
|
|
245
272
|
end: selectionEnd,
|
|
246
273
|
start: selectionStart
|
|
247
274
|
};
|
|
248
275
|
}
|
|
249
|
-
throw Error("[
|
|
276
|
+
throw Error("[MaskedInput] selection referenced, but no input");
|
|
250
277
|
}
|
|
251
278
|
click() {
|
|
252
279
|
if (this.#input) {
|
|
253
280
|
this.#isFocused = true;
|
|
254
|
-
const
|
|
255
|
-
if (
|
|
256
|
-
else
|
|
257
|
-
else {
|
|
258
|
-
const cursorPos = this.#input.selectionStart ?? 0;
|
|
259
|
-
this.select(this.getUnitAtCursorPos(cursorPos));
|
|
260
|
-
}
|
|
281
|
+
const { start, end } = this.getSelection();
|
|
282
|
+
if (null === start) this.selectFirst();
|
|
283
|
+
else 0 === start && end === this.length || this.select(this.getUnitAtCursorPos(start));
|
|
261
284
|
}
|
|
262
285
|
}
|
|
263
286
|
doubleClick() {
|
|
264
287
|
if (this.#input) {
|
|
265
|
-
const { selectionStart
|
|
266
|
-
if (null
|
|
267
|
-
else if (selectionStart < 3) this.select("hours");
|
|
268
|
-
else if (selectionStart < 6) this.select("minutes");
|
|
269
|
-
else if (selectionStart <= 8) this.select("seconds");
|
|
288
|
+
const { selectionStart } = this.#input;
|
|
289
|
+
if (null !== selectionStart) this.select(this.getUnitAtCursorPos(selectionStart));
|
|
270
290
|
}
|
|
271
291
|
}
|
|
272
292
|
focus = ()=>{
|
|
273
293
|
if (this.#input) {
|
|
274
294
|
this.#isFocused = true;
|
|
275
295
|
requestAnimationFrame(()=>{
|
|
276
|
-
this.
|
|
296
|
+
this.selectFirst();
|
|
277
297
|
});
|
|
278
298
|
}
|
|
279
299
|
};
|
|
@@ -282,4 +302,4 @@ class MaskedInput extends EventEmitter {
|
|
|
282
302
|
this.#isFocused = false;
|
|
283
303
|
};
|
|
284
304
|
}
|
|
285
|
-
export { MaskedInput };
|
|
305
|
+
export { MaskedInput, invalidClassName };
|
|
@@ -1,25 +1,48 @@
|
|
|
1
1
|
const css = `
|
|
2
|
-
.
|
|
3
|
-
--time-input-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
.vuuTimeInput-container {
|
|
3
|
+
--time-input-border: var(--vuuTimeInput-borderWidth, 1px);
|
|
4
|
+
--time-input-padding: var(--vuuTimeInput-paddingInline, var(--salt-spacing-50));
|
|
5
|
+
font-family: var(--salt-typography-fontFamily);
|
|
6
|
+
font-size: var(--vuuTimeInput-fontSize, var(--salt-text-fontSize));
|
|
7
|
+
font-variant-numeric: tabular-nums;
|
|
8
|
+
width: fit-content;
|
|
9
|
+
display: inline-grid;
|
|
10
|
+
|
|
11
|
+
&:before, &:after {
|
|
12
|
+
border: 0 solid #0000;
|
|
13
|
+
border-inline-width: var(--time-input-border);
|
|
14
|
+
box-sizing: content-box;
|
|
15
|
+
height: 0;
|
|
16
|
+
max-width: calc(var(--vuuTimeInput-width, 10000px) - 1px);
|
|
17
|
+
padding-inline: var(--time-input-padding);
|
|
18
|
+
visibility: hidden;
|
|
19
|
+
white-space: pre;
|
|
20
|
+
grid-area: 1 / 1;
|
|
21
|
+
padding-inline-end: calc(var(--time-input-padding) + 1px);
|
|
22
|
+
}
|
|
9
23
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
24
|
+
&:before {
|
|
25
|
+
content: attr(data-placeholder);
|
|
26
|
+
}
|
|
13
27
|
|
|
14
|
-
|
|
15
|
-
|
|
28
|
+
&:after {
|
|
29
|
+
content: attr(data-sample-value);
|
|
30
|
+
}
|
|
16
31
|
}
|
|
17
32
|
|
|
18
33
|
.vuuTimeInput {
|
|
19
34
|
background: var(--vuuTimeInput-background, inherit);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
35
|
+
border-width: var(--time-input-border);
|
|
36
|
+
box-sizing: content-box;
|
|
37
|
+
font-family: inherit;
|
|
38
|
+
font-size: inherit;
|
|
39
|
+
font-variant-numeric: inherit;
|
|
40
|
+
height: calc(var(--vuuTimeInput-height, var(--salt-size-base)) - 2 *
|
|
41
|
+
var(--time-input-border));
|
|
42
|
+
min-width: calc(100% - 2 * var(--time-input-padding) - 2 * var(--time-input-border));
|
|
43
|
+
padding: 0 var(--time-input-padding);
|
|
44
|
+
width: var(--vuuTimeInput-width, 0px);
|
|
45
|
+
grid-area: 1 / 1;
|
|
23
46
|
|
|
24
47
|
&:focus::-webkit-input-placeholder {
|
|
25
48
|
color: #0000;
|
|
@@ -28,10 +51,10 @@ const css = `
|
|
|
28
51
|
&:focus {
|
|
29
52
|
outline: var(--vuuTimeInput-outline, var(--salt-focused-outline));
|
|
30
53
|
}
|
|
31
|
-
}
|
|
32
54
|
|
|
33
|
-
|
|
34
|
-
|
|
55
|
+
&.vuuTimeInput-invalid {
|
|
56
|
+
border-color: var(--vuuTimeInput-invalid-borderColor, var(--salt-status-error-borderColor, red));
|
|
57
|
+
}
|
|
35
58
|
}
|
|
36
59
|
|
|
37
60
|
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useForkRef } from "@salt-ds/core";
|
|
3
3
|
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
4
4
|
import { useWindow } from "@salt-ds/window";
|
|
5
|
+
import { normaliseTimeString } from "@vuu-ui/vuu-utils";
|
|
5
6
|
import clsx from "clsx";
|
|
7
|
+
import { forwardRef } from "react";
|
|
6
8
|
import { useTimeInput } from "./useTimeInput.js";
|
|
7
9
|
import TimeInput_0 from "./TimeInput.css";
|
|
8
10
|
const classBase = "vuuTimeInput";
|
|
9
|
-
const TimeInput_TimeInput = /*#__PURE__*/ forwardRef(function({ className, date, defaultValue, onChange, onCommit, placeholder = "hh:mm:ss", value, ...htmlAttributes }, ref) {
|
|
11
|
+
const TimeInput_TimeInput = /*#__PURE__*/ forwardRef(function({ className, date, defaultValue, milliseconds = false, onChange, onCommit, placeholder = milliseconds ? "hh:mm:ss.sss" : "hh:mm:ss", value, ...htmlAttributes }, ref) {
|
|
10
12
|
const targetWindow = useWindow();
|
|
11
13
|
useComponentCssInjection({
|
|
12
14
|
testId: "vuu-time-input",
|
|
@@ -16,22 +18,31 @@ const TimeInput_TimeInput = /*#__PURE__*/ forwardRef(function({ className, date,
|
|
|
16
18
|
const { inputRef, eventHandlers } = useTimeInput({
|
|
17
19
|
date,
|
|
18
20
|
defaultValue,
|
|
21
|
+
milliseconds,
|
|
19
22
|
onChange,
|
|
20
23
|
onCommit,
|
|
21
24
|
value
|
|
22
25
|
});
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
const displayValue = void 0 === value ? void 0 : normaliseTimeString(value, milliseconds) ?? value;
|
|
27
|
+
const displayDefaultValue = void 0 === value && void 0 !== defaultValue ? normaliseTimeString(defaultValue, milliseconds) ?? defaultValue : void 0;
|
|
28
|
+
return /*#__PURE__*/ jsx("span", {
|
|
29
|
+
className: `${classBase}-container`,
|
|
30
|
+
"data-placeholder": placeholder,
|
|
31
|
+
"data-sample-value": milliseconds ? "00:00:00.000" : "00:00:00",
|
|
32
|
+
children: /*#__PURE__*/ jsx("input", {
|
|
33
|
+
...htmlAttributes,
|
|
34
|
+
...eventHandlers,
|
|
35
|
+
"aria-placeholder": placeholder,
|
|
36
|
+
className: clsx(classBase, className, {
|
|
37
|
+
[`${classBase}-milliseconds`]: milliseconds
|
|
38
|
+
}),
|
|
39
|
+
defaultValue: displayDefaultValue,
|
|
40
|
+
placeholder: placeholder,
|
|
41
|
+
readOnly: true,
|
|
42
|
+
ref: useForkRef(ref, inputRef),
|
|
43
|
+
spellCheck: "false",
|
|
44
|
+
value: displayValue
|
|
45
|
+
})
|
|
35
46
|
});
|
|
36
47
|
});
|
|
37
48
|
export { TimeInput_TimeInput as TimeInput };
|