@frak-labs/components 1.0.4 → 1.0.5-beta.53162c2d
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/Banner.CcOWT4lZ.js +178 -0
- package/cdn/ButtonShare._hjtruGc.js +1 -0
- package/cdn/ButtonWallet.L8LRS_pt.js +40 -0
- package/cdn/PostPurchase.DECOqME5.js +89 -0
- package/cdn/components.js +1 -1
- package/cdn/embeddedWallet.CDUxjdX2.js +1 -0
- package/cdn/loader.js +1 -1
- package/cdn/replay-V6FXES7X.CNozpSRg.js +1 -0
- package/cdn/useReward.BtBpuMwt.js +1 -0
- package/dist/banner.d.ts +17 -1
- package/dist/banner.js +7 -5
- package/dist/buttonShare.js +3 -3
- package/dist/buttonWallet.js +17 -1
- package/dist/embeddedWallet-By3_p5Xc.js +18 -0
- package/dist/openInApp.js +2 -2
- package/dist/postPurchase.js +3 -74
- package/dist/{useLightDomStyles-DVe5UDg6.js → useLightDomStyles-C8giLInY.js} +1 -1
- package/dist/{usePlacement-DzEuVg_u.js → usePlacement-5kbU3BKj.js} +144 -30
- package/package.json +3 -3
- package/cdn/Banner.B1y3jwHv.js +0 -178
- package/cdn/ButtonShare.elMtdxF3.js +0 -1
- package/cdn/ButtonWallet.BUUPX0gO.js +0 -40
- package/cdn/PostPurchase.Cy7-FrRh.js +0 -89
- package/cdn/replay-V6FXES7X.BoL9fAjx.js +0 -1
- package/cdn/sharingPage.BYsqcN9O.js +0 -1
- package/cdn/useReward.B530suzR.js +0 -1
- package/dist/sharingPage-D6fQEXV9.js +0 -15
package/dist/buttonWallet.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { a as registerWebComponent, i as useClientReady, n as buildStyleContent,
|
|
1
|
+
import { a as registerWebComponent, i as useClientReady, n as buildStyleContent, t as usePlacement } from "./usePlacement-5kbU3BKj.js";
|
|
2
|
+
import { t as openEmbeddedWallet } from "./embeddedWallet-By3_p5Xc.js";
|
|
2
3
|
import { t as useReward } from "./useReward-ClVShg45.js";
|
|
3
4
|
import { useEffect, useMemo, useState } from "preact/hooks";
|
|
4
5
|
import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
|
|
@@ -20,6 +21,21 @@ function GiftIcon(props) {
|
|
|
20
21
|
});
|
|
21
22
|
}
|
|
22
23
|
//#endregion
|
|
24
|
+
//#region src/utils/browser/safeVibrate.ts
|
|
25
|
+
/**
|
|
26
|
+
* Attempt to vibrate the device
|
|
27
|
+
*/
|
|
28
|
+
function safeVibrate() {
|
|
29
|
+
if ("vibrate" in navigator) navigator.vibrate(10);
|
|
30
|
+
else console.log("Vibration not supported");
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/components/ButtonWallet/utils.ts
|
|
34
|
+
function openWalletModal(targetInteraction, placement) {
|
|
35
|
+
safeVibrate();
|
|
36
|
+
openEmbeddedWallet(targetInteraction, placement);
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
23
39
|
//#region src/components/ButtonWallet/ButtonWallet.tsx
|
|
24
40
|
const componentCss = `
|
|
25
41
|
.button {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { displayEmbeddedWallet } from "@frak-labs/core-sdk/actions";
|
|
2
|
+
//#region src/actions/embeddedWallet.ts
|
|
3
|
+
async function openEmbeddedWallet(targetInteraction, placement) {
|
|
4
|
+
if (!window.FrakSetup?.client) {
|
|
5
|
+
console.error("Frak client not found");
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
const modalWalletConfig = window.FrakSetup?.modalWalletConfig ?? {};
|
|
9
|
+
await displayEmbeddedWallet(window.FrakSetup.client, targetInteraction ? {
|
|
10
|
+
...modalWalletConfig,
|
|
11
|
+
metadata: {
|
|
12
|
+
...modalWalletConfig.metadata,
|
|
13
|
+
targetInteraction
|
|
14
|
+
}
|
|
15
|
+
} : modalWalletConfig, placement);
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { openEmbeddedWallet as t };
|
package/dist/openInApp.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as registerWebComponent, i as useClientReady, t as usePlacement } from "./usePlacement-
|
|
2
|
-
import { t as useLightDomStyles } from "./useLightDomStyles-
|
|
1
|
+
import { a as registerWebComponent, i as useClientReady, t as usePlacement } from "./usePlacement-5kbU3BKj.js";
|
|
2
|
+
import { t as useLightDomStyles } from "./useLightDomStyles-C8giLInY.js";
|
|
3
3
|
import { DEEP_LINK_SCHEME, isMobile, trackEvent, triggerDeepLinkWithFallback } from "@frak-labs/core-sdk";
|
|
4
4
|
import { useMemo } from "preact/hooks";
|
|
5
5
|
import { jsx } from "preact/jsx-runtime";
|
package/dist/postPurchase.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { a as registerWebComponent, i as useClientReady, t as usePlacement } from "./usePlacement-
|
|
2
|
-
import { t as openSharingPage } from "./sharingPage-D6fQEXV9.js";
|
|
1
|
+
import { a as registerWebComponent, i as useClientReady, o as sanitizeProductList, s as openSharingPage, t as usePlacement } from "./usePlacement-5kbU3BKj.js";
|
|
3
2
|
import { t as useGlobalComponents } from "./useGlobalComponents-mSs9unyN.js";
|
|
4
|
-
import { t as useLightDomStyles } from "./useLightDomStyles-
|
|
3
|
+
import { t as useLightDomStyles } from "./useLightDomStyles-C8giLInY.js";
|
|
5
4
|
import { n as formatEstimatedReward, t as applyRewardPlaceholder } from "./formatReward-Cf2KpA3x.js";
|
|
6
5
|
import { i as LogoFrakWithName, n as cssSource$2, t as GiftIcon } from "./GiftIcon-BIp9FTJs.js";
|
|
7
6
|
import { trackEvent } from "@frak-labs/core-sdk";
|
|
@@ -112,67 +111,6 @@ var imageWrapper = "PostPurchase_imageWrapper__5fv5lh9";
|
|
|
112
111
|
var message = "PostPurchase_message__5fv5lh5";
|
|
113
112
|
const cssSource = cssSource$1;
|
|
114
113
|
//#endregion
|
|
115
|
-
//#region src/components/PostPurchase/products.ts
|
|
116
|
-
/**
|
|
117
|
-
* Whether `value` is a syntactically valid URL with an `http(s):` scheme.
|
|
118
|
-
*
|
|
119
|
-
* Used to gate `imageUrl` / `link` fields coming from the public `products`
|
|
120
|
-
* prop — the listener-side sharing-page builder calls `new URL(...)` on the
|
|
121
|
-
* incoming product link, and a `javascript:` URL would be a XSS sink in any
|
|
122
|
-
* consumer that binds the value to an `href`.
|
|
123
|
-
*/
|
|
124
|
-
function isHttpUrl(value) {
|
|
125
|
-
try {
|
|
126
|
-
const parsed = new URL(value);
|
|
127
|
-
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
128
|
-
} catch {
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Coerce a raw `products` prop value into a candidate array suitable for
|
|
134
|
-
* per-item normalisation, or null when it cannot be reduced to one.
|
|
135
|
-
*
|
|
136
|
-
* Surfaces that set the prop via the JS property (`el.products = [...]`)
|
|
137
|
-
* deliver a real array; surfaces that bind it as an HTML attribute
|
|
138
|
-
* (WP / Magento server-render) deliver a JSON-stringified array. Anything
|
|
139
|
-
* else (truthy non-array non-string, JSON parse failure, JSON that decodes
|
|
140
|
-
* to a non-array) is treated as "no products" so the share still works
|
|
141
|
-
* without the product card section.
|
|
142
|
-
*/
|
|
143
|
-
function coerceProductCandidates(products) {
|
|
144
|
-
if (!products) return null;
|
|
145
|
-
if (Array.isArray(products)) return products;
|
|
146
|
-
if (typeof products !== "string") return null;
|
|
147
|
-
try {
|
|
148
|
-
const parsed = JSON.parse(products);
|
|
149
|
-
return Array.isArray(parsed) ? parsed : null;
|
|
150
|
-
} catch {
|
|
151
|
-
return null;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Normalise one untrusted candidate into a {@link SharingPageProduct}, or
|
|
156
|
-
* return null when the candidate has no usable title.
|
|
157
|
-
*
|
|
158
|
-
* The `products` prop is a public API boundary (merchants can set it
|
|
159
|
-
* server-side via WP/Magento or imperatively from arbitrary JS). Each entry
|
|
160
|
-
* is validated structurally so a malformed `link` reaching `new URL(...)`
|
|
161
|
-
* downstream would not crash the sharing-page builder, and so a
|
|
162
|
-
* `javascript:` URL cannot slip through as `imageUrl` / `link`.
|
|
163
|
-
*/
|
|
164
|
-
function normalizeProductCandidate(candidate) {
|
|
165
|
-
if (!candidate || typeof candidate !== "object") return null;
|
|
166
|
-
const item = candidate;
|
|
167
|
-
const title = typeof item.title === "string" ? item.title.trim() : "";
|
|
168
|
-
if (title === "") return null;
|
|
169
|
-
const entry = { title };
|
|
170
|
-
if (typeof item.imageUrl === "string" && isHttpUrl(item.imageUrl)) entry.imageUrl = item.imageUrl;
|
|
171
|
-
if (typeof item.link === "string" && isHttpUrl(item.link)) entry.link = item.link;
|
|
172
|
-
if (typeof item.utmContent === "string" && item.utmContent !== "") entry.utmContent = item.utmContent;
|
|
173
|
-
return entry;
|
|
174
|
-
}
|
|
175
|
-
//#endregion
|
|
176
114
|
//#region src/components/PostPurchase/PostPurchase.tsx
|
|
177
115
|
/**
|
|
178
116
|
* Given referral status and merchant info, compute the display variant
|
|
@@ -303,16 +241,7 @@ function PostPurchase({ customerId, orderId, token, sharingUrl, merchantId, plac
|
|
|
303
241
|
placementId,
|
|
304
242
|
context?.reward
|
|
305
243
|
]);
|
|
306
|
-
const parsedProducts = useMemo(() =>
|
|
307
|
-
const candidates = coerceProductCandidates(products);
|
|
308
|
-
if (!candidates) return void 0;
|
|
309
|
-
const sanitized = [];
|
|
310
|
-
for (const candidate of candidates) {
|
|
311
|
-
const entry = normalizeProductCandidate(candidate);
|
|
312
|
-
if (entry) sanitized.push(entry);
|
|
313
|
-
}
|
|
314
|
-
return sanitized.length > 0 ? sanitized : void 0;
|
|
315
|
-
}, [products]);
|
|
244
|
+
const parsedProducts = useMemo(() => sanitizeProductList(products), [products]);
|
|
316
245
|
const handleClick = useCallback(() => {
|
|
317
246
|
if (!resolvedVariant) return;
|
|
318
247
|
trackEvent(window.FrakSetup?.client, "post_purchase_clicked", {
|
|
@@ -1,38 +1,126 @@
|
|
|
1
1
|
import register from "preact-custom-element";
|
|
2
2
|
import * as coreSdkIndex from "@frak-labs/core-sdk";
|
|
3
|
-
import { sdkConfigStore, setupClient, trackEvent, withCache } from "@frak-labs/core-sdk";
|
|
3
|
+
import { decompressJsonFromB64, sdkConfigStore, setupClient, trackEvent, withCache } from "@frak-labs/core-sdk";
|
|
4
4
|
import * as coreSdkActions from "@frak-labs/core-sdk/actions";
|
|
5
|
-
import {
|
|
5
|
+
import { displaySharingPage } from "@frak-labs/core-sdk/actions";
|
|
6
6
|
import { useEffect, useMemo, useState } from "preact/hooks";
|
|
7
|
-
//#region src/actions/
|
|
8
|
-
async function
|
|
7
|
+
//#region src/actions/sharingPage.ts
|
|
8
|
+
async function openSharingPage(targetInteraction, placement, options) {
|
|
9
9
|
if (!window.FrakSetup?.client) {
|
|
10
10
|
console.error("Frak client not found");
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
...
|
|
16
|
-
metadata: {
|
|
17
|
-
|
|
18
|
-
targetInteraction
|
|
19
|
-
}
|
|
20
|
-
} : modalWalletConfig, placement);
|
|
13
|
+
await displaySharingPage(window.FrakSetup.client, {
|
|
14
|
+
...options?.link && { link: options.link },
|
|
15
|
+
...options?.products?.length && { products: options.products },
|
|
16
|
+
...targetInteraction && { metadata: { targetInteraction } }
|
|
17
|
+
}, placement);
|
|
21
18
|
}
|
|
22
19
|
//#endregion
|
|
23
|
-
//#region src/utils/
|
|
20
|
+
//#region src/utils/sharingPageProducts.ts
|
|
24
21
|
/**
|
|
25
|
-
*
|
|
22
|
+
* Whether `value` is a syntactically valid URL with an `http(s):` scheme.
|
|
23
|
+
*
|
|
24
|
+
* Used to gate `imageUrl` / `link` fields coming from untrusted inputs (the
|
|
25
|
+
* public `products` prop on `<frak-post-purchase>`, decoded query params for
|
|
26
|
+
* Klaviyo / email share links, etc.) — the listener-side sharing-page builder
|
|
27
|
+
* calls `new URL(...)` on the incoming product link, and a `javascript:` URL
|
|
28
|
+
* would be a XSS sink in any consumer that binds the value to an `href`.
|
|
26
29
|
*/
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
function isHttpUrl(value) {
|
|
31
|
+
try {
|
|
32
|
+
const parsed = new URL(value);
|
|
33
|
+
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
34
|
+
} catch {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
30
37
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Coerce a raw `products` value into a candidate array suitable for
|
|
40
|
+
* per-item normalisation, or null when it cannot be reduced to one.
|
|
41
|
+
*
|
|
42
|
+
* Accepts:
|
|
43
|
+
* - Real arrays (JS-property surface, decompressed query payloads).
|
|
44
|
+
* - JSON-stringified arrays (HTML-attribute surface — WP / Magento
|
|
45
|
+
* server-render delivers attribute values as raw strings).
|
|
46
|
+
*
|
|
47
|
+
* Anything else (non-array non-string, JSON parse failure, JSON that
|
|
48
|
+
* decodes to a non-array) is treated as "no products" so the share still
|
|
49
|
+
* works without the product card section.
|
|
50
|
+
*/
|
|
51
|
+
function coerceProductCandidates(products) {
|
|
52
|
+
if (!products) return null;
|
|
53
|
+
if (Array.isArray(products)) return products;
|
|
54
|
+
if (typeof products !== "string") return null;
|
|
55
|
+
try {
|
|
56
|
+
const parsed = JSON.parse(products);
|
|
57
|
+
return Array.isArray(parsed) ? parsed : null;
|
|
58
|
+
} catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Normalise one untrusted candidate into a {@link SharingPageProduct}, or
|
|
64
|
+
* return null when the candidate has no usable title.
|
|
65
|
+
*
|
|
66
|
+
* The `products` payload is a public API boundary — merchants can set it
|
|
67
|
+
* server-side via WP / Magento, imperatively from arbitrary JS, or via
|
|
68
|
+
* email-template query params built by Klaviyo. Each entry is validated
|
|
69
|
+
* structurally so a malformed `link` reaching `new URL(...)` downstream
|
|
70
|
+
* would not crash the sharing-page builder, and so a `javascript:` URL
|
|
71
|
+
* cannot slip through as `imageUrl` / `link`.
|
|
72
|
+
*/
|
|
73
|
+
function normalizeProductCandidate(candidate) {
|
|
74
|
+
if (!candidate || typeof candidate !== "object") return null;
|
|
75
|
+
const item = candidate;
|
|
76
|
+
const title = typeof item.title === "string" ? item.title.trim() : "";
|
|
77
|
+
if (title === "") return null;
|
|
78
|
+
const entry = { title };
|
|
79
|
+
if (typeof item.imageUrl === "string" && isHttpUrl(item.imageUrl)) entry.imageUrl = item.imageUrl;
|
|
80
|
+
if (typeof item.link === "string" && isHttpUrl(item.link)) entry.link = item.link;
|
|
81
|
+
if (typeof item.utmContent === "string" && item.utmContent !== "") entry.utmContent = item.utmContent;
|
|
82
|
+
return entry;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Pipe `coerceProductCandidates` + `normalizeProductCandidate` over an
|
|
86
|
+
* untrusted value and return a non-empty {@link SharingPageProduct}[] or
|
|
87
|
+
* `undefined` when nothing usable came out.
|
|
88
|
+
*
|
|
89
|
+
* The undefined sentinel is what `openSharingPage` / `displaySharingPage`
|
|
90
|
+
* expect when the caller has no products to show — the sharing page just
|
|
91
|
+
* skips the product card section.
|
|
92
|
+
*/
|
|
93
|
+
function sanitizeProductList(input) {
|
|
94
|
+
const candidates = coerceProductCandidates(input);
|
|
95
|
+
if (!candidates) return void 0;
|
|
96
|
+
const sanitized = [];
|
|
97
|
+
for (const candidate of candidates) {
|
|
98
|
+
const entry = normalizeProductCandidate(candidate);
|
|
99
|
+
if (entry) sanitized.push(entry);
|
|
100
|
+
}
|
|
101
|
+
return sanitized.length > 0 ? sanitized : void 0;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Decode a `products` URL query param produced by
|
|
105
|
+
* `compressJsonToB64(productsArray)` — the encoding Klaviyo (and any
|
|
106
|
+
* other email tool) uses when embedding the product list of an order
|
|
107
|
+
* confirmation into a Frak share CTA.
|
|
108
|
+
*
|
|
109
|
+
* The result is run through `sanitizeProductList` so every link / image
|
|
110
|
+
* URL is structurally validated before reaching `new URL(...)` downstream.
|
|
111
|
+
* Malformed / tampered payloads degrade gracefully to `undefined` — the
|
|
112
|
+
* share still works, just without the product card section.
|
|
113
|
+
*/
|
|
114
|
+
function decodeProductsParam(value) {
|
|
115
|
+
if (!value) return void 0;
|
|
116
|
+
let decoded;
|
|
117
|
+
try {
|
|
118
|
+
decoded = decompressJsonFromB64(value);
|
|
119
|
+
} catch {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (decoded === null) return void 0;
|
|
123
|
+
return sanitizeProductList(decoded);
|
|
36
124
|
}
|
|
37
125
|
//#endregion
|
|
38
126
|
//#region src/bootstrap/clientReady.ts
|
|
@@ -97,15 +185,41 @@ async function doInit() {
|
|
|
97
185
|
handleActionQueryParam();
|
|
98
186
|
}
|
|
99
187
|
/**
|
|
100
|
-
* Check the query param
|
|
188
|
+
* Check the query param for an auto-opening of the Frak sharing page.
|
|
189
|
+
*
|
|
190
|
+
* Supported params (all optional except `frakAction`):
|
|
191
|
+
* - `frakAction=share` triggers the auto-open.
|
|
192
|
+
* - `link` overrides the URL the sharing page generates outbound shares for.
|
|
193
|
+
* When omitted, the listener falls back to the merchant domain.
|
|
194
|
+
* - `products` is a base64-encoded compressed JSON payload of
|
|
195
|
+
* `SharingPageProduct[]` — produced by `compressJsonToB64(productsArray)`
|
|
196
|
+
* on the sender side (e.g. a Klaviyo email template). Used by
|
|
197
|
+
* post-purchase emails to surface the items the customer just bought as
|
|
198
|
+
* product cards on the sharing page.
|
|
199
|
+
* - `placement` lets the caller scope backend-driven CSS / config to a
|
|
200
|
+
* specific placement (mirrors the prop on the components).
|
|
201
|
+
*
|
|
202
|
+
* The four params are stripped from the URL via `history.replaceState` as
|
|
203
|
+
* soon as they are read, so refreshes / shares of the current URL do not
|
|
204
|
+
* re-trigger the auto-open. Matches the `fmt` (merge token) and `sso`
|
|
205
|
+
* cleanup patterns elsewhere in the SDK.
|
|
101
206
|
*/
|
|
102
207
|
function handleActionQueryParam() {
|
|
103
|
-
const
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
208
|
+
const url = new URL(window.location.href);
|
|
209
|
+
if (url.searchParams.get("frakAction") !== "share") return;
|
|
210
|
+
console.log("[Frak SDK] Auto open share via query param");
|
|
211
|
+
const link = url.searchParams.get("link") ?? void 0;
|
|
212
|
+
const placement = url.searchParams.get("placement") ?? void 0;
|
|
213
|
+
const products = decodeProductsParam(url.searchParams.get("products"));
|
|
214
|
+
url.searchParams.delete("frakAction");
|
|
215
|
+
url.searchParams.delete("link");
|
|
216
|
+
url.searchParams.delete("placement");
|
|
217
|
+
url.searchParams.delete("products");
|
|
218
|
+
window.history.replaceState({}, "", url.toString());
|
|
219
|
+
openSharingPage(void 0, placement, {
|
|
220
|
+
link,
|
|
221
|
+
products
|
|
222
|
+
});
|
|
109
223
|
}
|
|
110
224
|
//#endregion
|
|
111
225
|
//#region src/utils/browser/onDocumentReady.ts
|
|
@@ -250,4 +364,4 @@ function usePlacement(placementId) {
|
|
|
250
364
|
return useMemo(() => placementId ? getPlacement(placementId) : void 0, [placementId, configVersion]);
|
|
251
365
|
}
|
|
252
366
|
//#endregion
|
|
253
|
-
export { registerWebComponent as a, useClientReady as i, buildStyleContent as n,
|
|
367
|
+
export { registerWebComponent as a, useClientReady as i, buildStyleContent as n, sanitizeProductList as o, lightDomBaseCss as r, openSharingPage as s, usePlacement as t };
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"url": "https://twitter.com/QNivelais"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
14
|
-
"version": "1.0.
|
|
14
|
+
"version": "1.0.5-beta.53162c2d",
|
|
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",
|
|
@@ -86,8 +86,8 @@
|
|
|
86
86
|
"publish": "echo 'Publishing components...'"
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"@frak-labs/core-sdk": "1.1.0",
|
|
90
|
-
"@frak-labs/frame-connector": "0.2.0",
|
|
89
|
+
"@frak-labs/core-sdk": "1.1.0-beta.53162c2d",
|
|
90
|
+
"@frak-labs/frame-connector": "0.2.0-beta.53162c2d",
|
|
91
91
|
"preact": "^10.29.0",
|
|
92
92
|
"preact-custom-element": "^4.6.0",
|
|
93
93
|
"@frak-labs/design-system": "0.0.0"
|
package/cdn/Banner.B1y3jwHv.js
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import{T as e,b as t,c as n,d as r,u as i,v as a}from"./loader.js";import{a as o,c as s,d as c,i as l,l as u,o as d,s as f,t as ee,u as p}from"./usePlacement.BgMXY5CX.js";import{a as m,i as h,n as g,r as te,t as _}from"./GiftIcon.eRNTGQ_r.js";import{t as v}from"./useGlobalComponents.TG9kIYSc.js";import{t as y}from"./useLightDomStyles.tjNBKcOr.js";import{t as b}from"./useReward.B530suzR.js";var x=`inAppBanner_body__1ibpiy75`,S=`inAppBanner_closeButton__1ibpiy78`,C=`inAppBanner_container__1ibpiy71`,w=`inAppBanner_cta__1ibpiy77`,T=`inAppBanner_description__1ibpiy76`,E=`inAppBanner_header__1ibpiy72`,D=`inAppBanner_iconWrapper__1ibpiy73`,O=`inAppBanner_title__1ibpiy74`;function k({title:e,description:t,cta:n,dismissLabel:r,onAction:i,onDismiss:a,className:o,classNames:s}){return p(`div`,{className:`${C}${o?` ${o}`:``}`,role:`alert`,children:[p(`div`,{className:E,children:[p(`span`,{className:`${D}${s?.icon?` ${s.icon}`:``}`,children:p(g,{width:20,height:20})}),p(`p`,{className:`${O}${s?.title?` ${s.title}`:``}`,children:e})]}),p(`div`,{className:x,children:[p(`p`,{className:`${T}${s?.description?` ${s.description}`:``}`,children:t}),p(`button`,{type:`button`,className:`${w}${s?.cta?` ${s.cta}`:``}`,onClick:i,children:[n,p(h,{width:14,height:14})]})]}),p(`button`,{type:`button`,className:`${S}${s?.close?` ${s.close}`:``}`,onClick:a,"aria-label":r,children:p(m,{width:16,height:16})})]})}var A=`Banner_frakLogo__1gnumzia`,j=`Banner_iconSvg__1gnumzi2`,M=`Banner_referral__1gnumzi3 reset_base__1831jhd0 Banner_rootBase__1gnumzi1`,N=`Banner_referralBody__1gnumzi6`,P=`Banner_referralCta__1gnumzi9 sharedBaseCss_buttonReset__7cswil0`,ne=`Banner_referralDescription__1gnumzi8 reset_base__1831jhd0`,F=`Banner_referralIconWrapper__1gnumzi4`,I=`Banner_referralImage__1gnumzi5`,L=`Banner_referralTitle__1gnumzi7 reset_base__1831jhd0`;function R({placement:c,classname:m=``,interaction:h,referralTitle:g,referralDescription:x,referralCta:S,inappTitle:C,inappDescription:w,inappCta:T,imageUrl:E,preview:D,previewMode:O}){let R=!!D,z=O===`inapp`?`inapp`:`referral`,B=ee(c),{shouldRender:V,isHidden:H,isClientReady:U}=l();y(`frak-banner`,c,B?.components?.banner?.css,`@keyframes inAppBanner_fadeIn__1ibpiy70 {
|
|
2
|
-
from {
|
|
3
|
-
opacity: 0;
|
|
4
|
-
transform: translateY(-4px);
|
|
5
|
-
}
|
|
6
|
-
to {
|
|
7
|
-
opacity: 1;
|
|
8
|
-
transform: translateY(0);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
.inAppBanner_container__1ibpiy71 {
|
|
12
|
-
position: fixed;
|
|
13
|
-
top: max(8px, env(safe-area-inset-top));
|
|
14
|
-
left: 16px;
|
|
15
|
-
right: 16px;
|
|
16
|
-
z-index: 1000;
|
|
17
|
-
display: flex;
|
|
18
|
-
flex-direction: column;
|
|
19
|
-
gap: 4px;
|
|
20
|
-
padding: 12px 16px;
|
|
21
|
-
padding-right: 32px;
|
|
22
|
-
border-radius: 12px;
|
|
23
|
-
background-color: #000000CC;
|
|
24
|
-
backdrop-filter: blur(12px);
|
|
25
|
-
-webkit-backdrop-filter: blur(12px);
|
|
26
|
-
color: #ffffff;
|
|
27
|
-
animation: inAppBanner_fadeIn__1ibpiy70 300ms ease-out;
|
|
28
|
-
}
|
|
29
|
-
.inAppBanner_header__1ibpiy72 {
|
|
30
|
-
display: flex;
|
|
31
|
-
align-items: center;
|
|
32
|
-
gap: 8px;
|
|
33
|
-
}
|
|
34
|
-
.inAppBanner_iconWrapper__1ibpiy73 {
|
|
35
|
-
flex-shrink: 0;
|
|
36
|
-
width: 20px;
|
|
37
|
-
height: 20px;
|
|
38
|
-
display: flex;
|
|
39
|
-
align-items: center;
|
|
40
|
-
justify-content: center;
|
|
41
|
-
color: #ffffff;
|
|
42
|
-
}
|
|
43
|
-
.inAppBanner_title__1ibpiy74 {
|
|
44
|
-
margin: 0;
|
|
45
|
-
padding: 0;
|
|
46
|
-
font-size: 16px;
|
|
47
|
-
font-weight: 500;
|
|
48
|
-
line-height: 26px;
|
|
49
|
-
color: var(--text-onAction__pbq4ak6);
|
|
50
|
-
}
|
|
51
|
-
.inAppBanner_body__1ibpiy75 {
|
|
52
|
-
display: flex;
|
|
53
|
-
flex-wrap: wrap;
|
|
54
|
-
align-items: baseline;
|
|
55
|
-
gap: 0 4px;
|
|
56
|
-
}
|
|
57
|
-
.inAppBanner_description__1ibpiy76 {
|
|
58
|
-
margin: 0;
|
|
59
|
-
padding: 0;
|
|
60
|
-
font-size: 14px;
|
|
61
|
-
color: var(--text-onAction__pbq4ak6);
|
|
62
|
-
line-height: 22px;
|
|
63
|
-
opacity: 0.96;
|
|
64
|
-
}
|
|
65
|
-
.inAppBanner_cta__1ibpiy77 {
|
|
66
|
-
all: unset;
|
|
67
|
-
display: inline-flex;
|
|
68
|
-
align-items: center;
|
|
69
|
-
gap: 4px;
|
|
70
|
-
color: #2BB2FF;
|
|
71
|
-
font-size: 14px;
|
|
72
|
-
font-weight: 600;
|
|
73
|
-
text-decoration: underline;
|
|
74
|
-
text-underline-offset: 2px;
|
|
75
|
-
cursor: pointer;
|
|
76
|
-
}
|
|
77
|
-
.inAppBanner_cta__1ibpiy77:focus-visible {
|
|
78
|
-
outline: 2px solid #2BB2FF;
|
|
79
|
-
outline-offset: 2px;
|
|
80
|
-
border-radius: 4px;
|
|
81
|
-
}
|
|
82
|
-
.inAppBanner_closeButton__1ibpiy78 {
|
|
83
|
-
all: unset;
|
|
84
|
-
position: absolute;
|
|
85
|
-
top: 8px;
|
|
86
|
-
right: 8px;
|
|
87
|
-
width: 28px;
|
|
88
|
-
height: 28px;
|
|
89
|
-
display: flex;
|
|
90
|
-
align-items: center;
|
|
91
|
-
justify-content: center;
|
|
92
|
-
border-radius: 9999px;
|
|
93
|
-
color: rgba(255, 255, 255, 0.6);
|
|
94
|
-
cursor: pointer;
|
|
95
|
-
}
|
|
96
|
-
.inAppBanner_closeButton__1ibpiy78:focus-visible {
|
|
97
|
-
outline: 2px solid #ffffff;
|
|
98
|
-
outline-offset: 2px;
|
|
99
|
-
}@keyframes Banner_fadeIn__1gnumzi0 {
|
|
100
|
-
from {
|
|
101
|
-
opacity: 0;
|
|
102
|
-
transform: translateY(-4px);
|
|
103
|
-
}
|
|
104
|
-
to {
|
|
105
|
-
opacity: 1;
|
|
106
|
-
transform: translateY(0);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
.Banner_rootBase__1gnumzi1 {
|
|
110
|
-
position: relative;
|
|
111
|
-
display: flex;
|
|
112
|
-
animation: Banner_fadeIn__1gnumzi0 300ms ease-out;
|
|
113
|
-
}
|
|
114
|
-
.Banner_iconSvg__1gnumzi2 {
|
|
115
|
-
width: 100%;
|
|
116
|
-
height: 100%;
|
|
117
|
-
}
|
|
118
|
-
.Banner_referral__1gnumzi3 {
|
|
119
|
-
flex-direction: row;
|
|
120
|
-
align-items: center;
|
|
121
|
-
gap: 16px;
|
|
122
|
-
padding: 16px;
|
|
123
|
-
background-color: #ffffff;
|
|
124
|
-
color: var(--text-primary__pbq4ak0);
|
|
125
|
-
border: 1px solid var(--border-default__pbq4akv);
|
|
126
|
-
border-radius: 12px;
|
|
127
|
-
}
|
|
128
|
-
.Banner_referralIconWrapper__1gnumzi4 {
|
|
129
|
-
flex-shrink: 0;
|
|
130
|
-
align-self: flex-start;
|
|
131
|
-
display: flex;
|
|
132
|
-
align-items: center;
|
|
133
|
-
justify-content: center;
|
|
134
|
-
width: 40px;
|
|
135
|
-
height: 40px;
|
|
136
|
-
overflow: hidden;
|
|
137
|
-
}
|
|
138
|
-
.Banner_referralImage__1gnumzi5 {
|
|
139
|
-
max-width: 100%;
|
|
140
|
-
max-height: 100%;
|
|
141
|
-
width: auto;
|
|
142
|
-
height: auto;
|
|
143
|
-
object-fit: contain;
|
|
144
|
-
display: block;
|
|
145
|
-
}
|
|
146
|
-
.Banner_referralBody__1gnumzi6 {
|
|
147
|
-
flex: 1;
|
|
148
|
-
min-width: 0;
|
|
149
|
-
}
|
|
150
|
-
.Banner_referralTitle__1gnumzi7 {
|
|
151
|
-
font-size: 16px;
|
|
152
|
-
font-weight: 600;
|
|
153
|
-
color: var(--text-primary__pbq4ak0);
|
|
154
|
-
line-height: 22px;
|
|
155
|
-
}
|
|
156
|
-
.Banner_referralDescription__1gnumzi8 {
|
|
157
|
-
margin-bottom: 8px;
|
|
158
|
-
font-size: 14px;
|
|
159
|
-
color: #979797;
|
|
160
|
-
line-height: 22px;
|
|
161
|
-
}
|
|
162
|
-
.Banner_referralCta__1gnumzi9 {
|
|
163
|
-
display: inline-block;
|
|
164
|
-
padding: 8px 16px;
|
|
165
|
-
border: 1px solid #000000;
|
|
166
|
-
border-radius: 9999px;
|
|
167
|
-
color: var(--text-primary__pbq4ak0);
|
|
168
|
-
font-size: 10px;
|
|
169
|
-
font-weight: 700;
|
|
170
|
-
line-height: 12px;
|
|
171
|
-
text-transform: uppercase;
|
|
172
|
-
}
|
|
173
|
-
.Banner_frakLogo__1gnumzia {
|
|
174
|
-
position: absolute;
|
|
175
|
-
right: 16px;
|
|
176
|
-
bottom: 12px;
|
|
177
|
-
pointer-events: none;
|
|
178
|
-
}`,e);let[W,G]=f(!1),[K,q]=f(()=>R?z:a?`inapp`:null),J=o(null);u(()=>{R&&q(z)},[R,z]);let{reward:Y}=b(K===`referral`&&U,h),[X,re]=f(null);u(()=>{let e=window.FrakSetup?.client;K!==`inapp`||R||!U||!e||n(e).then(e=>re(e)).catch(()=>{})},[K,R,U]),u(()=>{R||!K||W||J.current!==K&&U&&(t(window.FrakSetup?.client,`banner_impression`,{placement:c,variant:K,has_reward:K===`referral`?!!Y:void 0}),J.current=K)},[K,W,U,R,c]),u(()=>{if(R||K===`inapp`)return;let e=()=>q(`referral`);return window.addEventListener(i,e),()=>window.removeEventListener(i,e)},[R,K]);let Z=s(async()=>{if(R)return;if(t(window.FrakSetup?.client,`banner_resolved`,{placement:c,variant:K??`referral`,outcome:`clicked`}),K===`referral`){G(!0);return}let e=X;if(!e&&window.FrakSetup?.client)try{e=await n(window.FrakSetup?.client)}catch{}let i=window.location.href;if(e){let t=new URL(i);t.searchParams.set(`fmt`,e),i=t.toString()}r(i)},[R,K,X,c]),ie=s(()=>{R||(t(window.FrakSetup?.client,`banner_resolved`,{placement:c,variant:K??`referral`,outcome:`dismissed`}),G(!0))},[R,K,c]),ae=v(),Q=B?.components?.banner??ae?.banner,$=d(()=>{if(K===`referral`){let e=Y?`Earn ${Y} on purchases on this site`:`You've been referred!`;return{title:g??Q?.referralTitle??e,description:x??Q?.referralDescription??`Earn rewards after your purchase via the Frak partner app.`,cta:S??Q?.referralCta??`Got it`}}return{title:C??Q?.inappTitle??`Open in your browser`,description:w??Q?.inappDescription??`For a better experience and to earn your rewards, open this page in your default browser.`,cta:T??Q?.inappCta??`Open browser`}},[K,Y,Q,g,x,S,C,w,T]);if(!K||!R&&(!V||H||W))return null;let oe=[M,`frak-banner`,`frak-banner--${K}`,m].filter(Boolean).join(` `);return K===`inapp`?p(k,{title:$.title,description:$.description,cta:$.cta,dismissLabel:`Dismiss`,onAction:Z,onDismiss:ie,className:[`frak-banner`,`frak-banner--inapp`,m].filter(Boolean).join(` `),classNames:{icon:`frak-banner__icon`,title:`frak-banner__title`,description:`frak-banner__description`,cta:`frak-banner__cta`,close:`frak-banner__close`}}):p(`div`,{class:oe,role:`alert`,children:[p(`div`,{class:`${F} frak-banner__icon`,children:E?p(`img`,{src:E,alt:``,class:I}):p(_,{class:j})}),p(`div`,{class:`${N} frak-banner__text`,children:[p(`p`,{class:`${L} frak-banner__title`,children:$.title}),p(`p`,{class:`${ne} frak-banner__description`,children:$.description}),p(`button`,{type:`button`,class:`${P} frak-banner__cta`,onClick:Z,children:$.cta})]}),p(te,{class:`${A} frak-banner__logo`,width:42,height:24})]})}c(R,`frak-banner`,[`placement`,`classname`,`interaction`,`referralTitle`,`referralDescription`,`referralCta`,`inappTitle`,`inappDescription`,`inappCta`,`preview`,`previewMode`,`imageUrl`],{shadow:!1});export{R as Banner};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{b as e,i as t}from"./loader.js";import{c as n,d as r,i,o as a,t as o,u as s}from"./usePlacement.BgMXY5CX.js";import{t as c}from"./useGlobalComponents.TG9kIYSc.js";import{t as l}from"./useLightDomStyles.tjNBKcOr.js";import{t as u}from"./formatReward.B1ZyoceC.js";import{t as d}from"./useReward.B530suzR.js";import{t as f}from"./sharingPage.BYsqcN9O.js";function p({placement:r,text:p=`Share and earn!`,classname:m=``,useReward:h,noRewardText:g,targetInteraction:_,clickAction:v,preview:y}){let b=!!y,x=o(r),S=c(),C=x?.components?.buttonShare??S?.buttonShare;l(`frak-button-share`,r,C?.css);let w=a(()=>x?.targetInteraction===void 0?_:x.targetInteraction,[x?.targetInteraction,_]),T=C?.text??p,E=C?.noRewardText??g,D=a(()=>C?.useReward??h===!0,[C?.useReward,h]),O=a(()=>C?.clickAction??v??`sharing-page`,[C?.clickAction,v]),{shouldRender:k,isHidden:A,isClientReady:j}=i(),{reward:M}=d(D&&j,w),N=a(()=>D?M?T.includes(`{REWARD}`)?u(T,M):`${T} ${M}`:E??u(T,void 0):T,[D,T,E,M]),P=n(()=>{if(!b){if(e(window.FrakSetup.client,`share_button_clicked`,{placement:r,target_interaction:w,has_reward:!!M,click_action:O}),O===`embedded-wallet`){t(w,r);return}f(w,r)}},[b,O,w,r,M]);if(!b&&(!k||A))return null;let F=[`button`,`button__fadeIn`,m].filter(Boolean).join(` `);return s(`button`,{type:`button`,disabled:!b&&!j,class:F,onClick:P,children:N})}r(p,`frak-button-share`,[`text`,`placement`,`classname`,`clickAction`,`useReward`,`noRewardText`,`targetInteraction`,`preview`],{shadow:!1});export{p as ButtonShare};
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./loader.js";import{d as t,i as n,l as r,m as i,n as a,o,s,t as c,u as l}from"./usePlacement.BgMXY5CX.js";import{t as u}from"./useReward.B530suzR.js";function d(e){return l(`svg`,{fill:`none`,height:`1em`,viewBox:`0 0 28 28`,width:`1em`,xmlns:`http://www.w3.org/2000/svg`,...e,children:[l(`title`,{children:`Gift icon`}),l(`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`})]})}function f({placement:t,classname:f=``,useReward:p,targetInteraction:m}){let h=c(t),g=o(()=>h?.targetInteraction===void 0?m:h.targetInteraction,[h?.targetInteraction,m]),_=o(()=>p===!0,[p]),{shouldRender:v,isHidden:y,isClientReady:b}=n(),{reward:x}=u(_&&b,g),[S,C]=s(`right`);if(r(()=>{let e=h?.components?.buttonWallet?.position,t=window.FrakSetup?.modalWalletConfig?.metadata?.position;C(e??t??`right`)},[h?.components?.buttonWallet?.position]),!v||y)return null;let w=[`button`,`button__fadeIn`,S===`left`?`button__left`:`button__right`,f].filter(Boolean).join(` `);return l(i,{children:[l(`style`,{children:a(`
|
|
2
|
-
.button {
|
|
3
|
-
all: unset;
|
|
4
|
-
position: fixed;
|
|
5
|
-
bottom: 20px;
|
|
6
|
-
z-index: 2000000;
|
|
7
|
-
display: flex;
|
|
8
|
-
justify-content: center;
|
|
9
|
-
align-items: center;
|
|
10
|
-
background-color: #3e557e;
|
|
11
|
-
width: 45px;
|
|
12
|
-
height: 45px;
|
|
13
|
-
border-radius: 50%;
|
|
14
|
-
cursor: pointer;
|
|
15
|
-
text-align: center;
|
|
16
|
-
font-size: 24px;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
.button__left {
|
|
20
|
-
left: 20px;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
.button__right {
|
|
24
|
-
right: 20px;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.reward {
|
|
28
|
-
position: absolute;
|
|
29
|
-
top: -4px;
|
|
30
|
-
right: 27px;
|
|
31
|
-
padding: 2px 3px;
|
|
32
|
-
border-radius: 5px;
|
|
33
|
-
background: #ff3f3f;
|
|
34
|
-
font-size: 9px;
|
|
35
|
-
color: #fff;
|
|
36
|
-
font-weight: 600;
|
|
37
|
-
white-space: nowrap;
|
|
38
|
-
line-height: 9px;
|
|
39
|
-
}
|
|
40
|
-
`,h?.components?.buttonWallet?.css)}),l(`button`,{type:`button`,"aria-label":`Open wallet`,part:`button`,disabled:!b,class:w,onClick:()=>{e(g,t)},children:[l(d,{}),x&&l(`span`,{class:`reward`,children:x})]})]})}t(f,`frak-button-wallet`,[`placement`,`classname`,`useReward`,`targetInteraction`],{shadow:!0});export{f as ButtonWallet};
|