@fungies/fungies-js 0.0.1

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.
@@ -0,0 +1,8 @@
1
+ # Changesets
2
+
3
+ Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4
+ with multi-package repos, or single-package repos to help you version and publish your code. You can
5
+ find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6
+
7
+ We have a quick list of common questions to get you started engaging with this project in
8
+ [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
package/README.md ADDED
@@ -0,0 +1,178 @@
1
+ # Fungies JavaScript SDK
2
+
3
+ The Fungies JavaScript SDK provides easy integration for Fungies checkout in your web applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @fungies/fungies-js
9
+ ```
10
+
11
+ ```bash
12
+ yarn add @fungies/fungies-js
13
+ ```
14
+
15
+ ```bash
16
+ pnpm add @fungies/fungies-js
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ### JavaScript Initialization
22
+
23
+ ```javascript
24
+ import { Fungies } from "@fungies/fungies-js";
25
+
26
+ // Initialize Fungies
27
+ Fungies.Initialize({
28
+ // Optional: Disable data attribute support
29
+ // enableDataAttributes: false
30
+ });
31
+
32
+ // Open a checkout programmatically
33
+ Fungies.Checkout.open({
34
+ checkoutUrl: "https://store.example.com/checkout-element/my-checkout-id",
35
+ settings: {
36
+ mode: "overlay", // 'overlay' | 'embed'
37
+ frameTarget: "target-element-id", // Optional, for embed mode
38
+ },
39
+ });
40
+
41
+ // Close the checkout
42
+ Fungies.Checkout.close();
43
+ ```
44
+
45
+ ### HTML Data Attribute Support
46
+
47
+ You can also use HTML data attributes to create checkout buttons without writing JavaScript:
48
+
49
+ ```html
50
+ <!-- Basic checkout button -->
51
+ <button data-fungies-checkout-url="https://store.example.com/checkout-element/my-checkout-id" data-fungies-mode="overlay">
52
+ Open Checkout
53
+ </button>
54
+
55
+ <!-- Embed checkout with target element -->
56
+ <button
57
+ data-fungies-checkout-url="https://store.example.com/checkout-element/my-checkout-id"
58
+ data-fungies-mode="embed"
59
+ data-fungies-frame-target="target-element-id"
60
+ >
61
+ Open Embed Checkout
62
+ </button>
63
+
64
+ <!-- Target container for embed checkout -->
65
+ <div id="target-element-id"></div>
66
+ ```
67
+
68
+ ### Manual DOM Scanning
69
+
70
+ If you dynamically add checkout elements after page load, you can manually trigger a DOM scan:
71
+
72
+ ```javascript
73
+ // Scan the page for new checkout elements
74
+ Fungies.ScanDOM();
75
+ ```
76
+
77
+ ## Data Attributes Reference
78
+
79
+ - `data-fungies-checkout-url`: (Required for new format) The checkout URL
80
+ - `data-fungies-mode`: (Optional) The checkout mode ('overlay' or 'embed')
81
+ - `data-fungies-frame-target`: (Optional) Target element ID for embed checkouts
82
+ - `data-fungies-discount-code`: (Optional) Discount code to be applied
83
+ - `data-fungies-customer-email`: (Optional) Customer email to pre-fill
84
+ - `data-fungies-quantity`: (Optional) Default quantity for the checkout
85
+ - `data-fungies-items`: (Optional) JSON string of items to be purchased
86
+ - `data-fungies-custom-fields`: (Optional) JSON string of custom fields
87
+ - `data-fungies-button`: (Legacy format) Contains a checkout URL like "https://STORE_URL/checkout-element/:checkoutID" or "https://STORE_URL/overlay/:checkoutID"
88
+
89
+
90
+ ## TypeScript Support
91
+
92
+ This package includes TypeScript definitions. You can take advantage of type checking and IntelliSense in supported editors:
93
+
94
+ ```typescript
95
+ import { Fungies } from "@fungies/fungies-js";
96
+ import type { InitialCheckoutOpenOptions } from "@fungies/fungies-js";
97
+
98
+ // TypeScript will validate all parameters
99
+ const openOptions: InitialCheckoutOpenOptions = {
100
+ checkoutUrl: "https://store.example.com/checkout-element/my-checkout-id",
101
+ settings: {
102
+ mode: "overlay",
103
+ // frameTarget is optional and only used with embed mode
104
+ frameTarget: "container-id",
105
+ },
106
+ };
107
+
108
+ Fungies.Checkout.open(openOptions);
109
+ ```
110
+
111
+ ## Development
112
+
113
+ ### Building the Package Locally
114
+
115
+ ```bash
116
+ # Clone the repository
117
+ git clone <repository-url>
118
+ cd fungies-js
119
+
120
+ # Install dependencies
121
+ pnpm install
122
+
123
+ # Build the package
124
+ pnpm run build
125
+ ```
126
+
127
+ ### Testing with pnpm link
128
+
129
+ You can use pnpm link to create a symbolic link to your local package:
130
+
131
+ ```bash
132
+ pnpm setup # only if you haven't already
133
+
134
+ # In the fungies-js directory
135
+ pnpm link --global
136
+
137
+ # In your test project directory
138
+ pnpm link fungies-js
139
+ ```
140
+
141
+ ### Alternative: Direct Path Reference
142
+
143
+ Alternatively, you can reference the package directly in your test project's package.json:
144
+
145
+ ```json
146
+ {
147
+ "dependencies": {
148
+ "@fungies/fungies-js": "file:/path/to/fungies-js"
149
+ }
150
+ }
151
+ ```
152
+
153
+ Then run `pnpm install` in your test project.
154
+
155
+ ### After Making Changes
156
+
157
+ When you make changes to the package:
158
+
159
+ 1. Rebuild the package:
160
+
161
+ ```bash
162
+ # In the fungies-js directory
163
+ pnpm run build
164
+ ```
165
+
166
+ 2. The changes will be automatically reflected in your linked project.
167
+
168
+ ### Unlinking
169
+
170
+ When you're done testing:
171
+
172
+ ```bash
173
+ # In your test project
174
+ pnpm unlink fungies-js
175
+
176
+ # In the fungies-js directory (optional)
177
+ pnpm unlink --global
178
+ ```
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Configuration options for initializing the Fungies SDK
3
+ *
4
+ * @public
5
+ */
6
+ type InitialFungiesOptions = {
7
+ /**
8
+ * Your Fungies API token
9
+ */
10
+ token: string;
11
+ /**
12
+ * Whether to enable HTML data attribute support for checkout buttons
13
+ * When true (default), elements with data-fungies-checkout-id attributes
14
+ * will automatically have click handlers attached
15
+ *
16
+ * @default true
17
+ */
18
+ enableDataAttributes?: boolean;
19
+ };
20
+ /**
21
+ * Options for opening a checkout experience
22
+ *
23
+ * @public
24
+ */
25
+ type InitialCheckoutOpenOptions = {
26
+ /**
27
+ * Settings for customizing the checkout experience
28
+ */
29
+ settings: {
30
+ /**
31
+ * Target element selector for inline/embed checkouts
32
+ * Only used when mode is 'embed'
33
+ */
34
+ frameTarget?: string;
35
+ /**
36
+ * The display mode for the checkout
37
+ * - 'overlay': Full-screen checkout that overlays the current page
38
+ * - 'embed': Embedded checkout that renders within a container element
39
+ */
40
+ mode: 'embed' | 'overlay';
41
+ };
42
+ /**
43
+ * The unique identifier for the discount to be applied
44
+ */
45
+ discountCode?: string;
46
+ /**
47
+ * The email address of the customer
48
+ */
49
+ customerEmail?: string;
50
+ /**
51
+ * The quantity of the product to be purchased
52
+ */
53
+ quantity?: number;
54
+ /**
55
+ * The items to be purchased
56
+ * Each item must have an offerId that matches an offer configured in the dashboard
57
+ * for the overlay or embed element. Only the quantity can be modified.
58
+ */
59
+ items?: {
60
+ /**
61
+ * The unique identifier for the offer, must match an offer ID configured
62
+ * in the dashboard for this checkout element
63
+ */
64
+ offerId: string;
65
+ /**
66
+ * The quantity of this specific offer to be purchased
67
+ */
68
+ quantity: number;
69
+ }[];
70
+ /**
71
+ * Custom fields to be added to the checkout
72
+ */
73
+ customFields?: Record<string, string>;
74
+ /**
75
+ * The URL of the checkout to be displayed
76
+ * @required
77
+ */
78
+ checkoutUrl: string;
79
+ };
80
+
81
+ /**
82
+ * Main interface for the Fungies SDK
83
+ *
84
+ * @public
85
+ */
86
+ type FungiesInstance = {
87
+ /**
88
+ * Checkout functionality for opening and closing checkout experiences
89
+ */
90
+ Checkout: {
91
+ /**
92
+ * Opens a checkout experience with the specified parameters
93
+ *
94
+ * @param parameters - Configuration options for the checkout
95
+ * @returns void
96
+ *
97
+ * @example
98
+ * ```ts
99
+ * Fungies.Checkout.open({
100
+ * settings: {
101
+ * mode: 'overlay',
102
+ * // Optional: Only used for inline mode
103
+ * frameTarget: 'target-element-id'
104
+ * }
105
+ * });
106
+ * ```
107
+ */
108
+ open: (parameters: InitialCheckoutOpenOptions) => void;
109
+ /**
110
+ * Closes any currently open checkout experience
111
+ *
112
+ * @returns void
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * Fungies.Checkout.close();
117
+ * ```
118
+ */
119
+ close: () => void;
120
+ };
121
+ /**
122
+ * Initializes the Fungies SDK with the provided options
123
+ * Must be called before using any other functionality
124
+ *
125
+ * @param options - Configuration options for the Fungies SDK
126
+ * @returns void
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * Fungies.Initialize({
131
+ * token: 'your-fungies-token',
132
+ * // Optional: Set to false to disable HTML data attribute support
133
+ * enableDataAttributes: true
134
+ * });
135
+ * ```
136
+ *
137
+ * @throws Will throw an error if token is not provided
138
+ */
139
+ Initialize: (options: InitialFungiesOptions) => void;
140
+ /**
141
+ * Manually scans the DOM for elements with Fungies data attributes and attaches event handlers
142
+ * Useful when dynamically adding checkout elements after initialization
143
+ *
144
+ * @returns void
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * // After dynamically adding elements with data-fungies-checkout-id attributes
149
+ * Fungies.ScanDOM();
150
+ * ```
151
+ *
152
+ */
153
+ ScanDOM: () => void;
154
+ };
155
+
156
+ declare global {
157
+ interface Window {
158
+ FungiesWindow?: Window;
159
+ FungiesFrame?: HTMLIFrameElement;
160
+ Fungies?: FungiesInstance;
161
+ }
162
+ }
163
+ declare const Fungies: FungiesInstance;
164
+
165
+ export { Fungies, type FungiesInstance, type InitialCheckoutOpenOptions, type InitialFungiesOptions };
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Configuration options for initializing the Fungies SDK
3
+ *
4
+ * @public
5
+ */
6
+ type InitialFungiesOptions = {
7
+ /**
8
+ * Your Fungies API token
9
+ */
10
+ token: string;
11
+ /**
12
+ * Whether to enable HTML data attribute support for checkout buttons
13
+ * When true (default), elements with data-fungies-checkout-id attributes
14
+ * will automatically have click handlers attached
15
+ *
16
+ * @default true
17
+ */
18
+ enableDataAttributes?: boolean;
19
+ };
20
+ /**
21
+ * Options for opening a checkout experience
22
+ *
23
+ * @public
24
+ */
25
+ type InitialCheckoutOpenOptions = {
26
+ /**
27
+ * Settings for customizing the checkout experience
28
+ */
29
+ settings: {
30
+ /**
31
+ * Target element selector for inline/embed checkouts
32
+ * Only used when mode is 'embed'
33
+ */
34
+ frameTarget?: string;
35
+ /**
36
+ * The display mode for the checkout
37
+ * - 'overlay': Full-screen checkout that overlays the current page
38
+ * - 'embed': Embedded checkout that renders within a container element
39
+ */
40
+ mode: 'embed' | 'overlay';
41
+ };
42
+ /**
43
+ * The unique identifier for the discount to be applied
44
+ */
45
+ discountCode?: string;
46
+ /**
47
+ * The email address of the customer
48
+ */
49
+ customerEmail?: string;
50
+ /**
51
+ * The quantity of the product to be purchased
52
+ */
53
+ quantity?: number;
54
+ /**
55
+ * The items to be purchased
56
+ * Each item must have an offerId that matches an offer configured in the dashboard
57
+ * for the overlay or embed element. Only the quantity can be modified.
58
+ */
59
+ items?: {
60
+ /**
61
+ * The unique identifier for the offer, must match an offer ID configured
62
+ * in the dashboard for this checkout element
63
+ */
64
+ offerId: string;
65
+ /**
66
+ * The quantity of this specific offer to be purchased
67
+ */
68
+ quantity: number;
69
+ }[];
70
+ /**
71
+ * Custom fields to be added to the checkout
72
+ */
73
+ customFields?: Record<string, string>;
74
+ /**
75
+ * The URL of the checkout to be displayed
76
+ * @required
77
+ */
78
+ checkoutUrl: string;
79
+ };
80
+
81
+ /**
82
+ * Main interface for the Fungies SDK
83
+ *
84
+ * @public
85
+ */
86
+ type FungiesInstance = {
87
+ /**
88
+ * Checkout functionality for opening and closing checkout experiences
89
+ */
90
+ Checkout: {
91
+ /**
92
+ * Opens a checkout experience with the specified parameters
93
+ *
94
+ * @param parameters - Configuration options for the checkout
95
+ * @returns void
96
+ *
97
+ * @example
98
+ * ```ts
99
+ * Fungies.Checkout.open({
100
+ * settings: {
101
+ * mode: 'overlay',
102
+ * // Optional: Only used for inline mode
103
+ * frameTarget: 'target-element-id'
104
+ * }
105
+ * });
106
+ * ```
107
+ */
108
+ open: (parameters: InitialCheckoutOpenOptions) => void;
109
+ /**
110
+ * Closes any currently open checkout experience
111
+ *
112
+ * @returns void
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * Fungies.Checkout.close();
117
+ * ```
118
+ */
119
+ close: () => void;
120
+ };
121
+ /**
122
+ * Initializes the Fungies SDK with the provided options
123
+ * Must be called before using any other functionality
124
+ *
125
+ * @param options - Configuration options for the Fungies SDK
126
+ * @returns void
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * Fungies.Initialize({
131
+ * token: 'your-fungies-token',
132
+ * // Optional: Set to false to disable HTML data attribute support
133
+ * enableDataAttributes: true
134
+ * });
135
+ * ```
136
+ *
137
+ * @throws Will throw an error if token is not provided
138
+ */
139
+ Initialize: (options: InitialFungiesOptions) => void;
140
+ /**
141
+ * Manually scans the DOM for elements with Fungies data attributes and attaches event handlers
142
+ * Useful when dynamically adding checkout elements after initialization
143
+ *
144
+ * @returns void
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * // After dynamically adding elements with data-fungies-checkout-id attributes
149
+ * Fungies.ScanDOM();
150
+ * ```
151
+ *
152
+ */
153
+ ScanDOM: () => void;
154
+ };
155
+
156
+ declare global {
157
+ interface Window {
158
+ FungiesWindow?: Window;
159
+ FungiesFrame?: HTMLIFrameElement;
160
+ Fungies?: FungiesInstance;
161
+ }
162
+ }
163
+ declare const Fungies: FungiesInstance;
164
+
165
+ export { Fungies, type FungiesInstance, type InitialCheckoutOpenOptions, type InitialFungiesOptions };
package/dist/index.js ADDED
@@ -0,0 +1,389 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Fungies: () => Fungies
24
+ });
25
+ module.exports = __toCommonJS(index_exports);
26
+
27
+ // src/constants/checkout.ts
28
+ var CHECKOUT_FRAME_CLOSED = "Checkout frame/window has been closed.";
29
+ var CHECKOUT_EVENTS = {
30
+ CHECKOUT_CLOSE: "closeWindow"
31
+ };
32
+ var CHECKOUT_MODE = {
33
+ EMBED: "embed",
34
+ OVERLAY: "overlay"
35
+ };
36
+
37
+ // src/lib/logger.ts
38
+ var createLoggerConfig = () => ({
39
+ isEnabled: true
40
+ });
41
+ var log = (message, type = "log" /* LOG */, alwaysShow = false, config = createLoggerConfig()) => {
42
+ if (!config.isEnabled) return;
43
+ window.console.debug = window.console.debug || window.console.log;
44
+ const debugMessage = `[Fungies Debug]${message}`;
45
+ if (type === "log" /* LOG */) {
46
+ console.debug(debugMessage);
47
+ } else if (type === "warning" /* WARNING */) {
48
+ console.warn(debugMessage);
49
+ }
50
+ if (alwaysShow) {
51
+ console.warn(message);
52
+ }
53
+ };
54
+
55
+ // src/utils/device.ts
56
+ function isMobile() {
57
+ let check = false;
58
+ ((a) => {
59
+ if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
60
+ a
61
+ ) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(
62
+ a.substr(0, 4)
63
+ ))
64
+ check = true;
65
+ })(navigator.userAgent || navigator.vendor);
66
+ return check;
67
+ }
68
+
69
+ // src/utils/html.ts
70
+ function each(className, callback) {
71
+ const elements = document.getElementsByClassName(className);
72
+ for (let i = 0; i < elements.length; i++) {
73
+ const thisElement = elements[i];
74
+ if (typeof callback === "function") {
75
+ callback(thisElement);
76
+ } else {
77
+ throw new Error("each(className, function() {... requires the callback argument to be of type Function");
78
+ }
79
+ }
80
+ }
81
+
82
+ // src/utils/url.ts
83
+ var encodeForTransport = (jsonString) => {
84
+ return encodeURIComponent(encodeURIComponent(jsonString));
85
+ };
86
+ var getCheckoutFrontEndURL = (checkoutInputAttributes, checkoutUrl, mode) => {
87
+ const url = new URL(checkoutUrl);
88
+ url.searchParams.append("fngs-checkout-payload", encodeForTransport(JSON.stringify(checkoutInputAttributes)));
89
+ url.searchParams.append("fngs-display-mode", mode);
90
+ return url.toString();
91
+ };
92
+ var getCheckoutUrl = ({ checkoutUrl, ...restProps }, mode) => {
93
+ return getCheckoutFrontEndURL(restProps, checkoutUrl, mode);
94
+ };
95
+
96
+ // src/helpers/checkout.ts
97
+ function showLoading() {
98
+ hideLoading();
99
+ const keyFrameStyle = document.createElement("style");
100
+ keyFrameStyle.type = "text/css";
101
+ keyFrameStyle.innerHTML = // eslint-disable-next-line no-multi-str
102
+ " @-webkit-keyframes rotate { 0% { -webkit-transform: rotate(45deg); } 100% { -webkit-transform: rotate(405deg); } } @keyframes rotate { from { transform: rotate(45deg); } to { transform: rotate(405deg); } }";
103
+ const head = document.getElementsByTagName("head")[0];
104
+ if (head) {
105
+ head.appendChild(keyFrameStyle);
106
+ }
107
+ const htmlLoader = document.createElement("div");
108
+ htmlLoader.setAttribute(
109
+ "style",
110
+ "z-index:99998; display: block; position: fixed; height: 100%; width: 100%; top: 0px; left: 0px; right: 0px; bottom: 0px; margin: 0px; padding: 0px; background: rgba(0,0,0,0.38);"
111
+ );
112
+ htmlLoader.setAttribute("class", "fungies-loader" /* FUNGIES_LOADER */);
113
+ const mainSpinnerWrapper = document.createElement("main");
114
+ const htmlLoaderIconWrapper = "align-items: center;display: flex;flex-direction: column;justify-content: center;left: 50%;margin: 0.5rem 0;position: absolute;text-align: center;top: 50%;transform: translate(-50%, -50%);width: 90%;";
115
+ mainSpinnerWrapper.setAttribute("style", htmlLoaderIconWrapper);
116
+ const spinner = document.createElement("div");
117
+ const htmlLoaderIcon = "border: 4px solid #f3f3f3;border-radius: 50%;border-top: 4px solid #ccc;width: 34px;height: 34px;-webkit-animation: rotate 1s ease-in-out infinite forwards;animation: rotate 1s ease-in-out infinite forwards;";
118
+ spinner.setAttribute("style", htmlLoaderIcon);
119
+ mainSpinnerWrapper.appendChild(spinner);
120
+ htmlLoader.appendChild(mainSpinnerWrapper);
121
+ const appendLoader = () => {
122
+ const body = document.getElementsByTagName("body")[0];
123
+ if (body) {
124
+ body.appendChild(htmlLoader);
125
+ }
126
+ };
127
+ if (document.readyState === "loading") {
128
+ document.addEventListener("DOMContentLoaded", appendLoader);
129
+ } else {
130
+ appendLoader();
131
+ }
132
+ }
133
+ function hideLoading() {
134
+ each("fungies-loader" /* FUNGIES_LOADER */, (loader) => {
135
+ loader?.parentNode?.removeChild(loader);
136
+ });
137
+ }
138
+
139
+ // src/helpers/iframe.ts
140
+ var closeCheckoutIFrame = () => {
141
+ log(CHECKOUT_FRAME_CLOSED);
142
+ hideLoading();
143
+ each("fungies-frame" /* FUNGIES_FRAME */, (element) => {
144
+ element.parentNode?.removeChild(element);
145
+ });
146
+ if (typeof window.FungiesWindow !== "undefined" && !window.FungiesWindow.closed) {
147
+ window.FungiesWindow.close();
148
+ }
149
+ };
150
+ var renderCheckoutFrame = (checkoutProps, settings, embed) => {
151
+ const checkoutUrl = getCheckoutUrl(checkoutProps, settings.mode);
152
+ if (!embed) {
153
+ showLoading();
154
+ }
155
+ window.FungiesFrame = document.createElement("iframe");
156
+ window.FungiesFrame.className = "fungies-frame" /* FUNGIES_FRAME */;
157
+ window.FungiesFrame.name = "fungies_frame";
158
+ window.FungiesFrame.frameBorder = "0";
159
+ window.FungiesFrame.allowTransparency = "true";
160
+ window.FungiesFrame.allow = "payment";
161
+ if (embed) {
162
+ window.FungiesFrame.classList.add("fungies-frame-embed" /* FUNGIES_FRAME_EMBED */);
163
+ window.FungiesFrame.setAttribute("style", "width: 100%; height: 100%;");
164
+ const styleElement = document.createElement("style");
165
+ styleElement.type = "text/css";
166
+ styleElement.innerHTML = `.${"fungies-frame-embed" /* FUNGIES_FRAME_EMBED */}::-webkit-scrollbar { display: none !important; }`;
167
+ document?.getElementsByTagName("head")[0]?.appendChild(styleElement);
168
+ } else {
169
+ window.FungiesFrame.classList.add("fungies-frame-overlay" /* FUNGIES_FRAME_OVERLAY */);
170
+ }
171
+ if (!embed) {
172
+ if (!isMobile()) {
173
+ window.FungiesFrame.setAttribute(
174
+ "style",
175
+ "z-index: 2147483647; display: block; background-color: transparent; border: 0px none transparent; overflow-x: hidden; overflow-y: auto; visibility: visible; margin: 0px; padding: 0px; -webkit-tap-highlight-color: transparent; position: fixed; left: 0px; top: 0px; width: 100%; height: 100%;"
176
+ );
177
+ } else {
178
+ window.FungiesFrame.setAttribute(
179
+ "style",
180
+ "z-index: 2147483647; display: block; background-color: transparent; border: 0px none transparent; overflow-x: hidden; overflow-y: scroll; visibility: visible; margin: 0px; padding: 0px; -webkit-tap-highlight-color: transparent; position: fixed; left: 0px; top: 0px; width: 100%; height: 100%;"
181
+ );
182
+ }
183
+ }
184
+ window.FungiesFrame.src = checkoutUrl;
185
+ if (settings?.frameTarget && embed) {
186
+ const target = document.querySelector(`[${settings.frameTarget}]`);
187
+ if (target) {
188
+ target.appendChild(window.FungiesFrame);
189
+ }
190
+ } else {
191
+ const body = document.getElementsByTagName("body")[0];
192
+ if (body) {
193
+ body.appendChild(window.FungiesFrame);
194
+ }
195
+ }
196
+ };
197
+
198
+ // src/lib/checkout.ts
199
+ var openCheckout = ({ settings, ...checkoutInputAttributes }) => {
200
+ closeCheckoutIFrame();
201
+ const renderCheckoutWithSettings = () => {
202
+ renderCheckoutFrame(checkoutInputAttributes, settings, settings?.mode === CHECKOUT_MODE.EMBED);
203
+ };
204
+ if (document.readyState !== "loading") {
205
+ renderCheckoutWithSettings();
206
+ } else {
207
+ document.addEventListener("DOMContentLoaded", renderCheckoutWithSettings);
208
+ }
209
+ };
210
+ var closeCheckout = () => {
211
+ closeCheckoutIFrame();
212
+ };
213
+
214
+ // src/helpers/dom.ts
215
+ var scanForCheckoutElements = () => {
216
+ const newFormatElements = document.querySelectorAll("[data-fungies-checkout-url]:not([data-fungies-initialized])");
217
+ for (const element of newFormatElements) {
218
+ const checkoutUrl = element.getAttribute("data-fungies-checkout-url");
219
+ if (!checkoutUrl) {
220
+ log("Element has data-fungies-checkout-url attribute but no value", "warning" /* WARNING */);
221
+ continue;
222
+ }
223
+ const modeAttr = element.getAttribute("data-fungies-mode");
224
+ const mode = modeAttr === "embed" || modeAttr === "overlay" ? modeAttr : "overlay";
225
+ const frameTarget = element.getAttribute("data-fungies-frame-target") || void 0;
226
+ const discountCode = element.getAttribute("data-fungies-discount-code") || void 0;
227
+ const customerEmail = element.getAttribute("data-fungies-customer-email") || void 0;
228
+ const quantityAttr = element.getAttribute("data-fungies-quantity");
229
+ const quantity = quantityAttr ? Number.parseInt(quantityAttr, 10) : void 0;
230
+ let items = void 0;
231
+ const itemsAttr = element.getAttribute("data-fungies-items");
232
+ if (itemsAttr) {
233
+ try {
234
+ items = JSON.parse(itemsAttr);
235
+ } catch (_error) {
236
+ log(`Invalid JSON in data-fungies-items: ${itemsAttr}`, "warning" /* WARNING */);
237
+ }
238
+ }
239
+ let customFields = void 0;
240
+ const customFieldsAttr = element.getAttribute("data-fungies-custom-fields");
241
+ if (customFieldsAttr) {
242
+ try {
243
+ customFields = JSON.parse(customFieldsAttr);
244
+ } catch (_error) {
245
+ log(`Invalid JSON in data-fungies-custom-fields: ${customFieldsAttr}`, "warning" /* WARNING */);
246
+ }
247
+ }
248
+ const checkoutOptions = {
249
+ checkoutUrl,
250
+ settings: {
251
+ mode,
252
+ ...frameTarget && { frameTarget }
253
+ },
254
+ ...discountCode && { discountCode },
255
+ ...customerEmail && { customerEmail },
256
+ ...quantity && { quantity },
257
+ ...items && { items },
258
+ ...customFields && { customFields }
259
+ };
260
+ element.addEventListener("click", (event) => {
261
+ event.preventDefault();
262
+ openCheckout(checkoutOptions);
263
+ });
264
+ element.setAttribute("data-fungies-initialized", "true");
265
+ }
266
+ const legacyFormatElements = document.querySelectorAll("[data-fungies-button]:not([data-fungies-initialized])");
267
+ for (const element of legacyFormatElements) {
268
+ const buttonUrl = element.getAttribute("data-fungies-button");
269
+ if (!buttonUrl) {
270
+ log("Element has data-fungies-button attribute but no value", "warning" /* WARNING */);
271
+ continue;
272
+ }
273
+ try {
274
+ const url = new URL(buttonUrl);
275
+ const pathParts = url.pathname.split("/");
276
+ const checkoutElementIndex = pathParts.indexOf("checkout-element");
277
+ const overlayIndex = pathParts.indexOf("overlay");
278
+ if (checkoutElementIndex === -1 && overlayIndex === -1) {
279
+ log(`Invalid URL in data-fungies-button: ${buttonUrl}`, "warning" /* WARNING */);
280
+ continue;
281
+ }
282
+ const mode = "overlay";
283
+ const checkoutOptions = {
284
+ checkoutUrl: buttonUrl,
285
+ settings: {
286
+ mode
287
+ }
288
+ };
289
+ element.addEventListener("click", (event) => {
290
+ event.preventDefault();
291
+ openCheckout(checkoutOptions);
292
+ });
293
+ element.setAttribute("data-fungies-initialized", "true");
294
+ } catch (error) {
295
+ log(error, "error" /* ERROR */);
296
+ }
297
+ }
298
+ };
299
+ var initializeDomSupport = () => {
300
+ if (document.readyState !== "loading") {
301
+ scanForCheckoutElements();
302
+ } else {
303
+ document.addEventListener("DOMContentLoaded", scanForCheckoutElements);
304
+ }
305
+ const observer = new MutationObserver((mutations) => {
306
+ let shouldScan = false;
307
+ for (const mutation of mutations) {
308
+ if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
309
+ for (const node of mutation.addedNodes) {
310
+ if (node.nodeType === Node.ELEMENT_NODE) {
311
+ const element = node;
312
+ if (element.querySelector(
313
+ "[data-fungies-checkout-url]:not([data-fungies-initialized]), [data-fungies-button]:not([data-fungies-initialized])"
314
+ )) {
315
+ shouldScan = true;
316
+ break;
317
+ }
318
+ }
319
+ }
320
+ }
321
+ }
322
+ if (shouldScan) {
323
+ scanForCheckoutElements();
324
+ }
325
+ });
326
+ observer.observe(document.body, {
327
+ childList: true,
328
+ subtree: true
329
+ });
330
+ };
331
+
332
+ // src/helpers/events.ts
333
+ var _messageListener = (message) => {
334
+ const { data } = message;
335
+ switch (typeof data === "string" ? data.toLowerCase() : "") {
336
+ case CHECKOUT_EVENTS.CHECKOUT_CLOSE:
337
+ closeCheckoutIFrame();
338
+ break;
339
+ }
340
+ };
341
+ function listen() {
342
+ if (typeof window !== "undefined") {
343
+ window.addEventListener("message", _messageListener, false);
344
+ }
345
+ }
346
+
347
+ // src/lib/state.ts
348
+ var createInitialState = () => ({
349
+ completedSetup: false,
350
+ options: null
351
+ });
352
+ var updateState = (currentState, updates) => ({
353
+ ...currentState,
354
+ ...updates
355
+ });
356
+
357
+ // src/lib/fungies.ts
358
+ var initialize = (options, currentState = createInitialState()) => {
359
+ if (!currentState.completedSetup) {
360
+ listen();
361
+ if (options.enableDataAttributes !== false) {
362
+ initializeDomSupport();
363
+ }
364
+ updateState(currentState, {
365
+ completedSetup: true,
366
+ options
367
+ });
368
+ } else {
369
+ log("Cannot call Fungies.Initialize() more than once per page, the call was ignored.", "warning" /* WARNING */);
370
+ }
371
+ };
372
+ var createFungies = () => ({
373
+ Checkout: {
374
+ open: openCheckout,
375
+ close: closeCheckout
376
+ },
377
+ Initialize: initialize,
378
+ ScanDOM: scanForCheckoutElements
379
+ });
380
+
381
+ // src/index.ts
382
+ var Fungies = createFungies();
383
+ if (typeof window !== "undefined") {
384
+ window.Fungies = Fungies;
385
+ }
386
+ // Annotate the CommonJS export names for ESM import in node:
387
+ 0 && (module.exports = {
388
+ Fungies
389
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,362 @@
1
+ // src/constants/checkout.ts
2
+ var CHECKOUT_FRAME_CLOSED = "Checkout frame/window has been closed.";
3
+ var CHECKOUT_EVENTS = {
4
+ CHECKOUT_CLOSE: "closeWindow"
5
+ };
6
+ var CHECKOUT_MODE = {
7
+ EMBED: "embed",
8
+ OVERLAY: "overlay"
9
+ };
10
+
11
+ // src/lib/logger.ts
12
+ var createLoggerConfig = () => ({
13
+ isEnabled: true
14
+ });
15
+ var log = (message, type = "log" /* LOG */, alwaysShow = false, config = createLoggerConfig()) => {
16
+ if (!config.isEnabled) return;
17
+ window.console.debug = window.console.debug || window.console.log;
18
+ const debugMessage = `[Fungies Debug]${message}`;
19
+ if (type === "log" /* LOG */) {
20
+ console.debug(debugMessage);
21
+ } else if (type === "warning" /* WARNING */) {
22
+ console.warn(debugMessage);
23
+ }
24
+ if (alwaysShow) {
25
+ console.warn(message);
26
+ }
27
+ };
28
+
29
+ // src/utils/device.ts
30
+ function isMobile() {
31
+ let check = false;
32
+ ((a) => {
33
+ if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
34
+ a
35
+ ) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(
36
+ a.substr(0, 4)
37
+ ))
38
+ check = true;
39
+ })(navigator.userAgent || navigator.vendor);
40
+ return check;
41
+ }
42
+
43
+ // src/utils/html.ts
44
+ function each(className, callback) {
45
+ const elements = document.getElementsByClassName(className);
46
+ for (let i = 0; i < elements.length; i++) {
47
+ const thisElement = elements[i];
48
+ if (typeof callback === "function") {
49
+ callback(thisElement);
50
+ } else {
51
+ throw new Error("each(className, function() {... requires the callback argument to be of type Function");
52
+ }
53
+ }
54
+ }
55
+
56
+ // src/utils/url.ts
57
+ var encodeForTransport = (jsonString) => {
58
+ return encodeURIComponent(encodeURIComponent(jsonString));
59
+ };
60
+ var getCheckoutFrontEndURL = (checkoutInputAttributes, checkoutUrl, mode) => {
61
+ const url = new URL(checkoutUrl);
62
+ url.searchParams.append("fngs-checkout-payload", encodeForTransport(JSON.stringify(checkoutInputAttributes)));
63
+ url.searchParams.append("fngs-display-mode", mode);
64
+ return url.toString();
65
+ };
66
+ var getCheckoutUrl = ({ checkoutUrl, ...restProps }, mode) => {
67
+ return getCheckoutFrontEndURL(restProps, checkoutUrl, mode);
68
+ };
69
+
70
+ // src/helpers/checkout.ts
71
+ function showLoading() {
72
+ hideLoading();
73
+ const keyFrameStyle = document.createElement("style");
74
+ keyFrameStyle.type = "text/css";
75
+ keyFrameStyle.innerHTML = // eslint-disable-next-line no-multi-str
76
+ " @-webkit-keyframes rotate { 0% { -webkit-transform: rotate(45deg); } 100% { -webkit-transform: rotate(405deg); } } @keyframes rotate { from { transform: rotate(45deg); } to { transform: rotate(405deg); } }";
77
+ const head = document.getElementsByTagName("head")[0];
78
+ if (head) {
79
+ head.appendChild(keyFrameStyle);
80
+ }
81
+ const htmlLoader = document.createElement("div");
82
+ htmlLoader.setAttribute(
83
+ "style",
84
+ "z-index:99998; display: block; position: fixed; height: 100%; width: 100%; top: 0px; left: 0px; right: 0px; bottom: 0px; margin: 0px; padding: 0px; background: rgba(0,0,0,0.38);"
85
+ );
86
+ htmlLoader.setAttribute("class", "fungies-loader" /* FUNGIES_LOADER */);
87
+ const mainSpinnerWrapper = document.createElement("main");
88
+ const htmlLoaderIconWrapper = "align-items: center;display: flex;flex-direction: column;justify-content: center;left: 50%;margin: 0.5rem 0;position: absolute;text-align: center;top: 50%;transform: translate(-50%, -50%);width: 90%;";
89
+ mainSpinnerWrapper.setAttribute("style", htmlLoaderIconWrapper);
90
+ const spinner = document.createElement("div");
91
+ const htmlLoaderIcon = "border: 4px solid #f3f3f3;border-radius: 50%;border-top: 4px solid #ccc;width: 34px;height: 34px;-webkit-animation: rotate 1s ease-in-out infinite forwards;animation: rotate 1s ease-in-out infinite forwards;";
92
+ spinner.setAttribute("style", htmlLoaderIcon);
93
+ mainSpinnerWrapper.appendChild(spinner);
94
+ htmlLoader.appendChild(mainSpinnerWrapper);
95
+ const appendLoader = () => {
96
+ const body = document.getElementsByTagName("body")[0];
97
+ if (body) {
98
+ body.appendChild(htmlLoader);
99
+ }
100
+ };
101
+ if (document.readyState === "loading") {
102
+ document.addEventListener("DOMContentLoaded", appendLoader);
103
+ } else {
104
+ appendLoader();
105
+ }
106
+ }
107
+ function hideLoading() {
108
+ each("fungies-loader" /* FUNGIES_LOADER */, (loader) => {
109
+ loader?.parentNode?.removeChild(loader);
110
+ });
111
+ }
112
+
113
+ // src/helpers/iframe.ts
114
+ var closeCheckoutIFrame = () => {
115
+ log(CHECKOUT_FRAME_CLOSED);
116
+ hideLoading();
117
+ each("fungies-frame" /* FUNGIES_FRAME */, (element) => {
118
+ element.parentNode?.removeChild(element);
119
+ });
120
+ if (typeof window.FungiesWindow !== "undefined" && !window.FungiesWindow.closed) {
121
+ window.FungiesWindow.close();
122
+ }
123
+ };
124
+ var renderCheckoutFrame = (checkoutProps, settings, embed) => {
125
+ const checkoutUrl = getCheckoutUrl(checkoutProps, settings.mode);
126
+ if (!embed) {
127
+ showLoading();
128
+ }
129
+ window.FungiesFrame = document.createElement("iframe");
130
+ window.FungiesFrame.className = "fungies-frame" /* FUNGIES_FRAME */;
131
+ window.FungiesFrame.name = "fungies_frame";
132
+ window.FungiesFrame.frameBorder = "0";
133
+ window.FungiesFrame.allowTransparency = "true";
134
+ window.FungiesFrame.allow = "payment";
135
+ if (embed) {
136
+ window.FungiesFrame.classList.add("fungies-frame-embed" /* FUNGIES_FRAME_EMBED */);
137
+ window.FungiesFrame.setAttribute("style", "width: 100%; height: 100%;");
138
+ const styleElement = document.createElement("style");
139
+ styleElement.type = "text/css";
140
+ styleElement.innerHTML = `.${"fungies-frame-embed" /* FUNGIES_FRAME_EMBED */}::-webkit-scrollbar { display: none !important; }`;
141
+ document?.getElementsByTagName("head")[0]?.appendChild(styleElement);
142
+ } else {
143
+ window.FungiesFrame.classList.add("fungies-frame-overlay" /* FUNGIES_FRAME_OVERLAY */);
144
+ }
145
+ if (!embed) {
146
+ if (!isMobile()) {
147
+ window.FungiesFrame.setAttribute(
148
+ "style",
149
+ "z-index: 2147483647; display: block; background-color: transparent; border: 0px none transparent; overflow-x: hidden; overflow-y: auto; visibility: visible; margin: 0px; padding: 0px; -webkit-tap-highlight-color: transparent; position: fixed; left: 0px; top: 0px; width: 100%; height: 100%;"
150
+ );
151
+ } else {
152
+ window.FungiesFrame.setAttribute(
153
+ "style",
154
+ "z-index: 2147483647; display: block; background-color: transparent; border: 0px none transparent; overflow-x: hidden; overflow-y: scroll; visibility: visible; margin: 0px; padding: 0px; -webkit-tap-highlight-color: transparent; position: fixed; left: 0px; top: 0px; width: 100%; height: 100%;"
155
+ );
156
+ }
157
+ }
158
+ window.FungiesFrame.src = checkoutUrl;
159
+ if (settings?.frameTarget && embed) {
160
+ const target = document.querySelector(`[${settings.frameTarget}]`);
161
+ if (target) {
162
+ target.appendChild(window.FungiesFrame);
163
+ }
164
+ } else {
165
+ const body = document.getElementsByTagName("body")[0];
166
+ if (body) {
167
+ body.appendChild(window.FungiesFrame);
168
+ }
169
+ }
170
+ };
171
+
172
+ // src/lib/checkout.ts
173
+ var openCheckout = ({ settings, ...checkoutInputAttributes }) => {
174
+ closeCheckoutIFrame();
175
+ const renderCheckoutWithSettings = () => {
176
+ renderCheckoutFrame(checkoutInputAttributes, settings, settings?.mode === CHECKOUT_MODE.EMBED);
177
+ };
178
+ if (document.readyState !== "loading") {
179
+ renderCheckoutWithSettings();
180
+ } else {
181
+ document.addEventListener("DOMContentLoaded", renderCheckoutWithSettings);
182
+ }
183
+ };
184
+ var closeCheckout = () => {
185
+ closeCheckoutIFrame();
186
+ };
187
+
188
+ // src/helpers/dom.ts
189
+ var scanForCheckoutElements = () => {
190
+ const newFormatElements = document.querySelectorAll("[data-fungies-checkout-url]:not([data-fungies-initialized])");
191
+ for (const element of newFormatElements) {
192
+ const checkoutUrl = element.getAttribute("data-fungies-checkout-url");
193
+ if (!checkoutUrl) {
194
+ log("Element has data-fungies-checkout-url attribute but no value", "warning" /* WARNING */);
195
+ continue;
196
+ }
197
+ const modeAttr = element.getAttribute("data-fungies-mode");
198
+ const mode = modeAttr === "embed" || modeAttr === "overlay" ? modeAttr : "overlay";
199
+ const frameTarget = element.getAttribute("data-fungies-frame-target") || void 0;
200
+ const discountCode = element.getAttribute("data-fungies-discount-code") || void 0;
201
+ const customerEmail = element.getAttribute("data-fungies-customer-email") || void 0;
202
+ const quantityAttr = element.getAttribute("data-fungies-quantity");
203
+ const quantity = quantityAttr ? Number.parseInt(quantityAttr, 10) : void 0;
204
+ let items = void 0;
205
+ const itemsAttr = element.getAttribute("data-fungies-items");
206
+ if (itemsAttr) {
207
+ try {
208
+ items = JSON.parse(itemsAttr);
209
+ } catch (_error) {
210
+ log(`Invalid JSON in data-fungies-items: ${itemsAttr}`, "warning" /* WARNING */);
211
+ }
212
+ }
213
+ let customFields = void 0;
214
+ const customFieldsAttr = element.getAttribute("data-fungies-custom-fields");
215
+ if (customFieldsAttr) {
216
+ try {
217
+ customFields = JSON.parse(customFieldsAttr);
218
+ } catch (_error) {
219
+ log(`Invalid JSON in data-fungies-custom-fields: ${customFieldsAttr}`, "warning" /* WARNING */);
220
+ }
221
+ }
222
+ const checkoutOptions = {
223
+ checkoutUrl,
224
+ settings: {
225
+ mode,
226
+ ...frameTarget && { frameTarget }
227
+ },
228
+ ...discountCode && { discountCode },
229
+ ...customerEmail && { customerEmail },
230
+ ...quantity && { quantity },
231
+ ...items && { items },
232
+ ...customFields && { customFields }
233
+ };
234
+ element.addEventListener("click", (event) => {
235
+ event.preventDefault();
236
+ openCheckout(checkoutOptions);
237
+ });
238
+ element.setAttribute("data-fungies-initialized", "true");
239
+ }
240
+ const legacyFormatElements = document.querySelectorAll("[data-fungies-button]:not([data-fungies-initialized])");
241
+ for (const element of legacyFormatElements) {
242
+ const buttonUrl = element.getAttribute("data-fungies-button");
243
+ if (!buttonUrl) {
244
+ log("Element has data-fungies-button attribute but no value", "warning" /* WARNING */);
245
+ continue;
246
+ }
247
+ try {
248
+ const url = new URL(buttonUrl);
249
+ const pathParts = url.pathname.split("/");
250
+ const checkoutElementIndex = pathParts.indexOf("checkout-element");
251
+ const overlayIndex = pathParts.indexOf("overlay");
252
+ if (checkoutElementIndex === -1 && overlayIndex === -1) {
253
+ log(`Invalid URL in data-fungies-button: ${buttonUrl}`, "warning" /* WARNING */);
254
+ continue;
255
+ }
256
+ const mode = "overlay";
257
+ const checkoutOptions = {
258
+ checkoutUrl: buttonUrl,
259
+ settings: {
260
+ mode
261
+ }
262
+ };
263
+ element.addEventListener("click", (event) => {
264
+ event.preventDefault();
265
+ openCheckout(checkoutOptions);
266
+ });
267
+ element.setAttribute("data-fungies-initialized", "true");
268
+ } catch (error) {
269
+ log(error, "error" /* ERROR */);
270
+ }
271
+ }
272
+ };
273
+ var initializeDomSupport = () => {
274
+ if (document.readyState !== "loading") {
275
+ scanForCheckoutElements();
276
+ } else {
277
+ document.addEventListener("DOMContentLoaded", scanForCheckoutElements);
278
+ }
279
+ const observer = new MutationObserver((mutations) => {
280
+ let shouldScan = false;
281
+ for (const mutation of mutations) {
282
+ if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
283
+ for (const node of mutation.addedNodes) {
284
+ if (node.nodeType === Node.ELEMENT_NODE) {
285
+ const element = node;
286
+ if (element.querySelector(
287
+ "[data-fungies-checkout-url]:not([data-fungies-initialized]), [data-fungies-button]:not([data-fungies-initialized])"
288
+ )) {
289
+ shouldScan = true;
290
+ break;
291
+ }
292
+ }
293
+ }
294
+ }
295
+ }
296
+ if (shouldScan) {
297
+ scanForCheckoutElements();
298
+ }
299
+ });
300
+ observer.observe(document.body, {
301
+ childList: true,
302
+ subtree: true
303
+ });
304
+ };
305
+
306
+ // src/helpers/events.ts
307
+ var _messageListener = (message) => {
308
+ const { data } = message;
309
+ switch (typeof data === "string" ? data.toLowerCase() : "") {
310
+ case CHECKOUT_EVENTS.CHECKOUT_CLOSE:
311
+ closeCheckoutIFrame();
312
+ break;
313
+ }
314
+ };
315
+ function listen() {
316
+ if (typeof window !== "undefined") {
317
+ window.addEventListener("message", _messageListener, false);
318
+ }
319
+ }
320
+
321
+ // src/lib/state.ts
322
+ var createInitialState = () => ({
323
+ completedSetup: false,
324
+ options: null
325
+ });
326
+ var updateState = (currentState, updates) => ({
327
+ ...currentState,
328
+ ...updates
329
+ });
330
+
331
+ // src/lib/fungies.ts
332
+ var initialize = (options, currentState = createInitialState()) => {
333
+ if (!currentState.completedSetup) {
334
+ listen();
335
+ if (options.enableDataAttributes !== false) {
336
+ initializeDomSupport();
337
+ }
338
+ updateState(currentState, {
339
+ completedSetup: true,
340
+ options
341
+ });
342
+ } else {
343
+ log("Cannot call Fungies.Initialize() more than once per page, the call was ignored.", "warning" /* WARNING */);
344
+ }
345
+ };
346
+ var createFungies = () => ({
347
+ Checkout: {
348
+ open: openCheckout,
349
+ close: closeCheckout
350
+ },
351
+ Initialize: initialize,
352
+ ScanDOM: scanForCheckoutElements
353
+ });
354
+
355
+ // src/index.ts
356
+ var Fungies = createFungies();
357
+ if (typeof window !== "undefined") {
358
+ window.Fungies = Fungies;
359
+ }
360
+ export {
361
+ Fungies
362
+ };
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@fungies/fungies-js",
3
+ "version": "0.0.1",
4
+ "main": "dist/index.js",
5
+ "module": "dist/index.mjs",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsup src/index.ts --format cjs,esm --dts",
9
+ "release": "pnpm run build && changeset publish",
10
+ "prepare": "husky",
11
+ "format": "biome format --write",
12
+ "lint": "biome check"
13
+ },
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "author": "fungies",
18
+ "license": "MIT",
19
+ "description": "",
20
+ "packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0",
21
+ "devDependencies": {
22
+ "@biomejs/biome": "1.9.4",
23
+ "@changesets/cli": "^2.28.1",
24
+ "@commitlint/cli": "^19.7.1",
25
+ "@commitlint/config-conventional": "^19.7.1",
26
+ "husky": "^9.1.7",
27
+ "tsup": "^8.4.0",
28
+ "typescript": "^5.7.3"
29
+ }
30
+ }