@frak-labs/components 0.0.26 → 1.0.0-beta.7f085fb7

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 (46) hide show
  1. package/cdn/Banner.Ws9o79lU.js +64 -0
  2. package/cdn/ButtonShare.BDS1fgma.js +1 -0
  3. package/cdn/ButtonWallet.Be1UyRm8.js +40 -0
  4. package/cdn/OpenInAppButton.Diqt07eo.js +1 -0
  5. package/cdn/PostPurchase.DqFhm-Jn.js +52 -0
  6. package/cdn/components.js +1 -1
  7. package/cdn/formatReward.CXxVsWN3.js +1 -0
  8. package/cdn/loader.css +0 -14
  9. package/cdn/loader.js +14 -1
  10. package/cdn/sprinkles.css.ts.vanilla.BtFkD4B3.js +1175 -0
  11. package/cdn/useGlobalComponents.BRe8dKO7.js +1 -0
  12. package/cdn/useLightDomStyles.ZFa154u8.js +1 -0
  13. package/cdn/usePlacement.B7jMsQvP.js +58 -0
  14. package/cdn/useReward.qEKeySJG.js +1 -0
  15. package/cdn/useShareModal.B--64ELG.js +1 -0
  16. package/dist/GiftIcon-4sr9xXyq.js +1501 -0
  17. package/dist/banner.d.ts +116 -0
  18. package/dist/banner.js +431 -0
  19. package/dist/buttonShare.d.ts +8 -6
  20. package/dist/buttonShare.js +63 -101
  21. package/dist/buttonWallet.d.ts +10 -2
  22. package/dist/buttonWallet.js +79 -38
  23. package/dist/formatReward-Bub6Z6eY.js +33 -0
  24. package/dist/openInApp.d.ts +4 -2
  25. package/dist/openInApp.js +23 -27
  26. package/dist/postPurchase.d.ts +122 -0
  27. package/dist/postPurchase.js +1579 -0
  28. package/dist/useGlobalComponents-Cmfszr7v.js +21 -0
  29. package/dist/useLightDomStyles-hgYYZsTy.js +41 -0
  30. package/dist/usePlacement-LqYjZLX_.js +248 -0
  31. package/dist/useReward-DU3_yP8Q.js +65 -0
  32. package/dist/useShareModal-DgEf5WWG.js +53 -0
  33. package/package.json +29 -20
  34. package/cdn/ButtonShare.CqRLxX5u.js +0 -1
  35. package/cdn/ButtonWallet.ToH_g8FC.js +0 -1
  36. package/cdn/OpenInAppButton.BMZnXQLT.js +0 -1
  37. package/cdn/Spinner.DRiAlyyq.js +0 -1
  38. package/cdn/initFrakSdk.CA6zXtGT.js +0 -14
  39. package/cdn/useClientReady.DskSqlAg.js +0 -1
  40. package/dist/Spinner-1CZC_zy6.js +0 -36
  41. package/dist/Spinner-CHZD3tMn.css +0 -1
  42. package/dist/buttonShare.css +0 -1
  43. package/dist/buttonWallet.css +0 -1
  44. package/dist/openInApp.css +0 -1
  45. package/dist/useClientReady-iCtUeDsc.js +0 -197
  46. package/dist/useReward-DAkT-7wT.js +0 -48
@@ -1,17 +1,21 @@
1
- import { n as registerWebComponent, r as getModalBuilderSteps, t as useClientReady } from "./useClientReady-iCtUeDsc.js";
2
- import { t as Spinner } from "./Spinner-1CZC_zy6.js";
3
- import { t as useReward } from "./useReward-DAkT-7wT.js";
4
- import { DebugInfoGatherer, trackEvent } from "@frak-labs/core-sdk";
5
- import { displayEmbeddedWallet } from "@frak-labs/core-sdk/actions";
6
- import { cx } from "class-variance-authority";
1
+ import { a as registerWebComponent, i as useClientReady, s as openEmbeddedWallet, t as usePlacement } from "./usePlacement-LqYjZLX_.js";
2
+ import { t as useGlobalComponents } from "./useGlobalComponents-Cmfszr7v.js";
3
+ import { t as useLightDomStyles } from "./useLightDomStyles-hgYYZsTy.js";
4
+ import { t as applyRewardPlaceholder } from "./formatReward-Bub6Z6eY.js";
5
+ import { t as useReward } from "./useReward-DU3_yP8Q.js";
6
+ import { t as useShareModal } from "./useShareModal-DgEf5WWG.js";
7
+ import { trackEvent } from "@frak-labs/core-sdk";
8
+ import { displaySharingPage } from "@frak-labs/core-sdk/actions";
7
9
  import { useCallback, useMemo, useState } from "preact/hooks";
8
10
  import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
9
- import { FrakRpcError, RpcErrorCodes } from "@frak-labs/frame-connector";
10
-
11
- //#region src/components/ButtonShare/ButtonShare.module.css?css_module
12
- const classes = { "buttonShare": "nOB7Uq_buttonShare" };
13
- const _buttonShare0 = classes["buttonShare"];
14
-
11
+ //#region src/utils/sharingPage.ts
12
+ async function openSharingPage(targetInteraction, placement) {
13
+ if (!window.FrakSetup?.client) {
14
+ console.error("Frak client not found");
15
+ return;
16
+ }
17
+ await displaySharingPage(window.FrakSetup.client, { metadata: { ...targetInteraction && { targetInteraction } } }, placement);
18
+ }
15
19
  //#endregion
16
20
  //#region src/hooks/useCopyToClipboard.ts
17
21
  function useCopyToClipboard(options = {}) {
@@ -53,7 +57,6 @@ function useCopyToClipboard(options = {}) {
53
57
  copied
54
58
  };
55
59
  }
56
-
57
60
  //#endregion
58
61
  //#region src/components/ButtonShare/components/ErrorMessage.tsx
59
62
  const styles = {
@@ -164,66 +167,9 @@ function ErrorMessage({ debugInfo }) {
164
167
  ]
165
168
  });
166
169
  }
167
-
168
- //#endregion
169
- //#region src/components/ButtonShare/hooks/useShareModal.ts
170
- /**
171
- * Open the share modal
172
- *
173
- * @description
174
- * This function will open the share modal with the configuration provided in the `window.FrakSetup.modalShareConfig` object.
175
- */
176
- function useShareModal(targetInteraction) {
177
- const [debugInfo, setDebugInfo] = useState(void 0);
178
- const [isError, setIsError] = useState(false);
179
- return {
180
- handleShare: useCallback(async () => {
181
- if (!window.FrakSetup?.client) {
182
- console.error("Frak client not found");
183
- setDebugInfo(DebugInfoGatherer.empty().formatDebugInfo("Frak client not found"));
184
- setIsError(true);
185
- return;
186
- }
187
- const modalBuilderSteps = getModalBuilderSteps();
188
- if (!modalBuilderSteps) throw new Error("modalBuilderSteps not found");
189
- try {
190
- await modalBuilderSteps.sharing(window.FrakSetup?.modalShareConfig ?? {}).display((metadata) => ({
191
- ...metadata,
192
- targetInteraction
193
- }));
194
- } catch (e) {
195
- if (e instanceof FrakRpcError && e.code === RpcErrorCodes.clientAborted) {
196
- console.debug("User aborted the modal");
197
- return;
198
- }
199
- const debugInfo = window.FrakSetup.client.debugInfo.formatDebugInfo(e);
200
- trackEvent(window.FrakSetup.client, "share_modal_error", {
201
- error: e instanceof Object && "message" in e ? e.message : "Unknown error",
202
- debugInfo
203
- });
204
- setDebugInfo(debugInfo);
205
- setIsError(true);
206
- console.error("Error while opening the modal", e);
207
- }
208
- }, [targetInteraction]),
209
- isError,
210
- debugInfo
211
- };
212
- }
213
-
214
170
  //#endregion
215
171
  //#region src/components/ButtonShare/ButtonShare.tsx
216
172
  /**
217
- * Open the embedded wallet modal
218
- *
219
- * @description
220
- * This function will open the wallet modal with the configuration provided in the `window.FrakSetup.modalWalletConfig` object.
221
- */
222
- async function modalEmbeddedWallet() {
223
- if (!window.FrakSetup?.client) throw new Error("Frak client not found");
224
- await displayEmbeddedWallet(window.FrakSetup.client, window.FrakSetup?.modalWalletConfig ?? {});
225
- }
226
- /**
227
173
  * Button to share the current page
228
174
  *
229
175
  * @param args
@@ -264,48 +210,64 @@ async function modalEmbeddedWallet() {
264
210
  * @see {@link @frak-labs/core-sdk!actions.modalBuilder | `modalBuilder()`} for more info about the modal display
265
211
  * @see {@link @frak-labs/core-sdk!actions.getMerchantInformation | `getMerchantInformation()`} for more info about the estimated reward fetching
266
212
  */
267
- function ButtonShare({ text = "Share and earn!", classname = "", useReward: rawUseReward, noRewardText, targetInteraction, showWallet: rawShowWallet }) {
268
- const shouldUseReward = useMemo(() => rawUseReward !== void 0, [rawUseReward]);
269
- const showWallet = useMemo(() => rawShowWallet !== void 0, [rawShowWallet]);
270
- const { isClientReady } = useClientReady();
271
- const { reward } = useReward(shouldUseReward && isClientReady, targetInteraction);
272
- const { handleShare, isError, debugInfo } = useShareModal(targetInteraction);
273
- /**
274
- * Compute the text we will display
275
- */
213
+ function ButtonShare({ placement: placementId, text = "Share and earn!", classname = "", useReward: rawUseReward, noRewardText, targetInteraction, clickAction: rawClickAction }) {
214
+ const placement = usePlacement(placementId);
215
+ const globalComponents = useGlobalComponents();
216
+ const componentConfig = placement?.components?.buttonShare ?? globalComponents?.buttonShare;
217
+ useLightDomStyles("frak-button-share", placementId, componentConfig?.css);
218
+ const resolvedTargetInteraction = useMemo(() => placement?.targetInteraction !== void 0 ? placement.targetInteraction : targetInteraction, [placement?.targetInteraction, targetInteraction]);
219
+ const resolvedText = componentConfig?.text ?? text;
220
+ const resolvedNoRewardText = componentConfig?.noRewardText ?? noRewardText;
221
+ const shouldUseReward = useMemo(() => componentConfig?.useReward ?? rawUseReward === true, [componentConfig?.useReward, rawUseReward]);
222
+ const resolvedClickAction = useMemo(() => componentConfig?.clickAction ?? rawClickAction ?? "sharing-page", [componentConfig?.clickAction, rawClickAction]);
223
+ const { shouldRender, isHidden, isClientReady } = useClientReady();
224
+ const { reward } = useReward(shouldUseReward && isClientReady, resolvedTargetInteraction);
225
+ const { handleShare, isError, debugInfo } = useShareModal(resolvedTargetInteraction, placementId);
276
226
  const btnText = useMemo(() => {
277
- if (!shouldUseReward) return text;
278
- if (!reward) return noRewardText ?? text.replace("{REWARD}", "");
279
- return text.includes("{REWARD}") ? text.replace("{REWARD}", reward) : `${text} ${reward}`;
227
+ if (!shouldUseReward) return resolvedText;
228
+ if (!reward) return resolvedNoRewardText ?? applyRewardPlaceholder(resolvedText, void 0);
229
+ return resolvedText.includes("{REWARD}") ? applyRewardPlaceholder(resolvedText, reward) : `${resolvedText} ${reward}`;
280
230
  }, [
281
231
  shouldUseReward,
282
- text,
283
- noRewardText,
232
+ resolvedText,
233
+ resolvedNoRewardText,
284
234
  reward
285
235
  ]);
286
- /**
287
- * The action when the button is clicked
288
- */
289
236
  const onClick = useCallback(async () => {
290
237
  trackEvent(window.FrakSetup.client, "share_button_clicked");
291
- if (showWallet) await modalEmbeddedWallet();
292
- else await handleShare();
293
- }, [showWallet, handleShare]);
294
- return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("button", {
238
+ if (resolvedClickAction === "embedded-wallet") openEmbeddedWallet(resolvedTargetInteraction, placementId);
239
+ else if (resolvedClickAction === "share-modal") await handleShare();
240
+ else openSharingPage(resolvedTargetInteraction, placementId);
241
+ }, [
242
+ resolvedClickAction,
243
+ handleShare,
244
+ resolvedTargetInteraction,
245
+ placementId
246
+ ]);
247
+ if (!shouldRender || isHidden) return null;
248
+ const buttonClass = [
249
+ "button",
250
+ "button__fadeIn",
251
+ classname
252
+ ].filter(Boolean).join(" ");
253
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("button", {
295
254
  type: "button",
296
- className: cx(classes.buttonShare, classname, "override"),
255
+ disabled: !isClientReady,
256
+ class: buttonClass,
297
257
  onClick,
298
- children: [
299
- !isClientReady && /* @__PURE__ */ jsx(Spinner, {}),
300
- " ",
301
- btnText
302
- ]
258
+ children: btnText
303
259
  }), isError && /* @__PURE__ */ jsx(ErrorMessage, { debugInfo })] });
304
260
  }
305
-
306
261
  //#endregion
307
262
  //#region src/components/ButtonShare/index.ts
308
- registerWebComponent(ButtonShare, "frak-button-share", ["text"], { shadow: false });
309
-
263
+ registerWebComponent(ButtonShare, "frak-button-share", [
264
+ "text",
265
+ "placement",
266
+ "classname",
267
+ "clickAction",
268
+ "useReward",
269
+ "noRewardText",
270
+ "targetInteraction"
271
+ ], { shadow: false });
310
272
  //#endregion
311
- export { ButtonShare };
273
+ export { ButtonShare };
@@ -1,5 +1,5 @@
1
1
  import { InteractionTypeKey } from "@frak-labs/core-sdk";
2
- import * as preact from "preact";
2
+ import * as _$preact from "preact";
3
3
 
4
4
  //#region src/components/ButtonWallet/types.d.ts
5
5
  /**
@@ -7,6 +7,7 @@ import * as preact from "preact";
7
7
  * @inline
8
8
  */
9
9
  type ButtonWalletProps = {
10
+ placement?: string;
10
11
  /**
11
12
  * Classname to apply to the button
12
13
  */
@@ -55,14 +56,21 @@ type ButtonWalletProps = {
55
56
  * <frak-button-wallet use-reward target-interaction="custom.customerMeeting"></frak-button-wallet>
56
57
  * ```
57
58
  *
59
+ * @example
60
+ * Using placement:
61
+ * ```html
62
+ * <frak-button-wallet placement="hero-wallet"></frak-button-wallet>
63
+ * ```
64
+ *
58
65
  * @see {@link @frak-labs/core-sdk!actions.modalBuilder | `modalBuilder()`} for more info about the modal display
59
66
  * @see {@link @frak-labs/core-sdk!actions.getMerchantInformation | `getMerchantInformation()`} for more info about the estimated reward fetching
60
67
  */
61
68
  declare function ButtonWallet({
69
+ placement: placementId,
62
70
  classname,
63
71
  useReward: rawUseReward,
64
72
  targetInteraction
65
- }: ButtonWalletProps): preact.JSX.Element;
73
+ }: ButtonWalletProps): _$preact.JSX.Element | null;
66
74
  //#endregion
67
75
  //#region src/components/ButtonWallet/index.d.ts
68
76
  /**
@@ -1,10 +1,8 @@
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";
1
+ import { a as registerWebComponent, i as useClientReady, n as buildStyleContent, o as openWalletModal, t as usePlacement } from "./usePlacement-LqYjZLX_.js";
2
+ import { t as useReward } from "./useReward-DU3_yP8Q.js";
3
3
  import { trackEvent } from "@frak-labs/core-sdk";
4
- import { cx } from "class-variance-authority";
5
4
  import { useEffect, useMemo, useState } from "preact/hooks";
6
- import { jsx, jsxs } from "preact/jsx-runtime";
7
-
5
+ import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
8
6
  //#region src/components/ButtonWallet/assets/GiftIcon.tsx
9
7
  function GiftIcon(props) {
10
8
  return /* @__PURE__ */ jsxs("svg", {
@@ -22,22 +20,48 @@ function GiftIcon(props) {
22
20
  })]
23
21
  });
24
22
  }
25
-
26
- //#endregion
27
- //#region src/components/ButtonWallet/ButtonWallet.module.css?css_module
28
- const classes = {
29
- "reward": "Kl62ia_reward",
30
- "button__left": "Kl62ia_button__left",
31
- "button": "Kl62ia_button",
32
- "button__right": "Kl62ia_button__right"
33
- };
34
- const _reward0 = classes["reward"];
35
- const _button__left0 = classes["button__left"];
36
- const _button0 = classes["button"];
37
- const _button__right0 = classes["button__right"];
38
-
39
23
  //#endregion
40
24
  //#region src/components/ButtonWallet/ButtonWallet.tsx
25
+ const componentCss = `
26
+ .button {
27
+ all: unset;
28
+ position: fixed;
29
+ bottom: 20px;
30
+ z-index: 2000000;
31
+ display: flex;
32
+ justify-content: center;
33
+ align-items: center;
34
+ background-color: #3e557e;
35
+ width: 45px;
36
+ height: 45px;
37
+ border-radius: 50%;
38
+ cursor: pointer;
39
+ text-align: center;
40
+ font-size: 24px;
41
+ }
42
+
43
+ .button__left {
44
+ left: 20px;
45
+ }
46
+
47
+ .button__right {
48
+ right: 20px;
49
+ }
50
+
51
+ .reward {
52
+ position: absolute;
53
+ top: -4px;
54
+ right: 27px;
55
+ padding: 2px 3px;
56
+ border-radius: 5px;
57
+ background: #ff3f3f;
58
+ font-size: 9px;
59
+ color: #fff;
60
+ font-weight: 600;
61
+ white-space: nowrap;
62
+ line-height: 9px;
63
+ }
64
+ `;
41
65
  /**
42
66
  * Button to open wallet modal
43
67
  *
@@ -70,40 +94,57 @@ const _button__right0 = classes["button__right"];
70
94
  * <frak-button-wallet use-reward target-interaction="custom.customerMeeting"></frak-button-wallet>
71
95
  * ```
72
96
  *
97
+ * @example
98
+ * Using placement:
99
+ * ```html
100
+ * <frak-button-wallet placement="hero-wallet"></frak-button-wallet>
101
+ * ```
102
+ *
73
103
  * @see {@link @frak-labs/core-sdk!actions.modalBuilder | `modalBuilder()`} for more info about the modal display
74
104
  * @see {@link @frak-labs/core-sdk!actions.getMerchantInformation | `getMerchantInformation()`} for more info about the estimated reward fetching
75
105
  */
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);
106
+ function ButtonWallet({ placement: placementId, classname = "", useReward: rawUseReward, targetInteraction }) {
107
+ const placement = usePlacement(placementId);
108
+ const resolvedTargetInteraction = useMemo(() => placement?.targetInteraction !== void 0 ? placement.targetInteraction : targetInteraction, [placement?.targetInteraction, targetInteraction]);
109
+ const shouldUseReward = useMemo(() => rawUseReward === true, [rawUseReward]);
110
+ const { shouldRender, isHidden, isClientReady } = useClientReady();
111
+ const { reward } = useReward(shouldUseReward && isClientReady, resolvedTargetInteraction);
80
112
  const [position, setPosition] = useState("right");
81
- /**
82
- * Setup the position of the button
83
- */
84
113
  useEffect(() => {
85
- const position = window.FrakSetup?.modalWalletConfig?.metadata?.position;
86
- setPosition(position ?? "right");
87
- }, []);
88
- return /* @__PURE__ */ jsxs("button", {
114
+ const placementPosition = placement?.components?.buttonWallet?.position;
115
+ const configPosition = window.FrakSetup?.modalWalletConfig?.metadata?.position;
116
+ setPosition(placementPosition ?? configPosition ?? "right");
117
+ }, [placement?.components?.buttonWallet?.position]);
118
+ if (!shouldRender || isHidden) return null;
119
+ const buttonClass = [
120
+ "button",
121
+ "button__fadeIn",
122
+ position === "left" ? "button__left" : "button__right",
123
+ classname
124
+ ].filter(Boolean).join(" ");
125
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("style", { children: buildStyleContent(componentCss, placement?.components?.buttonWallet?.css) }), /* @__PURE__ */ jsxs("button", {
89
126
  type: "button",
90
127
  "aria-label": "Open wallet",
91
- class: cx(classes.button, position === "left" ? classes.button__left : classes.button__right, classname, "override"),
128
+ part: "button",
92
129
  disabled: !isClientReady,
130
+ class: buttonClass,
93
131
  onClick: () => {
94
132
  trackEvent(window.FrakSetup.client, "wallet_button_clicked");
95
- openWalletModal();
133
+ openWalletModal(resolvedTargetInteraction, placementId);
96
134
  },
97
135
  children: [/* @__PURE__ */ jsx(GiftIcon, {}), reward && /* @__PURE__ */ jsx("span", {
98
- className: classes.reward,
136
+ class: "reward",
99
137
  children: reward
100
138
  })]
101
- });
139
+ })] });
102
140
  }
103
-
104
141
  //#endregion
105
142
  //#region src/components/ButtonWallet/index.ts
106
- registerWebComponent(ButtonWallet, "frak-button-wallet", [], { shadow: false });
107
-
143
+ registerWebComponent(ButtonWallet, "frak-button-wallet", [
144
+ "placement",
145
+ "classname",
146
+ "useReward",
147
+ "targetInteraction"
148
+ ], { shadow: true });
108
149
  //#endregion
109
- export { ButtonWallet };
150
+ export { ButtonWallet };
@@ -0,0 +1,33 @@
1
+ import { formatAmount, getCurrencyAmountKey, getSupportedCurrency } from "@frak-labs/core-sdk";
2
+ //#region src/utils/formatReward.ts
3
+ /**
4
+ * Format an {@link EstimatedReward} into a human-readable string.
5
+ *
6
+ * - `fixed` → e.g. `"5 €"`
7
+ * - `percentage` → if `basketAmount` is provided, computes the actual value
8
+ * (e.g. `"10 €"`), otherwise returns `"10 %"`
9
+ * - `tiered` → max tier value, e.g. `"50 €"`
10
+ */
11
+ function formatEstimatedReward(reward, currency, basketAmount) {
12
+ const supportedCurrency = getSupportedCurrency(currency);
13
+ const key = getCurrencyAmountKey(supportedCurrency);
14
+ switch (reward.payoutType) {
15
+ case "fixed": return formatAmount(Math.round(reward.amount[key]), supportedCurrency);
16
+ case "percentage":
17
+ if (basketAmount !== void 0) return formatAmount(Math.round(reward.percent * basketAmount / 100), supportedCurrency);
18
+ return `${reward.percent} %`;
19
+ case "tiered": {
20
+ const max = reward.tiers.reduce((acc, tier) => Math.max(acc, tier.amount[key]), 0);
21
+ return formatAmount(Math.round(max), supportedCurrency);
22
+ }
23
+ }
24
+ }
25
+ /**
26
+ * Replace the `{REWARD}` placeholder in a text string with a reward value.
27
+ * If no reward is provided, returns the text with `{REWARD}` stripped.
28
+ */
29
+ function applyRewardPlaceholder(text, reward) {
30
+ return reward ? text.replace("{REWARD}", reward) : text.replace("{REWARD}", "");
31
+ }
32
+ //#endregion
33
+ export { formatEstimatedReward as n, applyRewardPlaceholder as t };
@@ -1,4 +1,4 @@
1
- import * as preact from "preact";
1
+ import * as _$preact from "preact";
2
2
 
3
3
  //#region src/components/OpenInAppButton/types.d.ts
4
4
  /**
@@ -6,6 +6,7 @@ import * as preact from "preact";
6
6
  * @inline
7
7
  */
8
8
  type OpenInAppButtonProps = {
9
+ placement?: string;
9
10
  /**
10
11
  * Text to display on the button
11
12
  * @defaultValue `"Open in App"`
@@ -45,9 +46,10 @@ type OpenInAppButtonProps = {
45
46
  * ```
46
47
  */
47
48
  declare function OpenInAppButton({
49
+ placement: placementId,
48
50
  text,
49
51
  classname
50
- }: OpenInAppButtonProps): preact.JSX.Element | null;
52
+ }: OpenInAppButtonProps): _$preact.JSX.Element | null;
51
53
  //#endregion
52
54
  //#region src/components/OpenInAppButton/index.d.ts
53
55
  /**
package/dist/openInApp.js CHANGED
@@ -1,10 +1,8 @@
1
- import { n as registerWebComponent, t as useClientReady } from "./useClientReady-iCtUeDsc.js";
2
- import { t as Spinner } from "./Spinner-1CZC_zy6.js";
1
+ import { a as registerWebComponent, i as useClientReady, t as usePlacement } from "./usePlacement-LqYjZLX_.js";
2
+ import { t as useLightDomStyles } from "./useLightDomStyles-hgYYZsTy.js";
3
3
  import { DEEP_LINK_SCHEME, trackEvent, triggerDeepLinkWithFallback } from "@frak-labs/core-sdk";
4
- import { cx } from "class-variance-authority";
5
4
  import { useMemo } from "preact/hooks";
6
- import { jsx, jsxs } from "preact/jsx-runtime";
7
-
5
+ import { jsx } from "preact/jsx-runtime";
8
6
  //#region src/utils/isMobile.ts
9
7
  /**
10
8
  * Check if the current device is a mobile device
@@ -21,13 +19,11 @@ function isMobile() {
21
19
  if (/Macintosh/i.test(navigator.userAgent) && navigator.maxTouchPoints > 1) return true;
22
20
  return false;
23
21
  }
24
-
25
22
  //#endregion
26
23
  //#region src/hooks/useIsMobile.ts
27
24
  function useIsMobile() {
28
25
  return { isMobile: useMemo(() => isMobile(), []) };
29
26
  }
30
-
31
27
  //#endregion
32
28
  //#region src/utils/openInApp.ts
33
29
  const DEFAULT_PATH = "wallet";
@@ -47,12 +43,6 @@ function openFrakWalletApp(path = DEFAULT_PATH) {
47
43
  if (client) trackEvent(client, "app_not_installed");
48
44
  } });
49
45
  }
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
46
  //#endregion
57
47
  //#region src/components/OpenInAppButton/OpenInAppButton.tsx
58
48
  /**
@@ -81,30 +71,36 @@ const _button0 = classes["button"];
81
71
  * <frak-open-in-app classname="button button-primary"></frak-open-in-app>
82
72
  * ```
83
73
  */
84
- function OpenInAppButton({ text = "Open in App", classname = "" }) {
85
- const { isClientReady } = useClientReady();
74
+ function OpenInAppButton({ placement: placementId, text = "Open in App", classname = "" }) {
75
+ const placement = usePlacement(placementId);
76
+ const { shouldRender, isHidden, isClientReady } = useClientReady();
86
77
  const { isMobile } = useIsMobile();
87
- if (!isMobile) return null;
78
+ useLightDomStyles("frak-open-in-app", placementId, placement?.components?.openInApp?.css);
79
+ const resolvedText = placement?.components?.openInApp?.text ?? text;
80
+ if (!isMobile || !shouldRender || isHidden) return null;
88
81
  const handleClick = () => {
89
82
  openFrakWalletApp();
90
83
  };
91
- return /* @__PURE__ */ jsxs("button", {
84
+ const buttonClass = [
85
+ "button",
86
+ "button__fadeIn",
87
+ classname
88
+ ].filter(Boolean).join(" ");
89
+ return /* @__PURE__ */ jsx("button", {
92
90
  type: "button",
93
91
  "aria-label": "Open in Frak Wallet app",
94
- className: cx(classes.button, classname, "override"),
95
92
  disabled: !isClientReady,
93
+ class: buttonClass,
96
94
  onClick: handleClick,
97
- children: [
98
- !isClientReady && /* @__PURE__ */ jsx(Spinner, {}),
99
- " ",
100
- text
101
- ]
95
+ children: resolvedText
102
96
  });
103
97
  }
104
-
105
98
  //#endregion
106
99
  //#region src/components/OpenInAppButton/index.ts
107
- registerWebComponent(OpenInAppButton, "frak-open-in-app", ["text"], { shadow: false });
108
-
100
+ registerWebComponent(OpenInAppButton, "frak-open-in-app", [
101
+ "text",
102
+ "placement",
103
+ "classname"
104
+ ], { shadow: false });
109
105
  //#endregion
110
- export { OpenInAppButton };
106
+ export { OpenInAppButton };
@@ -0,0 +1,122 @@
1
+ import * as _$preact from "preact";
2
+
3
+ //#region src/components/PostPurchase/types.d.ts
4
+ /**
5
+ * Props for the {@link PostPurchase} component.
6
+ * @inline
7
+ */
8
+ type PostPurchaseProps = {
9
+ /**
10
+ * Merchant customer ID for purchase tracking fallback.
11
+ * All three tracking props (`customerId`, `orderId`, `token`) must be
12
+ * present for tracking to fire.
13
+ */
14
+ customerId?: string;
15
+ /**
16
+ * Merchant order ID for purchase tracking fallback.
17
+ */
18
+ orderId?: string;
19
+ /**
20
+ * Checkout token for purchase tracking fallback.
21
+ */
22
+ token?: string;
23
+ /**
24
+ * Base URL to share. Falls back to the merchant domain returned by
25
+ * the backend when omitted.
26
+ */
27
+ sharingUrl?: string;
28
+ /**
29
+ * Override the merchant ID resolved from the SDK config.
30
+ */
31
+ merchantId?: string;
32
+ /**
33
+ * Placement ID for backend-driven CSS customization.
34
+ */
35
+ placement?: string;
36
+ /**
37
+ * CSS class names passed through to the root element (Light DOM).
38
+ */
39
+ classname?: string;
40
+ /**
41
+ * Force a display variant instead of relying on the backend evaluation.
42
+ */
43
+ variant?: "referrer" | "referee";
44
+ /**
45
+ * Label for the pill badge displayed above the message.
46
+ * When omitted (and no placement config provides one), the badge is hidden.
47
+ */
48
+ badgeText?: string;
49
+ /**
50
+ * Override the message shown to referrers.
51
+ * Use `{REWARD}` as placeholder for the reward amount.
52
+ */
53
+ referrerText?: string;
54
+ /**
55
+ * Override the message shown to referees.
56
+ * Use `{REWARD}` as placeholder for the reward amount.
57
+ */
58
+ refereeText?: string;
59
+ /**
60
+ * Override the CTA button text.
61
+ * Use `{REWARD}` as placeholder for the reward amount.
62
+ */
63
+ ctaText?: string;
64
+ };
65
+ //#endregion
66
+ //#region src/components/PostPurchase/PostPurchase.d.ts
67
+ /**
68
+ * Post-purchase card component.
69
+ *
70
+ * Renders an inline card on the merchant's thank-you / order-status page
71
+ * that either congratulates a referee or invites a referrer to share.
72
+ *
73
+ * Fetches referral status and merchant information via two independent
74
+ * RPC calls, then computes the display variant locally.
75
+ *
76
+ * @group components
77
+ *
78
+ * @example
79
+ * Minimal — just show the card:
80
+ * ```html
81
+ * <frak-post-purchase></frak-post-purchase>
82
+ * ```
83
+ *
84
+ * @example
85
+ * With purchase tracking fallback and custom sharing URL:
86
+ * ```html
87
+ * <frak-post-purchase
88
+ * customer-id="cust_123"
89
+ * order-id="ord_456"
90
+ * token="checkout_abc"
91
+ * sharing-url="https://merchant.com/product/shoes"
92
+ * ></frak-post-purchase>
93
+ * ```
94
+ */
95
+ declare function PostPurchase({
96
+ customerId,
97
+ orderId,
98
+ token,
99
+ sharingUrl,
100
+ merchantId,
101
+ placement: placementId,
102
+ classname,
103
+ variant: forcedVariant,
104
+ badgeText: propBadgeText,
105
+ referrerText: propReferrerText,
106
+ refereeText: propRefereeText,
107
+ ctaText: propCtaText
108
+ }: PostPurchaseProps): _$preact.JSX.Element | null;
109
+ //#endregion
110
+ //#region src/components/PostPurchase/index.d.ts
111
+ /**
112
+ * Custom element interface for `<frak-post-purchase>`.
113
+ * Combines standard {@link HTMLElement} with {@link PostPurchaseProps}.
114
+ */
115
+ interface PostPurchaseElement extends HTMLElement, PostPurchaseProps {}
116
+ declare global {
117
+ interface HTMLElementTagNameMap {
118
+ "frak-post-purchase": PostPurchaseElement;
119
+ }
120
+ }
121
+ //#endregion
122
+ export { PostPurchase, PostPurchaseElement };