@frak-labs/components 0.0.23 → 0.0.24-beta.d13d0e5d
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/cdn/ButtonShare.KQ-V4O87.js +1 -0
- package/cdn/ButtonWallet.DmfyOd9N.js +1 -0
- package/cdn/OpenInAppButton.tACYgBah.js +1 -0
- package/cdn/Spinner.Did0mr0l.js +1 -0
- package/cdn/components.js +1 -1
- package/cdn/initFrakSdk.qhnp614c.js +14 -0
- package/cdn/loader.css +14 -0
- package/cdn/loader.js +1 -32
- package/cdn/useClientReady.C-ACrktG.js +1 -0
- package/dist/Spinner-CHZD3tMn.css +1 -0
- package/dist/Spinner-J7chVm6X.js +36 -0
- package/dist/buttonShare.css +1 -1
- package/dist/buttonShare.d.ts +99 -85
- package/dist/buttonShare.js +311 -1
- package/dist/buttonWallet.css +1 -1
- package/dist/buttonWallet.d.ts +75 -64
- package/dist/buttonWallet.js +109 -1
- package/dist/openInApp.css +1 -0
- package/dist/openInApp.d.ts +56 -0
- package/dist/openInApp.js +110 -0
- package/dist/useClientReady-iCtUeDsc.js +197 -0
- package/dist/useReward-DAkT-7wT.js +48 -0
- package/package.json +50 -16
- package/cdn/564.74bbd23d.js +0 -1
- package/cdn/button-share.4d8a18a0.js +0 -1
- package/cdn/button-share.823884d0.css +0 -1
- package/cdn/button-wallet.0a2b7d12.js +0 -1
- package/cdn/button-wallet.390d543a.css +0 -1
- package/cdn/loader.js.LICENSE.txt +0 -1
package/dist/buttonWallet.js
CHANGED
|
@@ -1 +1,109 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { i as openWalletModal, n as registerWebComponent, t as useClientReady } from "./useClientReady-iCtUeDsc.js";
|
|
2
|
+
import { t as useReward } from "./useReward-DAkT-7wT.js";
|
|
3
|
+
import { trackEvent } from "@frak-labs/core-sdk";
|
|
4
|
+
import { cx } from "class-variance-authority";
|
|
5
|
+
import { useEffect, useMemo, useState } from "preact/hooks";
|
|
6
|
+
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
7
|
+
|
|
8
|
+
//#region src/components/ButtonWallet/assets/GiftIcon.tsx
|
|
9
|
+
function GiftIcon(props) {
|
|
10
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
11
|
+
fill: "none",
|
|
12
|
+
height: "1em",
|
|
13
|
+
viewBox: "0 0 28 28",
|
|
14
|
+
width: "1em",
|
|
15
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
16
|
+
...props,
|
|
17
|
+
children: [/* @__PURE__ */ jsx("title", { children: "Gift icon" }), /* @__PURE__ */ jsx("path", {
|
|
18
|
+
d: "m23.1427 13.9999v11.4285h-18.2857v-11.4285m9.1429 11.4285v-17.14282m0 0h-5.1429c-.75776 0-1.48448-.30102-2.0203-.83684s-.83684-1.26255-.83684-2.02031.30102-1.48448.83684-2.0203 1.26254-.83684 2.0203-.83684c4 0 5.1429 5.71429 5.1429 5.71429zm0 0h5.1428c.7578 0 1.4845-.30102 2.0203-.83684s.8369-1.26255.8369-2.02031-.3011-1.48448-.8369-2.0203-1.2625-.83684-2.0203-.83684c-4 0-5.1428 5.71429-5.1428 5.71429zm-11.42861 0h22.85711v5.71432h-22.85711z",
|
|
19
|
+
stroke: "#fff",
|
|
20
|
+
"stroke-linecap": "round",
|
|
21
|
+
"stroke-linejoin": "round"
|
|
22
|
+
})]
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/components/ButtonWallet/ButtonWallet.module.css?css_module
|
|
28
|
+
const classes = {
|
|
29
|
+
"button__right": "Kl62ia_button__right",
|
|
30
|
+
"button__left": "Kl62ia_button__left",
|
|
31
|
+
"button": "Kl62ia_button",
|
|
32
|
+
"reward": "Kl62ia_reward"
|
|
33
|
+
};
|
|
34
|
+
const _button__right0 = classes["button__right"];
|
|
35
|
+
const _button__left0 = classes["button__left"];
|
|
36
|
+
const _button0 = classes["button"];
|
|
37
|
+
const _reward0 = classes["reward"];
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/components/ButtonWallet/ButtonWallet.tsx
|
|
41
|
+
/**
|
|
42
|
+
* Button to open wallet modal
|
|
43
|
+
*
|
|
44
|
+
* @param args
|
|
45
|
+
* @returns The wallet button with `<button>` tag
|
|
46
|
+
*
|
|
47
|
+
* @group components
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* Basic usage:
|
|
51
|
+
* ```html
|
|
52
|
+
* <frak-button-wallet></frak-button-wallet>
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* Using a custom class:
|
|
57
|
+
* ```html
|
|
58
|
+
* <frak-button-wallet classname="button button-primary"></frak-button-wallet>
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* Using reward information:
|
|
63
|
+
* ```html
|
|
64
|
+
* <frak-button-wallet use-reward></frak-button-wallet>
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* Using reward information for specific reward:
|
|
69
|
+
* ```html
|
|
70
|
+
* <frak-button-wallet use-reward target-interaction="custom.customerMeeting"></frak-button-wallet>
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @see {@link @frak-labs/core-sdk!actions.modalBuilder | `modalBuilder()`} for more info about the modal display
|
|
74
|
+
* @see {@link @frak-labs/core-sdk!actions.getProductInformation | `getProductInformation()`} for more info about the estimated reward fetching
|
|
75
|
+
*/
|
|
76
|
+
function ButtonWallet({ classname = "", useReward: rawUseReward, targetInteraction }) {
|
|
77
|
+
const shouldUseReward = useMemo(() => rawUseReward !== void 0, [rawUseReward]);
|
|
78
|
+
const { isClientReady } = useClientReady();
|
|
79
|
+
const { reward } = useReward(shouldUseReward && isClientReady, targetInteraction);
|
|
80
|
+
const [position, setPosition] = useState("right");
|
|
81
|
+
/**
|
|
82
|
+
* Setup the position of the button
|
|
83
|
+
*/
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
const position = window.FrakSetup?.modalWalletConfig?.metadata?.position;
|
|
86
|
+
setPosition(position ?? "right");
|
|
87
|
+
}, []);
|
|
88
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
89
|
+
type: "button",
|
|
90
|
+
"aria-label": "Open wallet",
|
|
91
|
+
class: cx(classes.button, position === "left" ? classes.button__left : classes.button__right, classname, "override"),
|
|
92
|
+
disabled: !isClientReady,
|
|
93
|
+
onClick: () => {
|
|
94
|
+
trackEvent(window.FrakSetup.client, "wallet_button_clicked");
|
|
95
|
+
openWalletModal();
|
|
96
|
+
},
|
|
97
|
+
children: [/* @__PURE__ */ jsx(GiftIcon, {}), reward && /* @__PURE__ */ jsx("span", {
|
|
98
|
+
className: classes.reward,
|
|
99
|
+
children: reward
|
|
100
|
+
})]
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/components/ButtonWallet/index.ts
|
|
106
|
+
registerWebComponent(ButtonWallet, "frak-button-wallet", [], { shadow: false });
|
|
107
|
+
|
|
108
|
+
//#endregion
|
|
109
|
+
export { ButtonWallet };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.XYfqGq_button{justify-content:center;align-items:center;gap:10px;display:flex}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as preact from "preact";
|
|
2
|
+
|
|
3
|
+
//#region src/components/OpenInAppButton/types.d.ts
|
|
4
|
+
type OpenInAppButtonProps = {
|
|
5
|
+
/**
|
|
6
|
+
* Text to display on the button
|
|
7
|
+
* @defaultValue `"Open in App"`
|
|
8
|
+
*/
|
|
9
|
+
text?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Classname to apply to the button
|
|
12
|
+
*/
|
|
13
|
+
classname?: string;
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/components/OpenInAppButton/OpenInAppButton.d.ts
|
|
17
|
+
/**
|
|
18
|
+
* Button to open the Frak Wallet mobile app via deep link
|
|
19
|
+
*
|
|
20
|
+
* @param args
|
|
21
|
+
* @returns The open in app button with `<button>` tag (only renders on mobile devices)
|
|
22
|
+
*
|
|
23
|
+
* @group components
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* Basic usage:
|
|
27
|
+
* ```html
|
|
28
|
+
* <frak-open-in-app></frak-open-in-app>
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* Using a custom text:
|
|
33
|
+
* ```html
|
|
34
|
+
* <frak-open-in-app text="Get the App"></frak-open-in-app>
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* With login action:
|
|
39
|
+
* ```html
|
|
40
|
+
* <frak-open-in-app classname="button button-primary"></frak-open-in-app>
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
declare function OpenInAppButton({
|
|
44
|
+
text,
|
|
45
|
+
classname
|
|
46
|
+
}: OpenInAppButtonProps): preact.JSX.Element | null;
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/components/OpenInAppButton/index.d.ts
|
|
49
|
+
interface OpenInAppButtonElement extends HTMLElement, OpenInAppButtonProps {}
|
|
50
|
+
declare global {
|
|
51
|
+
interface HTMLElementTagNameMap {
|
|
52
|
+
"frak-open-in-app": OpenInAppButtonElement;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { OpenInAppButton, OpenInAppButtonElement };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { n as registerWebComponent, t as useClientReady } from "./useClientReady-iCtUeDsc.js";
|
|
2
|
+
import { t as Spinner } from "./Spinner-J7chVm6X.js";
|
|
3
|
+
import { DEEP_LINK_SCHEME, trackEvent, triggerDeepLinkWithFallback } from "@frak-labs/core-sdk";
|
|
4
|
+
import { cx } from "class-variance-authority";
|
|
5
|
+
import { useMemo } from "preact/hooks";
|
|
6
|
+
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
7
|
+
|
|
8
|
+
//#region src/utils/isMobile.ts
|
|
9
|
+
/**
|
|
10
|
+
* Check if the current device is a mobile device
|
|
11
|
+
* Uses UA regex + iPad desktop mode heuristic (maxTouchPoints)
|
|
12
|
+
*
|
|
13
|
+
* iPadOS 13+ sends a Macintosh UA in desktop mode, so the regex alone
|
|
14
|
+
* misses it. The maxTouchPoints check catches iPads reporting as Mac.
|
|
15
|
+
*
|
|
16
|
+
* @returns True if the device is mobile (iOS, Android, iPadOS, etc.)
|
|
17
|
+
*/
|
|
18
|
+
function isMobile() {
|
|
19
|
+
if (typeof navigator === "undefined") return false;
|
|
20
|
+
if (/iPhone|iPad|iPod|Android|webOS|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) return true;
|
|
21
|
+
if (/Macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints > 1) return true;
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/hooks/useIsMobile.ts
|
|
27
|
+
function useIsMobile() {
|
|
28
|
+
return { isMobile: useMemo(() => isMobile(), []) };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/utils/openInApp.ts
|
|
33
|
+
const DEFAULT_PATH = "wallet";
|
|
34
|
+
/**
|
|
35
|
+
* Open the Frak Wallet mobile app via deep link with fallback detection.
|
|
36
|
+
*
|
|
37
|
+
* Uses visibility-based detection to determine if the app opened.
|
|
38
|
+
* If the app is not installed (page stays visible after 2.5s),
|
|
39
|
+
* tracks an "app_not_installed" event.
|
|
40
|
+
*
|
|
41
|
+
* @param path - Path to open in the app (default: "wallet")
|
|
42
|
+
*/
|
|
43
|
+
function openFrakWalletApp(path = DEFAULT_PATH) {
|
|
44
|
+
const client = window.FrakSetup?.client;
|
|
45
|
+
if (client) trackEvent(client, "open_in_app_clicked");
|
|
46
|
+
triggerDeepLinkWithFallback(`${DEEP_LINK_SCHEME}${path}`, { onFallback: () => {
|
|
47
|
+
if (client) trackEvent(client, "app_not_installed");
|
|
48
|
+
} });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/components/OpenInAppButton/OpenInAppButton.module.css?css_module
|
|
53
|
+
const classes = { "button": "XYfqGq_button" };
|
|
54
|
+
const _button0 = classes["button"];
|
|
55
|
+
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region src/components/OpenInAppButton/OpenInAppButton.tsx
|
|
58
|
+
/**
|
|
59
|
+
* Button to open the Frak Wallet mobile app via deep link
|
|
60
|
+
*
|
|
61
|
+
* @param args
|
|
62
|
+
* @returns The open in app button with `<button>` tag (only renders on mobile devices)
|
|
63
|
+
*
|
|
64
|
+
* @group components
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* Basic usage:
|
|
68
|
+
* ```html
|
|
69
|
+
* <frak-open-in-app></frak-open-in-app>
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* Using a custom text:
|
|
74
|
+
* ```html
|
|
75
|
+
* <frak-open-in-app text="Get the App"></frak-open-in-app>
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* With login action:
|
|
80
|
+
* ```html
|
|
81
|
+
* <frak-open-in-app classname="button button-primary"></frak-open-in-app>
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
function OpenInAppButton({ text = "Open in App", classname = "" }) {
|
|
85
|
+
const { isClientReady } = useClientReady();
|
|
86
|
+
const { isMobile } = useIsMobile();
|
|
87
|
+
if (!isMobile) return null;
|
|
88
|
+
const handleClick = () => {
|
|
89
|
+
openFrakWalletApp();
|
|
90
|
+
};
|
|
91
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
92
|
+
type: "button",
|
|
93
|
+
"aria-label": "Open in Frak Wallet app",
|
|
94
|
+
className: cx(classes.button, classname, "override"),
|
|
95
|
+
disabled: !isClientReady,
|
|
96
|
+
onClick: handleClick,
|
|
97
|
+
children: [
|
|
98
|
+
!isClientReady && /* @__PURE__ */ jsx(Spinner, {}),
|
|
99
|
+
" ",
|
|
100
|
+
text
|
|
101
|
+
]
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region src/components/OpenInAppButton/index.ts
|
|
107
|
+
registerWebComponent(OpenInAppButton, "frak-open-in-app", ["text"], { shadow: false });
|
|
108
|
+
|
|
109
|
+
//#endregion
|
|
110
|
+
export { OpenInAppButton };
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import register from "preact-custom-element";
|
|
2
|
+
import { setupClient } from "@frak-labs/core-sdk";
|
|
3
|
+
import * as coreSdk from "@frak-labs/core-sdk/bundle";
|
|
4
|
+
import { displayEmbeddedWallet, modalBuilder, referralInteraction } from "@frak-labs/core-sdk/actions";
|
|
5
|
+
import { useCallback, useEffect, useState } from "preact/hooks";
|
|
6
|
+
|
|
7
|
+
//#region ../../packages/ui/utils/onDocumentReady.ts
|
|
8
|
+
/**
|
|
9
|
+
* When the document is ready, run the callback
|
|
10
|
+
* @param callback
|
|
11
|
+
*/
|
|
12
|
+
function onDocumentReady(callback) {
|
|
13
|
+
if (document.readyState === "complete" || document.readyState === "interactive") setTimeout(callback, 1);
|
|
14
|
+
else if (document.addEventListener) document.addEventListener("DOMContentLoaded", callback);
|
|
15
|
+
else document.attachEvent("onreadystatechange", () => {
|
|
16
|
+
if (document.readyState === "complete") callback();
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/utils/safeVibrate.ts
|
|
22
|
+
/**
|
|
23
|
+
* Attempt to vibrate the device
|
|
24
|
+
*/
|
|
25
|
+
function safeVibrate() {
|
|
26
|
+
if ("vibrate" in navigator) navigator.vibrate(10);
|
|
27
|
+
else console.log("Vibration not supported");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/components/ButtonWallet/utils.ts
|
|
32
|
+
/**
|
|
33
|
+
* Open the wallet modal
|
|
34
|
+
*
|
|
35
|
+
* @description
|
|
36
|
+
* This function will open the wallet modal with the configuration provided in the `window.FrakSetup.modalWalletConfig` object.
|
|
37
|
+
*/
|
|
38
|
+
function openWalletModal() {
|
|
39
|
+
if (!window.FrakSetup?.client) {
|
|
40
|
+
console.error("Frak client not found");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
safeVibrate();
|
|
44
|
+
displayEmbeddedWallet(window.FrakSetup.client, window.FrakSetup?.modalWalletConfig ?? {});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/utils/clientReady.ts
|
|
49
|
+
const CUSTOM_EVENT_NAME = "frakClientReady";
|
|
50
|
+
/**
|
|
51
|
+
* Dispatch a custom event when the Frak client is ready
|
|
52
|
+
*/
|
|
53
|
+
function dispatchClientReadyEvent() {
|
|
54
|
+
const event = new CustomEvent(CUSTOM_EVENT_NAME);
|
|
55
|
+
window.dispatchEvent(event);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Add or remove an event listener for when the Frak client is ready
|
|
59
|
+
* @param action
|
|
60
|
+
* @param callback
|
|
61
|
+
*/
|
|
62
|
+
function onClientReady(action, callback) {
|
|
63
|
+
if (window.FrakSetup?.client && action === "add") {
|
|
64
|
+
callback();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
(action === "add" ? window.addEventListener : window.removeEventListener)(CUSTOM_EVENT_NAME, callback, false);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/utils/setup.ts
|
|
72
|
+
/**
|
|
73
|
+
* Setup the modal config
|
|
74
|
+
* @param client
|
|
75
|
+
*/
|
|
76
|
+
function setupModalConfig(client) {
|
|
77
|
+
window.modalBuilderSteps = modalBuilder(client, window.FrakSetup?.modalConfig ?? {});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Setup the referral
|
|
81
|
+
* @param client
|
|
82
|
+
*/
|
|
83
|
+
async function setupReferral(client) {
|
|
84
|
+
const referral = await referralInteraction(client, { modalConfig: window.FrakSetup?.modalWalletConfig });
|
|
85
|
+
console.log("referral", referral);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Return the modal builder steps
|
|
89
|
+
*/
|
|
90
|
+
function getModalBuilderSteps() {
|
|
91
|
+
if (!window.modalBuilderSteps) throw new Error("modalBuilderSteps not found");
|
|
92
|
+
return window.modalBuilderSteps;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/utils/initFrakSdk.ts
|
|
97
|
+
/**
|
|
98
|
+
* Initializes the Frak SDK client and sets up necessary configurations.
|
|
99
|
+
* This function handles the one-time setup of the Frak client and related features.
|
|
100
|
+
*
|
|
101
|
+
* @returns {Promise<void>}
|
|
102
|
+
*/
|
|
103
|
+
async function initFrakSdk() {
|
|
104
|
+
window.FrakSetup.core = coreSdk;
|
|
105
|
+
if (!preChecks()) return;
|
|
106
|
+
console.log("[Frak SDK] Starting initialization");
|
|
107
|
+
if (!window.FrakSetup.config) {
|
|
108
|
+
console.error("[Frak SDK] Configuration not found");
|
|
109
|
+
window.frakSetupInProgress = false;
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const client = await setupClient({ config: window.FrakSetup.config });
|
|
113
|
+
if (!client) {
|
|
114
|
+
console.error("[Frak SDK] Failed to create client");
|
|
115
|
+
window.frakSetupInProgress = false;
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
window.FrakSetup.client = client;
|
|
119
|
+
console.log("[Frak SDK] Client initialized successfully");
|
|
120
|
+
dispatchClientReadyEvent();
|
|
121
|
+
setupModalConfig(client);
|
|
122
|
+
setupReferral(client);
|
|
123
|
+
window.frakSetupInProgress = false;
|
|
124
|
+
handleActionQueryParam();
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Pre-checks for the Frak SDK initialization
|
|
128
|
+
* Sets frakSetupInProgress flag atomically to prevent race conditions
|
|
129
|
+
*/
|
|
130
|
+
function preChecks() {
|
|
131
|
+
if (window.frakSetupInProgress) {
|
|
132
|
+
console.log("[Frak SDK] Initialization already in progress");
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
window.frakSetupInProgress = true;
|
|
136
|
+
if (window.FrakSetup?.client) {
|
|
137
|
+
console.log("[Frak SDK] Client already initialized");
|
|
138
|
+
window.frakSetupInProgress = false;
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
if (!window.FrakSetup?.config) {
|
|
142
|
+
console.error("[Frak SDK] Configuration not found. Please ensure window.FrakSetup.config is set.");
|
|
143
|
+
window.frakSetupInProgress = false;
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Check the query param contain params for an auto opening of the frak modal
|
|
150
|
+
*/
|
|
151
|
+
function handleActionQueryParam() {
|
|
152
|
+
const frakAction = new URLSearchParams(window.location.search).get("frakAction");
|
|
153
|
+
if (!frakAction) return;
|
|
154
|
+
if (frakAction === "share") {
|
|
155
|
+
console.log("[Frak SDK] Auto open query param found");
|
|
156
|
+
openWalletModal();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region src/utils/registerWebComponent.ts
|
|
162
|
+
/**
|
|
163
|
+
* Registers a Preact component as a custom web component
|
|
164
|
+
*
|
|
165
|
+
* @param component - The Preact component to register
|
|
166
|
+
* @param tagName - The custom element tag name (e.g., "frak-button-wallet")
|
|
167
|
+
* @param observedAttributes - Array of attribute names to observe for changes
|
|
168
|
+
* @param options - Registration options (e.g., { shadow: false })
|
|
169
|
+
*/
|
|
170
|
+
function registerWebComponent(component, tagName, observedAttributes = [], options = { shadow: false }) {
|
|
171
|
+
if (typeof window !== "undefined") {
|
|
172
|
+
onDocumentReady(initFrakSdk);
|
|
173
|
+
if (!customElements.get(tagName)) register(component, tagName, observedAttributes, options);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
//#endregion
|
|
178
|
+
//#region src/hooks/useClientReady.ts
|
|
179
|
+
/**
|
|
180
|
+
* Hook to manage client readiness state for the wallet button
|
|
181
|
+
* Handles subscription to client ready events and manages readiness state
|
|
182
|
+
* @returns Object containing the readiness state of the client
|
|
183
|
+
*/
|
|
184
|
+
function useClientReady() {
|
|
185
|
+
const [disabled, setDisabled] = useState(true);
|
|
186
|
+
const handleClientReady = useCallback(() => {
|
|
187
|
+
setDisabled(false);
|
|
188
|
+
}, []);
|
|
189
|
+
useEffect(() => {
|
|
190
|
+
onClientReady("add", handleClientReady);
|
|
191
|
+
return () => onClientReady("remove", handleClientReady);
|
|
192
|
+
}, [handleClientReady]);
|
|
193
|
+
return { isClientReady: !disabled };
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
//#endregion
|
|
197
|
+
export { openWalletModal as i, registerWebComponent as n, getModalBuilderSteps as r, useClientReady as t };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { formatAmount, getCurrencyAmountKey } from "@frak-labs/core-sdk";
|
|
2
|
+
import { getMerchantInformation } from "@frak-labs/core-sdk/actions";
|
|
3
|
+
import { useEffect, useState } from "preact/hooks";
|
|
4
|
+
|
|
5
|
+
//#region src/utils/getCurrentReward.ts
|
|
6
|
+
function getFixedFiatAmount(estimated, key) {
|
|
7
|
+
if (!estimated || estimated.payoutType !== "fixed") return 0;
|
|
8
|
+
return estimated.amount[key];
|
|
9
|
+
}
|
|
10
|
+
function getMaxFixedReferrerReward(rewards, key) {
|
|
11
|
+
return rewards.reduce((max, reward) => Math.max(max, getFixedFiatAmount(reward.referrer, key)), 0);
|
|
12
|
+
}
|
|
13
|
+
async function getCurrentReward({ targetInteraction }) {
|
|
14
|
+
const client = window.FrakSetup?.client;
|
|
15
|
+
if (!client) {
|
|
16
|
+
console.warn("Frak client not ready yet");
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const { rewards } = await getMerchantInformation(client);
|
|
20
|
+
const currencyAmountKey = getCurrencyAmountKey(client.config.metadata?.currency);
|
|
21
|
+
const maxReward = getMaxFixedReferrerReward(targetInteraction ? rewards.filter((r) => r.interactionTypeKey === targetInteraction) : rewards, currencyAmountKey);
|
|
22
|
+
if (maxReward <= 0) return;
|
|
23
|
+
return formatAmount(Math.round(maxReward), client.config.metadata?.currency);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/hooks/useReward.ts
|
|
28
|
+
/**
|
|
29
|
+
* Hook to fetch and format the current reward value for a given interaction
|
|
30
|
+
* @param shouldUseReward - Flag to determine if reward should be fetched
|
|
31
|
+
* @param targetInteraction - Optional interaction type to get specific reward for
|
|
32
|
+
* @param currency - The currency to use for the reward (default is "eur")
|
|
33
|
+
* @returns Object containing the formatted reward value in euros
|
|
34
|
+
*/
|
|
35
|
+
function useReward(shouldUseReward, targetInteraction) {
|
|
36
|
+
const [reward, setReward] = useState(void 0);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!shouldUseReward) return;
|
|
39
|
+
getCurrentReward({ targetInteraction }).then((reward) => {
|
|
40
|
+
if (!reward) return;
|
|
41
|
+
setReward(reward);
|
|
42
|
+
});
|
|
43
|
+
}, [shouldUseReward, targetInteraction]);
|
|
44
|
+
return { reward };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
export { useReward as t };
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"url": "https://twitter.com/QNivelais"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
14
|
-
"version": "0.0.
|
|
14
|
+
"version": "0.0.24-beta.d13d0e5d",
|
|
15
15
|
"description": "Frak Wallet components, helping any person to interact with the Frak wallet.",
|
|
16
16
|
"repository": {
|
|
17
17
|
"url": "https://github.com/frak-id/wallet",
|
|
@@ -40,34 +40,68 @@
|
|
|
40
40
|
],
|
|
41
41
|
"main": "./cdn/components.js",
|
|
42
42
|
"browser": "./cdn/components.js",
|
|
43
|
+
"exports": {
|
|
44
|
+
"./buttonWallet": {
|
|
45
|
+
"development": "./src/components/ButtonWallet/index.ts",
|
|
46
|
+
"import": "./dist/buttonWallet.js",
|
|
47
|
+
"types": "./dist/buttonWallet.d.ts"
|
|
48
|
+
},
|
|
49
|
+
"./buttonShare": {
|
|
50
|
+
"development": "./src/components/ButtonShare/index.ts",
|
|
51
|
+
"import": "./dist/buttonShare.js",
|
|
52
|
+
"types": "./dist/buttonShare.d.ts"
|
|
53
|
+
},
|
|
54
|
+
"./openInApp": {
|
|
55
|
+
"development": "./src/components/OpenInAppButton/index.ts",
|
|
56
|
+
"import": "./dist/openInApp.js",
|
|
57
|
+
"types": "./dist/openInApp.d.ts"
|
|
58
|
+
},
|
|
59
|
+
"./cdn": {
|
|
60
|
+
"import": "./cdn/components.js"
|
|
61
|
+
},
|
|
62
|
+
"./dist/*": "./dist/*"
|
|
63
|
+
},
|
|
43
64
|
"scripts": {
|
|
44
65
|
"lint": "biome lint .",
|
|
45
66
|
"format:check": "biome check .",
|
|
46
67
|
"format": "biome check --write .",
|
|
47
68
|
"clean": "rimraf cdn dist",
|
|
48
|
-
"build": "
|
|
49
|
-
"build:watch": "
|
|
69
|
+
"build": "tsdown",
|
|
70
|
+
"build:watch": "tsdown --watch",
|
|
50
71
|
"typecheck": "tsc --noEmit",
|
|
72
|
+
"test": "vitest",
|
|
73
|
+
"test:ui": "vitest --ui",
|
|
74
|
+
"test:coverage": "vitest --coverage",
|
|
51
75
|
"prepublish": "bun run lint && bun run build",
|
|
52
76
|
"publish": "echo 'Publishing components...'"
|
|
53
77
|
},
|
|
54
78
|
"dependencies": {
|
|
55
|
-
"@frak-labs/frame-connector": "0.1.0",
|
|
56
|
-
"@frak-labs/core-sdk": "0.1.
|
|
79
|
+
"@frak-labs/frame-connector": "0.1.0-beta.d13d0e5d",
|
|
80
|
+
"@frak-labs/core-sdk": "0.1.1-beta.d13d0e5d",
|
|
57
81
|
"class-variance-authority": "^0.7.1",
|
|
58
|
-
"preact": "^10.
|
|
59
|
-
"preact-custom-element": "^4.
|
|
82
|
+
"preact": "^10.28.3",
|
|
83
|
+
"preact-custom-element": "^4.6.0"
|
|
60
84
|
},
|
|
61
85
|
"devDependencies": {
|
|
62
|
-
"@
|
|
63
|
-
"@
|
|
64
|
-
"@
|
|
65
|
-
"@
|
|
86
|
+
"@bosh-code/tsdown-plugin-inject-css": "^2.0.0",
|
|
87
|
+
"@frak-labs/dev-tooling": "0.0.0",
|
|
88
|
+
"@frak-labs/test-foundation": "0.1.0",
|
|
89
|
+
"@frak-labs/ui": "0.0.0",
|
|
90
|
+
"@preact/preset-vite": "^2.10.3",
|
|
91
|
+
"@rolldown/plugin-node-polyfills": "^1.0.3",
|
|
92
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
93
|
+
"@testing-library/preact": "^3.2.4",
|
|
94
|
+
"@testing-library/user-event": "^14.6.1",
|
|
95
|
+
"@types/jsdom": "^27.0.0",
|
|
96
|
+
"@types/node": "^24.10.13",
|
|
66
97
|
"@types/preact-custom-element": "^4.0.4",
|
|
98
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
99
|
+
"@vitest/ui": "^4.0.18",
|
|
100
|
+
"jsdom": "^28.0.0",
|
|
101
|
+
"tsdown": "^0.20.3",
|
|
67
102
|
"typescript": "^5",
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
]
|
|
103
|
+
"unplugin-lightningcss": "^0.4.5",
|
|
104
|
+
"vite-tsconfig-paths": "^6.1.0",
|
|
105
|
+
"vitest": "^4.0.18"
|
|
106
|
+
}
|
|
73
107
|
}
|