zh-web-sdk 1.0.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.
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ interface AppProps {
3
+ isOnboardingAppActive: boolean;
4
+ isOnboardingAppLoaded: boolean;
5
+ userOnboardingJWT: string;
6
+ zeroHashOnboardingURL: string;
7
+ }
8
+ declare const _default: import("react-redux").ConnectedComponent<({ isOnboardingAppActive, isOnboardingAppLoaded, userOnboardingJWT, zeroHashOnboardingURL }: AppProps) => import("react/jsx-runtime").JSX.Element, {
9
+ zeroHashOnboardingURL: string;
10
+ context?: React.Context<import("react-redux").ReactReduxContextValue<any, import("redux").AnyAction>> | undefined;
11
+ store?: import("redux").Store<any, import("redux").AnyAction> | undefined;
12
+ }>;
13
+ export default _default;
@@ -0,0 +1 @@
1
+ export declare const MESSAGE_TYPE_SEND_JWT_TOKEN: string;
@@ -0,0 +1,8 @@
1
+ export declare const openOnboardingModal: () => {
2
+ type: string;
3
+ isOnboardingAppActive: true;
4
+ };
5
+ export declare const closeOnboardingModal: () => {
6
+ type: string;
7
+ isOnboardingAppActive: false;
8
+ };
@@ -0,0 +1,13 @@
1
+ export interface IState {
2
+ isOnboardingAppActive: boolean;
3
+ isOnboardingAppLoaded: boolean;
4
+ userOnboardingJWT: string;
5
+ }
6
+ export interface IAction {
7
+ type: string;
8
+ isOnboardingAppActive?: boolean;
9
+ isOnboardingAppLoaded?: boolean;
10
+ userOnboardingJWT?: string;
11
+ }
12
+ declare const appReducer: (state: IState | undefined, action: IAction) => IState;
13
+ export default appReducer;
@@ -0,0 +1,3 @@
1
+ export declare const ACTION_SET_ONBOARDING_MODAL_STATE = "SET_ONBOARDING_MODAL_STATE";
2
+ export declare const ACTION_SET_USER_ONBOARDING_JWT = "SET_USER_ONBOARDING_JWT";
3
+ export declare const ACTION_ONBOARDING_APP_LOADED = "ONBOARDING_APP_LOADED";
@@ -0,0 +1,4 @@
1
+ declare const rootReducer: import("redux").Reducer<import("redux").CombinedState<{
2
+ appState: import("./app").IState;
3
+ }>, import("./app").IAction>;
4
+ export default rootReducer;
@@ -0,0 +1,4 @@
1
+ declare const store: import("redux").Store<import("redux").EmptyObject & {
2
+ appState: import("../reducers/app").IState;
3
+ }, import("../reducers/app").IAction>;
4
+ export default store;
@@ -0,0 +1,15 @@
1
+ import { CSSProperties } from "react";
2
+ export declare const screenSizes: {
3
+ id: string;
4
+ size: number;
5
+ }[];
6
+ export declare const minWidthMatcher: () => string;
7
+ export declare const containerStyle: CSSProperties;
8
+ export declare const containerMediaStyles: {
9
+ [id: string]: CSSProperties;
10
+ };
11
+ export declare const appWrapperStyle: CSSProperties;
12
+ export declare const appWrapperHiddenStyle: CSSProperties;
13
+ export declare const modalStyle: CSSProperties;
14
+ export declare const iframeWrapperStyle: CSSProperties;
15
+ export declare const iframeStyle: CSSProperties;
@@ -0,0 +1,101 @@
1
+ declare global {
2
+ interface Window {
3
+ zerohash: any;
4
+ }
5
+ }
6
+ /**
7
+ * IInitializeParameters describes the parameters
8
+ * required for initializing the platform SDK
9
+ */
10
+ export interface IInitializeParameters {
11
+ /**
12
+ * zeroHashOnboardingURL should be set to the URL of
13
+ * the webapp for onboarding users onto the ZeroHash
14
+ * platform.
15
+ */
16
+ zeroHashOnboardingURL: string;
17
+ /**
18
+ * rootQuerySelector is a query selector string that
19
+ * allows creating the ZeroHash UI subtree under a
20
+ * custom element.
21
+ *
22
+ * The default #zh-root query selector will be used
23
+ * instead otherwise. #zh-root will be a <div> appended
24
+ * as a child of the body in no specified order.
25
+ */
26
+ rootQuerySelector?: string;
27
+ /**
28
+ * userOnboardingJWT is the JWT that you received from
29
+ * the ZeroHash HTTP API that pertains to the customer
30
+ * to be onboarded.
31
+ *
32
+ * This is optional in the constructor and can be
33
+ * deferred to setUserOnboardingJWT() at a later time
34
+ * but must be provided before opening the onboarding
35
+ * UI in order for the onboarding UI to be loaded.
36
+ */
37
+ userOnboardingJWT?: string;
38
+ }
39
+ /**
40
+ * ISetUserOnboardingJWTParameters describes the
41
+ * parameters required for setting the user onboarding
42
+ * JWT.
43
+ */
44
+ export interface ISetUserOnboardingJWTParameters {
45
+ /**
46
+ * userOnboardingJWT is the JWT that you received from
47
+ * the ZeroHash HTTP API that pertains to the customer
48
+ * to be onboarded.
49
+ */
50
+ userOnboardingJWT: string;
51
+ }
52
+ export interface IOpenOnboardingModalParameters {
53
+ /**
54
+ * userOnboardingJWT is the JWT that you received from
55
+ * the ZeroHash HTTP API that pertains to the customer
56
+ * to be onboarded.
57
+ */
58
+ userOnboardingJWT?: string;
59
+ }
60
+ /**
61
+ * IncomingMessageType are enums of message types that
62
+ * are registered that the host can handle.
63
+ */
64
+ export declare enum IncomingMessageType {
65
+ /**
66
+ * OnboardingAppLoaded is received when the onboarding
67
+ * app has initialized.
68
+ */
69
+ OnboardingAppLoaded = "ONBOARDING_APP_LOADED",
70
+ /**
71
+ * OnboardingCloseButtonClicked is received when the close button
72
+ * has been clicked in the onboarding app
73
+ */
74
+ OnboardingCloseButtonClicked = "ONBOARDING_CLOSE_BUTTON_CLICKED"
75
+ }
76
+ /**
77
+ * IncomingMessage defines the structure of an incoming
78
+ * message
79
+ */
80
+ export interface IncomingMessage {
81
+ /**
82
+ * type is the type of message that is used for routing
83
+ * the request to the appropriate handler
84
+ */
85
+ type: IncomingMessageType;
86
+ /**
87
+ * payload is any freeform value that pertains to the
88
+ * request
89
+ */
90
+ payload: unknown;
91
+ }
92
+ export type IncomingMessageHandler = (payload: unknown) => void;
93
+ /**
94
+ * IZeroHashSDK is the interface that you may use to interact with the ZeroHash SDK.
95
+ */
96
+ export interface IZeroHashSDK {
97
+ setUserOnboardingJWT(params: ISetUserOnboardingJWTParameters): void;
98
+ isOnboardingModalOpen(): boolean;
99
+ openOnboardingModal(params: IOpenOnboardingModalParameters): void;
100
+ closeOnboardingModal(): void;
101
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * randomString generates a random string of specified
3
+ * @param length
4
+ * @param characters - charset to be used.
5
+ */
6
+ export declare const randomString: (length: number, characters?: string) => string;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * generateRootID attempts to create a dynamic ID to be
3
+ * used with a HTML element that is relatively unique
4
+ * and will not cause namespace conflicts.
5
+ *
6
+ * E.g. 'zerohash-49vt8y'
7
+ */
8
+ export declare const generateRootID: () => string;
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "zh-web-sdk",
3
+ "version": "1.0.2",
4
+ "private": false,
5
+ "description": "ZeroHash Web SDK",
6
+ "homepage": "https://github.com/seedcx/zh-web-sdk",
7
+ "main": "dist/index.js",
8
+ "module": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "keywords": [],
11
+ "author": "support@zerohash.com",
12
+ "license": "MIT",
13
+ "scripts": {
14
+ "prepublish": "npm run build",
15
+ "ts-types": "tsc --emitDeclarationOnly --outDir dist",
16
+ "build": "rimraf dist && node ./scripts/build.js && npm run ts-types",
17
+ "build:zip": "npm run build && npm run zip",
18
+ "zip": "rimraf build/* && node scripts/zip.js",
19
+ "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
20
+ "test": "echo \"Error: no test specified\" && exit 1"
21
+ },
22
+ "devDependencies": {
23
+ "@typescript-eslint/eslint-plugin": "^6.4.0",
24
+ "archiver": "^5.3.1",
25
+ "esbuild": "0.18.3",
26
+ "eslint": "^8.47.0",
27
+ "eslint-config-prettier": "6.15.0",
28
+ "eslint-config-standard": "^17.1.0",
29
+ "eslint-plugin-import": "^2.28.1",
30
+ "eslint-plugin-n": "^16.0.1",
31
+ "eslint-plugin-prettier": "3.4.1",
32
+ "eslint-plugin-promise": "^6.1.1",
33
+ "eslint-plugin-react-hooks": "^4.6.0",
34
+ "eslint-plugin-react-refresh": "^0.3.4",
35
+ "rimraf": "^5.0.1",
36
+ "typescript": "^4.9.5"
37
+ },
38
+ "dependencies": {
39
+ "@types/react": "^18.2.12",
40
+ "@types/react-dom": "^18.2.5",
41
+ "react": "^18.2.0",
42
+ "react-dom": "^18.2.0",
43
+ "react-redux": "^8.1.1",
44
+ "redux": "^4.2.1"
45
+ }
46
+ }
@@ -0,0 +1,34 @@
1
+ const esbuild = require("esbuild");
2
+ const {name, version} = require("../package.json");
3
+
4
+ const build = async () => {
5
+ console.log(`Building ${name}@${version}`);
6
+
7
+ const outputDir = "./dist/";
8
+ const minFileName = `${outputDir}zerohash_sdk.min.js`;
9
+ const bundleFileName = `${outputDir}zerohash_sdk.js`;
10
+
11
+ // Build minified dist
12
+ await esbuild
13
+ .build({
14
+ entryPoints: ['src/index.tsx'],
15
+ outdir: 'dist',
16
+ bundle: true,
17
+ sourcemap: true,
18
+ minify: true,
19
+ splitting: false,
20
+ format: 'esm',
21
+ target: ['esnext']
22
+ })
23
+ .catch(err => {
24
+ console.error('Error: build failed - unable to build minified dist');
25
+ throw err;
26
+ });
27
+ }
28
+
29
+ build()
30
+ .then(() => console.log("successfully built"))
31
+ .catch(err => {
32
+ console.error(err);
33
+ process.exit(1);
34
+ });
package/scripts/zip.js ADDED
@@ -0,0 +1,49 @@
1
+ const fs = require("fs");
2
+ const archiver = require("archiver");
3
+ const {name, version} = require("../package.json");
4
+
5
+ const zip = async () => {
6
+ const zipFile = `./build/zh_web_sdk_v${version}.zip`;
7
+ console.log(`Zipping to ${zipFile}`);
8
+
9
+ // create the directory forcibly
10
+ fs.mkdirSync("./build", {recursive: true});
11
+
12
+ // zip output as a package
13
+ const output = fs.createWriteStream(zipFile);
14
+ const archive = archiver('zip', {
15
+ zlib: { level: 9 }
16
+ });
17
+ output.on('close', () => {
18
+ console.log(archive.pointer() + ' total bytes');
19
+ console.log('archiver has been finalized and the output file descriptor has closed.');
20
+ });
21
+ output.on('end', () => {
22
+ console.log('Data has been drained');
23
+ });
24
+ archive.on('warning', (err) => {
25
+ if (err.code === "ENOENT") {
26
+ console.warn("ENOENT: ", err);
27
+ } else {
28
+ console.error(err);
29
+ throw err;
30
+ }
31
+ });
32
+ archive.on('error', (err) => {
33
+ console.error(err);
34
+ throw err;
35
+ });
36
+ archive.pipe(output);
37
+ archive.file("README.md");
38
+ archive.file("package.json");
39
+ archive.file("package-lock.json");
40
+ archive.directory("./dist/");
41
+ await archive.finalize();
42
+ }
43
+
44
+ zip()
45
+ .then(() => console.log("successfully zipped"))
46
+ .catch(err => {
47
+ console.error(err);
48
+ process.exit(1);
49
+ });
@@ -0,0 +1,2 @@
1
+ export const DEFAULT_ZH_ONBOARDING_URL = "https://onboarding.zerohash.com/";
2
+ export const DEFAULT_ROOT_ID_PREFIX = "zerohash"
package/src/index.tsx ADDED
@@ -0,0 +1,197 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import {
4
+ IInitializeParameters,
5
+ IncomingMessage,
6
+ IncomingMessageHandler,
7
+ IncomingMessageType, IOpenOnboardingModalParameters,
8
+ ISetUserOnboardingJWTParameters, IZeroHashSDK
9
+ } from './types';
10
+ import {generateRootID} from "./utils";
11
+ import {DEFAULT_ZH_ONBOARDING_URL} from "./constants";
12
+ import OnboardingApp from "./onboarding/OnboardingApp";
13
+ import {Provider} from "react-redux";
14
+ import store from "./redux/store";
15
+ import {
16
+ ACTION_ONBOARDING_APP_LOADED,
17
+ ACTION_SET_USER_ONBOARDING_JWT
18
+ } from "./redux/reducers/constants";
19
+ import {closeOnboardingModal, openOnboardingModal} from "./redux/actions";
20
+
21
+ let _zeroHashOnboardingURL: string = DEFAULT_ZH_ONBOARDING_URL;
22
+ let _zeroHashOnboardingOrigin: string = "";
23
+
24
+ /**
25
+ * onboardingMessageHandlers are the message handlers that
26
+ * handle incoming messages from the onboarding app iframe.
27
+ * @private - not meant to be invoked publicly
28
+ */
29
+ const onboardingMessageHandlers: { [messageType in IncomingMessageType]: IncomingMessageHandler } = {
30
+ [IncomingMessageType.OnboardingAppLoaded]: () => {
31
+ store.dispatch({
32
+ type: ACTION_ONBOARDING_APP_LOADED,
33
+ isOnboardingAppLoaded: true,
34
+ });
35
+ },
36
+ [IncomingMessageType.OnboardingCloseButtonClicked]: () => {
37
+ closeOnboardingModal();
38
+ }
39
+ }
40
+
41
+ /**
42
+ * messageRouter routes the message to the appropriate message handler based on the host
43
+ * @private - not meant to be invoked publicly
44
+ */
45
+ const messageRouter = (event: MessageEvent): void => {
46
+ if (event.origin === _zeroHashOnboardingOrigin) {
47
+ const incomingMessage: IncomingMessage = event.data;
48
+ if (incomingMessage && incomingMessage.type && onboardingMessageHandlers[incomingMessage.type]) {
49
+ try {
50
+ onboardingMessageHandlers[incomingMessage.type](incomingMessage.payload);
51
+ } catch (e) {
52
+ console.error(e);
53
+ // TODO: emit event that informs the platform of failure event, to inform ZH of bug
54
+ }
55
+ }
56
+ }
57
+ }
58
+
59
+ export class ZeroHashSDK implements IZeroHashSDK {
60
+ private rootQuerySelector: string = "";
61
+ private onboardingInitialized: boolean = false;
62
+
63
+ /**
64
+ * Sets up the ZeroHash SDK and appends the ZeroHash DOM elements onto the page.
65
+ *
66
+ * For more information, see {@code IInitializeParameters}
67
+ */
68
+ constructor(
69
+ {
70
+ zeroHashOnboardingURL = DEFAULT_ZH_ONBOARDING_URL,
71
+ rootQuerySelector,
72
+ userOnboardingJWT
73
+ }: IInitializeParameters
74
+ ) {
75
+ _zeroHashOnboardingURL = zeroHashOnboardingURL
76
+ const onboardingURL = new URL(_zeroHashOnboardingURL);
77
+ _zeroHashOnboardingOrigin = onboardingURL.origin;
78
+ if (rootQuerySelector) {
79
+ this.rootQuerySelector = rootQuerySelector as string
80
+ }
81
+
82
+ // register message handler
83
+ window.addEventListener(
84
+ "message",
85
+ messageRouter,
86
+ false
87
+ )
88
+
89
+ if (userOnboardingJWT) {
90
+ this.setUserOnboardingJWT({
91
+ userOnboardingJWT,
92
+ });
93
+ }
94
+ }
95
+
96
+ /**
97
+ * setUserOnboardingJWT sets the JWT to be whatever value is provided.
98
+ * The JWT should be the UserJWT provided by ZeroHash via the platform
99
+ * API proxied through your servers. As ZeroHash cannot authenticate
100
+ * your users' requests, it is paramount that the user be authenticated
101
+ * and validated on your servers, and exchanged for the JWT using your
102
+ * API key. DO NOT have the JWT exchange logic be on your front-end.
103
+ *
104
+ * As a precaution, we may restrict traffic to the JWT exchange API to
105
+ * whitelisted IPs that come from your server.
106
+ */
107
+ setUserOnboardingJWT(params: ISetUserOnboardingJWTParameters): void {
108
+ store.dispatch({
109
+ type: ACTION_SET_USER_ONBOARDING_JWT,
110
+ userOnboardingJWT: params.userOnboardingJWT,
111
+ });
112
+ }
113
+
114
+ /**
115
+ * isOnboardingModalOpen returns true if the onboarding modal is open,
116
+ * false otherwise
117
+ */
118
+ isOnboardingModalOpen(): boolean {
119
+ return store.getState().appState.isOnboardingAppActive
120
+ }
121
+
122
+ /**
123
+ * openOnboardingModal opens the onboarding modal
124
+ */
125
+ openOnboardingModal(params: IOpenOnboardingModalParameters): void {
126
+ if (params.userOnboardingJWT) {
127
+ this.setUserOnboardingJWT({
128
+ userOnboardingJWT: params.userOnboardingJWT,
129
+ });
130
+ }
131
+ openOnboardingModal();
132
+ if (this.onboardingInitialized) {
133
+ // if it was previously initialized already,
134
+ // simply open the modal, do not re-inject.
135
+ return
136
+ }
137
+
138
+ let root: HTMLElement | null = null;
139
+ if (this.rootQuerySelector) {
140
+ root = document.querySelector(this.rootQuerySelector);
141
+ }
142
+
143
+ if (!root) {
144
+ // Create the default ZeroHash div, e.g. <div id="zerohash-49vt8y"/>
145
+ root = document.createElement("div");
146
+ const rootID = generateRootID();
147
+ root.id = rootID;
148
+ root.style.position = "absolute";
149
+ root.style.top = "0";
150
+ root.style.left = "0";
151
+ this.rootQuerySelector = `#${rootID}`;
152
+
153
+ // Append the ZeroHash div as a child of <body>
154
+ const destinationBox = document.querySelector("body") as HTMLBodyElement;
155
+ destinationBox.appendChild(root);
156
+ }
157
+
158
+ if (root) {
159
+ // Create a shadow wrapper around ZeroHash app for encapsulation
160
+ const shadowRoot = root.attachShadow({mode: 'closed'});
161
+
162
+ // Render the React modal
163
+ ReactDOM
164
+ .createRoot(shadowRoot)
165
+ .render(
166
+ <Provider store={store}>
167
+ <OnboardingApp
168
+ zeroHashOnboardingURL={_zeroHashOnboardingURL}
169
+ />
170
+ </Provider>
171
+ )
172
+
173
+ // set as initialized
174
+ this.onboardingInitialized = true;
175
+ } else {
176
+ const errMsg = "failed to append ZeroHash root to the page: root not found";
177
+ console.error(errMsg);
178
+ throw new Error(errMsg)
179
+ }
180
+ }
181
+
182
+ /**
183
+ * closeOnboardingModalModal hides the onboarding modal
184
+ */
185
+ closeOnboardingModal(): void {
186
+ closeOnboardingModal();
187
+ }
188
+ }
189
+
190
+ if (window) {
191
+ // if the window object exists, the ZeroHash SDK
192
+ // constructor will be appended to it for easier
193
+ // access.
194
+ window.zerohash = ZeroHashSDK;
195
+ }
196
+
197
+ export default ZeroHashSDK;
@@ -0,0 +1,128 @@
1
+ import React, {useEffect, useRef, useState} from "react";
2
+ import {
3
+ appWrapperStyle,
4
+ containerMediaStyles,
5
+ containerStyle,
6
+ iframeStyle,
7
+ iframeWrapperStyle,
8
+ minWidthMatcher,
9
+ modalStyle,
10
+ screenSizes,
11
+ appWrapperHiddenStyle
12
+ } from "../styles";
13
+ import {connect} from "react-redux";
14
+ import {MESSAGE_TYPE_SEND_JWT_TOKEN} from "./constants";
15
+ import {closeOnboardingModal} from "../redux/actions";
16
+
17
+ interface AppProps {
18
+ isOnboardingAppActive: boolean
19
+ isOnboardingAppLoaded: boolean
20
+ userOnboardingJWT: string
21
+ zeroHashOnboardingURL: string
22
+ }
23
+
24
+ const appLoadTime = Date.now();
25
+
26
+ // eslint-disable-next-line react-refresh/only-export-components
27
+ const OnboardingApp = (
28
+ {
29
+ isOnboardingAppActive,
30
+ isOnboardingAppLoaded,
31
+ userOnboardingJWT,
32
+ zeroHashOnboardingURL
33
+ }: AppProps
34
+ ) => {
35
+ const [container, setContainerStyle] = useState(containerStyle);
36
+
37
+ /**
38
+ * setContainer sets the CSS styles based on the current matching media queries
39
+ */
40
+ const setContainer = () => {
41
+ const sizeId = minWidthMatcher();
42
+ const containerMediaStyle = containerMediaStyles[sizeId]
43
+ setContainerStyle({
44
+ ...containerStyle,
45
+ ...containerMediaStyle,
46
+ });
47
+ }
48
+
49
+ const iRef: React.MutableRefObject<HTMLIFrameElement | null> = useRef<HTMLIFrameElement | null>(null);
50
+ useEffect(() => {
51
+ // Send JWT to iframe when all 3 props are ready
52
+ if (zeroHashOnboardingURL && isOnboardingAppLoaded && userOnboardingJWT && iRef.current?.contentWindow) {
53
+ iRef.current.contentWindow.postMessage({
54
+ type: MESSAGE_TYPE_SEND_JWT_TOKEN,
55
+ userOnboardingJWT: userOnboardingJWT,
56
+ }, zeroHashOnboardingURL);
57
+ }
58
+ }, [isOnboardingAppLoaded, userOnboardingJWT, zeroHashOnboardingURL])
59
+
60
+ useEffect(() => {
61
+ // set the styles when the screen size changes
62
+ setContainer();
63
+ if (window) {
64
+ screenSizes.forEach(({size}) => {
65
+ window
66
+ .matchMedia(`(min-width: ${size}px)`)
67
+ .addEventListener('change', setContainer)
68
+ })
69
+ return () => screenSizes.forEach(({size}) => {
70
+ window
71
+ .matchMedia(`(min-width: ${size}px)`)
72
+ .removeEventListener('change', setContainer)
73
+ })
74
+ }
75
+ }, []);
76
+
77
+ const iframeURL = new URL(zeroHashOnboardingURL);
78
+ iframeURL.searchParams.set(
79
+ 'name',
80
+ appLoadTime.toString(),
81
+ )
82
+ if (window) {
83
+ iframeURL.searchParams.set(
84
+ 'origin',
85
+ window.location.origin,
86
+ );
87
+ }
88
+
89
+ return <div
90
+ style={isOnboardingAppActive ? appWrapperStyle : appWrapperHiddenStyle}
91
+ onClick={closeOnboardingModal}
92
+ >
93
+ <div
94
+ style={{
95
+ ...modalStyle,
96
+ ...container,
97
+ }}
98
+ >
99
+ <div
100
+ style={{
101
+ ...iframeWrapperStyle,
102
+ }}
103
+ >
104
+ <iframe
105
+ ref={iRef}
106
+ title="Zerohash Onboarding"
107
+ src={iframeURL.toString()}
108
+ style={iframeStyle}
109
+ />
110
+ </div>
111
+ </div>
112
+ </div>;
113
+ }
114
+
115
+ const mapStateToProps = (state: {
116
+ appState: {
117
+ isOnboardingAppActive: boolean,
118
+ isOnboardingAppLoaded: boolean,
119
+ userOnboardingJWT: string,
120
+ };
121
+ }) => ({
122
+ isOnboardingAppActive: state.appState.isOnboardingAppActive,
123
+ isOnboardingAppLoaded: state.appState.isOnboardingAppLoaded,
124
+ userOnboardingJWT: state.appState.userOnboardingJWT,
125
+ });
126
+
127
+ // eslint-disable-next-line react-refresh/only-export-components
128
+ export default connect(mapStateToProps)(OnboardingApp);
@@ -0,0 +1,2 @@
1
+ const ONBOARDING_MESSAGE_TYPE_PREFIX = "ONBOARDING_"
2
+ export const MESSAGE_TYPE_SEND_JWT_TOKEN = ONBOARDING_MESSAGE_TYPE_PREFIX + "SEND_JWT_TOKEN"
@@ -0,0 +1,12 @@
1
+ import store from "../store";
2
+ import {ACTION_SET_ONBOARDING_MODAL_STATE} from "../reducers/constants";
3
+
4
+ export const openOnboardingModal = () => store.dispatch({
5
+ type: ACTION_SET_ONBOARDING_MODAL_STATE,
6
+ isOnboardingAppActive: true,
7
+ });
8
+
9
+ export const closeOnboardingModal = () => store.dispatch({
10
+ type: ACTION_SET_ONBOARDING_MODAL_STATE,
11
+ isOnboardingAppActive: false,
12
+ });