@jobber/components 7.14.2 → 7.15.0

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.
Files changed (65) hide show
  1. package/dist/Autocomplete/index.cjs +4 -3
  2. package/dist/Autocomplete/index.mjs +3 -2
  3. package/dist/DataList/components/DataListSearch/index.cjs +2 -1
  4. package/dist/DataList/components/DataListSearch/index.mjs +2 -1
  5. package/dist/DataList/index.cjs +2 -1
  6. package/dist/DataList/index.mjs +2 -1
  7. package/dist/DataTable/index.cjs +2 -1
  8. package/dist/DataTable/index.mjs +2 -1
  9. package/dist/DatePicker/index.cjs +0 -1
  10. package/dist/DatePicker/index.mjs +0 -1
  11. package/dist/DatePicker-cjs.js +782 -4
  12. package/dist/DatePicker-es.js +782 -4
  13. package/dist/FormField/index.cjs +14 -13
  14. package/dist/FormField/index.mjs +5 -4
  15. package/dist/FormField-cjs.js +4 -3
  16. package/dist/FormField-es.js +2 -1
  17. package/dist/FormFieldPostFix-cjs.js +2 -237
  18. package/dist/FormFieldPostFix-es.js +3 -228
  19. package/dist/FormFieldWrapper-cjs.js +242 -0
  20. package/dist/FormFieldWrapper-es.js +231 -0
  21. package/dist/InputDate/index.cjs +2 -2
  22. package/dist/InputDate/index.mjs +2 -2
  23. package/dist/InputEmail/index.cjs +2 -1
  24. package/dist/InputEmail/index.mjs +2 -1
  25. package/dist/InputEmail-cjs.js +3 -2
  26. package/dist/InputEmail-es.js +2 -1
  27. package/dist/InputNumber/index.cjs +2 -1
  28. package/dist/InputNumber/index.mjs +2 -1
  29. package/dist/InputPassword/index.cjs +2 -1
  30. package/dist/InputPassword/index.mjs +2 -1
  31. package/dist/InputPhoneNumber/index.cjs +2 -1
  32. package/dist/InputPhoneNumber/index.mjs +2 -1
  33. package/dist/InputPhoneNumber-cjs.js +3 -2
  34. package/dist/InputPhoneNumber-es.js +2 -1
  35. package/dist/InputText/index.cjs +3 -2
  36. package/dist/InputText/index.mjs +2 -1
  37. package/dist/InputTime/InputTime.d.ts +1 -1
  38. package/dist/InputTime/InputTime.types.d.ts +10 -24
  39. package/dist/InputTime/hooks/useInputTimeActions.d.ts +2 -2
  40. package/dist/InputTime/index.cjs +16 -350
  41. package/dist/InputTime/index.d.ts +2 -4
  42. package/dist/InputTime/index.mjs +15 -353
  43. package/dist/InputTime-cjs.js +300 -0
  44. package/dist/InputTime-es.js +298 -0
  45. package/dist/RecurringSelect/index.cjs +2 -1
  46. package/dist/RecurringSelect/index.mjs +2 -1
  47. package/dist/Select/index.cjs +2 -1
  48. package/dist/Select/index.mjs +2 -1
  49. package/dist/Select-cjs.js +3 -2
  50. package/dist/Select-es.js +2 -1
  51. package/dist/Tabs-es.js +1 -1
  52. package/dist/_baseEach-es.js +2 -2
  53. package/dist/_getAllKeys-es.js +1 -1
  54. package/dist/debounce-es.js +1 -1
  55. package/dist/docs/InputTime/InputTime.md +45 -27
  56. package/dist/docs/usage-guidelines/usage-guidelines.md +0 -1
  57. package/dist/index.cjs +13 -13
  58. package/dist/index.mjs +3 -3
  59. package/dist/isTypedArray-es.js +1 -1
  60. package/dist/styles.css +7 -2
  61. package/dist/useScrollToActive-es.js +1 -1
  62. package/package.json +2 -2
  63. package/dist/InputTime/InputTime.rebuilt.d.ts +0 -3
  64. package/dist/omit-cjs.js +0 -783
  65. package/dist/omit-es.js +0 -781
@@ -1,360 +1,22 @@
1
- import React__default, { useState, useCallback, useEffect, useId, useRef } from 'react';
2
- import { _ as __rest } from '../tslib.es6-es.js';
3
- import { a as debounce } from '../debounce-es.js';
4
- import { c as FormFieldWrapper, g as formFieldStyles } from '../FormFieldPostFix-es.js';
5
- import 'classnames';
6
- import '@jobber/design';
7
- import 'react-hook-form';
8
- import { m as mergeRefs } from '../mergeRefs-es.js';
9
- import '../Button-es.js';
10
- import { f as filterDataAttributes } from '../filterDataAttributes-es.js';
11
- import { o as omit } from '../omit-es.js';
12
- import { F as FormField } from '../FormField-es.js';
13
- import '@jobber/hooks';
14
- import 'framer-motion';
1
+ export { I as InputTime } from '../InputTime-es.js';
2
+ import '../tslib.es6-es.js';
3
+ import 'react';
4
+ import '../debounce-es.js';
15
5
  import '../_commonjsHelpers-es.js';
16
6
  import '../isObjectLike-es.js';
17
7
  import '../isSymbol-es.js';
8
+ import '../FormFieldWrapper-es.js';
9
+ import '@jobber/hooks';
10
+ import 'framer-motion';
11
+ import '@jobber/design';
12
+ import 'classnames';
13
+ import '../Button-es.js';
14
+ import 'react-router-dom';
18
15
  import '../Icon-es.js';
19
- import '../Text-es.js';
20
16
  import '../Typography-es.js';
17
+ import '../Text-es.js';
21
18
  import '../useFormFieldFocus-es.js';
22
19
  import '../InputValidation-es.js';
23
- import '../Spinner-es.js';
24
- import 'react-router-dom';
25
- import '../_getAllKeys-es.js';
26
- import '../isTypedArray-es.js';
27
- import '../identity-es.js';
28
- import '../_getTag-es.js';
29
- import '../keysIn-es.js';
30
- import '../_baseAssignValue-es.js';
31
- import '../_baseFlatten-es.js';
32
- import '../_setToString-es.js';
33
- import '../useAtlantisFormFieldName-es.js';
34
-
35
- const DEBOUNCE_TIME = 300;
36
- function useTimePredict({ value, handleChange }) {
37
- const [IS_12_HOUR_FORMAT, set12HourFormat] = useState(false);
38
- const [typedTime, setTypedTime] = useState("");
39
- const predictTime = useCallback(debounce(() => {
40
- if (value)
41
- return;
42
- handleChange(predictHours(typedTime, IS_12_HOUR_FORMAT));
43
- }, DEBOUNCE_TIME), [typedTime, value, handleChange, IS_12_HOUR_FORMAT]);
44
- useEffect(() => {
45
- set12HourFormat(Boolean(Intl.DateTimeFormat(navigator.language, {
46
- hour: "numeric",
47
- }).resolvedOptions().hour12));
48
- }, []);
49
- /**
50
- * Predict the hour when user types a number
51
- */
52
- useEffect(() => {
53
- /**
54
- * Don't try to predict if the user types 0 as the user would almost always
55
- * type another number after 0.
56
- */
57
- if (typedTime && typedTime !== "0") {
58
- predictTime();
59
- if ((IS_12_HOUR_FORMAT && typedTime !== "1") || typedTime.length === 2) {
60
- // Immediately predict the hour
61
- predictTime.flush();
62
- }
63
- }
64
- return predictTime.cancel;
65
- }, [typedTime]);
66
- /**
67
- * Reset typed time when the value changed
68
- */
69
- useEffect(() => {
70
- setTypedTime("");
71
- }, [value]);
72
- return {
73
- setTypedTime,
74
- };
75
- }
76
- function predictHours(time, is12HourFormat = false) {
77
- const today = new Date();
78
- const currentHour = today.getHours();
79
- const parsedTime = parseInt(time, 10);
80
- let predictedTime;
81
- if (is12HourFormat) {
82
- predictedTime = predict12Hours(parsedTime, currentHour);
83
- }
84
- else {
85
- predictedTime = predict24Hours(time, parsedTime, currentHour);
86
- }
87
- return formatHour(predictedTime);
88
- }
89
- function predict12Hours(parsedTime, currentHour) {
90
- /**
91
- * We need to predict what the user wants when they type 1 since it could be
92
- * 10, 11, 12, or 1.
93
- *
94
- * If the current hour is over 12PM, we can skip this and go to the next logic.
95
- */
96
- if (parsedTime === 1 && currentHour < 12) {
97
- if (currentHour < 10) {
98
- return 10;
99
- }
100
- else {
101
- return currentHour + 1;
102
- }
103
- }
104
- /**
105
- * Typing 1-5 predicts that the user want that exact hour on the afternoon.
106
- */
107
- if (parsedTime <= 5) {
108
- return parsedTime + 12;
109
- }
110
- /**
111
- * Typing 13-15 predicts that the user want the 2nd number as the minute interval.
112
- */
113
- if (parsedTime > 12 && parsedTime <= 15) {
114
- const timeArray = parsedTime.toString().split("").map(Number); // 13 -> [1, 3]
115
- const convertToHoursAndMinutes = timeArray.map((time, i) => {
116
- if (i === 0)
117
- return time + 12; // 1 -> 13 as 1PM
118
- if (i === 1)
119
- return time * 10; // 3 -> 30 as 30 minutes
120
- });
121
- return Number(convertToHoursAndMinutes.join("")); // [13, 30] -> 1330
122
- }
123
- /**
124
- * Anything after 5 will be predicted to be set as AM.
125
- */
126
- return parsedTime;
127
- }
128
- function predict24Hours(time, parsedTime, currentHour) {
129
- /**
130
- * Typing 1 could be predicted from 10 to 19.
131
- * Typing 01 skips this logic and sets the time to 01:00.
132
- */
133
- if (parsedTime === 1 && time !== "01") {
134
- if (currentHour < 10 || currentHour > 19) {
135
- return 10;
136
- }
137
- else {
138
- return currentHour + 1;
139
- }
140
- }
141
- /**
142
- * Typing 2 could be predicted from 20 to 24.
143
- * Typing 02 skips this logic and sets the time to 02:00.
144
- */
145
- if (parsedTime === 2 && time !== "02") {
146
- if (currentHour < 20) {
147
- return 20;
148
- }
149
- else {
150
- return currentHour + 1;
151
- }
152
- }
153
- /**
154
- * Typing 24 or 00 is set to midnight. This ensures the time doesn't get set
155
- * to 24 as that would be invalid.
156
- */
157
- if (parsedTime === 24 || time === "00") {
158
- return 0;
159
- }
160
- return parsedTime;
161
- }
162
- function formatHour(time) {
163
- if (time > 99) {
164
- const splitTime = time.toString().split("");
165
- if (splitTime.length === 3)
166
- splitTime.unshift("0"); // 130 -> 0130
167
- splitTime.splice(2, 0, ":"); // 0130 -> 01:30
168
- return splitTime.join("");
169
- }
170
- if (time < 10) {
171
- return `0${time}:00`;
172
- }
173
- return `${time}:00`;
174
- }
175
-
176
- function dateToTimeString(date, includeSeconds = false) {
177
- if (!(date instanceof Date)) {
178
- return "";
179
- }
180
- const hours = date.getHours().toString().padStart(2, "0");
181
- const minutes = date.getMinutes().toString().padStart(2, "0");
182
- if (includeSeconds) {
183
- const seconds = date.getSeconds().toString().padStart(2, "0");
184
- return `${hours}:${minutes}:${seconds}`;
185
- }
186
- return `${hours}:${minutes}`;
187
- }
188
- function timeStringToDate(timeString, baseDate) {
189
- try {
190
- const [hours, minutes, seconds = 0] = timeString.split(":").map(Number);
191
- if (isNaN(hours) ||
192
- isNaN(minutes) ||
193
- isNaN(seconds) ||
194
- hours < 0 ||
195
- hours > 24 ||
196
- minutes < 0 ||
197
- minutes > 60 ||
198
- seconds < 0 ||
199
- seconds > 60) {
200
- return undefined;
201
- }
202
- // Try to preserve the Date part of the Date object as long as it is valid
203
- const date = baseDate instanceof Date && !isNaN(baseDate.getTime())
204
- ? new Date(baseDate)
205
- : new Date();
206
- date.setHours(hours, minutes, seconds, 0);
207
- return date;
208
- }
209
- catch (_a) {
210
- return undefined;
211
- }
212
- }
213
-
214
- function useInputTimeActions({ onChange, value, inputRef, onFocus, onBlur, onKeyDown, onClick, onMouseDown, onMouseUp, onPointerDown, onPointerUp, }) {
215
- function handleChangeEvent(event) {
216
- handleChange(event.target.value);
217
- }
218
- function handleChange(newValue) {
219
- onChange === null || onChange === void 0 ? void 0 : onChange(timeStringToDate(newValue, value));
220
- }
221
- function handleBlur(event) {
222
- onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
223
- if (inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) {
224
- if (!inputRef.current.checkValidity()) {
225
- inputRef.current.value = "";
226
- inputRef.current.valueAsDate = null;
227
- // Remove validation error. This is mainly needed for Safari
228
- inputRef.current.setCustomValidity("");
229
- }
230
- }
231
- }
232
- function handleClear() {
233
- var _a;
234
- // Clear the value and refocus without triggering blur event
235
- onChange === null || onChange === void 0 ? void 0 : onChange(undefined);
236
- (_a = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
237
- }
238
- function handleFocus(event) {
239
- onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
240
- }
241
- function handleKeyDown(event) {
242
- onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
243
- }
244
- function handleClick(event) {
245
- onClick === null || onClick === void 0 ? void 0 : onClick(event);
246
- }
247
- function handleMouseDown(event) {
248
- onMouseDown === null || onMouseDown === void 0 ? void 0 : onMouseDown(event);
249
- }
250
- function handleMouseUp(event) {
251
- onMouseUp === null || onMouseUp === void 0 ? void 0 : onMouseUp(event);
252
- }
253
- function handlePointerDown(event) {
254
- onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(event);
255
- }
256
- function handlePointerUp(event) {
257
- onPointerUp === null || onPointerUp === void 0 ? void 0 : onPointerUp(event);
258
- }
259
- return {
260
- handleChangeEvent,
261
- handleChange,
262
- handleBlur,
263
- handleClear,
264
- handleFocus,
265
- handleKeyDown,
266
- handleClick,
267
- handleMouseDown,
268
- handleMouseUp,
269
- handlePointerDown,
270
- handlePointerUp,
271
- };
272
- }
273
-
274
- function InputTimeRebuilt(_a) {
275
- var _b;
276
- var { value, onChange, readOnly, autoComplete, inputRef, step = 60 } = _a, props = __rest(_a, ["value", "onChange", "readOnly", "autoComplete", "inputRef", "step"]);
277
- const { internalRef, mergedRef, wrapperRef } = useInputTimeRefs(inputRef);
278
- const generatedId = useId();
279
- const id = props.id || generatedId;
280
- const { handleChangeEvent, handleChange, handleBlur, handleClear, handleFocus, handleKeyDown, handleClick, handleMouseDown, handleMouseUp, handlePointerDown, handlePointerUp, } = useInputTimeActions({
281
- onChange,
282
- value,
283
- readOnly,
284
- disabled: props.disabled,
285
- inputRef: internalRef,
286
- onFocus: props.onFocus,
287
- onBlur: props.onBlur,
288
- onKeyDown: props.onKeyDown,
289
- onClick: props.onClick,
290
- onMouseDown: props.onMouseDown,
291
- onMouseUp: props.onMouseUp,
292
- onPointerDown: props.onPointerDown,
293
- onPointerUp: props.onPointerUp,
294
- });
295
- const { setTypedTime } = useTimePredict({
296
- value,
297
- handleChange,
298
- });
299
- // Kept outside the useInputTimeActions hook to avoid circular dependency via setTypedTime and handleChange
300
- function handleKeyUp(event) {
301
- var _a;
302
- (_a = props.onKeyUp) === null || _a === void 0 ? void 0 : _a.call(props, event);
303
- if (props.disabled || readOnly)
304
- return;
305
- !isNaN(parseInt(event.key, 10)) && setTypedTime(prev => prev + event.key);
306
- }
307
- const dataAttrs = filterDataAttributes(props);
308
- const descriptionIdentifier = `descriptionUUID--${id}`;
309
- const descriptionVisible = props.description && !props.inline;
310
- const isInvalid = Boolean(props.error || props.invalid);
311
- return (React__default.createElement(FormFieldWrapper, { disabled: props.disabled, size: props.size, align: props.align, inline: props.inline, name: props.name, error: props.error || "", identifier: id, descriptionIdentifier: descriptionIdentifier, invalid: props.invalid, description: props.description, clearable: (_b = props.clearable) !== null && _b !== void 0 ? _b : "never", onClear: handleClear, type: "time", readonly: readOnly, placeholder: props.placeholder, value: dateToTimeString(value, step % 60 !== 0), wrapperRef: wrapperRef },
312
- React__default.createElement("input", Object.assign({ ref: mergedRef, type: "time", name: props.name, className: formFieldStyles.input, id: id, disabled: props.disabled, readOnly: readOnly, autoComplete: autoComplete, autoFocus: props.autoFocus, required: props.required, max: props.max, min: props.min, step: step, value: dateToTimeString(value, step % 60 !== 0), onChange: handleChangeEvent, onBlur: handleBlur, onFocus: handleFocus, onKeyDown: handleKeyDown, onKeyUp: handleKeyUp, onClick: handleClick, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, onPointerDown: handlePointerDown, onPointerUp: handlePointerUp, "data-testid": "ATL-InputTime-input", "aria-label": props["aria-label"], "aria-describedby": descriptionVisible ? descriptionIdentifier : props["aria-describedby"], "aria-invalid": isInvalid ? true : undefined, "aria-required": props["aria-required"] }, dataAttrs))));
313
- }
314
- function useInputTimeRefs(inputRef) {
315
- const internalRef = useRef(null);
316
- const mergedRef = mergeRefs([internalRef, inputRef]);
317
- const wrapperRef = useRef(null);
318
- return { internalRef, mergedRef, wrapperRef };
319
- }
320
-
321
- function InputTime$1(_a) {
322
- var { defaultValue, value, onChange } = _a, params = __rest(_a, ["defaultValue", "value", "onChange"]);
323
- const ref = useRef(null);
324
- const wrapperRef = useRef(null);
325
- const { setTypedTime } = useTimePredict({ value, handleChange });
326
- const fieldProps = omit(Object.assign(Object.assign(Object.assign({ onChange: handleChange }, (defaultValue && { defaultValue: dateToTimeString(defaultValue) })), (!defaultValue && { value: dateToTimeString(value) })), params), ["version"]);
327
- return (React__default.createElement(FormField, Object.assign({ inputRef: ref, type: "time" }, fieldProps, { onBlur: handleBlur, onKeyUp: e => {
328
- var _a;
329
- (_a = fieldProps.onKeyUp) === null || _a === void 0 ? void 0 : _a.call(fieldProps, e);
330
- !isNaN(parseInt(e.key, 10)) && setTypedTime(prev => prev + e.key);
331
- }, wrapperRef: wrapperRef })));
332
- function handleChange(newValue) {
333
- onChange === null || onChange === void 0 ? void 0 : onChange(timeStringToDate(newValue, value));
334
- }
335
- function handleBlur() {
336
- var _a;
337
- (_a = params.onBlur) === null || _a === void 0 ? void 0 : _a.call(params);
338
- // Time inputs doesn't clear the typed value when it's invalid. This should
339
- // force it to reset the input value when the typed value is invalid.
340
- if (ref.current) {
341
- if (!ref.current.checkValidity()) {
342
- ref.current.value = "";
343
- }
344
- }
345
- }
346
- }
347
-
348
- function isNewInputTimeProps(props) {
349
- return props.version === 2;
350
- }
351
- function InputTime(props) {
352
- if (isNewInputTimeProps(props)) {
353
- return React__default.createElement(InputTimeRebuilt, Object.assign({}, props));
354
- }
355
- else {
356
- return React__default.createElement(InputTime$1, Object.assign({}, props));
357
- }
358
- }
359
-
360
- export { InputTime };
20
+ import 'react-hook-form';
21
+ import '../mergeRefs-es.js';
22
+ import '../filterDataAttributes-es.js';
@@ -0,0 +1,300 @@
1
+ 'use strict';
2
+
3
+ var tslib_es6 = require('./tslib.es6-cjs.js');
4
+ var React = require('react');
5
+ var debounce = require('./debounce-cjs.js');
6
+ var FormFieldWrapper = require('./FormFieldWrapper-cjs.js');
7
+ require('classnames');
8
+ require('@jobber/design');
9
+ require('react-hook-form');
10
+ var mergeRefs = require('./mergeRefs-cjs.js');
11
+ require('./Button-cjs.js');
12
+ var filterDataAttributes = require('./filterDataAttributes-cjs.js');
13
+
14
+ const DEBOUNCE_TIME = 300;
15
+ function useTimePredict({ value, handleChange }) {
16
+ const [IS_12_HOUR_FORMAT, set12HourFormat] = React.useState(false);
17
+ const [typedTime, setTypedTime] = React.useState("");
18
+ const predictTime = React.useCallback(debounce.debounce(() => {
19
+ if (value)
20
+ return;
21
+ handleChange(predictHours(typedTime, IS_12_HOUR_FORMAT));
22
+ }, DEBOUNCE_TIME), [typedTime, value, handleChange, IS_12_HOUR_FORMAT]);
23
+ React.useEffect(() => {
24
+ set12HourFormat(Boolean(Intl.DateTimeFormat(navigator.language, {
25
+ hour: "numeric",
26
+ }).resolvedOptions().hour12));
27
+ }, []);
28
+ /**
29
+ * Predict the hour when user types a number
30
+ */
31
+ React.useEffect(() => {
32
+ /**
33
+ * Don't try to predict if the user types 0 as the user would almost always
34
+ * type another number after 0.
35
+ */
36
+ if (typedTime && typedTime !== "0") {
37
+ predictTime();
38
+ if ((IS_12_HOUR_FORMAT && typedTime !== "1") || typedTime.length === 2) {
39
+ // Immediately predict the hour
40
+ predictTime.flush();
41
+ }
42
+ }
43
+ return predictTime.cancel;
44
+ }, [typedTime]);
45
+ /**
46
+ * Reset typed time when the value changed
47
+ */
48
+ React.useEffect(() => {
49
+ setTypedTime("");
50
+ }, [value]);
51
+ return {
52
+ setTypedTime,
53
+ };
54
+ }
55
+ function predictHours(time, is12HourFormat = false) {
56
+ const today = new Date();
57
+ const currentHour = today.getHours();
58
+ const parsedTime = parseInt(time, 10);
59
+ let predictedTime;
60
+ if (is12HourFormat) {
61
+ predictedTime = predict12Hours(parsedTime, currentHour);
62
+ }
63
+ else {
64
+ predictedTime = predict24Hours(time, parsedTime, currentHour);
65
+ }
66
+ return formatHour(predictedTime);
67
+ }
68
+ function predict12Hours(parsedTime, currentHour) {
69
+ /**
70
+ * We need to predict what the user wants when they type 1 since it could be
71
+ * 10, 11, 12, or 1.
72
+ *
73
+ * If the current hour is over 12PM, we can skip this and go to the next logic.
74
+ */
75
+ if (parsedTime === 1 && currentHour < 12) {
76
+ if (currentHour < 10) {
77
+ return 10;
78
+ }
79
+ else {
80
+ return currentHour + 1;
81
+ }
82
+ }
83
+ /**
84
+ * Typing 1-5 predicts that the user want that exact hour on the afternoon.
85
+ */
86
+ if (parsedTime <= 5) {
87
+ return parsedTime + 12;
88
+ }
89
+ /**
90
+ * Typing 13-15 predicts that the user want the 2nd number as the minute interval.
91
+ */
92
+ if (parsedTime > 12 && parsedTime <= 15) {
93
+ const timeArray = parsedTime.toString().split("").map(Number); // 13 -> [1, 3]
94
+ const convertToHoursAndMinutes = timeArray.map((time, i) => {
95
+ if (i === 0)
96
+ return time + 12; // 1 -> 13 as 1PM
97
+ if (i === 1)
98
+ return time * 10; // 3 -> 30 as 30 minutes
99
+ });
100
+ return Number(convertToHoursAndMinutes.join("")); // [13, 30] -> 1330
101
+ }
102
+ /**
103
+ * Anything after 5 will be predicted to be set as AM.
104
+ */
105
+ return parsedTime;
106
+ }
107
+ function predict24Hours(time, parsedTime, currentHour) {
108
+ /**
109
+ * Typing 1 could be predicted from 10 to 19.
110
+ * Typing 01 skips this logic and sets the time to 01:00.
111
+ */
112
+ if (parsedTime === 1 && time !== "01") {
113
+ if (currentHour < 10 || currentHour > 19) {
114
+ return 10;
115
+ }
116
+ else {
117
+ return currentHour + 1;
118
+ }
119
+ }
120
+ /**
121
+ * Typing 2 could be predicted from 20 to 24.
122
+ * Typing 02 skips this logic and sets the time to 02:00.
123
+ */
124
+ if (parsedTime === 2 && time !== "02") {
125
+ if (currentHour < 20) {
126
+ return 20;
127
+ }
128
+ else {
129
+ return currentHour + 1;
130
+ }
131
+ }
132
+ /**
133
+ * Typing 24 or 00 is set to midnight. This ensures the time doesn't get set
134
+ * to 24 as that would be invalid.
135
+ */
136
+ if (parsedTime === 24 || time === "00") {
137
+ return 0;
138
+ }
139
+ return parsedTime;
140
+ }
141
+ function formatHour(time) {
142
+ if (time > 99) {
143
+ const splitTime = time.toString().split("");
144
+ if (splitTime.length === 3)
145
+ splitTime.unshift("0"); // 130 -> 0130
146
+ splitTime.splice(2, 0, ":"); // 0130 -> 01:30
147
+ return splitTime.join("");
148
+ }
149
+ if (time < 10) {
150
+ return `0${time}:00`;
151
+ }
152
+ return `${time}:00`;
153
+ }
154
+
155
+ function dateToTimeString(date, includeSeconds = false) {
156
+ if (!(date instanceof Date)) {
157
+ return "";
158
+ }
159
+ const hours = date.getHours().toString().padStart(2, "0");
160
+ const minutes = date.getMinutes().toString().padStart(2, "0");
161
+ if (includeSeconds) {
162
+ const seconds = date.getSeconds().toString().padStart(2, "0");
163
+ return `${hours}:${minutes}:${seconds}`;
164
+ }
165
+ return `${hours}:${minutes}`;
166
+ }
167
+ function timeStringToDate(timeString, baseDate) {
168
+ try {
169
+ const [hours, minutes, seconds = 0] = timeString.split(":").map(Number);
170
+ if (isNaN(hours) ||
171
+ isNaN(minutes) ||
172
+ isNaN(seconds) ||
173
+ hours < 0 ||
174
+ hours > 24 ||
175
+ minutes < 0 ||
176
+ minutes > 60 ||
177
+ seconds < 0 ||
178
+ seconds > 60) {
179
+ return undefined;
180
+ }
181
+ // Try to preserve the Date part of the Date object as long as it is valid
182
+ const date = baseDate instanceof Date && !isNaN(baseDate.getTime())
183
+ ? new Date(baseDate)
184
+ : new Date();
185
+ date.setHours(hours, minutes, seconds, 0);
186
+ return date;
187
+ }
188
+ catch (_a) {
189
+ return undefined;
190
+ }
191
+ }
192
+
193
+ function useInputTimeActions({ onChange, value, inputRef, onFocus, onBlur, onKeyDown, onClick, onMouseDown, onMouseUp, onPointerDown, onPointerUp, }) {
194
+ function handleChangeEvent(event) {
195
+ handleChange(event.target.value);
196
+ }
197
+ function handleChange(newValue) {
198
+ onChange === null || onChange === void 0 ? void 0 : onChange(timeStringToDate(newValue, value));
199
+ }
200
+ function handleBlur(event) {
201
+ onBlur === null || onBlur === void 0 ? void 0 : onBlur(event);
202
+ if (inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) {
203
+ if (!inputRef.current.checkValidity()) {
204
+ inputRef.current.value = "";
205
+ inputRef.current.valueAsDate = null;
206
+ // Remove validation error. This is mainly needed for Safari
207
+ inputRef.current.setCustomValidity("");
208
+ }
209
+ }
210
+ }
211
+ function handleClear() {
212
+ var _a;
213
+ // Clear the value and refocus without triggering blur event
214
+ onChange === null || onChange === void 0 ? void 0 : onChange(undefined);
215
+ (_a = inputRef === null || inputRef === void 0 ? void 0 : inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
216
+ }
217
+ function handleFocus(event) {
218
+ onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
219
+ }
220
+ function handleKeyDown(event) {
221
+ onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
222
+ }
223
+ function handleClick(event) {
224
+ onClick === null || onClick === void 0 ? void 0 : onClick(event);
225
+ }
226
+ function handleMouseDown(event) {
227
+ onMouseDown === null || onMouseDown === void 0 ? void 0 : onMouseDown(event);
228
+ }
229
+ function handleMouseUp(event) {
230
+ onMouseUp === null || onMouseUp === void 0 ? void 0 : onMouseUp(event);
231
+ }
232
+ function handlePointerDown(event) {
233
+ onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(event);
234
+ }
235
+ function handlePointerUp(event) {
236
+ onPointerUp === null || onPointerUp === void 0 ? void 0 : onPointerUp(event);
237
+ }
238
+ return {
239
+ handleChangeEvent,
240
+ handleChange,
241
+ handleBlur,
242
+ handleClear,
243
+ handleFocus,
244
+ handleKeyDown,
245
+ handleClick,
246
+ handleMouseDown,
247
+ handleMouseUp,
248
+ handlePointerDown,
249
+ handlePointerUp,
250
+ };
251
+ }
252
+
253
+ function InputTime(_a) {
254
+ var _b;
255
+ var { value, onChange, readOnly, autoComplete, inputRef, step = 60 } = _a, props = tslib_es6.__rest(_a, ["value", "onChange", "readOnly", "autoComplete", "inputRef", "step"]);
256
+ const { internalRef, mergedRef, wrapperRef } = useInputTimeRefs(inputRef);
257
+ const generatedId = React.useId();
258
+ const id = props.id || generatedId;
259
+ const { handleChangeEvent, handleChange, handleBlur, handleClear, handleFocus, handleKeyDown, handleClick, handleMouseDown, handleMouseUp, handlePointerDown, handlePointerUp, } = useInputTimeActions({
260
+ onChange,
261
+ value,
262
+ readOnly,
263
+ disabled: props.disabled,
264
+ inputRef: internalRef,
265
+ onFocus: props.onFocus,
266
+ onBlur: props.onBlur,
267
+ onKeyDown: props.onKeyDown,
268
+ onClick: props.onClick,
269
+ onMouseDown: props.onMouseDown,
270
+ onMouseUp: props.onMouseUp,
271
+ onPointerDown: props.onPointerDown,
272
+ onPointerUp: props.onPointerUp,
273
+ });
274
+ const { setTypedTime } = useTimePredict({
275
+ value,
276
+ handleChange,
277
+ });
278
+ // Kept outside the useInputTimeActions hook to avoid circular dependency via setTypedTime and handleChange
279
+ function handleKeyUp(event) {
280
+ var _a;
281
+ (_a = props.onKeyUp) === null || _a === void 0 ? void 0 : _a.call(props, event);
282
+ if (props.disabled || readOnly)
283
+ return;
284
+ !isNaN(parseInt(event.key, 10)) && setTypedTime(prev => prev + event.key);
285
+ }
286
+ const dataAttrs = filterDataAttributes.filterDataAttributes(props);
287
+ const descriptionIdentifier = `descriptionUUID--${id}`;
288
+ const descriptionVisible = props.description && !props.inline;
289
+ const isInvalid = Boolean(props.error || props.invalid);
290
+ return (React.createElement(FormFieldWrapper.FormFieldWrapper, { disabled: props.disabled, size: props.size, align: props.align, inline: props.inline, name: props.name, error: props.error || "", identifier: id, descriptionIdentifier: descriptionIdentifier, invalid: props.invalid, description: props.description, clearable: (_b = props.clearable) !== null && _b !== void 0 ? _b : "never", onClear: handleClear, type: "time", readonly: readOnly, placeholder: props.placeholder, value: dateToTimeString(value, step % 60 !== 0), wrapperRef: wrapperRef },
291
+ React.createElement("input", Object.assign({ ref: mergedRef, type: "time", name: props.name, className: FormFieldWrapper.formFieldStyles.input, id: id, disabled: props.disabled, readOnly: readOnly, autoComplete: autoComplete, autoFocus: props.autoFocus, required: props.required, max: props.max, min: props.min, step: step, value: dateToTimeString(value, step % 60 !== 0), onChange: handleChangeEvent, onBlur: handleBlur, onFocus: handleFocus, onKeyDown: handleKeyDown, onKeyUp: handleKeyUp, onClick: handleClick, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, onPointerDown: handlePointerDown, onPointerUp: handlePointerUp, "data-testid": "ATL-InputTime-input", "aria-label": props["aria-label"], "aria-describedby": descriptionVisible ? descriptionIdentifier : props["aria-describedby"], "aria-invalid": isInvalid ? true : undefined, "aria-required": props["aria-required"] }, dataAttrs))));
292
+ }
293
+ function useInputTimeRefs(inputRef) {
294
+ const internalRef = React.useRef(null);
295
+ const mergedRef = mergeRefs.mergeRefs([internalRef, inputRef]);
296
+ const wrapperRef = React.useRef(null);
297
+ return { internalRef, mergedRef, wrapperRef };
298
+ }
299
+
300
+ exports.InputTime = InputTime;