@jobber/components-native 0.35.0 → 0.35.1-JOB-70282.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/AtlantisContext/AtlantisContext.js +1 -0
- package/dist/src/InputDate/InputDate.js +68 -0
- package/dist/src/InputDate/index.js +1 -0
- package/dist/src/InputDate/messages.js +8 -0
- package/dist/src/hooks/useFormattedDate/index.js +1 -0
- package/dist/src/hooks/useFormattedDate/useFormattedDate.js +18 -0
- package/dist/src/index.js +1 -0
- package/dist/src/utils/format/date.js +46 -0
- package/dist/src/utils/format/index.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/src/AtlantisContext/AtlantisContext.d.ts +2 -1
- package/dist/types/src/InputDate/InputDate.d.ts +74 -0
- package/dist/types/src/InputDate/index.d.ts +1 -0
- package/dist/types/src/InputDate/messages.d.ts +7 -0
- package/dist/types/src/hooks/useFormattedDate/index.d.ts +2 -0
- package/dist/types/src/hooks/useFormattedDate/useFormattedDate.d.ts +3 -0
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/utils/format/date.d.ts +13 -0
- package/dist/types/src/utils/format/index.d.ts +1 -0
- package/package.json +2 -2
- package/src/AtlantisContext/AtlantisContext.tsx +3 -1
- package/src/InputDate/InputDate.test.tsx +232 -0
- package/src/InputDate/InputDate.tsx +222 -0
- package/src/InputDate/index.ts +1 -0
- package/src/InputDate/messages.ts +9 -0
- package/src/hooks/useFormattedDate/index.ts +2 -0
- package/src/hooks/useFormattedDate/useFormattedDate.test.tsx +33 -0
- package/src/hooks/useFormattedDate/useFormattedDate.ts +32 -0
- package/src/index.ts +1 -0
- package/src/utils/format/date.test.ts +72 -0
- package/src/utils/format/date.ts +69 -0
- package/src/utils/format/index.ts +5 -0
|
@@ -3,6 +3,7 @@ import { createContext, useContext } from "react";
|
|
|
3
3
|
import RNLocalize from "react-native-localize";
|
|
4
4
|
import { DEFAULT_CURRENCY_SYMBOL } from "../InputCurrency/constants";
|
|
5
5
|
export const defaultValues = {
|
|
6
|
+
dateFormat: "%b %d, %Y",
|
|
6
7
|
// The system time is "p"
|
|
7
8
|
timeFormat: "p",
|
|
8
9
|
timeZone: RNLocalize.getTimeZone(),
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React, { useMemo, useState } from "react";
|
|
2
|
+
import DateTimePicker from "react-native-modal-datetime-picker";
|
|
3
|
+
import { Platform } from "react-native";
|
|
4
|
+
import { useIntl } from "react-intl";
|
|
5
|
+
import { messages } from "./messages";
|
|
6
|
+
import { useFormattedDate } from "../hooks/useFormattedDate";
|
|
7
|
+
import { FormField } from "../FormField";
|
|
8
|
+
import { InputPressable } from "../InputPressable";
|
|
9
|
+
function formatInvalidState(error, invalid) {
|
|
10
|
+
if (invalid)
|
|
11
|
+
return invalid;
|
|
12
|
+
if (error && error.message) {
|
|
13
|
+
return error.message;
|
|
14
|
+
}
|
|
15
|
+
return Boolean(error);
|
|
16
|
+
}
|
|
17
|
+
const display = Platform.OS === "ios" ? "inline" : "default";
|
|
18
|
+
/**
|
|
19
|
+
* Allow users to select a date using the device date picker.
|
|
20
|
+
*/
|
|
21
|
+
export function InputDate(props) {
|
|
22
|
+
if (props.name) {
|
|
23
|
+
return (React.createElement(FormField, { name: props.name, defaultValue: props.defaultValue, validations: props.validations }, ({ value, onChange, onBlur }, error) => (React.createElement(InternalInputDate, Object.assign({}, props, { value: value, onChange: (newValue) => {
|
|
24
|
+
var _a;
|
|
25
|
+
onChange(newValue);
|
|
26
|
+
onBlur();
|
|
27
|
+
(_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, newValue);
|
|
28
|
+
}, invalid: formatInvalidState(error, props.invalid) })))));
|
|
29
|
+
}
|
|
30
|
+
return React.createElement(InternalInputDate, Object.assign({}, props));
|
|
31
|
+
}
|
|
32
|
+
function InternalInputDate({ clearable = "always", disabled, emptyValueLabel, invalid, maxDate, minDate, placeholder, value, name, onChange, accessibilityLabel, accessibilityHint, }) {
|
|
33
|
+
const [showPicker, setShowPicker] = useState(false);
|
|
34
|
+
const formatDate = useFormattedDate();
|
|
35
|
+
const { formatMessage } = useIntl();
|
|
36
|
+
const date = useMemo(() => {
|
|
37
|
+
if (typeof value === "string")
|
|
38
|
+
return new Date(value);
|
|
39
|
+
return value;
|
|
40
|
+
}, [value]);
|
|
41
|
+
const formattedDate = useMemo(() => { var _a; return (_a = (date && formatDate(date, "accountFormat"))) !== null && _a !== void 0 ? _a : emptyValueLabel; }, [date, emptyValueLabel, formatDate]);
|
|
42
|
+
const canClearDate = formattedDate === emptyValueLabel ? "never" : clearable;
|
|
43
|
+
const placeholderLabel = placeholder !== null && placeholder !== void 0 ? placeholder : formatMessage(messages.datePlaceholder);
|
|
44
|
+
return (React.createElement(React.Fragment, null,
|
|
45
|
+
React.createElement(InputPressable, { clearable: canClearDate, disabled: disabled, invalid: invalid, placeholder: placeholderLabel, prefix: { icon: "calendar" }, value: formattedDate, onClear: handleClear, onPress: showDatePicker, accessibilityLabel: accessibilityLabel, accessibilityHint: accessibilityHint }),
|
|
46
|
+
React.createElement(DateTimePicker, { testID: "inputDate-datePicker", date: date || undefined, display: display, isVisible: showPicker, maximumDate: maxDate, minimumDate: minDate, mode: "date", onCancel: handleCancel, onConfirm: handleConfirm })));
|
|
47
|
+
function showDatePicker() {
|
|
48
|
+
setShowPicker(true);
|
|
49
|
+
}
|
|
50
|
+
function handleConfirm(newVal) {
|
|
51
|
+
setShowPicker(false);
|
|
52
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newVal);
|
|
53
|
+
}
|
|
54
|
+
function handleCancel() {
|
|
55
|
+
setShowPicker(false);
|
|
56
|
+
// Ensure a change happens so we trigger the validation of one exists
|
|
57
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(date);
|
|
58
|
+
}
|
|
59
|
+
function handleClear() {
|
|
60
|
+
// Returns null only for Form controlled scenarios due to a limitation of react-hook-form that doesn't allow passing undefined to form values.
|
|
61
|
+
if (name) {
|
|
62
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(null);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(undefined);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { InputDate } from "./InputDate";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useFormattedDate } from "./useFormattedDate";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { formatInTimeZone } from "date-fns-tz";
|
|
2
|
+
import { useAtlantisContext } from "../../AtlantisContext";
|
|
3
|
+
import { accountFormattedDate, shortFormattedDate, } from "../../utils/format/date";
|
|
4
|
+
function formatDate(date, format, accountTimeZoneName, accountDateFormat) {
|
|
5
|
+
if (format === "shorthand") {
|
|
6
|
+
return shortFormattedDate(date, accountTimeZoneName);
|
|
7
|
+
}
|
|
8
|
+
else if (format === "ISO8601") {
|
|
9
|
+
return formatInTimeZone(date, accountTimeZoneName, "yyyy-MM-dd");
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
return accountFormattedDate(date, accountDateFormat, accountTimeZoneName);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function useFormattedDate() {
|
|
16
|
+
const { timeZone, dateFormat } = useAtlantisContext();
|
|
17
|
+
return (date, format) => formatDate(date, format, timeZone, dateFormat);
|
|
18
|
+
}
|
package/dist/src/index.js
CHANGED
|
@@ -19,6 +19,7 @@ export * from "./Icon";
|
|
|
19
19
|
export * from "./IconButton";
|
|
20
20
|
export * from "./InputFieldWrapper";
|
|
21
21
|
export * from "./InputCurrency";
|
|
22
|
+
export * from "./InputDate";
|
|
22
23
|
export * from "./InputNumber";
|
|
23
24
|
export * from "./InputPassword";
|
|
24
25
|
export * from "./InputPressable";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { isValid } from "date-fns";
|
|
2
|
+
import { enUS } from "date-fns/locale";
|
|
3
|
+
import { format } from "date-fns-tz";
|
|
4
|
+
export function accountFormattedDate(date, accountFormat, timeZone) {
|
|
5
|
+
if (!isValid(date)) {
|
|
6
|
+
return "";
|
|
7
|
+
}
|
|
8
|
+
// must take into account the timezone before obtaining
|
|
9
|
+
// any of the day/month/year values
|
|
10
|
+
const formattedDate = format(date, "dd|MM|MMM|y", {
|
|
11
|
+
locale: enUS,
|
|
12
|
+
timeZone: timeZone,
|
|
13
|
+
});
|
|
14
|
+
const [dd, MM, MMM, y] = formattedDate.split("|");
|
|
15
|
+
if (accountFormat === "%m/%d/%Y") {
|
|
16
|
+
return `${MM}/${dd}/${y}`; // 09/30/1992
|
|
17
|
+
}
|
|
18
|
+
else if (accountFormat === "%d/%m/%Y") {
|
|
19
|
+
return `${dd}/${MM}/${y}`; // 30/09/1992
|
|
20
|
+
}
|
|
21
|
+
else if (accountFormat === "%Y-%m-%d") {
|
|
22
|
+
return `${y}-${MM}-${dd}`; // 1992-09-30
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
return `${MMM} ${dd}, ${y}`; // Sep 30, 1992
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/***
|
|
29
|
+
* Returns a date in "MMM dd" format (e.g. July 01), using the provided timezone
|
|
30
|
+
*/
|
|
31
|
+
export function shortFormattedDate(date, timeZone) {
|
|
32
|
+
if (!isValid(date)) {
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
return format(date, "MMM dd", { locale: enUS, timeZone: timeZone });
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
* @param date
|
|
40
|
+
* Returns a date in true utc time with the timezone offset
|
|
41
|
+
* @returns Date
|
|
42
|
+
*/
|
|
43
|
+
export function convertDateToUTC(date) {
|
|
44
|
+
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds()) +
|
|
45
|
+
date.getTimezoneOffset() * 60 * 1000);
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { accountFormattedDate, shortFormattedDate, convertDateToUTC, } from "./date";
|