@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.
Files changed (32) hide show
  1. package/dist/src/AtlantisContext/AtlantisContext.js +1 -0
  2. package/dist/src/InputDate/InputDate.js +68 -0
  3. package/dist/src/InputDate/index.js +1 -0
  4. package/dist/src/InputDate/messages.js +8 -0
  5. package/dist/src/hooks/useFormattedDate/index.js +1 -0
  6. package/dist/src/hooks/useFormattedDate/useFormattedDate.js +18 -0
  7. package/dist/src/index.js +1 -0
  8. package/dist/src/utils/format/date.js +46 -0
  9. package/dist/src/utils/format/index.js +1 -0
  10. package/dist/tsconfig.tsbuildinfo +1 -1
  11. package/dist/types/src/AtlantisContext/AtlantisContext.d.ts +2 -1
  12. package/dist/types/src/InputDate/InputDate.d.ts +74 -0
  13. package/dist/types/src/InputDate/index.d.ts +1 -0
  14. package/dist/types/src/InputDate/messages.d.ts +7 -0
  15. package/dist/types/src/hooks/useFormattedDate/index.d.ts +2 -0
  16. package/dist/types/src/hooks/useFormattedDate/useFormattedDate.d.ts +3 -0
  17. package/dist/types/src/index.d.ts +1 -0
  18. package/dist/types/src/utils/format/date.d.ts +13 -0
  19. package/dist/types/src/utils/format/index.d.ts +1 -0
  20. package/package.json +2 -2
  21. package/src/AtlantisContext/AtlantisContext.tsx +3 -1
  22. package/src/InputDate/InputDate.test.tsx +232 -0
  23. package/src/InputDate/InputDate.tsx +222 -0
  24. package/src/InputDate/index.ts +1 -0
  25. package/src/InputDate/messages.ts +9 -0
  26. package/src/hooks/useFormattedDate/index.ts +2 -0
  27. package/src/hooks/useFormattedDate/useFormattedDate.test.tsx +33 -0
  28. package/src/hooks/useFormattedDate/useFormattedDate.ts +32 -0
  29. package/src/index.ts +1 -0
  30. package/src/utils/format/date.test.ts +72 -0
  31. package/src/utils/format/date.ts +69 -0
  32. 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,8 @@
1
+ import { defineMessages } from "react-intl";
2
+ export const messages = defineMessages({
3
+ datePlaceholder: {
4
+ id: "datePlaceholder",
5
+ defaultMessage: "Date",
6
+ description: "Default input label for the InputDate component",
7
+ },
8
+ });
@@ -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";