@jobber/components-native 0.34.0 → 0.35.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.
- package/dist/src/InputTime/InputTime.js +83 -0
- package/dist/src/InputTime/InputTime.style.js +7 -0
- package/dist/src/InputTime/index.js +2 -0
- package/dist/src/InputTime/messages.js +8 -0
- package/dist/src/InputTime/utils/index.js +16 -0
- package/dist/src/index.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/src/InputTime/InputTime.d.ts +61 -0
- package/dist/types/src/InputTime/InputTime.style.d.ts +6 -0
- package/dist/types/src/InputTime/index.d.ts +2 -0
- package/dist/types/src/InputTime/messages.d.ts +7 -0
- package/dist/types/src/InputTime/utils/index.d.ts +11 -0
- package/dist/types/src/index.d.ts +1 -0
- package/package.json +7 -3
- package/src/InputTime/InputTime.style.ts +8 -0
- package/src/InputTime/InputTime.test.tsx +323 -0
- package/src/InputTime/InputTime.tsx +221 -0
- package/src/InputTime/index.tsx +2 -0
- package/src/InputTime/messages.ts +9 -0
- package/src/InputTime/utils/index.ts +26 -0
- package/src/InputTime/utils/utils.test.ts +47 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React, { useMemo, useState } from "react";
|
|
2
|
+
import DateTimePicker from "react-native-modal-datetime-picker";
|
|
3
|
+
import { View } from "react-native";
|
|
4
|
+
import { useIntl } from "react-intl";
|
|
5
|
+
import { utcToZonedTime } from "date-fns-tz";
|
|
6
|
+
import { format as formatTime } from "date-fns";
|
|
7
|
+
import { styles } from "./InputTime.style";
|
|
8
|
+
import { messages } from "./messages";
|
|
9
|
+
import { getTimeZoneOffsetInMinutes, roundUpToNearestMinutes } from "./utils";
|
|
10
|
+
import { useAtlantisContext } from "../AtlantisContext";
|
|
11
|
+
import { InputPressable } from "../InputPressable";
|
|
12
|
+
import { FormField } from "../FormField";
|
|
13
|
+
const LOCALE_24_HOURS = "en_GB";
|
|
14
|
+
const LOCALE_12_HOURS = "en_US";
|
|
15
|
+
function formatInvalidState(error, invalid) {
|
|
16
|
+
if (invalid)
|
|
17
|
+
return invalid;
|
|
18
|
+
if (error && error.message) {
|
|
19
|
+
return error.message;
|
|
20
|
+
}
|
|
21
|
+
return Boolean(error);
|
|
22
|
+
}
|
|
23
|
+
export function InputTime(props) {
|
|
24
|
+
if (props.name) {
|
|
25
|
+
return (React.createElement(FormField, { name: props.name, validations: props.validations }, (field, error) => (React.createElement(InternalInputTime, Object.assign({}, props, { value: field.value, onChange: (newValue) => {
|
|
26
|
+
var _a;
|
|
27
|
+
field.onChange(newValue);
|
|
28
|
+
field.onBlur();
|
|
29
|
+
(_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, newValue);
|
|
30
|
+
}, invalid: formatInvalidState(error, props.invalid) })))));
|
|
31
|
+
}
|
|
32
|
+
return React.createElement(InternalInputTime, Object.assign({}, props));
|
|
33
|
+
}
|
|
34
|
+
function InternalInputTime({ clearable = "always", disabled, emptyValueLabel, invalid, placeholder, value, name, type = "scheduling", onChange, showIcon = true, }) {
|
|
35
|
+
const [showPicker, setShowPicker] = useState(false);
|
|
36
|
+
const { formatMessage } = useIntl();
|
|
37
|
+
const { timeZone, timeFormat } = useAtlantisContext();
|
|
38
|
+
const is24Hour = timeFormat === "HH:mm";
|
|
39
|
+
const dateTime = useMemo(() => (typeof value === "string" ? new Date(value) : value), [value]);
|
|
40
|
+
const formattedTime = useMemo(() => {
|
|
41
|
+
if (dateTime) {
|
|
42
|
+
const zonedTime = utcToZonedTime(dateTime, timeZone);
|
|
43
|
+
return formatTime(zonedTime, timeFormat);
|
|
44
|
+
}
|
|
45
|
+
return emptyValueLabel;
|
|
46
|
+
}, [dateTime, emptyValueLabel, timeZone, timeFormat]);
|
|
47
|
+
const canClearTime = formattedTime === emptyValueLabel ? "never" : clearable;
|
|
48
|
+
return (React.createElement(View, { style: styles.container },
|
|
49
|
+
React.createElement(InputPressable, { clearable: canClearTime, disabled: disabled, invalid: invalid, placeholder: placeholder !== null && placeholder !== void 0 ? placeholder : formatMessage(messages.time), prefix: showIcon ? { icon: "timer" } : undefined, value: formattedTime, onClear: handleClear, onPress: showDatePicker }),
|
|
50
|
+
React.createElement(DateTimePicker, { testID: "inputTime-Picker", minuteInterval: getMinuteInterval(type), date: getInitialPickerDate(dateTime), timeZoneOffsetInMinutes: getTimeZoneOffsetInMinutes(timeZone, dateTime), isVisible: showPicker, mode: "time", onCancel: handleCancel, onConfirm: handleConfirm, is24Hour: is24Hour, locale: is24Hour ? LOCALE_24_HOURS : LOCALE_12_HOURS })));
|
|
51
|
+
function showDatePicker() {
|
|
52
|
+
setShowPicker(true);
|
|
53
|
+
}
|
|
54
|
+
function handleConfirm(newValue) {
|
|
55
|
+
setShowPicker(false);
|
|
56
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
|
|
57
|
+
}
|
|
58
|
+
function handleCancel() {
|
|
59
|
+
setShowPicker(false);
|
|
60
|
+
// Call onChange with the current value to trigger form's validation.
|
|
61
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(dateTime);
|
|
62
|
+
}
|
|
63
|
+
function handleClear() {
|
|
64
|
+
// Returns null only for Form controlled scenarios due to a limitation of
|
|
65
|
+
// react-hook-form that doesn't allow passing undefined to form values.
|
|
66
|
+
if (name) {
|
|
67
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(null);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(undefined);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function getInitialPickerDate(date) {
|
|
75
|
+
if (date)
|
|
76
|
+
return date;
|
|
77
|
+
return roundUpToNearestMinutes(new Date(), 30);
|
|
78
|
+
}
|
|
79
|
+
function getMinuteInterval(type) {
|
|
80
|
+
if (type === "granular")
|
|
81
|
+
return 1;
|
|
82
|
+
return 5;
|
|
83
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getTimezoneOffset } from "date-fns-tz";
|
|
2
|
+
/**
|
|
3
|
+
* Rounds up the time by increment.
|
|
4
|
+
* - 15 mins - rounds to the next quarter time of `00:15`, `00:30`, `00:45`,
|
|
5
|
+
* and `01:00`
|
|
6
|
+
* - 30 mins - rounds to the next half hour be it `00:30` or `01:00`
|
|
7
|
+
* - 60 mins - rounds to the next hour. I.e., `02:01` gets rounded up
|
|
8
|
+
* to `03:00`.
|
|
9
|
+
*/
|
|
10
|
+
export function roundUpToNearestMinutes(date, minutes) {
|
|
11
|
+
const ms = 1000 * 60 * minutes;
|
|
12
|
+
return new Date(Math.ceil(date.getTime() / ms) * ms);
|
|
13
|
+
}
|
|
14
|
+
export function getTimeZoneOffsetInMinutes(timeZone, date) {
|
|
15
|
+
return getTimezoneOffset(timeZone, date) / 1000 / 60;
|
|
16
|
+
}
|
package/dist/src/index.js
CHANGED
|
@@ -23,6 +23,7 @@ export * from "./InputNumber";
|
|
|
23
23
|
export * from "./InputPassword";
|
|
24
24
|
export * from "./InputPressable";
|
|
25
25
|
export * from "./InputSearch";
|
|
26
|
+
export * from "./InputTime";
|
|
26
27
|
export * from "./InputText";
|
|
27
28
|
export * from "./TextList";
|
|
28
29
|
export * from "./ProgressBar";
|