@swan-io/shared-business 13.9.0 → 13.9.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": "13.9.0",
3
+ "version": "13.9.2",
4
4
  "engines": {
5
5
  "node": ">22.12.0"
6
6
  },
@@ -25,7 +25,7 @@
25
25
  ],
26
26
  "license": "MIT",
27
27
  "peerDependencies": {
28
- "@swan-io/lake": "13.9.0"
28
+ "@swan-io/lake": "13.9.2"
29
29
  },
30
30
  "dependencies": {
31
31
  "@formatjs/intl": "^4.1.2",
@@ -50,6 +50,6 @@
50
50
  "@types/react-dom": "^19.2.3",
51
51
  "@types/react-native": "^0.72.8",
52
52
  "type-fest": "^5.4.3",
53
- "@swan-io/lake": "13.9.0"
53
+ "@swan-io/lake": "13.9.2"
54
54
  }
55
55
  }
@@ -1,6 +1,7 @@
1
1
  import { Future, Result } from "@swan-io/boxed";
2
2
  import { NetworkError, Response, TimeoutError } from "@swan-io/request";
3
3
  import { Ref } from "react";
4
+ import { CountryCCA3 } from "../constants/countries";
4
5
  import { UploadFileInput, UploadOutputWithId } from "../hooks/useFilesUploader";
5
6
  import { SwanFile } from "../utils/SwanFile";
6
7
  export type Document<Purpose extends string> = {
@@ -45,6 +46,7 @@ type Props<Purpose extends string> = {
45
46
  onChange?: (documents: Document<Purpose>[]) => void;
46
47
  onRemoveFile?: (file: SwanFile) => Future<Result<unknown, unknown>>;
47
48
  templateLanguage?: string;
49
+ companyCountry?: CountryCCA3;
48
50
  showIds?: boolean;
49
51
  readOnly?: boolean;
50
52
  getPurposeMetadata?: (purose: Purpose) => PurposeMetadata | undefined;
@@ -52,5 +54,5 @@ type Props<Purpose extends string> = {
52
54
  };
53
55
  export declare const getSupportingDocumentPurposeLabel: (purpose: string) => string;
54
56
  export declare const getSupportingDocumentPurposeDescriptionLabel: (purpose: string) => string;
55
- export declare const SupportingDocumentCollection: <Purpose extends string>({ ref, documents, generateUpload, uploadFile, requiredDocumentPurposes, templateLanguage, status, onChange, onRemoveFile, showIds, readOnly, getPurposeMetadata, readonlyDocumentPurposes, }: Props<Purpose>) => import("react/jsx-runtime").JSX.Element;
57
+ export declare const SupportingDocumentCollection: <Purpose extends string>({ ref, documents, generateUpload, uploadFile, requiredDocumentPurposes, templateLanguage, status, onChange, onRemoveFile, showIds, readOnly, getPurposeMetadata, companyCountry, readonlyDocumentPurposes, }: Props<Purpose>) => import("react/jsx-runtime").JSX.Element;
56
58
  export {};
@@ -14,7 +14,7 @@ import { isNotNullish } from "@swan-io/lake/src/utils/nullish";
14
14
  import { badStatusToError, Request } from "@swan-io/request";
15
15
  import { Fragment, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
16
16
  import { StyleSheet } from "react-native";
17
- import { match } from "ts-pattern";
17
+ import { match, P } from "ts-pattern";
18
18
  import { isTranslationKey, locale, t } from "../utils/i18n";
19
19
  import { FilesUploader } from "./FilesUploader";
20
20
  import { LakeModal } from "./LakeModal";
@@ -35,12 +35,13 @@ const Help = (props) => {
35
35
  })
36
36
  .exhaustive();
37
37
  };
38
- const getSupportLink = (language) => match(language)
39
- .with("fr", () => "https://support.swan.io/hc/en-150/articles/22502977563933--Proof-of-registration-for-French-companies")
40
- .with("it", () => "https://support.swan.io/hc/en-150/articles/22537604831005--Proof-of-registration-for-Italian-companies")
41
- .with("de", () => "https://support.swan.io/hc/en-150/articles/22535023588509--Proof-of-registration-for-German-companies")
42
- .with("es", () => "https://support.swan.io/hc/en-150/articles/22544703221021--Proof-of-registration-for-Spanish-companies")
43
- .with("nl", () => "https://support.swan.io/hc/en-150/articles/22543228421277--Proof-of-registration-for-Dutch-companies")
38
+ const getSupportLink = (language, country) => match({ language, country })
39
+ .with(P.union({ country: "FRA" }, { country: P.nullish, language: "fr" }), () => `https://support.swan.io/hc/${language}/articles/22502977563933`)
40
+ .with(P.union({ country: "ITA" }, { country: P.nullish, language: "it" }), () => `https://support.swan.io/hc/${language}/articles/22537604831005`)
41
+ .with(P.union({ country: "DEU" }, { country: P.nullish, language: "de" }), () => `https://support.swan.io/hc/${language}/articles/22535023588509`)
42
+ .with(P.union({ country: "ESP" }, { country: P.nullish, language: "es" }), () => `https://support.swan.io/hc/${language}/articles/22544703221021`)
43
+ .with(P.union({ country: "NLD" }, { country: P.nullish, language: "nl" }), () => `https://support.swan.io/hc/${language}/articles/22543228421277`)
44
+ .with(P.union({ country: "BEL" }), () => `https://support.swan.io/hc/${language}/articles/31233251462173`)
44
45
  .otherwise(() => "https://support.swan.io/hc/en-150/articles/22620756787869-Proof-of-company-registration");
45
46
  export const getSupportingDocumentPurposeLabel = (purpose) => {
46
47
  const key = `supportingDocuments.purpose.${purpose}`;
@@ -50,7 +51,7 @@ export const getSupportingDocumentPurposeDescriptionLabel = (purpose) => {
50
51
  const key = `supportingDocuments.purpose.${purpose}.description`;
51
52
  return isTranslationKey(key) ? t(key) : "";
52
53
  };
53
- export const SupportingDocumentCollection = ({ ref, documents, generateUpload, uploadFile, requiredDocumentPurposes, templateLanguage = locale.language, status, onChange, onRemoveFile, showIds = false, readOnly = false, getPurposeMetadata, readonlyDocumentPurposes = [], }) => {
54
+ export const SupportingDocumentCollection = ({ ref, documents, generateUpload, uploadFile, requiredDocumentPurposes, templateLanguage = locale.language, status, onChange, onRemoveFile, showIds = false, readOnly = false, getPurposeMetadata, companyCountry, readonlyDocumentPurposes = [], }) => {
54
55
  const [showPowerOfAttorneyModal, setShowPowerOfAttorneyModal] = useState(false);
55
56
  const [showSwornStatementModal, setShowSwornStatementModal] = useState(false);
56
57
  const [currentMetadata, setCurrentMetadata] = useState(undefined);
@@ -131,8 +132,8 @@ export const SupportingDocumentCollection = ({ ref, documents, generateUpload, u
131
132
  return (_jsxs(Form, { children: [showableDocumentPurposes.map(({ purpose, files, areAllDocumentsValidated, isRequired }) => {
132
133
  var _a, _b, _c, _d, _e, _f;
133
134
  const metadata = getPurposeMetadata === null || getPurposeMetadata === void 0 ? void 0 : getPurposeMetadata(purpose);
134
- return (_jsxs(Fragment, { children: [_jsx(LakeLabel, { label: (_b = (_a = requiredDocumentPurposes[purpose]) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : getSupportingDocumentPurposeLabel(purpose), description: (_f = (_d = (_c = requiredDocumentPurposes[purpose]) === null || _c === void 0 ? void 0 : _c.purposeDetails) !== null && _d !== void 0 ? _d : (_e = requiredDocumentPurposes[purpose]) === null || _e === void 0 ? void 0 : _e.description) !== null && _f !== void 0 ? _f : getSupportingDocumentPurposeDescriptionLabel(purpose), render: () => (_jsxs(_Fragment, { children: [_jsxs(Box, { direction: "row", children: [_jsx(Box, { direction: "row", children: isNotNullish(metadata) ? (purpose === "CompanyRegistration" ? (_jsxs(_Fragment, { children: [_jsx(LakeButton, { size: "small", mode: "secondary", icon: "question-circle-regular", onPress: () => window.open(getSupportLink(locale.language)), ariaLabel: t("supportingDocuments.help.howToSendAGoodDocument"), children: t("supportingDocuments.help.howToSendAGoodDocument") }), _jsx(Space, { width: 8 })] })) : (_jsxs(_Fragment, { children: [_jsx(Help, { type: "button", label: metadata.title, onPress: () => setCurrentMetadata(metadata) }), _jsx(Space, { width: 8 })] }))) : (match(purpose)
135
- .with("CompanyRegistration", () => (_jsx(LakeButton, { size: "small", mode: "secondary", icon: "question-circle-regular", onPress: () => window.open(getSupportLink(locale.language)), ariaLabel: t("supportingDocuments.help.howToSendAGoodDocument"), children: t("supportingDocuments.help.howToSendAGoodDocument") })))
135
+ return (_jsxs(Fragment, { children: [_jsx(LakeLabel, { label: (_b = (_a = requiredDocumentPurposes[purpose]) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : getSupportingDocumentPurposeLabel(purpose), description: (_f = (_d = (_c = requiredDocumentPurposes[purpose]) === null || _c === void 0 ? void 0 : _c.purposeDetails) !== null && _d !== void 0 ? _d : (_e = requiredDocumentPurposes[purpose]) === null || _e === void 0 ? void 0 : _e.description) !== null && _f !== void 0 ? _f : getSupportingDocumentPurposeDescriptionLabel(purpose), render: () => (_jsxs(_Fragment, { children: [_jsxs(Box, { direction: "row", children: [_jsx(Box, { direction: "row", children: isNotNullish(metadata) ? (purpose === "CompanyRegistration" ? (_jsxs(_Fragment, { children: [_jsx(LakeButton, { size: "small", mode: "secondary", icon: "question-circle-regular", onPress: () => window.open(getSupportLink(locale.language, companyCountry)), ariaLabel: t("supportingDocuments.help.howToSendAGoodDocument"), children: t("supportingDocuments.help.howToSendAGoodDocument") }), _jsx(Space, { width: 8 })] })) : (_jsxs(_Fragment, { children: [_jsx(Help, { type: "button", label: metadata.title, onPress: () => setCurrentMetadata(metadata) }), _jsx(Space, { width: 8 })] }))) : (match(purpose)
136
+ .with("CompanyRegistration", () => (_jsx(LakeButton, { size: "small", mode: "secondary", icon: "question-circle-regular", onPress: () => window.open(getSupportLink(locale.language, companyCountry)), ariaLabel: t("supportingDocuments.help.howToSendAGoodDocument"), children: t("supportingDocuments.help.howToSendAGoodDocument") })))
136
137
  .otherwise(() => null)) }), match(purpose)
137
138
  .with("PowerOfAttorney", () => (_jsx(Help, { type: "button", icon: "arrow-down-filled", label: t("supportingDocuments.help.downloadTemplate"), onPress: () => setShowPowerOfAttorneyModal(true) })))
138
139
  .with("SwornStatement", () => (_jsx(Help, { type: "button", icon: "arrow-down-filled", label: t("supportingDocuments.help.downloadTemplate"), onPress: () => setShowSwornStatementModal(true) })))
@@ -1,9 +1,9 @@
1
1
  import { isNullish } from "@swan-io/lake/src/utils/nullish";
2
2
  import dayjs from "dayjs";
3
3
  import { isValid as isValidIban } from "iban";
4
- import { match } from "ts-pattern";
4
+ import { match, P } from "ts-pattern";
5
5
  import { formatExtractedDate } from "./date";
6
- import { t } from "./i18n";
6
+ import { locale, t } from "./i18n";
7
7
  const EMAIL_REGEX = /^[A-Z0-9_+.-]*[A-Z0-9_+-]@([A-Z0-9][A-Z0-9-]*\.)+[A-Z]{2,}$/i;
8
8
  const VAT_NUMBER_REGEX = /^((AT)?U[0-9]{8}|(BE)?[01][0-9]{9}|(BG)?[0-9]{9,10}|(CY)?[0-9]{8}L|(CZ)?[0-9]{8,10}|(DE)?[0-9]{9}|(DK)?[0-9]{8}|(EE)?[0-9]{9}|(EL|GR)?[0-9]{9}|(ES)?[0-9A-Z][0-9]{7}[0-9A-Z]|(FI)?[0-9]{8}|(FR)?[0-9A-Z]{2}[0-9]{9}|(GB)?([0-9]{9}([0-9]{3})?|[A-Z]{2}[0-9]{3})|(HU)?[0-9]{8}|(IE)?[0-9]S[0-9]{5}L|(IT)?[0-9]{11}|(LT)?([0-9]{9}|[0-9]{12})|(LU)?[0-9]{8}|(LV)?[0-9]{11}|(MT)?[0-9]{8}|(NL)?[0-9]{9}B[0-9]{2}|(PL)?[0-9]{10}|(PT)?[0-9]{9}|(RO)?[0-9]{2,10}|(SE)?[0-9]{12}|(SI)?[0-9]{8}|(SK)?[0-9]{10})$/;
9
9
  // (AT)?U[0-9]{8} | # Austria
@@ -238,15 +238,15 @@ export const validateBirthdate = (value) => {
238
238
  /*
239
239
  * Translation helpers for tax validation
240
240
  */
241
- export const getIndividualTaxNumberPlaceholder = (country) => match(country)
242
- .with("DEU", () => `${t("common.form.taxIdentificationNumber.placeholder")} (Steueridentifikationsnummer)`)
243
- .with("ESP", () => `${t("common.form.taxIdentificationNumber.placeholder")} (Número de Identificación Fiscal)`)
244
- .with("ITA", () => `${t("common.form.taxIdentificationNumber.placeholder")} (Codice fiscale)`)
241
+ export const getIndividualTaxNumberPlaceholder = (country) => match({ country, lang: locale.language })
242
+ .with({ country: "DEU", lang: P.not("de") }, () => `${t("common.form.taxIdentificationNumber.placeholder")} (Steueridentifikationsnummer)`)
243
+ .with({ country: "ESP", lang: P.not("es") }, () => `${t("common.form.taxIdentificationNumber.placeholder")} (Número de Identificación Fiscal)`)
244
+ .with({ country: "ITA", lang: P.not("it") }, () => `${t("common.form.taxIdentificationNumber.placeholder")} (Codice fiscale)`)
245
245
  .otherwise(() => t("common.form.taxIdentificationNumber.placeholder"));
246
- export const getCompanyTaxNumberPlaceholder = (country) => match(country)
247
- .with("DEU", () => `${t("common.form.taxIdentificationNumber.placeholder")} (Steuer-Nummer)`)
248
- .with("ESP", () => `${t("common.form.taxIdentificationNumber.placeholder")} (Número de Identificación Fiscal)`)
249
- .with("ITA", () => `${t("common.form.taxIdentificationNumber.placeholder")} (Codice fiscale)`)
246
+ export const getCompanyTaxNumberPlaceholder = (country) => match({ country, lang: locale.language })
247
+ .with({ country: "DEU", lang: P.not("de") }, () => `${t("common.form.taxIdentificationNumber.placeholder")} (Steuer-Nummer)`)
248
+ .with({ country: "ESP", lang: P.not("es") }, () => `${t("common.form.taxIdentificationNumber.placeholder")} (Número de Identificación Fiscal)`)
249
+ .with({ country: "ITA", lang: P.not("it") }, () => `${t("common.form.taxIdentificationNumber.placeholder")} (Codice fiscale)`)
250
250
  .otherwise(() => t("common.form.taxIdentificationNumber.placeholder"));
251
251
  export const getCompanyTaxNumberHelp = (country) => { var _a, _b; return (_b = (_a = TAX_NUMBER_REGEX.company[country]) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : ""; };
252
252
  export const getIndividualTaxNumberHelp = (country) => { var _a, _b; return (_b = (_a = TAX_NUMBER_REGEX.individual[country]) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : ""; };