@frak-labs/components 1.0.3-beta.7dfd3480 → 1.0.3-beta.9d4f564a
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 +4 -4
- package/cdn/Banner.Bu3GvJyS.js +0 -164
- package/cdn/ButtonShare.BMkk39K_.js +0 -1
- package/cdn/ButtonWallet.DT6bWcXS.js +0 -40
- package/cdn/OpenInAppButton.CBzl8Rgk.js +0 -1
- package/cdn/PostPurchase.CoLlrWLm.js +0 -52
- package/cdn/components.js +0 -1
- package/cdn/formatReward.CEAF0Lox.js +0 -1
- package/cdn/loader.css +0 -0
- package/cdn/loader.js +0 -14
- package/cdn/sharingPage.Do_xfrTN.js +0 -1
- package/cdn/sprinkles.css.ts.vanilla.06k5OzG1.js +0 -1175
- package/cdn/useGlobalComponents.UJmjUUxk.js +0 -1
- package/cdn/useLightDomStyles.Gt7YUMDl.js +0 -1
- package/cdn/usePlacement.BJ7qe-pw.js +0 -58
- package/cdn/useReward.Bn1RVE3i.js +0 -1
- package/dist/GiftIcon-c28NnqJ7.js +0 -1502
- package/dist/banner.d.ts +0 -116
- package/dist/banner.js +0 -466
- package/dist/buttonShare.d.ts +0 -118
- package/dist/buttonShare.js +0 -122
- package/dist/buttonWallet.d.ts +0 -87
- package/dist/buttonWallet.js +0 -148
- package/dist/formatReward-Bub6Z6eY.js +0 -33
- package/dist/openInApp.d.ts +0 -66
- package/dist/openInApp.js +0 -110
- package/dist/postPurchase.d.ts +0 -152
- package/dist/postPurchase.js +0 -1700
- package/dist/sharingPage-DFvQbviS.js +0 -15
- package/dist/useGlobalComponents-Cmfszr7v.js +0 -21
- package/dist/useLightDomStyles-gbuSWvRx.js +0 -89
- package/dist/usePlacement-V7NrKoub.js +0 -253
- package/dist/useReward-DU3_yP8Q.js +0 -65
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { displaySharingPage } from "@frak-labs/core-sdk/actions";
|
|
2
|
-
//#region src/utils/sharingPage.ts
|
|
3
|
-
async function openSharingPage(targetInteraction, placement, options) {
|
|
4
|
-
if (!window.FrakSetup?.client) {
|
|
5
|
-
console.error("Frak client not found");
|
|
6
|
-
return;
|
|
7
|
-
}
|
|
8
|
-
await displaySharingPage(window.FrakSetup.client, {
|
|
9
|
-
...options?.link && { link: options.link },
|
|
10
|
-
...options?.products?.length && { products: options.products },
|
|
11
|
-
...targetInteraction && { metadata: { targetInteraction } }
|
|
12
|
-
}, placement);
|
|
13
|
-
}
|
|
14
|
-
//#endregion
|
|
15
|
-
export { openSharingPage as t };
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { sdkConfigStore } from "@frak-labs/core-sdk";
|
|
2
|
-
import { useEffect, useMemo, useState } from "preact/hooks";
|
|
3
|
-
//#region src/hooks/useGlobalComponents.ts
|
|
4
|
-
/**
|
|
5
|
-
* Subscribe to the global component defaults from the SDK config store.
|
|
6
|
-
* These serve as fallbacks when no placement-level override exists.
|
|
7
|
-
*/
|
|
8
|
-
function useGlobalComponents() {
|
|
9
|
-
const [configVersion, setConfigVersion] = useState(0);
|
|
10
|
-
useEffect(() => {
|
|
11
|
-
const onConfig = (_e) => {
|
|
12
|
-
setConfigVersion((v) => v + 1);
|
|
13
|
-
};
|
|
14
|
-
window.addEventListener("frak:config", onConfig);
|
|
15
|
-
setConfigVersion((v) => v + 1);
|
|
16
|
-
return () => window.removeEventListener("frak:config", onConfig);
|
|
17
|
-
}, []);
|
|
18
|
-
return useMemo(() => sdkConfigStore.getConfig().components, [configVersion]);
|
|
19
|
-
}
|
|
20
|
-
//#endregion
|
|
21
|
-
export { useGlobalComponents as t };
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { r as lightDomBaseCss } from "./usePlacement-V7NrKoub.js";
|
|
2
|
-
import { useEffect } from "preact/hooks";
|
|
3
|
-
//#region src/utils/styleManager.ts
|
|
4
|
-
/**
|
|
5
|
-
* Tracks every base CSS rule (by exact cssText) already injected into <head>.
|
|
6
|
-
*
|
|
7
|
-
* Each Light DOM component (frak-banner, frak-post-purchase, …) ships a
|
|
8
|
-
* `cssSource` string that contains both component-specific rules AND shared
|
|
9
|
-
* design-system rules (reset, sprinkles, theme tokens) pulled in transitively
|
|
10
|
-
* by vanilla-extract. Without dedup, every component re-emits the same reset
|
|
11
|
-
* class definitions in its own <style> tag, and whichever stylesheet is
|
|
12
|
-
* appended LAST wins for those shared selectors — flipping the cascade order
|
|
13
|
-
* non-deterministically across mount orders.
|
|
14
|
-
*
|
|
15
|
-
* Deduplicating rule-by-rule guarantees that shared rules appear exactly once
|
|
16
|
-
* (in the first component's stylesheet) and component-specific rules always
|
|
17
|
-
* come AFTER them in document order, so component styles win deterministically.
|
|
18
|
-
*/
|
|
19
|
-
const injectedRules = /* @__PURE__ */ new Set();
|
|
20
|
-
function ensureStyle(id, css) {
|
|
21
|
-
const existing = document.getElementById(id);
|
|
22
|
-
if (existing) {
|
|
23
|
-
if (existing.textContent !== css) existing.textContent = css;
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
const style = document.createElement("style");
|
|
27
|
-
style.id = id;
|
|
28
|
-
style.textContent = css;
|
|
29
|
-
document.head.appendChild(style);
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Parses `css` and returns a new string containing only rules that have not
|
|
33
|
-
* already been injected into <head>. Tracks injected rules in `injectedRules`.
|
|
34
|
-
*
|
|
35
|
-
* Falls back to the raw input if the browser lacks the constructable
|
|
36
|
-
* `CSSStyleSheet` API or parsing fails — preserves correctness over dedup.
|
|
37
|
-
*/
|
|
38
|
-
function dedupeAgainstInjected(css) {
|
|
39
|
-
if (typeof CSSStyleSheet !== "function") return css;
|
|
40
|
-
let sheet;
|
|
41
|
-
try {
|
|
42
|
-
sheet = new CSSStyleSheet();
|
|
43
|
-
sheet.replaceSync(css);
|
|
44
|
-
} catch {
|
|
45
|
-
return css;
|
|
46
|
-
}
|
|
47
|
-
let out = "";
|
|
48
|
-
for (let i = 0; i < sheet.cssRules.length; i++) {
|
|
49
|
-
const ruleText = sheet.cssRules[i].cssText;
|
|
50
|
-
if (injectedRules.has(ruleText)) continue;
|
|
51
|
-
injectedRules.add(ruleText);
|
|
52
|
-
out += `${ruleText}\n`;
|
|
53
|
-
}
|
|
54
|
-
return out;
|
|
55
|
-
}
|
|
56
|
-
function injectBase(tag, css) {
|
|
57
|
-
const id = `frak-base-${tag}`;
|
|
58
|
-
if (document.getElementById(id)) return;
|
|
59
|
-
const deduped = dedupeAgainstInjected(css);
|
|
60
|
-
if (!deduped) return;
|
|
61
|
-
const style = document.createElement("style");
|
|
62
|
-
style.id = id;
|
|
63
|
-
style.textContent = deduped;
|
|
64
|
-
document.head.appendChild(style);
|
|
65
|
-
}
|
|
66
|
-
function injectPlacement(tag, placementId, scopedCss) {
|
|
67
|
-
ensureStyle(`frak-placement-${tag}-${placementId}`, scopedCss);
|
|
68
|
-
}
|
|
69
|
-
const styleManager = {
|
|
70
|
-
injectBase,
|
|
71
|
-
injectPlacement
|
|
72
|
-
};
|
|
73
|
-
//#endregion
|
|
74
|
-
//#region src/hooks/useLightDomStyles.ts
|
|
75
|
-
function useLightDomStyles(tag, placementId, placementCss, baseCss) {
|
|
76
|
-
useEffect(() => {
|
|
77
|
-
styleManager.injectBase(tag, baseCss ?? lightDomBaseCss);
|
|
78
|
-
}, [tag]);
|
|
79
|
-
useEffect(() => {
|
|
80
|
-
if (!placementId || !placementCss) return;
|
|
81
|
-
styleManager.injectPlacement(tag, placementId, placementCss);
|
|
82
|
-
}, [
|
|
83
|
-
tag,
|
|
84
|
-
placementId,
|
|
85
|
-
placementCss
|
|
86
|
-
]);
|
|
87
|
-
}
|
|
88
|
-
//#endregion
|
|
89
|
-
export { useLightDomStyles as t };
|
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
import register from "preact-custom-element";
|
|
2
|
-
import * as coreSdkIndex from "@frak-labs/core-sdk";
|
|
3
|
-
import { sdkConfigStore, setupClient, trackEvent, withCache } from "@frak-labs/core-sdk";
|
|
4
|
-
import * as coreSdkActions from "@frak-labs/core-sdk/actions";
|
|
5
|
-
import { displayEmbeddedWallet } from "@frak-labs/core-sdk/actions";
|
|
6
|
-
import { useEffect, useMemo, useState } from "preact/hooks";
|
|
7
|
-
//#region src/utils/embeddedWallet.ts
|
|
8
|
-
async function openEmbeddedWallet(targetInteraction, placement) {
|
|
9
|
-
if (!window.FrakSetup?.client) {
|
|
10
|
-
console.error("Frak client not found");
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
const modalWalletConfig = window.FrakSetup?.modalWalletConfig ?? {};
|
|
14
|
-
await displayEmbeddedWallet(window.FrakSetup.client, targetInteraction ? {
|
|
15
|
-
...modalWalletConfig,
|
|
16
|
-
metadata: {
|
|
17
|
-
...modalWalletConfig.metadata,
|
|
18
|
-
targetInteraction
|
|
19
|
-
}
|
|
20
|
-
} : modalWalletConfig, placement);
|
|
21
|
-
}
|
|
22
|
-
//#endregion
|
|
23
|
-
//#region src/utils/safeVibrate.ts
|
|
24
|
-
/**
|
|
25
|
-
* Attempt to vibrate the device
|
|
26
|
-
*/
|
|
27
|
-
function safeVibrate() {
|
|
28
|
-
if ("vibrate" in navigator) navigator.vibrate(10);
|
|
29
|
-
else console.log("Vibration not supported");
|
|
30
|
-
}
|
|
31
|
-
//#endregion
|
|
32
|
-
//#region src/components/ButtonWallet/utils.ts
|
|
33
|
-
function openWalletModal(targetInteraction, placement) {
|
|
34
|
-
safeVibrate();
|
|
35
|
-
openEmbeddedWallet(targetInteraction, placement);
|
|
36
|
-
}
|
|
37
|
-
//#endregion
|
|
38
|
-
//#region src/utils/clientReady.ts
|
|
39
|
-
const CUSTOM_EVENT_NAME = "frak:client";
|
|
40
|
-
/**
|
|
41
|
-
* Dispatch a custom event when the Frak client is ready
|
|
42
|
-
*/
|
|
43
|
-
function dispatchClientReadyEvent() {
|
|
44
|
-
const event = new CustomEvent(CUSTOM_EVENT_NAME);
|
|
45
|
-
window.dispatchEvent(event);
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Add or remove an event listener for when the Frak client is ready
|
|
49
|
-
* @param action
|
|
50
|
-
* @param callback
|
|
51
|
-
*/
|
|
52
|
-
function onClientReady(action, callback) {
|
|
53
|
-
if (window.FrakSetup?.client && action === "add") {
|
|
54
|
-
callback();
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
(action === "add" ? window.addEventListener : window.removeEventListener)(CUSTOM_EVENT_NAME, callback, false);
|
|
58
|
-
}
|
|
59
|
-
//#endregion
|
|
60
|
-
//#region src/utils/initFrakSdk.ts
|
|
61
|
-
/**
|
|
62
|
-
* Initializes the Frak SDK client and sets up necessary configurations.
|
|
63
|
-
* Uses withCache for inflight dedup — concurrent callers share the same promise.
|
|
64
|
-
* Failures are not cached, allowing retry on next call.
|
|
65
|
-
*
|
|
66
|
-
* @returns {Promise<void>}
|
|
67
|
-
*/
|
|
68
|
-
function initFrakSdk() {
|
|
69
|
-
window.FrakSetup.core = {
|
|
70
|
-
...coreSdkIndex,
|
|
71
|
-
...coreSdkActions
|
|
72
|
-
};
|
|
73
|
-
if (window.FrakSetup?.client) return Promise.resolve();
|
|
74
|
-
return withCache(() => doInit(), {
|
|
75
|
-
cacheKey: "frak-sdk-init",
|
|
76
|
-
cacheTime: Number.POSITIVE_INFINITY
|
|
77
|
-
}).catch((err) => {
|
|
78
|
-
trackEvent(window.FrakSetup?.client, "sdk_init_failed", {
|
|
79
|
-
reason: err instanceof Error ? err.message : typeof err === "string" ? err : "unknown",
|
|
80
|
-
config_missing: !window.FrakSetup?.config
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Performs the actual SDK initialization.
|
|
86
|
-
* Throws on failure so withCache doesn't cache failed attempts.
|
|
87
|
-
*/
|
|
88
|
-
async function doInit() {
|
|
89
|
-
if (!window.FrakSetup?.config) throw new Error("[Frak SDK] Configuration not found. Please ensure window.FrakSetup.config is set.");
|
|
90
|
-
console.log("[Frak SDK] Starting initialization");
|
|
91
|
-
const client = await setupClient({ config: window.FrakSetup.config });
|
|
92
|
-
if (!client) throw new Error("[Frak SDK] Failed to create client");
|
|
93
|
-
window.FrakSetup.client = client;
|
|
94
|
-
console.log("[Frak SDK] Client initialized successfully");
|
|
95
|
-
dispatchClientReadyEvent();
|
|
96
|
-
coreSdkActions.setupReferral(client);
|
|
97
|
-
handleActionQueryParam();
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Check the query param contain params for an auto opening of the frak modal
|
|
101
|
-
*/
|
|
102
|
-
function handleActionQueryParam() {
|
|
103
|
-
const frakAction = new URLSearchParams(window.location.search).get("frakAction");
|
|
104
|
-
if (!frakAction) return;
|
|
105
|
-
if (frakAction === "share") {
|
|
106
|
-
console.log("[Frak SDK] Auto open query param found");
|
|
107
|
-
openWalletModal();
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
//#endregion
|
|
111
|
-
//#region src/utils/onDocumentReady.ts
|
|
112
|
-
/**
|
|
113
|
-
* When the document is ready, run the callback
|
|
114
|
-
* @param callback
|
|
115
|
-
*/
|
|
116
|
-
function onDocumentReady(callback) {
|
|
117
|
-
if (document.readyState === "complete" || document.readyState === "interactive") setTimeout(callback, 1);
|
|
118
|
-
else document.addEventListener("DOMContentLoaded", callback);
|
|
119
|
-
}
|
|
120
|
-
//#endregion
|
|
121
|
-
//#region src/utils/registerWebComponent.ts
|
|
122
|
-
/**
|
|
123
|
-
* Registers a Preact component as a custom web component
|
|
124
|
-
*
|
|
125
|
-
* @param component - The Preact component to register
|
|
126
|
-
* @param tagName - The custom element tag name (e.g., "frak-button-wallet")
|
|
127
|
-
* @param observedAttributes - Array of attribute names to observe for changes
|
|
128
|
-
* @param options - Registration options (e.g., { shadow: true })
|
|
129
|
-
*/
|
|
130
|
-
function registerWebComponent(component, tagName, observedAttributes = [], options = { shadow: true }) {
|
|
131
|
-
if (typeof window !== "undefined") {
|
|
132
|
-
onDocumentReady(initFrakSdk);
|
|
133
|
-
if (!customElements.get(tagName)) register(component, tagName, observedAttributes, options);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
//#endregion
|
|
137
|
-
//#region src/hooks/useClientReady.ts
|
|
138
|
-
function useClientReady() {
|
|
139
|
-
const [shouldRender, setShouldRender] = useState(() => {
|
|
140
|
-
if (!(window.FrakSetup?.config?.waitForBackendConfig !== false)) return true;
|
|
141
|
-
return sdkConfigStore.isResolved;
|
|
142
|
-
});
|
|
143
|
-
const [isHidden, setIsHidden] = useState(() => sdkConfigStore.getConfig().hidden ?? false);
|
|
144
|
-
const [isClientReady, setIsClientReady] = useState(() => !!window.FrakSetup?.client);
|
|
145
|
-
useEffect(() => {
|
|
146
|
-
const currentConfig = sdkConfigStore.getConfig();
|
|
147
|
-
if (currentConfig.isResolved) {
|
|
148
|
-
setShouldRender(true);
|
|
149
|
-
setIsHidden(currentConfig.hidden ?? false);
|
|
150
|
-
}
|
|
151
|
-
if (window.FrakSetup?.client) setIsClientReady(true);
|
|
152
|
-
const onConfig = (e) => {
|
|
153
|
-
const config = e.detail;
|
|
154
|
-
if (config.isResolved) setShouldRender(true);
|
|
155
|
-
setIsHidden(config.hidden ?? false);
|
|
156
|
-
};
|
|
157
|
-
window.addEventListener("frak:config", onConfig);
|
|
158
|
-
const handleReady = () => setIsClientReady(true);
|
|
159
|
-
onClientReady("add", handleReady);
|
|
160
|
-
return () => {
|
|
161
|
-
window.removeEventListener("frak:config", onConfig);
|
|
162
|
-
onClientReady("remove", handleReady);
|
|
163
|
-
};
|
|
164
|
-
}, []);
|
|
165
|
-
return {
|
|
166
|
-
shouldRender,
|
|
167
|
-
isHidden,
|
|
168
|
-
isClientReady
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
//#endregion
|
|
172
|
-
//#region src/utils/sharedCss.ts
|
|
173
|
-
const sharedCss = `
|
|
174
|
-
:host {
|
|
175
|
-
display: contents;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
:host([hidden]) {
|
|
179
|
-
display: none;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
.button:disabled {
|
|
183
|
-
opacity: 0.7;
|
|
184
|
-
cursor: default;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
.button__fadeIn {
|
|
188
|
-
animation: frak-fadeIn 300ms ease-in;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
@keyframes frak-fadeIn {
|
|
192
|
-
from {
|
|
193
|
-
opacity: 0;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
to {
|
|
197
|
-
opacity: 1;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
`;
|
|
201
|
-
function buildStyleContent(componentCss, placementCss) {
|
|
202
|
-
return placementCss ? `${sharedCss}\n${componentCss}\n${placementCss}` : `${sharedCss}\n${componentCss}`;
|
|
203
|
-
}
|
|
204
|
-
const lightDomBaseCss = `
|
|
205
|
-
:where(frak-button-share, frak-open-in-app) {
|
|
206
|
-
display: contents;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
:where(frak-button-share .button, frak-open-in-app .button) {
|
|
210
|
-
display: flex;
|
|
211
|
-
align-items: center;
|
|
212
|
-
justify-content: center;
|
|
213
|
-
gap: 10px;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
:where(frak-button-share .button:disabled, frak-open-in-app .button:disabled) {
|
|
217
|
-
opacity: 0.7;
|
|
218
|
-
cursor: default;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
:where(frak-button-share .button__fadeIn, frak-open-in-app .button__fadeIn) {
|
|
222
|
-
animation: frak-fadeIn 300ms ease-in;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
@keyframes frak-fadeIn {
|
|
226
|
-
from {
|
|
227
|
-
opacity: 0;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
to {
|
|
231
|
-
opacity: 1;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
`;
|
|
235
|
-
//#endregion
|
|
236
|
-
//#region src/hooks/usePlacement.ts
|
|
237
|
-
function getPlacement(id) {
|
|
238
|
-
return sdkConfigStore.getConfig().placements?.[id];
|
|
239
|
-
}
|
|
240
|
-
function usePlacement(placementId) {
|
|
241
|
-
const [configVersion, setConfigVersion] = useState(0);
|
|
242
|
-
useEffect(() => {
|
|
243
|
-
const onConfig = (_e) => {
|
|
244
|
-
setConfigVersion((v) => v + 1);
|
|
245
|
-
};
|
|
246
|
-
window.addEventListener("frak:config", onConfig);
|
|
247
|
-
setConfigVersion((v) => v + 1);
|
|
248
|
-
return () => window.removeEventListener("frak:config", onConfig);
|
|
249
|
-
}, []);
|
|
250
|
-
return useMemo(() => placementId ? getPlacement(placementId) : void 0, [placementId, configVersion]);
|
|
251
|
-
}
|
|
252
|
-
//#endregion
|
|
253
|
-
export { registerWebComponent as a, useClientReady as i, buildStyleContent as n, openWalletModal as o, lightDomBaseCss as r, openEmbeddedWallet as s, usePlacement as t };
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { n as formatEstimatedReward } from "./formatReward-Bub6Z6eY.js";
|
|
2
|
-
import { getCurrencyAmountKey, getSupportedCurrency } from "@frak-labs/core-sdk";
|
|
3
|
-
import { getMerchantInformation } from "@frak-labs/core-sdk/actions";
|
|
4
|
-
import { useEffect, useState } from "preact/hooks";
|
|
5
|
-
//#region src/hooks/useReward.ts
|
|
6
|
-
/**
|
|
7
|
-
* Get the comparable fiat value of a reward for ranking purposes.
|
|
8
|
-
*/
|
|
9
|
-
function getRewardValue(reward, key) {
|
|
10
|
-
switch (reward.payoutType) {
|
|
11
|
-
case "fixed": return reward.amount[key];
|
|
12
|
-
case "tiered": return reward.tiers.reduce((acc, tier) => Math.max(acc, tier.amount[key]), 0);
|
|
13
|
-
case "percentage": return 0;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Pick the best referrer reward from merchant info and format it.
|
|
18
|
-
* Returns `undefined` when no displayable reward is found.
|
|
19
|
-
*/
|
|
20
|
-
function resolveBestReward({ rewards }, currency, targetInteraction) {
|
|
21
|
-
const referrerRewards = (targetInteraction ? rewards.filter((r) => r.interactionTypeKey === targetInteraction) : rewards).map((r) => r.referrer).filter((r) => r !== void 0);
|
|
22
|
-
if (referrerRewards.length === 0) return void 0;
|
|
23
|
-
const key = getCurrencyAmountKey(getSupportedCurrency(currency));
|
|
24
|
-
let bestReward = referrerRewards[0];
|
|
25
|
-
let bestValue = getRewardValue(bestReward, key);
|
|
26
|
-
for (let i = 1; i < referrerRewards.length; i++) {
|
|
27
|
-
const value = getRewardValue(referrerRewards[i], key);
|
|
28
|
-
if (value > bestValue) {
|
|
29
|
-
bestReward = referrerRewards[i];
|
|
30
|
-
bestValue = value;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
if (bestValue <= 0) {
|
|
34
|
-
const percentageReward = referrerRewards.find((r) => r.payoutType === "percentage");
|
|
35
|
-
if (!percentageReward) return void 0;
|
|
36
|
-
bestReward = percentageReward;
|
|
37
|
-
}
|
|
38
|
-
return formatEstimatedReward(bestReward, currency);
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Hook to fetch and format the best referrer reward for a given interaction type.
|
|
42
|
-
*
|
|
43
|
-
* Calls `getMerchantInformation`, picks the highest-value referrer reward
|
|
44
|
-
* across all matching campaigns, and returns it as a formatted string.
|
|
45
|
-
*
|
|
46
|
-
* @param shouldUseReward - Whether to fetch the reward at all
|
|
47
|
-
* @param targetInteraction - Optional filter by interaction type (e.g. "purchase")
|
|
48
|
-
* @returns Object containing the formatted reward string, or undefined if unavailable
|
|
49
|
-
*/
|
|
50
|
-
function useReward(shouldUseReward, targetInteraction) {
|
|
51
|
-
const [reward, setReward] = useState(void 0);
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
if (!shouldUseReward) return;
|
|
54
|
-
const client = window.FrakSetup?.client;
|
|
55
|
-
if (!client) return;
|
|
56
|
-
getMerchantInformation(client).then((merchantInfo) => {
|
|
57
|
-
const currency = client.config.metadata?.currency;
|
|
58
|
-
const formatted = resolveBestReward(merchantInfo, currency, targetInteraction);
|
|
59
|
-
if (formatted) setReward(formatted);
|
|
60
|
-
}).catch(() => {});
|
|
61
|
-
}, [shouldUseReward, targetInteraction]);
|
|
62
|
-
return { reward };
|
|
63
|
-
}
|
|
64
|
-
//#endregion
|
|
65
|
-
export { useReward as t };
|