@frak-labs/components 0.0.26-beta.b38eef2e → 0.0.26-beta.d04602ec

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.
Files changed (42) hide show
  1. package/cdn/Banner.BfkMel9Q.js +1 -0
  2. package/cdn/ButtonShare.BM9Inhmf.js +1 -0
  3. package/cdn/ButtonWallet.B7UmJcbb.js +40 -0
  4. package/cdn/OpenInAppButton.B4mrsz6L.js +1 -0
  5. package/cdn/PostPurchase.BIc0C4Ma.js +1 -0
  6. package/cdn/components.js +1 -1
  7. package/cdn/formatReward.C8hlSKRj.js +1 -0
  8. package/cdn/jsxRuntime.module.5UNmmhNi.js +138 -0
  9. package/cdn/loader.css +0 -14
  10. package/cdn/loader.js +66 -1
  11. package/cdn/useLightDomStyles.D895e4W1.js +1 -0
  12. package/cdn/useReward.DEU0AF3P.js +1 -0
  13. package/cdn/useShareModal.CN9_P7Sl.js +1 -0
  14. package/dist/banner.d.ts +103 -0
  15. package/dist/banner.js +187 -0
  16. package/dist/buttonShare.d.ts +7 -5
  17. package/dist/buttonShare.js +59 -94
  18. package/dist/buttonWallet.d.ts +9 -1
  19. package/dist/buttonWallet.js +78 -33
  20. package/dist/formatReward-6JQldDEC.js +28 -0
  21. package/dist/openInApp.d.ts +2 -0
  22. package/dist/openInApp.js +22 -20
  23. package/dist/postPurchase.d.ts +116 -0
  24. package/dist/postPurchase.js +146 -0
  25. package/dist/useLightDomStyles-DukxuNnJ.js +44 -0
  26. package/dist/usePlacement-BbMuz8_A.js +340 -0
  27. package/dist/useReward-CI2yRrCj.js +67 -0
  28. package/dist/useShareModal-DHlayNqk.js +55 -0
  29. package/package.json +21 -15
  30. package/cdn/ButtonShare.CSPl5Bi5.js +0 -1
  31. package/cdn/ButtonWallet.3Hp62hGr.js +0 -1
  32. package/cdn/OpenInAppButton.BTvukMkp.js +0 -1
  33. package/cdn/Spinner.DQogVqic.js +0 -1
  34. package/cdn/initFrakSdk.CMgrZQwQ.js +0 -14
  35. package/cdn/useClientReady.CKKC4IMk.js +0 -1
  36. package/dist/Spinner-Btnwk01x.js +0 -36
  37. package/dist/Spinner-CHZD3tMn.css +0 -1
  38. package/dist/buttonShare.css +0 -1
  39. package/dist/buttonWallet.css +0 -1
  40. package/dist/openInApp.css +0 -1
  41. package/dist/useClientReady-0vKBG0-p.js +0 -197
  42. package/dist/useReward-DAkT-7wT.js +0 -48
@@ -0,0 +1,340 @@
1
+ import register from "preact-custom-element";
2
+ import * as coreSdkIndex from "@frak-labs/core-sdk";
3
+ import { sdkConfigStore, setupClient, 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
+
8
+ //#region src/utils/embeddedWallet.ts
9
+ async function openEmbeddedWallet(targetInteraction, placement) {
10
+ if (!window.FrakSetup?.client) {
11
+ console.error("Frak client not found");
12
+ return;
13
+ }
14
+ const modalWalletConfig = window.FrakSetup?.modalWalletConfig ?? {};
15
+ await displayEmbeddedWallet(window.FrakSetup.client, targetInteraction ? {
16
+ ...modalWalletConfig,
17
+ metadata: {
18
+ ...modalWalletConfig.metadata,
19
+ targetInteraction
20
+ }
21
+ } : modalWalletConfig, placement);
22
+ }
23
+
24
+ //#endregion
25
+ //#region src/utils/safeVibrate.ts
26
+ /**
27
+ * Attempt to vibrate the device
28
+ */
29
+ function safeVibrate() {
30
+ if ("vibrate" in navigator) navigator.vibrate(10);
31
+ else console.log("Vibration not supported");
32
+ }
33
+
34
+ //#endregion
35
+ //#region src/components/ButtonWallet/utils.ts
36
+ function openWalletModal(targetInteraction, placement) {
37
+ safeVibrate();
38
+ openEmbeddedWallet(targetInteraction, placement);
39
+ }
40
+
41
+ //#endregion
42
+ //#region src/utils/clientReady.ts
43
+ const CUSTOM_EVENT_NAME = "frak:client";
44
+ /**
45
+ * Dispatch a custom event when the Frak client is ready
46
+ */
47
+ function dispatchClientReadyEvent() {
48
+ const event = new CustomEvent(CUSTOM_EVENT_NAME);
49
+ window.dispatchEvent(event);
50
+ }
51
+ /**
52
+ * Add or remove an event listener for when the Frak client is ready
53
+ * @param action
54
+ * @param callback
55
+ */
56
+ function onClientReady(action, callback) {
57
+ if (window.FrakSetup?.client && action === "add") {
58
+ callback();
59
+ return;
60
+ }
61
+ (action === "add" ? window.addEventListener : window.removeEventListener)(CUSTOM_EVENT_NAME, callback, false);
62
+ }
63
+
64
+ //#endregion
65
+ //#region src/utils/initFrakSdk.ts
66
+ /**
67
+ * Initializes the Frak SDK client and sets up necessary configurations.
68
+ * Uses withCache for inflight dedup — concurrent callers share the same promise.
69
+ * Failures are not cached, allowing retry on next call.
70
+ *
71
+ * @returns {Promise<void>}
72
+ */
73
+ function initFrakSdk() {
74
+ window.FrakSetup.core = {
75
+ ...coreSdkIndex,
76
+ ...coreSdkActions
77
+ };
78
+ if (window.FrakSetup?.client) return Promise.resolve();
79
+ return withCache(() => doInit(), {
80
+ cacheKey: "frak-sdk-init",
81
+ cacheTime: Number.POSITIVE_INFINITY
82
+ }).catch(() => {});
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
+
111
+ //#endregion
112
+ //#region src/utils/onDocumentReady.ts
113
+ /**
114
+ * When the document is ready, run the callback
115
+ * @param callback
116
+ */
117
+ function onDocumentReady(callback) {
118
+ if (document.readyState === "complete" || document.readyState === "interactive") setTimeout(callback, 1);
119
+ else document.addEventListener("DOMContentLoaded", callback);
120
+ }
121
+
122
+ //#endregion
123
+ //#region src/utils/registerWebComponent.ts
124
+ /**
125
+ * Registers a Preact component as a custom web component
126
+ *
127
+ * @param component - The Preact component to register
128
+ * @param tagName - The custom element tag name (e.g., "frak-button-wallet")
129
+ * @param observedAttributes - Array of attribute names to observe for changes
130
+ * @param options - Registration options (e.g., { shadow: true })
131
+ */
132
+ function registerWebComponent(component, tagName, observedAttributes = [], options = { shadow: true }) {
133
+ if (typeof window !== "undefined") {
134
+ onDocumentReady(initFrakSdk);
135
+ if (!customElements.get(tagName)) register(component, tagName, observedAttributes, options);
136
+ }
137
+ }
138
+
139
+ //#endregion
140
+ //#region src/hooks/useClientReady.ts
141
+ function useClientReady() {
142
+ const [shouldRender, setShouldRender] = useState(() => {
143
+ if (!(window.FrakSetup?.config?.waitForBackendConfig !== false)) return true;
144
+ return sdkConfigStore.isResolved;
145
+ });
146
+ const [isHidden, setIsHidden] = useState(() => sdkConfigStore.getConfig().hidden ?? false);
147
+ const [isClientReady, setIsClientReady] = useState(() => !!window.FrakSetup?.client);
148
+ useEffect(() => {
149
+ const currentConfig = sdkConfigStore.getConfig();
150
+ if (currentConfig.isResolved) {
151
+ setShouldRender(true);
152
+ setIsHidden(currentConfig.hidden ?? false);
153
+ }
154
+ if (window.FrakSetup?.client) setIsClientReady(true);
155
+ const onConfig = (e) => {
156
+ const config = e.detail;
157
+ if (config.isResolved) setShouldRender(true);
158
+ setIsHidden(config.hidden ?? false);
159
+ };
160
+ window.addEventListener("frak:config", onConfig);
161
+ const handleReady = () => setIsClientReady(true);
162
+ onClientReady("add", handleReady);
163
+ return () => {
164
+ window.removeEventListener("frak:config", onConfig);
165
+ onClientReady("remove", handleReady);
166
+ };
167
+ }, []);
168
+ return {
169
+ shouldRender,
170
+ isHidden,
171
+ isClientReady
172
+ };
173
+ }
174
+
175
+ //#endregion
176
+ //#region src/utils/sharedCss.ts
177
+ const sharedCss = `
178
+ :host {
179
+ display: contents;
180
+ }
181
+
182
+ :host([hidden]) {
183
+ display: none;
184
+ }
185
+
186
+ .button:disabled {
187
+ opacity: 0.7;
188
+ cursor: default;
189
+ }
190
+
191
+ .button__fadeIn {
192
+ animation: frak-fadeIn 300ms ease-in;
193
+ }
194
+
195
+ @keyframes frak-fadeIn {
196
+ from {
197
+ opacity: 0;
198
+ }
199
+
200
+ to {
201
+ opacity: 1;
202
+ }
203
+ }
204
+ `;
205
+ function buildStyleContent(componentCss, placementCss) {
206
+ return placementCss ? `${sharedCss}\n${componentCss}\n${placementCss}` : `${sharedCss}\n${componentCss}`;
207
+ }
208
+ const lightDomBaseCss = `
209
+ :where(frak-button-share, frak-open-in-app) {
210
+ display: contents;
211
+ }
212
+
213
+ :where(frak-button-share .button, frak-open-in-app .button) {
214
+ display: flex;
215
+ align-items: center;
216
+ justify-content: center;
217
+ gap: 10px;
218
+ }
219
+
220
+ :where(frak-button-share .button:disabled, frak-open-in-app .button:disabled) {
221
+ opacity: 0.7;
222
+ cursor: default;
223
+ }
224
+
225
+ :where(frak-button-share .button__fadeIn, frak-open-in-app .button__fadeIn) {
226
+ animation: frak-fadeIn 300ms ease-in;
227
+ }
228
+
229
+ @keyframes frak-fadeIn {
230
+ from {
231
+ opacity: 0;
232
+ }
233
+
234
+ to {
235
+ opacity: 1;
236
+ }
237
+ }
238
+ `;
239
+ const bannerBaseCss = `
240
+ :where(frak-banner) {
241
+ display: block;
242
+ }
243
+
244
+ :where(frak-banner .banner) {
245
+ display: flex;
246
+ align-items: center;
247
+ gap: 12px;
248
+ padding: 12px 16px;
249
+ border-top: 2px solid #3b82f6;
250
+ border-bottom: 2px solid #3b82f6;
251
+ font-family: inherit;
252
+ line-height: 1.4;
253
+ }
254
+
255
+ :where(frak-banner .banner__fadeIn) {
256
+ animation: frak-fadeIn 300ms ease-in;
257
+ }
258
+
259
+ @keyframes frak-fadeIn {
260
+ from {
261
+ opacity: 0;
262
+ }
263
+
264
+ to {
265
+ opacity: 1;
266
+ }
267
+ }
268
+
269
+ :where(frak-banner .banner__icon) {
270
+ flex-shrink: 0;
271
+ display: flex;
272
+ align-items: center;
273
+ justify-content: center;
274
+ width: 32px;
275
+ height: 32px;
276
+ color: #3b82f6;
277
+ }
278
+
279
+ :where(frak-banner .banner__icon svg) {
280
+ width: 100%;
281
+ height: 100%;
282
+ }
283
+
284
+ :where(frak-banner .banner__content) {
285
+ flex: 1;
286
+ min-width: 0;
287
+ }
288
+
289
+ :where(frak-banner .banner__title) {
290
+ font-weight: 700;
291
+ font-size: 0.875rem;
292
+ margin: 0 0 2px;
293
+ }
294
+
295
+ :where(frak-banner .banner__description) {
296
+ font-size: 0.75rem;
297
+ margin: 0;
298
+ opacity: 0.7;
299
+ }
300
+
301
+ :where(frak-banner .banner__cta) {
302
+ flex-shrink: 0;
303
+ padding: 8px 16px;
304
+ font-weight: 700;
305
+ font-size: 0.75rem;
306
+ text-transform: uppercase;
307
+ letter-spacing: 0.05em;
308
+ border: 2px solid #eab308;
309
+ border-radius: 0;
310
+ background: #eab308;
311
+ color: #1e293b;
312
+ cursor: pointer;
313
+ white-space: nowrap;
314
+ }
315
+
316
+ :where(frak-banner .banner__cta:hover) {
317
+ opacity: 0.9;
318
+ }
319
+ `;
320
+
321
+ //#endregion
322
+ //#region src/hooks/usePlacement.ts
323
+ function getPlacement(id) {
324
+ return sdkConfigStore.getConfig().placements?.[id];
325
+ }
326
+ function usePlacement(placementId) {
327
+ const [configVersion, setConfigVersion] = useState(0);
328
+ useEffect(() => {
329
+ const onConfig = (_e) => {
330
+ setConfigVersion((v) => v + 1);
331
+ };
332
+ window.addEventListener("frak:config", onConfig);
333
+ setConfigVersion((v) => v + 1);
334
+ return () => window.removeEventListener("frak:config", onConfig);
335
+ }, []);
336
+ return useMemo(() => placementId ? getPlacement(placementId) : void 0, [placementId, configVersion]);
337
+ }
338
+
339
+ //#endregion
340
+ export { useClientReady as a, openEmbeddedWallet as c, lightDomBaseCss as i, bannerBaseCss as n, registerWebComponent as o, buildStyleContent as r, openWalletModal as s, usePlacement as t };
@@ -0,0 +1,67 @@
1
+ import { t as formatEstimatedReward } from "./formatReward-6JQldDEC.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
+
6
+ //#region src/hooks/useReward.ts
7
+ /**
8
+ * Get the comparable fiat value of a reward for ranking purposes.
9
+ */
10
+ function getRewardValue(reward, key) {
11
+ switch (reward.payoutType) {
12
+ case "fixed": return reward.amount[key];
13
+ case "tiered": return reward.tiers.reduce((acc, tier) => Math.max(acc, tier.amount[key]), 0);
14
+ case "percentage": return 0;
15
+ }
16
+ }
17
+ /**
18
+ * Pick the best referrer reward from merchant info and format it.
19
+ * Returns `undefined` when no displayable reward is found.
20
+ */
21
+ function resolveBestReward({ rewards }, currency, targetInteraction) {
22
+ const referrerRewards = (targetInteraction ? rewards.filter((r) => r.interactionTypeKey === targetInteraction) : rewards).map((r) => r.referrer).filter((r) => r !== void 0);
23
+ if (referrerRewards.length === 0) return void 0;
24
+ const key = getCurrencyAmountKey(getSupportedCurrency(currency));
25
+ let bestReward = referrerRewards[0];
26
+ let bestValue = getRewardValue(bestReward, key);
27
+ for (let i = 1; i < referrerRewards.length; i++) {
28
+ const value = getRewardValue(referrerRewards[i], key);
29
+ if (value > bestValue) {
30
+ bestReward = referrerRewards[i];
31
+ bestValue = value;
32
+ }
33
+ }
34
+ if (bestValue <= 0) {
35
+ const percentageReward = referrerRewards.find((r) => r.payoutType === "percentage");
36
+ if (!percentageReward) return void 0;
37
+ bestReward = percentageReward;
38
+ }
39
+ return formatEstimatedReward(bestReward, currency);
40
+ }
41
+ /**
42
+ * Hook to fetch and format the best referrer reward for a given interaction type.
43
+ *
44
+ * Calls `getMerchantInformation`, picks the highest-value referrer reward
45
+ * across all matching campaigns, and returns it as a formatted string.
46
+ *
47
+ * @param shouldUseReward - Whether to fetch the reward at all
48
+ * @param targetInteraction - Optional filter by interaction type (e.g. "purchase")
49
+ * @returns Object containing the formatted reward string, or undefined if unavailable
50
+ */
51
+ function useReward(shouldUseReward, targetInteraction) {
52
+ const [reward, setReward] = useState(void 0);
53
+ useEffect(() => {
54
+ if (!shouldUseReward) return;
55
+ const client = window.FrakSetup?.client;
56
+ if (!client) return;
57
+ getMerchantInformation(client).then((merchantInfo) => {
58
+ const currency = client.config.metadata?.currency;
59
+ const formatted = resolveBestReward(merchantInfo, currency, targetInteraction);
60
+ if (formatted) setReward(formatted);
61
+ }).catch(() => {});
62
+ }, [shouldUseReward, targetInteraction]);
63
+ return { reward };
64
+ }
65
+
66
+ //#endregion
67
+ export { useReward as t };
@@ -0,0 +1,55 @@
1
+ import { DebugInfoGatherer, trackEvent } from "@frak-labs/core-sdk";
2
+ import { modalBuilder } from "@frak-labs/core-sdk/actions";
3
+ import { useCallback, useState } from "preact/hooks";
4
+ import { FrakRpcError, RpcErrorCodes } from "@frak-labs/frame-connector";
5
+
6
+ //#region src/components/ButtonShare/hooks/useShareModal.ts
7
+ /**
8
+ * Open the share modal
9
+ *
10
+ * @description
11
+ * This function will open the share modal, lazily creating a modal builder on demand.
12
+ */
13
+ function useShareModal(targetInteraction, placement, sharingLink) {
14
+ const [debugInfo, setDebugInfo] = useState(void 0);
15
+ const [isError, setIsError] = useState(false);
16
+ return {
17
+ handleShare: useCallback(async () => {
18
+ if (!window.FrakSetup?.client) {
19
+ console.error("Frak client not found");
20
+ setDebugInfo(DebugInfoGatherer.empty().formatDebugInfo("Frak client not found"));
21
+ setIsError(true);
22
+ return;
23
+ }
24
+ const builder = modalBuilder(window.FrakSetup.client, {});
25
+ try {
26
+ await builder.sharing(sharingLink ? { link: sharingLink } : {}).display((metadata) => ({
27
+ ...metadata,
28
+ targetInteraction
29
+ }), placement);
30
+ } catch (e) {
31
+ if (e instanceof FrakRpcError && e.code === RpcErrorCodes.clientAborted) {
32
+ console.debug("User aborted the modal");
33
+ return;
34
+ }
35
+ const debugInfo = window.FrakSetup.client.debugInfo.formatDebugInfo(e);
36
+ trackEvent(window.FrakSetup.client, "share_modal_error", {
37
+ error: e instanceof Object && "message" in e ? e.message : "Unknown error",
38
+ debugInfo
39
+ });
40
+ setDebugInfo(debugInfo);
41
+ setIsError(true);
42
+ console.error("Error while opening the modal", e);
43
+ }
44
+ }, [
45
+ targetInteraction,
46
+ placement,
47
+ sharingLink
48
+ ]),
49
+ isError,
50
+ debugInfo
51
+ };
52
+ }
53
+
54
+ //#endregion
55
+ export { useShareModal 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.26-beta.b38eef2e",
14
+ "version": "0.0.26-beta.d04602ec",
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",
@@ -56,6 +56,16 @@
56
56
  "import": "./dist/openInApp.js",
57
57
  "types": "./dist/openInApp.d.ts"
58
58
  },
59
+ "./postPurchase": {
60
+ "development": "./src/components/PostPurchase/index.ts",
61
+ "import": "./dist/postPurchase.js",
62
+ "types": "./dist/postPurchase.d.ts"
63
+ },
64
+ "./banner": {
65
+ "development": "./src/components/Banner/index.ts",
66
+ "import": "./dist/banner.js",
67
+ "types": "./dist/banner.d.ts"
68
+ },
59
69
  "./cdn": {
60
70
  "import": "./cdn/components.js"
61
71
  },
@@ -76,31 +86,27 @@
76
86
  "publish": "echo 'Publishing components...'"
77
87
  },
78
88
  "dependencies": {
79
- "@frak-labs/frame-connector": "0.2.0-beta.b38eef2e",
80
- "@frak-labs/core-sdk": "0.2.1-beta.b38eef2e",
81
- "class-variance-authority": "^0.7.1",
82
- "preact": "^10.28.3",
89
+ "@frak-labs/core-sdk": "0.2.1-beta.d04602ec",
90
+ "@frak-labs/frame-connector": "0.2.0-beta.d04602ec",
91
+ "preact": "^10.29.0",
83
92
  "preact-custom-element": "^4.6.0"
84
93
  },
85
94
  "devDependencies": {
86
- "@bosh-code/tsdown-plugin-inject-css": "^2.0.0",
87
95
  "@frak-labs/dev-tooling": "0.0.0",
88
96
  "@frak-labs/test-foundation": "0.1.0",
89
- "@frak-labs/ui": "0.0.0",
90
- "@preact/preset-vite": "^2.10.3",
97
+ "@preact/preset-vite": "^2.10.4",
91
98
  "@rolldown/plugin-node-polyfills": "^1.0.3",
92
99
  "@testing-library/jest-dom": "^6.9.1",
93
100
  "@testing-library/preact": "^3.2.4",
94
101
  "@testing-library/user-event": "^14.6.1",
95
- "@types/jsdom": "^27.0.0",
102
+ "@types/jsdom": "^28.0.0",
96
103
  "@types/node": "^24.10.13",
97
104
  "@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",
105
+ "@vitest/coverage-v8": "^4.1.0",
106
+ "@vitest/ui": "^4.1.0",
107
+ "jsdom": "^29.0.0",
101
108
  "tsdown": "^0.20.3",
102
- "typescript": "^5",
103
- "unplugin-lightningcss": "^0.4.5",
104
- "vitest": "^4.0.18"
109
+ "typescript": "^5.9.3",
110
+ "vitest": "^4.1.0"
105
111
  }
106
112
  }
@@ -1 +0,0 @@
1
- import{S as e,a as t,b as n,c as r,f as i,h as a,l as o,m as s,n as c,o as l,p as u,s as d}from"./initFrakSdk.CMgrZQwQ.js";import{t as f}from"./Spinner.DQogVqic.js";import{a as p,i as m,n as h,o as g,r as _,t as v}from"./useClientReady.CKKC4IMk.js";function y(e,t){return!e||e.payoutType!==`fixed`?0:e.amount[t]}function b(e,t){return e.reduce((e,n)=>Math.max(e,y(n.referrer,t)),0)}async function x({targetInteraction:e}){let n=window.FrakSetup?.client;if(!n){console.warn(`Frak client not ready yet`);return}let{rewards:i}=await t(n),a=r(n.config.metadata?.currency),s=b(e?i.filter(t=>t.interactionTypeKey===e):i,a);if(!(s<=0))return o(Math.round(s),n.config.metadata?.currency)}function S(e,t){let[n,r]=_(void 0);return p(()=>{e&&x({targetInteraction:t}).then(e=>{e&&r(e)})},[e,t]),{reward:n}}const C={buttonShare:`nOB7Uq_buttonShare`};C.buttonShare;function w(e={}){let{successDuration:t=2e3}=e,[n,r]=_(!1);return{copy:m(async e=>{try{if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(e),r(!0);else{let t=document.createElement(`textarea`);t.value=e,t.style.position=`fixed`,t.style.opacity=`0`,document.body.appendChild(t),t.focus(),t.select();try{document.execCommand(`copy`),r(!0)}catch(e){return console.error(`Failed to copy text:`,e),!1}finally{t.remove()}}return setTimeout(()=>{r(!1)},t),!0}catch(e){return console.error(`Failed to copy text:`,e),!1}},[t]),copied:n}}const T={errorContainer:{marginTop:`16px`,padding:`16px`,backgroundColor:`#FEE2E2`,border:`1px solid #FCA5A5`,borderRadius:`4px`,color:`#991B1B`},header:{display:`flex`,alignItems:`center`,gap:`8px`,marginBottom:`12px`},title:{margin:0,fontSize:`16px`,fontWeight:500},message:{fontSize:`14px`,lineHeight:`1.5`,margin:`0 0 12px 0`},link:{color:`#991B1B`,textDecoration:`underline`,textUnderlineOffset:`2px`},copyButton:{display:`inline-flex`,alignItems:`center`,gap:`8px`,marginBottom:`10px`,padding:`8px 12px`,backgroundColor:`white`,border:`1px solid #D1D5DB`,borderRadius:`4px`,color:`black`,fontSize:`14px`,fontWeight:500}};function E({debugInfo:e}){let[t,n]=_(!1);return a(`div`,{children:[a(`button`,{type:`button`,style:T.copyButton,onClick:()=>n(!t),children:`Ouvrir les informations`}),t&&a(`textarea`,{style:{display:`block`,width:`100%`,height:`200px`,fontSize:`12px`},children:e})]})}function D({debugInfo:e}){let{copied:t,copy:n}=w();return a(`div`,{style:T.errorContainer,children:[a(`div`,{style:T.header,children:a(`h3`,{style:T.title,children:`Oups ! Nous avons rencontré un petit problème`})}),a(`p`,{style:T.message,children:[`Impossible d'ouvrir le menu de partage pour le moment. Si le problème persiste, copiez les informations ci-dessous et collez-les dans votre mail à`,` `,a(`a`,{href:`mailto:help@frak-labs.com?subject=Debug`,style:T.link,children:`help@frak-labs.com`}),` `,a(`br`,{}),`Merci pour votre retour, nous traitons votre demande dans les plus brefs délais.`]}),a(`button`,{type:`button`,onClick:()=>n(e??``),style:T.copyButton,children:t?`Informations copiées !`:`Copier les informations de débogage`}),a(E,{debugInfo:e})]})}function O(e){let[t,n]=_(void 0),[r,a]=_(!1);return{handleShare:m(async()=>{if(!window.FrakSetup?.client){console.error(`Frak client not found`),n(d.empty().formatDebugInfo(`Frak client not found`)),a(!0);return}let t=c();if(!t)throw Error(`modalBuilderSteps not found`);try{await t.sharing(window.FrakSetup?.modalShareConfig??{}).display(t=>({...t,targetInteraction:e}))}catch(e){if(e instanceof s&&e.code===u.clientAborted){console.debug(`User aborted the modal`);return}let t=window.FrakSetup.client.debugInfo.formatDebugInfo(e);i(window.FrakSetup.client,`share_modal_error`,{error:e instanceof Object&&`message`in e?e.message:`Unknown error`,debugInfo:t}),n(t),a(!0),console.error(`Error while opening the modal`,e)}},[e]),isError:r,debugInfo:t}}async function k(){if(!window.FrakSetup?.client)throw Error(`Frak client not found`);await l(window.FrakSetup.client,window.FrakSetup?.modalWalletConfig??{})}function A({text:t=`Share and earn!`,classname:r=``,useReward:o,noRewardText:s,targetInteraction:c,showWallet:l}){let u=h(()=>o!==void 0,[o]),d=h(()=>l!==void 0,[l]),{isClientReady:p}=v(),{reward:g}=S(u&&p,c),{handleShare:_,isError:y,debugInfo:b}=O(c),x=h(()=>u?g?t.includes(`{REWARD}`)?t.replace(`{REWARD}`,g):`${t} ${g}`:s??t.replace(`{REWARD}`,``):t,[u,t,s,g]),w=m(async()=>{i(window.FrakSetup.client,`share_button_clicked`),d?await k():await _()},[d,_]);return a(n,{children:[a(`button`,{type:`button`,className:e(C.buttonShare,r,`override`),onClick:w,children:[!p&&a(f,{}),` `,x]}),y&&a(D,{debugInfo:b})]})}g(A,`frak-button-share`,[`text`],{shadow:!1});export{A as ButtonShare,S as t};
@@ -1 +0,0 @@
1
- import{S as e,f as t,h as n,i as r}from"./initFrakSdk.CMgrZQwQ.js";import{a as i,n as a,o,r as s,t as c}from"./useClientReady.CKKC4IMk.js";import{t as l}from"./ButtonShare.CSPl5Bi5.js";function u(e){return n(`svg`,{fill:`none`,height:`1em`,viewBox:`0 0 28 28`,width:`1em`,xmlns:`http://www.w3.org/2000/svg`,...e,children:[n(`title`,{children:`Gift icon`}),n(`path`,{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`,stroke:`#fff`,"stroke-linecap":`round`,"stroke-linejoin":`round`})]})}const d={button:`Kl62ia_button`,reward:`Kl62ia_reward`,button__left:`Kl62ia_button__left`,button__right:`Kl62ia_button__right`};d.button,d.reward,d.button__left,d.button__right;function f({classname:o=``,useReward:f,targetInteraction:p}){let m=a(()=>f!==void 0,[f]),{isClientReady:h}=c(),{reward:g}=l(m&&h,p),[_,v]=s(`right`);return i(()=>{let e=window.FrakSetup?.modalWalletConfig?.metadata?.position;v(e??`right`)},[]),n(`button`,{type:`button`,"aria-label":`Open wallet`,class:e(d.button,_===`left`?d.button__left:d.button__right,o,`override`),disabled:!h,onClick:()=>{t(window.FrakSetup.client,`wallet_button_clicked`),r()},children:[n(u,{}),g&&n(`span`,{className:d.reward,children:g})]})}o(f,`frak-button-wallet`,[],{shadow:!1});export{f as ButtonWallet};
@@ -1 +0,0 @@
1
- import{S as e,d as t,f as n,h as r,u as i}from"./initFrakSdk.CMgrZQwQ.js";import{t as a}from"./Spinner.DQogVqic.js";import{n as o,o as s,t as c}from"./useClientReady.CKKC4IMk.js";function l(){return typeof navigator>`u`?!1:!!(/iPhone|iPad|iPod|Android|webOS|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)||/Macintosh/i.test(navigator.userAgent)&&navigator.maxTouchPoints>1)}function u(){return{isMobile:o(()=>l(),[])}}function d(e=`wallet`){let r=window.FrakSetup?.client;r&&n(r,`open_in_app_clicked`),t(`${i}${e}`,{onFallback:()=>{r&&n(r,`app_not_installed`)}})}const f={button:`XYfqGq_button`};f.button;function p({text:t=`Open in App`,classname:n=``}){let{isClientReady:i}=c(),{isMobile:o}=u();if(!o)return null;let s=()=>{d()};return r(`button`,{type:`button`,"aria-label":`Open in Frak Wallet app`,className:e(f.button,n,`override`),disabled:!i,onClick:s,children:[!i&&r(a,{}),` `,t]})}s(p,`frak-open-in-app`,[`text`],{shadow:!1});export{p as OpenInAppButton};
@@ -1 +0,0 @@
1
- import{S as e,h as t}from"./initFrakSdk.CMgrZQwQ.js";const n={spinner:`M4fSKa_spinner`,spinner__leaf:`M4fSKa_spinner__leaf`,"rt-spinner-leaf-fade":`M4fSKa_rt-spinner-leaf-fade`};n.spinner,n.spinner__leaf,n[`rt-spinner-leaf-fade`];const r=({ref:r,className:i,...a})=>t(`span`,{...a,ref:r,className:e(n.spinner),children:[t(`span`,{className:n.spinner__leaf}),t(`span`,{className:n.spinner__leaf}),t(`span`,{className:n.spinner__leaf}),t(`span`,{className:n.spinner__leaf}),t(`span`,{className:n.spinner__leaf}),t(`span`,{className:n.spinner__leaf}),t(`span`,{className:n.spinner__leaf}),t(`span`,{className:n.spinner__leaf})]});r.displayName=`Spinner`;export{r as t};