@solucx/react-native-solucx-widget 0.2.5 → 2.0.7
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/README.md +526 -182
- package/lib/SoluCXWidget.d.ts +50 -7
- package/lib/SoluCXWidget.d.ts.map +1 -1
- package/lib/SoluCXWidget.js +105 -101
- package/lib/SoluCXWidget.js.map +1 -1
- package/lib/SoluCXWidgetHost.d.ts +3 -0
- package/lib/SoluCXWidgetHost.d.ts.map +1 -0
- package/lib/SoluCXWidgetHost.js +34 -0
- package/lib/SoluCXWidgetHost.js.map +1 -0
- package/lib/SoluCXWidgetView.d.ts +12 -0
- package/lib/SoluCXWidgetView.d.ts.map +1 -0
- package/lib/SoluCXWidgetView.js +61 -0
- package/lib/SoluCXWidgetView.js.map +1 -0
- package/lib/components/CloseButton.d.ts +1 -1
- package/lib/components/CloseButton.d.ts.map +1 -1
- package/lib/components/CloseButton.js +4 -1
- package/lib/components/CloseButton.js.map +1 -1
- package/lib/components/InlineWidget.d.ts.map +1 -1
- package/lib/components/InlineWidget.js +2 -7
- package/lib/components/InlineWidget.js.map +1 -1
- package/lib/components/ModalWidget.d.ts +1 -1
- package/lib/components/ModalWidget.d.ts.map +1 -1
- package/lib/components/ModalWidget.js +3 -16
- package/lib/components/ModalWidget.js.map +1 -1
- package/lib/components/OverlayWidget.d.ts.map +1 -1
- package/lib/components/OverlayWidget.js +5 -15
- package/lib/components/OverlayWidget.js.map +1 -1
- package/lib/components/index.d.ts +5 -0
- package/lib/components/index.d.ts.map +1 -0
- package/lib/components/index.js +12 -0
- package/lib/components/index.js.map +1 -0
- package/lib/constants/Constants.d.ts +11 -0
- package/lib/constants/Constants.d.ts.map +1 -1
- package/lib/constants/Constants.js +16 -1
- package/lib/constants/Constants.js.map +1 -1
- package/lib/{interfaces → domain}/WidgetCallbacks.d.ts +2 -2
- package/lib/domain/WidgetCallbacks.d.ts.map +1 -0
- package/lib/domain/WidgetCallbacks.js.map +1 -0
- package/{src/interfaces/WidgetData.ts → lib/domain/WidgetData.d.ts} +5 -2
- package/lib/domain/WidgetData.d.ts.map +1 -0
- package/lib/{interfaces → domain}/WidgetData.js.map +1 -1
- package/lib/domain/WidgetDisplayResult.d.ts +6 -0
- package/lib/domain/WidgetDisplayResult.d.ts.map +1 -0
- package/lib/domain/WidgetDisplayResult.js +3 -0
- package/lib/domain/WidgetDisplayResult.js.map +1 -0
- package/lib/domain/WidgetOptions.d.ts +27 -0
- package/lib/domain/WidgetOptions.d.ts.map +1 -0
- package/lib/domain/WidgetOptions.js +30 -0
- package/lib/domain/WidgetOptions.js.map +1 -0
- package/lib/domain/WidgetResponse.d.ts +5 -0
- package/lib/domain/WidgetResponse.d.ts.map +1 -0
- package/lib/{interfaces/WidgetOptions.js → domain/WidgetResponse.js} +1 -1
- package/lib/domain/WidgetResponse.js.map +1 -0
- package/lib/domain/WidgetSamplerLog.d.ts +12 -0
- package/lib/domain/WidgetSamplerLog.d.ts.map +1 -0
- package/lib/domain/WidgetSamplerLog.js.map +1 -0
- package/lib/{interfaces → domain}/index.d.ts +1 -2
- package/lib/domain/index.d.ts.map +1 -0
- package/lib/{interfaces → domain}/index.js.map +1 -1
- package/lib/hooks/index.d.ts +2 -2
- package/lib/hooks/index.d.ts.map +1 -1
- package/lib/hooks/index.js +5 -5
- package/lib/hooks/index.js.map +1 -1
- package/lib/hooks/useClientVersionCollector.d.ts +3 -0
- package/lib/hooks/useClientVersionCollector.d.ts.map +1 -0
- package/lib/{services/ClientVersionCollector.js → hooks/useClientVersionCollector.js} +7 -2
- package/lib/hooks/useClientVersionCollector.js.map +1 -0
- package/lib/hooks/useHeightAnimation.d.ts +0 -1
- package/lib/hooks/useHeightAnimation.d.ts.map +1 -1
- package/lib/hooks/useHeightAnimation.js +4 -2
- package/lib/hooks/useHeightAnimation.js.map +1 -1
- package/lib/hooks/useWidget.d.ts +13 -0
- package/lib/hooks/useWidget.d.ts.map +1 -0
- package/lib/hooks/useWidget.js +44 -0
- package/lib/hooks/useWidget.js.map +1 -0
- package/lib/hooks/useWidgetBootstrap.d.ts +21 -0
- package/lib/hooks/useWidgetBootstrap.d.ts.map +1 -0
- package/lib/hooks/useWidgetBootstrap.js +87 -0
- package/lib/hooks/useWidgetBootstrap.js.map +1 -0
- package/lib/hooks/useWidgetServices.d.ts +19 -0
- package/lib/hooks/useWidgetServices.d.ts.map +1 -0
- package/lib/hooks/useWidgetServices.js +34 -0
- package/lib/hooks/useWidgetServices.js.map +1 -0
- package/lib/hooks/useWidgetUI.d.ts +9 -0
- package/lib/hooks/useWidgetUI.d.ts.map +1 -0
- package/lib/hooks/useWidgetUI.js +33 -0
- package/lib/hooks/useWidgetUI.js.map +1 -0
- package/lib/index.d.ts +10 -11
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +13 -38
- package/lib/index.js.map +1 -1
- package/lib/services/UserIdentificationService.d.ts +3 -0
- package/lib/services/UserIdentificationService.d.ts.map +1 -0
- package/lib/services/UserIdentificationService.js +17 -0
- package/lib/services/UserIdentificationService.js.map +1 -0
- package/lib/services/WidgetBootstrapService.d.ts +12 -0
- package/lib/services/WidgetBootstrapService.d.ts.map +1 -0
- package/lib/services/{widgetBootstrapService.js → WidgetBootstrapService.js} +36 -15
- package/lib/services/WidgetBootstrapService.js.map +1 -0
- package/lib/services/WidgetEventService.d.ts +8 -0
- package/lib/services/WidgetEventService.d.ts.map +1 -0
- package/lib/services/WidgetEventService.js +14 -0
- package/lib/services/WidgetEventService.js.map +1 -0
- package/lib/services/WidgetStateManager.d.ts +20 -0
- package/lib/services/WidgetStateManager.d.ts.map +1 -0
- package/lib/services/WidgetStateManager.js +93 -0
- package/lib/services/WidgetStateManager.js.map +1 -0
- package/lib/services/WidgetValidationService.d.ts +17 -0
- package/lib/services/WidgetValidationService.d.ts.map +1 -0
- package/lib/services/WidgetValidationService.js +132 -0
- package/lib/services/WidgetValidationService.js.map +1 -0
- package/lib/services/events/EventHandlerFactory.d.ts +18 -0
- package/lib/services/events/EventHandlerFactory.d.ts.map +1 -0
- package/lib/services/events/EventHandlerFactory.js +67 -0
- package/lib/services/events/EventHandlerFactory.js.map +1 -0
- package/lib/services/events/EventHandlers.d.ts +10 -0
- package/lib/services/events/EventHandlers.d.ts.map +1 -0
- package/lib/services/events/EventHandlers.js +72 -0
- package/lib/services/events/EventHandlers.js.map +1 -0
- package/lib/services/events/index.d.ts +3 -0
- package/lib/services/events/index.d.ts.map +1 -0
- package/lib/services/events/index.js +21 -0
- package/lib/services/events/index.js.map +1 -0
- package/lib/services/height/HeightStrategies.d.ts +3 -0
- package/lib/services/height/HeightStrategies.d.ts.map +1 -0
- package/lib/services/height/HeightStrategies.js +14 -0
- package/lib/services/height/HeightStrategies.js.map +1 -0
- package/lib/services/storage/AsyncStorageService.d.ts +13 -0
- package/lib/services/storage/AsyncStorageService.d.ts.map +1 -0
- package/lib/services/storage/AsyncStorageService.js +73 -0
- package/lib/services/storage/AsyncStorageService.js.map +1 -0
- package/lib/services/storage/IStorageService.d.ts +30 -0
- package/lib/services/storage/IStorageService.d.ts.map +1 -0
- package/lib/services/storage/IStorageService.js +3 -0
- package/lib/services/storage/IStorageService.js.map +1 -0
- package/lib/services/storage/StorageIdBuilder.d.ts +11 -0
- package/lib/services/storage/StorageIdBuilder.d.ts.map +1 -0
- package/lib/services/storage/StorageIdBuilder.js +17 -0
- package/lib/services/storage/StorageIdBuilder.js.map +1 -0
- package/lib/services/storage/index.d.ts +3 -0
- package/lib/services/storage/index.d.ts.map +1 -0
- package/lib/services/storage/index.js +6 -0
- package/lib/services/storage/index.js.map +1 -0
- package/lib/styles/widgetStyles.d.ts +1 -1
- package/lib/styles/widgetStyles.d.ts.map +1 -1
- package/package.json +8 -2
- package/src/SoluCXWidget.ts +144 -0
- package/src/SoluCXWidgetHost.tsx +44 -0
- package/src/SoluCXWidgetView.tsx +97 -0
- package/src/__tests__/ClientVersionCollector.test.ts +5 -5
- package/src/__tests__/OverlayWidget.rendering.test.tsx +12 -14
- package/src/__tests__/SoluCXWidget.rendering.test.tsx +103 -60
- package/src/__tests__/SoluCXWidget.test.ts +448 -0
- package/src/__tests__/WidgetValidationService.test.ts +408 -0
- package/src/__tests__/e2e/widget-lifecycle.test.tsx +14 -23
- package/src/__tests__/index.test.tsx +39 -0
- package/src/__tests__/integration/webview-communication-simple.test.tsx +8 -6
- package/src/__tests__/integration/webview-communication.test.tsx +127 -130
- package/src/__tests__/normalizeWidgetOptions.test.ts +80 -0
- package/src/__tests__/useWidgetBootstrap.test.ts +634 -0
- package/src/__tests__/useWidgetState.test.ts +56 -13
- package/src/__tests__/widgetBootstrapService.test.ts +15 -17
- package/src/components/CloseButton.tsx +6 -2
- package/src/components/InlineWidget.tsx +4 -9
- package/src/components/ModalWidget.tsx +15 -45
- package/src/components/OverlayWidget.tsx +5 -15
- package/src/components/index.ts +4 -0
- package/src/constants/Constants.ts +15 -0
- package/src/{interfaces → domain}/WidgetCallbacks.ts +2 -2
- package/{lib/interfaces/WidgetData.d.ts → src/domain/WidgetData.ts} +3 -2
- package/src/domain/WidgetDisplayResult.ts +16 -0
- package/src/domain/WidgetOptions.ts +53 -0
- package/src/domain/WidgetResponse.ts +5 -0
- package/src/domain/WidgetSamplerLog.ts +11 -0
- package/src/{interfaces → domain}/index.ts +1 -2
- package/src/hooks/index.ts +2 -2
- package/src/{services/ClientVersionCollector.ts → hooks/useClientVersionCollector.ts} +6 -0
- package/src/hooks/useHeightAnimation.ts +6 -3
- package/src/hooks/useWidget.ts +46 -0
- package/src/hooks/useWidgetBootstrap.ts +117 -0
- package/src/hooks/useWidgetServices.ts +44 -0
- package/src/hooks/useWidgetUI.ts +38 -0
- package/src/index.ts +16 -11
- package/src/services/UserIdentificationService.ts +14 -0
- package/src/services/{widgetBootstrapService.ts → WidgetBootstrapService.ts} +43 -19
- package/src/services/WidgetEventService.ts +15 -0
- package/src/services/WidgetStateManager.ts +115 -0
- package/src/services/WidgetValidationService.ts +149 -0
- package/src/services/events/EventHandlerFactory.ts +70 -0
- package/src/services/events/EventHandlers.ts +67 -0
- package/src/services/events/index.ts +2 -0
- package/src/services/height/HeightStrategies.ts +15 -0
- package/src/services/storage/AsyncStorageService.ts +74 -0
- package/src/services/storage/IStorageService.ts +32 -0
- package/src/services/storage/StorageIdBuilder.ts +15 -0
- package/src/services/storage/index.ts +2 -0
- package/src/styles/widgetStyles.ts +1 -1
- package/README.intern.md +0 -490
- package/lib/constants/webViewConstants.d.ts +0 -12
- package/lib/constants/webViewConstants.d.ts.map +0 -1
- package/lib/constants/webViewConstants.js +0 -19
- package/lib/constants/webViewConstants.js.map +0 -1
- package/lib/hooks/useWidgetHeight.d.ts +0 -13
- package/lib/hooks/useWidgetHeight.d.ts.map +0 -1
- package/lib/hooks/useWidgetHeight.js +0 -21
- package/lib/hooks/useWidgetHeight.js.map +0 -1
- package/lib/hooks/useWidgetState.d.ts +0 -15
- package/lib/hooks/useWidgetState.d.ts.map +0 -1
- package/lib/hooks/useWidgetState.js +0 -79
- package/lib/hooks/useWidgetState.js.map +0 -1
- package/lib/interfaces/WidgetCallbacks.d.ts.map +0 -1
- package/lib/interfaces/WidgetCallbacks.js.map +0 -1
- package/lib/interfaces/WidgetData.d.ts.map +0 -1
- package/lib/interfaces/WidgetOptions.d.ts +0 -9
- package/lib/interfaces/WidgetOptions.d.ts.map +0 -1
- package/lib/interfaces/WidgetOptions.js.map +0 -1
- package/lib/interfaces/WidgetResponse.d.ts +0 -10
- package/lib/interfaces/WidgetResponse.d.ts.map +0 -1
- package/lib/interfaces/WidgetResponse.js +0 -12
- package/lib/interfaces/WidgetResponse.js.map +0 -1
- package/lib/interfaces/WidgetSamplerLog.d.ts +0 -7
- package/lib/interfaces/WidgetSamplerLog.d.ts.map +0 -1
- package/lib/interfaces/WidgetSamplerLog.js.map +0 -1
- package/lib/interfaces/index.d.ts.map +0 -1
- package/lib/services/ClientVersionCollector.d.ts +0 -2
- package/lib/services/ClientVersionCollector.d.ts.map +0 -1
- package/lib/services/ClientVersionCollector.js.map +0 -1
- package/lib/services/storage.d.ts +0 -8
- package/lib/services/storage.d.ts.map +0 -1
- package/lib/services/storage.js +0 -23
- package/lib/services/storage.js.map +0 -1
- package/lib/services/widgetBootstrapService.d.ts +0 -6
- package/lib/services/widgetBootstrapService.d.ts.map +0 -1
- package/lib/services/widgetBootstrapService.js.map +0 -1
- package/lib/services/widgetEventService.d.ts +0 -19
- package/lib/services/widgetEventService.d.ts.map +0 -1
- package/lib/services/widgetEventService.js +0 -79
- package/lib/services/widgetEventService.js.map +0 -1
- package/lib/services/widgetValidationService.d.ts +0 -18
- package/lib/services/widgetValidationService.d.ts.map +0 -1
- package/lib/services/widgetValidationService.js +0 -71
- package/lib/services/widgetValidationService.js.map +0 -1
- package/src/SoluCXWidget.tsx +0 -179
- package/src/constants/webViewConstants.ts +0 -15
- package/src/hooks/useWidgetHeight.ts +0 -38
- package/src/hooks/useWidgetState.ts +0 -101
- package/src/interfaces/WidgetOptions.ts +0 -8
- package/src/interfaces/WidgetResponse.ts +0 -15
- package/src/interfaces/WidgetSamplerLog.ts +0 -6
- package/src/services/storage.ts +0 -21
- package/src/services/widgetEventService.ts +0 -110
- package/src/services/widgetValidationService.ts +0 -102
- /package/lib/{interfaces → domain}/WidgetCallbacks.js +0 -0
- /package/lib/{interfaces → domain}/WidgetData.js +0 -0
- /package/lib/{interfaces → domain}/WidgetSamplerLog.js +0 -0
- /package/lib/{interfaces → domain}/index.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widgetStyles.d.ts","sourceRoot":"","sources":["../../src/styles/widgetStyles.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"widgetStyles.d.ts","sourceRoot":"","sources":["../../src/styles/widgetStyles.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCjB,CAAC;AAEH,eAAO,MAAM,mBAAmB,GAAI,YAAY,OAAO;;;CAKtD,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAS/C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solucx/react-native-solucx-widget",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "2.0.7",
|
|
4
4
|
"description": "The React Native SDK for Solucx Widget",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -42,8 +42,14 @@
|
|
|
42
42
|
"setupFilesAfterEnv": [
|
|
43
43
|
"<rootDir>/src/setupTests.js"
|
|
44
44
|
],
|
|
45
|
+
"testRegex": ".*\\.test\\.(ts|tsx)$",
|
|
46
|
+
"testMatch": null,
|
|
45
47
|
"testPathIgnorePatterns": [
|
|
46
|
-
"/lib/"
|
|
48
|
+
"/lib/",
|
|
49
|
+
"/old_tests/",
|
|
50
|
+
"\\.old\\.spec\\.",
|
|
51
|
+
"\\.spec\\.(ts|tsx)$",
|
|
52
|
+
"node_modules"
|
|
47
53
|
],
|
|
48
54
|
"moduleNameMapper": {
|
|
49
55
|
"expo-modules-core/src/Refs": "<rootDir>/src/__mocks__/expo-modules-core.js",
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import type { WidgetCallbacks, WidgetData, WidgetOptions, WidgetSamplerLog, WidgetType } from "./domain";
|
|
2
|
+
import { normalizeWidgetOptions } from "./domain/WidgetOptions";
|
|
3
|
+
import { AsyncStorageService } from "./services/storage/AsyncStorageService";
|
|
4
|
+
import { buildStorageId } from "./services/storage/StorageIdBuilder";
|
|
5
|
+
import { WidgetStateManager, type TimestampField } from "./services/WidgetStateManager";
|
|
6
|
+
|
|
7
|
+
export interface WidgetConfig {
|
|
8
|
+
instanceKey: string;
|
|
9
|
+
type: WidgetType;
|
|
10
|
+
data: WidgetData;
|
|
11
|
+
options?: WidgetOptions;
|
|
12
|
+
callbacks: WidgetCallbacks;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type ShowHandler = (config: WidgetConfig) => void;
|
|
16
|
+
type DismissHandler = () => void;
|
|
17
|
+
|
|
18
|
+
let registeredShowHandler: ShowHandler | null = null;
|
|
19
|
+
let registeredDismissHandler: DismissHandler | null = null;
|
|
20
|
+
|
|
21
|
+
export function _registerHost(show: ShowHandler, dismiss: DismissHandler) {
|
|
22
|
+
registeredShowHandler = show;
|
|
23
|
+
registeredDismissHandler = dismiss;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function _unregisterHost() {
|
|
27
|
+
registeredShowHandler = null;
|
|
28
|
+
registeredDismissHandler = null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class SoluCXWidget {
|
|
32
|
+
private _instanceKey: string = "";
|
|
33
|
+
private _type: WidgetType = "bottom";
|
|
34
|
+
private _data: WidgetData = {};
|
|
35
|
+
private _options: WidgetOptions | null = {};
|
|
36
|
+
private _callbacks: WidgetCallbacks = {};
|
|
37
|
+
|
|
38
|
+
private constructor(instanceKey: string) {
|
|
39
|
+
this._instanceKey = instanceKey;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// --- Builder methods ---
|
|
43
|
+
|
|
44
|
+
static create(instanceKey: string): SoluCXWidget {
|
|
45
|
+
return new SoluCXWidget(instanceKey);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
setData(data: WidgetData): this {
|
|
49
|
+
this._data = { ...data };
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
setOptions(options: WidgetOptions): this {
|
|
54
|
+
const isObjectValid = !!options && Object.keys(options).length > 0;
|
|
55
|
+
this._options = isObjectValid ? normalizeWidgetOptions(options) : null;
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
setCallbacks(callbacks: WidgetCallbacks): this {
|
|
60
|
+
this._callbacks = { ...callbacks };
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
setType(type: WidgetType): this {
|
|
65
|
+
this._type = type;
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
show(): void {
|
|
70
|
+
if (!registeredShowHandler) {
|
|
71
|
+
throw new Error("[SoluCXWidget] Cannot show widget — no <SoluCXWidgetHost /> is mounted. " + "Add <SoluCXWidgetHost /> at the root of your app.");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
registeredShowHandler({
|
|
75
|
+
instanceKey: this._instanceKey,
|
|
76
|
+
type: this._type,
|
|
77
|
+
data: { ...this._data },
|
|
78
|
+
options: { ...this._options },
|
|
79
|
+
callbacks: { ...this._callbacks },
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
this._cleanup();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// --- Static: dismiss ---
|
|
86
|
+
|
|
87
|
+
static dismiss(): void {
|
|
88
|
+
registeredDismissHandler?.();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// --- Log management (instance methods) ---
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Build the storage ID from the builder state.
|
|
95
|
+
* Uses instanceKey + journey (from data) + userId (from data).
|
|
96
|
+
*/
|
|
97
|
+
private _buildStorageId(): string {
|
|
98
|
+
return buildStorageId(this._instanceKey, this._data);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private _createStateManager(): WidgetStateManager {
|
|
102
|
+
const storageId = this._buildStorageId();
|
|
103
|
+
const storageService = new AsyncStorageService(storageId);
|
|
104
|
+
return new WidgetStateManager(storageService, storageId);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Override a specific event timestamp.
|
|
109
|
+
* Uses instanceKey from create() and journey/userId from setData().
|
|
110
|
+
*
|
|
111
|
+
* @param field - The timestamp field to override (e.g., 'lastFirstAccess', 'lastDismiss')
|
|
112
|
+
* @param date - The date to set (Date object or timestamp in milliseconds). Use 0 to clear.
|
|
113
|
+
*/
|
|
114
|
+
async overrideTimestamp(field: TimestampField, date: Date | number): Promise<this> {
|
|
115
|
+
await this._createStateManager().overrideTimestamp(field, date);
|
|
116
|
+
return this;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get the current widget logs.
|
|
121
|
+
* Uses instanceKey from create() and journey/userId from setData().
|
|
122
|
+
*/
|
|
123
|
+
async getWidgetLogs(): Promise<WidgetSamplerLog> {
|
|
124
|
+
return this._createStateManager().getLogs();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Clear all widget logs.
|
|
129
|
+
* Uses instanceKey from create() and journey/userId from setData().
|
|
130
|
+
*/
|
|
131
|
+
async clearWidgetLogs(): Promise<this> {
|
|
132
|
+
await this._createStateManager().clearLogs();
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// --- Private ---
|
|
137
|
+
|
|
138
|
+
private _cleanup(): void {
|
|
139
|
+
this._type = "bottom";
|
|
140
|
+
this._data = {};
|
|
141
|
+
this._options = {};
|
|
142
|
+
this._callbacks = {};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React, { useEffect, useState, useCallback } from "react";
|
|
2
|
+
import { SoluCXWidgetView } from "./SoluCXWidgetView";
|
|
3
|
+
import { _registerHost, _unregisterHost } from "./SoluCXWidget";
|
|
4
|
+
import type { WidgetConfig } from "./SoluCXWidget";
|
|
5
|
+
|
|
6
|
+
export const SoluCXWidgetHost: React.FC = () => {
|
|
7
|
+
const [config, setConfig] = useState<WidgetConfig | null>(null);
|
|
8
|
+
const [refreshKey, setRefreshKey] = useState(0);
|
|
9
|
+
|
|
10
|
+
const handleShow = useCallback((newConfig: WidgetConfig) => {
|
|
11
|
+
setConfig(newConfig);
|
|
12
|
+
setRefreshKey((k) => k + 1);
|
|
13
|
+
}, []);
|
|
14
|
+
|
|
15
|
+
const handleDismiss = useCallback(() => {
|
|
16
|
+
setConfig(null);
|
|
17
|
+
}, []);
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
_registerHost(handleShow, handleDismiss);
|
|
21
|
+
return () => _unregisterHost();
|
|
22
|
+
}, [handleShow, handleDismiss]);
|
|
23
|
+
|
|
24
|
+
if (!config) return null;
|
|
25
|
+
|
|
26
|
+
const wrappedCallbacks = {
|
|
27
|
+
...config.callbacks,
|
|
28
|
+
onClosed: () => {
|
|
29
|
+
config.callbacks?.onClosed?.();
|
|
30
|
+
setConfig(null);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<SoluCXWidgetView
|
|
36
|
+
key={refreshKey}
|
|
37
|
+
soluCXKey={config.instanceKey}
|
|
38
|
+
type={config.type}
|
|
39
|
+
data={config.data}
|
|
40
|
+
options={config.options}
|
|
41
|
+
callbacks={wrappedCallbacks}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import React, { useCallback, useEffect } from "react";
|
|
2
|
+
import { Dimensions } from "react-native";
|
|
3
|
+
import { WebView } from "react-native-webview";
|
|
4
|
+
|
|
5
|
+
import { InlineWidget } from "./components/InlineWidget";
|
|
6
|
+
import { ModalWidget } from "./components/ModalWidget";
|
|
7
|
+
import { OverlayWidget } from "./components/OverlayWidget";
|
|
8
|
+
import { WEB_VIEW_MESSAGE_LISTENER } from "./constants/Constants";
|
|
9
|
+
import type { SoluCXKey, WidgetCallbacks, WidgetData, WidgetOptions, WidgetType } from "./domain";
|
|
10
|
+
import { useWidget } from "./hooks/useWidget";
|
|
11
|
+
import { useWidgetBootstrap } from "./hooks/useWidgetBootstrap";
|
|
12
|
+
import { useWidgetServices } from "./hooks/useWidgetServices";
|
|
13
|
+
|
|
14
|
+
interface SoluCXWidgetProps {
|
|
15
|
+
soluCXKey: SoluCXKey;
|
|
16
|
+
type: WidgetType;
|
|
17
|
+
data: WidgetData;
|
|
18
|
+
options?: WidgetOptions;
|
|
19
|
+
callbacks?: WidgetCallbacks;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const SoluCXWidgetView: React.FC<SoluCXWidgetProps> = ({ soluCXKey, type, data, options, callbacks }) => {
|
|
23
|
+
const { width } = Dimensions.get("window");
|
|
24
|
+
|
|
25
|
+
const { widgetHeight, isWidgetVisible, resize, open, hide, userId, stateManager } = useWidget(soluCXKey, data, options);
|
|
26
|
+
|
|
27
|
+
const { validationService, handleWebViewMessage } = useWidgetServices({
|
|
28
|
+
hide,
|
|
29
|
+
resize,
|
|
30
|
+
userId,
|
|
31
|
+
callbacks,
|
|
32
|
+
data,
|
|
33
|
+
stateManager,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const { widgetUri, bootstrap } = useWidgetBootstrap({
|
|
37
|
+
soluCXKey,
|
|
38
|
+
data,
|
|
39
|
+
userId,
|
|
40
|
+
options,
|
|
41
|
+
callbacks,
|
|
42
|
+
open,
|
|
43
|
+
hide,
|
|
44
|
+
validationService,
|
|
45
|
+
stateManager,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
bootstrap();
|
|
50
|
+
}, []);
|
|
51
|
+
|
|
52
|
+
const handleClose = useCallback(() => {
|
|
53
|
+
hide();
|
|
54
|
+
callbacks?.onClosed?.();
|
|
55
|
+
}, [hide, callbacks]);
|
|
56
|
+
|
|
57
|
+
if (!data) {
|
|
58
|
+
callbacks?.onError?.("Widget data is required but was not provided");
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!widgetUri) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const webView = (
|
|
67
|
+
<WebView
|
|
68
|
+
style={[{ height: widgetHeight }, { width }]}
|
|
69
|
+
source={{ uri: widgetUri }}
|
|
70
|
+
injectedJavaScript={WEB_VIEW_MESSAGE_LISTENER}
|
|
71
|
+
onMessage={event => handleWebViewMessage(event.nativeEvent.data)}
|
|
72
|
+
originWhitelist={["*"]}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
if (type === "modal") {
|
|
77
|
+
return (
|
|
78
|
+
<ModalWidget visible={isWidgetVisible} height={widgetHeight} onClose={handleClose}>
|
|
79
|
+
{webView}
|
|
80
|
+
</ModalWidget>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (type === "inline") {
|
|
85
|
+
return (
|
|
86
|
+
<InlineWidget visible={isWidgetVisible} height={widgetHeight} onClose={handleClose}>
|
|
87
|
+
{webView}
|
|
88
|
+
</InlineWidget>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<OverlayWidget visible={isWidgetVisible} width={width} height={widgetHeight} position={type} onClose={handleClose}>
|
|
94
|
+
{webView}
|
|
95
|
+
</OverlayWidget>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
@@ -10,7 +10,7 @@ describe('ClientVersionCollector', () => {
|
|
|
10
10
|
},
|
|
11
11
|
}), { virtual: true });
|
|
12
12
|
|
|
13
|
-
const { getClientVersion } = require('../
|
|
13
|
+
const { getClientVersion } = require('../hooks/useClientVersionCollector');
|
|
14
14
|
expect(getClientVersion()).toBe('3.0.0');
|
|
15
15
|
});
|
|
16
16
|
|
|
@@ -19,7 +19,7 @@ describe('ClientVersionCollector', () => {
|
|
|
19
19
|
getVersion: () => '4.0.0',
|
|
20
20
|
}), { virtual: true });
|
|
21
21
|
|
|
22
|
-
const { getClientVersion } = require('../
|
|
22
|
+
const { getClientVersion } = require('../hooks/useClientVersionCollector');
|
|
23
23
|
expect(getClientVersion()).toBe('4.0.0');
|
|
24
24
|
});
|
|
25
25
|
|
|
@@ -28,7 +28,7 @@ describe('ClientVersionCollector', () => {
|
|
|
28
28
|
throw new Error('Module not found');
|
|
29
29
|
}, { virtual: true });
|
|
30
30
|
|
|
31
|
-
const { getClientVersion } = require('../
|
|
31
|
+
const { getClientVersion } = require('../hooks/useClientVersionCollector');
|
|
32
32
|
expect(getClientVersion()).toBe('unknown');
|
|
33
33
|
});
|
|
34
34
|
|
|
@@ -37,7 +37,7 @@ describe('ClientVersionCollector', () => {
|
|
|
37
37
|
default: {},
|
|
38
38
|
}), { virtual: true });
|
|
39
39
|
|
|
40
|
-
const { getClientVersion } = require('../
|
|
40
|
+
const { getClientVersion } = require('../hooks/useClientVersionCollector');
|
|
41
41
|
expect(getClientVersion()).toBe('unknown');
|
|
42
42
|
});
|
|
43
43
|
|
|
@@ -49,7 +49,7 @@ describe('ClientVersionCollector', () => {
|
|
|
49
49
|
getVersion: () => '6.0.0',
|
|
50
50
|
}), { virtual: true });
|
|
51
51
|
|
|
52
|
-
const { getClientVersion } = require('../
|
|
52
|
+
const { getClientVersion } = require('../hooks/useClientVersionCollector');
|
|
53
53
|
expect(getClientVersion()).toBe('5.0.0');
|
|
54
54
|
});
|
|
55
55
|
});
|
|
@@ -47,41 +47,39 @@ describe('OverlayWidget rendering', () => {
|
|
|
47
47
|
expect(mockOnClose).toHaveBeenCalledTimes(1);
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
it('should
|
|
51
|
-
const
|
|
52
|
-
|
|
50
|
+
it('should call onClose when close button is pressed and component is controlled by parent', () => {
|
|
51
|
+
const mockOnClose = jest.fn();
|
|
52
|
+
const { getByText } = render(
|
|
53
|
+
<OverlayWidget visible={true} width={390} height={300} position="bottom" onClose={mockOnClose}>
|
|
53
54
|
<Text>Dismissible Content</Text>
|
|
54
55
|
</OverlayWidget>
|
|
55
56
|
);
|
|
56
57
|
|
|
57
58
|
fireEvent.press(getByText('✕'));
|
|
58
59
|
|
|
59
|
-
expect(
|
|
60
|
+
expect(mockOnClose).toHaveBeenCalledTimes(1);
|
|
60
61
|
});
|
|
61
62
|
|
|
62
|
-
it('should not render
|
|
63
|
-
const {
|
|
64
|
-
<OverlayWidget visible={
|
|
63
|
+
it('should not render when visible prop is false', () => {
|
|
64
|
+
const { queryByText } = render(
|
|
65
|
+
<OverlayWidget visible={false} width={390} height={300} position="top" onClose={jest.fn()}>
|
|
65
66
|
<Text>Top Content</Text>
|
|
66
67
|
</OverlayWidget>
|
|
67
68
|
);
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
expect(queryByText('Top Content')).toBeNull();
|
|
71
71
|
expect(queryByText('✕')).toBeNull();
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
it('should
|
|
75
|
-
const {
|
|
74
|
+
it('should hide content when visible prop changes to false', () => {
|
|
75
|
+
const { queryByText, rerender } = render(
|
|
76
76
|
<OverlayWidget visible={true} width={390} height={300} position="bottom" onClose={jest.fn()}>
|
|
77
77
|
<Text>Content</Text>
|
|
78
78
|
</OverlayWidget>
|
|
79
79
|
);
|
|
80
80
|
|
|
81
|
-
fireEvent.press(getByText('✕'));
|
|
82
|
-
|
|
83
81
|
rerender(
|
|
84
|
-
<OverlayWidget visible={
|
|
82
|
+
<OverlayWidget visible={false} width={390} height={300} position="bottom" onClose={jest.fn()}>
|
|
85
83
|
<Text>Content</Text>
|
|
86
84
|
</OverlayWidget>
|
|
87
85
|
);
|