@wf-financing/ui 1.0.0 → 1.1.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/index.es.js +20508 -20429
- package/package.json +1 -1
- package/src/App.tsx +3 -2
- package/src/CtaWidget.tsx +13 -2
- package/src/components/banner/BannerActionsDesktop.tsx +10 -10
- package/src/components/banner/CloseButton.tsx +16 -0
- package/src/components/banner/CtaBanner.stories.tsx +40 -3
- package/src/components/banner/CtaBanner.tsx +4 -4
- package/src/components/banner/FooterActions.tsx +8 -0
- package/src/components/banner/HeaderActions.tsx +9 -0
- package/src/components/modal/Modal.tsx +1 -1
- package/src/components/modal/modalEnhancements.ts +2 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useCtaBanner.ts +2 -9
- package/src/hooks/usePartnerContext.ts +7 -0
- package/src/hooks/useStartHostedApplication.ts +3 -12
- package/src/main.tsx +8 -10
- package/src/utils/index.ts +1 -1
- package/src/utils/partnerContext.ts +6 -3
- package/src/components/banner/BannerActions.stories.tsx +0 -22
- package/src/components/banner/BannerActionsMobile.tsx +0 -12
package/package.json
CHANGED
package/src/App.tsx
CHANGED
|
@@ -12,6 +12,7 @@ type AppPropsType = {
|
|
|
12
12
|
companyToken: string;
|
|
13
13
|
mockedMode?: MockedModeType;
|
|
14
14
|
partnerCallback: PartnerCallbackType;
|
|
15
|
+
onWidgetClose: () => void;
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
const queryClient = new QueryClient();
|
|
@@ -19,7 +20,7 @@ const messages = {
|
|
|
19
20
|
en: enMessages,
|
|
20
21
|
};
|
|
21
22
|
|
|
22
|
-
export const App = ({ partnerDesignId, companyToken, mockedMode, partnerCallback }: AppPropsType) => {
|
|
23
|
+
export const App = ({ partnerDesignId, companyToken, mockedMode, partnerCallback, onWidgetClose }: AppPropsType) => {
|
|
23
24
|
const locale = 'en';
|
|
24
25
|
|
|
25
26
|
const intl: IntlShape = createIntl(
|
|
@@ -32,7 +33,7 @@ export const App = ({ partnerDesignId, companyToken, mockedMode, partnerCallback
|
|
|
32
33
|
|
|
33
34
|
return (
|
|
34
35
|
<QueryClientProvider client={queryClient}>
|
|
35
|
-
<PartnerContext.Provider value={{ companyToken, mockedMode, partnerCallback }}>
|
|
36
|
+
<PartnerContext.Provider value={{ companyToken, mockedMode, partnerCallback, onWidgetClose }}>
|
|
36
37
|
<FlyUIProvider theme={partnerDesignId} intl={intl}>
|
|
37
38
|
<CtaWidget />
|
|
38
39
|
</FlyUIProvider>
|
package/src/CtaWidget.tsx
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
1
3
|
import { CtaBanner } from './components/banner/CtaBanner';
|
|
2
|
-
import { useCtaBanner } from './hooks
|
|
4
|
+
import { useCtaBanner, usePartnerContext } from './hooks';
|
|
3
5
|
|
|
4
6
|
export const CtaWidget = () => {
|
|
5
7
|
const banner = useCtaBanner();
|
|
8
|
+
const partnerContext = usePartnerContext();
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (!banner.isLoading && !banner.data) {
|
|
12
|
+
requestAnimationFrame(() => {
|
|
13
|
+
partnerContext.onWidgetClose();
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}, [banner.data]);
|
|
6
17
|
|
|
7
|
-
return <>{!banner.isLoading && <CtaBanner />}</>;
|
|
18
|
+
return <>{!banner.isLoading && banner.data && <CtaBanner />}</>;
|
|
8
19
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { IconX16Line } from '@wayflyer/flyui-icons/16/line';
|
|
1
|
+
import { Flex } from '@wayflyer/flyui';
|
|
3
2
|
|
|
3
|
+
import { CloseButton } from './CloseButton';
|
|
4
4
|
import { ProceedFundingButton } from './ProceedFundingButton';
|
|
5
5
|
|
|
6
|
-
export const BannerActionsDesktop = () =>
|
|
7
|
-
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
<
|
|
11
|
-
</
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
export const BannerActionsDesktop = () => {
|
|
7
|
+
return (
|
|
8
|
+
<Flex gap="4">
|
|
9
|
+
<ProceedFundingButton />
|
|
10
|
+
<CloseButton />
|
|
11
|
+
</Flex>
|
|
12
|
+
);
|
|
13
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Button, Flex } from '@wayflyer/flyui';
|
|
2
|
+
import { IconX16Line } from '@wayflyer/flyui-icons/16/line';
|
|
3
|
+
|
|
4
|
+
import { usePartnerContext } from '../../hooks';
|
|
5
|
+
|
|
6
|
+
export const CloseButton = () => {
|
|
7
|
+
const { onWidgetClose: closeWidget } = usePartnerContext();
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<Button onClick={closeWidget} variant="Tertiary">
|
|
11
|
+
<Flex padding="2">
|
|
12
|
+
<IconX16Line />
|
|
13
|
+
</Flex>
|
|
14
|
+
</Button>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
@@ -1,14 +1,51 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Themes } from '@wayflyer/flyui';
|
|
3
|
+
import { CtaResponseTypes, MockedModeType } from '@wf-financing/embedded-types';
|
|
4
|
+
import { App } from '../../App';
|
|
2
5
|
import { CtaBanner } from './CtaBanner';
|
|
3
6
|
|
|
7
|
+
const defaultArgs = {
|
|
8
|
+
partnerDesignId: 'whiteLabel' as Themes,
|
|
9
|
+
companyToken: 'demo-token',
|
|
10
|
+
partnerCallback: () => {},
|
|
11
|
+
onWidgetClose: () => {},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type CtaBannerStoryArgs = typeof defaultArgs & { mockedMode: MockedModeType };
|
|
15
|
+
|
|
16
|
+
const Template = (args: CtaBannerStoryArgs) => (
|
|
17
|
+
<App {...args}>
|
|
18
|
+
<CtaBanner />
|
|
19
|
+
</App>
|
|
20
|
+
);
|
|
21
|
+
|
|
4
22
|
const meta: Meta<typeof CtaBanner> = {
|
|
5
23
|
title: 'CtaBanner',
|
|
6
24
|
component: CtaBanner,
|
|
25
|
+
argTypes: {
|
|
26
|
+
mockedMode: {
|
|
27
|
+
control: { type: 'object' },
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
args: {
|
|
31
|
+
...defaultArgs,
|
|
32
|
+
mockedMode: {
|
|
33
|
+
isMockedMode: true,
|
|
34
|
+
sdkScenario: CtaResponseTypes.GENERIC_OFFER,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
decorators: [(Story, context) => <Template {...(context.args as CtaBannerStoryArgs)} />],
|
|
7
38
|
};
|
|
8
39
|
|
|
9
40
|
export default meta;
|
|
10
41
|
type Story = StoryObj<typeof CtaBanner>;
|
|
11
42
|
|
|
12
|
-
export const
|
|
13
|
-
|
|
43
|
+
export const GenericOffer: Story = {
|
|
44
|
+
name: 'Generic Offer',
|
|
45
|
+
args: {
|
|
46
|
+
mockedMode: {
|
|
47
|
+
isMockedMode: true,
|
|
48
|
+
sdkScenario: CtaResponseTypes.GENERIC_OFFER,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
14
51
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Flex, Theme, useDetectDeviceSize, useTheme } from '@wayflyer/flyui';
|
|
2
2
|
import { styled } from 'styled-components';
|
|
3
3
|
|
|
4
|
-
import { BannerActionsDesktop } from './BannerActionsDesktop';
|
|
5
|
-
import { BannerActionsMobile } from './BannerActionsMobile';
|
|
6
4
|
import { CtaBannerContent } from './CtaBannerContent';
|
|
5
|
+
import { FooterActions } from './FooterActions';
|
|
6
|
+
import { HeaderActions } from './HeaderActions';
|
|
7
7
|
|
|
8
8
|
type BannerContainerPropTypes = {
|
|
9
9
|
theme: Theme;
|
|
@@ -28,9 +28,9 @@ export const CtaBanner = () => {
|
|
|
28
28
|
<BannerContainer isMobile={isMobile} theme={theme}>
|
|
29
29
|
<Flex gap="4" align="center" justify="space-between" width="100%">
|
|
30
30
|
<CtaBannerContent isMobile={isMobile} isTablet={isTablet} />
|
|
31
|
-
|
|
31
|
+
<HeaderActions />
|
|
32
32
|
</Flex>
|
|
33
|
-
|
|
33
|
+
<FooterActions />
|
|
34
34
|
</BannerContainer>
|
|
35
35
|
);
|
|
36
36
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { useDetectDeviceSize } from '@wayflyer/flyui';
|
|
2
|
+
import { ProceedFundingButton } from './ProceedFundingButton';
|
|
3
|
+
|
|
4
|
+
export const FooterActions = () => {
|
|
5
|
+
const { isMobile } = useDetectDeviceSize();
|
|
6
|
+
|
|
7
|
+
return isMobile ? <ProceedFundingButton /> : null;
|
|
8
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useDetectDeviceSize } from '@wayflyer/flyui';
|
|
2
|
+
import { BannerActionsDesktop } from './BannerActionsDesktop';
|
|
3
|
+
import { CloseButton } from './CloseButton';
|
|
4
|
+
|
|
5
|
+
export const HeaderActions = () => {
|
|
6
|
+
const { isMobile } = useDetectDeviceSize();
|
|
7
|
+
|
|
8
|
+
return isMobile ? <CloseButton /> : <BannerActionsDesktop />;
|
|
9
|
+
};
|
|
@@ -31,7 +31,7 @@ export const Modal = ({ isModalOpen, setIsModalOpen, children }: ModalProps) =>
|
|
|
31
31
|
animate={fullSize}
|
|
32
32
|
exit={small}
|
|
33
33
|
transition={{ duration: 0.3 }}
|
|
34
|
-
style={{ width: '438px', border: 'none' }}
|
|
34
|
+
style={{ width: '438px', border: 'none', maxWidth: '100vw' }}
|
|
35
35
|
>
|
|
36
36
|
<MotionModalOverlay
|
|
37
37
|
data-id="modal-mask"
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
import { useQuery } from '@tanstack/react-query';
|
|
2
|
-
import { useContext } from 'react';
|
|
3
|
-
import { MockedModeType } from '@wf-financing/embedded-types';
|
|
4
2
|
|
|
5
3
|
import { fetchCtaBanner } from '../api/ctaBanner';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
type PartnerDataType = {
|
|
9
|
-
companyToken: string;
|
|
10
|
-
mockedMode?: MockedModeType;
|
|
11
|
-
};
|
|
4
|
+
import { usePartnerContext } from './usePartnerContext';
|
|
12
5
|
|
|
13
6
|
export const useCtaBanner = () => {
|
|
14
|
-
const { companyToken, mockedMode } =
|
|
7
|
+
const { companyToken, mockedMode } = usePartnerContext();
|
|
15
8
|
|
|
16
9
|
return useQuery({
|
|
17
10
|
queryKey: ['cta', companyToken, mockedMode],
|
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
import { PartnerCallbackType, MockedModeType } from '@wf-financing/embedded-types';
|
|
2
|
-
import { useContext } from 'react';
|
|
3
|
-
|
|
4
|
-
import { PartnerContext } from '../utils/partnerContext';
|
|
5
|
-
|
|
6
|
-
type PartnerDataType = {
|
|
7
|
-
companyToken: string;
|
|
8
|
-
mockedMode?: MockedModeType;
|
|
9
|
-
partnerCallback: PartnerCallbackType;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
1
|
import { useMutation } from '@tanstack/react-query';
|
|
2
|
+
|
|
13
3
|
import { startHostedApplication } from '../api/startHostedApplication';
|
|
4
|
+
import { usePartnerContext } from './usePartnerContext';
|
|
14
5
|
|
|
15
6
|
export const useStartHostedApplication = () => {
|
|
16
|
-
const { companyToken, mockedMode, partnerCallback } =
|
|
7
|
+
const { companyToken, mockedMode, partnerCallback } = usePartnerContext();
|
|
17
8
|
|
|
18
9
|
return useMutation({
|
|
19
10
|
mutationFn: () => startHostedApplication(companyToken, partnerCallback, mockedMode),
|
package/src/main.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import ReactDOM from 'react-dom/client';
|
|
|
4
4
|
|
|
5
5
|
import { App } from './App';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
let root: ReactDOM.Root | undefined = undefined;
|
|
8
8
|
|
|
9
9
|
export const mountToTarget = (
|
|
10
10
|
targetId: string,
|
|
@@ -14,17 +14,14 @@ export const mountToTarget = (
|
|
|
14
14
|
mockedMode?: MockedModeType,
|
|
15
15
|
) => {
|
|
16
16
|
const targetElement = document.getElementById(targetId);
|
|
17
|
+
if (!targetElement) throw new Error(`Target element with id "${targetId}" not found.`);
|
|
17
18
|
|
|
18
|
-
if (!targetElement)
|
|
19
|
-
console.warn(`Target element with id "${targetId}" not found.`);
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
let root = roots.get(targetElement);
|
|
19
|
+
if (!root) root = ReactDOM.createRoot(targetElement);
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
root
|
|
27
|
-
|
|
21
|
+
function handleCloseWidget() {
|
|
22
|
+
if (!root) throw new Error('Root is not found');
|
|
23
|
+
root.unmount();
|
|
24
|
+
root = undefined;
|
|
28
25
|
}
|
|
29
26
|
|
|
30
27
|
root.render(
|
|
@@ -33,6 +30,7 @@ export const mountToTarget = (
|
|
|
33
30
|
companyToken={companyToken}
|
|
34
31
|
mockedMode={mockedMode}
|
|
35
32
|
partnerCallback={partnerCallback}
|
|
33
|
+
onWidgetClose={handleCloseWidget}
|
|
36
34
|
/>,
|
|
37
35
|
);
|
|
38
36
|
};
|
package/src/utils/index.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { PartnerCallbackType, MockedModeType } from '@wf-financing/embedded-types';
|
|
2
2
|
import { createContext } from 'react';
|
|
3
3
|
|
|
4
|
-
type PartnerContextType = {
|
|
4
|
+
export type PartnerContextType = {
|
|
5
5
|
companyToken: string;
|
|
6
6
|
isMockedMode?: boolean;
|
|
7
7
|
partnerCallback: PartnerCallbackType;
|
|
8
8
|
mockedMode?: MockedModeType;
|
|
9
|
-
|
|
9
|
+
onWidgetClose: () => void;
|
|
10
|
+
};
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
type PartnerContextWithDefaultType = PartnerContextType | null;
|
|
13
|
+
|
|
14
|
+
export const PartnerContext = createContext<PartnerContextWithDefaultType>(null);
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { BannerActionsDesktop } from './BannerActionsDesktop';
|
|
2
|
-
import { BannerActionsMobile } from './BannerActionsMobile';
|
|
3
|
-
|
|
4
|
-
import type { Meta, StoryObj } from '@storybook/react';
|
|
5
|
-
|
|
6
|
-
const meta: Meta = {
|
|
7
|
-
title: 'Banner/BannerActions',
|
|
8
|
-
component: BannerActionsDesktop,
|
|
9
|
-
tags: ['autodocs'],
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export default meta;
|
|
13
|
-
|
|
14
|
-
export const Desktop: StoryObj = {
|
|
15
|
-
render: () => <BannerActionsDesktop />,
|
|
16
|
-
name: 'Desktop Actions',
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const Mobile: StoryObj = {
|
|
20
|
-
render: () => <BannerActionsMobile />,
|
|
21
|
-
name: 'Mobile Actions',
|
|
22
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Button, Flex } from '@wayflyer/flyui';
|
|
2
|
-
|
|
3
|
-
import { ProceedFundingButton } from './ProceedFundingButton';
|
|
4
|
-
|
|
5
|
-
export const BannerActionsMobile = () => (
|
|
6
|
-
<Flex gap="2" align="center" width="100%" justify="space-around">
|
|
7
|
-
<ProceedFundingButton />
|
|
8
|
-
<Button fullWidth title="Dismiss" variant="Secondary">
|
|
9
|
-
Dismiss
|
|
10
|
-
</Button>
|
|
11
|
-
</Flex>
|
|
12
|
-
);
|