@monei-js/components 1.7.10 → 2.1.0

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 (56) hide show
  1. package/README.md +100 -9
  2. package/dist/chunk.js +13 -0
  3. package/dist/index.cjs +1643 -0
  4. package/dist/index.d.cts +528 -0
  5. package/dist/index.d.ts +526 -14
  6. package/dist/index.js +1616 -7
  7. package/dist/monei.umd.production.min.js +64 -0
  8. package/dist/monei.umd.production.min.js.map +1 -0
  9. package/package.json +42 -65
  10. package/src/bridge/types.ts +106 -0
  11. package/dist/api.d.ts +0 -13
  12. package/dist/bizum/container.d.ts +0 -4
  13. package/dist/bizum/index.d.ts +0 -5
  14. package/dist/bizum/modal.d.ts +0 -3
  15. package/dist/bizum/types.d.ts +0 -30
  16. package/dist/cardInput/index.d.ts +0 -8
  17. package/dist/cardInput/types.d.ts +0 -51
  18. package/dist/click2pay/container.d.ts +0 -4
  19. package/dist/click2pay/index.d.ts +0 -5
  20. package/dist/click2pay/modal.d.ts +0 -3
  21. package/dist/click2pay/types.d.ts +0 -23
  22. package/dist/cofidis/container.d.ts +0 -4
  23. package/dist/cofidis/index.d.ts +0 -6
  24. package/dist/cofidis/modal.d.ts +0 -3
  25. package/dist/cofidis/types.d.ts +0 -45
  26. package/dist/cofidis/widget.d.ts +0 -3
  27. package/dist/cofidisLoan/container.d.ts +0 -4
  28. package/dist/cofidisLoan/index.d.ts +0 -7
  29. package/dist/cofidisLoan/modal.d.ts +0 -4
  30. package/dist/cofidisLoan/types.d.ts +0 -45
  31. package/dist/cofidisLoan/widget.d.ts +0 -4
  32. package/dist/components.cjs.development.js +0 -18997
  33. package/dist/components.cjs.development.js.map +0 -1
  34. package/dist/components.cjs.production.min.js +0 -2
  35. package/dist/components.cjs.production.min.js.map +0 -1
  36. package/dist/components.esm.js +0 -18979
  37. package/dist/components.esm.js.map +0 -1
  38. package/dist/config.d.ts +0 -28
  39. package/dist/container.d.ts +0 -1
  40. package/dist/enums.d.ts +0 -4
  41. package/dist/googlePay/index.d.ts +0 -4
  42. package/dist/googlePay/types.d.ts +0 -21
  43. package/dist/paymentModal/container.d.ts +0 -4
  44. package/dist/paymentModal/index.d.ts +0 -6
  45. package/dist/paymentModal/types.d.ts +0 -28
  46. package/dist/paymentRequest/index.d.ts +0 -4
  47. package/dist/paymentRequest/types.d.ts +0 -22
  48. package/dist/paypal/index.d.ts +0 -4
  49. package/dist/paypal/types.d.ts +0 -27
  50. package/dist/types.d.ts +0 -194
  51. package/dist/utils.d.ts +0 -11
  52. package/types/belter.d.ts +0 -1
  53. package/types/component.d.ts +0 -196
  54. package/types/css.d.ts +0 -9
  55. package/types/global.d.ts +0 -3
  56. package/types/post-robot.d.ts +0 -1
package/dist/index.cjs ADDED
@@ -0,0 +1,1643 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
3
+ var __defProp = Object.defineProperty;
4
+ var __exportAll = (all, no_symbols) => {
5
+ let target = {};
6
+ for (var name in all) __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
11
+ return target;
12
+ };
13
+ //#endregion
14
+ let _thumbmarkjs_thumbmarkjs = require("@thumbmarkjs/thumbmarkjs");
15
+ let penpal = require("penpal");
16
+ //#region ../shared/lib/utils.ts
17
+ /** Parse a CSS px value — accepts "10px", "10", or 10. Returns number or defaultValue. */
18
+ const parsePx = (value, defaultValue) => {
19
+ if (value == null) return defaultValue;
20
+ if (typeof value === "number") return value;
21
+ const parsed = parseInt(value);
22
+ return isNaN(parsed) ? defaultValue : parsed;
23
+ };
24
+ /** Convert a value to CSS px string — 10 → "10px", "10px" → "10px", undefined → defaultValue */
25
+ const toCssPx = (value, defaultValue) => {
26
+ if (value == null) return defaultValue;
27
+ return typeof value === "number" ? `${value}px` : value || defaultValue;
28
+ };
29
+ //#endregion
30
+ //#region src/utils.ts
31
+ var utils_exports = /* @__PURE__ */ __exportAll({
32
+ fixLocalstorage: () => fixLocalstorage,
33
+ getClientEnv: () => getClientEnv,
34
+ getClientFingerprint: () => getClientFingerprint,
35
+ isMethodSupported: () => isMethodSupported,
36
+ loadScript: () => loadScript,
37
+ parsePx: () => parsePx,
38
+ stringify: () => stringify,
39
+ toCssPx: () => toCssPx,
40
+ transformStyle: () => transformStyle,
41
+ validateComponentProps: () => validateComponentProps,
42
+ withError: () => withError
43
+ });
44
+ const transformStyle = (style) => {
45
+ return Object.keys(style).reduce((result, prop) => {
46
+ if (typeof style[prop] === "string") result[prop] = style[prop];
47
+ else result[prop] = `${style[prop]}px`;
48
+ return result;
49
+ }, {});
50
+ };
51
+ const loadScript = (src, nonce, dataset, forceReload) => {
52
+ return new Promise((resolve, reject) => {
53
+ const existingScript = Array.from(document.scripts).find((s) => s.src === src);
54
+ if (existingScript) if (forceReload) existingScript.remove();
55
+ else {
56
+ resolve(existingScript);
57
+ return;
58
+ }
59
+ const script = document.createElement("script");
60
+ script.src = src;
61
+ script.onload = () => resolve(script);
62
+ script.onerror = (error) => reject(error);
63
+ if (nonce) script.setAttribute("nonce", nonce);
64
+ if (dataset) Object.keys(dataset).forEach((key) => {
65
+ if (dataset[key]) script.dataset[key] = dataset[key];
66
+ });
67
+ document.head.appendChild(script);
68
+ });
69
+ };
70
+ const stringify = (obj) => {
71
+ return Object.keys(obj).reduce((result, key) => {
72
+ if (obj[key] !== void 0) result.push(`${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`);
73
+ return result;
74
+ }, []).join("&");
75
+ };
76
+ const fixLocalstorage = () => {
77
+ let localStorage;
78
+ try {
79
+ ({localStorage} = window);
80
+ } catch (_error) {
81
+ const localStorageMock = (() => {
82
+ let store = /* @__PURE__ */ new Map();
83
+ return {
84
+ getItem(key) {
85
+ return store.get(key);
86
+ },
87
+ setItem: function(key, value) {
88
+ store.set(key, value);
89
+ },
90
+ clear: function() {
91
+ store = /* @__PURE__ */ new Map();
92
+ },
93
+ removeItem: function(key) {
94
+ store.delete(key);
95
+ }
96
+ };
97
+ })();
98
+ Object.defineProperty(window, "localStorage", { value: localStorageMock });
99
+ localStorage = localStorageMock;
100
+ }
101
+ return localStorage;
102
+ };
103
+ const getLanguage = () => {
104
+ let lang;
105
+ const localStorage = fixLocalstorage();
106
+ try {
107
+ lang = localStorage.getItem("i18nextLng");
108
+ } catch (_error) {}
109
+ if (lang) return lang.split("-")[0];
110
+ return "";
111
+ };
112
+ const safe = (fn) => {
113
+ try {
114
+ return String(fn() ?? "");
115
+ } catch {
116
+ return "";
117
+ }
118
+ };
119
+ const getClientEnv = () => {
120
+ const env = [
121
+ window.screen.colorDepth,
122
+ window.screen.height,
123
+ window.screen.width,
124
+ (/* @__PURE__ */ new Date()).getTimezoneOffset(),
125
+ getLanguage(),
126
+ safe(() => Intl.DateTimeFormat().resolvedOptions().timeZone),
127
+ safe(() => window.devicePixelRatio),
128
+ safe(() => navigator.hardwareConcurrency),
129
+ safe(() => navigator.deviceMemory),
130
+ safe(() => navigator.maxTouchPoints),
131
+ safe(() => navigator.platform),
132
+ safe(() => navigator.languages?.join(","))
133
+ ].join("|");
134
+ return window.btoa(env);
135
+ };
136
+ const FINGERPRINT_SEED_KEY = "_monei_fp";
137
+ const randomHex = (length) => {
138
+ if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") {
139
+ const bytes = new Uint8Array(length);
140
+ crypto.getRandomValues(bytes);
141
+ return Array.from(bytes, (b) => (b % 16).toString(16)).join("");
142
+ }
143
+ return Array.from({ length }, () => Math.floor(Math.random() * 16).toString(16)).join("");
144
+ };
145
+ let cachedSeed = null;
146
+ const getPersistentSeed = async () => {
147
+ if (cachedSeed) return { seed: cachedSeed };
148
+ try {
149
+ const localStorage = fixLocalstorage();
150
+ cachedSeed = localStorage.getItem(FINGERPRINT_SEED_KEY);
151
+ if (!cachedSeed) {
152
+ cachedSeed = randomHex(32);
153
+ try {
154
+ localStorage.setItem(FINGERPRINT_SEED_KEY, cachedSeed);
155
+ } catch {}
156
+ }
157
+ } catch {
158
+ cachedSeed = randomHex(32);
159
+ }
160
+ return { seed: cachedSeed };
161
+ };
162
+ const thumbmark = new _thumbmarkjs_thumbmarkjs.Thumbmark({ logging: false });
163
+ thumbmark.includeComponent("persistent_seed", getPersistentSeed);
164
+ const getClientFingerprint = async () => {
165
+ const [, result] = await withError(thumbmark.get());
166
+ return result?.thumbmark ?? "";
167
+ };
168
+ const withError = async (p) => {
169
+ try {
170
+ return [void 0, await p];
171
+ } catch (err) {
172
+ return [err, void 0];
173
+ }
174
+ };
175
+ const isMethodSupported = (config, paymentMethod) => {
176
+ return config.paymentMethods && config.paymentMethods.includes(paymentMethod);
177
+ };
178
+ const validateComponentProps = ({ props }) => {
179
+ if (props.paymentId) return;
180
+ if (props.accountId && props.amount && props.currency) return;
181
+ throw new Error("You need to provide paymentId or accountId amount and currency");
182
+ };
183
+ //#endregion
184
+ //#region src/config.ts
185
+ const stage = {}.env?.STAGE || "prod";
186
+ const domain = {}.env?.DOMAIN || "http://localhost:3001";
187
+ const version = {}.env?.VERSION || "v1";
188
+ const globalConfig = {
189
+ domain,
190
+ version,
191
+ stage,
192
+ isProduction: stage === "prod",
193
+ paymentPageUrl: `${domain}/${version}/payment-page/`,
194
+ cardInputUrl: `${domain}/${version}/inner-card-input/`,
195
+ paymentModalUrl: `${domain}/${version}/inner-payment-modal/`,
196
+ paypalUrl: `${domain}/${version}/inner-paypal/`,
197
+ bizumUrl: `${domain}/${version}/inner-bizum/`,
198
+ bizumButtonUrl: `${domain}/${version}/inner-bizum-button/`,
199
+ paymentRequestUrl: `${domain}/${version}/inner-payment-request/`
200
+ };
201
+ const stageConfig = {
202
+ local: {
203
+ domain: "http://card-input.localhost:1355",
204
+ paymentPageUrl: `http://payment-page.localhost:1355/`,
205
+ cardInputUrl: `http://card-input.localhost:1355/`,
206
+ paymentModalUrl: `http://payment-modal.localhost:1355/`,
207
+ paypalUrl: `http://paypal.localhost:1355/`,
208
+ bizumUrl: `http://bizum.localhost:1355/`,
209
+ bizumButtonUrl: `http://bizum-button.localhost:1355/`,
210
+ paymentRequestUrl: `http://payment-request.localhost:1355/`,
211
+ apiUrl: "https://api.monei-dev.com/v1",
212
+ secureDomain: "https://secure.monei-dev.com",
213
+ rootDomain: "monei-dev.com"
214
+ },
215
+ "local-prod": {
216
+ domain: "http://card-input.localhost:1355",
217
+ paymentPageUrl: `http://payment-page.localhost:1355/`,
218
+ cardInputUrl: `http://card-input.localhost:1355/`,
219
+ paymentModalUrl: `http://payment-modal.localhost:1355/`,
220
+ paypalUrl: `http://paypal.localhost:1355/`,
221
+ bizumUrl: `http://bizum.localhost:1355/`,
222
+ bizumButtonUrl: `http://bizum-button.localhost:1355/`,
223
+ paymentRequestUrl: `http://payment-request.localhost:1355/`,
224
+ apiUrl: "https://api.monei.com/v1",
225
+ secureDomain: "https://secure.monei.com",
226
+ rootDomain: "monei.com"
227
+ },
228
+ tunnel: {
229
+ domain: "https://card-input.monei-dev-tunnel.com",
230
+ paymentPageUrl: `https://payment-page.monei-dev-tunnel.com/`,
231
+ cardInputUrl: `https://card-input.monei-dev-tunnel.com/`,
232
+ paymentModalUrl: `https://payment-modal.monei-dev-tunnel.com/`,
233
+ paypalUrl: `https://paypal.monei-dev-tunnel.com/`,
234
+ bizumUrl: `https://bizum.monei-dev-tunnel.com/`,
235
+ bizumButtonUrl: `https://bizum-button.monei-dev-tunnel.com/`,
236
+ paymentRequestUrl: `https://payment-request.monei-dev-tunnel.com/`,
237
+ apiUrl: "https://api.monei.com/v1",
238
+ secureDomain: "https://secure.monei.com",
239
+ rootDomain: "monei.com"
240
+ },
241
+ dev: {
242
+ apiUrl: "https://api.monei-dev.com/v1",
243
+ secureDomain: "https://secure.monei-dev.com",
244
+ rootDomain: "monei-dev.com"
245
+ },
246
+ prod: {
247
+ apiUrl: "https://api.monei.com/v1",
248
+ secureDomain: "https://secure.monei.com",
249
+ rootDomain: "monei.com"
250
+ }
251
+ };
252
+ const config = {
253
+ ...globalConfig,
254
+ ...stageConfig[stage]
255
+ };
256
+ //#endregion
257
+ //#region src/api.ts
258
+ var api_exports = /* @__PURE__ */ __exportAll({
259
+ confirmPayment: () => confirmPayment$1,
260
+ createApplePaySession: () => createApplePaySession,
261
+ createPayment: () => createPayment,
262
+ createToken: () => createToken$1,
263
+ getPayment: () => getPayment,
264
+ getPaymentMethods: () => getPaymentMethods,
265
+ sendPaymentReceipt: () => sendPaymentReceipt,
266
+ validateBizumPhone: () => validateBizumPhone
267
+ });
268
+ const request = async (url, { method = "GET", headers, body } = {}) => {
269
+ if (method === "POST") headers = {
270
+ "Content-Type": "application/json",
271
+ ...headers
272
+ };
273
+ const res = await fetch(`${config.apiUrl}${url}`, {
274
+ method,
275
+ headers,
276
+ body: body ? JSON.stringify(body) : void 0
277
+ });
278
+ const [, result] = await withError(res.json());
279
+ if (!res.ok) throw result || new Error(res.statusText);
280
+ return result;
281
+ };
282
+ const pmCache = {};
283
+ const getPaymentMethods = async ({ accountId, paymentId }) => {
284
+ let params;
285
+ if (paymentId) params = { paymentId };
286
+ else if (accountId) params = { accountId };
287
+ else throw new Error("You need to provide paymentId or accountId");
288
+ const query = stringify(params);
289
+ if (query in pmCache) return pmCache[query];
290
+ const promise = request(`/payment-methods?${query}`);
291
+ pmCache[query] = promise;
292
+ promise.catch(() => delete pmCache[query]);
293
+ return promise;
294
+ };
295
+ const createToken$1 = async ({ paymentMethod, paymentId, sessionId, amount, currency, accountId, transactionType }) => {
296
+ let body;
297
+ if (paymentId) body = {
298
+ paymentId,
299
+ paymentMethod
300
+ };
301
+ else if (accountId) body = {
302
+ accountId,
303
+ paymentMethod,
304
+ sessionId,
305
+ amount,
306
+ currency,
307
+ transactionType
308
+ };
309
+ else throw new Error("You need to provide paymentId or accountId");
310
+ const res = await request("/tokens", {
311
+ method: "POST",
312
+ headers: {
313
+ "X-Client-Env": getClientEnv(),
314
+ "X-Client-Fingerprint": await getClientFingerprint()
315
+ },
316
+ body
317
+ });
318
+ if (res.paymentToken && !res.token) res.token = res.paymentToken;
319
+ return res;
320
+ };
321
+ const getPayment = async (paymentId) => {
322
+ return request(`/payments/${paymentId}/client-get`);
323
+ };
324
+ const confirmPayment$1 = async ({ paymentId, ...body }) => {
325
+ return request(`/payments/${paymentId}/client-confirm`, {
326
+ method: "POST",
327
+ headers: {
328
+ "X-Client-Env": getClientEnv(),
329
+ "X-Client-Fingerprint": await getClientFingerprint()
330
+ },
331
+ body
332
+ });
333
+ };
334
+ const createPayment = async ({ signature, ...body }) => {
335
+ return request("/client-payments", {
336
+ method: "POST",
337
+ headers: {
338
+ "X-Client-Env": getClientEnv(),
339
+ "X-Client-Fingerprint": await getClientFingerprint(),
340
+ "Client-Signature": signature
341
+ },
342
+ body
343
+ });
344
+ };
345
+ const sendPaymentReceipt = async ({ paymentId, customerEmail, signature, language }) => {
346
+ return request(`/payments/${paymentId}/client-receipt`, {
347
+ method: "POST",
348
+ body: {
349
+ customerEmail,
350
+ signature,
351
+ language
352
+ }
353
+ });
354
+ };
355
+ const createApplePaySession = async (body) => {
356
+ return request(`/apple-pay/sessions`, {
357
+ method: "POST",
358
+ body
359
+ });
360
+ };
361
+ const validateBizumPhone = async (req) => {
362
+ return request(`/bizum/validate-phone`, {
363
+ method: "POST",
364
+ body: req
365
+ });
366
+ };
367
+ //#endregion
368
+ //#region src/bridge/event-emitter.ts
369
+ var EventEmitter = class {
370
+ constructor() {
371
+ this.listeners = /* @__PURE__ */ new Map();
372
+ this.destroyed = false;
373
+ }
374
+ on(eventName, handler) {
375
+ if (this.destroyed) return { cancel: () => {} };
376
+ let handlers = this.listeners.get(eventName);
377
+ if (!handlers) {
378
+ handlers = /* @__PURE__ */ new Set();
379
+ this.listeners.set(eventName, handlers);
380
+ }
381
+ handlers.add(handler);
382
+ return { cancel: () => {
383
+ handlers.delete(handler);
384
+ } };
385
+ }
386
+ once(eventName, handler) {
387
+ const wrapper = (...args) => {
388
+ this.off(eventName, wrapper);
389
+ handler(...args);
390
+ };
391
+ return this.on(eventName, wrapper);
392
+ }
393
+ trigger(eventName, ...args) {
394
+ if (this.destroyed) return;
395
+ const handlers = this.listeners.get(eventName);
396
+ if (!handlers) return;
397
+ for (const handler of handlers) try {
398
+ handler(...args);
399
+ } catch (e) {
400
+ console.error(e);
401
+ }
402
+ }
403
+ off(eventName, handler) {
404
+ const handlers = this.listeners.get(eventName);
405
+ if (handlers) handlers.delete(handler);
406
+ }
407
+ destroy() {
408
+ this.destroyed = true;
409
+ this.listeners.clear();
410
+ }
411
+ };
412
+ //#endregion
413
+ //#region src/bridge/drivers/react.ts
414
+ /**
415
+ * Creates a React driver for a bridge component.
416
+ * Returns a forwardRef component that:
417
+ * - On mount: creates bridge instance, renders into container div
418
+ * - On update: calls updateProps with new props
419
+ * - On unmount: calls destroy
420
+ * - Exposes bridge instance via ref (needed for CardInput's createToken)
421
+ */
422
+ function createReactDriver(ComponentClass) {
423
+ return ({ React }) => {
424
+ return React.forwardRef(function BridgeReactWrapper(props, ref) {
425
+ const containerRef = React.useRef(null);
426
+ const instanceRef = React.useRef(null);
427
+ const isMounted = React.useRef(false);
428
+ const prevPropsRef = React.useRef({});
429
+ React.useLayoutEffect(() => {
430
+ const el = containerRef.current;
431
+ if (!el) return;
432
+ let cancelled = false;
433
+ const instance = new ComponentClass({ ...props });
434
+ instanceRef.current = instance;
435
+ instance.render(el).then(() => {
436
+ if (cancelled) return;
437
+ setRef(ref, instance);
438
+ isMounted.current = true;
439
+ }).catch((err) => {
440
+ if (!cancelled) console.error(err);
441
+ });
442
+ return () => {
443
+ cancelled = true;
444
+ instance.destroy();
445
+ instanceRef.current = null;
446
+ isMounted.current = false;
447
+ setRef(ref, null);
448
+ };
449
+ }, []);
450
+ React.useEffect(() => {
451
+ if (!isMounted.current || !instanceRef.current) return;
452
+ if (shallowEqual$1(prevPropsRef.current, props)) return;
453
+ prevPropsRef.current = { ...props };
454
+ instanceRef.current.updateProps({ ...props }).catch(noop);
455
+ });
456
+ return React.createElement("div", { ref: containerRef });
457
+ });
458
+ };
459
+ }
460
+ /** Set a React ref (callback or object ref) */
461
+ function setRef(ref, value) {
462
+ if (typeof ref === "function") ref(value);
463
+ else if (ref) ref.current = value;
464
+ }
465
+ function shallowEqual$1(a, b) {
466
+ const keysA = Object.keys(a);
467
+ const keysB = Object.keys(b);
468
+ if (keysA.length !== keysB.length) return false;
469
+ for (const key of keysA) if (a[key] !== b[key]) return false;
470
+ return true;
471
+ }
472
+ function noop() {}
473
+ //#endregion
474
+ //#region src/bridge/drivers/vue.ts
475
+ /**
476
+ * Creates a Vue 3 driver for a bridge component.
477
+ * Returns a Vue component options object that:
478
+ * - On mounted: creates bridge instance, renders into template div
479
+ * - On $attrs change: calls updateProps
480
+ * - On unmounted: calls destroy
481
+ * - Exposes bridge instance via template ref
482
+ */
483
+ function createVue3Driver(ComponentClass) {
484
+ return () => ({
485
+ template: "<div></div>",
486
+ inheritAttrs: false,
487
+ mounted() {
488
+ const el = this.$el;
489
+ this.__bridgeInstance = new ComponentClass({ ...this.$attrs });
490
+ this.__bridgeInstance.render(el).catch(console.error);
491
+ },
492
+ watch: { $attrs: {
493
+ handler() {
494
+ if (this.__bridgeInstance) this.__bridgeInstance.updateProps({ ...this.$attrs }).catch(() => {});
495
+ },
496
+ deep: true
497
+ } },
498
+ unmounted() {
499
+ if (this.__bridgeInstance) {
500
+ this.__bridgeInstance.destroy();
501
+ this.__bridgeInstance = null;
502
+ }
503
+ }
504
+ });
505
+ }
506
+ //#endregion
507
+ //#region src/bridge/drivers/angular.ts
508
+ /**
509
+ * Creates an Angular driver for a bridge component.
510
+ * Returns an Angular module that declares a component which:
511
+ * - On ngOnInit: creates bridge instance, renders into host element
512
+ * - On ngDoCheck: calls updateProps when props change
513
+ * - On ngOnDestroy: calls destroy
514
+ */
515
+ function createAngularDriver(ComponentClass) {
516
+ return ({ Component: AngularComponent, NgModule, ElementRef, NgZone, Inject }) => {
517
+ class ComponentInstance {
518
+ constructor(elementRef, zone) {
519
+ this.props = {};
520
+ this.__bridgeInstance = null;
521
+ this._prevProps = {};
522
+ this.elementRef = elementRef;
523
+ this.zone = zone;
524
+ }
525
+ getProps() {
526
+ const wrapped = { ...this.props };
527
+ const { zone } = this;
528
+ for (const [key, value] of Object.entries(wrapped)) if (typeof value === "function") wrapped[key] = function angularZoneWrapped(...args) {
529
+ return zone.run(() => value.apply(this, args));
530
+ };
531
+ return wrapped;
532
+ }
533
+ ngOnInit() {
534
+ const el = this.elementRef.nativeElement;
535
+ this.__bridgeInstance = new ComponentClass(this.getProps());
536
+ this.__bridgeInstance.render(el).catch(console.error);
537
+ }
538
+ ngDoCheck() {
539
+ if (this.__bridgeInstance && !shallowEqual(this._prevProps, this.props)) {
540
+ this._prevProps = { ...this.props };
541
+ this.__bridgeInstance.updateProps(this.getProps()).catch(() => {});
542
+ }
543
+ }
544
+ ngOnDestroy() {
545
+ if (this.__bridgeInstance) {
546
+ this.__bridgeInstance.destroy();
547
+ this.__bridgeInstance = null;
548
+ }
549
+ }
550
+ }
551
+ ComponentInstance.parameters = [[new Inject(ElementRef)], [new Inject(NgZone)]];
552
+ ComponentInstance.annotations = [new AngularComponent({
553
+ selector: ComponentClass.prototype.__options?.tag || "bridge-component",
554
+ template: "<div></div>",
555
+ inputs: ["props"]
556
+ })];
557
+ class ModuleInstance {}
558
+ ModuleInstance.annotations = [new NgModule({
559
+ declarations: [ComponentInstance],
560
+ exports: [ComponentInstance]
561
+ })];
562
+ return ModuleInstance;
563
+ };
564
+ }
565
+ function shallowEqual(a, b) {
566
+ const keysA = Object.keys(a);
567
+ const keysB = Object.keys(b);
568
+ if (keysA.length !== keysB.length) return false;
569
+ for (const key of keysA) if (a[key] !== b[key]) return false;
570
+ return true;
571
+ }
572
+ //#endregion
573
+ //#region src/bridge/drivers/index.ts
574
+ const driverFactories = {
575
+ react: createReactDriver,
576
+ vue3: createVue3Driver,
577
+ angular: createAngularDriver
578
+ };
579
+ /**
580
+ * Resolve a framework driver for a bridge component constructor.
581
+ * Called by both the static and instance .driver() methods.
582
+ */
583
+ function resolveDriver(name, ComponentClass, deps) {
584
+ const factory = driverFactories[name];
585
+ if (!factory) throw new Error(`Unknown driver: ${name}. Available: ${Object.keys(driverFactories).join(", ")}`);
586
+ return factory(ComponentClass)(deps);
587
+ }
588
+ //#endregion
589
+ //#region ../shared/lib/bridge-constants.ts
590
+ /** Protocol identifier for sync bootstrap messages between parent and child bridges */
591
+ const BRIDGE_INIT_MSG = "__monei_bridge_init__";
592
+ //#endregion
593
+ //#region src/bridge/constants.ts
594
+ /** Bridge lifecycle events (replaces zoid.EVENT) */
595
+ const EVENT = {
596
+ RENDERED: "RENDERED",
597
+ RESIZE: "RESIZE",
598
+ DESTROY: "DESTROY",
599
+ BEFORE_CLOSE: "BEFORE_CLOSE",
600
+ DISPLAY: "DISPLAY"
601
+ };
602
+ /**
603
+ * Lifecycle prop names filtered from dispatch.
604
+ * These are wired to bridge events, NOT forwarded to child.
605
+ *
606
+ * NOTE: onError, onFocus, onLoad are NOT here — they are user-facing
607
+ * props that merchants pass and children call.
608
+ */
609
+ const LIFECYCLE_PROPS = new Set([
610
+ "onClose",
611
+ "onDestroy",
612
+ "onRendered",
613
+ "onRender",
614
+ "onDisplay",
615
+ "onResize",
616
+ "onProps"
617
+ ]);
618
+ //#endregion
619
+ //#region src/bridge/props.ts
620
+ /**
621
+ * DOM utility: remove element from DOM.
622
+ * Replaces belter.destroyElement().
623
+ */
624
+ function destroyElement(el) {
625
+ if (el) el.remove();
626
+ }
627
+ /**
628
+ * CSS utility: convert number to CSS pixel string, pass strings through.
629
+ * Replaces belter.toCSS().
630
+ */
631
+ function toCSS(value) {
632
+ return typeof value === "number" ? `${value}px` : value;
633
+ }
634
+ //#endregion
635
+ //#region src/bridge/render.ts
636
+ /** Per-component iframe sandbox attributes — least-privilege per component */
637
+ const SANDBOX = {
638
+ "monei-card-input": "allow-scripts allow-forms allow-same-origin",
639
+ "monei-bizum": "allow-scripts allow-forms allow-same-origin allow-popups allow-popups-to-escape-sandbox",
640
+ "monei-bizum-button": "allow-scripts allow-forms allow-same-origin allow-popups allow-popups-to-escape-sandbox",
641
+ "monei-paypal": "allow-scripts allow-forms allow-same-origin allow-popups allow-popups-to-escape-sandbox",
642
+ "monei-payment-request": "allow-scripts allow-forms allow-same-origin allow-popups",
643
+ "monei-payment-modal": "allow-scripts allow-forms allow-same-origin allow-popups allow-popups-to-escape-sandbox",
644
+ "monei-google-pay": "allow-scripts allow-forms allow-same-origin allow-popups"
645
+ };
646
+ /**
647
+ * Resolve a container argument to an HTMLElement.
648
+ */
649
+ function resolveContainer(container) {
650
+ if (!container) throw new Error("render() requires a container element or selector");
651
+ if (typeof container === "string") {
652
+ const el = document.querySelector(container);
653
+ if (!el) throw new Error(`Container not found: ${container}`);
654
+ return el;
655
+ }
656
+ return container;
657
+ }
658
+ /**
659
+ * Generate a unique ID for the container element.
660
+ */
661
+ function generateUid(tag) {
662
+ return `${tag}-${Math.random().toString(36).slice(2, 9)}`;
663
+ }
664
+ /**
665
+ * Wire lifecycle props to bridge events.
666
+ * Called before containerTemplate in the render flow.
667
+ */
668
+ function wireLifecycleProps(props, event) {
669
+ const mappings = [
670
+ ["onClose", EVENT.DESTROY],
671
+ ["onDestroy", EVENT.DESTROY],
672
+ ["onRendered", EVENT.RENDERED],
673
+ ["onResize", EVENT.RESIZE]
674
+ ];
675
+ for (const [propKey, eventName] of mappings) event.on(eventName, (...args) => {
676
+ const fn = props[propKey];
677
+ if (typeof fn === "function") fn(...args);
678
+ });
679
+ }
680
+ /**
681
+ * Execute computed prop factories and classify remaining user props into
682
+ * dispatch map (functions) and data payload (everything else).
683
+ * Called AFTER containerTemplate so computed factories see state mutations.
684
+ */
685
+ function buildDataPayload(context) {
686
+ const { props, options, state, dispatchMap } = context;
687
+ const dataProps = {};
688
+ const computedPropKeys = new Set(options.computedProps ? Object.keys(options.computedProps) : []);
689
+ if (options.computedProps) for (const [key, config] of Object.entries(options.computedProps)) {
690
+ const result = config.factory({
691
+ props,
692
+ state
693
+ });
694
+ if (config.type === "function") dispatchMap.set(key, result);
695
+ else dataProps[key] = result;
696
+ }
697
+ for (const [key, value] of Object.entries(props)) {
698
+ if (LIFECYCLE_PROPS.has(key) || computedPropKeys.has(key)) continue;
699
+ if (typeof value === "function") dispatchMap.set(key, value);
700
+ else dataProps[key] = value;
701
+ }
702
+ const builtins = new Set([
703
+ "close",
704
+ "resize",
705
+ "show",
706
+ "hide",
707
+ "getParentDomain",
708
+ "focus"
709
+ ]);
710
+ return {
711
+ dataProps,
712
+ functionNames: [...dispatchMap.keys()].filter((k) => !builtins.has(k))
713
+ };
714
+ }
715
+ /**
716
+ * Implements .render(), .updateProps(), .destroy(), .close() on a bridge component instance.
717
+ * Called once from createComponent to wire up the actual rendering logic.
718
+ */
719
+ function attachRenderMethods(instance, options) {
720
+ const renderState = {
721
+ dispatchMap: /* @__PURE__ */ new Map(),
722
+ connection: null,
723
+ remote: null,
724
+ containerEl: null,
725
+ frame: null,
726
+ destroyed: false,
727
+ ownsContainer: false,
728
+ pendingPropsUpdate: null,
729
+ pendingRemovals: /* @__PURE__ */ new Set()
730
+ };
731
+ let renderedTriggered = false;
732
+ let lifecycleWired = false;
733
+ renderState.dispatchMap.set("resize", (dimensions) => {
734
+ const { autoResize } = options;
735
+ const applied = {};
736
+ if (dimensions.width !== void 0 && (!autoResize || autoResize.width === true)) applied.width = dimensions.width;
737
+ if (dimensions.height !== void 0 && (!autoResize || autoResize.height === true)) applied.height = dimensions.height;
738
+ if (renderState.frame) {
739
+ if (applied.width !== void 0) renderState.frame.style.width = toCSS(applied.width);
740
+ if (applied.height !== void 0) renderState.frame.style.height = toCSS(applied.height);
741
+ }
742
+ if (!renderedTriggered) {
743
+ renderedTriggered = true;
744
+ instance.event.trigger(EVENT.RENDERED);
745
+ }
746
+ instance.event.trigger(EVENT.RESIZE, applied);
747
+ });
748
+ renderState.dispatchMap.set("close", () => instance.close());
749
+ renderState.dispatchMap.set("show", () => {
750
+ if (renderState.frame) renderState.frame.style.display = "";
751
+ });
752
+ renderState.dispatchMap.set("hide", () => {
753
+ if (renderState.frame) renderState.frame.style.display = "none";
754
+ });
755
+ renderState.dispatchMap.set("getParentDomain", () => window.location.origin);
756
+ renderState.dispatchMap.set("focus", () => {
757
+ if (renderState.frame) renderState.frame.focus();
758
+ });
759
+ /**
760
+ * Render the component into the DOM and establish Penpal connection.
761
+ *
762
+ * Phase ordering:
763
+ * 1. wireLifecycleProps — bind onClose/onRendered/onResize to bridge events
764
+ * 2. prerenderTemplate — create loading placeholder (optional)
765
+ * 3. containerTemplate — build wrapper DOM, may mutate `state` (e.g., state.__container for PayPal)
766
+ * 4. buildDataPayload — run computed prop factories (read state mutations from step 3),
767
+ * classify user props into dispatch map (functions) and data payload (serializable values)
768
+ * 5. appendToDOM — container or bare iframe inserted into target element
769
+ * 6. triggerDISPLAY — notify container template that DOM is ready
770
+ * 7. sendBootstrap — postMessage initial props to iframe before script loads
771
+ * 8. createConnection — establish Penpal async RPC channel, deliver props via updateProps
772
+ */
773
+ instance.render = async (container) => {
774
+ if (renderState.destroyed) throw new Error("Component is destroyed");
775
+ if (renderState.frame) throw new Error("Component already rendered");
776
+ const targetEl = resolveContainer(container);
777
+ const uid = generateUid(options.tag);
778
+ const doc = targetEl.ownerDocument;
779
+ const frame = doc.createElement("iframe");
780
+ frame.src = options.url;
781
+ frame.setAttribute("title", options.tag.replace(/-/g, "_"));
782
+ frame.setAttribute("allowpaymentrequest", "true");
783
+ frame.setAttribute("allow", "payment");
784
+ frame.style.border = "none";
785
+ const sandbox = SANDBOX[options.tag] ?? "allow-scripts allow-forms allow-same-origin";
786
+ frame.setAttribute("sandbox", sandbox);
787
+ if (!lifecycleWired) {
788
+ wireLifecycleProps(instance.props, instance.event);
789
+ lifecycleWired = true;
790
+ }
791
+ const templateSubs = [];
792
+ const trackedEvent = {
793
+ on(eventName, handler) {
794
+ const sub = instance.event.on(eventName, handler);
795
+ templateSubs.push(sub);
796
+ return sub;
797
+ },
798
+ once(eventName, handler) {
799
+ const sub = instance.event.once(eventName, handler);
800
+ templateSubs.push(sub);
801
+ return sub;
802
+ },
803
+ trigger(eventName, ...args) {
804
+ instance.event.trigger(eventName, ...args);
805
+ },
806
+ off(eventName, handler) {
807
+ instance.event.off(eventName, handler);
808
+ },
809
+ destroy() {
810
+ instance.event.destroy();
811
+ }
812
+ };
813
+ let placeholder;
814
+ let containerNode;
815
+ let dataProps = {};
816
+ let functionNames = [];
817
+ try {
818
+ if (options.prerenderTemplate) placeholder = options.prerenderTemplate({
819
+ uid,
820
+ frame,
821
+ placeholder: void 0,
822
+ doc,
823
+ props: instance.props,
824
+ event: trackedEvent,
825
+ dimensions: options.dimensions ?? {
826
+ width: "100%",
827
+ height: "auto"
828
+ },
829
+ state: instance.state,
830
+ container: targetEl
831
+ });
832
+ if (options.containerTemplate) containerNode = options.containerTemplate({
833
+ uid,
834
+ frame,
835
+ placeholder,
836
+ doc,
837
+ props: instance.props,
838
+ event: trackedEvent,
839
+ dimensions: options.dimensions ?? {
840
+ width: "100%",
841
+ height: "auto"
842
+ },
843
+ state: instance.state,
844
+ container: targetEl
845
+ });
846
+ ({dataProps, functionNames} = buildDataPayload({
847
+ props: instance.props,
848
+ options,
849
+ state: instance.state,
850
+ dispatchMap: renderState.dispatchMap
851
+ }));
852
+ } catch (err) {
853
+ for (const sub of templateSubs) sub.cancel();
854
+ const builtins = new Set([
855
+ "close",
856
+ "resize",
857
+ "show",
858
+ "hide",
859
+ "getParentDomain",
860
+ "focus"
861
+ ]);
862
+ for (const key of renderState.dispatchMap.keys()) if (!builtins.has(key)) renderState.dispatchMap.delete(key);
863
+ throw err;
864
+ }
865
+ renderState.frame = frame;
866
+ const sendInitialProps = () => {
867
+ if (frame.contentWindow) frame.contentWindow.postMessage({
868
+ type: BRIDGE_INIT_MSG,
869
+ props: dataProps,
870
+ functionNames
871
+ }, new URL(options.url).origin);
872
+ };
873
+ try {
874
+ if (containerNode) {
875
+ targetEl.appendChild(containerNode);
876
+ renderState.containerEl = containerNode;
877
+ renderState.ownsContainer = true;
878
+ } else {
879
+ targetEl.appendChild(frame);
880
+ renderState.containerEl = targetEl;
881
+ }
882
+ instance.event.trigger(EVENT.DISPLAY);
883
+ frame.addEventListener("load", sendInitialProps);
884
+ if (frame.contentWindow) sendInitialProps();
885
+ if (!frame.contentWindow) throw new Error("iframe contentWindow is not available — frame may not be in the DOM");
886
+ const connection = (0, penpal.connect)({
887
+ messenger: new penpal.WindowMessenger({
888
+ remoteWindow: frame.contentWindow,
889
+ allowedOrigins: [new URL(options.url).origin]
890
+ }),
891
+ methods: { callParent: (name, args) => {
892
+ const fn = renderState.dispatchMap.get(name);
893
+ if (!fn) throw new Error(`Unknown parent method: ${name}`);
894
+ return fn(...args);
895
+ } }
896
+ });
897
+ renderState.connection = connection;
898
+ let remote;
899
+ try {
900
+ remote = await connection.promise;
901
+ } catch (err) {
902
+ if (renderState.destroyed) return;
903
+ throw err;
904
+ }
905
+ if (renderState.destroyed) return;
906
+ renderState.remote = remote;
907
+ instance.state.__callChild = remote.callChild;
908
+ await remote.updateProps(dataProps, functionNames);
909
+ if (renderState.destroyed) return;
910
+ if (renderState.pendingPropsUpdate) {
911
+ const pending = renderState.pendingPropsUpdate;
912
+ renderState.pendingPropsUpdate = null;
913
+ const retainedFns = new Set(pending.functionNames ?? []);
914
+ const flushRemovals = /* @__PURE__ */ new Map();
915
+ for (const key of Object.keys(pending.dataProps)) if (renderState.dispatchMap.has(key) && !retainedFns.has(key)) {
916
+ flushRemovals.set(key, renderState.dispatchMap.get(key));
917
+ renderState.pendingRemovals.add(key);
918
+ }
919
+ await renderState.remote.updateProps(pending.dataProps, pending.functionNames);
920
+ if (renderState.destroyed) return;
921
+ for (const [key, originalFn] of flushRemovals) {
922
+ renderState.pendingRemovals.delete(key);
923
+ if (renderState.dispatchMap.get(key) === originalFn) renderState.dispatchMap.delete(key);
924
+ }
925
+ }
926
+ if (!renderedTriggered) {
927
+ renderedTriggered = true;
928
+ instance.event.trigger(EVENT.RENDERED);
929
+ }
930
+ frame.removeEventListener("load", sendInitialProps);
931
+ } catch (err) {
932
+ frame.removeEventListener("load", sendInitialProps);
933
+ for (const sub of templateSubs) sub.cancel();
934
+ delete instance.state.__callChild;
935
+ if (renderState.connection) {
936
+ renderState.connection.destroy();
937
+ renderState.connection = null;
938
+ }
939
+ renderState.remote = null;
940
+ renderState.frame = null;
941
+ if (renderState.ownsContainer && renderState.containerEl) renderState.containerEl.remove();
942
+ else if (frame.parentNode) frame.remove();
943
+ renderState.containerEl = null;
944
+ renderState.ownsContainer = false;
945
+ renderState.pendingPropsUpdate = null;
946
+ renderState.pendingRemovals.clear();
947
+ const builtins = new Set([
948
+ "close",
949
+ "resize",
950
+ "show",
951
+ "hide",
952
+ "getParentDomain",
953
+ "focus"
954
+ ]);
955
+ for (const key of renderState.dispatchMap.keys()) if (!builtins.has(key)) renderState.dispatchMap.delete(key);
956
+ renderedTriggered = false;
957
+ throw err;
958
+ }
959
+ };
960
+ instance.updateProps = async (newProps) => {
961
+ if (renderState.destroyed) throw new Error("Component is destroyed");
962
+ const normalized = normalizeAliases(newProps, options.aliases);
963
+ Object.assign(instance.props, normalized);
964
+ if (!renderState.frame) return;
965
+ const newDataProps = {};
966
+ const newFunctionNames = [];
967
+ const computedPropKeys = new Set(options.computedProps ? Object.keys(options.computedProps) : []);
968
+ const deferredRemovals = /* @__PURE__ */ new Map();
969
+ for (const [key, value] of Object.entries(normalized)) {
970
+ if (LIFECYCLE_PROPS.has(key) || computedPropKeys.has(key)) continue;
971
+ if (typeof value === "function") {
972
+ const hasStaleBufferedData = renderState.pendingPropsUpdate != null && key in renderState.pendingPropsUpdate.dataProps;
973
+ const hasPendingRemoval = renderState.pendingRemovals.has(key);
974
+ if (!renderState.dispatchMap.has(key) || hasStaleBufferedData || hasPendingRemoval) newFunctionNames.push(key);
975
+ renderState.dispatchMap.set(key, value);
976
+ } else {
977
+ if (renderState.dispatchMap.has(key)) {
978
+ if (renderState.remote) {
979
+ deferredRemovals.set(key, renderState.dispatchMap.get(key));
980
+ renderState.pendingRemovals.add(key);
981
+ }
982
+ }
983
+ newDataProps[key] = value;
984
+ }
985
+ }
986
+ const resolvedFunctionNames = newFunctionNames.length > 0 ? newFunctionNames : void 0;
987
+ if (renderState.remote) {
988
+ await renderState.remote.updateProps(newDataProps, resolvedFunctionNames);
989
+ for (const [key, originalFn] of deferredRemovals) {
990
+ renderState.pendingRemovals.delete(key);
991
+ if (renderState.dispatchMap.get(key) === originalFn) renderState.dispatchMap.delete(key);
992
+ }
993
+ } else {
994
+ if (!renderState.pendingPropsUpdate) renderState.pendingPropsUpdate = {
995
+ dataProps: {},
996
+ functionNames: void 0
997
+ };
998
+ Object.assign(renderState.pendingPropsUpdate.dataProps, newDataProps);
999
+ if (renderState.pendingPropsUpdate.functionNames) {
1000
+ const dataKeys = Object.keys(newDataProps);
1001
+ if (dataKeys.length > 0) {
1002
+ const dataKeySet = new Set(dataKeys);
1003
+ renderState.pendingPropsUpdate.functionNames = renderState.pendingPropsUpdate.functionNames.filter((n) => !dataKeySet.has(n));
1004
+ if (renderState.pendingPropsUpdate.functionNames.length === 0) renderState.pendingPropsUpdate.functionNames = void 0;
1005
+ }
1006
+ }
1007
+ if (resolvedFunctionNames) {
1008
+ for (const name of resolvedFunctionNames) delete renderState.pendingPropsUpdate.dataProps[name];
1009
+ renderState.pendingPropsUpdate.functionNames = [...renderState.pendingPropsUpdate.functionNames ?? [], ...resolvedFunctionNames];
1010
+ }
1011
+ }
1012
+ };
1013
+ instance.destroy = async () => {
1014
+ if (renderState.destroyed) return;
1015
+ renderState.destroyed = true;
1016
+ instance.event.trigger(EVENT.DESTROY);
1017
+ if (renderState.connection) {
1018
+ renderState.connection.destroy();
1019
+ renderState.connection = null;
1020
+ }
1021
+ renderState.remote = null;
1022
+ if (renderState.frame) {
1023
+ renderState.frame.remove();
1024
+ renderState.frame = null;
1025
+ }
1026
+ if (renderState.ownsContainer && renderState.containerEl) renderState.containerEl.remove();
1027
+ instance.event.destroy();
1028
+ renderState.dispatchMap.clear();
1029
+ };
1030
+ instance.close = async () => {
1031
+ await instance.destroy();
1032
+ };
1033
+ /**
1034
+ * Expose renderState for tests
1035
+ */
1036
+ instance.__renderState = renderState;
1037
+ }
1038
+ //#endregion
1039
+ //#region src/bridge/create-component.ts
1040
+ const driverPackageMap = {
1041
+ react: "@monei-js/react-components",
1042
+ vue3: "@monei-js/vue-components",
1043
+ angular: "@monei-js/angular-components"
1044
+ };
1045
+ function warnDriverDeprecation(name) {
1046
+ const pkg = driverPackageMap[name];
1047
+ const replacement = pkg ? `Use ${pkg} instead.` : "";
1048
+ console.warn(`[MONEI] .driver('${name}') is deprecated. ${replacement}`.trim());
1049
+ }
1050
+ /**
1051
+ * Normalize aliased prop names to canonical names.
1052
+ * Aliases define alternative INPUT names: { style: 'innerStyle' } means
1053
+ * merchants can pass either `style` or `innerStyle`, but internally
1054
+ * the canonical name `style` is always used (matching zoid semantics).
1055
+ */
1056
+ function normalizeAliases(props, aliases) {
1057
+ if (!aliases) return props;
1058
+ const reverseMap = /* @__PURE__ */ new Map();
1059
+ for (const [canonical, alias] of Object.entries(aliases)) reverseMap.set(alias, canonical);
1060
+ const result = {};
1061
+ for (const [key, value] of Object.entries(props)) {
1062
+ const canonicalKey = reverseMap.get(key) ?? key;
1063
+ result[canonicalKey] = value;
1064
+ }
1065
+ return result;
1066
+ }
1067
+ /**
1068
+ * Creates a bridge component constructor (replaces zoid.create).
1069
+ *
1070
+ * Returns a class that can be instantiated with `new Component(props)`
1071
+ * and has a static `.driver()` method for framework wrappers.
1072
+ */
1073
+ function createComponent(options) {
1074
+ class Component {
1075
+ constructor(props) {
1076
+ this.state = {};
1077
+ this.event = new EventEmitter();
1078
+ const normalizedProps = normalizeAliases(props, options.aliases);
1079
+ if (options.defaultProps) this.props = {
1080
+ ...options.defaultProps({ event: this.event }),
1081
+ ...normalizedProps
1082
+ };
1083
+ else this.props = { ...normalizedProps };
1084
+ if (options.validate) options.validate({ props: this.props });
1085
+ attachRenderMethods(this, options);
1086
+ if (options.submit) this.submit = options.submit(this);
1087
+ }
1088
+ async render(_container) {
1089
+ throw new Error("render() not attached");
1090
+ }
1091
+ async updateProps(_props) {
1092
+ throw new Error("updateProps() not attached — call render() first");
1093
+ }
1094
+ async close() {
1095
+ throw new Error("close() not attached");
1096
+ }
1097
+ async destroy() {
1098
+ throw new Error("destroy() not attached");
1099
+ }
1100
+ driver(name, deps) {
1101
+ warnDriverDeprecation(name);
1102
+ return resolveDriver(name, Component, deps);
1103
+ }
1104
+ }
1105
+ function ComponentWrapper(props) {
1106
+ if (!(this instanceof ComponentWrapper)) return new ComponentWrapper(props);
1107
+ return new Component(props);
1108
+ }
1109
+ ComponentWrapper.prototype = Component.prototype;
1110
+ ComponentWrapper.driver = function(name, deps) {
1111
+ warnDriverDeprecation(name);
1112
+ return resolveDriver(name, ComponentWrapper, deps);
1113
+ };
1114
+ Component.prototype.__options = options;
1115
+ return ComponentWrapper;
1116
+ }
1117
+ //#endregion
1118
+ //#region src/enums.ts
1119
+ let CLASS = /* @__PURE__ */ function(CLASS) {
1120
+ CLASS["VISIBLE"] = "is-visible";
1121
+ CLASS["INVISIBLE"] = "is-invisible";
1122
+ return CLASS;
1123
+ }({});
1124
+ //#endregion
1125
+ //#region src/container.ts
1126
+ function createContainerTemplate(config = {}) {
1127
+ const { background = "#fff", overflow, borderRadius, fadeOnRender = true, allowTransparency = false, modal = false } = config;
1128
+ return function containerTemplateFn({ uid, frame, placeholder, doc, props, event, dimensions: { width, height } }) {
1129
+ if (!frame) return;
1130
+ if (allowTransparency) {
1131
+ frame.setAttribute("allowtransparency", "true");
1132
+ frame.style.background = "transparent";
1133
+ }
1134
+ const div = doc.createElement("div");
1135
+ div.setAttribute("id", uid);
1136
+ const style = doc.createElement("style");
1137
+ if (props?.cspNonce) style.setAttribute("nonce", props.cspNonce);
1138
+ if (modal) {
1139
+ const backdrop = doc.createElement("div");
1140
+ backdrop.classList.add("backdrop");
1141
+ style.appendChild(doc.createTextNode(`
1142
+ #${uid} {
1143
+ position: fixed;
1144
+ inset: 0;
1145
+ z-index: 99999;
1146
+ }
1147
+ #${uid} > .backdrop {
1148
+ position: fixed;
1149
+ inset: 0;
1150
+ background-color: rgba(40, 40, 40, 0.7);
1151
+ opacity: 0;
1152
+ transition: opacity 0.35s ease-in-out;
1153
+ will-change: opacity;
1154
+ }
1155
+ #${uid} > .backdrop.${CLASS.VISIBLE} {
1156
+ opacity: 1;
1157
+ }
1158
+ #${uid} > iframe {
1159
+ display: block;
1160
+ position: absolute;
1161
+ width: 100%;
1162
+ height: 100%;
1163
+ top: 0;
1164
+ left: 0;
1165
+ transition: opacity .2s ease-in-out;
1166
+ }
1167
+ #${uid} > iframe.${CLASS.INVISIBLE} {
1168
+ opacity: 0;
1169
+ }
1170
+ #${uid} > iframe.${CLASS.VISIBLE} {
1171
+ opacity: 1;
1172
+ }
1173
+ `));
1174
+ div.appendChild(backdrop);
1175
+ div.appendChild(frame);
1176
+ if (placeholder) div.appendChild(placeholder);
1177
+ div.appendChild(style);
1178
+ event.on(EVENT.DISPLAY, () => {
1179
+ backdrop.offsetHeight;
1180
+ requestAnimationFrame(() => backdrop.classList.add(CLASS.VISIBLE));
1181
+ });
1182
+ event.on(EVENT.BEFORE_CLOSE, () => {
1183
+ backdrop.classList.remove(CLASS.VISIBLE);
1184
+ });
1185
+ frame.classList.add(CLASS.INVISIBLE);
1186
+ if (fadeOnRender && placeholder) placeholder.classList.add(CLASS.VISIBLE);
1187
+ event.on(EVENT.RENDERED, () => {
1188
+ if (fadeOnRender) {
1189
+ if (placeholder) {
1190
+ placeholder.classList.remove(CLASS.VISIBLE);
1191
+ placeholder.classList.add(CLASS.INVISIBLE);
1192
+ }
1193
+ frame.classList.remove(CLASS.INVISIBLE);
1194
+ frame.classList.add(CLASS.VISIBLE);
1195
+ setTimeout(() => destroyElement(placeholder), 1);
1196
+ } else {
1197
+ if (placeholder) destroyElement(placeholder);
1198
+ frame.style.transition = "none";
1199
+ frame.classList.remove(CLASS.INVISIBLE);
1200
+ frame.classList.add(CLASS.VISIBLE);
1201
+ }
1202
+ });
1203
+ } else {
1204
+ const innerStyle = props?.style || props?.innerStyle;
1205
+ const initialHeight = height === "0" ? "0" : toCSS(innerStyle?.base?.height || innerStyle?.height || (height === "auto" ? 45 : height));
1206
+ const containerStyles = [
1207
+ "display: block",
1208
+ "position: relative",
1209
+ `width: ${width}`,
1210
+ `height: ${allowTransparency ? height : initialHeight}`,
1211
+ `background: ${background}`
1212
+ ];
1213
+ if (overflow) containerStyles.push(`overflow: ${overflow}`);
1214
+ if (borderRadius) containerStyles.push(`border-radius: ${borderRadius}`);
1215
+ style.appendChild(doc.createTextNode(`
1216
+ #${uid} {
1217
+ ${containerStyles.join(";\n ")};
1218
+ }
1219
+ #${uid} > iframe {
1220
+ display: block;
1221
+ position: absolute;
1222
+ width: 100%;
1223
+ height: 100%;
1224
+ top: 0;
1225
+ left: 0;
1226
+ transition: opacity .2s ease-in-out;
1227
+ }
1228
+ #${uid} > iframe.${CLASS.INVISIBLE} {
1229
+ opacity: 0;
1230
+ }
1231
+ #${uid} > iframe.${CLASS.VISIBLE} {
1232
+ opacity: 1;
1233
+ }
1234
+ `));
1235
+ div.appendChild(frame);
1236
+ if (placeholder) div.appendChild(placeholder);
1237
+ div.appendChild(style);
1238
+ event.on(EVENT.RESIZE, ({ width: newWidth, height: newHeight }) => {
1239
+ if (typeof newWidth === "number") div.style.width = toCSS(newWidth);
1240
+ if (typeof newHeight === "number") div.style.height = toCSS(newHeight);
1241
+ });
1242
+ if (placeholder) {
1243
+ frame.classList.add(CLASS.INVISIBLE);
1244
+ if (fadeOnRender) placeholder.classList.add(CLASS.VISIBLE);
1245
+ event.on(EVENT.RENDERED, () => {
1246
+ if (fadeOnRender) {
1247
+ placeholder.classList.remove(CLASS.VISIBLE);
1248
+ placeholder.classList.add(CLASS.INVISIBLE);
1249
+ frame.classList.remove(CLASS.INVISIBLE);
1250
+ frame.classList.add(CLASS.VISIBLE);
1251
+ setTimeout(() => destroyElement(placeholder), 1);
1252
+ } else {
1253
+ destroyElement(placeholder);
1254
+ frame.style.transition = "none";
1255
+ frame.classList.remove(CLASS.INVISIBLE);
1256
+ frame.classList.add(CLASS.VISIBLE);
1257
+ }
1258
+ });
1259
+ }
1260
+ }
1261
+ return div;
1262
+ };
1263
+ }
1264
+ const containerTemplate = createContainerTemplate({
1265
+ overflow: "hidden",
1266
+ borderRadius: "var(--monei-radius, 4px)"
1267
+ });
1268
+ const modalContainerTemplate = createContainerTemplate({ modal: true });
1269
+ //#endregion
1270
+ //#region src/card-input/index.ts
1271
+ const getCreateTokenFunction = (ref) => {
1272
+ if (ref.state?.__createToken) return ref.state.__createToken;
1273
+ throw new Error("Index is not registered");
1274
+ };
1275
+ const createToken = async (component, options) => {
1276
+ console.warn("[MONEI] Standalone createToken() is deprecated. Use cardInput.submit() instead.");
1277
+ const { data } = await getCreateTokenFunction(component)(options);
1278
+ return data;
1279
+ };
1280
+ const CardInput = createComponent({
1281
+ tag: "monei-card-input",
1282
+ url: config.cardInputUrl,
1283
+ dimensions: {
1284
+ width: "100%",
1285
+ height: "auto"
1286
+ },
1287
+ autoResize: {
1288
+ width: false,
1289
+ height: true
1290
+ },
1291
+ aliases: {
1292
+ sessionId: "orderId",
1293
+ style: "innerStyle"
1294
+ },
1295
+ computedProps: { __getConfig: {
1296
+ factory: ({ props }) => getPaymentMethods.bind(null, props),
1297
+ type: "function"
1298
+ } },
1299
+ validate: validateComponentProps,
1300
+ submit: (instance) => async (opts) => {
1301
+ const createTokenFn = instance.state?.__createToken;
1302
+ if (!createTokenFn) throw new Error("CardInput is not rendered or connection is pending — call render() first");
1303
+ const { data } = await createTokenFn(opts);
1304
+ return data;
1305
+ },
1306
+ containerTemplate: (params) => {
1307
+ params.state.__createToken = async (data = {}) => {
1308
+ const callChild = params.state.__callChild;
1309
+ if (!callChild) throw new Error("CardInput instance is not registered");
1310
+ return { data: await callChild("createToken", [data]) };
1311
+ };
1312
+ return containerTemplate(params);
1313
+ },
1314
+ prerenderTemplate: ({ doc, props }) => {
1315
+ const html = doc.createElement("html");
1316
+ const body = doc.createElement("body");
1317
+ body.style.margin = "0";
1318
+ body.style.background = "#fff";
1319
+ const div = doc.createElement("div");
1320
+ div.style.height = "45px";
1321
+ div.style.boxSizing = "border-box";
1322
+ const style = props.style || props.innerStyle;
1323
+ if (style?.base) Object.assign(div.style, transformStyle(style.base));
1324
+ if (style?.loading) Object.assign(div.style, transformStyle(style.loading));
1325
+ body.appendChild(div);
1326
+ html.appendChild(body);
1327
+ return html;
1328
+ }
1329
+ });
1330
+ const PaymentModal = createComponent({
1331
+ tag: "monei-payment-modal",
1332
+ url: config.paymentModalUrl,
1333
+ dimensions: {
1334
+ width: "100%",
1335
+ height: "100%"
1336
+ },
1337
+ autoResize: {
1338
+ width: false,
1339
+ height: false
1340
+ },
1341
+ aliases: { style: "innerStyle" },
1342
+ containerTemplate: createContainerTemplate({
1343
+ background: "transparent",
1344
+ fadeOnRender: false,
1345
+ allowTransparency: true
1346
+ })
1347
+ });
1348
+ const confirmPayment = (params) => {
1349
+ const rootNode = document.createElement("div");
1350
+ const bodyOverflow = document.body.style.overflow;
1351
+ Object.assign(document.body.style, { overflow: "hidden" });
1352
+ Object.assign(rootNode.style, {
1353
+ position: "fixed",
1354
+ overflow: "hidden",
1355
+ display: "block",
1356
+ top: "0",
1357
+ bottom: "0",
1358
+ left: "0",
1359
+ right: "0",
1360
+ width: "100%",
1361
+ height: "100%",
1362
+ zIndex: "99999"
1363
+ });
1364
+ document.body.appendChild(rootNode);
1365
+ let modal = null;
1366
+ const cleanup = () => {
1367
+ modal?.destroy();
1368
+ modal = null;
1369
+ Object.assign(document.body.style, { overflow: bodyOverflow });
1370
+ if (rootNode.parentNode) rootNode.parentNode.removeChild(rootNode);
1371
+ };
1372
+ return new Promise((resolve, reject) => {
1373
+ modal = new PaymentModal({
1374
+ ...params,
1375
+ isOpen: true,
1376
+ onResult: (result) => {
1377
+ resolve(result);
1378
+ cleanup();
1379
+ },
1380
+ onError: (error) => {
1381
+ reject(error);
1382
+ cleanup();
1383
+ }
1384
+ });
1385
+ modal.render(rootNode).catch((err) => {
1386
+ cleanup();
1387
+ reject(err);
1388
+ });
1389
+ });
1390
+ };
1391
+ //#endregion
1392
+ //#region src/paypal/index.ts
1393
+ const namespace = "monei-paypal";
1394
+ const onLoadPaypal = async (props, state, src) => {
1395
+ state.__scriptId = (await loadScript(src, props.cspNonce, {
1396
+ namespace,
1397
+ cspNonce: props.cspNonce
1398
+ }, true)).dataset.uidAuto;
1399
+ const defaultStyle = {
1400
+ layout: "horizontal",
1401
+ tagline: false,
1402
+ height: 45
1403
+ };
1404
+ const radius = parsePx(props.style?.borderRadius ?? props.borderRadius);
1405
+ if (radius) defaultStyle.borderRadius = radius;
1406
+ const style = {
1407
+ ...defaultStyle,
1408
+ ...props.style
1409
+ };
1410
+ style.height = parsePx(style.height, 45);
1411
+ props.onLoad?.(true);
1412
+ let token;
1413
+ await window[namespace].Buttons({
1414
+ createOrder: async () => {
1415
+ try {
1416
+ const result = await createToken$1({
1417
+ paymentId: props.paymentId,
1418
+ accountId: props.accountId,
1419
+ sessionId: props.sessionId,
1420
+ amount: props.amount,
1421
+ currency: props.currency,
1422
+ transactionType: props.transactionType,
1423
+ paymentMethod: { paypal: {} }
1424
+ });
1425
+ ({token} = result);
1426
+ return result.paypal?.orderId;
1427
+ } catch (error) {
1428
+ props.onError?.(error);
1429
+ return;
1430
+ }
1431
+ },
1432
+ onApprove: function(data) {
1433
+ if (data.orderID) props.onSubmit({ token });
1434
+ else props.onError?.(data);
1435
+ },
1436
+ onClick: function(_data, actions) {
1437
+ let shouldOpen = true;
1438
+ if (props.onBeforeOpen) shouldOpen = props.onBeforeOpen();
1439
+ if (!shouldOpen) return actions.reject();
1440
+ },
1441
+ style
1442
+ }).render(state.__container);
1443
+ };
1444
+ const PayPal = createComponent({
1445
+ tag: namespace,
1446
+ url: config.paypalUrl,
1447
+ dimensions: {
1448
+ width: "100%",
1449
+ height: "0"
1450
+ },
1451
+ autoResize: {
1452
+ width: false,
1453
+ height: false
1454
+ },
1455
+ aliases: { style: "innerStyle" },
1456
+ computedProps: {
1457
+ __getConfig: {
1458
+ factory: ({ props }) => getPaymentMethods.bind(null, props),
1459
+ type: "function"
1460
+ },
1461
+ __onLoadPayPal: {
1462
+ factory: ({ props, state }) => onLoadPaypal.bind(null, props, state),
1463
+ type: "function"
1464
+ }
1465
+ },
1466
+ containerTemplate: (params) => {
1467
+ params.state.__container = params.container;
1468
+ if (!params.props.accountId && !params.props.paymentId) throw new Error("You need to provide paymentId or accountId");
1469
+ const container = containerTemplate(params);
1470
+ params.event.on(EVENT.DESTROY, () => {
1471
+ window[namespace]?.Buttons?.instances?.forEach((instance) => {
1472
+ instance.close();
1473
+ });
1474
+ const scriptId = params.state.__scriptId;
1475
+ if (scriptId) {
1476
+ const script = document.querySelector(`script[data-uid-auto="${scriptId}"]`);
1477
+ if (script) script.remove();
1478
+ }
1479
+ });
1480
+ return container;
1481
+ }
1482
+ });
1483
+ const BizumModal = createComponent({
1484
+ tag: "monei-bizum",
1485
+ url: config.bizumUrl,
1486
+ autoResize: {
1487
+ width: false,
1488
+ height: false
1489
+ },
1490
+ containerTemplate: (params) => {
1491
+ if (!params.frame) return;
1492
+ if (params.props.isHidden) {
1493
+ const div = params.doc.createElement("div");
1494
+ div.setAttribute("id", params.uid);
1495
+ div.style.display = "none";
1496
+ div.appendChild(params.frame);
1497
+ if (params.placeholder) div.appendChild(params.placeholder);
1498
+ return div;
1499
+ }
1500
+ return modalContainerTemplate(params);
1501
+ },
1502
+ defaultProps: ({ event }) => ({ onBeforeClose: () => {
1503
+ event.trigger(EVENT.BEFORE_CLOSE);
1504
+ } })
1505
+ });
1506
+ const Bizum = createComponent({
1507
+ tag: "monei-bizum-button",
1508
+ url: config.bizumButtonUrl,
1509
+ dimensions: {
1510
+ width: "100%",
1511
+ height: "auto"
1512
+ },
1513
+ autoResize: {
1514
+ width: false,
1515
+ height: true
1516
+ },
1517
+ aliases: { style: "innerStyle" },
1518
+ computedProps: {
1519
+ __getConfig: {
1520
+ factory: ({ props }) => getPaymentMethods.bind(null, props),
1521
+ type: "function"
1522
+ },
1523
+ __onClick: {
1524
+ factory: ({ props, state }) => {
1525
+ const rootNode = document.createElement("div");
1526
+ return ({ amount, currency }) => {
1527
+ if (state.isOpen) return;
1528
+ let shouldOpen = true;
1529
+ if (props.onBeforeOpen) shouldOpen = props.onBeforeOpen();
1530
+ if (!shouldOpen) return;
1531
+ state.isOpen = true;
1532
+ if (!rootNode.parentNode) document.body.appendChild(rootNode);
1533
+ const bizumModal = new BizumModal({
1534
+ amount,
1535
+ currency,
1536
+ ...props,
1537
+ onClose: () => {
1538
+ state.isOpen = false;
1539
+ window.onpopstate = null;
1540
+ document.body.style.overflow = "";
1541
+ },
1542
+ isOpen: true
1543
+ });
1544
+ window.history.pushState(null, "", window.location.href);
1545
+ window.onpopstate = () => bizumModal.updateProps({ isOpen: false });
1546
+ Object.assign(document.body.style, { overflow: "hidden" });
1547
+ return bizumModal.render(rootNode);
1548
+ };
1549
+ },
1550
+ type: "function"
1551
+ }
1552
+ },
1553
+ validate: validateComponentProps,
1554
+ containerTemplate
1555
+ });
1556
+ const GooglePay = createComponent({
1557
+ tag: "monei-google-pay",
1558
+ url: config.paymentRequestUrl,
1559
+ dimensions: {
1560
+ width: "100%",
1561
+ height: "0"
1562
+ },
1563
+ autoResize: {
1564
+ width: false,
1565
+ height: true
1566
+ },
1567
+ aliases: { style: "innerStyle" },
1568
+ computedProps: { __getConfig: {
1569
+ factory: ({ props }) => getPaymentMethods.bind(null, props),
1570
+ type: "function"
1571
+ } },
1572
+ validate: validateComponentProps,
1573
+ containerTemplate
1574
+ });
1575
+ const PaymentRequest = createComponent({
1576
+ tag: "monei-payment-request",
1577
+ url: config.paymentRequestUrl,
1578
+ dimensions: {
1579
+ width: "100%",
1580
+ height: "auto"
1581
+ },
1582
+ autoResize: {
1583
+ width: false,
1584
+ height: true
1585
+ },
1586
+ aliases: { style: "innerStyle" },
1587
+ computedProps: { __getConfig: {
1588
+ factory: ({ props }) => getPaymentMethods.bind(null, props),
1589
+ type: "function"
1590
+ } },
1591
+ validate: validateComponentProps,
1592
+ containerTemplate
1593
+ });
1594
+ //#endregion
1595
+ //#region src/types.ts
1596
+ let NextActionType = /* @__PURE__ */ function(NextActionType) {
1597
+ NextActionType["CONFIRM"] = "CONFIRM";
1598
+ NextActionType["FRICTIONLESS_CHALLENGE"] = "FRICTIONLESS_CHALLENGE";
1599
+ NextActionType["BIZUM_CHALLENGE"] = "BIZUM_CHALLENGE";
1600
+ NextActionType["CHALLENGE"] = "CHALLENGE";
1601
+ NextActionType["COMPLETE"] = "COMPLETE";
1602
+ return NextActionType;
1603
+ }({});
1604
+ let CardBrand = /* @__PURE__ */ function(CardBrand) {
1605
+ CardBrand["Visa"] = "visa";
1606
+ CardBrand["Mastercard"] = "mastercard";
1607
+ CardBrand["Amex"] = "amex";
1608
+ CardBrand["Discover"] = "discover";
1609
+ CardBrand["Diners"] = "diners";
1610
+ CardBrand["JCB"] = "jcb";
1611
+ CardBrand["Maestro"] = "maestro";
1612
+ CardBrand["UnionPay"] = "unionpay";
1613
+ CardBrand["Elo"] = "elo";
1614
+ CardBrand["Hipercard"] = "hipercard";
1615
+ return CardBrand;
1616
+ }({});
1617
+ let TransactionType = /* @__PURE__ */ function(TransactionType) {
1618
+ TransactionType["AUTH"] = "AUTH";
1619
+ TransactionType["SALE"] = "SALE";
1620
+ TransactionType["PAYOUT"] = "PAYOUT";
1621
+ TransactionType["VERIF"] = "VERIF";
1622
+ return TransactionType;
1623
+ }({});
1624
+ //#endregion
1625
+ //#region src/index.ts
1626
+ const api = api_exports;
1627
+ const utils = utils_exports;
1628
+ //#endregion
1629
+ exports.Bizum = Bizum;
1630
+ exports.BizumModal = BizumModal;
1631
+ exports.CardBrand = CardBrand;
1632
+ exports.CardInput = CardInput;
1633
+ exports.GooglePay = GooglePay;
1634
+ exports.NextActionType = NextActionType;
1635
+ exports.PayPal = PayPal;
1636
+ exports.PaymentModal = PaymentModal;
1637
+ exports.PaymentRequest = PaymentRequest;
1638
+ exports.TransactionType = TransactionType;
1639
+ exports.api = api;
1640
+ exports.config = config;
1641
+ exports.confirmPayment = confirmPayment;
1642
+ exports.createToken = createToken;
1643
+ exports.utils = utils;