@wf-financing/ui 3.9.2 → 3.11.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/CHANGELOG.md +17 -0
- package/dist/index.es.js +6789 -6512
- package/global.d.ts +1 -1
- package/index.ts +2 -2
- package/package.json +3 -2
- package/src/App.tsx +5 -2
- package/src/CtaWidget.tsx +1 -1
- package/src/api/getHeadlessSdkInstance.ts +4 -2
- package/src/components/banner/CloseButton.tsx +2 -1
- package/src/components/banner/CtaBanner.snapshot.stories.tsx +2 -1
- package/src/components/banner/CtaBanner.tsx +8 -1
- package/src/components/banner/ProceedFundingButton.tsx +5 -3
- package/src/components/modal/ModalFooter.tsx +4 -1
- package/src/main.tsx +11 -3
- package/src/utils/applyStyles.ts +41 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/parseJwt.ts +4 -2
package/global.d.ts
CHANGED
package/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wf-financing/ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.0",
|
|
4
4
|
"exports": {
|
|
5
5
|
".": {
|
|
6
6
|
"import": "./dist/index.es.js",
|
|
@@ -36,7 +36,8 @@
|
|
|
36
36
|
"react-aria": "^3.41.1",
|
|
37
37
|
"react-intl": "^6.2.5",
|
|
38
38
|
"styled-components": "^6.1.19",
|
|
39
|
-
"@wf-financing/embedded-types": "0.6.0"
|
|
39
|
+
"@wf-financing/embedded-types": "0.6.0",
|
|
40
|
+
"@wf-financing/logger": "1.1.0"
|
|
40
41
|
},
|
|
41
42
|
"publishConfig": {
|
|
42
43
|
"access": "public"
|
package/src/App.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
2
2
|
import { FlyUIProvider } from '@wayflyer/flyui';
|
|
3
3
|
import { PartnerCallbackType, SdkOptionsType } from '@wf-financing/embedded-types';
|
|
4
|
+
import { Logger } from '@wf-financing/logger';
|
|
4
5
|
import { useState } from 'react';
|
|
5
6
|
import { createIntl, createIntlCache, IntlShape } from 'react-intl';
|
|
6
7
|
|
|
@@ -46,6 +47,7 @@ export const App = ({
|
|
|
46
47
|
|
|
47
48
|
const onWidgetDismiss = () => {
|
|
48
49
|
setIsWidgetDismissed(true);
|
|
50
|
+
Logger.logEvent('ui_sdk_banner_dismissed');
|
|
49
51
|
};
|
|
50
52
|
|
|
51
53
|
return (
|
|
@@ -65,8 +67,9 @@ export const App = ({
|
|
|
65
67
|
theme={theme}
|
|
66
68
|
intl={intl}
|
|
67
69
|
onThemeLoad={() => setIsThemeLoaded(true)}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
onThemeLoadError={() => {
|
|
71
|
+
Logger.logError(`Error while loading theme: ${theme}`);
|
|
72
|
+
}}
|
|
70
73
|
>
|
|
71
74
|
{isThemeLoaded && <CtaWidget />}
|
|
72
75
|
</FlyUIProvider>
|
package/src/CtaWidget.tsx
CHANGED
|
@@ -22,7 +22,7 @@ export const CtaWidget = () => {
|
|
|
22
22
|
<AnimatePresence mode="wait" onExitComplete={handleExitComplete}>
|
|
23
23
|
{showBanner && (
|
|
24
24
|
<AnimationWrapper skipAnimation={skipAnimation}>
|
|
25
|
-
<CtaBanner skipAnimation={skipAnimation} />
|
|
25
|
+
<CtaBanner skipAnimation={skipAnimation} bannerState={data.state} />
|
|
26
26
|
</AnimationWrapper>
|
|
27
27
|
)}
|
|
28
28
|
</AnimatePresence>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { IWayflyerHeadlessSdk, SdkOptionsType } from '@wf-financing/embedded-types';
|
|
2
2
|
|
|
3
|
+
import { Logger } from '@wf-financing/logger';
|
|
3
4
|
import { HEADLESS_SDK_URL, WAYFLYER_HEADLESS_SDK_ID } from '../config';
|
|
4
5
|
import { initializeHeadlessSdk, loadScriptAndInitializeSdk } from '../utils';
|
|
5
6
|
|
|
@@ -28,14 +29,15 @@ export const getHeadlessSdkInstance = async (companyToken: string, options?: Sdk
|
|
|
28
29
|
script.type = 'module';
|
|
29
30
|
script.id = WAYFLYER_HEADLESS_SDK_ID;
|
|
30
31
|
script.async = true;
|
|
32
|
+
script.onerror = () => Logger.logError('Error in loading headless SDK script');
|
|
31
33
|
|
|
32
34
|
document.head.appendChild(script);
|
|
33
35
|
const headlessSdk: IWayflyerHeadlessSdk = await loadScriptAndInitializeSdk(script, companyToken, options);
|
|
34
36
|
cachedSdkInstance = headlessSdk;
|
|
35
37
|
|
|
36
38
|
return headlessSdk;
|
|
37
|
-
} catch
|
|
38
|
-
|
|
39
|
+
} catch {
|
|
40
|
+
Logger.logError('Error in loading headless SDK');
|
|
39
41
|
throw new Error('Failed to load script');
|
|
40
42
|
}
|
|
41
43
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Button, Flex } from '@wayflyer/flyui';
|
|
2
2
|
import { IconX16Line } from '@wayflyer/flyui-icons/16/line';
|
|
3
3
|
|
|
4
|
+
import { Logger } from '@wf-financing/logger';
|
|
4
5
|
import { useDismissCta, usePartnerContext } from '../../hooks';
|
|
5
6
|
|
|
6
7
|
export const CloseButton = ({ isOnDarkTheme }: { isOnDarkTheme: boolean }) => {
|
|
@@ -12,7 +13,7 @@ export const CloseButton = ({ isOnDarkTheme }: { isOnDarkTheme: boolean }) => {
|
|
|
12
13
|
|
|
13
14
|
dismissCta.mutate(undefined, {
|
|
14
15
|
onError: (error) => {
|
|
15
|
-
|
|
16
|
+
Logger.logError(`Failed to dismiss CTA ${error.message}`);
|
|
16
17
|
},
|
|
17
18
|
});
|
|
18
19
|
};
|
|
@@ -12,6 +12,7 @@ const defaultArgs = {
|
|
|
12
12
|
onWidgetDismiss: () => {},
|
|
13
13
|
isWidgetDismissed: false,
|
|
14
14
|
skipAnimation: false,
|
|
15
|
+
bannerState: 'test',
|
|
15
16
|
portalContainer,
|
|
16
17
|
};
|
|
17
18
|
|
|
@@ -19,7 +20,7 @@ type CtaBannerStoryArgs = typeof defaultArgs;
|
|
|
19
20
|
|
|
20
21
|
const Template = (args: CtaBannerStoryArgs) => (
|
|
21
22
|
<PartnerContext.Provider value={{ ...args }}>
|
|
22
|
-
<CtaBanner skipAnimation={false} />
|
|
23
|
+
<CtaBanner skipAnimation={false} bannerState="test" />
|
|
23
24
|
</PartnerContext.Provider>
|
|
24
25
|
);
|
|
25
26
|
|
|
@@ -2,6 +2,8 @@ import { Flex, useDetectDeviceSize, useTheme } from '@wayflyer/flyui';
|
|
|
2
2
|
import { motion, MotionProps } from 'framer-motion';
|
|
3
3
|
import { css, styled } from 'styled-components';
|
|
4
4
|
|
|
5
|
+
import { Logger } from '@wf-financing/logger';
|
|
6
|
+
import { useEffect } from 'react';
|
|
5
7
|
import { MODAL_LOGO_IMAGE_URL, STATIC_BASE_URL } from '../../config';
|
|
6
8
|
import { usePreloadImage } from '../../hooks';
|
|
7
9
|
import { CtaBannerContent } from './CtaBannerContent';
|
|
@@ -60,9 +62,10 @@ const bannerAnimationProps: MotionProps = {
|
|
|
60
62
|
|
|
61
63
|
type Props = {
|
|
62
64
|
skipAnimation: boolean;
|
|
65
|
+
bannerState: string;
|
|
63
66
|
};
|
|
64
67
|
|
|
65
|
-
export const CtaBanner = ({ skipAnimation }: Props) => {
|
|
68
|
+
export const CtaBanner = ({ skipAnimation, bannerState }: Props) => {
|
|
66
69
|
const { isMobile, isTablet } = useDetectDeviceSize();
|
|
67
70
|
const logoImageUrl = `${STATIC_BASE_URL}${MODAL_LOGO_IMAGE_URL}`;
|
|
68
71
|
const { themeName } = useTheme();
|
|
@@ -71,6 +74,10 @@ export const CtaBanner = ({ skipAnimation }: Props) => {
|
|
|
71
74
|
const isTertiaryTheme = TERTIARY_THEMES.includes(themeName);
|
|
72
75
|
usePreloadImage(logoImageUrl);
|
|
73
76
|
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
Logger.logEvent('banner_cta_visible', { bannerState });
|
|
79
|
+
}, []);
|
|
80
|
+
|
|
74
81
|
return (
|
|
75
82
|
<BannerContainer
|
|
76
83
|
$isLightBgTheme={isLightBgTheme}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { Button } from '@wayflyer/flyui';
|
|
2
2
|
import {
|
|
3
|
+
ContinueHostedApplicationResponseType,
|
|
3
4
|
CtaContinueFundingType,
|
|
4
5
|
CtaGenericOfferType,
|
|
5
6
|
CtaIndicativeOfferType,
|
|
6
7
|
CtaStateType,
|
|
7
|
-
ContinueHostedApplicationResponseType,
|
|
8
8
|
} from '@wf-financing/embedded-types';
|
|
9
|
+
import { Logger } from '@wf-financing/logger';
|
|
9
10
|
import { useState } from 'react';
|
|
10
11
|
|
|
11
|
-
import {
|
|
12
|
+
import { useContinueHostedApplication, useCtaBanner } from '../../hooks';
|
|
12
13
|
import { ConsentModal } from '../modal/ConsentModal';
|
|
13
14
|
|
|
14
15
|
type CtaResponseType = CtaGenericOfferType | CtaIndicativeOfferType | CtaContinueFundingType;
|
|
@@ -29,13 +30,14 @@ export const ProceedFundingButton = ({ isOnDarkTheme }: { isOnDarkTheme: boolean
|
|
|
29
30
|
const handleContinueHostedApplication = () => {
|
|
30
31
|
switch (state) {
|
|
31
32
|
case CtaStateType.CONTINUE_APPLICATION:
|
|
33
|
+
Logger.logEvent('cta_continue_hosted_application');
|
|
32
34
|
mutate(undefined, {
|
|
33
35
|
onSuccess: (nextUrl: ContinueHostedApplicationResponseType) => {
|
|
34
36
|
const { next } = nextUrl;
|
|
35
37
|
window.open(next);
|
|
36
38
|
},
|
|
37
39
|
onError: (error) => {
|
|
38
|
-
|
|
40
|
+
Logger.logError(`Failed to continue application ${error.message}`);
|
|
39
41
|
},
|
|
40
42
|
});
|
|
41
43
|
break;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Button, Flex, Link, Text, useDetectDeviceSize } from '@wayflyer/flyui';
|
|
2
2
|
import { IconArrowOnSquareUpRight16Line } from '@wayflyer/flyui-icons/16/line';
|
|
3
3
|
import { StartHostedApplicationResponseType } from '@wf-financing/embedded-types';
|
|
4
|
+
import { Logger } from '@wf-financing/logger';
|
|
4
5
|
import { FormattedMessage } from 'react-intl';
|
|
5
6
|
|
|
6
7
|
import { useDetectSmallScreen, useStartHostedApplication } from '../../hooks';
|
|
@@ -15,6 +16,7 @@ export const ModalFooter = ({ setOpen }: ModalFooterType) => {
|
|
|
15
16
|
const isSmallScreen = useDetectSmallScreen();
|
|
16
17
|
|
|
17
18
|
const handleStartApplication = () => {
|
|
19
|
+
Logger.logEvent('cta_start_hosted_application');
|
|
18
20
|
mutate(undefined, {
|
|
19
21
|
onSuccess: (nextUrl: StartHostedApplicationResponseType) => {
|
|
20
22
|
const { next } = nextUrl;
|
|
@@ -22,12 +24,13 @@ export const ModalFooter = ({ setOpen }: ModalFooterType) => {
|
|
|
22
24
|
window.open(next);
|
|
23
25
|
},
|
|
24
26
|
onError: (error) => {
|
|
25
|
-
|
|
27
|
+
Logger.logError(`Failed to continue application ${error.message}`);
|
|
26
28
|
},
|
|
27
29
|
});
|
|
28
30
|
};
|
|
29
31
|
|
|
30
32
|
const handleOpenExternalLink = () => {
|
|
33
|
+
Logger.logEvent('cta_open_privacy_note');
|
|
31
34
|
window.open('https://wayflyer.com/en/privacy-notice', '_blank', 'noopener,noreferrer');
|
|
32
35
|
};
|
|
33
36
|
|
package/src/main.tsx
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { PartnerCallbackType, SdkOptionsType } from '@wf-financing/embedded-types';
|
|
2
|
+
import { Logger } from '@wf-financing/logger';
|
|
2
3
|
import ReactDOM from 'react-dom/client';
|
|
3
4
|
import { StyleSheetManager } from 'styled-components';
|
|
4
5
|
|
|
5
6
|
import { MotionGlobalConfig } from 'framer-motion';
|
|
6
7
|
import { App } from './App';
|
|
7
8
|
import { PartnerTheme } from './config';
|
|
8
|
-
import { applyFont, createRoots } from './utils';
|
|
9
|
+
import { applyFont, applyStyles, createRoots } from './utils';
|
|
9
10
|
|
|
10
11
|
let root: ReactDOM.Root | undefined;
|
|
11
12
|
let savedTargetId: string | undefined;
|
|
@@ -24,11 +25,16 @@ export const mountToTarget = async (
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
const hostEl = document.getElementById(savedTargetId as string);
|
|
27
|
-
if (!hostEl)
|
|
28
|
+
if (!hostEl) {
|
|
29
|
+
Logger.logError(`Target element with id "${savedTargetId}" not found.`);
|
|
30
|
+
throw new Error(`Target element with id "${savedTargetId}" not found.`);
|
|
31
|
+
}
|
|
28
32
|
|
|
29
|
-
const shadow = hostEl.shadowRoot ?? hostEl.attachShadow({ mode: 'open' });
|
|
33
|
+
const shadow = hostEl.shadowRoot ?? (hostEl.attachShadow({ mode: 'open' }) as ShadowRoot);
|
|
30
34
|
|
|
35
|
+
// TODO: remove font loading from SDK
|
|
31
36
|
try {
|
|
37
|
+
applyStyles({ shadow });
|
|
32
38
|
await applyFont(shadow, partnerTheme);
|
|
33
39
|
} catch (error) {
|
|
34
40
|
console.error(error);
|
|
@@ -60,4 +66,6 @@ export const mountToTarget = async (
|
|
|
60
66
|
/>
|
|
61
67
|
</StyleSheetManager>,
|
|
62
68
|
);
|
|
69
|
+
|
|
70
|
+
Logger.logEvent('cta_mounted_to_target');
|
|
63
71
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import assetsManifest from '@wayflyer/flyui/manifest.json';
|
|
2
|
+
|
|
3
|
+
const LINK_TAG_ID = 'wf-flyui-styles';
|
|
4
|
+
|
|
5
|
+
type ApplyFontsType = ({
|
|
6
|
+
shadow,
|
|
7
|
+
onStylesLoad,
|
|
8
|
+
onStylesLoadError,
|
|
9
|
+
}: {
|
|
10
|
+
shadow: ShadowRoot;
|
|
11
|
+
onStylesLoad?: () => void;
|
|
12
|
+
onStylesLoadError?: (error: unknown) => void;
|
|
13
|
+
}) => void;
|
|
14
|
+
|
|
15
|
+
export const applyStyles: ApplyFontsType = async ({ shadow, onStylesLoad, onStylesLoadError }) => {
|
|
16
|
+
if (!assetsManifest || !('styles' in assetsManifest)) {
|
|
17
|
+
return onStylesLoadError?.('Style manifest not found');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const stylesUrl = assetsManifest.styles as string;
|
|
21
|
+
|
|
22
|
+
const linkTag = document.createElement('link');
|
|
23
|
+
linkTag.href = stylesUrl;
|
|
24
|
+
linkTag.rel = 'stylesheet';
|
|
25
|
+
linkTag.id = LINK_TAG_ID;
|
|
26
|
+
|
|
27
|
+
linkTag.onload = () => {
|
|
28
|
+
onStylesLoad?.();
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
linkTag.onerror = (error) => {
|
|
32
|
+
onStylesLoadError?.(error);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const existingLinkTag = document.getElementById(LINK_TAG_ID);
|
|
36
|
+
if (existingLinkTag) {
|
|
37
|
+
existingLinkTag.replaceWith(linkTag);
|
|
38
|
+
} else {
|
|
39
|
+
shadow.prepend(linkTag);
|
|
40
|
+
}
|
|
41
|
+
};
|
package/src/utils/index.ts
CHANGED
package/src/utils/parseJwt.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Logger } from '@wf-financing/logger';
|
|
2
|
+
|
|
1
3
|
type CompanyToken = {
|
|
2
4
|
sub: string;
|
|
3
5
|
};
|
|
@@ -5,8 +7,8 @@ type CompanyToken = {
|
|
|
5
7
|
export const parseJwt = (token: string): CompanyToken | null => {
|
|
6
8
|
try {
|
|
7
9
|
return JSON.parse(atob(token.split('.')[1]));
|
|
8
|
-
} catch
|
|
9
|
-
|
|
10
|
+
} catch {
|
|
11
|
+
Logger.logError('Error parsing a company token');
|
|
10
12
|
return null;
|
|
11
13
|
}
|
|
12
14
|
};
|