@swan-io/shared-business 8.14.0 → 8.14.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swan-io/shared-business",
3
- "version": "8.14.0",
3
+ "version": "8.14.2",
4
4
  "engines": {
5
5
  "node": ">=20.9.0",
6
6
  "yarn": "^1.22.0"
@@ -5,6 +5,5 @@ export type InlineDatePickerProps = {
5
5
  onValueChange: (value: ExtractedDate) => void;
6
6
  error?: string;
7
7
  onBlur?: () => void;
8
- order: "day-month-year" | "month-day-year";
9
8
  };
10
- export declare const InlineDatePicker: ({ value, label, onValueChange, error, onBlur, order, }: InlineDatePickerProps) => import("react/jsx-runtime").JSX.Element;
9
+ export declare const InlineDatePicker: ({ value, label, onValueChange, error, onBlur, }: InlineDatePickerProps) => import("react/jsx-runtime").JSX.Element;
@@ -5,10 +5,12 @@ import { LakeLabel } from "@swan-io/lake/src/components/LakeLabel";
5
5
  import { LakeSelect } from "@swan-io/lake/src/components/LakeSelect";
6
6
  import { LakeTextInput } from "@swan-io/lake/src/components/LakeTextInput";
7
7
  import { Stack } from "@swan-io/lake/src/components/Stack";
8
- import { colors } from "@swan-io/lake/src/constants/design";
8
+ import { breakpoints, colors } from "@swan-io/lake/src/constants/design";
9
+ import { useResponsive } from "@swan-io/lake/src/hooks/useResponsive";
9
10
  import { isNotNullish } from "@swan-io/lake/src/utils/nullish";
10
11
  import { StyleSheet, View } from "react-native";
11
- import { t } from "../utils/i18n";
12
+ import { match } from "ts-pattern";
13
+ import { getCountry, t } from "../utils/i18n";
12
14
  const months = [
13
15
  { value: "01", name: t("datePicker.month.january") },
14
16
  { value: "02", name: t("datePicker.month.february") },
@@ -24,10 +26,18 @@ const months = [
24
26
  { value: "12", name: t("datePicker.month.december") },
25
27
  ];
26
28
  const styles = StyleSheet.create({
29
+ dayMobile: {
30
+ maxWidth: 70,
31
+ flexGrow: 0,
32
+ },
27
33
  day: {
28
34
  maxWidth: 90,
29
35
  flexGrow: 0,
30
36
  },
37
+ yearMobile: {
38
+ maxWidth: 80,
39
+ flexGrow: 0,
40
+ },
31
41
  year: {
32
42
  maxWidth: 120,
33
43
  flexGrow: 0,
@@ -36,9 +46,16 @@ const styles = StyleSheet.create({
36
46
  borderColor: colors.negative[400],
37
47
  },
38
48
  });
39
- export const InlineDatePicker = ({ value = { day: "", month: "", year: "" }, label, onValueChange, error, onBlur, order, }) => {
49
+ // https://en.wikipedia.org/wiki/List_of_date_formats_by_country
50
+ const order = match(getCountry().cca2)
51
+ .returnType()
52
+ .with("US", () => "MDY")
53
+ .with("CN", "JP", "KR", "KP", "TW", "HU", "MN", "LT", "BT", () => "YMD")
54
+ .otherwise(() => "DMY");
55
+ export const InlineDatePicker = ({ value = { day: "", month: "", year: "" }, label, onValueChange, error, onBlur, }) => {
56
+ const { desktop } = useResponsive(breakpoints.small);
40
57
  return (_jsx(LakeLabel, { label: label, render: id => {
41
- const day = (_jsx(View, { style: styles.day, children: _jsx(LakeTextInput, { id: id, style: isNotNullish(error) && styles.error, placeholder: t("datePicker.day"), value: value.day, onBlur: onBlur, hideErrors: true, onChangeText: day => {
58
+ const day = (_jsx(View, { style: desktop ? styles.day : styles.dayMobile, children: _jsx(LakeTextInput, { id: id, style: isNotNullish(error) && styles.error, placeholder: t("datePicker.day"), value: value.day, onBlur: onBlur, hideErrors: true, onChangeText: day => {
42
59
  onValueChange({
43
60
  day,
44
61
  month: value.month,
@@ -52,11 +69,11 @@ export const InlineDatePicker = ({ value = { day: "", month: "", year: "" }, lab
52
69
  year: value.year,
53
70
  });
54
71
  } }));
55
- const year = (_jsx(View, { style: styles.year, children: _jsx(LakeTextInput, { value: value.year, style: isNotNullish(error) && styles.error, placeholder: t("datePicker.year"), onBlur: onBlur, hideErrors: true, onChangeText: year => onValueChange({
72
+ const year = (_jsx(View, { style: desktop ? styles.year : styles.yearMobile, children: _jsx(LakeTextInput, { value: value.year, style: isNotNullish(error) && styles.error, placeholder: t("datePicker.year"), onBlur: onBlur, hideErrors: true, onChangeText: year => onValueChange({
56
73
  day: value.day,
57
74
  month: value.month,
58
75
  year,
59
76
  }), pattern: "[0-9]", maxLength: 4, autoComplete: "bday-year" }) }));
60
- return (_jsxs(Box, { children: [order === "day-month-year" ? (_jsxs(Stack, { direction: "row", space: 12, children: [day, " ", month, " ", year] })) : (_jsxs(Stack, { direction: "row", space: 12, children: [month, " ", day, " ", year] })), _jsx(InputError, { message: error })] }));
77
+ return (_jsxs(Box, { children: [order === "DMY" ? (_jsxs(Stack, { direction: "row", space: 4, children: [day, " ", month, " ", year] })) : (_jsxs(Stack, { direction: "row", space: 4, children: [month, " ", day, " ", year] })), _jsx(InputError, { message: error })] }));
61
78
  } }));
62
79
  };
@@ -297,6 +297,6 @@
297
297
  "transactionStatement.title.debtor": "Debtor information",
298
298
  "transactionStatement.title.document": "Transaction confirmation",
299
299
  "transactionStatement.title.information": "Information",
300
- "validation.invalidBirthDate": "Invalid birthdate",
300
+ "validation.invalidBirthDate": "Please enter your complete and valid birth date: month, day, and year",
301
301
  "validation.birthdateCannotBeFuture": "Birthdate cannot be in the future"
302
302
  }
@@ -1,6 +1,7 @@
1
1
  import { RifmProps } from "@swan-io/lake/src/utils/rifm";
2
2
  import { ReactElement, ReactNode } from "react";
3
3
  import type { DateFormat } from "../components/DatePicker";
4
+ import { Country } from "../constants/countries";
4
5
  import translationEN from "../locales/en.json";
5
6
  declare const supportedLanguages: readonly ["en", "es", "de", "fr", "it", "nl", "pt", "fi"];
6
7
  type SupportedLanguage = (typeof supportedLanguages)[number];
@@ -21,4 +22,5 @@ export declare const formatNestedMessage: (key: TranslationKey, params: Record<s
21
22
  export declare const rifmDateProps: RifmProps;
22
23
  export declare const isTranslationKey: (value: unknown) => value is TranslationKey;
23
24
  export declare const translateError: (error: unknown) => string;
25
+ export declare const getCountry: () => Country;
24
26
  export {};
package/src/utils/i18n.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { createIntl, createIntlCache } from "@formatjs/intl";
2
+ import { isNotNullish } from "@swan-io/lake/src/utils/nullish";
2
3
  import { getRifmProps } from "@swan-io/lake/src/utils/rifm";
3
4
  import { BadStatusError } from "@swan-io/request";
4
5
  import dayjs from "dayjs";
@@ -16,6 +17,7 @@ import relativeTime from "dayjs/plugin/relativeTime";
16
17
  import utc from "dayjs/plugin/utc";
17
18
  import { cloneElement, isValidElement } from "react";
18
19
  import { P, match } from "ts-pattern";
20
+ import { countries, france } from "../constants/countries";
19
21
  import translationDE from "../locales/de.json";
20
22
  import translationEN from "../locales/en.json";
21
23
  import translationES from "../locales/es.json";
@@ -138,3 +140,17 @@ export const translateError = (error) => {
138
140
  .otherwise(() => "error.generic");
139
141
  return t(isTranslationKey(key) ? key : "error.generic");
140
142
  };
143
+ export const getCountry = () => {
144
+ const navigatorCountries = navigator.languages
145
+ .map(language => language.split("-")[1])
146
+ .filter(isNotNullish);
147
+ for (let index = 0; index < navigatorCountries.length; index++) {
148
+ const navigatorCountry = navigatorCountries[index];
149
+ const country = countries.find(({ cca2 }) => cca2 === navigatorCountry);
150
+ if (isNotNullish(country)) {
151
+ return country;
152
+ }
153
+ }
154
+ // fallback to france when no valid country found in navigator locales
155
+ return france;
156
+ };
@@ -106,7 +106,7 @@ export const validateIban = (iban) => {
106
106
  };
107
107
  export const validateBirthdate = (value) => {
108
108
  const date = dayjs.utc(formatExtractedDate(value), "YYYY-MM-DD", true);
109
- const isBirthdateOver150years = date.isBefore(dayjs.utc().subtract(150, "years"));
109
+ const isBirthdateOver150years = date.isBefore(dayjs.utc().subtract(100, "years"));
110
110
  const isBirthdateWithin4years = date.isAfter(dayjs.utc().subtract(4, "years"));
111
111
  if (!date.isValid() || isBirthdateOver150years || isBirthdateWithin4years) {
112
112
  return t("validation.invalidBirthDate");